附011.Kubernetes-DNS及搭建

  • 2019 年 12 月 10 日
  • 筆記

一 Kubernetes DNS介紹

1.1 Kubernetes DNS發展

作為服務發現機制的基本功能,在集群內需要能夠通過服務名對服務進行訪問,因此需要一個集群範圍內的DNS服務來完成從服務名到ClusterIP的解析。

DNS服務在Kubernetes的發展過程中經歷了3個階段,SkyDNS —-> KubeDNS —-> CoreDNS。

1.2 SkyDNS

在Kubernetes 1.2版本時,DNS服務是由SkyDNS提供的,它由4個容器組成:kube2sky、skydns、etcd和healthz。

kube2sky容器監控Kubernetes中Service資源的變化,根據Service的名稱和IP地址資訊生DNS記錄,並將其保存到etcd中。

skydns容器從etcd中讀取DNS記錄,並為客戶端容器應用提供DNS查詢服務。

healthz容器提供對skydns服務的健康檢查功能。

SkyDNS的總體架構如下:

1.3 KubeDNS

從Kubernetes 1.4版本開始,SkyDNS組件便被KubeDNS替換,主要考慮是SkyDNS組件之間通訊較多,整體性能不高。

KubeDNS由3個容器組成:kubedns、dnsmasq和sidecar,去掉了SkyDNS中的etcd存儲,將DNS記錄直接保存在記憶體中,以提高查詢性能。

kubedns容器監控Kubernetes中Service資源的變化,根據Service的名稱和IP地址生成DNS記錄,並將DNS記錄保存在記憶體中。

dnsmasq容器從kubedns中獲取DNS記錄,提供DNS快取,為客戶端容器應用提供DNS查詢服務。

sidecar提供對kubedns和dnsmasq服務的健康檢查功能。

KubeDNS的總體架構如下:

1.4 CoreDNS

從Kubernetes 1.11版本開始,Kubernetes集群的DNS服務由CoreDNS提供。CoreDNS是CNCF基金會的一個項目,是用Go語言實現的高性能、插件式、易擴展的DNS服務端。

CoreDNS解決了KubeDNS的一些問題,例如dnsmasq的安全漏洞、externalName不能使用stubDomains設置,等等。

CoreDNS支援自定義DNS記錄及配置upstream DNS Server,可以統一管理Kubernetes基於服務的內部DNS和數據中心的物理DNS。

CoreDNS沒有使用多個容器的架構,只用一個容器便實現了KubeDNS內3個容器的全部功能。

CoreDNS的總體架構如下:

二 CoreDNS部署

2.1 修改kubelet啟動參數

部署之前需要修改每個Node上kubelet的啟動參數,加上以下兩個參數:

  • –cluster-dns=169.169.0.100:為DNS服務的ClusterIP地址。
  • –cluster-domain=cluster.local:為在DNS服務中設置的域名。

然後重啟kubelet服務。

提示:也可通過如下方式引入yaml配置文件實現:

  1 # vi /etc/systemd/system/kubelet.service    2 ……    3 --config=/etc/kubernetes/kubelet-config.yaml     4 ……    5 # vi /etc/kubernetes/kubelet-config.yaml    6 ……    7 clusterDomain: "cluster.local"    8 clusterDNS:    9   - "10.254.0.2"   10 ……

2.2 創建授權

在啟用了RBAC的集群中, 還可以設置ServiceAccount、 ClusterRole、 ClusterRoleBinding對CoreDNS容器進行許可權設置。ServiceAccount、 ClusterRole、 ClusterRoleBinding相關yaml如下:

  1 [root@k8smaster01 ~]# vi corednsaccout.yaml    2 # __MACHINE_GENERATED_WARNING__    3    4 apiVersion: v1    5 kind: ServiceAccount    6 metadata:    7   name: coredns    8   namespace: kube-system    9   labels:   10       kubernetes.io/cluster-service: "true"   11       addonmanager.kubernetes.io/mode: Reconcile   12 ---   13 apiVersion: rbac.authorization.k8s.io/v1   14 kind: ClusterRole   15 metadata:   16   labels:   17     kubernetes.io/bootstrapping: rbac-defaults   18     addonmanager.kubernetes.io/mode: Reconcile   19   name: system:coredns   20 rules:   21 - apiGroups:   22   - ""   23   resources:   24   - endpoints   25   - services   26   - pods   27   - namespaces   28   verbs:   29   - list   30   - watch   31 - apiGroups:   32   - ""   33   resources:   34   - nodes   35   verbs:   36   - get   37 ---   38 apiVersion: rbac.authorization.k8s.io/v1   39 kind: ClusterRoleBinding   40 metadata:   41   annotations:   42     rbac.authorization.kubernetes.io/autoupdate: "true"   43   labels:   44     kubernetes.io/bootstrapping: rbac-defaults   45     addonmanager.kubernetes.io/mode: EnsureExists   46   name: system:coredns   47 roleRef:   48   apiGroup: rbac.authorization.k8s.io   49   kind: ClusterRole   50   name: system:coredns   51 subjects:   52 - kind: ServiceAccount   53   name: coredns   54   namespace: kube-system   55   56 [root@k8smaster01 ~]# kubectl create -f corednsaccout.yaml

