通过在内网自建K8S环境及使用华为云CCE对现网平台进行一轮容器化改造测试后,积累一些k8s的常见问题和应对方案,整理如下。

问题一、POD时间同步问题

容器内部时间和node节点的系统时间不一致,这个问题其实不是k8s问题,单纯使用docker也存在类似问题。
K8S问题集锦_第1张图片
解决方案,将物理机的时区文件以hostpath方式只读挂载,这样只要保证物理机的系统时间是正确的即可。
K8S问题集锦_第2张图片
K8S问题集锦_第3张图片

问题二、POD内部hosts文件问题

默认情况下,k8s会将pod的hostname和ip地址添加到hosts文件里面,实际应用场景下会有手工去追加hosts文件记录的需求,而pod的生存周期是不固定的,因此官方提供了hostalias的解决方案。
https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/
K8S问题集锦_第4张图片
通过配置pod内部hosts文件的初衷有两个。
1、有些微服务之间的调用走的是公网解析,效率低且DNS有可能响应超时。
2、目前开发、测试和现网环境,本质上代码是同一套。
我们通过配置hosts记录,可以将程序连接mysql、mongodb、mq这些公共服务的名称固定。不同的环境对应的公共服务的IP地址通过hostalias方式注入(需要保证三套环境的公共服务用户名、密码、端口这些信息是一致的)可以有效避免由于配置的原因导致的问题。
K8S问题集锦_第5张图片
K8S问题集锦_第6张图片

问题三、滚动更新问题

在只配置一个POD副本且为配置滚动升级的情况下,当我们需要对POD进行升级重启的时候,会马上把仅有的一个正常POD关闭掉,同时启动一个新的POD,这个过程中,服务将会短暂不可用。
K8S问题集锦_第7张图片
解决方案,配置滚动更新策略
K8S问题集锦_第8张图片
K8S问题集锦_第9张图片

问题四、存活检测和工作负载检测

当POD内的进程不工作或者OOM了,需要进行自我重启工作。未配置liveness情况下是无法检测和处理类似情况的。
K8S问题集锦_第10张图片
解决方案,配置liveness和readiness探针
K8S问题集锦_第11张图片
K8S问题集锦_第12张图片
这里需要说明一下liveness探针主要用来判断POD内的进程是否存活,readiness探针用来判断pod内的进程是否已准备就绪,在未就绪之前,对应service的流量不会转发到pod内。

问题五、java应用时区同步问题

JVM启动时候的时区。如果不指定,则默认取系统时区,这就会导致java应用的时间和容器时间差8个小时。
K8S问题集锦_第13张图片
解决方案,通过配置JAVA_OPTS设置java时区(同样JVM的内存参数也可以通过这种方式配置)
-Duser.timezone=GMT+08 或者 -Duser.timezone=Asia/Shanghai
K8S问题集锦_第14张图片
K8S问题集锦_第15张图片

问题六、集群内外网络互通问题

K8s集群不同node上的pod网络通信是通过cni网络插件(例如flannel、calico等)实现的,路由信息保存在etcd中,pod网络访问互联网通过node的iptables nat实现。
K8S问题集锦_第16张图片
但在实际应用环境中,需求总是多样的,当在k8s集群外部的主机需要直接访问pod网络的时候,就需要通过配置路由手段才能实现。对应的解决方案就是添加路由。

和node节点在同一个网段内的主机,将对应网络的下一跳地址指向相应的node节点即可。
K8S问题集锦_第17张图片
和node节点不在同一个网段内的主机,需要在上层路由上进行配置。
K8S问题集锦_第18张图片
K8S问题集锦_第19张图片

问题七、POD间网络隔离

默认 Pod 是未隔离的,POD之间的网络畅通无阻。实际应用中,会有配置网络隔离的需求。
比如需要在pod间做流量的精细控制。
K8S问题集锦_第20张图片
解决方案,使用networkpolicy (要求集群的CNI插件能支持networkpolicy)

K8S问题集锦_第21张图片
K8S问题集锦_第22张图片
K8S问题集锦_第23张图片

后记

还有一些例如elb、Ingress关联进行服务发布、APM应用性能监控、AOM容器监控和日志收集、容器镜像仓库、CI\CD流水线的集成,目前国内公有云三巨头(阿里云、华为云、腾讯云)都有详尽的解决方案和文档,就不在一一介绍了,感兴趣的同学可以看看三巨头的官方文档。