0


Kubernetes从零到精通(15-安全)

   Kubernetes(K8s)是一个强大的容器编排平台,安全性至关重要。Kubernetes的安全机制可以分为多个层次,包括集群层、网络层、应用层等。以下是Kubernetes中主要的安全机制:Kubernetes API访问控制、Secret、网络策略(NetworkPolicy) 、审计日志等等。

一、Kubernetes API访问控制

    Kubernetes API访问控制是一组机制,确保只有经过授权的用户或服务可以访问和操作集群资源。它涵盖了多个层面,包括传输安全、认证、鉴权、准入控制和审计。以下是这些概念的详细介绍。

1.传输安全(Transport Security)

Kubernetes默认使用HTTPS来确保API通信的安全性,防止数据在传输过程中被窃取或篡改。API服务器会使用TLS(传输层安全协议)对请求进行加密:

客户端与服务器间通信加密:通过使用TLS证书来验证服务器和客户端的身份,从而加密通信。

Kubernetes API server的证书管理:需要为Kubernetes集群中的API服务器配置正确的证书(包括根证书和客户端证书)。

保护内部组件的通信:比如etcd的通信需要加密,并使用适当的证书。

2.认证(Authentication)

2.1 认证方式

    所有Kubernetes集群都有两类用户:由Kubernetes管理的服务账户(ServiceAccount)、普通用户。所有API请求都需要经过身份认证,以确保请求来自合法用户或服务,并授予适当的权限。Kubernetes支持多种认证方式,其中比较常见的是基于令牌的身份验证、x509证书、OpenID Connect(OIDC)、服务账户(ServiceAccount)等。

x509证书:用户通过x509证书与API服务器进行通信。这种方式通常用于Kubernetes管理员、集群节点和集群内的一些服务。例如:客户端使用带有用户身份的证书,通过kubectl命令访问API服务器。

Bearer Token:Kubernetes使用令牌(Token)进行身份验证,客户端可以通过将Bearer Token附加到HTTP请求中进行身份验证。

**OIDC(OpenID Connect)**:通过外部身份提供者(如Google、AWS、Keycloak等)验证用户身份。OIDC是一种基于OAuth2.0协议的身份验证协议,适合于与外部认证服务集成。

服务账户(ServiceAccount):服务账户用于集群内的应用程序或Pod来访问API服务器,通常与RBAC(基于角色的访问控制)结合使用。

    可以指定多个认证模块,在这种情况下,服务器依次尝试每个验证模块,直到其中一个成功。

2.2 ServiceAccount和普通用户的区别

    普通用户通常是指通过kubeconfig文件、证书或OIDC等方式认证的用户,通常是Kubernetes集群的管理员或开发者;Kubernetes不会直接在集群中创建或管理普通用户。

    普通用户使用场景:普通用户用于手动管理集群资源(例如 kubectl 命令行工具)或访问Kubernetes API。

    ServiceAccount是Kubernetes中的一种特殊类型的账户,用于赋予Pod在集群中运行时的身份。它主要用于集群内的自动化服务,而不是手动用户操作。

    ServiceAccount使用场景:ServiceAccount常用于需要与API服务器交互的应用程序,或用于Pod自动管理集群资源。例如CI/CD工具、监控工具、控制器等。

2.3 ServiceAccount管理方式

    每个ServiceAccount都与一个JSON Web Token (JWT) 关联,该令牌存储在Pod的文件系统中,位于** /var/run/secrets/kubernetes.io/serviceaccount/token**路径下。Pod启动后,会使用这个令牌与Kubernetes API服务器进行通信,API服务器根据该令牌进行身份验证。ServiceAccount通常与**RBAC**结合,授予Pod访问某些API资源的权限。

    ServiceAccount可以通过自动或手动方式使用。默认情况下,每个命名空间Namespace都有一个默认的ServiceAccount,Pod启动时会自动关联这个ServiceAccount。如果需要更高的权限或特殊用途,我们也可以手动创建并指定ServiceAccount。
