Develop Your Google Cloud Network
Solution for Develop Your Google Cloud Network. 1 lab: GSP321. Fast copy-paste commands for Google Cloud.
GSP321 — Develop your Google Cloud Network: Challenge Lab
Estimated time: 1 hour 15 minutes
# 🚀 Set Up and Configure a Cloud Environment in Google Cloud: Challenge Lab > ⚠️ **Disclaimer:** This guide is provided for educational and learning purposes only. It is intended to help you understand Google Cloud infrastructure setup, VPC networking, Bastion hosts, Cloud SQL, Google Kubernetes Engine (GKE), WordPress deployment, monitoring, uptime checks, and IAM configuration while practicing for Google Cloud certifications and hands-on Challenge Labs. Always follow the official Google Clou
clear
# ==============================================================================
# Color Variables & Orbit of Ops Branding
# ==============================================================================
RED='\e[1;31m'
GREEN='\e[1;32m'
YELLOW='\e[1;33m'
BLUE='\e[1;34m'
MAGENTA='\e[1;35m'
CYAN='\e[1;36m'
WHITE='\e[1;37m'
BOLD='\e[1m'
RESET='\e[0m'
echo -e "${CYAN}${BOLD}"
cat << "EOF"
____ _ _ _ __ ___
/ __ \ | | (_) | / _| / _ \
| | | |_ __| |__ _| |_ ___ | |_ | | | |_ __ ___
| | | | '__| '_ \| | __| / _ \ | _| | | | | '_ \/ __|
| |__| | | | |_) | | |_ | (_) || | | |_| | |_) \__ \
\____/|_| |_.__/|_|\__| \___/ |_| \___/| .__/|___/
| |
|_|
EOF
echo -e "${RESET}"
echo -e "${MAGENTA}${BOLD} 🚀 Starting Orbit of Ops Execution (GSP321: Part 1 of 2)... ${RESET}"
echo -e "${BLUE}--------------------------------------------------------------------------------${RESET}\n"
# ==============================================================================
# PRE-FLIGHT CHECKS & VARIABLES (DYNAMIC AUTO-FETCH)
# ==============================================================================
echo -e "${BOLD}${YELLOW}[Orbit of Ops] Auto-fetching Project, Zone, and Region...${RESET}"
export PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
if [[ -z "$PROJECT_ID" ]]; then
export PROJECT_ID=$DEVSHELL_PROJECT_ID
fi
export ZONE=$(gcloud compute project-info describe \
--format="value(commonInstanceMetadata.items[google-compute-default-zone])" 2>/dev/null | tail -n 1)
if [[ -z "$ZONE" ]]; then
echo -e "${BOLD}${RED}⚠️ Could not auto-detect the default zone via gcloud metadata.${RESET}"
echo -ne "${BOLD}${CYAN}Please enter the lab Zone (e.g., us-east1-c): ${RESET}"
read ZONE
export ZONE
fi
export REGION=${ZONE%-*}
gcloud config set compute/zone $ZONE 2>/dev/null
gcloud config set compute/region $REGION 2>/dev/null
echo -e "✅ Project ID: ${GREEN}$PROJECT_ID${RESET}"
echo -e "✅ Zone: ${GREEN}$ZONE${RESET}"
echo -e "✅ Region: ${GREEN}$REGION${RESET}\n"
echo -e "${BLUE}--------------------------------------------------------------------------------${RESET}\n"
# ==============================================================================
# MAIN SCRIPT EXECUTION - PART 1
# ==============================================================================
echo -e "${BOLD}${CYAN}[Orbit of Ops] Task 1: Creating development VPC manually...${RESET}"
gcloud compute networks create griffin-dev-vpc --subnet-mode custom --quiet
gcloud compute networks subnets create griffin-dev-wp --network=griffin-dev-vpc --region $REGION --range=192.168.16.0/20 --quiet
gcloud compute networks subnets create griffin-dev-mgmt --network=griffin-dev-vpc --region $REGION --range=192.168.32.0/20 --quiet
echo -e "\n${BOLD}${CYAN}[Orbit of Ops] Task 2: Creating production VPC manually...${RESET}"
gcloud compute networks create griffin-prod-vpc --subnet-mode custom --quiet
gcloud compute networks subnets create griffin-prod-wp --network=griffin-prod-vpc --region $REGION --range=192.168.48.0/20 --quiet
gcloud compute networks subnets create griffin-prod-mgmt --network=griffin-prod-vpc --region $REGION --range=192.168.64.0/20 --quiet
echo -e "\n${BOLD}${CYAN}[Orbit of Ops] Task 3: Creating bastion host with dual network interfaces...${RESET}"
gcloud compute instances create bastion \
--network-interface=network=griffin-dev-vpc,subnet=griffin-dev-mgmt \
--network-interface=network=griffin-prod-vpc,subnet=griffin-prod-mgmt \
--tags=ssh --zone=$ZONE --quiet
gcloud compute firewall-rules create fw-ssh-dev --source-ranges=0.0.0.0/0 --target-tags ssh --allow=tcp:22 --network=griffin-dev-vpc --quiet
gcloud compute firewall-rules create fw-ssh-prod --source-ranges=0.0.0.0/0 --target-tags ssh --allow=tcp:22 --network=griffin-prod-vpc --quiet
echo -e "\n${BOLD}${CYAN}[Orbit of Ops] Task 4: Creating and configuring Cloud SQL Instance...${RESET}"
echo -e "${BOLD}${YELLOW}⏳ This process takes roughly 5 to 8 minutes. Please wait...${RESET}"
gcloud sql instances create griffin-dev-db \
--database-version=MYSQL_5_7 \
--region=$REGION \
--root-password='stormwind_rules' \
--quiet
gcloud sql databases create wordpress --instance=griffin-dev-db --quiet
gcloud sql users create wp_user --instance=griffin-dev-db --password=stormwind_rules --quiet
echo -e "\n${GREEN}${BOLD}✅ Part 1 complete! Please proceed to Command 2 of 2.${RESET}"RED='\e[1;31m'
GREEN='\e[1;32m'
YELLOW='\e[1;33m'
CYAN='\e[1;36m'
MAGENTA='\e[1;35m'
BOLD='\e[1m'
RESET='\e[0m'
echo -e "\n${MAGENTA}${BOLD} 🚀 Starting Orbit of Ops Execution (GSP321: Part 2 of 2)... ${RESET}\n"
export PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
export ZONE=$(gcloud config get-value compute/zone 2>/dev/null)
echo -e "${BOLD}${CYAN}[Orbit of Ops] Task 5: Creating Kubernetes cluster (griffin-dev)...${RESET}"
echo -e "${BOLD}${YELLOW}⏳ This process takes roughly 4 to 6 minutes. Please wait...${RESET}"
gcloud container clusters create griffin-dev \
--network griffin-dev-vpc \
--subnetwork griffin-dev-wp \
--machine-type e2-standard-4 \
--num-nodes 2 \
--zone $ZONE \
--quiet
gcloud container clusters get-credentials griffin-dev --zone $ZONE
echo -e "\n${BOLD}${CYAN}[Orbit of Ops] Task 6: Preparing the Kubernetes cluster...${RESET}"
cd ~/
gsutil cp -r gs://spls/gsp321/wp-k8s .
cd wp-k8s
cat > wp-env.yaml <<EOF_END
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: wordpress-volumeclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 200Gi
---
apiVersion: v1
kind: Secret
metadata:
name: database
type: Opaque
stringData:
username: wp_user
password: stormwind_rules
EOF_END
kubectl apply -f wp-env.yaml
gcloud iam service-accounts keys create key.json \
--iam-account=cloud-sql-proxy@$PROJECT_ID.iam.gserviceaccount.com --quiet
kubectl create secret generic cloudsql-instance-credentials \
--from-file key.json
echo -e "\n${BOLD}${CYAN}[Orbit of Ops] Task 7: Creating WordPress deployment...${RESET}"
INSTANCE_ID=$(gcloud sql instances describe griffin-dev-db --format='value(connectionName)')
cat > wp-deployment.yaml <<EOF_END
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
labels:
app: wordpress
spec:
replicas: 1
selector:
matchLabels:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
containers:
- image: wordpress
name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: 127.0.0.1:3306
- name: WORDPRESS_DB_USER
valueFrom:
secretKeyRef:
name: database
key: username
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: database
key: password
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-persistent-storage
mountPath: /var/www/html
- name: cloudsql-proxy
image: gcr.io/cloudsql-docker/gce-proxy:1.33.2
command: ["/cloud_sql_proxy",
"-instances=$INSTANCE_ID=tcp:3306",
"-credential_file=/secrets/cloudsql/key.json"]
securityContext:
runAsUser: 2
allowPrivilegeEscalation: false
volumeMounts:
- name: cloudsql-instance-credentials
mountPath: /secrets/cloudsql
readOnly: true
volumes:
- name: wordpress-persistent-storage
persistentVolumeClaim:
claimName: wordpress-volumeclaim
- name: cloudsql-instance-credentials
secret:
secretName: cloudsql-instance-credentials
EOF_END
kubectl apply -f wp-deployment.yaml
kubectl apply -f wp-service.yaml
echo -e "\n${BOLD}${YELLOW}⏳ Waiting for LoadBalancer External IP to be assigned...${RESET}"
WP_IP=""
while [[ -z "$WP_IP" || "$WP_IP" == "pending" ]]; do
WP_IP=$(kubectl get svc wordpress -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2>/dev/null)
sleep 5
done
echo -e "${GREEN}✅ WordPress IP found: $WP_IP${RESET}"
echo -e "\n${BOLD}${CYAN}[Orbit of Ops] Task 8: Enabling monitoring and creating Uptime Check...${RESET}"
gcloud monitoring uptime create http wordpress-uptime-check \
--display-name="WordPress Uptime" \
--path="/" \
--host="$WP_IP" \
--quiet
echo -e "\n${BOLD}${CYAN}[Orbit of Ops] Task 9: Providing Editor access for the additional engineer...${RESET}"
SECOND_USER=$(gcloud projects get-iam-policy $PROJECT_ID --format=json | jq -r '.bindings[] | select(.role == "roles/viewer").members[]' | grep 'user:' | cut -d':' -f2 | head -n 1)
if [ ! -z "$SECOND_USER" ]; then
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="user:$SECOND_USER" \
--role="roles/editor" \
--quiet
echo -e "${GREEN}✅ Editor role granted to $SECOND_USER${RESET}"
else
echo -e "${RED}⚠️ Could not automatically detect the second user. You may need to assign it manually.${RESET}"
fi
# ==============================================================================
# COMPLETION
# ==============================================================================
echo -e "\n${MAGENTA}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${MAGENTA}${BOLD}║ 🎉 AUTOMATION COMPLETED SUCCESSFULLY 🎉 ║${RESET}"
echo -e "${MAGENTA}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}"
echo -e "${GREEN}${BOLD}You can now safely click ALL 'Check my progress' buttons in your lab manual.${RESET}"
echo -e "${CYAN}${BOLD}Subscribe to Orbit of Ops: https://www.youtube.com/@orbitofops/videos${RESET}\n"