1、API资源对象Networkpolicy
NetworkPolicy用来控制Pod与Pod之间的网络通信,它也支持针对Namespace进行限制。基于白名单模式,符合规则的对象通过,不符合的拒绝。
应用场景举例:
- Pod A不能访问Pod B;
- 开发环境所有Pod不能访问测试命名空间;
- 提供对外访问时,限制外部IP;
官方NetworkPolicy YAML示例:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
说明:必需字段:apiVersion
、 kind
和 metadata
字段。
- podSelector:定义目标Pod的匹配标签,即哪些Pod会生效此策略;
- policyTypes:表示给定的策略是应用于目标Pod的入站流量(Ingress)还是出站流量(Egress),或两者兼有。 如果NetworkPolicy未指定policyTypes则默认情况下始终设置Ingress。
- ingress:定义入流量限制规则,from用来定义白名单对象,比如网段、命名空间、Pod标签,Ports定义目标端口。
- egress:定义出流量限制规则,定义可以访问哪些IP和端口
案例一:
需求:aming命名空间下所有Pod可以互相访问,也可以访问其他命名空间Pod,但其他命名空间不能访问aming命名空间Pod。
首先创建几个Pod:
$ kubectl run busybox --image=busybox -- sleep 3600 ## default命名空间里创建busybox Pod
$ kubectl run busybox --image=busybox -n aming -- sleep 3600 ## aming命名空间里创建busybox Pod
$ kubectl run web --image=nginx:1.23.2 -n aming ## aming命名空间里创建web pod
在没有创建NetworkPolicy的情况下测试
$ kubectl exec busybox -n aming -- ping 10.18.235.161 ##aming命名空间的busybox ping default命名空间的busybox IP
$ kubectl exec busybox -n aming -- ping 10.18.235.162 ##aming命名空间的busybox ping aming命名空间的web IP
$ kubectl exec busybox -- ping 10.18.235.162 ##default命名空间的busybox ping aming命名空间的web IP
创建networkpolicy的YAML
$ vi deny-all-namespaces.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-namespaces
namespace: aming
spec:
podSelector: {} # 为空,表示匹配本命名空间所有Pod
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {} # 为空,表示匹配该命名空间所有Pod,即允许该命名空间所有Pod访问,没有定义namespaceSelector,也就是说不允许其它namespace的Pod访问。
应用YAML
$ kubectl apply -f deny-all-namespaces.yaml
测试:
$ kubectl exec busybox -n aming -- ping 10.18.235.161 ##aming命名空间的busybox ping default命名空间的busybox IP
$ kubectl exec busybox -n aming -- ping 10.18.235.162 ##aming命名空间的busybox ping aming命名空间的web IP
$ kubectl exec busybox -- ping 10.18.235.162 ##default命名空间的busybox ping aming命名空间的web IP
将刚刚创建的所有资源删除:
$ kubectl delete po busybox --force
$ kubectl delete po busybox -n aming --force
$ kubectl delete po web -n aming
$ kubectl delete -f deny-all-namespaces.yaml
案例二:
通过PodSelector限制
$ vi pod-selector.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: app-to-app
namespace: aming
spec:
podSelector:
matchLabels:
app: test
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: dev
ports:
- protocol: TCP
port: 80
- 只有带dev标签的pod才可以访问aming命名空间中带test标签的pod
应用YAML
$ kubectl apply -f pod-selector.yaml
创建测试pod
$ kubectl run web01 --image=nginx:1.23.2 -n aming -l 'app=test' #创建Pod时,指定label
$ kubectl get pod web01 -n aming --show-labels # 查看label
# 如果label创建错了,也可以修改,在本实验中不需要做如下操作
$ kubectl label pod busybox app=test123 --overwrite
$ kubectl run app01 --image=nginx:1.23.2 -n aming -l 'app=dev'
$ kubectl run app02 --image=nginx:1.23.2 -n aming
查看标签
$ kubectl get po app01 -n aming --show-labels
查看web01的IP
$ kubectl describe po web01 -n aming |grep -i ip
测试
$ kubectl exec -n aming app01 -- curl 10.18.235.170
$ kubectl exec -n aming app02 -- curl 10.18.235.170
测试成功后,删除掉刚刚创建的资源
$ kubectl delete po app01 -n aming
$ kubectl delete po app02 -n aming
$ kubectl delete po web01 -n aming
$ kubectl delete -f pod-selector.yaml
案例三:
限制namespace
$ vi allow-ns.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ns
namespace: aming
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: test
ports:
- protocol: TCP
port: 80
- 只有带test标签的命名空间才可以访问aming命名空间的pod
应用YAML
$ kubectl apply -f allow-ns.yaml
创建测试ns
$ kubectl create ns test
创建测试pod
$ kubectl run web01 --image=nginx:1.23.2 -n aming
$ kubectl run web02 --image=nginx:1.23.2 -n test
$ kubectl run web03 --image=nginx:1.23.2
$ kubectl run web04 --image=nginx:1.23.2 -n aming
查看web01的IP
$ kubectl describe po web01 -n aming |grep -i ip
查看ns label
$ kubectl get ns --show-labels
给ns设置标签
$ kubectl label namespace test name=test
测试:
$ kubectl -n test exec web02 -- curl 10.18.235.172 #可以访问
$ kubectl exec web03 -- curl 10.18.235.172 #不可以访问
$ kubectl -n aming exec web04 -- curl 10.18.235.172 #不可以访问,即使同一个命名空间也无法访问
2、Kubernetes用户安全控制
- 1)安全控制三阶段
三阶段: 认证(Authentication)、授权(Authorization)、准入控制(Admission Control)- ① 所谓认证,就是先验证用户的身份是否合法,比如看看其证书是否合法有效,看看其Token是否正确;
- ② 所谓授权,就是看看这个用户是否有权限来访问或者操作K8s的资源;
- ③ 所谓准入控制,就是检查对应客户端的请求是否符合对应请求或操作API规范,检查传递参数是否是正确的。比如创建Pod,它会检查提交的信息是否符合创建Pod的规范,如果不符合规范就拒绝。另外,准入控制还会帮助我们把我们没有明确指定的字段信息,通过默认值的方式把对应的字段填充到客户端请求中,然后把填充好的信息一并由APIserver把客户端请求更新到对应资源在etcd中的对应信息上。
- 2)K8s认证(Authentication) 两种认证方式:
- ① Kubeconfig 这种是基于https ca证书认证,咱们命令行管理K8s用的就是这种认证
- ② Token 这种通过一个Token来识别用户,比如前面我们讲dashboard时,有创建一个serviceaccount,然后再获取其token
- 3)K8s授权(Authorization) 授权模式:
- AlwaysDeny:表示拒绝所有的请求,一般用于测试
- AlwaysAllow:允许接收所有请求,如果集群不需要授权流程,则可以采用该策略
- ABAC(Attribute-Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制(老版本采用的方式,也就是定义属性的访问类型,如果用户拥有这个属性就能访问对应的资源。需要定义一长串的属性,并且ABAC修改完之后并不能生效,现在淘汰了)
- Webbook:通过调用外部 REST 服务对用户进行授权(在集群外部对集群鉴权)
- RBAC(Role-Based Access Control):基于角色的访问控制,现行的默认规则(拥有角色就代表拥有访问资源某些权限)
查看你的K8s授权模式:
$ cat /etc/kubernetes/manifests/kube-apiserver.yaml |grep authorization-mode
- --authorization-mode=Node,RBAC
RBAC 授权模式
RBAC(Role-Based Access Control)基于角色的访问控制,在 Kubernetes 1.5 中引入,现行版本成为默认标准。相对其它访问控制方式,拥有以下优势:
- 对集群中的资源(pod deploy cpu…)和非资源(元信息如pod状态)均拥有完整的覆盖
- 整个 RBAC 完全由几个 API 对象完成,同其它 API 对象一样,可以用 kubectl 或 API 进行操作
- 可以在运行时进行调整,无需重启API Server即可生效
RBAC 的 API 资源对象说明
RBAC资源对象:Subject(包括:User, Group, ServiceAccount)Role(角色)、ClusterRole(集群角色)、RoleBinding(角色绑定)、ClusterRoleBinding(集群角色绑定)
- 主体(subject)
- User:用户
- Group:用户组
- ServiceAccount:服务账号
- 角色
- Role:授权特定命名空间的访问权限
- ClusterRole:授权所有命名空间的访问权限
- 角色绑定
- RoleBinding:将角色绑定到主体(即subject)
- ClusterRoleBinding:将集群角色绑定到主体
- 4)K8s准入控制(Adminssion Control) Adminssion Control实际上是一个准入控制器插件列表,发送到API Server的请求都需要经过这个列表中的每个准入控制器插件的检查,检查不通过,则拒绝请求。
查看可以启用的准入控制器列表:
$ kubectl exec kube-apiserver-aminglinux01 -n kube-system -- kube-apiserver -h | grep ' --enable-admission-plugins'
查看当前K8s启用的准入控制器:
$ grep 'admission' /etc/kubernetes/manifests/kube-apiserver.yaml
或者
$ ps aux|grep apiserver|grep admission
启用准入控制器:
kubectl exec kube-apiserver-k8s01 -n kube-system -- kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger,...
关闭准入控制器:
kubectl exec kube-apiserver-k8s-01 -n kube-system -- kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny,...
更改准入控制器:
$ vi /etc/kubernetes/manifests/kube-apiserver.yaml
#找到--enable-admission-plugins那一行,直接修改
--enable-admission-plugins=NodeRestriction,SecurityContextDeny
以下为admission控制器列表以及说明
Admission 控制器 | 说明 |
---|---|
AlwaysPullImages | 强制要求每个容器始终从镜像仓库拉取最新的镜像。 |
DenyEscalatingExec | 防止容器执行特权操作,例如以root用户执行exec命令。 |
ExtendedResourceToleration | 允许 Pod 通过指定容忍性来请求使用扩展资源,如GPU。 |
InitialResources | 自动为 Pod 分配初始资源,例如 CPU 和内存。 |
LimitPodHardAntiAffinityTopology | 在同一拓扑域中,强制对 Pod 应用硬亲和度规则,以保证高可用性和冗余性。 |
LimitRanger | 实现资源限制(如 CPU、内存、存储等)的默认值和最大值,限制 Pod 和容器的资源使用。 |
MutatingAdmissionWebhook | 在资源提交到 API Server 之前,用于对请求进行修改,例如注入辅助容器、自动挂载存储等。 |
NamespaceLifecycle | 管理命名空间的生命周期,拦截 Kubernetes API 服务器对命名空间的创建、删除和更新请求,并在进行处理之前进行验证和审查。 |
NodeRestriction | 用于保护节点安全,限制 Pod 的访问权限以确保节点的安全性。 |
PodNodeSelector | 强制将 Pod 调度到与其节点选择器匹配的节点上。 |
PodPreset | 在创建 Pod 时,从预定义的资源清单中注入额外的容器配置或环境变量。 |
PodSecurityPolicy | 通过定义 Pod 所允许的行为,帮助管理员确保容器在运行时遵守安全最佳实践。 |
Priority | 通过定义优先级,帮助 Kubernetes 确定 Pod 调度顺序。 |
ReplicaSet | 对 ReplicaSet 资源的请求进行验证和审查,例如确保模板的正确性和匹配标签选择器。 |
ResourceQuota | 管理 Kubernetes 中的资源配额,限制命名空间中的资源使用量。 |
SecurityContextDeny | 防止 Pod 和容器在启动时执行不安全的操作,例如使用特权模式、访问主机网络等。 |
ServiceAccount | 用于自动为每个命名空间创建默认的 ServiceAccount,并为 ServiceAccount 分配适当的权限。 |
ServiceAccountTTL | 为 ServiceAccount 指定生存期,以避免积累不需要的 ServiceAccount。 |
ValidatingAdmissionWebhook | 在资源提交到 API Server 之前,用于对请求进行验证和审查,以确保符合预期的策略和规则。 |
ValidatingPodWebhook | 在 Pod 提交到 API Server 之前, 用于对 Pod 对象进行验证和审查。例如审查Pod 的标签、注释、容器规范和卷规范等,以确保它们符合预期和安全性最佳实践。 |
VolumeBinding | 强制在调度期间将 Pod 中的所有卷绑定到可用的节点上,以确保卷的可用性。 |
VolumeSubpath | 允许将子路径添加到 Pod 中的卷,从而更灵活地控制卷的使用方式。 |
ValidatingMutation | 在资源提交到 API Server 之前,用于对请求进行验证和修改。相较于 MutatingAdmissionWebhook,该插件不仅可以修改请求,还可以拒绝它。 |
PodOverhead | 允许 Kubernetes 在计算 Pod 资源使用量时考虑它们的开销。 |
PodSecurityPolicyReview | 在 PodSecurityPolicy 中增加了 Review 操作。可以使用 kubectl create、apply 和 delete 命令,以进行审计和测试。 |
RuntimeClass | 允许运行时类别动态定义 Kubernetes 节点上容器运行的属性和配置。 |
VolumeSnapshotDataSource | 允许使用 Snapshot 数据源创建 PV,以简化卷恢复过程。 |
CertificateApproval | 允许批准和拒绝凭证签发请求,确保凭证的安全性和正确性。 |
Certificates.k8s.io | 提供了一组用于管理和创建证书和私钥的 API,例如 CertificateSigningRequest 和 CertificateSigningRequestApproval。 |
CSI | 允许扩展 Kubernetes 的存储解决方案。CSI(Container Storage Interface)为存储厂商提供了一种通用的接口,从而简化了存储插件的开发和部署。 |
ImagePolicyWebhook | 在拉取镜像之前,用于对镜像进行验证和审查,以确保它们符合安全最佳实践和策略。 |
PodDisruptionBudget | 确保在进行计划性维护、故障排除和升级时,Pod 可以正常运行,防止应用程序的不可用。 |
PodPresets | 允许在创建 Pod 时注入容器配置和环境变量。 |
ValidatingResourceQuota | 允许管理员创建规则以确保 Kubernetes 中的资源分配和使用符合预期。 |
ValidatingSecurityContext | 在 Pod 提交到 API Server 之前,用于对安全上下文进行验证和审查,以确保 Pod 与集群中其他资源的安全性相匹配。 |
ValidatingVolumeMounts | 验证 Pod 中的卷是否正确挂载。 |
3、Kubernetets创建普通用户
- 需求1:创建一个Role和ServiceAccount并把他们绑定起来。ServiceAccount有get、list、watch的权限
创建YAML文件
cat > testsa.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: testsa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: testsa-role
rules:
- apiGroups: # api组,例如apps组,空值表示是核心API组,像namespace、pod、service、pv、pvc都在里面
- ""
resources: #资源名称(复数),例如pods, deployments, services
- pods
verbs: # 允许的操作,这里允许get, list, watch
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: testsa-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: testsa-role
subjects:
- kind: ServiceAccount
name: testsa
EOF
应用此YAML
$ kubectl apply -f testsa.yaml
生成token
$ kubectl create token testsa
- 需求2:
给user1用户授权aming命名空间Pod读取权限
① 生成ca证书
cd /etc/kubernetes/pki/
openssl genrsa -out user1.key 2048
openssl req -new -key user1.key -out user1.csr -subj "/CN=user1"
openssl x509 -req -in user1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out user1.crt -days 3650
② 生成kubeconfig授权文件
# 设置集群
kubectl config set-cluster myk8s
--certificate-authority=/etc/kubernetes/pki/ca.crt
--embed-certs=true
--server=https://192.168.222.101:6443
--kubeconfig=/root/user1.kubecfg
# 查看user1配置,users和context都为空
kubectl config view --kubeconfig=/root/user1.kubecfg
# 设置客户端认证
kubectl config set-credentials user1
--client-key=user1.key
--client-certificate=user1.crt
--embed-certs=true
--kubeconfig=/root/user1.kubecfg
# 查看user1配置,users有内容了
kubectl config view --kubeconfig=/root/user1.kubecfg
# 设置context
kubectl config set-context user1@myk8s
--cluster=myk8s
--user=user1
--kubeconfig=/root/user1.kubecfg
# 查看user1配置,context已经有内容了
kubectl config view --kubeconfig=/root/user1.kubecfg
# 切换context
kubectl config use-context user1@myk8s --kubeconfig=/root/user1.kubecfg
③ 创建角色
cat > user1-role.yaml <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: aming
name: user1-role
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
EOF
kubectl apply -f user1-role.yaml
④ 将用户与角色绑定
cat > user1-rolebinding.yaml <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: user1-rolebinding
namespace: aming
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: user1-role
subjects:
- kind: User
name: user1
apiGroup: rbac.authorization.k8s.io
EOF
kubectl apply -f user1-rolebinding.yaml
⑤ 创建系统用户并使用user1的配置
$ useradd aming
$ mkdir /home/aming/.kube
$ cp /root/user1.kubecfg /home/aming/.kube/config
$ chown -R aming.aming /home/aming/.kube/
⑥ 切换到普通用下并访问k8s
$ su - aming
$ kubectl get po
$ kubectl get po -n aming
$ kubectl get deploy -n aming