gke-security
google/skills
通过 Workload Identity、Secret Manager、RBAC、二进制授权、网络策略和 Pod 安全标准来强化 Google Kubernetes Engine (GKE) 集群的安全性。
...展开全部GKE 安全
本文档介绍了 GKE 集群的安全配置。黄金路径 默认会强制实施强化安全策略。
MCP 工具:
get_cluster、check_k8s_auth、get_k8s_resource、apply_k8s_manifest、update_cluster
“黄金路径”的安全默认设置
| 设置 | 黄金路径值 | 第 0/1 天 | 备注 |
|---|---|---|---|
workloadIdentityConfig.workloadPool |
|
第 0 天 | Pod 的工作负载身份联合 |
secretManagerConfig.enabled |
true |
第1天 | Google Secret Manager 集成 |
secretManagerConfig.rotationConfig |
启用:true,轮换间隔:120s |
第1天 | 自动密钥轮换 |
rbacBindingConfig.enableInsecureBindingSystemAuthenticated |
false |
第0天 | 阻止旧版system:authenticated绑定 |
rbacBindingConfig.enableInsecureBindingSystemUnauthenticated |
false |
Day-0 | 阻止旧系统:未经身份验证的绑定 |
nodeConfig.shieldedInstanceConfig.enableSecureBoot |
true |
第0天 | 可验证的启动完整性 |
nodeConfig.shieldedInstanceConfig.enableIntegrityMonitoring |
true |
第0天 | 运行时完整性检查 |
nodeConfig.workloadMetadataConfig.mode |
GKE_METADATA |
第0天 | 阻止旧版元数据 API,强制实施工作负载身份验证 |
| 私有集群 + Dataplane V2 设置 | 参见gke-networking技能 |
Day-0 | 私有节点、私有端点强制执行、ADVANCED_DATAPATH |
工作负载身份联合
工作负载身份是 Pod 访问 Google Cloud API 的推荐方式。 它消除了对静态服务账户密钥的需求。
设置
# 1. 创建 Google 服务账户 (GSA)
gcloud iam service-accounts create \
--project \
--display-name "Workload Identity SA" \
--quiet
# 2. 向 GSA 授予 IAM 角色
gcloud projects add-iam-policy-binding \
--member "serviceAccount:@.iam.gserviceaccount.com" \
--role "" \
--quiet
# 3. 创建 Kubernetes 服务账户 (KSA)
kubectl create namespace
kubectl create serviceaccount --namespace
# 4. 将 KSA 绑定到 GSA
gcloud iam service-accounts add-iam-policy-binding \
@.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:.svc.id.goog[/]" \
--quiet
# 5. 为 KSA 添加注解
kubectl annotate serviceaccount \
--namespace \
iam.gke.io/gcp-service-account=@.iam.gserviceaccount.com
请参阅 assets/workload-identity-pod.yaml 中的测试 Pod。
验证
kubectl run workload-identity-test \
--image=gcr.io/google.com/cloudsdktool/cloud-sdk:slim \
--serviceaccount= --namespace= \
--rm -it -- gcloud auth list --quiet
Secret Manager 集成
黄金路径支持 Secret Manager 并启用了自动轮换。密钥会 同步到 Kubernetes 密钥中。
# 验证集群上是否已启用 Secret Manager
gcloud container clusters describe --region \
--format="value(secretManagerConfig.enabled)" \
--quiet
# 若尚未启用,请启用(Day-1 变更)
gcloud container clusters update --region \
--enable-secret-manager \
--secret-manager-rotation-interval=120s \
--quiet
通过 CSI 卷挂载密钥(部署示例)
启用 Secret Manager 附加组件后,工作负载即可使用 Secrets Store CSI 驱动程序将密钥作为 卷挂载。这需要执行两个步骤:
- 定义一个
SecretProviderClass,以指定要从 Secret Manager 中检索哪些密钥。 - 在引用该类的
Deployment中挂载卷。
[!重要]生产环境最佳实践:始终使用符合生产标准的
Deployment清单(而非原始Pod清单)来演示工作负载 集成(如 Secret Manager CSI)。
步骤 1:创建 SecretProviderClass
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: app-secrets-provider
namespace: default
spec:
provider: gke # 标识 GKE 托管提供程序
parameters:
secrets: |
- resourceName: "projects//secrets/db-password/versions/latest"
fileName: "db-password.txt"
步骤 2:在 Deployment 中挂载密钥
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
spec:
serviceAccountName: secure-ksa # 必须绑定到具有 Secret Manager Secret Accessor 角色的 GSA
containers:
- name: app
image:
volumeMounts:
- name: secrets-volume
mountPath: "/var/secrets"
readOnly: true
volumes:
- name: secrets-volume
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "app-secrets-provider"
RBAC 安全强化
黄金路径会禁用不安全的旧版 RBAC 绑定,这些绑定会向
system:authenticated和system:unauthenticated组授予广泛的访问权限。
# 验证是否已禁用不安全的绑定
gcloud container clusters describe --region \
--format="yaml(rbacBindingConfig)" \
--quiet
RBAC 的最佳实践:
- 优先使用命名空间范围的角色,而非集群范围的 ClusterRoles
- 绑定到特定的组或服务账户,切勿绑定到
system:authenticated - 通过 MCP 审核权限:
check_k8s_auth(parent="...", verb="list", resourceType="pods", namespace="...")(或kubectl auth can-i --list --as=) - 通过 MCP 审查绑定:
get_k8s_resource(parent="...", resourceType="clusterrolebinding")(或kubectl get clusterrolebindings,rolebindings --all-namespaces)
有关企业级 RBAC 规划,请参阅
gke-multitenancy技能, https://docs.cloud.google.com/kubernetes-engine/docs/best-practices/rbac.md.txt
二进制授权
默认情况下在黄金路径中未启用,但建议在生产环境中启用以追踪镜像 来源:
# 启用二进制授权
gcloud container clusters update --region \
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE \
--quiet
网络策略
Dataplane V2(黄金路径)提供了内置的网络策略强制执行功能。按命名空间应用 默认拒绝策略:
# MCP(推荐)
apply_k8s_manifest(parent="...", yamlManifest="")
# kubectl 备用方案
kubectl apply -f ./assets/default-deny-netpol.yaml -n
GKE 沙箱 (gVisor)
要在隔离的沙箱中运行不受信任的工作负载:
# 在集群上启用(标准集群)
gcloud container clusters update --region --enable-gke-sandbox --quiet
# 在 Pod 规范中使用
# 添加:runtimeClassName: gvisor
Pod 安全标准(黄金路径)
Pod 安全标准定义了三个配置文件,用于限制 Pod 的操作范围。
restricted配置文件是生产命名空间的“黄金路径”默认选项。
| 配置文件 | 级别 | 用例 |
|---|---|---|
特权 |
无限制 | 系统命名空间(kube-system), |
| : : : 基础设施控制器 : | ||
基线 |
限制最少 | 共享/dev 命名空间、传统应用 |
| : : : 正在迁移中的 : | ||
受限 |
黄金路径 | 生产工作负载——块 |
| : : : 权限提升、主机访问、 : | ||
| : : : root : |
通过命名空间标签强制执行(Pod 安全准入):
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restricted
渐进式部署策略:
- 首先对现有命名空间启用
警告+审计功能,以识别违规情况 - 修复不符合规定的工作负载(移除
特权、hostNetwork、root 用户等) - 待所有工作负载均通过验证后启用
强制执行
受限项包括:以 root 身份运行、权限提升、主机
网络/PID/IPC、主机路径卷,以及大多数能力。黄金路径
workload-identity-pod.yaml已符合规范。
网络策略日志记录(推荐)
在 Dataplane V2(黄金路径)中,您可以为网络策略 决策启用日志记录。这并非黄金路径的默认设置——但建议用于安全审计。
gcloud container clusters update --region \
--enable-network-policy-logging \
--quiet
这会记录允许和拒绝的连接,有助于排查网络 策略规则问题并审计流量。
常见的 IAM 角色
GKE 中最常见的五个预定义 IAM 角色:
| 角色 | 用途 | 何时使用 |
|---|---|---|
roles/container.admin |
对以下内容拥有完全控制权 | 平台团队管理员 |
| : : 集群以及 : 管理集群 : | ||
| : : Kubernetes : 生命周期 : | ||
| : : 资源 : : | ||
角色/container.clusterAdmin |
管理集群,但 | 集群操作员 |
| : : 非项目级别 : 负责创建/删除 : | ||
| : : IAM : 集群 : | ||
roles/container.developer |
部署工作负载 | 应用程序 |
| : : (Pod、服务、 : 开发人员将 : | ||
| : : 部署) : 到现有集群 : | ||
roles/container.viewer |
对 | 监控、 |
| : : 集群和 : 审计,或 : | ||
| : : Kubernetes : 只读仪表盘 : | ||
| : : 资源 : : | ||
roles/container.clusterViewer |
列出并获取 | CI/CD 管道,这些管道 |
| : : 集群详细信息 : 需要集群 : | ||
| : : 仅需 : 元数据 : |
最小权限原则:从
roles/container.viewer或roles/container.developer开始,仅在必要时提升权限。避免广泛授予roles/container.admin 权限。
服务账户与代理
- GKE 服务代理
(
service-): 自动创建。代表您管理节点、网络和集群操作。 请勿删除或修改其权限。@container-engine-robot.iam.gserviceaccount.com - 节点服务账户:默认情况下,节点使用 Compute Engine 的默认 服务账户。对于生产环境,请创建一个权限最小的专用服务账户, 并通过节点池配置将其分配给节点。
- 工作负载身份:Pod 访问 Google Cloud API 的推荐方式。将 Kubernetes 服务账户映射到 Google IAM 服务账户——请参阅 上文中的“工作负载身份”设置。
跨服务身份验证模式
授予 GKE 工作负载访问其他 Google Cloud 服务的常见模式:
# 授予 GKE 工作负载访问 Cloud Storage 的权限
gcloud projects add-iam-policy-binding \
--member "serviceAccount:@.iam.gserviceaccount.com" \
--role "roles/storage.objectViewer" \
--quiet
# 授予 GKE 工作负载访问 Cloud SQL 的权限
gcloud projects add-iam-policy-binding \
--member "serviceAccount:@.iam.gserviceaccount.com" \
--role "roles/cloudsql.client" \
--quiet
# 授予 GKE 工作负载访问 Pub/Sub 的权限
gcloud projects add-iam-policy-binding \
--member "serviceAccount:@.iam.gserviceaccount.com" \
--role "roles/pubsub.subscriber" \
--quiet
在所有情况下,GSA 都必须通过工作负载身份(参见上文的设置) 与 KSA 进行绑定。随后,Pod 将使用 KSA 以 GSA 的身份进行身份验证。
---
name: gke-security
description: Hardens Google Kubernetes Engine (GKE) clusters with Workload Identity, Secret Manager, RBAC, Binary Authorization, Network Policies, and Pod Security Standards.
---
# GKE Security
This reference covers security configuration for GKE clusters. The golden path
enforces a hardened security posture by default.
> **MCP Tools:** `get_cluster`, `check_k8s_auth`, `get_k8s_resource`,
> `apply_k8s_manifest`, `update_cluster`
## Golden Path Security Defaults
Setting | Golden Path Value | Day-0/1 | Notes
-------------------------------------------------------------- | --------------------------------------- | ------- | -----
`workloadIdentityConfig.workloadPool` | `<PROJECT>.svc.id.goog` | Day-0 | Workload Identity Federation for Pods
`secretManagerConfig.enabled` | `true` | Day-1 | Google Secret Manager integration
`secretManagerConfig.rotationConfig` | `enabled: true, rotationInterval: 120s` | Day-1 | Automatic secret rotation
`rbacBindingConfig.enableInsecureBindingSystemAuthenticated` | `false` | Day-0 | Blocks legacy `system:authenticated` bindings
`rbacBindingConfig.enableInsecureBindingSystemUnauthenticated` | `false` | Day-0 | Blocks legacy `system:unauthenticated` bindings
`nodeConfig.shieldedInstanceConfig.enableSecureBoot` | `true` | Day-0 | Verifiable boot integrity
`nodeConfig.shieldedInstanceConfig.enableIntegrityMonitoring` | `true` | Day-0 | Runtime integrity checks
`nodeConfig.workloadMetadataConfig.mode` | `GKE_METADATA` | Day-0 | Blocks legacy metadata API, enforces Workload Identity
Private cluster + Dataplane V2 settings | See the `gke-networking` skill | Day-0 | Private nodes, private endpoint enforcement, ADVANCED_DATAPATH
## Workload Identity Federation
Workload Identity is the recommended way for pods to access Google Cloud APIs.
It eliminates the need for static service account keys.
### Setup
```bash
# 1. Create a Google Service Account (GSA)
gcloud iam service-accounts create <GSA_NAME> \
--project <PROJECT_ID> \
--display-name "Workload Identity SA" \
--quiet
# 2. Grant IAM roles to the GSA
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member "serviceAccount:<GSA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role "<ROLE>" \
--quiet
# 3. Create Kubernetes Service Account (KSA)
kubectl create namespace <NAMESPACE>
kubectl create serviceaccount <KSA_NAME> --namespace <NAMESPACE>
# 4. Bind KSA to GSA
gcloud iam service-accounts add-iam-policy-binding \
<GSA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:<PROJECT_ID>.svc.id.goog[<NAMESPACE>/<KSA_NAME>]" \
--quiet
# 5. Annotate KSA
kubectl annotate serviceaccount <KSA_NAME> \
--namespace <NAMESPACE> \
iam.gke.io/gcp-service-account=<GSA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com
```
> See [assets/workload-identity-pod.yaml](./assets/workload-identity-pod.yaml)
> for a test pod.
### Verification
```bash
kubectl run workload-identity-test \
--image=gcr.io/google.com/cloudsdktool/cloud-sdk:slim \
--serviceaccount=<KSA_NAME> --namespace=<NAMESPACE> \
--rm -it -- gcloud auth list --quiet
```
## Secret Manager Integration
The golden path enables Secret Manager with automatic rotation. Secrets are
synced to Kubernetes Secrets.
```bash
# Verify Secret Manager is enabled on cluster
gcloud container clusters describe <CLUSTER_NAME> --region <REGION> \
--format="value(secretManagerConfig.enabled)" \
--quiet
# Enable if not already (Day-1 change)
gcloud container clusters update <CLUSTER_NAME> --region <REGION> \
--enable-secret-manager \
--secret-manager-rotation-interval=120s \
--quiet
```
### Mounting Secrets via CSI Volume (Deployment Example)
Once the Secret Manager add-on is enabled, workloads can mount secrets as
volumes using the Secrets Store CSI driver. This requires two steps:
1. **Define a `SecretProviderClass`** to specify which secrets to retrieve from
Secret Manager.
2. **Mount the volume in a `Deployment`** referencing that class.
> [!IMPORTANT] **Production Best Practice**: Always demonstrate workload
> integrations (like Secret Manager CSI) using production-standard
> **`Deployment`** manifests rather than raw `Pod` manifests.
#### Step 1: Create the SecretProviderClass
```yaml
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: app-secrets-provider
namespace: default
spec:
provider: gke # Identifies GKE managed provider
parameters:
secrets: |
- resourceName: "projects/<PROJECT_ID>/secrets/db-password/versions/latest"
fileName: "db-password.txt"
```
#### Step 2: Mount the secret in a Deployment
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
spec:
serviceAccountName: secure-ksa # Must be bound to GSA with Secret Manager Secret Accessor role
containers:
- name: app
image: <IMAGE>
volumeMounts:
- name: secrets-volume
mountPath: "/var/secrets"
readOnly: true
volumes:
- name: secrets-volume
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "app-secrets-provider"
```
## RBAC Hardening
The golden path disables insecure legacy RBAC bindings that grant broad access
to `system:authenticated` and `system:unauthenticated` groups.
```bash
# Verify insecure bindings are disabled
gcloud container clusters describe <CLUSTER_NAME> --region <REGION> \
--format="yaml(rbacBindingConfig)" \
--quiet
```
**Best practices for RBAC:**
- Use namespace-scoped Roles over cluster-wide ClusterRoles
- Bind to specific Groups or ServiceAccounts, never to `system:authenticated`
- Audit permissions via MCP: `check_k8s_auth(parent="...", verb="list",
resourceType="pods", namespace="...")` (or `kubectl auth can-i --list
--as=<user>`)
- Review bindings via MCP: `get_k8s_resource(parent="...",
resourceType="clusterrolebinding")` (or `kubectl get
clusterrolebindings,rolebindings --all-namespaces`)
> See the `gke-multitenancy` skill for enterprise RBAC planning and
> https://docs.cloud.google.com/kubernetes-engine/docs/best-practices/rbac.md.txt
## Binary Authorization
Not enabled in golden path by default but recommended for production image
provenance:
```bash
# Enable Binary Authorization
gcloud container clusters update <CLUSTER_NAME> --region <REGION> \
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE \
--quiet
```
## Network Policies
Dataplane V2 (golden path) provides built-in Network Policy enforcement. Apply
default-deny per namespace:
```
# MCP (preferred)
apply_k8s_manifest(parent="...", yamlManifest="<contents of default-deny-netpol.yaml>")
# kubectl fallback
kubectl apply -f ./assets/default-deny-netpol.yaml -n <NAMESPACE>
```
## GKE Sandbox (gVisor)
For running untrusted workloads in an isolated sandbox:
```bash
# Enable on cluster (Standard clusters)
gcloud container clusters update <CLUSTER_NAME> --region <REGION> --enable-gke-sandbox --quiet
# Use in pod spec
# Add: runtimeClassName: gvisor
```
## Pod Security Standards (Golden Path)
Pod Security Standards define three profiles that restrict what pods can do. The
**`restricted` profile is the golden path default** for production namespaces.
| Profile | Level | Use Case |
| ------------ | --------------------- | ---------------------------------- |
| `privileged` | Unrestricted | System namespaces (`kube-system`), |
: : : infrastructure controllers :
| `baseline` | Minimally restrictive | Shared/dev namespaces, legacy apps |
: : : being migrated :
| `restricted` | **Golden path** | Production workloads -- blocks |
: : : privilege escalation, host access, :
: : : root :
**Enforce via namespace labels (Pod Security Admission):**
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restricted
```
**Gradual rollout strategy:**
1. Start with `warn` + `audit` on existing namespaces to identify violations
2. Fix non-compliant workloads (remove `privileged`, `hostNetwork`, root user,
etc.)
3. Enable `enforce` once all workloads pass
`restricted` blocks: running as root, privilege escalation, host
networking/PID/IPC, host path volumes, and most capabilities. The golden path
`workload-identity-pod.yaml` already complies.
## Network Policy Logging (Recommended)
With Dataplane V2 (golden path), you can enable logging for Network Policy
decisions. **Not a golden path default** -- recommended for security auditing.
```bash
gcloud container clusters update <CLUSTER_NAME> --region <REGION> \
--enable-network-policy-logging \
--quiet
```
This logs allowed and denied connections, useful for troubleshooting Network
Policy rules and auditing traffic flows.
## Common IAM Roles
The five most common predefined IAM roles for GKE:
| Role | Purpose | When to Use |
| ------------------------------- | ------------------- | -------------------- |
| `roles/container.admin` | Full control over | Platform team admins |
: : clusters and : managing cluster :
: : Kubernetes : lifecycle :
: : resources : :
| `roles/container.clusterAdmin` | Manage clusters but | Cluster operators |
: : not project-level : who create/delete :
: : IAM : clusters :
| `roles/container.developer` | Deploy workloads | Application |
: : (pods, services, : developers deploying :
: : deployments) : to existing clusters :
| `roles/container.viewer` | Read-only access to | Monitoring, |
: : clusters and : auditing, or :
: : Kubernetes : read-only dashboards :
: : resources : :
| `roles/container.clusterViewer` | List and get | CI/CD pipelines that |
: : cluster details : need cluster :
: : only : metadata :
> **Principle of least privilege**: Start with `roles/container.viewer` or
> `roles/container.developer` and escalate only as needed. Avoid granting
> `roles/container.admin` broadly.
## Service Accounts & Agents
- **GKE Service Agent**
(`service-<PROJECT_NUMBER>@container-engine-robot.iam.gserviceaccount.com`):
Automatically created. Manages nodes, networking, and cluster operations on
your behalf. Do not remove or modify its permissions.
- **Node Service Account**: By default, nodes use the Compute Engine default
service account. For production, create a dedicated SA with minimal
permissions and assign it via node pool config.
- **Workload Identity**: The recommended way for pods to access Google Cloud
APIs. Maps a Kubernetes ServiceAccount to a Google IAM ServiceAccount — see
[Workload Identity setup](#workload-identity-federation) above.
## Cross-Service Authentication Patterns
Common patterns for granting GKE workloads access to other Google Cloud
services:
```bash
# Grant a GKE workload access to Cloud Storage
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member "serviceAccount:<GSA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role "roles/storage.objectViewer" \
--quiet
# Grant a GKE workload access to Cloud SQL
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member "serviceAccount:<GSA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role "roles/cloudsql.client" \
--quiet
# Grant a GKE workload access to Pub/Sub
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member "serviceAccount:<GSA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role "roles/pubsub.subscriber" \
--quiet
```
In all cases, the GSA must be bound to a KSA via Workload Identity (see setup
above). The pod then uses the KSA to authenticate as the GSA.





首页
