跳转至

K8s 相关问题集锦(四)

6 安全类

6.1 管理访问控制

通过 RBAC(Role-Based Access Control)管理用户和服务账户的权限,描述 Role、ClusterRole、RoleBinding、ClusterRoleBinding 的作用。

Kubernetes 中的访问控制管理通过 RBAC(基于角色的访问控制)来实现,RBAC 允许你对集群中资源的访问进行控制。RBAC 的管理主要依赖于以下几个对象:Role、ClusterRole、RoleBinding、ClusterRoleBinding。

1. Role 和 ClusterRole

  • Role 是在命名空间内定义的访问权限集合,用于控制特定命名空间内资源的访问权限。
  • 例如,允许用户在命名空间 dev 中读取所有的 pod。
  • ClusterRole 则作用于整个集群,可以用于跨多个命名空间,或者在没有特定命名空间的资源(如节点)上进行权限控制。
  • 例如,允许用户在整个集群中读取所有命名空间的 pod。

示例:

```yaml

定义一个 Role,允许用户在 dev 命名空间中读取 Pod 资源

apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: dev name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"] ```

```yaml

定义一个 ClusterRole,允许用户读取集群中所有命名空间的 Pod

apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cluster-pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"] ```

2. RoleBinding 和 ClusterRoleBinding

  • RoleBinding 将 Role 绑定到一个用户或服务账户上,从而赋予该用户对特定命名空间的资源的访问权限。
  • ClusterRoleBinding 将 ClusterRole 绑定到一个用户或服务账户上,从而赋予该用户对整个集群的资源的访问权限。

示例:

```yaml

定义一个 RoleBinding,将 pod-reader Role 绑定到一个用户(或服务账户)上

apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods-binding namespace: dev subjects: - kind: User name: jane # 用户名称 apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io ```

```yaml

定义一个 ClusterRoleBinding,将 cluster-pod-reader ClusterRole 绑定到一个用户上

apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: cluster-read-pods-binding subjects: - kind: User name: john # 用户名称 apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: cluster-pod-reader apiGroup: rbac.authorization.k8s.io ```

操作步骤

  1. 创建 Role 或 ClusterRole

  2. 使用 kubectl apply -f role.yaml 命令创建 Role。

  3. 使用 kubectl apply -f clusterrole.yaml 命令创建 ClusterRole。
  4. 创建 RoleBinding 或 ClusterRoleBinding

  5. 使用 kubectl apply -f rolebinding.yaml 创建 RoleBinding,将 Role 绑定到用户。

  6. 使用 kubectl apply -f clusterrolebinding.yaml 创建 ClusterRoleBinding,将 ClusterRole 绑定到用户。
  7. 验证权限

  8. 你可以使用 kubectl auth can-i 命令来验证一个用户是否具有特定操作权限。例如: sh kubectl auth can-i list pods --namespace dev --as jane

  9. 以上命令会返回 yesno,表示 jane 用户是否有权限列出 dev 命名空间的 Pod。

总结

  • Role:为某个命名空间定义权限。
  • ClusterRole:为集群中所有命名空间或集群级资源定义权限。
  • RoleBinding:将一个 Role 绑定到用户或服务账户上,使其在命名空间中获得相应权限。
  • ClusterRoleBinding:将 ClusterRole 绑定到用户或服务账户上,使其获得集群级权限。

通过灵活地配置这些资源,Kubernetes 的访问控制可以很好地实现最小权限原则,从而保障集群的安全性。

6.2 PodSecurityPolicy 是什么?

PodSecurityPolicy 是什么?- PodSecurityPolicy 用于定义和控制 Pod 的安全策略,比如是否允许特权容器、挂载卷的类型等。

PodSecurityPolicy(PSP)是 Kubernetes 提供的一种用于控制和定义 Pod 安全性设置的策略对象。通过 PodSecurityPolicy,管理员可以对 Pod 的安全相关属性进行限制,确保集群中的 Pod 遵循安全策略,减少潜在的安全风险。

1. PodSecurityPolicy 的作用

