Pod中如何管理多个容器

Pod中可以同时运行多个进程(作为容器运行)协同工作。同一个Pod中的容器会自动的分配到同一个 node 上。同一个Pod中的容器共享资源、网络环境和依赖,它们总是被同时调度。

注意在一个Pod中同时运行多个容器是一种比较高级的用法。只有当你的容器需要紧密配合协作的时候才考虑用这种模式。例如,你有一个容器作为web服务器运行,需要用到共享的volume,有另一个“sidecar”容器来从远端获取资源更新这些文件,如下图所示:

一个容器里运行多个应用程序 一个pod运行多个容器_Pod

 

Pod中可以共享两种资源:网络和存储。
  •  网络:每个Pod都会被分配一个唯一的IP地址。Pod中的所有容器共享网络空间,包括IP地址和端口。Pod内部的容器可以使用localhost互相通信。Pod中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)。
  • 存储:可以Pod指定多个共享的Volume。Pod中的所有容器都可以访问共享的volume。Volume也可以用来持久化Pod中的存储资源,以防容器重启后文件丢失。
Pod容器分类

•Infrastructure Container:基础容器,维护整个Pod网络空间
•InitContainers:初始化容器,先于业务容器开始执行
•Containers:业务容器,并行启动

kubernetes中pod创建流程

Pod是Kubernetes中最基本的部署调度单元,可以包含container,逻辑上表示某种应用的一个实例。例如一个web站点应用由前端、后端及数据库构建而成,这三个组件将运行在各自的容器中,那么我们可以创建包含三个container的pod。

一个容器里运行多个应用程序 一个pod运行多个容器_Pod_02

具体的创建步骤包括:
(1)客户端提交创建请求,可以通过API Server的Restful API,也可以使用kubectl命令行工具。支持的数据类型包括JSON和YAML。
(2)API Server处理用户请求,存储Pod数据到etcd。
(3)调度器通过API Server查看未绑定的Pod。尝试为Pod分配主机。
(4)过滤主机 (调度预选):调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。
(5)主机打分(调度优选):对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把容一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等。
(6)选择主机:选择打分最高的主机,进行binding操作,结果存储到etcd中。
(7)kubelet根据调度结果执行Pod创建操作: 绑定成功后,scheduler会调用APIServer的API在etcd中创建一个boundpod对象,描述在一个工作节点上绑定运行的所有pod信息。运行在每个工作节点上的kubelet也会定期与etcd同步boundpod信息,一旦发现应该在该工作节点上运行的boundpod对象没有更新,则调用Docker API创建并启动pod内的容器。

调度约束

https://kubernetes.io/docs/concepts/configuration/assign-pod-node/

scheduler组件

k8s调度器会将pod调度到资源满足要求并且评分最高的node上。

我们可以使用多种规则比如:
1.设置cpu、内存的使用要求
2.增加node的label,并通过pod.Spec.NodeSelector进行强匹配;
3.直接设置pod的nodeName,跳过调度直接下发。
k8s 1.2加入了一个实验性的功能:affinity。意为亲和性。这个特性的设计初衷是为了替代nodeSelector,并扩展更强大的调度策略。

调度器的工作机制是这样的

一、预备工作
1、缓存所有的node节点,记录他们的规格:cpu、内存、磁盘空间、gpu显卡数等;
2、缓存所有运行中的pod,按照pod所在的node进行区分,统计每个node上的pod request了多少资源。request是pod的QoS配置。
3、list & watch pod资源,当检查到有新的Pending状态的pod出现,就将它加入到调度队列中。
4、调度器的worker组件从队列中取出pod进行调度。
二、调度过程
1、先将当前所有的node放入队列;
2、执行predicates算法,对队列中的node进行筛选。这里算法检查了一些pod运行的必要条件,包括port不冲突、cpu和内存资源QoS(如果有的话)必须满足、挂载volume(如果有的话)类型必须匹配、nodeSelector规则必须匹配、硬性的affinity规则(下文会提到)必须匹配、node的状态(condition)必须正常,taint_toleration硬规则(下文会提到)等等。
3、执行priorities算法,对队列中剩余的node进行评分,这里有许多评分项,各个项目有各自的权重:整体cpu,内存资源的平衡性、node上是否有存在要求的镜像、同rs的pod是否有调度、node affinity的软规则、taint_toleration软规则(下文会提到)等等。
4、最终评分最高的node会被选出。即代码中suggestedHost, err := sched.schedule(pod)一句(plugin/pkg/scheduler/scheduler.go)的返回值。
5、调度器执行assume方法,该方法在pod调度到node之前,就以“该pod运行在目标node上” 为场景更新调度器缓存中的node 信息,也即预备工作中的1、2两点。这么做是为了让pod在真正调度到node上时,调度器也可以同时做后续其他pod的调度工作。
6、调度器执行bind方法,该方法创建一个Binding资源,apiserver检查到创建该资源时,会主动更新pod的nodeName字段。完成调度

nodeSelector用于将Pod调度到匹配Label的Node上

将标签附加到node

[root@k8s-master1 ~]# kubectl label nodes 192.168.0.126 env_role=dev
node/192.168.0.126 labeled
[root@k8s-master1 ~]# kubectl label nodes 192.168.0.125 env_role=test
node/192.168.0.125 labeled
[root@k8s-master1 ~]# kubectl get nodes --show-labels
NAME            STATUS   ROLES    AGE    VERSION   LABELS
192.168.0.125   Ready    <none>   2d4h   v1.13.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=test,kubernetes.io/hostname=192.168.0.125
192.168.0.126   Ready    <none>   2d4h   v1.13.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=dev,kubernetes.io/hostname=192.168.0.126

将nodeSelector字段添加到pod配置中

[root@k8s-master1 ~]# vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    env_role: dev

[root@k8s-master1 ~]# kubectl create -f pod2.yaml 
pod/nginx created

查看pod

一个容器里运行多个应用程序 一个pod运行多个容器_nginx_03

一个容器里运行多个应用程序 一个pod运行多个容器_nginx_04

