公司使用rancher来部署k8s集群,最近因为有一个新的项目开发完成需要搭建环境,因此我编写了k8s的yaml来导入到rancher中,生成一个测试环境,一个演示环境,测试环境用于测试,演示环境用于给客户演示。导入之后namespace等成功生成,测试环境没有问题,但是demo环境出现了问题。
demo环境的yaml如下:
---
apiVersion: apps/v1 #接口版本
kind: Deployment #接口类型
metadata:
name: xxxx-demo #Deployment名称
namespace: xxxx-demo #命名空间
spec:
selector:
matchLabels:
app: xxxx
tier: frontend
replicas: 1
strategy:
rollingUpdate: ##由于replicas为1,则整个升级,pod个数在2-4个之间
maxSurge: 1 #滚动升级时会先启动1个pod
maxUnavailable: 1 #滚动升级时允许的最大Unavailable的pod个数
template:
metadata:
labels:
app: xxxx
tier: frontend
spec:
containers:
- name: xxxx
image: xxxxx.com:/xxxx-demo/xxxx
env:
- name: SPRING_PROFILE
value: demo
resources:
requests:
cpu: 200m
memory: 200Mi
ports:
- containerPort: 8080
imagePullSecrets:
- name: xxxx
---
kind: Service
apiVersion: v1
metadata:
name: xxxx-service
namespace: xxxx-demo #命名空间
spec:
selector:
app: xxxx-demo
type: NodePort
ports: #service需要暴露的端口列表
- name: string #端口名称
protocol: TCP #端口协议,支持TCP和UDP,默认TCP
port: 8080 #服务监听的端口号
targetPort: 8080 #需要转发到后端Pod的端口号
nodePort: 8080 #当type = NodePort时,指定映射到物理机的端口号 The range of valid ports is 30000-32767
---
刚开始在namespace页面时看起来并没有什么问题,但是点击进入到工作负载页面后,在访问端口处展示的端口却是n/a。当时感觉不对,但是并没有在意,
查看pod日志,也能正常展示
但是通过接口进行访问时,却一直访问不到。经过多次排查,发现是因为yaml编写的问题
图中三处的APP名称必须保持一致,才能正常访问。
labels:用来定位一个或多个资源,键值对方式进行定义,下方使用的selector会与这里的键值对对应,作为selector的挑选条件
matchlabels: ** 标签选择器,与上面的标签共用,这个部分是17版本开始加的,必须与上面的labels对应,选择包含标签app:xxxx的资源
Labels的重要性
在新版的k8s中labels是非常重要的
注意:
必须在 Deployment 中指定适当的选择器和 Pod 模板标签(在本例中为app: xxxx)。不要与其他控制器(包括其他Deployments 和状态设置)重叠标签或选择器。Kubernetes不会阻止重叠,如果多个控制器具有重叠的选择器,这些控制器可能会冲突并运行意外。
matchLabels/matchExpression作用
matchLabels用于定义一组Label,与直接写在Selector中作用相同,直接给定键值;
matchExpression用于定义一组基于集合的筛选条件,基于表达式来定义使用标签选择器,{key: “KEY”, operator:
“OPERATOR”, values:[VAL1,VAL2,…]}。可用的条件运算符包括:
In、NotIn:values字段的值必须为非空列表。
Exists、DoesNotExist:values字段的值必须为空列表。如果同时设置了matchLabels和matchExpression,则两组条件为“AND”关系,即所有条件需要满足才能完成Selector的筛选。
matchLabels使用场景
1.kube-controller进程通过资源对象ReplicaSet上定义的Label Selector来筛选要监控的Pod副本的数量,从而实现Pod副本的数量始终符合预期设定的全自动控制流程
2.kube-proxy进程通过Service的Label Selector来选择对应的Pod,自动建立器每个Service到对应Pod的请求转发路由表,从而实现Service的智能负载均衡机制
3.通过对某些Node定义特定的Label,并且在Pod定义文件中使用NodeSelector这种标签调度策略,Kube-scheduler进程可以实现Pod定向调度的特性
Pod 选择器
.spec.selector 字段是一个标签选择器。 ReplicationController 管理标签与选择器匹配的所有 Pod。它不区分它创建或删除的 Pod 和其他人或进程创建或删除的 Pod。 这允许在不影响正在运行的 Pod 的情况下替换ReplicationController。
如果指定了 .spec.template.metadata.labels,它必须和 .spec.selector 相同,否则它将被 API拒绝。 如果没有指定 .spec.selector,它将默认为 .spec.template.metadata.labels。
另外,通常不应直接使用另一个 ReplicationController 或另一个控制器(例如 Job)来创建其标签与该选择器匹配的任何Pod。如果这样做,ReplicationController 会认为它创建了这些 Pod,就会产生冲突, Kubernetes并没有阻止你这样做。
如果在生产环境中有大量的Deployment的话,无法快速确定哪些Pod是属于哪个Deployment,这个是就体现了label标签的重要性,而我上面的yaml并没有将service中的selector与deployment中的lables对应,因此创建的pod无法与service绑定,导致访问不到。
将yaml修改成如下之后修复了这个bug
---
apiVersion: apps/v1 #接口版本
kind: Deployment #接口类型
metadata:
name: xxxx-demo #Deployment名称
namespace: xxxx-demo #命名空间
spec:
selector:
matchLabels:
app: xxxx-demo
tier: frontend
replicas: 1
strategy:
rollingUpdate: ##由于replicas为1,则整个升级,pod个数在2-4个之间
maxSurge: 1 #滚动升级时会先启动1个pod
maxUnavailable: 1 #滚动升级时允许的最大Unavailable的pod个数
template:
metadata:
labels:
app: xxxx-demo
tier: frontend
spec:
containers:
- name: xxxx
image: xxxxx.com:/xxxx-demo/xxxx
env:
- name: SPRING_PROFILE
value: demo
resources:
requests:
cpu: 200m
memory: 200Mi
ports:
- containerPort: 8080
imagePullSecrets:
- name: xxxx
---
kind: Service
apiVersion: v1
metadata:
name: xxxx-service
namespace: xxxx-demo #命名空间
spec:
selector:
app: xxxx-demo
type: NodePort
ports: #service需要暴露的端口列表
- name: string #端口名称
protocol: TCP #端口协议,支持TCP和UDP,默认TCP
port: 8080 #服务监听的端口号
targetPort: 8080 #需要转发到后端Pod的端口号
nodePort: 8080 #当type = NodePort时,指定映射到物理机的端口号 The range of valid ports is 30000-32767
---