Kubernetes pod控制器应用-(六-九)
一、关于控制器
Kubernetes中内建了很多controller(控制器),这些相当于一个状态机,用来控制Pod的具体状态和行为。
Pod :
1)自主式pod(指定调度到某节点,如节点down, pod 无法恢复)
2)控制器管理pod 一般有如下控制器 不同类型的控制器用于不同类似的pod
ReplicationController (控制副本数,滚动更新)
ReplicaSet (新一代的控制器)
Deployment (一般使用此声明式管理器,只能用于无状态应用)
statefulset (有状态副本集控制器)
DaemonSet (使用此控制器部署的副本,会在每一个node上构建)
Job (job的pod多用于执行一次性任务,执行完成pod后就会停止)
Cronjob (计划性job执行)
3)ReplicationController、ReplicaSet、Deployment
现在主要关注ReplicaSet、Deployment,两者关系如下图:
ReplicaSet 也是用来管理多个 Pod 的副本;
Deployment运行于ReplicaSet之上,拥有更加灵活的升级、回滚功能。
当创建了 Deployment 之后,实际上也创建了 ReplicaSet,所以说 Deployment 管理着 ReplicaSet( Deployment 比 ReplicaSet 有着更多功能);
建议使用Deployment而不直接使用Replica Set;
Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationController 来方便的管理应用。典型的应用场景包括:
*定义Deployment来创建Pod和ReplicaSet
*滚动升级和回滚应用
*扩容和缩容
*暂停和继续Deployment
二、pod定义文件的属性
三、标签
1、
标签是K8s极具特色之一,一个资源可以拥有多个标签,同一个标签可以贴到不同的对象上;
spec.containers <[]object>
- name <string>
image <string>
imagePullPolicy <string>
Always, Never, IfNotPresent #Always总是去下载镜像;Never:有就用,没有就不用;IfNotPresent:如果没有就去下载;
ports <[]object>
key=value
- key:字符,数字 _ - .只能以字母数字开头
- value:可以为空,只能以字母数字开头和结尾
标签选择器:
等值关系:=,==,!=
集合关系:KEY notin(VALUE1,VALUE2)
KEY notin (VALUE1,VALUE2)
KEY
!KEY
许多资源支持内嵌字段定义其使用的标签选择器:
matchLabels:直接给定键值
matchExpressions:基于给定的表达式来定义使用标签选择器,{key:"KEY", operator:"OPERATOR",values:[VAL1,VAL2,...]}
操作符:
In, NotIn:values字段的值必须为非空列表;
Exists, NotExists:values字段的值必须为空列表;
[root@master ~]# kubectl get pods --show-labels #查看pod的标签 [root@master ~]# kubectl get pods -L app #过滤指定资源下app列中对应的值 [root@master ~]# kubectl get pods -l app --show-labels #过滤出含有app标签的pod [root@master ~]# kubectl label pods pod-demo release=canary #为pod打标签,pod-demo是一个pod名 [root@master ~]# kubectl label pods pod-demo release=stable --overwrite #更改pod的标签 #查看 node 标签 kubectl get nodes --show-labels #为node01节点打标签,这样添加资源时就可以对节点有倾向性了 [root@master ~]# kubectl label nodes node01 disktype=ssd
nodeSelector <map[string]string> #节点标签选择器,
nodeName <string> #直接指定节点
annotations:
资源注解,与label不同的地方在于,它不能用于挑选资源对象,仅用于为对象提供“元数据”
2、Pod的生命周期
状态:Pending, Running, Failed, Succeeded, Unknown
创建Pod:
Pod生命周期中的重要行为:
初始化容器:
容器探测:
liveness
readiness
restartPolicy字段: #一旦pod中的容器挂了,要做的动作
Always, OnFailure, Never. #Default to Always; Always:总是重启;OnFailure:容器状态为错误时重启;Never:不重启;
3、pod.demo.yaml例子
[root@master manifests]# cat pod.demo.yaml
1 apiVersion: v1 2 kind: Pod #pod控制器 3 metadata: 4 name: pod-demo 5 namespace: default 6 labels: 7 app: myapp 8 tier: frontend 9 annotations: 10 mageedu.com/created-by: "cluster admin" 11 spec: 12 containers: 13 - name: myapp 14 image: ikubernetes/myapp:v1 15 ports: 16 - name: http 17 containerPort: 80 18 - name: https 19 containerPort: 443 20 - name: busybox 21 image: busybox:latest 22 imagePullPolicy: IfNotPresent 23 command: 24 - "/bin/sh" 25 - "-c" 26 - "sleep 3600" 27 nodeSelector: #节点标签选择器 28 disktype: ssd #让pod运行在有此标签的节点上
四、容器探测机制
1、
pod中的容器探测,探测容器存活与否;
探针类型有三种:
ExecAction 探针在容器内执行任意命令,并检查状态码。状态码为0,则探测成功
TCPSockeAction 尝试与容器的指定端口建立TCP连接,成功建立,则探测成功
HTTPGetAction 对容器的IP地址执行 HTTP GET 请求,如果响应状态码不代表错误,则探测成功
K8S的应用程序健康检查分为livenessProbe和readinessProbe,两者相似,但也存在着一些区别:
livenessProbe在服务运行过程中检查应用程序是否运行正常,不正常将杀掉进程;
readnessProbe是用于检测应用程序启动完成后是否准备好对外提供服务,不正常继续检测,直到返回成功为止。
explain查看资源清单帮助信息:
[root@master ~]# kubectl explain pod.spec.containers.livenessProbe
[root@master ~]# kubectl explain pod.spec.containers.livenessProbe.exec
[root@master ~]# kubectl explain pod.spec.containers.livenessProbe.tcpSocket
[root@master ~]# kubectl explain pod.spec.containers.livenessProbe.httpGet
2、livenessProbe健康检查
ExecAction:
[root@master manifests]# cat liveness-exec.yaml
1 apiVersion: v1 2 kind: Pod 3 metadata: 4 name: liveness-exec-pod 5 namespace: default 6 spec: 7 containers: 8 - name: liveness-exec-container 9 image: busybox:latest 10 imagePullPolicy: IfNotPresent 11 command: ["/bin/sh","-c","touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 3600"] 12 livenessProbe: #探测 13 exec: 14 command: ["test","-e","/tmp/healthy"] #探测命令,看文件是否存 15 initialDelaySeconds: 1 #容器启动后的秒数,然后进行活性探测 16 periodSeconds: 3 #执行探测的频率(秒)。默认为10秒
HTTPGetAction:
[root@master manifests]# cat liveness-httpget.yaml
1 apiVersion: v1 2 kind: Pod 3 metadata: 4 name: liveness-httpget-pod 5 namespace: default 6 spec: 7 containers: 8 - name: liveness-httpget-container 9 image: ikubernetes/myapp:v1 10 imagePullPolicy: IfNotPresent 11 ports: 12 - name: http 13 containerPort: 80 14 livenessProbe: 15 httpGet: 16 port: http 17 path: /index.html 18 initialDelaySeconds: 1 19 periodSeconds: 3
3、readinessProbe健康检查
[root@master manifests]# cat readiness-httpget.yaml
1 apiVersion: v1 2 kind: Pod 3 metadata: 4 name: readiness-httpget-pod 5 namespace: default 6 spec: 7 containers: 8 - name: readiness-httpget-container 9 image: ikubernetes/myapp:v1 10 imagePullPolicy: IfNotPresent 11 ports: 12 - name: http 13 containerPort: 80 14 readinessProbe: 15 httpGet: 16 port: http 17 path: /index.html 18 initialDelaySeconds: 1 19 periodSeconds: 3
4、pod启动后钩子和终止前钩子
[root@master ~]# kubectl explain pod.spec.containers.lifecycle postStart <Object> #启动后 preStop <Object> #终止前 [root@master ~]# kubectl explain pod.spec.containers.lifecycle.postStart [root@master ~]# kubectl explain pod.spec.containers.lifecycle.preStop
root@master manifests]# cat poststart-pos.yaml
apiVersion: v1
kind: Pod
metadata:
name: poststart-pod
namespace: default
spec:
containers:
- name: busybox-httpd
image: busybox:latest
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command: ['mkdir','-p','/data/web/index.html']
command: ['/bin/sh','-c','sleep 3600'] #此条命令要依赖于上面那个command命令的执行结果
五、Pod控制器类别
1、控制器介绍
ReplicaSet
ReplicaSet控制器用来管理无状态的Pod资源,核心作用在于代用户创建指定数量的Pod副本,并确保Pod副本数量一直等于用户期望的数量。
而且还支持Pod滚动更新、及自动扩缩容等机制;它被称新一代的ReplicationCtroller。
ReplicaSet主要有三个组件组成:
- 用户期望的Pod副本数量;
- 标签选择器,用来选定由自己管理或控制的Pod副本,如果通过标签选择器挑选到的Pod少于定义的Pod副本数量,则会利用Pod资源模版来创建Pod副本,以达到规定的Pod数量;
- Pod资源模版。
但是Kubernetes却不建议用户直接使用ReplicaSet,而是应该使用Deployment。
Deployment
Deployment也是Pod控制器,但是它是工作在ReplicaSet之上的。Deployment是通过控制ReplicaSet,从而来控制Pod。Deployment能够提供比ReplicaSet更为强大的功能。
比如:Pod版本回滚、声明式配置(声明式配置是已经创建的Pod可以随时更改配置并应用到Pod)。Deployment是目前管理无状态应用最好的控制器。
DaemonSet
DaemonSet用于确保集群中的每一个节点只运行一个特定的Pod副本,这种特定的Pod通常是用来实现系统级的后台任务。把这样的任务托管在Kubernetes之上的好处是:
如果这个后台任务宕了以后,会由DaemonSet控制器自动重建一个Pod;新建一个Node节点,它也会在新节点上创建一个这样的Pod运行。
约束:我们也可以根据自己的需求,在K8S群集中的部分满足条件的节点上仅运行一个Pod副本。
总结: Deployment和DaemonSet管理的Pod中运行的服务都是无状态的,且是守护进程类的(必须始终持续运行在后台)。但是对于那种只希望运行一次就结束的任务,
显然以上两种控制器是不能够使用的。例如:我们需要对数据库进行备份,备份结束后,任务就应该结束了,而不是让任务持续运行在后台。那么对于这种任务只运行一次,
只要任务完成就正常退出,没有完成才会重建,这就应该选择使用Job这种控制器了。
Job
Job控制器控制只能执行一次作业的任务,它确保这个任务确实是正常完成而退出的,如果是异常退出,则Job控制器会重建任务再次执行直到任务正常完成。
那么对于周期性的任务呢?显然Job控制器也是无法胜任的。这就需要CronJob了。
CronJob
CronJob与Job类似,也是运行一次就退出。不同之处在于,Job是只运行一次,CronJob是周期性运行。但每次运行都会有正常退出的时间。如果前一次任务还没执行完成,
又到了下一次任务执行的时间点了怎么办呢?CronJob也可以解决这种问题。
StatufulSet
StatufulSet控制器能够管理有状态的Pod副本,而且每一个Pod副本都是被单独管理的,它拥有自己独有的标志和独有的数据集。一旦这个副本故障了,在重建Pod之前会做许多初始化操作。
以Redis群集为例:如果Redis集群中三个节点中的某一个节点宕机了,为了确保每个节点宕机后数据不丢失,我们传统的做法就是对每个节点做主从复制,当主节点宕机后,
需要人为的把从节点提升为主节点,想要恢复从节点,就需要很多运维操作了。
但是利用StatufulSet去定义管理Redis或Mysql或者Zookeeper,它们的配置是不一样的。例如:配置管理Redis主从复制和配置管理Mysql主从复制中间的操作步骤是不一样的。所以这样的配置没有任何规律可循。StatufulSet给我们提供了一个封装,用户把需要人为操作的复杂的执行逻辑定义成脚本,放置在StatufulSet的Pod模板中。
这样在每次Pod节点故障后,能通过脚本自动恢复过来。
CDR
Custom Defined Resources K8S 1.8+,用户自定义资源。
Helm
任何不把用户当傻瓜的应用,都难以取得成功。K8S资源清单定义起来,门槛过高,难度大。这就诞生了Helm,Helm对于Kubernetes来说,就
相当于Linux系统中的yum,以后在再部署大型的应用,就可以用Helm直接安装部署。不过Helm到目前为止,诞生也不超过两年的时间。
到目前为止,许多大型主流的应用,已经可以通过Helm去部署。
2、ReplicaSet控制器定义
资源的定义字段查询:
[root@master ~]# kubectl explain rs
[root@master ~]# kubectl explain rs.spec
[root@master ~]# kubectl explain rs.spec.template.spec
#ReplicaSet控制器清单文件
[root@master manifests]# cat rs-demo.yaml
1 apiVersion: apps/v1 2 kind: ReplicaSet 3 metadata: 4 name: myapp 5 namespace: default 6 spec: 7 replicas: 2 #pod数量 8 selector: 9 matchLabels: 10 app: myapp 11 release: canary 12 template: #创建pod时的模板 13 metadata: 14 name: myapp-pod 15 labels: 16 app: myapp 17 release: canary 18 environment: qa 19 spec: 20 containers: 21 - name: myapp-container 22 image: ikubernetes/myapp:v1 23 ports: 24 - name: http 25 containerPort: 80 26
[root@master manifests]# kubectl edit rs myapp #可以动态修改控制器文件,此时修改的是提交到apiserver的定义,而不是原yaml文件;
...
replicas: 5 #比如把pod副本数量修改为5,实现动态扩容、缩容;
...
[root@master manifests]# kubectl edit rs myapp
...
- image: ikubernetes/myapp:v2 #可以修改版本,此处把版本修改为v2,但是要pod重构以后才会生效;
...
此时可以依次删除每个pod,它就会一个个自动重构,版本就会升级了(灰度发布);
3、Deployment
Deployment管理保留的ReplicaSet版本数量可以由用户自定义,默认保留10个历史版本。Deployment能够使用声明式配置,声明式配置是使用kubectl apply -f demo.yaml
命令。
对于声明式配置的资源,将来还可以在命令行使用patch
子命令去打补丁实现配置修改更新。Deployment在控制Pod滚动更新时,还可以配置Pod的滚动更新逻辑。
资源的定义字段查询:
[root@master ~]# kubectl explain deploy [root@master ~]# kubectl explain deploy.spec revisionHistoryLimit <integer> #最多保存的历史版本数 [root@master ~]# kubectl explain deploy.spec.strategy #strategy字段:更新策略 [root@master ~]# kubectl explain deploy.spec.strategy.rollingUpdate #rollingUpdate字段:更新力度 maxSurge <string> #更新时能超出的目标副本数,(加一个,删一个...直到完成) maxUnavailable <string> #更新时最多有几个不可用
[root@master manifests]# cat deploy-demo.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy namespace: default spec: replicas: 2 #两个pod副本 selector: matchLabels: app: myapp release: canary template: metadata: labels: app: myapp release: canary spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80
创建:
[root@master manifests]# kubectl apply -f deploy-demo.yaml #声明式创建/更新
[root@master manifests]# kubectl get deploy
[root@master manifests]# kubectl get rs
[root@master manifests]# kubectl get pods
修改pod副本数量:
(1)编辑yaml文件的方式 [root@master manifests]# vim deploy-demo.yaml #直接编辑yaml文件 ... replicas: 3 ... [root@master manifests]# kubectl apply -f deploy-demo.yaml #更新;kubectl apply可以执行多次,与create不同; [root@master manifests]# kubectl get pods #此时pod数量已经成为三个 (2)补丁的方式 [root@master manifests]# kubectl patch deployment myapp-deploy -p '{"spec":{"replicas":5}}' #打补丁的方式修改pod副本数量,不会修改原文件
修改image版本号:
(1)编辑yaml文件的方式 [root@master manifests]# vim deploy-demo.yaml ... image: ikubernetes/myapp:v2 ... [root@master manifests]# kubectl apply -f deploy-demo.yaml #pod会自动滚动更新 [root@master manifests]# kubectl get rs -o wide #发现rs的版本已经更新 (2)打补丁的方式 [root@master manifests]# kubectl set image deployment myapp-deploy myapp=ikubernetes/myapp:v3
控制更新力度:
[root@master manifests]# kubectl patch deployment myapp-deploy -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'
4、DaemonSet
DaemonSet控制器能够在指定节点上运行能够实现系统级的管理功能的Pod,而且每个指定节点只运行一个这样的Pod副本。还可以把节点的目录挂载至Pod中,通过Pod实现某些管理功能。
DaemonSet会在每个节点上创建pod,所以不用设置副本数量;
资源清单的定义字段查询:
[root@master manifests]# kubectl explain ds
[root@master manifests]# cat ds-demo.yaml
apiVersion: apps/v1 kind: DaemonSet metadata: name: myapp-ds namespace: default spec: selector: matchLabels: app: filebeat release: stable template: metadata: labels: app: filebeat release: stable spec: containers: - name: filebeat image: ikubernetes/filebeat:5.6.5-alpine env: - name: REDIS_HOST value: redis.default.svc.cluster.local - name: REDIS_LOG_LEVEL value: info
例子:pod之间通信,让filebeat往redis里面通过service存日志;
资源清单的定义字段查询:
[root@master ~]# kubectl explain pods.spec.containers.env
[root@master manifests]# cat ds-demo.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: redis namespace: default spec: replicas: 1 selector: #对资源(pod...)的标签查询,匹配出对应的资源 matchLabels: app: redis role: logstor template: metadata: labels: app: redis #pod的标签 role: logstor spec: containers: - name: redis image: redis:4.0-alpine #redis pod ports: - name: redis containerPort: 6379 --- #用---隔开可以定义多个资源 apiVersion: apps/v1 kind: DaemonSet metadata: name: filebeat-ds namespace: default spec: selector: matchLabels: app: filebeat release: stable template: metadata: labels: app: filebeat release: stable spec: containers: - name: filebeat image: ikubernetes/filebeat:5.6.5-alpine env: #变量字段 - name: REDIS_HOST #变量名 value: redis.default.svc.cluster.local #变量值(主机名);这个主机名其实是一个service名,而且这个service背后应该是有pod在提供服务的; - name: REDIS_LOG_LEVEL value: info
[root@master ~]# kubectl expose deployment redis --port=80 #创建一个service,名字为redis,filebeat将通过此service与redis通信;
[root@master ~]# kubectl explain pods.spec.hostNetwork #hostNetwork字段:pod将直接使用宿主机的网络名称空间