对于在共享基础架构上运行的容器化应用程序,安全性至关重要。随着越来越多的组织将其容器流量负载转移到 Kubernetes,K8s 已成为容器编排的首选平台。随着这一趋势的出现,越来越多的威胁和新的攻击方式层出不穷。

在 Kubernetes 中,安全性有两个方面:集群安全性和应用程序安全性。在这篇文章中,我们将探讨如何保护Kubernetes Deployment资源类型和应用程序的安全。

基础知识

在这里快速回顾一下基础知识:Pod 是在 集群中运行一个或多个容器的逻辑原子单元;它由其他资源包装,例如 ReplicaSet、Deployment、StatefulSets 等。有多种方法可以改善在 Kubernetes 中运行的应用程序的安全状况。

在 Kubernetes 部署中, 模板 部分包含 pod 规范,这些规范定义了此部署必须运行的工作负载。在下面的模板中,几个与安全相关的部分以粗体突出显示:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx
spec:
 selector:
   matchLabels:
     app: nginx
 template:
   metadata:
     labels:
       app: nginx
   spec:
     serviceAccountName: nginx-sa
     securityContext:
       runAsUser: 1000
       runAsGroup: 3000
       fsGroup: 2000
     containers:
     - name: nginx
       image: my-private-registry.io/nginx:1.34
       resources:
         limits:
           memory: "128Mi"
           cpu: "500m"
       ports:
       - containerPort: 80
       securityContext:
         allowPrivilegeEscalation: false
         seccompProfile:
           type: RuntimeDefault
         capabilities:
           add: ["NET_ADMIN", "SYS_TIME"]
         seLinuxOptions:
           level: "s0:c123,c456"

现在让我们仔细看看 pod 规范中声明的这些部分。

Service Account

当容器内的进程与 API 服务器通信时,您应该使用服务帐户进行身份验证。如果您没有为 pod 定义服务帐户,则将使用默认帐户。建议使用执行该功能所需的最低权限创建一个特定于应用程序的服务帐户。如果您选择将角色授予默认服务帐户,则这些权限将可用于未在规范中定义服务帐户的每个 pod。这可能会无意中允许对其他应用程序的过度许可,因此不建议这样做。在 Kubernetes 1.6 及更高版本中,您可以通过设置来选择不为容器中的服务帐户自动挂载 API 令牌。

automountServiceAccountToken: false. 
For example:
apiVersion: v1
kind: ServiceAccount
metadata:
 name: nginx-sa
automountServiceAccountToken: false

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
 name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
 resources: ["pods"]
 verbs: ["get", "watch", "list"]

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
 name: read-pods
 namespace: default
subjects:
- kind: ServiceAccount
 name: nginx-sa # "name" is case sensitive
 namespace: default
roleRef:
 kind: Role
 name: pod-reader
 apiGroup: rbac.authorization.k8s.io

安全上下文

安全上下文定义和容器中的权限和访问控制设置。以下是一些重要的列表:

  • seLinuxOptions (Security-Enhanced Linux):应用提供更精细访问和控制策略的机制

  • runAsUser和runAsGroup:特定的UserID或GroupID(UID和GID)运行容器进程的入口点;如果未指定,则默认为用户在图像元数据中指定的(在 Windows 容器中均无效)。

  • privileged:以特权模式运行容器,默认为 false;与主机上的 root(具有所有功能)相同

  • runAsNonRoot:容器必须以非 root 用户身份运行(如果 Kubelet 在运行时验证时 UID 为 0,则容器将无法启动)。

  • capabilities:在运行容器时添加或删除能力;容器运行时授予功能,这是默认设置。

  • procMount:指定容器的 proc 挂载类型,默认为 DefaultProcMount;这将容器运行时默认值用于只读和掩码路径。

  • AppArmor:与 SELinux 类似,可以通过配置文件限制单个程序的功能。

  • seccompProfile:容器使用的 secomp 选项;过滤进程的系统调用

  • readOnlyRootFilesystem:将容器中的根文件系统挂载为只读;默认为false

  • AllowPrivilegeEscalation:决定一个进程是否可以获得比其父进程更多的权限;如果容器以 Privileged 或具有 CAP_SYS_ADMIN 功能运行,则始终为 true。该字段必须显式设置为 false,因为它的默认行为可能会在 PSP 中更改。

镜像

源镜像通常取自各种公共存储库;开发人员将他们的应用程序代码放在这些基础镜像之上。您还可以直接从流行的公共注册中心部署 OOTB 应用程序。

关于图像,需要牢记三件事,我们将在下面讨论。

镜像来源

确保您从受信任的注册表中获取镜像。攻击者可以将恶意图镜像放置在公共注册表中,这反过来又会导致数据泄露或攻击者获得对集群的访问权等问题。许多公共镜像也被发现被加密矿工机感染。

作为一个组织,您可以创建基本镜像并与开发人员共享它们,然后开发人员可以从他们的内部存储库中安全地使用它们。

Distroless 和容器优化镜像

这些镜像安全且经过优化,可在容器中运行,从而减少了潜在攻击的表面积。它们仅包含您的应用程序和依赖库,而 Linux 操作系统上通常可用的包管理器、shell 和程序已被删除。

持续漏洞扫描

强烈建议实施连续镜像扫描,以检测容器镜像中的漏洞、恶意软件和其他安全威胁(例如,与不受信任的网络的未经授权的连接)。有许多可用的安全解决方案,包括 Kubescape。

Pod 准入控制

您可能听说过 PodSecurityPolicies,它现在已被弃用,将在 Kubernetes 1.25 中删除。Pod S安全准入 (PSA) 将取代它,处理安全和其他与安全相关的要求。它为 pod 定义了不同的隔离级别,例如 privileged、  baseline和 restricted。截至 1.23,PSA 目前处于测试阶段。

这些级别在 Kubernetes 的 Pod 安全标准中有详细描述,但下面是 Kubernetes 自己的文档的摘要:

  • Privileged 该政策不受限制,并授予尽可能广泛的权限;它允许已知的特权升级。

  • Baseline 此策略具有最低限度的限制,防止已知的特权升级并允许默认(最低限度指定)pod 配置。

  • Restricted 此策略受到极大限制,并以当前的 pod 强化最佳实践为指导。

Pod Security 准入与内置的 Pod Security 准入控制器配合使用;您需要在集群中使用 –feature-gates=”...,PodSecurity=true” 或使用 pod admission webhook启用此功能。它应用于命名空间级别,带有以下标签:

  • Enforce 如果违反政策,该 pod 将被拒绝。

  • Audit 允许违反策略,但它们会触发对审计日志中记录的事件的注释。

  • Warn 违反政策将提示面向用户的警告,但仍然允许。在命名空间中,使用以下注解启用 Pod 安全准入:

# MODE can be one of enforce, audit or warn
# LEVEL can be one of privileged, baseline or restricted
# VERSION must be valid Kubernetes minor version or latest.
pod-security.kubernetes.io/<MODE>: <LEVEL>
pod-security.kubernetes.io/<MODE>-version: <VERSION>

使用Securit

如果您在应用程序中有可用的敏感信息(如凭证、令牌、加密密钥和证书),请使用 Kubernetes Secrets。您可以使用文字值或文件创建 Secret,然后将它们挂载到 pod 中。不要将此类信息存储在容器映像和 Git 存储库中。

使用 Secrets 时,最好不要使用环境变量将凭据投影到容器中,而是使用文件。

请记住,Secrets 是 base64 编码的值。它们未加密,因此必须限制对安全对象的访问,并且您应该  在 API 服务器的写入时启用加密。

总结

Kubernetes 提供了多种方法来改善您组织的安全状况。开发人员需要考虑这些结构以使他们的应用程序更安全。

回顾一下:

  • 每个应用程序使用服务帐户,并将服务帐户与最低角色和权限要求绑定,以实现您的目标。

  • 如果您的应用程序不需要服务帐户令牌,请不要自动挂载它。

  • 使用安全上下文来实现各种技术,例如防止容器在特权模式下以 root 用户身份运行,使用 SELinux 或 AppArmor 配置文件等等。

  • 确保你的容器镜像的来源是可信的,如果可能的话,将它们存储在私有注册表中。

  • 尝试使用优化镜像来减少表面积以最大程度地减少威胁。

  • 部署持续的漏洞扫描解决方案,不仅在 CI/CD 中,而且在集群中,可以实时监控和采取行动。

  • 使用 Pod 安全准入配置文件和模型为您的工作负载提供不同的隔离级别。

  • 使用 Secrets 存储敏感信息,并应用最低权限 RBAC 来限制用户/SA 秘密访问。

  • 对于应用程序开发人员来说,这一切似乎都是压倒性的。Kubescape等工具  可以帮助进行风险分析、CI/CD 中安全标准的实施、易于理解的 RBAC 可视化、自动漏洞扫描等等。Kubescape 帮助开发人员实现其应用程序的安全部署。

f21aa8d675bbfd58af5317df32baba63.png

推荐

如何在云原生中监控JVM指标

Kubernetes入门培训(内含PPT)


原创不易,随手关注或者”在看“,诚挚感谢!

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