KurosuSama/k8s-kustomize-devsecops

GitHub: KurosuSama/k8s-kustomize-devsecops

一个基于 Kustomize 与 GitOps 实践的 Kubernetes 多环境 DevSecOps 基础设施项目,对多层应用从构建、部署、网络到运行时进行全链路安全加固。

Stars: 0 | Forks: 0

# Kubernetes DevSecOps 平台 (Kustomize) ![Kubernetes](https://img.shields.io/badge/kubernetes-%23326ce5.svg?style=for-the-badge&logo=kubernetes&logoColor=white) ![Kustomize](https://img.shields.io/badge/kustomize-%23326ce5.svg?style=for-the-badge&logo=kubernetes&logoColor=white) ![Falco](https://img.shields.io/badge/falco-%2300AEC7.svg?style=for-the-badge&logo=falco&logoColor=white) ![Trivy](https://img.shields.io/badge/trivy-%231904DA.svg?style=for-the-badge&logo=aqua&logoColor=white) ![Prometheus](https://img.shields.io/badge/prometheus-%23E6522C.svg?style=for-the-badge&logo=prometheus&logoColor=white) ![GitHub Actions](https://img.shields.io/badge/github%20actions-%232671E5.svg?style=for-the-badge&logo=githubactions&logoColor=white) 一个使用 Kustomize 部署在 Kubernetes 上的多层应用,在构建、部署、网络和运行时层面进行了安全加固。它结合了预防性控制(镜像扫描、Pod 加固、准入控制执行、网络隔离)以及通过 Falco 进行的运行时检测,并通过 GitHub Actions 从 staging 环境推广至 production 环境。 ## 项目目标 该项目分两个阶段构建。 **第一阶段 — 部署。** 一个使用 Kustomize(base + overlays)运行在 Kubernetes 上的多层应用。应用本身(一个多层的 Java 技术栈)只是一个真实的工作负载。该项目真正的核心在于其周围的平台。 **第二阶段 — 安全。** 根据 DevSecOps 实践对第一阶段的部署进行审计,并逐一解决各层级的漏洞:供应链、Pod 安全、准入控制、网络、运行时以及可观测性。 目标是在构建、部署、网络和运行时层面遵循 DevSecOps 最佳实践来构建并保护基础设施。 ### 审计发现与修复方案 安全加固是由对第一阶段部署的审计驱动的。下表将每个初始状态的缺陷与相应的修复措施进行了对应展示。 | 领域 | 之前 (第一阶段) | 之后 (已加固) | | :--- | :--- | :--- | | **镜像供应链** | **可变的 `:latest` 标签。** 任何对镜像仓库的覆盖操作都会在下次重启时被静默拉取。 | **Digest 锁定镜像。** 通过 `@sha256` 锁定并配置显式的拉取策略;每次运行的都是经过确切审查的镜像,标签覆盖无法对其进行替换。 | | **CI 安全** | **无扫描。** 代码未经过扫描即发布。 | **阻塞性 Trivy 门禁。** 文件系统及 Kubernetes 配置错误扫描,锁定到特定发布版本,遇到 CRITICAL/HIGH 漏洞时使构建失败。 | | **集群访问 (CI)** | **关闭 TLS 验证。** 基于 Token 访问且禁用了 API-server 的 TLS 验证。 | **已验证的 kubeconfig。** 包含集群 CA 的完整 kubeconfig,从而验证到 API server 的 TLS 连接。 | | **Pod 安全** | **默认特权模式。** 容器以 root 身份运行,具有可写的 root FS 和所有 capabilities。 | **Restricted 配置。** 非 root 用户、只读 root FS、Drop 掉的 capabilities,以及在每个 Pod 上启用 seccomp `RuntimeDefault`。 | | **准入控制** | **无准入门禁。** 命名空间接受任何 Pod,包括特权 Pod。 | **Pod Security Admission。** `enforce: restricted` 在 API server 处拒绝不符合规范的 Pod。 | | **网络** | **扁平网络。** 每个 Pod 都能访问其他所有 Pod 和后端。 | **零信任 NetworkPolicies。** `default-deny-all` 加上针对每个数据流的显式允许,因此无关的 Pod 之间无法互相访问。 | | **运行时检测** | **无运行时可见性。** 仅具备预防性控制。 | **Falco DaemonSet。** 监控系统调用,并在应用 Pod 内部发生启动 shell、读取凭据和篡改行为时向 Telegram 发送告警。 | | **可观测性** | **无监控。** 没有任何监控措施。 | **Kube-prometheus-stack。** Prometheus、Grafana 和 Alertmanager 路由告警至 Telegram,经过调优以过滤 k3s 的误报和 Watchdog 的死信开关。 | ## 技术栈 * **编排:** Kubernetes (k3s) * **配置管理:** Kustomize (base + staging/prod overlays) * **镜像扫描:** Trivy (CI 门禁) * **准入控制:** Pod Security Admission (`restricted`) * **网络安全:** Kubernetes NetworkPolicy (零信任) * **运行时安全:** Falco + falcosidekick * **密钥管理:** Bitnami SealedSecrets * **可观测性:** kube-prometheus-stack (Prometheus, Grafana, Alertmanager) * **CI/CD:** GitHub Actions * **Ingress / LB:** ingress-nginx + MetalLB ## 安全态势 该平台叠加了多项独立的控制措施,确保没有任何单一层级会成为攻击者与工作负载之间唯一的防线: | 层级 | 控制措施 | 类型 | | :--- | :--- | :--- | | **构建** | CI 中的 Trivy 文件系统 + 配置扫描 | 预防性 | | **供应链** | 基于 digest 锁定的镜像 | 预防性 | | **部署** | `securityContext` (`restricted`) | 预防性 | | **准入** | Pod Security Admission | 预防性 | | **网络** | `default-deny` + 显式的 NetworkPolicies | 预防性 | | **运行时** | Falco 系统调用监控 | **检测性** | 密钥以 SealedSecrets 的形式存储,使用控制器的公钥进行加密,因此可以安全地提交到 git 仓库,只有集群内部的控制器才能对其进行解密。唯一不能存在于 git 中的是控制器的私钥,它作为恢复依赖被离线保存。 ## 核心特性 * **Digest 锁定镜像:** 应用容器通过 `@sha256` digest 而非变动的标签进行引用,确保每次部署运行的都是在审查中确认的镜像。 * **阻塞性 CI 门禁:** Trivy 运行文件系统扫描和 Kubernetes 配置错误扫描,两者均锁定到特定发布版本,遇到 CRITICAL/HIGH 漏洞时使流水线失败。 * **加固的 Pod 与准入执行:** 每个工作负载都以非 root 用户运行,具备只读的 root FS、被 drop 掉的 capabilities、禁止特权升级,以及 `RuntimeDefault` seccomp。随后,Pod Security Admission 会在 API server 处拒绝任何不符合规范的配置。我通过尝试在该命名空间中运行一个普通的 `alpine` Pod 并收到 `Forbidden` 提示验证了这一点。 * **零信任网络:** `default-deny-all` 策略阻止所有流量,显式的允许规则仅重建理应存在的数据流:外部到 Web、Web 到 App、App 到其后端以及 DNS。特别是由于 Memcached 在没有身份验证的情况下运行,防止其被任意 Pod 访问显得尤为重要。 * **运行时检测:** Falco DaemonSet 读取内核系统调用,并在应用 Pod 内部出现交互式 shell、凭据文件读取和日志篡改时向 Telegram 发送告警。这些规则限定于容器事件,否则主机级别的守护进程(DigitalOcean droplet 代理、读取 `/etc/pam.d` 的 systemd)会使通知频道被淹没。 * **基于 Release 的推广:** 每次合并到 `main` 分支时触发 Staging 部署。而 Production 仅在发布 GitHub Release 时触发,并检出对应的 tagged commit,因此合并到标签之后的拼写错误绝不会进入生产环境。部署步骤同样位于 GitHub `environment` 之后,这正是所需审核者门禁将会附加的位置。 ## 已知限制 出于个人作品集项目的范围考虑,有些内容被刻意省略了。 * **Ingress 上的 TLS。** 服务通过 HTTP 运行在公开的 `nip.io` 主机上。配合 Let's Encrypt 的 cert-manager 显然是下一步计划,但 `nip.io` 容易触及生产环境 ACME 颁发机构的速率限制,这使得它不适合用于演示。 * **Grafana 管理员密码。** 这本应是一个受管密钥(通过 `admin.existingSecret` 接入的 SealedSecret)。目前它依赖于 Helm chart 生成的随机密码。虽然不是默认密码,但也未纳入 git 管理。 * **Staging 和 Production 共用一个 Telegram 频道。** 真实的环境应当将它们分开,以免生产环境的告警淹没在 staging 环境的噪音中。 * **Production 仅进行了建模,未实际配置。** `deploy-prod.yaml` 展示了完整的推广模型(Release 触发、tagged checkout、`prod` overlay、针对生产环境的凭据),但生产环境集群从未实际搭建。完整的 DevSecOps 安全态势是在 staging 环境上构建并验证的。 * **镜像推广是手动完成的。** Production 环境运行与 `base` 相同的 digest,因此推广新版本意味着需要手动更新该 digest,而不是通过编写应用 CI 来向此仓库提交 PR。
标签:DevSecOps, Falco, GitOps, Kustomize, 上游代理, 子域名突变, 敏感词过滤, 自定义请求头