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 <name> --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: "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,会把他们删除。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容