k8s-pod

k8s-pod笔记

1.1创建pod

linux理念:一切皆文件

k8s理念:基础设施即代码

  • 创建pod的两种方式

    • 命令行方式创建
      kubectl run nginx-run --image=nginx:1.15.12

      run后面接pod的名称

      --image后面接镜像名称

    • 通过配置文件进行创建

      配置文件可以通过\-\-dry-run选项配合重定向生生成。
      
      root@k8s-master01:~/test# kubectl run nginx-yaml --image=nginx:1.15.12 -oyaml --dry-run > nginx_yaml.yaml
      W1115 02:23:50.996509  201390 helpers.go:663] --dry-run is deprecated and can be replaced with --dry-run=client.
      
      

      创建pod

      root@k8s-master01:~/test# cat nginx.yaml 
      apiVersion: v1
      kind: Pod
      metadata: 
        labels: 
          run: nginx
        name: nginx
      spec: 
        containers: 
        - image: nginx:1.15.12
          name: nginx
          
      root@k8s-master01:~/test# kubectl create -f nginx.yaml 
      pod/nginx created
      
  • 查看pod状态

    • 查看默认名称空间内的pod

      root@k8s-master01:~/test# kubectl get pod 
      NAME    READY   STATUS    RESTARTS   AGE
      nginx   1/1     Running   0          21s
      
      
    • 查看其他名称空间内的pod

      -n 指定名称空间

      NAME为pod的名称

      READY为容器启动数量,前面的数字为“已启动的容器的数量”,后面的数字为pod中包含的容器的总数

      STATUS为pod的状态

      RESTARTS为pod重启的次数

      root@k8s-master01:~/test# kubectl get pod -n kube-system
      NAME                                   READY   STATUS    RESTARTS       AGE
      coredns-7bdc4cb885-bmgqk               1/1     Running   1 (6d5h ago)   6d6h
      coredns-7bdc4cb885-t4qcs               1/1     Running   1 (6d5h ago)   6d6h
      etcd-k8s-master01                      1/1     Running   1 (6d5h ago)   6d6h
      kube-apiserver-k8s-master01            1/1     Running   1 (6d5h ago)   6d6h
      kube-controller-manager-k8s-master01   1/1     Running   1 (6d5h ago)   6d6h
      kube-proxy-5bkbw                       1/1     Running   1 (6d5h ago)   6d6h
      kube-proxy-9czkc                       1/1     Running   1 (6d5h ago)   6d6h
      kube-proxy-hlml9                       1/1     Running   1 (6d5h ago)   6d6h
      kube-proxy-vtccs                       1/1     Running   1 (6d5h ago)   6d6h
      kube-scheduler-k8s-master01            1/1     Running   1 (6d5h ago)   6d6h
      
      
    • 查看所有名称空间中的pod

      root@k8s-master01:~/test# kubectl get pod -A
      NAMESPACE      NAME                                   READY   STATUS    RESTARTS        AGE
      default        nginx                                  1/1     Running   0               38m
      kube-flannel   kube-flannel-ds-d2qjm                  1/1     Running   1 (6d5h ago)    6d5h
      kube-flannel   kube-flannel-ds-dqn8h                  1/1     Running   1 (6d5h ago)    6d5h
      kube-flannel   kube-flannel-ds-p9k7g                  1/1     Running   1 (6d5h ago)    6d5h
      kube-flannel   kube-flannel-ds-xjqj6                  1/1     Running   2 (4h25m ago)   6d5h
      
      

    1.2 修改容器默认启动命令

    更改容器的启动命令的操作也在创建pod时发生,只需要在创建的容器最后面加上一个command参数覆盖容器启动时的entrypoint即可,可选加args参数,entrypoint和args参数的作用待补充

    ps:查看参数,如果不记得容器里面的spec有哪些参数可以通过explain命令进行查询

    root@k8s-master01:~/test# kubectl explain pod.spec.containers
    

    ps:k8s调用集群的最小单位是pod,所以比pod中的配置是无法被k8s感知的,如果想要修改pod中的配置,只能将pod删除掉,再重新部署新的pod

    • 删除pod 的两种方法

      通过配置文件中的配置进行删除

      通过pod的名称进行删除

      root@k8s-master01:~/test# kubectl delete -f nginx.yaml 
      pod "nginx" deleted
      root@k8s-master01:~/test# kubectl delete pod nginx
      pod "nginx" deleted
      root@k8s-master01:~/test# kubectl create -f nginx.yaml 
      pod/nginx created
      
    • 修改容器启动是默认执行的命令

      root@k8s-master01:~/test# vim nginx.yaml 
      apiVersion: v1
      kind: Pod
      metadata: 
        labels:
          run: nginx
        name: nginx
      spec:
        containers:
        - image: nginx:1.15.12
          name: nginx
          command: [ "sleep", "10" ]
      
      

      创建pod

      root@k8s-master01:~/test# kubectl create -f nginx.yaml 
      pod/nginx created
      
      

      稍等一会,查看该容器状态

      发现容器已经变成了completed状态,是因为容器执行的命令不是前台程序,执行完该命令之后容器就退出了

      root@k8s-master01:~/test# kubectl get pod -o wide
      NAME    READY   STATUS      RESTARTS      AGE   IP           NODE         NOMINATED NODE   READINESS GATES
      nginx   0/1     Completed   2 (33s ago)   55s   10.244.2.3   k8s-node01   <none>           <none>
      
      

