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实战_第1张图片

所以我们给用户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用户保持一致。

你可能感兴趣的:(k8s)