Skip to content

在11章 k8s 认证-授权-准入控制

本章所讲内容:

11.1 k8s 安全管理:认证、授权、准入控制概述

11.2 对 serviceaccount 和 user 用户做授权

11.3 模拟攻击 k8s 核心组件 apiserver

11.4 ResourceQuota 准入控制器

11.5 基于 Trivy 对镜像进行漏洞扫描

11.1 k8s 安全管理:认证、授权、准入控制概述

  • 认证:(Authentication)判断是否为自己人
  • 鉴权:(Authorization)判断是否有权限
  • 准入控制:(Admission Control)有权限,判断操作是否合理

11.1.1 认证

​ 在 Kubernetes 中,认证是确保用户和组织身份验证的过程,以便他们能够安全地访问和操作集群中的资源。

​ Kubernetes 的认证基于一种称为"证书"的机制,该机制使用了公钥/私钥加密技术。下面是Kubernetes 认证的基本过程:

1、用户:在 Kubernetes 中,用户是指与集群交互的个体或实体。用户可以是开发人员、管理员或其他授权的实体。如 kubecconfig 文件里的 user 用户或者 sa 资源

2、身份验证器(Authenticator):身份验证器负责验证用户的身份并生成一个身份验证令牌。 Kubernetes 支持多种身份验证器,包括基于用户名和密码的身份验证、证书身份验证、LDAP 等。

3、证书:证书是一种用于身份验证和加密通信的数字凭证。在 Kubernetes 中,证书是通过公钥/ 私钥加密技术创建的。证书通常包含一个公钥和与之对应的私钥。

4、证书颁发机构(Certificate Authority,CA):CA 是负责颁发和管理证书的实体。 Kubernetes 集群通常有一个内置的 CA,也可以使用外部的 CA。CA 负责为用户和组织生成证书,并对证书进行签名以确保其有效性。

5、颁发身份验证令牌:一旦用户通过身份验证,身份验证器将颁发一个身份验证令牌。令牌是一个短暂的凭证,包含有关用户身份的信息,如用户名、角色等。

​ 总结来说,Kubernetes 的认证机制基于证书和令牌的方式,通过身份验证器验证用户身份并生成令牌,令牌用于访问和操作 k8s 集群资源。这种认证机制确保了对 Kubernetes 集群的安全访问和管理。

11.1.2 授权

​ Kubernetes(K8s)授权是确保用户在集群中访问和执行操作时拥有适当权限的过程。授权机制用于确定用户对集群资源的访问级别,并防止未经授权的访问和操作。下面是 Kubernetes 授权的基本过程:

1、角色(Roles)和角色绑定(Role Bindings):角色定义了一组权限,用于指定用户或组对特定资源的操作权限。角色绑定用于将角色与用户或组相关联,以赋予它们相应的权限。

2、ClusterRole(集群角色)和 ClusterRoleBinding(集群角色绑定):与 Role 和 RoleBinding类似,ClusterRole 和 ClusterRoleBinding 也是用于授权,但作用范围是整个集群,而不仅限于单个命名空间

2、Role-Based Access Control(RBAC):RBAC 是 Kubernetes 中最常用的授权机制。RBAC 允许管理员根据角色和权限的组合来定义和管理用户对资源的访问权限。RBAC 定义了一套规则和策略,以控制谁可以对哪些资源执行哪些操作。

3、Service Account(服务账户):Service Account 是由 Kubernetes 自动创建的一种资源,用于代表运行在 k8s 集群中的 pod 里的进程具有的权限。Service Account 可以与角色或者集群角色绑定, 以授予 pod 里的进程特定的权限。

4、Namespace(命名空间)级别的授权:Kubernetes 还支持基于命名空间的 RBAC 授权策略。通过在命名空间级别定义 Role 和 RoleBinding,可以在不同的命名空间中实现不同的权限设置。

5、Verb(动词)级别的授权:Kubernetes 的 RBAC 授权策略可以基于不同的动词对资源执行的操作进行控制。例如,可以定义只允许读取(get)资源但禁止修改(update)资源的权限。

6、Resource(资源)级别的授权:RBAC 授权策略可以基于资源类型进行控制。管理员可以精确指定允许或拒绝对某些资源类型执行特定操作的权限。

​ 通过这些 RBAC 授权策略,管理员可以根据需求和安全要求对 Kubernetes 集群中的用户、组和服务账户进行精细的权限控制。这样可以确保只有经过授权的实体才能访问和操作集群资源,从而提高集群的安全性和可管理性。

