zoukankan      html  css  js  c++  java
  • 021.Kubernetes掌握Pod-Pod调度策略

    一 Pod生命周期管理

    1.1 Pod生命周期

    Pod在整个生命周期过程中被系统定义了如下各种状态。
    状态值
    描述
    Pending
    API Server已经创建该Pod,且Pod内还有一个或多个容器的镜像没有创建,包括正在下载镜像的过程。
    Running
    Pod内所有容器均已创建,且至少有一个容器处于运行状态、正在启动状态或正在重启状态。
    Succeeded
    Pod内所有容器均成功执行退出,且不会重启。
    Failed
    Pod内所有容器均已退出,但至少有一个容器退出为失败状态。
    Unknown
    由于某种原因无法获取该Pod状态,可能由于网络通信不畅导致。

    1.2 Pod重启策略

    Pod重启策略(RestartPolicy)应用于Pod内的所有容器,并且仅在Pod所处的Node上由kubelet进行判断和重启操作。当某个容器异常退出或者健康检查失败时,kubelet将根据RestartPolicy的设置来进行相应操作。
    Pod的重启策略包括Always、OnFailure和Never,默认值为Always。
    • Always:当容器失效时,由kubelet自动重启该容器;
    • OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器;
    • Never:不论容器运行状态如何,kubelet都不会重启该容器。

           kubelet重启失效容器的时间间隔以sync-frequency乘以2n来计算,例如1/2/4/8倍等,最长延时5min,并且在成功重启后的10min后重置该时间。

    Pod的重启策略与控制方式关联,当前可用于管理Pod的控制器包括ReplicationController、Job、DaemonSet及直接管理kubelet管理(静态Pod)。
    不同控制器的重启策略限制如下:
    • RC和DaemonSet:必须设置为Always,需要保证该容器持续运行;
    • Job:OnFailure或Never,确保容器执行完成后不再重启;
    • kubelet:在Pod失效时重启,不论将RestartPolicy设置为何值,也不会对Pod进行健康检查。

    Pod包含的容器数
    Pod当前的状态
    发生事件
    Pod的结果状态
    RestartPolicy=Always
    RestartPolicy=OnFailure
    RestartPolicy=Never
    包含1个容器
    Running
    容器成功退出
    Running
    Succeeded
    Succeeded
    包含1个容器
    Running
    容器失败退出
    Running
    Running
    Failed
    包括两个容器
    Running
    1个容器失败退出
    Running
    Running
    Running
    包括两个容器
    Running
    容器被OOM杀掉
    Running
    Running
    Failed

    1.3 Pod健康检查

    对Pod的健康检查可以通过两类探针来检查:LivenessProbe和ReadinessProbe。
    LivenessProbe探针:用于判断容器是否存活(running状态),如果LivenessProbe探针探测到容器不健康,则kubelet将杀掉该容器,并根据容器的重启策略做相应处理。若一个容器不包含LivenessProbe探针,kubelet认为该容器的LivenessProbe探针返回值用于是“Success”。
    ReadineeProbe探针:用于判断容器是否启动完成(ready状态)。如果ReadinessProbe探针探测到失败,则Pod的状态将被修改。Endpoint Controller将从Service的Endpoint中删除包含该容器所在Pod的Eenpoint。
    kubelet定期执行LivenessProbe探针来诊断容器的健康状态,通常有以下三种方式:
    • ExecAction:在容器内执行一个命令,若返回码为0,则表明容器健康。
    示例:通过执行"cat /tmp/health"命令判断一个容器运行是否正常。容器初始化并创建该文件,10s后删除该文件,15s秒通过命令判断,由于该文件已被删除,因此判断该容器Fail,导致kubelet杀掉该容器并重启。
      1 [root@uk8s-m-01 study]# vi dapi-liveness.yaml
      2 apiVersion: v1
      3 kind: Pod
      4 metadata:
      5   name: dapi-liveness-pod
      6   labels:
      7     test: liveness-exec
      8 spec:
      9   containers:
     10     - name: dapi-liveness
     11       image: busybox
     12       args:
     13       - /bin/sh
     14       - -c
     15       - echo ok > /tmp/health; sleep 10; rm -rf /tmp/health; sleep 600
     16       livenessProbe:
     17         exec:
     18           command:
     19           - cat
     20           - /tmp/health
     21 
     22 [root@uk8s-m-01 study]# kubectl describe pod dapi-liveness-pod
    clipboard
    • TCPSocketAction:通过容器的IP地址和端口号执行TCP检查,若能建立TCP连接,则表明容器健康。
    示例:
      1 [root@uk8s-m-01 study]# vi dapi-tcpsocket.yaml
      2 apiVersion: v1
      3 kind: Pod
      4 metadata:
      5   name: dapi-healthcheck-tcp
      6 spec:
      7   containers:
      8     - name: nginx
      9       image: nginx
     10       ports:
     11       - containerPort: 80
     12       livenessProbe:
     13         tcpSocket:
     14           port: 80
     15         initialDelaySeconds: 30
     16         timeoutSeconds: 1
     17 
     18 [root@uk8s-m-01 study]# kubectl create -f dapi-tcpsocket.yaml
    提示:对于每种探测方式,都需要设置如下两个参数,其包含的含义如下:
    initialDelaySeconds:启动容器后进行首次健康检查的等待时间,单位为s;
    timeoutSeconds:健康检查发送请求后等待响应的超时时间,单位为s,当超时发生时,kubelet会认为容器已经无法提供服务,将会重启该容器。

    二 Pod调度

    Kubernetes中,Pod通常是容器的载体,一般需要通过Deployment、DaemonSet、RC、Job等对象来完成一组Pod的调度与自动控制功能。

    2.1 Depolyment/RC自动调度

    Deployment或RC的主要功能之一就是自动部署一个容器应用的多份副本,以及持续监控副本的数量,在集群内始终维持用户指定的副本数量。
    示例:
      1 [root@uk8s-m-01 study]# vi nginx-deployment.yaml
      2 apiVersion: apps/v1beta1
      3 kind: Deployment
      4 metadata:
      5   name: nginx-deployment-01
      6 spec:
      7   replicas: 3
      8   template:
      9     metadata:
     10       labels:
     11         app: nginx
     12     spec:
     13       containers:
     14       - name: nginx
     15         image: nginx:1.7.9
     16         ports:
     17         - containerPort: 80
     18 
     19 [root@uk8s-m-01 study]# kubectl get deployments
     20 NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
     21 nginx-deployment-01   3/3     3            3           30s
     22 [root@uk8s-m-01 study]# kubectl get rs
     23 NAME                             DESIRED   CURRENT   READY   AGE
     24 nginx-deployment-01-5754944d6c   3         3         3       75s
     25 [root@uk8s-m-01 study]# kubectl get pod | grep nginx
     26 nginx-deployment-01-5754944d6c-hmcpg   1/1     Running     0          84s
     27 nginx-deployment-01-5754944d6c-mcj8q   1/1     Running     0          84s
     28 nginx-deployment-01-5754944d6c-p42mh   1/1     Running     0          84s

    2.2 NodeSelector定向调度

    当需要手动指定将Pod调度到特定Node上,可以通过Node的标签(Label)和Pod的nodeSelector属性相匹配。
    # kubectl label nodes <node-name> <label-key>=<label-value>
    node节点创建对应的label后,可通过在定义Pod的时候加上nodeSelector的设置实现指定的调度。
    示例:
      1 [root@uk8s-m-01 study]# kubectl label nodes 172.24.9.14 speed=io
      2 node/172.24.9.14 labeled
      3 [root@uk8s-m-01 study]# vi nginx-master-controller.yaml
      4 kind: ReplicationController
      5 metadata:
      6   name: nginx-master
      7   labels:
      8     name: nginx-master
      9 spec:
     10   replicas: 1
     11   selector:
     12     name: nginx-master
     13   template:
     14     metadata:
     15       labels:
     16         name: nginx-master
     17     spec:
     18       containers:
     19       - name: master
     20         image: nginx:1.7.9
     21         ports:
     22         - containerPort: 80
     23       nodeSelector:
     24         speed: io
     25 
     26 [root@uk8s-m-01 study]# kubectl create -f nginx-master-controller.yaml
     27 [root@uk8s-m-01 study]# kubectl get pods -o wide
     28 NAME                READY   STATUS    RESTARTS    AGE    IP            NODE
     29 nginx-master-7fjgj  1/1     Running   0           82s    172.24.9.71   172.24.9.14
    提示:可以将集群中具有不同特点的Node贴上不同的标签,实现在部署时就可以根据应用的需求设置NodeSelector来进行指定Node范围的调度。
    注意:若在定义Pod中指定了NodeSelector条件,但集群中不存在符合该标签的Node,即使集群有其他可供使用的Node,Pod也无法被成功调度。

    2.3 NodeAffinity亲和性调度

    亲和性调度机制极大的扩展了Pod的调度能力,主要增强功能如下:
    1. 更具表达力,即更精细的力度控制;
    2. 可以使用软限制、优先采用等限制方式,即调度器在无法满足优先需求的情况下,会使用其他次条件进行满足;
    3. 可以依据节点上正在运行的其他Pod的标签来进行限制,而非节点本身的标签,从而实现Pod之间的亲和或互斥关系。
    目前有两种节点亲和力表达:
    requiredDuringSchedulingIgnoredDuringExecution:硬规则,必须满足指定的规则,调度器才可以调度Pod至Node上(类似nodeSelector,语法不同)。
    preferredDuringSchedulingIgnoredDuringExecution:软规则,优先调度至满足的Node的节点,但不强求,多个优先级规则还可以设置权重值。
    IgnoredDuringExecution指:如果一个Pod所在的节点在Pod运行期间标签发生了变化,不再符合该Pod的节点亲和性需求,则系统将忽略Node上Label的变化,该Pod能继续在该节点运行。
    示例:
    条件1:只运行在amd64的节点上;尽量运行在ssd节点上。
      1 [root@uk8s-m-01 study]# vi nodeaffinity-pod.yaml
      2 apiVersion: v1
      3 kind: Pod
      4 metadata:
      5   name: with-node-affinity
      6 spec:
      7   affinity:
      8     nodeAffinity:
      9       requiredDuringSchedulingIgnoredDuringExecution:
     10         nodeSelectorTerms:
     11         - matchExpressions:
     12           - key: kubernetes.io/arch
     13             operator: In
     14             values:
     15             - amd64
     16       preferredDuringSchedulingIgnoredDuringExecution:
     17       - weight: 1
     18         preference:
     19           matchExpressions:
     20           - key: disk-type
     21             operator: In
     22             values:
     23             - ssd
     24   containers:
     25   - name: with-node-affinity
     26     image: gcr.azk8s.cn/google_containers/pause:2.0
    NodeAffinity操作语法;In、NotIn、Exists、DoesNotExist、Gt、Lt。NotIn和DoesNotExist可以实现互斥功能。
    NodeAffinity规则设置注意事项:
    • 若同时定义nodeSelector和nodeAffinity,则必须两个条件都满足,Pod才能最终运行指定在Node上;;
    • 若nodeAffinity指定多个nodeSelectorTerms,则只需要其中一个能够匹配成功即可;
    • 若nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有matchExpressions才能运行该Pod。

    2.4 PodAffinity亲和性调度

    PodAffinity根据节点上正在运行的Pod标签而不是Node标签来判断和调度,要求对节点和Pod两个条件进行匹配。
    规则描述为:若在具有标签X的Node上运行了一个或多个符合条件Y的Pod,则Pod应该(或者不应该)运行在这个Node上。
    X通常为Node节点的机架、区域等概念,Pod是属于某个命名空间,所以条件Y表达的是一个或全部命名空间中的一个Label Selector。
    Pod亲和性定义与PodSpec的affinity字段下的podAffinity字段里,互斥性定义于同一层次的podAntiAffinity子字段中。
    举例:
      1 [root@uk8s-m-01 study]# vi nginx-flag.yaml	#创建名为pod-flag,带有两个标签的Pod
      2 apiVersion: v1
      3 kind: Pod
      4 metadata:
      5   name: pod-affinity
      6 spec:
      7   affinity:
      8     podAffinity:
      9       requiredDuringSchedulingIgnoredDuringExecution:
     10       - labelSelector:
     11           matchExpressions:
     12           - key: security
     13             operator: In
     14             values:
     15             - S1
     16         topologyKey: kubernetes.io/hostname
     17   containers:
     18   - name: with-pod-affinity
     19     image: gcr.azk8s.cn/google_containers/pause:2.0
      1 [root@uk8s-m-01 study]# vi nginx-affinity-in.yaml	#创建定义标签security=S1,对应如上Pod “Pod-flag”。
      2 apiVersion: v1
      3 kind: Pod
      4 metadata:
      5   name: pod-affinity
      6 spec:
      7   affinity:
      8     podAffinity:
      9       requiredDuringSchedulingIgnoredDuringExecution:
     10       - labelSelector:
     11           matchExpressions:
     12           - key: security
     13             operator: In
     14             values:
     15             - S1
     16         topologyKey: kubernetes.io/hostname
     17   containers:
     18   - name: with-pod-affinity
     19     image: gcr.azk8s.cn/google_containers/pause:2.0
     20 
     21 [root@uk8s-m-01 study]# kubectl create -f nginx-affinity-in.yaml
     22 [root@uk8s-m-01 study]# kubectl get pods -o wide
    clipboard
    提示:由上Pod亲和力可知,两个Pod处于同一个Node上。
      1 [root@uk8s-m-01 study]# vi nginx-affinity-out.yaml	#创建不能与参照目标Pod运行在同一个Node上的调度策略
      2 apiVersion: v1
      3 kind: Pod
      4 metadata:
      5   name: anti-affinity
      6 spec:
      7   affinity:
      8     podAffinity:
      9       requiredDuringSchedulingIgnoredDuringExecution:
     10       - labelSelector:
     11           matchExpressions:
     12           - key: security
     13             operator: In
     14             values:
     15             - S1
     16         topologyKey: failure-domain.beta.kubernetes.io/zone
     17     podAntiAffinity:
     18       requiredDuringSchedulingIgnoredDuringExecution:
     19       - labelSelector:
     20           matchExpressions:
     21           - key: security
     22             operator: In
     23             values:
     24             - nginx
     25         topologyKey: kubernetes.io/hostname
     26   containers:
     27   - name: anti-affinity
     28     image: gcr.azk8s.cn/google_containers/pause:2.0
     29 
     30 [root@uk8s-m-01 study]# kubectl get pods -o wide	#验证

    2.5 Taints和Tolerations(污点和容忍)

    Taint:使Node拒绝特定Pod运行;
    Toleration:为Pod的属性,表示Pod能容忍(运行)标注了Taint的Node。
    Taint语法:$ kubectl taint node node1 key=value:NoSchedule
    解释:为node1加上一个Taint,该Taint的键为key,值为value,Taint的效果为NoSchedule。即除非特定声明可以容忍此Taint,否则不会调度至node1上。
    Toleration示例:
      1 tolerations:
      2 - key: "key"
      3   operator: "Equal"
      4   value: "value"
      5   effect: "NoSchedule"
      1 tolerations:
      2 - key: "key"
      3   operator: "Exists"
      4   effect: "NoSchedule"
    注意:Pod的Toleration声明中的key和effect需要与Taint的设置保持一致,并且满足以下条件:
    • operator的值是Exists(无须指定value);
    • operator的值是Equal并且value相等;
    • 空的key配合Exists操作符能够匹配所有的键和值;
    • 空的effect匹配所有的effect。
    若不指定operator,则默认值为Equal。
    taint说明:系统允许在同一个Node上设置多个taint,也可以在Pod上设置多个toleration。Kubernetes调度器处理多个taint和toleration的逻辑顺序:首先列出节点中所有的taint,然后忽略pod的toleration能够匹配的部分,剩下的没有忽略掉的taint就是对pod的效果。以下是几种特殊情况:
    若剩余的taint中存在effect=NoSchedule,则调度器不会把该Pod调度到这一节点上;
    若剩余的taint中没有NoSchedule效果,但有PreferNoSchedule效果,则调度器会尝试不把这个Pod指派到此节点;
    若剩余taint的效果有NoSchedule,并且这个Pod已经在该节点上运行,则会被驱逐,若没有在该节点上运行,也不会再被调度到该节点上。
    示例:
      1 $ kubectl taint node node1 key=value1:NoSchedule
      2 $ kubectl taint node node1 key=value1:NoExecute
      3 $ kubectl taint node node1 key=value2:NoSchedule
      4 tolerations:
      5 - key: "key1"
      6   operator: "Equal"
      7   value: "value"
      8   effect: "NoSchedule"
      9 tolerations:
     10 - key: "key1"
     11   operator: "Equal"
     12   value: "value1"
     13   effect: "NoExecute"
    释义:此Pod声明了两个容忍,且能匹配Node1的taint,但是由于没有能匹配第三个taint的toleration,因此此Pod依旧不能调度至此Node。若该Pod已经在node1上运行了,那么在运行时设置了第3个taint,它还能继续在node1上运行,这是因为Pod可以容忍前两个taint。
    通常,若node加上effect=NoExecute的taint,那么该Node上正在运行的所有无对应toleration的Pod都会被立刻驱逐,而具有相应toleration的Pod则永远不会被驱逐。同时,系统可以给具有NoExecute效果的toleration加入一个可选的tolerationSeconds字段,表明Pod可以在taint添加到Node之后还能在此Node运行多久。
      1 tolerations:
      2 - key: "key1"
      3   operator: "Equal"
      4   value: "value"
      5   effect: "NoSchedule"
      6   tolerationSeconds: 3600
    释义:若Pod正在运行,所在节点被加入一个匹配的taint,则这个pod会持续在该节点运行3600s后被驱逐。若在此期限内,taint被移除,则不会触发驱逐事件。
    Taints和Tolerations常用场景:
    • 独占节点:
    给特定的节点运行特定应用。
    $ kubectl taint nodes 【nodename】 dedicated=groupName:NoSchedule
    同时在Pod中设置对应的toleration配合,带有合适toleration的Pod允许同时使用其他节点一样使用有taint的节点。
    • 具有特殊硬件设备的节点
    集群中部分特殊硬件(如安装了GPU),则可以把不需要占用GPU的Pod禁止在此Node上调度。
      1 $ kubectl taint nodes 【nodename】 special=true:NoSchedule
      2 $ kubectl taint nodes 【nodename】 special=true:PreferNoSchedule
    • 定义Pod驱逐行为
    NoExecute的taint对节点上正在运行的Pod有以下影响:
      1. 没有设置toleration的pod会被立刻驱逐;
      2. 配置了对应toleration的pod,若没有为tolerationSeconds赋值,则会一直保留在此节点中;
      3. 配置了对应toleration的pod,且为tolerationSeconds赋值,则在指定时间后驱逐。

    2.6 DaemonSet

    DaemonSet是在每个Node上调度一个Pod的资源对象,用于管理集群中每个Node仅运行一份Pod的副本实例。
    clipboard
    常见场景:
    在每个Node上运行一个GlusterFS存储的Daemon进程;
    在每个Node上运行一个日志采集程序,例如Fluentd;
    在每个Node上运行一个性能监控程序,采集该Node的运行性能数据,例如Prometheus。
    示例:
      1 [root@uk8s-m-01 study]# vi fluentd-ds.yaml
      2 apiVersion: extensions/v1beta1
      3 kind: DaemonSet
      4 metadata:
      5   name: fluentd-cloud-logging
      6   namespace: kube-system
      7   labels:
      8     k8s-app: fluentd-cloud-logging
      9 spec:
     10   template:
     11     metadata:
     12       namespace: kube-system
     13       labels:
     14         k8s-app: fluentd-cloud-logging
     15     spec:
     16       containers:
     17       - name: fluentd-cloud-logging
     18         image: gcr.azk8s.cn/google_containers/fluentd-elasticsearch:1.17
     19         resources:
     20           limits:
     21             cpu: 100m
     22             memory: 200Mi
     23         env:
     24         - name: FLUENTD_ARGS
     25           value: -q
     26         volumeMounts:
     27         - name: varlog
     28           mountPath: /var/log
     29           readOnly: false
     30         - name: containers
     31           mountPath: /var/lib/docker/containers
     32           readOnly: false
     33       volumes:
     34       - name: containers
     35         hostPath:
     36           path: /var/lib/docker/containers
     37       - name: varlog
     38         hostPath:
     39           path: /var/log
    clipboard

    2.7 Job批处理调度

    clipboard
    通过Kubernetes Job资源对象可以定义并启动一个批处理任务,批处理任务通过并行(或者串行)启动多个计算进程去处理一批工作项。根据批处理方式不同,批处理任务可以分为如下几种模式:
    Job Template Expansion模式:一个Job对象对应一个待处理的Work item,有几个work item就产生几个独立的Job。通常适合Work item数量少、每个Work item要处理的数据量比较大的场景。
    Queue with Pod Per Work Item模式:采用一个任务队列存放Work item,一个Job对象作为消费者去完成这些Work item。此模式下,Job会启动N个Pod,每个Pod都对应一个Work item。
    Queue with Variable Pod Count模式:采用一个任务队列存放Work item,一个Job对象作为消费者去完成这些Work item,但此模式下Job启动的数量是可变的。
    Kubernetes将Job氛围以下三类:
    • Non-parallel Jobs
    通常一个Job只启动一个Pod,除非Pod异常,才会重启该Pod,一旦此Pod正常结束,Job将结束。
    • Parallel Jobs with a fixed completion count
    并行Job会启动多个Pod,此时需要设定Job的.spec.completions参数为一个正数,当正常结束的Pod数量达至此参数设定的值后,Job结束。同时.spec.parallelism参数用来控制并行度,即同时启动几个Job来处理Work Item。
    • Parallel Jobs with a work queue
    任务队列方式的并行Job需要一个独立的Queue,Work Item都在一个Queue中存放,不能设置Job的.spec.completions参数,此时Job具有以下特性:
      1. 每个Pod都能独立判断和决定是否还有任务项需要处理;
      2. 如果某个Pod正常结束,则Job不会再启动新的Pod;
      3. 如果一个Pod成功结束,则此时应该不存在其他Pod还在工作的情况。它们应该都处于即将结束、退出的状态;
      4. 如果所有Pod都结束了,且至少有一个Pod成功结束,则整个Jod成功结束。

    2.8 Cronjob定时任务

    表达式:Minutes Hours DayofMonth Month DayofWeek Year
    Minutes:可出现","、"_"、"*"、"/",有效范围为0~59的整数;
    Hours:出现","、"_"、"*"、"/",有效范围为0~23的整数;
    DayofMonth:出现","、"_"、"*"、"/"、"L"、"W"、"C",有效范围为0~31的整数;
    Month:可出现","、"_"、"*"、"/",有效范围为1~12的整数或JAN~DEC;
    DayofWeek:出现","、"_"、"*"、"/"、"L"、"W"、"C"、"#",有效范围为1~7的整数或SUN~SAT;
    *: 表示匹配该域的任意值, 假如在Minutes域使用“*”, 则表示每分钟都会触发事件。
    /: 表示从起始时间开始触发, 然后每隔固定时间触发一次,例如在Minutes域设置为5/20, 则意味着第1次触发在第5min时, 接下来每20min触发一次, 将在第25min、 第45min等时刻分别触发。
    示例:*/1 * * * * #每隔1min执行一次任务
      1 [root@uk8s-m-01 study]# vi cron.yaml
      2 apiVersion: batch/v2alpha1
      3 kind: CronJob
      4 metadata:
      5   name: hello
      6 spec:
      7   schedule: "*/1 * * * *"
      8   jobTemplate:
      9     spec:
     10       template:
     11         spec:
     12           containers:
     13           - name: hello
     14             image: busybox
     15             args:
     16             - /bin/sh
     17             - -c
     18             - date; echo Hello from the Kubernetes cluster
     19           restartPolicy: OnFailure
      1 [root@master study]# kubectl create -f cron.yaml
      2 [root@master study]# kubectl get cronjob hello
      3 NAME    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
      4 hello   */1 * * * *   False     0        <none>          29s
      5 [root@master study]# kubectl get pods
      6 NAME                     READY   STATUS      RESTARTS   AGE
      7 hello-1573378080-zvvm5   0/1     Completed   0          68s
      8 hello-1573378140-9pmwz   0/1     Completed   0          8s
      9 [root@node1 ~]# docker logs c7					#node节点查看日志
     10 Sun Nov 10 09:31:13 UTC 2019
     11 Hello from the Kubernetes cluster
     12 [root@master study]# kubectl get jobs				#查看任务
     13 NAME               COMPLETIONS   DURATION   AGE
     14 hello-1573378500   1/1           8s         3m7s
     15 hello-1573378560   1/1           4s         2m7s
     16 hello-1573378620   1/1           6s         67s
     17 hello-1573378680   1/1           4s         7s
     18 [root@master study]# kubectl get pods -o wide | grep hello-1573378680	#以job任务查看对应的pod
     19 [root@master study]# kubectl delete cj hello			#删除cronjob

    2.9 初始化容器

    在很多应用场景中, 应用在启动之前都需要进行如下初始化操作。
    • 等待其他关联组件正确运行( 例如数据库或某个后台服务) 。
    • 基于环境变量或配置模板生成配置文件。
    • 从远程数据库获取本地所需配置, 或者将自身注册到某个中央数据库中。
    • 下载相关依赖包, 或者对系统进行一些预配置操作。
    示例:以Nginx应用为例, 在启动Nginx之前, 通过初始化容器busybox为Nginx创建一个index.html主页文件。同时init container和Nginx设置了一个共享的Volume, 以供Nginx访问init container设置的index.html文件。
      1 [root@uk8s-m-01 study]# vi nginx-init-containers.yaml
      2 apiVersion: v1
      3 kind: Pod
      4 metadata:
      5   name: nginx
      6   annotations:
      7 spec:
      8   initContainers:
      9   - name: install
     10     image: busybox
     11     command:
     12     - wget
     13     - "-O"
     14     - "/work-dir/index.html"
     15     - http://kubernetes.io
     16     volumeMounts:
     17     - name: workdir
     18       mountPath: "/work-dir"
     19   containers:
     20   - name: nginx
     21     image: nginx:1.7.9
     22     ports:
     23     - containerPort: 80
     24     volumeMounts:
     25     - name: workdir
     26       mountPath: /usr/share/nginx/html
     27   dnsPolicy: Default
     28   volumes:
     29   - name: workdir
     30     emptyDir: {}
      1 [root@uk8s-m-01 study]# kubectl get pods
      2 NAME    READY   STATUS     RESTARTS   AGE
      3 nginx   0/1     Init:0/1   0          2s
      4 [root@uk8s-m-01 study]# kubectl get pods
      5 NAME    READY   STATUS    RESTARTS   AGE
      6 nginx   1/1     Running   0          13s
      7 [root@uk8s-m-01 study]# kubectl describe pod nginx		#查看事件可知会先创建init容器,名为install
    init容器与应用容器的区别如下。
    (1) init container的运行方式与应用容器不同, 它们必须先于应用容器执行完成, 当设置了多个init container时, 将按顺序逐个运行, 并且只有前一个init container运行成功后才能运行后一个init container。 当所有init container都成功运行后, Kubernetes才会初始化Pod的各种信息, 并开始创建和运行应用容器。
    (2) 在init container的定义中也可以设置资源限制、 Volume的使用和安全策略, 等等。 但资源限制的设置与应用容器略有不同。
    • 如果多个init container都定义了资源请求/资源限制, 则取最大的值作为所有init container的资源请求值/资源限制值。
    • Pod的有效(effective) 资源请求值/资源限制值取以下二者中的较大值。
      • 所有应用容器的资源请求值/资源限制值之和。
      • init container的有效资源请求值/资源限制值。
    • 调度算法将基于Pod的有效资源请求值/资源限制值进行计算,即init container可以为初始化操作预留系统资源, 即使后续应用容器无须使用这些资源。
    • Pod的有效QoS等级适用于init container和应用容器。
    • 资源配额和限制将根据Pod的有效资源请求值/资源限制值计算生效。
    • Pod级别的cgroup将基于Pod的有效资源请求/限制, 与调度机制
    一致。
    (3) init container不能设置readinessProbe探针, 因为必须在它们成功运行后才能继续运行在Pod中定义的普通容器。在Pod重新启动时, init container将会重新运行, 常见的Pod重启场景如下。
    • init container的镜像被更新时, init container将会重新运行, 导致Pod重启。 仅更新应用容器的镜像只会使得应用容器被重启。
    • Pod的infrastructure容器更新时, Pod将会重启。
    • 若Pod中的所有应用容器都终止了, 并且RestartPolicy=Always, 则Pod会重启。
  • 相关阅读:
    C#流(stream)
    高并发图片(缩略图)处理中间层服务架构设计
    WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化
    我们一起学习WCF 第六篇文件传输
    远程服务器返回了意外相应:(413) Request Entity Too Large。
    三层架构
    传说中的WCF(9):流与文件传输
    分享WCF文件传输---WCFFileTransfer
    分享基于EF+WCF的通用三层架构及解析
    Winform开发框架之框架演化
  • 原文地址:https://www.cnblogs.com/itzgr/p/11904794.html
Copyright © 2011-2022 走看看