Kubernetes安全

艺帆风顺 发布于 2025-04-02 19 次阅读


Kubernetes安全

Kubernetes RBAC授权

Kubernetes 安全框架

         

K8S安全控制框架主要由下面3个阶段进行控制,每一个阶段都支持插件方式,通过API Server配置来启用插件。

1. Authentication(鉴权)

K8s Apiserver提供三种客户端身份认证:

• HTTPS 证书认证:基于CA证书签名的数字证书认证(kubeconfig)

• HTTP Token认证:通过一个Token来识别用户(serviceaccount)

• HTTP Base认证:用户名+密码的方式认证(1.19版本弃用)

         

2. Authorization(授权)

RBAC(Role-Based Access Control,基于角色的访问控制):负责完成授权(Authorization)工作。

RBAC根据API请求属性,决定允许还是拒绝。

         

比较常见的授权维度:

• user:用户名

• group:用户分组

• 资源,例如pod、 deployment

• 资源操作方法: get, list, create, update, patch, watch, delete

• 命名空间

• API组

         

3. Admission Control(准入控制)

Adminssion Control实际上是一个准入控制器插件列表, 发送到API Server的请求都需要经过这个列表中的每个准入控

制器插件的检查, 检查不通过, 则拒绝请求。

         

启用一个准入控制器:

kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger ...

关闭一个准入控制器:

kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny ...

查看默认启用:

kubectl exec kube-apiserver-k8s-master -n kube-system -- kube-apiserver -h | grep enable-admission-plugins

         

         

         

基于角色的权限访问控制: RBAC

RBAC(Role-Based Access Control,基于角色的访问控制),是K8s默认授权策略,并且是动态配置策略(修改即时生效)。

         

主体(subject)

• User:用户

• Group:用户组

• ServiceAccount:服务账号

角色

• Role:授权特定命名空间的访问权限

• ClusterRole:授权所有命名空间的访问权限

角色绑定

• RoleBinding:将角色绑定到主体(即subject)

• ClusterRoleBinding:将集群角色绑定到主体

注: RoleBinding在指定命名空间中执行授权, ClusterRoleBinding在集群范围执行授权。

         

RBAC授权案例

    为指定用户授权访问不同命名空间权限,例如新入职一个小弟,希望让他先熟悉K8s集群,为了安全性,先不能给他太大权限,因此先给他授权访问default命名空间Pod读取权限。

实施大致步骤:

1. 用K8S CA签发客户端证书

2. 生成kubeconfig授权文件

3. 创建RBAC权限策略

4. 指定kubeconfig文件测试权限: kubectl get pods --kubeconfig=./aliang.kubeconfig

         

为指定用户授权访问不同命名空间权限

生成kubeconfig授权文件:

# 设置集群

    kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --server=https://192.168.31.61:6443 #masterIP--kubeconfig=aliang.kubeconfig

             

    # 设置客户端认证

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

               

      # 设置默认上下文

        kubectl config set-context kubernetes --cluster=kubernetes --user=aliang --kubeconfig=aliang.kubeconfig

                 

        # 设置当前使用配置

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

                 

        创建角色(权限集合):

          apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:namespace: defaultname: pod-readerrules:- apiGroups: [“” ] # api组,例如apps组,空值表示是核心API组,像namespace、 pod、 service、 pv、 pvc都在里面resources: [“pods” ] #资源名称(复数),例如pods、 deployments、 servicesverbs: [“get” , “watch” , “list” ] # 资源操作方法

                   

          将用户与角色绑定:

            apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata:name: read-podsnamespace: defaultsubjects:- kind: User # 主体name: jane # 主体名称apiGroup: rbac.authorization.k8s.ioroleRef: # 绑定的角色kind: Rolename: pod-reader # 角色名称apiGroup: rbac.authorization.k8s.io

            认证流程

                     

            ServiceAccount(服务账号)简称SA,用于让集群内Pod访问k8s Api。授权方式与kubeconfig方式一样。

            示例:为一个服务账号分配只能创建deployment、 daemonset、statefulset的权限

            # 创建服务账号

            kubectl create serviceaccount cicd-token -n app-team1

            # 创建集群角色

              kubectl create clusterrole deployment-clusterrole --verb=create --resource=deployments,daemonsets,statefulsets

              # 将服务账号绑定角色

                kubectl create rolebinding cicd-token --serviceaccount=app-team1:cicd-token --clusterrole=deployment-clusterrole -n app-team1

                # 测试服务账号权限

                  kubectl --as=system:serviceaccount:app-team1:cicd-token get pods -n app-team1

                           

                  以上命令对应yaml文件

                    apiVersion: v1kind: ServiceAccountmetadata: name: cicd-token namespace: app-team1---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: deployment-clusterrolerules:- apiGroups: ["apps"] resources: ["deployments","daemonsets","statefulsets"] verbs: ["create"]---apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: cicd-token namespace: app-team1roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: deployment-clusterrolesubjects:- kind: ServiceAccount name: cicd-token namespace: app-team1

                    网络访问控制

                    网络访问控制应用场景

                    默认情况下, Kubernetes 集群网络没任何网络限制, Pod 可以与任何其他 Pod 通信,在某些场景下就需要进行网络控制,减少网络攻击面,提高安全性,这就会用到网络策略。

                    网络策略(Network Policy):是一个K8s资源,用于限制Pod出入流量,提供Pod级别和

                    Namespace级别网络访问控制。

                             

                    网络策略的应用场景(偏重多租户下)

                    • 应用程序间的访问控制,例如项目A不能访问项目B的Pod

                    • 开发环境命名空间不能访问测试环境命名空间Pod

                    • 当Pod暴露到外部时,需要做Pod白名单

                             

                    网络策略概述

                     

                    podSelector:目标Pod,根据标签选择。

                    policyTypes:策略类型,指定策略用于入站、出站流量。

                    Ingress: from是可以访问的白名单,可以来自于IP段、命名空间、 Pod标签等, ports是可以访问的端口。

                    Egress:这个Pod组可以访问外部的IP段和端口

                             

                    网络策略工作流程:

                    1、创建Network Policy资源

                    2、 Policy Controller监控网络策略,同步并通知节点上程序

                    3、节点上DaemonSet运行的程序从etcd中获取Policy,调用本地Iptables创建防火墙规则

                    网络访问控制3个案例

                             

                    案例1:拒绝其他命名空间Pod访问

                             

                    需求: test命名空间下所有pod可以互相访问,也可以访问其他命名空间Pod,但其他命名空间不能访问test命名空间Pod。

                    测试:

                      kubectl run busybox --image=busybox -n test -- sleep 12hkubectl run web --image=nginx -n test

                               

                      # 可以访问

                      kubectl exec busybox -n test -- ping 

                               

                      # 不能访问(在default命名空间测试访问test命名空间pod web)

                      kubectl exec busybox -- ping

                      命名空间pod>

                      对应的yaml

                               

                      案例2:同一个命名空间下应用之间限制访问

                      需求:将test命名空间携带run=web标签的Pod隔离,只允许携带run=client1标签的Pod访问80端口。

                               

                      测试:

                        kubectl run web --image=nginx -n testkubectl run client1 --image=busybox -n test -- sleep 12h

                                 

                        # 可以访问

                        kubectl exec client1 -n test -- wget

                        命名空间pod>

                                 

                        # 不能访问

                        kubectl exec busybox -- wget

                        命名空间pod>

                        对应yaml文件

                        案例3:只允许指定命名空间中的应用访问

                                 

                        需求: 只允许dev命名空间中的Pod访问prod命名空间中的pod 80端口

                                 

                        命名空间打标签:

                        kubectl label namespace dev name=dev

                                 

                        测试:

                        kubectl run busybox --image=busybox -n dev -- sleep 12h

                                 

                        # 可以访问

                        kubectl exec busybox -n dev -- wget

                        命名空间pod>

                                 

                        # 不可以访问

                        kubectl exec busybox -- wget

                        命名空间pod>

                        对应yaml文件