Kubernetes疑难杂症汇总


这里主要是为了记录在使用 Docker 的时候遇到的问题及其处理解决方法。

诡异的问题时常发生,如果正确的处理它们呢?将是一个值得思考和学习的问题!通过对错误和异常问题的排除和处理,能够增长我们的知识储备已经掌握处理问题最为有效和使用的方式。这里将会记录常见的集群使用的问题,以备不时之需。

Kubernetes 疑难杂症汇总


1. K8S 证书过期处理

默认 K8S 集群的证书(certificate)有效期为一年时间 => 最佳的做法是经常升级集群以确保安全

  • [问题起因] 监控突然发生了很多报警,反馈对应服务在解析文件的时候发生了异常。因为是时使用集群部署的,所以查看集群对应的 UI 界面,发现是证书过期,日志如下所示。
# 集群报错信息显示证书过期了
6月 17 17:23:16 c12 kubelet[23413]: E0617 17:23:16.878470   23413
bootstrap.go:265] part of the existing bootstrap client certificate is expired: 2020-06-14 11:22:14 +0000 UTC
  • [解决方法] 知道了问题的原因,现在我们需要做的就是如何来更新 K8S 集群的证书。更新证书分为自动更新证书手动更新证书两种方式,当然我们也可以使用源代码编译使得 kubeadm 生成的证书时间边长。下面,我们来了解下其对应的使用方式吧!

  • 自动更新证书: 主要是通过 kubeadm 命令来在控制面板升级的时候更新所有证书。如果你对此类证书的更新没有特殊要求,并且定期执行 Kubernetes 进行版本升级(每次升级之间的间隔时间少于 1 年)的话,则 kubeadm 将确保你的集群保持最新状态并保持合理的安全性。如果你对证书更新有更复杂的需求,则可通过将 --certificate-renewal=false 传递给 kubeadm upgrade apply 或者 kubeadm upgrade node,从而选择不采用默认行为。

  • 手动更新证书: 则是通过 kubeadm alpha certs renew 命令手动更新集群里面的证书。这个命令用 CA 证书和存储在 /etc/kubernetes/pki 中的密钥执行更新操作。如果你运行了一个 HA 集群的话,则通过这个命令需要在所有控制面板节点上执行,才可以。需要我们知道的是,Kubernetes 证书通常在一年后到期自动过期。

  • 需要注意的是,但是执行 renew 之后,发现并没有生效。原因是因为没有重新生成 *.conf 配置文件,删除配置文件之后才生效了。

# 重新生成证书
$ kubeadm alpha certs renew all
remove .conf in /etc/kubernetes/

# 重新生成配置文件
$ kubeadm init phase kubeconfig all

# 重启kubelet服务
$ systemctl restart kubelet
# 该命令显示/etc/kubernetes/pki文件夹中的客户端证书以及kubeadm使用的KUBECONFIG文件
# 中嵌入的客户端证书的到期时间/剩余时间,需要注意的是kubeadm不能管理由外部CA签名的证书
# 发现下面的列表中没有包含kubelet.conf,这是因为kubeadm将kubelet配置为自动更新证书了
$ kubeadm alpha certs check-expiration
CERTIFICATE                EXPIRES           RESIDUAL TIME   EXTERNALLY MANAGED
admin.conf                 Jun 17, 2021 ..   345d            false
apiserver                  Jun 17, 2021 ..   345d            false
apiserver-etcd-client      Jun 17, 2021 ..   345d            false
apiserver-kubelet-client   Jun 17, 2021 ..   345d            false
controller-manager.conf    Jun 17, 2021 ..   345d            false
etcd-healthcheck-client    Jun 17, 2021 ..   345d            false
etcd-peer                  Jun 17, 2021 ..   345d            false
etcd-server                Jun 17, 2021 ..   345d            false
front-proxy-client         Jun 17, 2021 ..   345d            false
scheduler.conf             Jun 17, 2021 ..   345d            false

2. K8S 磁盘容量不足

K8S 检测磁盘容量是按照百分比检测的,而不是实际剩余容量!

  • [问题起因] 发现 K8S 集群中的一台机器上面部署的服务发生了异常,查看之后发现是因为磁盘容量不足导致该节点异常。其检测机制是,当机器的磁盘容量不足 1% 的时候,则将该节点标记为异常节点。

Kubernetes 疑难杂症汇总

  • [解决方法] 该问题的处理方法就是,删除服务器上面的数据或者添加磁盘扩充磁盘空间。下面步骤主要是,启动节点的守护进程,比如网络等。
    • 先通过增加磁盘控盘空间,来解决节点状态的异常
    • 然后重启 kubelet systemctl restart kubelet 服务
    • 查看 k8s 容器的状态,如果 pod 不全就删了其他的 pod,再重启一下 kubelet 服务
    • 如果不行就进到 kube-system namespace 界面,在守护进程集把对应的容器组删了,让 k8s 从新拉起一组

3. K8S 跳板机实例配置

这里只是记录一下,顺便后续自己需要的时候看看。

  • [问题起因] 之前 AWS 上跳板机的 NAT 实例 gateway 上面忘记配置下面这个防火墙规则,导致内网无法 ping 通外网的 IP
$ sudo sysctl -w net.ipv4.ip_forward=1
$ sudo iptables -A FORWARD -i eth0 -j ACCEPT
$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
  • [解决方法] 这里记一下,上面三条命令到底做了什么呢?
    • 第一条:配置 Linux 内核参数,主要是用来把 Linux 当成路由器来用。一般来说,一个路由器至少要有两个网络接口,一个是 WAN,另一个是 LAN,为了让 LANWAN 的流量相通,需要进行内核上路由转发。
    • 第二条:通行所有需要转发的包,只有机器成为一个路由器时,需要在两个网卡间进行网络包转发时,才需要配置这条规则。
    • 第三条:关键字 MASQUERADE 意思是“伪装“,NAT 的工作原理是就像是个宿舍收发室对学生宿舍一样,学生宿舍的地址外部不可见邮递员只看得见整栋宿舍收发室的地址,邮递员把快递交给收发室,收发室再把快递转给学习宿舍(反之,如果学生要对外寄邮件,也是先到收发室,收发室传给邮局)。现在的问题是,所有的学生宿舍如何才能参与到任何快递的通信中,如果把学生宿舍地址发到外部,则没人能把信送回来。如果这个收发室是个自动化的机器人,他要干的事就是,把学生宿舍的地址换成收发室地址。这就是 MASQUERADE 的意思 —— 来自具有接收方 1 地址的本地网络到达 Internet 某处的数据包必须进行修改,也就是让发送方的地址等于路由器的地址。

4. K8S 日志空间不足

不做设置的话,Pod 将使用 emptyDir 这个模式使用临时目录!

  • [问题起因] 主要原因就是,对应节点上面启动的容器,占用了太多的临时目录,导致系统使用率太高了。
# 报错提示信息
The node was low on resource: ephemeral-storage.
Container xxx was using 44Ki, which exceeds its request of 0.
  • [解决方法] 解决方案有以下几种:
    • 第一种就是通过配置如下设置,将容器使用临时空间大小进行限制,设置好值以后,用超过 Limit 的话,kubernetes 就会干掉我们的 Pod 服务,防止系统空间不足。
    • 第二种就是将 /var/log/ 目录的磁盘空间改大,有些情况会看到其会挂载到 / 目录下,而 / 目录分配的空间有特别小,就会导致这个问题的出现。建议使用该方式,一劳永逸。
# ephemeral-storage
# 来调度和管理节点上的应用对主分区的消耗
- name: wordpress
  image: wordpress
  resources:
    requests:
      ephemeral-storage: "2Gi"
    limits:
      ephemeral-storage: "4Gi"

5. K8S 服务配置不存在

部署平台要不惜磁盘和内存,不然会存在很多异常的问题

  • [问题起因] 部署的时候,发现如下报错信息:
# 报错提示信息
Failed to create pod sandbox: rpc error: code = Unknown desc = rewrite resolv.conf failed for pod "redis-xxx"
ResolvConfPath: "/var/lib/docker/containers/xxx/resolv.conf" does not exist
  • [解决方法] 后来发现是内存不足导致的,需要新增内存资源,即可。

6. K8S 临时文件挂载

解决怎么在 K8S 平台上面挂载 /dev/shm 目录

  • [问题起因] /dev/shmlinux 非常有用的一个目录,就是所谓的 tmpfs,也可以称之为临时文件系统(不是块设备),用于加速和优化系统。该目录并没有放在磁盘上,而在内存当中,因此直接使用 /dev/shm 就可以达到很好的效果。
# 在docker中默认的设置的shm大小为64M
root@123456789:/app# df -h
Filesystem              Size  Used Avail Use% Mounted on
overlay                  17T  662G   15T   5% /
shm                      64M     0   64M   0% /dev/shm
# Tmpfs优势
1.动态文件系统的大小
2.读写速度快(在RAM中),读写几乎是瞬间完成
3.再Tmpfs中的数据在重新启动之后不会持久化保留

# 临时调整tmpfs大小
$ mount –o size=5128M –o nr_inodes=1000000 –o noatime,nodiratime –o remount /dev/shm

# 永久修改tmpfs大小
$ vim /etc/fstab
tmpfs /dev/shm defaults,size=1.5G 0 0
$ mount –o remount /dev/shm
  • [解决方法] 我们常会知道在 docker-compose 中设置 shm 的值,下面介绍如果在 k8s 中设置。在机器学习训练或需要高效率运行的其他应用场景中,应该根据实际情况调整 shm 的大小。设置太小,不能够满足高效率的要求,但是,一味地设置过大,容易导致宿主机内存(默认为 shm 是宿主机内存的 1/2)被占用过大,严重时会出现集群雪崩的问题。
# docker
$ docker run -it --name=app --shm-size 1024M -v ./data:/app app

# docker-compose
version: "2.4"
services:
  app:
    restart: on-failure
    container_name: app_demo
    image: app:latest
    cpu_percent: 60
    mem_limit: 10G
    ports:
      - "80:80"
    runtime: nvidia
    shm_size: '2gb'
    volumes:
      - "./data:/data"
    environment:
      - NVIDIA_VISIBLE_DEVICES=0
    networks:
      - app_network

networks:
  app_network:
# 不设置shm大小
# 设置/dev/shm挂载emptyDir目录(大小与pod所在宿主机上面shm的大小一致)

apiVersion: v1
kind: Pod
metadata:
  name: test-pd-shm
spec:
  containers:
    - image: centos
      name: centos
      command: ["sleep", "1000000"]
      imagePullPolicy: "IfNotPresent"
      volumeMounts:
        - mountPath: /dev/shm
          name: cache-volume
  volumes:
    - name: cache-volume
      emptyDir:
        medium: Memory
# 设置shm大小
# df看的话也为pod所在宿主机上shm的大小
# 显示为宿主机大小,但是实际pod内部有自己的限制

apiVersion: v1
kind: Pod
metadata:
  name: test-pd-shm
spec:
  containers:
    - image: centos
      name: centos
      command: ["sleep", "1000000"]
      imagePullPolicy: "IfNotPresent"
      volumeMounts:
        - mountPath: /dev/shm
          name: cache-volume
  volumes:
    - name: cache-volume
      emptyDir:
        medium: Memory
        sizeLimit: 128Mi

文章作者: Escape
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Escape !
  目录