1. 程式人生 > >kubernetes之部署kubedns

kubernetes之部署kubedns

def 規則 toc 環境 auto pst mem 參數 exe

一,理解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