1. 简介
在此 Codelab 中,您将构建一个基本演示应用,该应用展示了如何集成各种 Google Cloud 服务,以用于位于具有合规性限制的项目中的服务。此项目使用以下安全功能:
- 数据边界,有助于解决受监管环境的控制问题
- 客户管理的加密密钥 ( CMEK),用于保护静态数据;
- GKE 安全强化型节点和 GKE 机密节点,有助于在处理过程中保护数据;
- 适用于 GKE 的 Workload Identity,用于管理对 Vertex AI 的访问权限,该平台利用 Gemini 执行图像处理任务。
- Vertex AI 上的生成式 AI,用于管理视频流中的安全帽检测
本 Codelab 适合各种水平的开发者,包括新手。您将使用 Google Cloud Shell 中的命令行界面和 Python 代码。您无需成为 Python 专家,但对如何读取代码有基本的了解有助于您理解这些概念。
注意:这是一个简化的概念验证,而不是生产应用。在实际应用场景中,采取额外的预防措施,例如对该服务进行经过身份验证的安全外部访问。
2. 准备工作
项目设置
../shared/_project-setup.md
启动 Cloud Shell
Cloud Shell 是在 Google Cloud 中运行的命令行环境,预加载了必要的工具。
- 点击 Google Cloud 控制台顶部的激活 Cloud Shell:

- 连接到 Cloud Shell 后,运行以下命令以验证您在 Cloud Shell 中的身份验证:
gcloud auth list
- 运行以下命令,确认您的项目已配置为可与 gcloud 搭配使用:
gcloud config get project
- 确认项目符合预期,然后运行以下命令以设置项目 ID:
export PROJECT_ID=$(gcloud config get project)
必需的 IAM 权限
您用于此 Codelab 的账号必须具有以下 IAM 角色。这些权限对于创建所需的 Google Cloud 资源(项目、文件夹、GKE 集群、KMS 密钥、服务账号等)和配置保证型工作负载是必需的。
在组织级层:
- roles/assuredworkloads.admin (Assured Workloads Administrator):用于创建和管理 Assured Workloads 资源本身,确保合规性配置。
在结算账号级别(在您的结算账号中):
- roles/billing.accountUser (Billing Account User):用于关联指定的结算账号。
配置 Codelab 变量
如需创建所需的基础设施,您需要提供以下环境变量:
# The ID of the Billing Account in the format (XXXXXX-XXXXXX-XXXXXX).
# This value will be used to attach in the projects created using Assured Workloads
export BILLING_ACCOUNT=
# The ID of a Google Cloud Platform organization
# Run `gcloud organizations list` to check all your available organizations
export GCP_ORGANIZATION=
# The numeric ID of a folder where the Assured Workloads will create the resources.
export FOLDER_ID=
# Region where the application will be deployed.
# Since you are using Assured Workloads, you MUST use one of the valid locations as described here: <https://docs.cloud.google.com/assured-workloads/docs/locations>
export REGION="us-central1"
# The ID of an existing Google Cloud project to be used for API quota and billing purposes.
# This project will only be used to enable the Assured Workloads API and create an Assured Workload.
export QUOTA_PROJECT_ID=
# Random suffix used to avoid naming collisions when creating the GCP projects.
export RANDOM_SUFFIX=$(cat /dev/urandom | tr -dc 'a-z0-9' | head -c 5 ; echo)
# The ID of the projects that will be created using Assured Workloads.
# You can modify this value if you want a custom id.
export PROJECT_ID="il5-gemini-vision-aw-${RANDOM_SUFFIX}"
export KMS_PROJECT_ID="il5-gemini-vision-kms-${RANDOM_SUFFIX}"
3. 创建 Assured Workloads 基础
现在,您可以在受监管的环境中为应用奠定基础。使用 Assured Workloads 为资源创建受控环境,以帮助强制执行合规性要求。
配置配额项目
在配额项目中启用 Assured Workloads API。此 API 是创建和管理 Assured Workloads 所必需的。
gcloud services enable assuredworkloads.googleapis.com \
--project="${QUOTA_PROJECT_ID}"
创建 Assured Workloads 环境
以下命令会为您的演示创建一个安全的“着陆区”。它会在您指定的文件夹和结算账号下创建两个新的 Google Cloud 项目。
- 一个项目托管您的 GKE 集群和应用。
- 另一个项目管理您的客户管理的加密密钥 (CMEK)。
从项目创建之日起,该功能会自动将指定的 IL5 合规性控制措施应用于这两个项目。
运行以下命令以创建工作负载环境。
export ASSURED_WORKLOAD_ID=$(gcloud assured workloads create \
--project="${QUOTA_PROJECT_ID}" \
--display-name="DoD IL5 Gemini Vision Demo" \
--compliance-regime="IL5" \
--billing-account="billingAccounts/${BILLING_ACCOUNT}" \
--location="${REGION}" \
--organization="${GCP_ORGANIZATION}" \
--provisioned-resources-parent="folders/${FOLDER_ID}" \
--resource-settings="consumer-project-id=${PROJECT_ID},consumer-project-name=DoD IL5 Workloads,encryption-keys-project-id=${KMS_PROJECT_ID},encryption-keys-project-name=DoD IL5 KMS" \
--labels="codelab=gemini-vision-demo" \
--format="value(name)")
echo "Assured Workload created: ${ASSURED_WORKLOAD_ID}"
export WORKLOAD_FOLDER_ID=$(gcloud assured workloads describe ${ASSURED_WORKLOAD_ID} \
--location="${REGION}" \
--project="${QUOTA_PROJECT_ID}" \
--format="json" | grep -B 1 "CONSUMER_FOLDER" | grep -oE "[0-9]{10,}")
echo "Assured Workload folder created: ${WORKLOAD_FOLDER_ID}"
gcloud projects create "${PROJECT_ID}" \
--folder="${WORKLOAD_FOLDER_ID}" \
--name="DoD IL5 Workloads"
gcloud billing projects link "${PROJECT_ID}" \
--billing-account="${BILLING_ACCOUNT}"
export PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format="value(projectNumber)")
启用必需的 Google Cloud API
在构建之前,请为所需服务启用必需的 API。
以下命令会在您的主要工作负载项目中激活此 Codelab 所需的所有服务。
gcloud services enable \
aiplatform.googleapis.com \
artifactregistry.googleapis.com \
cloudkms.googleapis.com \
compute.googleapis.com \
container.googleapis.com \
iam.googleapis.com \
logging.googleapis.com \
monitoring.googleapis.com \
--project="${PROJECT_ID}"
4. GKE 基础架构设置
构建支持 GKE 集群的核心基础架构。这包括为集群设置专用网络,以及配置您自己的加密密钥来保护节点上的数据。
配置 VPC 网络
创建自定义的虚拟私有云 (VPC) 和子网。这种方法让您可以完全控制 IP 地址范围,并确保集群按预期隔离。
运行以下命令,以在指定区域内创建 VPC 网络和子网。
export GKE_NETWORK_NAME="il5-gke-network"
export GKE_SUBNETWORK_NAME="il5-gke-subnet"
gcloud compute networks create "${GKE_NETWORK_NAME}" \
--description="VPC network for GKE cluster in DoD IL5 Assured Workload" \
--subnet-mode="custom" \
--project="${PROJECT_ID}"
gcloud compute networks subnets create "${GKE_SUBNETWORK_NAME}" \
--network="${GKE_NETWORK_NAME}" \
--range="10.10.0.0/20" \
--region="${REGION}" \
--description="Subnet for GKE cluster nodes in DoD IL5 Assured Workload" \
--project="${PROJECT_ID}"
使用 Cloud KMS 配置加密
如需满足对静态数据的严格合规性要求,请使用客户管理的加密密钥 (CMEK)。这样,您就可以直接控制用于加密 GKE 节点启动磁盘的密钥。
export KMS_KEYRING_NAME="il5_gke_key_ring"
export KMS_KEY_NAME="il5_gke_key"
gcloud kms keyrings create "${KMS_KEYRING_NAME}" \
--location="$REGION" \
--project="${KMS_PROJECT_ID}"
gcloud kms keys create "${KMS_KEY_NAME}" \
--keyring="${KMS_KEYRING_NAME}" \
--location="${REGION}" \
--purpose="encryption" \
--project="${KMS_PROJECT_ID}"
由于加密密钥位于需要使用它的服务所在的 KMS 项目之外,因此工作负载项目中的 Google Compute Engine 服务代理需要获得对该密钥的访问权限。
您必须明确授予工作负载项目的 GCE 服务代理使用此密钥的权限。以下命令会向密钥添加 IAM 政策绑定,从而向服务代理授予必要的角色。
gcloud kms keys add-iam-policy-binding "${KMS_KEY_NAME}" \
--location="${REGION}" \
--keyring="${KMS_KEYRING_NAME}" \
--member="serviceAccount:service-${PROJECT_NUMBER}@compute-system.iam.gserviceaccount.com" \
--role="roles/cloudkms.cryptoKeyEncrypterDecrypter" \
--project="${KMS_PROJECT_ID}"
配置 GKE 节点服务账号
export GKE_NODE_SA=gke-node-sa
gcloud iam service-accounts create "${GKE_NODE_SA}" \
--display-name="GKE Node Service Account" \
--project="${PROJECT_ID}"
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member="serviceAccount:${GKE_NODE_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/logging.logWriter"
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member="serviceAccount:${GKE_NODE_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/monitoring.metricWriter"
5. GKE 集群创建和配置
现在,您可以创建 GKE 集群。以下命令用于预配启用了多项安全功能的 GKE 集群。
由于 Google Cloud 会预配节点和控制平面,因此此过程需要几分钟才能完成。
export GKE_CLUSTER=ppe-app
gcloud beta container clusters create "${GKE_CLUSTER}" \
--project="$PROJECT_ID" \
--region="$REGION" \
--service-account="${GKE_NODE_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
--release-channel="regular" \
--machine-type="n2d-standard-4" \
--image-type="COS_CONTAINERD" \
--disk-type="pd-ssd" \
--disk-size="50" \
--boot-disk-kms-key="projects/${KMS_PROJECT_ID}/locations/${REGION}/keyRings/${KMS_KEYRING_NAME}/cryptoKeys/${KMS_KEY_NAME}" \
--metadata disable-legacy-endpoints=true \
--num-nodes="1" \
--network="projects/${PROJECT_ID}/global/networks/${GKE_NETWORK_NAME}" \
--subnetwork="projects/${PROJECT_ID}/regions/${REGION}/subnetworks/${GKE_SUBNETWORK_NAME}" \
--security-posture="standard" \
--workload-vulnerability-scanning="disabled" \
--workload-pool="${PROJECT_ID}.svc.id.goog" \
--workload-metadata=GKE_METADATA \
--addons="HorizontalPodAutoscaling,HttpLoadBalancing,NodeLocalDNS,GcePersistentDiskCsiDriver" \
--max-surge-upgrade=1 \
--max-unavailable-upgrade=0 \
--binauthz-evaluation-mode="DISABLED" \
--no-enable-basic-auth \
--enable-autoupgrade \
--enable-autorepair \
--enable-confidential-nodes \
--confidential-node-type=sev \
--enable-ip-access \
--enable-ip-alias \
--enable-managed-prometheus \
--enable-dns-access \
--enable-shielded-nodes \
--shielded-integrity-monitoring \
--shielded-secure-boot
连接到新集群
如需与新集群互动,请配置本地 kubectl 命令行工具。
此命令会获取集群的凭据和端点,并自动配置本地 kubeconfig 文件。运行此命令后,您运行的任何 kubectl 命令都将针对新的 GKE 集群。
gcloud container clusters get-credentials "${GKE_CLUSTER}" \
--region="${REGION}" \
--project="${PROJECT_ID}" \
--dns-endpoint
6. 应用身份配置
如需将 Kubernetes 服务账号连接到 Google Cloud IAM 服务账号,请配置 Workload Identity。
创建服务账号
在集群内创建专用 Kubernetes 服务账号 (KSA)。
export GKE_NAMESPACE=default
export GKE_SA=ppe-sa
kubectl create sa "${GKE_SA}" --namespace="${GKE_NAMESPACE}"
接下来,您的应用需要在 Google Cloud 中拥有身份。为应用创建 Google Cloud IAM 服务账号。创建服务账号后,向其授予必要的角色。
# Create GCP service account
gcloud iam service-accounts create "${GKE_SA}" \
--project="${PROJECT_ID}"
# Grant necessary roles
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member="serviceAccount:${GKE_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"
允许 Kubernetes 服务账号模拟 IAM 服务账号
创建这两个服务账号后,最后一步是创建它们之间的关联。此流程分为两个部分。首先,向您的 Google Cloud 服务账号添加 IAM 政策。
# Allow the Kubernetes service account to act as GCP service account by using Workload Identity
gcloud iam service-accounts add-iam-policy-binding "${GKE_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
--project="${PROJECT_ID}" \
--role="roles/iam.workloadIdentityUser" \
--member="serviceAccount:${PROJECT_ID}.svc.id.goog[${GKE_NAMESPACE}/${GKE_SA}]"
其次,为 Kubernetes 服务账号添加注释。
kubectl annotate --namespace="${GKE_NAMESPACE}" serviceaccount "$GKE_SA" \
iam.gke.io/gcp-service-account="${GKE_SA}@${PROJECT_ID}.iam.gserviceaccount.com"
完成此操作后,集群中以 Kubernetes 服务账号运行的任何 pod 现在都可以访问 Vertex API。
注意:可以消除服务账号模拟,以简化此配置。如需了解详情和限制,请点击此处。
7. 应用构建和部署
现在,您可以打包应用、存储应用并将其部署到 GKE 集群了。
创建 Artifact Registry 代码库
您必须先将应用封装为 Docker 容器并将其存储在 Artifact Registry 代码库中,然后才能运行该应用。使用以下命令创建此代码库。
export REPOSITORY_ID=ppe-repo
gcloud artifacts repositories create "${REPOSITORY_ID}" \
--repository-format=docker \
--location="${REGION}" \
--project="${PROJECT_ID}" \
--description="Regional Docker repo for PPE App"
您必须明确授予 GKE 节点使用的服务账号从新代码库读取数据的权限。
gcloud artifacts repositories add-iam-policy-binding "${REPOSITORY_ID}" \
--location="${REGION}" \
--role="roles/artifactregistry.reader" \
--project="${PROJECT_ID}" \
--member="serviceAccount:${GKE_NODE_SA}@${PROJECT_ID}.iam.gserviceaccount.com"
构建和推送 Docker 映像
构建 Docker 映像并将其推送到代码库。首先,克隆源代码并构建容器映像。然后,使用完整的 Artifact Registry 路径为其添加标记,并将其推送到您之前创建的代码库。
git clone https://github.com/GoogleCloudPlatform/next-26-sessions.git
cd BRK3-034-workplace-safety
cd ppe
export IMAGE_TAG="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY_ID}/ppe-app:v15"
docker build -t "${IMAGE_TAG}" .
docker push "${IMAGE_TAG}"
部署到 GKE
现在,Artifact Registry 中已提供容器映像,最后一步是指示 GKE 拉取并运行该映像。为此,您需要在 Kubernetes 清单文件中定义应用资源,然后将其应用于集群。此命令会创建文件中定义的 Deployment 和 Service 对象。
export GKE_DEPLOY=ppe-detector
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${GKE_DEPLOY}
spec:
replicas: 2
selector:
matchLabels:
app: ${GKE_DEPLOY}
template:
metadata:
labels:
app: ${GKE_DEPLOY}
spec:
serviceAccountName: ${GKE_SA}
containers:
- name: ${GKE_DEPLOY}
image: ${IMAGE_TAG}
env:
- name: PROJECT_ID
value: ${PROJECT_ID}
- name: LOCATION
value: ${REGION}
ports:
- containerPort: 8080
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "500m"
memory: "1Gi"
---
apiVersion: v1
kind: Service
metadata:
name: ${GKE_DEPLOY}
spec:
type: LoadBalancer
selector:
app: ${GKE_DEPLOY}
ports:
- protocol: TCP
port: 80
targetPort: 8080
EOF
8. 测试应用
最后一步是访问并测试演示版应用。这包括检索分配给服务的外部 IP 地址,并通过简单的前端与之互动。
检索服务的外部 IP
获取公开服务的外部 IP 地址(预配需要约 30 秒)
export IP_ADDRESS=$(kubectl get service "${GKE_DEPLOY}" -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo $IP_ADDRESS
在本地运行前端
在此演示中,前端是一个简单的 HTML/JavaScript 页面,不属于 GKE 部署。它旨在在本地机器上运行。
在生产应用中,前端应从 GCP 提供。在本地机器上:
# Update the index.html file with the server IP address
cd frontend
# For Linux
sed -i "s#\(const BACKEND_URL = \"http://\)[^/]\+\(\/analyze\";\)#\1${IP_ADDRESS}\2#g" "index.html"
# For MacOS
#sed -i '' "s#\(const BACKEND_URL = #\"http://\)[^/]*\(\/analyze\";\)#\1${IP_ADDRESS}\2#g" "index.html"
python3 -m http.server 8001
在 Chrome 中打开 http://localhost:8001/index.html。
9. 清理
为避免持续产生费用,请删除在本 Codelab 中创建的资源。
销毁 GKE 集群
如需删除整个应用,只需删除 GKE 集群即可。为此,请运行以下命令:
gcloud container clusters delete "${GKE_CLUSTER}" \
--region="$REGION" \
--project="${PROJECT_ID}"
删除 Assured Workloads
运行以下命令可删除所有与 Assured Workloads 相关的资源。
# Workload project deletion
gcloud billing projects unlink "${PROJECT_ID}"
gcloud projects delete "${PROJECT_ID}"
# KMS project deletion
gcloud billing projects unlink "${KMS_PROJECT_ID}"
gcloud projects delete "${KMS_PROJECT_ID}"
# Assured Workload folder deletion
gcloud resource-manager folders delete ${WORKLOAD_FOLDER_ID} --quiet
# Assured Workload deletion
gcloud assured workloads delete "${ASSURED_WORKLOAD_ID}" \
--location="${REGION}" \
--organization="${GCP_ORGANIZATION}" \
--project="${QUOTA_PROJECT_ID}"
10. 恭喜
任务完成!您已成功构建了一个工作场所安全检测系统,该系统适用于受监管的行业,可使用 Gemini 检测安全帽。
您的学习成果:
- 数据保护和隐私权:您已预配使用 CMEK 的机密 GKE 节点
- 数据边界:您为受监管的环境启用了平台合规性控制措施