Kubernetes API 服务器的安全防护
类别: Kubernetes 标签: ServiceAccount RBAC目录
认证机制
API 服务器接收的请求经过认证插件列表,当遇到第一个成功返回用户名、用户ID和组信息给 API 服务器后,将停止剩余的认证调用,进入授权阶段。
ServiceAccount
镜像拉取密钥
向 ServiceAccount 中添加 imagePullSecrets,可以不必对每个 Pod 单独添加 imagePullSecrets。
创建 docker-registry Secret
kubectl create secret docker-registry mydockerhubsecret \
--docker-username=myusername \
--docker-password=mypassword \
--docker-email=myemail
编写 ServiceAccount YAML 文件(sa-image-pull-secret.yaml)
apiVersion: v1
kind: ServiceAccount
metadata:
name: image-pull-secret
imagePullSecrets:
- name: mydockerhubsecret
创建 ServiceAccount 对象
kubectl apply -f sa-image-pull-secret.yaml
编写 Pod YAML 文件(private-serviceaccount.yaml),指定 serviceAccountName 为 image-pull-secret。
apiVersion: v1
kind: Pod
metadata:
name: private
spec:
containers:
- image: wangjunjian/private:latest
name: private
serviceAccountName: image-pull-secret
创建 Pod 对象
kubectl apply -f private-serviceaccount.yaml
RBAC
基于角色的访问控制(Role-Based Access Control)
HTTP 动词与请求动词的映射关系
HTTP 动词 | 请求动词 |
---|---|
POST | create |
GET, HEAD | get (针对单个资源)、list(针对集合) |
PUT | update |
PATCH | patch |
DELETE | delete(针对单个资源)、deletecollection(针对集合) |
四种 RBAC 资源
RBAC API 声明了四种 Kubernetes 对象:Role、ClusterRole、RoleBinding 和 ClusterRoleBinding。
可以通过 kubectl api-resources 查看
$ kubectl api-resources | grep rbac
NAME SHORTNAMES APIGROUP NAMESPACED KIND
clusterrolebindings rbac.authorization.k8s.io false ClusterRoleBinding
clusterroles rbac.authorization.k8s.io false ClusterRole
rolebindings rbac.authorization.k8s.io true RoleBinding
roles rbac.authorization.k8s.io true Role
测试准备
创建两个名字空间 foo 和 bar 用于接下来的测试。
$ kubectl create namespace foo
namespace/foo created
$ kubectl create namespace bar
namespace/bar created
分别在两个名字空间中创建 Pod 对象
$ kubectl run test --image=luksa/kubectl-proxy -n foo
pod/test created
$ kubectl run test --image=luksa/kubectl-proxy -n bar
pod/test created
列出 foo 名字空间中的所有 Pod 对象
$ kubectl exec -it -n foo test -- curl localhost:8001/api/v1/namespaces/foo/pods
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "pods is forbidden: User \"system:serviceaccount:foo:default\" cannot list resource \"pods\" in API group \"\" in the namespace \"foo\"",
"reason": "Forbidden",
"details": {
"kind": "pods"
},
"code": 403
}
这说明没有权限。
Role(角色)
编写角色 YAML 文件(pod-reader.yaml)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: foo
name: pod-reader
rules:
- apiGroups: [""] # "" 标明 core API 组
resources: ["pods"]
verbs: ["get", "watch", "list"]
创建角色
$ kubectl apply -f pod-reader.yaml
role.rbac.authorization.k8s.io/pod-reader created
查看角色对象
$ kubectl get role -n foo
NAME CREATED AT
pod-reader 2021-08-04T08:53:50Z
这里通过命令的方式创建角色
$ kubectl create role pod-reader --verb=get --verb=watch --verb=list \
--resource=pods -n bar
role.rbac.authorization.k8s.io/pod-reader created
删除角色
$ kubectl delete role pod-reader -n bar
role.rbac.authorization.k8s.io "pod-reader" deleted
RoleBinding(角色绑定)
编写角色绑定 YAML 文件(read-pods.yaml)
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: foo
subjects:
- kind: ServiceAccount
name: default
namespace: foo
- kind: ServiceAccount
name: default
namespace: bar
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
创建角色绑定
$ kubectl apply -f read-pods.yaml
rolebinding.rbac.authorization.k8s.io/read-pods created
通过命令创建角色绑定
$ kubectl create rolebinding read-pods --role=pod-reader \
--serviceaccount=foo:default -n foo
rolebinding.rbac.authorization.k8s.io/read-pods created
列出 foo 名字空间中的所有 Pod 对象
kubectl exec -it -n foo test -- curl localhost:8001/api/v1/namespaces/foo/pods
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "984933"
},
"items": [
{
"metadata": {
"name": "test",
"namespace": "foo",
"uid": "55366a1f-307e-495e-8575-c2b61a462329",
"resourceVersion": "983870",
"creationTimestamp": "2021-08-04T10:42:28Z",
"labels": {
"run": "test"
},
...
}
]
}
删除角色绑定
$ kubectl delete rolebinding read-pods -n foo
rolebinding.rbac.authorization.k8s.io "read-pods" deleted
运行编辑命令在 subjects: 下面增加 bar 名字空间下的默认 ServiceAccount
kubectl edit rolebinding read-pods -n foo
- kind: ServiceAccount
name: default
namespace: bar
现在可以在 bar 名字空间下通过容器访问 foo 名字空间里的所有 Pod 对象。
$ kubectl exec -it -n bar test -- curl localhost:8001/api/v1/namespaces/foo/pods