1. 程式人生 > >kubernetes學習記錄(5)——服務發現機制與Cluster DNS的安裝(無CA認證版)

kubernetes學習記錄(5)——服務發現機制與Cluster DNS的安裝(無CA認證版)

服務發現機制

Kubernetes提供了兩種發現Service的方法:

1.環境變數

當Pod執行的時候,Kubernetes會將之前存在的Service的資訊通過環境變數寫到Pod中。

這種方法要求Pod必須要在Service之後啟動。

在Service之前啟動的Pod就不會有該Service的環境變數。

採用DNS的方式就沒有這個限制。

2.DNS

當有新的Service建立時,就會自動生成一條DNS記錄。

使用這種方法,需要安裝Cluster DNS。

Kubernetes1.2.7版本下Cluster DNS的安裝

閱讀github上官方原始碼發現:
Cluster DNS自Kubernetes1.3版本開始,結構發生了變化。這裡先以1.2.7版本作為研究。

1.2.7版本中,Cluster DNS主要包含如下幾項:

1)SkyDNS
提供DNS解析服務。
2)Etcd
用於DNS的儲存。
3)Kube2sky
監聽Kubernetes,當有新的Service建立時,將其註冊到etcd上。
4)healthz
提供對skydns服務的健康檢查功能。

安裝過程參考官方github文件。

在Master伺服器上下載Kubernetes釋出包

Cluster DNS在Kubernetes釋出包的cluster/addons/dns目錄下

yum -y install wget
wget https://codeload.github
.com/kubernetes/kubernetes/tar.gz/v1.2.7 tar zxvf v1.2.7 cd kubernetes-1.2.7/cluster/addons/dns

需要注意,skydns服務使用的clusterIP需要我們指定一個固定的IP地址,每個Node的kubelet程序都將使用這個IP地址,不能通過Kuberneters自動給skydns分配。

通過環境變數,配置引數

export DNS_SERVER_IP="10.254.10.2"
export DNS_DOMAIN="cluster.local"
export DNS_REPLICAS=1

設定 Cluster DNS Service的IP為 10.254.10.2(不能和已分配的IP重複

),Cluster DNS的本地域為 cluster.local。

修改每臺Node上的kubelet啟動引數

vim /etc/kubernetes/kubelet

在KUBELET_ARGS裡增加:

--cluster_dns=10.254.10.2 
--cluster_domain=cluster.local

cluster_dns為DNS服務的ClusterIP地址
cluster_domain為DNS服務中設定的域名

重啟kubelet服務

systemctl restart kubelet

生成dns-rc.yaml和dns-svc.yaml

kubernetes-1.2.7/cluster/addons/dns目錄下。

這裡寫圖片描述

skydns-rc.yaml.in和skydns-svc.yaml.in是兩個模板檔案,通過設定的環境變數修改其中的相應屬性值,可以生成Replication Controller和Service的定義檔案。

生成Replication Controller的定義檔案dns-rc.yaml建立RC

sed -e "s/{{ pillar\['dns_replicas'\] }}/${DNS_REPLICAS}/g;s/{{ pillar\['dns_domain'\] }}/${DNS_DOMAIN}/g" \skydns-rc.yaml.in > dns-rc.yaml

需要注意kube2sky需要ServiceAccount來呼叫Kubernetes API。
而ServiceAccount的使用需要對Kubernetes叢集進行安全認證,否則可能會導致RC無法自動建立Pod等錯誤

這裡有兩種解決辦法:

(1)選擇禁用ServiceAccount。編輯/etc/kubernetes/apiserver。
去除 KUBE_ADMISSION_CONTROL中的SecurityContextDeny,ServiceAccount,並重啟kube-apiserver.service服務

#vim /etc/kubernetes/apiserver
KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota"
#systemctl restart kube-apiserver.service

而關閉ServiceAccount,需要在kube2sky顯示指定Kubernetes API的URL
(2)對叢集進行安全認證,參考kubernetes學習記錄(9)——叢集基於CA簽名的安全設定 ,不需要對kube2sky顯示指定Kubernetes API的URL

修改生成的dns-rc.yaml,設定Kube2sky的啟動引數如下:

args:
  - --domain=cluster.local
  #如果已經進行CA認證,則可以不指定kube_master_url
  - --kube-master-url=http://192.168.121.143:8080

這裡特別注意:
在設定Kube2sky的啟動引數時
《Kubernetes實戰》和某些技術部落格中
將“- –domain”和“- –kube-master-url”錯誤地寫成了“- -domain”和“ - -kube-master-url”,均少了一個“-”

導致,Kube2sky的pod在啟動過程中,報CrashLoopBackOff的錯誤。

建議將dns-rc.yaml裡映象的下載地址gcr.io改成index.tenxcloud.com,能夠加速下載。

最終的dns-rc.yaml如下

apiVersion: v1
kind: ReplicationController
metadata:
  name: kube-dns-v11
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    version: v11
    kubernetes.io/cluster-service: "true"
spec:
  replicas: 1
  selector:
    k8s-app: kube-dns
    version: v11
  template:
    metadata:
      labels:
        k8s-app: kube-dns
        version: v11
        kubernetes.io/cluster-service: "true"
    spec:
      containers:
      - name: etcd
        image: index.tenxcloud.com/google_containers/etcd-amd64:2.2.1
        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:
            cpu: 100m
            memory: 500Mi
          requests:
            cpu: 100m
            memory: 50Mi
        command:
        - /usr/local/bin/etcd
        - -data-dir
        - /var/etcd/data
        - -listen-client-urls
        - http://127.0.0.1:2379,http://127.0.0.1:4001
        - -advertise-client-urls
        - http://127.0.0.1:2379,http://127.0.0.1:4001
        - -initial-cluster-token
        - skydns-etcd
        volumeMounts:
        - name: etcd-storage
          mountPath: /var/etcd/data
      - name: kube2sky
        image: index.tenxcloud.com/google_containers/kube2sky:1.14
        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:
            cpu: 100m
            # Kube2sky watches all pods.
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 50Mi
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
            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: 30
          timeoutSeconds: 5
        args:
        # command = "/kube2sky"
        #特別注意
        #- -domain=cluster.local是錯誤的寫法
        #- -kube-master-url=http://192.168.121.143:8080是錯誤的設定
        #會導致CrashLoopBackOff的錯誤
        #如果已經進行CA認證,則可以不指定kube-master-url
        - --domain=cluster.local
        - --kube-master-url=http://192.168.121.143:8080
      - name: skydns
        image: index.tenxcloud.com/google_containers/skydns:2015-10-13-8c72f8c
        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:
            cpu: 100m
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 50Mi
        args:
        # command = "/skydns"
        - -machines=http://127.0.0.1:4001
        - -addr=0.0.0.0:53
        - -ns-rotate=false
        - -domain=cluster.local.
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
      - name: healthz
        image: index.tenxcloud.com/google_containers/exechealthz:1.0
        resources:
          # keep request = limit to keep this container in guaranteed class
          limits:
            cpu: 10m
            memory: 20Mi
          requests:
            cpu: 10m
            memory: 20Mi
        args:
        - -cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
        - -port=8080
        ports:
        - containerPort: 8080
          protocol: TCP
      volumes:
      - name: etcd-storage
        emptyDir: {}
      dnsPolicy: Default  # Don't use cluster DNS.

通過定義檔案dns-rc.yaml建立Cluster DNS Replication Controller

kubectl create -f dns-rc.yaml

驗證Cluster DNS Pod是否建立執行成功:

kubectl get pod --namespace=kube-system -o wide

這裡寫圖片描述

生成Service的定義檔案dns-svc.yaml建立Service

sed -e "s/{{ pillar\['dns_server'\] }}/${DNS_SERVER_IP}/g" \skydns-svc.yaml.in > dns-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 10.254.10.2
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP

根據dns-svc.yaml建立Cluster DNS Service

kubectl create -f dns-svc.yaml

查詢驗證Cluster DNS Service

kubectl get svc --namespace=kube-system -o wide

這裡寫圖片描述

建立Pod驗證Cluster DNS

使用一個帶有nslookup的工具來驗證DNS是否能夠正常工作:
busybox.yaml

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - name: busybox
    image: index.tenxcloud.com/google_containers/busybox
    command:
      - sleep
      - "3600"
#kubectl create -f busybox.yaml
#kubectl exec busybox -- nslookup kubernetes.default.svc.cluster.local

發現報錯

Error from server: error dialing backend: dial tcp 192.168.121.144:10250: getsockopt: connection refused

除錯解決該問題的過程:
1)在192.168.121.144上執行

ip addr

發現沒有flanneld網橋。
《kubernetes學習記錄(4)——建立kubernetes覆蓋網路》忘記設定flanneld開機自啟了,部落格中已修改。
重啟flanneld網橋,仍報錯。
(所以這裡flanneld是否需要開機自啟還不確定)
2)在Master上執行

#curl 192.168.121.144:10250
curl: (7) Failed connect to 192.168.121.144:10250; Connection refused

埠無法連線。
10250是kubelet的埠。
在Node上檢查/etc/kubernetes/kubelet。
經過多方對比和測試發現。
KUBELET_ADDRESS需要修改為node ip。
最終的/etc/kubernetes/kubelet內容(未經過CA驗證版)如下:

KUBELET_ADDRESS="--address=192.168.121.145"
# The port for the info server to serve on
# KUBELET_PORT="--port=10250"
# You may leave this blank to use the actual hostname
KUBELET_HOSTNAME="--hostname-override=192.168.121.145"
# location of the api-server
KUBELET_API_SERVER="--api-servers=http://192.168.121.143:8080"
# pod infrastructure container
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
# Add your own!
KUBELET_ARGS="--cluster_dns=10.254.10.2 --cluster_domain=cluster.local"

重啟kubelet。
最後重新執行

kubectl exec busybox -- nslookup kubernetes.default.svc.cluster.local

這裡寫圖片描述

總結

網上的各種安裝教程和配置教程多多少少都存在一些問題,不能完全相信書籍和教程,我的部落格裡估計也有很多的坑。慢慢學習中。