1.3 Pod 状态及 Pod 故障排查命令

pod状态表

状态说明补充
Pending(挂起)Pod 已被 Kubernetes 系统接收,但仍有一个或多个容器未被创建,如果pod长时间处于pending状态,可以通过 kubectl describe 查看处于 Pending 状态的原因1.请求的资源太大,暂时无机器可供调度;2.挂载的文件不存在;3.节点状态都是异常导致集群内部无可用节点
Running(运行中)Pod 已经被绑定到一个节点上,并且所有的容器都已经被创建,而且至少有一个是运行状态,或者是正在启动或者重启,可以通过 kubectl logs 查看 Pod 的日志节点可用的标志:需要同时满足以下三点:1.pod状态为Running;2.容器全部启动(READY1/1);3.RESTART次数没有一直增加
Succeeded(成功)所有容器执行成功并终止,并且不会再次重启,可以通过 kubectl logs 查看 Pod 日志这个在job任务中经常出现,pod为一次性的,无报错执行完之后就会显示成功了(重启策略为never)
Failed(失败)所有容器都已终止,并且至少有一个容器以失败的方式终止,也就是说这个容器 要么以非零状态退出,要么被系统终止,可以通过 logs 和 describe 查看 Pod 日 志和状态跟上面一样,不过执行结果是失败
Unknown(未知)通常是由于通信问题造成的无法获得 Pod 的状态一般是node节点挂了会有这个报错
ImagePullBackOff ErrImagePull镜像拉取失败,一般是由于1.镜像不存在、2.网络不通或者3.需要登录认证引起的,可 以使用 describe 命令查看具体原因疑难杂症1.镜像的tag正确,镜像的拉取失败,操作节点的网络情况正常,仓库也是公开仓库,但是镜像拉取失败。像这种情况有可能是执行任务的那个node节点的服务器网络有问题。(因为主节点网络好不能代表从节点网络好,主节点上虽然能正常拉取镜像,但是实际的操作还是在从节点上)2.只要镜像仓库是私有的,就必须在yaml中配置认证相关的内容
CrashLoopBackOff容器启动失败,可以通过 logs 命令查看具体原因,一般为启动命令不正确,健 康检查不通过等也有可能是因为容器中没有一个前台运行的进程导致的
OOMKilled容器内存溢出,一般是容器的内存 Limit 设置的过小,或者程序本身有内存溢出, 可以通过 logs 查看程序启动日志
TerminatingPod 正在被删除,可以通过 describe 查看状态一般来说pod一下子就回被删除的,如果在执行过程中pod一直处于Terminating状态,多半是因为由于别的资源在调用该pod导致,也有可能是节点出了问题,可以通过describe查看
SysctlForbiddenPod 自定义了内核配置,但 kubelet 没有添加内核配置或配置的内核参数不支持, 可以通过 describe 查看具体原因
Completed容器内部主进程退出,一般计划任务执行结束会显示该状态,此时可以通过 logs 查看容器日志容器生成时的命令不是前台的命令,执行结束之后,pod就会显示completed状态
ContainerCreatingPod 正在创建,一般为正在下载镜像,或者有配置不当的地方,可以通过 describe 查看具体原因
  • 查看pod的详细状态信息

    root@k8s-master01:~/test# kubectl describe pod nginx
    
  • 查看pod的日志

    -f后面接上pod的名称

    root@k8s-master01:~/test# kubectl logs -f kube-proxy-5bkbw -n kube-system
    

1.4 容器镜像拉取策略

通过 spec.containers[].imagePullPolicy 参数可以指定容器的镜像拉取策略,目前支持的策略如下:

操作方式说明
Always不管本地有没有镜像总是拉取。当镜像 tag 为 latest ,且 imagePullPolicy 未配置时,默认为 Always
Never不管本地(当前node节点上)有没有镜像都不会从镜像仓库拉取镜像
IfNotPresent本地无该镜像时会拉取镜像,本地有镜像时则不去仓库拉取。如果 tag 为非 latest,且 imagePullPolicy 未配置,默认为 IfNotPresent

当镜像 tag 为 latest ,且 imagePullPolicy 未配置时,默认为 Always

本地有镜像时则不去仓库拉取。如果 tag 为非 latest,且 imagePullPolicy 未配置,默认为IfNotPresent

