最近想複習一下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使用
是以我們給使用者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使用者保持一緻。
複制