《Kubernetes进阶实战》第四章《管理Pod资源对象》

标签及标签选择器 

标签是kubernetes在极具特色,一个资源可以拥有多个标签,同一个标签可以贴到不同的对象上。

资源配置清单:
    自主式Pod资源
    资源的清单格式:
        一级字段:apiVersion(group/version),kind,metadata(name,namespace,labels,annotations,...),spec,status(只读)
    Pod资源
        spec.containers <[]object>
        - name
          image
          imagePullPolicy
             Always,Never,IfNotPresent 分别对应:总是去下载,总是不去下载,如果本地不存在就下载
        示例:在yaml文件中:
        spec:
          containers:
            imagePullPolicy: IfNotPresent
        查看端口的一些信息
        kubectl explain pods.spec.containers.ports
        例如:
        spec:
          containers:
          - name: myapp
            image: ikubernetes/myapp:v1
            ports: 
            - name: http
              containerPort: 80
            - name:https
              containerPort: 443
    标签:
        key=value
            key:字符,数字 _ - .只能以字母数字开头
            value:可以为空,只能使用以字母数字开头和结尾
        标签选择器:

              等值关系标签选择器:=, == , !=  (kubectl get pods -l app=test,app=dev)

              集合关系标签选择器: KEY in (v1,v2,v3), KEY notin (v1,v2,v3)   !KEY (kubectl get pods -l "app in (test,dev)")

        许多资源支持内嵌字段使用标签选择器:
            matchLabels:直接给定健值
            matchExpressions:基于给定的表达式来使用标签选择器{key:"KEY",operator:"OPERATOR",values:[VAL1,VAL2,...]}
            操作符:
                In, NotIn:value字段的值必须为非空列表
                Exists,NotExists:values字段的值必须为空列表
        nodeSelector
            节点选择器标签
        nodeName 指定节点选择器
        annotations:
            和label不同的地方在于,它不能用于挑选资源对象,仅用于对象提供"元数据"

查看所有的标签

[root@master mainfests]# kubectl get pods --show-labels
NAME                            READY   STATUS    RESTARTS   AGE    LABELS
client                          1/1     Running   0          165m   run=client
myapp-65899575cd-5grw5          1/1     Running   0          117m   pod-template-hash=65899575cd,run=myapp
myapp-65899575cd-6b49h          1/1     Running   0          117m   pod-template-hash=65899575cd,run=myapp
myapp-65899575cd-6p6qk          1/1     Running   0          117m   pod-template-hash=65899575cd,run=myapp
myapp-65899575cd-z4scr          1/1     Running   0          117m   pod-template-hash=65899575cd,run=myapp
nginx-deploy-84cbfc56b6-h5h7x   1/1     Running   0          157m   pod-template-hash=84cbfc56b6,run=nginx-deploy
pod-demo                        2/2     Running   0          49m    app=myapp,tire=frontend

指定标签过滤器

#显示每一个pod的标签值
[root@master mainfests]# kubectl get pods -L app
NAME                            READY   STATUS    RESTARTS   AGE    APP
client                          1/1     Running   0          166m   
myapp-65899575cd-5grw5          1/1     Running   0          118m   
myapp-65899575cd-6b49h          1/1     Running   0          118m   
myapp-65899575cd-6p6qk          1/1     Running   0          118m   
myapp-65899575cd-z4scr          1/1     Running   0          118m   
nginx-deploy-84cbfc56b6-h5h7x   1/1     Running   0          158m   
pod-demo                        2/2     Running   0          50m    myapp
#显示指定的标签的pod
[root@master mainfests]# kubectl get pods -l app
NAME       READY   STATUS    RESTARTS   AGE
pod-demo   2/2     Running   0          50m
[root@master mainfests]# kubectl get pods -l app --show-labels
NAME       READY   STATUS    RESTARTS   AGE   LABELS
pod-demo   2/2     Running   0          51m   app=myapp,tire=frontend

给特定的Pod增加一个标签:

