1. ภาพรวม
ห้องทดลองนี้จะแนะนำให้คุณรู้จักกับ ClusterNetworkPolicy ใน Google Kubernetes Engine (GKE) ClusterNetworkPolicy ใช้กับกรณีการใช้งานต่างๆ และสามารถใช้ได้ทั่วทั้งคลัสเตอร์และบังคับใช้ที่ระดับผู้ดูแลระบบและระดับพื้นฐาน ในตัวอย่างนี้ เราจะสาธิตการควบคุมด้วยการติดตั้งใช้งาน LLM (Gemma) ใน GKE ด้วย TPU, vLLM และการตรวจสอบความถูกต้อง
คุณจะได้ทำงานกับเทคโนโลยีต่อไปนี้
- Google Kubernetes Engine (GKE) - แพลตฟอร์มการจัดการคอนเทนเนอร์เป็นกลุ่มพื้นฐานสำหรับการโฮสต์เวิร์กโหลดส่วนตัวที่ปรับขนาดได้
- ClusterNetworkPolicy (CNP) — นโยบายเครือข่ายแบบหลายระดับที่กำหนดขอบเขตระดับคลัสเตอร์ ซึ่งช่วยให้ SecOps สามารถกำหนดขอบเขตการทำงานในระดับผู้ดูแลระบบ, NetworkPolicy และระดับพื้นฐาน
- vLLM TPU Inference Engine — การอนุมานที่มีอัตราการประมวลผลสูงซึ่งแสดงโมเดล Gemma 4 (google/gemma-4-E2B-it) ที่มีน้ำหนักเบาใน Google TPU พร้อมปลายทาง REST ที่เข้ากันได้กับ OpenAI
บทบาทและตัวตน
Network Policy API มีโครงสร้างตามบุคคลในองค์กรที่เฉพาะเจาะจง ดังนี้
- การใช้งานของผู้ดูแลระบบคลัสเตอร์ (
ClusterNetworkPolicy): บังคับใช้มาตรการป้องกันความปลอดภัยในคลัสเตอร์ที่ระดับผู้ดูแลระบบและระดับพื้นฐาน - การใช้งานของผู้ดูแลระบบเนมสเปซ (
NetworkPolicy): จัดการขอบเขตและการแยกในระดับกลุ่มผู้ใช้ภายในเนมสเปซที่เฉพาะเจาะจง - การใช้งานของนักพัฒนาแอปพลิเคชัน (
NetworkPolicy): กำหนดกฎแบบละเอียดสำหรับ Microservice เฉพาะแอปพลิเคชัน
หากต้องการกำหนดค่าสภาพแวดล้อมนี้ คุณจะต้องติดตั้งใช้งาน VPC ส่วนตัวที่กำหนดเอง, Cloud NAT และคลัสเตอร์ GKE ส่วนตัวที่มี Node Pool ของ TPU โดยเฉพาะ
ในการรักษาความปลอดภัยของคลัสเตอร์ คุณจะต้องเขียนทรัพยากร ClusterNetworkPolicy แบบหลายระดับควบคู่ไปกับออบเจ็กต์ NetworkPolicy มาตรฐานเพื่อบังคับใช้ Guardrail ของเครือข่ายที่เข้มงวด จากนั้นคุณจะติดตั้งใช้งานภาระงาน AI ที่ใช้ vLLM และ Cloud TPU ของ Google Cloud เพื่อแสดงโมเดล Gemma 4
สุดท้าย คุณจะสร้างเกณฑ์พื้นฐานในการทำงาน ใช้นโยบายความปลอดภัย และกำหนดค่า NetworkLogging โดยใช้ Cloud Logging และสตรีม Hubble eBPF observability แบบเรียลไทม์เพื่อตรวจสอบคำตัดสินเกี่ยวกับนโยบายเหล่านั้นและยืนยันการทิ้งแพ็กเก็ต การกำหนดค่าทั้งหมดจะใช้ Terraform, gcloud และ kubectl. ร่วมกัน
ในห้องทดลองนี้ คุณจะได้เรียนรู้วิธีทำงานต่อไปนี้
- จัดสรรเครือข่ายส่วนตัว, คลัสเตอร์ GKE และตัวเร่ง Cloud TPU v5e โดยใช้ Terraform
- กำหนดค่า GKE NetworkLogging เพื่อบันทึกการตรวจวัดระยะไกลของการเชื่อมต่อ
- ติดตั้งใช้งาน Gemma 4 E2B บน TPU โดยใช้อิมเมจคอนเทนเนอร์ vllm/vllm-tpu อย่างเป็นทางการ
- สร้างเกณฑ์พื้นฐานที่ใช้งานได้ซึ่งพิสูจน์การเชื่อมต่อจากต้นทางถึงปลายทางก่อนที่จะใช้ข้อจำกัด
- ใช้
Baseline-tierClusterNetworkPolicy เพื่อปฏิเสธการเข้าชมข้ามเนมสเปซที่ไม่ได้รับอนุญาตโดยค่าเริ่มต้น - ใช้ NetworkPolicy ที่นักพัฒนาแอปจัดการเพื่อมอบสิทธิ์เข้าถึงให้แก่ไคลเอ็นต์ที่ได้รับอนุญาต
- ใช้
Admin-tierClusterNetworkPolicy เพื่อบังคับใช้ Guardrail ขาออกส่วนกลางที่ลบล้างการตั้งค่าของนักพัฒนาซอฟต์แวร์ - ตรวจสอบการทิ้งและส่งแพ็กเก็ตแบบเรียลไทม์โดยใช้ (สตรีม Hubble eBPF และ Cloud Logging)
ในห้องทดลองนี้ คุณจะได้สร้างรูปแบบต่อไปนี้
รูปที่ 1 
2. การตั้งค่าบริการ Google Cloud
การตั้งค่าสภาพแวดล้อมแบบเรียนรู้ด้วยตนเอง
- ลงชื่อเข้าใช้คอนโซล Google Cloud แล้วสร้างโปรเจ็กต์ใหม่หรือใช้โปรเจ็กต์ที่มีอยู่ซ้ำ หากยังไม่มีบัญชี Gmail หรือ Google Workspace คุณต้องสร้างบัญชี



- ชื่อโปรเจ็กต์คือชื่อที่แสดงสำหรับผู้เข้าร่วมของโปรเจ็กต์นี้ ซึ่งเป็นสตริงอักขระที่ Google APIs ไม่ได้ใช้ คุณอัปเดตข้อมูลได้ทุกเมื่อ
- รหัสโปรเจ็กต์จะไม่ซ้ำกันในโปรเจ็กต์ Google Cloud ทั้งหมดและเปลี่ยนแปลงไม่ได้ (ไม่สามารถเปลี่ยนแปลงได้หลังจากตั้งค่าแล้ว) คอนโซล Cloud จะสร้างสตริงที่ไม่ซ้ำกันโดยอัตโนมัติ ซึ่งโดยปกติแล้วคุณจะไม่สนใจว่าสตริงนั้นคืออะไร ใน Codelab ส่วนใหญ่ คุณจะต้องอ้างอิงรหัสโปรเจ็กต์ (โดยปกติจะระบุเป็น
PROJECT_ID) หากไม่ชอบรหัสที่สร้างขึ้น คุณอาจสร้างรหัสแบบสุ่มอีกรหัสหนึ่งได้ หรือคุณจะลองใช้ชื่อของคุณเองและดูว่าพร้อมใช้งานหรือไม่ก็ได้ คุณจะเปลี่ยนรหัสนี้ไม่ได้หลังจากขั้นตอนนี้ และรหัสจะยังคงอยู่ตลอดระยะเวลาของโปรเจ็กต์ - โปรดทราบว่ายังมีค่าที่ 3 คือหมายเลขโปรเจ็กต์ ซึ่ง API บางรายการใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับค่าทั้ง 3 ค่านี้ได้ในเอกสารประกอบ
- ถัดไป คุณจะต้องเปิดใช้การเรียกเก็บเงินใน Cloud Console เพื่อใช้ทรัพยากร/API ของ Cloud การใช้งาน Codelab นี้จะมีค่าใช้จ่ายไม่มากนัก (หากมี) หากต้องการปิดทรัพยากรเพื่อหลีกเลี่ยงการเรียกเก็บเงินนอกเหนือจากบทแนะนำนี้ คุณสามารถลบทรัพยากรที่สร้างขึ้นหรือลบโปรเจ็กต์ได้ ผู้ใช้ Google Cloud รายใหม่มีสิทธิ์เข้าร่วมโปรแกรมทดลองใช้ฟรีมูลค่า$300 USD
เริ่ม Cloud Shell
แม้ว่า Google Cloud จะทำงานจากระยะไกลได้จากแล็ปท็อป แต่ใน Codelab นี้ คุณจะใช้ Google Cloud Shell ซึ่งเป็นสภาพแวดล้อมบรรทัดคำสั่งที่ทำงานในระบบคลาวด์
จากคอนโซล Google Cloud ให้คลิกไอคอน Cloud Shell บนแถบเครื่องมือด้านขวาบน

การจัดสรรและเชื่อมต่อกับสภาพแวดล้อมจะใช้เวลาเพียงไม่นาน เมื่อดำเนินการเสร็จแล้ว คุณควรจะเห็นข้อความลักษณะนี้

เครื่องเสมือนนี้โหลดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ทั้งหมดที่คุณต้องการไว้แล้ว โดยมีไดเรกทอรีหลักขนาด 5 GB ที่คงอยู่ถาวร และทำงานบน Google Cloud ซึ่งช่วยเพิ่มประสิทธิภาพเครือข่ายและการตรวจสอบสิทธิ์ได้อย่างมาก งานทั้งหมดของคุณใน Codelab นี้สามารถทำได้ภายในเบราว์เซอร์ คุณไม่จำเป็นต้องติดตั้งอะไรเลย
3. ตั้งค่าสภาพแวดล้อมด้วย Terraform
หากต้องการทำห้องทดลองนี้ให้เสร็จสมบูรณ์
- คุณต้องมีสิทธิ์เข้าถึงโควต้า TPU v5e ในภูมิภาคและโซนที่เลือก เช่น (
us-central1-a, us-west4-a, us-south1-a, us-west1-c, europe-west4-b) คุณควรทำตามเอกสารแพ็กเกจ TPU และเปิดใช้โควต้า TPU เพื่อรับสิทธิ์เข้าถึง - นี่เป็นการติดตั้งใช้งานขนาดเล็กที่ต้องใช้ชิป TPU v5e จำนวน 4 ตัว (
ct5lp-hightpu-4t),ซึ่งจะสร้างส่วน 2x2 ในโซนเดียว
วิธีใช้ Hugging Face
- โทเค็น Hugging Face: ต้องใช้โทเค็นเพื่อการเข้าถึงเพื่อดาวน์โหลดน้ำหนักโมเดล Gemma
- ยอมรับข้อตกลงการใช้งานตามที่กำหนด
เราจะสร้าง VPC ที่กำหนดเองพร้อมกฎไฟร์วอลล์ ซับเน็ต และคลัสเตอร์ Autopilot เปิด Cloud Console แล้วเลือกโปรเจ็กต์ที่คุณจะใช้
- เปิด Cloud Shell ที่ด้านบนของคอนโซลทางด้านขวา ตรวจสอบว่าคุณเห็นรหัสโปรเจ็กต์ที่ถูกต้องใน Cloud Shell และยืนยันข้อความแจ้งเพื่ออนุญาตการเข้าถึง

