赞
踩
前言
在 Kubernetes 中,定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存大小,以及其他类型的资源;另一方面,通过配置探针,可以确保容器在运行时保持健康,并且只有在准备好接收流量时才会被负载均衡器引导流量。从而提高应用程序的可靠性和稳定性。
目录
在 K8s 中,对 Pod 容器的资源限制主要围绕着两个关键参数:request 资源和 limit 资源,用于配置 CPU 和内存的使用情况;避免资源竞争和不必要的浪费,同时确保 Pod 在运行时具有足够的资源支持。
参考官网示例:为 Pod 和容器管理资源 | Kubernetes
针对每个容器,你都可以指定其资源限制和请求,包括如下选项:
创建 pod 容器时需要预留的资源量,cpu(0.5 或 500m),内存 Mi、Gi(以2为底的幂数),M、G(以10为底)。
- spec.containers[].resources.requests.cpu
- spec.containers[].resources.requests.memory
pod 容器能够使用资源量的一个上限。如:4Gi 代表内存上限不允许超过上限值;1 代表 cpu 上限不允许超过上限值。
- spec.containers[].resources.limits.cpu
- spec.containers[].resources.limits.memory
在 K8s 中,一个 CPU 等于 1 个物理 CPU 核 或者 1 个虚拟核, 取决于节点是一台物理主机还是运行在某物理主机上的虚拟机。
当定义一个容器,将其 spec.containers[].resources.requests.cpu 设置为 0.5 时, 所请求的 CPU 是请求 1.0 CPU 时的一半。 对于 CPU 资源单位,数量表达式 0.1 等价于表达式 100m(一百毫核),可以看作 “100 millicpu”。
注意:K8s 不允许设置精度小于 1m 或 0.001 的 CPU 资源。
memory 的限制和请求以字节为单位。 可以使用普通的整数,或者带有以下 数量后缀 的定点数字来表示内存:E、P、T、G、M、k。 也可以使用对应的 2 的幂数:Ei、Pi、Ti、Gi、Mi、Ki。
如果 Pod 运行所在的节点具有足够的可用资源,容器可以使用超出所设置的 request 资源量。不过,容器不可以使用超出所设置的 limit 资源量。
如果给容器设置了内存的 limit 值,但未设置内存的 request 值,Kubernetes 会自动为其设置与内存 limit 相匹配的 request 值;类似的 cpu 同理。
以下例子中的 Pod 有两个容器。每个容器的 request 值为 0.25 cpu 和 64MiB 内存,每个容器的 limit 值为 0.5 cpu 和 128MiB 内存。那么可以认为该 Pod 的总的资源 request 为 0.5 cpu 和 128 MiB 内存,总的资源 limit 为 1 cpu 和 256MiB 内存。
- [root@master01 demo]# vim demo1.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: demo-01
- spec:
- containers:
- - name: app
- image: images.my-company.example/app:v4
- env: # 定义了容器的环境变量
- - name: MYSQL_ROOT_PASSWORD # 设置环境变量
- value: "123456" # 环境变量的值
- resources: # 容器的资源限制和请求
- requests: # 容器的资源请求
- memory: "64Mi" # 请求容器使用的内存量为64MiB
- cpu: "250m" # 请求容器使用的CPU量为250 m
- limits: # 容器的资源限制
- memory: "128Mi" # 限制容器使用的最大内存量为128MiB
- cpu: "500m" # 限制容器使用的最大CPU量为500 m
- - name: log-aggregator
- image: images.my-company.example/log-aggregator:v6
- resources: # 容器的资源限制和请求
- requests: # 容器的资源请求
- memory: "64Mi" # 容器使用的内存量为64MiB
- cpu: "250m" # 第二个容器使用的CPU量为250 m
- limits: # 容器的资源限制
- memory: "128Mi" # 限制第二个容器使用的最大内存量为128MiB
- cpu: "500m" # 限制第二个容器使用的最大CPU量为500 m
为了模拟内存耗尽情况并观察OOMKilled(Out Of Memory Killed)内存耗尽保护机制的效果,我们将调整数据库容器的资源请求(requests)和内存限制(limits)到一个较小的值,以便触发内存不足的情况。
请注意,在生产环境中,调整容器的资源请求和限制应该谨慎进行,以避免对系统产生不可预料的影响。
① 创建 yaml 文件
- [root@master01 demo]# vim demo2.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: web-db
- spec:
- containers:
- - name: web
- image: nginx
- env:
- - name: WEB_ROOT_PASSWORD
- value: "123123"
- resources:
- requests:
- memory: "64Mi"
- cpu: "250m"
- limits:
- memory: "128Mi"
- cpu: "500m"
- - name: db
- image: mysql
- env:
- - name: MYSQL_ROOT_PASSWORD
- value: "123123"
- resources:
- requests:
- memory: "64Mi"
- cpu: "0.25"
- limits:
- memory: "128Mi"
- cpu: "500m"
② 启动 pod
- [root@master01 demo]# kubectl apply -f demo2.yaml
- pod/web-db created
③ 查看资源信息
- [root@master01 demo]# kubectl get pod web-db -w
- NAME READY STATUS RESTARTS AGE
- web-db 0/2 ContainerCreating 0 18s
- web-db 2/2 Running 0 63s
- web-db 1/2 OOMKilled 0 76s
- web-db 2/2 Running 1 93s
- web-db 1/2 OOMKilled 1 105s
- web-db 1/2 CrashLoopBackOff 1 2m
- web-db 2/2 Running 2 2m1s
- web-db 1/2 OOMKilled 2 2m14s
- web-db 1/2 CrashLoopBackOff 2 2m28s
- # 多次出现的 OOMKilled 表示容器由于内存耗尽而被系统终止
-
- [root@master01 demo]# kubectl describe pod web-db
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal Scheduled 3m20s default-scheduler Successfully assigned default/web-db to node01
- Normal Pulling 3m19s kubelet Pulling image "nginx"
- Normal Pulled 3m4s kubelet Successfully pulled image "nginx" in 15.521857377s
- Normal Created 3m4s kubelet Created container web
- Normal Started 3m4s kubelet Started container web
- Normal Pulled 2m18s kubelet Successfully pulled image "mysql" in 46.048445572s
- Normal Pulled 108s kubelet Successfully pulled image "mysql" in 15.474925496s
- Normal Pulled 80s kubelet Successfully pulled image "mysql" in 399.833869ms
- Normal Pulling 38s (x4 over 3m4s) kubelet Pulling image "mysql"
- Normal Created 38s (x4 over 2m17s) kubelet Created container db
- Normal Started 38s (x4 over 2m17s) kubelet Started container db
- Normal Pulled 38s kubelet Successfully pulled image "mysql" in 388.467767ms
- Warning BackOff 13s (x5 over 95s) kubelet Back-off restarting failed container
- # 容器 "db" 失败并且在多次尝试后仍然无法成功启动,导致触发了 BackOff 机制
④ 调整资源配额限制
- [root@master01 demo]# kubectl delete -f demo2.yaml
- pod "web-db" deleted
- [root@master01 demo]# vim demo2.yaml
- resources:
- requests:
- memory: "128Mi"
- cpu: "0.5"
- limits:
- memory: "1Gi"
- cpu: "1000m"
⑤ 再次尝试启动 pod
- [root@master01 demo]# kubectl apply -f demo2.yaml
- pod/web-db created
-
- [root@master01 demo]# kubectl get pod web-db
- NAME READY STATUS RESTARTS AGE
- web-db 2/2 Running 0 42s
⑥ 查看 node 节点资源占比
- [root@master01 demo]# kubectl get pod web-db -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- web-db 2/2 Running 0 94s 10.244.1.22 node01 <none> <none>
-
- [root@master01 demo]# kubectl describe node node01
- Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
- --------- ---- ------------ ---------- --------------- ------------- ---
- default pod-01 0 (0%) 0 (0%) 0 (0%) 0 (0%) 4h19m
- default web-db 750m (37%) 1500m (75%) 192Mi (11%) 1152Mi (66%) 2m13s
- kube-flannel kube-flannel-ds-wz8p2 100m (5%) 0 (0%) 50Mi (2%) 0 (0%) 8d
- kube-system kube-proxy-w7vl7 0 (0%) 0 (0%) 0 (0%) 0 (0%) 8d
- Allocated resources:
- (Total limits may be over 100 percent, i.e., overcommitted.)
- Resource Requests Limits
- -------- -------- ------
- cpu 850m (42%) 1500m (75%)
- memory 242Mi (14%) 1152Mi (66%)
- ephemeral-storage 0 (0%) 0 (0%)
- hugepages-1Gi 0 (0%) 0 (0%)
- hugepages-2Mi 0 (0%) 0 (0%)
Pod "web-db" 的资源请求和限制如下:
已分配的资源情况如下:
探针是由 kubelet 对容器执行的定期诊断。容器的探针是一种关键的机制,用于监测和管理容器的健康状态,确保容器在各种情况下都能正常运行。通过配置适当的探针,可以提高容器的可靠性和稳定性,确保容器能够有效应对各种运行时情况,并及时处理健康状态的变化。
在 Kubernetes 中,探针(Probes)用于监测容器的健康状态和确定容器是否已准备好接收流量。主要有三种类型的探针:
用于确定容器是否正在运行并且健康。如果存活探针失败,Kubernetes 将根据重启策略(如 `RestartPolicy`)尝试重新启动容器。如果容器不提供存活探针,则默认状态为 Success。
用于确定容器是否已准备好接收流量。如果就绪探针失败,容器将被从 Service 的负载均衡池中移除该 Pod 的 IP 地址,直到就绪探针再次成功。初始延迟之前的就绪状态默认为 Failure。如果容器不提供就绪探针,则默认状态为 Success。
1.17版本增加的。用于确定容器是否已经启动并且已经准备好接收其它探针的检查。启动探针在容器启动后执行,但在就绪探针和存活探针之前执行。
如果 startupProbe 失败,kubelet 将杀死容器,容器将根据 restartPolicy 来重启。如果容器没有配置 startupProbe, 则默认状态为 Success。
以上规则可以同时定义。在 readinessProbe 检测成功之前,Pod 的 running 状态是不会变成 ready 状态的。通过配置这些探针,可以确保容器在运行时保持健康,并且只有在准备好接收流量时才会被负载均衡器引导流量。这有助于提高应用程序的可靠性和稳定性。
每次探测都将获得以下三种结果之一:
许多长时间运行的应用最终会进入损坏状态,除非重新启动,否则无法被恢复。 Kubernetes 提供了存活探针来发现并处理这种情况。
示例1:livenessProbe 规则,配合 exec 检查方法。
① 编辑 pod 的 yaml 配置文件
- [root@master01 demo]# vim demo3.yaml
- apiVersion: v1
- kind: Pod
- metadata: # 元数据
- labels: # Pod 的标签
- test: liveness
- name: liveness-exec
- spec: # Pod 的规格
- containers: # 容器列表
- - name: liveness # 容器的名称
- image: busybox # 一个轻量级的 BusyBox 镜像
- imagePullPolicy: IfNotPresent # 镜像拉取策略,先本地后仓库
- args: # 容器的启动参数部分
- - /bin/sh
- - -c # 后面的内容将作为 shell 的命令执行
- - touch /tmp/healthy; sleep 10; rm -rf /tmp/healthy; sleep 10
- # 在容器启动时执行的命令,首先创建一个/tmp/healthy文件,然后等待10秒,接着删除该文件,最后再等待10秒
- livenessProbe: # 定义存活探针的配置
- exec: # 使用 exec 方式执行命令
- command: # 要执行的命令
- - cat
- - /tmp/healthy # 读取 /tmp/healthy 文件的内容
- failureThreshold: 1 # 存活探针的失败阈值为1,即连续失败1次后认为探针失败,默认值是3。最小值是1
- initialDelaySeconds: 3 # 容器启动后等待3秒开始进行存活探测,其实是4秒,默认是0秒,最小值是0
- periodSeconds: 2 # 每隔2秒进行一次存活探测,默认是10秒。最小值是1。
这个容器生命的前 10 秒,/tmp/healthy 文件是存在的。 所以在这最开始的 10 秒内,执行命令 cat /tmp/healthy 会返回成功代码。 10 秒之后,执行命令 cat /tmp/healthy 就会返回失败代码。
② 启动 pod
- [root@master01 demo]# kubectl apply -f demo3.yaml
- pod/liveness-exec created
③ 查看容器状态详情信息
- [root@master01 demo]# kubectl get pod liveness-exec -w
- NAME READY STATUS RESTARTS AGE
- liveness-exec 1/1 Running 0 3s
- liveness-exec 1/1 Running 1 22s
- liveness-exec 1/1 Running 2 43s
- liveness-exec 1/1 Running 3 63s
- liveness-exec 1/1 Running 4 83s
- liveness-exec 0/1 CrashLoopBackOff 4 103s
- # Pod中的容器liveness由于存活探针失败而不断重启,并最终进入了CrashLoopBackOff状态
- # 输出结果显示RESTARTS的值增加了1。 请注意,一旦失败的容器恢复为运行状态,RESTARTS计数器就会加1
-
- 查看 Pod 的事件:
- [root@master01 demo]# kubectl describe pod liveness-exec
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal Scheduled 2m24s default-scheduler Successfully assigned default/liveness-exec to node01
- Normal Pulled 62s (x5 over 2m24s) kubelet Container image "busybox" already present on machine
- Normal Created 62s (x5 over 2m24s) kubelet Created container liveness
- Normal Started 62s (x5 over 2m24s) kubelet Started container liveness
- Warning Unhealthy 51s (x5 over 2m13s) kubelet Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
- Normal Killing 51s (x5 over 2m13s) kubelet Container liveness failed liveness probe, will be restarted
- # 显示存活探针失败了,这个失败的容器被杀死并且被重建了
- # 是否重启还是根据重启策略来决定,这里明显是always
另外一种类型的存活探测方式是使用 HTTP GET 请求。
示例2:livenessProbe 规则,配合 httpGet 检查方法。
① 编辑 pod 的 yaml 配置文件
- [root@master01 demo]# vim demo4.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 # 容器内部的端口号为 80
- livenessProbe: # 定义存活探针的配置
- httpGet: # 使用HTTP GET请求方式进行探测
- port: http # 探测请求发送到的端口为http,即容器内部的80端口
- path: /index.html # 探测请求的路径为 /index.html
- initialDelaySeconds: 1 # 容器启动后等待1秒后开始进行存活探测
- periodSeconds: 3 # 每隔3秒进行一次存活探测
- timeoutSeconds: 5 # 超时时间为5秒
如果存活探针发送的 HTTPGET 请求返回成功(即能够访问到 /index.html),则认为容器是健康的。如果请求失败(无法访问到 /index.html 或返回错误),则认为容器不健康处理程序返回失败代码,kubelet 会杀死这个容器并且重新启动它。
② 启动 pod
- [root@master01 demo]# kubectl apply -f demo4.yaml
- pod/liveness-httpget created
-
- [root@master01 demo]# kubectl get pod liveness-httpget -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- liveness-httpget 1/1 Running 0 65s 10.244.1.24 node01 <none> <none>
-
- 尝试访问页面:
- [root@master01 demo]# curl 10.244.1.24
- Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
- [root@master01 demo]# curl 10.244.1.24 -I
- Server: nginx/1.12.2
③ 删除容器中 index.html
[root@master01 demo]# kubectl exec -it liveness-httpget -- rm -f /usr/share/nginx/html/index.html
③ 查看容器状态详情信息
- [root@master01 demo]# kubectl get pod liveness-httpget
- NAME READY STATUS RESTARTS AGE
- liveness-httpget 1/1 Running 2 5m42s
-
- [root@master01 demo]# kubectl describe pod liveness-httpget
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal Scheduled 6m32s default-scheduler Successfully assigned default/liveness-httpget to node01
- Normal Pulling 6m32s kubelet Pulling image "soscscs/myapp:v1"
- Normal Pulled 6m14s kubelet Successfully pulled image "soscscs/myapp:v1" in 18.054706565s
- Normal Created 66s (x3 over 6m13s) kubelet Created container liveness-httpget-container
- Warning Unhealthy 66s (x6 over 2m54s) kubelet Liveness probe failed: HTTP probe failed with statuscode: 404
- Normal Killing 66s (x2 over 2m48s) kubelet Container liveness-httpget-container failed liveness probe, will be restarted
- Normal Pulled 66s (x2 over 2m48s) kubelet Container image "soscscs/myapp:v1" already present on machine
- Normal Started 65s (x3 over 6m13s) kubelet Started container liveness-httpget-container
容器中的存活探针失败是因为 HTTP 探测返回了状态码 404,表示无法访问到指定的路径 /index.html。因此,容器被标记为不健康,被 Kubernetes 系统自动重新启动以尝试恢复其健康状态。
使用这种配置时,kubelet 会尝试在指定端口和容器建立套接字链接。 如果能建立连接,这个容器就被看作是健康的,如果不能则这个容器就被看作是有问题的。
示例3:livenessProbe 规则,配合 tcpSocket 检查方法。
① 编辑 pod 的 yaml 配置文件
- [root@master01 demo]# vim demo5.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: probe-tcp
- spec:
- containers:
- - name: nginx
- image: soscscs/myapp:v1
- livenessProbe:
- initialDelaySeconds: 5 # 容器启动后等待 5 秒后开始执行存活探针
- timeoutSeconds: 1 # 探测超时时间为 1 秒
- tcpSocket: # 使用 TCP 探测方式
- port: 8080 # 探测的端口为 8080
- periodSeconds: 10 # 每隔 10 秒执行一次存活探针
- failureThreshold: 2 # 如果连续 2 次探测失败,则认为容器不健康
上面的 YAML 文件描述了一个名为 probe-tcp 的 Pod,其中包含一个名为 nginx 的容器,使用镜像 soscscs/myapp:v1,配置了一个针对端口 8080 的 TCP 探测器,用于检测容器的健康状态。由于业务本身端口是 80,所有这步就是探针肯定是失败的,持续查看探针过程。
② 启动 pod
- [root@master01 demo]# kubectl apply -f demo5.yaml
- pod/probe-tcp created
-
- 使用kubectl工具在名为probe-tcp的容器中执行netstat -natp命令:
- [root@master01 demo]# 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 pr
③ 持续查看容器状态详情信息
- [root@master01 demo]# kubectl get pod -w
- NAME READY STATUS RESTARTS AGE
- probe-tcp 0/1 Pending 0 0s
- probe-tcp 0/1 Pending 0 0s
- probe-tcp 0/1 ContainerCreating 0 0s
- probe-tcp 1/1 Running 0 2s
- probe-tcp 1/1 Running 1 18s
- probe-tcp 1/1 Running 2 38s
- probe-tcp 1/1 Running 3 57s
- probe-tcp 1/1 Running 4 78s
- # 由于探测8080端口失败,可以看到 Pod 重启了多次
- # 理论上第一次重启时间为:5+1+10=16秒
- # 理论上第二次重启时间为:+20秒
- # 理论上第三次重启时间为:+20秒
- # 理论上第四次重启时间为:+20秒
有时候,应用会暂时性地无法为请求提供服务。 例如,应用在启动时可能需要加载大量的数据或配置文件,或是启动后要依赖等待外部服务。 在这种情况下,既不想杀死应用,也不想给它发送请求。 Kubernetes 提供了就绪探针来发现并缓解这些情况。 容器所在 Pod 上报还未就绪的信息,并且不接受通过 Kubernetes Service 的流量。
示例4: readinessProbe 和 livenessProbe 规则,配合 httpGet 检查方法。
① 编辑 pod 的 yaml 配置文件
- [root@master01 demo]# vim demo6.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 # 指定容器将监听的端口为 80
- readinessProbe: # 定义容器的就绪性探针
- httpGet: # 指定用于就绪性检查的 HTTP GET 请求
- port: 80 # 指定进行就绪性检查的端口(端口 80)
- path: /index1.html # 指定就绪性检查期间请求的路径("/index1.html")
- initialDelaySeconds: 1 # 指定容器启动后开始就绪性探针的等待时间(1 秒)
- periodSeconds: 3 # 指定连续就绪性探针之间的间隔(3 秒)
- livenessProbe: # 定义容器的存活性探针
- httpGet: # 指定用于存活性检查的 HTTP GET 请求
- port: http # 指定进行存活性检查的端口("http"端口)
- path: /index.html # 指定存活性检查期间请求的路径("/index.html")
- initialDelaySeconds: 1 # 指定容器启动后开始存活性探针的等待时间(1 秒)
- periodSeconds: 3 # 指定连续存活性探针之间的间隔(3 秒)
- timeoutSeconds: 10 # 指定存活性探针在等待响应的最大时间(10 秒)
② 启动 pod
- [root@master01 demo]# kubectl apply -f demo6.yaml
- pod/readiness-httpget created
③ 查看容器状态详情信息
- [root@master01 demo]# kubectl get pod
- NAME READY STATUS RESTARTS AGE
- readiness-httpget 0/1 Running 0 17s
- # 0/1表示该Pod中的容器当前处于未就绪状态
-
- [root@master01 demo]# kubectl describe pod readiness-httpget
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal Scheduled 39s default-scheduler Successfully assigned default/readiness-httpget to node01
- Normal Pulled 38s kubelet Container image "soscscs/myapp:v1" already present on machine
- Normal Created 38s kubelet Created container readiness-httpget-container
- Normal Started 38s kubelet Started container readiness-httpget-container
- Warning Unhealthy 3s (x12 over 36s) kubelet Readiness probe failed: HTTP probe failed with statuscode: 404
- # 就绪性探针失败,因为 HTTP 探测返回了状态码 404,由于就绪性探针配置中指定的路径/index1.html不存在或有误。
④ 创建 index1.html 页面
- [root@master01 demo]# kubectl exec -it readiness-httpget sh
- kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
- / # echo "index1" > /usr/share/nginx/html/index1.html
- / # exit
⑤ 再次查看 pod 状态
- [root@master01 demo]# kubectl get pod
- NAME READY STATUS RESTARTS AGE
- readiness-httpget 1/1 Running 0 5m36s
- # 已就绪
⑥ 删除原有 index.html,查看存活探针结果
- [root@master01 demo]# kubectl get pod
- NAME READY STATUS RESTARTS AGE
- readiness-httpget 0/1 Running 1 9m32s
-
- [root@master01 demo]# kubectl describe pod readiness-httpget
- Warning Unhealthy 33s kubelet Liveness probe failed: HTTP probe failed with statuscode: 404
- # 无法找到 index.html 页面
下面这个 YAML 文件定义了三个名为 myapp1、myapp2 和 myapp3 的 Pod,它们使用相同的镜像并具有相似的配置,以及一个名为 myapp 的 Service,用于将流量路由到这些 Pod 上的端口 80。
测试目的:readiness 探测失败,pod 无法进入 ready 状态,则端点控制器会将 pod 从 endpoints 中剔除删除该 pod 的 IP 地址。
示例5: readinessProbe 规则,配合 httpGet 检查方法。
① 编辑 pod 的 yaml 配置文件
- [root@master01 demo]# vim readiness-httpget.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: myapp1
- labels:
- app: myapp
- spec:
- containers:
- - name: myapp
- image: soscscs/myapp:v1
- ports:
- - name: http
- containerPort: 80 # 容器内部的端口号为 80
- readinessProbe: # 定义了就绪性探针
- httpGet: # 指定了使用 HTTP GET 请求进行探测
- port: 80 # 指定了探测的端口为 80
- path: /index.html # 指定健康检查发送请求的路径为 /index.html
- initialDelaySeconds: 5 # 容器创建后等待 5 秒开始执行健康检查
- periodSeconds: 5 # 每隔 5 秒进行一次健康检查
- timeoutSeconds: 10 # 健康检查的超时时间为 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
② 启动 pod
- [root@master01 demo]# kubectl apply -f readiness-httpget.yaml
- pod/myapp1 created
- pod/myapp2 created
- pod/myapp3 created
- service/myapp created
③ 查看 pod、svc 以及关联后端的节点信息
- [root@master01 demo]# kubectl get pod,svc,endpoints -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- pod/myapp1 1/1 Running 0 28s 10.244.1.27 node01 <none> <none>
- pod/myapp2 1/1 Running 0 28s 10.244.2.10 node02 <none> <none>
- pod/myapp3 1/1 Running 0 27s 10.244.1.28 node01 <none> <none>
-
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
- service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d <none>
- service/myapp ClusterIP 10.96.35.59 <none> 80/TCP 27s app=myapp
- service/nginx NodePort 10.96.75.23 <none> 80:32165/TCP 10d app=nginx
- service/nginx-deployment NodePort 10.96.101.251 <none> 30000:31603/TCP 9d app=nginx-deployment
-
- NAME ENDPOINTS AGE
- endpoints/kubernetes 192.168.190.100:6443 10d
- endpoints/myapp 10.244.1.27:80,10.244.1.28:80,10.244.2.10:80 27s
- endpoints/nginx <none> 10d
- endpoints/nginx-deployment 10.244.1.10:80,10.244.1.11:80,10.244.2.6:80 9d
④ 删除 index.html
[root@master01 demo]# kubectl exec -it myapp3 -- rm -rf /usr/share/nginx/html/index.html
⑤ 再次查看关联后端的节点
- [root@master01 demo]# kubectl get pod,svc,endpoints -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- pod/myapp1 1/1 Running 0 2m42s 10.244.1.27 node01 <none> <none>
- pod/myapp2 1/1 Running 0 2m42s 10.244.2.10 node02 <none> <none>
- pod/myapp3 0/1 Running 0 2m41s 10.244.1.28 node01 <none> <none>
-
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
- service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d <none>
- service/myapp ClusterIP 10.96.35.59 <none> 80/TCP 2m41s app=myapp
- service/nginx NodePort 10.96.75.23 <none> 80:32165/TCP 10d app=nginx
- service/nginx-deployment NodePort 10.96.101.251 <none> 30000:31603/TCP 9d app=nginx-deployment
-
- NAME ENDPOINTS AGE
- endpoints/kubernetes 192.168.190.100:6443 10d
- endpoints/myapp 10.244.1.27:80,10.244.2.10:80 2m41s
- endpoints/nginx <none> 10d
- endpoints/nginx-deployment 10.244.1.10:80,10.244.1.11:80,10.244.2.6:80 9d
此时可以看到对于 readiness 探测失败,pod myapp3 无法进入 reday 状态,端点控制器将 pod myapp3 的 ip 从 endpoints 中剔除删除。
以下将演示在 Kubernetes 中如何定义容器的生命周期事件,包括容器启动后和终止前的操作,以及如何使用初始化容器来执行特定任务。
示例6:根据日志反馈的内容了解容器处于生命周期的哪个阶段
① 编辑 pod 的 yaml 配置文件
- [root@master01 demo]# 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 Start >> /var/log/nginx/message"]
- # 执行的命令是往日志中写入启动信息
- preStop: # 容器终止前执行的操作
- exec: # 使用执行命令的方式
- command: ["/bin/sh", "-c", "echo Hello Stop >> /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 # 类型为目录或创建
② 启动 pod
- [root@master01 demo]# kubectl create -f post.yaml
- pod/lifecycle-demo created
③ 查看 pod 详情
- [root@master01 demo]# kubectl get pods -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- lifecycle-demo 1/1 Running 0 6s 10.244.1.29 node01 <none> <none>
④ 查看容器日志
- [root@master01 demo]# kubectl exec -it lifecycle-demo -- cat /var/log/nginx/message
- Hello initContainers
- Start
由此可见,首先启动了 init 容器,然后启动成功后返回信息“Start”,代表启动成功。
⑤ 在 node01 节点查看日志
- [root@node01 ~]# cd /data/volumes/nginx/log/
- [root@node01 log]# ls
- access.log error.log message
- [root@node01 log]# cat message
- Hello initContainers
- Start
⑥ 删除 pod 后,再在 node01 节点上查看日志
- [root@master01 demo]# kubectl delete pod lifecycle-demo
- pod "lifecycle-demo" deleted
-
- [root@node01 log]# cat message
- Hello initContainers
- Start
- Stop
由此课件,当在容器被终结之前, Kubernetes 将发送一个 preStop 事件,即探针关闭生命周期结束。
pending
Running
Succeeded
Failed
unknown
Waiting
Running
Terminated
如果容器长时间处于 Waiting 状态,可以查看容器的 reason 字段,该字段会显示容器所处的状态和原因。如果 reason 显示容器再也无法启动,例如 ContainerCannotRun,整个服务启动就会迅速返回。这是一个失败状态返回的特性。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。