天天看點

k8s之RBAC實戰

最近想複習一下k8s的知識,并将之前沒做的授權給弄一下。。一切問題就要從這裡開始了。

另外本文沒不怎麼涉及RBAC的理論知識,需要自行學習。

一、開啟RBAC

k8s的元件kube-apiserver是k8s的網關,一切請求都從這裡進去。是以我們開啟RBAC隻需要在該元件配置啟動參數。

在/etc/systemd/system/kube-apiserver.service檔案新增參數。 
--authorization-mode=RBAC            

複制

重新開機kube-apiserver

systemctl restart kube-apiserver.service            

複制

預期的效果元件

kube-controller-manager、kube-scheduler、kubelet、kubelet-proxy元件連接配接kube-apiserver失敗。 
kubectl get nodes/pod/svc/rc 應該都沒權限。            

複制

結果并不是我們預期的

kube-proxy、kubelet兩個連接配接失敗 
kube-controller-manager、kube-scheduler還是可以連接配接 
kubectl get nodes/pod/svc/rc 可以查詢            

複制

這下就懷疑人生了,将各個元件的啟動unit檔案翻了一遍

檔案 kube-apiserver.service 
[Unit] 
Description=Kubernetes API Server 
Documentation=https://github.com/GoogleCloudPlatform/kubernetes 
After=network.target 
After=etcd.service 
[Service] 
ExecStart=/usr/bin/kube-apiserver \ 
--admission-control=NamespaceLifecycle,LimitRanger,DefaultStorageClass,ResourceQuota,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook \ 
--bind-address=192.168.144.128 \ 
--insecure-bind-address=127.0.0.1 \ 
--service-cluster-ip-range=169.169.0.0/16 \ 
--service-node-port-range=30000-40000 \ 
--tls-cert-file=/root/ssl/apiserver.crt \ 
--tls-private-key-file=/root/ssl/apiserver.key \ 
--client-ca-file=/root/ssl/ca.crt \ 
--etcd-servers=http://192.168.144.128:2379,http://192.168.144.129:2379 \ 
--enable-swagger-ui=true \ 
--audit-log-maxage=30 \ 
--audit-log-maxbackup=3 \ 
--audit-log-maxsize=100 \ 
--audit-log-path=/var/log/audit.log \ 
--logtostderr=false \ 
--log-dir=/var/log/kubernetes \ 
--v=2 \ 
--authorization-mode=RBAC 
Restart=on-failure 
RestartSec=5 
Type=notify 
LimitNOFILE=65536 
[Install] 
WantedBy=multi-user.target 
檔案 kube-controller-manager.service 
[Unit] 
Description=Kubernetes Controller Manager 
Documentation=https://github.com/GoogleCloudPlatform/kubernetes 
After=kube-apiserver.service 
[Service] 
ExecStart=/usr/bin/kube-controller-manager \ 
--master=http://127.0.0.1:8080 \ 
--root-ca-file=/root/ssl/ca.key \ 
--leader-elect=true \ 
--logtostderr=false \ 
--log-dir=/var/log/kubernetes \ 
--v=2 
Restart=on-failure 
RestartSec=5 
[Install] 
WantedBy=multi-user.target 
檔案 kubelet.service 
[Unit] 
Description=Kubernetes Kubelet 
Documentation=https://github.com/GoogleCloudPlatform/kubernetes 
After=docker.service 
Requires=docker.service 
[Service] 
WorkingDirectory=/root/kubelet 
ExecStart=/usr/bin/kubelet \ 
--address=192.168.144.128 \ 
--hostname-override=192.168.144.128 \ 
--v=2 \ 
--logtostderr=false \ 
--log-dir=/var/log/kubernetes \ 
--allow-privileged=true \ 
--anonymous-auth=true \ 
--client-ca-file=/root/ssl/ca.crt \ 
--cluster-dns=169.169.0.2 \ 
--cluster-domain=cluster.local \ 
--fail-swap-on=false \ 
--kubeconfig=/root/kubernetes/kubelet.kubeconfig \ 
--pod-infra-container-image=xujinding/pause:3.1 \ 
--register-node=true \ 
--cgroups-per-qos=true \ 
--cgroup-driver=cgroupfs \ 
--enforce-node-allocatable=pods,kube-reserved \ 
--kube-reserved-cgroup=/system.slice/kubelet.service \ 
--system-reserved-cgroup=/system.slice 
Restart=on-failure 
RestartSec=5 
[Install] 
WantedBy=multi-user.target            

複制

如上面腳本所示

kube-apiserver.service參數—bind-address、—insecure-bind-address

—bind-address=192.168.144.128 \

—insecure-bind-address=127.0.0.1 \

注意insecure-bind-address(預設是8080端口)通路的不需要經過認證鑒權的,而bind-address(預設是6443端口)是需要的。

這次是直接使用之前部署的k8s叢集,當初是這樣想的kube-controller-manager、kube-scheduler是master的元件一般和kube-apiserver元件在統一機器,是以是127.0.0.1

而kubelet、kubelet-proxy是node的元件,多個node一般master寫的是多個master使用haproxy,keeplived的vip