更改镜像拉取策略为IfNotPresent

root@k8s-master01:~/test# vim nginx.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx:1.15.12
    name: nginx
    command: [ "sleep", "10" ]
    imagePullPolicy: IfNotPresent

查看创建容器过程中,是否拉取镜像

看event的部分

root@k8s-master01:~/test# kubectl describe pod nginx
  Normal   Pulled     9m55s (x5 over 12m)  kubelet            Container image "nginx:1.15.12" already present on machine

查看创建pod过程中采用的拉取镜像的策略

root@k8s-master01:~/test# kubectl get pod nginx -oyaml
imagePullPolicy: IfNotPresent

1.5 Pod 重启策略

可以使用 spec.restartPolicy 指定容器的重启策略,restartPolicypod级别的,与容器同级别

生产环境中用的最多的就是Always的pod重启策略。

OnFailure一般用于计划任务等不需要重启的策略。

Never一般不用。

操作方式说明
Always默认策略。容器失效时,自动重启该容器
OnFailure容器以不为 0 的状态码终止,自动重启该容器
Never无论何种状态,都不会重启

设置pod重启策略为Never

root@k8s-master01:~/test# vim nginx.yaml 
apiVersion: v1
kind: Pod
metadata: 
  labels:
    run: nginx
  name: nginx
spec:
  restartPolicy: Never
  containers:
  - image: nginx
    name: nginx
    command: [ "sleep", "3" ]
#   imagePullPolicy: IfNotPresent

检查pod是否重启过(RESTARTS的数值就是重启次数)

root@k8s-master01:~/test# kubectl get pod  -o wide
NAME    READY   STATUS      RESTARTS   AGE    IP           NODE         NOMINATED NODE   READINESS GATES
nginx   0/1     Completed   0          107s   10.244.2.7   k8s-node01   <none>           <none>

1.6 Pod 的三种探针

startupProbe只会在容器刚创建的时候探测一次,之后就不会探测了,startupProbe探测成功之后,就交给livenessProbereadinessProbe循环探测了;如果startupProbe探测失败了,就会根据startupProbe的策略执行相应的重启策略。

种类说明
startupProbeKubernetes1.16 新加的探测方式,用于判断容器内的应用程序是否已经启动。如果 配置了 startupProbe,就会先禁用其他探测,直到它成功为止。如果探测失败,Kubelet 会杀死容器,之后根据重启策略进行处理,如果探测成功,或没有配置 startupProbe, 则状态为成功,之后就不再探测。
livenessProbe存活探针:用于探测容器是否在运行,如果探测失败,kubelet 会“杀死”容器并根据重启策略 进行相应的处理。如果未指定该探针,将默认为 Success
readinessProbe就绪探针:一般用于探测容器内的程序是否健康,即判断容器是否为就绪(Ready)状态。如果健康,Endpoints Controller会将该容器提供服务的Endpoints添加到所有的Service中,那么我们可以处理请求(只有该检查通过了。才会有流量接进来),反之 Endpoints Controller 将从所有的 Service 的 Endpoints 中删除此容器所在 Pod 的 IP 地址。如果未指定,将默认为 Success

startupProbe一般用于启动时间非常长的应用,比如java应用。

1.7 Pod 探针的实现方式

HTTPGetAction是最可靠的检测方法,但是也是最复杂的,需要开发人员结合代码进行配置。

实现方式说明
ExecAction在容器内执行一个指定的命令,如果命令返回值为 0,则认为容器健康
TCPSocketAction通过 TCP 连接检查容器指定的端口,如果端口开放,则认为容器健康
HTTPGetAction对指定的 URL 进行 Get 请求,如果状态码在 200~400 之间,则认为容器健康

ExecAction:可以通过echo $?获取返回值,返回值为0 ,则代表容器健康。

TCPSocketAction:查看端口是否存在,存在则代表容器健康。

HTTPGetAction:查看状态码是否在200-400之间,在此区间,则容器正常。通过curl -I 可以查看到网站返回的状态码。

root@k8s-master01:~# curl -I baidu.com
HTTP/1.1 200 OK
Date: Wed, 15 Nov 2023 10:42:54 GMT

1.8 livenessProbe 和 readinessProbe

健康检查的重要性:如果不加健康性检查,那么pod一旦被创建,就会被置为Running状态,该状态对于service来说就是代表容器正常运行,此时,如果有请求访问该服务,service就会将流量调度到该pod上。但是,此时有可能pod并没有准备好。第一类情况,该pod中的服务启动时间很短,pod马上就能提供正常服务;第二类情况,该pod中的服务启动时间很长,虽然pod的状态是Runing状态,但是,pod中的服务实际并没有正常运行,如果流量现在被分发到该pod上,这个pod是无法提供正常的服务的。没懂,没关系,请看VCR:

  1. 创建一个没有探针的 Pod:
    创建一个名为nginx 的pod,该pod执行的命令为睡眠30s,之后再启动nginx
