Last active
September 16, 2024 11:51
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Overview
This test is following Google Cloud's documentation to implement Cloud CDN using a
BackendConfigwith anIngressas demonstrated at the following site: Example Cloud CDN BackendConfigResults
Cloud CDN was enabled.
Port 80 (success)
If we follow the Google example, and expose our

Servicewith port 80, it works correctly and we see the following CDN enabled: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,publicheaders, the CDN does not cache the content and noAgeheader appears.