4 pod的状态以及探针类型和方式

一 Pod的常见状态、pause容和init容器

1 pod常见的状态

Unschedulable  #pod不能被调度,kube-scheduler没有匹配到合适的node节点
PodScheduled  #pod正处于调度中,在kube-schedulerg刚开始调度的时候,还没有将pod分配到指定的node,在筛选出合适的节点后就会更新etcd数据,将pod分配到指定的node
Pending #正在创建的pod,但是pod中的容器还诶呦完全被创建完成(处于此状态的pod应该检查pod依赖的存储是否有权限挂载等)
Failed  #pod中有容器启动失败而导致pod工作异常
Unknown  #由于某种原因无法获得Pod的当前状态,通常是由于pod所在的node节点通信错误
initialized #所有的pod中的初始化容器已经完成了
imagePullBackOff #pod所在的node节点下载镜像失败
Running # pod内部的容器已经被创建并且启动
Ready  #表示pod中的容器已经可以提供访问服务
Error # 启动过程中发生错误
NodeLost #pod所在节点失联
waiting #pod等待启动
Terminating # pod正在被销毁
CrashLoopBackOff  #pod停止,但是kubelet正在将他重启
invalidlmagename # node节点无法解析镜像名称,导致无法下载
ImageinspectError #无法校验镜像,镜像不完整导致
ErrimageNeverPull #策略禁止拉取镜像,镜像中心权限是私有
RegistryUnavailable #镜像服务器不可用,网络原因或者harbor宕机
ErrimagePull #镜像拉取出错,超时或者下载被强制终止
createcontainerconfigerror #不能创建kubelet使用的容器配置
createcontainerError #创建容器失败
RuncontainerError  # pod运行失败,容器中没有初始化pid为1的守护进程等
containersNotlnitialized #pod没有初始化完毕
containerNotReady #pod 没有准备完毕

containerCreating #pod正在创建中
podinitializing #pod初始化中
DockerDaemonNotReady #node节点docker服务没有启动
NetworkPluginNotReady #网络插件没有启动

2 pause容和init容器

2.1 pause 容器

pause 容器,又叫infra容器,是Pod的基础容器,镜像体积只有几百kb左右,配置在kubelet中,主要功能是一个pod中多个容器的网络通信。
infra容器被创建后会初始化network namespace,之后其他容器剧可以加入的infra容器中共享infra容器的网络了。
一个pod中的两个容器A和bB,那么关系如下:
1 a容器和B容器能够直接使用localhost通信
2 a容器和b容器可以看到网卡,ip和端口监听信息。
3 pod只有一个ip地址,也就是改pod的network,namespace对应的ip地址(由infra容器初始化并创建)
4 k8s环境中的每个pod有一个独立的ip地址,并且此ip被当前pod中所有容器在内部共享使用。
5 pod删除后infra容器随机被删除,其ip被回收。
image

pause-宿主机的namespace
image
然后到Pod所在的宿主机验证网卡
image
查看一个pod的Ip,然后去宿主机找到对应的ip
image

然后在node节点运行如下命令

[root@k8s-node1 pause-test-case]# nsenter --net=/run/docker/netns/e8097040db3f ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.100.36.125  netmask 255.255.255.255  broadcast 10.100.36.125
        ether 0a:e4:27:eb:50:44  txqueuelen 0  (Ethernet)
        RX packets 5  bytes 446 (446.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

e8097040db3f 这个就是namespace

2.2 演示实例:通过docker演示pause,需要准备一个nginx.conf和index.html

[root@k8s-node1 pause-test-case]# cat nginx.conf 
error_log stderr;
events { worker_connections  1024; }
http {
    access_log /dev/stdout;
    server {
        listen 80 default_server;
        server_name www.mysite.com;
        location / {
          index index.html index.php;
          root /usr/share/nginx/html;
         }
        location ~ \.php$ {
            root           /usr/share/nginx/html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
             include        fastcgi_params;
             }
        }
}

index.html和index.php
image
1 启动一个pause容器

docker run -d -p80:80 --name pause-container-1 easzlab/pause:3.6

2 启动一个nginx容器,网络使用pause的网络

docker run -d --name  nginx-container-test -v `pwd`/nginx.conf:/etc/nginx/nginx.conf -v `pwd`/html:/usr/share/nginx/html/ --net=container:pause-container-1 nginx:1.20.0

3启动一个php容器,网络也使用pause的

 docker run -d --name php-test --net=container:pause-container-1 -v `pwd`/html:/usr/share/nginx/html/ php:5.6.40-fpm

访问效果
image

image

2.3 init容器

2.3.1 init 容器的作用:

1 可以为业务容器提前准备好业务容器的运行环境,
2 可以在卞业务容器之前准备好需要的业务数据
3 检查依赖的服务是否可以访问

2.3.2 init容器的特点:

1 一个pod可以有多个业务网容器,还能在有多个init容器,但是每个init容器和业务容器的运行环境都是隔离的
2 init容器会比业务容器先启动
3 init 容器运行成功后,才运行业务容器
4如果一个pod有多个init容器,那么需要从上到下逐个运行并且全部成功,最后才会运行业务容器。
5 init 容器不支持探针检测,因为初始化完成后退出就再也不运行了

举例:创建一个nginx的pod,需要初始化网站的数据,这里用centos:7.9.2009 这个镜像来做init的容器

[root@k8s-master1 init]# cat 1-init-container.yaml 
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: myserver-myapp 
  name: myserver-myapp-deployment-name
  namespace: myserver
spec:
  replicas: 1 
  selector:
    matchLabels:
      app: myserver-myapp-frontend
  template:
    metadata:
      labels:
        app: myserver-myapp-frontend
    spec:
      containers:
        - name: myserver-myapp-container
          image: nginx:1.20.0
          #imagePullPolicy: Always
          volumeMounts:
          - mountPath: "/usr/share/nginx/html/myserver"
            name: myserver-data
      initContainers:
        - name: init-web-data
          image: centos:7.9.2009
          command: ['/bin/bash','-c',"for i in `seq 1 10`;do echo '<h1>'$i web page at $(date +%Y%m%d%H%M%S) '<h1>' >> /data/nginx/html/myserver/index.html;sleep 1;done"]
          volumeMounts:
          - mountPath: "/data/nginx/html/myserver"
            name: myserver-data
        - name: change-data-owner
          image: busybox:1.28
          command: ['/bin/sh','-c',"/bin/chmod 644 /data/nginx/html/myserver/* -R"]
          volumeMounts:
          - mountPath: "/data/nginx/html/myserver"
            name: myserver-data
      volumes:
      - name: myserver-data
        hostPath:
          path: /tmp/data/html

---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: myserver-myapp-service
  name: myserver-myapp-service-name
  namespace: myserver
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30080
  selector:
    app: myserver-myapp-frontend

效果如下:
image

二 pod的声明周期和探针

2.1 生命周期

pod的声明周期,从start后可以配置poststart检查,运行过程中可以配置livenessprobe和readlinessprobe ,最后在stop前可以配置prestop配置

2.2 探针简介

探针是由kubelet对容器执行的定期诊断,以保证pod的状态始终处于运行状态,要执行诊断,kubelet调用由容器实现的handler,也称为钩子,有是那种类型的处理程序
1 Execaction
在容器内部执行指定命令,如果命令退出时,返回码为0,则认为诊断成功
2 TcpSocketaction
对指定端口上的容器ip地址进行tcp检查,如果端口打开,则认为是成功的
3 HTTPGetAction
对指定的端口和路径上的容器的ip地址执行httpget请求,如果相应状态码大于等于200且小于400,则认为是成功的。
HTTP 探针 允许针对 httpGet 配置额外的字段:


host:连接使用的主机名,默认是 Pod 的 IP。也可以在 HTTP 头中设置 “Host” 来代替。
scheme :用于设置连接主机的方式(HTTP 还是 HTTPS)。默认是 "HTTP"。
path:/index.html  #访问 HTTP 服务的路径。默认值为 "/"。
httpHeaders:请求中自定义的 HTTP 头。HTTP 头字段允许重复。
port:80 #访问容器的端口号或者端口名。如果数字必须在 1~65535 之间。

探针最终的三种结果
成功
失败
未知:诊断失败,因此不会采取任何行动

2.3 探针类型

1 startupProbe #启动探针,v1.16引入
判断容器内的应用程序是否已启动完成。如果配置了启动探测,则会先禁用所有其他的探测,直到startupprobe检查成功为止,如果startupprobe,检查失败,则kubelet将杀死容器,

2 livenssprobe #存活探针
检查容器是否正在运行,如果存活探测失败,则kublet会杀死容器,并且容器将受到其重启策略的影响,如果容器不提供存活探针,则默认状态为success,livessprobe用户控制是否重启pod

3 readinessprobe # 就绪探针
如果就绪探针检测失败,端点控制器将从与pod匹配的所有的service的端点中删除该pod的ip地址,初始延迟之前的就绪状态默认为failure 失败,如果容器不提供就绪探针,则默认为success,
readinessprobe用于控制pod是否添加到service里。

2.3.1 strtupProbe实例

[root@k8s-master1 probe]# cat 4-startupProbe.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myserver-myapp-frontend-deployment
  namespace: myserver
spec:
  replicas: 1
  selector:
    matchLabels: #rs or deployment
      app: myserver-myapp-frontend-label
    #matchExpressions:
    #  - {key: app, operator: In, values: [myserver-myapp-frontend,ng-rs-81]}
  template:
    metadata:
      labels:
        app: myserver-myapp-frontend-label
    spec:
      containers:
      - name: myserver-myapp-frontend-label
        image: nginx:1.20.2
        ports:
        - containerPort: 80
        startupProbe:
          httpGet:
            path: /index.html
            port: 80
          initialDelaySeconds: 5 #首次检测延迟5s
          failureThreshold: 3  #从成功转为失败的次数
          periodSeconds: 3 #探测间隔周期


---
apiVersion: v1
kind: Service
metadata:
  name: myserver-myapp-frontend-service
  namespace: myserver
spec:
  ports:
  - name: http
    port: 81 # k8s之间访问的端口
    targetPort: 80  #容器里的端口
    nodePort: 40012
    protocol: TCP
  type: NodePort
  selector:
    app: myserver-myapp-frontend-label


2.3.2 三种探针全部加上

[root@k8s-master1 probe]# cat 5-startupProbe-livenessProbe-readinessProbe.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myserver-myapp-frontend-deployment
  namespace: myserver
spec:
  replicas: 1
  selector:
    matchLabels: #rs or deployment
      app: myserver-myapp-frontend-label
    #matchExpressions:
    #  - {key: app, operator: In, values: [myserver-myapp-frontend,ng-rs-81]}
  template:
    metadata:
      labels:
        app: myserver-myapp-frontend-label
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: myserver-myapp-frontend-label
        image: nginx:1.20.2
        ports:
        - containerPort: 80
        startupProbe:
          httpGet:
            #path: /monitor/index.html
            path: /index.html
            port: 80
          initialDelaySeconds: 5 #首次检测延迟5s
          failureThreshold: 3  #从成功转为失败的次数
          periodSeconds: 3 #探测间隔周期
        readinessProbe:
          httpGet:
            #path: /monitor/monitor.html
            path: /index.html
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 3
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
        livenessProbe:
          httpGet:
            #path: /monitor/monitor.html
            path: /index.html
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 3
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3


---
apiVersion: v1
kind: Service
metadata:
  name: myserver-myapp-frontend-service
  namespace: myserver
spec:
  ports:
  - name: http
    port: 81
    targetPort: 80
    nodePort: 40012
    protocol: TCP
  type: NodePort
  selector:
    app: myserver-myapp-frontend-label


2.4 探针通用配置参数

initialDelaySeconds:120 # 容器启动后要等待多少秒后才启动存活和就绪探测器, 默认是 0 秒,最小值是 0。
periodSeconds:60 #执行探测的时间间隔(单位是秒)。默认是 10 秒。最小值是 1。
timeoutSeconds:5 #探测的超时后等待多少秒。默认值是 1 秒。最小值是 1。
successThreshold:1 # 探测器在失败后,被视为成功的最小连续成功数。默认值是 1。 存活和启动探测的这个值必须是 1。最小值是 1。
failureThreshold:3 #当探测失败时,Kubernetes 的重试次数。 对存活探测而言,放弃就意味着重新启动容器。 对就绪探测而言,放弃意味着 Pod 会被打上未就绪的标签。默认值是 3。最小值是 1。

2.5 探针检测方式演示

1 http类型探针

[root@k8s-master1 probe]# kubectl apply -f 1-http-Probe.yaml 
deployment.apps/myserver-myapp-frontend-deployment created
service/myserver-myapp-frontend-service created
[root@k8s-master1 probe]# cat 1-http-Probe.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myserver-myapp-frontend-deployment
  namespace: myserver
spec:
  replicas: 1
  selector:
    matchLabels: #rs or deployment
      app: myserver-myapp-frontend-label
    #matchExpressions:
    #  - {key: app, operator: In, values: [myserver-myapp-frontend,ng-rs-81]}
  template:
    metadata:
      labels:
        app: myserver-myapp-frontend-label
    spec:
      containers:
      - name: myserver-myapp-frontend-label
        image: nginx:1.20.2
        ports:
        - containerPort: 80
        #readinessProbe:
        livenessProbe:
          httpGet:
            #path: /monitor/monitor.html
            path: /index.html
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 3
          timeoutSeconds: 3
          successThreshold: 1
          failureThreshold: 3

        readinessProbe:
          httpGet:
            #path: /monitor/monitor.html
            path: /index.html
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 3
          timeoutSeconds: 3
          successThreshold: 1
          failureThreshold: 3

---
apiVersion: v1
kind: Service
metadata:
  name: myserver-myapp-frontend-service
  namespace: myserver
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 40018
    protocol: TCP
  type: NodePort
  selector:
    app: myserver-myapp-frontend-label

2 tcp检查

[root@k8s-master1 probe]# cat 2-tcp-Probe.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myserver-myapp-frontend-deployment
  namespace: myserver
spec:
  replicas: 1
  selector:
    matchLabels: #rs or deployment
      app: myserver-myapp-frontend-label
    #matchExpressions:
    #  - {key: app, operator: In, values: [myserver-myapp-frontend,ng-rs-81]}
  template:
    metadata:
      labels:
        app: myserver-myapp-frontend-label
    spec:
      containers:
      - name: myserver-myapp-frontend-label
        image: nginx:1.20.2
        ports:
        - containerPort: 80
        livenessProbe:
        #readinessProbe:
          tcpSocket:
            #port: 80
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 3
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3


---
apiVersion: v1
kind: Service
metadata:
  name: myserver-myapp-frontend-service
  namespace: myserver
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 40012
    protocol: TCP
  type: NodePort
  selector:
    app: myserver-myapp-frontend-label

3 exec-自定义命令

[root@k8s-master1 probe]# cat 3-exec-Probe.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myserver-myapp-redis-deployment
  namespace: myserver
spec:
  replicas: 1
  selector:
    matchLabels: #rs or deployment
      app: myserver-myapp-redis-label
    #matchExpressions:
    #  - {key: app, operator: In, values: [myserver-myapp-redis,ng-rs-81]}
  template:
    metadata:
      labels:
        app: myserver-myapp-redis-label
    spec:
      containers:
      - name: myserver-myapp-redis-container
        image: redis
        ports:
        - containerPort: 6379
        livenessProbe:
        #readinessProbe:
          exec:
            command:
            #- /apps/redis/bin/redis-cli
            - /usr/local/bin/redis-cli 
            - quit
          initialDelaySeconds: 5
          periodSeconds: 3
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
      
---
apiVersion: v1
kind: Service
metadata:
  name: myserver-myapp-redis-service
  namespace: myserver
spec:
  ports:
  - name: http
    port: 6379
    targetPort: 6379
    nodePort: 40016
    protocol: TCP
  type: NodePort
  selector:
    app: myserver-myapp-redis-label

2.6 如何优雅的终止pod(prestop)

poststart:
pod被创建后立即执行检查,及不等的pod中的服务启动
如果poststart执行失败pod不会被继续创建
prestop:
在pod被停止之前执行一些操作

通俗的讲就是等待一定时间,才会执行prestop的操作,在等待的时间,可以把pod从注册中心移走,或者让pod下线,这样当执行prestop的之后,避免用户发送访问请求,造成页面打不开的故障。

演示:

[root@k8s-master1 probe]# cat 1-myserver-myapp1-postStart-preStop.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myserver-myapp1-lifecycle
  labels:
    app: myserver-myapp1-lifecycle
  namespace: myserver
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myserver-myapp1-lifecycle-label
  template:
    metadata:
      labels:
        app: myserver-myapp1-lifecycle-label
    spec:
      terminationGracePeriodSeconds: 60  #终止等待期就是说等待60秒之后,才会执行prestop里的命令
      containers:
      - name: myserver-myapp1-lifecycle-label
        image: tomcat:7.0.94-alpine 
        lifecycle:
          postStart:
            exec:
             #command: 把自己注册到注册在中心
              command: ["/bin/sh", "-c", "echo 'Hello from the postStart handler' >> /usr/local/tomcat/webapps/ROOT/index.html"]

            #httpGet:
            #  #path: /monitor/monitor.html
            #  host: www.magedu.com
            #  port: 80
            #  scheme: HTTP
            #  path: index.html
          preStop:
            exec:
             #command: 把自己从注册中心移除
              command: ["/usr/local/tomcat/bin/catalina.sh","stop"]
        ports:
          - name: http
            containerPort: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: myserver-myapp1-lifecycle-service
  namespace: myserver
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
    nodePort: 30012
    protocol: TCP
  type: NodePort
  selector:
    app: myserver-myapp1-lifecycle-label


大致流程:
image

posted @ 2022-05-14 14:23  huningfei  阅读(376)  评论(0编辑  收藏  举报
levels of contents