PodSecurityPolicy 主要用于定义和控制 Pod 的以下安全设置:

  • 特权容器:是否允许 Pod 运行为特权容器。
  • 卷挂载类型:限制 Pod 可挂载的卷类型,如 hostPathNFS 等。
  • 宿主机文件系统:控制是否允许 Pod 挂载宿主机上的目录。
  • Linux 能力:限制容器中添加的 Linux 能力(Capabilities)。
  • 用户和组:控制运行容器的用户和组 ID,确保 Pod 不会以特权用户身份运行。
  • Root 权限:限制容器是否能以 root 身份运行。
  • SELinux:限制 Pod 的 SELinux 上下文。
  • AppArmor:定义容器的 AppArmor 安全配置。

通过 PSP,可以控制哪些 Pod 能够在集群中部署,限制特定行为(例如使用特权容器),以防止某些恶意行为或误操作对集群造成的潜在威胁。

2. PodSecurityPolicy 示例

以下是一个简单的 PodSecurityPolicy YAML 文件示例:

yaml apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: restricted spec: privileged: false # 不允许使用特权容器 allowPrivilegeEscalation: false # 不允许权限提升 seLinux: rule: RunAsAny # SELinux 配置规则 runAsUser: rule: MustRunAsNonRoot # 必须以非 root 用户运行 fsGroup: rule: MustRunAs ranges: - min: 1 max: 65535 volumes: - 'configMap' - 'emptyDir' - 'projected' - 'secret'

这个策略禁止使用特权容器,不允许权限提升,要求 Pod 以非 root 用户身份运行,并限制 Pod 能够挂载的卷类型。

3. 启用和使用 PodSecurityPolicy

  1. 启用 PodSecurityPolicy

  2. 在 Kubernetes 1.21 及之前版本中,可以通过 API server 参数 --enable-admission-plugins 启用 PodSecurityPolicy

  3. 创建 PodSecurityPolicy

  4. 使用上面的 YAML 文件定义 PodSecurityPolicy,然后通过 kubectl apply -f psp.yaml 创建它。

  5. 创建 RBAC 绑定

  6. PSP 本身并不会自动生效,必须通过 RBAC(Role-Based Access Control)将其与特定的用户或服务账户绑定。可以通过 RoleBinding 或 ClusterRoleBinding 将 PodSecurityPolicy 赋予特定用户。

yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: use-psp namespace: default rules: - apiGroups: - policy resourceNames: - restricted # PodSecurityPolicy 的名称 resources: - podsecuritypolicies verbs: - use

yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: use-psp-binding namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: use-psp subjects: - kind: ServiceAccount name: default namespace: default

4. PodSecurityPolicy 的弃用

需要注意的是,从 Kubernetes 1.21 开始,PodSecurityPolicy 已被标记为废弃,并计划在 Kubernetes 1.25 中移除。为了替代 PSP,Kubernetes 社区推荐使用更现代化的解决方案,如 Pod Security Admission(一种新的安全模式)或第三方工具,例如 Open Policy Agent(OPA)、Kyverno 等。

Pod Security Admission 使用三种策略来控制 Pod 的安全性:

  • Privileged(特权级):允许所有的 Pod,安全限制较少。
  • Baseline(基线级):阻止使用不安全的配置,例如特权容器,但允许普通应用程序的常见配置。
  • Restricted(受限级):对 Pod 进行最严格的安全限制,适用于高度安全的环境。

总结

  • PodSecurityPolicy 是一种用于控制 Pod 安全性的策略,帮助管理员对 Pod 的安全属性进行配置和限制。
  • 它控制了如特权容器、挂载卷类型、用户 ID、权限提升等安全设置,确保 Pod 运行时遵循集群的安全标准。
  • 从 Kubernetes 1.21 开始,PSP 已被废弃,推荐使用 Pod Security Admission 或其他现代化的替代方案。

6.3 配置 HTTPS

在 Kubernetes 集群中启用 HTTPS 是确保集群通信安全的重要步骤,通常包括以下两部分:

  1. 为集群的 API Server 配置安全连接(HTTPS)。
  2. 使用证书管理工具(例如 cert-manager)为集群中的应用程序自动管理和配置 HTTPS。

下面分别讨论如何实现这些目标:

1. 为 Kubernetes API Server 配置 HTTPS

Kubernetes API Server 是集群的核心组件,它为其他组件提供交互接口。为 API Server 配置 HTTPS,确保集群通信的安全性,可以按照以下步骤进行:

1.1 生成证书和密钥

首先,API Server 需要使用 TLS 证书进行加密。你可以使用 openssl 或其他证书管理工具来生成证书和私钥。

使用 openssl 生成自签名证书示例:

```sh

生成 CA 证书和私钥

openssl genrsa -out ca.key 2048 openssl req -x509 -new -nodes -key ca.key -subj "/CN=kubernetes-ca" -days 365 -out ca.crt

生成 API Server 私钥

openssl genrsa -out apiserver.key 2048

生成 API Server CSR(证书签名请求)

openssl req -new -key apiserver.key -subj "/CN=kubernetes-apiserver" -out apiserver.csr

使用 CA 签署 API Server 证书

openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out apiserver.crt -days 365 ```

1.2 配置 API Server 使用证书

将生成的证书和私钥放置在 Kubernetes API Server 所在的节点上。你需要编辑 Kubernetes API Server 的启动配置(通常是一个配置文件或服务启动参数),添加如下参数:

sh --tls-cert-file=/path/to/apiserver.crt --tls-private-key-file=/path/to/apiserver.key --client-ca-file=/path/to/ca.crt

  • --tls-cert-file:指定 API Server 使用的 TLS 证书路径。
  • --tls-private-key-file:指定 API Server 使用的私钥路径。
  • --client-ca-file:用于对客户端证书进行验证的 CA 证书。

编辑完配置文件后,重启 API Server 服务以使新配置生效。

2. 使用 cert-manager 管理证书

在 Kubernetes 集群中,不仅需要为 API Server 启用 HTTPS,还需要为应用程序启用 HTTPS。cert-manager 是 Kubernetes 集群中非常流行的自动化证书管理工具。

2.1 cert-manager 简介

cert-manager 是 Kubernetes 上的一个控制器,用于自动管理和颁发 SSL/TLS 证书。它可以使用像 Let’s Encrypt 这样的证书颁发机构(CA)来申请和自动更新证书,确保集群中的服务始终使用有效的 HTTPS 连接。

2.2 cert-manager 安装

可以使用 kubectlHelm 安装 cert-manager。以下是 Helm 安装示例:

  1. 添加 cert-manager 的 Helm 仓库:

sh helm repo add jetstack https://charts.jetstack.io helm repo update 2. 使用 Helm 安装 cert-manager:

sh kubectl create namespace cert-manager helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.9.1 \ --set installCRDs=true

安装完成后,cert-manager 将部署在 cert-manager 命名空间中,并在集群中运行以管理证书。

2.3 创建 Issuer 和 ClusterIssuer

IssuerClusterIssuer 是 cert-manager 中定义的资源,用于指定证书颁发机构(CA)。Issuer 用于特定命名空间,而 ClusterIssuer 可以在整个集群中使用。

下面是一个使用 Let’s Encrypt 创建 ClusterIssuer 的示例:

yaml apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: your-email@example.com # 申请证书的邮箱 privateKeySecretRef: name: letsencrypt-prod-private-key solvers: - http01: ingress: class: nginx # 指定 Ingress 控制器

2.4 为 Ingress 配置 HTTPS

要为 Kubernetes 中的服务启用 HTTPS,通常结合 Ingress 使用。在 Ingress 中引用 cert-manager 生成的证书,确保服务通过 HTTPS 对外暴露。

以下是一个 Ingress 配置示例,使用 cert-manager 申请证书:

yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress namespace: default annotations: cert-manager.io/cluster-issuer: "letsencrypt-prod" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" spec: tls: - hosts: - example.com secretName: example-com-tls # cert-manager 将自动创建这个 secret rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: example-service port: number: 80

在这个配置中:

  • cert-manager.io/cluster-issuer:指定使用的 ClusterIssuer。
  • tls:定义使用 TLS 并创建一个 secret,存储证书和私钥。
  • nginx.ingress.kubernetes.io/force-ssl-redirect:强制 HTTP 请求重定向到 HTTPS。

当创建了这个 Ingress 后,cert-manager 将自动向 Let’s Encrypt 申请证书,并在 example-com-tls Secret 中保存证书和密钥。

总结

  • 为 Kubernetes API Server 配置 HTTPS,可以通过生成自签名证书并配置 API Server 启动参数来实现。
  • cert-manager 是 Kubernetes 集群中用于管理 SSL/TLS 证书的自动化工具,可以与 Ingress 一起为集群中的应用服务配置和管理 HTTPS。
  • 使用 cert-manager 可以显著简化证书的申请、续期和管理过程,确保集群中的服务始终保持安全通信。