ServiceAccount
ServiceAccount是专供pod使用的,权限管理中的一种身份标记。ServiceAccount的作用范围是namespace。
创建ServiceAccount
创建ServiceAccount如下两种方式:
- 使用描述文件
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
- 使用命令行
kubectl create serviceaccount my-service-account
AdmissionController
如果一个pod绑定了ServiceAccount,AdmissionController会对这个pod做出修改,内容如下:
- 如果没有配置ServiceAccount,设置ServiceAccount为default。
- 必须确保pod关联的ServiceAccount存在。
- 如果没有包含ImagePullSecrets,自动添加ServiceAccount的ImagePullSecrets。
- 添加一个包含API访问的volume。
- pod中每个container添加一个volumeSource,挂载在
/var/run/secrets/kubernetes.io/serviceaccount
。
注意:可以通过在ServiceAccount或者pod中配置automountServiceAccountToken: false
,阻止API访问token的自动挂载。
Pod绑定ServiceAccount
如果创建pod的时候没有指定ServiceAccount,默认会使用名字为default的ServiceAccount。
pod绑定ServiceAccount的方法:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: my-service-account
...
在.spec.serviceAccountName
中配置需要绑定的ServiceAccount即可。
注意:不能修改已创建pod关联的ServiceAccount。
创建ServiceAccount的API token
创建ImagePullSecret
对于一些镜像源,拉取镜像的时候需要提供认证信息。主要步骤分为2步:
- 创建一个secret。包含docker镜像托管服务器地址,用户名和密码等。
kubectl create secret docker-registry <name> --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
- 在pod中引用这个Secret。
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: myregistrykey
为ServiceAccount添加ImagePullSecret
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
namespace: default
secrets:
- name: default-token-uudge
imagePullSecrets:
- name: myregistrykey
RBAC权限管理
Role-based access control,即基于角色的访问控制。
开启RBAC
启动apiserver带上--authorization-mode=RBAC
参数。
RBAC使用rbac.authorization.k8s.io/v1
API version。
Role和ClusterRole
Role和ClusterRole都是一些权限的集合。不同的地方是,Role的作用范围是namespace,而ClusterRole的范围是整个集群。
它们的描述文件示例如下:
Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" omitted since ClusterRoles are not namespaced
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
RoleBinding和ClusterRoleBinding
这两个负责把Role或ClusterRole绑定给User,Group和ServiceAccount。
他们的不同之处为:
- RoleBinding用来绑定同一个namespace内的Role,被绑定用户的权限也限制在同一个namespace。
- RoleBinding可以用来绑定ClusterRole,但是被绑定用户的权限仍然被限制在和RoleBinding相同的namespace中。
- ClusterRoleBinding用于绑定ClusterRole,被绑定用户的权限在所有namespace中都有效。
它们的描述文件示例如下所示:
RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "dave" to read secrets in the "development" namespace.
kind: RoleBinding
metadata:
name: read-secrets
namespace: development # This only grants permissions within the "development" namespace.
subjects:
- kind: User
name: dave # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
RoleBinding和ClusterRoleBinding的roleRef字段是不可以修改的。如果需要修改,必须删除再重新创建binding。
指定资源
Role或者是ClusterRole适用的资源位于.rules.resources
内,是一个数组的形式。编写的格式为:
${resource name}/${subresource name}
其中resource name为k8s中资源类型名称,例如pods,services,deployments等。是各种k8s资源描述文件kind
内容小写的复数形式。
动词对照表
一个role可以对资源进行什么操作是通过.rules.verbs
规定的。这些动词可以认为可传统数据库的增删改查操作对应。这些操作也和客户端的HTTP请求方法对应。完整的对应表如下所示:
HTTP方法 | 单个资源动词 | 集合动词 |
---|---|---|
GET, HEAD | get(持续查看用watch) | list |
POST | create | 无 |
PUT | update | 无 |
PATCH | patch | 无 |
DELETE | delete | deletecollection |
除了可以使用resources
约束特定类型资源的访问权限外,还可以根据资源的名称来限制。一个例子如下所示:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: configmap-updater
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["update", "get"]
这里使用resourceNames
指定资源名称。
注意:create动作无法使用resourceNames
进行限制,因为在鉴权的时候资源名称是未知的。deletecollection也是一个例外。
ClusterRole的聚合
可以在其他多个ClusterRole的基础上,创建出一个聚合的ClusterRole。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # Rules are automatically filled in by the controller manager.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-endpoints
labels:
rbac.example.com/aggregate-to-monitoring: "true"
# These rules will be added to the "monitoring" role.
rules:
- apiGroups: [""]
resources: ["services", "endpoints", "pods"]
verbs: ["get", "list", "watch"]
如上面的例子所示,monitoring这个ClusterRole会聚合所有label匹配rbac.example.com/aggregate-to-monitoring: "true"
的ClusterRole。紧接着创建出的ClusterRole具有这个label,会被上面的monitoring聚合。
一些role的例子
允许在core API group读取pod的信息:
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
允许在extensions和apps API group读写deployments:
rules:
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
使用多组apiGroups:
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch", "extensions"]
resources: ["jobs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
允许读取名字为my-config的ConfigMap
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-config"]
verbs: ["get"]
允许读取node信息。因为node是cluster级别的资源,因此必须使用ClusterRole和ClusterRoleBinding。
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
允许get,post调用非资源类型的URL(HTTP请求URL),healthz和healthz的所有子路径(必须使用ClusterRole和ClusterRoleBinding):
rules:
- nonResourceURLs: ["/healthz", "/healthz/*"] # '*' in a nonResourceURL is a suffix glob match
verbs: ["get", "post"]
指定目标
RoleBinding和ClusterRoleBinding可以用来限制Group, User和ServiceAccount。
User和Group没有格式限制,但是system:
前缀开头的是归k8s系统使用。用户自己创建的User和Group必须避免使用这个前缀。
几个role绑定的例子
绑定用户:
subjects:
- kind: User
name: "alice@example.com"
apiGroup: rbac.authorization.k8s.io
绑定组:
subjects:
- kind: Group
name: "frontend-admins"
apiGroup: rbac.authorization.k8s.io
绑定ServiceAccount:
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
绑定到namespace qa下所有的ServiceAccount:
subjects:
- kind: Group
name: system:serviceaccounts:qa
apiGroup: rbac.authorization.k8s.io
绑定所有的ServiceAccount:
subjects:
- kind: Group
name: system:serviceaccounts
apiGroup: rbac.authorization.k8s.io
绑定所有的认证用户:
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
绑定所有的未认证用户:
subjects:
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
绑定所有的用户:
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
默认的Role和RoleBinding
k8s系统默认的Role和RoleBinding使用system:
前缀。不要去修改这些role和role binding,否则会导致系统无法正常工作。所有默认的Role和RoleBinding都具有kubernetes.io/bootstrapping=rbac-defaults
标签。
防止越权
如果用户想创建一个role,他必须满足如下两个条件之一:
- 他已经拥有这个role包含的所有权限,同时范围也要匹配(创建ClusterRole需要有集群范围权限,创建Role需要有相同namespace的权限或者是集群范围的权限)。
- 这个用户对应的role具有
escalate
动词。
如果用户想创建一个role binding,他必须满足如下两个条件之一:
- 它拥有想创建的role binding关联的role的所有权限(范围和role binding相同或更大)。
- 用户权限具有
bind
动词。
权限修正
可以使用
kubectl auth reconcile -f my-rbac-rules.yaml
命令,修正系统中配置的权限,使之和my-rbac-rules.yaml
文件中的一致。
该命令还有如下常用参数:
- --dry-run:不真正执行,仅仅会显示要做出哪些修改。
- --remove-extra-permissions:删除多余的权限。如果role中有多余的权限,会把他们删除。
- --remove-extra-subjects:删除额外的subject(user, group, service account)。如果binding中有多余的subject,会把他们删除。