2.3 創建ConfigMap

  1 [root@k8smaster01 ~]# vi corednsconfigmap.yaml    2 apiVersion: v1    3 kind: ConfigMap    4 metadata:    5   name: coredns    6   namespace: kube-system    7   labels:    8       addonmanager.kubernetes.io/mode: EnsureExists    9 data:   10   Corefile: |   11     .:53 {   12         errors   13         health   14         kubernetes cluster.local in-addr.arpa ip6.arpa {   15             pods insecure   16             upstream   17             fallthrough in-addr.arpa ip6.arpa   18         }   19         prometheus :9153   20         forward . /etc/resolv.conf   21         cache 30   22         loop   23         reload   24         loadbalance   25     }   26   27 [root@k8smaster01 ~]# kubectl create -f corednsconfigmap.yaml

2.4 創建Deployment

  1 [root@k8smaster01 ~]# vi corednsdeploy.yaml    2 apiVersion: apps/v1    3 kind: Deployment    4 metadata:    5   name: coredns    6   namespace: kube-system    7   labels:    8     k8s-app: kube-dns    9     kubernetes.io/cluster-service: "true"   10     addonmanager.kubernetes.io/mode: Reconcile   11     kubernetes.io/name: "CoreDNS"   12 spec:   13   # replicas: not specified here:   14   # 1. In order to make Addon Manager do not reconcile this replicas parameter.   15   # 2. Default is 1.   16   # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on.   17   strategy:   18     type: RollingUpdate   19     rollingUpdate:   20       maxUnavailable: 1   21   selector:   22     matchLabels:   23       k8s-app: kube-dns   24   template:   25     metadata:   26       labels:   27         k8s-app: kube-dns   28       annotations:   29         seccomp.security.alpha.kubernetes.io/pod: 'docker/default'   30     spec:   31       priorityClassName: system-cluster-critical   32       serviceAccountName: coredns   33       tolerations:   34         - key: "CriticalAddonsOnly"   35           operator: "Exists"   36       nodeSelector:   37         beta.kubernetes.io/os: linux   38       containers:   39       - name: coredns   40         image: registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.3.1   41         imagePullPolicy: IfNotPresent   42         resources:   43           limits:   44             memory: 170Mi   45           requests:   46             cpu: 100m   47             memory: 70Mi   48         args: [ "-conf", "/etc/coredns/Corefile" ]   49         volumeMounts:   50         - name: config-volume   51           mountPath: /etc/coredns   52           readOnly: true   53         ports:   54         - containerPort: 53   55           name: dns   56           protocol: UDP   57         - containerPort: 53   58           name: dns-tcp   59           protocol: TCP   60         - containerPort: 9153   61           name: metrics   62           protocol: TCP   63         livenessProbe:   64           httpGet:   65             path: /health   66             port: 8080   67             scheme: HTTP   68           initialDelaySeconds: 60   69           timeoutSeconds: 5   70           successThreshold: 1   71           failureThreshold: 5   72         readinessProbe:   73           httpGet:   74             path: /health   75             port: 8080   76             scheme: HTTP   77         securityContext:   78           allowPrivilegeEscalation: false   79           capabilities:   80             add:   81             - NET_BIND_SERVICE   82             drop:   83             - all   84           readOnlyRootFilesystem: true   85       dnsPolicy: Default   86       volumes:   87         - name: config-volume   88           configMap:   89             name: coredns   90             items:   91             - key: Corefile   92               path: Corefile   93   94 [root@k8smaster01 ~]# kubectl create -f corednsdeploy.yaml

提示:replicas副本的數量通常應該根據集群的規模和服務數量確定,如果單個CoreDNS進程不足以支撐整個集群的DNS查詢,則可以通過水平擴展提高查詢能力。由於DNS服務是Kubernetes集群的關鍵核心服務,所以建議為其Deployment設置自動擴縮容控制器,自動管理其副本數量。

