Pod深入进阶

一、Pod基础概念

======Pod基础概念:======
Pod是kubernetes中最小的资源管理组件,Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes
中其他大多数组件都是围绕着Pod来进行支撑和扩展Pod功能的,例如,用于管理Pod运行的StatefulSet和Deployment等控制器对象,用于
暴露Pod应用的Service和Ingress对象,为Pod提供存储的PersistentVolume存储资源对象等

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

一个Pod下的容器必须运行于同一节点上。现代容器技术建议一个容器只运行一个进程,该进程在容器中PID命令空间中的进程号为1,可直
接接收并处理信号,进程终止时容器生命周期也就结束了。若想在容器内运行多个进程,需要有一个类似Linux操作系统init进程的管控类
进程,以树状结构完成多进程的生命周期管理。运行于各自容器内的进程无法直接完成网络想信,这是由于容器间的隔离机制导致,k8s中
的Pod资源抽象正是解决此类问题,Pod对象是一组容器的集合,这些容器共享Network、UTS及IPC命令空间,因此具有相同的域名、主机名
和网络接口,并可通过IPC直接通信

Pod资源中针对各容器提供网络命令空间等共享机制的是底层基础容器pause,基础容器(也可称为父容器)pause就是为了管理Pod容器间
的共字操作,这个父容器需要能够准确地知道如何去创建共享运行环境的容器,还能管理这些容器的生命周期。为了实现这个父容器的构
想,kubernetes中,用pause容器来作为一个Pod中所有容器的父容器。这个pause容器有两个核心的功能,一是它提供整个Pod的Linux命名
空间的基础。二来启用PID命名空间,它在每个Pod中都作为PID为1进程(init进程) ,并回收僵尸进程

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

- 存储:
可以Pod指定多个共享的Volume。Pod中的所有容器都可以访问共享的Volume。Volume也可以用来持久化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中的pause容器主要为每个业务容器提供以下功能:======
- 在pod中担任Linux命名空间(如网络命令空间)共享的基础;
- 启用PID命名空间,开启init进程

======Kubernetes设计这样的Pod概念和特殊组成结构有什么用意?======
- 原因一:在一组容器作为一个单元的情况下,难以对整体的容器简单地进行判断及有效地进行行动。比如,一个容器死亡了,此时是算整
体挂了么?那么引入与业务无关的Pause容器作为Pod的根容器,以它的状态代表着整个容器组的状态,这样就可以解决该问题

- 原因二:Pod里的多个业务容器共享Pause容器的IP,共享Pause容器挂载的Volume,这样简化了业务容器之间的通信问题,也解决了容器
之间的文件共享问题

二、pod容器的分类

======Pod容器的分类:======
1、基础容器( infrastructure container)
//维护整个Pod网络和存储空间
//node节点中操作
//启动一个容器时,k8s会自动启动一个基础容器
cat /opt/kubernetes/cfg/kubelet
-- pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0

//每次创建Pod 时候就会创建,运行的每一个容器都有一个pause-amd64 的基础容器自动会运行,对于用户是透明的
docker ps -a 
registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0 "/pause"

2、初始化容器( initcontainers )
//Init容器必须在应用程序容器启动之前运行完成,而应用程序容器是并行运行的,所以Init容器能够提供了一种简单的阻塞或延迟应用
容器的启动的方法。

Init容器与普通的容器非常像,除了以下两点:
- Init容器总是运行到成功完成为止
- 每个Init 容器都必须在下一个Init 容器启动之前成功完成
如果Pod的Init 容器失败,k8s会不断地重启该Pod, 直到Init 容器成功为止。然而,如果Pod
对应的重启策略( restartPolicy)为Never, 它不会重新启动

3、业务容器( Maincontainer )
//并行启动
官网示例: 
https://kubernetes.io/docs/concepts/workloads/pods/init-containers/

