【K8S专栏】Kubernetes权限管理

简介: 【K8S专栏】Kubernetes权限管理

Kubernetes 主要通过 API Server 对外提供服务,对于这样的系统来说,如果不加以安全限制,那么可能导致请求被滥用,甚至导致整个集群崩塌。

鉴于此,Kubernetes 对于访问 API 的用户提供了相应的安全控制:认证和授权。认证解决用户是谁的问题,授权解决用户能做什么的问题。只有通过合理的权限控制,才能够保证整个集群系统的安全可靠。

下图是 API 访问需要经过的三个步骤,它们分别是:认证、授权和准入,准入不在这章节讨论,它更多专注的是资源的管理。

640.png

认证

认证(Authentication)是指用户是否可以登录 Kubernetes,即是否可以向 API Server 发送请求。

在 Kubernetes 中,有两类用户:

  • Normal Users:外部用户
  • Service Accounts:内部用户

认证用户

Normal Users

Normal Users 独立于 Kubernetes,不归其管理,这类用户可以是:

  • 可以分发 private keys 的管理员(真人)
  • 提供用户服务的第三方厂商,比如 Google Accounts
  • 保存用户名和密码的列表文件

如果用户都不在 Kubernetes 中,都不归它管,那它是如何进行认证的呢?

对于一般的应用系统来说,用户提供用户名和密码,服务端收到过后会在数据库中进行检查是否存在并有效,如果有就表示鉴权成功,反之失败。

那对于 Kubernetes 来说,是如何实现的呢?

尽管无法通过 API 调用来添加普通用户,Kubernetes 巧妙的通过证书来进行用户认证。也就是说,不管任何用户,只要能提供有效的证书就能通过 Kubernetes 用户认证。

通过用户认证过后,Kubernetes 会把证书中的 CN 作为用户名(比如证书中”/CN=joker“,则用户名就是 Joker),把 Organization 作为用户组,然后由用户名和用户组绑定的 Role 来决定用户的权限。

Service Accounts

Service Accounts 由 Kubernetes 管理,它们被绑定到特定的 namespace,其可以通过 API Server 自己创建,也可以通过调用 API 来创建,比如使用 kubectl 客户端工具。

与 Normal Users 不同,Service Accounts 存在对应的 Kubernetes 对象,当创建 Service Accounts,会创建相应的 Secret,里面保存对应的密码信息(在 1.24.x 版本中,不会创建对应的 secret)。当创建的 Pod 指定了一个 Service Account,其 Secret 会被 Mount 到 Pod 中,Pod 中的进程就可以访问 Kubernetes API 了。

认证策略

Kubernetes 有以下几种鉴权方法:

  • 客户端证书
  • 不记名令牌
  • 身份认证代理
  • 通过鉴权插件的 HTTP 基本认证机制

当 HTTP 请求发送到 API Server 时,Kubernetes 会从 Request 中关联以下信息:

  • Username:用户名,用来辨识最终用户的字符串,比如 kube-admin 或jane@example.com
  • UID:用户 ID,代表用户的唯一 ID
  • Groups:用户组,代表逻辑相关的一组用户,
  • Extra Fields,扩展字段,鉴权可能需要的其他信息

需要注意的是,当多种鉴权方法同时启用时,第一个鉴权方法鉴权成功即通过验证,其它方法不再鉴权,同时 api-server 也不保证鉴权方法的顺序。所有鉴权成功的用户都会加到 group “system:authenticated”中。

客户端证书

当我们使用客户端证书进进行认证时,需要向 Kubernetes 提供有效的证书,这个证书可以是外部证书,也可以是 Kubernetes 自己审批的证书。

如果是外部证书,就需要在 API Server 启动的时候用--client-ca-file=SOMEFILE参数引入外部证书的 CA 等信息,用来验证客户端证书的有效性。

当认证通过后,Kubernetes 会把证书的 Subject CN 作为用户名,Organization 作为用户组(Group)。

不记名令牌

当使用不记名令牌(Bearer token)来对某 HTTP 客户端执行身份认证时,API 服务器希望看到一个名为 Authorization 的 HTTP 头,其值格式为 Bearer。不记名令牌(Bearer token)必须是一个可以放入 HTTP 头部值字段的字符序列,至多可使用 HTTP 的编码和引用机制。例如:如果持有者令牌为 31ada4fd-adec-460c-809a-9e56ceb75269,则其出现在 HTTP 头部时如下所示:

Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269

