Warning
This article was automatically translated by OpenAI (claude-sonnet-4-20250514).It may be edited eventually, but please be aware that it may contain incorrect information at this time.
Notes on installing Keycloak to Kubernetes using the Helm Chart from https://github.com/codecentric/helm-charts/tree/master/charts/keycloakx.
First, create a Namespace for Keycloak.
kubectl create namespace keycloak
Install PostgreSQL. Here we create a simple StatefulSet for operational verification. In practice, it is recommended to use a Managed PostgreSQL service.
cat <<EOF > postgres.yaml
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: keycloak-db
spec:
serviceName: keycloak-db-headless
selector:
matchLabels:
app: keycloak-db
replicas: 1
template:
metadata:
labels:
app: keycloak-db
spec:
containers:
- name: keycloak-db
image: postgres:17
volumeMounts:
- mountPath: /data
name: cache-volume
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: keycloak-db
key: username
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: keycloak-db
key: password
- name: PGDATA
value: /data/pgdata
- name: POSTGRES_DB
value: keycloak
volumes:
- name: cache-volume
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: keycloak-db-headless
spec:
clusterIP: None
selector:
app: keycloak-db
ports:
- port: 5432
targetPort: 5432
protocol: TCP
name: postgres
---
EOF
Create the PostgreSQL username and password as a Kubernetes Secret, and deploy PostgreSQL.
kubectl create secret generic keycloak-db \
--from-literal=username=testuser \
--from-literal=password=testpassword \
-n keycloak
kubectl apply -f postgres.yaml -n keycloak
Once PostgreSQL is running, install Keycloak with Helm. Create a values file as follows.
cat <<EOF > keycloak-values.yaml
---
args: [ "start" ]
extraEnv: |
- name: KC_BOOTSTRAP_ADMIN_USERNAME
value: admin
- name: KC_BOOTSTRAP_ADMIN_PASSWORD
value: admin
- name: KC_DB_URL
value: jdbc:postgresql://keycloak-db-headless:5432/keycloak
- name: KC_DB_USERNAME
valueFrom:
secretKeyRef:
name: keycloak-db
key: username
- name: KC_DB_PASSWORD
valueFrom:
secretKeyRef:
name: keycloak-db
key: password
- name: KC_HOSTNAME_STRICT
value: "false"
- name: KC_LOG_CONSOLE_OUTPUT
value: json
- name: KC_LOG_CONSOLE_JSON_FORMAT
value: ecs
- name: JAVA_OPTS_APPEND
value: >-
-Djgroups.dns.query={{ include "keycloak.fullname" . }}-headless
database:
vendor: postgres
cache:
stack: jdbc-ping
proxy:
mode: xforwarded
ingress:
enabled: true
annotations:
projectcontour.io/tls-cert-namespace: projectcontour
rules:
- host: keycloak.lan.ik.am
paths:
- path: /
pathType: Prefix
tls:
- hosts:
- keycloak.lan.ik.am
secretName: default-tls
---
EOF
You can check the Helm Chart template with the following command.
helm template -n keycloak keycloakx oci://ghcr.io/codecentric/helm-charts/keycloakx --version 7.1.3 -f keycloak-values.yaml
Install Keycloak with the following command.
helm upgrade --install -n keycloak keycloakx oci://ghcr.io/codecentric/helm-charts/keycloakx --version 7.1.3 -f keycloak-values.yaml --create-namespace --wait
You can check the Keycloak Pod, StatefulSet, and Ingress with the following command.
$ kubectl get pod,sts,ing -n keycloak -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/keycloak-db-0 1/1 Running 0 56m 10.1.173.137 cherry <none> <none>
pod/keycloakx-0 1/1 Running 0 55m 10.1.173.187 cherry <none> <none>
NAME READY AGE CONTAINERS IMAGES
statefulset.apps/keycloak-db 1/1 56m keycloak-db postgres:17
statefulset.apps/keycloakx 1/1 55m keycloak quay.io/keycloak/keycloak:26.3.3
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/keycloakx contour keycloak.lan.ik.am 192.168.11.240 80, 443 55m
When you access the Ingress address with a browser, the Keycloak login screen will be displayed.
