K8s 权限和认证

ServiceAccount

ServiceAccount是专供pod使用的,权限管理中的一种身份标记。ServiceAccount的作用范围是namespace。

创建ServiceAccount

创建ServiceAccount如下两种方式:

  1. 使用描述文件
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-service-account
  1. 使用命令行
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步:

  1. 创建一个secret。包含docker镜像托管服务器地址,用户名和密码等。
kubectl create secret docker-registry  --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
  1. 在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: "[email protected]"
  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,会把他们删除。

你可能感兴趣的:(K8s 权限和认证)