Prerequisites: Basic Kubernetes knowledge, kubectl, containerized architecture, cloud account access
Table of Contents
- Course Overview
- Running Kubernetes Effectively in the Cloud
- Determining What You Need to Build
- Hands-On: The Tools
- Deployment on Amazon EKS
- Deployment on Azure AKS
- Deployment on Google GKE
- Evaluating Your Options
- Architecture Diagrams
- Cloud Provider Comparison Tables
- Command Reference
1. Course Overview
This course covers deploying and managing a managed Kubernetes cluster in the cloud:
- Creating Kubernetes clusters in the cloud with Terraform
- Deploying a Helm chart
- Comparing cloud approaches: AWS EKS, Azure AKS, Google GKE
Running Kubernetes on a cloud managed service allows you to:
- Simplify operations (no control plane management)
- Reduce maintenance costs
- Improve performance and stability
2. Running Kubernetes Effectively in the Cloud
What is the Cloud?
Running in the cloud means operating your application on a cloud service provider’s infrastructure. Providers manage:
- Physical data center security (power, cooling)
- Machines, switches, routers, firewalls, and internet bandwidth
- 24/7/365 staff to monitor and maintain all resources
Key Cloud Advantages
| Advantage | Description |
|---|---|
| Agility | Immediate access to a wide range of services — hours instead of weeks |
| Elasticity | Automatic scale up/down based on load, without overprovisioning |
| Cost savings | Pay-as-you-go model, no hardware CAPEX |
| Global reach | Regions and availability zones worldwide |
Interacting with the Cloud
| Method | Advantages | Disadvantages |
|---|---|---|
| Web Console | Easy access, defaults, wizards | Slow (too many clicks), hard to document and reproduce |
| CLI (aws, az, gcloud) | Scriptable, reproducible | Service/provider specific |
| SDK | Programmatic integration | Code complexity |
| Infrastructure as Code (IaC) | Declarative, versionable, multi-provider | Initial learning curve |
Terraform allows declaring desired infrastructure in HCL files with patterns similar across cloud providers.
3. Determining What You Need to Build
What’s Included by Default
Decision points when creating the cluster:
- Kubernetes version: providers may not have the latest version
- Network configuration: node IP assignments, compatibility with other resources
Additional Services to Configure
| Service | Role |
|---|---|
| Cluster Autoscaler | Adds/removes nodes based on pod count |
| Ingress Controller | Manages incoming traffic to the cluster |
| Secrets Manager | Manages secrets for cluster operations |
| Certificate Manager | Creates and renews TLS certificates |
| External DNS | Creates routable endpoints with custom domain names |
| Container Registry | Image repository for deployments |
Scale Levels
Trying it out
└─ Simple cluster with defaults → Familiarization
Proof of Concept (PoC)
└─ Dedicated cluster in a single account → Experimentation
Production-grade
└─ Multi-region, multi-account, high availability → Critical infrastructure
Environment Management Strategies
| Approach | Description | Isolation |
|---|---|---|
| 3 distinct accounts | One cluster per cloud account | Maximum |
| 3 clusters in same account | Logical separation | Strong |
| 1 cluster with 3 namespaces | K8s namespace separation | Light |
4. Hands-On: The Tools
Required Tools
| Tool | Usage | Verification Command |
|---|---|---|
| Terraform 1.5.5 | Infrastructure as Code | terraform -v |
| kubectl | Cluster administration | kubectl version --client |
AWS CLI (aws) | EKS interaction | aws --version |
Azure CLI (az) | AKS interaction | az -v |
Google Cloud CLI (gcloud) | GKE interaction | gcloud -v |
| Helm | Kubernetes package manager | helm version |
5. Deployment on Amazon EKS
EKS = Elastic Kubernetes Service (AWS)
CLI Authentication
aws configure
# Access Key ID: <your-access-key>
# Secret Access Key: <your-secret-key>
# Default region name: us-east-1
# Default output format: json
aws eks list-clusters
Terraform — main.tf for EKS
provider "aws" {
region = var.region
}
data "aws_availability_zones" "available" {
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
locals {
cluster_name = "my-eks-cluster"
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.1.2"
name = "kube-vpc"
cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
enable_dns_hostnames = true
public_subnet_tags = {
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
"kubernetes.io/role/elb" = 1
}
private_subnet_tags = {
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
"kubernetes.io/role/internal-elb" = 1
}
}
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "19.16.0"
cluster_name = local.cluster_name
cluster_version = "1.27"
cluster_endpoint_public_access = true
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
eks_managed_node_groups = {
one = {
name = "node-group-1"
instance_types = ["t3.small"]
min_size = 1
max_size = 3
desired_size = 2
}
two = {
name = "node-group-2"
instance_types = ["t3.medium"]
min_size = 1
max_size = 2
desired_size = 1
}
}
}
Helm Provider for EKS
provider "helm" {
kubernetes {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
exec {
api_version = "client.authentication.k8s.io/v1beta1"
args = ["eks", "get-token", "--cluster-name", local.cluster_name]
command = "aws"
}
}
}
resource "helm_release" "hello_kubernetes" {
name = "my-hello-kubernetes"
repository = "https://helmcharts.opsmx.com/"
chart = "hello-kubernetes"
}
Deploy the Cluster
terraform init
terraform plan
terraform apply -auto-approve
Configure kubectl (AWS)
aws eks --region $(terraform output -raw region) update-kubeconfig \
--name $(terraform output -raw cluster_name)
kubectl get pods --all-namespaces
kubectl get nodes
Deploy Helm Chart on EKS
helm repo add opsmx https://helmcharts.opsmx.com/
helm install my-hello-kubernetes opsmx/hello-kubernetes --version 1.0.3
helm list
kubectl get services
# External IP allows browser access (AWS auto-creates a Load Balancer)
helm uninstall my-hello-kubernetes
AWS Cleanup
terraform destroy
aws eks list-clusters
6. Deployment on Azure AKS
AKS = Azure Kubernetes Service
CLI Authentication
az upgrade
az login --allow-no-subscriptions
# Create service principal for Terraform
az ad sp create-for-rbac -n aksdemo --skip-assignment
# Copy appId and password to terraform.tfvars
az aks list
Terraform — main.tf for AKS
provider "azurerm" {
features {}
}
locals {
cluster_name = "my-aks-cluster"
}
resource "azurerm_resource_group" "default" {
name = "${local.cluster_name}-rg"
location = "East US"
}
resource "azurerm_kubernetes_cluster" "default" {
name = local.cluster_name
location = azurerm_resource_group.default.location
resource_group_name = azurerm_resource_group.default.name
dns_prefix = "${local.cluster_name}-k8s"
kubernetes_version = "1.27.3"
default_node_pool {
name = "default"
node_count = 2
vm_size = "standard_b2s"
os_disk_size_gb = 30
}
service_principal {
client_id = var.appId
client_secret = var.password
}
role_based_access_control_enabled = true
}
resource "azurerm_kubernetes_cluster_node_pool" "additional" {
name = "second"
kubernetes_cluster_id = azurerm_kubernetes_cluster.default.id
vm_size = "standard_b2ms"
node_count = 2
}
Configure kubectl (Azure)
az aks get-credentials \
--resource-group $(terraform output -raw resource_group_name) \
--name $(terraform output -raw kubernetes_cluster_name)
kubectl get pods --all-namespaces
kubectl get nodes
Azure Cleanup
terraform destroy
az aks list
7. Deployment on Google GKE
GKE = Google Kubernetes Engine
CLI Authentication
gcloud init
gcloud auth application-default-login
# Enable in Google Cloud Console: Compute Engine API, Kubernetes Engine API
gcloud container clusters list
Terraform — main.tf for GKE
data "google_client_config" "default" {}
resource "google_container_cluster" "primary" {
name = "my-gke-cluster"
project = var.project
location = var.region
remove_default_node_pool = true
initial_node_count = 1
networking_mode = "VPC_NATIVE"
ip_allocation_policy {}
}
resource "google_container_node_pool" "primary_nodes" {
project = var.project
name = "primary-node-pool"
location = var.region
cluster = google_container_cluster.primary.name
node_count = 1
node_config {
machine_type = "e2-small"
disk_size_gb = 30
oauth_scopes = [
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring",
]
}
}
resource "google_container_node_pool" "secondary_nodes" {
project = var.project
name = "secondary-node-pool"
location = var.region
cluster = google_container_cluster.primary.name
node_count = 1
node_config {
machine_type = "e2-medium"
disk_size_gb = 30
oauth_scopes = [
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring",
]
}
}
Helm Provider for GKE
provider "helm" {
kubernetes {
host = "https://${google_container_cluster.primary.endpoint}"
token = data.google_client_config.default.access_token
cluster_ca_certificate = base64decode(google_container_cluster.primary.master_auth.0.cluster_ca_certificate)
}
}
resource "helm_release" "hello_kubernetes" {
name = "my-hello-kubernetes"
repository = "https://helmcharts.opsmx.com/"
chart = "hello-kubernetes"
depends_on = [google_container_cluster.primary]
}
Configure kubectl (GKE)
gcloud components install gke-gcloud-auth-plugin
gcloud container clusters get-credentials \
$(terraform output -raw kubernetes_cluster_name) \
--region $(terraform output -raw region)
kubectl get pods --all-namespaces
kubectl get nodes
GKE Cleanup
terraform destroy
gcloud container clusters list
8. Evaluating Your Options
Complementary Services
| Provider | Native IaC | Container Registry |
|---|---|---|
| AWS | CloudFormation | Amazon ECR |
| Azure | Azure Resource Manager (ARM) | Azure Container Registry (ACR) |
| Google Cloud | Cloud Deployment Manager | Artifact Registry |
Cost Considerations
| Category | Detail |
|---|---|
| Storage | Based on performance needs and size |
| Node types | Balance cost/performance per workload |
| Spot/Preemptible instances | Significant savings — ideal for K8s since node failures are handled automatically |
| Commitment plans | Discounts for reserved usage |
Advice: Mastering one cloud provider in depth lets you leverage services designed to work together, bringing simplicity and efficiency.
9. Architecture Diagrams
General Architecture: Managed Kubernetes in the Cloud
graph TB
subgraph Cloud["Cloud Provider (AWS / Azure / GCP)"]
subgraph Network["Network (VPC / VNet)"]
subgraph ManagedK8s["Managed Kubernetes (EKS / AKS / GKE)"]
CP["Control Plane\n(managed by provider)"]
subgraph NodeGroup1["Node Group 1"]
N1["Node 1"]
N2["Node 2"]
end
subgraph NodeGroup2["Node Group 2"]
N3["Node 3"]
end
subgraph Pods["Pods"]
APP1["App Pod 1"]
APP2["App Pod 2"]
end
end
LB["Load Balancer\n(External IP)"]
REG["Container Registry"]
end
end
DEV["Developer"] -->|kubectl / Helm| CP
TF["Terraform"] -->|terraform apply| CP
INTERNET["Internet"] --> LB
LB --> Pods
Pods -->|pull images| REG
Migration Flow: Local → Cloud
flowchart LR
subgraph Local["Local / On-premise"]
L1["Docker local"]
L2["minikube / kind"]
L1 --> L2
end
subgraph IaC["Infrastructure as Code"]
T1["Terraform .tf files"]
T2["terraform apply"]
T1 --> T2
end
subgraph CloudK8s["Managed Cloud K8s"]
C1["Cluster created\n(EKS / AKS / GKE)"]
C2["Node Groups configured"]
C3["kubeconfig generated"]
C4["Helm Charts deployed"]
C1 --> C2 --> C3 --> C4
end
Local --> IaC
IaC --> CloudK8s
CloudK8s --> DONE["Application online"]
10. Cloud Provider Comparison Tables
Managed Kubernetes Service Comparison
| Feature | AWS EKS | Azure AKS | Google GKE |
|---|---|---|---|
| Service name | Elastic Kubernetes Service | Azure Kubernetes Service | Google Kubernetes Engine |
| CLI | aws eks | az aks | gcloud container |
| kubeconfig | update-kubeconfig | get-credentials | get-credentials |
| Auth plugin | Built-in | Built-in | gke-gcloud-auth-plugin |
| Container Registry | Amazon ECR | Azure ACR | Google Artifact Registry |
| Native IaC | CloudFormation | ARM Templates | Cloud Deployment Manager |
| IaC module | terraform-aws-modules/eks | azurerm_kubernetes_cluster | google_container_cluster |
11. Command Reference
General Kubectl
kubectl get pods --all-namespaces
kubectl get nodes
kubectl get services
kubectl get deployments
kubectl describe pod <pod-name>
kubectl logs <pod-name>
Helm
helm repo add opsmx https://helmcharts.opsmx.com/
helm repo update
helm search repo hello-kubernetes
helm install my-release opsmx/hello-kubernetes
helm list
helm uninstall my-release
AWS EKS
aws configure
aws eks list-clusters
aws eks --region $(terraform output -raw region) update-kubeconfig \
--name $(terraform output -raw cluster_name)
Azure AKS
az upgrade
az login --allow-no-subscriptions
az aks list
az aks get-credentials \
--resource-group $(terraform output -raw resource_group_name) \
--name $(terraform output -raw kubernetes_cluster_name)
Google Cloud GKE
gcloud init
gcloud auth application-default-login
gcloud container clusters list
gcloud components install gke-gcloud-auth-plugin
gcloud container clusters get-credentials \
$(terraform output -raw kubernetes_cluster_name) \
--region $(terraform output -raw region)
Key Concepts
- Toil (SRE): manual, repetitive, automatable work — reduce via IaC and automation
- Managed Kubernetes: cloud provider manages the control plane, you manage worker nodes and workloads
- Terraform state: always manage resources via Terraform to maintain declared state consistency
- Node Pool: group of nodes sharing the same configuration (instance type, disk size, labels)
- Helm: K8s package manager — prefer managing via Terraform for IaC consistency
- kubeconfig: configuration file generated by the provider CLI to connect kubectl to the cloud cluster
Search Terms
kubernetes · developers · moving · cloud · containers · gke · eks · azure · configure · helm · kubectl · aks · authentication · aws · cleanup · cli · deployment · main.tf · provider · terraform · architecture · comparison · deploy · google