11.1.3 准入控制

​ Kubernetes(K8s)准入控制是一种机制,用于对将被接受或拒绝加入到集群中的资源进行审查和筛选。准入控制可以帮助管理员在资源创建、更新或删除之前对其进行验证和控制,以确保集群的安全性、稳定性和一致性。下面是 Kubernetes 准入控制的基本过程:

1、准入控制器(Admission Controller):准入控制器是 Kubernetes 集群中的一种插件机制,用于在资源提交到 API 服务器之前进行验证和筛选。它可以根据预定义的规则和策略来检查请求,包括资源对象的结构、标签、注释等。

2、准入控制器类型:Kubernetes 提供了多种准入控制器类型,每种类型都可以应用不同的策略和规则。常见的准入控制器类型包括:

1)AlwaysPullImages:确保容器镜像总是从可信的镜像仓库拉取。

2)DenyEscalatingExec:阻止 Pod 中的用户通过执行特权容器来提升权限。

3)ImagePolicyWebhook:根据镜像策略对容器镜像进行验证和审查。

4)NamespaceLifecycle:确保命名空间的生命周期符合规定的策略。

5)PodSecurityPolicy:检查 Pod 的安全配置是否符合集群定义的安全策略。

3、配置准入控制器:准入控制器可以通过 Kubernetes API 服务器的参数或配置文件进行配置。管理员可以根据需求启用或禁用特定的准入控制器,并设置其参数和规则。

4、准入控制规则:每个准入控制器都有自己的规则和策略,用于定义资源的接受或拒绝条件。这些规则可以基于多个因素,如标签、注释、资源限制、网络策略等。

5、审核日志:准入控制器可以生成审计日志,记录对资源请求的处理情况。这些日志对于审计、故障排除和安全审查非常有价值。

​ 通过准入控制,管理员可以实施一系列的策略和规则,对集群中的资源进行审查和筛选。这有助于确保只有符合规定条件的资源可以加入到集群中,并提供一定程度的安全保障。准入控制器的灵活性和可扩展性使得管理员可以根据集群需求和策略定制化地配置和管理准入控制的行为。

11.2 对serviceaccount 和user 用户做授权

11.2.1 对 ServiceAccount 做授权

1、Kubernetes 在创建Pod 时,默认将 token、ca.crt 和 namespace 这三个文件挂载到 Pod 的/var/run/secrets/kubernetes.io/serviceaccount 目录下。

备注:

Token(令牌): token 文件包含一个用于身份验证的令牌(Token),用于标识 Pod 与 Kubernetes集群之间的信任关系。Pod 可以使用该令牌与 API 服务器进行通信,并执行特定的操作,例如获取 Pod自身的信息、访问其他资源等。

ca.crt(证书): ca.crt 文件是 Kubernetes 集群的根证书,用于验证与 API 服务器的通信。该证书用于建立安全的连接,并确保通信的机密性和完整性。Pod 可以使用此证书验证 API 服务器的身份,以确保与正确的集群进行通信。

Namespace(命名空间):namespace 文件包含Pod 所属的命名空间名称。命名空间是 Kubernetes中用于隔离和组织资源的一种机制。Pod 通过读取此文件可以确定自己所在的命名空间,从而正确访问该命名空间下的其他资源。

​ 这些文件的自动生成和挂载是 Kubernetes 的一种安全机制,确保 Pod 能够与集群进行安全的通信并限制其访问的范围。通过挂载这些文件到 Pod 中,Kubernetes 为每个 Pod 提供了唯一的身份验证令牌和集群证书,以及相关的命名空间信息。

创建 sa,并绑定到 pod

1、创建 sa

[root@k8s-master01 sa]# kubectl create sa test

2、创建 pod

$ vim pod.yaml 

apiVersion: v1
kind: Pod 
metadata:
  name: test 
  namespace: default 
  labels:
    app: test 
spec:
  serviceAccountName: test
  containers:
  - name: nginx
    image: centos:centos7.9.2009
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c","sleep 3600"]
$ kubectl apply -f pod.yaml 

$ kubectl exec -it test -- /bin/bash

[root@test /]# cd /var/run/secrets/kubernetes.io/serviceaccount/

[root@test serviceaccount]# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes/api/v1/namespaces/kube-system

显示如下:

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "namespaces \"kube-system\" is forbidden: User \"system:serviceaccount:default:test\" cannot get resource \"namespaces\" in API group \"\" in the namespace \"kube-system\"",
  "reason": "Forbidden",
  "details": {
    "name": "kube-system",
    "kind": "namespaces"
  },
  "code": 403
}

​ 上面结果能看到 sa 能通过 https 方式成功认证 API,但是没有权限访问 k8s 资源,所以 code 状态码是 403,表示没有权限操作 k8s 资源

3、对 sa 做授权

$ kubectl create clusterrolebinding test --clusterrole=cluster-admin --serviceaccount=default:test

备注:上述授权之后,sa 具有最大权限,能对 k8s 做任何操作

4、再次请求

$ kubectl exec -it test -- /bin/bash

[root@test /]# cd /var/run/secrets/kubernetes.io/serviceaccount/

[root@test serviceaccount]# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes/api/v1/namespaces/kube-system

显示如下:

{
  "kind": "Namespace",
  "apiVersion": "v1",
  "metadata": {
    "name": "kube-system",
    "uid": "172d4b1f-a558-4bf3-a7ee-dae10d5b7d2a",
    "resourceVersion": "9",
    "creationTimestamp": "2023-08-20T13:05:27Z",
    "labels": {
      "kubernetes.io/metadata.name": "kube-system"
    },
    "managedFields": [
      {
        "manager": "kube-apiserver",
        "operation": "Update",
        "apiVersion": "v1",
        "time": "2023-08-20T13:05:27Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {
          "f:metadata": {
            "f:labels": {
              ".": {},
              "f:kubernetes.io/metadata.name": {}
            }
          }
        }
      }
    ]
  },
  "spec": {
    "finalizers": [
      "kubernetes"
    ]
  },
  "status": {
    "phase": "Active"
  }
}

通过上面可以看到,对 sa 做授权之后就有权限访问 k8s 资源了

备注: 其他 api 接口可参考官网

https://kubernetes.io/zh-cn/docs/reference/using-api/api-concepts/

11.2.2 对 kubeconfig 文件里的 user 用户做授权,kubectl 操作 k8s,user 用户有最大权限

1、授权

(1) 生成一个私钥
$ cd /etc/kubernetes/pki/
$ (umask 077; openssl genrsa -out test.key 2048)

该命令使用 OpenSSL 生成一个名为 test.key的私钥。genrsa 命令生成一个2048位的 RSA私钥。umask 077 确保生成的私钥具有适当的文件权限(仅允许所有者读取和写入)。

(2) 生成一个证书请求文件
$ openssl req -new -key test.key -out test.csr -subj "/CN=test"

该命令使用前面生成的私钥(test.key)生成一个证书请求。证书请求包含有关实体的信息(在本例中,Common Name 设置为 "test")。-subj 标志用于指定 CSR 的主题字段,其中 /CN=test 设置了 Common Name 属性。

(3) 生成一个证书
$ openssl x509 -req -in test.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out test.crt -days 3650

该命令使用之前生成的证书请求(CSR)生成一个证书。它使用名为 ca.crt 的 CA 证书和 ca.key

的 CA 私钥进行签名,并使用 -CAcreateserial 选项生成一个序列号文件。生成的证书名为 lucky.crt ,有效期为 3650 天(约 10 年)。

2、创建一个 kubeconfig 文件:

创建一个 k8s 集群

$ kubectl config set-cluster kubernetes --server=https://192.168.2.201:6443 --insecure-skip-tls-verify=true --kubeconfig=/root/test.config

$ ls /root/test.config

把 test 这个用户添加到 kubernetes 集群中,可以用来认证 apiserver 的连接

$ pwd
/etc/kubernetes/pki/

$ kubectl config set-credentials test --client-certificate=./test.crt --client-key=./test.key --embed-certs=true --kubeconfig=/root/test.config

设置上下文

$ kubectl config set-context test@kubernetes --cluster=kubernetes --user=test --kubeconfig=/root/test.config

切换账号到 lucky,默认没有任何权限

$ kubectl config use-context test@kubernetes --kubeconfig=/root/test.config

3、绑定

把 user 这个用户通过 rolebinding 绑定到 clusterrole 上,授予权限,权限只是在 lucky 这个名称空间有效

(1) 把 lucky 这个用户通过rolebinding 绑定到 clusterrole 上
$ kubectl create ns lucky

$ kubectl create rolebinding lucky -n lucky --clusterrole=cluster-admin --user=test
(2) 测试是否有权限
$ kubectl run pod --image=busybox:1.28 -n lucky --kubeconfig=/root/test.config

