1. Tổng quan
Phòng thí nghiệm này giới thiệu cho bạn cách xây dựng cơ sở hạ tầng AI tự quản lý ngay trên Google Compute Engine (GCE). Bạn sẽ khởi động một cụm Kubernetes không được quản lý trên máy ảo (một số máy ảo có TPU) bằng Terraform, kubeadm và định cấu hình Phân bổ tài nguyên động (DRA) của Kubernetes bằng trình điều khiển nguồn mở. Bạn sẽ làm việc với những nội dung sau:
- Google Compute Engine – Dịch vụ này cung cấp tài nguyên điện toán để khởi động các cụm của bạn
- TPU – Các chip tăng tốc do Google thiết kế riêng.
- Kubernetes OSS – Phần mềm để cài đặt và thiết lập Kubernetes theo cách thủ công
- OSS DRANET – Trình điều khiển mạng DRA
- OSS DRA cho TPU – Trình điều khiển DRA hỗ trợ TPU
Để định cấu hình môi trường, bạn sẽ triển khai nhiều mạng VPC độc lập, mỗi mạng có một mạng con riêng. Điều này cho phép bạn cung cấp các phiên bản VM có nhiều giao diện mạng (nhiều NIC), tách lưu lượng truy cập quản lý khỏi lưu lượng truy cập dữ liệu TPU tốc độ cao.
Tiếp theo, để bật tính năng Phân bổ tài nguyên linh hoạt (DRA) mã nguồn mở, bạn sẽ cài đặt cả trình điều khiển phần cứng DRA Google TPU và trình điều khiển mạng DRANET. Sau đó, bạn sẽ định cấu hình Kubernetes DeviceClasses và viết ResourceClaimTemplates để xử lý việc cung cấp động các tài nguyên này.
Cuối cùng, bạn sẽ triển khai một tải kiểm thử hiệu suất cao bằng cách sử dụng Neper để xác thực các đường dẫn dữ liệu mạng Jumbo Frame giữa các nút worker, sau đó là một bài kiểm thử Python JAX để xác thực silicon TPU cơ bản. Sau đó, bạn sẽ triển khai vLLM để phân phát mô hình Gemma 4 tiên tiến của Google thông qua Hugging Face bằng cách sử dụng các yêu cầu DRA về phần cứng và mạng hoàn toàn biệt lập.
Các cấu hình sẽ kết hợp Terraform, gcloud và kubectl.
Trong bài thực hành này, bạn sẽ tìm hiểu cách thực hiện nhiệm vụ sau:
- Thiết lập mạng VPC
- Triển khai 3 nút trên GCE (1 nút Standard và 2 nút TPU phiên bản 6)
- Khởi động Kubernetes
- Định cấu hình OSS DRANET và DRA cho TPU
- Hiệu suất theo điểm chuẩn
- Tạo DeviceClass và ResourceClaimTemplate
- Đo điểm chuẩn hiệu suất mạng và phần cứng
- Triển khai Gemma 4: Triển khai mô hình trên phần cứng TPU v6e bằng vLLM và các yêu cầu DRA đang hoạt động
- Kiểm tra khả năng kết nối với LLM
Trong lớp học lập trình này, bạn sẽ tạo mẫu sau.
Hình 1.

2. Thiết lập các dịch vụ của Google Cloud
Thiết lập môi trường theo tốc độ của riêng bạn
- Đăng nhập vào Google Cloud Console rồi tạo một dự án mới hoặc sử dụng lại một dự án hiện có. Nếu chưa có tài khoản Gmail hoặc Google Workspace, bạn phải tạo một tài khoản.



- Tên dự án là tên hiển thị của những người tham gia dự án này. Đây là một chuỗi ký tự mà các API của Google không sử dụng. Bạn luôn có thể cập nhật thông tin này.
- Mã dự án là mã duy nhất trên tất cả các dự án trên Google Cloud và không thể thay đổi (bạn không thể thay đổi mã này sau khi đã đặt). Cloud Console sẽ tự động tạo một chuỗi duy nhất; thường thì bạn không cần quan tâm đến chuỗi này. Trong hầu hết các lớp học lập trình, bạn sẽ cần tham chiếu đến Mã dự án (thường được xác định là
PROJECT_ID). Nếu không thích mã nhận dạng được tạo, bạn có thể tạo một mã nhận dạng ngẫu nhiên khác. Hoặc bạn có thể thử tên người dùng của riêng mình để xem tên đó có dùng được hay không. Bạn không thể thay đổi tên này sau bước này và tên này sẽ tồn tại trong suốt thời gian diễn ra dự án. - Để bạn biết, có một giá trị thứ ba là Số dự án mà một số API sử dụng. Tìm hiểu thêm về cả 3 giá trị này trong tài liệu.
- Tiếp theo, bạn cần bật tính năng thanh toán trong Cloud Console để sử dụng các tài nguyên/API trên Cloud. Việc thực hiện lớp học lập trình này sẽ không tốn nhiều chi phí, nếu có. Để tắt các tài nguyên nhằm tránh bị tính phí ngoài phạm vi hướng dẫn này, bạn có thể xoá các tài nguyên đã tạo hoặc xoá dự án. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí trị giá 300 USD.
Khởi động Cloud Shell
Mặc dù có thể vận hành Google Cloud từ xa trên máy tính xách tay, nhưng trong lớp học lập trình này, bạn sẽ sử dụng Google Cloud Shell, một môi trường dòng lệnh chạy trên Cloud.
Trên Bảng điều khiển Google Cloud, hãy nhấp vào biểu tượng Cloud Shell trên thanh công cụ ở trên cùng bên phải:

Quá trình này chỉ mất vài phút để cung cấp và kết nối với môi trường. Khi quá trình này kết thúc, bạn sẽ thấy như sau:

Máy ảo này được trang bị tất cả các công cụ phát triển mà bạn cần. Nền tảng này cung cấp một thư mục chính có dung lượng 5 GB và chạy trên Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và hoạt động xác thực. Bạn có thể thực hiện mọi thao tác trong lớp học lập trình này trong trình duyệt. Bạn không cần cài đặt bất cứ thứ gì.
3. Thiết lập môi trường bằng Terraform
Để thực hiện bài thực hành này, bạn cần có quyền truy cập vào các TPU. Phiên bản chính xác được dùng là TPU v6e.
- Bạn nên làm theo tài liệu về kế hoạch sử dụng TPU và bật hạn mức TPU để có quyền truy cập.
- Sử dụng một khu vực mà bạn có hạn mức TPU. Để biết thêm thông tin, hãy xem tài liệu "Xác thực trạng thái sẵn có của TPU trong GKE"
- Chúng tôi đang sử dụng một quy trình triển khai nhỏ yêu cầu (2) chip TPU v6e (
ct6e-standard-4t)sẽ là một lát 2x2 trong một khu vực. - Mã thông báo Hugging Face: Bạn cần có Mã truy cập để tải các trọng số mô hình Gemma xuống
Chúng ta sẽ tạo 3 VPC tuỳ chỉnh có quy tắc tường lửa và mạng con. Mở Cloud Console rồi chọn dự án mà bạn sẽ sử dụng.
- Mở Cloud Shell ở phía trên cùng bên phải của bảng điều khiển, đảm bảo bạn thấy mã dự án chính xác trong Cloud Shell, xác nhận mọi lời nhắc cho phép truy cập.

- Tạo một thư mục có tên là
oss-kube-dra,, chuyển đến thư mục đó rồi thêm một số biến. tái bút Cập nhật các giá trị biến cho "REGION" và "ZONE" thành khu vực và múi giờ thực tế của bạn. Khu vực mặc định được dùng là "europe-west4" và múi giờ mặc định được dùng là "europe-west4-a".
mkdir -p oss-kube-dra && cd oss-kube-dra
export PROJECT_ID=$(gcloud config get-value project)
export REGION="europe-west4"
export ZONE="europe-west4-a"
echo $PROJECT_ID
echo $REGION
echo $ZONE
- Bây giờ, hãy thêm một số tệp cấu hình. Các lệnh này sẽ tạo tệp terraform.tfvars , variables.tf, vpc.tf sau đây.
cat << EOF > terraform.tfvars
project_id = "${PROJECT_ID}"
region = "${REGION}"
zone = "${ZONE}"
EOF
cat << 'EOF' > variables.tf
variable "project_id" {
type = string
description = "The Google Cloud Project ID"
}
variable "region" {
type = string
description = "The region to deploy the resources"
}
variable "zone" {
type = string
description = "The specific zone for the VMs"
}
variable "control_plane_machine_type" {
type = string
default = "e2-standard-8"
description = "Machine type for the Kubernetes control plane node"
}
variable "tpu_worker_machine_type" {
type = string
default = "ct6e-standard-4t"
description = "The machine type for TPU workers (TPU v6e Trillium VM)"
}
EOF
cat << 'EOF' > vpc.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 7.32.0"
}
}
}
provider "google" {
project = var.project_id
region = var.region
}
# 1. Primary Management VPC and Subnet
resource "google_compute_network" "primary_vpc" {
name = "oss-k8s-primary-vpc"
auto_create_subnetworks = false
mtu = 1460
}
resource "google_compute_subnetwork" "primary_subnet" {
name = "oss-k8s-primary-subnet"
ip_cidr_range = "10.0.0.0/24"
region = var.region
network = google_compute_network.primary_vpc.id
}
# 2. Cloud NAT Router and NAT Gateway for Primary VPC (Outbound Access)
resource "google_compute_router" "router" {
name = "oss-k8s-router"
network = google_compute_network.primary_vpc.id
region = var.region
}
resource "google_compute_router_nat" "nat" {
name = "oss-k8s-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"
}
# 3. Firewalls for Primary VPC
resource "google_compute_firewall" "allow_internal" {
name = "oss-k8s-primary-allow-internal"
network = google_compute_network.primary_vpc.id
allow {
protocol = "tcp"
}
allow {
protocol = "udp"
}
allow {
protocol = "icmp"
}
source_ranges = ["10.0.0.0/24"]
}
resource "google_compute_firewall" "allow_iap" {
name = "oss-k8s-allow-iap-ssh"
network = google_compute_network.primary_vpc.id
allow {
protocol = "tcp"
ports = ["22"]
}
source_ranges = ["35.235.240.0/20"]
}
# 4. Multi-NIC TPU Networks and Subnets (With Jumbo Frames MTU 8896)
resource "google_compute_network" "tpu_vpc" {
count = 2
name = "oss-tpu-vpc-${count.index + 1}"
auto_create_subnetworks = false
mtu = 8896
}
resource "google_compute_subnetwork" "tpu_subnet" {
count = 2
name = "oss-tpu-vpc-${count.index + 1}-subnet"
ip_cidr_range = "10.${count.index + 1}0.0.0/24"
region = var.region
network = google_compute_network.tpu_vpc[count.index].id
}
resource "google_compute_firewall" "tpu_allow_internal" {
count = 2
name = "oss-tpu${count.index + 1}-allow-internal"
network = google_compute_network.tpu_vpc[count.index].id
allow {
protocol = "tcp"
}
allow {
protocol = "udp"
}
allow {
protocol = "icmp"
}
source_ranges = ["10.${count.index + 1}0.0.0/24"]
}
EOF
- Đảm bảo bạn đang ở trong thư mục
oss-kube-dravà chạy các lệnh sauterraform initKhởi tạo thư mục làm việc. Đây là bước đầu tiên và bước này sẽ tải các nhà cung cấp cần thiết cho cấu hình đã cho.terraform plan -outtạo một kế hoạch thực thi, cho biết những hành động mà Terraform sẽ thực hiện để triển khai cơ sở hạ tầng của bạn.-outcho phép bạn lưu kế hoạch thực thi vào một tệp nhị phân có tên. Bạn có thể xem điều gì sẽ xảy ra mà không cần thực hiện bất kỳ thay đổi nào.terraform applysẽ chạy các bản cập nhật.
terraform init
terraform plan -out=tfplan
- Bây giờ, hãy chạy quy trình triển khai sau khi bạn chạy
terraform apply. Vì bạn đang áp dụng kế hoạch thực thi đã lưu, nên quy trình này sẽ thực thi ngay mà không cần nhắc xác nhận. (Quá trình này có thể mất từ 5 đến 10 phút)
terraform apply tfplan
- Xác minh chế độ thiết lập.
echo -e "\n=== Verifying VPC Networks ==="
gcloud compute networks list --filter="name~oss-.*" --project=$PROJECT_ID
echo -e "\n=== Verifying Subnetworks ==="
gcloud compute networks subnets list --filter="name~oss-.*" --project=$PROJECT_ID
echo -e "\n=== Verifying Firewall Rules ==="
gcloud compute firewall-rules list --filter="name~oss-.*" --project=$PROJECT_ID
echo -e "\n=== Verifying Cloud NAT ==="
gcloud compute routers nats list --router=oss-k8s-router --router-region=$REGION --project=$PROJECT_ID
Tạo các nút máy ảo
Bây giờ, bạn sẽ xác định các phiên bản Compute Engine.
- Đảm bảo bạn đang ở trong thư mục
oss-kube-dravà chạy lệnh sau trong Cloud Shell để ghi tệpnodes.tf.
cat << 'EOF' > nodes.tf
# 1. K8s Control Plane VM (No TPU)
resource "google_compute_instance" "control_plane" {
name = "k8s-control-plane"
machine_type = var.control_plane_machine_type
zone = var.zone
boot_disk {
initialize_params {
image = "projects/ubuntu-os-cloud/global/images/family/ubuntu-2204-lts"
size = 100
}
}
network_interface {
network = google_compute_network.primary_vpc.id
subnetwork = google_compute_subnetwork.primary_subnet.id
# No public IP block keeps this node private
}
service_account {
scopes = ["cloud-platform"]
}
}
# 2. TPU Worker VMs (Multi-NIC ct6e-standard-4t instances)
resource "google_compute_instance" "tpu_workers" {
count = 2
name = "k8s-tpu-worker-${count.index + 1}"
machine_type = var.tpu_worker_machine_type
zone = var.zone
boot_disk {
initialize_params {
image = "projects/ubuntu-os-accelerator-images/global/images/family/ubuntu-accel-2204-amd64-tpu-v5e-v5p-v6e"
size = 200
}
}
scheduling {
on_host_maintenance = "TERMINATE"
provisioning_model = "STANDARD"
}
# NIC 1: Management VPC Subnet
network_interface {
network = google_compute_network.primary_vpc.id
subnetwork = google_compute_subnetwork.primary_subnet.id
}
# NIC 2: TPU VPC 1 Subnet
network_interface {
network = google_compute_network.tpu_vpc[0].id
subnetwork = google_compute_subnetwork.tpu_subnet[0].id
}
# NIC 3: TPU VPC 2 Subnet
network_interface {
network = google_compute_network.tpu_vpc[1].id
subnetwork = google_compute_subnetwork.tpu_subnet[1].id
}
service_account {
scopes = ["cloud-platform"]
}
lifecycle {
ignore_changes = [
boot_disk[0].initialize_params[0].image,
guest_accelerator,
metadata
]
}
}
EOF
- Sau khi viết cấu hình mới, hãy tạo một kế hoạch mới và áp dụng kế hoạch đó để cung cấp các phiên bản.
terraform plan -out=tfplan
terraform apply tfplan
- Xác minh.
echo -e "\n=== Verifying Provisioned VM Instances ==="
gcloud compute instances list --filter="name~k8s-.*" --project=$PROJECT_ID
echo -e "\n=== Verifying Network Interfaces on Workers ==="
for i in 1 2; do
echo -e "\n--- Interfaces for k8s-tpu-worker-${i} ---"
gcloud compute instances describe k8s-tpu-worker-${i} \
--zone=$ZONE \
--project=$PROJECT_ID \
--format="table(networkInterfaces[].network.basename(), networkInterfaces[].networkIP)"
done
4. Khởi động nút điều khiển cụm Kubernetes
Trong phần này, bạn sẽ kết nối một cách an toàn với phiên bản máy ảo của lớp điều khiển mà bạn vừa tạo, định cấu hình hệ điều hành cơ bản, cài đặt thời gian chạy vùng chứa và các gói Kubernetes, khởi động cụm và triển khai Calico CNI với khả năng cô lập lưu lượng truy cập nghiêm ngặt cho mạng quản lý.
- Kết nối an toàn với phiên bản
k8s-control-planebằng đường hầm Identity-Aware Proxy (IAP) của GCE. Chạy lệnh sau trong cửa sổ dòng lệnh Cloud Shell:
gcloud compute ssh k8s-control-plane \
--zone=$ZONE \
--tunnel-through-iap
- Trên máy ảo
k8s-control-plane, hãy tạo một tập lệnh có tên làinit-control-plane.shđể tự động hoá các bước cài đặt và định cấu hình.
cat << 'CONTROL_PLANE_EOF' > init-control-plane.sh
#!/bin/bash
# Strict error handling: fail instantly if any command exits with a non-zero status
set -e
echo "=== 1. Neutralizing Background Updates & Preparing Base OS ==="
# Prevent unattended upgrades from locking apt or breaking network configuration mid-setup
sudo systemctl stop apt-daily.timer apt-daily-upgrade.timer || true
sudo systemctl disable apt-daily.timer apt-daily-upgrade.timer || true
sudo systemctl mask apt-daily.service apt-daily-upgrade.service || true
# Turn off swap (mandatory for Kubernetes)
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
# Load required kernel modules
cat << 'EOT' | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOT
sudo modprobe overlay
sudo modprobe br_netfilter
# Configure sysctl requirements for Kubernetes bridging
cat << 'EOT' | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOT
sudo sysctl --system
echo "=== 2. Installing Container Runtime (Containerd) ==="
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg bash-completion
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
echo "=== 3. Configuring Containerd with Systemd Cgroups ==="
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl daemon-reload
sudo systemctl restart containerd
sudo systemctl enable containerd
# Validation Step: Verify runtime engine health
if ! systemctl is-active --quiet containerd; then
echo "❌ ERROR: Containerd failed to start properly."
exit 1
fi
echo "✅ Containerd runtime is active and healthy."
echo "=== 4. Installing Kubernetes 1.36 Binaries ==="
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key | sudo gpg --dearmor --yes -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.36/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
# Configure Autocomplete and Aliases system-wide
kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null
kubeadm completion bash | sudo tee /etc/bash_completion.d/kubeadm > /dev/null
if ! grep -q 'alias k=kubectl' ~/.bashrc; then
echo 'alias k=kubectl' >> ~/.bashrc
echo 'complete -o default -F __start_kubectl k' >> ~/.bashrc
fi
echo "=== 5. Initializing Control Plane Engine ==="
sudo kubeadm init --pod-network-cidr=192.168.0.0/16
echo "=== 6. Configuring Administrative Cluster Credentials ==="
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# Validation Step: Verify API Server local responsiveness
echo "Waiting for local API server context..."
until kubectl cluster-info &>/dev/null; do
sleep 2
done
echo "✅ Kubernetes API server is responding locally."
echo "=== 7. Deploying Calico Network Operator ==="
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/tigera-operator.yaml
# Validation Step: Ensure Tigera Operator CRD is fully available before applying configuration
echo "Waiting for Tigera Installation CRD to register on the API server..."
kubectl wait --for=condition=established crd/installations.operator.tigera.io --timeout=60s
echo "=== 8. Deploying Calico Custom Resources (Subnet Interlock Locked to 10.0.0.0/24) ==="
cat << 'CALICO_EOF' > custom-calico.yaml
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
calicoNetwork:
nodeAddressAutodetectionV4:
cidrs:
- "10.0.0.0/24"
ipPools:
- blockSize: 26
cidr: 192.168.0.0/16
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
nodeSelector: all()
CALICO_EOF
kubectl apply -f custom-calico.yaml
# Validation Step: Confirm Calico daemon configurations are processing
echo "Waiting 10 seconds for Calico system namespaces to initialize..."
sleep 10
echo "Current Calico workload deployment status:"
kubectl get pods -n calico-system
echo "=== 9. Exporting Worker Cluster Join Token ==="
sudo kubeadm token create --print-join-command > ~/join.sh
chmod +x ~/join.sh
echo "--------------------------------------------------------"
echo "✅ CONTROL PLANE BOOTSTRAP COMPLETE!"
echo "Your cluster join command for the TPU workers is saved below:"
echo "--------------------------------------------------------"
cat ~/join.sh
CONTROL_PLANE_EOF
- Chạy tập lệnh.
chmod +x init-control-plane.sh
./init-control-plane.sh
- Sau khi hoàn tất, hãy xác minh. Sẽ mất vài phút để tất cả các tính năng này hoạt động.
kubectl get nodes
kubectl get pods -A
Bạn sẽ thấy nội dung tương tự như sau
NAME STATUS ROLES AGE VERSION k8s-control-plane Ready control-plane 6m50s v1.36.2 NAMESPACE NAME READY STATUS RESTARTS AGE calico-system calico-kube-controllers-5578ff64dd-87vp2 1/1 Running 0 6m33s calico-system calico-node-fxzpp 1/1 Running 0 6m33s calico-system calico-typha-785cbc858-rv4nz 1/1 Running 0 6m33s calico-system csi-node-driver-wlrhx 2/2 Running 0 6m33s kube-system coredns-589f44dc88-pqfrl 1/1 Running 0 6m42s kube-system coredns-589f44dc88-sdwmj 1/1 Running 0 6m42s kube-system etcd-k8s-control-plane 1/1 Running 0 6m47s kube-system kube-apiserver-k8s-control-plane 1/1 Running 0 6m47s kube-system kube-controller-manager-k8s-control-plane 1/1 Running 0 6m47s kube-system kube-proxy-jnm2p 1/1 Running 0 6m42s kube-system kube-scheduler-k8s-control-plane 1/1 Running 0 6m47s tigera-operator tigera-operator-6bc8d879b5-w5mrq 1/1 Running 0 6m42s
- Thoát khỏi kết nối
sshđể quay lại Cloud Shell
exit
5. Thêm các nút worker TPU
Bạn sẽ chạy một tập lệnh từ Cloud Shell để kết nối an toàn với VM của tầng điều khiển, truy xuất mã thông báo tham gia cụm, đồng thời định cấu hình và đăng ký các nút worker TPU vào cụm.
- Chạy lệnh sau trong Cloud Shell để viết tập lệnh điều phối:
cat << 'WORKER_BOOTSTRAP_EOF' > bootstrap-workers.sh
#!/bin/bash
# Strict error handling: fail instantly if any command exits with a non-zero status
set -e
# Fetch the join command safely from the control plane
echo "Fetching join command from Control Plane..."
JOIN_CMD=$(gcloud compute ssh k8s-control-plane --zone=$ZONE --tunnel-through-iap --command="cat ~/join.sh" 2>/dev/null)
if [ -z "$JOIN_CMD" ]; then
echo "❌ ERROR: Failed to retrieve the join command. Ensure the control plane is reachable."
exit 1
fi
echo "✅ Successfully retrieved join command."
# Create the setup script locally to be copied to the workers
cat << 'WORKER_INIT_EOF' > init-worker.sh
#!/bin/bash
set -e
echo "=== 1. Neutralizing Background Updates & Setting Non-Interactive Mode ==="
export DEBIAN_FRONTEND=noninteractive
sudo sed -i "s/#\$nrconf{restart} = 'i';/\$nrconf{restart} = 'a';/g" /etc/needrestart/needrestart.conf 2>/dev/null || true
# Prevent unattended upgrades from tearing down network interfaces mid-setup
sudo systemctl stop apt-daily.timer apt-daily-upgrade.timer || true
sudo systemctl disable apt-daily.timer apt-daily-upgrade.timer || true
sudo systemctl mask apt-daily.service apt-daily-upgrade.service || true
echo "=== 2. Base OS Prep ==="
# Disable swap
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
# Load required kernel modules
cat << 'EOT' | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOT
sudo modprobe overlay
sudo modprobe br_netfilter
# Configure bridging and IP forwarding sysctls
cat << 'EOT' | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOT
sudo sysctl --system
echo "=== 3. Installing Containerd (CRI-Only) ==="
sudo apt-get update && sudo apt-get install -yq ca-certificates curl gnupg bash-completion
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install only containerd to avoid unnecessary Docker CE overhead
sudo apt-get update && sudo apt-get install -yq containerd.io
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl daemon-reload
sudo systemctl restart containerd
sudo systemctl enable containerd
# Validation: Check containerd status
if ! systemctl is-active --quiet containerd; then
echo "❌ ERROR: Containerd failed to start."
exit 1
fi
echo "=== 4. Installing Kubernetes 1.36 Binaries ==="
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key | sudo gpg --dearmor --yes -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.36/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update && sudo apt-get install -yq kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
WORKER_INIT_EOF
# Append the actual join command to the script
echo "echo \"=== 5. Joining Cluster ===\"" >> init-worker.sh
echo "sudo $JOIN_CMD" >> init-worker.sh
# Push and run on both Workers concurrently
echo "Starting concurrent bootstrap on both workers..."
(
echo "[Worker 1] Copying script..."
gcloud compute scp init-worker.sh k8s-tpu-worker-1:~ --zone=$ZONE --tunnel-through-iap --quiet
echo "[Worker 1] Executing script..."
gcloud compute ssh k8s-tpu-worker-1 --zone=$ZONE --tunnel-through-iap --command="bash ~/init-worker.sh"
echo "✅ [Worker 1] Bootstrap and Join complete!"
) &
(
echo "[Worker 2] Copying script..."
gcloud compute scp init-worker.sh k8s-tpu-worker-2:~ --zone=$ZONE --tunnel-through-iap --quiet
echo "[Worker 2] Executing script..."
gcloud compute ssh k8s-tpu-worker-2 --zone=$ZONE --tunnel-through-iap --command="bash ~/init-worker.sh"
echo "✅ [Worker 2] Bootstrap and Join complete!"
) &
# Wait for both background processes to finish
wait
echo "--------------------------------------------------------"
echo "✅ BOTH WORKERS HAVE FINISHED PROCESSING"
echo "--------------------------------------------------------"
# Final Validation Check from Control Plane
echo "Verifying cluster node status..."
sleep 5 # Give kubelet a moment to register the nodes
gcloud compute ssh k8s-control-plane --zone=$ZONE --tunnel-through-iap --command="kubectl get nodes -o wide"
WORKER_BOOTSTRAP_EOF
- Thực thi Thiết lập Worker. (Quá trình này sẽ chạy đồng thời cả hai quy trình cài đặt trong nền và mất khoảng 3 đến 5 phút để hoàn tất).
chmod +x bootstrap-workers.sh
./bootstrap-workers.sh
Bạn sẽ thấy kết quả tương tự khi thêm tất cả các nút vào cụm
To increase the performance of the tunnel, consider installing NumPy. For instructions, please see https://cloud.google.com/iap/docs/using-tcp-forwarding#increasing_the_tcp_upload_bandwidth NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME k8s-control-plane Ready control-plane 25m v1.36.2 10.0.0.2 <none> Ubuntu 22.04.5 LTS 6.8.0-1064-gcp (amd64) containerd://2.2.6 k8s-tpu-worker-1 NotReady <none> 10s v1.36.2 10.0.0.3 <none> Ubuntu 22.04.5 LTS 6.8.0-1064-gcp (amd64) containerd://2.2.6 k8s-tpu-worker-2 Ready <none> 27s v1.36.2 10.0.0.4 <none> Ubuntu 22.04.5 LTS 6.8.0-1064-gcp (amd64) containerd://2.2.6
6. Triển khai trình điều khiển TPU DRA OSS
Trong phần này, bạn sẽ quay lại mặt phẳng điều khiển, gắn nhãn các nút worker TPU bằng thông tin chi tiết cụ thể về cấu trúc liên kết của bộ tăng tốc và cài đặt trình điều khiển DRA TPU nguồn mở của Google bằng Helm. Trình điều khiển này chịu trách nhiệm phát hiện các chip TPU v6e thực và ánh xạ chúng một cách tự nhiên đến API Kubernetes.
- Kết nối lại một cách an toàn với máy ảo
k8s-control-planetừ Cloud Shell.
gcloud compute ssh k8s-control-plane \
--zone=$ZONE \
--tunnel-through-iap
- Chạy các lệnh này trong phiên SSH
k8s-control-plane. Gắn nhãn cho các nút bằng bộ nhãn hoàn chỉnh (bao gồm cả các khoá đếm số lượng chip chính xác)
kubectl label node k8s-tpu-worker-1 \
cloud.google.com/gke-tpu-accelerator=tpu-v6e-slice \
cloud.google.com/gke-tpu-topology=2x2 \
cloud.google.com/gke-tpu-dra-driver=true \
cloud.google.com/gke-accelerator-count=4 \
cloud.google.com/gke-tpu-count=4 \
--overwrite
kubectl label node k8s-tpu-worker-2 \
cloud.google.com/gke-tpu-accelerator=tpu-v6e-slice \
cloud.google.com/gke-tpu-topology=2x2 \
cloud.google.com/gke-tpu-dra-driver=true \
cloud.google.com/gke-accelerator-count=4 \
cloud.google.com/gke-tpu-count=4 \
--overwrite
- Sao chép và cài đặt trình điều khiển DRA TPU bằng Helm
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
git clone https://github.com/kubernetes-sigs/dra-driver-google-tpu.git ~/dra-driver-google-tpu || true
cd ~/dra-driver-google-tpu
rm -f *.pack *.tgz
helm install dra-driver-google-tpu ./deployments/helm/dra-driver-google-tpu \
-n dra-driver-google-tpu \
--create-namespace \
--set 'kubeletPlugin.env[0].name=NODE_NAME' \
--set 'kubeletPlugin.env[0].valueFrom.fieldRef.fieldPath=spec.nodeName'
cd ~
- Xác thực chế độ thiết lập trình điều khiển DRA TPU
# Verify driver daemonset status (Pods should show as Running and Ready)
kubectl get pods -n dra-driver-google-tpu -o wide
# Verify TPU ResourceSlices are successfully published to the API server
kubectl get resourceslices
# Safely parse the ResourceSlices to show the Node Name and the number of TPU chips registered
kubectl get resourceslices -o json | jq -r '.items[] | select(.spec.driver=="tpu.google.com") | "Node: \(.spec.nodeName) | TPUs Registered: \(.spec.devices | length)"'
# Inspect driver logs to confirm the TPU hardware was initialized successfully
kubectl logs -n dra-driver-google-tpu -l app.kubernetes.io/name=dra-driver-google-tpu -c tpu-dra-plugin --tail=20
7. Triển khai DRANET nguồn mở và các lớp thiết bị
Trong phần này, bạn sẽ quay lại mặt phẳng điều khiển, cài đặt trình điều khiển DRANET nguồn mở, áp dụng bản vá bộ lọc tuỳ chỉnh để loại trừ các giao diện ảo, đồng thời thiết lập Kubernetes DeviceClass và ResourceClaimTemplate bằng các tiền tố mạng oss phù hợp.
- Kết nối lại một cách an toàn với máy ảo
k8s-control-planetừ Cloud Shell. Nếu đã kết nối, hãy bỏ qua.
gcloud compute ssh k8s-control-plane \
--zone=$ZONE \
--tunnel-through-iap
- Chạy các lệnh này trong phiên
k8s-control-planeSSH
# Install the core components and patch
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/dranet/refs/heads/main/install.yaml
kubectl patch daemonset dranet -n kube-system --type='json' -p='[ { "op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "-filter=!(\"dra.net/type\" in attributes) || (attributes[\"dra.net/type\"].StringValue != \"veth\" && attributes[\"dra.net/type\"].StringValue != \"vxlan\" && attributes[\"dra.net/type\"].StringValue != \"bridge\")" } ]'
# Monitor rollout readiness
kubectl rollout status daemonset/dranet -n kube-system
# Verify running components and permissions
kubectl get pods -n kube-system -l app=dranet -o wide
kubectl get clusterrole,clusterrolebinding,sa dranet -n kube-system
# Interrogate logs for driver binding confirmation
kubectl logs -n kube-system -l app=dranet --tail=20
- Áp dụng DeviceClass và ResourceClaimTemplate
# Apply DRANET DeviceClass and BOTH ResourceClaimTemplates (Network + Hardware)
cat << 'EOF' | kubectl apply -f -
apiVersion: resource.k8s.io/v1
kind: DeviceClass
metadata:
name: dranet
spec:
selectors:
- cel:
expression: device.driver == "dra.net"
---
apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
name: tpu-net-interfaces
namespace: default
spec:
spec:
devices:
requests:
- name: tpu-net-interface
exactly:
deviceClassName: dranet
count: 2
selectors:
- cel:
expression: device.attributes["gce.dra.net"].networkName.startsWith("oss-tpu-vpc")
config:
- opaque:
driver: dra.net
parameters:
interface:
mtu: 8896
gsoMaxSize: 65536
groMaxSize: 65536
gsoIPv4MaxSize: 65536
groIPv4MaxSize: 65536
disableEbpfPrograms: true
---
apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
name: tpu-device-template
namespace: default
spec:
spec:
devices:
requests:
- name: tpu-devices
exactly:
deviceClassName: tpu.google.com
allocationMode: ExactCount
count: 4
EOF
- Xác nhận rằng các mẫu và lớp của bạn đã được đăng ký đúng cách trong Kubernetes API.
# Verify ResourceSlices exist and are actively serving both drivers
kubectl get resourceslices -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName,DRIVER:.spec.driver | grep -E "dra.net|tpu.google.com"
# Verify the DRANET daemonset pods are Running across all nodes
kubectl get pods -n kube-system -l app=dranet -o wide
- Triển khai Parallel Neper StatefulSet.
cat << 'EOF' | kubectl apply -f -
---
apiVersion: v1
kind: Service
metadata:
name: neper
spec:
clusterIP: None
selector:
app: neper
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: neper
spec:
selector:
matchLabels:
app: neper
serviceName: neper
replicas: 2
template:
metadata:
labels:
app: neper
spec:
initContainers:
- name: "network-optimization-sysctls"
image: "busybox"
securityContext:
privileged: true
command:
- sh
- -c
- |
echo 5000 > /proc/sys/net/ipv4/tcp_rto_min_us
echo 1 > /proc/sys/net/ipv4/tcp_no_metrics_save
echo 0 > /proc/sys/net/ipv4/tcp_slow_start_after_idle
echo 131072 > /proc/sys/net/core/optmem_max
echo "4096 41943040 314572800" > /proc/sys/net/ipv4/tcp_rmem
containers:
- name: neper
image: ubuntu:22.04
command:
- /bin/bash
- -c
- |
apt-get update && apt-get install -y iproute2 build-essential git jq python3-pip &&
git clone https://github.com/google/neper.git /tmp/neper &&
cd /tmp/neper && make &&
cp tcp_stream /usr/local/bin/ &&
sleep infinity
securityContext:
privileged: true
resources:
requests:
cpu: "170"
memory: "650Gi"
limits:
cpu: "170"
memory: "650Gi"
claims:
- name: tpu-net-claim
- name: tpu-hardware-claim
resourceClaims:
- name: tpu-net-claim
resourceClaimTemplateName: tpu-net-interfaces
- name: tpu-hardware-claim
resourceClaimTemplateName: tpu-device-template
EOF
- Kiểm tra xác thực
echo -e "\n=== Verifying StatefulSet Pod Status ==="
kubectl get pods -l app=neper -o wide
echo -e "\n=== Verifying Dynamic Resource Claims (DRCs) ==="
kubectl get resourceclaims
echo -e "\n=== Inspecting Device Claim Allocation ==="
# Using a safer JSONPath query to extract the allocated drivers and devices
kubectl get resourceclaims -o json | jq -r '.items[] | "Claim: \(.metadata.name) | Driver: \(.status.allocation.devices.results[0].driver // "Pending")"'
8. Chạy kiểm tra
Chạy bộ kiểm thử đo điểm chuẩn và xác thực phần cứng có giao diện kép.
Giai đoạn 1 (Đo điểm chuẩn mạng): Giai đoạn này đợi cả hai nhóm Neper (neper-0 và neper-1) biên dịch các phần phụ thuộc, trích xuất các địa chỉ IP nhiều NIC không mặc định được liên kết thông qua DRANET, khởi chạy các máy chủ tcp_stream đồng thời trên neper-1, tạo tải có thông lượng cao từ neper-0 và phân tích cú pháp thông lượng tổng hợp theo Gigabit/giây (Gbps).
Giai đoạn 2 (Xác thực phần cứng): Giai đoạn này cài đặt Google JAX bên trong neper-0 và thực hiện phép nhân ma trận (5000x5000) trực tiếp trên các chip TPU được ánh xạ thông qua VFIO để xác nhận trạng thái hoạt động của silicon.
- Chạy lệnh sau trong
k8s-control-planeđể ghirun_dual_neper_test.sh
cat << 'EOF' > run_dual_neper_test.sh
#!/bin/bash
set -e
SERVER_POD="neper-1"
CLIENT_POD="neper-0"
echo "================================================="
echo " PHASE 1: DUAL-INTERFACE HIGH-SPEED NETWORK TEST"
echo "================================================="
echo "=== Waiting for Pods to be Ready ==="
kubectl wait --for=condition=ready pod/$CLIENT_POD pod/$SERVER_POD --timeout=300s
echo "=== Waiting for neper compilation to finish inside Pods ==="
for POD in $SERVER_POD $CLIENT_POD; do
until kubectl exec $POD -c neper -- sh -c 'command -v jq >/dev/null 2>&1 && command -v tcp_stream >/dev/null 2>&1'; do
sleep 5
done
done
echo ""
echo "=== Step 1: Extract Target IPs from $SERVER_POD ==="
# Using jq to parse the network interfaces directly from Linux JSON output
IFACE1=$(kubectl exec $SERVER_POD -c neper -- sh -c "ip -j -4 addr show | jq -r '.[] | select(.ifname != \"lo\" and .ifname != \"eth0\") | .ifname' | sed -n '1p'")
IFACE2=$(kubectl exec $SERVER_POD -c neper -- sh -c "ip -j -4 addr show | jq -r '.[] | select(.ifname != \"lo\" and .ifname != \"eth0\") | .ifname' | sed -n '2p'")
IP1=$(kubectl exec $SERVER_POD -c neper -- sh -c "ip -j -4 addr show | jq -r '.[] | select(.ifname != \"lo\" and .ifname != \"eth0\") | .addr_info[0].local' | sed -n '1p'")
IP2=$(kubectl exec $SERVER_POD -c neper -- sh -c "ip -j -4 addr show | jq -r '.[] | select(.ifname != \"lo\" and .ifname != \"eth0\") | .addr_info[0].local' | sed -n '2p'")
echo " 📍 Target IP 1 ($IFACE1): $IP1"
echo " 📍 Target IP 2 ($IFACE2): $IP2"
echo ""
echo "=== Step 2: Initialize TCP Servers on $SERVER_POD ==="
kubectl exec $SERVER_POD -c neper -- sh -c '
for i in 0 1; do
nohup tcp_stream -C$((52279 + i)) --port=$((38339 + i)) --skip-rx-copy -rw -Z -B16384 \
--test-length=60 --suicide-length=120 -F100 --num-threads=16 --num-flows=32 -D0 \
--logtostderr > test${i}.log 2>&1 &
done
'
sleep 3
echo "=== Step 3: Generate Concurrent High-Throughput Load from $CLIENT_POD ==="
echo "Blasting Traffic via Interface 1 -> $IP1 ..."
kubectl exec $CLIENT_POD -c neper -- sh -c "nohup tcp_stream -C52279 --port=38339 --skip-rx-copy -rw -Z -B16384 \
--test-length=60 --suicide-length=70 -F100 --num-threads=16 --num-flows=32 \
--client -H $IP1 -D0 --logtostderr > test0.log 2>&1 &"
echo "Blasting Traffic via Interface 2 -> $IP2 ..."
kubectl exec $CLIENT_POD -c neper -- sh -c "nohup tcp_stream -C52280 --port=38340 --skip-rx-copy -rw -Z -B16384 \
--test-length=60 --suicide-length=70 -F100 --num-threads=16 --num-flows=32 \
--client -H $IP2 -D0 --logtostderr > test1.log 2>&1 &"
echo ""
echo "=== Testing in progress... Waiting 65 seconds for test completion ==="
sleep 65
echo ""
echo "=== Step 4: Evaluate Throughput Metrics ==="
RAW_BPS1=$(kubectl exec $CLIENT_POD -c neper -- grep -a "remote_throughput=" test0.log | cut -d= -f2 | tr -d '\r' || echo "0")
RAW_BPS2=$(kubectl exec $CLIENT_POD -c neper -- grep -a "remote_throughput=" test1.log | cut -d= -f2 | tr -d '\r' || echo "0")
GBPS1=$(awk -v bps="$RAW_BPS1" 'BEGIN { printf "%.2f", bps / 1000000000 }')
GBPS2=$(awk -v bps="$RAW_BPS2" 'BEGIN { printf "%.2f", bps / 1000000000 }')
TOTAL=$(awk -v b1="$RAW_BPS1" -v b2="$RAW_BPS2" 'BEGIN { printf "%.2f", (b1 + b2) / 1000000000 }')
echo "📊 --- NETWORK RESULTS ---"
echo "Interface 1 ($IFACE1) : ${GBPS1} Gbps"
echo "Interface 2 ($IFACE2) : ${GBPS2} Gbps"
echo "🔥 TOTAL AGGREGATE : ${TOTAL} Gbps"
echo "--------------------------"
echo ""
echo "================================================="
echo " PHASE 2: TPU HARDWARE VALIDATION TEST"
echo "================================================="
echo "⏳ Installing Python and Google JAX on $CLIENT_POD (Takes ~1 minute)..."
kubectl exec $CLIENT_POD -c neper -- bash -c "apt-get update > /dev/null 2>&1 && apt-get install -y python3-pip > /dev/null 2>&1 && pip3 install jax[tpu] -f https://storage.googleapis.com/jax-releases/libtpu_releases.html > /dev/null 2>&1"
echo "🧠 Running matrix math directly on the TPU chips..."
kubectl exec $CLIENT_POD -c neper -- python3 -c "
import jax
import jax.numpy as jnp
print(f'✅ TPU Hardware Detected: {jax.device_count()} chips mapped via vfio')
print('🚀 Executing 5000x5000 Matrix Multiplication on TPU silicon...')
x = jnp.ones((5000, 5000))
y = jnp.dot(x, x)
print('✅ Success! The TPU driver is fully operational and executing math.')
"
EOF
chmod +x run_dual_neper_test.sh
- Thực thi kiểm thử. Quá trình này sẽ mất 2 phút để hoàn tất.
./run_dual_neper_test.sh
Sau khi hoàn tất, đầu ra của thiết bị đầu cuối sẽ hiển thị các chỉ số mạng tốc độ cao đã xác thực và quá trình thực thi phép toán ma trận TPU
=== Step 4: Evaluate Throughput Metrics === 📊 --- NETWORK RESULTS --- Interface 1 (ens9) : 157.51 Gbps Interface 2 (ens10) : 167.04 Gbps 🔥 TOTAL AGGREGATE : 324.55 Gbps -------------------------- ================================================= PHASE 2: TPU HARDWARE VALIDATION TEST ================================================= ⏳ Installing Python and Google JAX on neper-0 (Takes ~1 minute)... 🧠 Running matrix math directly on the TPU chips... ✅ TPU Hardware Detected: 4 chips mapped via vfio 🚀 Executing 5000x5000 Matrix Multiplication on TPU silicon... ✅ Success! The TPU driver is fully operational and executing math.
9. Triển khai Gemma 4 trên cụm của bạn
Trong phần này, bạn sẽ định cấu hình thông tin đăng nhập API Hugging Face bảo mật dưới dạng một bí mật Kubernetes, triển khai công cụ suy luận vLLM bằng cả mạng Phân bổ tài nguyên động (DRA) và các yêu cầu về phần cứng, đồng thời chạy một truy vấn kiểm thử toàn diện dựa trên mô hình Gemma 4 của Google.
Đảm bảo rằng bạn đã đăng nhập vào phiên SSH bảo mật trên k8s-control-plane:
- Kết nối lại một cách an toàn với máy ảo của lớp điều khiển từ Cloud Shell. Nếu bạn đã kết nối, hãy bỏ qua bước này.
gcloud compute ssh k8s-control-plane \
--zone=$ZONE \
--tunnel-through-iap
- Dọn dẹp các hoạt động triển khai trước đây
# 1. Delete the StatefulSet to stop the benchmarking pods
kubectl delete statefulset neper
# 2. Wait for the pods to terminate fully and release the claims
kubectl wait --for=delete pod/neper-0 pod/neper-1 --timeout=60s
- Lưu trữ mã truy cập Hugging Face. Thay thế
<YOUR_ACTUAL_HUGGING_FACE_TOKEN>bằng mã thông báo của bạn.
export HF_TOKEN="<YOUR_ACTUAL_HUGGING_FACE_TOKEN>"
- Tạo một bí mật
kubectl create secret generic hf-token --from-literal=token="${HF_TOKEN}"
- Tệp kê khai này lên lịch một bản sao duy nhất của vLLM chạy trên một VM TPU thô gồm 4 chip. Nó sử dụng tiêu chuẩn DRA của Kubernetes để gắn cả yêu cầu mạng tuỳ chỉnh (tpu-net-claim) và yêu cầu phần cứng (tpu-hardware-claim) để truy cập an toàn vào phần cứng TPU thô mà không cần các điểm gắn ổ đĩa không an toàn. Cuối cùng, nó sẽ hiển thị máy chủ API tương thích với OpenAI qua cổng 8080. Chạy lệnh sau để tạo tệp:
cat << 'EOF' > gemma-inference.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-gemma-4
labels:
app: gemma-server
spec:
replicas: 1
selector:
matchLabels:
app: gemma-server
template:
metadata:
labels:
app: gemma-server
spec:
hostIPC: true
containers:
- name: vllm-tpu
image: vllm/vllm-tpu:latest
securityContext:
privileged: true
env:
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token
key: token
- name: JAX_PLATFORMS
value: "tpu,cpu"
- name: TPU_ACCELERATOR_TYPE
value: "v6e-4"
- name: TPU_WORKER_HOSTNAMES
value: "127.0.0.1"
- name: TPU_WORKER_ID
value: "0"
- name: LIBTPU_INIT_ARGS
value: "--noenable_tpunetd_client"
- name: BARE_METAL_MODE
value: "true"
- name: BYPASS_VBAR_CONTROL_SERVICE
value: "1"
- name: TPU_SKIP_MDS_QUERY
value: "1"
- name: TPU_DEFAULT_NETWORK_TYPE
value: "loopback"
- name: CHIPS_PER_HOST_BOUNDS
value: "2,2,1"
- name: HOST_BOUNDS
value: "1,1,1"
- name: ALT
value: "false,false,false"
- name: WRAP
value: "false,false,false"
command:
- bash
- -c
- |
export PYTHONUNBUFFERED=1
sysctl -w net.ipv6.conf.all.disable_ipv6=0
sysctl -w net.ipv6.conf.default.disable_ipv6=0
sysctl -w net.ipv6.conf.lo.disable_ipv6=0
ip link set lo up || true
exec python3 -m vllm.entrypoints.openai.api_server \
--model google/gemma-4-E4B-it \
--tensor-parallel-size 4 \
--trust-remote-code \
--max-model-len 8192 \
--max-num-batched-tokens 4096 \
--host 0.0.0.0 \
--port 8080
ports:
- containerPort: 8080
resources:
requests:
cpu: "170"
memory: "650Gi"
limits:
cpu: "170"
memory: "650Gi"
claims:
- name: tpu-net-claim
- name: tpu-hardware-claim
volumeMounts:
- name: dshm
mountPath: /dev/shm
volumes:
- name: dshm
emptyDir:
medium: Memory
resourceClaims:
- name: tpu-net-claim
resourceClaimTemplateName: tpu-net-interfaces
- name: tpu-hardware-claim
resourceClaimTemplateName: tpu-device-template
---
apiVersion: v1
kind: Service
metadata:
name: vllm-gemma-service
spec:
selector:
app: gemma-server
ports:
- protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
EOF
- Triển khai khối lượng công việc Suy luận
kubectl apply -f gemma-inference.yaml
- Xác minh trạng thái triển khai. Quá trình thiết lập này phải tải mô hình xuống và tải
vLLM. Thiscó thể mất từ10 - 25 minutes.
kubectl get pods -l app=gemma-server
kubectl describe pods -l app=gemma-server
Bạn cũng có thể xem nhật ký trong vùng chứa để xem quy trình. Nhấn CTRL+C để thoát chế độ xem nhật ký.
kubectl logs -l app=gemma-server -f
Bạn sẽ biết công cụ đã được khởi tạo hoàn toàn khi thấy các dòng
(APIServer pid=1) INFO: Started server process [1]
(APIServer pid=1) INFO: Waiting for application startup.
(APIServer pid=1) INFO: Application startup complete.
Nhấn CTRL+C để thoát luồng nhật ký trước khi chuyển sang bước tiếp theo.
- Xác minh phần đính kèm giao diện. Kiểm tra các giao diện mạng được liên kết bên trong vùng chứa
kubectl exec deployment/vllm-gemma-4 -c vllm-tpu -- ls /sys/class/net
kubectl exec deployment/vllm-gemma-4 -c vllm-tpu -- cat /proc/net/fib_trie | grep -B 1 "32 host"
Những điều cần lưu ý: Bạn sẽ thấy ens9 và ens10 (hoặc các tên ensX tương tự) cùng với giao diện CNI tiêu chuẩn (eth0) và vòng lặp (lo). Đây là các giao diện mạng PCI của máy chủ GCE thực được trình điều khiển DRANET nguồn mở liên kết động bên trong nhóm của bạn bằng quy ước đặt tên khe cắm có thể dự đoán của systemd.
kubectl exec deployment/vllm-gemma-4 -c vllm-tpu -- ls /sys/class/net
ens10
ens9
eth0
Lo
kubectl exec deployment/vllm-gemma-4 -c vllm-tpu -- cat /proc/net/fib_trie | grep -B 1 "32 host"
|-- 10.10.0.3
/32 host LOCAL
--
|-- 10.20.0.3
/32 host LOCAL
--
|-- 127.0.0.1
/32 host LOCAL
--
|-- 192.168.238.67
/32 host LOCAL
--
|-- 10.10.0.3
/32 host LOCAL
--
|-- 10.20.0.3
/32 host LOCAL
--
|-- 127.0.0.1
/32 host LOCAL
--
|-- 192.168.238.67
/32 host LOCAL
10. Kiểm thử LLM
Sau khi xác thực các giao diện, hãy khởi chạy một vùng chứa kiểm thử đơn giản trong cụm để gửi yêu cầu suy luận truyền trực tuyến đối với Gemma 4.
- Chạy lệnh sau trên phiên
k8s-control-planeđể chạy ứng dụng tương tác:
kubectl run gemma-chat --rm -i --tty --image=alpine --restart=Never -- sh -c '
# 1. Silently install curl and jq
apk add --no-cache curl jq > /dev/null
echo -e "\n========================================================"
echo -e "💬 Welcome to the Gemma 4 Real-Time CLI Chat client!"
echo -e "========================================================"
echo -e " Type your prompt below. Type '\''exit'\'' or '\''quit'\'' to end."
echo -e "========================================================\n"
while true; do
# Read user input
echo -n -e "👤 \033[1;34mYou:\033[0m "
read -r USER_INPUT
# Handle exit conditions
if [ "$USER_INPUT" = "exit" ] || [ "$USER_INPUT" = "quit" ] || [ -z "$USER_INPUT" ]; then
echo -e "\n👋 Goodbye!"
break
fi
echo -n -e "🤖 \033[1;32mGemma:\033[0m "
# Use jq to safely escape double quotes and special characters in user input
JSON_PAYLOAD=$(jq -n --arg msg "$USER_INPUT" '\''{
model: "google/gemma-4-E4B-it",
messages: [{role: "user", content: $msg}],
temperature: 0.7,
stream: true
}'\'')
# Stream the tokens in real-time with a typewriter effect
curl -s -X POST http://vllm-gemma-service:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD" | while read -r line; do
# Extract SSE data streams
if echo "$line" | grep -q "data:"; then
DATA_CLEAN=$(echo "$line" | sed "s/^data: //" | tr -d "\r")
if [ "$DATA_CLEAN" != "[DONE]" ] && [ -n "$DATA_CLEAN" ]; then
# Parse and print only the token content
TOKEN=$(echo "$DATA_CLEAN" | jq -r ".choices[0].delta.content // empty" 2>/dev/null)
echo -n "$TOKEN"
fi
fi
done
echo -e "\n"
done
'
Interactive chat

