如何在 Amazon EKS 中使用拓扑感知提示?
我想在 Amazon Elastic Kubernetes Service (Amazon EKS) 集群中使用拓扑感知提示 (TAH)。
解决方法
**注意:**TAH 可能不适合开启了 Amazon Elastic Compute Cloud (Amazon EC2) 竞价型实例、Horizontal Pod Autoscaling 或自动扩缩的集群。当您使用这些集群配置时,将无法实现与 Amazon EKS 分配给节点的 CPU 内核成比例的分配。您超过了允许的开销阈值。此外,如果存在禁止端点再分发的容器组 (pod) 分配限制,则 kube-proxy 将不使用 TAH。
在集群中设置 TAH
先决条件:
- 确保您的 Amazon EKS 集群版本为 1.24 或更高版本。
- 设置 Amazon EKS 集群和包含三个节点的托管节点组。每个节点必须具有相同的 CPU 容量,并且必须将节点分布在三个可用区中。
要在 Amazon EKS 中使用 TAH,请完成以下步骤:
-
创建新的命名空间:
apiVersion: v1 kind: Namespace metadata: name: "example-namespace" labels: pod-security.kubernetes.io/audit: restricted pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io/warn: restricted**注意:**请将 example-namespace 替换为您的命名空间名称。
-
要创建示例部署,请使用 BusyBox 映像:
apiVersion: apps/v1 kind: Deployment metadata: name: example-deployment-name namespace: example-namespace spec: replicas: 3 selector: matchLabels: app: demo template: metadata: labels: app: demo spec: dnsPolicy: Default enableServiceLinks: false automountServiceAccountToken: false securityContext: seccompProfile: type: RuntimeDefault runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 containers: - name: busybox image: public.ecr.aws/docker/library/busybox:latest command: ["/bin/sh"] args: - "-c" - | echo "<html><body><h1>PodName: $MY_POD_NAME NodeName: $MY_NODE_NAME podIP:$MY_POD_IP</h1></body></html>" > /tmp/index.html; while true; do printf 'HTTP/1.1 200 OK\n\n%s\n' $(cat /tmp/index.html) | nc -l -p 8080 done ports: - containerPort: 8080 env: - name: MY_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName - name: MY_POD_IP valueFrom: fieldRef: fieldPath: status.podIP - name: MY_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name resources: limits: memory: "128Mi" cpu: "500m" requests: memory: "64Mi" cpu: "250m" securityContext: readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: - ALL volumeMounts: - name: tmp mountPath: /tmp volumes: - name: tmp emptyDir: {}**注意:**请将 example-deployment-name 替换为您的部署名称,并将 example-namespace 替换为您的命名空间名称。
-
将部署公开为 ClusterIP 服务类型,然后添加 service.kubernetes.io/topology-mode: auto 作为注释:
apiVersion: v1 kind: Service metadata: name: example-service-name namespace: example-namespace annotations: service.kubernetes.io/topology-mode: auto spec: selector: app: demo ports: - protocol: TCP port: 80 targetPort: 8080**注意:**请将 example-service-name 替换为您的服务名称,并将 example-namespace 替换为您的命名空间名称。对于版本 1.26 或更早版本,请改用 service.kubernetes.io/topology-aware-hints: auto 注解。
-
要检查 TAH 是否在端点中填充,请运行以下命令:
kubectl get 'endpointslices.discovery.k8s.io' -l kubernetes.io/service-name=example-service-name -n example-namespace -o yaml**注意:**请将 example-namespace 替换为您的命名空间名称,并将 example-service-name 替换为您的服务名称。
输出示例:endpoints: - addresses: - 10.0.21.125 conditions: ready: true serving: true terminating: false hints: forZones: - name: eu-west-1b nodeName: ip-10-0-17-215.eu-west-1.compute.internal targetRef: kind: Pod name: example-deployment-name-5875bbbb7c-m2j8t namespace: example-namespace uid: 4e789648-965e-4caa-91db-bd27d240ea59 zone: eu-west-1b -
要检查流量是否路由到同一可用区中的容器组 (pod),请运行以下命令来部署测试容器组 (pod):
kubectl run tmp-shell --rm -i --tty --image nicolaka/netshoot --overrides='{"spec": { "nodeSelector": {"kubernetes.io/hostname":"example-node-name"}}}'**注意:**请将 example-node-name 替换为您的节点名称。
-
运行以下命令来查找您的测试容器组 (pod) 连接的容器组 (pod) 和节点:
curl example-service-name.example-namespace:80**注意:**请将 example-namespace 替换为您的命名空间名称,并将 example-service-name 替换为您的服务名称。
输出示例:PodName: 7b7b9bf455-c27z9 HTTP/1.1 200 OK NodeName: ip-10-0-9-45.eu-west-1.compute.internal HTTP/1.1 200 OK podIP: example-10.0.11.140 -
使用上述输出中的 PodName 和 NodeName 检查流量是否与部署测试容器组 (pod) 的可用区保持一致。
-
将部署扩展到四个副本,然后运行以下命令来检查 EndpointSlices:
kubectl -n example-namespace scale deployments example-deployment-name --replicas=4**注意:**请将 example-namespace 替换为您的命名空间名称,并将 example-deployment-name 替换为您的部署名称。
扩展到四个副本的部署会导致至少一个可用区的端点比例为 50%。此外,您会超出 20% 的开销阈值,kube-proxy 将不会使用 TAH。
对集群中的 TAH 问题进行故障排除
在 Amazon EKS 中使用 TAH 时,您可能会看到以下错误:
"Skipping topology aware endpoint filtering since node is missing label"
您可能会遇到此问题,原因是您的节点缺少标签,或者您使用了自定义域名但未识别节点 IP 地址。
要解决此问题,请完成以下步骤:
-
要验证节点上是否存在标签,请运行以下命令:
kubectl get nodes --show-labels |grep "topology.kubernetes.io/zone" -
如果 Amazon EKS 已为节点添加标签,请检查 kube-proxy 日志,确认 Amazon EKS 已正确识别节点 IP 地址:
kubectl logs -n kube-system kube-proxy-pod-name | grep -i retrieved**注意:**请将 kube-proxy-pod-name 替换为您的 kube-proxy 容器组 (pod) 名称。
如果您使用自定义域名,则 Amazon EKS 可能无法正确识别您的节点 IP 地址,您会收到以下错误:
"I1215 12:24:22.082120 1 server_others.go:138] "Detected node IP" address="127.0.0.1" "
--hostname-override 必须与 EC2 DescribeInstances 调用返回的 PrivateDnsName 相同。
要修改虚拟私有云 (VPC) DNS 和动态主机配置协议 (DHCP) 选项,请使用自定义域。以下示例使用了修改后的主机名:
kubectl edit ds -n kube-system kube-proxy spec: template: spec: containers: - name: kube-proxy command: - kube-proxy - --hostname-override=$(NODE_NAME) - --v=6 - --config=/var/lib/kube-proxy-config/config env: - name: NODE_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName
有关详细信息,请参阅 GitHub 网站上的 bootstrap.sh。
相关信息
Kubernetes 网站上的 Topology Aware Routing(拓扑感知路由)
- 语言
- 中文 (简体)
