Skip to content

Custom Domain in Google Kubernetes Engine with GCP Cloud DNS, Cloud SQL, Istio, Lets Encrypt, PostgreSQL and Keycloak


In this article we are going to setup a custom domain for a Dirigible application in a GKE cluster with GCP Cloud DNS, GCP Cloud SQL Postgre, Istio, Let's Encrypt, Keycloak.

Components: gcp-gke-dns-istio-letsencrypt-postgresql-keycloak


Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications in a cluster environment. You can read more about Kubernetes at


Reliable, resilient, low-latency DNS serving from Google's worldwide network provides you with everything you need to register, manage, and serve your domains. For more information, see Cloud DNS.


Fully managed relational database service for MySQL, PostgreSQL, and SQL Server with rich extension collections, configuration flags, and developer ecosystems. For more information, see GCP Cloud SQL Postgreere.


Istio is an open-source service mesh that layers transparently onto existing distributed applications. Istio’s powerful features provide a uniform and more efficient way to secure, connect, and monitor services. For more information, see Istio.


Istio is an open-source service mesh that layers transparently onto existing distributed applications. Istio’s powerful features provide a uniform and more efficient way to secure, connect, and monitor services. For more information, see Let's Encrypt.


Cert-manager is a powerful and extensible X.509 certificate controller for Kubernetes and OpenShift workloads. It will obtain certificates from a variety of Issuers, both popular public Issuers as well as private Issuers, and ensure the certificates are valid and up-to-date, and will attempt to renew certificates at a configured time before expiry. For more information, see Cert-manager.


Keycloak is an open source Identity and Access Management system for applications and services.For more information, see Keycloak.


In this article, we assume that you already have a GCP account and added billing account.

GKE Cluster Configuration


  1. Create project

    Go to create your project.

    • Set name, organization and billing account. create-project
  2. Enable Engine API

    • To be able to create a cluster, we need to enable Kubernetes Api.

    Go to enable Kubernetes API gcp-gke-dns-istio-letsencrypt-postgresql-keycloak

  3. Create GKE cluster

You can create standard and an autopilot cluster. In ths article, we will create the standard cluster. At this time you have two options to create a cluster: manually or by Use a setup guide.

  • Manually create-manually-cluster

  • Use a setup guide

    In this article we will use a setup guide and cost-optimized cluster. create-setup-guide

  • Choose a suitable location and name your cluster. cost-optimized-cluster

  • Set a release channel. We are going to set Regular channel . This version have passed internal validation and are considered production-quality. set-release-channel

  • Choose a cluster size. In this article we are going to keep the default size. set-cluster-size

  • Verify the machine type.


  • Advanced settings:

    • In this article we will use Optimize utilization.
      Prioritize optimizing utilization over keeping spare resources in the cluster. When selected, the cluster autoscaler scales down the cluster more aggressively: it can remove more nodes, and remove nodes faster.
    • For cluster autoscaler you can configure how many maximum nodes to scale. It depends on your requirements. For this article we are going to keep this configuration maximum nodes 3.
    • Vertical Pod Autoscaling will ensure that the pods will be deployed on the right node. advanced-settings
  • Configure usage metering.

    • In this article we are not using metering. configure-usage-metering

Enable Workload Identity

We need a workload identity to allow our Dirigible pod to access PostgreSQL.

  • Cluster Workload Identity cluster-workload-identity

  • Node Workload Identity node-workload-identity

Istio Configuration


  • In this article we will configure istioctl to use the configmaps from the 1-14-3 revision. We can run multiple versions of Istio concurrently and can specify exactly which revision gets applied in the tooling.
  • Initialize or reinitialize gcloud - check this url for more information.

    gcloud init
  • Enable the specific GKE cluster as the default cluster to be used for the remaining commands.


    You need to replace dirigible with your cluster name and europe-north1-a with your region .

    gcloud container clusters get-credentials dirigible \
      --region europe-north1-a
  • Create istio-system namespace and add label istio-injection.

    kubectl create namespace istio-system
    kubectl label namespace istio-system istio-injection=enabled --overwrite
  • Create Istio control plane service istiod.

kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
    app: istiod
    istio: pilot
    release: istio
  name: istiod
  namespace: istio-system
  type: ClusterIP  
  - name: grpc-xds
    port: 15010
  - name: https-dns
    port: 15012
  - name: https-webhook
    port: 443
    targetPort: 15017
  - name: http-monitoring
    port: 15014
    app: istiod
  • Install minimal control plane.