同時,對資源限制部分(CPU限制和記憶體限制) 的設置也應根據實際環境進行調整。

2.5 創建Service

  1 [root@k8smaster01 ~]# vi corednssvc.yaml    2 apiVersion: v1    3 kind: Service    4 metadata:    5   name: kube-dns    6   namespace: kube-system    7   annotations:    8     prometheus.io/port: "9153"    9     prometheus.io/scrape: "true"   10   labels:   11     k8s-app: kube-dns   12     kubernetes.io/cluster-service: "true"   13     addonmanager.kubernetes.io/mode: Reconcile   14     kubernetes.io/name: "CoreDNS"   15 spec:   16   selector:   17     k8s-app: kube-dns   18   clusterIP: 10.254.0.2   19   ports:   20   - name: dns   21     port: 53   22     protocol: UDP   23   - name: dns-tcp   24     port: 53   25     protocol: TCP   26   - name: metrics   27     port: 9153   28     protocol: TCP   29   30 [root@k8smaster01 ~]# kubectl create -f corednssvc.yaml

2.6 確認驗證

  1 [root@k8smaster01 ~]# kubectl get deployments --namespace=kube-system    2 NAME                   READY   UP-TO-DATE   AVAILABLE   AGE    3 coredns                1/1     1            1           14s    4 [root@k8smaster01 ~]# kubectl get pod --namespace=kube-system    5 NAME                                    READY   STATUS    RESTARTS   AGE    6 coredns-5b46b98d57-cknrr                1/1     Running   0          34s    7 [root@k8smaster01 ~]# kubectl get svc --namespace=kube-system    8 NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                  AGE    9 kube-dns               ClusterIP   10.254.0.2     <none>        53/UDP,53/TCP,9153/TCP   47s

三 服務名DNS解析

3.1 創建測試Pod

  1 [root@k8smaster01 ~]# vi busybox.yaml    2 apiVersion: v1    3 kind: Pod    4 metadata:    5   name: busybox    6   namespace: default    7 spec:    8   containers:    9   - name: busybox   10     image: gcr.azk8s.cn/google_containers/busybox   11     command:   12       - sleep   13       - "3600"   14   15 [root@k8smaster01 ~]# kubectl exec -ti busybox -- nslookup webapp		#測試解析   16 Server:    10.254.0.2   17 Address 1: 10.254.0.2 kube-dns.kube-system.svc.cluster.local   18   19 Name:      webapp   20 Address 1: 10.254.156.234 webapp.default.svc.cluster.local

提示:如果某個Service屬於不同的命名空間,那麼在進行Service查找時,需要補充Namespace的名稱,組合成完整的域名。

  1 [root@k8smaster01 ~]# kubectl exec -ti busybox -- nslookup kube-dns.kube-system	#補充kube-system的namespace    2 Server:    10.254.0.2    3 Address 1: 10.254.0.2 kube-dns.kube-system.svc.cluster.local    4    5 Name:      kube-dns.kube-system    6 Address 1: 10.254.0.2 kube-dns.kube-system.svc.cluster.local

四 CoreDNS配置說明

4.1 常見插件

CoreDNS的主要功能是通過插件系統實現的。CoreDNS實現了一種鏈式插件結構,將DNS的邏輯抽象成了一個個插件,能夠靈活組合使用。

常用的插件如下:

  • loadbalance:提供基於DNS的負載均衡功能。
  • loop:檢測在DNS解析過程中出現的簡單循環問題。
  • cache:提供前端快取功能。
  • health:對Endpoint進行健康檢查。
  • kubernetes:從Kubernetes中讀取zone數據。
  • etcd:從etcd讀取zone數據,可以用於自定義域名記錄。
  • file:從RFC1035格式文件中讀取zone數據。
  • hosts:使用/etc/hosts文件或者其他文件讀取zone數據,可以用於自定義域名記錄。
  • auto:從磁碟中自動載入區域文件。
  • reload:定時自動重新載入Corefile配置文件的內容。
  • forward:轉發域名查詢到上游DNS伺服器。
  • proxy:轉發特定的域名查詢到多個其他DNS伺服器,同時提供到多個DNS伺服器的負載均衡功能。
  • prometheus:為Prometheus系統提供採集性能指標數據的URL。
  • pprof:在URL路徑/debug/pprof下提供運行時的性能數據。
  • log:對DNS查詢進行日誌記錄。
  • errors:對錯誤資訊進行日誌記錄。

