使用NodeLocal DNSCache组件

为了解决CoreDNS负载过高或业务Pod所在节点负载过高引发的DNS解析失败的问题,可部署NodeLocal DNSCache组件,在各节点运行DNS缓存代理,降低解析延迟,提高可用性。

工作原理

  • 启用DNS缓存的Pod:PodDNS请求发送到DNS缓存,如果命中缓存则直接返回结果;如果缓存未命中,则向CoreDNS发送请求,CoreDNS会解析所有集群内域名并向Pod返回结果。对于集群外域名,则会将请求发送至内网DNS解析处理。

    • ECS节点池混合云节点池场景:ACK NodeLocal DNSCache组件通过在每个节点部署DaemonSet实现DNS缓存。

    • 虚拟节点场景:组件通过在每个Pod中部署Blazing DNS Hidecar容器实现DNS缓存。

  • 未启用DNS缓存的Pod:PodDNS请求直接发送到CoreDNS。对于集群外域名,则会将请求发送至内网DNS解析处理。

image

适用范围

  • 不支持Windows节点。

  • 只有当Pod适用主机网络(hostNetwork:true)且DNS策略为DNSPolicy: ClusterFirstWithHostNet,或未使用主机网络模式(hostNetwork:false)且DNS策略为DNSPolicy: ClusterFirst时,才会自动注入。

  • 若集群网络插件为Terway,要求Terway版本为v1.0.10.301或更高。

    若集群创建时使用的网络插件为Terway早期版本且使用了IPvlan模式,请参照为什么配置组件后没有效果判断是否需要修改Terway配置。
  • 虚拟节点在ACK NodeLocal DNSCache版本为v1.6.0或更高,且ACK Virtual Node版本为2.14.0或更高时支持启用DNS缓存。

启用DNS缓存

步骤一:安装组件

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

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,单击组件管理

  3. 网络页签中找到ACK NodeLocal DNSCache卡片,单击安装,在弹出的对话框中单击确认

步骤二:配置并启用

启用DNS缓存有多种方式,作用范围不同:

在集群全局启用(推荐)

NodeLocal DNSCache组件提供了是否默认启用 DNSCache配置。启用此配置后,除系统保留命名空间外的所有命名空间中的Pod在新建时都会被自动注入DNS Cache。

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

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,单击组件管理

  3. 网络页签中找到ACK NodeLocal DNSCache卡片,单击配置,在弹出的对话框中勾选是否默认启用 DNSCache,然后单击确认

为单个命名空间启用

NodeLocal DNSCache组件会自动监听包含了node-local-dns-injection=enabled标签的命名空间,并为其中新建的Pod自动注入DNS Cache相关配置。

为命名空间添加标签:

kubectl label <namespace> node-local-dns-injection=enabled

在启用DNS缓存的命名空间中,新建的Pod会自动注入下方的dnsConfig配置,使用DNS缓存:

nameservers中会额外添加CoreDNSClusterIP作为备份的DNS服务器,保证DNS请求高可用(不适用于虚拟节点上的Pod)。
dnsConfig:
  nameservers:
  - 169.254.20.10
  - <kube-dns> # 自动填入kube-dns Service的ClusterIP
  options:
  - name: ndots
    value: "3"
  - name: attempts
    value: "2"
  - name: timeout
    value: "1"
  searches:
  - default.svc.cluster.local
  - svc.cluster.local
  - cluster.local
dnsPolicy: None

为单个Pod手动启用

Pod中添加spec.dnsConfig配置,在其中配置nameservers169.254.20.10kube-dns ServiceIP,可手动为Pod启用DNS缓存。

该方式不适用于虚拟节点,虚拟节点上的PoddnsConfig会被强制覆盖,无法使用169.254.20.10作为DNS Server。
apiVersion: v1
kind: Pod
metadata:
  name: alpine
  namespace: default
spec:
  containers:
  - image: alpine
    command:
      - sleep
      - "10000"
    imagePullPolicy: Always
    name: alpine
  dnsPolicy: None
  dnsConfig:
    nameservers: ["169.254.20.10","<kube-dns>"] # 替换为kube-dns Service IP
    searches:
    - default.svc.cluster.local
    - svc.cluster.local
    - cluster.local
    options:
    - name: ndots
      value: "3"
    - name: attempts
      value: "2"
    - name: timeout 
      value: "1"
  • dnsPolicy:必须设置为None

  • nameservers:配置为169.254.20.10(NodeLocal DNSCache在节点上的IP),<kube-dns>需替换为kube-system命名空间中的kube-dns ServiceIP地址。请登录容器服务管理控制台,在左侧网络 > 服务中查看。

  • searches:设置搜索域,保证集群内部域名能够被正常解析。

  • ndots:默认为3,适当降低ndots可以提升解析效率。更多信息,请参见resolv.conf

效果验证

启用DNS缓存后,创建一个新的工作负载,验证是否自动注入DNS缓存配置。

  1. 查看Pod信息。

    kubectl get pods

    预期输出:

    NAME                     READY   STATUS    RESTARTS   AGE
    nginx-766448f68c-m****   1/1     Running   0          4m39s
    nginx-766448f68c-w****   1/1     Running   0          4m39s
  2. 选择其中一个Pod,查看dnsConfig。

    kubectl get pod nginx-766448f68c-m**** -o=jsonpath='{.spec.dnsConfig}'

    预期输出如下,nameservers中同时存在两个IP,说明成功为应用接入NodeLocal DNSCache。

    下方输出中的172.21.0.10kube-dnsClusterIP,请以实际输出为准。
    map[nameservers:[169.254.20.10 172.21.0.10] options:[map[name:ndots value:5]] searches:[default.svc.cluster.local svc.cluster.local cluster.local]]

使用限制

  • 在命名空间启用DNS Cache的情况下,拥有node-local-dns-injection=disabled标签的Pod不会进行自动注入。

  • NodeLocal DNSCache不提供Hosts、Rewrite等插件能力,仅作为CoreDNS的透明缓存代理。如有需要,请在CoreDNS配置中修改。

  • DNS缓存在ACK系统保留的命名空间中不会生效,请查看不生效的命名空间

常见问题

为什么配置组件后没有效果?

配置组件后没有效果,同时NodeLocal DNSCache的日志中也看不到来自Pod的访问,这是由于在Terway早期版本创建的集群中,默认Terway配置无法使用NodeLocal DNSCache。请参照下方的步骤,对Terway配置进行修改。

  1. 查看Terway配置文件。

    kubectl -n kube-system get cm eni-config -o yaml | grep eniip_virtual_type
    kubectl -n kube-system get cm eni-config -o yaml | grep host_stack_cidrs
    • 检查配置文件中eniip_virtual_type字段是否开启IPVLAN模式。如果配置文件中此项不存在或不是IPVLAN,则无需进行后续配置。

    • 检查配置文件中是否已配置host_stack_cidrs字段。如果配置文件中已配置host_stack_cidrs字段,则无需进行后续配置。

  2. Terway配置文件中添加host_stack_cidrs字段,并输入网段169.254.20.10/32,保存并退出。

     10-terway.conf: |
      {
        "cniVersion": "0.3.0",
        "name": "terway",
        "eniip_virtual_type": "IPVlan",
        "host_stack_cidrs": ["169.254.20.10/32"], 
        "type": "terway"
      }
  3. 查看当前TerwayDaemonSet。

    kubectl -n kube-system get daemonset terway-eniip

    预期输出:

    NAME           DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
    terway-eniip   2         2         2       2            2           <none>          15m
  4. 触发Terway DaemonSet重建。

    kubectl rollout restart -n kube-system daemonset terway-eniip
  5. 登录任意集群节点,查看Terway配置文件。

    如果Terway配置文件包含添加的网段,则说明配置成功。

    cat /etc/cni/net.d/*

    预期输出:

     {
       "cniVersion": "0.3.0",
       "name": "terway-chainer",
       "plugins": [
         {
           "eniip_virtual_type": "IPVlan",
           "host_stack_cidrs": [ 
             "169.254.20.10/32",
           ],
           "type": "terway"
         },
         {
           "type": "cilium-cni"
         }
       ]
     }

    所有Terway Pod重建并正常后,可以继续安装NodeLocal DNSCache了。

为什么Pod没有注入DNS缓存配置?

下列原因都可能导致Pod没有自动注入DNS配置:

  • Pod处于ACK系统保留命名空间:

    查看ACK系统保留命名空间

    kubectl get mutatingwebhookconfigurations ack-node-local-dns-admission-controller -o yaml | grep -A 30 namespaceSelector

    预期输出如下,namespaceSelector.matchExpressions.values中的命名空间的Pod不会自动注入DNS Cache。

    namespaceSelector:
        matchExpressions:
          ...
          values:
          - kube-system
          - kube-public
          - arms-prom
          - security-inspector
          - ack-csi-fuse
        matchLabels:
          node-local-dns-injection: enabled
      ...
  • ACK NodeLocal DNSCache版本早于v1.6.0,且Pod处于虚拟节点上、Pod或其所在命名空间拥有ECI相关标签,例如virtual-node-affinity-injectionecialibabacloud.com/eci等。

  • Pod拥有node-local-dns-injection=disabled标签。

  • Pod的网络为hostNetwork时,未配置DNSPolicy: ClusterFirstWithHostNet;其他类型的Pod,未配置DNSPolicy: ClusterFirst

如何查看组件监控?

ack-arms-prometheus组件版本为1.1.33及以上时,才会显示NodeLocal DNSCache大盘。

NodeLocal DNSCache监控大盘记录了包括缓存命中率等关键数据。请通过大盘确认组件状况、评估组件负载,确保NodeLocal DNSCache在生产环境中的稳定性。

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

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择运维管理 > Prometheus 监控

  3. Prometheus监控页面,单击网络监控页签。然后在NodeLocal DNSCache页签查看监控大盘。

    如果监控大盘内无数据,请参见为什么监控大盘内无数据?

    image

为什么监控大盘内无数据?

可能是由于NodeLocal DNSCache未配置Prometheus采集相关配置。

kube-system命名空间中找到名为node-local-dnsDaemonSet,确认Annotations中是否已存在Prometheus相关配置。如果未存在,请添加相关配置。

apiVersion: apps/v1
kind: DaemonSet
metadata:
  annotations:
    deprecated.daemonset.template.generation: '1'
    meta.helm.sh/release-name: ack-node-local-dns
    meta.helm.sh/release-namespace: kube-system
    #Prometheus相关配置:
    prometheus.io/path: "/metrics"
    prometheus.io/port: "9253"
    prometheus.io/scrape: "true"
...

升级组件时,有哪些注意事项?

及时升级组件版本,可以获取新功能、性能改进或安全修复。

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

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,单击组件管理

  3. 组件管理页面单击ACK NodeLocal DNSCache卡片下的升级,在弹出的对话框中单击确认

    重要
    • 若对ConfigMap node-local-dns进行过修改操作,升级时修改配置将会被覆盖。建议在升级前对node-local-dns进行备份,当组件升级完成后,重新配置组件。

    • 若对node-local-dns DaemonSet进行过污点容忍等修改操作,升级时污点容忍等操作将会被覆盖,升级后需要再次设置。

    • 如果升级NodeLocal DNSCache失败,需要根据操作异常码查找对应的问题,查看问题原因和解决方案。详细描述,请参见组件异常问题排查

如何卸载组件?

  1. 关闭DNS缓存注入功能:根据DNS缓存的配置方式关闭DNS缓存,例如开启方式为通过组件配置在集群全局开启时,则通过组件配置关闭DNS缓存注入。

  2. 调整现有Pod中的DNS配置:

    1. 修改现有Pod中的DNS配置,移除169.254.20.10(NodeLocal DNSCache在节点上的IP)配置,将DNS服务器地址设置为kube-dns ServiceClusterIP),然后重启Pod。

    2. 检查Pod配置中是否留存DNS缓存,如果没有任何输出,表明所有Pod都已迁移。

      kubectl get pods -A -o jsonpath='{range .items[?(@.spec.dnsConfig.nameservers[*] contains "169.254.20.10")]}{.metadata.namespace}{"/"}{.metadata.name}{"\n"}{end}'
  3. 登录容器服务管理控制台,在左侧导航栏选择集群列表

  4. 集群列表页面,单击目标集群名称,然后在左侧导航栏,单击组件管理

  5. 组件管理页面单击ACK NodeLocal DNSCache卡片下的卸载,在弹出的对话框中单击确认

    重要

    卸载后所有解析流量会请求至CoreDNS,建议参照DNS最佳实践进行配置以保证DNS的高可用性。