在 Kubernetes 中,主要有以下几种使用不记名令牌(Bearer token)的方法:

  • Static Token File(静态令牌)
  • Service Account Tokens(服务账号令牌)
  • OpenID Connect Tokens(OIDC 令牌)

Static Token File

当使用静态令牌的时候,API Server 会通过--token-auth-file=SOMEFILE从外部引入一个 CSV 文件,API Server 会从这个文件中读取对应的用户名和用户组。

当客户端进行请求时,API Server 把请求 Header 中的 Bearer tokens 和文件中的 token 进行比较,然后判断 Token 是否有效。

Service Account Tokens

当手动或者自动创建 Service Account 的时候,Kubernetes 会自动创建一个 Service Account Token,在 v1.24 版本之前,会对应创建一个 secret 保存到对应的 namespace 中,在 v1.24 版本之后不会再单独创建 secret,而是在启动 Pod 的时候,由 kubelet 通过 TokenRequest API 生成一个 Token 挂载到 Pod 中。

上文提到,Service Account 主要是为 Pods 提供访问 API Server 的功能,当 Pod 创建过后,Service Account Token 就会被 Mount 到 Pod 中,此时 Pod 就拥有访问 API Server 的能力。

当然,Service Account Token 除了用在 Pod 上,在外部也可以使用,在《Kubernetes 集群管理》中的集群安装章节,有介绍使用 Token 访问 Kubernetes Dashboard,这时候使用的也是 Service Account Token。

OpenID Connect Tokens

OpenID Connect 是一种 OAuth2 认证方式,Kubernetes 可以利用 OAuth2 Token Response 中的 ID Token 作为 Bearer Token 进行认证访问。

其流程如下:

640.png

  1. 登录到你的身份服务(Identity Provider)
  2. 你的身份服务将为你提供 access_token、id_token 和 refresh_token
  3. 在使用 kubectl 时,将 id_token 设置为 --token 标志值,或者将其直接添加到 kubeconfig 中
  4. kubectl 将你的 id_token 放到一个称作 Authorization 的头部,发送给 API 服务器
  5. API 服务器将负责通过检查配置中引用的证书来确认 JWT 的签名是合法的
  6. 检查确认 id_token 尚未过期
  7. 确认用户有权限执行操作
  8. 鉴权成功之后,API 服务器向 kubectl 返回响应
  9. kubectl 向用户提供反馈信息

不管用户通过哪种方式进行认证,认证通过并不代表就有操作权限,仅仅只是通过第一条防线而已,下一步就要进行鉴权,用来决定用户是否有具体的操作权限。

鉴权

鉴权流程

当请求通过认证(Authentication)过后,就会进入鉴权(Authorization)阶段。在这个阶段 Kubernetes 会检查请求是否有权限访问需要的资源,如果有权限则开始处理请求,反之则返回权限不足。

API Server 会检查所有 Policy 来检查是否存在 Policy 允许请求中的动作,存在则允许请求执行,否则会拒绝执行并返回 403 错误。当配置了多个授权模块的时候,请求会按顺序校验每一个模板,如果其中任一模块校验不通过,则请求会被拒绝,不再进行后续的校验。

Kubernetes 在做鉴权时,主要检查以下信息:

  • user:同鉴权中检查的信息相同
  • group:同鉴权中检查的信息相同
  • extra:同鉴权中检查的信息相同
  • API:是否为 Api 资源
  • Request path:非资源(API 资源)endpoint,比如/healthz
  • API request verb:API 动作,比如 get, list, create, update, patch,对某个资源的具体动作,比如,列出所有的 pod
  • HTTP request verb:用于非资源的请求中的 HTTP 动作,比如 get, post, put
  • Resource:请求访问的资源名字或 ID
  • Subresource:请求访问的子资源名字或 ID
  • Namespace:资源所在的名字空间
  • API group:请求访问的 API group,API group 指控制相关资源的一组 Api,如果未指定则代表 core API group

鉴权模块

Kubernetes 提供了以下 4 种鉴权模式:

  • Node:一种特殊的授权模块,基于 Node 上运行的 Pod 为 Kubelet 授权
  • ABAC:基于属性的访问控制
  • RBAC:基于角色的访问控制
  • Webhook:HTTP 请求回调,通过一个 WEB 应用鉴定是否有权限进行某项操作