//特别说明:
- 在Pod启动过程中,Init容器会按顺序在网络和数据卷初始化之后启动。每个容器必须在下一个容器启动之前成功退出
- 如果由于运行时或失败退出,将导致容器启动失败,它会根据Pod的restartPolicy指定的策略进行重试。然而,如果Pod的restartPolicy
设置为Always,Init容 器失败时会使用RestartPolicy策略
- 在所有的Init容器没有成功之前,Pod将不 会变成Ready状态。Init 容器的端口将不会在Service中进行聚集。正在初始化中的Pod处于Pend
ing状态,但应该会将Initializing状态设置为true
- 如果Pod重启,所有Init容器必须重新执行
- 对Init容器spec的修改被限制在容器image字段, 修改其他字段都不会生效。更改Init容器的image字段, 等价于重启该Pod
- Init容器具有应用容器的所有字段。除了readinessProbe,因为Init容器无法定义不同于完成(completion) 的就绪( readiness)之外的其他状态。这会在验证过程中强制执行
- 在Pod中的每个app和Init容器的名称必须唯一;与任何其它容器共享同一个名称,会在验证时抛出错误

//镜像拉取策略( image PullPolicy) :
Pod的核心是运行容器,必须指定容器引擎,比如Docker, 启动容器时,需要拉取镜像,k8s 的镜像拉取策略可以由用户指定:
1、IfNotPresent:在镜像已经存在的情况下,kubelet将不再去拉取镜像,仅当本地缺失时才从仓库中拉取,默认的镜像拉取策略
2、Always: 每次创建Pod 都会重新拉取一次镜像;
3、Never: Pod不会主动拉取这个镜像,仅使用本地镜像
注意:对于标签为“:latest”的镜像文件,其默认的镜像获取策略即为“Always”;而对于其他标签的镜像,其默认策略则为“IfNotPresent"
Pod 进阶

三、资源限制

  • 当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。
    最常见的可设定资源是 CPU 和内存大小,以及其他类型的资源。

  • 当为 Pod 中的容器指定了 request 资源时,调度器就使用该信息来决定将 Pod 调度到哪个节点上。
    当还为容器指定了 limit 资源时,kubelet 就会确保运行的容器不会使用超出所设的 limit 资源量。
    kubelet 还会为容器预留所设的 request 资源量, 供该容器使用。

  • 如果 Pod 运行所在的节点具有足够的可用资源,容器可以使用超出所设置的 request 资源量。
    不过,容器不可以使用超出所设置的 limit 资源量。

  • 如果给容器设置了内存的 limit 值,但未设置内存的 request 值,Kubernetes 会自动为其设置与内存 limit 相匹配的 request 值。
    类似的,如果给容器设置了 CPU 的 limit 值但未设置 CPU 的 request 值,则 Kubernetes 自动为其设置 CPU 的 request 值 并使之与 CPU 的 limit 值匹配。

官网示例:
https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

//Pod和容器的资源请求和限制:
spec.containers[].resources.requests.cpu		//定义创建容器时预分配的CPU资源
spec.containers[].resources.requests.memory		//定义创建容器时预分配的内存资源
spec.containers[].resources.limits.cpu			//定义 cpu 的资源上限 
spec.containers[].resources.limits.memory		//定义内存的资源上限

四、CPU 资源单位

  • CPU 资源的 request 和 limit 以 cpu 为单位。Kubernetes 中的一个 cpu 相当于1个 vCPU(1个超线程)。
  • Kubernetes 也支持带小数 CPU 的请求。spec.containers[].resources.requests.cpu 为 0.5 的容器能够获得一个 cpu 的一半 CPU 资源(类似于Cgroup对CPU资源的时间分片)。
  • 表达式 0.1 等价于表达式 100m(毫核),表示每 1000 毫秒内容器可以使用的 CPU 时间总量为 0.1*1000 毫秒。

五、内存资源单位

内存的 request 和 limit 以字节为单位。可以以整数表示,或者以10为底数的指数的单位(E、P、T、G、M、K)来表示, 或者以2为底数的指数的单位(Ei、Pi、Ti、Gi、Mi、Ki)来表示。

如:1KB=10^3=10001MB=10^6=1000000=1000KB,1GB=10^9=1000000000=1000MB
1KiB=2^10=10241MiB=2^20=1048576=1024KiB

PS:在买硬盘的时候,操作系统报的数量要比产品标出或商家号称的小一些,主要原因是标出的是以 MB、GB为单位的,1GB 就是1,000,000,000Byte,而操作系统是以2进制为处理单位的,因此检查硬盘容量时是以MiB、GiB为单位,1GB=2^30=1,073,741,824,相比较而言,1GiB要比1GB多出1,073,741,824-1,000,000,000=73,741,824Byte,所以检测实际结果要比标出的少一些。

示例1
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

此例子中的 Pod 有两个容器。每个容器的 request 值为 0.25 cpu 和 64MiB 内存,每个容器的 limit 值为 0.5 cpu 和 128MiB 内存。那么可以认为该 Pod 的总的资源 request 为 0.5 cpu 和 128 MiB 内存,总的资源 limit 为 1 cpu 和 256MiB 内存。

示例2
vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: web
    image: nginx
    env:
    - name: WEB_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"


kubectl apply -f pod2.yaml
kubectl describe pod frontend

kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
frontend   2/2     Running   5          15m   10.244.2.4   node02   <none>           <none>

kubectl describe nodes node02				#由于当前虚拟机有2个CPU,所以Pod的CPU Limits一共占用了50%
Namespace                  Name                           CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                  ----                           ------------  ----------  ---------------  -------------  ---
  default                    frontend                       500m (25%)    1 (50%)     128Mi (3%)       256Mi (6%)     16m
  kube-system                kube-flannel-ds-amd64-f4pbp    100m (5%)     100m (5%)   50Mi (1%)        50Mi (1%)      19h
  kube-system                kube-proxy-pj4wp               0 (0%)        0 (0%)      0 (0%)           0 (0%)         19h
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests    Limits
  --------           --------    ------
  cpu                600m (30%)  1100m (55%)
  memory             178Mi (4%)  306Mi (7%)
  ephemeral-storage  0 (0%)      0 (0%)

六、重启策略(restartPolicy)

——Pod在遇到故障之后重启的动作

  1. Always:当容器终止退出后,总是重启容器,默认策略
  2. OnFailure:当容器异常退出(退出状态码非0)时,重启容器;正常退出则不重启容器
  3. Never:当容器终止退出,从不重启容器。
    注意K8S 中不支持重启 Pod 资源,只有删除重建
kubectl edit deployment nginx-deployment
......
 restartPolicy: Always


//示例
vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
  - name: busybox
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 30; exit 3


kubectl apply -f pod3.yaml
//查看Pod状态,等容器启动后30秒后执行exit退出进程进入error状态,就会重启次数加1
kubectl get pods
NAME                              READY   STATUS             RESTARTS   AGE
foo                               1/1     Running            1          50s


kubectl delete -f pod3.yaml

vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
  - name: busybox
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 30; exit 3
  restartPolicy: Never
#注意:跟container同一个级别

kubectl apply -f pod3.yaml

//容器进入error状态不会进行重启
kubectl get pods -w

七、健康检查:又称为探针(Probe)

探针是由kubelet对容器执行的定期诊断。

