K8s ServiceAccount和RBAC

Service Account

Service account是为了方便Pod里面的进程调用Kubernetes API或其他外部服务而设计的。它与User account不同

  • User account是为人设计的,而service account则是为Pod中的进程调用Kubernetes API而设计;
  • User account是跨namespace的,而service account则是仅局限它所在的namespace;
  • 每个namespace都会自动创建一个default service account
  • Token controller检测service account的创建,并为它们创建secret

在开启ServiceAccount Admission Controller后

  • 每个Pod在创建后都会自动设置spec.serviceAccount为default(除非指定了其他ServiceAccout)
  • 验证Pod引用的service account已经存在,否则拒绝创建
  • 如果Pod没有指定ImagePullSecrets,则把service account的ImagePullSecrets加到Pod中
  • 每个container启动后都会挂载该service account的token和ca.crt到/var/run/secrets/kubernetes.io/serviceaccount/

创建一个Service Account

通过create命令或者资源定义文件创建一个ServiceAccount:

$ kubectl create serviceaccount jenkins
serviceaccount "jenkins" created
$ kubectl get serviceaccounts jenkins -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: 2017-05-27T14:32:25Z
  name: jenkins
  namespace: default
  resourceVersion: "45559"
  selfLink: /api/v1/namespaces/default/serviceaccounts/jenkins
  uid: 4d66eb4c-42e9-11e7-9860-ee7d8982865f
secrets:
- name: jenkins-token-l9v7v

自动创建的secret:

$ kubectl get secret jenkins-token-l9v7v -o yaml
apiVersion: v1
data:
  ca.crt: (APISERVER CA BASE64 ENCODED)
  namespace: ZGVmYXVsdA==
  token: (BEARER TOKEN BASE64 ENCODED)
kind: Secret
metadata:
  annotations:
    kubernetes.io/service-account.name: jenkins
    kubernetes.io/service-account.uid: 4d66eb4c-42e9-11e7-9860-ee7d8982865f
  creationTimestamp: 2017-05-27T14:32:25Z
  name: jenkins-token-l9v7v
  namespace: default
  resourceVersion: "45558"
  selfLink: /api/v1/namespaces/default/secrets/jenkins-token-l9v7v
  uid: 4d697992-42e9-11e7-9860-ee7d8982865f
type: kubernetes.io/service-account-token

RBAC

Service Account为服务提供了一种方便的认证机制,但它不关心授权的问题。可以配合RBAC(Role Based Access Control)来为Service Account鉴权。如果要启用RBAC,请使用--authorization-mode=RBAC参数启动API Server。

Role和ClusterRole

在RBAC API中,一个角色包含了一套表示一组权限的规则。 权限以纯粹的累加形式累积(没有”否定”的规则)。 角色可以由namespace内的Role对象定义,而整个Kubernetes集群范围内有效的角色则通过ClusterRole对象实现。

一个Role对象只能用于授予对某一单一命名空间中资源的访问权限。 以下示例描述了”default”命名空间中的一个Role对象的定义,用于授予对pod的读访问权限:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # 空字符串""表明使用core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

ClusterRole对象可以授予与Role对象相同的权限,但由于它们属于集群范围对象, 也可以使用它们授予对以下几种资源的访问权限:

  • 集群范围资源(例如节点,即node)
  • 非资源类型endpoint(例如”/healthz”)
  • 跨所有命名空间的命名空间范围资源(例如pod,需要运行命令kubectl get pods --all-namespaces来查询集群中所有的pod)

下面示例中的ClusterRole定义可用于授予用户对某一特定命名空间或者所有命名空间(取决于其绑定方式)中的secret的读访问权限:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  # 鉴于ClusterRole是集群范围对象,所以这里不需要定义"namespace"字段
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

RoleBinding和ClusterRoleBinding

角色绑定将一个角色中定义的各种权限授予一个或者一组用户。 角色绑定包含了一组相关主体(即subject, 可选的subject包括用户User、用户组Group、或者服务账户Service Account)以及对被授予角色的引用。 在特定namespace中的授权可以通过RoleBinding对象授予权限,而集群范围的权限授予则通过ClusterRoleBinding对象完成。

RoleBinding只能引用在同一命名空间内定义的Role对象。下面的示例中将允许用户”jane”从”default”命名空间中读取pod。

# 以下角色绑定定义将允许用户"jane"从"default"命名空间中读取pod。
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

RoleBinding对象也可以引用一个ClusterRole对象,用于在RoleBinding所在的命名空间内授予用户对所引用的ClusterRole中 定义的命名空间资源的访问权限。这一点允许管理员在整个集群范围内首先定义一组通用的角色,然后再在不同的命名空间中复用这些角色。

# 以下角色绑定允许用户"dave"读取"development"命名空间中的secret。
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets
  namespace: development # 这里表明仅授权读取"development"命名空间中的资源。
subjects:
- kind: User
  name: dave
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

最后,可以使用ClusterRoleBinding在集群级别和所有命名空间中授予权限。下面示例中所定义的ClusterRoleBinding 允许在用户组”manager”中的任何用户都可以读取集群中任何命名空间中的secret。

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

一些例子

允许读取core API Group中定义的资源”pods”:

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"]

参考文章

  • https://jimmysong.io/kubernetes-handbook/guide/rbac.html
  • https://jimmysong.io/kubernetes-handbook/guide/configure-pod-service-account.html
  • https://cloud.tencent.com/developer/article/1186443
  • https://www.kubernetes.org.cn/service-account

你可能感兴趣的:(K8s ServiceAccount和RBAC)