1. 安全机制

1.1 认证 (Authentication)

1.1.1 认证方式

  • HTTP Token:Authorization: Bearer $TOKEN

  • HTTP Basic: Authorization: Basic $(base64encode USERNAME:PASSWORD),

  • HTTPS: 基于CA根证书签名的客户端身份认证方式(推荐)

https

证书颁发:

  • 手动签发:通过k8s集群的根 ca 进行签发 HTTPS 证书
  • 自动签发:kubelet 首次访问 API Server 时,使用 token 认证通过后,Controller Manager 会为kubelet生成一个证书,以后的访问均使用该证书

1.1.2 认证方案

img

  • kubeconfig

    kubeconfig 文件包含集群参数(CA证书、API Server地址),客户端参数,集群context信息(集群名称、用户名)。k8s 组件通过启动时指定不同的 kubeconfig 文件可以切换到不同的集群cat ~/.kube/config

  • ServiceAccount

    Pod 中的容器访问API Server。因为Pod的创建和销毁是动态的,所以要为它手动生成证书是不可行的,k8s 使用 Service Account解决Pod访问API Server的认证问题

1.2 鉴权 (Authorization)

API Server的授权策略,通过启动参数--authorization-mode

  • AlwaysDeny: 拒绝所有请求,一般用于测试

  • AlwaysAllow: 接收所有请求。如果集群不需要授权流程,采用该策略

  • ABAC (Attribute-Based Access Control): 基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制

  • Webbook: 通过调用外部REST服务对用户进行授权

  • RBAC (Role-Based Access Control): 基于角色的访问控制,默认规则,其优点如下

    • 对集群中的资源和非资源均拥有完整的覆盖

    • 整个RBAC完全由几个API对象完成,同其他API对象一样,可以用kubectl或API进行操作

    • 可在运行时调整,无需重启API Server

1.3 准入控制

准入控制是 API Server 的插件集合,通过添加不同的插件,实现额外的准入控制规则

常见准入控制插件:

  • NamespaceLifecycle: 防止在不存在的namespace上创建对象;防止删除系统预置的namespace;删除namespace时,连带删除它下面的所有资源
  • LimitRanger: 确保请求的资源不会超过资源所在Namespace的LimitRange的限制
  • ServiceAccount: 实现自动化添加SA
  • ResourceQuota: 确保请求的资源不会超过资源的ResourceQuota限制

1.4 总结

API Server 是集群内部各个组件通讯的中介,也是外部控制的入口。k8s 使用认证(Authentication)、鉴权(Authorization)、准入控制(Admission Control) 三步来确保API Server的安全

认证 和鉴权:

  • 认证(authencation): 通过只代表通讯双方是可信的
  • 鉴权(authorization): 确定请求方有哪些资源权限

2. ServiceAccount

2.1 kubernetes 账户

  • UserAccount:给集群外用户访问 API Server,执行 kubectl 命令时用的就是该账号。它是全局性的,跨 namespace, 通常为admin,也可以自定义

    $ cat /root/.kube/config
    users:
    - name: cluster-admin
      user:
    
  • ServiceAccount:Pod 容器访问 API Server 的身份认证。它与 namespace 绑定,每个namespace 都会自动创建一个默认的 SA。创建 Pod 时,如果未指定 SA, 则使用默认的SA,可通过配置 spec.serviceAccount 指定 SA

    # default namespace SA
    $ kubectl get sa default -o yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: default
      namespace: default
    secrets:
    - name: default-token-gqgrp
    

2.2 什么是 SA

SA 是一种特殊的 secret,类型为 kubernetes.io/service-account-token,它由三部分组成:

  • token:由 API Server 私钥签发的 JWT,Pod访问API Server的凭证
  • ca.crt:根证书,用于Client端验证API Server发送的证书,与 /etc/kubernetes/pki/ca.pem 一致
  • namespace:该service-account-token的作用域名空间,Pod 所属 namespace
$ kubectl run -it nginx --rm --image=nginx -- /bin/bash
root@nginx:/# ls /run/secrets/kubernetes.io/serviceaccount
ca.crt  namespace  token

2.3 自定义 SA

$ kubectl create ns my-ns
$ kubectl create sa my-sa -n my-ns

$ kubectl get sa -n my-ns
NAME      SECRETS   AGE
default   1         18s
my-sa     1         12s

$ kubectl get secret -n my-ns
NAME                  TYPE                                  DATA   AGE
default-token-xp4hg   kubernetes.io/service-account-token   3      42s
my-sa-token-xs257     kubernetes.io/service-account-token   3      36s

Pod 中SA 配置:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-sa
  namespace: my-ns
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
  serviceAccountName: my-sa   # 指定 SA

3. RBAC

3.1 概述

ServiceAccount 是 APIServer 的认证过程,而授权机制通过 RBAC:基于角色的访问控制实现(Role-based access control )

auth

kubernetes 中所有资源对象都是模块化的 API 对象,允许执行 CRUD (Create, Read, Update, Delete) 操作:

  • 资源:pods,configmaps,deployments,nodes,secrets,namespaces,services 等

  • 动作:create,get,delete,list,update,edit,watch,exec,patch

API 对象在 Etcd 里的完整资源路径,由三部分组成:

  • Group:/apis/batch
  • Version:v1
  • Resource:cronjobs
# APIs
$ kubectl get --raw /
{
  "paths": [
    "/api",
    "/api/v1",
    "/apis",
    "/apis/",
    ......
    "/version"
  ]
}

# API 详情
kubectl get --raw /apis/batch/v1 | python3 -m json.tool
{
    "kind": "APIResourceList",
    "apiVersion": "v1",
    "groupVersion": "batch/v1",
    "resources": [
        {
            "name": "cronjobs",
            "singularName": "",
            "namespaced": true,
            "kind": "CronJob",
            "verbs": [
                "create",
                "delete",
                "deletecollection",
                "get",
                "list",
                "patch",
                "update",
                "watch"
            ],
            "shortNames": [
                "cj"
            ],
            "categories": [
                "all"
            ],
            "storageVersionHash": "h/JlFAZkyyY="
        },
   ...
}

3.2 Role & ClusterRole

Role:表示一组规则权限,权限只会增加(累加权限),它定义的规则,只适用于单个 namespace

ClusterRole:集群级别的权限控制

  • 集群级别资源控制,如 node 访问控制
  • 非资源型 endpoints,如对某个目录和文件的访问:/healthz
  • 所有命名空间资源控制 (Pod、Deployment等)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: my-role
  namespace: my-ns
rules:
- apiGroups: [""]   # 默认 core api group
  resources: ["pods"] 
  verbs: ["get","watch","list"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get","list","create","update","patch","delete","watch"]
  
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: my-clusterrole
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get","create","list"]

系统默认的 ClusterRole: cluster-admin,具有所有资源的管理权限

$ kubectl get clusterrole cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: cluster-admin
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
- nonResourceURLs:
  - '*'
  verbs:
  - '*'

3.3 Subject

尝试访问和操作 API Server 的对象:

  • UserAccount:集群外的用户账号
  • Group:用户组,集群中有一些默认创建的组,比如 cluster-admin
  • ServiceAccount:集群内的服务账号,它和 namespace 进行关联,适用于集群内部运行的应用程序,需要通过 API 来完成权限认证,所以在集群内部进行权限操作,我们都需要使用到 ServiceAccount

3.4 RoleBinding & ClusterRoleBinding

RoleBinding:将 Role 或 ClusterRole 授权给 Subject,它与 namespace 绑定

ClusterRoleBinding:将 ClusterRole 授权给 Subject,属于集群范围内的授权,与 namespace 无关

# 绑定 Role
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: my-rolebinding-1
  namespace: my-ns
subjects:
- kind: User    # 权限资源类型
  name: eli     # 名称
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: my-role
  apiGroup: rbac.authorization.k8s.io
  
# 绑定 ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: my-rolebinding-2
  namespace: my-ns
subjects:
- kind: User
  name: eli
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: my-clusterrole
  apiGroup: rbac.authorization.k8s.io
  
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: my-clusterrolebinding
subjects:
- kind: Group
  name: developer
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: my-clusterrole
  apiGroup: rbac.authorization.k8s.io

3.5 示例

3.5.1 UserAccount (namespace)

  • user: eli
  • organization:exped.top
  1. 创建用户凭证
# 创建私钥
openssl genrsa -out eli.key 2048

# 创建证书请求文件
openssl req -new -key eli.key -out eli.csr -subj "/CN=eli/O=exped.top"

# 使用CA证书签发证书
openssl x509 -req -in eli.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out eli.crt -days 365

# 在集群中创建用户凭证
kubectl config set-credentials eli --client-certificate=eli.crt --client-key=eli.key

# 创建上下文
kubectl config set-context eli-context --cluster=kubernetes --namespace=kube-system --user=eli

# 暂未给用户赋予任何权限,无法进行操作
kubectl get pods --context=eli-context
Error from server (Forbidden): pods is forbidd
  1. 创建角色并绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: eli-role
  namespace: kube-system
rules:
- apiGroups: ["", "apps"]
  resources: ["deployments", "replicasets", "pods"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: eli-rolebinding
  namespace: kube-system
subjects:
- kind: User
  name: eli
  apiGroup: ""
roleRef:
  kind: Role
  name: eli-role
  apiGroup: rbac.authorization.k8s.io 
  1. 验证
$  kubectl get deploy,rs,pod --context=eli-context
NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/calico-kube-controllers   1/1     1            1           23h
deployment.apps/coredns                   2/2     2            2           23h

NAME                                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/calico-kube-controllers-654b987fd9   1         1         1       23h
replicaset.apps/coredns-59d64cd4d4                   2         2         2       23h

NAME                                           READY   STATUS    RESTARTS   AGE
pod/calico-kube-controllers-654b987fd9-86w7m   1/1     Running   0          23h
pod/calico-node-5z74f                          1/1     Running   0          23h
pod/calico-node-bttbd                          1/1     Running   0          23h
pod/calico-node-gbgrz                          1/1     Running   0          23h
pod/coredns-59d64cd4d4-47jd5                   1/1     Running   0          23h
pod/coredns-59d64cd4d4-68zj9                   1/1     Running   0          23h
pod/etcd-k8s-master                            1/1     Running   0          23h
pod/kube-apiserver-k8s-master                  1/1     Running   0          23h
pod/kube-controller-manager-k8s-master         1/1     Running   0          23h
pod/kube-proxy-47cwt                           1/1     Running   0          23h
pod/kube-proxy-6g99p                           1/1     Running   0          23h
pod/kube-proxy-btjdf                           1/1     Running   0          23h
pod/kube-scheduler-k8s-master                  1/1     Running   0          23h

3.5.2 ServiceAccount (namespace)

apiVersion: v1
kind: ServiceAccount
metadata:
  name: eli-sa
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: eli-sa-role
  namespace: kube-system
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: eli-sa-rolebinding
  namespace: kube-system
subjects:
- kind: ServiceAccount
  name: eli-sa
  namespace: kube-system
roleRef:
  kind: Role
  name: eli-sa-role
  apiGroup: rbac.authorization.k8s.io

验证:

# 获取新建的SA信息
$ kubectl get secret -n kube-system | grep eli-sa
eli-sa-token-rltqf       kubernetes.io/service-account-token   3      39s

# 获取该SA的JWT,可使用它来作为Dashboard登录凭证
$ kubectl get secret eli-sa-token-rltqf -o jsonpath={.data.token} -n kube-system | base64 -d

注意:该 JWT 只能访问 kube-system 一个命名空间

3.5.3 ServiceAccount (cluster全局)

apiVersion: v1
kind: ServiceAccount
metadata:
  name: eli-sa
  namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: eli-sa-clusterrolebinding
subjects:
- kind: ServiceAccount
  name: eli-sa
  namespace: kube-system
roleRef:
  kind: ClusterRole
  name: cluster-admin   # 集群默认管理角色
  apiGroup: rbac.authorization.k8s.io

验证:

# 获取新建的SA信息
$ kubectl get secret -n kube-system | grep eli-sa
eli-sa-token-shhwv              kubernetes.io/service-account-token   3      35s

# 获取该SA的JWT,可使用它来作为Dashboard登录凭证
$ kubectl get secret eli-sa-token-shhwv -o jsonpath={.data.token} -n kube-system | base64 -d

注意:该 JWT 是全局性的,可访问所有命名空间

4. 准入控制器

准入控制器是一段代码,它会在请求通过认证和授权之后、对象被持久化之前拦截到达 API 服务器的请求。

启用和禁用准入控制器:

kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger ...
kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny ...

两个特殊的控制器:

  • MutatingAdmissionWebhook:执行变更准入控制的 webhook
  • ValidatingAdmissionWebhook:执行验证准入控制的 webhook

准入控制过程分为两个阶段,任何一个阶段控制器拒绝请求,则整个请求将立即被拒绝,并向终端返回一个错误:

  1. 运行变更准入控制器
  2. 运行验证准入控制器

常见准入控制器:

  • AlwaysPullImages:修改 Pod 时,强制重新拉取镜像
  • DefaultStorageClass:创建 PersistentVolumeClaim 时,不请求任何特定存储类的对象,并自动向其添加默认存储
  • DefaultTolerationSeconds:将Pod的容忍时间notready:NoExecuteunreachable:NoExecute 默认设置为5分钟
  • DenyEscalatingExec:拒绝 exec 和附加命令到以允许访问宿主机的升级了权限运行的pod
  • LimitPodHardAntiAffinityTopology:拒绝任何在 requiredDuringSchedulingRequiredDuringExecutionAntiAffinity 字段中定义除了kubernetes.io/hostname 之外的拓扑关键字的 pod
  • LimitRanger:确保所有资源请求不会超过 namespace 的 LimitRange
  • MutatingAdmissionWebhook:调用与请求匹配的任何变更 webhook。匹配的 webhook是串行调用的;如果需要,每个人都可以修改对象
  • NamespaceAutoProvision:检查命名空间资源上的所有传入请求,并检查引用的命名空间是否存在。如果不存在就创建一个命名空间
  • NamespaceExists:此检查除 Namespace 其自身之外的命名空间资源上的所有请求。如果请求引用的命名空间不存在,则拒绝该请求
  • NamespaceLifecycle:强制执行正在终止的命令空间中不能创建新对象,并确保Namespace拒绝不存在的请求。它还防止缺失三个系统保留的命名空间defaultkube-systemkube-public
  • NodeRestriction:限制 kubelet 可以修改的NodePod对象
  • OwnerReferencesPermissionEnforcement:保护对metadata.ownerReferences对象的访问,以便只有对该对象具有“删除”权限的用户才能对其进行更改
  • PodNodeSelector:通过读取命名空间注释和全局配置来限制可在命名空间内使用的节点选择器
  • PodPreset:注入一个pod,其中包含匹配的PodPreset中指定的字段
  • PodSecurityPolicy:用于创建和修改pod,并根据请求的安全上下文和可用的Pod安全策略确定是否应该允许它
  • PodTolerationRestriction:验证容器的容忍度与其命名空间的容忍度之间是否存在冲突,并在存在冲突时拒绝该容器请求
  • Priority:使用priorityClassName字段并填充优先级的整数值。如果未找到优先级,则拒绝Pod
  • ResourceQuota:观察传入请求并确保它不违反命名空间的ResourceQuota对象中列举的任何约束
  • SecurityContextDeny:拒绝任何试图设置某些升级的 SecurityContext 字段的pod
  • ServiceAccount:实现 ServiceAccounts 的自动化。
  • StorageObjectInUseProtection:将 kubernetes.io/pvc-protectionkubernetes.io/pv-protection finalizers 添加到新创建的持久化卷声明(PVC) 或持久化卷(PV)中。 如果用户尝试删除 PVC/PV,除非 PVC/PV 的保护控制器移除 finalizers,否则 PVC/PV 不会被删除
  • ValidatingAdmissionWebhook:调用与请求匹配的任何验证webhook。匹配的webhooks是并行调用的;如果其中任何一个拒绝请求,则请求失败。

5. Security Context

5.1 概述

kubernetes 提供了三种配置安全上下文级别的方法:

  • Container-level Security Context:应用到指定的容器
  • Pod-level Security Context:应用到 Pod 内所有容器和 Volume
  • Pod Security Policies (PSP):应用到集群内部所有 Pod 以及 Volume

pod.spec.securityContext 字段设置:

字段名详细说明
runAsNonRoot是否在运行容器前执行检查,以确保容器不以root用户运行(UID为0)
runAsUser运行容器entrypoint进程的UID,默认为Dockerfile中User指定的用户
runAsGroup运行容器entrypoint进程的GID,默认为容器引擎的GID
fsGroup数据卷GID控制,多个不同的容器操作同一份数据卷时,保存GID统一
supplementalGroups运行容器时的GID之外的附加组
seLinuxOptions它设定的SELinux上下文将被应用到Pod中的所有容器。如果不指定,容器引擎将随机分配一个
sysctls将给定的sysctls应用到Pod容器中
seccompProfile限制系统调用

pod.spec.containers.securityContext 字段设置:

字段名详细说明
runAsNonRoot同pod中的设置,同时存在时,以容器为准
runAsUser同pod中的设置,同时存在时,以容器为准
runAsGroup同pod中的设置,同时存在时,以容器为准
seLinuxOptions同pod中的设置,同时存在时,以容器为准
capabilities给某个特定的进行超级权限,而不用给root用户所有的 privileged 权限
allowPrivilegeEscalation定义了一个进程是否可以比其父进程获得更多的特权
privileged以特权模式运行
seccompProfile限制系统调用

5.2 Linux Capabilities

Linux 将传统上与超级用户 root 关联的特权划分为不同的单元,称为 capabilites。它的每个单元都可以独立启用和禁用。系统在作权限检查时:在执行特权操作时,如果进程的有效身份不是 root,就去检查是否具有该特权操作所对应的 capabilites,并以此决定是否可以进行该特权操作。详细说明:https://man7.org/linux/man-pages/man7/capabilities.7.html

使用 Capabilities:

$ getcap /bin/ping
/bin/ping = cap_net_admin,cap_net_raw+p

$ sudo setcap cap_net_admin,cap_net_raw-p /bin/ping
$ getcap /bin/ping
/bin/ping =

$ ping www.baidu.com
ping: socket: Operation not permitted

可执行文件的属性中有三个集合来保存三类 capabilities

  • Permitted:在进程执行时,Permitted 集合中的 capabilites 自动被加入到进程的 Permitted 集合中。
  • Inheritable:Inheritable 集合中的 capabilites 会与进程的 Inheritable 集合执行与操作,以确定进程在执行 execve 函数后哪些 capabilites 被继承。
  • Effective:Effective 只是一个 bit。如果设置为开启,那么在执行 execve 函数后,Permitted 集合中新增的 capabilities 会自动出现在进程的 Effective 集合中

5.3 实例

5.3.1 Pod Security Context

apiVersion: v1
kind: Pod
metadata:
  name: pod-sec-ctx
spec:
  volumes:
  - name: sec-ctx-vol
    emptyDir: {}
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  containers:
  - name: sec-ctx-demo
    image: busybox
    command: ["sh", "-c", "sleep 3600"]
    volumeMounts:
    - name: sec-ctx-vol
      mountPath: /mnt/data  # 该数据卷下创建的文件,其 GID 为2000
    securityContext:
      allowPrivilegeEscalation: false

验证:

$ kubectl exec -it pod-sec-ctx -- top
Mem: 3706896K used, 331828K free, 1804K shrd, 266016K buff, 2729800K cached
CPU:  2.5% usr  2.5% sys  0.0% nic 95.0% idle  0.0% io  0.0% irq  0.0% sirq
Load average: 1.93 0.99 0.40 2/397 13
  PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND
    7     0 1000     R     1324  0.0   0  0.0 top
    1     0 1000     S     1312  0.0   0  0.0 sleep 3600

$ kubectl exec -it pod-sec-ctx -- id
uid=1000 gid=3000 groups=2000

$ kubectl exec -it pod-sec-ctx -- ls -l /mnt
total 4
drwxrwsrwx    2 root     2000          4096 Feb 27 07:12 data

5.3.2 容器 Security Context

apiVersion: v1
kind: Pod
metadata:
  name: container-sec-ctx
spec:
  securityContext:
    runAsUser: 1000
  containers:
  - name: sec-ctx-demo
    image: busybox
    command: [ "sh", "-c", "sleep 3600" ]
    securityContext:
      runAsUser: 2000
      allowPrivilegeEscalation: false

验证:

$ kubectl exec -it container-sec-ctx -- top
Mem: 3268492K used, 770232K free, 1644K shrd, 284924K buff, 2115456K cached
CPU:  0.8% usr  0.6% sys  0.0% nic 98.4% idle  0.0% io  0.0% irq  0.0% sirq
Load average: 0.17 0.16 0.11 2/361 12
  PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND
    7     0 2000     R     1324  0.0   2  0.0 top
    1     0 2000     S     1312  0.0   2  0.0 sleep 3600

5.3.3 Capabilities

apiVersion: v1
kind: Pod
metadata:
  name: container-sec-ctx-cap
spec:
  containers:
  - name: cpb
    image: busybox
    args:
    - sleep
    - "3600"
    securityContext:
      capabilities:
        add: 
        - NET_ADMIN
        drop:
        - KILL

6. 普通用户管理集群

6.1 创建用户

# 创建 namespace
kubectl create ns eli

# 创建用户
useradd -s /bin/bash -d /home/eli -m eli
su - eli

$ kubectl get pod
The connection to the server localhost:8080 was refused - did you specify the right host or port?

6.2 创建证书

mkdir -p /root/certs && cd $_

cat > eli-csr.json <<EOF
{
  "CN": "eli",    
  "hosts": [],  
  "key": {
    "algo": "rsa", 
    "size": 2048
},
  "names": [
    {
       "C": "CN",
       "L": "Nanjing",
       "O": "k8s",
       "ST": "Jiangsu",            
       "OU": "System"
    }
  ]
}
EOF

cd /etc/kubernetes/pki

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -profile=kubernetes /root/certs/eli-csr.json | cfssljson -bare eli

6.3 生成集群配置

cd /root/certs

export KUBE_APISERVER="https://192.168.80.240:6443"

# 创建 kubeconfig
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.pem \
--embed-certs=true --server=${KUBE_APISERVER} \
--kubeconfig=eli.kubeconfig

# 设置客户端参数,绑定用户到 kubeconfig
kubectl config set-credentials eli \
--client-certificate=/etc/kubernetes/pki/eli.pem \
--client-key=/etc/kubernetes/pki/eli-key.pem \
--embed-certs=true \
--kubeconfig=eli.kubeconfig

# 设置上下文
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=eli \
--namespace=eli \
--kubeconfig=eli.kubeconfig

6.4 创建角色并绑定

cat > eli-role.yaml <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: admin
  namespace: eli
rules:
- apiGroups: [""] 
  resources: ["pods"] 
  verbs: ["get","watch","list"]  
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get","list","create","update","patch","delete","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: admin
  namespace: eli
subjects:
- kind: User
  name: eli
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: admin
  apiGroup: rbac.authorization.k8s.io
EOF

kubectl apply -f eli-role.yml

6.5 验证权限

# 复制配置
mkdir -p /home/eli/.kube
cp eli.kubeconfig /home/eli/.kube/config
chown -R eli:eli /home/eli/.kube

# 切换用户
su - eli

# 切换上下文,使 Kubectl 读取到config 信息
$ kubectl config use-context kubernetes --kubeconfig=.kube/config

# 验证
$ kubectl get pod
No resources found in eli namespace.

$ kubectl get svc
Error from server (Forbidden): services is forbidden: User "eli" cannot list resource "services" in API group "" in the namespace "eli"

# 创建 deployment
$ kubectl create deployment nginx --replicas=10 --image=nginx --port-80

$ kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
nginx-7848d4b86f-2j7lt   1/1     Running   0          86s
nginx-7848d4b86f-89l2d   1/1     Running   0          86s
nginx-7848d4b86f-9tf57   1/1     Running   0          86s
nginx-7848d4b86f-bhhz2   1/1     Running   0          86s
nginx-7848d4b86f-ft7fv   1/1     Running   0          86s
nginx-7848d4b86f-l7vqn   1/1     Running   0          86s
nginx-7848d4b86f-qrkvh   1/1     Running   0          86s
nginx-7848d4b86f-sjpch   1/1     Running   0          86s
nginx-7848d4b86f-wvm4n   1/1     Running   0          86s
nginx-7848d4b86f-xwnsf   1/1     Running   0          86s
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