$ kubectl get pods -n lucky --kubeconfig=/root/test.config 
NAME   READY   STATUS      RESTARTS      AGE
pod    0/1     Completed   2 (25s ago)   26s
(3)创新linux用户,使用kuckky名称空间的K8S
$ useradd zhangsan
$ cp /root/test.config /home/zhangsan/
$ chown -R zhangsan.zhangsan /home/zhangsan
$ su - zhangsan
$ mkdir .kube;cd .kube
$ mv ../test.config config


$ kubectl get pod -n lucky --kubeconfig=/root/.kube/config
$ kubectl get pod -n lucky
NAME   READY   STATUS      RESTARTS      AGE
pod    0/1     Completed   4 (48s ago)   95s

删除sa、clusterrolebinding

$ kubectl delete sa test
$ kubectl delete clusterrolebinding test

11.3 模拟攻击 k8s 核心组件apiserver

默认情况下,外部用户无法直接访问 Kubernetes 集群的 API Server 和 Kubelet。这是因为 API Server 和 Kubelet 都没有进行授权配置。然而,如果 Kubernetes 管理员进行了适当的 RBAC 授权配置,外部用户可以对 API Server 发起攻击。

以下是关于 Kubernetes API Server 和 Kubelet 的一些更详细的信息:

1、Kubernetes API Server (kube-apiserver):

1) 默认监听端口:6443

2) API Server 是集群的控制平面组件,用于处理对集群的请求,并暴露 Kubernetes API。

3) 外部用户无法直接访问 API Server,因为它通常位于集群内部网络中。

4) API Server 可以通过不同的认证和授权机制来限制访问,例如基于 RBAC 的授权配置。

2、Kubernetes Kubelet:

1) 默认监听端口:10250(只接受本地连接)和 10255(只读端口,允许远程访问)。

2) Kubelet 是每个节点上的代理,负责管理节点上的容器和与主控制平面的通信。

如果 Kubernetes 管理员对 kube-system 命名空间的 default 服务账号进行了 RBAC 授权,并将其绑定到 cluster-admin 角色,那么这个服务账号拥有了集群管理员权限。这意味着服务账号可以对API Server 发起攻击,以及通过 API Server 进行各种操作,例如创建、删除或执行命令等。

11.3.1 kube-apiserver 未授权客户访问,模拟攻击 apiserver

​ apiserver 有两个端口,8080 和 6443。现在的云服务商提供的容器默认已不存在 8080 端口,主要问题还是在 6443 端口上。

​ 正常访问 6443 端口,会出现以下情况,我们默认访问的角色就是系统给的 anonymous。

https://192.168.2.201:6443

img

1、给匿名用户授权

$ kubectl create clusterrolebinding anno --clusterrole=cluster-admin --user=system:anonymous

取消匿名用户授权

$ kubectl get clusterrolebinding |grep -v system |grep cluster-admin
anno                                                   ClusterRole/cluster-admin                                                          2s
cluster-admin                                          ClusterRole/cluster-admin                                                          27d
clusterrolebinding-user-3                              ClusterRole/cluster-admin                                                          6d11h
jenkins-k8s-sa-cluster                                 ClusterRole/cluster-admin                                                          6d9h
test                                                   ClusterRole/cluster-admin                                                          46m

$ kubectl delete clusterrolebinding anno

当把 system:anonymous 用户被 k8s 管理员绑定到 cluster-admin 的集群角色时

再次访问https://192.168.2.201:6443。即可看到能访问的内容:

img

访问 https://192.168.2.201:6443/api/v1/namespaces/kube-system/secrets/

2、获取 kube-system 命名空间的 token 信息:

image-20230916214145834

我们这里先模拟使用 default 这个 sa 对应的 token

image-20230916213838514

3、生成config文件

拿到了 token 后,可以在攻击机上安装 kubectl 工具,然后执行以下命令创建一个 test_token 文件,并把安全上下文内容输入到 test_token 文件里:

$ touch test_token 
$ echo "ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklqUklUak5oTkdOWlpITjFhVXhQUjNGeFZXbzVPWFJmUjIxWVNEaDJWWFpWT1RGNk0zTndkWFZhUW04aWZRLmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZVzFsYzNCaFkyVWlPaUpyZFdKbExYTjVjM1JsYlNJc0ltdDFZbVZ5Ym1WMFpYTXVhVzh2YzJWeWRtbGpaV0ZqWTI5MWJuUXZjMlZqY21WMExtNWhiV1VpT2lKa1pXWmhkV3gwTFhSdmEyVnVMVzVtZG1ac0lpd2lhM1ZpWlhKdVpYUmxjeTVwYnk5elpYSjJhV05sWVdOamIzVnVkQzl6WlhKMmFXTmxMV0ZqWTI5MWJuUXVibUZ0WlNJNkltUmxabUYxYkhRaUxDSnJkV0psY201bGRHVnpMbWx2TDNObGNuWnBZMlZoWTJOdmRXNTBMM05sY25acFkyVXRZV05qYjNWdWRDNTFhV1FpT2lJeU5UVTBOelU1T1MwNFpUQmtMVFF6TUdNdE9HRTNOaTAwTWpWa1l6Qm1OakppWkRRaUxDSnpkV0lpT2lKemVYTjBaVzA2YzJWeWRtbGpaV0ZqWTI5MWJuUTZhM1ZpWlMxemVYTjBaVzA2WkdWbVlYVnNkQ0o5LkdxeFBBaXZ2aF8zZjNWVEI4S04tQjQwaE1sdENtdHJsTGc1QUZOeXBRMkFNWGxVamd3a2tsUkdLR0x6YUN4NFdIdUxSUUgxLUU0dGtFVFBuZ1VuNzFFWE1lcDI0cGV5d2x6OFFuMXlMMDNxN0FWU081NVNBX1djNXFVTHRPcVFpdTdMSkJteFFDbkY1ekVjTElwSW1lSkV3ZThHcXhoQXlSeDZyS05NRG01MkpuUHA0Mmd0MENDYUVsWWhjQ0ZVR2E4RzdfSzJrOVV1bEt4VTRsVEo0NkVfNEdKVFdrX3BjOWpMdjZycWdqaDZ5SFZWNE1WMThnc210eGpjZU1tbFl1bkc0ZnI3X0JZN2lfb0QwN3NMNjlHQzFiWFpIa0FYWVpXZEhPN19ZSmdrWjJ0eUZYRGV5NXNDc0xNWXJ6SDJ3VnlCY0ZWaENuTU9pOVUwb1ZiTjJSQQ==" |base64 -d

显示如下:

eyJhbGciOiJSUzI1NiIsImtpZCI6IjRITjNhNGNZZHN1aUxPR3FxVWo5OXRfR21YSDh2VXZVOTF6M3NwdXVaQm8ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLW5mdmZsIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIyNTU0NzU5OS04ZTBkLTQzMGMtOGE3Ni00MjVkYzBmNjJiZDQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.GqxPAivvh_3f3VTB8KN-B40hMltCmtrlLg5AFNypQ2AMXlUjgwkklRGKGLzaCx4WHuLRQH1-E4tkETPngUn71EXMep24peywlz8Qn1yL03q7AVSO55SA_Wc5qULtOqQiu7LJBmxQCnF5zEcLIpImeJEwe8GqxhAyRx6rKNMDm52JnPp42gt0CCaElYhcCFUGa8G7_K2k9UulKxU4lTJ46E_4GJTWk_pc9jLv6rqgjh6yHVV4MV18gsmtxjceMmlYunG4fr7_BY7i_oD07sL69GC1bXZHkAXYZWdHO7_YJgkZ2tyFXDey5sCsLMYrzH2wVyBcFVhCnMOi9U0oVbN2RA
$ kubectl --kubeconfig=./test_token config set-credentials test --token="eyJhbGciOiJSUzI1NiIsImtpZCI6IjRITjNhNGNZZHN1aUxPR3FxVWo5OXRfR21YSDh2VXZVOTF6M3NwdXVaQm8ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLW5mdmZsIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIyNTU0NzU5OS04ZTBkLTQzMGMtOGE3Ni00MjVkYzBmNjJiZDQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.GqxPAivvh_3f3VTB8KN-B40hMltCmtrlLg5AFNypQ2AMXlUjgwkklRGKGLzaCx4WHuLRQH1-E4tkETPngUn71EXMep24peywlz8Qn1yL03q7AVSO55SA_Wc5qULtOqQiu7LJBmxQCnF5zEcLIpImeJEwe8GqxhAyRx6rKNMDm52JnPp42gt0CCaElYhcCFUGa8G7_K2k9UulKxU4lTJ46E_4GJTWk_pc9jLv6rqgjh6yHVV4MV18gsmtxjceMmlYunG4fr7_BY7i_oD07sL69GC1bXZHkAXYZWdHO7_YJgkZ2tyFXDey5sCsLMYrzH2wVyBcFVhCnMOi9U0oVbN2RA"
$ kubectl --kubeconfig=./test_token config set-cluster lucky_cluster --server=https://192.168.2.201:6443/ --insecure-skip-tls-verify