打标签之前
[root@master mainfests]# kubectl get pods -L app --show-labels
NAME                            READY   STATUS    RESTARTS   AGE    APP     LABELS
client                          1/1     Running   0          169m           run=client
myapp-65899575cd-5grw5          1/1     Running   0          121m           pod-template-hash=65899575cd,run=myapp
myapp-65899575cd-6b49h          1/1     Running   0          121m           pod-template-hash=65899575cd,run=myapp
myapp-65899575cd-6p6qk          1/1     Running   0          121m           pod-template-hash=65899575cd,run=myapp
myapp-65899575cd-z4scr          1/1     Running   0          121m           pod-template-hash=65899575cd,run=myapp
nginx-deploy-84cbfc56b6-h5h7x   1/1     Running   0          161m           pod-template-hash=84cbfc56b6,run=nginx-deploy
pod-demo                        2/2     Running   0          54m    myapp   app=myapp,tire=frontend
给pod-demo打上canary标签
[root@master mainfests]# kubectl label pods pod-demo release=canary
pod/pod-demo labeled
打标签之后
[root@master mainfests]# kubectl get pods -L app --show-labels
NAME                            READY   STATUS    RESTARTS   AGE    APP     LABELS
client                          1/1     Running   0          169m           run=client
myapp-65899575cd-5grw5          1/1     Running   0          121m           pod-template-hash=65899575cd,run=myapp
myapp-65899575cd-6b49h          1/1     Running   0          121m           pod-template-hash=65899575cd,run=myapp
myapp-65899575cd-6p6qk          1/1     Running   0          121m           pod-template-hash=65899575cd,run=myapp
myapp-65899575cd-z4scr          1/1     Running   0          121m           pod-template-hash=65899575cd,run=myapp
nginx-deploy-84cbfc56b6-h5h7x   1/1     Running   0          162m           pod-template-hash=84cbfc56b6,run=nginx-deploy
pod-demo                        2/2     Running   0          54m    myapp   app=myapp,release=canary,tire=frontend

如果已经有这个标签,再次打上标签会报错

在Pod-demo上打上lk标签
[root@master mainfests]# kubectl label pods pod-demo release=lk
error: 'release' already has a value (canary), and --overwrite is false
#已经有这个标签,如果想继续打上标签,可以使用--overwrite覆盖标签
[root@master mainfests]# kubectl label pods pod-demo release=lk --overwrite
pod/pod-demo labeled
[root@master mainfests]# kubectl get pods -L app --show-labels
NAME                            READY   STATUS    RESTARTS   AGE    APP     LABELS
client                          1/1     Running   0          173m           run=client
myapp-65899575cd-5grw5          1/1     Running   0          125m           pod-template-hash=65899575cd,run=myapp
myapp-65899575cd-6b49h          1/1     Running   0          125m           pod-template-hash=65899575cd,run=myapp
myapp-65899575cd-6p6qk          1/1     Running   0          125m           pod-template-hash=65899575cd,run=myapp
myapp-65899575cd-z4scr          1/1     Running   0          125m           pod-template-hash=65899575cd,run=myapp
nginx-deploy-84cbfc56b6-h5h7x   1/1     Running   0          165m           pod-template-hash=84cbfc56b6,run=nginx-deploy
pod-demo                        2/2     Running   0          57m    myapp   app=myapp,release=lk,tire=frontend

筛选标签

[root@master mainfests]# kubectl get pods -l app --show-labels
NAME       READY   STATUS    RESTARTS   AGE   LABELS
pod-demo   2/2     Running   1          62m   app=myapp,release=lk,tire=frontend
筛选有release标签的
[root@master mainfests]# kubectl get pods -l release
NAME       READY   STATUS    RESTARTS   AGE
pod-demo   2/2     Running   1          62m
筛选有release和app标签的
[root@master mainfests]# kubectl get pods -l release,app
NAME       READY   STATUS    RESTARTS   AGE
pod-demo   2/2     Running   1          62m
筛选出release=lk的pod
[root@master mainfests]# kubectl get pods -l release=lk --show-labels
NAME       READY   STATUS    RESTARTS   AGE   LABELS
pod-demo   2/2     Running   1          62m   app=myapp,release=lk,tire=frontend

给别的pod打标签

[root@master mainfests]# kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
client                          1/1     Running   0          3h1m
myapp-65899575cd-5grw5          1/1     Running   0          133m
myapp-65899575cd-6b49h          1/1     Running   0          133m
myapp-65899575cd-6p6qk          1/1     Running   0          133m
myapp-65899575cd-z4scr          1/1     Running   0          133m
nginx-deploy-84cbfc56b6-h5h7x   1/1     Running   0          173m
pod-demo                        2/2     Running   1          66m
[root@master mainfests]# kubectl label pods nginx-deploy-84cbfc56b6-h5h7x release=zisefeizhu
pod/nginx-deploy-84cbfc56b6-h5h7x labeled
[root@master mainfests]# kubectl get  pods -l release=zisefeizhu --show-labels
NAME                            READY   STATUS    RESTARTS   AGE    LABELS
nginx-deploy-84cbfc56b6-h5h7x   1/1     Running   0          175m   pod-template-hash=84cbfc56b6,release=zisefeizhu,run=nginx-deploy
[root@master mainfests]#

多标签筛选

[root@master mainfests]# kubectl get pods -l release,app --show-labels
NAME       READY   STATUS    RESTARTS   AGE   LABELS
pod-demo   2/2     Running   1          69m   app=myapp,release=lk,tire=frontend
排除lk标签
[root@master mainfests]# kubectl get pods -l release!=lk
NAME                            READY   STATUS    RESTARTS   AGE
client                          1/1     Running   0          3h4m
myapp-65899575cd-5grw5          1/1     Running   0          136m
myapp-65899575cd-6b49h          1/1     Running   0          136m
myapp-65899575cd-6p6qk          1/1     Running   0          136m
myapp-65899575cd-z4scr          1/1     Running   0          136m
nginx-deploy-84cbfc56b6-h5h7x   1/1     Running   0          176m
包含和不包含(lk,beta,alpha)标签
[root@master mainfests]# kubectl get pods -l "release in (lk,beta,alpha)"
NAME       READY   STATUS    RESTARTS   AGE
pod-demo   2/2     Running   1          69m
[root@master mainfests]# kubectl get pods -l "release notin (lk,beta,alpha)"
NAME                            READY   STATUS    RESTARTS   AGE
client                          1/1     Running   0          3h5m
myapp-65899575cd-5grw5          1/1     Running   0          137m
myapp-65899575cd-6b49h          1/1     Running   0          137m
myapp-65899575cd-6p6qk          1/1     Running   0          137m
myapp-65899575cd-z4scr          1/1     Running   0          137m
nginx-deploy-84cbfc56b6-h5h7x   1/1     Running   0          177m

节点标签选择器

查看节点
[root@master mainfests]# kubectl get nodes
NAME     STATUS   ROLES    AGE    VERSION
master   Ready    master   3d2h   v1.13.3
node01   Ready       3d1h   v1.13.3
node02   Ready       3d1h   v1.13.3
给node01打上disktype=ssh标签
[root@master mainfests]# kubectl label node node01 disktype=ssh
node/node01 labeled
查看节点的所有标签
[root@master mainfests]# kubectl get nodes --show-labels
NAME     STATUS   ROLES    AGE    VERSION   LABELS
master   Ready    master   3d2h   v1.13.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=
node01   Ready       3d1h   v1.13.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssh,kubernetes.io/hostname=node01
node02   Ready       3d1h   v1.13.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node02
修改yaml文件,增加标签选择器
[root@master mainfests]# cp pod-demo.yaml{,.cp}
[root@master mainfests]# vim pod-demo.yaml
[root@master mainfests]# kubectl delete pod-demo.yaml 
error: resource(s) were provided, but no name, label selector, or --all flag specified
[root@master mainfests]# kubectl delete -f pod-demo.yaml 
pod "pod-demo" deleted 
[root@master mainfests]# vim pod-demo.yaml.cp 
[root@master mainfests]# diff pod-demo.yaml{,.cp}
19,20d18
<   nodeSelector:
<     disktype: ssd

=================================================

Pod状态和生命周期管理

什么是Pod?

Pod是kubernetes中你可以创建和部署的最小也是最简的单位。一个Pod代表着集群中运行的一个进程。

Pod中封装着应用的容器(有的情况下是好几个容器),存储、独立的网络IP,管理容器如何运行的策略选项。Pod代表着部署的一个单位:kubernetes中应用的一个实例,可能由一个或者多个容器组合在一起共享资源。

