Skip to content

8 Kubernetes-集群安全机制

Kubernetes 一个分布式集群的管理工具

Kubernetes 的安全机制围绕着保护apiserver设计,使用了 3A 服务:

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

一、认证(Authentication)

  • HTTP Token 认证:通过一个 Token 来识别合法用户

客户端发起api调用请求时,在HTTP Header 里放入 Token

​ HTTP Token 的认证是用一个很长的特殊编码方式的并且难以被模仿的字符串 - Token 来表达客户的一种方式

​ Token 是一个很长的很复杂的字符串,每一个 Token 对应一个用户名存储在 API Server 能访问的文件中

  • HTTP Base 认证:通过 用户名+密码 的方式认证

​ 用户名+:+密码 用 BASE64 算法进行编码后的字符串放在 HTTP Request 中的 Heather Authorization 域里发送给服务端,服务端收到后进行编码,获取用户名及密码

  • 最严格的 HTTPS 证书认证:基于 CA 根证书签名的客户端身份认证方式 (√)

​ 单向认证:客户端认证服务端是否合法

​ 双向认证:客户端和服务端,相互认证是否合法(金融级认证,在Kubernetes集群中,采用此方式进行认证)

1)HTTPS 证书双向认证原理:

image-20230206221623893

2)需要认证的节点

并非所有组件与 ApiServer 通讯都采用 HTTPS 双向认证:

​ 若组件与 ApiServer 在同一个物理机,不采用 HTTPS 双向认证,比如 Controller Manager、Schedule

​ (排除用二进制安装集群的方式,二进制安装,有可能将所有组件都分布在不同物理机)

1、存储

​ HTTPS 双向认证。认证文件: /etc/kubernetes/pki/etcd/{ca.crt,ca.key}

​ 服务端:ETCD

​ 客户端:ApiServer

2、服务

Ⅰ、组件认证

认证文件:/etc/kubernetes/pki/{ca.crt,ca.key}

服务端:ApiServer
客户端:
        需要加密:
                手动颁发:若采用kubeadm安装集群(容器化安装),kubeadm组件帮助完成了手动颁发证书
                        kube-proxy
                        kubectl
                自动颁发:节点加入集群时,用的kubeadm join ,使用了双向认证,能自动颁发
                        kubelet
        无需加密:
                Controller Manager、Scheduler

注意:客户端需要加密的手动颁发证书机制

​ 采用kubeadm安装集群(容器化安装),kubeadm组件帮助完成了手动颁发证书

注意:客户端需要加密的自动颁发证书机制

​ 节点加入集群时,用的kubeadm join ,使用了双向认证,能自动颁发

拓展:md5sum 命令

验证两个文件的md5值是否相同。(此处判断存储、服务使用的证书不同)

[root@k8s-master01 ~]# cd /etc/kubernetes/pki/

[root@k8s-master01 pki]# md5sum ca.crt 
42eb20c11d98bcff8bc18c1199e8f668  ca.crt
[root@k8s-master01 pki]# md5sum etcd/ca.crt 
8448c984c06a6893ff1f4d79558f9f5b  etcd/ca.crt
kubeconfig

组件通过 kubeconfig 连接 ApiServer

Ⅱ、pod认证

使用 SA(Server Account)

1、token         JWT 使用 ApiServer 私钥签发的,用于server认证pod是否合法
2、ca.crt        用于pod认证apiserver是否合法
3、namespace     标识当前pod的作用域

默认挂载目录:     /run/secrets/kubernetes.io/serviceaccount

二、鉴权(Authorization)

  • AlwaysDeny:都拒绝(一般用于测试)
  • AlwaysAllow:都允许(一般用于测试)
  • ABAC:基于属性的访问控制 (在K8S中需有一个pod作为授权的载体)
  • WebHook:通过其他服务,进行授权操作

​ openstark中:使用keystone进行统一授权

​ openstartk和K8S结合时:使用keystone进行统一授权(目前还未使用)

  • RBAC:基于角色的访问控制

1)RBAC授权模式

​ RBAC基于角色的访问控制,在K8S中引入,直连 ApiServer的接口进行授权

  • 对集群中的资源和非资源,都拥有完整的覆盖
  • RBAC完全由几个API对象完成
  • 运行中可调整,无需重启ApiServer

2)RBAC的四个顶级资源对象

ROLE、ClusterRole、RoleBinding、ClusterRolebinding

image-20230207181237398

在 Kubernetes 集群中,权限可以绑定给 用户/组/SA(默认无权限):

​ 1.通过角色 或 集群角色与权限绑定

​ 2.然后, 用户/组/SA 通过角色绑定 或 集群角色绑定,获取权限

image-20230207184343787

角色              角色绑定         # 需要指定名称空间
集群角色           集群角色绑定      # 所有空间
集群角色           角色绑定         # 需要指定名称空间

角色绑定 与 集群角色绑定区别:

image-20230207185848248

Kubernetes 集群中的 用户、组来源:证书信息

​ 证书请求的模板文件:(json格式)( cfssl 工具:基于json文件,签发证书)

{
  "CN": "admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "HangZhou",
      "L": "XS",
      "O": "system:masters",
      "OU": "System"
    }
  ]
}
# 重点选项
  "CN": "admin",                # 用户名
  "hosts": [],                  # 证书能被使用的位置。[]表示任意位置可用

      "O": "system:masters",    # 组

Kubernetes 集群中的 Service Account: 通过命令

$ kubectl create sa

3)Role and ClusterRole

Role 例子:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""]                   # [""] 表示 core/v1
  resources: ["pods"]               # 指定资源
  verbs: ["get", "watch", "list"]   # 指定动作类型

ClusterRole:

  • 集群级别的资源控制( 例如 node 访问权限 )
  • 非资源型 endpoints( 例如 /health 访问 )
  • 所有命名空间资源控制(例如 pods )
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  #### 不能指定namespace
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

4)RoleBinding and ClusterRoleBinding

Rolebinding例子:( jane 用户,将 pod-reader 角色,进行绑定)

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

( dave 用户,将 secret-reader 集群角色,进行绑定,在 dev 名字空间下)

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets
  namespace: dev
subjects:
- kind: User
  name: dave
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRolebinding 例子:

( manager 组,将 secret-reader 集群角色,进行绑定,在所有空间下)

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

5)Resources(子资源)

资源下的子资源限制

# 格式:
GET /api/v1/namespaces/{namespace}/pods/{name}/log

# 例子:
/api/v1/namespaces/default/pods/pod-demo/log

6)to Subject

​ 角色绑定、集群角色绑定,将角色绑定到 Subject

​ Subeject 命名随意:字符串表示,它可以是一个普通的名字字符串,也可以是 email 格式的邮箱地址,甚至是一组字符串形式的数字 ID(但不能是 system: 为前缀,system: 是系统保留的)

7)实践:创建一个用户只能管理 dev 空间

注意:此处仅能限制用户在名字空间下的操作,但每个名字空间默认能使用集群的最大资源(后续介绍资源限制)

1、创建证书描述文件

[root@k8s-master01 ~]# cd /etc/kubernetes/pki/
[root@k8s-master01 pki]# vim devuser.json
[root@k8s-master01 pki]# cat devuser.json
{
  "CN": "devuser",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}

2、安装 cfssl 工具包

# 下载证书生成工具
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl

coreOS json 

wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson

wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo
# 本地上传到 /usr/local/bin/
chmod a+x /usr/local/bin/*

image-20230207193627552

3、签发证书

[root@k8s-master01 bin]# cd /etc/kubernetes/pki/
[root@k8s-master01 pki]# pwd
/etc/kubernetes/pki


[root@k8s-master01 pki]# cfssl gencert -ca=ca.crt -ca-key=ca.key  -profile=kubernetes devuser.json | cfssljson -bare devuser

4、设置集群参数

export KUBE_APISERVER="https://192.168.20.201:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=devuser.kubeconfig

5、设置客户端认证参数

kubectl config set-credentials devuser \
--client-certificate=devuser.pem \
--client-key=devuser-key.pem \
--embed-certs=true \
--kubeconfig=devuser.kubeconfig

6、设置上下文参数---context(将用户和集群关联)

kubectl create ns dev
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=devuser \
--namespace=dev \
--kubeconfig=devuser.kubeconfig

7、设置默认上下文(刷新)

kubectl config use-context kubernetes --kubeconfig=devuser.kubeconfig

8、角色绑定

​ 本次使用命令进行角色绑定(也可以通过 yaml 文件进行绑定)

kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: devuser-admin-binding
  namespace: dev
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: devuser

9、测试

更改当前角色为 devuser,创建控制器进行测试

[root@k8s-master01 pki]# pwd
/etc/kubernetes/pki

[root@k8s-master01 pki]# useradd devuser && echo "123" |passwd --stdin devuser

[root@k8s-master01 pki]# mkdir /home/devuser/.kube
[root@k8s-master01 pki]# cp -a /etc/kubernetes/pki/devuser.kubeconfig /home/devuser/.kube/config
[root@k8s-master01 pki]# chown -R devuser:devuser /home/devuser/


[root@k8s-master01 pki]# su - devuser
[devuser@k8s-master01 ~]$ kubectl create deployment nginx --image=wangyanglinux/myapp:v1


[devuser@k8s-master01 ~]$ kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
nginx-74c68d8687-cvk52   1/1     Running   0          5s    172.100.2.3   k8s-node02   <none>           <none>


[devuser@k8s-master01 ~]$ exit
登出
[root@k8s-master01 pki]# kubectl get pod 
No resources found.
[root@k8s-master01 pki]# kubectl get pod -n dev
NAME                     READY   STATUS    RESTARTS   AGE
nginx-74c68d8687-cvk52   1/1     Running   0          27s

三、准入控制---(插件集合)

1.有权限,但不合理操作的拒绝

2.一些特殊功能

列举几个插件的功能:

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