4.2 插件配置

示例1:

  1 [root@k8smaster01 ~]# vi corednsconfigmap.yaml    2 apiVersion: v1    3 kind: ConfigMap    4 metadata:    5   name: coredns    6   namespace: kube-system    7   labels:    8       addonmanager.kubernetes.io/mode: EnsureExists    9 data:   10   Corefile: |   11     .:53 {   12         errors   13         health   14         kubernetes cluster.local in-addr.arpa ip6.arpa {   15             pods insecure   16             upstream   17             fallthrough in-addr.arpa ip6.arpa   18         }   19         prometheus :9153   20         forward . /etc/resolv.conf   21         cache 30   22         loop   23         reload   24         loadbalance   25     }

如上所示為域名「cluster.local」設置了一系列插件, 包括errors、health、kubernetes、prometheus、forward、cache、loop、reload和loadbalance,在進行域名解析時, 這些插件將以從上到下的順序依次執行。

示例2:如下為使用etcd插件的配置示例,將以「.com」結尾的域名記錄配置為從etcd中獲取,並將域名記錄保存在/skydns路徑下。

  1 {    2 etcd com {    3 path /skydns    4 endpoint http://192.168.18.3:2379    5 upstream /etc/resolv.conf    6 }    7 cache 160 com    8 loadbalance    9 proxy . /etc/resolv.conf   10   11 }   12 [root@k8smaster01 ~]# etcdctl put /skydns/com/mycompany '{"host":"10.1.1.1","ttl":"60"}'	#測試插入   13 [root@k8smaster01 ~]# nslookpu mycompany.com

提示:forward和proxy插件都可以用於配置上游DNS伺服器或其他DNS伺服器,當在CoreDNS中查詢不到域名時,會到其他DNS伺服器上進行查詢。在實際環境中,可以將Kubernetes集群外部的DNS納入CoreDNS,進行統一的DNS管理。

五 Pod級別的DNS設置

5.1 Pod級別設置

集群的DNS(CoreDNS)配置之外,針對Pod中也可以設置相應的DNS策略。

示例1:

  1 [root@k8smaster01 study]# vi mywebapp.yaml    2 apiVersion: v1    3 kind: Pod    4 metadata:    5   name: webapp    6 spec:    7   containers:    8   - name: webapp    9     image: tomcat   10   dnsPolicy: Default   11 ……

目前可以設置的DNS策略如下:

  • Default:繼承Pod所在宿主機的DNS設置。
  • ClusterFirst:優先使用Kubernetes環境的DNS服務(如CoreDNS提供的域名解析服務),將無法解析的域名轉發到從宿主機繼承的DNS伺服器。
  • ClusterFirstWithHostNet:與ClusterFirst相同,對於以hostNetwork模式運行的Pod,應明確指定使用該策略。
  • None:忽略Kubernetes環境的DNS配置,通過spec.dnsConfig自定義DNS配置。這個選項從Kubernetes1.9版本開始引入,到Kubernetes 1.10版本升級為Beta版,到Kubernetes1.14版本升級為穩定版。自定義DNS配置可以通過spec.dnsConfig欄位進行設置,可以設置下列資訊。
    • nameservers:一組DNS伺服器的列表,最多可以設置3個。
    • searches:一組用於域名搜索的DNS域名後綴,最多可以設置6個。
    • options:配置其他可選DNS參數,例如ndots、timeout等,以name或name/value對的形式表示。

示例2:dnsConfig外部欄位配置示例。

  1 [root@k8smaster01 study]# vi mywebapp.yaml    2 apiVersion: v1    3 kind: Pod    4 metadata:    5   namespace: default    6   name: dns-example    7 spec:    8   containers:    9   - name: test   10     image: nginx   11   dnsPolicy: "None"   12   dnsConfig:   13     nameservers:   14       - 223.5.5.5   15     searches:   16       - ns1.svc.cluster.local   17       - my.dns.search.suffix   18     options:   19       - name: ndots   20         value: "2"   21       - name: edns0
  1 [root@k8smaster01 study]# kubectl create -f mywebapp.yaml    2 [root@k8smaster01 study]# kubectl exec -ti dns-example -- cat /etc/resolv.conf		#確認查看    3 nameserver 223.5.5.5    4 search ns1.svc.cluster.local my.dns.search.suffix    5 options ndots:2 edns0

提示:如上配置從而實現Pod中自定義DNS,而不再使用Kubernetes環境的DNS服務。