istioctl install -y -n istio-system --revision 1-14-3 -f - <<EOF
kind: IstioOperator
  name: control-plane
  profile: minimal
        autoscaleEnabled: true
        - name: PILOT_FILTER_GATEWAY_CLUSTER_CONFIG                                                  
          value: "true"
        ISTIO_META_DNS_CAPTURE: "true"
    enablePrometheusMerge: true  
  • Enable the istio-ingressgateway component.

    • Install the istio-ingress gateway in a namespace that is different from istiod and add the istio-injection tag.
    kubectl create namespace istio-ingress
    kubectl label namespace istio-ingress istio-injection=enabled --overwrite
    • Install it with a revision that matches the control plane in the istio-system namespace.
istioctl install -y -n istio-ingress --revision 1-14-3 -f - <<EOF
kind: IstioOperator
  name: istio-ingress-gw-install
  profile: empty
        autoscaleEnabled: true
    - name: istio-ingressgateway
      namespace: istio-ingress
      enabled: true
        - apiVersion: apps/v1
          kind: Deployment
          name: istio-ingressgateway
          - path: spec.template.spec.containers[name:istio-proxy].lifecycle
                  command: ["sh", "-c", "sleep 5"]      
  • Apply Strict mTLS

    • Encrypt the traffic between services in the mesh with mutual TLS.
kubectl apply --namespace istio-system -f - <<EOF
kind: PeerAuthentication
  name: default
    mode: STRICT

GCP Cloud DNS Configuration

  • Enable Cloud DNS API.

    Go to page and choose Enable to enable the API.


  • Create Cloud DNS Zone.

    Go to page create-dns-zone

  • Copy the generated DNS name servers for your zone and add them to your domain, if your control is not in Google Clod DNS.

    The generated DNS name servers should look like this:

  • Create an A record for Dirigible and Keycloak.

    • We need Istio Gateway IP .

      kubectl get svc -n istio-ingress istio-ingressgateway -o jsonpath="{.status.loadBalancer.ingress[0].ip}"

    • A static external IP address is the IP address that is reserved for your project until you decide to release it.
      You need to create the IP address in your region.

      gcloud compute addresses create demo --addresses=<YOUR-GATEWAY-IP> \

    • Set the IP for Dirigible. create-a-record

    • Set the IP for Keycloak. create-a-record

Let's Encrypt Configuration

  • Install Cert-manager.

  • Add cert-manager helm repo.

    helm repo add jetstack
    helm repo update
  • Install Cert-Manager.

    helm install \
    cert-manager jetstack/cert-manager \
    --namespace cert-manager \
    --create-namespace \
    --version v1.9.1 \
    --set installCRDs=true
  • Create ClusterIssuer.


    You need to replace <YOUR-EMAIL-ADDRESS> with your valid email address.

kubectl apply -f - <<EOF
kind: ClusterIssuer
  name: letsencrypt
  namespace: cert-manager
      name: letsencrypt
    - selector: {}
          class: istio

GCP Cloud SQL Postgre Configuration

  • Enable Cloud SQL API and create an instance. Go to page

  • Enable Cloud SQL Admin API. Go to page

  • Choose PostgreSQL database engine. choose-postgresql-database-engine


  • For this article we will create separate instances for Dirigible and Keycloak. You can follow these steps for Dirigible and Keycloak.
  • Create an instance.

    • Set instance info, production. sql-configuration-1

    • Set region, machine type, storage. set-region-machine-storage

    • Set connections.

    We need to Enable Service Networking API set-connections

    • Set automatically allocated IP range. set-connections

    • Set data protection and maintenance. set-data-protection-maintance

    • After you create the instance update the configuration for connections to allow only SSL connection. set-only-ssl-connections

Set Up a Dirigible Database


Create the same way a database and a user for Keycloak.

