k8s教程(service篇)-Node本地DNS缓存

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
可观测监控 Prometheus 版,每月50GB免费额度
简介: k8s教程(service篇)-Node本地DNS缓存

01 引言

声明:本文为《Kubernetes权威指南:从Docker到Kubernetes实践全接触(第5版)》的读书笔记

由于在Kubernetes集群中配置的DNS服务 是一个名为 “kube-dns” 的Service, 所以容器应用都通过其ClusterIP地址(例如169.169.0.100)去执行服务名的DNS域名解析。这对于大规模集群可能引起以下两个问题:

  • 集群DNS服务压力增大(这可以通过自动扩容缓解)
  • 由于DNS服务的IP地址是ServiceClusterIP地址,所以会通过kube- proxy设置的iptables规则进行转发,可能导致域名解析性能很差,原因是Netfilter 在做DNAT转换时可能会引起conntrack冲突,从而导致DNS查询产生5s的延时

为了解决这两个问题,Kubernetes引入了Node本地DNS缓存NodeLocal DNSCache)来提高整个集群的DNS域名解析的性能,本文来讲解下。

02 Node本地DNS缓存

使用Node本地DNS缓存的好处如下

  • 在没有本地DNS缓存时,集群DNS服务的Pod很可能在其他节点上,跨主机访问会增加网络延时,使用Node本地DNS缓存可 显著减少跨主机查询的网络延时
  • 跳过iptables DNAT和连接跟踪将有助于 减少conntrack竞争,并避免UDP DNS记录填满conntrack表
  • 本地缓存到集群DNS服务的连接协议可以升级为TCP。TCP conntrack条目将在连接关闭时被删除;默认使用UDP时,conntrack条目只能等到超时时间过后才被删除,操作系统的默认超时时间(nf_conntrack_udp_timeout),为30s;
  • 将DNS查询从UDP升级为TCP,将减少由于丢弃的UDP数据包和DNS超时而引起的尾部延迟(tail latency),UDP超时时间可能会长达30s(3次重试, 每次10s);
  • 提供Node级别DNS解析请求的度量 (Metrics)和可见性 (visibility) 可以重新启用负缓存(Negative caching)功能,减少对集群DNS服务的查询数量

2.1 工作流程

Node本地DNS缓存(NodeLocal DNSCache)的工作流程如图所示,客户端Pod首先会通过本地DNS缓存进行域名解析,当缓存中不存在域名时,会将请求转发到集群DS服务进行解析

2.2 部署Node本地DNS缓存工具

配置文件nodelocaldns.yaml的内容如下,主要包括 ServiceAccount、Daemonset、ConfigMap和Service 几个资源对象。

2.2.1 资源对象配置


Service Account的定义如下:

apiVersion: v1
kind: ServiceAccount
metadata: 
  name: node-local-dns
  namespace: kube-system 
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile

Service的定义如下:

apiVersion: v1
kind: Service
metadata:
  name: kube-dns-upstream
  namespace: kube-system 
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile 
    kubernetes.io/name: "KubeDNSUpstream"
spec:
  ports:
  - name: dns
    port: 53
    protocol: UDP
    targetPort: 53
  - name: dns-tcp
    port: 53
    protocol: TCP
    targetPort: 53
  selector:
    k8s-app: kube-dns

ConfigMap的定义如下:

apiversion: v1
kind: ConfigMap
metadata:
  name: node-local-dns
  namespace: kube-system 
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
data:
Corefile: |
  cluster.local:53 {
    errors
    cache{
      success 9984 30 
      denial 9984 5
    }
    reload
    loop
    bind169.254.20.10
    forward.169.169.0.100{
      force tcp
    }
    prometheus 9253
    hea1th169.254.20.10:8081 
    }
  in-addr.arpa:53 {
    errors 
    cache 30 
    reload
    loop
    bind 169.254.20.10
    forward . 169.169.0.100{
      force tcp
    }
    prometheus 9253 
    }
  ip6.arpa:53 {
    errors 
    cache 30 
    reload
    loop
      bind 169.254.20.10
      forward . 169.169.0.100{
      force tcp
      }
    prometheus 9253
    }
  .:53 {
    errors 
    cache 30 
    reload
    loop
    bind 169.254.20.10
    forward . 169.169.0.100{
      force tcp
    }
    prometheus 9253 
    }

ConfigMap Corefile的主要配置参数如下:

  • bind 169.254.20.10 :node-local-dns需要绑定的本地IP地址,建议将其设置为169.254.0.0/16范围,确保不与集群内的其他IP冲突;
  • forward.169.169.0.100:在node-local-dns缓存中不存在域名记录时, 将转发到的上游DNS服务器IP设置为Kubernetes集群DNS服务(kube-dns)的IP,例如169.169.0.100;
  • health169.254.20.10:8081:健康检查端口号设置与Daemonset的livenessProbe一致,需要注意,node-local-dns网络模式设置了 hostNetwork=true,这个端口号也会被直接绑定到宿主机上,需要确保不与宿主机的其他应用冲突。

