Google Cloud SDK #
I’m using an Ubuntu 24.04 server to run the gcloud CLI.
Installation #
The Google Cloud SDK (Software Development Kit) includes the gcloud command-line interface (CLI).
# Install dependencies
sudo apt install curl apt-transport-https ca-certificates gnupg -y
# Add package source
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
# Import the Google Cloud public key
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
# Update package index
sudo apt update
# Install the Google Cloud SDK
sudo apt install google-cloud-sdk -y
Verify Installation #
# Verify installation / list version
gcloud version
Login #
Open the link from the shell in a browser, login to GCP and paste the verification code in the shell.
# Alternative use the following command to login without a browser
gcloud auth login --no-launch-browser
Verify Login #
# List Google Cloud accounts that are currently authenticated
gcloud auth list
Kubernetes Cluster Prerequisites #
GCP Project #
Create new Project #
# Create a new project: The project ID has to be globally unique across all Google Cloud projects
gcloud projects create jkw-gcp-playground
Verify Project / List available Projects #
# List available projects
gcloud projects list
# Shell output:
PROJECT_ID NAME PROJECT_NUMBER
jkw-gcp-playground jkw-gcp-playground 147765757820
thematic-carver-429718-h5 My First Project 642160671846
Set the Default Project #
# Set default project: Syntax
gcloud config set project PROJECT_ID
# Set default project: Example
gcloud config set project jkw-gcp-playground
Verify the Default Project #
# Verify the default project
gcloud config get-value project
# Shell output:
jkw-gcp-playground
Add Billing Account #
This can only be done via the GCP webconsole:
-
Open the GCP console: https://console.cloud.google.com/welcome/new?project=jkw-gcp-playground
-
Select project “jkw-gcp-playground”
-
Click the hamburger menu and select “billing”
-
Add a billing account
Verify Billing Account #
# Verify the billing account
gcloud billing projects describe jkw-gcp-playground
# Shell output:
billingAccountName: billingAccounts/01B347-some-billig-account...
billingEnabled: true
name: projects/jkw-gcp-playground/billingInfo
projectId: jkw-gcp-playground
Enable APIs #
Enable the required APIs for project “jkw-gcp-playground”:
# Specify the project ID
PROJECT_ID="jkw-gcp-playground"
# Enable Kubernetes Engine API: "container.googleapis.co"
gcloud services enable container.googleapis.com --project=${PROJECT_ID}
# Enable Compute Engine API: "compute.googleapis.com"
gcloud services enable compute.googleapis.com --project=${PROJECT_ID}
# Enable IAM API: "iam.googleapis.com"
gcloud services enable iam.googleapis.com --project=${PROJECT_ID}
Verify APIs #
# List the APIs and services that are currently enabled in the GCP project
gcloud services list --project=jkw-gcp-playground --enabled
# Shell output:
NAME TITLE
analyticshub.googleapis.com Analytics Hub API
artifactregistry.googleapis.com Artifact Registry API
autoscaling.googleapis.com Cloud Autoscaling API
bigquery.googleapis.com BigQuery API
bigqueryconnection.googleapis.com BigQuery Connection API
bigquerydatapolicy.googleapis.com BigQuery Data Policy API
bigquerymigration.googleapis.com BigQuery Migration API
bigqueryreservation.googleapis.com BigQuery Reservation API
bigquerystorage.googleapis.com BigQuery Storage API
cloudapis.googleapis.com Google Cloud APIs
cloudtrace.googleapis.com Cloud Trace API
compute.googleapis.com Compute Engine API
container.googleapis.com Kubernetes Engine API
containerfilesystem.googleapis.com Container File System API
containerregistry.googleapis.com Container Registry API
dataform.googleapis.com Dataform API
dataplex.googleapis.com Cloud Dataplex API
datastore.googleapis.com Cloud Datastore API
dns.googleapis.com Cloud DNS API
gkebackup.googleapis.com Backup for GKE API
iam.googleapis.com Identity and Access Management (IAM) API
iamcredentials.googleapis.com IAM Service Account Credentials API
logging.googleapis.com Cloud Logging API
monitoring.googleapis.com Cloud Monitoring API
networkconnectivity.googleapis.com Network Connectivity API
oslogin.googleapis.com Cloud OS Login API
pubsub.googleapis.com Cloud Pub/Sub API
servicemanagement.googleapis.com Service Management API
serviceusage.googleapis.com Service Usage API
sql-component.googleapis.com Cloud SQL
storage-api.googleapis.com Google Cloud Storage JSON API
storage-component.googleapis.com Cloud Storage
storage.googleapis.com Cloud Storage API
GCP Region #
List Available Regions #
# List available regios
gcloud compute regions list
# Shell output:
NAME CPUS DISKS_GB ADDRESSES RESERVED_ADDRESSES STATUS TURNDOWN_DATE
africa-south1 0/24 0/4096 0/8 0/8 UP
asia-east1 0/24 0/4096 0/8 0/8 UP
asia-east2 0/24 0/4096 0/8 0/8 UP
asia-northeast1 0/24 0/4096 0/8 0/8 UP
asia-northeast2 0/24 0/4096 0/8 0/8 UP
asia-northeast3 0/24 0/4096 0/8 0/8 UP
asia-south1 0/24 0/4096 0/8 0/8 UP
asia-south2 0/24 0/4096 0/8 0/8 UP
asia-southeast1 0/24 0/4096 0/8 0/8 UP
asia-southeast2 0/24 0/4096 0/8 0/8 UP
australia-southeast1 0/24 0/4096 0/8 0/8 UP
australia-southeast2 0/24 0/4096 0/8 0/8 UP
europe-central2 0/24 0/4096 0/8 0/8 UP
europe-north1 0/24 0/4096 0/8 0/8 UP
europe-southwest1 0/24 0/4096 0/8 0/8 UP
europe-west1 0/24 0/4096 0/8 0/8 UP
europe-west10 0/24 0/4096 0/8 0/8 UP
europe-west12 0/24 0/4096 0/8 0/8 UP
europe-west2 0/24 0/4096 0/8 0/8 UP
europe-west3 0/24 0/4096 0/8 0/8 UP
europe-west4 0/24 0/4096 0/8 0/8 UP
europe-west6 0/24 0/4096 0/8 0/8 UP
europe-west8 0/24 0/4096 0/8 0/8 UP
europe-west9 0/24 0/4096 0/8 0/8 UP
me-central1 0/24 0/4096 0/8 0/8 UP
me-central2 0/24 0/4096 0/8 0/8 UP
me-west1 0/24 0/4096 0/8 0/8 UP
northamerica-northeast1 0/24 0/4096 0/8 0/8 UP
northamerica-northeast2 0/24 0/4096 0/8 0/8 UP
southamerica-east1 0/24 0/4096 0/8 0/8 UP
southamerica-west1 0/24 0/4096 0/8 0/8 UP
us-central1 0/24 0/4096 0/8 0/8 UP
us-east1 0/24 0/4096 0/8 0/8 UP
us-east4 0/24 0/4096 0/8 0/8 UP
us-east5 0/24 0/4096 0/8 0/8 UP
us-south1 0/24 0/4096 0/8 0/8 UP
us-west1 0/24 0/4096 0/8 0/8 UP
us-west2 0/24 0/4096 0/8 0/8 UP
us-west3 0/24 0/4096 0/8 0/8 UP
us-west4 0/24 0/4096 0/8 0/8 UP
Set Default Region #
# Set default region
gcloud config set compute/region europe-west1
Verify Region #
# List current default region
gcloud config get-value compute/region
# Shell output:
europe-west1
Verify Configuration #
# Verify default configuration
gcloud config list
# Shell output:
[compute]
region = europe-west1
[core]
account = juergen@jklug.work
disable_usage_reporting = True
project = jkw-gcp-playground
Your active configuration is: [default]
Prerequisites #
Install Kubectl #
# Install Kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" &&
chmod +x kubectl &&
sudo mv kubectl /usr/local/bin/
# Verify / check version
kubectl version --client
Install gke-gcloud-auth-plugin #
# Install gke-gcloud-auth-plugin: Kubectl authentication plugin
sudo apt install google-cloud-cli-gke-gcloud-auth-plugin -y
# Verify / check version
gke-gcloud-auth-plugin --version
Create GKE Cluster #
Create Cluster #
# Create a cluster with 2 nodes: Regional cluster (Replicates the nodes across multiple zones within a region)
gcloud container clusters create gke-playground \
--num-nodes 1 \
--machine-type e2-micro \
--disk-size 15
# Create a cluster with 2 nodes: Zonal cluster
gcloud container clusters create gke-zonal-playground \
--num-nodes 1 \
--machine-type e2-micro \
--disk-size 15 \
--zone europe-west1-b \
--node-locations europe-west1-b
Verify Cluster #
# Verify cluster
gcloud container clusters list
# Shell output: Regional cluster
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
gke-playground europe-west1 1.29.5-gke.1091002 34.77.108.155 e2-micro 1.29.5-gke.1091002 3 RUNNING
# Shell output: Zonal cluster
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
gke-zonal-playground europe-west1-b 1.29.5-gke.1091002 34.38.207.175 e2-micro 1.29.5-gke.1091002 1 RUNNING
Set Kubeconfig #
# Configure the kubectl configuration for the GKE cluster: Regional cluster
gcloud container clusters get-credentials gke-playground --region europe-west1 --project jkw-gcp-playground
# Configure the kubectl configuration for the GKE cluster: Zonal cluster
gcloud container clusters get-credentials gke-zonal-playground --region europe-west1-b --project jkw-gcp-playground
# Shell output: Regional cluster
Fetching cluster endpoint and auth data.
kubeconfig entry generated for gke-playground.
# Shell output: Zonal cluster
Fetching cluster endpoint and auth data.
kubeconfig entry generated for gke-zonal-playground.
Verify Cluster with Kubectl #
# List cluster nodes
kubectl get nodes -o wide
# Shell output: Regional cluster
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
gke-gke-playground-default-pool-7b3a9e1d-c340 Ready <none> 7m44s v1.29.5-gke.1091002 10.132.0.4 35.241.128.145 Container-Optimized OS from Google 6.1.85+ containerd://1.7.15
gke-gke-playground-default-pool-9850b4c8-vq0v Ready <none> 7m43s v1.29.5-gke.1091002 10.132.0.3 104.155.43.32 Container-Optimized OS from Google 6.1.85+ containerd://1.7.15
gke-gke-playground-default-pool-fcf51c91-sx32 Ready <none> 7m43s v1.29.5-gke.1091002 10.132.0.5 34.79.89.140 Container-Optimized OS from Google 6.1.85+ containerd://1.7.15
# Shell output: Zonal cluster
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
gke-gke-zonal-playground-default-pool-fc3d154d-ps7t Ready <none> 4m35s v1.29.5-gke.1091002 10.132.0.20 35.195.255.198 Container-Optimized OS from Google 6.1.85+ containerd://1.7.15
List Cluster Details #
Node Pools #
# List node pools
gcloud container node-pools list --cluster gke-playground --region europe-west1
# Shell output:
NAME MACHINE_TYPE DISK_SIZE_GB NODE_VERSION
default-pool e2-micro 15 1.29.5-gke.1091002
# Describe node pool
gcloud container node-pools describe default-pool --cluster gke-playground --region europe-west1
Cluster Configuration #
# Review cluster configuration
gcloud container clusters describe gke-playground --region europe-west1
Exaple Deployment with Ingress & Managed TLS Certificate #
Deployment & Service #
# Create manifest for the deployment and it's ClusterIP service
vi nginx-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
# Deploy the manifest
kubectl apply -f nginx-service.yaml
Verify Service #
# List service
kubectl get svc nginx-service
# Shell output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service ClusterIP 34.118.230.74 <none> 80/TCP 92m
Ingress #
Create Global IP Address #
# Create global IP address with the name "kubernetes-ingress"
gcloud compute addresses create kubernetes-ingress --global
# Shell output
Created [https://www.googleapis.com/compute/v1/projects/jkw-gcp-playground/global/addresses/kubernetes-ingress].
List Global IP Address #
# List the IP address
gcloud compute addresses describe kubernetes-ingress --global --format="get(address)"
# Shell output:
34.54.191.35
Create DNS Entry #
Create an A record the points to the public IP of the GKE Ingress LoadBalancer:
# Create DNS entry
34.54.191.35 gcp-gke.jklug.work
# Verify the DNS entry (It can take a while till the public DNS entry is ready)
ping gcp-gke.jklug.work
Google-managed Certificate #
# Create manifest for the Google-manged certificate
vi managed-cert.yaml
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: managed-cert
spec:
domains:
- gcp-gke.jklug.work
# Deploy the managed certificate
kubectl apply -f managed-cert.yaml
# Shell output:
managedcertificate.networking.gke.io/managed-cert created
Verify Managed Certificate Status #
Note: It can take up to 60 min till the certificate status changes from “provisioning” to “active”
# List ingress details
kubectl describe managedcertificate managed-cert
# Shell output
Name: managed-cert
Namespace: default
Labels: <none>
Annotations: <none>
API Version: networking.gke.io/v1
Kind: ManagedCertificate
Metadata:
Creation Timestamp: 2024-07-18T15:59:31Z
Generation: 2
Resource Version: 69970
UID: 1ce240fa-f5bb-4da8-8812-02f25ca7d3a4
Spec:
Domains:
gcp-gke.jklug.work
Status:
Certificate Name: mcrt-1b79c7fe-f384-42ae-8544-dbfc12b0228f
Certificate Status: Provisioning # Wait till status changes to active
Domain Status:
Domain: gcp-gke.jklug.work
Status: Provisioning # Wait till status changes to active
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Create 7m48s managed-certificate-controller Create SslCertificate mcrt-1b79c7fe-f384-42ae-8544-dbfc12b0228f
# Shell output:
kubectl describe managedcertificate managed-cert
Name: managed-cert
Namespace: default
Labels: <none>
Annotations: <none>
API Version: networking.gke.io/v1
Kind: ManagedCertificate
Metadata:
Creation Timestamp: 2024-07-18T15:59:31Z
Generation: 3
Resource Version: 78641
UID: 1ce240fa-f5bb-4da8-7712-02f45ca7r3a4
Spec:
Domains:
gcp-gke.jklug.work
Status:
Certificate Name: mcrt-1b79c7fe-f384-42ae-8544-dbfc12b0228f
Certificate Status: Active # Wait till status changes to active
Domain Status:
Domain: gcp-gke.jklug.work
Status: Active # Wait till status changes to active
Expire Time: 2024-10-16T08:59:35.000-07:00
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Create 15m managed-certificate-controller Create SslCertificate mcrt-1b79c6fe-f384-42ae-8544-cbfc12b1228f
Create Ingress Resource #
# Create GKE Ingress resources
vi managed-cert-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: managed-cert-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "kubernetes-ingress"
networking.gke.io/managed-certificates: "managed-cert"
kubernetes.io/ingress.class: "gce"
spec:
defaultBackend:
service:
name: nginx-service
port:
number: 80
# Deploy GKE Ingress resources
kubectl apply -f managed-cert-ingress.yaml
# Shell output:
Warning: annotation "kubernetes.io/ingress.class" is deprecated, please use 'spec.ingressClassName' instead
ingress.networking.k8s.io/managed-cert-ingress created
Note: Ignore the warning about “kubernetes.io/ingress.class”, if the ingress class is defined as recommended in the warning, the Ingress does not get an external IP.
List Ingress Details #
Note: It takes some time to assign an external IP, because GCP is provisioning a load-balancer.
# List Ingress details
kubectl get ing managed-cert-ingress
# Shell output:
NAME CLASS HOSTS ADDRESS PORTS AGE
managed-cert-ingress <none> * 34.54.191.35 80 18m
# List ingress details
kubectl describe ing managed-cert-ingress
Verify the Deployment with TLS encryption #
# Curl the DNS name via via HTTPS
curl https://gcp-gke.jklug.work
# Shell output:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
Delete GCP Resources #
Delete Ingress Resource #
# Delete GKE Ingress resource
kubectl delete ing managed-cert-ingress
Delete Managed Certificate #
# Delete Google-managed certificate
kubectl delete managedcertificate managed-cert
Delete Global IP #
# Delete the global IP address
gcloud compute addresses delete kubernetes-ingress --global
Delete GKE Cluster #
# Delete Kubernetes Cluster
gcloud container clusters delete gke-zonal-playground --region europe-west1-b --quiet
Delete Project #
# Delete project
gcloud projects delete jkw-gcp-playground
Links #
https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs