• 4.pod资源清单


    pod参数

    test.yaml
    apiVersion: v1       #版本号,例如v1
    kind: Pod       #资源类型,如Pod
    metadata:       #元数据
      name: string       # Pod名字
      namespace: string    # Pod所属的命名空间
      labels:      #自定义标签
        - name: string     #自定义标签名字
      annotations:       #自定义注释列表
        - name: string
    spec:         # Pod中容器的详细定义
      containers:      # Pod中容器列表
      - name: string     #容器名称
        image: string    #容器的镜像名称
        imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
        command: [string]    #容器的启动命令列表,如不指定,使用打包时使用的启动命令
        args: [string]     #容器的启动命令参数列表
        workingDir: string     #容器的工作目录
        volumeMounts:    #挂载到容器内部的存储卷配置
        - name: string     #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
          mountPath: string    #存储卷在容器内mount的绝对路径,应少于512字符
          readOnly: boolean    #是否为只读模式
        ports:       #需要暴露的端口库号
        - name: string     #端口号名称
          containerPort: int   #容器需要监听的端口号
          hostPort: int    #容器所在主机需要监听的端口号,默认与Container相同
          protocol: string     #端口协议,支持TCP和UDP,默认TCP
        env:       #容器运行前需设置的环境变量列表
        - name: string     #环境变量名称
          value: string    #环境变量的值
        resources:       #资源限制和请求的设置
          limits:      #资源限制的设置
            cpu: string    #cpu的限制,单位为core数
            memory: string     #内存限制,单位可以为Mib/Gib
          requests:      #资源请求的设置
            cpu: string    #cpu请求,容器启动的初始可用数量
            memory: string     #内存请求,容器启动的初始可用内存
        livenessProbe:     #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可
          exec:      #对Pod容器内检查方式设置为exec方式
            command: [string]  #exec方式需要制定的命令或脚本
          httpGet:       #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
            path: string
            port: number
            host: string
            scheme: string
            HttpHeaders:
            - name: string
              value: string
          tcpSocket:     #对Pod内个容器健康检查方式设置为tcpSocket方式
             port: number
           initialDelaySeconds: 0  #容器启动完成后首次探测的时间,单位为秒
           timeoutSeconds: 0   #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
           periodSeconds: 0    #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
           successThreshold: 0
           failureThreshold: 0
           securityContext:
             privileged:false
        restartPolicy: [Always | Never | OnFailure]#Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
        nodeSelector: obeject  #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
        imagePullSecrets:    #Pull镜像时使用的secret名称,以key:secretkey格式指定
        - name: string
        hostNetwork:false      #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
        volumes:       #在该pod上定义共享存储卷列表
        - name: string     #共享存储卷名称 (volumes类型有很多种)
          emptyDir: {}     #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
          hostPath: string     #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
            path: string     #Pod所在宿主机的目录,将被用于同期中mount的目录
          secret:      #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
            scretname: string  
            items:     
            - key: string
              path: string
          configMap:     #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
            name: string
            items:
            - key: string
              path: string
    

    1.node节点选择器

    我们在创建pod资源的时候,pod会根据schduler进行调度,那么默认会调度到随机的一个工作节点,如果我们想要pod调度到指定节点或者调度到一些具有相同特点的node节点,怎么办呢?
    可以使用pod中的nodeName或者nodeSelector字段指定要调度到的node节点

    • nodeName:指定pod节点运行在哪个具体node上

    获取节点名称

    [root@master1 ~]# kubectl get nodes
    NAME      STATUS   ROLES                  AGE   VERSION
    master1   Ready    control-plane,master   42h   v1.20.10
    node1     Ready    worker                 24h   v1.20.10
    node2     Ready    worker                 24h   v1.20.10
    

    资源配置清单

    apiVersion: v1
    kind: Pod
    metadata:
      name: demo-pod
      namespace: default
      labels:
        app: myapp
        env: dev
    spec:
      nodeName: node1
      containers:
      - name:  tomcat-pod-java
        ports:
        - containerPort: 8080
        image: tomcat:8.5-jre8-alpine
        imagePullPolicy: IfNotPresent
      - name: busybox
        image: busybox:latest
        command:
        - "/bin/sh"
        - "-c"
        - "sleep 3600"
    
    • nodeSelector:指定pod调度到具有哪些标签的node节点上

    给node节点打标签,打个具有disk=ceph的标签

    [root@master1 ~]# kubectl label nodes node2 disk=ceph
    node/node2 labeled
    

    资源配置清单

    apiVersion: v1
    kind: Pod
    metadata:
      name: demo-pod-1
      namespace: default
      labels:
        app: myapp
        env: dev
    spec:
      nodeSelector:
        disk: ceph
      containers:
      - name:  tomcat-pod-java
        ports:
        - containerPort: 8080
        image: tomcat:8.5-jre8-alpine
        imagePullPolicy: IfNotPresent
    

    2.亲和性

    • node节点亲和性:nodeAffinity

    Node节点亲和性针对的是pod和node的关系,Pod调度到node节点的时候匹配的条件

    [root@master1 ~]#  kubectl explain  pods.spec.affinity.nodeAffinity
    KIND:     Pod
    VERSION:  v1
    RESOURCE: nodeAffinity <Object>
    DESCRIPTION:
         Describes node affinity scheduling rules for the pod.
         Node affinity is a group of node affinity scheduling rules.
    FIELDS:
       preferredDuringSchedulingIgnoredDuringExecution	<[]Object>
       requiredDuringSchedulingIgnoredDuringExecution	<Object>
    

    prefered表示有节点尽量满足这个位置定义的亲和性,这不是一个必须的条件,软亲和性
    require表示必须有节点满足这个位置定义的亲和性,这是个硬性条件,硬亲和性

    [root@master1 ~]# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions
    KIND:     Pod
    VERSION:  v1
    RESOURCE: matchExpressions <[]Object>
    DESCRIPTION:
         A list of node selector requirements by node's labels.
         A node selector requirement is a selector that contains values, a key, and
         an operator that relates the key and values.
    FIELDS:
       key	<string> -required-
         The label key that the selector applies to.
       operator	<string> -required-
         Represents a key's relationship to a set of values. Valid operators are In,
         NotIn, Exists, DoesNotExist. Gt, and Lt.
       values	<[]string>
         An array of string values. If the operator is In or NotIn, the values array
         must be non-empty. If the operator is Exists or DoesNotExist, the values
         array must be empty. If the operator is Gt or Lt, the values array must
         have a single element, which will be interpreted as an integer. This array
         is replaced during a strategic merge patch.
    

    key: 就是node上的label
    operator: 规则,分别有In,NotIn, Exists, DoesNotExist. Gt, and Lt
    values:就是值

    硬亲和性示例

    apiVersion: v1
    kind: Pod
    metadata:
            name: pod-node-affinity-demo
            namespace: default
            labels:
                app: myapp
                tier: frontend
    spec:
        containers:
        - name: myapp
          image: ikubernetes/myapp:v1
        affinity:
            nodeAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                       nodeSelectorTerms:
                       - matchExpressions:
                         - key: zone
                           operator: In
                           values:
                           - foo
                           - bar
    

    我们检查当前节点中有任意一个节点拥有zone标签的值是foo或者bar,就可以把pod调度到这个node节点的foo或者bar标签上的节点上

    [root@master1 ~]# kubectl apply -f pod-nodeaffinity-demo.yaml 
    [root@master1 ~]# kubectl get pods -o wide | grep pod-node
    pod-node-affinity-demo             0/1     Pending     0   node1                       
    status的状态是pending,上面说明没有完成调度,因为没有一个拥有zone的标签的值是foo或者bar,而且使用的是硬亲和性,必须满足条件才能完成调度
    [root@master1 ~]# kubectl label nodes node1 zone=foo
    给这个node1节点打上标签zone=foo,在查看
    [root@master1 ~]#kubectl get pods -o wide 显示如下:
    pod-node-affinity-demo             1/1     Running  0   node1
    
    • pod节点亲和性:podaffinity

    pod自身的亲和性调度有两种表示形式
    podaffinity:pod和pod更倾向腻在一起,把相近的pod结合到相近的位置,如同一区域,同一机架,这样的话pod和pod之间更好通信,比方说有两个机房,这两个机房部署的集群有1000台主机,那么我们希望把nginx和tomcat都部署同一个地方的node节点上,可以提高通信效率;
    podunaffinity:pod和pod更倾向不腻在一起,如果部署两套程序,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响。
    第一个pod随机选则一个节点,做为评判后续的pod能否到达这个pod所在的节点上的运行方式,这就称为pod亲和性;我们怎么判定哪些节点是相同位置的,哪些节点是不同位置的;我们在定义pod亲和性时需要有一个前提,哪些pod在同一个位置,哪些pod不在同一个位置,这个位置是怎么定义的,标准是什么?以节点名称为标准,这个节点名称相同的表示是同一个位置,节点名称不相同的表示不是一个位置。

    [root@master1 ~]# kubectl explain pods.spec.affinity.podAffinity
    KIND:     Pod
    VERSION:  v1
    RESOURCE: podAffinity <Object>
    DESCRIPTION:
         Describes pod affinity scheduling rules (e.g. co-locate this pod in the
         same node, zone, etc. as some other pod(s)).
         Pod affinity is a group of inter pod affinity scheduling rules.
    FIELDS:
       preferredDuringSchedulingIgnoredDuringExecution	<[]Object>
       requiredDuringSchedulingIgnoredDuringExecution	<[]Object>
    

    requiredDuringSchedulingIgnoredDuringExecution: 硬亲和性
    preferredDuringSchedulingIgnoredDuringExecution:软亲和性

    [root@xianchaomaster1 ~]# kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution
    KIND:     Pod
    VERSION:  v1
    RESOURCE: requiredDuringSchedulingIgnoredDuringExecution <[]Object>
    DESCRIPTION:
    FIELDS:
       labelSelector	<Object>
       namespaces	<[]string>
       topologyKey	<string> -required-
    

    topologyKey:位置拓扑的键,这个是必须字段,这个字段就是node节点的标签key字段(不包含value),把具有相同标签key的节点归为一组,亲和性和反亲和性都是在具有这一组标签key的node节点上进行选择.假如集群中只有一个key为abc的node,当设置反亲和性的时候,第二个pod会处于挂起状态
    labelSelector:我们要判断pod跟别的pod亲和,跟哪个pod亲和,需要靠labelSelector,通过labelSelector选则一组能作为亲和对象的pod资源
    namespace:labelSelector需要选则一组资源,那么这组资源是在哪个名称空间中呢,通过namespace指定,如果不指定namespaces,那么就是当前创建pod的名称空间

    硬亲和性示例

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-first
      labels:
        app2: myapp2
        tier: frontend
    spec:
        containers:
        - name: myapp
          image: ikubernetes/myapp:v1
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-second
      labels:
        app: backend
        tier: db
    spec:
        containers:
        - name: busybox
          image: busybox:latest
          imagePullPolicy: IfNotPresent
          command: ["sh","-c","sleep 3600"]
        affinity:
          podAffinity:
             requiredDuringSchedulingIgnoredDuringExecution:
             - labelSelector:
                  matchExpressions:
                  - key: app2
                    operator: In
                    values: 
                    - myapp2
               topologyKey: kubernetes.io/hostname
    
    • node节点反亲和性:nodeAntiAffinity

    参考node节点亲和性

    • pod节点反亲和性:podAntiaffinity

    参考pod节点亲和性

    3.污点和容忍度

    给了节点选择的主动权,我们给节点打一个污点,不容忍的pod就无法调度到节点上,污点就是定义在节点上的键值属性数据,可以定决定拒绝那些pod
    pod亲和性是pod属性;但是污点是节点的属性,污点定义在nodeSelector上

    • 污点: taints,是键值数据,用在节点上
    • 容忍度: tolerations,是键值数据,用在pod上,能容忍哪些污点

    给节点打污点

    [root@master1 ~]# kubectl taint node node1 disk=hdd:PreferNoSchedule
    node/node1 tainted
    

    查看node上的污点

    [root@master1 ~]# kubectl describe node master1 | grep Taints
    Taints:             node-role.kubernetes.io/master:NoSchedule
    
    [root@master1 ~]# kubectl describe node/node1 | grep Taint
    Taints:             disk=hdd:PreferNoSchedule
    

    删除节点上的污点(就是加个横杠)

    [root@master1 ~]# kubectl taint node node1 disk=hdd:PreferNoSchedule-
    node/node1 untainted
    

    查看node污点参数

    [root@master1 ~]# kubectl explain node.spec.taints
    KIND:     Node
    VERSION:  v1
    RESOURCE: taints <[]Object>
    DESCRIPTION:
         If specified, the node's taints.
         The node this Taint is attached to has the "effect" on any pod that does
         not tolerate the Taint.
    FIELDS:
       effect	<string> -required-
         Required. The effect of the taint on pods that do not tolerate the taint.
         Valid effects are NoSchedule, PreferNoSchedule and NoExecute.
       key	<string> -required-
         Required. The taint key to be applied to a node.
       timeAdded	<string>
         TimeAdded represents the time at which the taint was added. It is only
         written for NoExecute taints.
       value	<string>
         The taint value corresponding to the taint key.
    

    effect:污点影响等级,必须参数

    • NoSchedule:仅影响pod调度过程,当pod能容忍这个节点污点,就可以调度到当前节点,后来这个节点的污点改了,加了一个新的污点,使得之前调度的pod不能容忍了,那这个pod会怎么处理,对现存的pod对象不产生影响
    • NoExecute:既影响调度过程,又影响现存的pod对象,如果现存的pod不能容忍节点后来加的污点,这个pod就会被驱逐
    • PreferNoSchedule:最好不,也可以,是NoSchedule的柔性版本

    在pod对象定义容忍度的时候支持两种操作:
    1.等值密钥:key和value上完全匹配
    2.存在性判断:key和effect必须同时匹配,value可以是空
    在pod上定义的容忍度可能不止一个,在节点上定义的污点可能多个,需要琢个检查容忍度和污点能否匹配,每一个污点都能被容忍,才能完成调度,如果不能容忍怎么办,那就需要看pod的容忍度了

    查看pod容忍污点参数

    [root@master1 ~]# kubectl explain pod.spec.tolerations
    KIND:     Pod
    VERSION:  v1
    RESOURCE: tolerations <[]Object>
    DESCRIPTION:
         If specified, the pod's tolerations.
         The pod this Toleration is attached to tolerates any taint that matches the
         triple <key,value,effect> using the matching operator <operator>.
    FIELDS:
       effect	<string>
         Effect indicates the taint effect to match. Empty means match all taint
         effects. When specified, allowed values are NoSchedule, PreferNoSchedule
         and NoExecute.
       key	<string>
         Key is the taint key that the toleration applies to. Empty means match all
         taint keys. If the key is empty, operator must be Exists; this combination
         means to match all values and all keys.
       operator	<string>
         Operator represents a key's relationship to the value. Valid operators are
         Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for
         value, so that a pod can tolerate all taints of a particular category.
       tolerationSeconds	<integer>
         TolerationSeconds represents the period of time the toleration (which must
         be of effect NoExecute, otherwise this field is ignored) tolerates the
         taint. By default, it is not set, which means tolerate the taint forever
         (do not evict). Zero and negative values will be treated as 0 (evict
         immediately) by the system.
       value	<string>
         Value is the taint value the toleration matches to. If the operator is
         Exists, the value should be empty, otherwise just a regular string.
    

    pod容忍污点示例

    apiVersion: v1
    kind: Pod
    metadata:
      name: myapp-deploy
      namespace: default
      labels:
        app: myapp
        release: canary
    spec:
          containers:
          - name: myapp
            image: ikubernetes/myapp:v1
            ports:
            - name: http
              containerPort: 80
          tolerations:
          - key: "node-type"
            operator: "Equal"
            value: "production"
            effect: "NoExecute"
            tolerationSeconds: 3600
    

    上面yaml代表容忍node-type=production:NoExecute 驱离时间为3600秒

    4.pod常见状态

    Pod的status定义在PodStatus对象中,其中有一个phase字段。它简单描述了Pod在其生命周期的阶段。熟悉Pod的各种状态对我们理解如何设置Pod的调度策略、重启策略是很有必要的。下面是 phase 可能的值,也就是pod常见的状态:

    • 挂起(Pending):我们在请求创建pod时,条件不满足,调度没有完成,没有任何一个节点能满足调度条件,已经创建了pod但是没有适合它运行的节点叫做挂起,调度没有完成,处于pending的状态会持续一段时间:包括调度Pod的时间和通过网络下载镜像的时间。
    • 运行中(Running):Pod已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态。
    • 成功(Succeeded):Pod 中的所有容器都被成功终止,并且不会再重启。
    • 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。
    • 未知(Unknown):未知状态,所谓pod是什么状态是apiserver和运行在pod节点的kubelet进行通信获取状态信息的,如果节点之上的kubelet本身出故障,那么apiserver就连不上kubelet,得不到信息了,就会看Unknown
    • Evicted状态:出现这种情况,多见于系统内存或硬盘资源不足,可df-h查看docker存储所在目录的资源使用情况,如果百分比大于85%,就要及时清理下资源,尤其是一些大文件、docker镜像。
    • CrashLoopBackOff:容器曾经启动了,但可能又异常退出了
    • Error 状态:Pod 启动过程中发生了错误

    5.pod重启策略

    Pod的重启策略(RestartPolicy)应用于Pod内的所有容器,并且仅在Pod所处的Node上由kubelet进行判断和重启操作。当某个容器异常退出或者健康检查失败时,kubelet将根据 RestartPolicy 的设置来进行相应的操作。

    • Always:默认值当容器启动失败时,由kubelet自动重启该容器。
    • OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器。
    • Never:不论容器运行状态如何,kubelet都不会重启该容器。
    apiVersion: v1
    kind: Pod
    metadata:
      name: demo-pod
      namespace: default
      labels:
        app: myapp
    spec:
      restartPolicy: Always
      containers:
      - name:  tomcat-pod-java
        ports:
        - containerPort: 8080
        image: tomcat:8.5-jre8-alpine
        imagePullPolicy: IfNotPresent
    

    6.pod生命周期


    Pod 里面可以有一个或者多个容器,部署应用的容器可以称为主容器,在创建Pod时候,Pod 中可以有一个或多个先于主容器启动的Init容器,这个init容器就可以成为初始化容器,初始化容器一旦执行完,它从启动开始到初始化代码执行完就退出了,它不会一直存在,所以在主容器启动之前执行初始化,初始化容器可以有多个,多个初始化容器是要串行执行的,先执行初始化容器1,在执行初始化容器2等,等初始化容器执行完初始化就退出了,然后再执行主容器,主容器一退出,pod就结束了,主容器退出的时间点就是pod的结束点,它俩时间轴是一致的;

    Init容器

    Init容器就是做初始化工作的容器。可以有一个或多个,如果多个按照定义的顺序依次执行,只有所有的初始化容器执行完后,主容器才启动。由于一个Pod里的存储卷是共享的,所以Init Container里产生的数据可以被主容器使用到,Init Container可以在多种K8S资源里被使用到,如Deployment、DaemonSet, StatefulSet、Job等,但都是在Pod启动时,在主容器启动前执行,做初始化工作。

    Init容器与普通的容器区别是:

    1. Init 容器不支持 Readiness,因为它们必须在Pod就绪之前运行完成
    2. 每个Init容器必须运行成功,下一个才能够运行
    3. 如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止,然而,如果Pod对应的restartPolicy值为 Never,它不会重新启动。

    示例

    apiVersion: v1
    kind: Pod
    metadata:
      name: myapp-pod
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp-container
        image: busybox:1.28
        command: ['sh', '-c', 'echo The app is running! && sleep 3600']
      initContainers:
      - name: init-myservice
        image: busybox:1.28
        command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
      - name: init-mydb
        image: busybox:1.28
        command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
    

    主容器

    初始化容器启动之后,开始启动主容器,在主容器启动之前有一个post start hook(容器启动后钩子)和pre stop hook(容器结束前钩子),无论启动后还是结束前所做的事我们可以把它放两个钩子,这个钩子就表示用户可以用它来钩住一些命令,来执行它,做开场前的预设,结束前的清理,如awk有begin,end,和这个效果类似;

    • postStart:该钩子在容器被创建后立刻触发,通知容器它已经被创建。如果该钩子对应的hook handler执行失败,则该容器会被杀死,并根据该容器的重启策略决定是否要重启该容器,这个钩子不需要传递任何参数。
    • preStop:该钩子在容器被删除前触发,其所对应的hook handler必须在删除该容器的请求发送给Docker daemon之前完成。在该钩子对应的hook handler完成后不论执行的结果如何,Docker daemon会发送一个SGTERN信号量给Docker daemon来删除该容器,这个钩子不需要传递任何参数。

    在k8s中支持两类对pod的检测

    • livenessprobe(pod存活性探测):存活探针主要作用是,用指定的方式检测pod中的容器应用是否正常运行,如果检测失败,则认为容器不健康,那么Kubelet将根据Pod中设置的 restartPolicy来判断Pod 是否要进行重启操作,如果容器配置中没有配置 livenessProbe,Kubelet 将认为存活探针探测一直为成功状态。
    • readinessprobe(pod就绪性探测):用于判断容器中应用是否启动完成,当探测成功后才使Pod对外提供网络访问,设置容器Ready状态为true,如果探测失败,则设置容器的Ready状态为false。

    pod启动流程

    1. 用户使用kubectl create命令创建pod,请求提交给api-server
    2. api-server接到请求,将请求写入etcd数据库
    3. 同时api-server将请求也提交给调度器(scheduler)
    4. 调度器(scheduler)匹配好节点(node),并将节点返回给api-server
    5. api-server接收到相应节点(node)信息,将信息写入etcd数据库
    6. 同时提交创建pod的信息给相应节点(node)
    7. 对应节点收到创建pod的请求,将该请求发送给自身的docker,让docker执行后续操作并返回信息
    8. 对应节点创建完成pod后,将信息返回给api-server
    9. api-server收到节点的信息后,写入etcd数据库

    7.pod容器钩子

    • postStart:容器创建成功后,运行前的任务,用于资源部署、环境准备等。
    • preStop:在容器被终止前的任务,用于优雅关闭应用程序、通知其他系统等。
    ......
    containers:
    - image: sample:v2  
         name: war
         lifecycle:
          postStart:
           exec:
             command:
              - “cp”
              - “/sample.war”
              - “/app”
          prestop:
           httpGet:
            host: monitor.com
            path: /waring
            port: 8080
            scheme: HTTP
    ......
    

    以上示例中,定义了一个Pod,包含一个JAVA的web应用容器,其中设置了PostStart和PreStop回调函数。即在容器创建成功后,复制/sample.war到/app文件夹中。而在容器终止之前,发送HTTP请求到http://monitor.com:8080/waring,即向监控系统发送警告。

    优雅的删除资源对象
    当用户请求删除含有pod的资源对象时(如RC、deployment等),K8S为了让应用程序优雅关闭(即让应用程序完成正在处理的请求后,再关闭软件),K8S提供两种信息通知:

    1. 默认:K8S通知node执行docker stop命令,docker会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认超时时间(30s),会继续发送SIGKILL的系统信号强行kill掉进程。
    2. 使用pod生命周期(利用PreStop回调函数),它执行在发送终止信号之前。
      默认情况下,所有的删除操作的优雅退出时间都在30秒以内。kubectl delete命令支持--grace-period=的选项,以运行用户来修改默认值。0表示删除立即执行,并且立即从API中删除pod。在节点上,被设置了立即结束的的pod,仍然会给一个很短的优雅退出时间段,才会开始被强制杀死。如下:
        spec:
          containers:
          - name: nginx-demo
            image: centos:nginx
            lifecycle:
              preStop:
                exec:
                  # nginx -s quit gracefully terminate while SIGTERM triggers a quick exit
                  command: ["/usr/local/nginx/sbin/nginx","-s","quit"]
            ports:
              - name: http
                containerPort: 80
    

    8.pod容器探针

    • livenessProbe:存活性探测 当检测失败后,将杀死容器并根据 Pod 的重启策略来决定作出对应的措施。
      许多应用程序经过长时间运行,最终过渡到无法运行的状态,除了重启,无法恢复。通常情况下,K8S会发现应用程序已经终止,然后重启应用程序pod。有时应用程序可能因为某些原因(后端服务故障等)导致暂时无法对外提供服务,但应用软件没有终止,导致K8S无法隔离有故障的pod,调用者可能会访问到有故障的pod,导致业务不稳定。K8S提供livenessProbe来检测容器是否正常运行,并且对相应状况进行相应的补救措施。

    • readinessProbe:就绪性探测 当检测失败后,将 Pod 的 IP:Port 从对应的 EndPoint 列表中删除。
      在没有配置readinessProbe的资源对象中,pod中的容器启动完成后,就认为pod中的应用程序可以对外提供服务,该pod就会加入相对应的service,对外提供服务。但有时一些应用程序启动后,需要较长时间的加载才能对外服务,如果这时对外提供服务,执行结果必然无法达到预期效果,影响用户体验。比如使用tomcat的应用程序来说,并不是简单地说tomcat启动成功就可以对外提供服务的,还需要等待spring容器初始化,数据库连接上等等。

    目前LivenessProbe和ReadinessProbe两种探针都支持下面三种探测方法:

    • ExecAction:在容器中执行指定的命令,如果执行成功,退出码为 0 则探测成功。
    • TCPSocketAction:通过容器的 IP 地址和端口号执行 TCP 检 查,如果能够建立 TCP 连接,则表明容器健康。
    • HTTPGetAction:通过容器的IP地址、端口号及路径调用 HTTP Get方法,如果响应的状态码大于等于200且小于400,则认为容器健康

    探针探测结果有以下值:

    • Success:表示通过检测。
    • Failure:表示未通过检测。
    • Unknown:表示检测没有正常进行。

    Pod探针相关的属性: 探针(Probe)有许多可选字段,可以用来更加精确的控制Liveness和Readiness两种探针的行为

    • initialDelaySeconds: Pod启动后首次进行检查的等待时间,单位“秒”。
    • periodSeconds: 检查的间隔时间,默认为10s,单位“秒”。
    • timeoutSeconds: 探针执行检测请求后,等待响应的超时时间,默认为1s,单位“秒”。
    • successThreshold:连续探测几次成功,才认为探测成功,默认为 1,在 Liveness 探针中必须为1,最小值为1。
    • failureThreshold: 探测失败的重试次数,重试一定次数后将认为失败,在 readiness 探针中,Pod会被标记为未就绪,默认为 3,最小值为 1

    LivenessProbe 探针使用示例

    • 通过exec方式做健康探测:liveness-exec.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: liveness-exec
      labels:
        app: liveness
    spec:
      containers:
      - name: liveness
        image: busybox
        args:                       #创建测试探针探测的文件
        - /bin/sh
        - -c
        - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
        livenessProbe:
          initialDelaySeconds: 10   #延迟检测时间
          periodSeconds: 5          #检测时间间隔
          exec:
            command:
            - cat
            - /tmp/healthy
    

    容器在初始化后,首先创建一个 /tmp/healthy 文件,然后执行睡眠命令,睡眠 30 秒,到时间后执行删除 /tmp/healthy 文件命令。而设置的存活探针检检测方式为执行 shell 命令,用 cat 命令输出 healthy 文件的内容,如果能成功执行这条命令,存活探针就认为探测成功,否则探测失败。在前 30 秒内,由于文件存在,所以存活探针探测时执行 cat /tmp/healthy 命令成功执行。30 秒后 healthy 文件被删除,所以执行命令失败,Kubernetes 会根据 Pod 设置的重启策略来判断,是否重启 Pod。

    • 通过HTTP方式做健康探测:liveness-http.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: liveness-http
      labels:
        test: liveness
    spec:
      containers:
      - name: liveness
        image: mydlqclub/springboot-helloworld:0.0.1
        livenessProbe:
          initialDelaySeconds: 20   #延迟加载时间
          periodSeconds: 5          #重试时间间隔
          timeoutSeconds: 10        #超时时间设置
          httpGet:
            scheme: HTTP
            port: 8081
            path: /actuator/health
    

    上面 Pod 中启动的容器是一个 SpringBoot 应用,其中引用了 Actuator 组件,提供了 /actuator/health 健康检查地址,存活探针可以使用 HTTPGet 方式向服务发起请求,请求 8081 端口的 /actuator/health 路径来进行存活判断,任何大于或等于200且小于400的代码表示探测成功。
    任何其他代码表示失败。如果探测失败,则会杀死 Pod 进行重启操作。

    httpGet探测方式有如下可选的控制字段:

    1. scheme: 用于连接host的协议,默认为HTTP。
    2. host:要连接的主机名,默认为Pod IP,可以在http request head中设置host头部。
    3. port:容器上要访问端口号或名称。
    4. path:http服务器上的访问URI。
    5. httpHeaders:自定义HTTP请求headers,HTTP允许重复headers。
    • 通过TCP方式做健康探测:liveness-tcp.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: liveness-tcp
      labels:
        app: liveness
    spec:
      containers:
      - name: liveness
        image: nginx
        livenessProbe:
          initialDelaySeconds: 15
          periodSeconds: 20
          tcpSocket:
            port: 80
    

    TCP 检查方式和 HTTP 检查方式非常相似,在容器启动 initialDelaySeconds 参数设定的时间后,kubelet 将发送第一个 livenessProbe 探针,尝试连接容器的 80 端口,如果连接失败则将杀死 Pod 重启容器。

    ReadinessProbe 探针使用示例

    Pod 的ReadinessProbe 探针使用方式和 LivenessProbe 探针探测方法一样,也是支持三种,只是一个是用于探测应用的存活,一个是判断是否对外提供流量的条件。这里用一个 Springboot 项目,设置 ReadinessProbe 探测 SpringBoot 项目的 8081 端口下的 /actuator/health 接口,如果探测成功则代表内部程序以及启动,就开放对外提供接口访问,否则内部应用没有成功启动,暂不对外提供访问,直到就绪探针探测成功。

    • 示例文件:readiness-exec.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: springboot
      labels:
        app: springboot
    spec:
      type: NodePort
      ports:
      - name: server
        port: 8080
        targetPort: 8080
        nodePort: 31180
      - name: management
        port: 8081
        targetPort: 8081
        nodePort: 31181
      selector:
        app: springboot
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: springboot
      labels:
        app: springboot
    spec:
      containers:
      - name: springboot
        image: mydlqclub/springboot-helloworld:0.0.1
        ports:
        - name: server
          containerPort: 8080
        - name: management
          containerPort: 8081
        readinessProbe:
          initialDelaySeconds: 20   
          periodSeconds: 5          
          timeoutSeconds: 10   
          httpGet:
            scheme: HTTP
            port: 8081
            path: /actuator/health
    

    ReadinessProbe + LivenessProbe

    一般程序中需要设置两种探针结合使用,并且也要结合实际情况,来配置初始化检查时间和检测间隔,下面列一个简单的 SpringBoot 项目的 Deployment 例子。

    springboot.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: springboot
      labels:
        app: springboot
    spec:
      type: NodePort
      ports:
      - name: server
        port: 8080
        targetPort: 8080
        nodePort: 31180
      - name: management
        port: 8081
        targetPort: 8081
        nodePort: 31181
      selector:
        app: springboot
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: springboot
      labels:
        app: springboot
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: springboot
      template:
        metadata:
          name: springboot
          labels:
            app: springboot
        spec:
          containers:
          - name: readiness
            image: mydlqclub/springboot-helloworld:0.0.1
            ports:
            - name: server 
              containerPort: 8080
            - name: management
              containerPort: 8081
            readinessProbe:
              initialDelaySeconds: 20 
              periodSeconds: 5      
              timeoutSeconds: 10        
              httpGet:
                scheme: HTTP
                port: 8081
                path: /actuator/health
             livenessProbe:
                initialDelaySeconds: 30 
                periodSeconds: 10 
                timeoutSeconds: 5 
                httpGet:
                  scheme: HTTP
                  port: 8081
                  path: /actuator/health
    
  • 相关阅读:
    网易云课堂--妙味 《js基础课程》
    salesforce 零基础学习(五十八)通过sObject的field返回其对应的基础类型
    salesforce 零基础学习(五十七)Test 类中创建TestUser帮助类
    salesforce 零基础学习(五十六)实现getById
    salesforce 零基础学习(五十五)java通过SOAP方式定时访问某个文件然后插入到sObject中
    salesforce 零基础学习(五十四)常见异常友好消息提示
    salesforce 零基础学习(五十三)多个文件生成一个zip文件(使用git上封装的代码)
    salesforce 零基础学习(五十二)Trigger使用篇(二)
    salesforce 零基础学习(五十一)使用 Salesforce.com SOAP API 实现用户登录以及简单的增删改查(JAVA访问salesforce)
    salesforce 零基础学习(五十)自定义View或者List以及查看系统原来的View或者List
  • 原文地址:https://www.cnblogs.com/forlive/p/15942748.html
Copyright © 2020-2023  润新知