跳至内容

如何在 EKS 集群中安装 NodeLocalDNS 并对问题进行故障排除?

5 分钟阅读
0

我想在 Amazon Elastic Kubernetes Service (Amazon EKS) 集群中安装 NodeLocalDNS 并对问题进行故障排除。

解决方法

先决条件:

安装 NodeLocalDNS

NodeLocalDNS 使用链路本地 IP 地址在每个节点上提供 DNS 缓存。链路本地地址是 169.254.0.0/16 范围内的 IP 地址,仅在网段内有效。

**注意:**NodeLocalDNS 的标准链路本地 IP 地址是 169.254.20.10。除非您的环境中存在特定冲突,否则请勿更改此值。

要在您的 Amazon EKS 集群中安装 NodeLocalDNS,请完成以下步骤:

  1. 运行以下 curl 命令,从 Kubernetes 存储库下载 NodeLocalDNS 清单:

    curl -Lo nodelocaldns.yaml.template https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
  2. 要检索集群的 kube-dns 服务 IP 地址,请运行以下命令:

    kubectl get svc kube-dns -n kube-system -o jsonpath='{.spec.clusterIP}'

    **注意:**记下输出中的 IP 地址。

  3. 要检索集群的域,请运行以下命令:

    kubectl get configmap coredns -n kube-system -o yaml | grep 'kubernetes'

    输出显示您的集群域。

  4. 要确定您的 kube-proxy 模式,请运行以下命令:

    kubectl get configmap kube-proxy-config -n kube-system -o yaml | grep mode

    输出显示 iptables 或 ipvs 作为模式值。

  5. 根据您的 kube-proxy 模式编辑 NodeLocalDNS 清单。

    对于 iptables 模式,请使用以下命令编辑清单:

    # Set environment variables for node-local-dns
    kubedns=$(kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP})
    domain=cluster.local
    localdns=`169.254.20.10`
    
    # Update the manifest with your cluster's specific values:
    sed "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/__PILLAR__DNS__SERVER__/$kubedns/g" nodelocaldns.yaml.template > nodelocaldns.yaml

    **注意:**如果您的集群使用不同的域,请将 cluster.local 替换为步骤 3 中的集群域。如果不同,请将 169.254.20.10 替换为您的集群的链路本地 IP 地址。

    对于 IPVS 模式,请使用以下命令编辑清单:

    # Set environment variables for node-local-dns
    kubedns=$(kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP})
    domain=cluster.local
    localdns=169.254.20.10
    
    # Update the manifest with your cluster's specific values:
    sed "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/,__PILLAR__DNS__SERVER__//g; s/__PILLAR__CLUSTER__DNS__/$kubedns/g" nodelocaldns.yaml.template > nodelocaldns.yaml

    **注意:**如果您的集群使用不同的域,请将 cluster.local 替换为步骤 3 中的集群域。如果不同,请将 169.254.20.10 替换为您的集群的链路本地 IP 地址。在 IPVS 模式下,您需要配置容器组 (pod) 以使用 NodeLocalDNS。请参阅“配置容器组 (pod) 以使用 NodeLocalDNS(仅限 IPVS 模式)”部分。

  6. 要应用 NodeLocalDNS 清单,请运行以下命令:

    kubectl apply -f nodelocaldns.yaml
  7. 要验证 NodeLocalDNS 容器是否处于 Running(正在运行)状态,请运行以下命令:

    kubectl get pods -n kube-system -l k8s-app=node-local-dns

配置容器组 (pod) 以使用 NodeLocalDNS(仅限 IPVS 模式)

**重要事项:**本部分仅在您的集群为 kube-proxy 使用 IPVS 模式时适用。如果您的集群使用 iptables 模式,则 DNS 流量会自动重定向到 NodeLocalDNS。

对于 IPVS 模式集群,您必须手动配置容器组 (pod) 以使用 NodeLocalDNS。要将您的容器组 (pod) 定向到 NodeLocalDNS,您可以配置单个容器组 (pod) 或使用 kubelet 配置集群。

配置单个容器组 (pod)

要配置单个容器组 (pod),请将以下配置添加到您的容器组 (pod) 规范中:

spec:
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - [169.254.20.10]
    searches:
      - default.svc.cluster.local
      - svc.cluster.local
      - cluster.local
    options:
      - name: ndots
        value: "5"

**注意:**请将 169.254.20.10 替换为您的集群的链路本地 IP 地址。如果您的集群使用不同的域,请将 cluster.local 替换为您的集群域。

使用 kubelet 配置集群

在 IPVS 模式下,NodeLocalDNS 仅在链路本地地址 169.254.20.10 上侦听。您必须修改 kubelet 配置以指向此链路本地地址。

要配置集群中的所有容器组 (pod) 以使用 NodeLocalDNS,同时修改每个节点上的 kubelet 配置,请完成以下步骤:

  1. 编辑 kubelet 配置文件。添加以下配置:

    {  "clusterDNS": ["169.254.20.10"],
      "clusterDomain": "cluster.local"
    }

    **注意:**请将 169.254.20.10 替换为您的集群的链路本地 IP 地址。如果您的集群使用不同的域,请将 cluster.local 替换为您的集群域。

  2. 要在每个节点上重新启动 kubelet 服务,请运行以下 sudo 命令:

    sudo systemctl restart kubelet
  3. 要验证 kubelet 配置,请运行以下命令:

    cat /etc/kubernetes/kubelet/config.json | grep clusterDNS

    **注意:**输出显示 169.254.20.10 作为 NodeLocalDNS 链路本地 IP 地址。

**注意:**对于自动部署,您可以在启动模板的用户数据部分修改 kubelet 配置。有关更多信息,请参阅如何将自定义用户数据与 AL2023 Amazon EKS 节点一起使用?

验证您是否已正确安装 NodeLocalDNS

要验证 NodeLocalDNS 是否正常运行,请完成以下步骤:

  1. 要创建测试容器组 (pod),请运行以下命令:

    kubectl run test-dns --image=busybox:1.28 --restart=Never --rm -it -- nslookup kubernetes.default
  2. 如果 NodeLocalDNS 容器组 (pod) 处于 CrashLoopBackOff 状态,并出现指示端口 53 已被占用的错误。请查看输出以确认 DNS 查询已正确解析。

  3. 要验证 DNS 查询是否正在使用 NodeLocalDNS,请运行以下命令:

    kubectl logs -n kube-system -l k8s-app=node-local-dns --tail=50

    日志显示 DNS 查询正在由 NodeLocalDNS 进行处理。

    **注意:**默认情况下,NodeLocalDNS 中未启用日志记录。要查看日志,请在 node-local-dns ConfigMap 中启用日志记录。

    # kubectl edit configmaps -n kube-system node-local-dns
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: node-local-dns
      namespace: kube-system
    data:
      Corefile: |
        cluster.local:53 {
           log  # Enable logging
           errors
           cache 30
           ...
        }

对 NodeLocalDNS 问题进行故障排除

**注意:**如果您在运行 AWS 命令行界面 (AWS CLI) 命令时收到错误,请参阅 AWS CLI 错误故障排除。此外,请确保您使用的是最新版本的 AWS CLI

解决由端口冲突引起的 CrashLoopBackOff 错误

如果 NodeLocalDNS 容器组 (pod) 进入 CrashLoopBackOff 状态并出现端口 53 错误,则会发生这种情况,这是因为 Amazon EKS 自动模式节点保留了端口 53。要解决此问题,请选择以下方法之一:

方法 1: 添加节点关联性规则以排除自动模式节点

完成以下步骤:

  1. 编辑 NodeLocalDNS 进程守护程序:

    kubectl edit daemonset node-local-dns -n kube-system
  2. 在 spec.template.spec 下添加以下关联性配置:

    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: eks.amazonaws.com/compute-type
              operator: NotIn
              values:
              - auto
  3. 保存更改,然后验证容器组 (pod) 是否成功重新启动。

方法 2: 修改 NodeLocalDNS ConfigMap 以更改运行状况检查端口

完成以下步骤:

  1. 要查看当前的 NodeLocalDNS ConfigMap,请运行以下命令:

    kubectl get configmap node-local-dns -n kube-system -o yaml
  2. 要编辑 ConfigMap 以更改运行状况检查端口,请运行以下命令:

    kubectl edit configmap node-local-dns -n kube-system
  3. 在 ConfigMap 中,找到运行状况插件配置并修改端口。ConfigMap 结构如下所示:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: node-local-dns
      namespace: kube-system
    data:
      Corefile: |
        cluster.local:53 {
           errors
           cache {
              success 9984 30
              denial 9984 5
           }
           reload
           loop
           bind IP_ADDRESS
           forward. __PILLAR__CLUSTER__DNS__ {
              force_tcp
           }
           prometheus :9253
           health 169.254.20.10:8081
        }

    **注意:**请将 health 行中的端口从 8081 替换为您所需的端口。如果不同,请将 169.254.20.10 替换为您的集群的链路本地 IP 地址。

  4. 保存更改。

  5. 要重新启动 NodeLocalDNS 容器组 (pod),请运行以下命令:

    kubectl rollout restart daemonset node-local-dns -n kube-system
  6. 要更新进程守护程序运行状况检查配置以匹配新端口,请运行以下命令:

    kubectl edit daemonset node-local-dns -n kube-system
  7. 找到 livenessProbereadinessProbe 部分,更新端口以匹配新的运行状况检查端口。

解决 DNS 查询超时错误

如果您的容器组 (pod) 遇到 DNS 查询超时,请验证您的安全组和网络 ACL 是否允许端口 53 上的 TCP 和 UDP 流量。这些流量是容器组 (pod) 间通信所必需的。

完成以下步骤:

  1. 要识别附加到您的节点的安全组,请运行以下 AWS CLI 命令 describe-instances

    aws ec2 describe-instances --filters "Name=tag:eks:cluster-name,Values=YOUR-CLUSTER-NAME" --query "Reservations[*].Instances[*].SecurityGroups[*].[GroupId,GroupName]" --output table

    **注意:**请将 YOUR-CLUSTER-NAME 替换为您的 Amazon EKS 集群名称。

  2. 打开 Amazon EC2 控制台

  3. 在导航窗格中,选择 Security Groups(安全组)。

  4. 选择本部分步骤 1 中确定的安全组。

  5. 选择 Inbound rules(入站规则)选项卡。

  6. 验证是否存在允许来自容器组 (pod) CIDR 范围的端口 53 上的 TCP 和 UDP 流量的规则。
    **注意:**如果规则不存在,请选择 Edit inbound rules(编辑入站规则)。然后,在端口 53 上添加 TCP 和 UDP 规则,并将源设置为您的容器组 (pod) CIDR 范围。

解决 "Connection refused" 错误消息

如果容器组 (pod) 尝试使用 NodeLocalDNS 时收到 "Connection refused" 错误消息,请验证是否至少有一个 CoreDNS 容器组 (pod) 正在运行。

要检查 CoreDNS 容器组 (pod) 状态,请运行以下命令:

kubectl get pods -n kube-system -l k8s-app=kube-dns

如果没有 CoreDNS 容器组 (pod) 正在运行或容器组 (pod) 处于故障状态,请重新启动 CoreDNS 部署。要重新启动部署,请运行以下命令:

kubectl rollout restart deployment coredns -n kube-system

要验证 CoreDNS 容器组 (pod) 是否正在运行,请运行以下命令:

kubectl get pods -n kube-system -l k8s-app=kube-dns -w

要在 CoreDNS 容器组 (pod) 运行后重新启动 NodeLocalDNS 进程守护程序,请运行以下命令:

kubectl rollout restart daemonset node-local-dns -n kube-system

相关信息

Kubernetes 网站上的 Using CoreDNS for Service Discovery(使用 CoreDNS 进行服务发现)

Kubernetes 网站上的 Run kube-proxy in IPVS Mode(在 IPVS 模式下运行 kube-proxy)

使用 EKS 自动模式实现集群基础设施自动化

管理 Amazon EKS 集群的联网附加组件

AWS 官方已更新 4 个月前