在Kubrenetes集群中Pod有如下两种使用方式:

  • 一个Pod中运行一个容器。“每个Pod中一个容器”的模式是最常见的用法;在这种使用方式中,你可以把Pod想象成是单个容器的封装,kuberentes管理的是Pod而不是直接管理容器。
  • 在一个Pod中同时运行多个容器。一个Pod中也可以同时封装几个需要紧密耦合互相协作的容器,它们之间共享资源。这些在同一个Pod中的容器可以互相协作成为一个service单位——一个容器共享文件,另一个“sidecar”容器来更新这些文件。Pod将这些容器的存储资源作为一个实体来管理。

Pod中共享的环境包括Linux的namespace,cgroup和其他可能的隔绝环境,这一点跟Docker容器一致。在Pod的环境中,每个容器中可能还有更小的子隔离环境。

Pod中的容器共享IP地址和端口号,它们之间可以通过localhost互相发现。它们之间可以通过进程间通信,例如SystemV信号或者POSIX共享内存。不同Pod之间的容器具有不同的IP地址,不能直接通过IPC通信。

Pod中的容器也有访问共享volume的权限,这些volume会被定义成pod的一部分并挂载到应用容器的文件系统中。

就像每个应用容器,pod被认为是临时实体。在Pod的生命周期中,pod被创建后,被分配一个唯一的ID(UID),调度到节点上,并一致维持期望的状态直到被终结(根据重启策略)或者被删除。如果node死掉了,分配到了这个node上的pod,在经过一个超时时间后会被重新调度到其他node节点上。一个给定的pod(如UID定义的)不会被“重新调度”到新的节点上,而是被一个同样的pod取代,如果期望的话甚至可以是相同的名字,但是会有一个新的UID(查看replication controller获取详情)。

Pod中如何管理多个容器?

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

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

《Kubernetes进阶实战》第四章《管理Pod资源对象》_第1张图片

Pod中可以共享两种资源:网络和存储。

  •  网络:

  每个Pod都会被分配一个唯一的IP地址。Pod中的所有容器共享网络空间,包括IP地址和端口。Pod内部的容器可以使用localhost互相通信。Pod中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)。

  • 存储:

  可以Pod指定多个共享的Volume。Pod中的所有容器都可以访问共享的volume。Volume也可以用来持久化Pod中的存储资源,以防容器重启后文件丢失。

使用Pod

通常把pod分为两类:

  • 自主式Pod  这种Pod本身是不能自我修复的,当Pod被创建后(不论是由你直接创建还是被其他Controller),都会被Kuberentes调度到集群的Node上。直到Pod的进程终止、被删掉、因为缺少资源而被驱逐、或者Node故障之前这个Pod都会一直保持在那个Node上。Pod不会自愈。如果Pod运行的Node故障,或者是调度器本身故障,这个Pod就会被删除。同样的,如果Pod所在Node缺少资源或者Pod处于维护状态,Pod也会被驱逐。
  • 控制器管理的Pod  Kubernetes使用更高级的称为Controller的抽象层,来管理Pod实例。Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。虽然可以直接使用Pod,但是在Kubernetes中通常是使用Controller来管理Pod的。如下图:

每个Pod都有一个特殊的被称为“根容器”的Pause 容器。 Pause容器对应的镜像属于Kubernetes平台的一部分,除了Pause容器,每个Pod还包含一个或者多个紧密相关的用户业务容器。

《Kubernetes进阶实战》第四章《管理Pod资源对象》_第2张图片

Pod的持久性和终止

(1)Pod的持久性

Pod在设计支持就不是作为持久化实体的。在调度失败、节点故障、缺少资源或者节点维护的状态下都会死掉会被驱逐

通常,用户不需要手动直接创建Pod,而是应该使用controller(例如Deployments),即使是在创建单个Pod的情况下。Controller可以提供集群级别的自愈功能、复制和升级管理。

(2)Pod的终止

因为Pod作为在集群的节点上运行的进程,所以在不再需要的时候能够优雅的终止掉是十分必要的(比起使用发送KILL信号这种暴力的方式)。用户需要能够放松删除请求,并且知道它们何时会被终止,是否被正确的删除。用户想终止程序时发送删除pod的请求,在pod可以被强制删除前会有一个宽限期,会发送一个TERM请求到每个容器的主进程。一旦超时,将向主进程发送KILL信号并从API server中删除。如果kubelet或者container manager在等待进程终止的过程中重启,在重启后仍然会重试完整的宽限期。

