從零開始搭建Kubernetes集群(四、搭建K8S Dashboard)

一、前言

前面三篇文章介紹了如何從零開始搭建一個基本的Kubernetes集群,本文將介紹一下如何搭建K8S的Dashboard。

簡單的說,K8S Dashboard是官方的一個基于WEB的用戶界面,專門用來管理K8S集群,并可展示集群的狀態。K8S集群安裝好后默認沒有包含Dashboard,我們需要額外創建它。

本人覺得Dashboard設計的還不錯,界面友好,功能也比較強大。如果你厭倦了命令行的操作,全程使用Dashboard也是可行的。

Dashboard的搭建過程中,會遇到一些坑。現在開始,咱們一步一步踩來,走你!

二、RABC簡介

還是那句話,官方文檔是最重要的參考資料:https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/
該文檔中,創建kubernetes-dashboard的命令為:
kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml
當然,直接這樣創建的dashboard會有很多問題,參見:

Please note, this works only if the apiserver is set up to allow authentication with username and password. This is not currently the case with some setup tools (e.g., kubeadm). Refer to the authentication admin documentation for information on how to configure authentication manually.

因為我們使用kubeadm搭建的集群會默認開啟RABC(角色訪問控制機制),所以我們必須要進行額外的設置。關于RABC的概念,網上資料很多,大家務必提前了解。這里簡要介紹一下幾個重要概念:

  • RBAC
    K8S 1.6引進,是讓用戶能夠訪問 k8S API 資源的授權方式【不授權就沒有資格訪問K8S的資源】
  • 用戶
    K8S有兩種用戶:User和Service Account。其中,User給人用,Service Account給進程用,讓進程有相關權限。如Dashboard就是一個進程,我們就可以創建一個Service Account給它
  • 角色
    Role是一系列權限的集合,例如一個Role可包含讀取和列出 Pod的權限【 ClusterRole 和 Role 類似,其權限范圍是整個集群】
  • 角色綁定
    RoleBinding把角色映射到用戶,從而讓這些用戶擁有該角色的權限【ClusterRoleBinding 和RoleBinding 類似,可讓用戶擁有 ClusterRole 的權限】
  • Secret
    Secret是一個包含少量敏感信息如密碼,令牌,或秘鑰的對象。把這些信息保存在 Secret對象中,可以在這些信息被使用時加以控制,并可以降低信息泄露的風險

如下圖,灰色是“角色”,藍色是“用戶”,綠色是“角色綁定”,黃色是該角色擁有的權限。簡言之 ,角色綁定角色用戶進行掛鉤:

image.png

三、官方kubernetes-dashboard.yaml簡介

很有必要介紹一下官方的kubernetes-dashboard.yaml,我們首先將其下載下來:
wget https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

該文件分為以下幾部分:

  1. Dashboard Service
  2. Dashboard Deployment
  3. Dashboard Role
  4. RoleBinding
  5. Dashboard Service Account
  6. Dashboard Secret

這里,我們簡單的對各個部分的功能進行介紹:

Dashboard Role

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: kubernetes-dashboard-minimal
  namespace: kube-system
rules:
  # Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret.
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["create"]
  # Allow Dashboard to create 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["create"]
  # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
- apiGroups: [""]
  resources: ["secrets"]
  resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"]
  verbs: ["get", "update", "delete"]
  # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["kubernetes-dashboard-settings"]
  verbs: ["get", "update"]
  # Allow Dashboard to get metrics from heapster.
- apiGroups: [""]
  resources: ["services"]
  resourceNames: ["heapster"]
  verbs: ["proxy"]
- apiGroups: [""]
  resources: ["services/proxy"]
  resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
  verbs: ["get"]

如上定義了Dashboard 的角色,其角色名稱為kubernetes-dashboard-minimalrules中清晰的列出了其擁有的多個權限。通過名稱我們可以猜到,這個權限級別是比較低的。

ServiceAccount

kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system

如上定義了Dashboard的用戶,其類型為ServiceAccount,名稱為kubernetes-dashboard

RoleBinding

kind: RoleBinding
metadata:
  name: kubernetes-dashboard-minimal
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kubernetes-dashboard-minimal
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kube-system

