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运行在有此标签的节点上
pod.dmeo.yaml


四、容器探测机制

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秒
liveness-exec.yaml


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
liveness-httpget.yaml


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
readiness-httpget.yaml


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主要有三个组件组成:

  1. 用户期望的Pod副本数量;
  2. 标签选择器,用来选定由自己管理或控制的Pod副本,如果通过标签选择器挑选到的Pod少于定义的Pod副本数量,则会利用Pod资源模版来创建Pod副本,以达到规定的Pod数量;
  3. 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 
rs-demo.yaml


[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
deploy-demo.yaml


创建:

[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
ds-demo.yaml



例子: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
ds-demo.yaml


[root@master ~]# kubectl expose deployment redis --port=80        #创建一个service,名字为redis,filebeat将通过此service与redis通信;

[root@master ~]# kubectl explain pods.spec.hostNetwork            #hostNetwork字段:pod将直接使用宿主机的网络名称空间

posted @ 2020-04-16 17:00  米兰的小铁將  阅读(294)  评论(0编辑  收藏  举报