- สร้างไดเรกทอรีชื่อ
gke-cnp-lab,แล้วย้ายไปยังไดเรกทอรีนั้น
mkdir -p gke-cnp-lab && cd gke-cnp-lab
- ตอนนี้ให้สร้างตัวแปรบางรายการ ป.ล. แก้ไข REGION, ZONE เพื่อแสดงตำแหน่งจริงที่คุณมีสิทธิ์เข้าถึงทรัพยากร TPU ค่าเริ่มต้นที่ใช้ในภูมิภาค
us-west4และโซนus-west4-aของห้องทดลอง
export PROJECT_ID=$(gcloud config get-value project)
export REGION="us-west4"
export ZONE="us-west4-a"
export NETWORK="cnp-demo-vpc"
export SUBNET="cnp-main-subnet"
export CLUSTER_NAME="cnp-demo-cluster"
- บันทึกตัวแปรการกำหนดค่าลงในสคริปต์ตัวช่วยในไดเรกทอรี gke-cnp-lab หากเซสชัน Cloud Shell ยกเลิกการเชื่อมต่อหรือรีเซ็ต คุณสามารถกู้คืนตัวแปรที่ใช้งานอยู่ได้อย่างรวดเร็วโดยเรียกใช้
source ./env.sh
cat << EOF > env.sh
export PROJECT_ID="${PROJECT_ID}"
export REGION="${REGION}"
export ZONE="${ZONE}"
export NETWORK="${NETWORK}"
export SUBNET="${SUBNET}"
export CLUSTER_NAME="${CLUSTER_NAME}"
echo -e "\n=== Validating Environment Configuration ==="
echo "Project ID : \${PROJECT_ID}"
echo "Region : \${REGION}"
echo "Zone : \${ZONE}"
echo "Network Name : \${NETWORK}"
echo "Subnet Name : \${SUBNET}"
echo "Cluster Name : \${CLUSTER_NAME}"
if [[ -z "\${PROJECT_ID}" || -z "\${REGION}" || -z "\${ZONE}" || -z "\${NETWORK}" || -z "\${SUBNET}" || -z "\${CLUSTER_NAME}" ]]; then
echo -e "\n[ERROR] One or more environment variables are missing! Check your configuration."
else
echo -e "\n[SUCCESS] Environment variables successfully populated and validated."
fi
EOF
chmod +x env.sh
source ./env.sh
- ตอนนี้ให้เพิ่มไฟล์การกำหนดค่าบางไฟล์ ซึ่งจะสร้างไฟล์ terraform.tfvars , variables.tf, main.tf ต่อไปนี้ในไดเรกทอรี gke-cnp-lab
cat << EOF > terraform.tfvars
project_id = "${PROJECT_ID}"
region = "${REGION}"
zone = "${ZONE}"
network_name = "${NETWORK}"
subnet_name = "${SUBNET}"
cluster_name = "${CLUSTER_NAME}"
EOF
cat << 'EOF' > variables.tf
variable "project_id" {
type = string
description = "Google Cloud Project ID"
}
variable "region" {
type = string
description = "Target GCP region"
}
variable "zone" {
type = string
description = "Target GCP zone"
}
variable "network_name" {
type = string
description = "VPC network name"
}
variable "subnet_name" {
type = string
description = "Subnetwork name"
}
variable "cluster_name" {
type = string
description = "GKE cluster name"
}
EOF
cat << 'EOF' > main.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 7.32.0"
}
google-beta = {
source = "hashicorp/google-beta"
version = "~> 7.32.0"
}
}
}
provider "google" {
project = var.project_id
region = var.region
}
provider "google-beta" {
project = var.project_id
region = var.region
}
# 1. Custom Private VPC Network
resource "google_compute_network" "vpc" {
name = var.network_name
auto_create_subnetworks = false
mtu = 8896
}
# 2. Private Subnet with Secondary IP Ranges for Pods & Services
resource "google_compute_subnetwork" "subnet" {
name = var.subnet_name
ip_cidr_range = "10.10.0.0/20"
region = var.region
network = google_compute_network.vpc.id
private_ip_google_access = true
secondary_ip_range {
range_name = "gke-pods"
ip_cidr_range = "10.20.0.0/16"
}
secondary_ip_range {
range_name = "gke-services"
ip_cidr_range = "10.30.0.0/20"
}
}
# 3. Cloud Router & Cloud NAT for Secure Outbound Egress
resource "google_compute_router" "router" {
name = "${var.network_name}-router"
network = google_compute_network.vpc.id
region = var.region
}
resource "google_compute_router_nat" "nat" {
name = "${var.network_name}-nat"
router = google_compute_router.router.name
region = var.region
nat_ip_allocate_option = "AUTO_ONLY"
source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"
}
# 4. Internal Firewall Rules
resource "google_compute_firewall" "allow_internal" {
name = "${var.network_name}-allow-internal"
network = google_compute_network.vpc.id
direction = "INGRESS"
priority = 1000
allow {
protocol = "all"
}
source_ranges = ["10.10.0.0/20", "10.20.0.0/16", "10.30.0.0/20"]
}
# 5. Private GKE Cluster with Observability and Dataplane V2
resource "google_container_cluster" "primary" {
name = var.cluster_name
location = var.region
node_locations = [var.zone]
network = google_compute_network.vpc.id
subnetwork = google_compute_subnetwork.subnet.id
initial_node_count = 1
datapath_provider = "ADVANCED_DATAPATH"
# FIX: Observability config must be nested inside monitoring_config
monitoring_config {
advanced_datapath_observability_config {
enable_metrics = true
enable_relay = true
}
}
release_channel {
channel = "RAPID"
}
ip_allocation_policy {
cluster_secondary_range_name = "gke-pods"
services_secondary_range_name = "gke-services"
}
private_cluster_config {
enable_private_nodes = true
enable_private_endpoint = false
master_ipv4_cidr_block = "172.16.0.0/28"
}
node_config {
machine_type = "e2-standard-4"
oauth_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
}
deletion_protection = false
}
# 6. Dedicated Cloud TPU v5e Node Pool (ct5lp-hightpu-4t / 2x2 Topology)
resource "google_container_node_pool" "tpu_pool" {
provider = google-beta
name = "tpu-v5e-pool"
location = var.region
node_locations = [var.zone]
cluster = google_container_cluster.primary.name
node_count = 1
node_config {
machine_type = "ct5lp-hightpu-4t"
oauth_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
labels = {
"cloud.google.com/gke-tpu-accelerator" = "tpu-v5-lite-podslice"
"cloud.google.com/gke-tpu-topology" = "2x2"
}
taint {
key = "google.com/tpu"
value = "present"
effect = "NO_SCHEDULE"
}
}
}
EOF
- ตรวจสอบว่าคุณอยู่ในไดเรกทอรี gke-cnp-lab แล้วเรียกใช้คำสั่งต่อไปนี้
terraform initเริ่มต้นไดเรกทอรีที่ใช้งานอยู่ นี่คือขั้นตอนแรกและจะดาวน์โหลดผู้ให้บริการที่จำเป็นสำหรับการกำหนดค่าที่ระบุterraform plan -outสร้างแผนการดำเนินการ โดยแสดงการดำเนินการที่ Terraform จะทำเพื่อทำให้โครงสร้างพื้นฐานใช้งานได้-outช่วยให้คุณบันทึกแผนการดำเนินการเป็นไบนารีที่มีชื่อได้ คุณสามารถดูสิ่งที่จะเกิดขึ้นได้โดยไม่ต้องทำการเปลี่ยนแปลงใดๆterraform applyจะเรียกใช้การอัปเดต
terraform init
terraform plan -out cnpgke
- ใช้แผนการดำเนินการ เนื่องจากคุณกำลังใช้แผนการดำเนินการที่บันทึกไว้ ระบบจะดำเนินการทันทีโดยไม่แจ้งให้ยืนยัน (ซึ่งอาจใช้เวลา 6-10 นาที)
terraform apply cnpgke
- ยืนยันการติดตั้งใช้งานโครงสร้างพื้นฐานโดยทำดังนี้
gcloud container clusters get-credentials ${CLUSTER_NAME} --region ${REGION} --project=${PROJECT_ID}
echo -e "\n=== Verifying Cluster Nodes ==="
kubectl get nodes -L cloud.google.com/gke-tpu-accelerator,cloud.google.com/gke-tpu-topology

