前言
kubernetes对API访问提供了三种安全访问控制措施:认证,授权,准入控制。
- 认证解决用户是谁的问题
- 授权解决用户能做什么的问题
- 准入控制是资源管理方面的作用。
- 集群的所有操作基本上都是通过kube-apiserver组件进行,它提供http Restful 形式的api供集群内外客户端调用。
认证
对外不暴露8080端口,只内部访问,对外使用6443端口。(k8s不直接管理用户,不创建user对象,也不存储)
认证方式有:
- HTTPS证书认证,基于ca证书
- http token认证,通过token识别用户
- http基本认证,用户名+密码
授权
对集群资源的访问控制,通过检查请求包含的相关属性值,与相对应的访问策略相比较,api请求必须满足某些策略才能被处理。
授权请求属性:user、group、namespace、请求方法(get、post、update、delete)
授权插件:RBAC、ABAC
准入控制
在授权后对请求做进一步的验证或添加默认参数,还处理请求内容,仅对创建、更新、删除、连接等有效,对读操作无效
注意
认证授权过程只存在HTTPS形式的api中。如果客户端使用http连接到kube-apiserver就不会进行认证授权的。可以这么设置,在集群内部组件间通信使用http,集群外部就使用HTTPS,既增加安全性,也不至于太复杂。
RBAC
让用户能够访问kubernetes API 资源的授权方式。基于角色的访问控制机制(Role-Based Access),角色与权限相关联,用户通过成为适当角色的成员而得到这些角色的权限。
可以利用kubectl 或者 kubernetes api 进行配置,可以授权给用户,让用户有权进行授权管理,无需接触节点,直接进行授权。
主体
user、group、serviceAccount
部署步骤
- 新建命名空间
- ns里新建pod
- 创建角色role
- 创建角色绑定rolebinding
- 生成证书,识别身份
- 查看pod、svc
ServiceAccount
Service account 是为了方便 Pod 里面的进程调用 Kubernetes API 或其他外部服务而设计的, service account 则是仅局限它所在的namespace;
每个 namespace 都会自动创建一个 default service account,Token controller 检测 service account 的创建,并为它们创建 secret;
开启 ServiceAccount Admission Controller 后,每个 Pod 在创建后都会自动设置 spec.serviceAccountName 为 default(除非指定了其他 ServiceAccout);
验证 Pod 引用的 service account 已经存在,否则拒绝创建;
如果 Pod 没有指定 ImagePullSecrets,则把 service account 的ImagePullSecrets 加到 Pod 中;
每个 container 启动后都会挂载该 service account 的 token 和 ca.crt 到/var/run/secrets/kubernetes.io/serviceaccount/;
[root@k8s-master ~]# kubectl exec web1-8c7889f4d-7nm54 ls /var/run/secrets/kubernetes.io/serviceaccount/
ca.crt
namespace
token
Role和ClusterRole
role(角色)是一系列权限的集合,一个角色可以包含读取pod的权限和列出pod的权限,role只能用来给某个特定namespace中的资源作鉴权,对多namespace和集群级的资源使用clusterRole。
#创建ns和pod
[root@k8s-master ~]# kubectl create ns roledemo
[root@k8s-master ~]# kubectl run nginx --image=nginx -n roledemo
#role
[root@k8s-master ~]# cat role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: roledemo
name: pod-reader
rules:
- apiGroups:
- ''
resources:
- pods
verbs:
- get
- watch
- list
[root@k8s-master ~]# kubectl apply -f role.yaml
role.rbac.authorization.k8s.io/pod-reader created
[root@k8s-master ~]# kubectl get role -n roledemo
NAME CREATED AT
pod-reader 2022-10-24T07:40:51Z
#cluster-role
[root@k8s-master ~]# cat clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" 被忽略,因为 ClusterRoles 不受名字空间限制
name: secret-reader
rules:
- apiGroups: [""]
# 在 HTTP 层面,用来访问 Secret 资源的名称为 "secrets"
resources: ["secrets"]
verbs: ["get", "watch", "list"]
[root@k8s-master ~]# kubectl apply -f clusterrole.yaml
clusterrole.rbac.authorization.k8s.io/secret-reader created
[root@k8s-master ~]# kubectl get clusterrole |grep reader
secret-reader 2022-10-24T09:24:17Z
RoleBinding 和 ClusterRoleBinding
Rolebinding是把角色(role或clusterrole)的权限映射到用户或用户组,让用户继承角色在namespace中的权限。
Clusterrolebinding是让用户继承clusterrole在整个集群中的权限。
#roleBinding
[root@k8s-master ~]# cat role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: roledemo
subjects:
- kind: User
name: lucy
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
[root@k8s-master ~]# kubectl apply -f role-binding.yaml
rolebinding.rbac.authorization.k8s.io/read-pods created
[root@k8s-master ~]# kubectl get rolebinding -n roledemo
NAME ROLE AGE
read-pods Role/pod-reader 38s
#clusterrole-binding
[root@k8s-master ~]# cat << EOF > clusterrole-binding.yaml
> apiVersion: rbac.authorization.k8s.io/v1
> # 此集群角色绑定允许 “manager” 组中的任何人访问任何名字空间中的 Secret 资源
> kind: ClusterRoleBinding
> metadata:
> name: read-secrets-global
> subjects:
> - kind: User
> name: lucy # 'name' 是区分大小写的
> apiGroup: rbac.authorization.k8s.io
> roleRef:
> kind: ClusterRole
> name: secret-reader
> apiGroup: rbac.authorization.k8s.io
> EOF
[root@k8s-master ~]# kubectl apply -f clusterrole-binding.yaml
clusterrolebinding.rbac.authorization.k8s.io/read-secrets-global created
[root@k8s-master ~]# kubectl get clusterrolebinding |grep reader
read-secrets-global ClusterRole/secret-reader
#用户证书
[root@k8s-master pki]# cd /root/kubeneters/pki
[root@k8s-master pki]# cp admin-csr.json lucy-csr.json
[root@k8s-master pki]# sed -i 's/admin/lucy/g' lucy-csr.json
[root@k8s-master pki]# cfssl gencert \
> -ca=/etc/kubernetes/pki/ca.pem \
> -ca-key=/etc/kubernetes/pki/ca-key.pem \
> -config=ca-config.json \
> -profile=kubernetes \
> lucy-csr.json | cfssljson -bare /etc/kubernetes/pki/lucy
2022/10/24 16:17:54 [INFO] generate received request
2022/10/24 16:17:54 [INFO] received CSR
2022/10/24 16:17:54 [INFO] generating key: rsa-2048
2022/10/24 16:17:54 [INFO] encoded CSR
2022/10/24 16:17:54 [INFO] signed certificate with serial number 135872415710505091694801536062924858471880164898
[root@k8s-master pki]# kubectl config set-cluster kubernetes \
> --certificate-authority=/etc/kubernetes/pki/ca.pem \
> --embed-certs=true \
> --server=https://10.103.3.249:8443 \
> --kubeconfig=/etc/kubernetes/lucy.kubeconfig
Cluster "kubernetes" set.
[root@k8s-master pki]# kubectl config set-credentials kubernetes-lucy \
> --client-certificate=/etc/kubernetes/pki/lucy.pem \
> --client-key=/etc/kubernetes/pki/lucy-key.pem \
> --embed-certs=true \
> --kubeconfig=/etc/kubernetes/lucy.kubeconfig
User "kubernetes-lucy" set.
[root@k8s-master pki]# kubectl config set-context kubernetes-lucy@kubernetes \
> --cluster=kubernetes \
> --user=kubernetes-lucy \
> --kubeconfig=/etc/kubernetes/lucy.kubeconfig
Context "kubernetes-lucy@kubernetes" modified.
[root@k8s-master pki]# kubectl config use-context kubernetes-lucy@kubernetes --kubeconfig=/etc/kubernetes/lucy.kubeconfig
Switched to context "kubernetes-lucy@kubernetes".