探针的三种规则:

  • livenessProbe :判断容器是否正在运行。如果探测失败,则kubelet会杀死容器,并且容器将根据 restartPolicy 来设置 Pod 状态。如果容器不提供存活探针,则默认状态为Success。

  • readinessProbe:判断容器是否准备好接受请求。如果探测失败,端点控制器将从与 Pod 匹配的所有 service endpoints 中剔除删除该Pod的IP地址。初始延迟之前的就绪状态默认为Failure。如果容器不提供就绪探针,则默认状态为Success。

  • startupProbe(这个1.17版本增加的):判断容器内的应用程序是否已启动,主要针对于不能确定具体启动时间的应用。如果配置了 startupProbe 探测,在则在 startupProbe 状态为 Success 之前,其他所有探针都处于无效状态,直到它成功后其他探针才起作用。 如果 startupProbe 失败,kubelet 将杀死容器,容器将根据 restartPolicy 来重启。如果容器没有配置 startupProbe, 则默认状态为 Success。
    #注:以上规则可以同时定义。在readinessProbe检测成功之前,Pod的running状态是不会变成ready状态的。

Probe支持三种检查方法:

  • exec :在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功。

  • tcpSocket :对指定端口上的容器的IP地址进行TCP检查(三次握手)。如果端口打开,则诊断被认为是成功的。

  • httpGet :对指定的端口和路径上的容器的IP地址执行HTTPGet请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的

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

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

官网示例:
https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

//示例1:exec方式
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      failureThreshold: 1
      initialDelaySeconds: 5
      periodSeconds: 5
#initialDelaySeconds:指定 kubelet 在执行第一次探测前应该等待5秒,即第一次探测是在容器启动后的第6秒才开始执行。默认是 0 秒,最小值是 0。
#periodSeconds:      指定了 kubelet 应该每 5 秒执行一次存活探测。默认是 10 秒。最小值是 1。
#failureThreshold:    当探测失败时,Kubernetes 将在放弃之前重试的次数。 存活探测情况下的放弃就意味着重新启动容器。就绪探测情况下的放弃 Pod 会被打上未就绪的标签。默认值是 3。最小值是 1。
#timeoutSeconds:探测的超时后等待多少秒。默认值是 1 秒。最小值是 1。(在 Kubernetes 1.20 版本之前,exec 探针会忽略 timeoutSeconds 探针会无限期地 持续运行,甚至可能超过所配置的限期,直到返回结果为止。)
  • 可以看到 Pod 中只有一个容器。
  • kubelet 在执行第一次探测前需要等待 5 秒,kubelet 会每 5 秒执行一次存活探测。
  • kubelet 在容器内执行命令 cat /tmp/healthy 来进行探测。如果命令执行成功并且返回值为 0,kubelet 就会认为这个容器是健康存活的。
  • 当到达第 31 秒时,这个命令返回非 0 值,kubelet 会杀死这个容器并重新启动它。
vim exec.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec
  namespace: default
spec:
  containers:
  - name: liveness-exec-container
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c","touch /tmp/live ; sleep 30; rm -rf /tmp/live; sleep 3600"]
    livenessProbe:
      exec:
        command: ["test","-e","/tmp/live"]
      initialDelaySeconds: 1
      periodSeconds: 3
	  
kubectl create -f exec.yaml

kubectl describe pods liveness-exec
Events:
  Type     Reason     Age               From               Message
  ----     ------     ----              ----               -------
  Normal   Scheduled  51s               default-scheduler  Successfully assigned default/liveness-exec-pod to node02
  Normal   Pulled     46s               kubelet, node02    Container image "busybox" already present on machine
  Normal   Created    46s               kubelet, node02    Created container liveness-exec-container
  Normal   Started    45s               kubelet, node02    Started container liveness-exec-container
  Warning  Unhealthy  8s (x3 over 14s)  kubelet, node02    Liveness probe failed:
  Normal   Killing    8s                kubelet, node02    Container liveness-exec-container failed liveness probe,will be restarted