DaemonSet的定义如下:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-local-dns 
  namespace: kube-system 
  labels:
    k8s-app: node-local-dns
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile 
spec:
  updatestrategy:
    rollingUpdate:
      maxUnavai1able: 10% 
  selector:
    matchLabels:
      k8s-app: node-local-dns 
  template:
    metadata:
      labels:
        k8s-app: node-local-dns 
      annotations:
        prometheus.io/port: "9253" 
        prometheus.io/scrape: "true" 
    spec:
      priorityclassName: system-node-critical 
      serviceAccountName: node-local-dns 
      hostNetwork: true
      dnsPolicy: Default Don't use cluster DNS. 
      tolerations:
      - key: "CriticalAddonsOnly" 
        operator: "Exists"
      - effect: "NoExecute"
        operator: "Exists"
      - effect: "NoSchedule"
        operator: "Exists"
    containers:
    - name: node-cache
      image: k8s.gcr.io/k8s-dns-node-cache: 1.15.13 
      resources:
        requests:
        cpu: 25m
        memory: 5Mi
        args: ["-localip","169.254.20.10","-conf","/etc/Corefile","-upstreamsvc","kube-dns-upstream"]
      securityContext:
        privileged: true
      ports:
      - containerPort: 53
        name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        - containerPort: 9253
          name: metrics
          protocol: TCP
        livenessProbe:
        httpGet:
          host: 169.254.20.10
          path: /health
          port: 8081
        initialDelaySeconds: 60 
        timeoutSeconds: 5
      volumeMounts:
      - mountPath: /run/xtables.lock 
        name: xtables-lock
          readonly: false
        - name: config-volume 
        mountPath: /etc/coredns 
      - name: kube-dns-config 
        mountPath: /etc/kube-dns
    volumes:
    - name: xtables-lock
      hostPath:
        path: /run/xtables.lock 
        type: FileorCreate 
    - name: kube-dns-config 
      configMap:
      name: coredns
      optional: true
    - name: config-volume
      configMap:
        name: node-local-dns
        items:
          - key: Corefile
            path: Corefile.base

Daemonset node-local-dns的主要配置参数如下:

  • args: [“-localip” , “169.254.20.10” , “-conf” , “/etc/Corefile” , “upstreamsvc” , “kube-dns-upstream”]:将-localip参数设置为node-local-dns绑定的本地IP地址,对其他参数无须修改;
  • livenessProber中的健康检查端口号与ConfigMap中的一致;

另外,如果kube-proxy代理模式(-proxy-mode)使用的是ipvs模式,则还需要修改kubelet的启动参数-cluster-dns为node-local-dns绑定的本地IP地169.254.20.10。

2.2.2 部署

通过kubectl create命令创建node-local-dns服务:

kubectl create -f nodelocaldns.yaml 
serviceaccount/node-local-dns created 
service/kube-dns-upstream created 
configmap/node-local-dns created 
daemonset.apps/node-local-dns created

确认在每个Node上都运行了一个node-local-dns Pod:

在客户端Pod内对服务名的解析没有变化,仍然可以直接通过服务名访问其他服务,例如:

03 文末

本文主要讲解Node本地DNS缓存相关的概念,希望能帮助到大家,谢谢大家的阅读,本文完!

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
3月前
|
Kubernetes 容器
K8S的Service的LoadBanlance之Metallb解决方案
本文介绍了如何在Kubernetes中使用MetalLB来实现Service的LoadBalancer功能,包括MetalLB的部署、配置、以及通过创建地址池和部署服务来测试MetalLB的过程。
158 1
K8S的Service的LoadBanlance之Metallb解决方案
|
4月前
|
Kubernetes Ubuntu Windows
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
142 3
|
1月前
|
Web App开发 JavaScript 前端开发
2024年5月node.js安装(winmac系统)保姆级教程
本篇博客为2024年5月版Node.js安装教程,适用于Windows和Mac系统。作者是一名熟悉JavaScript与Vue的大一学生,分享了Node.js的基本介绍、下载链接及简单安装步骤。安装完成后,通过终端命令`node -v`验证版本即可确认安装成功。欢迎关注作者,获取更多技术文章。
28 2
2024年5月node.js安装(winmac系统)保姆级教程
|
2月前
|
JavaScript 前端开发 Java
Node.js 教程
10月更文挑战第1天
53 0
|
4月前
|
JavaScript NoSQL 前端开发
|
4月前
|
Kubernetes 网络安全 容器
在K8S中,有个服务使用service的nodeport进行暴露,发现访问不到如何排查?
在K8S中,有个服务使用service的nodeport进行暴露,发现访问不到如何排查?
|
4月前
|
存储 Kubernetes 负载均衡
在K8S中,node数量增多会有什么影响吗?
在K8S中,node数量增多会有什么影响吗?
|
28天前
|
存储 JavaScript 搜索推荐
Node框架的安装和配置方法
安装 Node 框架是进行 Node 开发的第一步,通过正确的安装和配置,可以为后续的开发工作提供良好的基础。在安装过程中,需要仔细阅读相关文档和提示,遇到问题及时解决,以确保安装顺利完成。
81 2
|
3月前
|
JavaScript
NodeJs的安装
文章介绍了Node.js的安装步骤和如何创建第一个Node.js应用。包括从官网下载安装包、安装过程、验证安装是否成功,以及使用Node.js监听端口构建简单服务器的示例代码。
NodeJs的安装
|
2月前
|
JavaScript 开发工具 git
已安装nodejs但是安装hexo报错
已安装nodejs但是安装hexo报错
38 2
下一篇
DataWorks