Skip to content

Commit

Permalink
Merge pull request #38 from projectsyn/db-backup
Browse files Browse the repository at this point in the history
Add k8up support
  • Loading branch information
megian authored Jul 26, 2021
2 parents ea906ef + db9562d commit e241d98
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 0 deletions.
15 changes: 15 additions & 0 deletions class/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,18 @@ parameters:
host: postgres.example.com
port: 5432

k8up:
enabled: false
keepjobs: 3
repo:
secretName: k8up-repo
password: '?{vaultkv:${cluster:tenant}/${cluster:name}/keycloak/k8up-repo-password}'
s3:
secretName: k8up-s3-credentials
bucket: k8up-${cluster:name}-syn-keycloak
accessKey: '?{vaultkv:${cluster:tenant}/${cluster:name}/keycloak/k8up-s3-accesskey}'
secretKey: '?{vaultkv:${cluster:tenant}/${cluster:name}/keycloak/k8up-s3-secretkey}'

helm_values:
image:
repository: quay.io/keycloak/keycloak
Expand Down Expand Up @@ -211,7 +223,10 @@ parameters:
existingSecret: ${keycloak:database:secretname}
image:
registry: quay.io
# TODO: Rename master to primary when upgrading to Postgres 11 https://github.com/bitnami/charts/commit/7eabc85fd4fae43127228a22829c7ce3fe85c389
master:
annotations:
k8up.syn.tools/backupcommand: sh -c 'PGDATABASE="$POSTGRES_DB" PGUSER="$POSTGRES_USER" PGPASSWORD="$POSTGRES_PASSWORD" pg_dump'
labels: ${keycloak:labels}
volumePermissions:
enabled: ${keycloak:database:tls:enabled}
Expand Down
43 changes: 43 additions & 0 deletions component/main.jsonnet
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// main template for keycloak
local k8up = import 'lib/backup-k8up.libjsonnet';
local kap = import 'lib/kapitan.libjsonnet';
local kube = import 'lib/kube.libjsonnet';
local rl = import 'lib/resource-locker.libjsonnet';
Expand Down Expand Up @@ -122,6 +123,47 @@ local create_ingress_cert_secret =
local create_ingress_cert =
params.ingress.enabled && params.tls.termination == 'passthrough' && params.tls.provider == 'certmanager';

local k8up_repo_secret = kube.Secret(params.k8up.repo.secretName) {
metadata+: {
labels+: params.labels,
},
stringData: {
password: params.k8up.repo.password,
},
};

local k8up_repo_secret_ref = {
key: 'password',
name: k8up_repo_secret.metadata.name,
};

local k8up_s3_secret = kube.Secret(params.k8up.s3.secretName) {
metadata+: {
labels+: params.labels,
},
stringData: {
username: params.k8up.s3.accessKey,
password: params.k8up.s3.secretKey,
},
};

local k8up_s3_secret_ref = {
name: k8up_s3_secret.metadata.name,
accesskeyname: 'username',
secretkeyname: 'password',
};

local k8up_schedule =
k8up.Schedule(
'backup',
'@hourly-random',
keep_jobs=params.k8up.keepjobs,
bucket=params.k8up.s3.bucket,
backupkey=k8up_repo_secret_ref,
s3secret=k8up_s3_secret_ref,
create_bucket=false,
).schedule + k8up.PruneSpec('@daily-random', 30, 20);

// Define outputs below
{
'00_namespace': namespace,
Expand All @@ -132,4 +174,5 @@ local create_ingress_cert =
[if create_keycloak_cert_secret then '13_keycloak_certs']: keycloak_cert_secret,
[if create_ingress_cert_secret then '14_ingress_certs']: ingress_tls_secret,
[if create_ingress_cert then '20_le_cert']: cert_manager_cert,
[if params.k8up.enabled then '30_k8up']: [ k8up_repo_secret, k8up_s3_secret, k8up_schedule ],
}
42 changes: 42 additions & 0 deletions docs/modules/ROOT/pages/explanations/backup.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
= Keycloak Backup