示例流程如下:

  1. 用户发送删除pod的命令,默认宽限期是30秒;
  2. 在Pod超过该宽限期后API server就会更新Pod的状态为“dead”;
  3. 在客户端命令行上显示的Pod状态为“terminating”;
  4. 跟第三步同时,当kubelet发现pod被标记为“terminating”状态时,开始停止pod进程:
    1. 如果在pod中定义了preStop hook,在停止pod前会被调用。如果在宽限期过后,preStop hook依然在运行,第二步会再增加2秒的宽限期;
    2. 向Pod中的进程发送TERM信号;
  5. 跟第三步同时,该Pod将从该service的端点列表中删除,不再是replication controller的一部分。关闭的慢的pod将继续处理load balancer转发的流量;
  6. 过了宽限期后,将向Pod中依然运行的进程发送SIGKILL信号而杀掉进程。
  7. Kublete会在API server中完成Pod的的删除,通过将优雅周期设置为0(立即删除)。Pod在API中消失,并且在客户端也不可见。

删除宽限期默认是30秒。 kubectl delete命令支持 —grace-period= 选项,允许用户设置自己的宽限期。如果设置为0将强制删除pod。在kubectl>=1.5版本的命令中,你必须同时使用 --force 和 --grace-period=0 来强制删除pod。

Pod的强制删除是通过在集群和etcd中将其定义为删除状态。当执行强制删除命令时,API server不会等待该pod所运行在节点上的kubelet确认,就会立即将该pod从API server中移除,这时就可以创建跟原pod同名的pod了。这时,在节点上的pod会被立即设置为terminating状态,不过在被强制删除之前依然有一小段优雅删除周期。 

Pause容器

 Pause容器,又叫Infra容器。我们检查node节点的时候会发现每个node上都运行了很多的pause容器,例如如下。

[root@node01 ~]# docker ps |grep pause
a0c48cd0107b        k8s.gcr.io/pause:3.1   "/pause"                 3 hours ago         Up 3 hours                              k8s_POD_myapp-65899575cd-5grw5_default_c7a19c5b-3581-11e9-8e77-000c297bb055_0
7668b89c2781        k8s.gcr.io/pause:3.1   "/pause"                 3 hours ago         Up 3 hours                              k8s_POD_myapp-65899575cd-6p6qk_default_c60c67f1-3581-11e9-8e77-000c297bb055_0
367dbe3d64af        k8s.gcr.io/pause:3.1   "/pause"                 3 hours ago         Up 3 hours                              k8s_POD_myapp-65899575cd-6b49h_default_c6039afb-3581-11e9-8e77-000c297bb055_0
d311bc498720        k8s.gcr.io/pause:3.1   "/pause"                 5 hours ago         Up 5 hours                              k8s_POD_kube-flannel-ds-amd64-rxzf8_kube-system_e1884725-332b-11e9-8124-000c297bb055_1
665b55b6e7ae        k8s.gcr.io/pause:3.1   "/pause"                 5 hours ago         Up 5 hours                              k8s_POD_kube-proxy-vwnbv_kube-system_e1896976-332b-11e9-8124-000c297bb055_1

kubernetes中的pause容器主要为每个业务容器提供以下功能:

  • 在pod中担任Linux命名空间共享的基础;
  • 启用pid命名空间,开启init进程。

如图:

《Kubernetes进阶实战》第四章《管理Pod资源对象》_第3张图片

 

[root@k8s-node01 ~]# docker run -d --name pause -p 8880:80 k8s.gcr.io/pause:3.1
d3057ceb54bc6565d28ded2c33ad2042010be73d76117775c130984c3718d609
[root@k8s-node01 ~]# cat <> nginx.conf
> error_log stderr;
> events { worker_connections  1024; }
> http {
>     access_log /dev/stdout combined;
>     server {
>         listen 80 default_server;
>         server_name example.com www.example.com;
>         location / {
>             proxy_pass http://127.0.0.1:2368;
>         }
>     }
> }
> EOF
[root@k8s-node01 ~]# docker run -d --name nginx -v `pwd`/nginx.conf:/etc/nginx/nginx.conf --net=container:pause --ipc=container:pause --pid=container:pause nginx
d04f848b7386109085ee350ebb81103e4efc7df8e48da18404efb9712f926082
[root@k8s-node01 ~]#  docker run -d --name ghost --net=container:pause --ipc=container:pause --pid=container:pause ghost
332c86a722f71680b76b3072e85228a8d8e9608456c653edd214f06c2a77f112

