Lab 06: Step-by-Step Guide
Prerequisites Check
Before starting, ensure you have:
# Check common tools (required for all providers)
kubectl version --client
terraform version # If using cloud providerKind-Specific Prerequisites
kind version # If using KindGCP-Specific Prerequisites
gcloud version # If using GCPAWS-Specific Prerequisites
aws --version # If using AWS
aws sts get-caller-identity # Verify AWS credentialsPhase 1: Cluster Setup (10-15 minutes)
Step 1: Choose Deployment Option
This lab supports three deployment options:
Option A: Local (Kind) - Recommended for Learning
- Free and fast
- No cloud account needed
- Perfect for learning multi-tenant patterns
Option B: GCP (GKE)
- Requires GCP account
- More realistic environment
- Free control plane
Option C: AWS (EKS)
- Requires AWS account
- Production-ready environment
- Control plane costs $0.10/hour
Step 2: Configure Provider
Edit terraform.tfvars:
# For Kind (local)
cloud_provider = "kind"
cluster_name = "multi-tenant-cluster"
# For GCP
cloud_provider = "gcp"
project_id = "your-project-id"
region = "us-central1"
# For AWS
cloud_provider = "aws"
region = "us-west-2"
vpc_cidr = "10.0.0.0/16"
availability_zones = ["us-west-2a", "us-west-2b"]Step 3: Setup Cluster
If Using Kind:
cd labs/06-multi-tenant-deployment
./scripts/setup.shThis will create a Kind cluster automatically.
If Using GCP:
cd labs/06-multi-tenant-deployment
cp terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars: set cloud_provider = "gcp" and project_id
terraform init
terraform plan
terraform apply
# Get credentials
terraform output get_credentials_command
eval $(terraform output -raw get_credentials_command)If Using AWS:
cd labs/06-multi-tenant-deployment
cp terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars: set cloud_provider = "aws" and region
terraform init
terraform plan
terraform apply
# Get credentials
terraform output get_credentials_command
eval $(terraform output -raw get_credentials_command)Step 4: Verify Cluster
# Verify cluster access
kubectl cluster-info
kubectl get nodes
# Verify network policy support (for GCP and AWS)
# GCP
kubectl get nodes -o jsonpath='{.items[0].metadata.labels}' | grep network-policy
# AWS (network policies work with VPC CNI)
kubectl get nodesPhase 2: Shared Services (5 minutes)
Step 5: Create Shared Services Namespace
# Create shared services namespace
kubectl apply -f manifests/shared-services/namespace.yaml
# Verify
kubectl get namespace shared-servicesStep 6: Apply Shared Services Network Policy
# Apply network policy
kubectl apply -f manifests/shared-services/network-policy.yaml
# Verify
kubectl get networkpolicy -n shared-servicesPhase 3: Create Tenants (15-20 minutes)
Step 7: Create First Tenant
# Create tenant with standard quota
./tenant-onboarding/create-tenant.sh tenant-a standard
# Verify tenant was created
kubectl get namespace tenant-a
kubectl get resourcequota -n tenant-a
kubectl get networkpolicy -n tenant-a
kubectl get role -n tenant-aStep 8: Create Second Tenant
# Create tenant with limited quota
./tenant-onboarding/create-tenant.sh tenant-b limited
# Verify
kubectl get namespace tenant-bStep 9: Create Third Tenant (Optional)
# Create another tenant
./tenant-onboarding/create-tenant.sh tenant-c standardPhase 4: Deploy Applications (10-15 minutes)
Step 10: Deploy to Tenant A
# Deploy sample application
kubectl run nginx-a --image=nginx -n tenant-a
# Deploy Argo Workflow (if desired)
sed "s/{{TENANT_NAME}}/tenant-a/g" manifests/tenant-templates/argo-workflows.yaml | \
kubectl apply -f -Step 11: Deploy to Tenant B
# Deploy sample application
kubectl run nginx-b --image=nginx -n tenant-b
# Verify deployment
kubectl get pods -n tenant-bPhase 5: Validate Isolation (15-20 minutes)
Step 12: Test RBAC Isolation
# As tenant-a admin, try to access tenant-b
kubectl get pods -n tenant-b
# Should fail if RBAC is working (unless you're cluster admin)
# Check what you can access in tenant-a
kubectl get pods -n tenant-a
# Should workStep 13: Test Network Isolation
# Get pod IPs
TENANT_A_POD=$(kubectl get pod -n tenant-a -l run=nginx-a -o jsonpath='{.items[0].status.podIP}')
TENANT_B_POD=$(kubectl get pod -n tenant-b -l run=nginx-b -o jsonpath='{.items[0].status.podIP}')
# Try to reach tenant-b from tenant-a (should fail)
kubectl run test --image=busybox -n tenant-a --rm -it --restart=Never -- \
wget -O- --timeout=5 http://$TENANT_B_POD || echo "✅ Network isolation working (connection failed as expected)"Step 14: Test Resource Quota
# Check current quota usage
kubectl describe resourcequota -n tenant-a
# Try to exceed quota (should fail)
kubectl run test-large --image=nginx -n tenant-a \
--requests=cpu=10,memory=20Gi \
--limits=cpu=10,memory=20Gi
# Should fail with quota exceeded errorStep 15: Test Shared Services Access
# Deploy a service in shared-services
kubectl run shared-service --image=nginx -n shared-services
kubectl expose pod shared-service -n shared-services --port=80
# Try to access from tenant-a (should work)
kubectl run test --image=busybox -n tenant-a --rm -it --restart=Never -- \
wget -O- http://shared-service.shared-services.svc.cluster.local
# Should succeedPhase 6: Validate Deployment (5 minutes)
Step 16: Run Validation Script
./scripts/validate.shThis will check:
- Shared services namespace
- Tenant namespaces
- Resource quotas
- Network policies
- RBAC configurations
Step 17: Manual Verification
# List all tenants
kubectl get namespaces -l tenant
# Check quota usage across tenants
for ns in $(kubectl get namespaces -l tenant -o name | cut -d/ -f2); do
echo "=== $ns ==="
kubectl describe resourcequota -n $ns | grep -A 5 "Resource Quotas"
donePhase 7: Experiment (Optional, 20-30 minutes)
Step 18: Test Different Scenarios
Test Quota Adjustment:
# Edit quota
kubectl edit resourcequota tenant-quota -n tenant-a
# Increase limits, save
# Verify new limits
kubectl describe resourcequota -n tenant-aTest RBAC Permissions:
# Create read-only user
sed "s/{{NAMESPACE}}/tenant-a/g; s/{{USER}}/readonly@example.com/g" \
../../modules/kubernetes/rbac-patterns/read-only.yaml | \
kubectl apply -f - -n tenant-a
# Test permissions (as that user)
kubectl auth can-i get pods -n tenant-a --as=readonly@example.com
kubectl auth can-i create pods -n tenant-a --as=readonly@example.comTest Network Policy Changes:
# View current network policy
kubectl get networkpolicy -n tenant-a -o yaml
# Modify if needed
kubectl edit networkpolicy tenant-isolation -n tenant-aPhase 8: Cleanup (5 minutes)
Step 19: Clean Up Resources
Kind:
kind delete cluster --name multi-tenant-clusterGCP/AWS:
# Delete tenant namespaces
kubectl delete namespace tenant-a tenant-b tenant-c
# Delete shared services
kubectl delete namespace shared-services
# Destroy infrastructure
terraform destroyProvider-Specific Notes
Kind (Local)
- Setup Time: < 1 minute
- Cost: Free
- Network Policies: Fully supported
- Best For: Learning, testing, development
GCP (GKE)
- Setup Time: 5-10 minutes
- Cost: Free control plane, ~$0.10/hour per node
- Network Policies: Requires
network_policy_enabled = true - Best For: Production GCP deployments
AWS (EKS)
- Setup Time: 10-15 minutes
- Cost: $0.10/hour control plane + ~$0.05/hour per node
- Network Policies: Works with VPC CNI (automatic)
- Best For: Production AWS deployments
Tips for Success
Do's
✅ Start with Kind - Faster, free, good for learning ✅ Create Multiple Tenants - Test isolation properly ✅ Test Each Layer - RBAC, quotas, network policies ✅ Monitor Resource Usage - Understand quota impact ✅ Document Your Setup - Keep notes on what you created
Don'ts
❌ Don't Skip Network Policies - Critical for isolation ❌ Don't Forget Limit Ranges - Ensures all pods have resources ❌ Don't Use ClusterRole - Breaks namespace isolation ❌ Don't Skip Validation - Verify isolation works ❌ Don't Forget Cleanup - Free up resources
Common Issues
See Troubleshooting Guide for detailed solutions to common issues.
Next Steps
After completing this lab:
- Review the Kubernetes modules in
modules/kubernetes/ - Understand different isolation strategies
- Practice tenant lifecycle management
- Experiment with different quota levels
- Proceed to Lab 07: Integration Patterns