这里只会介绍 RBAC——基于角色的访问控制。在实际中,这种模式使用的场景比较多。

RBAC

RBAC 是 Kubernetes 中常用的鉴权模式,其基本概念如下:

  1. Rule:规则,一组属于不同 API Group 的操作集合;
  2. Role:角色,用于定义一组对 Kubernetes API 对象操作的一组规则,作用于当个 namespace;
  3. ClusterRole:集群角色,该角色不受 namespace 的限制;
  4. Subject:被作用者,也就是规则作用的对象;
  5. RoleBinding:将角色和被作用者进行绑定,作用于当个 namespace;
  6. ClusterRoleBinding:将集群角色和作用者进行绑定,不受 namespace 限制;

Role 和 ClusterRole

Role 和 ClusterRole 中定义一组相关权限的规则,这些权限是累加的(不存在拒绝某操作的规则)。其中 Role 是 Namespace 级别的,而 ClusterRole 是集群级别的。

Role 的定义如下:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: role-demo
  namespace: devops
rules:
- apiGroups: [""]
  resources: ["pods", "deployment"]
  verbs: ["creat", "delete", "watch", "list", "get"]

其含义是:它允许被作用者在 devops 的 namespace 中对 pod 和 deployment 有 creat,delete,watch,list,get 操作。由于 Role 是 Namespace 级别,所以上面的规则只对 devops 的 namespace 有效。

ClusterRole 的定义如下:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-role-demo
rules:
- apiGroups: [""]
  resources: [""]
  verbs: ["watch", "list", "get"]

其含义是对所有资源都有 watch、list、get 的操作权限。

如果要定义所有权限,可以将 verbs 字段定义如下:

verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

RoleBinding 和 ClusterRoleBinding

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

RoleBinding 可以引用在同一命名空间内定义的 Role 对象。如下:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: joker-rolebinding
  namespace: devops
subjects:
  - kind: User
    name: joker
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: role-demo
  apiGroup: rbac.authorization.k8s.io

这就给 joker 用户和 role-demo 的 Role 建立了绑定关系,其中 joker 这个 User 只是一个授权系统中的逻辑概念,它需要通过外部认证服务,比如 Keystone,或者直接给 API Server 指定一个用户名,密码文件。

上面的 YAML 文件中其中一个重要的字段是 Subjects 字段,它定义"被作用者",其中的 kind 表示被作用者的类型,其有以下三种类型:

  • User:用户,这是由外部独立服务进行管理的,管理员进行私钥的分配,用户可以使用 KeyStone 或者 Goolge 帐号,甚至一个用户名和密码的文件列表,对于用户的管理集群内部没有一个关联的资源对象,所以用户不能通过集群内部的 API 来进行管理。
  • Group:组,这是用来关联多个账户,集群中有一个默认的组,比如 cluster-admin。
  • ServiceAccount:服务帐号,通过 Kubernetes API 来管理的一些用户帐号,和 namespace 进行关联的,适用于集群内部运行的应用程序,需要通过 API 来完成权限认证,所以在集群内部进行权限操作,我们都需要使用到 ServiceAccount。

另外一个重要字段是 roleRef,它定义 RoleBing 对象可以直接通过 Role 的名字来引用我们定义的 Role 对象,从而定义被作业者和角色之间的绑定关系。

RoleBinding 是 namespace 级别的,如果是集群级别则用 ClusterRoleBinding,如下:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: joker-clusterrolebinding
subjects:
  - kind: User
    name: joker
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-role-demo
  apiGroup: rbac.authorization.k8s.io

上面定义的就是 joker 这个用户对所有 namespace 里的资源都有 watch,list,get 的操作权限。

Service Account

Service Account 也是一种账号,但它并不是给 Kubernetes 集群的用户(系统管理员、运维人员、租户用户等)用的,而是给运行在 Pod 里的进程用的,它为 Pod 里的进程提供了必要的身份证明。

我们通过一个例子来了解 ServiceAccount 的授权过程。1、首先定义一个 ServiceAccount:

apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: devops
  name: sa-demo

一个简单的 ServiceAccount 只需要简单的 namespace 和 name 即可。

2、编写 RoleBinding 的 YAML 文件来为这个 ServiceAccount 分配权限:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: role-demo
  namespace: devops
