【DevOps基础篇之k8s】如何应用Kubernetes中的Role Based Access Control(RBAC)

2019-09-10T13:11:33+08:00 | 9分钟阅读 | 更新于 2019-09-10T13:11:33+08:00

Macro Zhao

【DevOps基础篇之k8s】如何应用Kubernetes中的Role Based Access Control(RBAC)

@TOC

推荐超级课程:

背景

访问控制过程和技术使您能够控制应用程序和用户是否被允许或被拒绝访问或权限。 访问控制是Kubernetes安全的基础。Kubernetes提供了两种主要的访问控制选项,基于角色的访问控制(RBAC)基于属性的访问控制(ABAC)

在本文中,我将讨论RBAC。

Kubernetes身份验证和授权

假设您使用kubectl apply命令部署一个pod。 当您输入kubectl apply时,会发生一些事情, 1)从您的KUBECONFIG读取配置, 2)从API中发现API和对象, 3)在客户端验证资源(是否有任何明显的错误?), 4)将携带有效载荷的请求发送到kube-apiserver。

当kube-apiserver接收到请求时,它不会立即将其存储在etcd中。 首先,它必须验证请求者的合法性。换句话说,它必须对请求进行身份验证。 仅仅因为您可以访问集群并不意味着您可以创建或读取所有资源。 因此,一旦经过身份验证,它会检查请求者是否具有创建资源的权限。 换句话说,检查请求授权。授权通常使用基于角色的访问控制(RBAC)完成。

下面的图表显示了API服务器处理这些身份验证和授权请求的流程。

基于角色的访问控制(RBAC)

如果您在您的组织中有一个小团队和小型集群设置(例如仅包含几个节点),您可能还没有一种系统化的方式处理授权。也许您甚至授予团队中的每个人集群管理员权限,以简化管理。 但并非每个用户都需要无限制地创建、修改和删除资源的能力。 随着集群节点、应用程序和团队成员数量的增加,您将希望限制团队成员和应用程序可以访问的资源,以及他们可以执行的操作。

Kubernetes中的RBAC框架允许您做到这一点。 例如,它可以帮助确保开发人员只能将某些应用程序部署到给定的命名空间,或者确保您的基础设施管理团队具有用于监控任务的只读访问权限。 基本上,RBAC通过使用附加到用户身上的角色来定义限制和控制用户对系统资源的访问的策略。

用户账户 vs. 服务账户

在Kubernetes中,RBAC权限/策略可用于定义人类用户(或人类用户组)的访问权限。Kubernetes将人类用户标识为用户账户。但是,RBAC策略也可以管理软件资源的行为,Kubernetes将其标识为服务账户。服务账户为在pod中运行的进程提供了身份。服务账户不是用户账户。 用户账户由管理员和开发人员等使用,用于访问集群并进行一些开发工作或维护。 服务账户用于应用程序和进程在与ApiServer交谈时进行身份验证。并且这些服务账户可以通过Kubernetes RBAC受限制。 这使您可以对过程/应用程序进行身份验证和限制访问以及该过程/应用程序可以做些什么。

每个命名空间都有一个默认的服务账户。 并且如果创建时没有指定服务账户,则创建的每个pod都会分配默认的服务账户(并在其中安装令牌作为Secrets),尽管它的权限非常有限。 因此,如果想要为应用程序授予更多权限,或者想要自定义控制,您应该为您的应用程序或进程创建一个服务账户。

角色 vs. 集群角色

RBAC授权可以定义限制在命名空间内或整个集群内的权限/策略。 为此,您可以定义一组权限,称为角色,它在给定命名空间内定义。 如果想要在整个集群中定义角色,则称之为集群角色。 基本上,集群角色和角色分别定义用户在集群或命名空间内可以执行的操作。 Kubernetes允许您配置自定义角色或使用默认用户界面角色(例如集群管理员、管理员、编辑、查看)。

RoleBinding vs. ClusterRoleBinding

您可以将角色和集群角色分配给Kubernetes主体(例如用户、用户组或服务账户)。 角色可以通过RoleBindings分配给主体(例如用户、用户组或服务账户),集群角色可以通过ClusterRoleBindings分配给主体(例如用户、用户组或服务账户)。 在本文中,我将讨论使用RoleBindings和ClusterRoleBindings为服务账户分配角色和集群角色,处理Kubernetes RBAC策略。 有两种主要的权限处理类型, 1)在命名空间范围内处理RBAC策略, 2)在集群范围内处理RBAC策略。

1. 命名空间范围内的RBAC策略

首先,我测试了命名空间范围内的RBAC策略功能,通过Role和RoleBinding将服务账户权限分配给命名空间。 为此,我创建了命名空间、服务账户,使用Role定义了命名空间策略,并通过RoleBinding将这些策略分配给服务账户。

1.1. 创建命名空间 首先,我检查了Kubernetes集群中的RBAC功能是否启用。然后创建了一个名为rahasak的命名空间。

# verify k8s rbac installed 
❯❯ kubectl api-versions | grep rbac
rbac.authorization.k8s.io/v1


---


# create namespace 
kubectl create namespace rahasak

❯❯ kubectl get ns
NAME              STATUS   AGE
default           Active   20h
kube-node-lease   Active   20h
kube-public       Active   20h
kube-system       Active   20h
rahasak           Active   20h

1.2. 创建服务账户 以下是创建服务账户的方式。我将此服务账户分配到先前创建的rahasak命名空间中。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: rahasak-serviceaccount
  namespace: rahasak
# create service account
kubectl apply -f rahasak-service-account.yaml

# view service accounts
# service account created in rahasak namespace
❯❯ kubectl get serviceaccounts -n rahasak
NAME                     SECRETS   AGE
default                  1         20h
rahasak-serviceaccount   1         10s

服务账户具有一个令牌。我刚刚创建的一个命名为rahasak-serviceaccount-token-vntdr。 此令牌存储为KubernetesSecrets,可以作为Secrets读取。这个令牌是您用来将第三方应用程序身份验证到Kubernetes ApiServer的令牌。

# view service account token 
❯❯ kubectl describe serviceaccount rahasak-serviceaccount -n rahasak

Name:                rahasak-serviceaccount
Namespace:           rahasak
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   rahasak-serviceaccount-token-vntdr
Tokens:              rahasak-serviceaccount-token-vntdr
Events:              <none>

# token is stored as a secret, so it can be viewed with token name
❯❯ kubectl describe secret rahasak-serviceaccount-token-vntdr -n rahasak
Name:         rahasak-serviceaccount-token-vntdr
Namespace:    rahasak
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: rahasak-serviceaccount
              kubernetes.io/service-account.uid: 237ec5f9-0050-402a-a553-72f26c39a11c

Type:  kubernetes.io/service-account-token

Data
====
token:      xxxxxxxxxx-xxx_mxxx6j_xxxxx
ca.crt:     1111 bytes
namespace:  7 bytes

1.3. 创建角色 以下是创建具有不同权限的角色的方法。此角色定义可以在rahasak命名空间中执行的操作(get, watch, list)只能作用于资源pod。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: rahasak
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

1.4. 创建RoleBinding 可以通过RoleBinding将此角色分配给服务账户。因此,服务账户只能在rahasak命名空间中列出、获取、观察pod。

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader-binding
  namespace: rahasak
roleRef: # points to the Role
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pod-reader # name of Role
subjects: # points to the ServiceAccount
- kind: ServiceAccount
  name: rahasak-serviceaccount # service account to bind to
  namespace: rahasak # ns of service account
  
# create role
kubectl apply -f rahasak-role.yaml

# list roles in rahasak namespace
❯❯ kubectl get roles -n rahasak
NAME         CREATED AT
pod-reader   2022-06-17T01:00:35Z

# describe role permissions
❯❯ kubectl describe role pod-reader -n rahasak
Name:         pod-reader
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [get watch list]
  

1.5. 测试权限 为了测试分配给服务账户的权限,我使用了一个内含kubectl命令的自定义pod。 这个pod是可用的bibinwilson/docker-kubectl Docker镜像。 我使用这个Docker镜像创建了一个pod,并分配了rahasak-serviceaccount给它。 因此,该pod应该只允许执行角色中指定的权限(例如在rahasak命名空间中列出、获取、观察pod)。 我已部署了这个pod,通过kubectl exec连接到pod并检查它是否具有我们在角色中提到的权限。

apiVersion: v1
kind: Pod
metadata:
  name: rahasak-kubectl
  namespace: rahasak
spec:
  containers:
  - image: bibinwilson/docker-kubectl:latest
    name: kubectl
  serviceAccountName: rahasak-serviceaccount
  
# deploy pod with kubectl
kubectl apply -f rahasak-kubectl.yaml

# list pods
❯❯ kubectl get pods -n rahasak
NAME              READY   STATUS    RESTARTS       AGE
rahasak-kubectl   1/1     Running   0              4s

# connect to kubectl pod
kubectl exec -it --namespace=rahasak rahasak-kubectl -- /bin/bash

# check list pod permission in rahasak
# permission should be there
root@debug-kubectl:/# kubectl get pods -n rahasak
NAME            READY   STATUS    RESTARTS       AGE
busybox         1/1     Running   10 (28m ago)   20h
debug-kubectl   1/1     Running   0              97s
nginx           1/1     Running   0              21h

# check list pod permission in bassa
# give forbidden error
root@debug-kubectl:/# kubectl get pods -n bassa
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:rahasak:rahasak-serviceaccount" cannot list resource "pods" in API group "" in the namespace "bassa"

# check list services permission
# give forbidden error
kubectl get svc
Error from server (Forbidden): services is forbidden: User "system:serviceaccount:rahasak:rahasak-serviceaccount" cannot list resource "services" in API group "" in the namespace "rahasak"

2. 集群范围内的RBAC策略

其次,我测试了分配集群范围服务账户权限的集群范围RBAC策略,通过ClusterRole和ClusterRoleBinding定义集群策略,并通过ClusterRoleBinding将这些策略分配给服务账户。 为此,我创建了命名空间、服务账户,使用ClusterRole定义了集群策略,并通过ClusterRoleBinding将这些策略分配给服务账户。

2.1. 创建命名空间 我为这种情景创建了一个名为bassa的不同的命名空间(之前创建的命名空间,rahasak)。

# create namespace 
kubectl create namespace bassa

❯❯ kubectl get ns
NAME              STATUS   AGE
bassa             Active   5s
default           Active   21h
kube-node-lease   Active   21h
kube-public       Active   21h
kube-system       Active   21h
rahasak           Active   21h

2.2. 创建服务账户 以下是创建服务账户的方式。我将此服务账户分配到bassa命名空间中。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: bassa-serviceaccount
  namespace: bassa
# create service account
kubectl apply -f bassa-service-account.yaml

# view service accounts
# service account created in bassa namespace
❯❯ kubectl get serviceaccounts -n bassa
NAME                   SECRETS   AGE
bassa-serviceaccount   1         6s
default                1         2m49s

2.3. 创建ClusterRole 以下是创建具有不同权限的ClusterRole的方法。此角色定义可以在整个集群中对资源pod执行的操作(获取、观察、列出)。由于ClusterRoles不具有命名空间,所以ClusterRole的命名空间被省略。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  # namespace: bassa
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
  
# create cluster role
kubectl apply -f bassa-cluster-role.yaml

# list cluster roles 
❯❯ kubectl get clusterroles | grep pod-reader
NAME                                                                   CREATED AT
pod-reader                                                             2022-06-17T02:01:43Z

# describe cluster role permissions
❯❯ kubectl describe clusterrole pod-reader
Name:         pod-reader
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [get watch list]
  

2.4. 创建ClusterRoleBinding 可以通过ClusterRoleBinding将此ClusterRole分配给服务账户。因此,服务账户可以在集群中的所有命名空间中列出、获取、观察pod。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: pod-reader-binding
  namespace: bassa
roleRef: # points to the ClusterRole
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: pod-reader # name of ClusterRole
subjects: # points to the ServiceAccount
- kind: ServiceAccount
  name: bassa-serviceaccount # service account to bind to
  namespace: bassa # ns of service account
  

Test:

# create cluster role binding
kubectl apply -f bassa-cluster-role-binding.yaml

# list cluster role binding
kubectl get clusterrolebindings.rbac.authorization.k8s.io | grep pod-reader
NAME                                                   ROLE                                                                               AGE
pod-reader-binding                                     ClusterRole/pod-reader                                                             35s

# describe clusetr role binding
❯❯ kubectl describe clusterrolebindings pod-reader-binding
Name:         pod-reader-binding
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  pod-reader
Subjects:
  Kind            Name                  Namespace
  ----            ----                  ---------
  ServiceAccount  bassa-serviceaccount  bassa
  

2.5. 测试权限 与以前的情景类似,为了测试分配给服务账户的权限,我使用了一个内含kubectl命令的自定义pod。这个pod是可用的bibinwilson/docker-kubectl Docker镜像。我使用这个Docker镜像创建了一个pod,并将bassa-serviceaccount分配给它。因此,该pod应该只允许执行ClusterRole中指定的权限(例如在集群中的所有命名空间中列出、获取、观察pod)。我已部署了这个pod,通过kubectl exec连接到pod并检查它是否具有我们在ClusterRole中提到的权限。

apiVersion: v1
kind: Pod
metadata:
  name: bassa-kubectl
  namespace: bassa
spec:
  containers:
  - image: bibinwilson/docker-kubectl:latest
    name: kubectl
  serviceAccountName: bassa-serviceaccount
  

Test:

# deploy pod with kubectl
kubectl apply -f bassa-kubectl.yaml

# list pods
❯❯ kubectl get pods -n bassa
NAME            READY   STATUS    RESTARTS   AGE
bassa-kubectl   1/1     Running   0          14s

# connect to kubectl pod
kubectl exec -it --namespace=bassa bassa-kubectl -- /bin/bash

# check list pod permission in bassa namespace
# permission should be there
root@bassa-kubectl:/# kubectl get pods -n bassa
NAME            READY   STATUS    RESTARTS   AGE
bassa-kubectl   1/1     Running   0          57s

# check list pod permission in rahasak namespace
# permission should be there
root@bassa-kubectl:/# kubectl get pods -n rahasak
NAME            READY   STATUS    RESTARTS         AGE
busybox         1/1     Running   11 (7m47s ago)   21h
debug-kubectl   1/1     Running   0                40m
nginx           1/1     Running   0                21h

# check list services permission
# give forbidden error
kubectl get svc
Error from server (Forbidden): services is forbidden: User "system:serviceaccount:rahasak:rahasak-serviceaccount" cannot list resource "services" in API group "" in the namespace "rahasak"

© 2011 - 2025 Macro Zhao的分享站

关于我

如遇到加载502错误,请尝试刷新😄

Hi,欢迎访问 Macro Zhao 的博客。Macro Zhao(或 Macro)是我在互联网上经常使用的名字。

我是一个热衷于技术探索和分享的IT工程师,在这里我会记录分享一些关于技术、工作和生活上的事情。

我的CSDN博客:
https://macro-zhao.blog.csdn.net/

欢迎你通过评论或者邮件与我交流。
Mail Me

推荐好玩(You'll Like)
  • AI 动·画
    • 这是一款有趣·免费的能让您画的画中的角色动起来的AI工具。
    • 支持几十种动作生成。
我的项目(My Projects)
  • 爱学习网

  • 小乙日语App

    • 这是一个帮助日语学习者学习日语的App。
      (当然初衷也是为了自用😄)
    • 界面干净,简洁,漂亮!
    • 其中包含 N1 + N2 的全部单词和语法。
    • 不需注册,更不需要订阅!完全免费!
  • 小乙日文阅读器

    • 词汇不够?照样能读日语名著!
    • 越读积累越多,积跬步致千里!
    • 哪里不会点哪里!妈妈再也不担心我读不了原版读物了!
赞助我(Sponsor Me)

如果你喜欢我的作品或者发现它们对你有所帮助,可以考虑给我买一杯咖啡 ☕️。这将激励我在未来创作和分享更多的项目和技术。🦾

👉 请我喝一杯咖啡

If you like my works or find them helpful, please consider buying me a cup of coffee ☕️. It inspires me to create and share more projects in the future. 🦾

👉 Buy me a coffee