节点与节点池FAQ

本文为您介绍节点与节点池常见问题。例如,如何更改节点的Pod数量,如何更换节点池的OS镜像,如何解决节点相关timeout问题等。

如何更换节点池OS镜像?

更换节点池OS镜像的方法与升级节点池的方法一致,以下为详细操作步骤。

  1. 登录容器服务管理控制台,在左侧导航栏选择集群

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择节点管理 > 节点池

  3. 在目标节点池所在行,单击操作列的更多 > 升级

  4. 选中更换操作系统,选择要替换的镜像,然后单击开始升级

    说明

    更换操作系统时,默认选中Kubelet升级通过替换节点系统盘的方式升级节点池。请根据实际情况,确认是否选中升级前为节点建立快照

是否支持关闭期望节点数功能?

不支持。

如果您想移除、释放指定节点,请参见移除节点。如果您想添加指定节点,请参见添加已有节点移除节点添加已有节点后,期望节点数自动适配为调整后的节点数,无需人为修改。

开启期望节点数与未开启期望节点数的节点池有什么不同?

期望节点数是指节点池应该维持的节点数量。您可以通过调整期望节点数,达到扩容或缩容节点池的目的。但部分老节点池没有设置过期望节点数,从而未开启期望节点数功能。

开启或未开启期望节点数的节点池对于移除节点、释放ECS等不同的操作方式,会有不同感知,具体如下表。

操作

开启期望节点数节点池

未开启期望节点数节点池

建议

通过ACK的OpenAPI或者控制台缩小期望节点数进行缩容。

缩小期望节点数后,将缩容节点池内节点,直到满足指定的期望节点数量。

如果节点池内当前节点数大于期望节点数,将缩容节点,直到满足终态期望节点数量,并将开启期望节点数功能。

无。

通过ACK的OpenAPI或者控制台移除指定节点。

移除指定节点,期望节点数减少移除节点的数目。例如节点池移除指定节点前,期望节点数为10。移除3个节点后,期望节点数更新为7。

移除指定节点。

无。

通过kubectl delete node方式移除节点。

期望节点数不会改变,没有变化。

无变化。

不推荐。

手动通过ECS控制台或者OpenAPI释放ECS。

生成新ECS实例,补充到设定的期望节点数中。

节点池不感知。不会有新ECS实例生成。节点池节点列表被删除的节点会显示状态为“未知”一段时间。

不推荐,会导致ACK、ESS数据与实际情况不一致,请使用推荐方式移除节点。具体操作,请参见移除节点

包年包月ECS实例到期。

生成新的ECS实例,补充到设置的期望节点数。

节点池不感知。不会有新ECS实例生成。节点池节点列表中被删除的节点会显示状态为“未知”一段时间。

不推荐,会导致ACK、ESS数据与实际情况不一致,请使用推荐方式移除节点。具体操作,请参见移除节点

ESS伸缩组手动开启“实例的健康检查”,并且ECS实例无法通过ESS健康检查(如停机)。

生成新ECS实例,补充到设置的期望节点数。

生成新ECS实例,替换停机实例。

不推荐,请不要直接操作节点池相关的伸缩组。

通过ESS将ECS实例从伸缩组中移除,并且不修改期望实例数。

生成新ECS实例,补充到设置的期望节点数。

不会生成新的ECS实例。

不推荐,请不要直接操作节点池相关的伸缩组。

如何将游离节点(没有节点池纳管的节点)添加到节点池?

ACK节点池功能推出前创建的老集群中,可能存在未被节点池管理的游离Worker节点。如不再需要这些节点,您可以直接释放对应的ECS实例。如仍需要保留这些节点,推荐您将这些节点纳入节点池进行管理,实现节点的分组管理和运维。

您可以创建并扩容一个节点池,将游离节点移除后添加到节点池中。具体操作,请参见迁移游离节点至节点池

如何在节点池中选用抢占性实例?

可以通过新建节点池或者spot-instance-advisor命令行的方式使用抢占性实例。详细信息请参见抢占式实例节点池最佳实践

说明

不支持在创建集群的节点池配置中选择抢占性实例。

Pod数量达到上限时,如何调整可使用的节点Pod数量?

