1. 程式人生 > >dashboard 1.8

dashboard 1.8

新版的dashboard在安全方面下了不少功夫,也提供了多種認證方式。以下就踩過的坑來進行一下介紹。

dashboard官方文件:

Installation

dashboard有兩個發行版本,offical和deployment. 這裡使用offical版本。

dashboard的安裝文件中提到了3中方式:
1. quick setup
快速安裝,但是隻能通過kubectl proxy的方式使用本機地址(localhost,127.0.0.1)來進行登入。
2. recommended setup
常規安裝,可以通過NodePortingress的方式訪問。
3. alternative setup
採用http協議訪問,出於安全性考慮,就沒使用這個了。

快速安裝和常規安裝幾乎一模一樣,唯一不同的是採用常規安裝的時候,需要先生成dashboard的伺服器端證書,然後通過configMap掛載到dashboard容器中。

第一步,生成證書:

mkdir certs && cd certs

openssl genrsa -out dashboard.key 2048

openssl req -new -key dashboard.key -out dashboard.csr -config dashboard-csr.conf

openssl x509 -req -in dashboard.
csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out dashboard.crt -days 1000 -extensions v3_ext -extfile dashboard-csr.conf

dashboard-csr.conf 檔案內容如下:

[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
C = CN
L
= SZ O = Fonsview CN = 172.16.6.79 [ req_ext ] subjectAltName = @alt_names [ alt_names ] DNS.1 = kubernetes-dashboard DNS.2 = kubernetes-dashboard.kube-system DNS.3 = kubernetes-dashboard.kube-system.svc DNS.4 = kubernetes-dashboard.kube-system.svc.cluster DNS.5 = kubernetes-dashboard.kube-system.svc.cluster.local DNS.6 = dashboard.k8s.fonsview.com IP.1 = 172.16.6.79 IP.2 = 172.16.6.47 IP.3 = 172.16.6.249 [ v3_ext ] authorityKeyIdentifier=keyid,issuer:always basicConstraints=CA:FALSE keyUsage=keyEncipherment,dataEncipherment extendedKeyUsage=serverAuth,clientAuth subjectAltName[email protected]_names

這裡我直接使用了kubernetes 裡面的ca證書,用瀏覽器訪問的時候會提示該網站證書不可靠. 官方推薦是去Let’s Encrypt 網站中生成自己的證書。

將建立好的證書,新增到Secret中.

kubectl create secret generic kubernetes-dashboard-certs --from-file=./certs -n kube-system

修改kubernetes-dashboard的yaml檔案:

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: gcr.io/google_containers/kubernetes-dashboard-amd64:v1.8.0
        ports:
        - containerPort: 8443
          protocol: TCP
        args:
          # - --auto-generate-certificates
          - --tls-key-file=dashboard.key
          - --tls-cert-file=dashboard.crt
          - --authentication-mode=basic
          # 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

新增--tls-key-file--tls-cert-file.

如果要採用使用者名稱和密碼的認證形式,需要加上--authentication-mode=basic。 預設是使用token認證。

Note: 這裡要注意證書的路徑

然後執行

kubectl apply -f kubernetes-dashboard.yaml

不出意外的話,可以用命令看到pod能正常啟動:

[root@walker-1 kubernetes]# kubectl get po -o wide --namespace=kube-system | grep dashboard
kubernetes-dashboard-68b6699b8-mrvfl         1/1       Running   0          5s        192.168.187.202   walker-1.novalocal

訪問dashboard

修改dashboard的service, 改為NodePort的訪問形式

[[email protected]1 kubernetes]# kubectl describe svc kubernetes-dashboard -n kube-system
Name:                     kubernetes-dashboard
Namespace:                kube-system
Labels:                   k8s-app=kubernetes-dashboard
Annotations:              kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"k8s-app":"kubernetes-dashboard"},"name":"kubernetes-dashboard","namespace":...
Selector:                 k8s-app=kubernetes-dashboard
Type:                     NodePort
IP:                       10.103.175.251
Port:                     <unset>  443/TCP
TargetPort:               8443/TCP
NodePort:                 <unset>  32723/TCP
Endpoints:                192.168.187.202:8443
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

至此就可以通過 https://<nodeip>:<nodeport> 的方式來訪問dashboard了

image

官網上還提及了通過apiserver和kubectl proxy 的方式來訪問頁面。據個人實際使用,kubectl proxy預設監聽127.0.0.1。只能通過本地地址去訪問。當然可以繫結到其他地址,但是頁面無法進行登入操作。這在文件中有描述:

NOTE: Dashboard should not be exposed publicly using kubectl proxy command as it only allows HTTP connection. For domains other than localhost and 127.0.0.1 it will not be possible to sign in. Nothing will happen after clicking Sign in button on login page.