自动ServiceAccount示例
    创建及查看Pod:

#创建Pod

kubectl run my-pod --image=nginx

#查看Pod的ServiceAccount

kubectl get pod my-pod -o yaml

    在输出中,会看到以下部分,表示该Pod使用了
default

ServiceAccount:

serviceAccount: default
serviceAccountName: default

    查看ServiceAccount令牌:

kubectl exec -it my-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token

手动ServiceAccount示例
    创建ServiceAccount:

#手动创建一个新的ServiceAccount

kubectl create serviceaccount my-service-account
#查看ServiceAccount的详细信息

kubectl get serviceaccount my-service-account -o yaml

     创建Pod并绑定自定义的ServiceAccount:
apiVersion: v1
kind: Pod
metadata:
  name: my-pod-with-sa
spec:
  serviceAccountName: my-service-account  # 指定使用的ServiceAccount
  containers:
  - name: my-container
    image: nginx
    验证Pod是否绑定了自定义ServiceAccount:

#创建Pod

kubectl apply -f pod-with-sa.yaml
#查看该 Pod 的详细信息

kubectl get pod my-pod-with-sa -o yaml

    输出中会显示:

serviceAccount: my-service-account
serviceAccountName: my-service-account

    为ServiceAccount配置权限(可选):

#授予

my-service-account

读取Pod信息的权限。

kubectl create role my-role --verb=get,list,watch --resource=pods
kubectl create rolebinding my-role-binding --role=my-role --serviceaccount=default:my-service-account

    ServiceAccount 默认没有太多权限,可以使用
Role

RoleBinding

为它配置权限。

    关于权限在**鉴权 (Authorization)**部分说明。 

3.鉴权 (Authorization)

3.1鉴权方式

    在认证之后,Kubernetes会决定认证通过的用户是否有权限执行特定操作。Kubernetes使用多种授权方式来控制API请求的访问权限。

**RBAC (基于角色的访问控制)**:基于预定义的角色来授予用户或组的权限,通过Role和ClusterRole结合RoleBinding和ClusterRoleBinding来实施访问控制。

**ABAC (基于属性的访问控制)**:通过指定策略文件,根据请求的属性(如用户名、资源类型、动作)决定是否授权。

Webhook模式:将鉴权请求转发到外部服务处理,适合实现自定义的访问控制逻辑。

3.2 RBAC

    RBAC(Role-Based Access Control,基于角色的访问控制)是Kubernetes中的一种访问控制机制,用于定义用户或服务账号对 Kubernetes 资源的访问权限。通过 RBAC,集群管理员可以根据角色分配权限,并通过绑定这些角色给用户、组或ServiceAccount来控制访问权限。

    RBAC 主要由四个核心组件构成:
  • Role:定义某个特定Namespace下的权限。它包含了对资源(例如Pods、Services等)的操作规则(如getcreatedelete等)。

  • ClusterRole:定义集群范围的权限,可以在所有Namespace中使用,或直接应用于集群级资源(如节点、PersistentVolumes等)。

  • RoleBinding:将Role绑定到用户、组或ServiceAccount,使其在指定的Namespace中拥有相应的权限。

  • ClusterRoleBinding:将ClusterRole绑定到用户、组或ServiceAccount,使其在整个集群中拥有相应的权限。

      Role & RoleBinding示例:
    
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default  #作用范围是default命名空间
  name: pod-reader
rules:
- apiGroups: [""]  #空字符串表示核心API组
  resources: ["pods"]
  verbs: ["get", "list", "watch"]  #授予的操作权限
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:  #绑定的用户或服务账户
- kind: User  #可以是User、Group或ServiceAccount
  name: "example-user"  #用户名
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role  #绑定的角色类型
  name: pod-reader  #绑定的角色名称
  apiGroup: rbac.authorization.k8s.io
example-user

现在拥有

default

命名空间中读取

pods

资源的权限。

     ClusterRole & ClusterRoleBinding示例:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-pod-reader
