希望长大对我而言,是可以做更多想做的事,而不是被迫做更多不想做的事...... 首页 k8s之RBAC实战 丁D 学无止境 2019-11-19 17:16 182456已阅读 RBAC k8s 摘要本文是个人对K8S的认证授权的一次实战笔记。 最近想复习一下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使用 ![](/upload/20180421201151269.png) 所以我们给用户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去访问集群 ```yaml [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用户保持一致。 ``` 很赞哦! (21) 上一篇:k8s命名空间和运行环境 下一篇:k8s滚动升级和扩缩容 目录 点击排行 Elasticsearch6.3.2之x-pack redis哨兵 2019-07-09 22:05 Redis+Twemproxy+HAProxy+Keepalived 2019-07-12 17:20 GC优化策略和相关实践案例 2019-10-10 10:54 JVM垃圾回收器 2019-10-10 10:23 标签云 Java Spring MVC Mybatis Ansible Elasticsearch Redis Hive Docker Kubernetes RocketMQ Jenkins Nginx 友情链接 郑晓博客 佛布朗斯基 凉风有信 MarkHoo's Blog 冰洛博客 南实博客 Rui | 丁D Java研发工程师 生活可以用「没办法」三个字概括。但别人的没办法是「腿长,没办法」、「长得好看,没办法」、「有才华,没办法」。而你的没办法,是真的没办法。 请作者喝咖啡