单Worker节点支持的最大Pod数受网络插件类型影响,在大部分场景下不支持变更。在Terway模式下,单节点支持的最大Pod数依赖于ECS实例所提供的弹性网卡数量;在Flannel模式下,单节点最大Pod数在创建集群时指定。指定后不支持修改。Pod数量达到上限时,推荐您通过扩容节点池增加节点,提升可使用的Pod数量。

更多信息,请参见调整可使用的节点Pod数量

如何更改节点配置?

为了业务的平稳运行及方便节点管理:

  • 部分节点配置项,在节点池创建完成后不支持修改,例如容器运行时、节点所属的专有网络等。

  • 部分节点配置项,在节点池创建完成后修改是受限的,例如,操作系统仅允许修改为同类型镜像的最新版本,不支持更改镜像类型。

  • 部分节点配置项,在节点池创建完成后支持修改。例如虚拟交换机、付费类型、实例规格等。

另外,部分支持修改的配置项,仅对节点池新增节点生效,对节点池已有节点无效。例如公网IP、云监控插件等。关于节点配置项是否支持修改以及对节点的生效信息,请参见编辑节点池

综上,如果您想运行一个新配置的节点,建议您按照新配置新建节点池,将旧节点池中的节点设置为不可调度,然后对其进行排水操作。将业务运行到新节点以后,释放旧的节点即可。

如何释放指定的ECS实例?

请通过移除节点,释放指定的ECS实例。释放ECS实例后,期望节点数自动适配到释放后的节点数量,无需人为修改。另外,修改期望节点数并不能释放指定的ECS实例。

对于不属于任何节点池的Worker节点,如何升级它的容器运行时?

按照如下步骤进行操作:

  1. 移除节点。移除Worker节点的过程中,系统会将节点置为不可调度,并对节点进行排水。如果排水失败,系统将停止移除节点,如果成功,则将节点继续移出集群。

  2. 添加已有节点。可以将目标节点加入已有节点池,也可以创建0节点的节点池,然后将目标节点添加到节点池中。节点添加完成后,已有节点的容器运行时自动变成与节点池相同的容器运行时。

    说明

    节点池本身不收费,但节点池使用的ECS实例等云资源由对应的云产品计费。详细信息,请参见云产品资源计费

添加已有节点后报错,提示timeout,怎么办?

请排查节点与APIServer CLB的网络是否可以连通,请先排查安全组是否符合要求。添加已有节点时安全组的使用限制,请参见安全组限制。关于网络不通的其他问题,请参见网络管理FAQ

如何更改ACK集群中Worker节点的主机名称?

集群创建完成后,不支持自定义Worker节点的主机名称,但是您可以通过节点池的节点命名规则来修改Worker节点的主机名称。

说明

创建集群时,您可以在自定义节点名称参数中定义Worker节点的主机名称。具体操作,请参见创建ACK托管集群

  1. 移除节点。

    1. 登录容器服务管理控制台,在左侧导航栏选择集群

    2. 在集群管理页左侧导航栏,选择节点管理 > 节点

    3. 节点页面单击目标节点右侧操作列下的更多 > 移除

    4. 在弹出的对话框中选中我已了解上述说明,确认移除节点,然后单击确定

  2. 将移除的节点再添加到节点池。具体操作,请参见手动添加节点

    添加的节点将根据节点池的节点命名规则进行命名。

如何在已有集群的GPU节点上手动升级Kernel?

下面为您介绍如何在已有集群的GPU节点上手动升级Kernel。

说明

当前kernel版本低于3.10.0-957.21.3

请确认需要升级的目标kernel版本,并谨慎操作。

本文提供方案并不涉及kernel升级,仅针对在kernel升级的前提下对应的Nvidia驱动升级。

  1. 获取集群KubeConfig并通过kubectl工具连接集群

  2. 将GPU节点设置为不可调度(本例以节点 cn-beijing.i-2ze19qyi8votgjz12345为例)。

    kubectl cordon cn-beijing.i-2ze19qyi8votgjz12345
    
    node/cn-beijing.i-2ze19qyi8votgjz12345 already cordoned
  3. 将要升级驱动的GPU节点进行排水。

    kubectl drain cn-beijing.i-2ze19qyi8votgjz12345 --grace-period=120 --ignore-daemonsets=true
    
    node/cn-beijing.i-2ze19qyi8votgjz12345 cordoned
    WARNING: Ignoring DaemonSet-managed pods: flexvolume-9scb4, kube-flannel-ds-r2qmh, kube-proxy-worker-l62sf, logtail-ds-f9vbg
    pod/nginx-ingress-controller-78d847fb96-5fkkw evicted
  4. 卸载当前的nvidia-driver。

    说明

    本步骤中卸载的是版本为384.111的驱动包,如果您的驱动版本不是384.111,则需要在Nvidia官网下载对应的驱动安装包,并将本步骤中的384.111替换成您实际的版本。

    1. 登录到该GPU节点,通过nvidia-smi查看驱动版本。

      sudo nvidia-smi -a | grep 'Driver Version'
      Driver Version                      : 384.111
    2. 下载Nvidia驱动安装包。

      sudo cd /tmp/
      sudo curl -O https://cn.download.nvidia.cn/tesla/384.111/NVIDIA-Linux-x86_64-384.111.run
      说明

      需要在安装包中卸载Nvidia。

    3. 卸载当前Nvidia驱动。

      sudo chmod u+x NVIDIA-Linux-x86_64-384.111.run
      sudo sh ./NVIDIA-Linux-x86_64-384.111.run --uninstall -a -s -q
  5. 升级Kernel。

    您可以根据需要升级Kernel。

  6. 重启GPU机器。

    sudo reboot
  7. 重新登录GPU节点,安装对应的kernel devel。

    sudo yum install -y kernel-devel-$(uname -r)
  8. 请到Nvidia官网下载和安装您需要的Nvidia驱动, 本文以410.79为例。

    sudo cd /tmp/
    sudo curl -O https://cn.download.nvidia.cn/tesla/410.79/NVIDIA-Linux-x86_64-410.79.run
    sudo chmod u+x NVIDIA-Linux-x86_64-410.79.run
    sudo sh ./NVIDIA-Linux-x86_64-410.79.run -a -s -q
    
    warm up GPU
    sudo nvidia-smi -pm 1 || true
    sudo nvidia-smi -acp 0 || true
    sudo nvidia-smi --auto-boost-default=0 || true
    sudo nvidia-smi --auto-boost-permission=0 || true
    sudo nvidia-modprobe -u -c=0 -m || true
  9. 查看 /etc/rc.d/rc.local,确认其中是否包含以下配置,如果没有请手动添加。

    sudo nvidia-smi -pm 1 || true
    sudo nvidia-smi -acp 0 || true
    sudo nvidia-smi --auto-boost-default=0 || true
    sudo nvidia-smi --auto-boost-permission=0 || true
    sudo nvidia-modprobe -u -c=0 -m || true
  10. 重启kubelet和Docker。

    sudo service kubelet stop
    sudo service docker restart
    sudo service kubelet start
  11. 将此GPU节点重新设置为可调度。

    kubectl uncordon cn-beijing.i-2ze19qyi8votgjz12345
    
    node/cn-beijing.i-2ze19qyi8votgjz12345 already uncordoned
  12. 在GPU节点上的device plugin pod验证版本。

    kubectl exec -n kube-system -t nvidia-device-plugin-cn-beijing.i-2ze19qyi8votgjz12345 nvidia-smi
    Thu Jan 17 00:33:27 2019
    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 410.79       Driver Version: 410.79       CUDA Version: N/A      |
    |-------------------------------+----------------------+----------------------+
    | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
    | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
    |===============================+======================+======================|
    |   0  Tesla P100-PCIE...  On   | 00000000:00:09.0 Off |                    0 |
    | N/A   27C    P0    28W / 250W |      0MiB / 16280MiB |      0%      Default |
    +-------------------------------+----------------------+----------------------+
    
    +-----------------------------------------------------------------------------+
    | Processes:                                                       GPU Memory |
    |  GPU       PID   Type   Process name                             Usage      |
    |=============================================================================|
    |  No running processes found                                                 |
    +-----------------------------------------------------------------------------+
    说明

    如果通过docker ps命令,发现GPU节点没有容器被启动,请参见修复GPU节点容器启动问题

修复GPU节点容器启动问题

在某些特定Kubernetes版本中的GPU节点上,重启Kubelet和Docker时,发现没有容器被启动。

sudo service kubelet stop
Redirecting to /bin/systemctl stop kubelet.service
sudo service docker stop
Redirecting to /bin/systemctl stop docker.service
sudo service docker start
Redirecting to /bin/systemctl start docker.service
sudo service kubelet start
Redirecting to /bin/systemctl start kubelet.service

sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

执行以下命令,查看Docker的Cgroup Driver。

sudo docker info | grep -i cgroup
Cgroup Driver: cgroupfs

此时发现的Cgroup Driver类型是cgroupfs。

您可以按照以下操作,修复该问题。

  1. 备份/etc/docker/daemon.json,完成后,执行以下命令更新/etc/docker/daemon.json

    sudo cat >/etc/docker/daemon.json <<-EOF
    {
        "default-runtime": "nvidia",
        "runtimes": {
            "nvidia": {
                "path": "/usr/bin/nvidia-container-runtime",
                "runtimeArgs": []
            }
        },
        "exec-opts": ["native.cgroupdriver=systemd"],
        "log-driver": "json-file",
        "log-opts": {
            "max-size": "100m",
            "max-file": "10"
        },
        "oom-score-adjust": -1000,
        "storage-driver": "overlay2",
        "storage-opts":["overlay2.override_kernel_check=true"],
        "live-restore": true
    }
    EOF
  2. 执行以下命令,重启Docker和Kubelet。

    sudo service kubelet stop
    Redirecting to /bin/systemctl stop kubelet.service
    sudo service docker restart
    Redirecting to /bin/systemctl restart docker.service
    sudo service kubelet start
    Redirecting to /bin/systemctl start kubelet.service
  3. 执行以下命令,确认Docker的Cgroup Driver的类型为systemd。

    sudo docker info | grep -i cgroup
    Cgroup Driver: systemd

节点故障时,如何将节点Pod批量转移到其他节点上重新部署?

您可以将故障节点设置为不可调度并进行排水,将故障节点的应用Pod逐步迁移至新节点。

  1. 登录容器服务管理控制台,在节点页面的操作列,选择更多>节点排水。此操作会将旧节点设置为不可调度状态,将旧节点池的应用逐步迁移至新节点池。

  2. 排查故障节点问题。关于故障排查的思路,请参见节点异常问题排查

    您也可以提交工单联系容器服务技术团队。

有跨可用区节点的集群发生故障时,集群会如何决定节点驱逐策略?

通常情况下,当节点发生故障时,节点Controller会驱逐不健康的节点,驱逐速率--node-eviction-rate默认为0.1个/秒,即每10秒钟内至多从一个节点驱逐Pod。

而一个存在多个可用区节点的ACK集群发生故障时,节点Controller会根据可用区的状态以及集群大小来决定如何驱逐。

可用区故障分为三种情况。

  • FullDisruption:该可用区不存在正常节点,且至少有1个异常节点。

  • PartialDisruption:该可用区至少有2个异常节点,并且异常节点的比例,即(异常节点/(异常节点+正常节点)),大于0.55。

  • Normal:除FullDisruption和PartialDisruption两种情况外,其余均为Normal状态。

在此场景下,集群大小分为两种情况:

  • 大集群:大于50个节点的集群。

  • 小集群:小于等于50个节点的集群。

在三种故障状态下,节点Controller的驱逐速率计算方式如下:

  • 如果所有可用区都处于FullDisruption状态时,则关闭系统所有可用区的驱逐功能。

  • 如果不是所有可用区都处于FullDisruption状态,驱逐速率通过以下方式确定。

    • 如果某个可用区处于FullDisruption状态,那么驱逐速率设定为正常值(0.1),不受集群大小影响。

    • 如果某个可用区处于PartialDisruption状态,那么驱逐速率受集群大小因素影响。在大集群中,该可用区的驱逐速率为0.01;在小集群中,该可用区的驱逐速率为0,即不进行驱逐。

    • 如果某个可用区处于Normal状态,那么驱逐速率设定为正常值(0.1),不受集群大小因素影响。

更多信息,请参见逐出速率限制

ACK集群中kubelet目录路径是什么?支持自定义吗?