rules:
- apiGroups: [""]  # 核心API组
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: read-pods-clusterwide
subjects:  #绑定的用户或服务账户
- kind: User
  name: "example-user"  #用户名
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole  #绑定ClusterRole
  name: cluster-pod-reader  #绑定的角色名称
  apiGroup: rbac.authorization.k8s.io
ci-service-account

现在可以读取集群中所有命名空间的Pod信息。

4.准入控制 (Admission Control)

    准入控制是对经过认证和授权的API请求进行进一步的检查和修改的一个步骤。在请求进入Kubernetes API Server之前,准入控制器可以阻止请求或修改对象。推荐使用的准入控制器默认情况下都处于启用状态。可以使用--enable-admission-plugins来启用默认设置以外的其他准入控制器。

    常见的内置准入控制器:例如NamespaceLifecycle、LimitRanger、PodSecurity、RuntimeClass等,用于特定的访问和资源管理。以下介绍PodSecurity概念:

PodSecurity

     **Pod 安全性标准(Pod Security Standards,PSS)**是Kubernetes提供的一套安全标准,用于定义和管理Pod 的安全策略。通过使用Pod安全性标准,Kubernetes集群管理员可以控制和限制 Pod在运行时的行为,从而提高集群的整体安全性。这套标准是通过Kubernetes的内置准入控制器**PodSecurity**来实现的。

    默认情况下,Kubernetes不启用PodSecurity,因此没有默认的安全级别和模式。如果启用PodSecurity准入控制器,默认的安全级别和模式需要手动配置。
安全级别
    Pod 安全性标准主要定义了三个安全级别(或模式):
  • 特权级别(Privileged)- 用途:最宽松的安全级别,允许Pod以完全特权运行。适用于那些需要完全控制底层主机的Pod,例如需要执行主机级别操作的系统组件或Pod。- 特点:- 允许使用特权模式、HostPath挂载、特权容器、HostNetwork等功能。- 几乎没有安全约束,风险较高。
  • 基线级别(Baseline)- 用途:旨在允许大多数应用程序正常运行,同时施加基本的安全限制。适合一般的应用程序。- 特点:- 拒绝特权模式和特权容器。- 限制HostPath挂载,防止容器访问主机的敏感文件。- 限制某些Linux特性,如CAP_SYS_ADMIN等高危特权。- 禁止使用HostNetworkHostPID
  • 受限级别(Restricted)- 用途:最严格的安全级别,施加了所有可用的最佳安全实践。适用于高度敏感的应用程序,需要严格限制Pod的行为。- 特点:- 禁止一切特权操作,包括HostPath挂载、特权容器、HostNetwork、HostPID、HostIPC等。- 强制限制容器的用户权限(如不能以root用户身份运行容器)。- 强制限制进程和文件系统的权限,最大限度减少攻击面。
安全实施
      Pod 安全性标准的实施分为以下几种操作模式:
  • Enforce(执行):强制执行指定的安全策略,如果Pod不符合要求,则禁止其创建或更新。

  • Audit(审计):记录违反安全策略的操作,但不阻止Pod创建或更新。

  • Warn(警告):向用户发出警告,通知其违反了安全策略,但不阻止Pod创建或更新。

      这些模式允许管理员以递进方式加强安全控制,逐步引导开发人员适应更严格的安全标准。
    
配置示例
apiVersion: v1
kind: Namespace
metadata:
  name: restricted-namespace
  labels:
    pod-security.kubernetes.io/enforce: "restricted"  #强制执行受限级别
    pod-security.kubernetes.io/audit: "baseline"      #审计基线级别
    pod-security.kubernetes.io/warn: "baseline"       #警告基线级别
    在这个示例中,
restricted-namespace

命名空间中,强制执行受限级别的Pod安全策略,并在审计和警告模式下评估基线级别的策略。

apiVersion: v1
kind: Namespace
metadata:
  name: baseline-namespace
  labels:
    pod-security.kubernetes.io/enforce: "baseline"  #强制执行基线级别
    在这个示例中,
baseline-namespace