如上定義了Dashboard的角色綁定,其名稱為kubernetes-dashboard-minimal,roleRef中為被綁定的角色,也叫kubernetes-dashboard-minimalsubjects中為綁定的用戶:kubernetes-dashboard

Dashboard Secret

kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-certs
  namespace: kube-system
type: Opaque

Dashboard Deployment

kind: Deployment
apiVersion: apps/v1beta2
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kubernetes-dashboard
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
    spec:
      containers:
      - name: kubernetes-dashboard
        image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3
        ports:
        - containerPort: 8443
          protocol: TCP
        args:
          - --auto-generate-certificates
          # Uncomment the following line to manually specify Kubernetes API server Host
          # If not specified, Dashboard will attempt to auto discover the API server and connect
          # to it. Uncomment only if the default does not work.
          # - --apiserver-host=http://my-address:port
        volumeMounts:
        - name: kubernetes-dashboard-certs
          mountPath: /certs
          # Create on-disk volume to store exec logs
        - mountPath: /tmp
          name: tmp-volume
        livenessProbe:
          httpGet:
            scheme: HTTPS
            path: /
            port: 8443
          initialDelaySeconds: 30
          timeoutSeconds: 30
      volumes:
      - name: kubernetes-dashboard-certs
        secret:
          secretName: kubernetes-dashboard-certs
      - name: tmp-volume
        emptyDir: {}
      serviceAccountName: kubernetes-dashboard
      # Comment the following tolerations if Dashboard must not be deployed on master
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule

如上可以看到,Dashboard的Deployment指定了其使用的ServiceAccount是kubernetes-dashboard。并且還將Secret kubernetes-dashboard-certs通過volumes掛在到pod內部的/certs路徑。為何要掛載Secret ?原因是創建Secret 時會自動生成token。請注意參數--auto-generate-certificates,其表示Dashboard會自動生成證書。

四、安裝Dashboard

1.導入鏡像

如果直接使用官方的kubernetes-dashboard.yaml創建Dashboard,你會踩到很多坑,首先是鏡像拉取會超時失敗。截止目前,Dashboard的最新版本是1.8.3,我已經將鏡像k8s.gcr.io#kubernetes-dashboard-amd64.tar導出,提供給大家:
鏈接:https://pan.baidu.com/s/11AheivJxFzc4X6Q5_qCw8A 密碼:2zov

在所有節點上(因為你不知道K8S會將Dashboard的pod調度到哪個節點),使用如下命令導入鏡像:
docker load < k8s.gcr.io#kubernetes-dashboard-amd64.tar
導入成功后,執行docker images可以看到Dashboard的版本是1.8.3:

image.png

2.創建Dashboard

導入鏡像后,使用之前下載的yaml文件即可創建Dashboard:
kubectl create -f kubernetes-dashboard.yaml

3.訪問Dashboard

根據官方文檔,目前訪問Dashboard有四種方式:

  • NodePort
  • API Server
  • kubectl proxy
  • Ingress

以上四種方式,我測試了前三種,目前只有NodePort和kubectl proxy可用,API Server暫時沒有解決。

使用NodePort
為kubernetes-dashboard.yaml添加Service后,就可以使用NodePort訪問Dashboard。在我們的物理機上,使用Chrome訪問https://192.168.56.101:32159/,結果如下圖所示:

image.png

如上可以看到,這里提示了證書錯誤NET::ERR_CERT_INVALID,原因是由于物理機的瀏覽器證書不可用。但是,不要放棄,我們這里不打算使用物理機訪問瀏覽器,而使用Dashboard所在節點上的瀏覽器來訪問(即CentOS自帶的瀏覽器),這樣的證書應該是可行的(官方默認就是這種方式)。

由于之前建立虛擬機環境時,我們關閉了CentOS的圖形界面,這里我們為了訪問Dashboard臨時開啟,執行:systemctl set-default graphical.target。重啟后,即可進入圖形界面。我們用Firefox訪問:https://192.168.56.101:32159/,成功后出現如下界面:

image.png