现在访问http://192.168.56.12:8880/就可以看到ghost博客的界面了。

解析

pause容器将内部的80端口映射到宿主机的8880端口,pause容器在宿主机上设置好了网络namespace后,nginx容器加入到该网络namespace中,我们看到nginx容器启动的时候指定了--net=container:pause,ghost容器同样加入到了该网络namespace中,这样三个容器就共享了网络,互相之间就可以使用localhost直接通信,--ipc=contianer:pause --pid=container:pause就是三个容器处于同一个namespace中,init进程为pause,这时我们进入到ghost容器中查看进程情况。

[root@k8s-node01 ~]# docker exec -it ghost /bin/bash
root@d3057ceb54bc:/var/lib/ghost# ps axu 
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.0   1012     4 ?        Ss   03:48   0:00 /pause
root          6  0.0  0.0  32472   780 ?        Ss   03:53   0:00 nginx: master process nginx -g daemon off;
systemd+     11  0.0  0.1  32932  1700 ?        S    03:53   0:00 nginx: worker process
node         12  0.4  7.5 1259816 74868 ?       Ssl  04:00   0:07 node current/index.js
root         77  0.6  0.1  20240  1896 pts/0    Ss   04:29   0:00 /bin/bash
root         82  0.0  0.1  17496  1156 pts/0    R+   04:29   0:00 ps axu

在ghost容器中同时可以看到pause和nginx容器的进程,并且pause容器的PID是1。而在kubernetes中容器的PID=1的进程即为容器本身的业务进程。

init容器 

Pod 能够具有多个容器,应用运行在容器里面,但是它也可能有一个或多个先于应用容器启动的 Init 容器。

Init 容器与普通的容器非常像,除了如下两点:

  • Init 容器总是运行到成功完成为止。
  • 每个 Init 容器都必须在下一个 Init 容器启动之前成功完成。

如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的 restartPolicy 为 Never,它不会重新启动。

Pod的生命周期

Pod phase

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状态的变化。

《Kubernetes进阶实战》第四章《管理Pod资源对象》_第4张图片

Pod的状态

Pod 有一个 PodStatus 对象,其中包含一个 PodCondition 数组。 PodCondition 数组的每个元素都有一个 type 字段和一个 status 字段。type 字段是字符串,可能的值有 PodScheduled、Ready、Initialized 和 Unschedulable。status 字段是一个字符串,可能的值有 True、False 和 Unknown。

容器探针

在pod生命周期中可以做的一些事情。主容器启动前可以完成初始化容器,初始化容器可以有多个,他们是串行执行的,执行完成后就推出了,在主程序刚刚启动的时候可以指定一个post start 主程序启动开始后执行一些操作,在主程序结束前可以指定一个 pre stop 表示主程序结束前执行的一些操作。在程序启动后可以做两类检测 liveness probe 和 readness probe。如下图:

 《Kubernetes进阶实战》第四章《管理Pod资源对象》_第5张图片

探针是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的Handler。有三种类型的处理程序:

  • ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
  • TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
  • HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的。

每次探测都将获得以下三种结果之一:

  • 成功:容器通过了诊断。
  • 失败:容器未通过诊断。
  • 未知:诊断失败,因此不会采取任何行动。

Kubelet 可以选择是否执行在容器上运行的两种探针执行和做出反应:

  • livenessProbe指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且容器将受到其 重启策略 的影响。如果容器不提供存活探针,则默认状态为 Success
  • readinessProbe指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有 Service 的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为 Failure。如果容器不提供就绪探针,则默认状态为 Success

livenessProbe和readinessProbe使用场景

如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活探针; kubelet 将根据 Pod 的restartPolicy 自动执行正确的操作。