4. กำหนดค่าการบันทึกเครือข่าย
ก่อนที่จะติดตั้งใช้งานภาระงานและนโยบาย ให้กำหนดค่าการบันทึกเครือข่าย GKE เพื่อบันทึกการตรวจวัดระยะไกลของการเชื่อมต่อและตรวจสอบคำตัดสินเกี่ยวกับนโยบายใน Cloud Logging
- ในไดเรกทอรี
gke-cnp-labให้สร้างไฟล์ Manifest การกำหนดค่า NetworkLogging
cat << 'EOF' > 00-network-logging.yaml
apiVersion: networking.gke.io/v1alpha1
kind: NetworkLogging
metadata:
name: default
spec:
cluster:
allow:
delegate: false
log: true
deny:
delegate: false
log: true
EOF
- ใช้การกำหนดค่ากับคลัสเตอร์
kubectl apply -f 00-network-logging.yaml
kubectl get networklogging default
หมายเหตุ: คุณอาจเห็นคำเตือนที่ระบุว่าทรัพยากรไม่มี kubectl.kubernetes.io/last-applied-configuration annotation. ซึ่งเป็นเรื่องปกติและคาดการณ์ได้ GKE จะสร้างออบเจ็กต์ NetworkLogging เริ่มต้นไว้ล่วงหน้าเมื่อคลัสเตอร์เริ่มทำงาน และ kubectl apply จะเข้าควบคุมการจัดการออบเจ็กต์ดังกล่าวเพื่อใช้กฎใหม่ของคุณ
5. ติดตั้งใช้งานภาระงานและโพรบไคลเอ็นต์ของ Gemma 4
คุณจะสร้างเนมสเปซที่แยกต่างหากเพื่อทดสอบการประเมินนโยบายหลายระดับ ดังนี้
gemma-llm: รองรับภาระงานการอนุมานหลักของ Gemma 4 (tier: ai-core)client-ns: มีโปรแกรมแชท RAG ที่ได้รับอนุญาต (tier: app-frontend)untrusted-tenant: มีคอนเทนเนอร์โพรบที่ไม่ได้รับอนุญาต (tier: untrusted)
- ใน
gke-cnp-lab directory,ให้สร้างไฟล์ Manifest01-namespaces-clients.yamlที่มีเนมสเปซและพ็อดไคลเอ็นต์ทดสอบ ดังนี้
cat << 'EOF' > 01-namespaces-clients.yaml
apiVersion: v1
kind: Namespace
metadata:
name: gemma-llm
labels:
tier: ai-core
---
apiVersion: v1
kind: Namespace
metadata:
name: client-ns
labels:
tier: app-frontend
---
apiVersion: v1
kind: Namespace
metadata:
name: untrusted-tenant
labels:
tier: untrusted
---
# Authorized Client Pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: rag-agent-client
namespace: client-ns
labels:
app: rag-agent
spec:
replicas: 1
selector:
matchLabels:
app: rag-agent
template:
metadata:
labels:
app: rag-agent
spec:
containers:
- name: client
image: curlimages/curl:latest
command: ["/bin/sh", "-c", "sleep 86400"]
---
# Rogue / Untrusted Probe Pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: rogue-client
namespace: untrusted-tenant
labels:
app: rogue-app
spec:
replicas: 1
selector:
matchLabels:
app: rogue-app
template:
metadata:
labels:
app: rogue-app
spec:
containers:
- name: probe
image: curlimages/curl:latest
command: ["/bin/sh", "-c", "sleep 86400"]
EOF
- ใช้เนมสเปซและการติดตั้งใช้งานไคลเอ็นต์โดยทำดังนี้
kubectl apply -f 01-namespaces-clients.yaml
kubectl get namespaces gemma-llm client-ns untrusted-tenant --show-labels
ติดตั้งใช้งานภาระงาน vLLM และ Gemma
สร้างข้อมูลลับ Hugging Face แทนที่ YOUR_ACTUAL_HUGGING_FACE_TOKEN ด้วยโทเค็นของคุณ
export HF_TOKEN="YOUR_ACTUAL_HUGGING_FACE_TOKEN"
echo $HF_TOKEN
kubectl create secret generic hf-secret -n gemma-llm --from-literal=hf_token=${HF_TOKEN}
- สร้างไฟล์ Manifest ของภาระงานการอนุมาน Gemma 4 ที่กำหนดเป้าหมายเป็น Cloud TPU v5e โดยใช้ vllm-tpu ดังนี้
cat << 'EOF' > 02-gemma4-tpu-vllm.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gemma-serving
namespace: gemma-llm
labels:
app: gemma-service
spec:
replicas: 1
selector:
matchLabels:
app: gemma-service
template:
metadata:
labels:
app: gemma-service
ai.gke.io/model: gemma4
ai.gke.io/inference-server: vllm-tpu
spec:
tolerations:
- key: "google.com/tpu"
operator: "Exists"
effect: "NoSchedule"
nodeSelector:
cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
cloud.google.com/gke-tpu-topology: 2x2
containers:
- name: vllm-inference
image: vllm/vllm-tpu:latest
command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
args:
- "--model=google/gemma-4-E2B-it"
- "--tensor-parallel-size=4"
- "--host=0.0.0.0"
- "--port=8000"
- "--max-model-len=4096"
- "--max-num-batched-tokens=4096"
env:
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-secret
key: hf_token
- name: HUGGING_FACE_HUB_TOKEN
valueFrom:
secretKeyRef:
name: hf-secret
key: hf_token
volumeMounts:
- mountPath: /dev/shm
name: dshm
ports:
- name: http-inference
containerPort: 8000
resources:
requests:
google.com/tpu: "4"
memory: "32Gi"
cpu: "8"
limits:
google.com/tpu: "4"
memory: "32Gi"
cpu: "8"
startupProbe:
httpGet:
path: /health
port: 8000
failureThreshold: 120
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8000
periodSeconds: 5
volumes:
- name: dshm
emptyDir:
medium: Memory
---
apiVersion: v1
kind: Service
metadata:
name: gemma-service
namespace: gemma-llm
spec:
type: ClusterIP
selector:
app: gemma-service
ports:
- name: http
protocol: TCP
port: 8000
targetPort: 8000
EOF
- สร้างการทำให้ใช้งานได้
kubectl apply -f 02-gemma4-tpu-vllm.yaml
- หากต้องการตรวจสอบสถานะการดำเนินการเสร็จสมบูรณ์ ให้เรียกใช้สคริปต์ต่อไปนี้ด้านล่าง พ็อดจะรอจนกว่าจะมีการจัดสรรโหนดก่อนจึงจะดำเนินการต่อได้ ซึ่งอาจใช้เวลา 13 นาทีขึ้นไป
echo " __|__"
echo " --@--(_|_)--@--"
echo ""
echo "Waiting for Gemma 4 TPU Pod to initialize and become Ready..."
# 1. Wait for the pod to be scheduled and reach the Running state
kubectl wait -n gemma-llm --for=condition=Ready pod -l app=gemma-service --timeout=600s
echo ""
echo "✅ Pod is Running! Streaming vLLM engine initialization logs..."
# 2. Stream logs until Uvicorn/vLLM is ready to serve
kubectl logs -n gemma-llm -l app=gemma-service -c vllm-inference -f | sed -u '/Application startup complete/q'
echo ""
echo "🚀 Gemma 4 on TPU v5e is ready for inference!"
6. ทำความเข้าใจการประเมินนโยบายและสถานะเริ่มต้น
ก่อนใช้นโยบายเครือข่าย โปรดทำความเข้าใจวิธีที่ ClusterNetworkPolicy ของ GKE และ NetworkPolicy ของ Kubernetes มาตรฐานโต้ตอบกันในระดับการประเมินต่างๆ
ระบบจะประเมินการรับส่งข้อมูลใน GKE ผ่านโมเดลลำดับความสำคัญแบบหลายระดับ ดังนี้
Admin Tier ⟶ NetworkPolicy Tier ⟶ Baseline Tier ⟶ Default GKE Behavior