[root@k8s-master01 test]# vim pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
    command:
    - sh
    - -c
    - sleep 30; nginx -g "daemon off;"
  restartPolicy: OnFailure
  1. 通过curl命令访问nginx服务
    curl这个nginx网址的动作一定要在30s之内完成,因为在30s之内,nginx服务还未启动,所以此时curl网页会失败(看到访问失败的提示,就是我们要看到的效果)
[root@k8s-master01 test]# kubectl create -f pod.yaml 
[root@k8s-master01 test]# kubectl get pod -owide
NAME    READY   STATUS    RESTARTS   AGE     IP               NODE         NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          7m12s   192.168.58.196   k8s-node02   <none>           <none>
[root@k8s-master01 test]# curl 192.168.58.196
[root@k8s-master01 test]# curl 192.168.58.196
curl: (7) Failed connect to 192.168.58.196:80; Connection refused

结论:当未配置健康性检查时,对于启动时间过长的应用而言,pod存在无法正常提供服务的风险。

配置readinessProbeLivenessProbe探针

  • 只有readinessProbe探测成功,service才会将服务的请求流量发送到该pod

  • 探针要配置在容器层面,因为同一个pod中可能会有多个容器,但是每个容器的启动过程是不一样,所以探针是需要为容器单独配置的。

  • 每个探针只能用四种探测方式(ExecAction,TCPSocketAction,HTTPGetAction,gRPC)中的一种,本例采用的探测方式为`HTTPGet``

  • path路径是针对根路径写的

  • initialDelaySeconds: 10 # 健康性检查延迟执行时间,就是当服务启动10s钟之后,再进行探测的延时时间。建议将该延时时间配置为服务启动的时间,例如:该服务启动需要40s,你可以将initialDelaySeconds配置为40,那么上面的readinessProbe就会在创建容器40s之后才开始工作。

  • timeoutSeconds: 2 # 超时时间

  • periodSeconds: 5 # 检测间隔

  • successThreshold: 1 # 检查成功为 2 次表示就绪

  • failureThreshold: 2 # 检测失败 1 次表示未就绪

    此例表示:当用户在访问容器中的nginx服务提供的index网页超过2s,而服务端未返回信息时,readinessProbe会间隔5s之后,再次对该资源进行探测,如果连续探测失败2次则认为该pod故障,就会让service切断该pod的流量,不对外提供服务;如果探测成功1次,readinessProbe就会认为该pod正常。只有容器的Ready个数为1/1,readinessProbe才会任务该pod正常。

  • tcpSocket: # 端口检测方式
    port: 80
    该探测方式就是探测容器的端口是否可以正常启动,如果正常启动,则代表该容器正常;如果端口故障,则该容器会指定对应的重启策略。

注意:readinessProbelivenessProbe的区别:
readiness探测失败会导致流量被切断livenessProbe探测失败会导致pod被重启

测试readinessProbe探针
pod正常情况下
  1. 配置readinessProbe探针

    [root@k8s-master01 test]# vim pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        run: nginx
      name: nginx
    spec:
      containers:
      - image: nginx
      containers:
      - image: nginx
        name: nginx
        readinessProbe: # 可选,健康检查。若成功,则接入流量;若失败,则切断流量。
            httpGet: # 接口检测方式,注意三种检查方式同时只能使用一种。
              path: /index.html # 检查路径
              port: 80
              scheme: HTTP # HTTP or HTTPS
             #httpHeaders: # 可选, 检查的请求头
             #- name: end-user
             # value: Jason
            initialDelaySeconds: 10 # 初始化时间, 健康检查延迟执行时间
            timeoutSeconds: 2 # 超时时间
            periodSeconds: 5 # 检测间隔
            successThreshold: 1 # 检查成功为 1 次表示就绪,可以接入流量
            failureThreshold: 2 # 检测失败 2 次表示未就绪,开始切断流量
        command:
        - sh
        - -c
        - sleep 30; nginx -g "daemon off;"
      restartPolicy: OnFailure
    
  2. 检查容器是否可以正常访问

    该检查操作需要在容器未启动完成之前进行操作

    root@k8s-master01:~/test# kubectl get pod -o wide
    NAME    READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
    nginx   0/1     Running   0          10s   10.244.2.10   k8s-node02   <none>           <none>
    root@k8s-master01:~/test# curl 10.244.2.10
    curl: (7) Failed to connect to 10.244.2.10 port 80: Connection refused
    root@k8s-master01:~/test# curl 10.244.2.10
    
  3. 检查容器是否可以正常访问

    该检查操作需要在容器未启动完成之前进行操作

    root@k8s-master01:~/test# kubectl get pod -o wide
    NAME    READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
    nginx   1/1     Running   0          40s   10.244.2.10   k8s-node02   <none>           <none>
    root@k8s-master01:~/test# curl 10.244.2.10
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
    html { color-scheme: light dark; }
    body { width: 35em; margin: 0 auto;
    font-family: Tahoma, Verdana, Arial, sans-serif; }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
    
    

结论:readinessProbe探针可以待容器完全启动,应用都正常的情况下,再将pod暴露到网络中,供service进行调用。

pod异常情况下
  1. 配置readinessProbe探针

    在该示例中,我们将readinessProbe探针的检测方式设置为HTTPGet,检测的端口为8080,众所周知啊,nginx的默认启动的端口为80,此处我们将检测的端口设置为8080,所以readinessProbe的探测一定是会失败的。失败的情况下我们再去观察pod是否会被重启。

    先说结论啊:不会重启的,这辈子都不会了,因为我们仅仅只配置了readinessProbe,再强调一遍,readinessProbe探针只会影响service的流量分发,不管pod重启啊,所以,只要readinessProbe探针探测失败,service就不会讲流量分发过来,但是并不会影响pod的重启,不过readinessProbe探针还是会一直对pod进行7*24小时的循环探测(不论readinessProbe的探测是成功还是失败)。

    root@k8s-master01:~/test# cat pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        run: nginx
      name: nginx
    spec:
      containers:
      - image: nginx
      containers:
      - image: nginx
        name: nginx
        readinessProbe: # 可选,健康检查。若成功,则接入流量;若失败,则切断流量。
            httpGet: # 接口检测方式,注意三种检查方式同时只能使用一种。
              path: /index.html # 检查路径
              port: 8080
              scheme: HTTP # HTTP or HTTPS
             #httpHeaders: # 可选, 检查的请求头
             #- name: end-user
             # value: Jason
            initialDelaySeconds: 10 # 初始化时间, 健康检查延迟执行时间
            timeoutSeconds: 2 # 超时时间
            periodSeconds: 5 # 检测间隔
            successThreshold: 1 # 检查成功为 1 次表示就绪,可以接入流量
            failureThreshold: 2 # 检测失败 2 次表示未就绪,开始切断流量
        command:
        - sh
        - -c
        - sleep 30; nginx -g "daemon off;"
      restartPolicy: OnFailure
    
    

    备用啊

    [root@k8s-master01 test]# vim pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        run: nginx
      name: nginx
    spec:
      containers:
      - image: nginx
      containers:
      - image: nginx
        name: nginx
        readinessProbe: # 可选,健康检查。若成功,则接入流量;若失败,则切断流量。
            httpGet: # 接口检测方式,注意三种检查方式同时只能使用一种。
              path: /index.html # 检查路径
              port: 8080	#把端口号改成8080
              scheme: HTTP # HTTP or HTTPS
             #httpHeaders: # 可选, 检查的请求头
             #- name: end-user
             # value: Jason
            initialDelaySeconds: 10 # 初始化时间, 健康检查延迟执行时间
            timeoutSeconds: 2 # 超时时间
            periodSeconds: 5 # 检测间隔
            successThreshold: 1 # 检查成功为 1 次表示就绪,可以接入流量
            failureThreshold: 2 # 检测失败 2 次表示未就绪,开始切断流量
        livenessProbe: # 可选,健康检查。若成功,则无动作;若失败,则根据下面的重启策略(restartPolicy)重启pod。
            tcpSocket: # 端口检测方式
              port: 80
            initialDelaySeconds: 10 # 初始化时间
            timeoutSeconds: 2 # 超时时间
            periodSeconds: 5 # 检测间隔
            successThreshold: 1 # 检查成功为 2 次表示就绪
            failureThreshold: 2 # 检测失败 1 次表示未就绪
        command:
        - sh
        - -c
        - sleep 30; nginx -g "daemon off;"
      restartPolicy: OnFailure
    
  2. 检查pod状态
    在pod创建完成后的30s之内,发现pod的状态虽然是Running状态,但是容器的数量一直都是0/1,代表该pod目前还不能对外提供服务

[root@k8s-master01 test]# kubectl delete -f pod.yaml
[root@k8s-master01 test]# kubectl create -f pod.yaml
root@k8s-master01:~/test# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
nginx   0/1     Running   0          113s
root@k8s-master01:~/test# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
nginx   0/1     Running   0          115s

  1. 查看pod的内部发生了什么
    探针探测失败时才会在event中打印日志,成功是不打印日志的。(所以在上个实验中,使用describe命令时,在输出结果中的Events中是无法看见readinessProbe的异常情况的)

    Started container nginx Warning Unhealthy 107s (x21 over 3m22s) kubelet由此可见:在3分22秒之内,readinessProbe已经探测失败了21次了,但是容器依然没有重启。

root@k8s-master01:~/test# kubectl describe pod nginx
---
Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled  3m37s                  default-scheduler  Successfully assigned default/nginx to k8s-node02
  Normal   Pulling    3m37s                  kubelet            Pulling image "nginx"
  Normal   Pulled     3m32s                  kubelet            Successfully pulled image "nginx" in 4.195205549s (4.195212157s including waiting)
  Normal   Created    3m32s                  kubelet            Created container nginx
  Normal   Started    3m32s                  kubelet            Started container nginx
  Warning  Unhealthy  107s (x21 over 3m22s)  kubelet            Readiness probe failed: Get "http://10.244.2.11:8080/index.html": dial tcp 10.244.2.11:8080: connect: connection refused

  1. 查看pod状态

已经经过好久了,但是pod只是探测失败,并未重启,这就是readinessProbe的作用,是用来切断service的流量的。

root@k8s-master01:~/test# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
nginx   0/1     Running   0          5m16s

测试livenessProbe探针
pod正常情况下
  1. 配置livenessProbe

    本实例中,我们模拟启动耗时较长的应用,再使用livenessProbe对pod进行循环探测端口以确保pod正常。

    实验条件:

    ​ 假设nginx应用启动耗时30s(sleep 30)

    ​ 检测延时时间设置为30s(initialDelaySeconds: 30)

    ​ 检测方式:tcpSocket(用于检测端口的tcpSocket:)

    ​ 监测对象是80端口(port: 80)

    [root@k8s-master01 test]# vim pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        run: nginx
      name: nginx
    spec:
      containers:
      - image: nginx
      containers:
      - image: nginx
        name: nginx
        livenessProbe: # 可选,健康检查。若成功,则无动作;若失败,则根据下面的重启策略(restartPolicy)重启pod。
          tcpSocket: # 端口检测方式
            port: 80
          initialDelaySeconds: 30 # 初始化时间
          timeoutSeconds: 2 # 超时时间
          periodSeconds: 5 # 检测间隔
          successThreshold: 1 # 检查成功为 2 次表示就绪
          failureThreshold: 2 # 检测失败 1 次表示未就绪
        command:
        - sh
        - -c
        - sleep 30; nginx -g "daemon off;"
      restartPolicy: OnFailure
    
  2. 启动pod

    root@k8s-master01:~/test# kubectl delete -f pod.yaml 
    pod "nginx" deleted
    root@k8s-master01:~/test# kubectl create -f pod.yaml 
    pod/nginx created
    
  3. 检查pod状态

    root@k8s-master01:~/test# kubectl get pod -o wide
    NAME    READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
    nginx   1/1     Running   0          11s   10.244.2.12   k8s-node02   <none>           <none>
    
    
  4. 监测服务是否可以正常访问

    在30s内,nginx服务是无法正常提供服务的

    root@k8s-master01:~/test# kubectl get pod -o wide
    NAME    READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
    nginx   1/1     Running   0          13s   10.244.2.14   k8s-node02   <none>           <none>
    root@k8s-master01:~/test# curl 10.244.2.14
    curl: (7) Failed to connect to 10.244.2.14 port 80: Connection refused
    
    
  5. 检查pod详细状态

    pod正常启动,没有发现异常

    root@k8s-master01:~/test# kubectl descrivbe pod nginx
    ---
    Events:
      Type    Reason     Age    From               Message
      ----    ------     ----   ----               -------
      Normal  Scheduled  2m12s  default-scheduler  Successfully assigned default/nginx to k8s-node02
      Normal  Pulling    2m11s  kubelet            Pulling image "nginx"
      Normal  Pulled     2m6s   kubelet            Successfully pulled image "nginx" in 5.634722374s (5.634726784s including waiting)
      Normal  Created    2m6s   kubelet            Created container nginx
      Normal  Started    2m5s   kubelet            Started container nginx
    
    
pod异常情况下

pod在异常情况下,会被livenessProbe探测为失败,就会导致pod一直被重启。

  1. 配置livenessProbe

    root@k8s-master01:~/test# vim pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        run: nginx
      name: nginx
    spec:
      containers:
      - image: nginx
      containers:
      - image: nginx
        name: nginx
        livenessProbe: # 可选,健康检查。若成功,则无动作;若失败,则根据下面的重启策略(restartPolicy)重启pod。
          tcpSocket: # 端口检测方式
            port: 8080
          initialDelaySeconds: 30 # 初始化时间
          timeoutSeconds: 2 # 超时时间
          periodSeconds: 5 # 检测间隔
          successThreshold: 1 # 检查成功为 2 次表示就绪
          failureThreshold: 2 # 检测失败 1 次表示未就绪
        command:
        - sh
        - -c
        - sleep 30; nginx -g "daemon off;"
      restartPolicy: OnFailure
    
    
  2. 启动pod

    root@k8s-master01:~/test# kubectl delete -f pod.yaml 
    pod "nginx" deleted
    root@k8s-master01:~/test# kubectl create -f pod.yaml 
    pod/nginx created
    
  3. 检查pod状态

    因为livenessProbe一直在探测8080端口,但是探测不到,就导致了探测失败,然后就一直重启。

    root@k8s-master01:~/test# kubectl get pod -o wide
    NAME    READY   STATUS             RESTARTS      AGE     IP            NODE         NOMINATED NODE   READINESS GATES
    nginx   0/1     CrashLoopBackOff   5 (76s ago)   8m16s   10.244.2.16   k8s-node02   <none>           <none>
    
    
  4. 查看pod日志

    root@k8s-master01:~/test# kubectl describe pod nginx
    ---
    Events:
      Type     Reason     Age                    From               Message
      ----     ------     ----                   ----               -------
      Normal   Scheduled  8m44s                  default-scheduler  Successfully assigned default/nginx to k8s-node02
      Normal   Pulled     8m39s                  kubelet            Successfully pulled image "nginx" in 4.215320758s (4.215339705s including waiting)
      Normal   Pulled     7m31s                  kubelet            Successfully pulled image "nginx" in 3.010210738s (3.01021607s including waiting)
      Normal   Pulled     6m20s                  kubelet            Successfully pulled image "nginx" in 3.055648235s (3.055652158s including waiting)
      Normal   Killing    5m44s (x3 over 8m4s)   kubelet            Container nginx failed liveness probe, will be restarted
      Normal   Pulling    5m14s (x4 over 8m43s)  kubelet            Pulling image "nginx"
      Normal   Created    5m10s (x4 over 8m39s)  kubelet            Created container nginx
      Normal   Started    5m10s (x4 over 8m39s)  kubelet            Started container nginx
      Normal   Pulled     5m10s                  kubelet            Successfully pulled image "nginx" in 3.1806318s (3.180656536s including waiting)
      Warning  Unhealthy  3m29s (x9 over 8m9s)   kubelet            Liveness probe failed: dial tcp 10.244.2.16:8080: connect: connection refused
    
    

1.9 配置 StartupProbe

对于启动时间很长的应用,需要使用startupProbe。
如果没有startupProbe,对于启动时间较长的应用(假设该应用需要启动200s)只有两种办法对其进行健康行检查:1. 增加initialDelaySeconds,比如设置为220,这个操作会影响新pod生效的时间,当故障pod被探测失败后,系统会创建一个新的pod,但是由于initialDelaySeconds被设置为220,所以新的pod会在220s之后才能提供服务,这在生产中是不被允许的。2. 增加探测间隔periodSeconds和判定失败的次数failureThreshold,这个会导致pod内部错误无法被及时发现,及时处理。所以,k8s增加了启动探针startupProbe来应对启动时间长的应用。

下面我们做相同的实验来检查livenessProbe和startupProbe的区别
实验过程:建立一个pod,配置livenessProbe或者startupProbe用于监测容器状态,进入容器后删除index文件,用于模拟容器不能正常使用。然后比较两种探针对容器重启时间的影响,比较两种探针对于容器状态检测的优劣。

  • 实验一:通过livenessProbe监测容器状态
  1. 配置容器livenessProbe
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
  containers:
  - image: nginx
    name: nginx
    livenessProbe: # ~O~@~I~L~A康~@~_~@~B~K~H~P~J~_~L~H~Y~W| ~J~\~[~K失败~L~H~Y| ~M~K~]~Z~D~G~M~P~V~U~HrestartPolicy
      httpGet: # 端~O~@~K~V~O
        path: /index.html
        port: 80
      initialDelaySeconds: 30 # ~H~]~K~L~V~W~W
      timeoutSeconds: 2 # ~E~W~W~W
      periodSeconds: 5 # ~@~K~W~Z~T
      successThreshold: 1 # ~@~_~H~P~J~_为 2 次表示就绪
      failureThreshold: 2 # ~@~K失败 1 次表示~\就绪
    command:
    - sh
    - -c
    - sleep 30; nginx -g "daemon off;"
  restartPolicy: OnFailure
  1. 创建容器
controlplane $ kubectl create -f pod.yaml 
pod/nginx created
  1. 删除监测文件
controlplane $ kubectl exec -it nginx -- bash
root@nginx:/# cd /usr/share/nginx/html/
root@nginx:/usr/share/nginx/html# rm -rf index.html 
root@nginx:/usr/share/nginx/html# exit
exit
  1. 查看容器重启时间
controlplane $ kubectl get pod 
NAME    READY   STATUS    RESTARTS      AGE
nginx   1/1     Running   1 (15s ago)   5m10s
controlplane $ kubectl describe pod nginx
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  6m1s                 default-scheduler  Successfully assigned default/nginx to node01
  Normal   Pulled     5m55s                kubelet            Successfully pulled image "nginx" in 5.571s (5.571s including waiting)
  Warning  Unhealthy  96s (x2 over 101s)   kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404
  Normal   Killing    96s                  kubelet            Container nginx failed liveness probe, will be restarted
  Normal   Pulling    66s (x2 over 6m)     kubelet            Pulling image "nginx"
  Normal   Pulled     65s                  kubelet            Successfully pulled image "nginx" in 1.026s (1.026s including waiting)
  Normal   Created    64s (x2 over 5m55s)  kubelet            Created container nginx
  Normal   Started    64s (x2 over 5m55s)  kubelet            Started container nginx
  • 实验二:通过startupProbe监测容器状态
  1. 配置startupProbe
    配置接口级的探测方式,检测index文件是否存在。
apiVersion: v1 # 必选,API 的版本号
kind: Pod # 必选,类型 Pod
metadata: # 必选,元数据
 name: nginx # 必选,符合 RFC 1035 规范的 Pod 名称
spec: # 必选,用于定义 Pod 的详细信息
 containers: # 必选,容器列表
 - name: nginx # 必选,符合 RFC 1035 规范的容器名称
 image: nginx:1.15.12 # 必选,容器所用的镜像的地址
 imagePullPolicy: IfNotPresent
 command: # 可选,容器启动执行的命令
 - sh
 - -c
 - sleep 30; nginx -g "daemon off;"
 startupProbe:
 tcpSocket: # 端口检测方式
 port: 80
 initialDelaySeconds: 10 # 初始化时间
 timeoutSeconds: 2 # 超时时间
 periodSeconds: 5 # 检测间隔
 successThreshold: 1 # 检查成功为 2 次表示就绪
 failureThreshold: 5 # 检测失败 1 次表示未就绪
 readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
 httpGet: # 接口检测方式
 path: /index.html # 检查路径
 port: 80
 scheme: HTTP # HTTP or HTTPS
 #httpHeaders: # 可选, 检查的请求头
 #- name: end-user
 # value: Jason
 initialDelaySeconds: 10 # 初始化时间, 健康检查延迟执行时间
 timeoutSeconds: 2 # 超时时间
 periodSeconds: 5 # 检测间隔
 successThreshold: 1 # 检查成功为 2 次表示就绪
 failureThreshold: 2 # 检测失败 1 次表示未就绪
 livenessProbe: # 可选,健康检查
 exec: # 端口检测方式
 command:
 - sh
 - -c
 - pgrep nginx
 initialDelaySeconds: 10 # 初始化时间
 timeoutSeconds: 2 # 超时时间
 periodSeconds: 5 # 检测间隔
 successThreshold: 1 # 检查成功为 2 次表示就绪
 failureThreshold: 2 # 检测失败 1 次表示未就绪
 ports: # 可选,容器需要暴露的端口号列表
 - containerPort: 80 # 端口号
 restartPolicy: Never
  1. 检查pod是否正常运行
[root@k8s-master01 test]# kubectl get pod
  1. 模拟容器故障
    进入容器,删除index文件
[root@k8s-master01 test]# kubectl exec -it nginx -- sh
/ # cd /usr/share/nginx/html
/ # rm -rf index.html

再次查看pod状态

[root@k8s-master01 test]# kubectl get pod

此时可以看到pod还不会被重启,因为

1.10 preStop 和 postStart

apiVersion: v1 # 必选,API 的版本号
kind: Pod # 必选,类型 Pod
metadata: # 必选,元数据
 name: nginx # 必选,符合 RFC 1035 规范的 Pod 名称
spec: # 必选,用于定义 Pod 的详细信息
 containers: # 必选,容器列表
 - name: nginx # 必选,符合 RFC 1035 规范的容器名称
 image: nginx:1.15.12 # 必选,容器所用的镜像的地址
 imagePullPolicy: IfNotPresent
 lifecycle:
 postStart: # 容器创建完成后执行的指令, 可以是 exec httpGet TCPSocket
 exec:
 command:
 - sh
 - -c
 - 'mkdir /data/'
 preStop:
 exec:
 command:
 - sh
 - -c
 - sleep 10
 ports: # 可选,容器需要暴露的端口号列表
 - containerPort: 80 # 端口号
 restartPolicy: Never

1.11 gRPC 探测(1.24 默认开启)

apiVersion: v1
kind: Pod
metadata:
 name: etcd-with-grpc
spec:
 containers:
 - name: etcd
 image: registry.cnhangzhou.aliyuncs.com/google_containers/etcd:3.5.1-0
 command: [ "/usr/local/bin/etcd", "--data-dir", "/var/lib/etcd", "--
listen-client-urls", "http://0.0.0.0:2379", "--advertise-client-urls",
"http://127.0.0.1:2379", "--log-level", "debug"]
 ports:
 - containerPort: 2379
 livenessProbe:
 grpc:
 port: 2379
 initialDelaySeconds: 10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值