一 Kubernetes DNS介紹1.1 Kubernetes DNS發展作為服務發現機制的基本功能,在集群內需要能夠通過服務名對服務進行訪問,因此需要一個集群範圍內的DNS服務來完成從服務名到ClusterIP的解析。DNS服務在Kubernetes的發展過程中經歷了3個階段,SkyDNS --... ...
一 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服務中設置的功能變數名稱。
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對的形式表示。
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服務。