[root@k8s-master1 ~]# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          115s
[root@k8s-master1 ~]# kubectl describe pod nginx
Name:               nginx
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               192.168.0.126/192.168.0.126
Start Time:         Fri, 21 Dec 2018 14:07:49 +0800
Labels:             <none>
Annotations:        <none>
Status:             Running
IP:                 172.17.92.2
Containers:
  nginx:
    Container ID:   docker://8c7e442cc83b6532b3bda707f389fa371861d173e9395149bbede9e166bf559c
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:1a0043cfb1987774c6981c41e49f758c58ace64c30e1c4ecff5cedff0b5c88da
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Fri, 21 Dec 2018 14:07:50 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-7vs6s (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-7vs6s:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-7vs6s
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  env_role=dev
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age    From                    Message
  ----    ------     ----   ----                    -------
  Normal  Scheduled  2m11s  default-scheduler       Successfully assigned default/nginx to 192.168.0.126
  Normal  Pulled     2m11s  kubelet, 192.168.0.126  Container image "nginx" already present on machine
  Normal  Created    2m10s  kubelet, 192.168.0.126  Created container
  Normal  Started    2m10s  kubelet, 192.168.0.126  Started container

View Code

nodeName用于将Pod调度到指定的Node名称上

spec.nodeName用于强制约束将Pod调度到指定的Node节点上,这里说是“调度”,但其实指定了nodeName的Pod会直接跳过Scheduler的调度逻辑,直接写入PodList列表,该匹配规则是强制匹配。

[root@k8s-master1 ~]# vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-example
  labels:
    app: nginx
spec:
  nodeName: 192.168.0.125
  containers:
  - name: nginx
    image: nginx:1.15

[root@k8s-master1 ~]# kubectl create -f pod3.yaml 
pod/pod-example created

查看pod

一个容器里运行多个应用程序 一个pod运行多个容器_nginx_03

一个容器里运行多个应用程序 一个pod运行多个容器_nginx_04

[root@k8s-master1 ~]# kubectl get pod
NAME          READY   STATUS    RESTARTS   AGE
nginx         1/1     Running   0          10m
pod-example   1/1     Running   0          22s
[root@k8s-master1 ~]# kubectl describe pod pod-example
Name:               pod-example
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               192.168.0.125/192.168.0.125
Start Time:         Fri, 21 Dec 2018 14:17:47 +0800
Labels:             app=nginx
Annotations:        <none>
Status:             Running
IP:                 172.17.19.2
Containers:
  nginx:
    Container ID:   docker://5e33eacb41e9b4ffd072141af63209229543105feb804d23b72a09be9e414409
    Image:          nginx:1.15
    Image ID:       docker-pullable://nginx@sha256:5d32f60db294b5deb55d078cd4feb410ad88e6fe77500c87d3970eca97f54dba
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Fri, 21 Dec 2018 14:17:48 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-7vs6s (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-7vs6s:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-7vs6s
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason   Age   From                    Message
  ----    ------   ----  ----                    -------
  Normal  Pulled   31s   kubelet, 192.168.0.125  Container image "nginx:1.15" already present on machine
  Normal  Created  31s   kubelet, 192.168.0.125  Created container
  Normal  Started  30s   kubelet, 192.168.0.125  Started container

View Code

从私有镜像仓库拉取镜像

参考:https://kubernetes.io/docs/concepts/containers/images/

查看docker登陆私有仓库的凭据

[root@k8s-node01 ~]# cat .docker/config.json |base64 -w 0
ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjAuMTIyIjogewoJCQkiYXV0aCI6ICJiM0J6T2xCQWMzTjNNSEprIgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xOC4wOS4wIChsaW51eCkiCgl9Cn0=

创建Secret   

[root@k8s-master1 tomcat]# vim registry-pull-secret.yaml 
apiVersion: v1
kind: Secret
metadata:
  name: registry-pull-secret
data:
  .dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjAuMTIyIjogewoJCQkiYXV0aCI6ICJiM0J6T2xCQWMzTjNNSEprIgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xOC4wOS4wIChsaW51eCkiCgl9Cn0=
type: kubernetes.io/dockerconfigjson

[root@k8s-master1 tomcat]# kubectl create -f registry-pull-secret.yaml 
secret/registry-pull-secret created
[root@k8s-master1 tomcat]# kubectl get secret
NAME                   TYPE                                  DATA   AGE
default-token-7vs6s    kubernetes.io/service-account-token   3      44h
registry-pull-secret   kubernetes.io/dockerconfigjson        1      23s

创建pod时,设置从私有仓库拉取镜像

一个容器里运行多个应用程序 一个pod运行多个容器_nginx_03

一个容器里运行多个应用程序 一个pod运行多个容器_nginx_04

[root@k8s-master1 tomcat]# vim tomcat.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: tomcat-deployment
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      imagePullSecrets:
      - name: registry-pull-secret          #secret 登陆仓库的凭据
      containers:
      - name: tomcat
        image: 192.168.0.122/ceba/tomcat       #镜像地址
        imagePullPolicy: Always            #设置每次创建pod都重新拉取镜像
        ports:
        - containerPort: 8080

---

apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
  labels:
    app: tomcat
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: tomcat

View Code

镜像拉取策略

•IfNotPresent:默认值,镜像在宿主机上不存在时才拉取
•Always:每次创建Pod 都会重新拉取一次镜像
•Never:Pod 永远不会主动拉取这个镜像

查看拉取的镜像正常启动

[root@k8s-master1 tomcat]# kubectl get pod,svc,deploy
NAME                                     READY   STATUS    RESTARTS   AGE
pod/tomcat-deployment-6bb6864d4f-4xj82   1/1     Running   0          65s
pod/tomcat-deployment-6bb6864d4f-drcjc   1/1     Running   0          47s
pod/tomcat-deployment-6bb6864d4f-wmkxx   1/1     Running   0          45s

NAME                     TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
service/kubernetes       ClusterIP   10.0.0.1     <none>        443/TCP        44h
service/tomcat-service   NodePort    10.0.0.3     <none>        80:49014/TCP   8m20s

NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/tomcat-deployment   3/3     3            3           8m20s

 资源限制

创建Pod的时候,可以指定计算资源(目前支持的资源类型有CPU和内存),即指定每个容器的资源请求(Request)和资源限制(Limit),资源请求是容器所需的最小资源需求,资源限制则是容器不能超过的资源上限。它们的大小关系是:0<=request<=limit<=infinity

  Pod的资源请求就是Pod中容器资源请求之和。Kubernetes在调度Pod时,会根据Node中的资源总量(通过cAdvisor接口获得),以及该Node上已使用的计算资源,来判断该Node是否满足需求。

  资源请求能够保证Pod有足够的资源来运行,而资源限制则是防止某个Pod无限制地使用资源,导致其他Pod崩溃。特别是在公有云场景,往往会有恶意软件通过抢占内存来攻击平台。

  原理:Docker 通过使用Linux Cgroup来实现对容器资源的控制,具体到启动参数上是--memory和--cpu-shares。Kubernetes中是通过控制这两个参数来实现对容器资源的控制。

Pod和Container的资源请求和限制:
•spec.containers[].resources.limits.cpu
•spec.containers[].resources.limits.memory
•spec.containers[].resources.requests.cpu
•spec.containers[].resources.requests.memory

示例

以下Pod有两个容器。每个Container都有0.25 cpu和64MiB内存的请求。每个Container的内存限制为0.5 cpu和128MiB。你可以说Pod有0.5 cpu和128 MiB内存的请求,并且限制为1 cpu和256MiB的内存。

[root@k8s-master1 ~]# vim pod1.yaml 

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: db
    image: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: wp
    image: wordpress
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

查看node节点资源使用情况

一个容器里运行多个应用程序 一个pod运行多个容器_nginx_03

一个容器里运行多个应用程序 一个pod运行多个容器_nginx_04

[root@k8s-master1 ~]# kubectl describe pod frontend | grep -A 3 Events
Events:
  Type     Reason          Age                From                    Message
  ----     ------          ----               ----                    -------
  Normal   Scheduled       19m                default-scheduler       Successfully assigned default/frontend to 192.168.0.125
[root@k8s-master1 ~]# kubectl describe nodes 192.168.0.125
Name:               192.168.0.125
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/hostname=192.168.0.125
Annotations:        node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Wed, 19 Dec 2018 09:54:14 +0800
Taints:             <none>
Unschedulable:      false
Conditions:
  Type             Status    LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----             ------    -----------------                 ------------------                ------                       -------
  MemoryPressure   False     Thu, 20 Dec 2018 17:26:03 +0800   Thu, 20 Dec 2018 10:29:48 +0800   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure     False     Thu, 20 Dec 2018 17:26:03 +0800   Thu, 20 Dec 2018 10:29:48 +0800   KubeletHasNoDiskPressure     kubelet has no disk pressure
  PIDPressure      False     Thu, 20 Dec 2018 17:26:03 +0800   Thu, 20 Dec 2018 10:29:48 +0800   KubeletHasSufficientPID      kubelet has sufficient PID available
  Ready            True      Thu, 20 Dec 2018 17:26:03 +0800   Thu, 20 Dec 2018 10:29:48 +0800   KubeletReady                 kubelet is posting ready status
  OutOfDisk        Unknown   Wed, 19 Dec 2018 09:54:14 +0800   Wed, 19 Dec 2018 13:23:20 +0800   NodeStatusNeverUpdated       Kubelet never posted node status.
Addresses:
  InternalIP:  192.168.0.125
  Hostname:    192.168.0.125
Capacity:
 cpu:                2
 ephemeral-storage:  80699908Ki
 hugepages-1Gi:      0
 hugepages-2Mi:      0
 memory:             3861520Ki
 pods:               110
Allocatable:
 cpu:                2
 ephemeral-storage:  74373035090
 hugepages-1Gi:      0
 hugepages-2Mi:      0
 memory:             3759120Ki
 pods:               110
System Info:
 Machine ID:                 def36d2abcbe49839534858f6f1e13c5
 System UUID:                86B24D56-709A-3467-6DDB-966B3B807949
 Boot ID:                    949f73c9-b14b-4e94-9137-78b2ac83d046
 Kernel Version:             3.10.0-957.1.3.el7.x86_64
 OS Image:                   CentOS Linux 7 (Core)
 Operating System:           linux
 Architecture:               amd64
 Container Runtime Version:  docker://18.9.0
 Kubelet Version:            v1.13.0
 Kube-Proxy Version:         v1.13.0
Non-terminated Pods:         (3 in total)
  Namespace                  Name                                  CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                  ----                                  ------------  ----------  ---------------  -------------  ---
  default                    frontend                              500m (25%)    1 (50%)     128Mi (3%)       256Mi (6%)     20m
  default                    tomcat-deployment-6bb6864d4f-drcjc    0 (0%)        0 (0%)      0 (0%)           0 (0%)         3h25m
  default                    tomcat-deployment-6bb6864d4f-wmkxx    0 (0%)        0 (0%)      0 (0%)           0 (0%)         3h25m
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests    Limits
  --------           --------    ------
  cpu                500m (25%)  1 (50%)
  memory             128Mi (3%)  256Mi (6%)
  ephemeral-storage  0 (0%)      0 (0%)
Events:
  Type     Reason                   Age    From                       Message
  ----     ------                   ----   ----                       -------
  Normal   Starting                 9m29s  kube-proxy, 192.168.0.125  Starting kube-proxy.
  Normal   Starting                 8m42s  kubelet, 192.168.0.125     Starting kubelet.
  Normal   NodeHasSufficientMemory  8m42s  kubelet, 192.168.0.125     Node 192.168.0.125 status is now: NodeHasSufficientMemory
  Normal   NodeHasNoDiskPressure    8m42s  kubelet, 192.168.0.125     Node 192.168.0.125 status is now: NodeHasNoDiskPressure
  Normal   NodeHasSufficientPID     8m42s  kubelet, 192.168.0.125     Node 192.168.0.125 status is now: NodeHasSufficientPID
  Normal   NodeAllocatableEnforced  8m42s  kubelet, 192.168.0.125     Updated Node Allocatable limit across pods
  Warning  Rebooted                 8m42s  kubelet, 192.168.0.125     Node 192.168.0.125 has been rebooted, boot id: 949f73c9-b14b-4e94-9137-78b2ac83d046

View Code

 健康检查(Probe)

在实际生产环境中,想要使得开发的应用程序完全没有bug,在任何时候都运行正常,几乎 是不可能的任务。因此,我们需要一套管理系统,来对用户的应用程序执行周期性的健康检查和修复操作。这套管理系统必须运行在应用程序之外,这一点非常重要一一如果它是应用程序的一部分,极有可能会和应用程序一起崩溃。因此,在Kubernetes中,系统和应用程序的健康检查是由Kubelet来完成的。

1、进程级健康检查
  最简单的健康检查是进程级的健康检查,即检验容器进程是否存活。这类健康检查的监控粒 度是在Kubernetes集群中运行的单一容器。Kubelet会定期通过Docker Daemon获取所有Docker进程的运行情况,如果发现某个Docker容器未正常运行,则重新启动该容器进程。目前,进程级的健康检查都是默认启用的。

2.业务级健康检查
  在很多实际场景下,仅仅使用进程级健康检查还远远不够。有时,从Docker的角度来看,容器进程依旧在运行;但是如果从应用程序的角度来看,代码处于死锁状态,即容器永远都无法正常响应用户的业务为了解决以上问题,Kubernetes引人了一个在容器内执行的活性探针的概念,以支持用户自己实现应用业务级的健康检查。

Probe有以下两种类型:

livenessProbe:如果检查失败,将杀死容器,根据Pod的restartPolicy来操作。
readinessProbe:如果检查失败,Kubernetes会把Pod从service endpoints中剔除。

一个容器里运行多个应用程序 一个pod运行多个容器_Pod_11

Probe支持以下三种检查方法:
  • ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
  • TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
  • HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的。
livenessProbe解析
[root@k8s-master1 ~]# kubectl explain pod.spec.containers.livenessProbe
KIND:     Pod
VERSION:  v1

RESOURCE: livenessProbe <Object>

exec  command 的方式探测 例如 ps 一个进程

failureThreshold 探测几次失败 才算失败 默认是连续三次

periodSeconds 每次的多长时间探测一次  默认10s

timeoutSeconds 探测超市的秒数 默认1s

initialDelaySeconds  初始化延迟探测,第一次探测的时候,因为主程序未必启动完成

tcpSocket 检测端口的探测

httpGet http请求探测
exec探针的示例:
[root@k8s-master1 ~]# vim exec-liveness.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5


[root@k8s-master1 ~]# kubectl create -f exec-liveness.yaml 
pod/liveness-exec created
[root@k8s-master1 ~]# kubectl get pod
NAME                                 READY   STATUS    RESTARTS   AGE
frontend                             2/2     Running   106        16h
liveness-exec                        1/1     Running   0          16s

在配置文件中,您可以看到Pod具有单个Container。该periodSeconds字段指定kubelet应每5秒执行一次活跃度探测。该initialDelaySeconds字段告诉kubelet它应该在执行第一次探测之前等待5秒。要执行探测,kubelet将cat /tmp/healthy在Container中执行命令。如果命令成功,则返回0,并且kubelet认为Container是活动且健康的。如果该命令返回非零值,则kubelet会终止Container并重新启动它。

再等30秒,确认Container已重新启动,RESTARTS已增加
Events:
  Type     Reason     Age               From                    Message
  ----     ------     ----              ----                    -------
  Normal   Scheduled  57s               default-scheduler       Successfully assigned default/liveness-exec to 192.168.0.126
  Normal   Pulling    55s               kubelet, 192.168.0.126  pulling image "busybox"
  Normal   Pulled     47s               kubelet, 192.168.0.126  Successfully pulled image "busybox"
  Normal   Created    47s               kubelet, 192.168.0.126  Created container
  Normal   Started    47s               kubelet, 192.168.0.126  Started container
  Warning  Unhealthy  5s (x3 over 15s)  kubelet, 192.168.0.126  Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
[root@k8s-master1 ~]# kubectl get pod
NAME                                 READY   STATUS    RESTARTS   AGE
frontend                             2/2     Running   106        16h
liveness-exec                        1/1     Running   1          107s

pod生命周期

Pod 的 status 在信息保存在 PodStatus 中定义,其中有一个 phase 字段。

Pod 的相位(phase)是 Pod 在其生命周期中的简单宏观概述。该阶段并不是对容器或 Pod 的综合汇总,也不是为了做为综合状态机。

Pod 相位的数量和含义是严格指定的。除了本文档中列举的状态外,不应该再假定 Pod 有其他的 phase值。

下面是 phase 可能的值:

  • 挂起(Pending):Pod 已被 Kubernetes 系统接受,但有一个或者多个容器镜像尚未创建。等待时间包括调度 Pod 的时间和通过网络下载镜像的时间,这可能需要花点时间。
  • 运行中(Running):该 Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态。
  • 成功(Succeeded):Pod 中的所有容器都被成功终止,并且不会再重启。
  • 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。
  • 未知(Unknown):因为某些原因无法取得 Pod 的状态,通常是因为与 Pod 所在主机通信失败。

下图是Pod的生命周期示意图,从图中可以看到Pod状态的变化。

一个容器里运行多个应用程序 一个pod运行多个容器_nginx_12

故障排查
kubectl describe TYPE/NAME
kubectl logs TYPE/NAME [-c CONTAINER]
kubectl exec POD [-c CONTAINER] --COMMAND [args...]