(這樣也沒毛病,https://github.com/easzlab/kubeasz也是這樣的)

是以結果就很明顯了kubelet、kubelet-proxy啟動檔案配置的是master的位址這裡是 192.168.144.128是以是需要認證授權的,而kube-controller-manager、kube-scheduler是127.0.0.1不需要認證授權

kubectl預設是使用/~/user/.kube/config檔案配置的叢集和證書去通路。。。。沒有的話就使用127.0.0.1:8080去通路。。。是以這個也不需要認證授權

原因知道了,我們繼續搞

接下來我們将非安全的8080端口關掉

修改檔案 kube-apiserver.service 
删除這句--insecure-bind-address=127.0.0.1 \ 
新增這句--insecure-port=0 
重新開機kube-apiserver 
修改檔案 kube-controller-manager.service 
--master=http://127.0.0.1:8080 \ 改為--master=http://192.168.144.128:6443 \ 
重新開機kube-controller-manager 
同理 
kube-scheduler将master位址改成安全連結,并重新開機 
這樣就跟我們預期的一樣了,kubectl後面再說。            

複制

二、問題處理

現在

kube-controller-manager、kube-scheduler、kubelet、kubelet-proxy元件連接配接kube-apiserver失敗了。

檢視日志就是

is forbidden: User “192.168.144.128” cannot

使用者192.168.144.128不能通路,認證不過??還是授權沒過??

我們使用的CA認證,這個我們沒開啟RBAC的時候是沒毛病的,是以不是!!!那就是授權沒過了!!!

使用者192.168.144.128這個哪裡來的???

生成私鑰 
openssl genrsa -out admin.key 
生成證書 
openssl req -new -key client.key -subj "/CN={{inventory_hostname}}" -out client.csr 
這裡我們注意到/CN={{inventory_hostname}} 這個是ansible變量意思是本機ip 
k8s通路apiserver元件使用的使用者就是證書的/CN,是以這裡是192.168.144.128。 
而使用者192.168.144.128。。沒有任何權限。。            

複制

解決問題

1.給使用者192.168.144.128授權

2.重新生成證書,/CN設定有權限的使用者

k8s有内置了一些clusterrole友善我們使用

如下圖

system:kube-scheduler 專門給kube-scheduler用的

system:kube-controller-manager 專門給kube-controller-manager使用

system:node 專門給kubelet使用

system:node-proxier 專門給kube-proxy使用

k8s之RBAC實戰

是以我們給使用者192.168.144.128授權system:kube-scheduler、system:kube-node、system:kube-conroller-manager、system:node-proxier權限就行了

檢視clusterrolebindings 
kubectl get clusterrolebindings 
檢視system:node角色綁定的詳細資訊 
kubectl describe clusterrolebindings system:node 
授予system:kube-controller-manager權限和system:node 
kubectl create clusterrolebinding kubelet-controller-manager-clusterbinding --clusterrole=system:kube-controller-manager --user=192.168.144.128 
kubectl create clusterrolebinding kubelet-clusterbinding --clusterrole=system:node --user=192.168.144.128 
同理system:node-proxier 、system:kube-scheduler 
有人要說kubectl不是不能用嗎? 
其實這裡我的叢集是因為有兩個master 我是在另一個master使用kubectl建立的。。你可以先開啟非安全來配置,再改回來。            

複制

第二種辦法,我們可以重新生成證書。

管理者證書

這裡生成一個擁有管理者權限的證書admin.crt 
openssl genrsa -out admin.key 
openssl req -new -key admin.key -out admin.csr -subj "/CN=admin/O=system:masters/OU=System" 
openssl x509 -req -in admin.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out admin.crt -days 5000 
注意"/CN=admin/O=system:masters/OU=System" 
kube-apiserver 預定義了一些 RBAC 使用的 RoleBindings(角色),如 cluster-admin (角色)将 Group(組) system:masters與 Role(角色) cluster-admin 綁定,該 Role 授予了調用kube-apiserver 的所有 API的權限; 
在證書的簽名中,OU 指定該證書的 Group 為 system:masters,kubelet 使用該證書通路 kube-apiserver 時 ,由于證書被 CA 簽名,是以認證通過,同時由于證書使用者組為經過預授權的 system:masters,是以被授予通路所有 API 的權限; 
是以這裡我們不需要為admin賦予權限了,預設是system:masters,是以當我們元件用戶端證書配置為admin.crt就可以擁有管理者權限了。 
當然我們還是讓對應得元件擁有對應得權限就行。。下面使用kube-proxy做例子            

複制

kube-proxy證書

生成kube-proxy證書 
openssl genrsa -out kube-proxy.key 
openssl req -new -key kube-proxy.key -out kube-proxy.csr -subj "/CN=system:kube-proxy" 
openssl x509 -req -in kube-proxy.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kube-proxy.crt -days 5000 
這樣kube-proxy啟動檔案配置kube-proxy.crt證書就可以擁有權限了。。 
同理其他的元件也一樣            

複制

kubectl權限

上面我們已經說過:kubectl預設是使用/~/user/.kube/config檔案配置的叢集和證書去通路。

假設這裡我們有個liunx的使用者dev那麼配置檔案位置/home/dev/.kube/config。。預設沒有這個檔案,使用127.0.0.1:8080去通路叢集

[root@k8s-master1 .kube]# vim config 
apiVersion: v1 
kind: Config 
clusters: 
- cluster: 
certificate-authority: /usr/local/ssl/ca.crt 
server: https://192.168.144.128:6443 
name: kubernetes 
users: 
- name: dev 
user: 
client-certificate: /usr/local/ssl/client.crt 
client-key: /usr/local/ssl/client.key 
contexts: 
- context: 
cluster: kubernetes 
namespace: dev 
user: dev 
name: ctx-dev 
current-context: ctx-dev 
dev使用者就會使用/usr/local/ssl/client.crt的證書去通路kubernetes叢集的ctx-dev命名空間。 
使用者就是client.crt生成的時候CN配置的。 
users: name: dev 這個dev好像沒什麼用。。。。我這裡跟liunx使用者保持一緻。            

複制