通過apiserver埠來訪問時,會出現403許可權問題。提示是以匿名使用者身份訪問的,許可權拒絕。但是要讓瀏覽器支援提供身份請求顯然不現實,所以也放棄了。

為使用者授權

如果使用token的認證方式來登入,也是可行的。不過需要為service account新增合適的許可權。如果想直接跳過認證,那麼預設是以kubernetes-dashboard的service account賬戶來訪問。如果不做配置,kubernetes-dashboard 只能訪問很少一部分資源。官方文件中提供了將所有許可權賦予kubernetes-dashboard的配置。

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

將使用者繫結到 cluster-admin許可權組。這樣一來kubernetes-dashboard就能訪問平臺所有資源。這樣做很方便,但有安全風險,不建議。

token認證方案已經很好了,但是大佬們顯然更傾向使用賬戶+密碼的方式認證。具體配置步驟如下:

  1. 在dashboard的deployment配置中,新增 --authentication-mode=basic
  2. 修改apiserver的配置,在啟動引數中新增密碼檔案、ABAC認證以及指定ABAC策略檔案。

    • 編輯密碼檔案
      密碼檔案的格式如下:
password,user,uid,"group1, group2..."

為了方便起見,我建立了/etc/kubernetes/dashboard 資料夾

[root@walker-1 ~]# cd /etc/kubernetes/dashboard/
[root@walker-1 dashboard]# cat dashboard.basic 
password,walker,123123,system:authenticated

Note: 一定要為使用者新增system:authenticated組,否則預設為system:unauthenticated組,使用者被視為匿名使用者,喪失訪問許可權。

  • 編輯ABAC策略檔案
[root@walker-1 dashboard]# cat dashboard-abac.json 
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "walker", "namespace": "*", "resource": "*", "apiGroup": "*"}}

這裡把所有許可權放開給walker使用者。

Note: 策略檔案中的使用者名稱要和密碼檔案對應。

  • 修改apiserver配置
apiVersion: v1
kind: Pod
metadata:
  annotations:
    scheduler.alpha.kubernetes.io/critical-pod: ""
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    - --service-cluster-ip-range=10.96.0.0/12
    - --service-account-key-file=/etc/kubernetes/pki/sa.pub
    - --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
    - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
    - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
    - --enable-bootstrap-token-auth=true
    - --admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota
    - --advertise-address=172.16.6.47
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
    - --insecure-port=0
    - --requestheader-username-headers=X-Remote-User
    - --requestheader-extra-headers-prefix=X-Remote-Extra-
    - --requestheader-allowed-names=front-proxy-client
    - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
    - --allow-privileged=true
    - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
    - --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
    - --secure-port=6443
    - --requestheader-group-headers=X-Remote-Group
    - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
    - --authorization-mode=Node,RBAC,ABAC
    - --authorization-policy-file=/etc/kubernetes/dashboard/dashboard-abac.json
    - --basic-auth-file=/etc/kubernetes/dashboard/dashboard.basic
    - --etcd-servers=http://walker-1:2379,http://walker-2:2379,http://walker-4:2379
    image: gcr.io/google_containers/kube-apiserver-amd64:v1.8.1
    livenessProbe:
      failureThreshold: 8
      httpGet:
        host: 127.0.0.1
        path: /healthz
        port: 6443
        scheme: HTTPS
      initialDelaySeconds: 15
      timeoutSeconds: 15
    name: kube-apiserver
    resources:
      requests:
        cpu: 250m
    volumeMounts:
    - mountPath: /etc/kubernetes/pki
      name: k8s-certs
      readOnly: true
    - mountPath: /etc/kubernetes/dashboard
      name: k8s-dashboard
      readOnly: true
    - mountPath: /etc/ssl/certs
      name: ca-certs
      readOnly: true
    - mountPath: /etc/pki
      name: ca-certs-etc-pki
      readOnly: true
  hostNetwork: true
  volumes:
  - hostPath:
      path: /etc/kubernetes/pki
      type: DirectoryOrCreate
    name: k8s-certs
  - hostPath:
      path: /etc/kubernetes/dashboard
      type: DirectoryOrCreate
    name: k8s-dashboard
  - hostPath:
      path: /etc/ssl/certs
      type: DirectoryOrCreate
    name: ca-certs
  - hostPath:
      path: /etc/pki
      type: DirectoryOrCreate
    name: ca-certs-etc-pki
status: {}

添加了ABAC認證方式,--authorization-policy-file以及--basic-auth-file。將/etc/kubernetes/dashboard 掛載到容器中。

  1. 重啟apiserver, 使用新增的使用者進行訪問。
    先使用一個錯誤的密碼試試認證有沒有生效:

image

在使用正確密碼登入:

image

至此密碼認證方式配置完畢。