$ kubectl --kubeconfig=./test_token config set-context test_context --cluster=lucky_cluster --user=test

$ kubectl --kubeconfig=./test_token config use-context test_context

通过 kubectl 加载刚才的 config 文件访问 k8s 集群:

$ kubectl --kubeconfig=./test_token get pods -n kube-system

报错如下:

image-20230916215449849

4、对报错的 user 用户做授权:

$ kubectl create clusterrolebinding aa --clusterrole=cluster-admin --user=system:serviceaccount:kube-system:default

再次查看 pod:

$ kubectl --kubeconfig=./test_token get pods -n kube-system

显示如下:

NAME                                       READY   STATUS    RESTARTS         AGE
calico-kube-controllers-677cd97c8d-qn6mt   1/1     Running   17 (4h50m ago)   27d
calico-node-b4nwm                          1/1     Running   17 (4h50m ago)   27d
calico-node-lpwnj                          1/1     Running   5 (4h39m ago)    6d11h
calico-node-tt6pd                          1/1     Running   8 (4h49m ago)    6d11h
coredns-65c54cc984-mmwww                   1/1     Running   17 (4h50m ago)   27d
coredns-65c54cc984-s5f4c                   1/1     Running   17 (4h50m ago)   27d
etcd-k8s-master01                          1/1     Running   17 (4h50m ago)   27d
kube-apiserver-k8s-master01                1/1     Running   7 (4h50m ago)    10d
kube-controller-manager-k8s-master01       1/1     Running   18 (4h50m ago)   27d
kube-proxy-75rlz                           1/1     Running   17 (4h50m ago)   27d
kube-proxy-cb945                           1/1     Running   7 (4h51m ago)    6d11h
kube-proxy-n9bjw                           1/1     Running   4 (4h39m ago)    6d11h
kube-scheduler-k8s-master01                1/1     Running   18 (4h50m ago)   27d
metrics-server-79dd7fc689-dfwch            1/1     Running   0                4h43m
$ kubectl --kubeconfig=./test_token get pods
NAME   READY   STATUS    RESTARTS      AGE
test   1/1     Running   1 (12m ago)   72m

5、模拟删除 k8s 集群 pod

$ kubectl --kubeconfig=./test_token delete pod test

6、模拟其他用户使用集群

[root@k8s-master01 api]# cp test_token /home/zhangsan/.kube/config 
cp:是否覆盖"/home/zhangsan/.kube/config" y

[root@k8s-master01 api]# chown -R zhangsan.zhangsan /home/zhangsan/

[root@k8s-master01 api]# su - zhangsan

[zhangsan@k8s-master01 ~]$ kubectl get pod -A 
NAMESPACE     NAME                                       READY   STATUS             RESTARTS         AGE
jenkins-k8s   jenkins-686dcfb594-sjb5z                   1/1     Running            1 (5h19m ago)    6d6h
kube-system   calico-kube-controllers-677cd97c8d-qn6mt   1/1     Running            17 (5h18m ago)   27d
kube-system   calico-node-b4nwm                          1/1     Running            17 (5h18m ago)   27d
kube-system   calico-node-lpwnj                          1/1     Running            5 (5h7m ago)     6d12h
kube-system   calico-node-tt6pd                          1/1     Running            8 (5h17m ago)    6d12h
kube-system   coredns-65c54cc984-mmwww                   1/1     Running            17 (5h18m ago)   27d
kube-system   coredns-65c54cc984-s5f4c                   1/1     Running            17 (5h18m ago)   27d
kube-system   etcd-k8s-master01                          1/1     Running            17 (5h18m ago)   27d
kube-system   kube-apiserver-k8s-master01                1/1     Running            7 (5h18m ago)    11d
kube-system   kube-controller-manager-k8s-master01       1/1     Running            18 (5h18m ago)   27d
kube-system   kube-proxy-75rlz                           1/1     Running            17 (5h18m ago)   27d
kube-system   kube-proxy-cb945                           1/1     Running            7 (5h19m ago)    6d12h
kube-system   kube-proxy-n9bjw                           1/1     Running            4 (5h7m ago)     6d12h
kube-system   kube-scheduler-k8s-master01                1/1     Running            18 (5h18m ago)   27d
kube-system   metrics-server-79dd7fc689-dfwch            1/1     Running            0                5h11m
lucky         pod                                        0/1     CrashLoopBackOff   18 (85s ago)     68m

7、清理

$ kubectl get clusterrolebinding |grep -v system |grep cluster-admin
aa                                                     ClusterRole/cluster-admin                                                          31m
anno                                                   ClusterRole/cluster-admin                                                          57m
cluster-admin                                          ClusterRole/cluster-admin                                                          27d
clusterrolebinding-user-3                              ClusterRole/cluster-admin                                                          6d12h
jenkins-k8s-sa-cluster                                 ClusterRole/cluster-admin                                                          6d10h
test                                                   ClusterRole/cluster-admin                                                          103m


$ kubectl delete clusterrolebinding aa
$ kubectl delete clusterrolebinding anno
$ kubectl get sa
NAME      SECRETS   AGE
default   1         27d
test      1         104m
$ kubectl delete sa test

11.4 ResourceQuota 准入控制机制

ResourceQuota 的主要功能是限制一个命名空间下的资源使用,防止过度占用集群资源。

ResourceQuota 控制器可以在命名空间级别对资源进行限制,如:

1) CPU:指定命名空间内可使用的 CPU 资源总量。

2) 内存:指定命名空间内可使用的内存资源总量。

3) 存储:指定命名空间内可使用的存储资源总量。

4) Pod 数量:指定命名空间内允许的最大 Pod 数量。

5) 服务数量:指定命名空间内允许的最大服务(Service)数量。

6) 配额数量:指定命名空间内允许的最大配额(ResourceQuota)数量等。

​ 当 ResourceQuota 被设置并生效后,在命名空间中创建或更新资源对象(如 Pod、Deployment、Service 等)时,Kubernetes 会检查该命名空间的资源使用情况,并与ResourceQuota 中定义的限制进行比较。如果超过了配额限制,将阻止资源对象的创建或更新,并返回相应的错误。

​ 通过使用 ResourceQuota,可以在 Kubernetes 集群中实现对命名空间级别资源使用的限制和控制。这有助于确保不同的用户或团队在共享的 Kubernetes 环境中能够公平合理地使用资源,并避免资源滥用和资源饥饿的情况发生。

限制 cpu、内存、pod、deployment 数量创建 resourcequota 资源

$ kubectl create ns resourcequota

$ vim resourcequota-1.yaml 

apiVersion: v1
kind: ResourceQuota
metadata:
  name: resourcequota-test
  namespace: resourcequota
spec:
  hard:
    pods: "2"
    count/deployments.apps: "2"
    persistentvolumeclaims: "2"
$ kubectl apply -f resourcequota-1.yaml

上述 YAML 文件解读:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: resourcequota-test
  namespace: resourcequota
spec:
  hard:                     ## 定义了在命名空间中的资源对象所允许的硬限制,即资源的最大使用量。
    pods: "2"               ## 指定了命名空间中允许创建的最大 Pod 数量为 2。
    requests.cpu: "6"       ## 指定了命名空间中所有 Pod 的 CPU 请求总量的最大值为 6。
    requests.memory: 6Gi    ## 指定了命名空间中所有 Pod 的内存请求总量的最大值为 6Gi
    limits.cpu: "8"         ## 指定了命名空间中所有 Pod 的 CPU 限制总量的最大值为 8。
    limits.memory: 8Gi      ## 指定了命名空间中所有 Pod 的内存限制总量的最大值为 8Gi
    count/deployments.apps: "8"     ## 指定了命名空间中允许创建的最大 Deployment 数量为8
    persistentvolumeclaims: "8"     ## 指定了命名空间中允许创建的最大(持久卷声明)数量为 8

1、测试是否成功限制了 pod 数量

$ vim quota-deployment.yaml 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: quota
  namespace: resourcequota
spec:
  replicas: 3
  selector:
    matchLabels:
      app: quota
  template:
    metadata:
      labels:
         app: quota
    spec:
      containers:
      - name: myapp
        image: janakiramm/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
$ kubectl apply -f quota-deployment.yaml 

$ kubectl get pod -n resourcequota
NAME                     READY   STATUS    RESTARTS   AGE
quota-54988d5668-n7jvf   1/1     Running   0          111s
quota-54988d5668-txg4h   1/1     Running   0          111s

通过上面可以看到:

yaml文件中定义三个副本数,但是只能创建 2 个 pod,说明限制成功了

2、限制存储空间大小

$ vim resourcequota-2.yaml 

apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-storage-test
  namespace: resourcequota
spec:
  hard:
    requests.storage: "5Gi"
    persistentvolumeclaims: "5"
    requests.ephemeral-storage: "1Gi"
    limits.ephemeral-storage: "2Gi"

上述 YAML 文件解读:

## 定义了资源配额的规格,包括硬限制(hard limits)。
spec:

## 定义了在命名空间中的资源对象所允许的硬限制,即资源的最大使用量。
  hard:

## 指定了命名空间中所有 PersistentVolumeClaim(持久卷声明)的存储请求总量的最大值为 5Gi(5 Gibibytes)。
    requests.storage: "5Gi"

## 指定了命名空间中允许创建的最大PersistentVolumeClaim 数量为 5。    
    persistentvolumeclaims: "5"

## 指定了命名空间中所有 Pod 的临时存储请求总量的最大值为 1Gi(1 Gibibytes)。
    requests.ephemeral-storage: "1Gi"

##  指定了命名空间中所有 Pod 的临时存储限制总量的最大值为 2Gi(2 Gibibytes)。
    limits.ephemeral-storage: "2Gi"     
$ kubectl apply -f resourcequota-2.yaml

这样,当在该命名空间下的存储资源使用达到或超过限制时,进一步创建或更新资源对象将被阻止, 并返回相应的错误信息。这有助于在 Kubernetes 环境中限制存储资源的使用,确保资源分配的合理性和避免资源过度占用。

11.5 基于 Trivy 对镜像进行漏洞扫描

Trivy 是一个适用于持续集成(CI)的简单而全面的容器漏洞扫描工具。它用于检测容器镜像中操作系统包和应用程序依赖项的漏洞。

以下是 Trivy 的主要特点:

1) 全面的漏洞检测:Trivy 可以检测各种漏洞,包括操作系统软件包(如 Alpine、RHEL、CentOS 等)和应用程序依赖项(如 Bundler、Composer、npm、yarn 等)的漏洞。这使得它可以广泛适用于不同类型的容器镜像。

2) 简单易用:Trivy 的使用非常简单,只需安装二进制文件,并指定要扫描的容器镜像名称即可。它不需要复杂的配置和依赖项,使得集成到 CI 流程中变得方便快捷。

3) 快速和无状态:Trivy 的扫描速度很快,并且是无状态的。首次扫描可能需要一些时间(大约 10 秒),取决于网络连接和镜像大小。随后的扫描通常在一秒内完成。与其他漏洞扫描工具相比,Trivy 不需要维护持久的漏洞数据库,因此不需要花费时间来获取漏洞信息。

与其他容器镜像扫描工具(如 Clair、Anchore Engine、Quay 等)相比,Trivy 在准确性、易用性和对 CI 的支持方面具有显著优势。它能够快速检测容器镜像中的漏洞,帮助提前发现并修复安全问题,确保容器镜像的安全性。因此,在持续集成过程中推荐使用 Trivy,在将容器镜像推送到容器注册表之前,可以轻松地对本地容器镜像进行扫描。

$ rpm -ivh trivy_0.16.0_Linux-64bit.rpm

$ trivy image --skip-update 'registry.aliyuncs.com/google_containers/pause:3.6' | egrep -i "High|Critical"

$ trivy image   --skip-update 'wangyanglinux/myapp:v1' | egrep -i "High|Critical"
Total: 24 (UNKNOWN: 0, LOW: 0, MEDIUM: 16, HIGH: 5, CRITICAL: 3)
| freetype      | CVE-2017-8105    | CRITICAL | 2.7-r1            | 2.7.1-r1      | freetype: heap-based buffer             |
| gd            | CVE-2018-1000222 | HIGH     | 2.2.5-r0          | 2.2.5-r1      | gd: Double free in                      |
| libjpeg-turbo | CVE-2018-11813   | HIGH     | 1.5.1-r0          | 1.5.3-r2      | libjpeg: "cjpeg" utility                |
| libssl1.0     | CVE-2018-0732    | HIGH     | 1.0.2n-r0         | 1.0.2o-r1     | openssl: Malicious server               |
| libxml2       | CVE-2017-16931   | CRITICAL | 2.9.4-r3          | 2.9.5-r0      | libxml2: Mishandling                    |
|               | CVE-2018-14404   | HIGH     |                   | 2.9.8-r1      | libxml2: NULL pointer dereference       |

备注:registry.aliyuncs.com/google_containers/pause:3.7 表示要扫描的镜像