命名空间中,所有创建的Pod必须符合基线级别的安全标准,否则创建或更新请求将被拒绝。

二、审计 (Auditing)

     Kubernetes 审计日志会记录API服务器处理的每一个HTTP请求,它包括从请求的接收到最终的处理结果(允许或拒绝),以及返回的响应。审计的事件按照发生的顺序记录下来,管理员可以根据这些日志了解集群的操作情况。

    Kubernetes 默认**没有开启审计**,需要在
kube-apiserver

的配置文件中启用审计功能,并手动配置审计策略文件。API 服务器不默认生成审计日志,也没有预设的审计级别。

审计架构

审计系统由三个主要组件组成:

  • Audit Policy:定义审计事件的记录规则,如记录哪些操作、哪些用户的行为等。
  • Audit Sink:审计日志的存储位置,可以是文件、标准输出,或通过HTTP Webhook发送到外部服务。
  • Audit Event:每个 API 请求会被记录为一个审计事件,包含详细的上下文信息。

审计策略(Audit Policy)

    审计策略通过一个策略文件来定义,策略文件控制什么样的API请求会被记录,以及记录的详细程度。

审计级别

    每个请求可以按不同的审计级别记录:
  • None:不记录任何内容。
  • Metadata:仅记录请求的元数据(如用户、操作、时间等),不记录请求和响应的内容。
  • Request:记录请求的元数据以及请求体,但不记录响应体。
  • RequestResponse:记录请求的元数据、请求体和响应体,包含了所有详细信息。

审计策略文件示例

    一个典型的审计策略文件会定义不同资源、不同用户和操作的记录级别。下面是一个示例策略文件:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse  # 对于所有的pod操作,记录请求和响应
  resources:
  - group: ""
    resources: ["pods"]
- level: Metadata  #对于所有的secrets操作,记录元数据
  resources:
  - group: ""
    resources: ["secrets"]
- level: None  #忽略对serviceaccounts的请求
  resources:
  - group: ""
    resources: ["serviceaccounts"]
- level: Request  #记录所有的请求操作和元数据
  users: ["system:serviceaccount:kube-system:default"]
  verbs: ["create", "update", "patch"]
- level: Metadata  #默认记录所有其他请求的元数据
  omitStages:
  - "RequestReceived"
    这个策略文件的规则说明如下:
  • 对于所有的Pod操作,记录详细的请求和响应。
  • 对于 Secret 操作,仅记录元数据(例如操作的时间、用户)。
  • 忽略ServiceAccount的所有操作。
  • 对特定的服务账户的createupdatepatch请求,记录请求的详细信息。
  • 对所有其他请求,默认记录元数据。

审计日志的存储(Audit Sink)

    Kubernetes 支持多种审计日志的输出方式,通常包括:
  • 文件输出:将审计日志写入文件。

  • Webhook 输出:通过HTTP POST请求将审计日志发送到外部服务。

      文件输出是一种常见的方式,API服务器可以将审计日志写入到指定文件。 启动
    
kube-apiserver

时,可以通过以下参数配置文件输出:、

kube-apiserver
--audit-policy-file=/etc/kubernetes/audit-policy.yaml
--audit-log-path=/var/log/kubernetes/audit.log
--audit-log-maxage=30
--audit-log-maxbackup=10
--audit-log-maxsize=100

  • --audit-policy-file:指定审计策略文件路径。
  • --audit-log-path:审计日志文件的存储路径。
  • --audit-log-maxage:日志文件保存的最大天数。
  • --audit-log-maxbackup:保留的旧审计日志文件的最大数量。
  • --audit-log-maxsize:每个日志文件的最大大小(以 MB 为单位)。

审计事件结构

     审计日志中的每个事件都包含丰富的上下文信息,在下面的输出示例中,
requestObject

responseObject

分别记录了请求和响应的详细内容:

{
  "kind": "Event",
  "apiVersion": "audit.k8s.io/v1",
  "level": "RequestResponse",
  "stage": "ResponseComplete",
  "requestURI": "/api/v1/namespaces/default/pods",
  "verb": "create",
  "user": {
    "username": "admin",
    "groups": ["system:masters"]
  },
  "sourceIPs": ["192.168.1.100"],
  "objectRef": {
    "resource": "pods",
    "namespace": "default",
    "name": "my-pod"
  },
  "responseStatus": {
    "metadata": {},
    "code": 201
  },
  "requestObject": {
    "kind": "Pod",
    "metadata": {
      "name": "my-pod"
    },
    "spec": {
      "containers": [
        {
          "name": "nginx",
          "image": "nginx:latest"
        }
      ]
    }
  },
  "responseObject": {
    "kind": "Pod",
    "metadata": {
      "name": "my-pod"
    },
    "spec": {
      "containers": [
        {
          "name": "nginx",
          "image": "nginx:latest"
        }
      ]
    }
  }
}

三、Secret

    Secret API为需要保密的配置值提供基本保护。可以回顾 Kubernetes从零到精通(13-Configmap、Secret)

四、网络策略(NetworkPolicy)

    Kubernetes 中的网络策略(NetworkPolicy) 是一种控制Pod间流量和Pod与外部网络流量的安全机制。它允许用户定义哪些流量可以进入和离开Pod,以确保集群的安全性。

    网络策略**仅会在支持网络策略的网络插件CNI(如 Calico)中生效**。Kubernetes 默认的网络实现不支持网络策略。网络插件可以回顾Kubernetes从零到精通(11-CNI网络插件)。

网络策略的作用

    NetworkPolicy是通过定义一组规则来允许或拒绝指定Pod的网络流量。这些规则可以基于:
  • 命名空间:限制特定命名空间中的 Pod 间的流量。
  • Pod 标签:限制带有特定标签的 Pod 间的流量。
  • IP Block:限制特定的 IP 地址段的流量。

网络策略的工作原理

    Kubernetes 网络策略主要用来定义:
  • 入口流量(Ingress):进入Pod的流量。
  • 出口流量(Egress):从Pod发送出的流量。

没有配置网络策略时,所有Pod之间的网络流量默认是允许的,一旦定义了网络策略,只有符合规则的流量才会被允许。

网络策略的基本结构

    一个网络策略通过以下几部分定义:
  • Pod选择器:选择哪些 Pod 应该应用这条策略。
  • 策略类型Ingress(不是Ingress、Gateway api,只是名称相同)Egress,指定策略是控制入口流量还是出口流量。
  • 规则:指定允许哪些流量通过,规则可以基于Pod标签、IP 地址块、命名空间等定义。

网络策略示例

    下面的网络策略将阻止所有流向
my-pod

的流量,除了带有特定标签的Pod发送的流量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-specific-pods
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: my-pod  #应用此策略的Pod
  policyTypes:
  - Ingress  #定义入口流量规则
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: allowed-app  #允许带有此标签的Pod发送流量
    该策略允许来自特定IP地址段(如192.168.0.0/16)的流量,其他流量会被拒绝:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-ip-range
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: my-pod  #应用此策略的Pod
  policyTypes:
  - Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 192.168.0.0/16  #允许的IP地址范围
     下面的网络策略允许Pod访问外部网络(**注意这里只是在策略上允许访问外部网络,底层网络能不能支持该**Pod**访问外部网络,需要看具体网络情况**),但限制对特定命名空间内其他 Pod 的访问:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-egress
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: my-app
  policyTypes:
  - Egress  #定义出口流量规则
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0  #允许Pod访问外部网络
    该策略将完全隔离某个Pod的网络流量,既不允许它接收流量,也不允许它发送流量:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: isolated-pod  #目标Pod
  policyTypes:
  - Ingress  #不允许任何流量进入
  - Egress   #不允许任何流量离开

本文转载自: https://blog.csdn.net/fzw1030/article/details/142597314
版权归原作者 炸裂狸花猫 所有, 如有侵权,请联系我们删除。

“Kubernetes从零到精通(15-安全)”的评论:

还没有评论