ขั้นตอนการทดสอบของเรา
===================================================
4-STAGE POLICY EVALUATION FLOW
===================================================
[Stage 1: Default State]
├── Pre-Policy State: Default Kubernetes allow-all
├── Ingress: client-ns ──▶ Gemma 4: ALLOWED (200 OK)
├── Ingress: untrusted ──▶ Gemma 4: ALLOWED (200 OK)
├── Egress: All Pods ──▶ Metadata: ALLOWED (Exposed)
└── Security Posture: ⚠️ Overly permissive
│
▼
[Stage 2: Baseline Lockdown]
├── Policy: ClusterNetworkPolicy (tier: Baseline)
├── Rule: Default-deny all cross-namespace ingress
├── Ingress: client-ns ──▶ Gemma 4: DROPPED (Timeout)
├── Ingress: untrusted ──▶ Gemma 4: DROPPED (Timeout)
└── Security Posture: 🛑 Zero-trust baseline active
│
▼
[Stage 3: Developer Delegation]
├── Policy: NetworkPolicy (tier: NetworkPolicy)
├── Rule: App team allows ingress from client-ns
├── Ingress: client-ns ──▶ Gemma 4: ALLOWED (200 OK)
├── Ingress: untrusted ──▶ Gemma 4: DROPPED (Timeout)
└── Security Posture: 🔀 App isolation achieved
│
▼
[Stage 4: Admin Guardrail]
├── Policy: ClusterNetworkPolicy (tier: Admin)
├── Rule: Cluster-wide metadata drop (169.254.169.254)
├── Egress: All Pods ──▶ Metadata: DROPPED (Timeout)
├── Dev NetPol bypass attempt: OVERRIDDEN (Blocked)
└── Security Posture: 🔒 Enforced guardrail
===================================================
สร้างรากฐานพื้นฐาน (การทดสอบก่อนนโยบาย)
ตรวจสอบว่าโมเดล Gemma 4 ทำงานได้ดีและแสดงคำขอการอนุมาน ใน Kubernetes มาตรฐานที่ไม่มีนโยบาย การรับส่งข้อมูลข้ามเนมสเปซทั้งหมดจะได้รับอนุญาตโดยนัย
- ทดสอบการอนุมานจากไคลเอ็นต์ที่ได้รับอนุญาตใน
client-ns:
kubectl exec -n client-ns deploy/rag-agent-client -- curl --connect-timeout 3 -s -X POST \
http://gemma-service.gemma-llm.svc.cluster.local:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-E2B-it",
"messages": [{"role": "user", "content": "Explain zero trust in one short sentence."}],
"max_tokens": 40
}' | jq -r '.choices[0].message.content'
- ทดสอบการอนุมานจากไคลเอ็นต์อันตรายที่ไม่ได้รับอนุญาตใน
untrusted-tenant:
kubectl exec -n untrusted-tenant deploy/rogue-client -- curl --connect-timeout 3 -s -X POST \
http://gemma-service.gemma-llm.svc.cluster.local:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-E2B-it",
"messages": [{"role": "user", "content": "Explain zero trust in one short sentence."}],
"max_tokens": 40
}' | jq -r '.choices[0].message.content'
- ทดสอบว่าพ็อดในเนมสเปซทั้ง 3 รายการเข้าถึงเซิร์ฟเวอร์ข้อมูลเมตา (169.254.169.254) ได้หรือไม่ โดยทำดังนี้
echo -e "\n[1/3] Testing Metadata access from Gemma serving pod (gemma-llm)..."
kubectl exec -n gemma-llm deploy/gemma-serving -- curl --connect-timeout 3 -s -w "\nHTTP Code: %{http_code}\n" -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/zone || echo "🛑 RESULT: Connection Timed Out (Blocked)"
echo -e "\n[2/3] Testing Metadata access from authorized client (client-ns)..."
kubectl exec -n client-ns deploy/rag-agent-client -- curl --connect-timeout 3 -s -w "\nHTTP Code: %{http_code}\n" -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/zone || echo "🛑 RESULT: Connection Timed Out (Blocked)"
echo -e "\n[3/3] Testing Metadata access from rogue client (untrusted-tenant)..."
kubectl exec -n untrusted-tenant deploy/rogue-client -- curl --connect-timeout 3 -s -w "\nHTTP Code: %{http_code}\n" -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/zone || echo "🛑 RESULT: Connection Timed Out (Blocked)"
7. การทดสอบการประเมิน Baseline และระดับนโยบายเครือข่าย
ในขั้นตอนนี้ ในฐานะผู้ดูแลระบบคลัสเตอร์ คุณจะใช้ระดับพื้นฐานClusterNetworkPolicy เพื่อสร้างสถานะการปฏิเสธเริ่มต้นสำรองทั่วทั้งคลัสเตอร์ ระบบจะยกเลิกการสื่อสารข้ามเนมสเปซที่ไม่ได้รับอนุญาตอย่างชัดแจ้งจากระดับที่สูงกว่า
สร้างมาตรการ Zero Trust (ระดับพื้นฐาน)
- สร้างไฟล์ Manifest ของนโยบาย
03-baseline-deny.yamlระดับพื้นฐาน:
cat << 'EOF' > 03-baseline-deny.yaml
apiVersion: policy.networking.k8s.io/v1alpha2
kind: ClusterNetworkPolicy
metadata:
name: baseline-default-deny
spec:
tier: Baseline
priority: 1000
subject:
namespaces: {}
ingress:
# 1. Allow CoreDNS Ingress cluster-wide so DNS resolution never breaks
- name: allow-dns-ingress
action: Accept
from:
- namespaces: {}
protocols:
- udp:
destinationPort:
number: 53
- tcp:
destinationPort:
number: 53
# 2. Default Deny all other cross-namespace ingress
- name: baseline-deny-cross-ns
action: Deny
from:
- namespaces: {}
EOF
- ใช้นโยบายระดับพื้นฐาน
kubectl apply -f 03-baseline-deny.yaml
- ทดสอบการเชื่อมต่อไคลเอ็นต์จาก
client-ns.
kubectl exec -n client-ns deploy/rag-agent-client -- curl --connect-timeout 3 -s -X POST \
http://gemma-service.gemma-llm.svc.cluster.local:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-E2B-it",
"messages": [{"role": "user", "content": "Explain zero trust in one short sentence."}],
"max_tokens": 40
}' | jq -r '.choices[0].message.content'
- ทดสอบการอนุมานจากไคลเอ็นต์อันตรายที่ไม่ได้รับอนุญาตในกลุ่มผู้ใช้ที่ไม่น่าเชื่อถือ
kubectl exec -n untrusted-tenant deploy/rogue-client -- curl --connect-timeout 3 -s -X POST \
http://gemma-service.gemma-llm.svc.cluster.local:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-E2B-it",
"messages": [{"role": "user", "content": "Explain zero trust in one short sentence."}],
"max_tokens": 40
}' | jq -r '.choices[0].message.content'
มอบสิทธิ์เข้าถึงแก่นักพัฒนาซอฟต์แวร์ (ระดับ NetworkPolicy)
ตอนนี้ทีมแอปพลิเคชัน gemma-llm จะใช้ NetworkPolicy ที่กำหนดขอบเขตเนมสเปซมาตรฐานเพื่ออนุญาตการเข้าชมที่ได้รับสิทธิ์จาก client-ns
- สร้างไฟล์ Manifest NetworkPolicy ของนักพัฒนาแอป
04-app-networkpolicy.yamlดังนี้
cat << 'EOF' > 04-app-networkpolicy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-rag-client
namespace: gemma-llm
spec:
podSelector:
matchLabels:
app: gemma-service
policyTypes:
- Ingress
ingress:
# Explicitly permit ingress only from pods matching app: rag-agent in client-ns
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: client-ns
podSelector:
matchLabels:
app: rag-agent
ports:
- protocol: TCP
port: 8000
EOF
- ใช้นโยบาย
kubectl apply -f 04-app-networkpolicy.yaml
- ทดสอบการเชื่อมต่อไคลเอ็นต์จาก
client-ns
kubectl exec -n client-ns deploy/rag-agent-client -- curl --connect-timeout 3 -s -X POST \
http://gemma-service.gemma-llm.svc.cluster.local:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-E2B-it",
"messages": [{"role": "user", "content": "Explain zero trust in one short sentence."}],
"max_tokens": 40
}' | jq -r '.choices[0].message.content'
- ทดสอบการเชื่อมต่อจากไคลเอ็นต์ที่ไม่ได้รับอนุญาตใน
untrusted-tenantโดยทำดังนี้
kubectl exec -n untrusted-tenant deploy/rogue-client -- curl --connect-timeout 3 -s -X POST \
http://gemma-service.gemma-llm.svc.cluster.local:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-E2B-it",
"messages": [{"role": "user", "content": "Explain zero trust in one short sentence."}],
"max_tokens": 40
}' | jq -r '.choices[0].message.content'
8. การประเมินบังคับใช้แนวทางป้องกันทั่วโลก (ระดับผู้ดูแลระบบ)
ในฐานะผู้ดูแลระบบคลัสเตอร์ ตอนนี้คุณจะบังคับใช้ClusterNetworkPolicyระดับผู้ดูแลระบบที่ด้านบนสุดของลำดับการประเมินของ GKE ระบบจะประเมินระดับนี้ก่อน โดยกฎที่ตรงกันจะมีความสำคัญเหนือกว่าระดับอื่นๆ ทั้งหมดทันที หากไม่มีการจับคู่ ระบบจะส่งแพ็กเก็ตลงไปเพื่อประเมินโดยระดับที่ต่ำกว่า (NetworkPolicy และ Baseline)
ในขั้นตอนนี้ คุณจะใช้นโยบายที่ทำสิ่งต่อไปนี้
- Cluster-wide Egress Guardrail: บล็อกพ็อดทั้งหมดในทุกเนมสเปซไม่ให้เข้าถึงเซิร์ฟเวอร์ข้อมูลเมตาของ Google Cloud (
169.254.169.254/32) - การรองรับ DNS: อนุญาตการรับส่งข้อมูล DNS ทั้งหมดในพอร์ต 53 เพื่อให้พ็อดสามารถแปลงชื่อโฮสต์ได้ (พิจารณาแคช DNS ในเครื่องของ GKE)
- การมอบสิทธิ์ขาเข้าและขาออก: ส่งต่อการตัดสินใจด้านการรับส่งข้อมูลอื่นๆ ทั้งหมดโดยใช้การดำเนินการ "ส่งต่อ" เพื่อให้นโยบายเครือข่ายนักพัฒนาแอปมาตรฐานและกฎการปฏิเสธพื้นฐานตามค่าเริ่มต้นสามารถทำการตัดสินใจขั้นสุดท้ายได้
- สร้างไฟล์ Manifest ของนโยบายระดับผู้ดูแลระบบ
05-admin-guardrails.yamlที่กำหนดเป้าหมายเนมสเปซทั้งหมด
cat << 'EOF' > 05-admin-guardrails.yaml
apiVersion: policy.networking.k8s.io/v1alpha2
kind: ClusterNetworkPolicy
metadata:
name: admin-global-guardrails
spec:
tier: Admin
priority: 10
subject:
namespaces: {}
ingress:
- name: delegate-all-ingress
action: Pass
from:
- namespaces: {}
egress:
- name: allow-all-dns
action: Accept
to:
- networks:
- 0.0.0.0/0
protocols:
- udp:
destinationPort:
number: 53
- tcp:
destinationPort:
number: 53
- name: block-metadata-server-global
action: Deny
to:
- networks:
- 169.254.169.254/32
- name: delegate-other-egress
action: Pass
to:
- namespaces: {}
EOF
- ใช้นโยบายระดับผู้ดูแลระบบโดยทำดังนี้
kubectl apply -f 05-admin-guardrails.yaml
- ทดสอบการขโมยข้อมูลเมตาในเนมสเปซทั้ง 3 รายการ ดังนี้
echo -e "\n[1/3] Testing Metadata access from Gemma serving pod (gemma-llm)..."
kubectl exec -n gemma-llm deploy/gemma-serving -- curl --connect-timeout 3 -s -w "\nHTTP Code: %{http_code}\n" -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/zone || echo "🛑 RESULT: Connection Timed Out (Blocked)"
echo -e "\n[2/3] Testing Metadata access from authorized client (client-ns)..."
kubectl exec -n client-ns deploy/rag-agent-client -- curl --connect-timeout 3 -s -w "\nHTTP Code: %{http_code}\n" -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/zone || echo "🛑 RESULT: Connection Timed Out (Blocked)"
echo -e "\n[3/3] Testing Metadata access from rogue client (untrusted-tenant)..."
kubectl exec -n untrusted-tenant deploy/rogue-client -- curl --connect-timeout 3 -s -w "\nHTTP Code: %{http_code}\n" -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/zone || echo "🛑 RESULT: Connection Timed Out (Blocked)"
- ทดสอบการเชื่อมต่อไคลเอ็นต์จาก
client-ns
kubectl exec -n client-ns deploy/rag-agent-client -- curl --connect-timeout 3 -s -X POST \
http://gemma-service.gemma-llm.svc.cluster.local:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-E2B-it",
"messages": [{"role": "user", "content": "Explain zero trust in one short sentence."}],
"max_tokens": 40
}' | jq -r '.choices[0].message.content'
- จำลองความพยายามในการข้ามของนักพัฒนาแอปโดยใช้ NetworkPolicy ขาออกที่อนุญาตทั้งหมดภายใน gemma-llm:
cat << 'EOF' > 06-bypass-attempt.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: dev-allow-all-egress
namespace: gemma-llm
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- {}
EOF
kubectl apply -f 06-bypass-attempt.yaml
- ทดสอบว่าการข้ามของนักพัฒนาซอฟต์แวร์สามารถเลิกบล็อกการเข้าถึงข้อมูลเมตาได้หรือไม่ โดยทำดังนี้
kubectl exec -n gemma-llm deploy/gemma-serving -- curl --connect-timeout 3 -s -w "\nHTTP Code: %{http_code}\n" -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/zone || echo "🛑 RESULT: Connection Timed Out (Admin Guardrail Overrode Developer Policy)"
9. การตรวจสอบแบบอินเทอร์แอกทีฟด้วย Hubble และ Cloud Logging
หากต้องการสังเกตการบังคับใช้นโยบายแบบเรียลไทม์และการตัดสินใจเกี่ยวกับแพ็กเก็ตการตรวจสอบในคลัสเตอร์ คุณจะใช้เซสชัน Cloud Shell แบบแยกหน้าจอที่รวมการติดตามแพ็กเก็ต eBPF ระดับเคอร์เนลเข้ากับการดำเนินการทดสอบอัตโนมัติ
- คลิกไอคอน "+" ในเมนู Cloud Shell เพื่อเปิดแท็บเทอร์มินัลที่ 2
- ในแท็บใหม่นี้ ให้เรียกใช้คำสั่งต่อไปนี้เพื่อสร้างชื่อแทนและเริ่มสังเกตการเข้าชมแบบเรียลไทม์สำหรับเนมสเปซ
gemma-llm
# Create an alias to execute Hubble natively inside the relay pod
alias hubble="kubectl exec -it -n gke-managed-dpv2-observability deploy/hubble-relay -c hubble-cli -- hubble"
# Observe real-time traffic to and from the Gemma namespace
hubble observe --follow --namespace gemma-llm
- สลับกลับไปที่แท็บ Cloud Shell แรกและตรวจสอบว่าคุณอยู่ในไดเรกทอรี
gke-cnp-lab
cd ~/gke-cnp-lab
- เรียกใช้บล็อกต่อไปนี้เพื่อสร้างและเรียกใช้สคริปต์การยืนยันอัตโนมัติ สคริปต์นี้จะทำการทดสอบการรับส่งข้อมูลที่จำเป็นและค้นหา Cloud Logging โดยใช้สคีมาข้อมูลเมตาระดับรูทที่แน่นอนของ GKE เพื่อแสดงกฎ Dataplane V2 ที่แน่นอนซึ่งประเมินคำขอ
cat << 'EOF' > verify-suite.sh
#!/usr/bin/env bash
set -e
echo "========================================================"
echo " 🧪 RUNNING MULTI-TIER POLICY VERIFICATION SUITE"
echo "========================================================"
# Test 1: Ingress Authorized Client -> Gemma (Allowed by NetworkPolicy)
echo -e "\n[1/5] Testing Authorized Client -> Gemma Serving..."
if kubectl exec -n client-ns deploy/rag-agent-client -- \
curl -s --connect-timeout 3 \
http://gemma-service.gemma-llm.svc.cluster.local:8000/v1/chat/completions > /dev/null; then
echo " ✅ RESULT: FORWARDED (Allowed by Developer Network Policy)"
else
echo " 🛑 RESULT: FAILED"
fi
# Test 2: Ingress Rogue Client -> Gemma (Blocked by Baseline Tier)
echo -e "\n[2/5] Testing Unauthorized Rogue Tenant -> Gemma Serving..."
if kubectl exec -n untrusted-tenant deploy/rogue-client -- \
curl -s --connect-timeout 3 \
http://gemma-service.gemma-llm.svc.cluster.local:8000/v1/chat/completions > /dev/null; then
echo " ⚠️ RESULT: UNEXPECTED ALLOW"
else
echo " 🛑 RESULT: DROPPED (Blocked by Baseline Tier)"
fi
# Test 3: Egress Gemma -> GCP Metadata Server (Blocked by Admin Tier)
echo -e "\n[3/5] Testing Metadata access from Gemma serving pod (gemma-llm)..."
kubectl exec -n gemma-llm deploy/gemma-serving -- \
curl --connect-timeout 3 -s -w "\nHTTP Code: %{http_code}\n" -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/zone || echo " 🛑 RESULT: Connection Timed Out (Blocked)"
# Test 4: Egress Authorized Client -> GCP Metadata Server (Blocked by Admin Tier)
echo -e "\n[4/5] Testing Metadata access from authorized client (client-ns)..."
kubectl exec -n client-ns deploy/rag-agent-client -- \
curl --connect-timeout 3 -s -w "\nHTTP Code: %{http_code}\n" -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/zone || echo " 🛑 RESULT: Connection Timed Out (Blocked)"
# Test 5: Egress Rogue Client -> GCP Metadata Server (Blocked by Admin Tier)
echo -e "\n[5/5] Testing Metadata access from rogue client (untrusted-tenant)..."
kubectl exec -n untrusted-tenant deploy/rogue-client -- \
curl --connect-timeout 3 -s -w "\nHTTP Code: %{http_code}\n" -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/zone || echo " 🛑 RESULT: Connection Timed Out (Blocked)"
echo -e "\n========================================================"
echo " 📋 FETCHING AUDIT TRAIL FROM CLOUD LOGGING"
echo "========================================================"
echo "Waiting 12 seconds for telemetry ingestion..."
sleep 12
echo -e "\n🔍 1. Validating Baseline Tier (Rogue Client Block):"
gcloud logging read '
resource.type="k8s_node"
logName=~"logs/policy-action"
jsonPayload.disposition="deny"
jsonPayload.src.namespace="untrusted-tenant"
jsonPayload.dest.namespace="gemma-llm"
' --limit=1 --format="table(
timestamp.date('%H:%M:%S', tz=LOCAL):label=TIME,
jsonPayload.src.namespace:label=SRC_NS,
jsonPayload.dest.namespace:label=DEST_NS,
jsonPayload.policies[0].name:label=BLOCKED_BY_POLICY
)"
echo -e "\n🔍 2. Validating Admin Tier (Metadata Block across all namespaces):"
gcloud logging read '
resource.type="k8s_node"
logName=~"logs/policy-action"
jsonPayload.disposition="deny"
jsonPayload.connection.dest_ip="169.254.169.254"
' --limit=3 --format="table(
timestamp.date('%H:%M:%S', tz=LOCAL):label=TIME,
jsonPayload.src.namespace:label=SRC_NS,
jsonPayload.connection.dest_ip:label=DEST_IP,
jsonPayload.policies[0].name:label=BLOCKED_BY_POLICY
)"
EOF
chmod +x verify-suite.sh
./verify-suite.sh
- ขณะที่สคริปต์ทำงานในแท็บแรก ให้ดูเอาต์พุต Hubble ในแท็บที่ 2
ใน Hubble (แท็บ 2): คุณจะเห็นคำขอ HTTP ที่ได้รับอนุญาตซึ่งส่งต่อเป็นสีเขียว สำหรับการเข้าชมที่ถูกบล็อก คุณจะเห็นเหตุการณ์สีแดง (ถูกทิ้ง) ผู้เช่าที่ไม่ได้รับอนุญาต: การเชื่อมต่อจะส่งผ่านระดับผู้ดูแลระบบและถูกบล็อกที่ระดับพื้นฐาน การค้นหาข้อมูลเมตา: คำขอเข้าถึงข้อมูลเข้าสู่ระบบระบบคลาวด์จะถูกบล็อกทันทีที่ระดับผู้ดูแลระบบ