rules:
  - apiGroups: [""]
    resources: ["pods", "deployment"]
    verbs: ["creat", "delete", "watch", "list", "get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: sa-rolebinding
  namespace: devops
subjects:
  - kind: ServiceAccount
    name: sa-demo
    namespace: devops
roleRef:
  kind: Role
  name: role-demo
  apiGroup: rbac.authorization.k8s.io

然后我们创建上面定义的 YAML 文件,查看创建完成后的信息:

$ kubectl get sa -n devops
NAME      SECRETS   AGE
default   0         6m25s
sa-demo   0         6m25s
$ kubectl get role -n devops
NAME        CREATED AT
role-demo   2022-07-06T04:27:02Z
$ kubectl get rolebinding -n devops
NAME             ROLE             AGE
sa-rolebinding   Role/role-demo   6m50s

现在创建一个 Pod 并使用 sa-demo Service Account。

apiVersion: v1
kind: Pod
metadata:
  name: pod-sa-demo
  namespace: devops
spec:
  serviceAccountName: sa-demo
  containers:
  - name: pod-sa-demo
    image: nginx
    imagePullPolicy: IfNotPresent

查看 Pod 信息如下:

$ kubectl get po -n devops pod-sa-demo -oyaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    cni.projectcalico.org/containerID: c0820de4319bb6915602c84132ff83a63f62abaa1e9c706bad04e64661455d30
    cni.projectcalico.org/podIP: 172.16.51.225/32
    cni.projectcalico.org/podIPs: 172.16.51.225/32
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"pod-sa-demo","namespace":"devops"},"spec":{"containers":[{"image":"nginx","imagePullPolicy":"IfNotPresent","name":"pod-sa-demo"}],"serviceAccountName":"sa-demo"}}
  creationTimestamp: "2022-07-06T04:30:13Z"
  name: pod-sa-demo
  namespace: devops
  resourceVersion: "192831"
  uid: 4f4c7c5a-53ca-45f7-94ad-63e546cfcc62
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: pod-sa-demo
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: kube-api-access-vxrcd
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  nodeName: kk-node01
  preemptionPolicy: PreemptLowerPriority
  priority: 0
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext: {}
  serviceAccount: sa-demo
  serviceAccountName: sa-demo
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
  - effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
    tolerationSeconds: 300
  volumes:
  - name: kube-api-access-vxrcd
    projected:
      defaultMode: 420
      sources:
      - serviceAccountToken:
          expirationSeconds: 3607
          path: token
      - configMap:
          items:
          - key: ca.crt
            path: ca.crt
          name: kube-root-ca.crt
      - downwardAPI:
          items:
          - fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
            path: namespace

从上面可以看到 Service Account Token 被挂载到 Pod 中了。

$ kubectl exec -it -n devops pod-sa-demo -- /bin/sh
# ls /var/run/secrets/kubernetes.io/serviceaccount
ca.crt  namespace  token

其中 ca,crt 就是用来访问 API Server 的。

如果一个 Pod 在定义时没有指定 spec.serviceAccountName 属性,则系统会自动为其赋值为 default,即大家都使用同一个 Namespace 下的默认 Service Account。

Subjects 的 kind 类型除了 User,ServiceAccount 之外,还有一个 Group,就是一组用户的意思。如果你为 Kubernetes 配置了外部认证服务的话,这个用户组就由外部认证服务提供。而对于 Kubernetes 内置用户 ServiceAccount 来说,其也有用户和用户组的概念,其中对于一个 ServiceAccount,其在 Kubernetes 中对应的用户是:

system:serviceaccount:<ServiceAccount名字>

而对于其用户组是:

system:serviceaccounts:<Namespace名字>

比如我们定义下面这个 RoleBinding:

subjects:
  - kind: Group
    name: system:serviceaccounts:devops
    apiGroup: rbac.authorization.k8s.io

这就意味着 Role 这个角色的权限规则作用与 devops 的 namespace 中的所有 ServiceAccount。

再比如:

subjects:
  - kind: Group
    name: system:serviceaccounts
    apiGroup: rbac.authorization.k8s.io

这就意味着 Role 这个角色规则作用与整个集群的所有 ServiceAccount。

kubernetes 已经内置了许多 ClusterRole,以 system:开头,可以用 kubectl get clusterrole 查看。

另外,Kubernetes 还提供了四个预先定义好的 ClusterRole 来供用户直接使用,它们是:

  • cluster-admin:超管
  • admin:普通管理权限
  • edit:修改权限
  • view:只读权限

我们在定义 RoleBinding 或 ClusterRolebinding 的时候可以直接使用。

最后

Kubernetes 的权限管理就介绍到这里,本章节主要介绍了认证、授权的大概流程以及在 Kubernetes 中是如何实现认证、授权的。学完本章,你可以掌握认证用户有哪些,有哪些认证策略,以及如何使用 RBAC 实现鉴权。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
16天前
|
监控 Kubernetes Cloud Native
基于阿里云容器服务Kubernetes版(ACK)的微服务架构设计与实践
本文介绍了如何基于阿里云容器服务Kubernetes版(ACK)设计和实现微服务架构。首先概述了微服务架构的优势与挑战,如模块化、可扩展性及技术多样性。接着详细描述了ACK的核心功能,包括集群管理、应用管理、网络与安全、监控与日志等。在设计基于ACK的微服务架构时,需考虑服务拆分、通信、发现与负载均衡、配置管理、监控与日志以及CI/CD等方面。通过一个电商应用案例,展示了用户服务、商品服务、订单服务和支付服务的具体部署步骤。最后总结了ACK为微服务架构提供的强大支持,帮助应对各种挑战,构建高效可靠的云原生应用。
|
2月前
|
存储 运维 Kubernetes
正式开源,Doris Operator 支持高效 Kubernetes 容器化部署方案
飞轮科技推出了 Doris 的 Kubernetes Operator 开源项目(简称:Doris Operator),并捐赠给 Apache 基金会。该工具集成了原生 Kubernetes 资源的复杂管理能力,并融合了 Doris 组件间的分布式协同、用户集群形态的按需定制等经验,为用户提供了一个更简洁、高效、易用的容器化部署方案。
正式开源,Doris Operator 支持高效 Kubernetes 容器化部署方案
|
3月前
|
存储 Kubernetes Docker
Kubernetes(k8s)和Docker Compose本质区别
理解它们的区别和各自的优势,有助于选择合适的工具来满足特定的项目需求。
313 19
|
3月前
|
Kubernetes 应用服务中间件 nginx
二进制安装Kubernetes(k8s)v1.32.0
本指南提供了一个详细的步骤,用于在Linux系统上通过二进制文件安装Kubernetes(k8s)v1.32.0,支持IPv4+IPv6双栈。具体步骤包括环境准备、系统配置、组件安装和配置等。
1099 11
|
3月前
|
存储 Kubernetes 关系型数据库
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
本文源自2024云栖大会苏雅诗的演讲,探讨了K8s集群业务为何需要灾备及其重要性。文中强调了集群与业务高可用配置对稳定性的重要性,并指出人为误操作等风险,建议实施周期性和特定情况下的灾备措施。针对容器化业务,提出了灾备的新特性与需求,包括工作负载为核心、云资源信息的备份,以及有状态应用的数据保护。介绍了ACK推出的备份中心解决方案,支持命名空间、标签、资源类型等维度的备份,并具备存储卷数据保护功能,能够满足GitOps流程企业的特定需求。此外,还详细描述了备份中心的使用流程、控制台展示、灾备难点及解决方案等内容,展示了备份中心如何有效应对K8s集群资源和存储卷数据的灾备挑战。
|
4月前
|
Kubernetes Cloud Native API
深入理解Kubernetes——容器编排的王者之道
深入理解Kubernetes——容器编排的王者之道
82 1
|
4月前
|
Kubernetes Cloud Native 持续交付
深入理解Kubernetes:容器编排的基石
深入理解Kubernetes:容器编排的基石
|
1天前
|
人工智能 分布式计算 调度
打破资源边界、告别资源浪费:ACK One 多集群Spark和AI作业调度
ACK One多集群Spark作业调度,可以帮助您在不影响集群中正在运行的在线业务的前提下,打破资源边界,根据各集群实际剩余资源来进行调度,最大化您多集群中闲置资源的利用率。
|
12天前
|
Prometheus Kubernetes 监控
OpenAI故障复盘丨如何保障大规模K8s集群稳定性
OpenAI故障复盘丨如何保障大规模K8s集群稳定性
|
16天前
|
运维 分布式计算 Kubernetes
ACK One多集群Service帮助大批量应用跨集群无缝迁移
ACK One多集群Service可以帮助您,在无需关注服务间的依赖,和最小化迁移风险的前提下,完成跨集群无缝迁移大批量应用。

热门文章

最新文章