kubectl get pods -w
NAME                READY   STATUS    RESTARTS   AGE
liveness-exec       1/1     Running   1          85s
//示例2:httpGet方式
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/liveness
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 3
      periodSeconds: 3
  • 在这个配置文件中,可以看到 Pod 也只有一个容器。
    initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 3 秒。periodSeconds 字段指定了 kubelet 每隔 3 秒执行一次存活探测。
    kubelet 会向容器内运行的服务(服务会监听 8080 端口)发送一个 HTTP GET 请求来执行探测。
    如果服务器上 /healthz 路径下的处理程序返回成功代码,则 kubelet 认为容器是健康存活的。
    如果处理程序返回失败代码,则 kubelet 会杀死这个容器并且重新启动它。

  • 任何大于或等于 200 并且小于 400 的返回代码标示成功,其它返回代码都标示失败。

vim httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget
  namespace: default
spec:
  containers:
  - name: liveness-httpget-container
    image: soscscs/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10
	  
kubectl create -f httpget.yaml

kubectl exec -it liveness-httpget -- rm -rf /usr/share/nginx/html/index.html

kubectl get pods
NAME               READY   STATUS    RESTARTS   AGE
liveness-httpget   1/1     Running   1          2m44s
//示例3:tcpSocket方式
apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: k8s.gcr.io/goproxy:0.1
    ports:
    - containerPort: 8080
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20
  • 这个例子同时使用 readinessProbe 和 livenessProbe 探测。
  • kubelet 会在容器启动 5 秒后发送第一个 readinessProbe 探测。
  • 这会尝试连接 goproxy 容器的 8080 端口。
  • 如果探测成功,kubelet 将继续每隔 10 秒运行一次检测。
  • 除了 readinessProbe 探测,这个配置包括了一个 livenessProbe 探测。kubelet 会在容器启动 15 秒后进行第一次 livenessProbe 探测。
  • 就像 readinessProbe 探测一样,会尝试连接 goproxy 容器的 8080 端口。
  • 如果 livenessProbe 探测失败,这个容器会被重新启动。
vim tcpsocket.yaml
apiVersion: v1
kind: Pod
metadata:
  name: probe-tcp
spec:
  containers:
  - name: nginx
    image: soscscs/myapp:v1
    livenessProbe:
      initialDelaySeconds: 5
      timeoutSeconds: 1
      tcpSocket:
        port: 8080
      periodSeconds: 3

kubectl create -f tcpsocket.yaml

kubectl exec -it probe-tcp  -- netstat -natp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1/nginx: master pro

kubectl get pods -w
NAME        READY   STATUS    RESTARTS   AGE
probe-tcp   1/1     Running   0          4s
probe-tcp   1/1     Running   1          14s
probe-tcp   1/1     Running   2          26s
//示例4:就绪检测
vim readiness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget
  namespace: default
spec:
  containers:
  - name: readiness-httpget-container
    image: soscscs/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    readinessProbe:
      httpGet:
        port: 80
        path: /index1.html
      initialDelaySeconds: 1
      periodSeconds: 3
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10

kubectl create -f readiness-httpget.yaml

//readiness探测失败,无法进入READY状态
kubectl get pods 
NAME                READY   STATUS    RESTARTS   AGE
readiness-httpget   0/1     Running   0          18s

kubectl exec -it readiness-httpget sh
 # cd /usr/share/nginx/html/
 # ls
50x.html    index.html
 # echo 123 > index1.html 
 # exit

kubectl get pods 
NAME                READY   STATUS    RESTARTS   AGE
readiness-httpget   1/1     Running   0          2m31s

kubectl exec -it readiness-httpget -- rm -rf /usr/share/nginx/html/index.html

kubectl get pods -w
NAME                READY   STATUS    RESTARTS   AGE
readiness-httpget   1/1     Running   0          4m10s
readiness-httpget   0/1     Running   1          4m15s
//示例5:就绪检测2
vim readiness-myapp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp1
  labels:
     app: myapp
spec:
  containers:
  - name: myapp
    image: soscscs/myapp:v1
    ports:
    - name: http
      containerPort: 80
    readinessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 10 
---
apiVersion: v1
kind: Pod
metadata:
  name: myapp2
  labels:
     app: myapp
spec:
  containers:
  - name: myapp
    image: soscscs/myapp:v1
    ports:
    - name: http
      containerPort: 80
    readinessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 10 
