平台安全框架
- 1 平台安全框架
- 1.1 安全框架
- 1.1.1 认证框架
- 1.1.2 框架解读
- 1.2 认证实践
- 1.2.1 令牌用户
- 1.2.2 证书用户
- 1.3 授权实践
- 1.3.1 集群用户
- 1.3.2 角色基础
- 1.3.3 授权基础
- 1.3.4 用户组实践
- 1.3.5 SA授权
- 1.3.6 SA秘钥
- 1.4 准入实践
- 1.4.1 准入基础
- 1.4.2 优先调度
- 1.4.3 资源配额
- 1.4.4 配额实践
- 1.4.5 资源限制
- 1.4.6 Pod策略
- 1.4.7 策略实践
- 1.4.8 策略进阶
1 平台安全框架
1.1 安全框架
1.1.1 认证框架
学习目标
这一节,我们从 基础知识、认证流程、小结 三个方面来学习。
基础知识
安全机制
Kubernetes通过一系列的安全机制来实现Kubernetes的集群安全控制,这里面包括API Server的认证、授权、准入、Secret等机制。一般情况下,Kubernetes集群的安全性主要考虑如下几个目标:
容器和宿主机的资源隔离、容器和宿主机的权限隔离、容器操作的最小权限
组件通信的功能边界、普通用户和管理员用户、资源操作权限、等
资源操作
用户访问k8s业务应用的流程:
方法一:无需api_server认证
用户 -- ingress|service -- pod
方法二:基于api_server认证
管理k8s平台上各种应用对象
表现样式
对于Kubernetes平台来说,几乎所有的操作基本上都是通过kube-apiserver这个组件进行的,该组件提供HTTP RESTful形式的API供集群内外客户端调用,对于kubernetes集群的部署样式主要有两种:http形式和https形式。
我们采用kubeadm部署的形式默认对外是基于https的方式,而内部组件的通信时基于http方式,而k8s的认证授权机制仅仅存在于https形式的api访问中,也就是说,如果客户端使用HTTP连接到kube-apiserver,那么是不会进行认证授权的,这样既增加了安全性,也不至于太复杂。
认证流程
简介
对APIServer的访问一般都要经过的三个步骤,认证(Authn)+授权(Authz)、准入控制(Admission),它也能在一定程度上提高安全性,不过更多是资源管理方面的作用。
注意:认证和授权功能都是以插件化的方式来实现的,这样可以最大化的用户自定义效果。
认证(Authn)
对用户身份进行基本的认证,只允许被当前系统许可的人进入集群内部
授权(Authz)
不同的用户可以获取不同的资源操作权限,比如普通用户、超级用户、等
准入控制(Admission)
类似于审计,主要侧重于 操作动作的校验、语法规范的矫正等写操作场景。
解析
左侧:
对于k8s来说,它主要面对两种用户:
普通人类用户(交互模式) - User Account
集群内部的pod用户(服务进程) - Service Account
中间:
每个部分都是以插件的方式来整合到 k8s 集群环境中:
- 认证和授权是按照 插件的顺序进行依次性的检测,并且遵循 "短路模型" 的认证方式
所谓的"短路"即,失败的时候,到此结束,后续的规则不会进行。
- 准入控制 由于仅用户写操作场景,所以它不遵循 "短路模型",而是会全部检测
原因在于,它要记录为什么不执行,原因是什么,方便后续审计等动作。
小结
1.1.2 框架解读
学习目标
这一节,我们从 流程解读、对象梳理、小结 三个方面来学习。
流程解读
认证
认证用户
在我们的认证范围中,有一个术语叫Subject,它表示我们在集群中基于某些规则和动作尝试操作的对象,在k8s集群中定义了两种类型的subject资源:
User Account:
有外部独立服务进行管理的,对于用户的管理集群内部没有一个关联的资源对象
如果需要操作k8s资源,需要集群内部证书的认证签名。
因为是基于证书方式实现集群的https方式,所以这种认证,我们也称为 HTTPS证书认证
Service Account
通过Kubernetes API 来管理的一些用户帐号,和 namespace 进行关联的
一般是内部资源对象操作资源的一种方式
由于K8s内部的资源对象操作是借助于token方式认证校验的,我们也称为HTTP token认证
注意:
曾经Kubernetes还有一种 HTTP Base的认证方式,通过在kube-apiserver内部实现用户名和密码方式认证,不过由于操作复杂、安全隐患过多,所以在 1.19版本之后就被废弃了
常见令牌
引导令牌:
kubeadm创建集群环境的时候,自动创建好的令牌,用于其他节点加入到集群环境中
静态令牌:
存储于API Server进程可直接加载到的文件中保存的令牌,该文件内容会由API Server缓存于内存中
比如我们在使用kubelet的时候,需要依赖的token文件
SA令牌:
SA 就是 ServiceAccount,集群内部账号之间操作相关资源的一些认证方式。
Webhook令牌:
常应用于触发第三个动作时候的一些认证机制,主要侧重于http协议场景。
等等
参考资料:
https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/authentication/
用户组
单个控制用户的权限台繁琐,可以借助于用户组的机制实现批量用户的自动化管理,主要有以下几种
system:unauthenticated
未能通过任何一个授权插件检验的账号的所有未通过认证测试的用户统一隶属的用户组;
system:authenticated
认证成功后的用户自动加入的一个专用组,用于快捷引用所有正常通过认证的用户账号;
system:serviceaccounts
所有名称空间中的所有ServiceAccount对象
system:serviceaccounts:<namespace>
特定名称空间内所有的ServiceAccount对象
认证方式
kubernetes的认证方式主要有两种:
证书认证 - 本质上就是TLS双向认证
令牌认证 - 大量手动配置TLS认证比较麻烦,可以将证书生成token进行间接使用。
授权
授权主要是在认证的基础上,用于对集群资源的访问控制权限设置,通过检查请求包含的相关属性值,与相对应的访问策略相比较,API请求必须满足某些策略才能被处理。
我们可以在apiserver的启用文件kube-apiserver.yaml中使用
--authorization-mode=xxx
常见授权机制有:
Node
一个专用鉴权模式,根据调度到 kubelet 上运行的 Pod 为 kubelet 授予权限。
ABAC (Attribute Based Access Control)
基于属性的访问控制(ABAC)定义了一种访问控制范型,通过使用将属性组合在一起的策略, 将访问权限授予用户。策略可以使用任何类型的属性(用户属性、资源属性、对象,环境属性等)。
RBAC (Role Based Access Control)
基于角色的访问控制(RBAC) 是一种基于企业内个人用户的角色来管理对计算机或网络资源的访问的方法。 在此上下文中,权限是单个用户执行特定任务的能力, 例如查看、创建或修改文件。
被启用之后,RBAC基于 rbac.authorization.k8s.io允许管理员动态配置权限策略。
要启用 RBAC,请使用 --authorization-mode=RBAC 启动 API 服务器。
Webhook
WebHook 是一个 HTTP Callback:发生某些事情时调用的 HTTP POST,利用外部授权接口对于已有访问控制组件实现权限控制的无缝衔接。
AlwaysDeny
此标志阻止所有请求. 仅使用此标志进行测试
AlwaysAllow
此标志允许所有请求. 只有在您不需要API请求授权的情况下才能使用此标志
我们重点使用的授权机制和默认使用的授权机制就是RBAC,而RBAC可以针对API的请求属性进行多层次的权限配置操作,这些授权的维度有:
用户级别:用户名、用户组、用户扩展身份信息、服务账号等
URL级别:API、API组、请求路径、请求权限、http属性等
资源级别:资源名、子资源、命名空间等
准入控制
准入控制(Admission Control)是一段代码,它会在请求通过认证和授权之后、对象被持久化之前拦截到达 API 服务器的请求。实际上是一个准入控制器插件列表并编译进 kube-apiserver 可执行文件,并且只能由集群管理员配置。准入控制器可以执行 “验证(Validating)” 和/或 “变更(Mutating)” 操作。
发送到APIServer的请求都需要经过这个列表中的每个准入控制器插件的检查,如果某一个控制器插件准入失败,就准入失败。它主要涉及到pod和容器对特定用户和特定权限之间的关联关系。
比如操作的对象是否存在依赖关系、被操作的对象是否能够增删改查等限制。
启用准入控制器
kube-apiserver --enable-admission-plugins=xxx,xxx,...
关闭准入控制器
kube-apiserver --disable-admission-plugins=xxx,xxx,...
查看准入控制器
kube-apiserver -h | grep enable-admission-plugins
官方对于准入控制器的理解:
Kubernetes 的许多高级功能都要求启用一个准入控制器,以便正确地支持该特性。 因此,没有正确配置准入控制器的 Kubernetes API 服务器是不完整的,它无法支持你所期望的所有特性。
准入控制器解读:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/admission-controllers/#what-does-each-admission-controller-do
对象梳理
资源对象
对象简介
认证对象:SA、token
授权对象:Role、ClusterRole、RoleBinding、ClusterRoleBinding
准入对象:LimitRanger、ResourceQuota、PodSecurityPolicy等
小结
1.2 认证实践
1.2.1 令牌用户
学习目标
这一节,我们从 SA简介、SA实践、小结 三个方面来学习。
SA简介
简介
当我们在创建 Pod 时,如果没有指定服务账户,Pod 会被指定给命名空间中的 default 服务账户。 如果你查看 Pod 的原始 JSON 或 YAML,你可以看到 spec.serviceAccountName 字段已经被自动设置了。相关的认证token信息会自动挂载到容器内部的 /var/run/secrets/kubernetes.io/serviceaccount 目录下。当然了,我们可以借助于 pod.spec.automountServiceAccountToken 属性禁止pod创建时候自动挂载Sa相关的信息。
查看默认的SA
[root@kubernetes-master1 ~]# kubectl get sa
NAME SECRETS AGE
default 0 27h
确认默认的pod自动关联默认SA
[root@kubernetes-master1 ~]# kubectl run nginx --image kubernetes-register.superopsmsb.com/superopsmsb/nginx
pod/nginx created
[root@kubernetes-master1 ~]# kubectl get pod nginx -o yaml | grep serviceAccountName
serviceAccountName: default
SA & Secret
kubernetes的 SA 和 token的关系:
1.20版本之前
-- 创建SA的时候,自动创建secret和配套的token
-- 在pod内部直接挂载使用
1.21-1.23版本间
-- 创建SA的时候,自动创建secret和配套的token
-- 在pod内部挂载后,不直接使用
1.24版本之后
-- 创建SA的时候,不创建secret和配套的token
-- 在pod使用的时候,由kubelet来自动申请
[root@kubernetes-master1 ~]# kubectl describe sa default
Name: default
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: <none>
Tokens: <none>
Events: <none>
可以看到:
对于1.24版本的k8s,sa账号内部没有关联任何其他的信息
SA实践
资源属性
apiVersion: v1 # ServiceAccount所属的API群组及版本
kind: ServiceAccount # 资源类型标识
metadata:
name <string> # 资源名称
namespace <string> # ServiceAccount是名称空间级别的资源
automountServiceAccountToken <boolean> # 是否让Pod自动挂载API令牌
secrets <[]Object> # 以该SA运行的Pod所要使用的Secret对象组成的列表
apiVersion <string> # 引用的Secret对象所属的API群组及版本,可省略
kind <string> # 引用的资源的类型,这里是指Secret,可省略
name <string> # 引用的Secret对象的名称,通常仅给出该字段即可
namespace <string> # 引用的Secret对象所属的名称空间
uid <string> # 引用的Secret对象的标识符;
imagePullSecrets <[]Object> # 引用的用于下载Pod中容器镜像的Secret对象列表
name <string> # docker-registry类型的Secret资源的名称
命令解析
命令格式:kubectl create serviceaccount NAME [--dry-run] [options]
作用:创建一个"服务账号"
参数详解
--dry-run=false 模拟创建模式
--generator='serviceaccount/v1' 设定api版本信息
-o, --output='' 设定输出信息格式,常见的有:
json|yaml|name|template|...
--save-config=false 保存配置信息
--template='' 设定配置模板文件
简单实践
创建专属目录
[root@kubernetes-master1 ~]# mkdir /data/kubernetes/secure -p; cd /data/kubernetes/secure
手工创建SA账号
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl create serviceaccount mysa
serviceaccount/mysa created
检查效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get sa mysa
NAME SECRETS AGE
mysa 1 9s
资源清单创建SA 01_kubernetes_platform_secure_sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: superopsmsb
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-web
spec:
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
serviceAccountName: superopsmsb
应用资源清单
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl apply -f 01_kubernetes_platform_secure_sa.yaml
serviceaccount/superopsmsb created
pod/nginx-web created
查看资源属性
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl describe pod nginx-web
Name: nginx-web
...
Containers:
nginx-web:
...
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-wqb6w (ro)
...
结果显示:
用户信息挂载到容器的 /var/run/secrets/kubernetes.io/serviceaccount 目录下了
容器内部的账号身份信息
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl exec -it nginx-web -- /bin/sh
# ls /var/run/secrets/kubernetes.io/serviceaccount/
ca.crt namespace token
清理环境
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl delete -f 01_kubernetes_platform_secure_sa.yaml
禁止挂载SA信息
定制资源清单文件 02_kubernetes_platform_secure_nosa.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-web
spec:
automountServiceAccountToken: false
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
应用资源清单文件
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl apply -f 02_kubernetes_platform_secure_nosa.yaml
pod/nginx-web created
确认效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl describe pod nginx-web | grep 'Mounts:'
Mounts: <none>
结果显示:
SA账号没有进行相关证书的挂载操作
创建SA时候关联Secret
定制资源清单文件 03_kubernetes_platform_secure_sa_secret.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: superopsmsb
---
apiVersion: v1
kind: Secret
metadata:
name: superopsmsb-secret
annotations:
kubernetes.io/service-account.name: superopsmsb
type: kubernetes.io/service-account-token
应用资源清单文件
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl apply -f 03_kubernetes_platform_secure_sa_secret.yaml
serviceaccount/superopsmsb created
secret/superopsmsb-secret created
确认效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get secret
NAME TYPE DATA AGE
superopsmsb-secret kubernetes.io/service-account-token 3 5s
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl describe sa superopsmsb
Name: superopsmsb
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: <none>
Tokens: superopsmsb-secret
Events: <none>
挂载SA的token信息给pod使用
定制资源清单文件 04_kubernetes_platform_secure_sa_secret_mount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: superopsmsb
---
apiVersion: v1
kind: Secret
metadata:
name: superopsmsb-secret
annotations:
kubernetes.io/service-account.name: superopsmsb
type: kubernetes.io/service-account-token
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-web
spec:
containers:
- image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
name: nginx
volumeMounts:
- mountPath: /var/run/secrets/tokens
name: superopsmsb-token
serviceAccountName: superopsmsb
volumes:
- name: superopsmsb-token
projected:
sources:
- serviceAccountToken:
path: superopsmsb-token
expirationSeconds: 7200
audience: superopsmsb
应用资源清单文件
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl apply -f 04_kubernetes_platform_secure_sa_secret_mount.yaml
serviceaccount/superopsmsb created
secret/superopsmsb-secret created
pod/nginx-web created
确认效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl describe pod nginx-web
Name: nginx-web
...
Containers:
nginx:
...
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-9t6n8 (ro)
/var/run/secrets/tokens from superopsmsb-token (rw)
...
Volumes:
superopsmsb-token:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 7200
kube-api-access-9t6n8:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
1.2.2 证书用户
学习目标
这一节,我们从 UA简介、UA实践、小结 三个方面来学习。
UA简介
简介
所有 Kubernetes 集群都有两类用户:由 Kubernetes 管理的服务账号和普通用户。当Kubernetes 集群有由一个与集群无关的服务通过以下方式之一进行管理的:
负责分发私钥的管理员
类似 Keystone 或者 App Accounts 这类用户数据库
包含用户名和密码列表的文件
Kubernetes 可以通过提供由集群的证书机构签名的合法证书的用户来进行登录,然后操作对应的资源对象。
关于用户,我们可以通过证书中的 'subject' 的
通用名称(Common Name)字段 (例如,"/CN=zhangsan") 来确定用户名
用户组(Organization)字段 (例如,"/O=dev")来确定用户组
示例:
openssl req -new -key xxx.pem -out csr.pem -subj "/CN=zhangsan/O=dev/O=test"
创建证书相关资料:
https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/certificates/
UA实践
简介
所谓的UA其实就是我们平常做CA时候的基本步骤,主要包括如下几步
1 创建私钥文件
2 基于私钥文件创建证书签名请求
3 基于私钥和签名请求生成证书文件
1 创建私钥文件
给用户 superopsmsb 创建一个私钥,命名成:superopsmsb.key(无加密)
[root@kubernetes-master1 ~]# cd /etc/kubernetes/pki/
[root@kubernetes-master1 /etc/kubernetes/pki]# (umask 077; openssl genrsa -out superopsmsb.key 2048)
G
命令解析:
genrsa 该子命令用于生成RSA私钥,不会生成公钥,因为公钥提取自私钥
-out filename 生成的私钥保存至filename文件,若未指定输出文件,则为标准输出
-numbits 指定私钥的长度,默认1024,该项必须为命令行的最后一项参数
2 签名请求
用刚创建的私钥创建一个证书签名请求文件:superopsmsb.csr
[root@kubernetes-master1 /etc/kubernetes/pki]# openssl req -new -key superopsmsb.key -out superopsmsb.csr -subj "/CN=superopsmsb/O=superopsmsb"
参数说明:
-new 生成证书请求文件
-key 指定已有的秘钥文件生成签名请求,必须与-new配合使用
-out 输出证书文件名称
-subj 输入证书拥有者信息,这里指定 CN 以及 O 的值,/表示内容分隔
CN以及O的值对于kubernetes很重要,因为kubernetes会从证书这两个值对应获取相关信息:
"CN":Common Name,用于从证书中提取该字段作为请求的用户名 (User Name);
浏览器使用该字段验证网站是否合法;
"O":Organization,用于分组认证
检查效果:
[root@kubernetes-master1 /etc/kubernetes/pki]# ls superopsmsb.*
superopsmsb.csr superopsmsb.key
结果显示:
*.key 是我们的私钥,*.csr是我们的签名请求文件
3 生成证书
利用Kubernetes集群的CA相关证书对UA文件进行认证
[root@kubernetes-master1 /etc/kubernetes/pki]# openssl x509 -req -in superopsmsb.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out superopsmsb.crt -days 365
Signature ok
subject=/CN=superopsmsb/O=superopsmsb
Getting CA Private Key
参数说明:
-req 产生证书签发申请命令
-in 指定需要签名的请求文件
-CA 指定CA证书文件
-CAkey 指定CA证书的秘钥文件
-CAcreateserial 生成唯一的证书序列号
-x509 表示输出一个X509格式的证书
-days 指定证书过期时间为365天
-out 输出证书文件
检查文件效果
[root@kubernetes-master1 /etc/kubernetes/pki]# ls superopsmsb.*
superopsmsb.crt superopsmsb.csr superopsmsb.key
结果显示:
*.crt就是我们最终生成的签证证书
提取信息效果
]# openssl x509 -in superopsmsb.crt -text -noout
Certificate:
...
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=kubernetes
...
Subject: CN=superopsmsb, O=superopsmsb
结果显示:
Issuer: 表示是哪个CA机构帮我们认证的
我们关注的重点在于Subject内容中的请求用户所属的组信息
用户认证脚本
脚本文件内容 05_kubernetes_create_UA.sh
#!/bin/bash
# 功能: 创建kubernetes专属的UA信息
# 版本: v0.1
# 作者: 书记
# 联系: superopsmsb.com
# 定制普通环境变量
ssl_dir='/etc/kubernetes/pki'
config_dir='/tmp'
kubernernetes_entry='https://10.0.0.200:6443'
target_type=(证书 配置 退出)
# 菜单
menu(){
echo -e "\e[31m批量设定远程主机免密码认证管理界面\e[0m"
echo "====================================================="
echo -e "\e[32m 1: 创建证书 2: 创建config 3: 退出操作 \e[0m"
echo "====================================================="
}
# 创建证书文件
create_cert(){
# 接收外部参数
user_name="$1"
group_name="$2"
expire_time="$3"
# 创建逻辑
cd ${ssl_dir}
(umask 077; openssl genrsa -out ${user_name}.key 2048)
openssl req -new -key ${user_name}.key -out ${user_name}.csr -subj "/CN=${user_name}/O=${group_name}"
openssl x509 -req -in ${user_name}.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out ${user_name}.crt -days ${expire_time}
}
# 创建认证配置文件
create_config(){
# 接收外部参数
conf_name="$1"
user_name="$2"
# 创建逻辑
cd ${ssl_dir}
kubectl config set-credentials ${user_name} --client-certificate=./${user_name}.crt --client-key=./${user_name}.key --embed-certs=true --kubeconfig=${config_dir}/${conf_name}
kubectl config set-cluster ${user_name} --server="${kubernernetes_entry}" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --kubeconfig=${config_dir}/${conf_name}
kubectl config set-context ${user_name}@${user_name} --cluster=${user_name} --user=${user_name} --kubeconfig=${config_dir}/${conf_name}
kubectl config use-context ${user_name}@${user_name} --kubeconfig=${config_dir}/${conf_name}
}
# 帮助信息逻辑
Usage(){
echo "请输入有效的操作id"
}
# 逻辑入口
while true
do
menu
read -p "请输入有效的操作id: " target_id
if [ ${#target_type[@]} -ge ${target_id} ]
then
if [ ${target_type[${target_id}-1]} == "证书" ]
then
read -p "请输入有效的证书信息(用户名 组名 有效时间): " user_name group_name expire_time
echo "开始创建证书操作..."
create_cert ${user_name} ${group_name} ${expire_time}
elif [ ${target_type[${target_id}-1]} == "配置" ]
then
read -p "请输入config文件名称(示例: zhangsan.conf): " conf_name
echo "开始创建config操作..."
create_config ${conf_name} ${user_name}
elif [ ${target_type[${target_id}-1]} == "退出" ]
then
echo "开始退出管理界面..."
exit
fi
else
Usage
fi
done
小结
1.3 授权实践
1.3.1 集群用户
学习目标
这一节,我们从 config基础、简单实践、小结 三个方面来学习。
config基础
简介
根据我们之前对kubernetes集群的了解,我们主要是通过config文件来进入到kubernetes集群内部的,然后具有操作相关资源的权限。
在config文件内部主要做了四件事情:
1 创建登录k8s集群的用户
基于证书和秘钥信息创建用户
2 创建登录k8s集群的地址
3 将登录用户和目标k8s集群关联在一起,形成k8s集群入口
4 设定默认的k8s集群入口
注意:
这里的k8s集群入口其实就类似于我们 通过ssh登录远程主机的一个入口,示例如下:
ssh root@10.0.0.12
命令解读
集群操作
get-clusters 显示 kubeconfig 文件中定义的集群
delete-cluster 删除 kubeconfig 文件中指定的集群
set-cluster Set a cluster entry in kubeconfig
用户操作
delete-user Delete the specified user from the kubeconfig
get-users Display users defined in the kubeconfig
set-credentials Set a user entry in kubeconfig
上下文操作
current-context Display the current-context
delete-context 删除 kubeconfig 文件中指定的 context
get-contexts 描述一个或多个 contexts
rename-context Rename a context from the kubeconfig file
set-context Set a context entry in kubeconfig
use-context Set the current-context in a kubeconfig file
其他操作
set Set an individual value in a kubeconfig file
unset Unset an individual value in a kubeconfig file
view 显示合并的 kubeconfig 配置或一个指定的 kubeconfig 文件
简单实践
创建用户
创建用户
[root@kubernetes-master1 /etc/kubernetes/pki]# kubectl config set-credentials superopsmsb --client-certificate=./superopsmsb.crt --client-key=./superopsmsb.key --embed-certs=true --kubeconfig=/tmp/superopsmsb.conf
参数详解:
set-credentials 子命令的作用就是给kubeconfig认证文件创建一个用户条目
--client-certificate=path/to/certfile 指定用户的签证证书文件
--client-key=path/to/keyfile 指定用户的私钥文件
--embed-certs=true,在kubeconfig中为用户条目嵌入客户端证书/密钥,默认值是false,
--kubeconfig=/path/to/other_config.file 表示将属性信息单独输出到一个文件,不指定的话,表示存到默认的 ~/.kube/config文件中
创建集群
创建集群
[root@kubernetes-master1 /etc/kubernetes/pki]# kubectl config set-cluster mycluster --server="https://10.0.0.200:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --kubeconfig=/tmp/superopsmsb.conf
参数详解:
--server=cluster_api_server
--certificate-authority=path/to/certificate/authority
关联用户和集群
配置上下文信息
[root@kubernetes-master1 /etc/kubernetes/pki]# kubectl config set-context superopsmsb@mycluster --cluster=mycluster --user=superopsmsb --kubeconfig=/tmp/superopsmsb.conf
属性详解
--cluster=cluster_nickname 关联的集群名称
--user=user_nickname 关联的用户名称
--namespace=namespace 可以设置该生效的命名空间
设定默认的入口
更改默认登录kubernetes的用户
[root@kubernetes-master1 /etc/kubernetes/pki]# kubectl config use-context superopsmsb@mycluster --kubeconfig=/tmp/superopsmsb.conf
测试效果
查看配置文件内容
[root@kubernetes-master1 /etc/kubernetes/pki]# kubectl config view --kubeconfig=/tmp/superopsmsb.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.0.0.200:6443
name: mycluster
contexts:
- context:
cluster: mycluster
user: superopsmsb
name: superopsmsb@mycluster
current-context: superopsmsb@mycluster
kind: Config
preferences: {}
users:
- name: superopsmsb
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
查看资源测试
[root@kubernetes-master1 /etc/kubernetes/pki]# kubectl get pod --kubeconfig=/tmp/superopsmsb.conf
Error from server (Forbidden): pods is forbidden: User "superopsmsb" cannot list resource "pods" in API group "" in the namespace "default"
结果显示:
虽然提示报错,但是这也证明了用户已经被kubernetes承认了
小结
1.3.2 角色基础
学习目标
这一节,我们从 RBAC、角色绑定、小结三个方面来学习。
RBAC
场景简介
授权机制
RBAC使用rbac.authorization.k8s.io API Group 来实现授权决策,允许管理员通过 Kubernetes API 动态配置策略,要启用RBAC,需要在 apiserver 中添加参数--authorization-mode=RBAC,kubeadm安装的集群默认开启了RBAC,我们可以通过查看 Master 节点上 apiserver 的静态Pod定义文件:
[root@kubernetes-master1 ~]# grep authorization-mode /etc/kubernetes/manifests/kube-apiserver.yaml
- --authorization-mode=Node,RBAC
Kubernetes的基本特性就是它的所有资源对象都是模型化的 API 对象,我们可以基于api-server对各种资源进行增、删、改、查等操作,但是这些操作涉及到的不仅仅是资源本身和动作,而且还涉及到资源和动作之间的内容,比如api的分组版本和资源和api的关联即权限授权等。
授权
所谓的授权,其实指的是,将某些subject对象赋予执行某些资源动作的权限。我们有时候会将其称为Group(权限组),而这个组其实是有两部分组成:组名和组关联(也称绑定)。
简单来说:所谓的授权,其实是为用户授予xx角色
所谓的RBAC,说白了就是为 xx用户 赋予 xx资源 的 xx权限。
授权主体: 用户、用户组、服务账号
授权对象: 集群角色、命名空间角色
授权动作: 集群绑定、命名空间绑定
授权属性
关于kubernetes的授权属性,主要包括如下三个层次:namespace级别、cluster级别、混合级别
namespace级别
rules
- 规则,是一组属于不同 API Group 资源上的权限操作的集合
role
- 表示在一个namespace中基于rules使用资源的权限,主要涉及到操作和对象
RoleBingding
- 将Subject和Role绑定在一起,表示Subject具有指定资源的role操作权限
cluster级别
ClusterRole
- 表示在一个Cluster中基于rules使用资源的权限
ClusterRoleBingding
- 将Subject和ClusterRole绑定在一起,表示Subject指定资源的ClusterRole操作权限
混合级别
RoleBingding
- 将Subject基于RoleBingding与ClusterRole绑定在一起
- 表示Subject可以使用所有ClusterRole中指定资源的role角色
- 但是限制在了只能操作某个命名空间的资源。
- 也就是所谓的"权限降级"
场景1:
多个namespace中的role角色都一致,如果都使用内部的RoleBingding的话,每个namespace都必须单独创建role,而使用ClusterRole的话,只需要一个就可以了,大大的减轻批量使用namespace中的RoleBingding 操作。
场景2:
我们对A用户要提升权限,但是,由于A处于考察期,那么我们暂时给他分配一个区域,测试一下它的运行效果。生活中的场景,提升张三为公司副总裁,但是由于是新手,所以加了一个限制 -- 主管销售范围的副总裁。
角色绑定
内部角色
kubernetes 预制了很多不同功能场景的内部角色功,这些角色主要有:资源发现、用户操作、核心组件、其他组件、控制器等。这些常见的角色除了用户操作相关的角色之外,其他的角色都是以system:为前缀
资源发现角色:
system:basic-user system:authenticated 组
允许用户以只读的方式去访问他们自己的基本信息。
system:discovery system:authenticated 组
允许以只读方式访问 API 发现端点,这些端点用来发现和协商 API 级别。
system:public-info-viewer system:authenticated 和 system:unauthenticated 组
允许对集群的非敏感信息进行只读访问。
注意:
这些ClusterRole 是以前缀 system: 开头的
用户操作角色:
cluster-admin system:masters 组
允许超级用户在平台上的任何资源上执行所有操作。
当在 ClusterRoleBinding 中使用时,可以授权对集群所有资源进行完全控制。
当在 RoleBinding 中使用时,可以授权特定名字空间中的所有资源操作。
admin 无组
允许管理员访问权限,旨在使用 RoleBinding 在名字空间内执行授权。
edit 无组
允许对名字空间的大多数对象进行读/写操作,不允许查看或者修改角色或者角色绑定。
可以访问 Secret,以名字空间中任何 ServiceAccount 的身份运行 Pod
view 无组
允许对名字空间的大多数对象有只读权限,不允许查看角色或角色绑定。
不允许查看 Secrets,因为读取 Secret 的内容依赖 ServiceAccount 的凭据信息。
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get clusterrole | grep -v 'system:'
NAME CREATED AT
admin 2062-09-04T10:57:12Z
cluster-admin 2062-09-04T10:57:12Z
edit 2062-09-04T10:57:12Z
flannel 2062-09-05T01:25:49Z
kubeadm:get-nodes 2062-09-04T10:57:27Z
view 2062-09-04T10:57:12Z
小结
1.3.3 授权基础
学习目标
这一节,我们从 Role实践、clusterRole实践、小结 三个方面来学习。
Role实践
属性解析
我们可以使用 kubectl explain role 的方式来查看一下Role的属性信息:
apiVersion <string>
kind <string>
metadata <Object>
rules <[]Object>
apiGroups <[]string>
nonResourceURLs <[]string>
resourceNames <[]string>
resources <[]string>
verbs <[]string> -required-
结果显示:
对于role来说,其核心的内容主要是rules的权限规则
在这么多rules属性中,最重要的是verbs权限条目,而且所有的属性都是可以以列表的形式累加存在
kubectl 提供 auth can-i 子命令,用于快速查询当前用户是否可以执行给定操作。格式如下:
kubectl auth can-i [权限] [资源对象] <--namespace 命名空间>
注意:
如果返回值是True,表示当前用户具有该权限
命令行创建role,查看具有pod资源的get、list权限的属性信息
[root@kubernetes-master1 ~]# kubectl create role pods-reader --verb=get,list --resource=pods --dry-run -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null 时间信息
name: pods-reader role的名称
rules: 授权规则
- apiGroups: 操作的对象
- "" 所有权限
resources: 资源对象
- pods pod的对象
verbs: 对pod允许的权限
- get 获取
- list 查看
结果显示:
对于一个role必备的rules来说,他主要有三部分组成:apiGroup、resources、verbs
apiGroups 设定包含资源的api组,如果是多个,表示只要属于api组范围中的任意资源都可以操作
resources 位于apiGroup范围中的某些具体的资源对象
verbs 针对具体资源对象的一些具体操作
注意:
关于api组的信息获取,可以参照https://kubernetes.io/docs/reference/#api-reference
简单实践
按照上面的role格式,我们写一个role资源文件,允许用户操作 Deployment、Pod、RS 的所有权限
[root@kubernetes-master1 /data/kubernetes/secure]# 05_kubernetes_platform_secure_rbac_role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: myrole
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["pods", "deployments", "replicasets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
属性解析:
Pod属于 core 的 API Group,在YAML中用空字符就可以,Deployment 属于 apps 的 API Group,ReplicaSets属于extensions这个 API Group,所以 rules 下面的 apiGroups 的内容:["", "extensions", "apps"]
verbs是可以对这些资源对象执行的操作,如果是所有动作,也可以使用["*"]来代替。
查看资源对象
初始化实例对象
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl apply -f 05_kubernetes_platform_secure_rbac_role.yaml
role.rbac.authorization.k8s.io/myrole created
查看效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl describe role myrole
Role用户授权实践
限定用户只能访问命名空间资源
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl create rolebinding super-rolebind --role=myrole --user=superopsmsb
rolebinding.rbac.authorization.k8s.io/super-rolebind created
查看资源效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get pod --kubeconfig=/tmp/superopsmsb.conf
NAME READY STATUS RESTARTS AGE
nginx-web 1/1 Running 0 56m
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get svc --kubeconfig=/tmp/superopsmsb.conf
Error from server (Forbidden): services is forbidden: User "superopsmsb" cannot list resource "services" in API group "" in the namespace "default"
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get svc --kubeconfig=/tmp/superopsmsb.conf -n kube-system
Error from server (Forbidden): services is forbidden: User "superopsmsb" cannot list resource "services" in API group "" in the namespace "kube-system"
清理授权
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl delete rolebindings super-rolebind
rolebinding.rbac.authorization.k8s.io "super-rolebind" deleted
ClusterRole实践
属性解析
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl explain clusterrole
aggregationRule <Object>
apiVersion <string>
kind <string>
metadata <Object>
rules <[]Object>
apiGroups <[]string>
nonResourceURLs <[]string>
resourceNames <[]string>
resources <[]string>
verbs <[]string> -required-
结果显示:
clusterrole相对于role的属性多了一个集中控制器的属性aggregationRule,而这是一个可选的属性
命令行创建clusterrole,查看具有pod资源的get、list权限的属性信息
[root@kubernetes-master1 ~]# kubectl create clusterrole myclusterrole --verb=get,list --resource=pods --dry-run -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null 时间信息
name: myclusterrole role的名称
rules: 授权规则
- apiGroups: 操作的对象
- "" 所有权限
resources: 资源对象
- pods pod的对象
verbs: 对pod允许的权限
- get 获取
- list 查看
结果显示:
ClusterRole与role的配置一样,也由三部分组成:apiGroup、resources、verbs
简单实践
按照上面的clusterrole格式,我们写一个clusterrole资源文件,允许用户操作 Deployment、Pod、RS 的所有权限
[root@kubernetes-master1 /data/kubernetes/secure]# 06_kubernetes_platform_secure_rbac_clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: myclusterrole
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
创建资源对象
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl apply -f 06_kubernetes_platform_secure_rbac_clusterrole.yaml
clusterrole.rbac.authorization.k8s.io/myclusterrole created
查看效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl describe clusterrole myclusterrole
Name: myclusterrole
Labels: <none>
Annotations: <none>
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
pods [] [] [get list watch]
ClusterRole用户授权实践
限定用户只能访问命名空间资源
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl create clusterrolebinding super-clusterrolebind --clusterrole=myclusterrole --user=superopsmsb
查看资源效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get pod --kubeconfig=/tmp/superopsmsb.conf
NAME READY STATUS RESTARTS AGE
nginx-web 1/1 Running 0 68m
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get svc --kubeconfig=/tmp/superopsmsb.conf
Error from server (Forbidden): services is forbidden: User "superopsmsb" cannot list resource "services" in API group "" in the namespace "default"
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get pod --kubeconfig=/tmp/superopsmsb.conf -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5d555c984-hzq8q 1/1 Running 0 9h
清理授权
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl delete clusterrolebinding super-clusterrolebind
rolebinding.rbac.authorization.k8s.io "super-clusterrolebind" deleted
小结
1.3.4 用户组实践
学习目标
这一节,我们从 基础知识、简单实践、小结 三个方面来学习。
基础知识
简介
在实际的工作中,往往会有一大批用户具有相同的角色权限,那么我们就没有必要为每一个用户赋予一些权限,这样的话太过繁琐。有一种简单的方法就是将用户加入到一个用户组,然后为用户组赋予操作权限,这样的话,该用户组的所有用户都会具有对应的操作权限。
创建用户的时候,用户组的设定
]# openssl req -new -key superopsmsb.key -out superopsmsb.csr -subj "/CN=superopsmsb/O=superopsmsb"
查看证书的用户组信息
]# openssl x509 -in superopsmsb.crt -text -noout
Certificate:
...
Signature Algorithm: sha256WithRSAEncryption
...
Subject: CN=superopsmsb, O=superopsmsb
创建普通用户
[root@kubernetes-master1 /data/scripts]# /bin/bash 05_kubernetes_create_UA.sh
批量设定远程主机免密码认证管理界面
=====================================================
1: 创建证书 2: 创建config 3: 退出操作
=====================================================
请输入有效的操作id: 1
请输入有效的证书信息(用户名 组名 有效时间): zhangsan superopsmsb 365
开始创建证书操作...
Generating RSA private key, 2048 bit long modulus
..+++
...............................+++
e is 65537 (0x10001)
Signature ok
subject=/CN=zhangsan/O=superopsmsb
Getting CA Private Key
批量设定远程主机免密码认证管理界面
=====================================================
1: 创建证书 2: 创建config 3: 退出操作
=====================================================
请输入有效的操作id: 2
请输入config文件名称(示例: zhangsan.conf): zhangsan.conf
开始创建config操作...
User "zhangsan" set.
Cluster "zhangsan" set.
Context "zhangsan@zhangsan" created.
Switched to context "zhangsan@zhangsan".
批量设定远程主机免密码认证管理界面
=====================================================
1: 创建证书 2: 创建config 3: 退出操作
=====================================================
请输入有效的操作id: 3
开始退出管理界面...
简单实践
role用户赋权
创建role资源对象
kubectl apply -f 05_kubernetes_platform_secure_rbac_role.yaml
创建基于组的 rolebinding
kubectl create rolebinding super-rolebind --role=myrole --group=superopsmsb
正常演示效果效果
kubectl get pod --kubeconfig=/tmp/superopsmsb.conf
kubectl get pod --kubeconfig=/tmp/zhangsan.conf
异常演示效果
kubectl get svc --kubeconfig=/tmp/superopsmsb.conf
kubectl get svc --kubeconfig=/tmp/zhangsan.conf
还原环境
kubectl delete rolebindings super-rolebind
clusterrole用户赋权
创建clusterrole资源对象
kubectl apply -f 06_kubernetes_platform_secure_rbac_clusterrole.yaml
创建基于组的 rolebinding
kubectl create clusterrolebinding super-clusterrolebind --clusterrole=myclusterrole --group=superopsmsb
正常演示效果效果
kubectl get pod --kubeconfig=/tmp/superopsmsb.conf
kubectl get pod --kubeconfig=/tmp/zhangsan.conf
异常演示效果
kubectl get svc --kubeconfig=/tmp/superopsmsb.conf -n kube-system
kubectl get svc --kubeconfig=/tmp/zhangsan.conf -n kube-system
还原环境
kubectl delete clusterrolebinding super-clusterrolebind
小结
1.3.5 SA授权
学习目标
这一节,我们从 场景需求、简单实践、小结 三个方面来学习。
场景需求
简介
作为k8s平台的应用资源,肯定会出现平台上的A应用需要访问B应用的资源对象的一些情况,对于这种场景的需求,我们一般是直接借助于kubernetes的SA的token机制来实现的。
基本操作流程:
1 创建SA账号
2 创建Role角色
3 SA和Role角色进行绑定
4 使用pod内部的token进行通信认证测试
准备工作 - 升级django镜像(旧有django镜像的Python版本太低了,需要升级)
准备python镜像
docker pull python
docker tag python kubernetes-register.superopsmsb.com/superopsmsb/python
准备基准代码文件
cd /data/images/web/django/
cp -a django python
修改首页信息
# vim blog/app1/views.py
...
version=os.environ.get("PYTHON_VERSION")
....
定制Dockerfile文件
[root@kubernetes-master1 ~]# cat /data/images/web/python/Dockerfile
# 构建一个基于python的定制镜像
# 基础镜像
FROM kubernetes-register.superopsmsb.com/superopsmsb/python
# 镜像作者
MAINTAINER shuji@superopsmsb.com
# 拷贝文件
RUN pip install django==3.1.2
ADD blog /data/code/blog
ADD scripts/startup.sh /data/scripts/startup.sh
# 暴露django端口
EXPOSE 8000
# 定制容器的启动命令
CMD ["/bin/bash", "/data/scripts/startup.sh"]
定制构造镜像
docker build -t kubernetes-register.superopsmsb.com/superopsmsb/django_web:v0.2 /data/images/web/python/
测试构造镜像
docker run -d --name django-test -p 666:8000 kubernetes-register.superopsmsb.com/superopsmsb/django_web:v0.2
测试效果
curl 10.0.0.12:666
docker rm -f django-test
提交镜像到远程仓库
docker push kubernetes-register.superopsmsb.com/superopsmsb/django_web:v0.2
测试脚本
准备测试脚本
]# cat /data/scripts/06_kubernetes_test_pod.py
"""
检测Kubernetes的SA令牌文件权限
"""
# 1 导入模块
from kubernetes import client, config
# 2 打开令牌
with open('/var/run/secrets/kubernetes.io/serviceaccount/token') as f:
token = f.read()
# 3 定制连接kubernetes对象
configuration = client.Configuration()
configuration.host = "https://kubernetes"
configuration.ssl_ca_cert = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
configuration.verify_ssl = True
configuration.api_key = {"authorization": "Bearer " + token}
client.Configuration.set_default(configuration)
apps_api = client.AppsV1Api()
core_api = client.CoreV1Api()
# 4 检测权限信息
try:
print("----显示default空间的Service资源对象----")
for svc in apps_api.list_namespaced_service("default").items:
print(svc.metadata.name)
print("Service名称: %s, 命名空间: %s" % (svc.metadata.name, svc.metadata.namespace))
except:
print("没有访问default空间的Service资源对象的权限")
# 5 检测权限信息
try:
print("----显示default空间的Pod资源对象----")
for pod in core_api.list_namespaced_pod("default").items:
print("Pod名称: %s, Pod地址: %s, 命名空间: %s" % (pod.metadata.name, pod.status.pod_ip, pod.metadata.namespace))
except:
print("没有访问default空间的Pod资源对象的权限")
try:
print("----显示kube-system空间的Pod资源对象----")
for pod in core_api.list_namespaced_pod("kube-system").items:
print("Pod名称: %s, Pod地址: %s, 命名空间: %s" % (pod.metadata.name, pod.status.pod_ip, pod.metadata.namespace))
except:
print("没有访问kube-system空间的Pod资源对象的权限")
简单实践
创建资源
资源清单文件内容 08_kubernetes_platform_secure_sa_username.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: superopsmsb
---
apiVersion: v1
kind: Pod
metadata:
name: django-web
spec:
containers:
- image: kubernetes-register.superopsmsb.com/superopsmsb/django_web:v0.2
name: django
volumeMounts:
- mountPath: /var/run/secrets/tokens
name: superopsmsb-token
serviceAccountName: superopsmsb
应用资源对象
kubectl apply -f 08_kubernetes_platform_secure_sa_username.yaml
拷贝脚本文件到容器内部
kubectl cp /data/scripts/06_kubernetes_test_pod.py django-web:/
进入django-web环境中
kubectl exec -it django-web -- /bin/bash
安装模块插件
pip install kubernetes
测试效果
role赋权操作
kubectl apply -f 05_kubernetes_platform_secure_rbac_role.yaml
kubectl create rolebinding super-rolebind --role=myrole --serviceaccount=default:superopsmsb
django-web环境中测试效果
root@django-web:/# python 06_kubernetes_test_pod.py
----显示default空间的Service资源对象----
没有访问default空间的Service资源对象的权限
----显示default空间的Pod资源对象----
Pod名称: django-web, Pod地址: 10.244.4.9, 命名空间: default
Pod名称: my-deploy-6c44c54668-rzhmg, Pod地址: 10.244.5.9, 命名空间: default
Pod名称: nginx, Pod地址: 10.244.4.6, 命名空间: default
Pod名称: nginx-nosa, Pod地址: 10.244.5.2, 命名空间: default
----显示kube-system空间的Pod资源对象----
没有访问kube-system空间的Pod资源对象的权限
clusterrole赋权操作
kubectl apply -f 06_kubernetes_platform_secure_rbac_clusterrole.yaml
kubectl create clusterrolebinding super-clusterrolebind --clusterrole=myclusterrole --serviceaccount=default:superopsmsb
django-web环境中测试效果
root@django-web:/# python 06_kubernetes_test_pod.py
----显示default空间的Service资源对象----
没有访问default空间的Service资源对象的权限
----显示default空间的Pod资源对象----
Pod名称: django-web, Pod地址: 10.244.4.9, 命名空间: default
...
----显示kube-system空间的Pod资源对象----
Pod名称: coredns-7dc9dcf7fd-4b8vp, Pod地址: 10.244.2.4, 命名空间: kube-system
...
小结
1.3.6 SA秘钥
学习目标
这一节,我们从 场景需求、简单实践、小结 三个方面来学习。
场景需求
简介
我们以kubernetes的dashboard页面访问为例,基于SA的token信息做一个config的文件认证。
功能需求:
基于zhangsan的SA账号定制config文件,只允许访问superopsmsb的命名空间资源对象。
基于lisi的SA账号定制config文件,允许访问所有命名空间资源对象。
注意:
集群级别的权限,可以借助于默认的 Clusterrole -- cluster-admin
准备工作
创建命名空间
kubectl create ns superopsmsb
创建资源对象
kubectl create deployment nginx --image kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1 --replicas 3 -n superopsmsb
kubectl expose deployment nginx --port 80 -n superopsmsb
简单实践
命名空间SA实践
定制SA资源清单文件
cat 03_kubernetes_platform_secure_sa_secret.yaml > 09_kubernetes_platform_secure_zhangsan_config.yaml
修改资源清单文件 09_kubernetes_platform_secure_zhangsan_config.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: zhangsan
namespace: superopsmsb
---
apiVersion: v1
kind: Secret
metadata:
name: zhangsan-secret
namespace: superopsmsb
annotations:
kubernetes.io/service-account.name: zhangsan
type: kubernetes.io/service-account-token
定制集群权限角色策略
kubectl -n superopsmsb create role zhangsan --verb="*" --resource="*" --dry-run=client
echo '---' >> 09_kubernetes_platform_secure_zhangsan_config.yaml
kubectl -n superopsmsb create role zhangsan --verb="*" --resource="*" --dry-run=client -o yaml >> 09_kubernetes_platform_secure_zhangsan_config.yaml
定制集群权限绑定策略
kubectl -n superopsmsb create rolebinding zhangsan-rolebind --role=zhangsan --serviceaccount=superopsmsb:zhangsan --dry-run=client
echo '---' >> 09_kubernetes_platform_secure_zhangsan_config.yaml
kubectl -n superopsmsb create rolebinding zhangsan-rolebind --role=zhangsan --serviceaccount=superopsmsb:zhangsan --dry-run=client -o yaml >> 09_kubernetes_platform_secure_zhangsan_config.yaml
创建资源对象
kubectl apply -f 09_kubernetes_platform_secure_zhangsan_config.yaml
定制config文件的集群内容
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server="https://10.0.0.200:6443" --embed-certs=true --kubeconfig=/root/dashboard-zhangsan.conf
定制config文件的用户内容
NAMESPACE_TOKEN=$(kubectl -n superopsmsb get secrets $(kubectl get secret -n superopsmsb | awk '/zhangsan/{print $1}') -o jsonpath={.data.token} | base64 -d)
kubectl config set-credentials dashboard-zhangsan --token=$NAMESPACE_TOKEN --kubeconfig=/root/dashboard-zhangsan.conf
定制config文件的上下文内容
kubectl config set-context dashboard-zhangsan@kubernetes --cluster=kubernetes --user=dashboard-zhangsan --kubeconfig=/root/dashboard-zhangsan.conf
kubectl config use-context dashboard-zhangsan@kubernetes --kubeconfig=/root/dashboard-zhangsan.conf
确认效果
kubectl get pod -n superopsmsb --kubeconfig /root/dashboard-zhangsan.conf
kubectl get pod -n kube-system --kubeconfig /root/dashboard-zhangsan.conf
下载 dashboard-superopsmsb.conf 文件到宿主机,然后用宿主机进行应用访问
集群级别SA实践
定制SA资源清单文件
cat 03_kubernetes_platform_secure_sa_secret.yaml > 10_kubernetes_platform_secure_lisi_config.yaml
修改资源清单文件 10_kubernetes_platform_secure_lisi_config.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: lisi
namespace: superopsmsb
---
apiVersion: v1
kind: Secret
metadata:
name: lisi-secret
namespace: superopsmsb
annotations:
kubernetes.io/service-account.name: lisi
type: kubernetes.io/service-account-token
定制集群权限绑定策略
kubectl create clusterrolebinding lisi-clusterrolebind --clusterrole=cluster-admin --serviceaccount=superopsmsb:lisi --dry-run=client
echo '---' >> 10_kubernetes_platform_secure_lisi_config.yaml
kubectl create clusterrolebinding lisi-clusterrolebind --clusterrole=cluster-admin --serviceaccount=superopsmsb:lisi --dry-run=client -o yaml >> 10_kubernetes_platform_secure_lisi_config.yaml
创建资源对象
kubectl apply -f 10_kubernetes_platform_secure_lisi_config.yaml
定制config文件的集群内容
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server="https://10.0.0.200:6443" --embed-certs=true --kubeconfig=/root/dashboard-lisi.conf
定制config文件的用户内容
NAMESPACE_TOKEN=$(kubectl -n superopsmsb get secrets $(kubectl get secret -n superopsmsb | awk '/lisi/{print $1}') -o jsonpath={.data.token} | base64 -d)
kubectl config set-credentials dashboard-lisi --token=$NAMESPACE_TOKEN --kubeconfig=/root/dashboard-lisi.conf
定制config文件的上下文内容
kubectl config set-context dashboard-lisi@kubernetes --cluster=kubernetes --user=dashboard-lisi --kubeconfig=/root/dashboard-lisi.conf
kubectl config use-context dashboard-lisi@kubernetes --kubeconfig=/root/dashboard-lisi.conf
测试效果
kubectl get pod -n kube-system --kubeconfig /root/dashboard-lisi.conf
下载 dashboard-cluster.conf 文件到宿主机,然后用宿主机进行应用访问
小结
1.4 准入实践
1.4.1 准入基础
学习目标
这一节,我们从 基础知识、流程解读、小结 三个方面来学习。
基础知识
简介
准入控制(Admission Control)是一段代码,它会在请求通过认证和授权之后、对象被持久化之前拦截到达 API 服务器的请求。实际上是一个准入控制器插件列表并编译进 kube-apiserver 可执行文件,并且只能由集群管理员配置。准入控制器可以执行 “验证(Validating)” 和/或 “变更(Mutating)” 操作。
发送到APIServer的请求都需要经过这个列表中的每个准入控制器插件的检查,如果某一个控制器插件准入失败,就准入失败。它主要涉及到pod和容器对特定用户和特定权限之间的关联关系。
比如操作的对象是否存在依赖关系、被操作的对象是否能够增删改查等限制。
Kubernetes 的许多高级功能都要求启用一个准入控制器,以便正确地支持该特性。 因此,没有正确配置准入控制器的 Kubernetes API 服务器是不完整的,它无法支持你所期望的所有特性。而且越来越多的控制性功能组件以准入控制器的样式出现。
准入机制
准入控制过程分为两个阶段,运行变更准入控制器 和 运行验证准入控制器。 实际上,某些控制器既是变更准入控制器又是验证准入控制器。如果任何一个阶段的任何控制器拒绝了该请求,则整个请求将立即被拒绝,并向终端用户返回一个错误。
最后,除了对对象进行变更外,准入控制器还可以有其它作用:将相关资源作为请求处理的一部分进行变更。 增加使用配额就是一个典型的示例,说明了这样做的必要性。 此类用法都需要相应的回收或回调过程,因为任一准入控制器都无法确定某个请求能否通过所有其它准入控制器。
准入控制器类型
kubernetes的准入控制器主要有两种类型:
内置的静态准入控制器组件
- 基于kube-apiserver启动时候设置的控制器属性
扩展的动态准入控制器组件
- 用于接收准入请求并对其进行处理的 HTTP 回调机制
流程解读
控制器配置
准入控制器需要在kube-apiserver中进行配置,我们的kubeadm的kube-apiserver的配置文件中就通过属性开启了准入控制器:
# grep -ni 'admission' /etc/kubernetes/manifests/kube-apiserver.yaml
20: - --enable-admission-plugins=NodeRestriction
准入控制器使用
启用准入控制器
kube-apiserver --enable-admission-plugins=xxx,xxx,...
关闭准入控制器
kube-apiserver --disable-admission-plugins=xxx,xxx,...
查看准入控制器
kube-apiserver -h | grep enable-admission-plugins
更多控制器的作用:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/admission-controllers/#what-does-each-admission-controller-do
查看默认开启的准入控制器
[root@kubernetes-master1 ~]# kubectl -n kube-system exec -it kube-apiserver-kubernetes-master1 -- kube-apiserver -h | grep 'enable-admission-plugins strings'
--enable-admission-plugins strings admission plugins that should be enabled in addition to default enabled ones (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, PodSecurity, Priority, DefaultTolerationSeconds, DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, RuntimeClass, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, DefaultIngressClass, MutatingAdmissionWebhook, ValidatingAdmissionWebhook, ResourceQuota). Comma-delimited list of admission plugins: AlwaysAdmit,....
结果显示:
默认启用了 18个 准入控制器。
常见与pod相关的准入控制器
limitranger
为Pod添加默认的计算资源需求和计算资源限制;以及存储资源需求和存储资源限制; 支持分别在容器和Pod级别进行限制;
resourcequota
限制资源数量,限制计算资源总量,存储资源总量;资源类型名称
ResourceQuotapodsecuritpolicy
在集群级别限制用户能够在Pod上可配置使用的所有securityContext。由于RBAC的加强,该功能在 Kubernetes v1.21 版本中被弃用,将在 v1.25 中删除
小结
1.4.2 优先调度
学习目标
这一节,我们从 场景解析、简单实践、小结 三个方面来学习。
场景解析
资源调度
资源调度为即将执行的任务,选择合理的节点Pod调度为即将执行的任务,分配合理的逻辑关联搭配污点调度在任务调度的时候,设定一些避免措施拓扑调度在任务已确定调度的前提下,合理的分配任务,实现资源的高效利用。按照调度的基本属性可以划分为:
节点调度、pod调度、污点调度、拓扑调度
调度优先级
在实际的工作场景中,往往会因为应用资源的需求特点,我们在调度的时候,可能先出现的应用可以正常的运行,在后出现的资源对象往往会因为资源不足而无法调度。
如果后续创建的pod的重要性比较高,如果以默认的资源调度方式实现pod创建的话,导致无法创建,所以我们会引入pod优先级的概念,如果当前pod优先级比较高的话,我们可以抢占优先级值较低的pod资源。
在一个并非所有用户都是可信的集群中,恶意用户可能以最高优先级创建 Pod, 导致"调度队列"中的其他 Pod 被驱逐或者无法被调度。管理员可以使用 ResourceQuota 来阻止用户创建高优先级的 Pod。
注意:
它不会对已经调度的资源对象进行驱逐,它主要针对的是调度队列里面的pod
优先级和抢占
要使用优先级和抢占:
1 新增一个或多个 PriorityClass。
2 创建 Pod,并将其 priorityClassName 设置为新增的 PriorityClass。
- PriorityClass 可以内嵌到deployment的模板属性中
注意:
PriorityClass 是一个无命名空间对象,它定义了从优先级类名称到优先级整数值的映射
默认的优先级抢占
Kubernetes 已经提供了 2 个 PriorityClass: system-cluster-critical 和 system-node-critical
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get priorityclasses
NAME VALUE GLOBAL-DEFAULT AGE
system-cluster-critical 2000000000 false 3d18h
system-node-critical 2000001000 false 3d18h
注意:
这两个值是20亿,远远超过可以定义的优先级值,它用于确保始终优先调度关键组件
属性解析
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass # 资源类型
metadata:
name: high-priority # 调度优先级名称,不能以 system- 为前缀
value: 1000000 # 值越大,优先级越高,不允许超过10亿
preemptionPolicy: Never # 是否为非抢占式优先级,1.24版本正式
globalDefault: false # 是否是全局默认的优先级
description: "xxx" # 基本描述信息
简单实践
定制优先级
资源对象文件 11_kubernetes_platform_secure_priorityclass.yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "定制高优先级"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low-priority
value: 100000
globalDefault: false
description: "定制低优先级"
应用资源对象
kubectl apply -f 11_kubernetes_platform_secure_priorityclass.yaml
确认效果
kubectl get priorityclass
kubectl describe priorityclass
应用优先级
在node1上创建资源对象
apiVersion: v1
kind: Pod
metadata:
name: low-priority
spec:
nodeName: "kubernetes-node1"
containers:
- name: low-priority
image: kubernetes-register.superopsmsb.com/superopsmsb/busybox
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]
resources:
requests:
memory: "2Gi"
cpu: "1"
priorityClassName: low-priority
应用资源清单文件
kubectl apply -f 12_kubernetes_platform_secure_priorityclass_pod.yaml
确认效果
]# kubectl get pod
]# kubectl describe nodes kubernetes-node1 | egrep 'cpu |memory '
cpu 1250m (62%) 0 (0%)
memory 2Gi (55%) 0 (0%)
清理环境
kubectl delete -f 12_kubernetes_platform_secure_priorityclass_pod.yaml
kubectl apply -f 11_kubernetes_platform_secure_priorityclass.yaml
小结
1.4.3 资源配额
学习目标
这一节,我们从 属性解读、简单实践、小结 三个方面来学习。
属性解读
简介
Kubernetes技术已经对Pod做了相应的资源配额设置,这些资源主要体现在:CPU和内存、存储,因为存储在k8s中有专门的资源对象来进行管控,所以我们在说到pod资源限制的时候,一半指的是 CPU和内存。Kubernetes中,对于每种资源的配额限定都需要两个参数:Resquests和Limits
申请配额(Requests):
业务运行时最小的资源申请使用量,该参数的值必须满足,若不满足,业务运行不起来。
最大配额(Limits):
业务运行时最大的资源允许使用量,该参数的值不能被突破,若突破,该资源对象会被重启或删除
资源配额
当k8s集群被多个用户或团队使用时,为了避免因为团队的资源对象使用导致资源抢占的问题,我们需要借助于资源配额(ResourceQuota),来帮助集群管理员为不同的团队或资源对象分配资源的使用量。
ResourceQuota是命名空间级别的资源对象,它主要基于资源对象的数量 和 资源消耗的总量来进行限制。
-- ResourceQuota 处理的是 资源的不均匀使用
参考资料:https://kubernetes.io/zh/docs/concepts/policy/resource-quotas/
工作方式
资源配额的工作方式如下:
ResourceQuota为命名空间做资源配额,不同的团队在不同的命名空间下工作。
ResourceQuota为命名空间做多个资源配额,团队针对场景使用不同的配额,实现精细化配置
结合LimitRange 准入控制器对资源的使用量进行更加精细化的设置
超出配额限制,返回403 FORBIDDEN
使用示例
k8s集群的资源量:32 GiB 内存 和 16 核CPU资源,该集群被两个团队使用:
- 允许A团队使用 15 GiB 内存 和 8 核的CPU资源
- 允许B团队使用 10 GiB 内存 和 4 核的CPU资源
- 预留 7 GiB 内存 和 4 核的CPU资源供将来分配。
- 限制 “dev” 命名空间使用 1 GiB 内存 和 核的CPU资源
- 允许 “superopsmsb”命名空间使用任意数量。
常见资源配额限制
计算资源配额
limits.cpu|memory 所有非终止状态的 Pod,其 CPU|MEM 限额总量不能超过该值。
requests.cpu|memory 所有非终止状态的 Pod,其 CPU|MEM 需求总量不能超过该值。
cpu|memory 与 requests.cpu|memory 相同。
存储资源配置
requests.storage 所有 PVC,存储资源的需求总量不能超过该值。
persistentvolumeclaims 在该命名空间中所允许的 PVC 总量。
<storage-class-name>.storageclass.storage.k8s.io/requests.storage
在与 <storage-class-name> 相关的持久卷申领中,存储请求的总和不能超过该值。
<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims
在与 <storage-class-name> 相关的所有持久卷申领中,命名空间中可以存在的持久卷申领总数。
资源对象配额
样式:
count/<resource>.<group>:用于非核心(core)组的资源的数量上限
count/<resource>:用于核心组的资源的数量上限
资源对象
configmaps、persistentvolumeclaims、pods、replicationcontrollers
ReplicationController、resourcequotas、services、services.loadbalancers
services.nodeports、secrets
属性解读
ResourceQuota的配置属性
apiVersion: v1
kind: ResourceQuota
metadata:
name: # 资源对象的名称
spec:
hard: # 资源配额的优先级,主要有low、medium、high三类
cpu: "1000" # CPU资源的配额
memory: 200Gi # mem资源的配额
pods: "10" # pod数量的配额
scopeSelector: # 选择合适的pod资源对象
matchExpressions: # 标签选择器
- operator : In # 操作符号,支持In、NotIn、Exists、DoesNotExist
scopeName: PriorityClass # 基于谁来比较,PriorityClass代表配额优先级
values: ["high"]
注意:
如果 operator 为 Exists 或 DoesNotExist,则不可以设置 values 字段。
定制优先调度
资源对象文件 13_kubernetes_platform_secure_priorityclass_list.yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high
value: 10000
globalDefault: false
description: "high priority"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low
value: 100
globalDefault: false
description: "low priority"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: medium
value: 1000
globalDefault: false
description: "medium priority"
应用资源对象文件
kubectl apply -f 13_kubernetes_platform_secure_priorityclass_list.yaml
查看效果
kubectl get priorityclass
设定资源配额
资源清单文件 14_kubernetes_platform_secure_resourcequota_list.yaml
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-high
spec:
hard:
cpu: "2"
memory: 2Gi
pods: "5"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["high"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-medium
spec:
hard:
cpu: "2"
memory: 1Gi
pods: "4"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["medium"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-low
spec:
hard:
cpu: "1"
memory: 1Gi
pods: "3"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["low"]
创建资源对象
kubectl apply -f 14_kubernetes_platform_secure_resourcequota_list.yaml
检查效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl describe quota
Name: pods-high
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 2
memory 0 2Gi
pods 0 5
...
Name: pods-medium
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 2
memory 0 1Gi
pods 0 4
使用资源配额
资源对象文件 15_kubernetes_platform_secure_resourcequota_pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: high-priority
spec:
containers:
- name: high-priority
image: kubernetes-register.superopsmsb.com/superopsmsb/busybox
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "500m"
priorityClassName: high
创建资源对象
kubectl apply -f 15_kubernetes_platform_secure_resourcequota_pod.yaml
检查效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get quota
NAME AGE REQUEST LIMIT
pods-high 89m cpu: 0/1k, memory: 0/200Gi, pods: 0/10
pods-low 89m cpu: 300m/5, memory: 500Mi/10Gi, pods: 1/10
pods-medium 89m cpu: 0/10, memory: 0/20Gi, pods: 0/10
小结
1.4.4 配额实践
学习目标
这一节,我们从 pod资源、对象数量、小结 三个方面来学习。
pod资源
简介
ResourceQuota是命名空间级别的资源对象,它主要基于资源对象的数量 和 资源消耗的总量来进行限制。这一节,我们针对pod的资源使用量来进行调整。
关于资源的使用量,我们主要是针对 cpu、mem、storage 对象来进行设置
简单实践
资源对象文件 16_kubernetes_platform_secure_resourcequota_compute.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
namespace: superopsmsb
spec:
hard:
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: storage-resources
namespace: superopsmsb
spec:
hard:
requests.storage: "5Gi"
应用资源对象
kubectl apply -f 16_kubernetes_platform_secure_resourcequota_compute.yaml
查看效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl describe quota compute-resources storage-resources --namespace=superopsmsb
Name: compute-resources
Namespace: superopsmsb
Resource Used Hard
-------- ---- ----
limits.cpu 0 2
limits.memory 0 2Gi
requests.cpu 0 1
requests.memory 0 1Gi
Name: storage-resources
Namespace: superopsmsb
Resource Used Hard
-------- ---- ----
requests.storage 0 5Gi
创建资源对象 17_kubernetes_platform_secure_resourcequota_compute_test.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx1
namespace: superopsmsb
spec:
containers:
- name: nginx
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
resources:
requests:
memory: "1Gi"
cpu: "1"
limits:
memory: "1Gi"
cpu: "1"
---
apiVersion: v1
kind: Pod
metadata:
name: nginx2
namespace: superopsmsb
spec:
containers:
- name: nginx
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
resources:
requests:
memory: "1Gi"
cpu: "1"
limits:
memory: "1Gi"
cpu: "1"
应用资源对象
kubectl apply -f 17_kubernetes_platform_secure_resourcequota_compute_test.yaml
删除对象
kubectl delete -f 17_kubernetes_platform_secure_resourcequota_compute_test.yaml
kubectl delete -f 16_kubernetes_platform_secure_resourcequota_compute.yaml
对象数量
简介
ResourceQuota是命名空间级别的资源对象,它主要基于资源对象的数量 和 资源消耗的总量来进行限制。这一节,我们针对资源对象的使用数量来进行限制。
简单实践
资源对象文件 18_kubernetes_platform_secure_resourcequota_count.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-counts
namespace: superopsmsb
spec:
hard:
configmaps: "2"
persistentvolumeclaims: "2"
pods: "7"
replicationcontrollers: "6"
secrets: "2"
services: "6"
services.loadbalancers: "2"
应用资源对象
kubectl apply -f 18_kubernetes_platform_secure_resourcequota_count.yaml
查看效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl describe quota -n superopsmsb
Name: object-counts
Namespace: superopsmsb
Resource Used Hard
-------- ---- ----
configmaps 1 2
persistentvolumeclaims 0 2
pods 3 7
replicationcontrollers 0 6
secrets 0 2
services 1 6
services.loadbalancers 0 2
测试效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl -n superopsmsb create configmap cm1 --from-literal=a=a
configmap/cm1 created
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl -n superopsmsb create configmap cm2 --from-literal=a=a
error: failed to create configmap: configmaps "cm2" is forbidden: exceeded quota: object-counts, requested: configmaps=1, used: configmaps=2, limited: configmaps=2
清理环境
kubectl delete -f 18_kubernetes_platform_secure_resourcequota_count.yaml
小结
1.4.5 资源限制
学习目标
这一节,我们从 属性解读、简单实践、小结 三个方面来学习。
属性解读
简介
默认情况下, Kubernetes 集群上的容器运行使用的计算资源没有限制。 使用资源配额,集群管理员可以以名字空间为单位,限制其资源的使用与创建。 在命名空间中,一个 Pod 或 Container 最多能够使用命名空间的资源配额所定义的 CPU 和内存用量。 这可能导致 Pod 或 Container 会垄断所有可用的资源。 LimitRange 是在命名空间内限制资源分配(给多个 Pod 或 Container)的策略对象。
limitranger可以对集群内Request和Limits的配置做一个全局的统一的限制,相当于批量设置了某一个范围内(某个命名空间)的Pod的资源使用限制。
Limitrange的功能特点:
在一个命名空间中实施对每个 Pod 或 Container 最小和最大的资源使用量的限制。
在一个命名空间中实施对每个 PersistentVolumeClaim 能申请的最小和最大的存储空间大小的限制。
在一个命名空间中实施对一种资源的申请值和限制值的比值的控制。
设置一个命名空间中对计算资源的默认申请/限制值,并且自动的在运行时注入到多个 Container 中。
属性解析
apiVersion: v1
kind: LimitRange
metadata:
name: # 资源对象的名称
spec:
limits: # 资源对象的运行限制
- max: # 最大资源限制,支持cpu 和 memory
cpu: "800m"
min: # 最小资源限制,支持cpu 和 memory
cpu: "200m"
default: # 默认资源限制,支持cpu 和 memory
cpu: 800m
defaultRequest: # 默认资源请求限制,支持cpu 和 memory
cpu: "110m"
maxLimitRequestRatio: # 控制资源限制量和请求量的最大比例,支持cpu 和 memory
memory: 2
type: Container # 资源限制作用类型,,常见的类型有:
# Container、Pod、PersistentVolumeClaim等
简单实践
容器资源限制
资源对象内容 19_kubernetes_platform_secure_limitrange_container.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: limit-container
spec:
limits:
- max:
cpu: "800m"
memory: "1Gi"
min:
cpu: "100m"
memory: "99Mi"
default:
cpu: "700m"
memory: "900Mi"
defaultRequest:
cpu: "110m"
memory: "111Mi"
type: Container
应用资源对象
kubectl apply -f 19_kubernetes_platform_secure_limitrange_contaner.yaml
查看效果
# kubectl get limitranges
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl describe limitranges limit-container
Name: limit-container
Namespace: default
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -------------------
Container cpu 100m 800m 110m 700m -
Container memory 99Mi 1Gi 111Mi 900Mi -
创建测试资源对象 20_kubernetes_platform_secure_limitrange_container_test.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx-1
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
- name: nginx-2
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
resources:
requests:
memory: "100Mi"
cpu: "100m"
- name: nginx-3
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
resources:
limits:
memory: "200Mi"
cpu: "500m"
应用资源对象
kubectl apply -f 20_kubernetes_platform_secure_limitrange_container_test.yaml
确认效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl describe pod nginx
Name: nginx
...
Containers:
nginx-1:
...
Limits:
cpu: 700m
memory: 900Mi
Requests:
cpu: 110m
memory: 111Mi
nginx-2:
...
Limits:
cpu: 700m
memory: 900Mi
Requests:
cpu: 100m
memory: 100Mi
nginx-3:
...
Limits:
cpu: 500m
memory: 200Mi
Requests:
cpu: 500m
memory: 200Mi
清理环境
kubectl delete -f 19_kubernetes_platform_secure_limitrange_container.yaml -f 20_kubernetes_platform_secure_limitrange_container_test.yaml
pvc资源限制
资源对象内容 21_kubernetes_platform_secure_limitrange_pvc.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: limit-pvc
spec:
limits:
- type: PersistentVolumeClaim
max:
storage: 2Gi
min:
storage: 1Gi
应用资源对象
kubectl apply -f kubectl apply -f 21_kubernetes_platform_secure_limitrange_pvc.yaml
查看效果
# kubectl get limitranges
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl describe limitranges limit-pvc
Name: limit-pvc
Namespace: default
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
PersistentVolumeClaim storage 1Gi 2Gi - - -
创建测试资源对象 22_kubernetes_platform_secure_limitrange_pvc_test.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-volume
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/tmp"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
应用资源对象
kubectl apply -f 22_kubernetes_platform_secure_limitrange_pvc_test.yaml
清理资源对象
kubectl delete -f 21_kubernetes_platform_secure_limitrange_pvc.yaml -f 22_kubernetes_platform_secure_limitrange_pvc_test.yaml
小结
1.4.6 Pod策略
学习目标
这一节,我们从 功能解读、环境部署、小结 三个方面来学习。
功能解读
简介
在 Kubernetes 中,我们定义了代表软件应用程序构建块的资源,例如 Deployment、StatefulSet 和 Services。Kubernetes 集群内的各种控制器对这些资源做出反应,创建更多的 Kubernetes 资源或配置一些软件或硬件来实现我们的目标。
虽然我们可以借助于与RBAC实现资源对象的权限管控,但是安全的管理粒度还是比较大,PodSecurityPolicy是一个内置的准入控制器,允许集群管理员控制 Pod 规范的安全敏感方面,而且它还可以与PodSecurityContext 实现pod级别的更深层次的安全管控。
只不过,由于kubernetes管理人员的能力水平不足,导致在使用PSP的时候,意外授予比预期更广泛的权限,而且难以检查在给定情况下应用哪些 PSP可以被我们进行正常使用,所以为了照顾大部分的普通kubernetes管理人员的玻璃心,PSP被废弃了,预计在1.25版本清除掉。但是PSP并没有完全移除,而是以 PodSecurity 准入控制器的方式来进行存在了。
基本信息
查看默认的准入控制器列表
kubectl -n kube-system exec -it kube-apiserver-kubernetes-master1 -- kube-apiserver -h | grep 'enable-admission-plugins strings'
结果显示:
PodSecurityPolicy 默认情况下,没有启用
注意:
由于默认psp是拒绝所有pod的,所以我们在启用psp的时候,需要额外做一些措施 -- 即提前做好psp相关的策略,然后再开启PSP功能。
PodSecurityPolicy默认情况下可以进行多个维度的安全限制:
pod级别的特权:
privileged 创建具有特权命令执行权限的容器
volumes 允许使用的数据卷
宿主机资源:
hostNetwork|hostPorts 使用宿主机网络资源
hostPID|hostIPC 使用宿主机命名空间
容器级别属性:
runAsUser|runAsGroup|supplementalGroups 指定容器的用户属性信息
其他属性:
allowedCapabilities、defaultAddCapabilities、等
参考资料:
https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/psp-to-pod-security-standards/#podsecuritypolicy-spec
实践步骤
Policy本身并不会产生实际作用,需要将其与用户或者serviceaccount绑定才可以完成授权。所以生产中PSP的基本的操作步骤是:
1 定义psp资源的策略
2 定制PSP相关的账号授权
3 集群启用PSP功能
如果要在生产环境中使用,必须要提前测试一下,否则不推荐使用,因为它的门槛较多
我们这里直接从集群直接启用PSP的步骤开始,来给大家演示一个完整的安全过程
环境部署
启用psp功能
编辑 /etc/kubernetes/manifests/kube-apiserver.yaml 文件,添加如下配置
--enable-admission-plugins=NodeRestriction,PodSecurityPolicy
由于kubeadm集群中,api-server是以静态pod的方式来进行管控的,所以我们不用重启,稍等一会,环境自然就开启了PSP功能
因为PSP默认已经禁用所有的pod创建权限,所以默认情况下,我们也看不到api-server的pod的
kubectl get pod -n kube-system | grep api
注意:
如果出现api-server的pod,是因为其他master启用PSP太慢导致的。
我们只能通过端口方式来进行检测
[root@kubernetes-master1 ~]# netstat -atnulp | grep 6443
tcp 0 0 10.0.0.12:52818 10.0.0.12:6443 ESTABLISHED 108627/kube-control
tcp 0 0 10.0.0.12:36852 10.0.0.200:6443 ESTABLISHED 127389/kubelet
tcp 0 0 10.0.0.12:52350 10.0.0.12:6443 ESTABLISHED 123701/kube-schedul
tcp 0 0 10.0.0.12:36314 10.0.0.200:6443 ESTABLISHED 3109/kube-proxy
...
结果显示:
只要我们能够看到 6443,说明kube-apiserver服务已经启动成功了
检查效果
定制资源清单文件 23_kubernetes_platform_secure_psp_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
创建资源清单文件
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl apply -f 23_kubernetes_platform_secure_psp_deployment.yaml
deployment.apps/nginx-deployment created
检查效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 0/1 0 0 79s
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-647c85d77f 1 0 0 84s
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get pod
No resources found in default namespace.
结果显示:
除了pod没有创建成功,其他的都创建成功了
手工测试创建pod
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl run pod-client --image kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
Error from server (Forbidden): pods "pod-client" is forbidden: PodSecurityPolicy: no providers available to validate pod request
结果显示:
没有权限操作PSP资源
临时允许PSP开启所有权限
资源对象文件 24_kubernetes_platform_secure_psp_all.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: privileged
spec:
privileged: true
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
seLinux:
rule: RunAsAny
volumes:
- '*'
创建资源对象
kubectl apply -f 24_kubernetes_platform_secure_psp_all.yaml
创建pod
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl run pod-client --image kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
pod/pod-client created
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod-client 1/1 Running 0 3s
结果显示:
经过psp的授权,所以我们能够创建pod了
清理环境
kubectl delete -f 23_kubernetes_platform_secure_psp_deployment.yaml -f 24_kubernetes_platform_secure_psp_all.yaml
小结
1.4.7 策略实践
学习目标
这一节,我们从 属性解读、简单实践、小结 三个方面来学习。
属性解读
简介
根据我们刚才的实践,应该能够感受的到,PSP的核心就是针对Pod资源对象的所有权限的精细化管控,如果要实现Pod的更加精细的安全性,我们需要定制特定的PSP规则。
为了让管理员可以自由的管理pod资源对象,所以我们还需要针对PSP的策略规则定制RBAC的授权,才可以放心的交给相关的人员去使用,否则会导致更大的问题。
策略属性
PSP策略基本属性
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: privileged # 设定PSP策略名称
spec: # 设定PSP的特定规则,实现多个维度的安全限制
privileged: true # 是否开启容器的特权模式
hostNetwork: false # 是否允许pod使用宿主机网络
hostPorts: # 允许容器使用宿主机的端口范围
- min: 10000
max: 13000
runAsUser: # 设定容器的属主、属组等相关信息
rule: RunAsAny
fsGroup:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
seLinux: # 使用宿主机的Selinux策略
rule: RunAsAny
volumes: # 允许pod使用所有类型的数据卷模式
- '*'
简单实践
定制PSP策略
资源清单文件 25_kubernetes_platform_secure_psp_mul.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: psp-restrictive
spec:
privileged: false
hostNetwork: false
allowPrivilegeEscalation: false
defaultAllowPrivilegeEscalation: false
hostPID: false
hostIPC: false
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
volumes:
- '*'
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: psp-permissive
spec:
privileged: true
hostNetwork: true
hostIPC: true
hostPID: true
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
应用资源清单文件
kubectl apply -f 25_kubernetes_platform_secure_psp_mul.yaml
查看效果
[root@kubernetes-master1 /data/kubernetes/secure]# kubectl get psp
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP READONLYROOTFS VOLUMES
psp-permissive true RunAsAny RunAsAny RunAsAny RunAsAny false *
psp-restrictive false RunAsAny RunAsAny RunAsAny RunAsAny false *
定制SA使用PSP的RBAC
定制角色权限
kubectl create clusterrole psp-restrictive --verb=use --resource=podsecuritypolicies --resource-name=psp-restrictive --dry-run=client
kubectl create clusterrole psp-restrictive --verb=use --resource=podsecuritypolicies --resource-name=psp-restrictive --dry-run=client -o yaml >> 26_kubernetes_platform_secure_psp_restrictive_rbac.yaml
echo '---' >> 26_kubernetes_platform_secure_psp_restrictive_rbac.yaml
定制角色授权
kubectl create clusterrolebinding psp-restrictive --clusterrole=psp-restrictive --group="system:serviceaccounts" --dry-run=client -o yaml
kubectl create clusterrolebinding psp-restrictive --clusterrole=psp-restrictive --group="system:serviceaccounts" --dry-run=client -o yaml >> 26_kubernetes_platform_secure_psp_restrictive_rbac.yaml
应用资源清单文件
kubectl apply -f 26_kubernetes_platform_secure_psp_restrictive_rbac.yaml
测试效果
kubectl apply -f 23_kubernetes_platform_secure_psp_deployment.yaml
kubectl get all
kubectl apply -f 23_kubernetes_platform_secure_psp_deployment.yaml -n superopsmsb
kubectl get all -n superopsmsb
结果显示:
正常的资源可以正常的创建
清理环境
kubectl delete -f 23_kubernetes_platform_secure_psp_deployment.yaml
kubectl delete -f 23_kubernetes_platform_secure_psp_deployment.yaml -n superopsmsb
小结
1.4.8 策略进阶
学习目标
这一节,我们从 网络策略、SA策略、小结 三个方面来学习。
网络策略
简介
虽然我们刚才实现了通用用户组创建资源对象的效果,但是对于一些特殊场景来说,比如 kube-apiserver之类的服务需要底层网络的支持才能够建立起来:。
]# grep hostNe /etc/kubernetes/manifests/kube-apiserver.yaml
hostNetwork: true
如果当前的psp没有hostNetwork的支持的话,很多特殊的依赖于底层网络的应用pod都无法建立。
改造实践
改造deployment
cp 23_kubernetes_platform_secure_psp_deployment.yaml 27_kubernetes_platform_secure_psp_deployment_hostnetwork.yaml
改造文件
[root@kubernetes-master1 /data/kubernetes/secure]# cat 27_kubernetes_platform_secure_psp_deployment_hostnetwork.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
hostNetwork: true # 增加此处配置
containers:
- name: nginx
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
创建资源对象
kubectl apply -f 27_kubernetes_platform_secure_psp_deployment_hostnetwork.yaml
查看效果
kubectl get deployments.apps
结果显示:
pod无法创建
分析:
我们刚才定制的RBAC使用的PSP策略是没有包含 hostNetwork 等宿主机属性的使用权限的。所以我们要使用另外一个PSP的策略来进行管理
定制网络使用PSP的RBAC
定制角色权限
kubectl create clusterrole psp-permissive --verb=use --resource=podsecuritypolicies --resource-name=psp-permissive --dry-run=client
kubectl create clusterrole psp-permissive --verb=use --resource=podsecuritypolicies --resource-name=psp-permissive --dry-run=client -o yaml >> 28_kubernetes_platform_secure_psp_permissive_rbac.yaml
echo '---' >> 28_kubernetes_platform_secure_psp_permissive_rbac.yaml
定制角色授权
kubectl create clusterrolebinding psp-permissive --clusterrole=psp-permissive --group="system:serviceaccounts" --dry-run=client -o yaml
kubectl create clusterrolebinding psp-permissive --clusterrole=psp-permissive --group="system:serviceaccounts" --dry-run=client -o yaml >> 28_kubernetes_platform_secure_psp_permissive_rbac.yaml
应用资源清单文件
kubectl apply -f 28_kubernetes_platform_secure_psp_permissive_rbac.yaml
测试效果
kubectl delete -f 27_kubernetes_platform_secure_psp_deployment_hostnetwork.yaml
kubectl apply -f 27_kubernetes_platform_secure_psp_deployment_hostnetwork.yaml
kubectl get deployments.apps
结果显示:
正常的资源可以正常的创建
清理环境
kubectl delete -f 27_kubernetes_platform_secure_psp_deployment_hostnetwork.yaml
kubectl delete -f 28_kubernetes_platform_secure_psp_permissive_rbac.yaml
SA策略
简介
如果我们有一个需求: 在某个命名空间下面要使用受限制的psp_restrictive策略,但是个别应用需要使用 psp_permissive策略。
对于这种场景,我们可以为应用的 ServiceAccount 提供使用 psp_permissive 策略,其思路与Clusterrole和rolebinding的逻辑类似。
准备资源清单
准备资源清单文件
kubectl create sa superopsmsb -n superopsmsb --dry-run=client -o yaml > 29_kubernetes_platform_secure_psp_deployment_sa.yaml
echo '---' >> 29_kubernetes_platform_secure_psp_deployment_sa.yaml
cat 27_kubernetes_platform_secure_psp_deployment_hostnetwork.yaml >> 29_kubernetes_platform_secure_psp_deployment_sa.yaml
定制资源清单文件 29_kubernetes_platform_secure_psp_deployment_sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: null
name: superopsmsb
namespace: superopsmsb
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: superopsmsb
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
serviceAccount: superopsmsb
hostNetwork: true
containers:
- name: nginx
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
尝试创建资源清单文件
kubectl apply -f 29_kubernetes_platform_secure_psp_deployment_sa.yaml
检查效果
kubectl get deployments.apps -n superopsmsb
结果显示:
没有创建成功
kubectl delete -f 29_kubernetes_platform_secure_psp_deployment_sa.yaml
定制特定SA使用PSP的RBAC
定制角色权限
kubectl create clusterrole psp-permissive --verb=use --resource=podsecuritypolicies --resource-name=psp-permissive --dry-run=client
kubectl create clusterrole psp-permissive --verb=use --resource=podsecuritypolicies --resource-name=psp-permissive --dry-run=client -o yaml >> 30_kubernetes_platform_secure_psp_permissive_rbac_sa.yaml
echo '---' >> 30_kubernetes_platform_secure_psp_permissive_rbac_sa.yaml
定制角色授权
kubectl create clusterrolebinding psp-permissive --clusterrole=psp-permissive --serviceaccount=superopsmsb:superopsmsb --dry-run=client -o yaml
kubectl create clusterrolebinding psp-permissive --clusterrole=psp-permissive --serviceaccount=superopsmsb:superopsmsb --dry-run=client -o yaml >>30_kubernetes_platform_secure_psp_permissive_rbac_sa.yaml
应用资源清单文件
kubectl apply -f 30_kubernetes_platform_secure_psp_permissive_rbac_sa.yaml
测试效果
kubectl apply -f 30_kubernetes_platform_secure_psp_permissive_rbac_sa.yaml
kubectl get deployments.apps
结果显示:
正常的资源可以正常的创建
清理环境
kubectl delete -f 29_kubernetes_platform_secure_psp_deployment_sa.yaml
kubectl delete -f 30_kubernetes_platform_secure_psp_permissive_rbac_sa.yaml
收尾动作
为了不影响后续知识点的学习,我们这里将所有kube-apiserver的服务的PSP功能移除,查看最终效果
[root@kubernetes-master1 ~]# kubectl get pod -n kube-system | grep api
kube-apiserver-kubernetes-master1 1/1 Running 0 6s
kube-apiserver-kubernetes-master2 1/1 Running 0 8s
kube-apiserver-kubernetes-master3 1/1 Pending 0 1s
小结