超级节点上支持运行 Daemonset

最近更新时间:2024-05-13 11:54:01

我的收藏

功能概述

由于超级节点没有实节点概念,因此在普通节点上运行的资源对象 DaemonSet 无法按照预期的方式运行,DaemonSet 所支持的某些系统层面的应用能力,如日志收集、资源监控等服务均无法在超级节点上统一支持。业内常规的解决方案为通过 sidecar 注入的方式实现 Daemonset 相关的能力,但这带来了跟常规节点不一致的使用体验,且在功能上也是有损的,例如 sidecar 的更新将影响业务 Pod 的生命周期等,基于此,腾讯云全新推出了 Daemonset Pod 注入方案用于在超级节点上运行 Daemonset。作为业内唯一的在 Nodeless 架构中支持了 Daemonset Pod 的运行,该方案拥有如下优势:
全兼容:完全兼容原生 Daemonset Pod 的使用方式。
零侵入:Daemonset Pod 与业务 Pod 拥有独立的生命周期,Daemonset 的任何变更不会影响业务 Pod。
可观测:控制台支持对 Daemonset Pod 的监控,支持查询 Daemonset Pod 日志、事件等。

使用场景

TKE 托管集群:在 TKE 托管集群中,如果您添加了超级节点,且超级节点上运行的 Pod 期望支持与普通节点一致的 Daemonset 能力。
TKE Serverless 集群:在 TKE Serverless 集群中,若期望运行 Daemonset 资源。
IDC 集群:在 IDC 集群中,如果您添加了超级节点,且超级节点上运行的 Pod 期望支持与 IDC 节点一致的 Daemonset 能力。

前置准备

检查控制面 master 组件是否已升级到如下指定版本或更高版本:
Kubernetes 版本
控制面 master 组件版本要求
v1.26
v1.26.1-tke.1 或更高版本
v1.24
v1.24.4-tke.4 或更高版本
v1.22
v1.22.5-tke.8 或更高版本
v1.20
v1.20.6-tke.30 或更高版本
v1.18
v1.18.4-tke.34 或更高版本
v1.16
v1.16.3-tke.33 或更高版本
检查超级节点的版本是否已升级到 v2.11.20 或以上。

使用方法

1. 创建 Daemonset 并标记需要运行在超级节点的 Daemonset

该步骤目的为声明哪些 Daemonset 需要运行在超级节点上。
如果您希望在 TKE 的普通节点和超级节点上运行相同的 DaemonSet,建议新建一个相同的 Daemonset,并为其打上标记,这样不影响原本运行在普通节点上的 Daemonset 且便于管理。
如下面文件所示,标记将要注入的 DaemonSet 为:eks.tke.cloud.tencent.com/ds-injection: "true"。对于按量计费超级节点,由于默认打了污点(key=eks.tke.cloud.tencent.com/eklet,effect=NoSchedule),因此需要容忍污点,才能支持将 Daemonset Pod 创建上去。
注意:
调度时,Daemonset 中定义的 resources 不会有效,并且也不会产生额外计费。
spec:
template:
metadata:
annotations:
eks.tke.cloud.tencent.com/ds-injection: "true"
spec:
tolerations:
- key: eks.tke.cloud.tencent.com/eklet
operator: Exists
effect: NoSchedule
通过以上步骤,如果集群内存在超级节点,则可以通过运行 kubectl get ds 命令查看新的副本扩出情况,集群内有多少个超级节点则会展示多少个副本,如下图所示:

img



2. 启动 Daemonset Pod

完成 Daemonset 在超级节点的运行声明后,意味着当前超级节点的业务 Pod 均会自动注入一个 DaemonSet Pod,后续启动的业务 Pod 也会被自动注入(kube-system 命名空间下的 Pod 除外)。
被注入的 Pod 本身的 YAML 配置不会发生任何变化,但 Container Status 里会新增注入的 DaemonSet Pod 容器的状态,以便更方便地观察 DaemonSet Pod 的状态,如下图所示:

img


DaemonSet Pod 容器的事件,例如拉镜像、启动、异常退出等信息,都会上报到被注入的 Pod 上:

img



3. 登录 Daemonset Pod

使用 kubectl exec 命令可以正常登录原本 Pod 的容器。若要登录 DaemonSet Pod 的容器,则需要将 exec 指向被注入的 Pod,然后通过 -c 参数,指定要登录的 DaemonSet Pod 容器。命令如下:
kubectl exec -it <pod-name> -c <daemonset-container-name> -- /bin/bash
示例如下:

img


注意:
如果 DaemonSet Pod 的容器名称与原本 Pod 的容器名称相同,exec 命令会优先指向原本 Pod,此时无法登录 DaemonSet Pod 的容器。但是,DaemonSet Pod 的容器依旧在正常运行,为了 DaemonSet Pod 的容器可观测,建议将 DaemonSet Pod 的容器名称与 Pod 名称区分开。

4. 查看 Daemonset Pod 日志

与使用 kubectl exec 命令类似,您可以使用 kubectl logs 命令结合 -c 参数来查看 DaemonSet Pod 容器的日志。命令如下:
kubectl logs <pod-name> -c <daemonset-container-name>
示例如下:

img


请注意,由于 kubectl 1.18及以上版本的客户端,会在发起 logs 请求之前校验 Pod Spec 是否包含指定容器。如果不存在指定容器,则直接返回如下错误:
container xxx is not valid for pod xxx
出现此类情况时,您可以将 kubectl 版本切换到1.16版本,或者使用我们后续提供的发行版。以下是 kubectl 1.16 版本的下载链接:
curl -LO "https://dl.k8s.io/release/v1.16.0/bin/linux/amd64/kubectl"

5. 注入规则

若超级节点上声明启用了 DaemonSet Pod,则除 kube-system 命名空间下的 Pod 外,该超级节点上的其他 Pod ,均会被注入 DaemonSet Pod。若您有特殊 Pod 不希望被注入 DaemonSet Pod,可以配置如下 annotation:
eks.tke.cloud.tencent.com/ds-injection: "false"
如果您希望整个命名空间下的所有 Pod 都不被注入 DaemonSet Pod,可以在命名空间上配置如下 annotation:
eks.tke.cloud.tencent.com/ds-injection: "false"
如果您希望 kube-system 命名空间下的 Pod 被注入 DaemonSet Pod,则需要在创建这些 Pod 时显式声明如下 annotation:
eks.tke.cloud.tencent.com/ds-injection: "true"
如果您希望按 Label 过滤需要注入的 Daemonset,可以在 Daemonset 上配合使用如下 annotation:
当与 pod 的某个 label 匹配时注入:
eks.tke.cloud.tencent.com/ds-inject-by-label: "k1:v1,k2:v2"
当与 pod 的某个 label 匹配时不注入:
eks.tke.cloud.tencent.com/ds-evict-by-label: "k1:v1,k2:v2"
注意:
当两个 annotation 同时存在时,ds-evict-by-label 的优先级更高。

6. 特殊能力

调整 Daemonset Pod 的启动顺序

如果注入的 DaemonSet Pod 需要先于业务 Pod 启动,可以给业务 Pod 配上如下 annotation ,让业务 Pod 晚于 Daemonset Pod 启动:
eks.tke.cloud.tencent.com/start-after-ds: "true"

开放端口

注入的 DaemonSet Pod 若需要对外暴露端口,则需额外通过 annotation 声明,声明方式如下:
eks.tke.cloud.tencent.com/metrics-port: "9100,8080,3000-5000"
默认只暴露9100端口,用来提供监控数据 metrics,您可以在9100之后添加其他端口,支持范围 range 写法,多个端口之间用逗号分隔,最多支持 4 个逗号。请注意,可以变更9100端口,但不要删除,第一个端口默认用于提供监控数据 metrics。
从容器外访问 DaemonSet Pod 的端口时,访问的 IP 为业务 Pod 的 IP,端口为 DaemonSet Pod 的端口:
curl "http://<pod-ip>:<ds-port>/"

业务 Pod 与本地 DaemonSet Pod 通信

如果业务 Pod 需要主动访问注入的 DaemonSet Pod,则需要获取到注入的 DaemonSet Pod 使用的虚拟 IP。通过添加如下 annotation,业务 Pod 可以通过 env from hostIP,获取到 DaemonSet Pod 所使用的虚拟 IP:
eks.tke.cloud.tencent.com/env-host-ip: "true"
容器里使用类似 env from hostIP:
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP

DaemonSet Pod 访问 kubelet 的 10250 端口

如果 DaemonSet Pod 要通过 kubelet 的接口获取本地 pod 的列表,可以给业务 pod 配上如下 annotation:
eks.tke.cloud.tencent.com/read-only-port: "10250"
此时 DaemonSet Pod 就可以通过 127.0.0.1:10250 访问到 pod 列表。