如果希望容器在探测失败时被杀死并重新启动,那么请指定一个存活探针,并指定restartPolicy 为 Always 或 OnFailure。

如果要仅在探测成功时才开始向 Pod 发送流量,请指定就绪探针。在这种情况下,就绪探针可能与存活探针相同,但是 spec 中的就绪探针的存在意味着 Pod 将在没有接收到任何流量的情况下启动,并且只有在探针探测成功后才开始接收流量。

如果您希望容器能够自行维护,您可以指定一个就绪探针,该探针检查与存活探针不同的端点。

请注意,如果您只想在 Pod 被删除时能够排除请求,则不一定需要使用就绪探针;在删除 Pod 时,Pod 会自动将自身置于未完成状态,无论就绪探针是否存在。当等待 Pod 中的容器停止时,Pod 仍处于未完成状态。

Pod的重启策略

PodSpec 中有一个 restartPolicy 字段,可能的值为 Always、OnFailure 和 Never。默认为 Always。 restartPolicy 适用于 Pod 中的所有容器。restartPolicy 仅指通过同一节点上的 kubelet 重新启动容器。失败的容器由 kubelet 以五分钟为上限的指数退避延迟(10秒,20秒,40秒...)重新启动,并在成功执行十分钟后重置。pod一旦绑定到一个节点,Pod 将永远不会重新绑定到另一个节点。

Pod的生命

一般来说,Pod 不会消失,直到人为销毁他们。这可能是一个人或控制器。这个规则的唯一例外是成功或失败的 phase 超过一段时间(由 master 确定)的Pod将过期并被自动销毁。

有三种可用的控制器:

  • 使用 Job 运行预期会终止的 Pod,例如批量计算。Job 仅适用于重启策略为 OnFailure 或 Never 的 Pod。
  • 对预期不会终止的 Pod 使用 ReplicationController、ReplicaSet 和 Deployment ,例如 Web 服务器。 ReplicationController 仅适用于具有 restartPolicy 为 Always 的 Pod。
  • 提供特定于机器的系统服务,使用 DaemonSet 为每台机器运行一个 Pod 。

所有这三种类型的控制器都包含一个 PodTemplate。建议创建适当的控制器,让它们来创建 Pod,而不是直接自己创建 Pod。这是因为单独的 Pod 在机器故障的情况下没有办法自动复原,而控制器却可以。

如果节点死亡或与集群的其余部分断开连接,则 Kubernetes 将应用一个策略将丢失节点上的所有 Pod 的 phase 设置为 Failed。

livenessProbe解析

[root@k8s-master ~]# kubectl explain pod.spec.containers.livenessProbe

KIND:     Pod
VERSION:  v1

RESOURCE: livenessProbe 

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

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

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

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

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

tcpSocket 检测端口的探测

httpGet http请求探测 
  

举个例子:定义一个liveness的pod资源类型,基础镜像为busybox,在busybox这个容器启动后会执行创建/tmp/test的文件啊,并删除,然后等待3600秒。随后定义了存活性探测,方式是以exec的方式执行命令判断/tmp/test是否存在,存在即表示存活,不存在则表示容器已经挂了。

[root@k8s-master ~]# vim liveness.yaml

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-pod
  namespace: default
  labels:
    name: myapp
spec:
  containers:
  - name: livess-exec
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c","touch /tmp/test; sleep 30; rm -f /tmp/test; sleep 3600"]
    livenessProbe:
      exec:
        command: ["test","-e","/tmp/test"]
      initialDelaySeconds: 1
      periodSeconds: 3
[root@k8s-master ~]# kubectl apply -f lineness.yaml

=================================================

注:======中的内容来自https://www.cnblogs.com/linuxk/p/9569618.html

容器存活性探测

容器监控探针类型有三种:
    ExecAction,TCPSockeAction,HTTPGetAction

    kubectl explain pods.spec.containers.livenessProbe

    kubectl explain pods.spec.containers.livenessProbe.exec
    命令执行返回成功是成功的,如果返回状态码是不成功的
使用exec存活性探测:

[root@master mainfests]# vim liveness-exec.yaml
[root@master mainfests]# cat liveness-exec.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-pod
  namespace: default