Create a Dirigible and Keycloak Kubernetes Service Account

  • Create the namespace dirigible-demo.

    kubectl create namespace dirigible-demo
  • Add an Istio injection.

    kubectl label namespace dirigible-demo istio-injection=enabled --overwrite
  • Configure a Kubernetes service account binding to the Google Cloud service account using Workload Identity.

    kubectl create sa dirigible-sa -n dirigible-demo
    kubectl create sa keycloak-sa -n dirigible-demo
  • Add a new binding between your gcp service account and kubernetes service account


    You need to replace dirigible-gke-demo with your project id.

    • Dirigible
    gcloud iam service-accounts add-iam-policy-binding \
    --role="roles/iam.workloadIdentityUser" \
    --member="[dirigible-demo/dirigible-sa]" \
    • Keycloak
    gcloud iam service-accounts add-iam-policy-binding \
    --role="roles/iam.workloadIdentityUser" \
    --member="[dirigible-demo/keycloak-sa]" \
  • Annotate the Kubernetes Service Account with the new binding.


    You need to replace dirigible-gke-demo with your project id.

    • Dirigible
    kubectl annotate serviceaccount -n dirigible-demo \
    dirigible-sa  \
    • Keycloak
    kubectl annotate serviceaccount -n dirigible-demo \
    keycloak-sa  \
  • Create secrets for Kubernetes service accounts.

    • Dirigible
    kubectl create secret generic dirigible-db -n dirigible-demo \
    --from-literal=username=dirigible_user \
    --from-literal=password=<your-password> \
    --from-literal=database=dirigible \
    • Keycloak
    kubectl create secret generic keycloak-db -n dirigible-demo \
    --from-literal=username=keycloak_user \
    --from-literal=password=<your-password> \
    --from-literal=database=keycloak \

Dirigible Deployment

  • When you run this Dirigible helm chart with these sets, it will create volume, enable https, install Keycloak, create Istio gateway and virtualservice, enable usages for GCP Cloud SQL. You don't need to create a service account for Dirigible annd Keycloak, because it was already created in the previous steps. You need to provide gke.projectId, gke.region,
helm repo add dirigible
helm repo update


  • You need to replace:
    • dirigible-gke-demo with your-project-id.
    • europe-north1 with your-region.
    • with your domain.
    • dirigible-demo with your namespace.
helm upgrade --install dirigible dirigible/dirigible -n dirigible-demo \
--set volume.enabled=true \
--set serviceAccount.create=false \
--set keycloak.serviceAccountCreate=false \
--set ingress.tls=true \
--set keycloak.enabled=true \
--set keycloak.install=true \
--set istio.enabled=true \
--set istio.enableHttps=true \
--set gke.cloudSQL=true \
--set gke.projectId=dirigible-gke-demo \
--set gke.region=europe-north1 \
--set \
--set dirigible.image=dirigiblelabs/dirigible-keycloak:latest

Check the Logs on the Cert-Manager Pod

Wait for 3-5 minutes and check the logs.

kubectl logs -n cert-manager -lapp=cert-manager |  grep -i "READY"

You should see something telling you that the certificate is ready and you can redirect http traffic to https.

I0809 13:58:22.750528       1 conditions.go:190] Found status change for Certificate "keycloak" condition "Ready": "False" -> "True"; setting lastTransitionTime to 2022-08-09 13:58:22.750516762 +0000 UTC m=+18939.377721330
I0809 13:58:22.781247       1 conditions.go:190] Found status change for Certificate "keycloak" condition "Ready": "False" -> "True"; setting lastTransitionTime to 2022-08-09 13:58:22.781230149 +0000 UTC m=+18939.408434691
I0809 13:58:23.193897       1 conditions.go:250] Found status change for CertificateRequest "dirigible-spnjm" condition "Ready": "False" -> "True"; setting lastTransitionTime to 2022-08-09 13:58:23.193882791 +0000 UTC m=+18939.821087330
I0809 13:58:23.347574       1 conditions.go:190] Found status change for Certificate "dirigible" condition "Ready": "False" -> "True"; setting lastTransitionTime to 2022-08-09 13:58:23.347561322 +0000 UTC m=+18939.974765874
Now you can set httpsRedirect: true to redirect HTTP traffic to HTTPS.

--set istio.httpsRedirect=true

Keycloak Configuration


You need to replace with your domain.

When you first open, you will see keycloak-configure-client.

  1. We need to create clientId dirigible that's why go to and login with username admin and password admin. create-clientid

  2. Add Role – Open a new client and add the new roles Developer, Operator, Everyone.   create-default-roles

  3. Add Default Roles – Roles->Default Roles add all roles from the previous step. keycloak-add-default-roles

  4. Add User – By default, the new user should have the default roles assigned to it.

Go to page to create the new user. add-user

  1. Add a password. keycloak-add-password

  2. Set a valid redirect URL. valid-recirect

Finally access Dirigible at and log in with the password that we used for our user password. We can see that we have database connection to Cloud SQL PostgreSQL and we have assigned a certificate.