I'm trying to get Helm Keycloak chart to work with Postgres database. I would like my data to persist during the uninstalls. I've created a /mnt/disks/vol1/postgresql mount. When I run this command: helm install keycloak -f keycloak.yaml codecentric/keycloak
Postgres database is created in the mount directory. The problem is, it doesn't save any of the my updated data in Keycloak like adding a new realm, etc. Next time I come back after doing "helm delete keycloak" and installing the chart again, all the data is gone. What am I doing wrong? Here are my files:
keycloak.yaml
init:
image:
repository: busybox
tag: 1.31
pullPolicy: IfNotPresent
resources: {}
# limits:
# cpu: "10m"
# memory: "32Mi"
# requests:
# cpu: "10m"
# memory: "32Mi"
clusterDomain: cluster.local
## Optionally override the fully qualified name
# fullnameOverride: keycloak
## Optionally override the name
# nameOverride: keycloak
keycloak:
replicas: 1
image:
repository: jboss/keycloak
tag: 8.0.1
pullPolicy: IfNotPresent
## Optionally specify an array of imagePullSecrets.
## Secrets must be manually created in the namespace.
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
##
pullSecrets: []
# - myRegistrKeySecretName
hostAliases: []
# - ip: "1.2.3.4"
# hostnames:
# - "my.host.com"
proxyAddressForwarding: true
enableServiceLinks: false
podManagementPolicy: Parallel
restartPolicy: Always
serviceAccount:
# Specifies whether a service account should be created
create: false
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name:
securityContext:
fsGroup: 1000
containerSecurityContext:
runAsUser: 1000
runAsNonRoot: true
## The path keycloak will be served from. To serve keycloak from the root path, use two quotes (e.g. "").
basepath: "auth"
## Additional sidecar containers, e. g. for a database proxy, such as Google's cloudsql-proxy
extraContainers: |
## lifecycleHooks defines the container lifecycle hooks
lifecycleHooks: |
# postStart:
# exec:
# command: ["/bin/sh", "-c", "ls"]
## Override the default for the Keycloak container, e.g. for clusters with large cache that requires rebalancing.
terminationGracePeriodSeconds: 60
## Additional arguments to start command e.g. -Dkeycloak.import= to load a realm
extraArgs: ""
## Username for the initial Keycloak admin user
username: admin
## Password for the initial Keycloak admin user. Applicable only if existingSecret is not set.
## If not set, a random 10 characters password will be used
password: "aaaa"
# Specifies an existing secret to be used for the admin password
existingSecret: ""
# The key in the existing secret that stores the password
existingSecretKey: password
## jGroups configuration (only for HA deployment)
jgroups:
discoveryProtocol: dns.DNS_PING
discoveryProperties: >
"dns_query={{ template "keycloak.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}"
javaToolOptions: >-
-XX:+UseContainerSupport
-XX:MaxRAMPercentage=50.0
## Allows the specification of additional environment variables for Keycloak
extraEnv: |
- name: KEYCLOAK_LOGLEVEL
value: DEBUG
# - name: WILDFLY_LOGLEVEL
# value: DEBUG
# - name: CACHE_OWNERS
# value: "2"
# - name: DB_QUERY_TIMEOUT
# value: "60"
# - name: DB_VALIDATE_ON_MATCH
# value: true
# - name: DB_USE_CAST_FAIL
# value: false
affinity: |
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
{{- include "keycloak.selectorLabels" . | nindent 10 }}
matchExpressions:
- key: role
operator: NotIn
values:
- test
topologyKey: kubernetes.io/hostname
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
{{- include "keycloak.selectorLabels" . | nindent 12 }}
matchExpressions:
- key: role
operator: NotIn
values:
- test
topologyKey: failure-domain.beta.kubernetes.io/zone
nodeSelector: {}
priorityClassName: ""
tolerations: []
## Additional pod labels
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
podLabels: {}
## Extra Annotations to be added to pod
podAnnotations: {}
livenessProbe: |
httpGet:
path: {{ if ne .Values.keycloak.basepath "" }}/{{ .Values.keycloak.basepath }}{{ end }}/
port: http
initialDelaySeconds: 300
timeoutSeconds: 5
readinessProbe: |
httpGet:
path: {{ if ne .Values.keycloak.basepath "" }}/{{ .Values.keycloak.basepath }}{{ end }}/realms/master
port: http
initialDelaySeconds: 30
timeoutSeconds: 1
resources: {}
# limits:
# cpu: "100m"
# memory: "1024Mi"
# requests:
# cpu: "100m"
# memory: "1024Mi"
## WildFly CLI configurations. They all end up in the file 'keycloak.cli' configured in the configmap which is
## executed on server startup.
cli:
enabled: true
nodeIdentifier: |
{{ .Files.Get "scripts/node-identifier.cli" }}
logging: |
{{ .Files.Get "scripts/logging.cli" }}
ha: |
{{ .Files.Get "scripts/ha.cli" }}
datasource: |
{{ .Files.Get "scripts/datasource.cli" }}
# Custom CLI script
custom: |
## Custom startup scripts to run before Keycloak starts up
startupScripts: {}
# mystartup.sh: |
# #!/bin/sh
#
# echo 'Hello from my custom startup script!'
## Additional init containers, e. g. for providing custom themes
extraInitContainers: |
## Add additional volumes and mounts, e. g. for custom themes
extraVolumeMounts: |
- name: theme
mountPath: /opt/jboss/keycloak/themes/
subPath: kcthemes
extraVolumes: |
- name: theme
persistentVolumeClaim:
claimName: keycloak-pv-claim
## Add additional ports, eg. for custom admin console
extraPorts: |
podDisruptionBudget: {}
# maxUnavailable: 1
# minAvailable: 1
service:
annotations: {}
# service.beta.kubernetes.io/aws-load-balancer-internal: "0.0.0.0/0"
labels: {}
# key: value
## ServiceType
## ref: https://kubernetes.io/docs/user-guide/services/#publishing-services---service-types
type: ClusterIP
## Optional static port assignment for service type NodePort.
# nodePort: 30000
httpPort: 8080
httpNodePort: ""
httpsPort: 8443
httpsNodePort: ""
# Optional: jGroups port for high availability clustering
jgroupsPort: 7600
## Ingress configuration.
## ref: https://kubernetes.io/docs/user-guide/ingress/
ingress:
enabled: true
path: /
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
# ingress.kubernetes.io/affinity: cookie
labels: {}
# key: value
## List of hosts for the ingress
hosts:
- localhost
## TLS configuration
tls:
- hosts:
- localhost
secretName: keycloak-secret
## OpenShift route configuration.
## ref: https://docs.openshift.com/container-platform/3.11/architecture/networking/routes.html
route:
enabled: false
path: /
annotations: {}
# kubernetes.io/tls-acme: "true"
# haproxy.router.openshift.io/disable_cookies: "true"
# haproxy.router.openshift.io/balance: roundrobin
labels: {}
# key: value
# Host name for the route
host:
# TLS configuration
tls:
enabled: true
insecureEdgeTerminationPolicy: Redirect
termination: edge
## Persistence configuration
persistence:
# If true, the Postgres chart is deployed
deployPostgres: true
# The database vendor. Can be either "postgres", "mysql", "mariadb", or "h2"
dbVendor: postgres
## The following values only apply if "deployPostgres" is set to "false"
dbName: keycloak
dbHost: keycloak-postgresql
dbPort: 5432
## Database Credentials are loaded from a Secret residing in the same Namespace as keycloak.
## The Chart can read credentials from an existing Secret OR it can provision its own Secret.
## Specify existing Secret
# If set, specifies the Name of an existing Secret to read db credentials from.
existingSecret: ""
existingSecretPasswordKey: "" # read keycloak db password from existingSecret under this Key
existingSecretUsernameKey: "" # read keycloak db user from existingSecret under this Key
## Provision new Secret
# Only used if existingSecret is not specified. In this case a new secret is created
# populated by the variables below.
dbUser: KcSuperUser
dbPassword: KcSuperPass
postgresql:
image:
tag: 12
### PostgreSQL User to create.
##
postgresqlUsername: "KcSuperUser"
## PostgreSQL Password for the new user.
## If not set, a random 10 characters password will be used.
##
postgresqlPassword: "KcSuperPassword"
## PostgreSQL Database to create.
##
postgresqlDatabase: keycloak
## Persistent Volume Storage configuration.
## ref: https://kubernetes.io/docs/user-guide/persistent-volumes
##
persistence:
## Enable PostgreSQL persistence using Persistent Volume Claims.
##
enabled: true
exitingClaim: "pdata-keycloak-postgresql-0"
mountPath: /var/lib/postgresql/data
classes:
- name: postgres # Defines name of storage class.
# Path on the host where local volumes of this storage class are mounted
# under.
#hostDir: /mnt/fast-disks
# Optionally specify mount path of local volumes. By default, we use same
# path as hostDir in container.
mountDir: /mnt/disks/vol1/postgresdata
# The volume mode of created PersistentVolume object. Default to Filesystem
# if not specified.
volumeMode: Filesystem
# Filesystem type to mount.
# It applies only when the source path is a block device,
# and desire volume mode is Filesystem.
# Must be a filesystem type supported by the host operating system.
fsType: ext4
blockCleanerCommand:
# Do a quick reset of the block device during its cleanup.
# - "/scripts/quick_reset.sh"
# or use dd to zero out block dev in two iterations by uncommenting these lines
# - "/scripts/dd_zero.sh"
# - "2"
# or run shred utility for 2 iteration.s
- "/scripts/shred.sh"
- "2"
# or blkdiscard utility by uncommenting the line below.
# - "/scripts/blkdiscard.sh"
# Uncomment to create storage class object with default configuration.
# storageClass: true
# Uncomment to create storage class object and configure it.
# storageClass:
test:
enabled: true
image:
repository: unguiculus/docker-python3-phantomjs-selenium
tag: v1
pullPolicy: IfNotPresent
securityContext:
fsGroup: 1000
containerSecurityContext:
runAsUser: 1000
runAsNonRoot: true
prometheus:
operator:
## Are you using Prometheus Operator?
enabled: false
serviceMonitor:
## Optionally set a target namespace in which to deploy serviceMonitor
namespace: ""
## Additional labels to add to the ServiceMonitor so it is picked up by the operator.
## If using the [Helm Chart](https://github.com/helm/charts/tree/master/stable/prometheus-operator) this is the name of the Helm release.
selector:
release: prometheus
## Interval at which Prometheus scrapes metrics
interval: 10s
## Timeout at which Prometheus timeouts scrape run
scrapeTimeout: 10s
## The path to scrape
path: /auth/realms/master/metrics
prometheusRules:
## Add Prometheus Rules?
enabled: false
## Additional labels to add to the PrometheusRule so it is picked up by the operator.
## If using the [Helm Chart](https://github.com/helm/charts/tree/master/stable/prometheus-operator) this is the name of the Helm release and 'app: prometheus-operator'
selector:
app: prometheus-operator
release: prometheus
## Some example rules.
rules: {}
# - alert: keycloak-IngressHigh5xxRate
# annotations:
# message: The percentage of 5xx errors for keycloak over the last 5 minutes is over 1%.
# expr: (sum(rate(nginx_ingress_controller_response_duration_seconds_count{exported_namespace="mynamespace",ingress="mynamespace-keycloak",status=~"5[0-9]{2}"}[1m]))/sum(rate(nginx_ingress_controller_response_duration_seconds_count{exported_namespace="mynamespace",ingress="mynamespace-keycloak"}[1m])))*100 > 1
# for: 5m
# labels:
# severity: warning
# - alert: keycloak-IngressHigh5xxRate
# annotations:
# message: The percentage of 5xx errors for keycloak over the last 5 minutes is over 5%.
# expr: (sum(rate(nginx_ingress_controller_response_duration_seconds_count{exported_namespace="mynamespace",ingress="mynamespace-keycloak",status=~"5[0-9]{2}"}[1m]))/sum(rate(nginx_ingress_controller_response_duration_seconds_count{exported_namespace="mynamespace",ingress="mynamespace-keycloak"}[1m])))*100 > 5
# for: 5m
# labels:
# severity: critical
Volume
kind: PersistentVolume
apiVersion: v1
metadata:
name: keycloak-postgres-volume
labels:
app: postgres
type: local
spec:
storageClassName: postgres
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/disks/vol1/postgresdata"
Claim:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: data-keycloak-postgresql-0
labels:
app: postgres
spec:
storageClassName: postgres
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
Storage
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: postgres
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer