Skip to content

Instantly share code, notes, and snippets.

@mikesparr
Last active September 16, 2024 11:51
Show Gist options
  • Select an option

  • Save mikesparr/ae9311bdb826cc9fef67269f06a5e697 to your computer and use it in GitHub Desktop.

Select an option

Save mikesparr/ae9311bdb826cc9fef67269f06a5e697 to your computer and use it in GitHub Desktop.
Example BackendConfig for Google Kubernetes Engine (GKE) to enable Cloud CDN and cache content
#!/usr/bin/env bash
#####################################################################
# REFERENCES
# - https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features#cloud_cdn
# - https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features#expandable-1
#####################################################################
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_USER=$(gcloud config get-value core/account) # set current user
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
export IDNS=${PROJECT_ID}.svc.id.goog # workload identity domain
export GCP_REGION="us-central1" # CHANGEME (OPT)
export GCP_ZONE="us-central1-a" # CHANGEME (OPT)
export NETWORK_NAME="default"
# enable apis
gcloud services enable compute.googleapis.com \
container.googleapis.com
# configure gcloud sdk
gcloud config set compute/region $GCP_REGION
gcloud config set compute/zone $GCP_ZONE
# create cluster
export CLUSTER_NAME="central"
gcloud beta container --project $PROJECT_ID clusters create $CLUSTER_NAME \
--zone $GCP_ZONE \
--no-enable-basic-auth \
--cluster-version "1.22.6-gke.300" \
--release-channel "regular" \
--machine-type "e2-medium" \
--image-type "COS_CONTAINERD" \
--disk-type "pd-standard" --disk-size "100" \
--metadata disable-legacy-endpoints=true \
--scopes "https://www.googleapis.com/auth/cloud-platform" \
--max-pods-per-node "110" \
--num-nodes "1" \
--logging=SYSTEM,WORKLOAD \
--monitoring=SYSTEM \
--enable-ip-alias \
--network "projects/$PROJECT_ID/global/networks/default" \
--subnetwork "projects/$PROJECT_ID/regions/us-central1/subnetworks/default" \
--no-enable-intra-node-visibility \
--default-max-pods-per-node "110" \
--enable-autoscaling --min-nodes "0" --max-nodes "3" \
--no-enable-master-authorized-networks \
--addons HorizontalPodAutoscaling,HttpLoadBalancing,NodeLocalDNS,GcePersistentDiskCsiDriver \
--enable-autoupgrade \
--enable-autorepair \
--max-surge-upgrade 1 \
--max-unavailable-upgrade 0 \
--workload-pool "$PROJECT_ID.svc.id.goog" \
--enable-shielded-nodes \
--node-locations $GCP_ZONE
# create deployment (fake app)
cat > deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-deployment
labels:
app: hello
spec:
replicas: 1
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
spec:
containers:
- name: hello
# image: nicholasjackson/fake-service:vm-v1.10.7-v0.22.7
image: us-docker.pkg.dev/google-samples/containers/gke/hello-app-cdn:1.0
# env:
# - name: NAME
# value: "Hello Dave Service"
# - name: MESSAGE
# value: "Hello, Dave!"
ports:
- containerPort: 8080
EOF
# create backend config with CDN
cat > backend.yaml << EOF
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
namespace: default
name: hello-backendconfig
spec:
cdn:
enabled: true
cachePolicy:
includeHost: true
includeProtocol: true
includeQueryString: false
EOF
# expose hello app with NodePort service
cat > service.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: hello-service
annotations:
cloud.google.com/backend-config: '{"ports": {"80":"hello-backendconfig"}}'
spec:
type: NodePort
selector:
app: hello
ports:
- port: 80
targetPort: 8080
EOF
# expose hello service with Ingress and public IP
cat > ingress.yaml << EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-ingress
# annotations:
spec:
rules:
- http:
paths:
- path: /*
pathType: ImplementationSpecific
backend:
service:
name: hello-service
port:
number: 80
EOF
###################### TESTING ####################
# get the public IP (after 10 min) of the Ingress
export PUBLIC_IP=$(kubectl get ingress/hello-ingress -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
# test app with curl
curl -v "$PUBLIC_IP/?cache=true"
# wait 1 minute for CDN to warm up and retry (confirm Age: is in header)
# < HTTP/1.1 200 OK
# < Content-Length: 73
# < Via: 1.1 google
# < Date: Thu, 31 Mar 2022 15:25:34 GMT
# < Content-Type: text/plain; charset=utf-8
# < Age: 20 <------------------- AGE CONFIRMS CACHED *******
# < Cache-Control: max-age=3600,public
@mikesparr
Copy link
Author

Overview

This test is following Google Cloud's documentation to implement Cloud CDN using a BackendConfig with an Ingress as demonstrated at the following site: Example Cloud CDN BackendConfig

Results

Cloud CDN was enabled.

Port 80 (success)

If we follow the Google example, and expose our Service with port 80, it works correctly and we see the following CDN enabled:
Screen Shot 2022-03-31 at 9 36 23 AM

Screen Shot 2022-03-31 at 9 26 28 AM

Port 8080 (success)

Testing whether a specific port needed to be exposed or declared seems to have no effect.

No cache-control headers (failure)

If the application does not return Cache-Control: max-age=3600,public headers, the CDN does not cache the content and no Age header appears.

< HTTP/1.1 200 OK
< Date: Thu, 31 Mar 2022 16:02:37 GMT
< Content-Length: 277
< Content-Type: text/plain; charset=utf-8
< Via: 1.1 google

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment