# 使用节点本地域名解析加速（NodeLocal DNSCache）提升DNS性能
#### 应用现状
当集群中的DNS请求量增加时，CoreDNS将会承受更大的压力，可能会导致如下影响：
- 延迟增加：CoreDNS需要处理更多的请求，可能会导致DNS查询变慢，从而影响业务性能。
- 资源占用率增加：为保证DNS性能，CoreDNS往往需要更高规格的配置。
 
#### 解决方案
为了避免DNS延迟的影响，可以在集群中部署NodeLocal DNSCache来提升服务发现的稳定性和性能。NodeLocal DNSCache会在集群节点上运行DNS缓存代理，所有注入DNS配置的Pod都会使用节点上运行的DNS缓存代理进行域名解析，而不是使用CoreDNS服务，以此来减少CoreDNS服务的压力，提高集群DNS性能。
启用NodeLocal DNSCache之后，DNS查询所遵循的路径如下图所示。
图1NodeLocal DNSCache查询路径   
![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000001860673889.png "点击放大")
其中解析线路说明如下：
- ①：已注入DNS本地缓存的Pod，默认会通过NodeLocal DNSCache解析请求域名。
- ②：NodeLocal DNSCache本地缓存如果无法解析请求，则会请求集群CoreDNS进行解析。
- ③：对于非集群内的域名，CoreDNS会通过VPC的DNS服务器进行解析。
- ④：已注入DNS本地缓存的Pod，如果无法连通NodeLocal DNSCache，则会直接通过CoreDNS解析域名。
- ⑤：未注入DNS本地缓存的Pod，默认会通过CoreDNS解析域名。
 
#### 约束与限制
- [节点本地域名解析加速](https://support.huaweicloud.com/usermanual-cce/cce_10_0404.html)插件仅支持1.19及以上版本集群。
- CCI上不支持NodeLocal DNSCache。当负载动态弹性伸缩到CCI时，CCI上Pod会因为无法连通NodeLocal DNSCache导致域名解析超时。因此创建弹性到CCI的负载时，需为Pod添加**node-local-dns-injection: disabled** 的标签，避免DNSConfig自动注入，详情请参见[常见问题]。
- **node-local-dns-injection** 标签为NodeLocal DNSCache使用的系统标签，除[避免DNSConfig自动注入]的场景外，应避免使用该标签。
 
 #### 插件安装
CCE提供了[节点本地域名解析加速](https://support.huaweicloud.com/usermanual-cce/cce_10_0404.html)插件，可以快捷安装NodeLocal DNSCache。
![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/note_3.0-zh-cn.png)
NodeLocal DNSCache不提供Hosts、Rewrite等插件能力，仅作为CoreDNS的透明缓存代理。如有需要，可在CoreDNS配置中修改。
1. （可选）修改CoreDNS配置，让CoreDNS优先采用UDP协议与上游DNS服务器通信。 
   NodeLocal DNSCache采用TCP协议与CoreDNS进行通信，CoreDNS会根据请求来源使用的协议与上游DNS服务器进行通信。当使用了NodeLocal DNSCache时，访问上游DNS服务器时会使用TCP协议，而云上DNS服务器对TCP协议支持有限，如果您使用了NodeLocal DNSCache，您需要修改CoreDNS配置，让其总是优先采用UDP协议与上游DNS服务器进行通信，避免解析异常。
   执行如下步骤，在forward插件中指定请求上游的协议为prefer_udp，修改之后CoreDNS会优先使用UDP协议与上游通信。
   1. 登录[CCE控制台](https://console.huaweicloud.com/cce2.0/?#/cce/cluster/list)，单击集群名称进入集群。
   
   2. 在左侧导航栏中选择"插件中心"，找到**CoreDNS 域名解析**插件，单击"编辑"，进入插件详情页。
   
   3. 在"参数配置"下编辑扩展参数，在plugins字段修改以下内容。
      ```
      {
          "configBlock": "prefer_udp",
          "name": "forward",
          "parameters": ". /etc/resolv.conf"
      }
      ```
      如果使用Corefile视图，则对应的Corefile为：
      ```
      Corefile: |-
        .:5353 {
            bind {$POD_IP}
            cache 30 {
                servfail 5s
            }
            errors
            health {$POD_IP}:8080
            kubernetes cluster.local in-addr.arpa ip6.arpa {
                pods insecure
                fallthrough in-addr.arpa ip6.arpa
            }
            loadbalance round_robin
            prometheus {$POD_IP}:9153
            forward . /etc/resolv.conf {
                prefer_udp
            }
            reload
            ready {$POD_IP}:8081
        }
      ```
      
   
   4. 单击"下一步"，完成升级检查后单击"确定"。
   
   
   
   
2. 在左侧导航栏中选择"插件中心"，在右侧找到**节点本地域名解析加速**插件，单击"安装"。
3. 在安装插件页面，选择插件规格，并配置相关参数。 
   - DNSConfig自动注入：启用后，会创建DNSConfig动态注入控制器，该控制器基于Admission Webhook机制拦截目标命名空间（即命名空间包含标签node-local-dns-injection=enabled）下Pod的创建请求，自动为Pod配置DNSConfig。未开启DNSConfig自动注入或Pod属于非目标命名空间，则需要手动给Pod配置DNSConfig。
     开启自动注入后，您可以为DNSConfig自定义以下配置项（插件版本为1.6.7及以上支持）：
     ![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/note_3.0-zh-cn.png)
     如果开启自动注入时Pod中已经配置了DNSConfig，则优先使用Pod中的DNSConfig。
     - 域名解析服务器地址（可选）：容器解析域名时查询的DNS服务器的IP地址列表。默认会添加NodeLocal DNSCache的地址，以及CoreDNS的地址，允许用户额外追加1个地址，重复的IP地址将被删除。
     
     - 搜索域（可选）：定义域名的搜索域列表，当访问的域名不能被DNS解析时，会把该域名与搜索域列表中的域依次进行组合，并重新向DNS发起请求，直到域名被正确解析或者尝试完搜索域列表为止。允许用户额外追加3个搜索域，重复的域名将被删除。
     
     - ndots（可选）：该参数的含义是当域名的"."个数小于ndots的值，会先把域名与search搜索域列表进行组合后进行DNS查询，如果均没有被正确解析，再以域名本身去进行DNS查询。当域名的"."个数大于或者等于ndots的值，会先对域名本身进行DNS查询，如果没有被正确解析，再把域名与search搜索域列表依次进行组合后进行DNS查询。
       
   
   - 目标命名空间：启用DNSConfig自动注入时支持设置。仅1.3.0及以上版本的插件支持。
     - 全部开启：CCE会为已创建的命名空间添加标签（node-local-dns-injection=enabled），同时会识别命名空间的创建请求并自动添加该标签，这些操作的目标不包含系统内置及部分插件预置的命名空间（包括kube-system、kube-public、kube-node-lease、istio-system、monitoring）。 1.6.77及以上版本的插件中，命名空间标签（node-local-dns-injection=enabled）不支持手动删除，您可以将标签node-local-dns-injection设置为disabled，来关闭指定命名空间的自动注入。
       
     
     - 手动配置：手动为需要注入DNSConfig的命名空间添加标签（node-local-dns-injection=enabled），操作步骤请参见[管理命名空间标签](https://support.huaweicloud.com/usermanual-cce/cce_10_0285.html#cce_10_0285__section124953014352)。
      
   
   
   
   
4. 完成以上配置后，单击"安装"。
 
 #### 使用NodeLocal DNSCache
默认情况下，应用的请求会通过CoreDNS代理，如果需要使用node-local-dns进行DNS缓存代理，您有以下几种方式可以选择：
- 自动注入DNSConfig：创建Pod时自动配置Pod的dnsConfig字段。（kube-system等系统命名空间下的Pod不支持自动注入）
- 手动指定DNSConfig：手动配置Pod的dnsConfig字段，从而使用NodeLocal DNSCache。
 
- [自动注入DNSConfig]
  开启自动注入的操作步骤如下：
  1. 安装节点本地域名解析加速插件，并开启"DNSConfig自动注入"，并配置需要开启自动注入的"目标命名空间"，详情请参见[插件安装]。
     
     目标命名空间：启用DNSConfig自动注入时支持设置。仅1.3.0及以上版本的插件支持。
     - 全部开启：CCE会为已创建的命名空间添加标签（node-local-dns-injection=enabled），同时会识别命名空间的创建请求并自动添加标签，这些操作的目标不包含系统内置的命名空间（如kube-system）。
     
     - 手动配置：手动为需要注入DNSConfig的命名空间添加标签（node-local-dns-injection=enabled），操作步骤请参见[管理命名空间标签](https://support.huaweicloud.com/usermanual-cce/cce_10_0285.html#cce_10_0285__section124953014352)。
      
     
     
  
  2. 在开启自动注入的目标命名空间中，任意创建一个工作负载。操作步骤详情请参见[创建无状态负载（Deployment）](https://support.huaweicloud.com/usermanual-cce/cce_10_0047.html)。
     
     ![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/notice_3.0-zh-cn.png)
     开启自动注入的Pod需满足以下要求：
     - 新建Pod不位于kube-system和kube-public等系统命名空间。
     
     - 新建Pod没有被打上禁用DNS注入的标签node-local-dns-injection=disabled。
     
     - 新建Pod的DNSPolicy设置为ClusterFirstWithHostNet，或Pod未使用hostNetwork且DNSPolicy为ClusterFirst。
      
     
     
  
  3. 使用kubectl命令查看该Pod的DNS配置。 
     ```
     kubectl get pod <pod_name> -oyaml
     ```
     开启自动注入后，创建的Pod会自动添加如下dnsConfig字段，其中nameservers字段中除了NodeLocal DNSCache的地址（示例中为169.254.20.10）外，还添加了CoreDNS的地址（示例中为10.247.3.10），保障了业务DNS请求高可用。
     ![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/note_3.0-zh-cn.png)
     不同集群类型的NodeLocal DNSCache地址如下：
     - CCE Standard集群：169.254.20.10
     
     - CCE Turbo集群：169.254.1.1
      
     ```
     ...
       dnsConfig:
         nameservers:
           - 169.254.20.10
           - 10.247.3.10
         searches:
           - default.svc.cluster.local
           - svc.cluster.local
           - cluster.local
         options:
           - name: timeout
             value: ''
           - name: ndots
             value: '5'
           - name: single-request-reopen
     ...
     ```
     
     
   
- [手动指定DNSConfig]
  手动配置即自行给Pod加上dnsConfig配置。
  1. 使用kubectl连接集群，详情请参见[通过kubectl连接集群](https://support.huaweicloud.com/usermanual-cce/cce_10_0107.html)。
  
  2. 创建一个Pod，并在dnsConfig中的nameservers配置中添加NodeLocal DNSCache的地址（示例中为169.254.20.10）。 
     ![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/note_3.0-zh-cn.png)
     不同集群类型的NodeLocal DNSCache地址如下：
     - CCE Standard集群：169.254.20.10
     
     - CCE Turbo集群：169.254.1.1
      
     创建nginx.yaml文件，示例如下：
     ```
     apiVersion: v1
     kind: Pod
     metadata:
       name: nginx
     spec:
       containers:
       - image: nginx:alpine
         name: container-0
       dnsConfig:
         nameservers:
         - 169.254.20.10
         - 10.247.3.10
         searches:
         - default.svc.cluster.local
         - svc.cluster.local
         - cluster.local
         options:
         - name: ndots
           value: '2'
       imagePullSecrets:
       - name: default-secret
     ```
     
     
  
  3. 执行以下命令创建Pod。 
     ```
     kubectl create -f nginx.yaml
     ```
     
     
   
 #### 常见问题
- 如何让指定Pod避免自动注入DNSConfig？ **解决方案：**
  如果某个工作负载需要避免DNSConfig自动注入，可在Pod模板的labels字段中添加**node-local-dns-injection: disabled** 的标签。示例如下：
  ```
  apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: test
    namespace: default
  spec:
    replicas: 2
    selector:
      matchLabels:
        app: test
    template:
      metadata:
        labels:
          app: test
          node-local-dns-injection: disabled   # 避免DNSConfig自动注入
      spec:
        containers:
          - name: container-1
            image: nginx:latest
            imagePullPolicy: IfNotPresent
        imagePullSecrets:
          - name: default-secret
  ```
  
 
#### 相关文档
- 节点本地域名解析加速（NodeLocal DNSCache）的更新记录请参见[版本记录](https://support.huaweicloud.com/usermanual-cce/cce_10_0404.html#cce_10_0404__section183121449435)。
- 安装节点本地域名解析加速插件时，插件组件默认会占用宿主机的8080端口，而8080端口为常用端口，可能会和节点上部署的其他业务发生冲突，如果需要修改插件使用的默认端口，请参见[修改节点本地域名解析加速（NodeLocal DNSCache）插件默认端口](https://support.huaweicloud.com/usermanual-cce/cce_10_0959.html)。
- 如果需要卸载节点本地域名解析加速，请参见[卸载插件](https://support.huaweicloud.com/usermanual-cce/cce_10_0404.html#cce_10_0404__section106191537124815)。
 
