CoreDNS for kubernetes Service Discovery

1、CoreDNS簡介php

       Kubernetes包括用於服務發現的DNS服務器Kube-DNS。 該DNS服務器利用SkyDNS的庫來爲Kubernetes pod和服務提供DNS請求。SkyDNS2的做者,Miek Gieben,建立了一個新的DNS服務器,CoreDNS,它採用更模塊化,可擴展的框架構建。 Infoblox已經與Miek合做,將此DNS服務器做爲Kube-DNS的替代品。html

      CoreDNS利用做爲Web服務器Caddy的一部分而開發的服務器框架。該框架具備很是靈活,可擴展的模型,用於經過各類中間件組件傳遞請求。這些中間件組件根據請求提供不一樣的操做,例如記錄,重定向,修改或維護。雖然它一開始做爲Web服務器,可是Caddy並非專門針對HTTP協議的,而是構建了一個基於CoreDNS的理想框架。node

      在這種靈活的模型中添加對Kubernetes的支持,至關於建立了一個Kubernetes中間件。該中間件使用Kubernetes API來知足針對特定Kubernetes pod或服務的DNS請求。並且因爲Kube-DNS做爲Kubernetes的另外一項服務,kubelet和Kube-DNS之間沒有緊密的綁定。您只須要將DNS服務的IP地址和域名傳遞給kubelet,而Kubernetes並不關心誰在實際處理該IP請求。linux

2、CoreDNS支持的行爲nginx

1.0.0版本主要遵循Kube-DNS的當前行爲。 CoreDNS的005及更高版本實現了完整的規範和更多功能。git

  • A記錄(正常的Service分配了一個名爲my-svc.my-namespace.svc.cluster.local的DNS A記錄。 這解決了服務的集羣IP)
  • 「headless」(沒有集羣IP)的Service也分配了一個名爲my-svc.my-namespace.svc.cluster.local的DNS A記錄。 與普通服務不一樣,這解決了Service選擇了pods的一組IP。 客戶預計將從這ip集合中消耗集合或使用標準循環選擇。
  • 針對名爲正常或無頭服務的端口建立的SRV記錄,對於每一個命名的端口,SRV記錄的格式爲_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster.local。對於常規服務,這將解析爲端口號和CNAME:my-svc.my-namespace.svc.cluster.local;對於無頭服務,這解決了多個答案,一個用於支持服務的每一個pod,幷包含端口號還有格式爲auto-generated-name.my-svc.my-namespace.svc.cluster.local 的pod的CNAME 。SRV記錄包含它們中的「svc」段,對於省略「svc」段的舊式CNAME不支持。
  • 做爲Service一部分的endpoints的A記錄(好比「pets」的記錄)
  • pod的Spec中描述的A記錄
  • 還有就是用來發現正在使用的DNS模式版本的TXT記錄

      全部羣集中不須要pod A記錄支持,默認狀況下禁用。 此外,CoreDNS對此用例的支持超出了在Kube-DNS中找到的標準行爲。github

     在Kube-DNS中,這些記錄不反映集羣的狀態,例如,對w-x-y-z.namespace.pod.cluster.local的任何查詢將返回帶有w.x.y.z(ip)的A記錄,即便該IP不屬於指定的命名空間,甚至不屬於集羣地址空間。最初的想法是啓用對* .namespace.pod.cluster.local這樣的域使用通配符SSL證書。web

    CoreDNS集成了提供pod驗證的選項,驗證返回的IP地址w.x.y.z其實是指定命名空間中的pod的IP。他防止在命名空間中欺騙DNS名稱。 然而,它確實會大大增長CoreDNS實例的內存佔用,由於如今它須要觀察全部的pod,而不只僅是服務端點。docker

  

3、在kubernetes中部署corednsapache

一、下載coredns部署包:

https://github.com/coredns/deployment/tree/master/kubernetes

主要有幾個文件:

      deploy.sh是一個便捷的腳本,用於生成用於在當前運行標準kube-dns的集羣上運行CoreDNS的清單。使用coredns.yaml.sed文件做爲模板,它建立一個ConfigMap和一個CoreDNS  deployment,而後更新 Kube-DNS service selector以使用CoreDNS deployment。 經過從新使用現有服務,服務請求不會中斷。

    腳本不會刪除kube-dns的deployment或replication controller - 您必須手動執行:

kubectl delete --namespace=kube-system deployment kube-dns

要使用它,只需將它們放在同一目錄中,而後運行deploy.sh腳本,將其傳遞給您的服務CIDR(10.3.0.0/24)。 這將生成具備必要Corefile的ConfigMap。 它還將查找現有的kube-dns服務的集羣IP。 

(注意:以上原始腳本只適用於當前kubernetes集羣含有kube-dns的狀況,若是沒有須要修改下腳本)

#!/bin/bash

# Deploys CoreDNS to a cluster currently running Kube-DNS.

SERVICE_CIDR=$1
CLUSTER_DOMAIN=${2:-cluster.local}
YAML_TEMPLATE=${3:-`pwd`/coredns.yaml.sed}
YAML=${4:-`pwd`/coredns.yaml}

if [[ -z $SERVICE_CIDR ]]; then
        echo "Usage: $0 SERVICE-CIDR [ CLUSTER-DOMAIN ] [ YAML-TEMPLATE ] [ YAML ]"
        exit 1
fi

#CLUSTER_DNS_IP=$(kubectl get service --namespace kube-system kube-dns -o jsonpath="{.spec.clusterIP}") CLUSTER_DNS_IP=10.3.0.10

sed -e s/CLUSTER_DNS_IP/$CLUSTER_DNS_IP/g -e s/CLUSTER_DOMAIN/$CLUSTER_DOMAIN/g -e s?SERVICE_CIDR?$SERVICE_CIDR?g $YAML_TEMPLATE

默認狀況下CLUSTER_DNS_IP是自動獲取kube-dns的集羣ip的,可是因爲沒有部署kube-dns因此只能手動指定一個集羣ip了。

coredns.yaml.sed的內容以下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        log stdout
        health
        kubernetes CLUSTER_DOMAIN SERVICE_CIDR
        proxy . /etc/resolv.conf
        cache 30
    }
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: coredns
  namespace: kube-system
  labels:
    k8s-app: coredns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "CoreDNS"
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: coredns
  template:
    metadata:
      labels:
        k8s-app: coredns
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
    spec:
      containers:
      - name: coredns
        image: coredns/coredns:latest
        imagePullPolicy: Always
        args: [ "-conf", "/etc/coredns/Corefile" ]
        volumeMounts:
        - name: config-volume
          mountPath: /etc/coredns
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
      dnsPolicy: Default
      volumes:
        - name: config-volume
          configMap:
            name: coredns
            items:
            - key: Corefile
              path: Corefile
---
apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: coredns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "CoreDNS"
spec:
  selector:
    k8s-app: coredns
  clusterIP: CLUSTER_DNS_IP
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP

 執行:

./deploy.sh 10.3.0.0/24 cluster.local

以上腳本執行後能夠看到預覽的效果:

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        log stdout
        health
        kubernetes cluster.local 10.3.0.0/24
        proxy . /etc/resolv.conf
        cache 30
    }
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: coredns
  namespace: kube-system
  labels:
    k8s-app: coredns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "CoreDNS"
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: coredns
  template:
    metadata:
      labels:
        k8s-app: coredns
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
    spec:
      containers:
      - name: coredns
        image: coredns/coredns:latest
        imagePullPolicy: Always
        args: [ "-conf", "/etc/coredns/Corefile" ]
        volumeMounts:
        - name: config-volume
          mountPath: /etc/coredns
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
      dnsPolicy: Default
      volumes:
        - name: config-volume
          configMap:
            name: coredns
            items:
            - key: Corefile
              path: Corefile
---
apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: coredns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "CoreDNS"
spec:
  selector:
    k8s-app: coredns
  clusterIP: 10.3.0.10
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP

仔細觀察上面的Corefile部分,這是一個在端口53上運行CoreDNS併爲Kubernetes提供cluster.local域的示例

    .:53 {
        errors
        log stdout
        health
        kubernetes cluster.local 10.3.0.0/24
        proxy . /etc/resolv.conf
        cache 30
    }

1)errors官方沒有明確解釋,後面研究

2)log stdout:日誌中間件配置爲將日誌寫入STDOUT

3)health:健康檢查,提供了指定端口(默認爲8080)上的HTTP端點,若是實例是健康的,則返回「OK」。

4)cluster.local:CoreDNS爲kubernetes提供的域,10.3.0.0/24這告訴Kubernetes中間件它負責爲反向區域提供PTR請求0.0.3.10.in-addr.arpa ..換句話說,這是容許反向DNS解析服務(咱們常用到得DNS服務器裏面有兩個區域,即「正向查找區域」和「反向查找區域」,正向查找區域就是咱們一般所說的域名解析,反向查找區域便是這裏所說的IP反向解析,它的做用就是經過查詢IP地址的PTR記錄來獲得該IP地址指向的域名,固然,要成功獲得域名就必須要有該IP地址的PTR記錄。PTR記錄是郵件交換記錄的一種,郵件交換記錄中有A記錄和PTR記錄,A記錄解析名字到地址,而PTR記錄解析地址到名字。地址是指一個客戶端的IP地址,名字是指一個客戶的徹底合格域名。經過對PTR記錄的查詢,達到反查的目的。

5)proxy:這能夠配置多個upstream 域名服務器,也能夠用於延遲查找 /etc/resolv.conf 中定義的域名服務器