需要注意的是,若提示“連接不安全”的警告時,點擊“高級”,點擊“添加例外”后即可:


image.png

image.png

使用API Server
在我們的物理機上,使用Chrome訪問地址:https://192.168.56.101:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/,返回如下錯誤:

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "services \"https:kubernetes-dashboard:\" is forbidden: User \"system:anonymous\" cannot get services/proxy in the namespace \"kube-system\"",
  "reason": "Forbidden",
  "details": {
    "name": "https:kubernetes-dashboard:",
    "kind": "services"
  },
  "code": 403
}

原因是由于kube-apiserver使用了TLS認證,而我們的真實物理機上的瀏覽器使用匿名證書(因為沒有可用的證書)去訪問Dashboard,導致授權失敗而不無法訪問。官方提供的解決方法是將kubelet的證書轉化為瀏覽器可用的證書,然后導入進瀏覽器。

Note: This way of accessing Dashboard is only possible if you choose to install your user certificates in the browser. In example certificates used by kubeconfig file to contact API Server can be used.

但是該方法目前似乎不適用于kubeadm方式安裝的集群,參見:https://github.com/opsnull/follow-me-install-kubernetes-cluster/issues/5

那如果使用節點自帶的Firefox呢?我們在Firefox中訪問:https://192.168.56.101:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/,仍然提示上面的錯誤:

image.png

看來,無論物理機還是K8S節點上的瀏覽器,都需要導入這個證書,暫時無解。

使用kubectl proxy
這里,我主要介紹一下最便捷的kubectl proxy方式。在Master上執行kubecll proxy,然后使用如下地址訪問Dashboard:
http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy
但限制就是必須在Master上訪問,這顯然是個坑,我們的目標是在我們真實的物理機上去訪問Master的Dashboard。

所以,在主節點上,我們執行kubectl proxy --address=192.168.56.101 --disable-filter=true開啟代理。
其中:

  • address表示外界可以使用192.168.56.101來訪問Dashboard,我們也可以使用0.0.0.0
  • disable-filter=true表示禁用請求過濾功能,否則我們的請求會被拒絕,并提示 Forbidden (403) Unauthorized
  • 我們也可以指定端口,具體請查看kubectl proxy --help

如下圖所示,proxy默認對Master的8001端口進行監聽:


image.png

這樣,我們就可以使用如下地址訪問登錄界面:
http://192.168.56.101:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login

image.png

4.配置Dashboard

Dashboard的配置是難點,尤其是涉及到安全權限相關,相當復雜,坑也比較多。

進入Dashboard的登錄界面后,認證方式有Kubeconfig和令牌兩種方式(實際上還有賬號密碼的方式,默認不開啟不顯示)。看到Kubeconfig和令牌,估計頭都大了。是否有簡便的方法,讓我們能直接訪問Dashboard?當然有,選擇跳過,會出現如下頁面:

image.png

如上圖,很遺憾,我們看到了很多權限錯誤提示,主要是system:serviceaccount:kube-system:kubernetes-dashboard的權限不足引起的。

我們回想本文第三小節對kubernetes-dashboard.yaml的介紹,現在就理解了為什么其角色的名稱為kubernetes-dashboard-minimal。一句話,這個Role的權限不夠!

因此,我們可以更改RoleBinding修改為ClusterRoleBinding,并且修改roleRef中的kindname,使用cluster-admin這個非常牛逼的CusterRole(超級用戶權限,其擁有訪問kube-apiserver的所有權限)。如下:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard-minimal
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kube-system

修改后,重新創建kubernetes-dashboard.yaml,Dashboard就可以擁有訪問整個K8S 集群API的權限。我們重新訪問Dashboard,如下圖所示:

image.png

如上,一切正常,請在界面上盡情的亂點吧。另外,如果有興趣,你還可以安裝Dashboard的Heapster插件,這里就不再介紹了。

八、廢話

到目前為止,我們的K8S的Dashboard就真正搭建完畢了,下一章節《從零開始搭建Kubernetes集群(五、搭建K8S Ingress)》,敬請期待。

本人水平有限,難免有錯誤或遺漏之處,望大家指正和諒解,歡迎評論留言。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容