11. Dọn dẹp
Trước tiên, hãy xoá tất cả tải, bí mật và cấu hình khỏi cụm của bạn.
Nếu bạn vẫn đăng nhập vào phiên SSH bảo mật k8s-control-plane, hãy chạy trực tiếp lệnh sau. (Nếu bạn đã thoát, trước tiên hãy SSH lại):
- Kết nối lại một cách an toàn với máy ảo của lớp điều khiển từ Cloud Shell. Nếu bạn đã kết nối với VM này, hãy bỏ qua bước này.
gcloud compute ssh k8s-control-plane \
--zone=$ZONE \
--tunnel-through-iap
- Dọn dẹp các tài nguyên Kubernetes
# 1. Delete the Gemma 4 deployment and service
kubectl delete -f gemma-inference.yaml --ignore-not-found=true
# 2. Delete the Hugging Face access secret
kubectl delete secret hf-token --ignore-not-found=true
# 3. Delete the open-source DRANET specs and drivers
kubectl delete deviceclass dranet --ignore-not-found=true
kubectl delete resourceclaimtemplate tpu-net-interfaces --ignore-not-found=true
kubectl delete -f https://raw.githubusercontent.com/kubernetes-sigs/dranet/refs/heads/main/install.yaml --ignore-not-found=true
# 4. Uninstall the OSS TPU Hardware Driver
helm uninstall dra-driver-google-tpu -n dra-driver-google-tpu --wait || true
- Bây giờ, hãy nhập
exitrồi quay lại thư mục Cloud Shell đang hoạt động nơi bạn lưu trữ các tệp Terraform và hủy bỏ tất cả các nút, mạng VPC và quy tắc tường lửa.
# 1. Create the teardown script
cat << 'EOF' > teardown.sh
#!/bin/bash
# The specific networks defined in your Terraform vpc.tf
NETWORKS=(
"oss-k8s-primary-vpc"
"oss-tpu-vpc-1"
"oss-tpu-vpc-2"
)
echo "=== Hunting down and deleting ALL firewall rules for OSS networks ==="
for NETWORK in "${NETWORKS[@]}"; do
echo "Searching for firewall rules attached to network: $NETWORK..."
# Query GCP for any firewall rule tied to this specific network
STUCK_RULES=$(gcloud compute firewall-rules list \
--filter="network:($NETWORK)" \
--format="value(name)" | tr '\n' ' ')
# Check if the string is not empty and contains more than just whitespace
if [ -n "$STUCK_RULES" ] && [ "$STUCK_RULES" != " " ]; then
echo "🔥 Found rules holding $NETWORK hostage: $STUCK_RULES"
echo "Deleting them now..."
gcloud compute firewall-rules delete $STUCK_RULES --quiet
else
echo "✅ No firewall rules found for $NETWORK."
fi
done
# Fallback: Explicitly delete the named rules from your Terraform file
# just in case the dynamic filter missed them due to caching delays
echo "=== Running fallback deletion for explicitly named Terraform rules ==="
gcloud compute firewall-rules delete \
oss-k8s-primary-allow-internal \
oss-k8s-allow-iap-ssh \
oss-tpu1-allow-internal \
oss-tpu2-allow-internal \
--quiet 2>/dev/null || true
echo "--------------------------------------------------------"
echo "✅ Firewall cleanup complete!"
echo "Your networks are now stripped of firewalls and ready to be deleted."
echo "--------------------------------------------------------"
echo "=== Destroying Infrastructure ==="
cd ~/oss-kube-dra || exit
terraform destroy -auto-approve
echo "--------------------------------------------------------"
echo "✅ Infrastructure successfully destroyed!"
echo "--------------------------------------------------------"
EOF
# 2. Make the script executable and run it
chmod +x teardown.sh
./teardown.sh
- Xoá thư mục terraform
oss-kube-dra
cd
rm -r oss-kube-dra
12. Xin chúc mừng
Bạn đã cung cấp, khởi động và xác thực thành công một cơ sở hạ tầng AI Kubernetes tự quản lý, hiệu suất cao ngay trên các phiên bản VM của Google Compute Engine (GCE).
Giờ đây, bạn đã hiểu rõ ở cấp hệ thống về cách Kubernetes sử dụng tính năng Phân bổ tài nguyên động (DRA) để điều phối các bộ tăng tốc TPU thô, liên kết các cấu trúc liên kết máy chủ đa NIC tốc độ cao và phân phát các mô hình ngôn ngữ lớn tiên tiến.
Các bước tiếp theo / Tìm hiểu thêm
Bạn có thể đọc thêm về mạng GKE
Tham gia phòng thí nghiệm tiếp theo
Tiếp tục hành trình khám phá của bạn với Google Cloud và xem các phòng thí nghiệm khác của Google Cloud: