s3nafps/GCP-Kube-Vanguard

GitHub: s3nafps/GCP-Kube-Vanguard

一套用于在 GCP 上快速部署安全、私有 GKE 集群的企业级 Terraform 架构,内置了零信任身份管理与自动化 GitOps 流水线。

Stars: 0 | Forks: 0

# GCP-Kube-Vanguard 在 Google Cloud Platform 上私有部署 GKE 用于私有 Google Kubernetes Engine 集群的模块化 Terraform,具备最小权限 IAM、Workload Identity 以及通过 GitHub Actions 实现的 CI/CD。 ## 架构 ``` graph TB subgraph Internet GAR["Artifact Registry
(Docker Images)"] GHA["GitHub Actions
(CI/CD)"] end subgraph GCP["Google Cloud Platform"] subgraph VPC["Custom VPC (vanguard-vpc)"] subgraph Subnet["Private Subnet (10.0.0.0/20)"] subgraph GKE["Private GKE Cluster"] CP["Control Plane
(172.16.0.0/28)"] NP["Node Pool
(No Public IPs)"] KSA["KSA: workload-ksa"] end end NAT["Cloud NAT"] Router["Cloud Router"] end GSA_Node["Node SA
(least-privilege)"] GSA_Workload["Workload GSA"] WIF["Workload Identity
Federation"] end subgraph Access["Authorized Access"] IAP["IAP Bastion /
Authorized CIDR"] end NP -->|"egress via"| NAT NAT -->|"routes through"| Router Router -->|"pulls images"| GAR IAP -->|"authorized network"| CP KSA -.->|"Workload Identity"| GSA_Workload NP -->|"runs as"| GSA_Node GHA -->|"OIDC token exchange"| WIF WIF -->|"impersonates"| GSA_Workload GHA -->|"pushes images"| GAR ``` ## 安全深度解析 ### 为什么使用私有集群? **私有 GKE 集群** 强制实施了网络层面的隔离,消除了最常见的 Kubernetes 攻击向量: | 安全属性 | 实施方式 | |---|---| | **无公共节点 IP** | `enable_private_nodes = true` — 节点仅接收 RFC 1918 地址。攻击者无法直接从互联网访问节点,即使某个 pod 被攻破。 | | **控制平面访问控制** | `master_authorized_networks_config` 将 API server 的访问限制在特定的 CIDR 块(例如 IAP bastion `35.235.240.0/20`)。未经授权的网络会收到 `connection refused`。 | | **仅限出口的互联网** | Cloud NAT 提供用于拉取容器镜像的出站连接,而不会暴露入站攻击面。 | | **VPC 对等互连隔离** | 控制平面运行在由 Google 管理的 VPC 中,并通过 `master_ipv4_cidr_block` 与您的 VPC 建立对等互连。不存在传递性对等互连 —— 从架构上防止了横向移动。 | | **Shielded Nodes** | `enable_shielded_nodes` 通过 vTPM 和 Secure Boot 验证节点启动完整性,防止针对底层 VM 的 rootkit 级攻击。 | | **Dataplane V2** | 基于 Cilium 的 eBPF 网络提供内核级别的网络策略强制执行 —— 没有 iptables 瓶颈,并具备内置的可观测性。 | ### 为什么使用 Workload Identity? 传统方法将 JSON 密钥文件挂载到 pod 中 —— 这是一个 **严重的反模式**,因为: 1. 密钥是长期有效的,且不会自动轮换 2. 单个被攻破的 pod 会将密钥暴露给所有工作负载 3. 存储在 Secrets 中的密钥可能会因 RBAC 配置错误而被窃取 **Workload Identity** 消除了所有这三个风险: ``` Pod (KSA: workload-ksa) │ ├── requests token from GKE metadata server │ ├── GKE metadata server mints a short-lived OIDC token │ scoped to: PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME] │ ├── Token is exchanged for a GCP access token via STS │ └── Pod operates as GSA: workload-gsa@PROJECT.iam.gserviceaccount.com (with ONLY the IAM roles bound to that GSA) ``` **核心优势:** - **无密钥泄漏风险** — 凭证是自动轮换的短期 token - **Pod 级别身份** — 每个 KSA 仅映射到一个 GSA;爆炸半径被严格限制 - **可审计性** — 所有 API 调用都会以 GSA 身份显示在 Cloud Audit Logs 中 ### 最小权限节点 Service Account 默认的 Compute Engine SA (`PROJECT_NUMBER-compute@developer.gserviceaccount.com`) 拥有 **Editor** 访问权限 —— 这太宽泛了。此代码库创建了一个专用的节点 SA,仅包含以下权限: | 角色 | 用途 | |---|---| | `roles/logging.logWriter` | 将容器日志发送到 Cloud Logging | | `roles/monitoring.metricWriter` | 将指标写入 Cloud Monitoring | | `roles/monitoring.viewer` | 读取监控仪表板 | | `roles/artifactregistry.reader` | 从 Artifact Registry 拉取镜像 | | `roles/stackdriver.resourceMetadata.writer` | 写入资源元数据 | ## 仓库结构 ``` GCP-Kube-Vanguard/ ├── main.tf # Root module — wires all child modules ├── variables.tf # Root input variables ├── outputs.tf # Root outputs ├── providers.tf # Provider & version constraints ├── backend.tf # GCS remote state backend ├── terraform.tfvars.example # Example variable values ├── .gitignore │ ├── modules/ │ ├── networking/ # VPC, Subnet, Cloud Router, Cloud NAT │ │ ├── main.tf │ │ ├── variables.tf │ │ └── outputs.tf │ │ │ ├── cluster/ # Private GKE Cluster, Node Pool, Node SA │ │ ├── main.tf │ │ ├── variables.tf │ │ └── outputs.tf │ │ │ ├── iam/ # Workload Identity KSA ↔ GSA binding │ │ ├── main.tf │ │ ├── variables.tf │ │ └── outputs.tf │ │ │ └── registry/ # Google Artifact Registry │ ├── main.tf │ ├── variables.tf │ └── outputs.tf │ ├── .github/ │ └── workflows/ │ └── ci.yaml # GitHub Actions: build, push, validate │ └── README.md ``` ## 前置条件 | 要求 | 版本 | |---|---| | [Terraform](https://www.terraform.io/) | >= 1.5 | | [Google Cloud SDK](https://cloud.google.com/sdk) | 最新版 | | 启用计费功能的 GCP 项目 | — | ### 所需的 GCP API ``` gcloud services enable \ container.googleapis.com \ compute.googleapis.com \ artifactregistry.googleapis.com \ iam.googleapis.com \ iamcredentials.googleapis.com \ cloudresourcemanager.googleapis.com \ sts.googleapis.com ``` ## 部署 ### 1. 初始化远程状态 ``` # 为 Terraform state 创建 GCS bucket export PROJECT_ID="your-project-id" export REGION="europe-west1" gsutil mb -p $PROJECT_ID -l $REGION -b on gs://${PROJECT_ID}-tfstate gsutil versioning set on gs://${PROJECT_ID}-tfstate ``` 更新 [`backend.tf`](./backend.tf) 中的 bucket 名称。 ### 2. 配置变量 ``` cp terraform.tfvars.example terraform.tfvars # 使用您的项目特定值编辑 terraform.tfvars ``` ### 3. 部署 ``` terraform init terraform plan -out=tfplan terraform apply tfplan ``` ### 4. 连接到集群 ``` gcloud container clusters get-credentials \ $(terraform output -raw cluster_name) \ --zone $(terraform output -raw zone) \ --project $PROJECT_ID # 验证 Workload Identity kubectl get serviceaccount workload-ksa -o yaml ``` ## CI/CD 流水线 (GitHub Actions) 该流水线使用 **Workload Identity Federation** —— 一种无密钥身份验证机制,可将 GitHub OIDC token 换取为短期的 GCP 凭证。 ### 设置 Workload Identity Federation ``` # 1. 创建 Workload Identity Pool gcloud iam workload-identity-pools create "github-pool" \ --project=$PROJECT_ID \ --location="global" \ --display-name="GitHub Actions Pool" # 2. 创建 OIDC Provider gcloud iam workload-identity-pools providers create-oidc "github-provider" \ --project=$PROJECT_ID \ --location="global" \ --workload-identity-pool="github-pool" \ --display-name="GitHub Provider" \ --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository" \ --issuer-uri="https://token.actions.githubusercontent.com" # 3. 将 SA 绑定到 GitHub repository gcloud iam service-accounts add-iam-policy-binding \ "ci-sa@${PROJECT_ID}.iam.gserviceaccount.com" \ --project=$PROJECT_ID \ --role="roles/iam.workloadIdentityUser" \ --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool/attribute.repository/YOUR_ORG/GCP-Kube-Vanguard" ``` ### 必需的 GitHub Secrets | Secret | 描述 | |---|---| | `GCP_PROJECT_ID` | 您的 GCP 项目 ID | | `WIF_PROVIDER` | WIF OIDC provider 的完整资源名称 | | `WIF_SERVICE_ACCOUNT` | CI/CD 服务账号的电子邮件 | | `GAR_REGION` | Artifact Registry 区域 (例如 `europe-west1`) | | `GAR_REPOSITORY` | Artifact Registry 仓库 ID | ## 输出参考 | 输出 | 描述 | 敏感 | |---|---|---| | `cluster_name` | GKE 集群名称 | 否 | | `cluster_endpoint` | 控制平面 endpoint | ✅ | | `cluster_ca_certificate` | 集群 CA 证书 | ✅ | | `node_service_account_email` | 节点 SA 电子邮件 | 否 | | `workload_gsa_email` | 工作负载 GSA 电子邮件 | 否 | | `workload_ksa_name` | Kubernetes SA 名称 | 否 | | `gar_repository_url` | GAR Docker 仓库 URL | 否 | ## 成本考量 主要的成本驱动因素包括: - **GKE 集群管理费** (Standard 层级约 $0.10/小时) - **Compute Engine 节点** (根据机器类型而异) - **Cloud NAT** (按 VM 收费 + 数据处理费用) ## 许可证 本项目采用 MIT 许可证授权。
标签:ECS, GCP, GitOps, Terraform, 云原生架构, 私有GKE, 请求拦截