kubernetes之部署kubedns
通俗理解,首先明白k8s dns是為服務的發現而生,即service的發現,為了能夠讓其它服務能夠直接通過service 名字找到它們,於是就需要dns將service名轉換為它的VIP, 那麽service的變化如何知道? 如何知道目前有哪些service 及知道他們的vip呢,service的增加減少又如何知道了,
所以要有一個組件(1.3中是Kube2sky,1.3後是kubedns)來時刻監控它的變化,監控到了什麽就把它記錄下來,記錄的是service和ip之間的映射關系,稱為DNS解析記錄,但是記錄在某個位置呢,監控的組件不同,記錄的位置也不同, Kube2sky是記錄到etcd中,kubedns是記錄到哪了呢, 記錄在內存當中,使用樹形結構在內存中保存監控到的記錄。
由於一切對集群的操作都是通過其API來的,所以它監控service資源變化也是借助於k8s API
這個組件僅僅是記錄下來以後,並不提供查詢。所以查詢就是另外一個組件的作用了,1.3之前是由Skydns來查詢的, 所有服務(pod)都找skydns查詢,1.3以後都是由dnsmasq查詢的,它們從前面記錄的地方查詢相關service的解析記錄,之所以用dnsmasq來查詢,因為它提供DNS查詢緩存,在內存中完成查詢,查詢速度非常快!
兩個組件一個負責監控並記錄,另外一個負責幫其它服務做查詢, 兩個組件必須要同時運行,如果其中一個出問題了,那麽dns系統將無法解析,於是需要有另一個組件專門來監控它們的健康狀態,這個組件就是exechealthz,Exechealthz是兩個版本中唯一保留的容器,依然提供健康檢查。
在K8s中,這三個組件都是用容器運行的,而且是在同一個pod中,
官方理解,上圖:
● dnsmasq簡介
Dnsmasq是一款小巧的DNS配置工具
在kube-dns插件中的作用:
● 通過kubedns容器獲取DNS規則,在集群中提供DNS查詢服務
● 提供DNS緩存,提高查詢性能
● 降低kubedns容器的壓力、提高穩定性
● Dockerfile在GitHub上Kubernetes組織的contrib倉庫中,位於dnsmasq目錄下
● exechealthz簡介
● 在kube-dns插件中提供健康檢查功能
● 源碼同樣在contrib倉庫中,位於exec-healthz目錄下。
● 新版中會對兩個容器都進行健康檢查,更加完善。
● 總結
kube-dns插件的三個容器的功能如下:
● kubedns容器
● 監視k8s Service資源並更新DNS記錄
● 替換etcd,使用TreeCache數據結構保存DNS記錄並實現SkyDNS的Backend接口
● 接入SkyDNS,對dnsmasq提供DNS查詢服務
● dnsmasq容器
● 對集群提供DNS查詢服務
● 設置kubedns為upstream
● 提供DNS緩存,降低kubedns負載,提高性能
● exechealthz容器
● 定期檢查kubedns和dnsmasq的健康狀態
● 為k8s活性檢測提供HTTP API
二、部署kubedns
1,上官方網址下載需要的yaml部署文件:https://github.com/kubernetes/kubernetes/tree/release-1.8/cluster/addons/dns
$ ls *.yaml *.base kubedns-cm.yaml kubedns-sa.yaml kubedns-controller.yaml.base kubedns-svc.yaml.base
2,主要是修改這四個部署文件
# cat kubedns-cm.yaml #此文件不需修改 apiVersion: v1 kind: ConfigMap metadata: name: kube-dns namespace: kube-system labels: addonmanager.kubernetes.io/mode: EnsureExists
# cat kubedns-sa.yaml #此文件不需修改 apiVersion: v1 kind: ServiceAccount metadata: name: kube-dns namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile
接下來主要修改的是 kubedns-controller.yaml 和 kubedns-svc.yaml
主要diff來比較下原文件與修改過的文件區別:
diff kubedns-controller.yaml.base /root/kubernetes/k8s-deploy/mainifest/dns/kubedns-controller.yaml 58c58 < image: gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.5 --- > image: gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.4 88c88 < - --domain=$DNS_DOMAIN. --- > - --domain=cluster.local. 109c109 < image: gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.5 --- > image: gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.4 128c128 < - --server=/$DNS_DOMAIN/127.0.0.1#10053 --- > - --server=/cluster.local/127.0.0.1#10053 147c147 < image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.5 --- > image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.4 160,161c160,161 < - --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.$DNS_DOMAIN,5,A < - --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.$DNS_DOMAIN,5,A --- > - --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.cluster.local,5,A > - --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.cluster.local,5,A 無非就是將有 k8s-dns-sidecar-amd64:1.14.5 的改為 k8s-dns-sidecar-amd64:1.14.4,將變量集群域名的環境變量 $DNS_DOMAIN 替換我們之前設置好的域名,如cluster.local。
修改過後的完整文件內容如下:
# cat kubedns-controller.yaml # Copyright 2016 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Should keep target in cluster/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml # in sync with this file. # __MACHINE_GENERATED_WARNING__ apiVersion: extensions/v1beta1 kind: Deployment metadata: name: kube-dns namespace: kube-system labels: k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile spec: # replicas: not specified here: # 1. In order to make Addon Manager do not reconcile this replicas parameter. # 2. Default is 1. # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on. strategy: rollingUpdate: maxSurge: 10% maxUnavailable: 0 selector: matchLabels: k8s-app: kube-dns template: metadata: labels: k8s-app: kube-dns annotations: scheduler.alpha.kubernetes.io/critical-pod: '' spec: tolerations: - key: "CriticalAddonsOnly" operator: "Exists" volumes: - name: kube-dns-config configMap: name: kube-dns optional: true containers: - name: kubedns image: gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.4 resources: # TODO: Set memory limits when we've profiled the container for large # clusters, then set request = limit to keep this container in # guaranteed class. Currently, this container falls into the # "burstable" category so the kubelet doesn't backoff from restarting it. limits: memory: 170Mi requests: cpu: 100m memory: 70Mi livenessProbe: httpGet: path: /healthcheck/kubedns port: 10054 scheme: HTTP initialDelaySeconds: 60 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 readinessProbe: httpGet: path: /readiness port: 8081 scheme: HTTP # we poll on pod startup for the Kubernetes master service and # only setup the /readiness HTTP server once that's available. initialDelaySeconds: 3 timeoutSeconds: 5 args: - --domain=cluster.local. - --dns-port=10053 - --config-dir=/kube-dns-config - --v=2 env: - name: PROMETHEUS_PORT value: "10055" ports: - containerPort: 10053 name: dns-local protocol: UDP - containerPort: 10053 name: dns-tcp-local protocol: TCP - containerPort: 10055 name: metrics protocol: TCP volumeMounts: - name: kube-dns-config mountPath: /kube-dns-config - name: dnsmasq image: gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.4 livenessProbe: httpGet: path: /healthcheck/dnsmasq port: 10054 scheme: HTTP initialDelaySeconds: 60 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 args: - -v=2 - -logtostderr - -configDir=/etc/k8s/dns/dnsmasq-nanny - -restartDnsmasq=true - -- - -k - --cache-size=1000 - --log-facility=- - --server=/cluster.local/127.0.0.1#10053 - --server=/in-addr.arpa/127.0.0.1#10053 - --server=/ip6.arpa/127.0.0.1#10053 ports: - containerPort: 53 name: dns protocol: UDP - containerPort: 53 name: dns-tcp protocol: TCP # see: https://github.com/kubernetes/kubernetes/issues/29055 for details resources: requests: cpu: 150m memory: 20Mi volumeMounts: - name: kube-dns-config mountPath: /etc/k8s/dns/dnsmasq-nanny - name: sidecar image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.4 livenessProbe: httpGet: path: /metrics port: 10054 scheme: HTTP initialDelaySeconds: 60 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 args: - --v=2 - --logtostderr - --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.cluster.local,5,A - --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.cluster.local,5,A ports: - containerPort: 10054 name: metrics protocol: TCP resources: requests: memory: 20Mi cpu: 10m dnsPolicy: Default # Don't use cluster DNS. serviceAccountName: kube-dns
kubedns-controller 運行了 三個容器:kubedns dnsmasq sidecar
# cat kubedns-svc.yaml # Copyright 2016 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # __MACHINE_GENERATED_WARNING__ apiVersion: v1 kind: Service metadata: name: kube-dns namespace: kube-system labels: k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "KubeDNS" spec: selector: k8s-app: kube-dns clusterIP: 10.254.0.2 #修改為我們設定的cluster的IP,其它默認。 ports: - name: dns port: 53 protocol: UDP - name: dns-tcp port: 53 protocol: TCP
部署文件設置好後,一起來創建:
# kubectl create -f kubedns-cm.yaml -f kubedns-sa.yaml -f kubedns-controller.yaml kubedns-svc.yaml
查看創建後的pod,svc:
# kubectl get pod,svc -n kube-system NAME READY STATUS RESTARTS AGE po/kube-dns-7797cb8758-dlhqs 3/3 Running 0 3h NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE svc/kube-dns ClusterIP 10.254.0.2 <none> 53/UDP,53/TCP 3h
三,驗證kubedns功能
如果我們此前已經有了部署了許多pod和服務,並且在Kubelet 啟動配置文件加入了 --cluster-dns=10.254.0.2 --cluster-domain=cluster.local 參數,則可以進入某個pod中的容器內查看其/etc/resolv.conf 文件
root@jekins:~# cat /etc/resolv.conf nameserver 10.254.0.2 search default.svc.cluster.local svc.cluster.local cluster.local options ndots:5 如上所示,根據kubelet的啟動參數,kubelet會在每個pod中設置DNS域名解析文件/etc/resolv.conf,加入了nameser和search搜索域。最後應用程序就能夠像訪問網站一樣,僅僅通過服務的名字就能訪問到服務了。 root@jek:~# ping jenkinsservice PING jenkinsservice.default.svc.cluster.local (10.254.145.97) 56(84) bytes of data. 可以看到已經解析出來了
通常可以啟動一個帶有nslookup工具的pod,比如busybox,鏡像從gcr.io/google_containers/busybox下載,來驗證DNS服務是否能夠正常工作。
至此,kubedns部署完成。
kubernetes之部署kubedns