想理解認證,咱們得從認證解決什麼問題、防止什麼問題的發生入手。
防止什麼問題呢?是防止有人入侵你的集羣,root你的機器後讓咱們集羣依然安全嗎?不是吧,root都到手了,那就隨心所欲,防不勝防了。
其實網絡安全自己就是爲了解決在某些假設成立的條件下如何防範的問題。好比一個很是重要的假設就是兩個節點或者ip之間的通信網絡是不可信任的,可能會被第三方竊取,也可能會被第三方篡改。就像咱們上學時候給心儀的女孩傳紙條,傳送的過程可能會被別的同窗偷看,甚至內容可能會從我喜歡你修改爲我不喜歡你了。固然這種假設不是隨便想出來的,而是從網絡技術現狀和實際發生的問題中發現、總結出來的。kubernetes的認證也是從這個問題出發來實現的。html
爲了解決上面說的問題,kubernetes並不須要本身想辦法,畢竟是網絡安全層面的問題,是每一個服務都會遇到的問題,業內也有成熟的方案來解決。這裏咱們一塊兒瞭解一下業內方案和相關的概念。node
受權的概念就簡單多了,就是什麼人具備什麼樣的權限,通常經過角色做爲紐帶把他們組合在一塊兒。也就是一個角色一邊擁有多種權限,一邊擁有多我的。這樣就把人和權限創建了一個關係。linux
Kubernetes集羣的全部操做基本上都是經過kube-apiserver這個組件進行的,它提供HTTP RESTful形式的API供集羣內外客戶端調用。須要注意的是:認證受權過程只存在HTTPS形式的API中。也就是說,若是客戶端使用HTTP鏈接到kube-apiserver,那麼是不會進行認證受權的。因此說,能夠這麼設置,在集羣內部組件間通訊使用HTTP,集羣外部就使用HTTPS,這樣既增長了安全性,也不至於太複雜。
對APIServer的訪問要通過的三個步驟,前面兩個是認證和受權,第三個是 Admission Control,它也能在必定程度上提升安全性,不過更可能是資源管理方面的做用。nginx
kubernetes提供了多種認證方式,好比客戶端證書、靜態token、靜態密碼文件、ServiceAccountTokens等等。你能夠同時使用一種或多種認證方式。只要經過任何一個都被認做是認證經過。下面咱們就認識幾個常見的認證方式。docker
在Kubernetes1.6版本中新增角色訪問控制機制(Role-Based Access,RBAC)讓集羣管理員能夠針對特定使用者或服務帳號的角色,進行更精確的資源訪問控制。在RBAC中,權限與角色相關聯,用戶經過成爲適當角色的成員而獲得這些角色的權限。這就極大地簡化了權限的管理。在一個組織中,角色是爲了完成各類工做而創造,用戶則依據它的責任和資格來被指派相應的角色,用戶能夠很容易地從一個角色被指派到另外一個角色。 目前 Kubernetes 中有一系列的鑑權機制,由於Kubernetes社區的投入和偏好,相對於其它鑑權機制而言,RBAC是更好的選擇。具體RBAC是如何體如今kubernetes系統中的咱們會在後面的部署中逐步的深刻了解。json
AdmissionControl - 准入控制本質上爲一段准入代碼,在對kubernetes api的請求過程當中,順序爲:先通過認證 & 受權,而後執行准入操做,最後對目標對象進行操做。這個准入代碼在api-server中,並且必須被編譯到二進制文件中才能被執行。 在對集羣進行請求時,每一個准入控制代碼都按照必定順序執行。若是有一個准入控制拒絕了這次請求,那麼整個請求的結果將會當即返回,並提示用戶相應的error信息。 經常使用組件(控制代碼)以下:bootstrap
開始以前咱們要先把基礎版本的集羣停掉,包括service,deployments,pods以及運行的全部kubernetes組件vim
#刪除services $ kubectl delete services nginx-service #刪除deployments $ kubectl delete deploy kubernetes-bootcamp $ kubectl delete deploy nginx-deployment $ kubectl delete service kubernetes-bootcamp #停掉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的全部相關配置文件api
$ cd ~/kubernetes-starter #按照配置文件的提示編輯好配置 $ 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 ~/kubernetes-starter/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
建議你們先比較一下增長認證的etcd配置與原有配置的區別,作到心中有數。 可使用命令比較:
$ cd ~/kubernetes-starter/ $ vimdiff kubernetes-simple/master-node/etcd.service kubernetes-with-ca/master-node/etcd.service
更新etcd服務:
$ cp ~/kubernetes-starter/target/master-node/etcd.service /lib/systemd/system/ $ systemctl daemon-reload $ service etcd start #驗證etcd服務(endpoints自行替換) $ ETCDCTL_API=3 etcdctl \ --endpoints=https://10.0.94.112:2379 \ --cacert=/etc/kubernetes/ca/ca.pem \ --cert=/etc/kubernetes/ca/etcd/etcd.pem \ --key=/etc/kubernetes/ca/etcd/etcd-key.pem \ endpoint health
若是直接執行上述命令出現以下錯誤:
cluster may be unhealthy: failed to list membersError: client: etcd cluster is unavailable or misconfigured; error #0: malformed HTTP response "\x15\x03\x01\x00\x02\x02"; error #1: dial tcp 127.0.0.1:4001: getsockopt: connection refused |
---|
執行export ETCDCTL_ENDPOINT=https://127.0.0.1:2379
修改ETCDCTL_ENDPOINT環境變量, 以後再次執行, 則能夠看到結果.
#api-server證書放在這,api-server是核心,文件夾叫kubernetes吧,若是想叫apiserver也能夠,不過相關的地方都須要修改哦 $ mkdir -p /etc/kubernetes/ca/kubernetes #準備apiserver證書配置 $ cp ~/kubernetes-starter/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
查看diff
$ cd ~/kubernetes-starter $ vimdiff kubernetes-simple/master-node/kube-apiserver.service kubernetes-with-ca/master-node/kube-apiserver.service
生成token認證文件
#生成隨機token $ head -c 16 /dev/urandom | od -An -t x | tr -d ' ' a691e60cc11e7438deb03a91e70ab000 #按照固定格式寫入token.csv,注意替換token內容 $ echo "a691e60cc11e7438deb03a91e70ab000,kubelet-bootstrap,10001,\"system:kubelet-bootstrap\""> /etc/kubernetes/ca/kubernetes/token.csv
更新api-server服務
$ cp ~/kubernetes-starter/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通信,不須要生成證書和私鑰。
查看diff
$ cd ~/kubernetes-starter/ $ vimdiff kubernetes-simple/master-node/kube-controller-manager.service kubernetes-with-ca/master-node/kube-controller-manager.service
更新controller-manager服務
$ cp ~/kubernetes-starter/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通信。不須要生成證書和私鑰。
查看diff比較會發現兩個文件並無區別,不須要改造
$ cd ~/kubernetes-starter/ $ vimdiff kubernetes-simple/master-node/kube-scheduler.service kubernetes-with-ca/master-node/kube-scheduler.service
啓動服務
$ 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
#指定apiserver的地址和證書位置(ip自行修改) $ kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/ca/ca.pem \ --embed-certs=true \ --server=https://10.0.94.112: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證書用在四個地方:
#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
查看diff
$ cd ~/kubernetes-starter $ vimdiff kubernetes-simple/all-node/kube-calico.service kubernetes-with-ca/all-node/kube-calico.service
經過diff會發現,calico多了幾個認證相關的文件:
/etc/kubernetes/ca/ca.pem
/etc/kubernetes/ca/calico/calico.pem
/etc/kubernetes/ca/calico/calico-key.pemscp -r /etc/kubernetes/ca/ root@10.0.94.246:/etc/kubernetes/
因爲calico服務是全部節點都須要啓動的,你們須要把這幾個文件拷貝到每臺服務器上
更新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 自動簽發。
引導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 a691e60cc11e7438deb03a91e70ab000,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://10.0.94.112:6443 \ --kubeconfig=bootstrap.kubeconfig #設置客戶端認證參數(注意替換token) $ kubectl config set-credentials kubelet-bootstrap \ --token=a691e60cc11e7438deb03a91e70ab000 \ --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/
查看diff
$ cd ~/kubernetes-starter $ vimdiff kubernetes-simple/worker-node/10-calico.conf kubernetes-with-ca/worker-node/10-calico.conf
copy配置
$ cp ~/kubernetes-starter/target/worker-node/10-calico.conf /etc/cni/net.d/
查看diff
$ cd ~/kubernetes-starter $ vimdiff kubernetes-simple/worker-node/kubelet.service kubernetes-with-ca/worker-node/kubelet.service
更新服務
$ cp ~/kubernetes-starter/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://10.0.94.112: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
查看diff
$ cd ~/kubernetes-starter $ vimdiff kubernetes-simple/worker-node/kube-proxy.service kubernetes-with-ca/worker-node/kube-proxy.service
通過diff你應該發現kube-proxy.service沒有變化
啓動服務
#若是以前的配置沒有了,能夠從新複製一份過去 $ cp ~/kubernetes-starter/target/worker-node/kube-proxy.service /lib/systemd/system/ $ systemctl daemon-reload #安裝依賴軟件 $ yum install conntrack -y #啓動服務 $ service kube-proxy start #查看日誌 $ journalctl -f -u kube-proxy
kube-dns有些特別,由於它自己是運行在kubernetes集羣中,以kubernetes應用的形式運行。因此它的認證受權方式跟以前的組件都不同。它須要用到service account認證和RBAC受權。
service account認證:
每一個service account都會自動生成本身的secret,用於包含一個ca,token和secret,用於跟api-server認證
RBAC受權:
權限、角色和角色綁定都是kubernetes自動建立好的。咱們只須要建立一個叫作kube-dns的 ServiceAccount便可,官方現有的配置已經把它包含進去了。
咱們在官方的基礎上添加的變量,生成適合咱們集羣的配置。直接copy就能夠啦
$ cd ~/kubernetes-starter $ vimdiff kubernetes-simple/services/kube-dns.yaml kubernetes-with-ca/services/kube-dns.yaml
你們能夠看到diff只有一處,新的配置沒有設定api-server。不訪問api-server,它是怎麼知道每一個服務的cluster ip和pod的endpoints的呢?這就是由於kubernetes在啓動每一個服務service的時候會以環境變量的方式把全部服務的ip,端口等信息注入進來。
$ kubectl create -f ~/kubernetes-starter/target/services/kube-dns.yaml #看看啓動是否成功 $ kubectl -n kube-system get pods
終於,安全版的kubernetes集羣咱們部署完成了。下面咱們使用新集羣先溫習一下以前學習過的命令,而後再認識一些新的命令,新的參數,新的功能。