spec:
  containers:
  - name: liveness-exec-container
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c","touch /tmp/healthy;sleep 30; rm -f /tmp/healthy;sleep 3600"]
    livenessProbe:
      exec:
        command: ["test","-e","/tmp/healthy"]
      initialDelaySeconds: 1
      periodSeconds: 3
[root@master mainfests]# kubectl create -f liveness-exec.yaml 
pod/liveness-exec-pod created
[root@master mainfests]# kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
client                          1/1     Running   0          4h4m
liveness-exec-pod               1/1     Running   0          27s
myapp-65899575cd-5grw5          1/1     Running   0          3h16m
myapp-65899575cd-6b49h          1/1     Running   0          3h16m
myapp-65899575cd-6p6qk          1/1     Running   0          3h16m
myapp-65899575cd-z4scr          1/1     Running   0          3h16m
nginx-deploy-84cbfc56b6-h5h7x   1/1     Running   0          3h56m
[root@master mainfests]# kubectl get pod -w
NAME                            READY   STATUS    RESTARTS   AGE
client                          1/1     Running   0          4h5m
liveness-exec-pod               1/1     Running   1          72s
myapp-65899575cd-5grw5          1/1     Running   0          3h16m
myapp-65899575cd-6b49h          1/1     Running   0          3h17m
myapp-65899575cd-6p6qk          1/1     Running   0          3h17m
myapp-65899575cd-z4scr          1/1     Running   0          3h16m
nginx-deploy-84cbfc56b6-h5h7x   1/1     Running   0          3h57m
[root@master mainfests]# kubectl describe pods liveness-exec-pod
    Restart Count:  3

使用tcpSocket探测
    kubectl explain pods.spec.containers.livenessProbe.tcpSocket
使用httpGet探测
    kubectl explain pods.spec.containers.livenessProbe.httpGet
进入容器
    

kubectl exec -it liveness-httpget -- /bin/sh
这时候我们在容器的内部删除index.html网页
/ # rm -f /usr/share/nginx/html/index.html
过了几秒后,我们再次查看pod的信息
kubectl describe pods liveness-httpget
日志内容:
Restart Count:  1
Liveness:       http-get http://:http/index.html delay=1s timeout=1s period=3s #success=1 #failure=3
再次回到容器中:L
kubectl exec -it liveness-httpget -- /bin/sh
文件出现了 /usr/share/nginx/html/index.html

注:容器启动了并不一定是可以正常使用的,需要里面的服务正常启动之后才可以使用,如:redis和tomcat,这时候我们需要做一个探测。 

​这时候就用到了Pod应用状态就绪监测:
[root@master test]# cat readiness-httpget.yaml 

apiVersion: v1
    kind: Pod
    metadata:
      name: readiness-httpget-container
      namespace: default
    spec:
      containers:
      - name: liveness-httpget-container
        image: ikubernetes/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
          - name: http
            containerPort: 80
        readinessProbe:
           httpGet:
             port: http
             path: /index.html
           initialDelaySeconds: 1
           periodSeconds: 3
 
启动:kubectl create -f readiness-httpget.yaml
这时候kubectl get pods 是正常启动的
这时候进入容器内部
kubectl exec -it readiness-httpget -- /bin/sh
rm -f /usr/share/nginx/html/index.html
这时候kubectl get pods 是不启动的
# echo "hi">usr/share/nginx/html/index.html
kubectl get pods
这个时候是启动成功的
启动后多久和终止前多久?
kubectl explain pods.spec.containers.lifecycle

利用busybox来测试:
busybox是有httpd服务的,但是没有网页,我们做一个网页,然后再启动httpd服务,看看两个能不能关联。
 
cat poststart-pod.yaml 
 
[root@master manifests]# cat poststart-pod.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: ['bin/sh','-c','echo Home_Page >> /tmp/index.html']
        command: ["/bin/httpd"]
        args: ["-f","-h /tmp"]

​

spec:

spec:
    name
    image
    imagePullPolicy:Always,Never,IfNotPresent
    ports:
        name
        containerPort
    livenessProbe
    readinessProbe
    liftcycle
ExecAction: exec
TCPSocketAction: tcpSocker
HTTPGetAction: httpGet

 

你可能感兴趣的:(Kubernetes部分)