Skip to content
This repository has been archived by the owner on Feb 22, 2022. It is now read-only.

Commit

Permalink
[stable/keycloak] Add option to configure sidecars and misc improveme…
Browse files Browse the repository at this point in the history
…nts (#6090)

* [stable/keycloak] Add option to configure sidecars and misc improvements

* Allow configuring additional containers as sidecars, e. g. for
  a database proxy
* Use `tpl` function for affinity and configure default anti-affinity
* Configure Postgres-specifics only when Postgres is used
* Miscellaneous minor fixes and improvements

* Extend and document 'tpl' function usage

* Bump major version due to breaking changes
  • Loading branch information
unguiculus authored and k8s-ci-robot committed Jun 13, 2018
1 parent 04cb328 commit 8f5c342
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 71 deletions.
13 changes: 9 additions & 4 deletions stable/keycloak/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
name: keycloak
version: 1.2.0
version: 2.0.0
appVersion: 3.4.3.Final
description: Open Source Identity and Access Management For Modern Applications and Services
keywords:
- authentication
home: http://www.keycloak.org/
icon: http://www.keycloak.org/resources/images/keycloak_logo_480x108.png
- sso
- idm
- openid connect
- saml
- kerberos
- ldap
home: https://www.keycloak.org/
icon: https://www.keycloak.org/resources/images/keycloak_logo_480x108.png
sources:
- https://github.com/jboss-dockerfiles/keycloak
maintainers:
Expand Down
122 changes: 86 additions & 36 deletions stable/keycloak/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ $ helm install stable/keycloak

## Introduction

This chart bootstraps a [Keycloak](http://www.keycloak.org/) StatefulSet on a [Kubernetes](https://kubernetes.io) cluster
using the [Helm](https://helm.sh) package manager. It provisions a fully featured Keycloak installation.
This chart bootstraps a [Keycloak](http://www.keycloak.org/) StatefulSet on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. It provisions a fully featured Keycloak installation.
For more information on Keycloak and its capabilities, see its [documentation](http://www.keycloak.org/documentation.html).

## Prerequisites Details
Expand Down Expand Up @@ -42,22 +41,23 @@ The following table lists the configurable parameters of the Keycloak chart and
Parameter | Description | Default
--- | --- | ---
`init.image.repository` | Init image repository | `alpine`
`init.image.tag` | Init image tag | `3.6`
`init.image.tag` | Init image tag | `3.7`
`init.image.pullPolicy` | Init image pull policy | `IfNotPresent`
`keycloak.replicas` | The number of Keycloak replicas | `1`
`keycloak.image.repository` | The Keycloak image repository | `jboss/keycloak`
`keycloak.image.tag` | The Keycloak image tag | `3.4.3.Final`
`keycloak.image.pullPolicy` | The Keycloak image pull policy | `IfNotPresent`
`keycloak.image.pullSecrets`| Specify image pull secrets | `nil` (does not add image pull secrets to deployed pods) |
`keycloak.image.pullSecrets` | Image pull secrets | `[]`
`keycloak.username` | Username for the initial Keycloak admin user | `keycloak`
`keycloak.password` | Password for the initial Keycloak admin user. If not set, a random 10 characters password is created | `""`
`keycloak.extraInitContainers`| Additional init containers, e. g. for providing themes, etc. | `[]`
`keycloak.extraEnv` | Allows the specification of additional environment variables for Keycloak | `[]`
`keycloak.extraVolumeMounts` | Add additional volumes mounts, e. g. for custom themes | `[]`
`keycloak.extraVolumes` | Add additional volumes, e. g. for custom themes | `[]`
`keycloak.extraInitContainers` | Additional init containers, e. g. for providing themes, etc. Passed through the `tpl` funtion and thus to be configured a string | `""`
`keycloak.extraContainers` | Additional sidecar containers, e. g. for a database proxy, such as Google's cloudsql-proxy. Passed through the `tpl` funtion and thus to be configured a string | `""`
`keycloak.extraEnv` | Allows the specification of additional environment variables for Keycloak. Passed through the `tpl` funtion and thus to be configured a string | `""`
`keycloak.extraVolumeMounts` | Add additional volumes mounts, e. g. for custom themes. Passed through the `tpl` funtion and thus to be configured a string | `""`
`keycloak.extraVolumes` | Add additional volumes, e. g. for custom themes. Passed through the `tpl` funtion and thus to be configured a string | `""`
`keycloak.podDisruptionBudget` | Pod disruption budget | `{}`
`keycloak.resources` | Pod resource requests and limits | `{}`
`keycloak.affinity` | Pod affinity | ``
`keycloak.affinity` | Pod affinity. Passed through the `tpl` funtion and thus to be configured a string | `Hard node and soft zone anti-affinity`
`keycloak.nodeSelector` | Node labels for pod assignment | `{}`
`keycloak.tolerations` | Node taints to tolerate | `[]`
`keycloak.securityContext` | Security context for the pod | `{runAsUser: 1000, fsGroup: 1000, runAsNonRoot: true}`
Expand Down Expand Up @@ -90,7 +90,7 @@ Parameter | Description | Default
`keycloak.persistence.dbHost` | The database host name (if `deployPostgres=false`) | `mykeycloak`
`keycloak.persistence.dbPort` | The database host port (if `deployPostgres=false`) | `5432`
`keycloak.persistence.dbUser` |The database user (if `deployPostgres=false`) | `keycloak`
`keycloak.persistence.dbPassword` |The database password (if `deployPostgres=false`) | `keycloak`
`keycloak.persistence.dbPassword` |The database password (if `deployPostgres=false`) | `""`
`postgresql.postgresUser` | The PostgreSQL user (if `keycloak.persistence.deployPostgres=true`) | `keycloak`
`postgresql.postgresPassword` | The PostgreSQL password (if `keycloak.persistence.deployPostgres=true`) | `""`
`postgresql.postgresDatabase` | The PostgreSQL database (if `keycloak.persistence.deployPostgres=true`) | `keycloak`
Expand All @@ -106,17 +106,27 @@ Alternatively, a YAML file that specifies the values for the parameters can be p
$ helm install --name keycloak -f values.yaml stable/keycloak
```

### Usage of the `tpl` Function

The `tpl` function allows us to pass string values from `values.yaml` through the templating engine. It is used for the following values:

* `keycloak.extraInitContainers`
* `keycloak.extraContainers`
* `keycloak.extraEnv`
* `keycloak.affinity`
* `keycloak.extraVolumeMounts`
* `keycloak.extraVolumes`

It is important that these values be configured as strings. Otherwise, installation will fail. See example for Google Cloud Proxy or default affinity configuration in `values.yaml`.

### Database Setup

By default, the [PostgreSQL](https://github.com/kubernetes/charts/tree/master/stable/postgresql) chart is deployed and used as database.
Please refer to this chart for additional PostgreSQL configuration options. If PostgreSQL is disabled, Keycloak uses an embedded H2
database which is only suitable for testing with a single replica.
Please refer to this chart for additional PostgreSQL configuration options. If PostgreSQL is disabled, Keycloak uses an embedded H2 database which is only suitable for testing with a single replica.

#### Using an External Database

The Keycloak Docker image supports PostgreSQL and MySQL. The password for the database user is read from a Kubernetes secret. It
is possible to specify an existing secret that is not managed with this chart. The key in the secret the password is read
from may be specified as well (defaults to `password`).
The Keycloak Docker image supports PostgreSQL and MySQL. The password for the database user is read from a Kubernetes secret. It is possible to specify an existing secret that is not managed with this chart. The key in the secret the password is read from may be specified as well (defaults to `password`).

```yaml
keycloak:
Expand Down Expand Up @@ -159,8 +169,7 @@ keycloak:
### Providing a Custom Theme
One option is certainly to provide a custom Keycloak image that includes the theme. However, if you prefer to stick with the
official Keycloak image, you can use an init container as theme provider.
One option is certainly to provide a custom Keycloak image that includes the theme. However, if you prefer to stick with the official Keycloak image, you can use an init container as theme provider.
Create your own theme and package it up into a Docker image.
Expand All @@ -169,8 +178,7 @@ FROM busybox
COPY my_theme /my_theme
```

In combination with an `emptyDir` that is shared with the Keycloak container, configure an init container that runs
your theme image and copies the theme over to the right place where Keycloak will pick it up automatically.
In combination with an `emptyDir` that is shared with the Keycloak container, configure an init container that runs your theme image and copies the theme over to the right place where Keycloak will pick it up automatically.

```yaml
keycloak:
Expand Down Expand Up @@ -199,49 +207,91 @@ keycloak:
```
### Setting a Custom Realm
A realm can be added by creating a secret or configmap for the realm json file and then supplying this into the chart.
It could be mounted using `extraVolumeMounts` and then specified in `extraArgs` using `-Dimport`.
A realm can be added by creating a secret or configmap for the realm json file and then supplying this into the chart.
It could be mounted using `extraVolumeMounts` and then specified in `extraArgs` using `-Dkeycloak.import`.
First we could create a Secret from a json file using `kubectl create secret generic realm-secret --from-file=realm.json` which we need to reference in `values.yaml`:

```yaml
keycloak:
extraVolumes:
extraVolumes: |
- name: realm-secret
secret:
secretName: realm-secret
extraVolumeMounts:
extraVolumeMounts: |
- name: realm-secret
mountPath: "/realm/"
readOnly: true
extraArgs: -Dkeycloak.import=/realm/realm.json
```

Alternatively, the file could be added to a custom image (set in `keycloak.image`) and then referenced by `-Dimport`.
Alternatively, the file could be added to a custom image (set in `keycloak.image`) and then referenced by `-Dkeycloak.import`.

After startup the web admin console for the realm should be available on the path /auth/admin/\<realm name>/console/.

### Using Google Cloud SQL Proxy

Depending on your environment you may need a local proxy to connect to the database. This is, e. g., the case for Google Kubernetes Engine when using Google Cloud SQL. Create the secret for the credentials as documented [here](https://cloud.google.com/sql/docs/postgres/connect-kubernetes-engine) and configure the proxy as a sidecar.

Because `keycloak.extraContainers` is a string that is passed through the `tpl` function, it is possible to create custom values and use them in the string.

```yaml
# Custom values for Google Cloud SQL
gcloudsql:
project: my-project
region: europe-west1
instance: my-instance
keycloak:
extraContainers: |
- name: cloudsql-proxy
image: gcr.io/cloudsql-docker/gce-proxy:1.11
command:
- /cloud_sql_proxy
args:
- -instances={{ .Values.cloudsql.project }}:{{ .Values.cloudsql.region }}:{{ .Values.cloudsql.instance }}=tcp:5432=tcp:5432
- -credential_file=/secrets/cloudsql/credentials.json
volumeMounts:
- name: cloudsql-creds
mountPath: /secrets/cloudsql
readOnly: true
extraVolumes: |
- name: cloudsql-creds
secret:
secretName: cloudsql-instance-credentials
After startup the web admin console for the realm should be available on the path /auth/admin/\<realm name>/console/
persistence:
deployPostgres: false
dbVendor: POSTGRES
dbName: postgres
dbHost: 127.0.0.1
dbPort: 5432
dbUser: myuser
dbPassword: mypassword
```

### WildFly Configuration

WildFly can be configured via its [command line interface (CLI)](https://docs.jboss.org/author/display/WFLY/Command+Line+Interface).
This chart uses the official Keycloak Docker image and customizes the installation running CLI scripts at server startup.

In order to make further customization easier, the CLI commands are separated by their concerns into smaller scripts.
Everything is in `values.yaml` and can be overridden. Additional CLI commands may be added via `keycloak.cli.custom`,
which is empty by default.
Everything is in `values.yaml` and can be overridden. Additional CLI commands may be added via `keycloak.cli.custom`, which is empty by default.

### High Availability and Clustering

For high availability, Keycloak should be run with multiple replicas (`keycloak.replicas > 1`). WildFly uses Infinispan
for caching. These caches can be replicated across all instances forming a cluster. If `keycloak.replicas > 1`, the
WildFly CLI script `keycloak.cli.discovery` adds JGroups' [JDBC_PING](http://www.jgroups.org/javadoc/org/jgroups/protocols/JDBC_PING.html)
for cluster discovery and Keycloak is started with `--server-config standalone-ha.xml`.
For high availability, Keycloak should be run with multiple replicas (`keycloak.replicas > 1`).
WildFly uses Infinispan for caching. These caches can be replicated across all instances forming a cluster.
If `keycloak.replicas > 1`, the WildFly CLI script `keycloak.cli.discovery` adds JGroups' [JDBC_PING](http://www.jgroups.org/javadoc/org/jgroups/protocols/JDBC_PING.html) for cluster discovery and Keycloak is started with `--server-config standalone-ha.xml`.

## Why StatefulSet?

The chart sets node identifiers to the system property `jboss.node.name` which is in fact the pod name. Node identifiers
must not be longer than 23 characters. This can be problematic because pod names are quite long. We would have to truncate
the chart's fullname to six characters because pods get a 17-character suffix (e. g. `-697f8b7655-mf5ht`). Using a
StatefulSet allows us to truncate to 20 characters leaving room for up to 99 replicas, which is much better.
The chart sets node identifiers to the system property `jboss.node.name` which is in fact the pod name.
Node identifiers must not be longer than 23 characters.
This can be problematic because pod names are quite long.
We would have to truncate the chart's fullname to six characters because pods get a 17-character suffix (e. g. `-697f8b7655-mf5ht`).
Using a StatefulSet allows us to truncate to 20 characters leaving room for up to 99 replicas, which is much better.
Additionally, we get stable values for `jboss.node.name` which can be advantageous for cluster discovery.
18 changes: 12 additions & 6 deletions stable/keycloak/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,26 @@ data:
keycloak.cli: |
embed-server {{- if $highAvailability }} --server-config=standalone-ha.xml{{ end }} --std-out=echo
{{- $cli := .Values.keycloak.cli }}
{{- with .Values.keycloak.cli }}

{{ $cli.nodeIdentifier | indent 4 }}
{{ .nodeIdentifier | indent 4 }}

{{ $cli.logging | indent 4 }}
{{ .logging | indent 4 }}

{{ $cli.reverseProxy | indent 4 }}
{{ .reverseProxy | indent 4 }}

{{- if $highAvailability }}
{{ $cli.discovery | indent 4 }}
{{ .discovery | indent 4 }}
{{- end }}

{{- with $cli.custom }}
{{- if and $highAvailability (eq $.Values.keycloak.persistence.dbVendor "POSTGRES") }}
{{ .postgresql | indent 4 }}
{{- end }}

{{- with .custom }}
{{ . | indent 4 }}
{{- end }}

{{- end }}

stop-embedded-server
5 changes: 2 additions & 3 deletions stable/keycloak/templates/keycloak-secret.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

apiVersion: v1
kind: Secret
metadata:
Expand All @@ -10,8 +9,8 @@ metadata:
heritage: "{{ .Release.Service }}"
type: Opaque
data:
{{- with .Values.keycloak.password }}
password: {{ . | b64enc | quote }}
{{- if .Values.keycloak.password }}
password: {{ .Values.keycloak.password | b64enc | quote }}
{{- else }}
password: {{ randAlphaNum 10 | b64enc | quote }}
{{- end }}
19 changes: 10 additions & 9 deletions stable/keycloak/templates/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,9 @@ spec:
spec:
securityContext:
{{ toYaml .Values.keycloak.securityContext | indent 8 }}
{{- if .Values.keycloak.image.pullSecrets }}
{{- with .Values.keycloak.image.pullSecrets }}
imagePullSecrets:
{{- range .Values.keycloak.image.pullSecrets }}
- name: {{ . }}
{{- end}}
{{ toYaml . | indent 8 }}
{{- end }}
{{- if or .Values.keycloak.persistence.deployPostgres .Values.keycloak.extraInitContainers }}
initContainers:
Expand All @@ -46,7 +44,7 @@ spec:
echo 'PostgreSQL OK ✓'
{{- end }}
{{- if .Values.keycloak.extraInitContainers }}
{{ toYaml .Values.keycloak.extraInitContainers | indent 8 }}
{{ tpl .Values.keycloak.extraInitContainers . | indent 8 }}
{{- end }}
{{- end }}
containers:
Expand Down Expand Up @@ -81,13 +79,13 @@ spec:
{{ include "keycloak.externalDbConfig" . | indent 12 }}
{{- end }}
{{- with .Values.keycloak.extraEnv }}
{{ toYaml . | indent 12 }}
{{ tpl . $ | indent 12 }}
{{- end }}
volumeMounts:
- name: scripts
mountPath: /scripts
{{- with .Values.keycloak.extraVolumeMounts }}
{{ toYaml . | indent 12 }}
{{ tpl . $ | indent 12 }}
{{- end }}
ports:
- name: http
Expand All @@ -107,9 +105,12 @@ spec:
timeoutSeconds: {{ .Values.keycloak.readinessProbe.timeoutSeconds }}
resources:
{{ toYaml .Values.keycloak.resources | indent 12 }}
{{- with .Values.keycloak.extraContainers }}
{{ tpl . $ | indent 8 }}
{{- end }}
{{- with .Values.keycloak.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{ tpl . $ | indent 8 }}
{{- end }}
{{- with .Values.keycloak.nodeSelector }}
nodeSelector:
Expand All @@ -126,5 +127,5 @@ spec:
name: {{ template "keycloak.fullname" . }}
defaultMode: 0555
{{- with .Values.keycloak.extraVolumes }}
{{ toYaml . | indent 8 }}
{{ tpl . $ | indent 8 }}
{{- end }}
Loading

0 comments on commit 8f5c342

Please sign in to comment.