8-kubernetes-安全
kubernetes安全框架
访问K8S集群的资源需要过三关:认证、鉴权、准入控制,任意一个不通过都会失败
普通用户若要安全访问集群API server,往往需要证书、token或者用户名+密码,pod访问需要ServiceAccout
K8S安全控制框架主要由下面三个阶段进行控制,每个阶段都支持插件方式,通过API server配置来启用插件
1、Authentication(鉴权) 2、Authorization (授权) 3、Admission Control (准入控制)
1、鉴权(Authentication)
三种客户端身份认证:
https证书认证:基于CA证书签名的数字证书认证 http token认证:通过一个token来识别用户 http base认证:用户名+密码的方式认证(基本不用,安全系数低)
2、授权(Authorization)
RBAC(Role-Based Access Control基于角色的访问控制):复制完成授权(Authorization)工作
根据API请求属性,决定允许还是拒绝
user:用户 group:用户分组 extra:用户额外信息 API 请求路径:例如/api,/healthz API请求方法:get、list、create、update、patch、delete http请求方法:get、post、put、delete 资源 子资源 命名空间 API组
3、准入控制(Admission Control)
Adminssion Control实际上是一个准入控制器插件列表,发送到API server的请求都需要经过这个列表中的每个准入控制器插件的检查,检查不通过,则拒绝请求
进入到容器中查看启用和禁用的
kubectl exec -it kube-apiserver-k8s-master sh -n kube-system
kube-apiserver | grep admin
基于角色的权限访问控制:RBAC
RBAC(Role-Based Access Control基于角色的访问控制),允许通过kubernetes API动态配置策略
角色
Role:授权特定命名空间的访问权限 ClusterRole:权限所有命名空间的访问权限
角色绑定
RoleBinding:将角色绑定到主体(即subject) ClusterRolebinding:将集群角色绑定到主体
主体(subject)
User:用户 Group:用户组 ServiceAccount:服务账号
例子:指定用户授权访问不同命名空间权限
示例:为fage用户授权default命名空间pod读取权限
1、用K8S CA签发客户端证书 2、生成kubeconfig授权文件 3、创建RBAC权限策略
1、生成CA签发的证书,需要K8S内的CA证书
[root@k8s-master ~]# mkdir ssl && cd ssl
[root@k8s-master ssl]# cat cert.sh
cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "87600h" } } } } EOF cat > fage-csr.json <<EOF { "CN": "fage", #用户名,根据客户端证书里包含的user、group确认一个用户 "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", #用户组 "OU": "System" } ] } EOF #生成客户端证书 cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes fage-csr.json | cfssljson -bare aliang
[root@k8s-master ssl]# bash cert.sh
[root@k8s-master ssl]# ls | grep "fage*"
fage.csr
fage-csr.json
fage-key.pem
fage.pem
[root@k8s-master ssl]#
2、生成用户认证文件
[root@k8s-master ssl]# cat kubeconfig.sh
kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/pki/ca.crt \ #指定ca根证书 --embed-certs=true \ --server=https://192.168.10.10:6443 \ #集群地址 --kubeconfig=fage.kubeconfig #生成文件的文件名 # 设置客户端认证 kubectl config set-credentials fage \ --client-key=fage-key.pem \ #指定CA颁发的用户证书 --client-certificate=fage.pem \ --embed-certs=true \ #生成为配置文件,true为是false则不写入 --kubeconfig=fage.kubeconfig #生成用户的认证文件 # 设置默认上下文 kubectl config set-context kubernetes \ --cluster=kubernetes \ --user=fage \ #只是标识没有实际的意义。 --kubeconfig=fage.kubeconfig #生成用户的认证文件 # 设置当前使用配置 kubectl config use-context kubernetes --kubeconfig=fage.kubeconfig
[root@k8s-master ssl]# bash kubeconfig.sh
3、指定命名空间授权
[root@k8s-master ssl]# cat rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: pod-reader rules: #权限控制位置 - apiGroups: [""] #要加deployments需要在这个位置加上"apps" resources: ["pods","services","deployments"] verbs: ["get", "watch", "list"] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: read-pods namespace: default subjects: - kind: User name: fage apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
[root@k8s-master ssl]#
如果修改权限后重新生效文件即可
kubectl apply -f rbac.yaml
复制生成的文件到节点上去验证,或者给使用的同事
scp /root/fage.kubeconfig root@192.168.10.112:/root/.kube/config
网络策略
网络策略(Network Policy)用于现在pod出入流量,提供pod级别和namespace级别网络访问控制。一些应用场景
应用程序之间访问控制,如微服务A允许访问微服务B,微服务C不能访问微服务A 开发环境命名空间不能访问测试环境命名空间pod 当pod暴露到外部时,需要做pod白名单 多租户网络环境隔离
pod网络入口方向隔离
基于pod级网络隔离:值允许特点对象访问pod(使用标签定义),允许白名单上的IP地址或者IP段访问pod 基于namespace级网络隔离:多个命名空间,A和B命名空间的pod完全隔离
pod网络出口方向
拒绝某个namespace上所有pod访问外部 基于目的IP的网络隔离:只允许pod访问白名单上的IP地址或IP段 基于目标端口的网络隔离:只允许pod访问白名单上的端口
网络概述案例参考地址:
https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/
字段含义
podSelector:目标pod,根据标签选择 policyType:策略类型,知道策略用于入栈、出站流量 ingress: from 是可以访问的白名单,可以来自于IP段、命名空间、pod标签等,ports是可以访问的端口 egress: 这个pod组可以访问外部的IP段和端口
实例:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: test-network-policy namespace: default spec: podSelector: #将策略应用到那个对象中 matchLabels: role: db policyTypes: #应用到出口还是入口,这里出入都应用了 - Ingress - Egress ingress: #这里的ingress代表是入口,下面是策略明细 - from: - ipBlock: cidr: 172.17.0.0/16 #允许访问的访问的网段 except: - 172.17.1.0/24 #允许网段中除了这个网段不能访问 - namespaceSelector: #允许访问的命名空间 matchLabels: project: myproject - podSelector: #那些pod可以访问 matchLabels: role: frontend ports: #允许访问的端口 - protocol: TCP port: 6379 egress: #这里egress代表出口 - to: - ipBlock: cidr: 10.0.0.0/24 ports: - protocol: TCP port: 5978
案例:项目pod出入流量访问控制
需求1
将default命名空间写到run=web标签的pod隔离,只允许default命名空间携带run=client1标签的pod访问80端口
vim network-policy.yaml
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: test-network-policy namespace: default spec: posSelector: matchLabels: app: web policyTypes: - Ingress ingress: - from: # - namespaceSelector: # matchLabels: # project: default - podSelector: matchLabels: run: client1 ports: - protocol: TCP port: 80
生效配置
kubectl apply -f network-policy.yaml
需求2
default命名空间下所有pod可以互相访问,也可以访问其他命名空间Pod,但其他命名空间不能访问default命名空间pod
cat network-policy.yaml
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name:deny-from-other-namespaces namespace: default spec: podSelector: {} policyTypes: - Ingress ingress: - from: - podSelector: {}