上一節安裝了一個基礎版的k8s叢集,現在加上認證授權的部分。
Kubernetes叢集的所有操作基本上都是通過kube-apiserver這個元件進行的,它提供HTTP RESTful形式的API供叢集內外用戶端呼叫。需要注意的是:認證授權過程只存在HTTPS形式的API中。也就是說,如果用戶端使用HTTP連線到kube-apiserver,那麼是不會進行認證授權的。所以說,可以這麼設定,在叢集內部元件間通訊使用HTTP,叢集外部就使用HTTPS,這樣既增加了安全性,也不至於太複雜。
對APIServer的存取要經過的三個步驟,前面兩個是認證和授權,第三個是 Admission Control,它也能在一定程度上提高安全性,不過更多是資源管理方面的作用。
kubernetes提供了多種認證方式,比如用戶端證書、靜態token、靜態密碼檔案、ServiceAccountTokens等等。你可以同時使用一種或多種認證方式。只要通過任何一個都被認作是認證通過。下面 下麪我們就認識幾個常見的認證方式。
在Kubernetes1.6版本中新增角色存取控制機制 機製(Role-Based Access,RBAC)讓叢集管理員可以針對特定使用者或服務賬號的角色,進行更精確的資源存取控制。在RBAC中,許可權與角色相關聯,使用者通過成爲適當角色的成員而得到這些角色的許可權。這就極大地簡化了許可權的管理。在一個組織中,角色是爲了完成各種工作而創造,使用者則依據它的責任和資格來被指派相應的角色,使用者可以很容易地從一個角色被指派到另一個角色。 目前 Kubernetes 中有一系列的鑑權機制 機製,因爲Kubernetes社羣的投入和偏好,相對於其它鑑權機制 機製而言,RBAC是更好的選擇。具體RBAC是如何體現在kubernetes系統中的我們會在後面的部署中逐步的深入瞭解。
AdmissionControl - 準入控制本質上爲一段準入程式碼,在對kubernetes api的請求過程中,順序爲:先經過認證 & 授權,然後執行準入操作,最後對目標物件進行操作。這個準入程式碼在api-server中,而且必須被編譯到二進制檔案中才能 纔能被執行。 在對叢集進行請求時,每個準入控制程式碼都按照一定順序執行。如果有一個準入控制拒絕了此次請求,那麼整個請求的結果將會立即返回,並提示使用者相應的error資訊。 常用元件(控制程式碼)如下:
開始之前我們要先把基礎版本的叢集停掉,包括service,deployments,pods以及執行的所有kubernetes元件
#刪除services
kubectl delete services nginx-service
#刪除deployments
kubectl delete deploy kubernetes-bootcamp
kubectl delete deploy nginx-deployment
#停掉worker節點的服務
service kubelet stop && rm -fr /var/lib/kubelet/*
service kube-proxy stop && rm -fr /var/lib/kube-proxy/*
service kube-calico stop
#停掉master節點的服務
service kube-calico stop
service kube-scheduler stop
service kube-controller-manager stop
service kube-apiserver stop
service etcd stop && rm -fr /var/lib/etcd/*
跟基礎環境搭建一樣,我們需要生成kubernetes-with-ca的所有相關組態檔
cd /home/kubernetes-starter-master
#按照組態檔的提示編輯好設定
$ vi config.properties
#生成設定
$ ./gen-config.sh with-ca
cfssl是非常好用的CA工具,我們用它來生成證書和祕鑰檔案
安裝過程比較簡單,如下:
#下載
wget -q --show-progress --https-only --timestamping \
https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 \
https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
#修改爲可執行許可權
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64
#移動到bin目錄
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
#驗證
cfssl version
根證書是證書信任鏈的根,各個元件通訊的前提是有一份大家都信任的證書(根證書),每個人使用的證書都是由這個根證書籤發的。
#所有證書相關的東西都放在這
$ mkdir -p /etc/kubernetes/ca
#準備生成證書的組態檔
$ cp ~/kubernetes-starter/target/ca/ca-config.json /etc/kubernetes/ca
$ cp ~/kubernetes-starter/target/ca/ca-csr.json /etc/kubernetes/ca
#生成證書和祕鑰
$ cd /etc/kubernetes/ca
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca
#生成完成後會有以下檔案(我們最終想要的就是ca-key.pem和ca.pem,一個祕鑰,一個證書)
$ ls
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
etcd節點需要提供給其他服務存取,就要驗證其他服務的身份,所以需要一個標識自己監聽服務的server證書,當有多個etcd節點的時候也需要client證書與etcd叢集其他節點互動,當然也可以client和server使用同一個證書因爲它們本質上沒有區別。
#etcd證書放在這
mkdir -p /etc/kubernetes/ca/etcd
#準備etcd證書設定
cp /target/ca/etcd/etcd-csr.json /etc/kubernetes/ca/etcd/
cd /etc/kubernetes/ca/etcd/
#使用根證書(ca.pem)簽發etcd證書
cfssl gencert \
-ca=/etc/kubernetes/ca/ca.pem \
-ca-key=/etc/kubernetes/ca/ca-key.pem \
-config=/etc/kubernetes/ca/ca-config.json \
-profile=kubernetes etcd-csr.json | cfssljson -bare etcd
#跟之前類似生成三個檔案etcd.csr是個中間證書請求檔案,我們最終要的是etcd-key.pem和etcd.pem
ls
etcd.csr etcd-csr.json etcd-key.pem etcd.pem
cp target/master-node/etcd.service /lib/systemd/system/
systemctl daemon-reload
service etcd start
#api-server證書放在這,api-server是核心,資料夾叫kubernetes吧,如果想叫apiserver也可以,不過相關的地方都需要修改哦
$ mkdir -p /etc/kubernetes/ca/kubernetes
#準備apiserver證書設定
$ cp target/ca/kubernetes/kubernetes-csr.json /etc/kubernetes/ca/kubernetes/
$ cd /etc/kubernetes/ca/kubernetes/
#使用根證書(ca.pem)簽發kubernetes證書
$ cfssl gencert \
-ca=/etc/kubernetes/ca/ca.pem \
-ca-key=/etc/kubernetes/ca/ca-key.pem \
-config=/etc/kubernetes/ca/ca-config.json \
-profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
#跟之前類似生成三個檔案kubernetes.csr是個中間證書請求檔案,我們最終要的是kubernetes-key.pem和kubernetes.pem
$ ls
kubernetes.csr kubernetes-csr.json kubernetes-key.pem kubernetes.pem
生成token認證檔案
#生成隨機token
$ head -c 16 /dev/urandom | od -An -t x | tr -d ' '
8afdf3c4eb7c74018452423c29433609
#按照固定格式寫入token.csv,注意替換token內容
$ echo "8afdf3c4eb7c74018452423c29433609,kubelet-bootstrap,10001,\"system:kubelet-bootstrap\"" > /etc/kubernetes/ca/kubernetes/token.csv
更新api-server服務
$ cp target/master-node/kube-apiserver.service /lib/systemd/system/
$ systemctl daemon-reload
$ service kube-apiserver start
#檢查日誌
$ journalctl -f -u kube-apiserver
controller-manager一般與api-server在同一臺機器上,所以可以使用非安全埠與api-server通訊,不需要生成證書和私鑰。
更新controller-manager服務
cp target/master-node/kube-controller-manager.service /lib/systemd/system/
systemctl daemon-reload
service kube-controller-manager start
#檢查日誌
journalctl -f -u kube-controller-manager
scheduler一般與apiserver在同一臺機器上,所以可以使用非安全埠與apiserver通訊。不需要生成證書和私鑰。
啓動服務
$ service kube-scheduler start
#檢查日誌
$ journalctl -f -u kube-scheduler
準備證書
#kubectl證書放在這,由於kubectl相當於系統管理員,我們使用admin命名
$ mkdir -p /etc/kubernetes/ca/admin
#準備admin證書設定 - kubectl只需用戶端證書,因此證書請求中 hosts 欄位可以爲空
$ cp ~/kubernetes-starter/target/ca/admin/admin-csr.json /etc/kubernetes/ca/admin/
$ cd /etc/kubernetes/ca/admin/
#使用根證書(ca.pem)簽發admin證書
$ cfssl gencert \
-ca=/etc/kubernetes/ca/ca.pem \
-ca-key=/etc/kubernetes/ca/ca-key.pem \
-config=/etc/kubernetes/ca/ca-config.json \
-profile=kubernetes admin-csr.json | cfssljson -bare admin
#我們最終要的是admin-key.pem和admin.pem
$ ls
admin.csr admin-csr.json admin-key.pem admin.pem
設定kubectl
#指定apiserver的地址和證書位置(ip自行修改)
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ca/ca.pem \
--embed-certs=true \
--server=https://192.168.200.243:6443
#設定用戶端認證參數,指定admin證書和祕鑰
kubectl config set-credentials admin \
--client-certificate=/etc/kubernetes/ca/admin/admin.pem \
--embed-certs=true \
--client-key=/etc/kubernetes/ca/admin/admin-key.pem
#關聯使用者和叢集
kubectl config set-context kubernetes \
--cluster=kubernetes --user=admin
#設定當前上下文
kubectl config use-context kubernetes
#設定結果就是一個組態檔,可以看看內容
cat ~/.kube/config
驗證master節點
#可以使用剛設定好的kubectl檢視一下元件狀態
kubectl get componentstatus
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health": "true"}
#calico證書放在這
mkdir -p /etc/kubernetes/ca/calico
#準備calico證書設定 - calico只需用戶端證書,因此證書請求中 hosts 欄位可以爲空
cp ~/kubernetes-starter/target/ca/calico/calico-csr.json /etc/kubernetes/ca/calico/
cd /etc/kubernetes/ca/calico/
#使用根證書(ca.pem)簽發calico證書
cfssl gencert \
-ca=/etc/kubernetes/ca/ca.pem \
-ca-key=/etc/kubernetes/ca/ca-key.pem \
-config=/etc/kubernetes/ca/ca-config.json \
-profile=kubernetes calico-csr.json | cfssljson -bare calico
#我們最終要的是calico-key.pem和calico.pem
$ ls
calico.csr calico-csr.json calico-key.pem calico.pem
更新calico服務
cp ~/kubernetes-starter/target/all-node/kube-calico.service /lib/systemd/system/
systemctl daemon-reload
service kube-calico start
#驗證calico(能看到其他節點的列表就對啦)
$ calicoctl node status
我們這裏讓kubelet使用引導token的方式認證,所以認證方式跟之前的元件不同,它的證書不是手動生成,而是由工作節點TLS BootStrap 向api-server請求,由主節點的controller-manager 自動簽發。
#####1 建立角色系結(主節點)
引導token的方式要求用戶端向api-server發起請求時告訴他你的使用者名稱和token,並且這個使用者是具有一個特定的角色:system:node-bootstrapper,所以需要先將 bootstrap token 檔案中的 kubelet-bootstrap 使用者賦予這個特定角色,然後 kubelet 纔有許可權發起建立認證請求。 在主節點執行下面 下麪命令
#可以通過下面 下麪命令查詢clusterrole列表
kubectl -n kube-system get clusterrole
#可以回顧一下token檔案的內容
$ cat /etc/kubernetes/ca/kubernetes/token.csv
8afdf3c4eb7c74018452423c29433609,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
#建立角色系結(將使用者kubelet-bootstrap與角色system:node-bootstrapper系結)
$ kubectl create clusterrolebinding kubelet-bootstrap \
--clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
這個設定是用來完成bootstrap token認證的,儲存了像使用者,token等重要的認證資訊,這個檔案可以藉助kubectl命令生成:(也可以自己寫設定)
#設定叢集參數(注意替換ip)
$ kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ca/ca.pem \
--embed-certs=true \
--server=https://192.168.200.243:6443 \
--kubeconfig=bootstrap.kubeconfig
#設定用戶端認證參數(注意替換token)
$ kubectl config set-credentials kubelet-bootstrap \
--token=8afdf3c4eb7c74018452423c29433609 \
--kubeconfig=bootstrap.kubeconfig
#設定上下文
$ kubectl config set-context default \
--cluster=kubernetes \
--user=kubelet-bootstrap \
--kubeconfig=bootstrap.kubeconfig
#選擇上下文
$ kubectl config use-context default --kubeconfig=bootstrap.kubeconfig
#將剛生成的檔案移動到合適的位置
$ mv bootstrap.kubeconfig /etc/kubernetes/
copy設定
$ cp ~/kubernetes-starter/target/worker-node/10-calico.conf /etc/cni/net.d/
更新服務
$ cp target/worker-node/kubelet.service /lib/systemd/system/
$ systemctl daemon-reload
$ service kubelet start
#啓動kubelet之後到master節點允許worker加入(批準worker的tls證書請求)
#--------*在主節點執行*---------
$ kubectl get csr|grep 'Pending' | awk '{print $1}'| xargs kubectl certificate approve
#-----------------------------
#檢查日誌
$ journalctl -f -u kubelet
#proxy證書放在這
mkdir -p /etc/kubernetes/ca/kube-proxy
#準備proxy證書設定 - proxy只需用戶端證書,因此證書請求中 hosts 欄位可以爲空。
#CN 指定該證書的 User 爲 system:kube-proxy,預定義的 ClusterRoleBinding system:node-proxy 將User system:kube-proxy 與 Role system:node-proxier 系結,授予了呼叫 kube-api-server proxy的相關 API 的許可權
cp ~/kubernetes-starter/target/ca/kube-proxy/kube-proxy-csr.json /etc/kubernetes/ca/kube-proxy/
cd /etc/kubernetes/ca/kube-proxy/
#使用根證書(ca.pem)簽發calico證書
$ cfssl gencert \
-ca=/etc/kubernetes/ca/ca.pem \
-ca-key=/etc/kubernetes/ca/ca-key.pem \
-config=/etc/kubernetes/ca/ca-config.json \
-profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
#我們最終要的是kube-proxy-key.pem和kube-proxy.pem
$ ls
kube-proxy.csr kube-proxy-csr.json kube-proxy-key.pem kube-proxy.pem
#設定叢集參數(注意替換ip)
$ kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ca/ca.pem \
--embed-certs=true \
--server=https://192.168.200.243:6443 \
--kubeconfig=kube-proxy.kubeconfig
#置用戶端認證參數
$ kubectl config set-credentials kube-proxy \
--client-certificate=/etc/kubernetes/ca/kube-proxy/kube-proxy.pem \
--client-key=/etc/kubernetes/ca/kube-proxy/kube-proxy-key.pem \
--embed-certs=true \
--kubeconfig=kube-proxy.kubeconfig
#設定上下文參數
$ kubectl config set-context default \
--cluster=kubernetes \
--user=kube-proxy \
--kubeconfig=kube-proxy.kubeconfig
#選擇上下文
$ kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
#移動到合適位置
$ mv kube-proxy.kubeconfig /etc/kubernetes/kube-proxy.kubeconfig
啓動服務
#如果之前的設定沒有了,可以重新複製一份過去
$ cp target/worker-node/kube-proxy.service /lib/systemd/system/
$ systemctl daemon-reload
#安裝依賴軟體
$ yum install conntrack
#啓動服務
$ service kube-proxy start
#檢視日誌
$ journalctl -f -u kube-proxy
kube-dns有些特別,因爲它本身是執行在kubernetes叢集中,以kubernetes應用的形式執行。所以它的認證授權方式跟之前的元件都不一樣。它需要用到service account認證和RBAC授權。
我們在官方的基礎上新增的變數,生成適合我們叢集的設定。直接copy就可以啦
建立kube-dns
$ kubectl create -f target/services/kube-dns.yaml
#看看啓動是否成功
$ kubectl -n kube-system get pods