通过在内网自建 K8S 环境及使用华为云 CCE 对现网平台进行一轮容器化改造测试后, 积累一些 k8s 的常见问题和应对方案, 整理如下.
问题一, POD 时间同步问题
容器内部时间和 node 节点的系统时间不一致, 这个问题其实不是 k8s 问题, 单纯使用 docker 也存在类似问题.
解决方案, 将物理机的时区文件以 hostpath 方式只读挂载, 这样只要保证物理机的系统时间是正确的即可.
问题二, POD 内部 hosts 文件问题
默认情况下, k8s 会将 pod 的 hostname 和 ip 地址添加到 hosts 文件里面, 实际应用场景下会有手工去追加 hosts 文件记录的需求, 而 pod 的生存周期是不固定的, 因此官方提供了 hostalias 的解决方案.
通过配置 pod 内部 hosts 文件的初衷有两个.
1, 有些微服务之间的调用走的是公网解析, 效率低且 DNS 有可能响应超时.
2, 目前开发, 测试和现网环境, 本质上代码是同一套.
我们通过配置 hosts 记录, 可以将程序连接 MySQL,MongoDB,mq 这些公共服务的名称固定. 不同的环境对应的公共服务的 IP 地址通过 hostalias 方式注入 (需要保证三套环境的公共服务用户名, 密码, 端口这些信息是一致的) 可以有效避免由于配置的原因导致的问题.
问题三, 滚动更新问题
在只配置一个 POD 副本且为配置滚动升级的情况下, 当我们需要对 POD 进行升级重启的时候, 会马上把仅有的一个正常 POD 关闭掉, 同时启动一个新的 POD, 这个过程中, 服务将会短暂不可用.
解决方案, 配置滚动更新策略
问题四, 存活检测和工作负载检测
当 POD 内的进程不工作或者 OOM 了, 需要进行自我重启工作. 未配置 liveness 情况下是无法检测和处理类似情况的.
解决方案, 配置 liveness 和 readiness 探针
这里需要说明一下 liveness 探针主要用来判断 POD 内的进程是否存活, readiness 探针用来判断 pod 内的进程是否已准备就绪, 在未就绪之前, 对应 service 的流量不会转发到 pod 内.
问题五, java 应用时区同步问题
JVM 启动时候的时区. 如果不指定, 则默认取系统时区, 这就会导致 java 应用的时间和容器时间差 8 个小时.
解决方案, 通过配置 JAVA_OPTS 设置 java 时区(同样 JVM 的内存参数也可以通过这种方式配置)
-Duser.timezone=GMT+08 或者 -Duser.timezone=Asia/Shanghai
问题六, 集群内外网络互通问题
K8s 集群不同 node 上的 pod 网络通信是通过 cni 网络插件 (例如 flannel,calico 等) 实现的, 路由信息保存在 etcd 中, pod 网络访问互联网通过 node 的 iptables nat 实现.
但在实际应用环境中, 需求总是多样的, 当在 k8s 集群外部的主机需要直接访问 pod 网络的时候, 就需要通过配置路由手段才能实现. 对应的解决方案就是添加路由.
和 node 节点在同一个网段内的主机, 将对应网络的下一跳地址指向相应的 node 节点即可.
和 node 节点不在同一个网段内的主机, 需要在上层路由上进行配置.
问题七, POD 间网络隔离
默认 Pod 是未隔离的, POD 之间的网络畅通无阻. 实际应用中, 会有配置网络隔离的需求.
比如需要在 pod 间做流量的精细控制.
解决方案, 使用 networkpolicy (要求集群的 CNI 插件能支持 networkpolicy)
后记
还有一些例如 elb,Ingress 关联进行服务发布, APM 应用性能监控, AOM 容器监控和日志收集, 容器镜像仓库, CI\CD 流水线的集成, 目前国内公有云三巨头 (阿里云, 华为云, 腾讯云) 都有详尽的解决方案和文档, 就不在一一介绍了, 感兴趣的同学可以看看三巨头的官方文档.
来源: http://www.bubuko.com/infodetail-2855005.html