---
apiVersion: v1
kind: Pod
metadata:
  name: myapp3
  labels:
     app: myapp
spec:
  containers:
  - name: myapp
    image: soscscs/myapp:v1
    ports:
    - name: http
      containerPort: 80
    readinessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 10 
---
apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  selector:
    app: myapp
  type: ClusterIP
  ports:
  - name: http
    port: 80
    targetPort: 80

kubectl create -f readiness-myapp.yaml

kubectl get pods,svc,endpoints -o wide
NAME         READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
pod/myapp1   1/1     Running   0          3m42s   10.244.2.13   node02   <none>           <none>
pod/myapp2   1/1     Running   0          3m42s   10.244.1.15   node01   <none>           <none>
pod/myapp3   1/1     Running   0          3m42s   10.244.2.14   node02   <none>           <none>

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE     SELECTOR
......
service/myapp        ClusterIP   10.96.138.13   <none>        80/TCP    3m42s   app=myapp

NAME                   ENDPOINTS                                      AGE
......
endpoints/myapp        10.244.1.15:80,10.244.2.13:80,10.244.2.14:80   3m42s


kubectl exec -it pod/myapp1 -- rm -rf /usr/share/nginx/html/index.html
//readiness探测失败,Pod 无法进入READY状态,且端点控制器将从 endpoints 中剔除删除该 Pod  IP 地址
kubectl get pods,svc,endpoints -o wide
NAME         READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
pod/myapp1   0/1     Running   0          5m17s   10.244.2.13   node02   <none>           <none>
pod/myapp2   1/1     Running   0          5m17s   10.244.1.15   node01   <none>           <none>
pod/myapp3   1/1     Running   0          5m17s   10.244.2.14   node02   <none>           <none>

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE     SELECTOR
......
service/myapp        ClusterIP   10.96.138.13   <none>        80/TCP    5m17s   app=myapp

NAME                   ENDPOINTS                       AGE
......
endpoints/myapp        10.244.1.15:80,10.244.2.14:80   5m17s


//启动、退出动作
vim post.yaml
apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: soscscs/myapp:v1
    lifecycle:   #此为关键字段
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler >> /var/log/nginx/message"]      
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the poststop handler >> /var/log/nginx/message"]
    volumeMounts:
    - name: message-log
      mountPath: /var/log/nginx/
      readOnly: false
  initContainers:
  - name: init-myservice
    image: soscscs/myapp:v1
    command: ["/bin/sh", "-c", "echo 'Hello initContainers'   >> /var/log/nginx/message"]
    volumeMounts:
    - name: message-log
      mountPath: /var/log/nginx/
      readOnly: false
  volumes:
  - name: message-log
    hostPath:
      path: /data/volumes/nginx/log/
      type: DirectoryOrCreate

kubectl create -f post.yaml

kubectl get pods -o wide
NAME             READY   STATUS    RESTARTS   AGE    IP            NODE     NOMINATED NODE   READINESS GATES
lifecycle-demo   1/1     Running   0          2m8s   10.244.2.28   node02   <none>           <none>

kubectl exec -it lifecycle-demo -- cat /var/log/nginx/message
Hello initContainers
Hello from the postStart handler

// node02 节点上查看
[root@node02 ~]# cd /data/volumes/nginx/log/
[root@node02 log]# ls
access.log  error.log  message
[root@node02 log]# cat message 
Hello initContainers
Hello from the postStart handler
#由上可知,init Container先执行,然后当一个主容器启动后,Kubernetes 将立即发送 postStart 事件。

//删除 pod 后,再在 node02 节点上查看
kubectl delete pod lifecycle-demo

[root@node02 log]# cat message 
Hello initContainers
Hello from the postStart handler
Hello from the poststop handler
#由上可知,当在容器被终结之前, Kubernetes 将发送一个 preStop 事件。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值