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
常規安裝,可以通過NodePort
和ingress
的方式訪問。
3. alternative setup
採用http協議訪問,出於安全性考慮,就沒使用這個了。
快速安裝和常規安裝幾乎一模一樣,唯一不同的是採用常規安裝的時候,需要先生成dashboard的伺服器端證書,然後通過configMap
掛載到dashboard容器中。
Recommended setup
第一步,生成證書:
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了
官網上還提及了通過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認證方案已經很好了,但是大佬們顯然更傾向使用賬戶+密碼的方式認證。具體配置步驟如下:
- 在dashboard的deployment配置中,新增
--authentication-mode=basic
修改
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 掛載到容器中。
- 重啟apiserver, 使用新增的使用者進行訪問。
先使用一個錯誤的密碼試試認證有沒有生效:
在使用正確密碼登入:
至此密碼認證方式配置完畢。