zoukankan      html  css  js  c++  java
  • 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将直接使用宿主机的网络名称空间

  • 相关阅读:
    在linux上使用Android systrace
    perf性能调优
    未初始化内存检测(MSan)
    数据竞争检查工具(TSan)
    应用层内存溢出/越界/重复释放等问题检查工具(ASan)
    gperf heap profiler
    cmake打印shell
    github clone加速
    获取一个进程的所有物理地址上的内存
    Jenkins <1>: System Management
  • 原文地址:https://www.cnblogs.com/weiyiming007/p/12714006.html
Copyright © 2011-2022 走看看