ใน Cloud Logging (แท็บ 1): สคริปต์จะเสร็จสิ้นโดยการดึงบันทึกการตรวจสอบที่แน่นอนซึ่งส่งไปยัง Google Cloud Logging ซึ่งจะแสดงอย่างชัดเจนว่าระดับใด (ผู้ดูแลระบบหรือพื้นฐาน) และนโยบายใดเป็นผู้รับผิดชอบในการหยุดการรับส่งข้อมูลที่ไม่ได้รับอนุญาต โดยจัดรูปแบบด้วยการประทับเวลาที่แปลแล้วและคำนึงถึงเขตเวลา

10. ล้างข้อมูล
- ปิดแท็บที่ 2
- สลับกลับไปที่แท็บ Cloud Shell แรก
- ลบไฟล์ Manifest, เนมสเปซ และข้อมูลลับของ Kubernetes ที่ติดตั้งใช้งานตามลำดับต่อไปนี้
cd ~/gke-cnp-lab
# Delete policy and verification scripts
rm -f verify-suite.sh
kubectl delete -f 05-admin-guardrails.yaml --ignore-not-found
kubectl delete -f 04-app-networkpolicy.yaml --ignore-not-found
kubectl delete -f 03-baseline-deny.yaml --ignore-not-found
kubectl delete -f 00-network-logging.yaml --ignore-not-found
# Delete workload deployments, secrets, and namespaces
kubectl delete -f 02-gemma4-tpu-vllm.yaml --ignore-not-found
kubectl delete secret hf-secret -n gemma-llm --ignore-not-found
kubectl delete -f 01-namespaces-clients.yaml --ignore-not-found
- ล้างโครงสร้างพื้นฐานโดยใช้คำสั่งต่อไปนี้ พิมพ์
yesเพื่อยืนยัน
terraform destroy --auto-approve
- ตรวจสอบว่าทรัพยากรทั้งหมดถูกยกเลิกอย่างสมบูรณ์ในโปรเจ็กต์ที่ใช้งานอยู่ โดยทำดังนี้
gcloud container clusters list --region=us-west4
gcloud compute networks list
- ลบไดเรกทอรี
gke-cnp-labและเนื้อหา
cd
rm -r gke-cnp-lab
11. ขอแสดงความยินดี
คุณทำ Codelab เรื่องภาระงานการอนุมาน AI ที่ปลอดภัยด้วย ClusterNetworkPolicy ของ GKE เสร็จสมบูรณ์แล้ว
เมื่อทำห้องทดลองเชิงปฏิบัตินี้เสร็จแล้ว คุณจะได้ออกแบบและตรวจสอบสถาปัตยกรรมเครือข่ายการป้องกันหลายชั้นแบบหลายระดับที่แข็งแกร่งสำหรับการแสดงภาระงาน LLM ส่วนตัวที่มีความละเอียดอ่อนใน Google Kubernetes Engine
สิ่งที่คุณทำสำเร็จ
- Infrastructure as Code: จัดสรรคลัสเตอร์ GKE มาตรฐานแบบส่วนตัวที่มีความปลอดภัยสูง ซับเน็ตระดับภูมิภาคแบบส่วนตัว และฮาร์ดแวร์ Cloud TPU v5e โดยเฉพาะแบบไดนามิกโดยใช้ Terraform
- การส่งข้อมูลทางไกลและความสามารถในการสังเกต: กำหนดค่าการบันทึกเครือข่าย Dataplane V2 ควบคู่ไปกับการติดตาม eBPF Hubble ระดับเคอร์เนลเพื่อให้เห็นแพ็กเก็ตรันไทม์อย่างละเอียด
- มาตรการรักษาความปลอดภัยตามลำดับชั้น: เช่น การแยกหน้าที่การปฏิบัติงานอย่างชัดเจนในระดับการประเมินที่แตกต่างกัน 3 ระดับ ได้แก่
- ระดับผู้ดูแลระบบ: มีการบังคับใช้ทั่วทั้งคลัสเตอร์ โดยมีมาตรการป้องกันขาออกที่ข้ามไม่ได้ซึ่งจะบล็อกการเข้าถึงข้อมูลเข้าสู่ระบบของข้อมูลเมตาในแนวราบ (169.254.169.254)
- ระดับ NetworkPolicy: ขอบเขตขาเข้าที่กำหนดขอบเขตเนมสเปซซึ่งได้รับมอบสิทธิ์ให้กับนักพัฒนาแอปพลิเคชันเพื่ออนุญาตการเชื่อมต่อไคลเอ็นต์เวอร์ชันที่ใช้งานจริงอย่างปลอดภัย
- ระดับพื้นฐาน: สร้างเครือข่ายความปลอดภัยสำรองทั่วทั้งคลัสเตอร์ที่ปฏิเสธการเข้าชมของผู้เช่าที่ไม่ได้รับอนุญาตโดยค่าเริ่มต้น
- การตรวจสอบแบบเรียลไทม์: เรียกใช้ชุดโปรแกรมทดสอบการยืนยันที่สมบูรณ์ ดูการทิ้งแพ็กเก็ตแบบเรียลไทม์ที่ระดับเคอร์เนล Linux และค้นหาการตรวจสอบการดำเนินการตามนโยบายที่มีโครงสร้างโดยตรงใน Google Cloud Logging
ขั้นตอนถัดไป / ดูข้อมูลเพิ่มเติม
อ่านข้อมูลเพิ่มเติมเกี่ยวกับเครือข่าย GKE
- เจาะลึกเกี่ยวกับ การกำหนดค่า GKE ClusterNetworkPolicy