There are two possibilities to backup Keycloak.
The first approach is to backup the database.
The component currently supports backups of the database with https://k8up.io[K8up], if the builtin database is enabled.
The second way is to export all objects via the Keycloak application.
This approach is currently not supported by the component, but may be implemented in the future.

== Database backup

Most of the sources are recommending doing a database backup:

* https://www.keycloak.org/docs/latest/upgrading/#_prep_migration[Handbook]
* https://www.keycloak.org/docs/latest/server_installation/index.html#_backup-cr[Operator]
* https://keycloak.discourse.group/t/best-practice-for-backing-up-the-db/4811[Forum]

The handbook also mentions that configuration, themes, and scripts require a backup.
In the case of a container deployment, those parts are attached to the container and so will usually be part of the deployment.
The component currently doesn't backup anything other than the built-in database.

== Export and import

In theory, using Keycloak's export/import functionality would be the preferred way to implement a backup.
However, the Keycloak documentation documents some downsides to this approach.

The Keycloak handbook has the following to say regarding import/export:

[quote,'Keycloak Handbook, https://www.keycloak.org/docs/latest/server_admin/#_export_import[Export and Import]']
____
It's important to note that because import and export happens at server startup, no other actions should be taken on the server or the database while this happens.
____
Reading this quote, it appears that there's currently no lock preventing parallel access during the export to guarantee consistent exports.

[quote,'Keycloak Handbook, https://www.keycloak.org/docs/latest/server_admin/#admin-console-export-import[Admin console export/import]']
____
Attributes containing secrets or private information will be masked in export file. Export files obtained via Admin Console are thus not appropriate for backups or data transfer between servers. Only boot-time exports are appropriate for that.
____
To create an export suitable for backup purposes, we'd have to create a boot-time export, as other exports don't contain the secrets or other private information.
Therefore we'd have to stop and restart the Keycloak service to create backups, which is undesirable.


Reconsider using this kind of backup in newer versions, once the export functionality might have been improved.
74 changes: 74 additions & 0 deletions docs/modules/ROOT/pages/references/parameters.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,80 @@ default:: `?{vaultkv:${customer:name}/${cluster:name}/${_instance}/server-cert-k
See xref:how-tos/db-tls.adoc[Encrypt database connection] to install Keycloak with encryption.


== `k8up.enabled`

[horizontal]
type:: bool
default:: `false`

Defines whether the K8up database backup is enabled or not.


== `k8up.keepjobs`

[horizontal]
type:: int
default:: `3`

Defines how many backup jobs are kept.
It's useful for debugging to have a few recent completed (or failed) backup jobs available in K8s.
Keeping a lot of jobs may negatively impact the K8s cluster performance however.


== `k8up.repo.secretName`

[horizontal]
type:: string
default:: `k8up-repo`

The name of the secret containing the password for the K8up restic repository.


== `k8up.repo.password`

[horizontal]
type:: string
default:: `?{vaultkv:${cluster:tenant}/${cluster:name}/keycloak/k8up-repo-password}`

Vault reference to the K8up restic repository password.


== `k8up.s3.secretName`

[horizontal]
type:: string
default:: `k8up-s3-credentials`

The name of the secret containing the credentials to access the S3 bucket holding the backups.


== `k8up.s3.bucket`

[horizontal]
type:: string
default:: `k8up-${cluster:name}-syn-keycloak`

The name of the S3 bucket where the backups gets stored.


== `k8up.s3.accessKey`

[horizontal]
type:: string
default:: `?{vaultkv:${cluster:tenant}/${cluster:name}/keycloak/k8up-s3-accesskey}`

S3 access key to the bucket where the backups gets stored.


== `k8up.s3.secretKey`

[horizontal]
type:: string
default:: `?{vaultkv:${cluster:tenant}/${cluster:name}/keycloak/k8up-s3-secretkey}`

S3 secret key to the bucket where the backups gets stored.


== `helm_values`

[horizontal]
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/partials/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
.Explanations
* xref:explanations/default-features.adoc[Default features]
* xref:explanations/backup.adoc[Backup]
.Technical reference
* xref:references/parameters.adoc[Parameters]

0 comments on commit e241d98

Please sign in to comment.