ACK不支持自定kubelet路径。kubelet路径默认为/var/lib/kubelet,请勿更改。

ACK节点池中数据盘可以自定义目录挂载吗?

自定义目录挂载功能目前处于灰度发布中,请提交工单申请。开启此功能后,可自动将节点池中添加的数据盘格式化并挂载到操作系统中的指定目录上。但挂载目录存在以下限制。

  • 请勿挂载到以下操作系统重要目录上:

    • /

    • /etc

    • /var/run

    • /run

    • /boot

  • 请勿挂载到以下系统及容器运行时所使用的目录及其子目录:

    • /usr

    • /bin

    • /sbin

    • /lib

    • /lib64

    • /ostree

    • /sysroot

    • /proc

    • /sys

    • /dev

    • /var/lib/kubelet

    • /var/lib/docker

    • /var/lib/containerd

    • /var/lib/container

  • 不同数据盘的挂载目录不可重复。

  • 挂载目录必须是以/开头的绝对路径。

  • 挂载目录中不能包含回车和换行字符(C语言转义字符\r\n),不能以反斜杠字符\结尾。

如何修改最大文件句柄数?

最大文件句柄数即打开文件数的最大限制,Alibaba Cloud Linux和CentOS系统中包含两个维度的文件句柄限制:

  • 系统级别:所有用户的进程能够同时打开文件数的上限。

  • 用户级别:单个用户进程能够打开文件数的上限。

在容器环境中,还有另一个文件句柄限制,即容器内部单进程的最大文件句柄数。

说明

在节点池升级场景下,通过黑屏命令自定义修改的最大文件句柄数配置可能会被覆盖。推荐使用实例自定义数据进行配置。

修改节点系统级最大文件句柄数

请参见自定义节点池OS参数了解操作的注意事项以及操作入口

修改节点单进程最大文件句柄数

  1. 登录节点,查看/etc/security/limits.conf文件。

    cat /etc/security/limits.conf

    通过以下参数配置节点单进程最大文件句柄数:

    ...
    root soft nofile 65535
    root hard nofile 65535
    * soft nofile 65535
    * hard nofile 65535
  2. 执行sed命令,修改最大文件句柄数(其中65535为最大文件句柄数的建议取值)。

    sed -i "s/nofile.[0-9]*$/nofile 65535/g" /etc/security/limits.conf
  3. 重新登录节点,执行以下命令检查修改是否生效。

    当返回与修改值一致时,表明修改正确。

    # ulimit -n
    65535

修改容器最大文件句柄数

重要

修改容器最大文件句柄数将会重启Docker或containerd进程。请在业务低峰期谨慎操作。

  1. 登录节点,执行以下命令查看配置文件。

    • containerd节点:cat /etc/systemd/system/containerd.service

    • Docker节点:cat /etc/systemd/system/docker.service

    容器单进程最大文件句柄数通过以下参数设置:

    ...
    LimitNOFILE=1048576   ******单进程最大文件句柄数
    LimitNPROC=1048576    ******最大进程数
    ...
  2. 执行如下命令,修改对应参数取值(其中1048576为最大文件句柄数的建议取值)。

    • containerd节点:

       sed -i "s/LimitNOFILE=[0-9a-Z]*$/LimitNOFILE=65536/g" /etc/systemd/system/containerd.service;sed -i "s/LimitNPROC=[0-9a-Z]*$/LimitNPROC=65537/g" /etc/systemd/system/containerd.service && systemctl daemon-reload && systemctl restart containerd
    • Docker节点:

      sed -i "s/LimitNOFILE=[0-9a-Z]*$/LimitNOFILE=1048576/g" /etc/systemd/system/docker.service;sed -i "s/LimitNPROC=[0-9a-Z]*$/LimitNPROC=1048576/g" /etc/systemd/system/docker.service && systemctl daemon-reload && systemctl restart docker
  3. 执行以下命令,查看容器单进程最大文件句柄数。

    当返回与修改值一致时,表明修改正确。

    • containerd节点:

      # cat /proc/`pidof containerd`/limits | grep files
      Max open files            1048576              1048576              files
    • Docker节点:

      # cat /proc/`pidof dockerd`/limits | grep files
      Max open files            1048576              1048576              files