最近想复习一下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用户保持一致。