How to deploy Keycloak with Postgres on GKE

keycloak on kubernetes with postgres
Reading Time: 3 minutes

In this blog, we will se how we can deploy Keycloak with Postgres database on kubernetes here, Postgres database is to persist keycloak data. Without Postgres Keycloak will use it’s internal embedded databse H2.

Keycloak is an open-source Identity and Access management application. It can be used for authentication applications and it has many providers like google to provide sign-in from your google account. It has many security services like SSO, Social logins, Identity brokering, LDAP & active directory, and much more.

Read more about Keycloak from here.

Scope – Keycloak with Postgres

We will deploy Keycloak with the Postgresql database to persist data. We will deploy all workloads on Google Kubernetes Engine.

Prerequisites – Keycloak with Postgres

Deploy Postgresql YAMLs

Create 2 directories postgres/ & keycloak/ and place yaml files in these directories then deploy the workloads on cluster.

1. Create storageclass for dynamic storage provisioning

postgres/storageclass.yml

allowVolumeExpansion: true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: postgres-sc
parameters:
  type: pd-standard
provisioner: kubernetes.io/gce-pd
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

2. Create secrets for postgres database

postgres/postgres-secrets.yml

apiVersion: v1
kind: Secret
metadata:
  name: postgres-sec
type: Opaque
data:
  POSTGRES_PASSWORD: YWRtaW4K
  POSTGRES_USER: YWRtaW4K

3. Create statefulset and service for postgres database

postgres/postgres-statefulset.yml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app: postgres
  name: postgres
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: postgres
  serviceName: postgres-svc
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - env:
        - name: PGDATA
          value: /var/lib/postgresql/data/pgdata
        - name: POSTGRES_USER
          valueFrom:
            secretKeyRef:
              key: POSTGRES_USER
              name: postgres-sec
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              key: POSTGRES_PASSWORD
              name: postgres-sec
        - name: POSTGRES_DB
          value: keycloak
        image: postgres:12.4-alpine
        imagePullPolicy: IfNotPresent
        name: postgres
        ports:
        - containerPort: 5432
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /var/lib/postgresql/data
          name: postgres-pvc
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
  updateStrategy:
    rollingUpdate:
      partition: 0
    type: RollingUpdate
  volumeClaimTemplates:
  - apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: postgres-pvc
      labels:
        app: postgres
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
      storageClassName: postgres-sc
---
apiVersion: v1
kind: Service
metadata:
  name: postgres-svc
spec:
  ports:
  - port: 5432
    protocol: TCP
    targetPort: 5432
  selector:
    app: postgres

4. Deploy on GKE

Check directory structure

tree postgres

output will look like this.

postgres/
├── postgres-secrets.yml
├── postgres-statefulset.yml
└── storageclass.yml

0 directories, 3 files

Deploy all yaml files

kubectl apply -f storageclass.yml
kubectl apply -f postgres-secrets.yml
kubectl apply -f postgres-statefulset.yml

Deploy Keycloak YAMLs

1. Create secrets for Keycloak

keycloak/keycloak-secrets.yml

apiVersion: v1
kind: Secret
metadata:
  name: keycloak-secrets
type: Opaque
data:
  KEYCLOAK_ADMIN: YWRtaW4K
  KEYCLOAK_ADMIN_PASSWORD: YWRtaW4K

2. Create statefulset and service for Keycloak

keycloak/keycloak-statefulset.yml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app: keyclaok
  name: keycloak
spec:
  podManagementPolicy: Parallel
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: keycloak
  serviceName: keycloak-headless
  template:
    metadata:
      labels:
        app: keycloak
    spec:
      containers:
      - env:
        - name: KEYCLOAK_ADMIN
          valueFrom:
            secretKeyRef:
              key: KEYCLOAK_ADMIN
              name: keycloak-secrets
        - name: KEYCLOAK_ADMIN_PASSWORD
          valueFrom:
            secretKeyRef:
              key: KEYCLOAK_ADMIN_PASSWORD
              name: keycloak-secrets
        - name: DB_VENDOR
          value: postgres
        - name: DB_ADDR
          value: postgres-svc
        - name: DB_PORT
          value: "5432"
        - name: DB_DATABASE
          value: keycloak
        - name: DB_SCHEMA
          value: public
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              key: POSTGRES_USER
              name: postgres-sec
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              key: POSTGRES_PASSWORD
              name: postgres-sec
        image: quay.io/keycloak/keycloak:17.0.0
        args: ["start-dev"]
        imagePullPolicy: IfNotPresent
        name: keycloak
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP
        - containerPort: 8443
          name: https
          protocol: TCP
        resources: {}
        securityContext:
          runAsNonRoot: true
          runAsUser: 1000
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      terminationGracePeriodSeconds: 60
  updateStrategy:
    type: RollingUpdate
---
apiVersion: v1
kind: Service
metadata:
  name: keycloak
  labels:
    app: keycloak
spec:
  ports:
  - name: http
    port: 8080
    targetPort: 8080
  selector:
    app: keycloak
  type: LoadBalancer

3. Deploy Keycloak on Kubernetes

Check directory structure

tree keycloak/

Output will look like this.

├── keycloak-sec.yml
├── keycloak-service.yml
└── keycloak-statefulset.yml

0 directories, 3 files

Deploy the workloads on kubernetes

kubectl apply -f keycloak-sec.yml
kubectl apply -f keycloak-service.yml
kubectl apply -f keycloak-statefulset.yml

4. Keycloak URL

Run the below command to see external-IP of Keycloak

echo "Keycloak_URL  http://$(kubectl get svc keycloak -o go-template='{{(index .status.loadBalancer.ingress 0).ip}}'):8080"

conclusion

So we successfully deployed Keycloak on kubernetes. If you want to migrate form H2 database to postgres database to persist all data.

Refer this blog link.

Written by 

Rahul Soni is a Software Consultant at Knoldus Software. He is always charged up for new things & learnings. He is dedicated to his work and believes in quality output. He loves to take deep dives into cloud technologies & different tools.