6)cache:這容許緩存兩個響應結果,一個是確定結果(即,查詢返回一個結果)和否認結果(查詢返回「沒有這樣的域」),具備單獨的高速緩存大小和TTLs。

 

二、如今安裝coredns到kubernetes中

[root@dev-master CoreDNS]# ./deploy.sh 10.3.0.0/24 cluster.local | kubectl apply -f -
configmap "coredns" created
deployment "coredns" created
service "kube-dns" created
[root@dev-master CoreDNS]# kubectl get pods --namespace=kube-system
NAME                                        READY     STATUS    RESTARTS   AGE
coredns-512496995-c1x9g 1/1 Running 0 5m default-http-backend-905355492-nrt1z        1/1       Running   0          23h
heapster-2450140206-dw408                   1/1       Running   2          23h
kube-apiserver-172.16.71.200                1/1       Running   3          7d
kube-controller-manager-172.16.71.200       1/1       Running   10         8d
kube-proxy-172.16.71.200                    1/1       Running   49         37d
kube-scheduler-172.16.71.200                1/1       Running   300        14d
kubernetes-dashboard-654048359-p73r9        1/1       Running   0          23h
monitoring-grafana-438219031-32btw          1/1       Running   1          5d
monitoring-influxdb-3584808869-s6sh1        1/1       Running   2          23h
nginx-ingress-controller-1644785683-9fxsp   1/1       Running   4          26d
nginx-ingress-controller-1644785683-mw7nx   1/1       Running   2          23h
tiller-deploy-411327518-q9zn3               1/1       Running   2          23h
[root@dev-master CoreDNS]# kubectl logs -f  coredns-512496995-c1x9g --namespace=kube-system
.:53
2017/09/13 02:36:31 [INFO] CoreDNS-011
2017/09/13 02:36:31 [INFO] linux/amd64, go1.9, 1b60688d
CoreDNS-011
linux/amd64, go1.9, 1b60688d

 

三、修改master節點和全部node節點的/etc/systemd/system/kube-kubelet.service,修改內容如紅色所注,與上面的Corefile中的值對應。

[Unit]
Description=Kubernetes Kubelet Master
Documentation=https://github.com/GoogleCloudPlatform/kubernetes




[Service]
Environment=KUBELET_IMAGE_TAG=v1.6.2
ExecStartPre=/usr/bin/mkdir -p /var/log/containers
ExecStart=/opt/bin/kubelet \
  --api-servers=http://127.0.0.1:8080 \
  --register-schedulable=false \
  --cni-conf-dir=/etc/kubernetes/cni/net.d \
  --container-runtime=docker \
  --allow-privileged=true \
  --pod-manifest-path=/etc/kubernetes/manifests \
  --hostname-override=172.16.71.200 \
  --pod-infra-container-image=172.16.80.94/mir/pause-amd64:3.0 \
  --v=3 \
  --cluster-dns=10.3.0.10 \ --cluster-domain=cluster.local. \ --resolv-conf=/etc/resolv.conf \
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

 

四、測試CoreDNS是否起做用

如今咱們來建立一個nginx的pod和service,測試一下coredns是否起做用

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: 172.16.71.199/common/nginx:1.8.1
    ports:
    - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: nginx
[root@dev-master CoreDNS]# kubectl create -f nginx.yaml 
pod "nginx" created
service "nginx" created
[root@dev-master CoreDNS]# kubectl get pod
NAME                              READY     STATUS    RESTARTS   AGE
load-generator-1962471460-6v7lb   1/1       Running   3          22d
nginx                             1/1       Running   0          1m
php-apache-1106203038-w51jw       1/1       Running   3          22d

用curl測試,首先進入這個集羣內的另外一個pod(這個pod是在修改master節點和node節點的/etc/systemd/system/kube-kubelet.service以後建立的),在pod內部訪問剛纔建立的

nginx

[root@mir2-handler-deployment-3595565332-bqk3t /]# 
<5332-bqk3t /]# curl nginx.default.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

實驗證實用:my-svc.my-namespace.svc.cluster.local的方式能夠訪問服務。

相關文章
相關標籤/搜索