這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
第一次利用kube-up.sh指令碼方式安裝Kubernetes 1.3.7叢集時,我就已經順利地將kubernetes dashboard addon安裝ok了。至今在這個環境下運行十分穩定。但是畢竟是一個實驗環境,有些配置是無法滿足生產環境要求的,比如:安全問題。今天有時間對Dashboard的配置進行一些調整,順帶將之前Dashboard外掛程式的安裝和配置過程也記錄下來,供大家參考。
一、Dashboard的預設安裝步驟
1、基於預設配置項的安裝
採用kube-up.sh在Ubuntu上安裝dashboard的原理與安裝DNS外掛程式大同小異,主要涉及的指令檔和配置項包括:
// kubernetes/cluster/config-default.sh... ...# Optional: Install Kubernetes UIENABLE_CLUSTER_UI="${KUBE_ENABLE_CLUSTER_UI:-true}"... ...// kubernetes/cluster/ubuntu/deployAddons.sh... ...function deploy_dashboard { if ${KUBECTL} get rc -l k8s-app=kubernetes-dashboard --namespace=kube-system | grep kubernetes-dashboard-v &> /dev/null; then echo "Kubernetes Dashboard replicationController already exists" else echo "Creating Kubernetes Dashboard replicationController" ${KUBECTL} create -f ${KUBE_ROOT}/cluster/addons/dashboard/dashboard-controller.yaml fi if ${KUBECTL} get service/kubernetes-dashboard --namespace=kube-system &> /dev/null; then echo "Kubernetes Dashboard service already exists" else echo "Creating Kubernetes Dashboard service" ${KUBECTL} create -f ${KUBE_ROOT}/cluster/addons/dashboard/dashboard-service.yaml fi echo}init... ...if [ "${ENABLE_CLUSTER_UI}" == true ]; then deploy_dashboardfi
kube-up.sh會嘗試建立”kube-system” namespace,並執行下面命令:
kubectl create -f kubernetes/cluster/addons/dashboard/dashboard-controller.yamlkubectl create -f kubernetes/cluster/addons/dashboard/dashboard-service.yaml
這和我們在cluster中建立一個rc和service沒有多大區別。
當然上面的安裝方式是伴隨著k8s cluster的安裝進行的,如果要單獨安裝Dashboard,那麼Dashboard首頁上的安裝方式顯然更為簡單:
kubectl create -f https://rawgit.com/kubernetes/dashboard/master/src/deploy/kubernetes-dashboard.yaml
2、調整Dashboard容器啟動參數
dashboard-controller.yaml和dashboard-service.yaml兩個檔案內容如下:
//dashboard-controller.yamlapiVersion: v1kind: ReplicationControllermetadata: name: kubernetes-dashboard-v1.1.1 namespace: kube-system labels: k8s-app: kubernetes-dashboard version: v1.1.1 kubernetes.io/cluster-service: "true"spec: replicas: 1 selector: k8s-app: kubernetes-dashboard template: metadata: labels: k8s-app: kubernetes-dashboard version: v1.1.1 kubernetes.io/cluster-service: "true" spec: containers: - name: kubernetes-dashboard image: gcr.io/google_containers/kubernetes-dashboard-amd64:v1.1.1 resources: # keep request = limit to keep this container in guaranteed class limits: cpu: 100m memory: 50Mi requests: cpu: 100m memory: 50Mi ports: - containerPort: 9090 livenessProbe: httpGet: path: / port: 9090 initialDelaySeconds: 30 timeoutSeconds: 30// dashboard-service.yamlapiVersion: v1kind: Servicemetadata: name: kubernetes-dashboard namespace: kube-system labels: k8s-app: kubernetes-dashboard kubernetes.io/cluster-service: "true"spec: selector: k8s-app: kubernetes-dashboard ports: - port: 80 targetPort: 9090
這兩個檔案的內容略微陳舊些,用的還是目前已不推薦使用的ReplicationController。
不過這樣預設安裝後,你可能還會遇到如下問題:
(1) Dashboard pod建立失敗:這是由於kubernetes-dashboard-amd64:v1.1.1 image在牆外,pull image失敗導致的。
可以通過使用加速器或使用替代image的方式來解決,比如:mritd/kubernetes-dashboard-amd64:v1.4.0。修改一下dashboard-controller.yaml中image那一行即可。
(2)Dashboard無法串連到master node上的api server
如果唯一的dashboard pod(由於replicas=1)被調度到minion node上,那麼很可能無法串連上master node上api server(dashboard會在cluster中自動檢測api server的存在,但有時候會失敗),導致頁面無法正常顯示。因此,需要指定一下api server的url,比如:我們在dashboard-controller.yaml中為container啟動增加一個啟動參數–apiserver-host:
// dashboard-controller.yaml... ...spec: containers: - name: kubernetes-dashboard image: mritd/kubernetes-dashboard-amd64:v1.4.0 imagePullPolicy: Always ports: - containerPort: 9090 protocol: TCP args: - --apiserver-host=http://{api server host}:{api server insecure-port}... ...
(3)增加nodeport,提供外部存取路徑
dashboard以cluster service的角色運行在cluster中,我們雖然可以在Node上訪問該service或直接存取pod,但要想在外部網路訪問到dashboard,還需要另外設定,比如:設定nodeport。
在dashboard-service.yaml中,修改配置如下:
spec: type: NodePort ports: - port: 80 targetPort: 9090 nodePort: 12345
這樣你就可以通過node 的public ip+nodeport訪問到dashboard了。
不過這時,你的dashboard算是在“裸奔”,沒有任何安全可言:
- dashboard ui沒有訪問管理機制,任何access都可以全面接管dashboard;
- 同時在背後,dashboard通過insecure-port訪問apiserver,沒有使用加密機制。
二、dashboard通過kubeconfig檔案資訊訪問apiserver
我們先來建立dashboard和apiserver之間的安全通訊機制。
當前master上的kube-apiserver的啟動參數如下:
// /etc/default/kube-apiserverKUBE_APISERVER_OPTS=" --insecure-bind-address=0.0.0.0 --insecure-port=8080 --etcd-servers=http://127.0.0.1:4001 --logtostderr=true --service-cluster-ip-range=192.168.3.0/24 --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,SecurityContextDeny,ResourceQuota --service-node-port-range=80-32767 --advertise-address={master node local ip} --basic-auth-file=/srv/kubernetes/basic_auth_file --client-ca-file=/srv/kubernetes/ca.crt --tls-cert-file=/srv/kubernetes/server.cert --tls-private-key-file=/srv/kubernetes/server.key"
dashboard要與apiserver建立安全通訊機制,務必不能使用insecure port。kubernetes apiserver預設情況下secure port也是開啟的,連接埠為6443。同時,apiserver開啟了basic auth(–basic-auth-file=/srv/kubernetes/basic_auth_file)。這樣一來,dashboard光靠傳入的–apiserver-host參數將無法正常訪問apiserver的secure port並通過basic auth。我們需要找到另外一個option:
我們來看一下dashboard還支援哪些cmdline options:
# docker run mritd/kubernetes-dashboard-amd64:v1.4.0 /dashboard -helpUsage of /dashboard: --alsologtostderr value log to standard error as well as files --apiserver-host string The address of the Kubernetes Apiserver to connect to in the format of protocol://address:port, e.g., http://localhost:8080. If not specified, the assumption is that the binary runs inside aKubernetes cluster and local discovery is attempted. --heapster-host string The address of the Heapster Apiserver to connect to in the format of protocol://address:port, e.g., http://localhost:8082. If not specified, the assumption is that the binary runs inside aKubernetes cluster and service proxy will be used. --kubeconfig string Path to kubeconfig file with authorization and master location information. --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s) --log_backtrace_at value when logging hits line file:N, emit a stack trace (default :0) --log_dir value If non-empty, write log files in this directory --logtostderr value log to standard error instead of files (default true) --port int The port to listen to for incoming HTTP requests (default 9090) --stderrthreshold value logs at or above this threshold go to stderr (default 2) -v, --v value log level for V logs --vmodule value comma-separated list of pattern=N settings for file-filtered logging
從輸出的options來看,只有–kubeconfig這個能夠滿足需求。
1、kubeconfig檔案介紹
採用kube-up.sh指令碼進行kubernetes預設安裝後,指令碼會在每個Cluster node上建立一個~/.kube/config檔案,該kubeconfig檔案可為k8s cluster中的組件(比如kubectl等)、addons(比如dashboard等)提供跨全cluster的安全驗證機制。
下面是我的minion node上的kubeconfig檔案
# cat ~/.kube/configapiVersion: v1clusters:- cluster: certificate-authority: /srv/kubernetes/ca.crt server: https://{master node local ip}:6443 name: ubuntucontexts:- context: cluster: ubuntu namespace: default user: admin name: ubuntucurrent-context: ubuntukind: Configpreferences: {}users:- name: admin user: password: {apiserver_password} username: {apiserver_username} client-certificate: /srv/kubernetes/kubecfg.crt client-key: /srv/kubernetes/kubecfg.key
kubeconfig中儲存了clusters、users、contexts資訊,以及其他一些雜項,並通過current-context指定當前context。通過該設定檔,類似kubectl這樣的cluster操作工具可以很容易的在各個cluster之間切換context。一個context就是一個三元組:{cluster、user、namespace},current-context指定當前選定的context,比如上面的kubeconfig檔案,當我們執行kubectl時,kubectl會讀取該設定檔,並以current-context指定的那個context中的資訊去尋找user和cluster。這裡current-context是ubuntu。
ubuntu這個context三元組中的資訊是:
{ cluster = ubuntu namespace = default user = admin}
之後kubectl到clusters中找到name為ubuntu的cluster,發現其server為https://{master node local ip}:6443,以及其CA資訊;到users中找到name為admin的user,並使用該user下的資訊:
password: {apiserver_password} username: {apiserver_username} client-certificate: /srv/kubernetes/kubecfg.crt client-key: /srv/kubernetes/kubecfg.key
通過kubectl config命令可以配置kubeconfig檔案,具體命令可以參考這裡。
另外上面的/srv/kubernetes/ca.crt、/srv/kubernetes/kubecfg.crt和/srv/kubernetes/kubecfg.key都是kube-up.sh在安裝k8s 1.3.7時在各個node上建立的,可以直接用來作為訪問apiserver的參數傳遞給kubectl或其他要訪問apiserver的組件或addons。
2、修改dashboard啟動參數,使用kubeconfig檔案
現在我們要讓dashboard使用kubeconfig檔案,我們需要修改dashboard-controller.yaml檔案中涉及containers的配置資訊:
spec: containers: - name: kubernetes-dashboard image: mritd/kubernetes-dashboard-amd64:v1.4.0 volumeMounts: - mountPath: /srv/kubernetes name: auth - mountPath: /root/.kube name: config imagePullPolicy: Always ports: - containerPort: 9090 protocol: TCP args: - --kubeconfig=/root/.kube/config livenessProbe: httpGet: path: / port: 9090 initialDelaySeconds: 30 timeoutSeconds: 30 volumes: - name: auth hostPath: path: /srv/kubernetes - name: config hostPath: path: /root/.kube
由於要用到各種認證以及kubeconfig,我們在pod裡掛載了host主機的path: /root/.kube和/srv/kubernetes。
重新部署dashboard後,dashboard與kube-apiserver之間就有了安全保障了(https+basic_auth)。
三、實現dashboard UI login
雖然上面實現了dashboard與apiserver之間的安全通道和basic auth,但通過nodeport方式訪問dashboard,我們依舊可以掌控dashboard,而dashboard依舊沒有任何存取控制機制。而實際情況是dashboard目前還不支援identity and access management,不過在不久的將來,dashboard將添加這方面的支援。
那麼在目前的版本下,如何?一個簡易的login流程呢?除了前面提到的nodeport方式訪問dashboard UI外,官方在trouble shooting裡還提供了另外兩種訪問dashboard的方法,我們一起來看看是否能滿足我們的最低級需求^0^。
1、kubectl proxy方式
kubectl proxy的方式預設只允許local network訪問,但是kubectl proxy提供了若干flag options可以設定,我們來試試:
我們在minion node上執行:
# kubectl proxy --address='0.0.0.0' --port=30099Starting to serve on [::]:30099
我們在minion node上的30099連接埠提供外網服務。開啟瀏覽器,訪問: http://{minion node public ip}:30099/ui,得到如下結果:
Unauthorized
到底哪沒授權呢?我們查看kubectl proxy的flag options發現下面一個疑點:
--accept-hosts='^localhost$,^127\.0\.0\.1$,^\[::1\]$': Regular expression for hosts that the proxy should accept.
顯然–accept-hosts預設接受的host地址形式讓我們的訪問受限。重新調整配置再次執行:
# kubectl proxy --address='0.0.0.0' --port=30099 --accept-hosts='^*$'Starting to serve on [::]:30099
再次開啟瀏覽器,訪問:http://{minion node public ip}:30099/ui
瀏覽器會跳轉至下面的地址:
http://{minion node public ip}:30099/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard/#/workload?namespace=default
dashboard ui訪問成功!不過,這種方式依舊無需你輸入user/password,這不符合我們的要求。
2、直接存取apiserver方式
trouble shooting文檔提供的最後一種訪問方式是直接存取apiserver方式:
開啟瀏覽器訪問:https://{master node public ip}:6443
這時瀏覽器會提示你:認證問題。忽略之(由於apiserver採用的是自簽署的私人認證,瀏覽器端無法驗證apiserver的server.crt),繼續訪問,瀏覽器彈出登入對話方塊,讓你輸入使用者名稱和密碼,這裡我們輸入apiserver —basic-auth-file中的使用者名稱和密碼,就可以成功登入apiserver,並在瀏覽器頁面看到如下內容:
{ "paths": [ "/api", "/api/v1", "/apis", "/apis/apps", "/apis/apps/v1alpha1", "/apis/autoscaling", "/apis/autoscaling/v1", "/apis/batch", "/apis/batch/v1", "/apis/batch/v2alpha1", "/apis/extensions", "/apis/extensions/v1beta1", "/apis/policy", "/apis/policy/v1alpha1", "/apis/rbac.authorization.k8s.io", "/apis/rbac.authorization.k8s.io/v1alpha1", "/healthz", "/healthz/ping", "/logs/", "/metrics", "/swaggerapi/", "/ui/", "/version" ]}
接下來,我們訪問下面地址:
https://{master node public ip}:6443/ui
你會看到頁面跳轉到:
https://101.201.78.51:6443/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard/
我們成功進入dashboard UI中! 顯然這種訪問方式滿足了我們對dashboard UI採用登入訪問的最低需求!
三、小結
到目前為止,dashboard已經可以使用。但它還缺少metric和類儀錶盤圖形展示功能,這兩個功能需要額外安裝Heapster才能實現,不過一般功能足以滿足你對k8s cluster的管理需求。
2017, bigwhite. 著作權.