Dapr and Azure Functions: Part 5c – Deploying to Google with GKE
Previously, we’ve deployed our Dapr Hello World project to both AWS and Azure.
This time, we’re going to deploy to Google GKE.
Step 1: Get Google Cloud Set up
Start by following the instructions here to get your Google Cloud account set up.
Set your default region to simplify some of the commands we’ll use later on:
1 |
gcloud config set compute/region us-east1 |
Do not use something like us-east1-c since this is a “zone” and not a “region”. You will get an error later on:
1 |
ERROR: (gcloud.container.clusters.create-auto) ResponseError: code=400, message=Autopilot clusters must be regional clusters. |
Step 2: First Attempt Set up GKE Autopilot
Note: this will fail; but I left it here for posterity.
For our first attempt, we’ll try Google GKE Autopilot
Follow the instructions and we should see our cluster created:
Conveniently, the kubectl context is automatically set.
Step 3: Setup Google Artifact Registry
Next, we’ll set up the Google Artifact Registry where we can store our container images.
From the Google web Console, create a Docker Repository helloworld-dapr-func .
You’ll need to run run:
1 |
gcloud auth configure-docker us-east1-docker.pkg.dev |
to authorize your machine to push to the Artifact Registry (replace us-east1 with your region).
There are multiple ways of doing this but the command above seems the simplest.
Step 4: Tag and Push
Like before, we now need to tag and push our local images to the Artifact Registry. There are specifics to the formatting of the image names that differ a bit from AWS and Azure so pay attention to the naming.
1 2 3 4 5 6 7 |
docker tag helloworldfuncdapr/helloworld.api:linux-latest us-east1-docker.pkg.dev/dapr-func/helloworld-dapr-func/helloworld.api-latest docker push us-east1-docker.pkg.dev/dapr-func/helloworld-dapr-func/helloworld.api-latest docker tag helloworldfuncdapr/date.api:linux-latest us-east1-docker.pkg.dev/dapr-func/helloworld-dapr-func/date.api-latest docker push us-east1-docker.pkg.dev/dapr-func/helloworld-dapr-func/date.api-latest |
Once we push it up, we can see the images in our Artifact Registry:
Step 5: Install Dapr
As we did with Azure, we can now install Dapr to the cluster by running: dapr init -k
.
But as it turns out, this is a limitation of GKE Autopilot; mutating WebHooks are not supported so it is not possible to install Dapr using this mechanism.
So back to the drawing board. I deleted my GKE Autopilot cluster and set up a regular cluster:
1 |
gcloud container clusters create helloworldk8s --num-nodes=1 |
If we run kubectl get pods --all-namespaces -o wide
, we can see:
Then after dapr init -k :
We’ll need to make some minor modifications to the .yaml file for GKE:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
apiVersion: v1 kind: Namespace metadata: name: helloworld --- kind: Deployment apiVersion: apps/v1 metadata: name: helloapp namespace: helloworld labels: app: helloworld service: helloapp spec: replicas: 1 selector: matchLabels: service: helloapp template: metadata: labels: app: helloworld service: helloapp annotations: dapr.io/enabled: "true" dapr.io/app-id: "helloapp" dapr.io/app-port: "80" spec: containers: - name: helloapp image: us-east1-docker.pkg.dev/dapr-func/helloworld-dapr-func/helloworld.api-latest imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 protocol: TCP --- kind: Service apiVersion: v1 metadata: name: helloapp-svc namespace: helloworld spec: type: NodePort ports: - port: 80 targetPort: 80 protocol: TCP name: http selector: service: helloapp --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: namespace: helloworld name: helloworld-ingress annotations: kubernetes.io/ingress.class: "gce" spec: rules: - http: paths: - path: /* pathType: ImplementationSpecific backend: service: name: helloapp-svc port: number: 80 --- kind: Deployment apiVersion: apps/v1 metadata: name: dateapp namespace: helloworld labels: app: helloworld service: dateapp spec: replicas: 1 selector: matchLabels: service: dateapp template: metadata: labels: app: helloworld service: dateapp annotations: dapr.io/enabled: "true" dapr.io/app-id: "dateapp" dapr.io/app-port: "80" spec: containers: - name: dateapp image: us-east1-docker.pkg.dev/dapr-func/helloworld-dapr-func/date.api-latest imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 protocol: TCP |
Run kubectl apply -f deploy/gke-deployment.yaml and we can see our pods now:
Run kubectl get ingress/helloworld-ingress -n helloworld to get the IP address and we can use that to hit the API endpoint:
Closing Thoughts
If I had to rank the experience of working with all three now considering documentation, ergonomics, and ease of use, I’d rank them as:
- Microsoft Azure
- Amazon
Google has the most coherent user interface, but the documentation was not quite as good as Microsoft’s IMO (is it personal bias? I’m not sure). All three are functionally very similar, but the AWS ergonomics and documentation left a lot to be desired, IMO.
Google also offers $300 of credits for 90 days so it’s relatively risk free to try it out!
What I still struggle with a bit is why Kubernetes? If anything, this experience has reinforced the case for the convenience of serverless options that let teams focus on delivering value rather than managing yet another layer. Sure, it’s better than VMs, but I have a hard time justifying this additional layer of architecture when serverless options exist and if your application code is segregated the right way, just as portable (treat the serverless interface as an eventing source and put your actual domain logic separate from your eventing logic).
1 Response
[…] Part 5c – Deploying to Google Cloud with Artifact Registry and GKE […]