经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Kubernetes » 查看文章
K8s 里多容器 Pod 的健康检查探针工作机制分析
来源:cnblogs  作者:胡说云原生  时间:2023/12/13 9:10:01  对本文有异议

1. 开篇

米娜桑,宝子们,ladies and 砖头们…… 总之,我回来了!

你看这标题,没错,K8s 的。兜转两载,我还是决定从“DevOps 工程师”变回“机器学习平台研发工程师”。直观一点讲,就是“云平台开发”那点事配上 GPU 那点料,是不是很好理解?

Anyway,以后又有机会玩 K8s 了,所以接下来我会继续更新和 K8s 或者“机器学习平台”相关的内容。总之总之,你们蹲了那么久的更新,来了!

2. 聊啥

今天有个同事问我:在1个 Pod 中跑多个 Container,如果其中一个挂了,另外一个会怎样?

嗯…… 我记得大概,不过没有确切的结论,这个取决于 probes 是怎么工作的,于是我实测了一下,发现和预期不是完全一致。

于是乎,今天和大伙分享下这个知识点。

3. 结论(TL;DR)

对,结论在开头。毕竟,我知道你们都很忙。


一番操作猛如虎,然后我发现:

当1个 Pod 中包含2个 Containers 的时候,如果2个 Containers 分别对外暴露不同的端口(http 服务为例),当其中有1个 Container 的:

  1. Liveness probe 失败,则该 Container 会被 Kubelet 干掉,然后该 Container 重启/重建(当然,你的重启策略得是 Always),另外一个 Container 不会重启(也就是不会发生 Pod 级别的重启/重建,因此 Pod IP 也不会变化);
  2. Readiness probe 失败,这时候 Pod 状态里的 Ready 列自然是1/2,关键是 Service 会怎样工作呢?
    1. 当使用1个 Service 负载流量到这个 Pod 的2个端口时,Service 对应的 Endpoint 会变成 NotReady,导致 Pod 中 ready 的那个 Container 也不能通过 Service 地址访问到;
    2. 当使用2个不同的 Service 分别负载流量到这个 Pod 的2个端口时,很遗憾,对应的2个 Endpoint 均会变成 NotReady,而不是1个 Ready,一个 NotReady。(这是和我最开始的猜测不相符的)

4. 测试过程

你居然看到了这里,宝子,你是个求知欲很强的孩子啊!

4.1 准备测试用镜像

我想用 NGINX 镜像来完成这次 probes 特性测试,但是要让2个 containers 在1个 Pod 里监听不同的端口,那就得重新打下镜像,包一层了。

1. 首先,准备一个配置文件

  • default.conf
  1. server {
  2. listen 8080;
  3. location / {
  4. root /usr/share/nginx/html;
  5. index index.html index.htm;
  6. }
  7. }

2. 然后准备一个 Dockerfile

  • Dockerfile
  1. FROM nginx
  2. RUN rm /etc/nginx/conf.d/default.conf
  3. COPY default.conf /etc/nginx/conf.d/
  4. EXPOSE 8080

注意到这里我们将端口号指定成了8080。

3. 接着 build 一下

  1. docker build -t my-nginx-8080:1.0 .

很酷,第一个镜像有了。然后咱需要继续搞一个监听8081端口的新镜像。

4. 更新配置文件

  • default.conf
  1. server {
  2. listen 8081;
  3. location / {
  4. root /usr/share/nginx/html;
  5. index index.html index.htm;
  6. }
  7. }

5. 更新 Dockerfile

  1. FROM nginx
  2. RUN rm /etc/nginx/conf.d/default.conf
  3. COPY default.conf /etc/nginx/conf.d/
  4. EXPOSE 8081

6. build 第二个镜像

  1. docker build -t my-nginx-8081:1.0 .

OK,到这里2个镜像就准备完成了。接着如何将镜像丢到 K8s worker 节点,大家就各显神通吧,通过镜像仓库也行,手动拷贝也罢。

4.2 准备 Deployment YAML

首先跑一个 probe 能过的版本,确保“1 Pod 2 Container”启起来。

  • deploy.yaml
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: nginx-deployment
  5. spec:
  6. replicas: 1
  7. selector:
  8. matchLabels:
  9. app: nginx
  10. template:
  11. metadata:
  12. labels:
  13. app: nginx
  14. spec:
  15. containers:
  16. - name: nginx-container1
  17. image: my-nginx-8080:1.0
  18. ports:
  19. - containerPort: 8080
  20. livenessProbe:
  21. httpGet:
  22. path: /
  23. port: 8080
  24. initialDelaySeconds: 5
  25. periodSeconds: 5
  26. readinessProbe:
  27. httpGet:
  28. path: /
  29. port: 8080
  30. initialDelaySeconds: 5
  31. periodSeconds: 5
  32. - name: nginx-container2
  33. image: my-nginx-8081:1.0
  34. ports:
  35. - containerPort: 8081
  36. livenessProbe:
  37. httpGet:
  38. path: /
  39. port: 8081
  40. initialDelaySeconds: 5
  41. periodSeconds: 5
  42. readinessProbe:
  43. httpGet:
  44. path: /
  45. port: 8081
  46. initialDelaySeconds: 5
  47. periodSeconds: 5

4.3 准备 Service YAML

然后准备一个 Service,用来测试 readinessProbe 相关行为。

  • svc.yaml
  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: my-nginx-service
  5. spec:
  6. selector:
  7. app: nginx
  8. ports:
  9. - name: port1
  10. protocol: TCP
  11. port: 8080
  12. targetPort: 8080
  13. - name: port2
  14. protocol: TCP
  15. port: 8081
  16. targetPort: 8081

4.4 准备第二个 Service YAML

如果是分开的2个 Services 去转发流量到 Pod 内的2个 Containers 呢?也试一下:

  • svc-2.yaml
  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: my-nginx-service-1
  5. spec:
  6. selector:
  7. app: nginx
  8. ports:
  9. - protocol: TCP
  10. port: 8080
  11. targetPort: 8080
  12. ---
  13. apiVersion: v1
  14. kind: Service
  15. metadata:
  16. name: my-nginx-service-2
  17. spec:
  18. selector:
  19. app: nginx
  20. ports:
  21. - protocol: TCP
  22. port: 8081
  23. targetPort: 8081

4.5 测试过程

Apply YAML 后,依次将 Deployment 配置里的 livenessProbe.httpGet.pathreadinessProbe.httpGet.path 从正确的 / 改成会引发404的 /hehe,然后观察 Pod 的状态变化,Service/Endpoint 的状态变化,就可以啦。

(对,不放截图,显得冗长,不是懒,真的不是懒!)

5. 结论

前面贴过结论了,复制粘贴一波:

当1个 Pod 中包含2个 Containers 的时候,如果2个 Containers 分别对外暴露不同的端口(http 服务为例),当其中有1个 Container 的:

  1. Liveness probe 失败,则该 Container 会被 Kubelet 干掉,然后该 Container 重启/重建(当然,你的重启策略得是 Always),另外一个 Container 不会重启(也就是不会发生 Pod 级别的重启/重建,因此 Pod IP 也不会变化);
  2. Readiness probe 失败,这时候 Pod 状态里的 Ready 列自然是1/2,关键是 Service 会怎样工作呢?
    1. 当使用1个 Service 负载流量到这个 Pod 的2个端口时,Service 对应的 Endpoint 会变成 NotReady,导致 Pod 中 ready 的那个 Container 也不能通过 Service 地址访问到;
    2. 当使用2个不同的 Service 分别负载流量到这个 Pod 的2个端口时,很遗憾,对应的2个 Endpoint 均会变成 NotReady,而不是1个 Ready,一个 NotReady。(这是和我最开始的猜测不相符的)

6. 结尾

没看够?别急嘛,关注微信公众号“胡说云原生”,来日方长,see you tomorrow。

原文链接:https://www.cnblogs.com/daniel-hutao/p/17897704.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号