keycloakx 차트를 7.2.2에서 7.3.0으로 업그레이드한다
breaking_change_check 결과 breaking=false — custom-values.yaml이 실제로 쓰는 키 (image, http.relativePath, command, ingress, proxy, resources, database, extraEnv) 중 어느 것도 diff에 걸리지 않았다. 유일한 템플릿 변경(probe 경로가 managementRelativePath를 coalesce로 우선하도록 바뀜)도 relativePath: "/" 를 그대로 쓰므로 동작 영향이 없다. CRD·의존성 변경 없음. appVersion은 26.6.4→26.7.2로 오르지만 custom-values.yaml이 자체 빌드 이미지 태그(26.7.1-bci15.7-hardened)를 명시적으로 고정하므로 이 업그레이드로 실제 배포 버전이 바뀌지는 않는다 — 26.7.2로 올리려면 hardened-containers에서 별도로 자체 빌드해야 한다. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
[bumpversion]
|
||||
current_version = 7.0.0
|
||||
commit = true
|
||||
tag = false
|
||||
message = Bump keycloakx chart version: {current_version} → {new_version}
|
||||
|
||||
[bumpversion:file:Chart.yaml]
|
||||
@@ -0,0 +1,25 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
ci/
|
||||
examples/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
@@ -0,0 +1,88 @@
|
||||
# keycloakx 버전 갱신 가이드
|
||||
|
||||
## 1. git 작업 환경 구성
|
||||
|
||||
- DIP 카탈로그 git 다운로드
|
||||
```
|
||||
$ git clone https://github.com/paasup/dip-catalog.git
|
||||
```
|
||||
|
||||
- 작업 브랜치로 체크아웃
|
||||
```
|
||||
$ git checkout -b update-keycloakx/7.3.0
|
||||
```
|
||||
|
||||
## 2. helm chart 업데이트
|
||||
|
||||
#### * 배경 — 왜 keycloakx인가 (이슈 #1)
|
||||
|
||||
기존 `manifests/helm/keycloak/` 는 codecentric의 구버전 WildFly 기반 `keycloak` 차트(17.0.1-legacy)였고, bitnami postgresql 서브차트를 조건부 의존성으로 포함하고 있었다(bitnami 무료 배포 정책 변경으로 문제가 된 지점). codecentric은 17.0.1 이후 이 WildFly 차트를 더 이상 업데이트하지 않고, Quarkus 기반 Keycloak(17+)용으로 새 차트 `keycloakx`를 별도로 제공한다. `keycloakx`는 서브차트 의존성이 전혀 없어(`Chart.yaml`에 dependencies 없음) bitnami 의존 문제가 근본적으로 해소된다 — 그래서 `keycloak` 대신 `keycloakx`로 신규 등록한다. 기존 `manifests/helm/keycloak/18.4.0/` 는 같은 PR에서 제거한다(실제 소비자 없음, 문서 예시 표 한 줄 외 참조 없음).
|
||||
|
||||
### 1) 차트 버전 변경
|
||||
|
||||
- BUILD-README.md, CUSTOM-README.md, custom-values.yaml을 제외한 파일 삭제.
|
||||
``` sh
|
||||
# chart 디렉토리로 이동
|
||||
cd manifests/helm/keycloakx/7.3.0
|
||||
|
||||
# 파일 삭제 전 삭제할 파일 목록 확인
|
||||
find . -mindepth 1 \( -name "CUSTOM-README.md" -o -name "BUILD-README.md" -o -name "custom-values.yaml" \) -prune -o -print
|
||||
|
||||
# 파일 삭제
|
||||
find . -mindepth 1 \( -name "CUSTOM-README.md" -o -name "BUILD-README.md" -o -name "custom-values.yaml" \) -prune -o -exec rm -rf {} +
|
||||
```
|
||||
|
||||
- codecentric/keycloakx 차트 다운로드
|
||||
``` sh
|
||||
# manifests/helm 디렉토리로 이동
|
||||
cd manifests/helm
|
||||
|
||||
# helm repo 추가
|
||||
helm repo add codecentric https://codecentric.github.io/helm-charts
|
||||
helm repo update
|
||||
|
||||
# helm 차트 pull
|
||||
helm pull codecentric/keycloakx --version="7.3.0" --untar --untardir /tmp/keycloakx-pull
|
||||
|
||||
# 새 버전 디렉토리로 복사
|
||||
mkdir -p keycloakx/7.3.0
|
||||
cp -R /tmp/keycloakx-pull/keycloakx/. keycloakx/7.3.0/
|
||||
rm -rf /tmp/keycloakx-pull
|
||||
```
|
||||
|
||||
## 3. git push 및 tag 추가
|
||||
|
||||
- 갱신작업 진행 후 commit
|
||||
```
|
||||
$ git add .
|
||||
$ git commit -m "add keycloakx/7.3.0 (이슈 #1 대응, keycloak/18.4.0 대체)"
|
||||
```
|
||||
|
||||
- main 브랜치에 체크아웃 후 merge
|
||||
```
|
||||
$ git checkout main
|
||||
$ git merge update-keycloakx/7.3.0
|
||||
```
|
||||
|
||||
- git에 push 후 작업 브랜치 삭제
|
||||
```
|
||||
$ git push -u origin main
|
||||
$ git branch -d update-keycloakx/7.3.0
|
||||
```
|
||||
|
||||
- git tag 추가 후 push
|
||||
```
|
||||
$ git tag keycloakx/7.3.0
|
||||
$ git push origin keycloakx/7.3.0
|
||||
```
|
||||
|
||||
## 4. 차트 버전 정보
|
||||
|
||||
- keycloakx/7.3.0 (appVersion 26.7.2)
|
||||
- `manifests/helm/keycloak/18.4.0`(codecentric 구버전 WildFly 기반, bitnami postgresql 서브차트 포함) 대체. 신규 등록.
|
||||
- 서브차트 의존성 없음(`Chart.yaml`에 dependencies 없음).
|
||||
- 서비스 배포를 위하여 custom-values.yaml에 정의하였다.
|
||||
- **주의 1**: 이 차트의 `http.relativePath` 기본값은 `"/auth"`(구 WildFly Keycloak 호환용)다. `custom-values.yaml`에서 `"/"`로 반드시 오버라이드해야 한다 — 그대로 두면 OIDC issuer/admin API 경로가 소비자 앱들의 가정(경로 접미사 없음)과 어긋난다.
|
||||
- **주의 2**: `command`/`args` 기본값이 둘 다 빈 배열이라, 지정하지 않으면 컨테이너가 인자 없는 `kc.sh`(도움말 출력, exit 0)로 끝나 CrashLoopBackOff가 된다. `custom-values.yaml`의 `command: ["/opt/keycloak/bin/kc.sh", "start"]`를 유지해야 한다.
|
||||
- **주의 3**: `extraEnv`에 `KC_HOSTNAME`을 반드시 지정해야 한다 — 미지정 시 hostname-strict 검증(기본 true)으로 `hostname is not configured` 에러가 나며 기동이 실패한다.
|
||||
- 세 항목 모두 dev 클러스터 격리 네임스페이스 실배포 테스트로 확인했다(admin 부트스트랩 로그, DB 연결, realm/client 생성 REST API 호출까지 성공).
|
||||
@@ -0,0 +1,183 @@
|
||||
# Upgrade History
|
||||
|
||||
## 7.2.2 → 7.3.0
|
||||
### 변경 요약
|
||||
- from_version: 7.2.2
|
||||
- to_version: 7.3.0
|
||||
- Chart `keycloakx` 7.2.2 → 7.3.0 업데이트
|
||||
- Values: +4 / -0 / ~6 / type~0
|
||||
- Templates: +0 / -0
|
||||
- Dependencies: +0 / -0 / ~0
|
||||
|
||||
### custom-values.yaml 수정 필요 항목
|
||||
없음
|
||||
|
||||
### 참고
|
||||
- severity: warning
|
||||
- breaking: false
|
||||
|
||||
# keycloakx 배포
|
||||
|
||||
## 1. 배포 방법
|
||||
|
||||
### 1) 배포 시 주의 사항
|
||||
|
||||
- keycloakx를 배포하려면 외부 postgresql이 필요하다(이 차트는 내장 DB를 지원하지 않는다 — 서브차트 의존성 없음).
|
||||
- `custom-values.yaml`의 `database.*` 를 배포된 DB 정보로 변경한다.
|
||||
- **`http.relativePath: "/"` 를 지우거나 값을 바꾸지 말 것.** 이 차트의 기본값은 구버전 WildFly Keycloak 호환을 위한 `"/auth"`다. `"/"`로 명시하지 않으면 Quarkus 네이티브 경로 규칙과 달라져, OIDC issuer URL(`/realms/{realm}`)이나 admin REST API(`/admin/realms/...`)를 경로 접미사 없이 호출하는 소비 앱들의 연동이 조용히 깨진다.
|
||||
- **`command`를 반드시 지정할 것.** 차트 기본값(`command: []`, `args: []`)만으로는 컨테이너가 인자 없는 `kc.sh`(도움말 출력, exit 0)로 끝나 CrashLoopBackOff가 된다(실측 확인). `custom-values.yaml`의 `command: ["/opt/keycloak/bin/kc.sh", "start"]`를 유지한다.
|
||||
- **`extraEnv`에 `KC_HOSTNAME`을 반드시 지정할 것.** 미지정 시 `hostname is not configured; either configure hostname, or set hostname-strict to false`로 기동이 실패한다(실측 확인, hostname-strict 기본값 true).
|
||||
- **이미지는 업스트림이 아니라 자체 빌드 하드닝 이미지다** — 아래 "3. 자체 빌드 이미지" 참조. `kcadm.sh`/`kcreg.sh`(`bin/client`)가 들어 있지 않다.
|
||||
|
||||
### 2) 배포 방법
|
||||
|
||||
``` sh
|
||||
git clone https://github.com/paasup/dip-catalog.git
|
||||
cd manifests/helm/keycloakx/7.3.0
|
||||
helm upgrade keycloak ./ -f custom-values.yaml --install -n platform --create-namespace
|
||||
```
|
||||
|
||||
## 2. custom-values.yaml 설명
|
||||
|
||||
### 1) pod 설정
|
||||
|
||||
| Name | 설명 | 기본값 |
|
||||
| --- | --- | --- |
|
||||
| `image.repository`/`image.tag` | **자체 빌드 하드닝 이미지**(아래 3절). 오프라인 설치 시에는 사설 미러 레지스트리로 변경. | `custom-values.yaml 참조` |
|
||||
| `resources` | keycloak pod의 자원 설정. | `custom-values.yaml 참조` |
|
||||
|
||||
### 2) Postgresql 연동 설정
|
||||
|
||||
`database.*` 구조화 필드를 사용한다(구버전 `keycloak` 차트의 `DB_VENDOR`/`DB_ADDR` 같은 extraEnv 방식이 아니다).
|
||||
|
||||
``` yaml
|
||||
database:
|
||||
vendor: postgres
|
||||
hostname: keycloak-postgresql # 배포된 DB 서비스명으로 변경
|
||||
port: 5432
|
||||
database: keycloak
|
||||
username: keycloak
|
||||
existingSecret: keycloak-db # kubernetes.io/basic-auth 시크릿 이름
|
||||
existingSecretKey: password # 시크릿 안의 비밀번호 키 (기본값 "password")
|
||||
|
||||
extraEnv: |
|
||||
- name: KC_HOSTNAME # 필수 — 미지정 시 hostname-strict 검증으로 기동 실패
|
||||
value: keycloak.example.org
|
||||
- name: KC_DB_SCHEMA # public 이 아닌 전용 스키마를 쓸 때 지정
|
||||
value: keycloak
|
||||
- name: KC_BOOTSTRAP_ADMIN_USERNAME
|
||||
value: admin
|
||||
- name: KC_BOOTSTRAP_ADMIN_PASSWORD
|
||||
value: ChangeMe1234! # 예시 값 — 배포 전 교체한다
|
||||
- name: TZ
|
||||
value: Asia/Seoul
|
||||
```
|
||||
|
||||
- `existingSecret`으로 지정한 시크릿은 미리 생성해야 한다(이 차트는 시크릿을 만들어주지 않고 참조만 한다):
|
||||
``` sh
|
||||
kubectl create secret generic keycloak-db \
|
||||
--type=kubernetes.io/basic-auth \
|
||||
--from-literal=username=keycloak \
|
||||
--from-literal=password=<비밀번호> \
|
||||
-n platform
|
||||
```
|
||||
- `KC_BOOTSTRAP_ADMIN_USERNAME`/`KC_BOOTSTRAP_ADMIN_PASSWORD`(Keycloak 25+ 표준 부트스트랩 메커니즘)는 **master realm이 완전히 비어있는 최초 부팅에만** admin 계정을 생성한다. 재설치·재기동 시 비밀번호를 바꿔주지 않는다 — 정상 동작이다.
|
||||
|
||||
### 3) Ingress 설정
|
||||
|
||||
#### 3.1) tls 시크릿 직접 생성
|
||||
|
||||
``` yaml
|
||||
ingress:
|
||||
enabled: true
|
||||
ingressClassName: apisix # 사용하는 ingress controller 클래스로 변경
|
||||
rules:
|
||||
- host: keycloak.example.org # keycloak에서 사용할 도메인으로 변경
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
tls:
|
||||
- hosts:
|
||||
- keycloak.example.org # keycloak에서 사용할 도메인으로 변경
|
||||
secretName: keycloak-tls
|
||||
```
|
||||
|
||||
인증서를 secret으로 직접 제공하는 경우:
|
||||
|
||||
``` sh
|
||||
kubectl create secret tls keycloak-tls --cert=<path-to-cert-file> --key=<path-to-key-file> -n <namespace>
|
||||
```
|
||||
|
||||
#### 3.2) cert-manager를 이용한 자동 생성
|
||||
|
||||
`custom-values.yaml`의 `ingress.annotations.cert-manager.io/cluster-issuer`를 미리 배포된 ClusterIssuer 이름으로 변경한다.
|
||||
|
||||
``` yaml
|
||||
ingress:
|
||||
enabled: true
|
||||
ingressClassName: apisix
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: "root-ca-issuer"
|
||||
rules:
|
||||
- host: keycloak.example.org
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
tls:
|
||||
- hosts:
|
||||
- keycloak.example.org
|
||||
secretName: keycloak-tls
|
||||
```
|
||||
|
||||
### 4) Proxy 설정
|
||||
|
||||
ingress/리버스 프록시 뒤에 배포하는 표준 구성:
|
||||
|
||||
``` yaml
|
||||
proxy:
|
||||
enabled: true
|
||||
mode: forwarded
|
||||
```
|
||||
|
||||
## 3. 자체 빌드 이미지
|
||||
|
||||
`image.repository`/`image.tag` 는 업스트림 `quay.io/keycloak/keycloak` 이 아니라
|
||||
`docker.io/paasup/keycloak` 자체 빌드 하드닝 이미지를 가리킨다. 빌드 정의와, 왜 자체
|
||||
빌드인지·업스트림과 무엇이 다른지는 별도 레포 `hardened-containers` 의 `images/keycloak/`
|
||||
(`README.md` 포함)가 단일 출처다 — 이 레포에는 없다. 배포 관점에서 알아야 할 것만
|
||||
아래에 적는다.
|
||||
|
||||
### 앱 버전이 차트 `appVersion` 과 다르다
|
||||
|
||||
차트(7.3.0) `appVersion` 은 `26.7.2` 지만 이미지는 **Keycloak 26.7.1** 이다.
|
||||
|
||||
- `appVersion` 은 `image.tag` 미지정 시의 기본값일 뿐이고, `custom-values.yaml` 이
|
||||
태그를 명시하므로 실제 배포 버전은 26.7.1 이다.
|
||||
- 7.2.2 시절에는 차트 `appVersion`(26.6.4)이 우리가 쓰는 26.7.1보다 뒤처져 있었다.
|
||||
7.3.0(`appVersion` 26.7.2)로 올라오며 이제 반대로 차트 기본값이 우리 배포판보다
|
||||
한 패치 앞선다 — 26.7.2로 올리려면 `hardened-containers`에서 그 버전을 새로 자체
|
||||
빌드해야 한다("이미지 갱신" 절 참고). 차트 업그레이드 자체는 이미지 버전과 무관하게
|
||||
적용 가능했다(breaking=false, 아래 "Upgrade History" 참고).
|
||||
- 26.6.4 를 쓰지 않는 이유: 26.7.1(및 26.6.5)에서만 패치된 `keycloak-services`
|
||||
HIGH 5건(CVE-2026-16102 / 16442 / 16443 / 15572 / 15573)에 취약하다.
|
||||
|
||||
### 업스트림 이미지와의 차이 — `kcadm.sh`/`kcreg.sh` 없음
|
||||
|
||||
`/opt/keycloak/bin/client/` 를 제거했다. 이 디렉토리의 `keycloak-admin-cli-*.jar` 가
|
||||
취약한 jackson 을 shade 로 품은 uber-jar 라 교체가 불가능해서다. **서버 런타임은 이
|
||||
디렉토리를 쓰지 않으므로 배포 동작에는 영향이 없다.**
|
||||
|
||||
파드에 exec 해서 `kcadm.sh` 를 쓰던 절차가 있다면 대안이 필요하다.
|
||||
|
||||
- 권장: admin REST API 직접 호출 (`/admin/realms/...`, 토큰은
|
||||
`/realms/master/protocol/openid-connect/token` 에서 발급)
|
||||
- 또는 업스트림 이미지(`quay.io/keycloak/keycloak:26.7.1`)를 일회성 잡/디버그
|
||||
컨테이너로 띄워 `kcadm.sh` 만 쓴다 (서버로 쓰지 않는다)
|
||||
|
||||
### 이미지 갱신
|
||||
|
||||
`hardened-containers` 레포의 `images/keycloak/suse.build.env` 의 `KEYCLOAK_VERSION` 과
|
||||
jar 오버레이 버전을 사람이 고쳐 커밋하는 것이 갱신 트리거다(그 레포에서). 그 레포의
|
||||
`build-image.yml` 이 빌드·게이트 통과 후 push 하면 `published.json` 이 갱신되고,
|
||||
이 카탈로그의 `catalog-tag-update.yml` 이 그것을 읽어가 이 파일의 `image.tag` 를
|
||||
자동 갱신한 브랜치를 이 레포에 만든다.
|
||||
@@ -0,0 +1,24 @@
|
||||
apiVersion: v2
|
||||
appVersion: 26.7.2
|
||||
description: Keycloak.X - Open Source Identity and Access Management for Modern Applications
|
||||
and Services
|
||||
home: https://www.keycloak.org/
|
||||
icon: https://www.keycloak.org/resources/images/keycloak_logo_200px.svg
|
||||
keywords:
|
||||
- sso
|
||||
- idm
|
||||
- openid connect
|
||||
- saml
|
||||
- kerberos
|
||||
- oauth
|
||||
- ldap
|
||||
- keycloakx
|
||||
- quarkus
|
||||
maintainers:
|
||||
- email: thomas.darimont+github@gmail.com
|
||||
name: thomasdarimont
|
||||
name: keycloakx
|
||||
sources:
|
||||
- https://github.com/codecentric/helm-charts
|
||||
- https://github.com/keycloak/keycloak/tree/main/quarkus/container
|
||||
version: 7.3.0
|
||||
@@ -0,0 +1,4 @@
|
||||
approvers:
|
||||
- thomasdarimont
|
||||
reviewers:
|
||||
- thomasdarimont
|
||||
@@ -0,0 +1,694 @@
|
||||
# Keycloak-X
|
||||
|
||||
[Keycloak-X](http://www.keycloak.org/) is an open source identity and access management for modern applications and services.
|
||||
|
||||
Note that this chart is the logical successor of the Wildfly based [codecentric/keycloak](https://github.com/codecentric/helm-charts/tree/master/charts/keycloak) chart.
|
||||
|
||||
## TL;DR;
|
||||
|
||||
```console
|
||||
$ cat << EOF > values.yaml
|
||||
command:
|
||||
- "/opt/keycloak/bin/kc.sh"
|
||||
- "start"
|
||||
- "--http-port=8080"
|
||||
- "--hostname-strict=false"
|
||||
extraEnv: |
|
||||
- name: KEYCLOAK_ADMIN
|
||||
value: admin
|
||||
- name: KEYCLOAK_ADMIN_PASSWORD
|
||||
value: admin
|
||||
- name: JAVA_OPTS_APPEND
|
||||
value: >-
|
||||
-Djgroups.dns.query={{ include "keycloak.fullname" . }}-headless
|
||||
EOF
|
||||
|
||||
$ helm install keycloak codecentric/keycloakx --values ./values.yaml
|
||||
```
|
||||
Note that the default configuration is not suitable for production since it uses a h2 file database by default.
|
||||
It is strongly recommended to use a dedicated database with Keycloak.
|
||||
|
||||
For more examples see the [examples](./examples) folder.
|
||||
|
||||
## 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.
|
||||
For more information on Keycloak and its capabilities, see its [documentation](http://www.keycloak.org/documentation.html).
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
To install the chart with the release name `keycloakx`:
|
||||
|
||||
```console
|
||||
$ helm install keycloak codecentric/keycloakx
|
||||
```
|
||||
|
||||
or via GitHub Container Registry:
|
||||
|
||||
```console
|
||||
$ helm install keycloak oci://ghcr.io/codecentric/helm-charts/keycloakx --version <version>
|
||||
```
|
||||
|
||||
## Uninstalling the Chart
|
||||
|
||||
To uninstall the `keycloakx` deployment:
|
||||
|
||||
```console
|
||||
$ helm uninstall keycloakx
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The following table lists the configurable parameters of the Keycloak-X chart and their default values.
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `fullnameOverride` | Optionally override the fully qualified name | `""` |
|
||||
| `nameOverride` | Optionally override the name | `""` |
|
||||
| `namespaceOverride` | Optionally override the namespace for all resources. Useful for umbrella charts that deploy multiple aliased keycloak instances each into their own namespace. | `""` |
|
||||
| `replicas` | The number of replicas to create | `1` |
|
||||
| `commonLabels` | Additional labels applied to every resource in this chart, and on the StatefulSet's pods | `{}` |
|
||||
| `image.repository` | The Keycloak image repository | `quay.io/keycloak/keycloak` |
|
||||
| `image.tag` | Overrides the Keycloak image tag whose default is the chart version | `""` |
|
||||
| `image.digest` | Overrides the Keycloak image tag with a digest | `""` |
|
||||
| `image.pullPolicy` | The Keycloak image pull policy | `IfNotPresent` |
|
||||
| `imagePullSecrets` | Image pull secrets for the Pod | `[]` |
|
||||
| `hostAliases` | Mapping between IPs and hostnames that will be injected as entries in the Pod's hosts files | `[]` |
|
||||
| `enableServiceLinks` | Indicates whether information about services should be injected into Pod's environment variables, matching the syntax of Docker links | `true` |
|
||||
| `updateStrategy` | StatefulSet update strategy. One of `RollingUpdate` or `OnDelete` | `RollingUpdate` |
|
||||
| `podManagementPolicy` | Pod management policy. One of `Parallel` or `OrderedReady` | `OrderedReady` |
|
||||
| `revisionHistoryLimit` | Number of old ReplicaSets to retain for rollback. Defaults to Kubernetes default (10) if not set | `""` |
|
||||
| `restartPolicy` | Pod restart policy. One of `Always`, `OnFailure`, or `Never` | `Always` |
|
||||
| `serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` |
|
||||
| `serviceAccount.allowReadPods` | Specifies whether the ServiceAccount can get or list pods | `false` |
|
||||
| `serviceAccount.name` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | `""` |
|
||||
| `serviceAccount.annotations` | Additional annotations for the ServiceAccount | `{}` |
|
||||
| `serviceAccount.labels` | Additional labels for the ServiceAccount | `{}` |
|
||||
| `serviceAccount.imagePullSecrets` | Image pull secrets that are attached to the ServiceAccount | `[]` |
|
||||
| `serviceAccount.automountServiceAccountToken` | Automount API credentials for the Service Account | `true` |
|
||||
| `rbac.create` | Specifies whether RBAC resources are to be created | `false` |
|
||||
| `rbac.rules` | Custom RBAC rules, e. g. for KUBE_PING | `[]` |
|
||||
| `podSecurityContext` | SecurityContext for the entire Pod. Every container running in the Pod will inherit this SecurityContext. This might be relevant when other components of the environment inject additional containers into running Pods (service meshes are the most prominent example for this) | `{"fsGroup":1000}` |
|
||||
| `securityContext` | SecurityContext for the Keycloak container | `{"runAsNonRoot":true,"runAsUser":1000}` |
|
||||
| `extraInitContainers` | Additional init containers, e. g. for providing custom themes | `[]` |
|
||||
| `skipInitContainers` | Skip all init containers (to avoid issues with service meshes which require sidecar proxies for connectivity) | `false` |
|
||||
| `extraContainers` | Additional sidecar containers, e. g. for a database proxy, such as Google's cloudsql-proxy | `[]` |
|
||||
| `lifecycleHooks` | Lifecycle hooks for the Keycloak container | `{}` |
|
||||
| `terminationGracePeriodSeconds` | Termination grace period in seconds for Keycloak shutdown. Clusters with a large cache might need to extend this to give Infinispan more time to rebalance | `60` |
|
||||
| `clusterDomain` | The internal Kubernetes cluster domain | `cluster.local` |
|
||||
| `command` | Overrides the default entrypoint of the Keycloak container | `[]` |
|
||||
| `args` | Overrides the default args for the Keycloak container | `[]` |
|
||||
| `extraEnv` | Additional environment variables for Keycloak | `""` |
|
||||
| `extraEnvFrom` | Additional environment variables for Keycloak mapped from a Secret or ConfigMap | `""` |
|
||||
| `priorityClassName` | Pod priority class name | `""` |
|
||||
| `affinity` | Pod affinity | Hard node and soft zone anti-affinity |
|
||||
| `topologySpreadConstraints` | Topology spread constraints | Constraints used to spread pods |
|
||||
| `nodeSelector` | Node labels for Pod assignment | `{}` |
|
||||
| `tolerations` | Node taints to tolerate | `[]` |
|
||||
| `podLabels` | Additional Pod labels | `{}` |
|
||||
| `podAnnotations` | Additional Pod annotations | `{}` |
|
||||
| `livenessProbe` | Liveness probe configuration | `{"httpGet":{"path":"{{ tpl (coalesce .Values.http.managementRelativePath .Values.http.relativePath) $ \| trimSuffix "/" }}/health/live","port":"http-internal","scheme":"HTTP"},"initialDelaySeconds":0,"timeoutSeconds":5}` |
|
||||
| `readinessProbe` | Readiness probe configuration | `{"httpGet":{"path":"{{ tpl (coalesce .Values.http.managementRelativePath .Values.http.relativePath) $ \| trimSuffix "/" }}/health/ready","port":"http-internal","scheme":"HTTP"},"initialDelaySeconds":10,"timeoutSeconds":1}` |
|
||||
| `startupProbe` | Startup probe configuration | `{"httpGet":{"path":"{{ tpl (coalesce .Values.http.managementRelativePath .Values.http.relativePath) $ \| trimSuffix "/" }}/health","port":"http-internal","scheme":"HTTP"},"initialDelaySeconds":15,"timeoutSeconds":1,"failureThreshold":60,"periodSeconds":5}` |
|
||||
| `resources` | Pod resource requests and limits | `{}` |
|
||||
| `extraVolumes` | Add additional volumes, e. g. for custom themes | `""` |
|
||||
| `volumeClaimTemplates` | Add volume claim templates to the StatefulSet, e. g. for dynamic provisioning | `""` |
|
||||
| `extraVolumeMounts` | Add additional volumes mounts, e. g. for custom themes | `""` |
|
||||
| `extraPorts` | Add additional ports, e. g. for admin console or exposing JGroups ports | `[]` |
|
||||
| `podDisruptionBudget` | Pod disruption budget | `{}` |
|
||||
| `statefulsetAnnotations` | Annotations for the StatefulSet | `{}` |
|
||||
| `statefulsetLabels` | Additional labels for the StatefulSet | `{}` |
|
||||
| `secrets` | Configuration for secrets that should be created | `{}` |
|
||||
| `service.annotations` | Annotations for HTTP service | `{}` |
|
||||
| `service.labels` | Additional labels for headless and HTTP Services | `{}` |
|
||||
| `service.type` | The Service type | `ClusterIP` |
|
||||
| `service.loadBalancerIP` | Optional IP for the load balancer. Used for services of type LoadBalancer only | `""` |
|
||||
| `loadBalancerSourceRanges` | Optional List of allowed source ranges (CIDRs). Used for service of type LoadBalancer only | `[]` |
|
||||
| `service.externalTrafficPolicy` | Optional external traffic policy. Used for services of type LoadBalancer & NodePort only | `"Cluster"` |
|
||||
| `service.internalTrafficPolicy` | Optional internal traffic policy. Valid values: `Cluster`, `Local`. | `""` |
|
||||
| `service.httpPort` | The http Service port | `80` |
|
||||
| `service.httpNodePort` | The HTTP Service node port if type is NodePort | `""` |
|
||||
| `service.httpsPort` | The HTTPS Service port | `8443` |
|
||||
| `service.httpsNodePort` | The HTTPS Service node port if type is NodePort | `""` |
|
||||
| `service.extraPorts` | Additional Service ports, e. g. for custom admin console | `[]` |
|
||||
| `service.sessionAffinity` | sessionAffinity for Service, e. g. "ClientIP" | `""` |
|
||||
| `service.sessionAffinityConfig` | sessionAffinityConfig for Service | `{}` |
|
||||
| `serviceHeadless.annotations` | Annotations for headless service | `{}` |
|
||||
| `serviceHeadless.extraPorts` | Add additional ports to the headless service, e. g. for admin console or exposing JGroups ports | `[]` |
|
||||
| `ingress.enabled` | If `true`, an Ingress is created | `false` |
|
||||
| `ingress.rules` | List of Ingress Ingress rule | see below |
|
||||
| `ingress.rules[0].host` | Host for the Ingress rule | `{{ .Release.Name }}.keycloak.example.com` |
|
||||
| `ingress.rules[0].paths` | Paths for the Ingress rule | see below |
|
||||
| `ingress.rules[0].paths[0].path` | Path for the Ingress rule | `/` |
|
||||
| `ingress.rules[0].paths[0].pathType` | Path Type for the Ingress rule | `Prefix` |
|
||||
| `ingress.rules[0].paths[0].serviceName` | Optional override for backend service name (useful for AWS ALB action annotations) | `""` |
|
||||
| `ingress.rules[0].paths[0].servicePort` | Optional override for backend service port name | `""` |
|
||||
| `ingress.servicePort` | The Service port targeted by the Ingress | `http` |
|
||||
| `ingress.annotations` | Ingress annotations | `{}` |
|
||||
| `ingress.ingressClassName` | The name of the Ingress Class associated with the ingress | `""` |
|
||||
| `ingress.labels` | Additional Ingress labels | `{}` |
|
||||
| `ingress.tls` | TLS configuration | see below |
|
||||
| `ingress.tls[0].hosts` | List of TLS hosts | `[keycloak.example.com]` |
|
||||
| `ingress.tls[0].secretName` | Name of the TLS secret | `""` |
|
||||
| `ingress.console.enabled` | If `true`, an Ingress for the console is created | `false` |
|
||||
| `ingress.console.rules` | List of Ingress Ingress rule for the console | see below |
|
||||
| `ingress.console.rules[0].host` | Host for the Ingress rule for the console | `{{ .Release.Name }}.keycloak.example.com` |
|
||||
| `ingress.console.rules[0].paths` | Paths for the Ingress rule for the console | see below |
|
||||
| `ingress.console.rules[0].paths[0].path` | Path for the Ingress rule for the console | `[{{ tpl .Values.http.relativePath $ \| trimSuffix "/" }}/admin]` |
|
||||
| `ingress.console.rules[0].paths[0].pathType` | Path Type for the Ingress rule for the console | `Prefix` |
|
||||
| `ingress.console.rules[0].paths[0].serviceName` | Optional override for backend service name (console ingress) | `""` |
|
||||
| `ingress.console.rules[0].paths[0].servicePort` | Optional override for backend service port name (console ingress) | `""` |
|
||||
| `ingress.console.labels` | Additional labels for the console ingress only | `{}` |
|
||||
| `ingress.console.annotations` | Ingress annotations for the console | `{}` |
|
||||
| `ingress.console.ingressClassName` | The name of the Ingress Class associated with the console ingress | `""` |
|
||||
| `ingress.console.tls` | TLS configuration | see below |
|
||||
| `ingress.console.tls[0].hosts` | List of TLS hosts | `[keycloak.example.com]` |
|
||||
| `ingress.console.tls[0].secretName` | Name of the TLS secret | `""` |
|
||||
| `networkPolicy.enabled` | If true, the ingress network policy is deployed | `false` |
|
||||
| `networkPolicy.extraFrom` | Allows to define allowed external ingress traffic (see Kubernetes doc for network policy `from` format) | `[]` |
|
||||
| `networkPolicy.egress` | Allows to define allowed egress from Keycloak pods (see Kubernetes doc for network policy `egress` format) | `[]` |
|
||||
| `httpRoute.enabled` | If `true`, a Gateway API HTTPRoute is created | `false` |
|
||||
| `httpRoute.labels` | Additional HTTPRoute labels | `{}` |
|
||||
| `httpRoute.annotations` | HTTPRoute annotations | `{}` |
|
||||
| `httpRoute.servicePort` | The Service port targeted by the HTTPRoute | `80` |
|
||||
| `httpRoute.parentRefs` | Gateways this HTTPRoute is attached to. Unused when `listenerSet.enabled` is `true` | see values.yaml |
|
||||
| `httpRoute.hostnames` | Hostnames matching HTTP header. Unused when `listenerSet.enabled` is `true` | `[chart-example.local]` |
|
||||
| `httpRoute.rules` | List of rules and filters applied | see values.yaml |
|
||||
| `httpRoute.console.enabled` | If `true`, a separate HTTPRoute is created for the admin console path only | `false` |
|
||||
| `httpRoute.console.labels` | Additional labels for the console HTTPRoute | `{}` |
|
||||
| `httpRoute.console.annotations` | Annotations for the console HTTPRoute | `{}` |
|
||||
| `httpRoute.console.parentRefs` | Gateways the console HTTPRoute is attached to. Falls back to `httpRoute.parentRefs` if unset | see values.yaml |
|
||||
| `httpRoute.console.hostnames` | Hostnames for the console HTTPRoute. Falls back to `httpRoute.hostnames` if unset | `[chart-example.local]` |
|
||||
| `httpRoute.console.rules` | Rules for the console HTTPRoute | see values.yaml |
|
||||
| `httpRoute.listenerSet.enabled` | If `true`, a Gateway API ListenerSet is created alongside the HTTPRoute, enabling namespace-level listener configuration without Gateway write access | `false` |
|
||||
| `httpRoute.listenerSet.labels` | Additional ListenerSet labels | `{}` |
|
||||
| `httpRoute.listenerSet.annotations` | ListenerSet annotations | `{}` |
|
||||
| `httpRoute.listenerSet.parentRef.name` | Name of the Gateway this ListenerSet attaches to | `gateway` |
|
||||
| `httpRoute.listenerSet.parentRef.namespace` | Namespace of the Gateway this ListenerSet attaches to | `""` |
|
||||
| `httpRoute.listenerSet.listeners` | Listeners to attach to the Gateway. Full Gateway API listener spec accepted. Listener hostnames are used to populate the HTTPRoute `hostnames` field | `[]` |
|
||||
| `route.enabled` | If `true`, an OpenShift Route is created | `false` |
|
||||
| `route.path` | Path for the Route | `/` |
|
||||
| `route.annotations` | Route annotations | `{}` |
|
||||
| `route.labels` | Additional Route labels | `{}` |
|
||||
| `route.host` | Host name for the Route | `""` |
|
||||
| `route.tls.enabled` | If `true`, TLS is enabled for the Route | `true` |
|
||||
| `route.tls.insecureEdgeTerminationPolicy` | Insecure edge termination policy of the Route. Can be `None`, `Redirect`, or `Allow` | `Redirect` |
|
||||
| `route.tls.termination` | TLS termination of the route. Can be `edge`, `passthrough`, or `reencrypt` | `edge` |
|
||||
| `dbchecker.enabled` | Enable database readiness check | `false` |
|
||||
| `dbchecker.image.repository` | Docker image used to check database readiness at startup | `docker.io/busybox` |
|
||||
| `dbchecker.image.tag` | Image tag for the dbchecker image | `1.32` |
|
||||
| `dbchecker.image.pullPolicy` | Image pull policy for the dbchecker image | `IfNotPresent` |
|
||||
| `dbchecker.securityContext` | SecurityContext for the dbchecker container | `{"allowPrivilegeEscalation":false,"runAsGroup":1000,"runAsNonRoot":true,"runAsUser":1000}` |
|
||||
| `dbchecker.resources` | Resource requests and limits for the dbchecker container | `{"limits":{"cpu":"20m","memory":"32Mi"},"requests":{"cpu":"20m","memory":"32Mi"}}` |
|
||||
| `database.vendor` | Database vendor | unset |
|
||||
| `database.hostname` | Database Hostname | unset |
|
||||
| `database.port` | Database Port | unset |
|
||||
| `database.username` | Database User | unset |
|
||||
| `database.password` | Database Password | unset |
|
||||
| `database.database` | Database | unset |
|
||||
| `database.existingSecret` | Existing Secret containing database password (expects key `password`) | `""` |
|
||||
| `database.existingSecretKey` | Key in existing Secret containing database password | `""`
|
||||
| `cache.stack` | Cache / Cluster Discovery, use `custom` to disable automatic configuration. | `default` |
|
||||
| `proxy.enabled` | If `true`, the `KC_PROXY` env variable will be set to the configured mode | `true` |
|
||||
| `proxy.mode` | The configured proxy mode | `forwarded` |
|
||||
| `proxy.http.enabled` | If `true`, HTTP forwarding is enabled | `true` |
|
||||
| `http.relativePath` | The relative http path (context-path) | `/auth` |
|
||||
| `http.managementRelativePath` | The relative path for the management interface (KC_HTTP_MANAGEMENT_RELATIVE_PATH). When empty, Keycloak inherits the value from `http.relativePath`. Set to `/` to serve management endpoints at the root. | `""` |
|
||||
| `http.internalPort` | The port of the internal management interface | `http-internal` |
|
||||
| `http.internalScheme` | The scheme of the internal management interface | `HTTP` |
|
||||
| `metrics.enabled` | If `true` then the metrics endpoint is exposed | `true` |
|
||||
| `health.enabled` | If `true` then the health endpoint is exposed. If the `readinessProbe` is is needed `metrics.enable` must be `true`. | `true` |
|
||||
| `serviceMonitor.enabled` | If `true`, a ServiceMonitor resource for the prometheus-operator is created | `false` |
|
||||
| `serviceMonitor.namespace` | Optionally sets a target namespace in which to deploy the ServiceMonitor resource | `""` |
|
||||
| `serviceMonitor.namespaceSelector` | Optionally sets a namespace selector for the ServiceMonitor | `{}` |
|
||||
| `serviceMonitor.annotations` | Annotations for the ServiceMonitor | `{}` |
|
||||
| `serviceMonitor.labels` | Additional labels for the ServiceMonitor | `{}` |
|
||||
| `serviceMonitor.interval` | Interval at which Prometheus scrapes metrics | `10s` |
|
||||
| `serviceMonitor.scrapeTimeout` | Timeout for scraping | `10s` |
|
||||
| `serviceMonitor.relabelings` | Relabelings for the Servicemonitor | `[]` |
|
||||
| `serviceMonitor.metricRelabelings` | metricRelabelings for the Servicemonitor | `[]` |
|
||||
| `serviceMonitor.path` | The path at which metrics are served | `{{ tpl (coalesce .Values.http.managementRelativePath .Values.http.relativePath) $ \| trimSuffix "/" }}/metrics` |
|
||||
| `serviceMonitor.port` | The Service port at which metrics are served | `http-internal` |
|
||||
| `serviceMonitor.scheme` | The scheme to use for scraping metrics ("http" or "https"); if not set, the `http.internalScheme` value is used | `""` |
|
||||
| `serviceMonitor.tlsConfig` | TLS configuration for the ServiceMonitor, set CA certificates or `insecureSkipVerify` if Keycloak uses https | `{}` |
|
||||
| `extraServiceMonitor.enabled` | If `true`, an additional ServiceMonitor resource for the prometheus-operator is created. Could be used for additional metrics via [Keycloak Metrics SPI](https://github.com/aerogear/keycloak-metrics-spi) | `false` |
|
||||
| `extraServiceMonitor.namespace` | Optionally sets a target namespace in which to deploy the additional ServiceMonitor resource | `""` |
|
||||
| `extraServiceMonitor.namespaceSelector` | Optionally sets a namespace selector for the additional ServiceMonitor | `{}` |
|
||||
| `extraServiceMonitor.annotations` | Annotations for the additional ServiceMonitor | `{}` |
|
||||
| `extraServiceMonitor.labels` | Additional labels for the additional ServiceMonitor | `{}` |
|
||||
| `extraServiceMonitor.interval` | Interval at which Prometheus scrapes metrics | `10s` |
|
||||
| `extraServiceMonitor.scrapeTimeout` | Timeout for scraping | `10s` |
|
||||
| `extraServiceMonitor.relabelings` | Relabelings for the additional ServiceMonitor | `[]` |
|
||||
| `extraServiceMonitor.metricRelabelings` | metricRelabelings for the additional ServiceMonitor | `[]` |
|
||||
| `extraServiceMonitor.path` | The path at which metrics are served | `{{ tpl (coalesce .Values.http.managementRelativePath .Values.http.relativePath) $ \| trimSuffix "/" }}/metrics` |
|
||||
| `extraServiceMonitor.port` | The Service port at which metrics are served | `http-internal` |
|
||||
| `extraServiceMonitor.scheme` | The scheme to use for scraping metrics ("http" or "https"); if not set, the `http.internalScheme` value is used | `""` |
|
||||
| `prometheusRule.enabled` | If `true`, a PrometheusRule resource for the prometheus-operator is created | `false` |
|
||||
| `prometheusRule.namespace` | Optionally sets a target namespace in which to deploy the PrometheusRule resource | `""` |
|
||||
| `prometheusRule.annotations` | Annotations for the PrometheusRule | `{}` |
|
||||
| `prometheusRule.labels` | Additional labels for the PrometheusRule | `{}` |
|
||||
| `prometheusRule.rules` | List of rules for Prometheus | `[]` |
|
||||
| `autoscaling.enabled` | Enable creation of a HorizontalPodAutoscaler resource | `false` |
|
||||
| `autoscaling.labels` | Additional labels for the HorizontalPodAutoscaler resource | `{}` |
|
||||
| `autoscaling.minReplicas` | The minimum number of Pods when autoscaling is enabled | `3` |
|
||||
| `autoscaling.maxReplicas` | The maximum number of Pods when autoscaling is enabled | `10` |
|
||||
| `autoscaling.metrics` | The metrics configuration for the HorizontalPodAutoscaler | `[{"resource":{"name":"cpu","target":{"averageUtilization":80,"type":"Utilization"}},"type":"Resource"}]` |
|
||||
| `autoscaling.behavior` | The scaling policy configuration for the HorizontalPodAutoscaler | `{"scaleDown":{"policies":[{"periodSeconds":300,"type":"Pods","value":1}],"stabilizationWindowSeconds":300}` |
|
||||
| `test.enabled` | If `true`, test resources are created | `false` |
|
||||
| `test.image.repository` | The image for the test Pod | `docker.io/seleniarm/standalone-chromium` |
|
||||
| `test.image.tag` | The tag for the test Pod image | `117.0` |
|
||||
| `test.image.pullPolicy` | The image pull policy for the test Pod image | `IfNotPresent` |
|
||||
| `test.podSecurityContext` | SecurityContext for the entire test Pod | `{"fsGroup":1000}` |
|
||||
| `test.securityContext` | SecurityContext for the test container | `{"runAsNonRoot":true,"runAsUser":1000}` |
|
||||
| `test.deletionPolicy` | `helm.sh/hook-delete-policy` for the test Pod | `before-hook-creation` | | `before-hook-creation` |
|
||||
|
||||
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example:
|
||||
|
||||
```console
|
||||
$ helm install keycloak codecentric/keycloakx -n keycloak --set replicas=1
|
||||
```
|
||||
|
||||
Alternatively, a YAML file that specifies the values for the parameters can be provided while
|
||||
installing the chart. For example:
|
||||
|
||||
```console
|
||||
$ helm install keycloak codecentric/keycloakx -n keycloak --values values.yaml
|
||||
```
|
||||
|
||||
The chart offers great flexibility.
|
||||
It can be configured to work with the official Keycloak-X Docker image but any custom image can be used as well.
|
||||
|
||||
For the official Docker image, please check it's configuration at https://github.com/keycloak/keycloak/tree/main/quarkus/container.
|
||||
|
||||
### 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:
|
||||
|
||||
* `extraInitContainers`
|
||||
* `extraContainers`
|
||||
* `extraEnv`
|
||||
* `extraEnvFrom`
|
||||
* `affinity`
|
||||
* `extraVolumeMounts`
|
||||
* `extraVolumes`
|
||||
* `livenessProbe`
|
||||
* `readinessProbe`
|
||||
* `startupProbe`
|
||||
* `topologySpreadConstraints`
|
||||
|
||||
Additionally, custom labels and annotations can be set on various resources the values of which being passed through `tpl` as well.
|
||||
|
||||
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`.
|
||||
|
||||
### JVM Settings
|
||||
|
||||
Keycloak sets the following system properties by default:
|
||||
`-Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m`
|
||||
|
||||
You can override these by setting the `JAVA_OPTS` environment variable.
|
||||
Make sure you configure container support.
|
||||
This allows you to only configure memory using Kubernetes resources and the JVM will automatically adapt.
|
||||
|
||||
```yaml
|
||||
extraEnv: |
|
||||
- name: JAVA_OPTS
|
||||
value: >-
|
||||
-XX:MaxRAMPercentage=50.0
|
||||
```
|
||||
|
||||
Alternatively one can append custom JVM options by setting the `JAVA_OPTS_APPEND` environment variable.
|
||||
|
||||
The parameter `-Djava.net.preferIPv4Stack=true` is [optional](https://github.com/keycloak/keycloak/commit/ee205c8fbc1846f679bd604fa8d25310c117c87e) for [Keycloak >= v22](https://www.keycloak.org/server/configuration-production#_configure_keycloak_server_with_ipv4_or_ipv6).
|
||||
|
||||
The parameter `-XX:+UseContainerSupport` is no longer required for [Keycloak >= v21 based on JDK v17](https://github.com/keycloak/keycloak/blob/release/21.0/quarkus/container/Dockerfile#L20).
|
||||
|
||||
The parameter `-Djava.awt.headless=true` is no longer required for Quarkus based Keycloak as it is set by [default](https://quarkus.io/guides/building-native-image).
|
||||
|
||||
#### Using an External Database
|
||||
|
||||
The Keycloak Docker image supports various database types.
|
||||
Configuration happens in a generic manner.
|
||||
|
||||
##### Using a Secret Managed by the Chart
|
||||
|
||||
The following examples uses a PostgreSQL database with a secret that is managed by the Helm chart.
|
||||
|
||||
```yaml
|
||||
dbchecker:
|
||||
enabled: true
|
||||
|
||||
database:
|
||||
vendor: postgres
|
||||
hostname: mypostgres
|
||||
port: 5432
|
||||
username: '{{ .Values.dbUser }}'
|
||||
password: '{{ .Values.dbPassword }}'
|
||||
database: mydb
|
||||
```
|
||||
|
||||
`dbUser` and `dbPassword` are custom values you'd then specify on the commandline using `--set-string`.
|
||||
|
||||
##### Using an Existing Secret
|
||||
|
||||
The following examples uses a PostgreSQL database with an existing secret.
|
||||
|
||||
```yaml
|
||||
dbchecker:
|
||||
enabled: true
|
||||
|
||||
database:
|
||||
vendor: postgres
|
||||
hostname: mypostgres
|
||||
port: 5432
|
||||
database: mydb
|
||||
username: db-user
|
||||
existingSecret: byo-db-creds # Password is retrieved via .password
|
||||
```
|
||||
|
||||
### Creating a Keycloak Admin User
|
||||
|
||||
The Keycloak-X Docker image supports creating an initial admin user.
|
||||
It must be configured via environment variables:
|
||||
|
||||
* `KEYCLOAK_ADMIN`
|
||||
* `KEYCLOAK_ADMIN_PASSWORD`
|
||||
|
||||
This can be done like so in the `values.yaml`, where the `KEYCLOAK_ADMIN` is an insecure example with the value in plaintext.
|
||||
The `KEYCLOAK_ADMIN_PASSWORD` is referenced from already existing secret but for testing it can be set with `value` too.
|
||||
```yaml
|
||||
extraEnv: |
|
||||
- name: KEYCLOAK_ADMIN
|
||||
value: admin
|
||||
- name: KEYCLOAK_ADMIN_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: keycloak-admin-password
|
||||
key: password
|
||||
```
|
||||
|
||||
### High Availability and Clustering
|
||||
|
||||
For high availability, Keycloak must be run with multiple replicas (`replicas > 1`).
|
||||
The chart has a helper template (`keycloak.serviceDnsName`) that creates the DNS name based on the headless service.
|
||||
|
||||
### Default Cache Stack
|
||||
|
||||
The default cache stack is now using `jdbc-ping` which leverages a table called `jgroups_ping` in the keycloak database to store the cache and significantly reduces network complexity. Keycloak has set this [transport stack](https://www.keycloak.org/server/caching#_transport_stacks) as the default starting in 26.1.0 and it is backwards compatible with all 26.X releases.
|
||||
|
||||
It is recommended to use the new default value as it works in kubernetes and across multiple cloud providers alike. Currently all other options have been marked as deprecated. However, if the original value of `kubernetes` is required in a given environment, it can still be set by using a custom stack:
|
||||
|
||||
```yaml
|
||||
cache:
|
||||
stack: custom
|
||||
```
|
||||
|
||||
Addtionally, the following environment variables would need to be added for it to function properly:
|
||||
|
||||
```yaml
|
||||
extraEnv: |
|
||||
- name: KC_CACHE
|
||||
value: "ispn"
|
||||
- name: KC_CACHE_STACK
|
||||
value: "kubernetes"
|
||||
- name: JAVA_OPTS_APPEND
|
||||
value: >-
|
||||
-Djgroups.dns.query={{ include "keycloak.fullname" . }}-headless
|
||||
```
|
||||
|
||||
#### Custom Service Discovery
|
||||
|
||||
If a custom JGroups discovery is needed, then you can configure:
|
||||
|
||||
```yaml
|
||||
cache:
|
||||
stack: custom
|
||||
```
|
||||
|
||||
You can then reference your custom infinispan configuration file, e.g. `cache-custom.xml` via the `KC_CACHE_CONFIG_FILE` environment variable.
|
||||
Note that the `cache-custom.xml` must be available via `/opt/keycloak/conf/cache-custom.xml`.
|
||||
|
||||
```yaml
|
||||
extraEnv: |
|
||||
- name: KC_CACHE
|
||||
value: "ispn"
|
||||
- name: KC_CACHE_CONFIG_FILE
|
||||
value: cache-custom.xml
|
||||
```
|
||||
|
||||
#### Autoscaling
|
||||
|
||||
Due to the caches in Keycloak only replicating to a few nodes (two in the example configuration above) and the limited controls around autoscaling built into Kubernetes, it has historically been problematic to autoscale Keycloak.
|
||||
However, in Kubernetes 1.18 [additional controls were introduced](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-configurable-scaling-behavior) which make it possible to scale down in a more controlled manner.
|
||||
|
||||
The example autoscaling configuration in the values file scales from three up to a maximum of ten Pods using CPU utilization as the metric. Scaling up is done as quickly as required but scaling down is done at a maximum rate of one Pod per five minutes.
|
||||
|
||||
Autoscaling can be enabled as follows:
|
||||
|
||||
```yaml
|
||||
autoscaling:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
KUBE_PING service discovery seems to be the most reliable mechanism to use when enabling autoscaling, due to being faster than DNS_PING at detecting changes in the cluster.
|
||||
|
||||
### Running Keycloak Behind a Reverse Proxy
|
||||
|
||||
When running Keycloak behind a reverse proxy, which is the case when using an ingress controller,
|
||||
proxy address forwarding must be enabled as follows:
|
||||
|
||||
```yaml
|
||||
extraEnv: |
|
||||
- name: KC_PROXY
|
||||
value: "passthrough"
|
||||
```
|
||||
|
||||
### Providing a Custom Theme
|
||||
|
||||
One option is certainly to provide a custom Keycloak-X image that includes the theme.
|
||||
However, if you prefer to stick with the official Keycloak-X image, you can use an init container as theme provider.
|
||||
|
||||
Create your own theme and package it up into a Docker image.
|
||||
|
||||
```docker
|
||||
FROM busybox
|
||||
COPY mytheme /mytheme
|
||||
```
|
||||
|
||||
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
|
||||
extraInitContainers: |
|
||||
- name: theme-provider
|
||||
image: myuser/mytheme:1
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- sh
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
echo "Copying theme..."
|
||||
cp -R /mytheme/* /theme
|
||||
volumeMounts:
|
||||
- name: theme
|
||||
mountPath: /theme
|
||||
|
||||
extraVolumeMounts: |
|
||||
- name: theme
|
||||
mountPath: /opt/keycloak/themes/mytheme
|
||||
|
||||
extraVolumes: |
|
||||
- name: theme
|
||||
emptyDir: {}
|
||||
```
|
||||
|
||||
### 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 `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
|
||||
database:
|
||||
vendor: postgres
|
||||
hostname: '127.0.0.1'
|
||||
port: 5432
|
||||
database: postgres
|
||||
username: myuser
|
||||
password: mypassword
|
||||
|
||||
# Custom values for Google Cloud SQL
|
||||
cloudsql:
|
||||
project: my-project
|
||||
region: europe-west1
|
||||
instance: my-instance
|
||||
|
||||
extraContainers: |
|
||||
- name: cloudsql-proxy
|
||||
image: gcr.io/cloudsql-docker/gce-proxy:1.17
|
||||
command:
|
||||
- /cloud_sql_proxy
|
||||
args:
|
||||
- -instances={{ .Values.cloudsql.project }}:{{ .Values.cloudsql.region }}:{{ .Values.cloudsql.instance }}=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
|
||||
```
|
||||
|
||||
### Changing the Context Path
|
||||
|
||||
By default, Keycloak-X is served under context `/auth`.
|
||||
Trailing slash is removed from path. This can be changed to another context path like `/` as follows:
|
||||
|
||||
```yaml
|
||||
http:
|
||||
relativePath: '/'
|
||||
```
|
||||
|
||||
Alternatively, you may supply it via CLI flag:
|
||||
|
||||
```console
|
||||
--set-string http.relativePath=/
|
||||
```
|
||||
|
||||
### Management Interface
|
||||
|
||||
Keycloak serves health and metrics endpoints on a separate management interface (port 9000).
|
||||
By default, the management interface inherits its relative path from `http.relativePath` (e.g. `/auth`),
|
||||
so endpoints are available at `/auth/health` and `/auth/metrics`.
|
||||
|
||||
To serve management endpoints at a different path, set `http.managementRelativePath`:
|
||||
|
||||
```yaml
|
||||
http:
|
||||
relativePath: "/auth"
|
||||
managementRelativePath: "/"
|
||||
```
|
||||
|
||||
This sets `KC_HTTP_MANAGEMENT_RELATIVE_PATH=/` so health and metrics are available at
|
||||
`/health` and `/metrics` on port 9000. When left empty, the env var is not set and
|
||||
Keycloak inherits the value from `http.relativePath`.
|
||||
|
||||
### Prometheus Metrics Support
|
||||
|
||||
#### Keycloak Metrics
|
||||
|
||||
Keycloak-X can expose metrics via `/auth/metrics`.
|
||||
|
||||
Metrics are enabled by default via:
|
||||
```yaml
|
||||
metrics:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
Add a ServiceMonitor if using prometheus-operator:
|
||||
|
||||
```yaml
|
||||
serviceMonitor:
|
||||
# If `true`, a ServiceMonitor resource for the prometheus-operator is created
|
||||
enabled: true
|
||||
```
|
||||
|
||||
Checkout `values.yaml` for customizing the ServiceMonitor and for adding custom Prometheus rules.
|
||||
|
||||
Add annotations if you don't use prometheus-operator:
|
||||
|
||||
```yaml
|
||||
service:
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "8080"
|
||||
```
|
||||
|
||||
#### Keycloak Metrics SPI
|
||||
|
||||
Optionally, it is possible to add [Keycloak Metrics SPI](https://github.com/aerogear/keycloak-metrics-spi) via init container.
|
||||
Note that the `keycloak-metrics-spi.jar` needs to be added to the `/opt/keycloak/providers` directory.
|
||||
|
||||
A separate `ServiceMonitor` can be enabled to scrape metrics from the SPI:
|
||||
|
||||
```yaml
|
||||
extraServiceMonitor:
|
||||
# If `true`, an additional ServiceMonitor resource for the prometheus-operator is created
|
||||
enabled: true
|
||||
```
|
||||
|
||||
Checkout `values.yaml` for customizing this ServiceMonitor.
|
||||
|
||||
Note that the metrics endpoint is exposed on the HTTP port.
|
||||
You may want to restrict access to it in your ingress controller configuration.
|
||||
For ingress-nginx, this could be done as follows:
|
||||
|
||||
```yaml
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/server-snippet: |
|
||||
location ~* /auth/realms/[^/]+/metrics {
|
||||
return 403;
|
||||
}
|
||||
```
|
||||
|
||||
### Extra Kubernetes Manifests
|
||||
|
||||
It is possible to deploy extra Kubernetes resources (such as ConfigMaps, Secrets, Jobs, or any other Kubernetes objects) alongside the Keycloak chart by using the `extraManifests` value.
|
||||
This feature supports Helm templating, allowing you to use chart helpers like `{{ include "keycloak.fullname" . }}` within your manifests.
|
||||
|
||||
```yaml
|
||||
extraManifests:
|
||||
- |
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}-extra-config
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 8 }}
|
||||
data:
|
||||
custom-key: custom-value
|
||||
- |
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}-extra-secret
|
||||
type: Opaque
|
||||
stringData:
|
||||
my-secret-key: my-secret-value
|
||||
```
|
||||
|
||||
## Why StatefulSet?
|
||||
|
||||
The headless service that governs the StatefulSet is used for DNS discovery via DNS_PING.
|
||||
|
||||
## Bad Gateway and Proxy Buffer Size in Nginx
|
||||
|
||||
A common issue with Keycloak and nginx is that the proxy buffer may be too small for what Keycloak is trying to send. This will result in a Bad Gateway (502) error. There are [many](https://github.com/kubernetes/ingress-nginx/issues/4637) [issues](https://stackoverflow.com/questions/56126864/why-do-i-get-502-when-trying-to-authenticate) around the internet about this. The solution is to increase the buffer size of nginx. This can be done by creating an annotation in the ingress specification:
|
||||
|
||||
```yaml
|
||||
ingress:
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/proxy-buffer-size: "128k"
|
||||
```
|
||||
|
||||
## Upgrading
|
||||
|
||||
Notes for upgrading from previous Keycloak chart versions.
|
||||
|
||||
### From chart < 18.0.0
|
||||
|
||||
* Keycloak is updated to 18.0.0
|
||||
* Added new `health.enabled` option.
|
||||
|
||||
Keycloak 18.0.0 allows to enable the health endpoint independently of the metrics endpoint via the `health-enabled` setting.
|
||||
We reflect that via the new config option `health.enabled`.
|
||||
|
||||
Please read the additional notes about [Migrating to 18.0.0](https://www.keycloak.org/docs/latest/upgrading/index.html#migrating-to-18-0-0) in the Keycloak documentation.
|
||||
@@ -0,0 +1,80 @@
|
||||
image:
|
||||
repository: docker.io/paasup/keycloak
|
||||
tag: "26.7.1-bci15.7-hardened-20260807"
|
||||
|
||||
# keycloakx 기본값은 "/auth"(구 WildFly 기반 codecentric/keycloak 호환용). Keycloak
|
||||
# 26(Quarkus) 네이티브 기본값은 "/"이며, /auth 를 그대로 두면 OIDC issuer/admin API
|
||||
# 경로가 다른 앱들의 가정(경로 접미사 없음)과 어긋난다.
|
||||
http:
|
||||
relativePath: "/"
|
||||
|
||||
# 차트 기본값은 command/args 모두 빈 배열이다 — 지정하지 않으면 컨테이너가 인자 없는
|
||||
# kc.sh(도움말 출력, exit 0)로 끝나 CrashLoopBackOff가 된다(실측 확인, dip-catalog#1).
|
||||
command:
|
||||
- "/opt/keycloak/bin/kc.sh"
|
||||
- "start"
|
||||
|
||||
# path 를 exact "/" 로 두면 apisix 에서 루트만 매치되어 Keycloak 의 실제 엔드포인트
|
||||
# (/realms/*, /admin/*, /resources/*)가 전부 404 가 난다 — airflow·superset·mlflow·
|
||||
# lakekeeper 에서 이미 실측된 문제로 카탈로그 전체가 regex 방식으로 통일돼 있다
|
||||
# (.claude/pitfalls.md). ingressClassName 도 반드시 명시한다 — 미지정 시 이 클러스터의
|
||||
# apisix 가 인식하지 않아 CLASS: <none> 으로 뜨고 접근 자체가 불가능하다.
|
||||
ingress:
|
||||
enabled: true
|
||||
ingressClassName: apisix
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: "root-ca-issuer"
|
||||
k8s.apisix.apache.org/use-regex: "true"
|
||||
rules:
|
||||
- host: keycloak.example.org
|
||||
paths:
|
||||
- path: /.*
|
||||
pathType: ImplementationSpecific
|
||||
tls:
|
||||
- hosts:
|
||||
- keycloak.example.org
|
||||
secretName: keycloak-tls
|
||||
|
||||
proxy:
|
||||
enabled: true
|
||||
mode: forwarded
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 500Mi
|
||||
limits:
|
||||
cpu: 2000m
|
||||
memory: 1500Mi
|
||||
|
||||
# 외부 postgresql 사용. vendor/hostname/port/database/username 값을 배포된 DB로 변경.
|
||||
# 비밀번호는 password 평문 대신 existingSecret(kubernetes.io/basic-auth 시크릿의
|
||||
# password 키, 기본 existingSecretKey)을 쓰는 것을 권장.
|
||||
database:
|
||||
vendor: postgres
|
||||
hostname: keycloak-postgresql
|
||||
port: 5432
|
||||
database: keycloak
|
||||
username: keycloak
|
||||
existingSecret: keycloak-db
|
||||
existingSecretKey: password
|
||||
|
||||
# KC_DB_SCHEMA: Keycloak Quarkus 정식 config 옵션(db-schema) — public 이 아닌 전용
|
||||
# 스키마를 쓸 때 지정.
|
||||
# KC_BOOTSTRAP_ADMIN_USERNAME/PASSWORD: Keycloak 25+ 의 admin 계정 부트스트랩
|
||||
# 메커니즘(구버전 KEYCLOAK_ADMIN/KEYCLOAK_ADMIN_PASSWORD 대체). master realm이
|
||||
# 완전히 비어있는 최초 부팅에만 동작 — 재설치 시 비밀번호가 갱신되지 않는 것이 정상.
|
||||
# KC_HOSTNAME: 반드시 지정할 것. hostname-strict 가 기본 true 라 미지정 시
|
||||
# "hostname is not configured; either configure hostname, or set hostname-strict
|
||||
# to false" 로 기동이 실패한다(실측 확인).
|
||||
extraEnv: |
|
||||
- name: KC_HOSTNAME
|
||||
value: keycloak.example.org
|
||||
- name: KC_DB_SCHEMA
|
||||
value: keycloak
|
||||
- name: KC_BOOTSTRAP_ADMIN_USERNAME
|
||||
value: admin
|
||||
- name: KC_BOOTSTRAP_ADMIN_PASSWORD
|
||||
value: ChangeMe1234! # 예시 값 — 배포 전 교체한다
|
||||
- name: TZ
|
||||
value: Asia/Seoul
|
||||
@@ -0,0 +1,75 @@
|
||||
***********************************************************************
|
||||
* *
|
||||
* Keycloak.X Helm Chart by codecentric AG *
|
||||
* *
|
||||
***********************************************************************
|
||||
|
||||
{{- if and .Values.httpRoute.enabled .Values.httpRoute.listenerSet.enabled }}
|
||||
|
||||
Keycloak was installed with a Gateway API HTTPRoute and ListenerSet.
|
||||
The ListenerSet {{ include "keycloak.fullname" . }} attaches listeners to the Gateway "{{ .Values.httpRoute.listenerSet.parentRef.name }}"{{ with .Values.httpRoute.listenerSet.parentRef.namespace }} in namespace "{{ . }}"{{ end }}.
|
||||
|
||||
Ensure the Gateway is configured to allow ListenerSet attachment from namespace {{ .Release.Namespace }}.
|
||||
|
||||
{{- else if .Values.httpRoute.enabled }}
|
||||
|
||||
Keycloak was installed with a Gateway API HTTPRoute attached to:
|
||||
{{- range .Values.httpRoute.parentRefs }}
|
||||
- Gateway: {{ .name }}{{ with .sectionName }}, section: {{ . }}{{ end }}
|
||||
{{- end }}
|
||||
|
||||
{{- else if .Values.ingress.enabled }}
|
||||
|
||||
Keycloak was installed with an Ingress and an be reached at the following URL(s):
|
||||
{{ range $unused, $rule := .Values.ingress.rules }}
|
||||
{{- range $rule.paths }}
|
||||
- http{{ if $.Values.ingress.tls }}s{{ end }}://{{ tpl $rule.host $ }}{{ .path }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- else if eq "NodePort" .Values.service.type }}
|
||||
|
||||
Keycloak was installed with a Service of type NodePort.
|
||||
{{ if .Values.service.httpNodePort }}
|
||||
Get its HTTP URL with the following commands:
|
||||
|
||||
export NODE_PORT=$(kubectl get --namespace {{ include "keycloak.namespace" . }} service {{ include "keycloak.fullname" . }}-http --template='{{"{{ range .spec.ports }}{{ if eq .name \"http\" }}{{ .nodePort }}{{ end }}{{ end }}"}}')
|
||||
export NODE_IP=$(kubectl get nodes --namespace {{ include "keycloak.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
echo "http://$NODE_IP:$NODE_PORT"
|
||||
{{- end }}
|
||||
{{ if .Values.service.httpsNodePort }}
|
||||
Get its HTTPS URL with the following commands:
|
||||
|
||||
export NODE_PORT=$(kubectl get --namespace {{ include "keycloak.namespace" . }} service {{ include "keycloak.fullname" . }}-http --template='{{"{{ range .spec.ports }}{{ if eq .name \"https\" }}{{ .nodePort }}{{ end }}{{ end }}"}}')
|
||||
export NODE_IP=$(kubectl get nodes --namespace {{ include "keycloak.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
echo "http://$NODE_IP:$NODE_PORT"
|
||||
{{- end }}
|
||||
|
||||
{{- else if eq "LoadBalancer" .Values.service.type }}
|
||||
|
||||
Keycloak was installed with a Service of type LoadBalancer
|
||||
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
You can watch the status of by running 'kubectl get --namespace {{ include "keycloak.namespace" . }} service -w {{ include "keycloak.fullname" . }}'
|
||||
|
||||
Get its HTTP URL with the following commands:
|
||||
|
||||
export SERVICE_IP=$(kubectl get service --namespace {{ include "keycloak.namespace" . }} {{ include "keycloak.fullname" . }}-http --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||
echo "http://$SERVICE_IP:{{ .Values.service.httpPort }}"
|
||||
|
||||
Get its HTTPS URL with the following commands:
|
||||
|
||||
export SERVICE_IP=$(kubectl get service --namespace {{ include "keycloak.namespace" . }} {{ include "keycloak.fullname" . }}-http --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||
echo "http://$SERVICE_IP:{{ .Values.service.httpsPort }}"
|
||||
|
||||
{{- else if eq "ClusterIP" .Values.service.type }}
|
||||
|
||||
Keycloak was installed with a Service of type ClusterIP
|
||||
|
||||
Create a port-forwarding with the following commands:
|
||||
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ include "keycloak.namespace" . }} -l "app.kubernetes.io/name={{ include "keycloak.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o name)
|
||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||
kubectl --namespace {{ include "keycloak.namespace" . }} port-forward "$POD_NAME" 8080
|
||||
|
||||
{{- end }}
|
||||
@@ -0,0 +1,97 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "keycloak.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
*/}}
|
||||
{{- define "keycloak.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "keycloak.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "keycloak.labels" -}}
|
||||
helm.sh/chart: {{ include "keycloak.chart" . }}
|
||||
{{ include "keycloak.selectorLabels" . }}
|
||||
app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | toString | trunc 63 | trimSuffix "-" | quote }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- range $key, $value := .Values.commonLabels }}
|
||||
{{ printf "%s: %s" $key (tpl $value $ | quote) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "keycloak.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "keycloak.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "keycloak.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "keycloak.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the service DNS name.
|
||||
*/}}
|
||||
{{- define "keycloak.serviceDnsName" -}}
|
||||
{{ include "keycloak.fullname" . }}-headless.{{ include "keycloak.namespace" . }}.svc.{{ .Values.clusterDomain }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Namespace for all resources. Callers can override via .Values.namespaceOverride.
|
||||
*/}}
|
||||
{{- define "keycloak.namespace" -}}
|
||||
{{- default .Release.Namespace .Values.namespaceOverride -}}
|
||||
{{- end }}
|
||||
|
||||
{{- define "keycloak.databasePasswordEnv" -}}
|
||||
{{- if or .Values.database.password .Values.database.existingSecret -}}
|
||||
- name: KC_DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .Values.database.existingSecret | default (printf "%s-database" (include "keycloak.fullname" . ))}}
|
||||
key: {{ .Values.database.existingSecretKey | default "password" }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Renders a complete tree, even values that contains template.
|
||||
*/}}
|
||||
{{- define "keycloak.render" -}}
|
||||
{{- if typeIs "string" .value }}
|
||||
{{- tpl .value .context }}
|
||||
{{ else }}
|
||||
{{- tpl (.value | toYaml) .context }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,14 @@
|
||||
{{- if .Values.startupScripts }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}-startup
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
data:
|
||||
{{- range $key, $value := .Values.startupScripts }}
|
||||
{{ $key }}: |
|
||||
{{- tpl $value $ | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,12 @@
|
||||
{{- if and .Values.database.password (not .Values.database.existingSecret) -}}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" $ }}-database
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" $ | nindent 4 }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
password: {{ .Values.database.password | quote }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,4 @@
|
||||
{{- range .Values.extraManifests }}
|
||||
---
|
||||
{{ include "keycloak.render" (dict "value" . "context" $) }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,23 @@
|
||||
{{- if .Values.autoscaling.enabled }}
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
{{- range $key, $value := .Values.autoscaling.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
name: {{ include "keycloak.fullname" . }}
|
||||
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
{{- toYaml .Values.autoscaling.metrics | nindent 4 }}
|
||||
behavior:
|
||||
{{- toYaml .Values.autoscaling.behavior | nindent 4 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,118 @@
|
||||
{{- $httpRoute := .Values.httpRoute -}}
|
||||
{{- if $httpRoute.enabled -}}
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
{{- range $key, $value := $httpRoute.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with $httpRoute.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
parentRefs:
|
||||
{{- if $httpRoute.listenerSet.enabled }}
|
||||
- kind: ListenerSet
|
||||
name: {{ include "keycloak.fullname" $ }}
|
||||
namespace: {{ $.Release.Namespace }}
|
||||
{{- else }}
|
||||
{{- with $httpRoute.parentRefs }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if $httpRoute.listenerSet.enabled }}
|
||||
{{- $hostnames := list }}
|
||||
{{- range $httpRoute.listenerSet.listeners }}
|
||||
{{- if .hostname }}
|
||||
{{- $hostnames = append $hostnames .hostname }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with $hostnames }}
|
||||
hostnames:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- with $httpRoute.hostnames }}
|
||||
hostnames:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range $httpRoute.rules }}
|
||||
{{- with .matches }}
|
||||
- matches:
|
||||
{{- range . }}
|
||||
{{- if .path }}
|
||||
- path:
|
||||
type: {{ .path.type }}
|
||||
value: {{ tpl .path.value $ }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{ . | toYaml | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .filters }}
|
||||
filters:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
backendRefs:
|
||||
- name: {{ include "keycloak.fullname" $ }}-http
|
||||
port: {{ $httpRoute.servicePort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
---
|
||||
{{- if $httpRoute.console.enabled }}
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}-console
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
{{- range $key, $value := $httpRoute.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := $httpRoute.console.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with $httpRoute.console.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
parentRefs:
|
||||
{{- with pluck "parentRefs" $httpRoute.console $httpRoute | first }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with pluck "hostnames" $httpRoute.console $httpRoute | first }}
|
||||
hostnames:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range $httpRoute.console.rules }}
|
||||
{{- with .matches }}
|
||||
- matches:
|
||||
{{- range . }}
|
||||
{{- if .path }}
|
||||
- path:
|
||||
type: {{ .path.type }}
|
||||
value: {{ tpl .path.value $ }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{ . | toYaml | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .filters }}
|
||||
filters:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
backendRefs:
|
||||
- name: {{ include "keycloak.fullname" $ }}-http
|
||||
port: {{ $httpRoute.servicePort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,116 @@
|
||||
{{- $ingress := .Values.ingress -}}
|
||||
{{- if $ingress.enabled -}}
|
||||
{{- $apiVersion := "networking.k8s.io/v1" -}}
|
||||
{{- $fullName := ( include "keycloak.fullname" . ) -}}
|
||||
apiVersion: {{ $apiVersion }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
{{- with $ingress.annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := . }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
{{- range $key, $value := $ingress.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if $ingress.ingressClassName }}
|
||||
ingressClassName: {{ $ingress.ingressClassName }}
|
||||
{{- end }}
|
||||
{{- if $ingress.tls }}
|
||||
tls:
|
||||
{{- range $ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ tpl . $ | quote }}
|
||||
{{- end }}
|
||||
{{- with .secretName }}
|
||||
secretName: {{ tpl . $ }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.rules }}
|
||||
- host: {{ tpl .host $ | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ tpl .path $ | quote }}
|
||||
pathType: {{ .pathType }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ default (printf "%s-http" $fullName) (.serviceName) }}
|
||||
port:
|
||||
name: {{ default ($ingress.servicePort) (.servicePort) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if $ingress.console.enabled }}
|
||||
---
|
||||
apiVersion: {{ $apiVersion }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}-console
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
{{- with $ingress.console.annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := . }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
{{- range $key, $value := $ingress.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := $ingress.console.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if $ingress.console.ingressClassName }}
|
||||
ingressClassName: {{ $ingress.console.ingressClassName }}
|
||||
{{- end }}
|
||||
{{- if $ingress.console.tls }}
|
||||
tls:
|
||||
{{- range $ingress.console.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ tpl . $ | quote }}
|
||||
{{- end }}
|
||||
{{- with .secretName }}
|
||||
secretName: {{ tpl . $ }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ else if $ingress.tls }}
|
||||
tls:
|
||||
{{- range $ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ tpl . $ | quote }}
|
||||
{{- end }}
|
||||
{{- with .secretName }}
|
||||
secretName: {{ tpl . $ }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.console.rules }}
|
||||
- host: {{ tpl .host $ | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ tpl .path $ | quote }}
|
||||
pathType: {{ .pathType }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ default (printf "%s-http" $fullName) (.serviceName) }}
|
||||
port:
|
||||
name: {{ default ($ingress.servicePort) (.servicePort) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,29 @@
|
||||
{{- $httpRoute := .Values.httpRoute -}}
|
||||
{{- $listenerSet := $httpRoute.listenerSet -}}
|
||||
{{- if and $httpRoute.enabled $listenerSet.enabled -}}
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: ListenerSet
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
{{- range $key, $value := $httpRoute.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := $listenerSet.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with $listenerSet.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
parentRef:
|
||||
name: {{ $listenerSet.parentRef.name }}
|
||||
{{- with $listenerSet.parentRef.namespace }}
|
||||
namespace: {{ . }}
|
||||
{{- end }}
|
||||
listeners:
|
||||
{{- toYaml $listenerSet.listeners | nindent 4 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,52 @@
|
||||
{{- if .Values.networkPolicy.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . | quote }}
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
{{- range $key, $value := .Values.networkPolicy.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
policyTypes:
|
||||
- Ingress
|
||||
{{- if .Values.networkPolicy.egress }}
|
||||
- Egress
|
||||
{{- end}}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
{{- include "keycloak.selectorLabels" . | nindent 6 }}
|
||||
ingress:
|
||||
{{- with .Values.networkPolicy.extraFrom }}
|
||||
- from:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
- protocol: TCP
|
||||
port: 8443
|
||||
{{ range $.Values.extraPorts }}
|
||||
- protocol: {{ default "TCP" .protocol }}
|
||||
port: {{ .containerPort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
{{- include "keycloak.selectorLabels" . | nindent 14 }}
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
- protocol: TCP
|
||||
port: 8443
|
||||
{{ range .Values.extraPorts }}
|
||||
- protocol: {{ default "TCP" .protocol }}
|
||||
port: {{ .containerPort }}
|
||||
{{- end }}
|
||||
{{- if .Values.networkPolicy.egress }}
|
||||
egress:
|
||||
{{- .Values.networkPolicy.egress | toYaml | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,14 @@
|
||||
{{- if .Values.podDisruptionBudget -}}
|
||||
apiVersion: {{ ternary "policy/v1" "policy/v1beta1" (semverCompare ">=1.21.0-0" .Capabilities.KubeVersion.Version) }}
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "keycloak.selectorLabels" . | nindent 6 }}
|
||||
{{- toYaml .Values.podDisruptionBudget | nindent 2 }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,29 @@
|
||||
{{- with .Values.prometheusRule -}}
|
||||
{{- if .enabled }}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: PrometheusRule
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" $ }}
|
||||
{{- with .namespace }}
|
||||
namespace: {{ . }}
|
||||
{{- else }}
|
||||
namespace: {{ include "keycloak.namespace" $ }}
|
||||
{{- end }}
|
||||
{{- with .annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := . }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" $ | nindent 4 }}
|
||||
{{- range $key, $value := .labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
groups:
|
||||
- name: {{ include "keycloak.fullname" $ }}
|
||||
rules:
|
||||
{{- toYaml .rules | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,27 @@
|
||||
{{- if and .Values.rbac.create .Values.rbac.rules }}
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
rules:
|
||||
{{- toYaml .Values.rbac.rules | nindent 2 }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ include "keycloak.fullname" . }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "keycloak.serviceAccountName" . }}
|
||||
namespace: {{ include "keycloak.namespace" . | quote }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,39 @@
|
||||
{{- $route := .Values.route -}}
|
||||
{{- if $route.enabled -}}
|
||||
apiVersion: route.openshift.io/v1
|
||||
kind: Route
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
{{- with $route.annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := . }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
{{- range $key, $value := $route.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if $route.host }}
|
||||
host: {{ tpl $route.host $ | quote }}
|
||||
{{- end }}
|
||||
path: {{ $route.path }}
|
||||
port:
|
||||
{{- if or (not $route.tls.enabled) (eq $route.tls.termination "edge") }}
|
||||
targetPort: http
|
||||
{{- else}}
|
||||
targetPort: https
|
||||
{{- end}}
|
||||
to:
|
||||
kind: Service
|
||||
name: {{ include "keycloak.fullname" $ }}-http
|
||||
weight: 100
|
||||
{{- if $route.tls.enabled }}
|
||||
tls:
|
||||
insecureEdgeTerminationPolicy: {{ $route.tls.insecureEdgeTerminationPolicy }}
|
||||
termination: {{ $route.tls.termination }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,30 @@
|
||||
{{- range $nameSuffix, $values := .Values.secrets }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" $ }}-{{ $nameSuffix }}
|
||||
namespace: {{ include "keycloak.namespace" $ }}
|
||||
{{- with $values.annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := . }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" $ | nindent 4 }}
|
||||
{{- range $key, $value := $values.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
type: {{ default "Opaque" $values.type }}
|
||||
{{- with $values.data }}
|
||||
data:
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- with $values.stringData }}
|
||||
stringData:
|
||||
{{- range $key, $value := . }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,30 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}-headless
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
{{- with .Values.serviceHeadless.annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := . }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
{{- range $key, $value := .Values.serviceHeadless.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/component: headless
|
||||
spec:
|
||||
type: ClusterIP
|
||||
clusterIP: None
|
||||
ports:
|
||||
- name: http
|
||||
port: {{ .Values.service.httpPort }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
{{- with .Values.serviceHeadless.extraPorts }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- include "keycloak.selectorLabels" . | nindent 4 }}
|
||||
@@ -0,0 +1,65 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}-http
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
{{- with .Values.service.annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := . }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
{{- range $key, $value := .Values.service.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/component: http
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
{{- if and (eq "LoadBalancer" .Values.service.type) .Values.service.loadBalancerIP }}
|
||||
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
|
||||
{{- end }}
|
||||
{{- if and (eq "LoadBalancer" .Values.service.type) .Values.service.loadBalancerSourceRanges }}
|
||||
loadBalancerSourceRanges:
|
||||
{{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- if or (eq "LoadBalancer" .Values.service.type) (eq "NodePort" .Values.service.type) }}
|
||||
externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy }}
|
||||
{{- end }}
|
||||
{{- if .Values.service.internalTrafficPolicy }}
|
||||
internalTrafficPolicy: {{ .Values.service.internalTrafficPolicy }}
|
||||
{{- end }}
|
||||
{{- if .Values.service.sessionAffinity }}
|
||||
sessionAffinity: {{ .Values.service.sessionAffinity }}
|
||||
{{- with .Values.service.sessionAffinityConfig }}
|
||||
sessionAffinityConfig:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: '{{ .Values.http.internalPort }}'
|
||||
port: 9000
|
||||
protocol: TCP
|
||||
targetPort: '{{ .Values.http.internalPort }}'
|
||||
- name: http
|
||||
port: {{ .Values.service.httpPort }}
|
||||
targetPort: http
|
||||
{{- if and (or (eq "NodePort" .Values.service.type) (eq "LoadBalancer" .Values.service.type) ) .Values.service.httpNodePort }}
|
||||
nodePort: {{ .Values.service.httpNodePort }}
|
||||
{{- end }}
|
||||
protocol: TCP
|
||||
{{- if .Values.service.httpsPort }}
|
||||
- name: https
|
||||
port: {{ .Values.service.httpsPort }}
|
||||
targetPort: https
|
||||
{{- if and (or (eq "NodePort" .Values.service.type) (eq "LoadBalancer" .Values.service.type) ) .Values.service.httpsNodePort }}
|
||||
nodePort: {{ .Values.service.httpsNodePort }}
|
||||
{{- end }}
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
{{- with .Values.service.extraPorts }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- include "keycloak.selectorLabels" . | nindent 4 }}
|
||||
@@ -0,0 +1,47 @@
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "keycloak.serviceAccountName" . }}
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := . }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
{{- range $key, $value := .Values.serviceAccount.labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.serviceAccount.imagePullSecrets }}
|
||||
imagePullSecrets: {{ toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
|
||||
|
||||
{{- if .Values.serviceAccount.allowReadPods }}
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: jgroups-kubeping-pod-reader-{{ include "keycloak.namespace" . }}
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get", "list"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: jgroups-kubeping-api-access-{{ include "keycloak.namespace" . }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: jgroups-kubeping-pod-reader-{{ include "keycloak.namespace" . }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "keycloak.serviceAccountName" . }}
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,54 @@
|
||||
{{- range $key, $serviceMonitor := dict "keycloakx" .Values.serviceMonitor "extra" .Values.extraServiceMonitor }}
|
||||
{{- with $serviceMonitor }}
|
||||
{{- if .enabled }}
|
||||
---
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" $ }}-{{ $key }}
|
||||
{{- with .namespace }}
|
||||
namespace: {{ . }}
|
||||
{{- else }}
|
||||
namespace: {{ include "keycloak.namespace" $ }}
|
||||
{{- end }}
|
||||
{{- with .annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := . }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" $ | nindent 4 }}
|
||||
{{- range $key, $value := .labels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- with .namespaceSelector }}
|
||||
namespaceSelector:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "keycloak.selectorLabels" $ | nindent 6 }}
|
||||
app.kubernetes.io/component: http
|
||||
endpoints:
|
||||
- port: {{ tpl .port $ | quote }}
|
||||
path: {{ tpl .path $ | quote }}
|
||||
scheme: {{ coalesce .scheme $.Values.http.internalScheme | lower }}
|
||||
interval: {{ .interval }}
|
||||
scrapeTimeout: {{ .scrapeTimeout }}
|
||||
{{- with .relabelings }}
|
||||
relabelings:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .metricRelabelings }}
|
||||
metricRelabelings:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .tlsConfig }}
|
||||
tlsConfig:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,253 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
{{- with .Values.statefulsetAnnotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := . }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
{{- range $key, $value := .Values.statefulsetLabels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "keycloak.selectorLabels" . | nindent 6 }}
|
||||
{{- if not .Values.autoscaling.enabled }}
|
||||
replicas: {{ .Values.replicas }}
|
||||
{{- end }}
|
||||
serviceName: {{ include "keycloak.fullname" . }}-headless
|
||||
podManagementPolicy: {{ .Values.podManagementPolicy }}
|
||||
updateStrategy:
|
||||
type: {{ .Values.updateStrategy }}
|
||||
{{- if not (eq (.Values.revisionHistoryLimit | toString) "") }}
|
||||
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
|
||||
{{- end }}
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config-startup: {{ include (print .Template.BasePath "/configmap-startup.yaml") . | sha256sum }}
|
||||
checksum/secrets: {{ tpl (toYaml .Values.secrets) . | sha256sum }}
|
||||
{{- range $key, $value := .Values.podAnnotations }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "keycloak.selectorLabels" . | nindent 8 }}
|
||||
{{- range $key, $value := .Values.commonLabels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.podLabels }}
|
||||
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if not .Values.skipInitContainers }}
|
||||
{{- if or .Values.dbchecker.enabled .Values.extraInitContainers }}
|
||||
initContainers:
|
||||
{{- if and .Values.dbchecker.enabled }}
|
||||
- name: dbchecker
|
||||
image: "{{ .Values.dbchecker.image.repository }}{{- if (.Values.dbchecker.image.digest) -}}@{{ .Values.dbchecker.image.digest }}{{- else -}}:{{ .Values.dbchecker.image.tag }} {{- end }}"
|
||||
imagePullPolicy: {{ .Values.dbchecker.image.pullPolicy }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.dbchecker.securityContext | nindent 12 }}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
echo 'Waiting for Database to become ready...'
|
||||
|
||||
until printf "." && nc -z -w 2 {{ required ".Values.database.hostname is required if dbchecker is enabled!" .Values.database.hostname }} {{ required ".Values.database.port is required if dbchecker is enabled!" .Values.database.port }}; do
|
||||
sleep 2;
|
||||
done;
|
||||
|
||||
echo 'Database OK ✓'
|
||||
resources:
|
||||
{{- toYaml .Values.dbchecker.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.extraInitContainers }}
|
||||
{{- tpl . $ | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: keycloak
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}{{- if (.Values.image.digest) -}}@{{ .Values.image.digest }}{{- else -}}:{{ .Values.image.tag | default .Chart.AppVersion }} {{- end }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
{{- if .Values.command }}
|
||||
command:
|
||||
{{- toYaml .Values.command | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.args }}
|
||||
args:
|
||||
{{- toYaml .Values.args | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.lifecycleHooks }}
|
||||
lifecycle:
|
||||
{{- tpl . $ | nindent 12 }}
|
||||
{{- end }}
|
||||
env:
|
||||
{{- if and (.Values.http.relativePath) (eq .Values.http.relativePath "/") }}
|
||||
- name: KC_HTTP_RELATIVE_PATH
|
||||
value: {{ tpl .Values.http.relativePath $ }}
|
||||
{{ else }}
|
||||
- name: KC_HTTP_RELATIVE_PATH
|
||||
value: {{ tpl .Values.http.relativePath $ | trimSuffix "/" }}
|
||||
{{- end }}
|
||||
{{- if .Values.http.managementRelativePath }}
|
||||
- name: KC_HTTP_MANAGEMENT_RELATIVE_PATH
|
||||
{{- if eq .Values.http.managementRelativePath "/" }}
|
||||
value: {{ tpl .Values.http.managementRelativePath $ }}
|
||||
{{- else }}
|
||||
value: {{ tpl .Values.http.managementRelativePath $ | trimSuffix "/" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if eq .Values.cache.stack "default" }}
|
||||
- name: KC_CACHE
|
||||
value: "ispn"
|
||||
- name: KC_CACHE_STACK
|
||||
value: "jdbc-ping"
|
||||
{{- end }}
|
||||
{{- if .Values.proxy.enabled }}
|
||||
- name: KC_PROXY_HEADERS
|
||||
value: {{ .Values.proxy.mode }}
|
||||
{{- end }}
|
||||
{{- if .Values.proxy.http.enabled }}
|
||||
- name: KC_HTTP_ENABLED
|
||||
value: "true"
|
||||
{{- end }}
|
||||
{{- if .Values.database.vendor }}
|
||||
- name: KC_DB
|
||||
value: {{ .Values.database.vendor }}
|
||||
{{- end }}
|
||||
{{- if .Values.database.hostname }}
|
||||
- name: KC_DB_URL_HOST
|
||||
value: {{ .Values.database.hostname }}
|
||||
{{- end }}
|
||||
{{- if .Values.database.port }}
|
||||
- name: KC_DB_URL_PORT
|
||||
value: {{ .Values.database.port | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.database.database }}
|
||||
- name: KC_DB_URL_DATABASE
|
||||
value: {{ .Values.database.database }}
|
||||
{{- end }}
|
||||
{{- if .Values.database.username }}
|
||||
- name: KC_DB_USERNAME
|
||||
value: {{ .Values.database.username }}
|
||||
{{- end }}
|
||||
{{- if or .Values.database.password .Values.database.existingSecret -}}
|
||||
{{- include "keycloak.databasePasswordEnv" . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.enabled }}
|
||||
- name: KC_METRICS_ENABLED
|
||||
value: "true"
|
||||
{{- end }}
|
||||
{{- if .Values.health.enabled }}
|
||||
- name: KC_HEALTH_ENABLED
|
||||
value: "true"
|
||||
{{- end }}
|
||||
{{- with .Values.extraEnv }}
|
||||
{{- tpl . $ | nindent 12 }}
|
||||
{{- end }}
|
||||
envFrom:
|
||||
{{- with .Values.extraEnvFrom }}
|
||||
{{- tpl . $ | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
- name: '{{ .Values.http.internalPort }}'
|
||||
containerPort: 9000
|
||||
protocol: TCP
|
||||
{{- if .Values.service.httpsPort }}
|
||||
- name: https
|
||||
containerPort: 8443
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
{{- with .Values.extraPorts }}
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.health.enabled }}
|
||||
{{- with .Values.livenessProbe }}
|
||||
livenessProbe:
|
||||
{{- tpl . $ | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.enabled }}
|
||||
{{- with .Values.readinessProbe }}
|
||||
readinessProbe:
|
||||
{{- tpl . $ | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end}}
|
||||
{{- with .Values.startupProbe }}
|
||||
startupProbe:
|
||||
{{- tpl . $ | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
volumeMounts:
|
||||
{{- with .Values.extraVolumeMounts }}
|
||||
{{- tpl . $ | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.extraContainers }}
|
||||
{{- tpl . $ | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "keycloak.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
{{- with .Values.hostAliases }}
|
||||
hostAliases:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
enableServiceLinks: {{ .Values.enableServiceLinks }}
|
||||
restartPolicy: {{ .Values.restartPolicy }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- tpl . $ | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.topologySpreadConstraints }}
|
||||
topologySpreadConstraints:
|
||||
{{- tpl . $ | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.priorityClassName }}
|
||||
priorityClassName: {{ . }}
|
||||
{{- end }}
|
||||
terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}
|
||||
volumes:
|
||||
{{- with .Values.startupScripts }}
|
||||
- name: startup
|
||||
configMap:
|
||||
name: {{ include "keycloak.fullname" $ }}-startup
|
||||
defaultMode: 0555
|
||||
items:
|
||||
{{- range $key, $value := . }}
|
||||
- key: {{ $key }}
|
||||
path: {{ $key }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.extraVolumes }}
|
||||
{{- tpl . $ | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.volumeClaimTemplates }}
|
||||
volumeClaimTemplates:
|
||||
{{- tpl . $ | nindent 4 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,67 @@
|
||||
{{- if .Values.test.enabled }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}-test
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
helm.sh/hook: test
|
||||
helm.sh/hook-delete-policy: hook-succeeded
|
||||
data:
|
||||
test.sh: |
|
||||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
|
||||
if ! python3 -c 'import selenium' &> /dev/null; then
|
||||
echo 'Installing selenium module...'
|
||||
python3 -m venv /tmp/test-venv
|
||||
/tmp/test-venv/bin/pip install -q selenium
|
||||
exec /tmp/test-venv/bin/python "$(dirname "$0")/test.py"
|
||||
fi
|
||||
|
||||
python3 "$(dirname "$0")/test.py"
|
||||
test.py: |
|
||||
import os
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from selenium.webdriver.support import expected_conditions
|
||||
|
||||
print('Creating chrome driver in headless mode')
|
||||
chrome_options = Options()
|
||||
chrome_options.add_argument("--headless")
|
||||
chrome_options.add_argument('--no-sandbox')
|
||||
chrome_options.add_argument('--disable-dev-shm-usage')
|
||||
driver = webdriver.Chrome(options=chrome_options)
|
||||
|
||||
base_url = 'http://{{ include "keycloak.fullname" . }}-http{{ if ne 80 (int .Values.service.httpPort) }}:{{ .Values.service.httpPort }}{{ end }}'
|
||||
|
||||
print('Opening Keycloak...')
|
||||
driver.get('{0}{{ tpl .Values.http.relativePath . | trimSuffix "/" }}/admin/'.format(base_url))
|
||||
|
||||
username = os.environ['KEYCLOAK_USER']
|
||||
password = os.environ['KEYCLOAK_PASSWORD']
|
||||
|
||||
username_input = WebDriverWait(driver, 30).until(expected_conditions.presence_of_element_located((By.ID, "username")))
|
||||
password_input = WebDriverWait(driver, 30).until(expected_conditions.presence_of_element_located((By.ID, "password")))
|
||||
login_button = WebDriverWait(driver, 30).until(expected_conditions.presence_of_element_located((By.ID, "kc-login")))
|
||||
|
||||
print('Entering username...')
|
||||
username_input.send_keys(username)
|
||||
|
||||
print('Entering password...')
|
||||
password_input.send_keys(password)
|
||||
|
||||
print('Clicking login button...')
|
||||
login_button.click()
|
||||
|
||||
WebDriverWait(driver, 30).until(lambda driver: '{{ tpl .Values.http.relativePath . | trimSuffix "/" }}/admin/master/console/' in driver.current_url)
|
||||
|
||||
print('Admin console visible. Login successful.')
|
||||
|
||||
driver.quit()
|
||||
|
||||
{{- end }}
|
||||
@@ -0,0 +1,45 @@
|
||||
{{- if .Values.test.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: {{ include "keycloak.fullname" . }}-test
|
||||
namespace: {{ include "keycloak.namespace" . }}
|
||||
labels:
|
||||
{{- include "keycloak.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: test
|
||||
annotations:
|
||||
helm.sh/hook: test
|
||||
helm.sh/hook-delete-policy: {{ .Values.test.deletionPolicy }}
|
||||
spec:
|
||||
securityContext:
|
||||
{{- toYaml .Values.test.podSecurityContext | nindent 4 }}
|
||||
containers:
|
||||
- name: keycloak-test
|
||||
image: "{{ .Values.test.image.repository }}{{- if (.Values.test.image.digest) -}}@{{ .Values.test.image.digest }}{{- else -}}:{{ .Values.test.image.tag }} {{- end }}"
|
||||
imagePullPolicy: {{ .Values.test.image.pullPolicy }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.test.securityContext | nindent 8 }}
|
||||
command:
|
||||
- bash
|
||||
args:
|
||||
- /tests/test.sh
|
||||
env:
|
||||
- name: KEYCLOAK_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "keycloak.fullname" . }}-admin-creds
|
||||
key: user
|
||||
- name: KEYCLOAK_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "keycloak.fullname" . }}-admin-creds
|
||||
key: password
|
||||
volumeMounts:
|
||||
- name: tests
|
||||
mountPath: /tests
|
||||
volumes:
|
||||
- name: tests
|
||||
configMap:
|
||||
name: {{ include "keycloak.fullname" . }}-test
|
||||
restartPolicy: Never
|
||||
{{- end }}
|
||||
@@ -0,0 +1,635 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema#",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"image"
|
||||
],
|
||||
"definitions": {
|
||||
"httpRoute": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"type": "object"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object"
|
||||
},
|
||||
"parentRefs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"sectionName": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"hostnames": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$comment": "don't allow additionalProperties to make sure backendRefs isn't set by the user",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"matches": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$comment": "don't allow additionalProperties, only path matcher supported",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"filters": {
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"image": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"repository",
|
||||
"tag"
|
||||
],
|
||||
"properties": {
|
||||
"pullPolicy": {
|
||||
"type": "string",
|
||||
"pattern": "^(Always|Never|IfNotPresent)$"
|
||||
},
|
||||
"repository": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": ["string", "integer"]
|
||||
},
|
||||
"digest": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"imagePullSecrets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"affinity": {
|
||||
"type": "string"
|
||||
},
|
||||
"args": {
|
||||
"type": "array"
|
||||
},
|
||||
"clusterDomain": {
|
||||
"type": "string"
|
||||
},
|
||||
"command": {
|
||||
"type": "array"
|
||||
},
|
||||
"commonLabels": {
|
||||
"type": "object"
|
||||
},
|
||||
"enableServiceLinks": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"extraContainers": {
|
||||
"type": "string"
|
||||
},
|
||||
"extraEnv": {
|
||||
"type": "string"
|
||||
},
|
||||
"extraEnvFrom": {
|
||||
"type": "string"
|
||||
},
|
||||
"extraInitContainers": {
|
||||
"type": "string"
|
||||
},
|
||||
"extraPorts": {
|
||||
"type": "array"
|
||||
},
|
||||
"extraVolumeMounts": {
|
||||
"type": "string"
|
||||
},
|
||||
"extraVolumes": {
|
||||
"type": "string"
|
||||
},
|
||||
"volumeClaimTemplates": {
|
||||
"type": "string"
|
||||
},
|
||||
"fullnameOverride": {
|
||||
"type": "string"
|
||||
},
|
||||
"hostAliases": {
|
||||
"type": "array"
|
||||
},
|
||||
"http": {
|
||||
"relativePath": "string",
|
||||
"managementRelativePath": "string",
|
||||
"internalPort": "string",
|
||||
"internalScheme": "string"
|
||||
},
|
||||
"httpRoute": {
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/httpRoute" },
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"servicePort": {
|
||||
"type": "integer"
|
||||
},
|
||||
"console": {
|
||||
"$ref": "#/definitions/httpRoute"
|
||||
},
|
||||
"listenerSet": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"annotations": {
|
||||
"type": "object"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object"
|
||||
},
|
||||
"parentRef": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"namespace": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"listeners": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"image": {
|
||||
"$ref": "#/definitions/image"
|
||||
},
|
||||
"imagePullSecrets": {
|
||||
"$ref": "#/definitions/imagePullSecrets"
|
||||
},
|
||||
"ingress": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"type": "object"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object"
|
||||
},
|
||||
"rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"paths": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"pathType": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"servicePort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"tls": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"hosts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"secretName": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"lifecycleHooks": {
|
||||
"type": "string"
|
||||
},
|
||||
"livenessProbe": {
|
||||
"type": "string"
|
||||
},
|
||||
"nameOverride": {
|
||||
"type": "string"
|
||||
},
|
||||
"namespaceOverride": {
|
||||
"type": "string"
|
||||
},
|
||||
"nodeSelector": {
|
||||
"type": "object"
|
||||
},
|
||||
"dbchecker": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"image": {
|
||||
"$ref": "#/definitions/image"
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limits": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"type": "string"
|
||||
},
|
||||
"memory": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"type": "string"
|
||||
},
|
||||
"memory": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityContext": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"podAnnotations": {
|
||||
"type": "object"
|
||||
},
|
||||
"podDisruptionBudget": {
|
||||
"type": "object"
|
||||
},
|
||||
"podLabels": {
|
||||
"type": "object"
|
||||
},
|
||||
"podManagementPolicy": {
|
||||
"type": "string"
|
||||
},
|
||||
"updateStrategy": {
|
||||
"type": "string"
|
||||
},
|
||||
"podSecurityContext": {
|
||||
"type": "object"
|
||||
},
|
||||
"cache": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"stack": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"proxy": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"mode": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"metrics": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"health": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"database": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vendor": {
|
||||
"type": "string"
|
||||
},
|
||||
"hostname": {
|
||||
"type": "string"
|
||||
},
|
||||
"port": {
|
||||
"type": "integer"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"database": {
|
||||
"type": "string"
|
||||
},
|
||||
"existingSecret": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"priorityClassName": {
|
||||
"type": "string"
|
||||
},
|
||||
"prometheusRule": {
|
||||
"type": "object"
|
||||
},
|
||||
"serviceMonitor": {
|
||||
"type": "object"
|
||||
},
|
||||
"extraServiceMonitor": {
|
||||
"type": "object"
|
||||
},
|
||||
"readinessProbe": {
|
||||
"type": "string"
|
||||
},
|
||||
"replicas": {
|
||||
"type": "integer"
|
||||
},
|
||||
"resources": {
|
||||
"type": "object"
|
||||
},
|
||||
"restartPolicy": {
|
||||
"type": "string"
|
||||
},
|
||||
"route": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"type": "object"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"tls": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"secrets": {
|
||||
"type": "object"
|
||||
},
|
||||
"securityContext": {
|
||||
"type": "object"
|
||||
},
|
||||
"service": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"type": "object"
|
||||
},
|
||||
"extraPorts": {
|
||||
"type": "array"
|
||||
},
|
||||
"loadBalancerSourceRanges": {
|
||||
"type": "array"
|
||||
},
|
||||
"httpNodePort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"httpPort": {
|
||||
"type": "integer"
|
||||
},
|
||||
"httpsNodePort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"httpsPort": {
|
||||
"type": "integer"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object"
|
||||
},
|
||||
"nodePort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"loadBalancerIP": {
|
||||
"type": "string"
|
||||
},
|
||||
"internalTrafficPolicy": {
|
||||
"type": "string"
|
||||
},
|
||||
"sessionAffinity": {
|
||||
"type": "string"
|
||||
},
|
||||
"sessionAffinityConfig": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"serviceHeadless": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"type": "object"
|
||||
},
|
||||
"extraPorts": {
|
||||
"type": "array"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"serviceAccount": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"type": "object"
|
||||
},
|
||||
"create": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"allowReadPods": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"imagePullSecrets": {
|
||||
"$ref": "#/definitions/imagePullSecrets"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"rbac": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"create": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"statefulsetAnnotations": {
|
||||
"type": "object"
|
||||
},
|
||||
"statefulsetLabels": {
|
||||
"type": "object"
|
||||
},
|
||||
"terminationGracePeriodSeconds": {
|
||||
"type": "integer"
|
||||
},
|
||||
"autoscaling": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object"
|
||||
},
|
||||
"minReplicas": {
|
||||
"type": "integer"
|
||||
},
|
||||
"maxReplicas": {
|
||||
"type": "integer"
|
||||
},
|
||||
"metrics": {
|
||||
"type": "array"
|
||||
},
|
||||
"behavior": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"image": {
|
||||
"$ref": "#/definitions/image"
|
||||
},
|
||||
"podSecurityContext": {
|
||||
"type": "object"
|
||||
},
|
||||
"securityContext": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tolerations": {
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,691 @@
|
||||
# Optionally override the fully qualified name
|
||||
fullnameOverride: ""
|
||||
|
||||
# Optionally override the name
|
||||
nameOverride: ""
|
||||
|
||||
# Optionally override the namespace for all resources. Useful for umbrella charts that
|
||||
# deploy multiple aliased keycloak instances each into their own namespace.
|
||||
namespaceOverride: ""
|
||||
|
||||
# The number of replicas to create (has no effect if autoscaling enabled)
|
||||
replicas: 1
|
||||
|
||||
# Additional labels applied to every resource in this chart, and on the StatefulSet's pods
|
||||
commonLabels: {}
|
||||
|
||||
image:
|
||||
# The Keycloak image repository
|
||||
repository: quay.io/keycloak/keycloak
|
||||
# Overrides the Keycloak image tag whose default is the chart appVersion
|
||||
tag: "26.7.2"
|
||||
# Overrides the Keycloak image tag with a specific digest
|
||||
digest: ""
|
||||
# The Keycloak image pull policy
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# Image pull secrets for the Pod
|
||||
imagePullSecrets: []
|
||||
# - name: myRegistrKeySecretName
|
||||
|
||||
# Mapping between IPs and hostnames that will be injected as entries in the Pod's hosts files
|
||||
hostAliases: []
|
||||
# - ip: "1.2.3.4"
|
||||
# hostnames:
|
||||
# - "my.host.com"
|
||||
|
||||
# Indicates whether information about services should be injected into Pod's environment variables, matching the syntax of Docker links
|
||||
enableServiceLinks: true
|
||||
|
||||
# Pod management policy. One of `Parallel` or `OrderedReady`
|
||||
podManagementPolicy: OrderedReady
|
||||
|
||||
# StatefulSet's update strategy
|
||||
updateStrategy: RollingUpdate
|
||||
|
||||
# StatefulSet's revision history limit (number of old ReplicaSets to retain). Defaults to 10 if not set
|
||||
revisionHistoryLimit: ""
|
||||
|
||||
# Pod restart policy. One of `Always`, `OnFailure`, or `Never`
|
||||
restartPolicy: Always
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a ServiceAccount should be created
|
||||
create: true
|
||||
# Specifies whether the ServiceAccount can get and list pods
|
||||
allowReadPods: 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: ""
|
||||
# Additional annotations for the ServiceAccount
|
||||
annotations: {}
|
||||
# Additional labels for the ServiceAccount
|
||||
labels: {}
|
||||
# Image pull secrets that are attached to the ServiceAccount
|
||||
imagePullSecrets: []
|
||||
# Automount API credentials for the Service Account
|
||||
automountServiceAccountToken: true
|
||||
|
||||
rbac:
|
||||
create: false
|
||||
rules: []
|
||||
# RBAC rules for KUBE_PING
|
||||
# - apiGroups:
|
||||
# - ""
|
||||
# resources:
|
||||
# - pods
|
||||
# verbs:
|
||||
# - get
|
||||
# - list
|
||||
|
||||
# SecurityContext for the entire Pod. Every container running in the Pod will inherit this SecurityContext. This might be relevant when other components of the environment inject additional containers into running Pods (service meshes are the most prominent example for this)
|
||||
podSecurityContext:
|
||||
fsGroup: 1000
|
||||
|
||||
# SecurityContext for the Keycloak container
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
runAsNonRoot: true
|
||||
|
||||
# Additional init containers, e. g. for providing custom themes
|
||||
extraInitContainers: ""
|
||||
|
||||
# When using service meshes which rely on a sidecar, it may be necessary to skip init containers altogether,
|
||||
# since the sidecar doesn't start until the init containers are done, and the sidecar may be required
|
||||
# for network access.
|
||||
# For example, Istio in strict mTLS mode prevents the dbchecker init container from ever completing
|
||||
skipInitContainers: false
|
||||
|
||||
# Additional sidecar containers, e. g. for a database proxy, such as Google's cloudsql-proxy
|
||||
extraContainers: ""
|
||||
|
||||
# Lifecycle hooks for the Keycloak container
|
||||
lifecycleHooks: |
|
||||
# postStart:
|
||||
# exec:
|
||||
# command:
|
||||
# - /bin/sh
|
||||
# - -c
|
||||
# - ls
|
||||
|
||||
# Termination grace period in seconds for Keycloak shutdown. Clusters with a large cache might need to extend this to give Infinispan more time to rebalance
|
||||
terminationGracePeriodSeconds: 60
|
||||
|
||||
# The internal Kubernetes cluster domain
|
||||
clusterDomain: cluster.local
|
||||
|
||||
## Overrides the default entrypoint of the Keycloak container
|
||||
command: []
|
||||
|
||||
## Overrides the default args for the Keycloak container
|
||||
args: []
|
||||
|
||||
# Additional environment variables for Keycloak
|
||||
extraEnv: ""
|
||||
# - name: KC_LOG_LEVEL
|
||||
# value: DEBUG
|
||||
|
||||
# Additional environment variables for Keycloak mapped from Secret or ConfigMap
|
||||
extraEnvFrom: ""
|
||||
|
||||
# Pod priority class name
|
||||
priorityClassName: ""
|
||||
|
||||
# Pod affinity
|
||||
affinity: |
|
||||
podAntiAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- labelSelector:
|
||||
matchLabels:
|
||||
{{- include "keycloak.selectorLabels" . | nindent 10 }}
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/component
|
||||
operator: NotIn
|
||||
values:
|
||||
- test
|
||||
topologyKey: kubernetes.io/hostname
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
{{- include "keycloak.selectorLabels" . | nindent 12 }}
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/component
|
||||
operator: NotIn
|
||||
values:
|
||||
- test
|
||||
topologyKey: topology.kubernetes.io/zone
|
||||
|
||||
# Topology spread constraints template
|
||||
topologySpreadConstraints:
|
||||
|
||||
# Node labels for Pod assignment
|
||||
nodeSelector: {}
|
||||
|
||||
# Node taints to tolerate
|
||||
tolerations: []
|
||||
|
||||
# Additional Pod labels
|
||||
podLabels: {}
|
||||
|
||||
# Additional Pod annotations
|
||||
podAnnotations: {}
|
||||
|
||||
# Liveness probe configuration
|
||||
livenessProbe: |
|
||||
httpGet:
|
||||
path: '{{ tpl (coalesce .Values.http.managementRelativePath .Values.http.relativePath) $ | trimSuffix "/" }}/health/live'
|
||||
port: '{{ .Values.http.internalPort }}'
|
||||
scheme: '{{ .Values.http.internalScheme }}'
|
||||
initialDelaySeconds: 0
|
||||
timeoutSeconds: 5
|
||||
|
||||
# Readiness probe configuration
|
||||
readinessProbe: |
|
||||
httpGet:
|
||||
path: '{{ tpl (coalesce .Values.http.managementRelativePath .Values.http.relativePath) $ | trimSuffix "/" }}/health/ready'
|
||||
port: '{{ .Values.http.internalPort }}'
|
||||
scheme: '{{ .Values.http.internalScheme }}'
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 1
|
||||
|
||||
# Startup probe configuration
|
||||
startupProbe: |
|
||||
httpGet:
|
||||
path: '{{ tpl (coalesce .Values.http.managementRelativePath .Values.http.relativePath) $ | trimSuffix "/" }}/health'
|
||||
port: '{{ .Values.http.internalPort }}'
|
||||
scheme: '{{ .Values.http.internalScheme }}'
|
||||
initialDelaySeconds: 15
|
||||
timeoutSeconds: 1
|
||||
failureThreshold: 60
|
||||
periodSeconds: 5
|
||||
|
||||
# Pod resource requests and limits
|
||||
resources: {}
|
||||
# requests:
|
||||
# cpu: "500m"
|
||||
# memory: "1024Mi"
|
||||
# limits:
|
||||
# cpu: "500m"
|
||||
# memory: "1024Mi"
|
||||
|
||||
# Add additional volumes, e. g. for custom themes
|
||||
extraVolumes: ""
|
||||
|
||||
# Add volume claim templates to the StatefulSet, e. g. for dynamic provisioning
|
||||
volumeClaimTemplates: ""
|
||||
# - metadata:
|
||||
# name: themes
|
||||
# spec:
|
||||
# accessModes: [ "ReadWriteOncePod" ]
|
||||
# storageClassName: "my-storage-class"
|
||||
# resources:
|
||||
# requests:
|
||||
# storage: 1Gi
|
||||
|
||||
# Add additional volumes mounts, e. g. for custom themes
|
||||
extraVolumeMounts: ""
|
||||
|
||||
# Add additional ports, e. g. for admin console or exposing JGroups ports
|
||||
extraPorts: []
|
||||
|
||||
# Pod disruption budget
|
||||
podDisruptionBudget: {}
|
||||
# maxUnavailable: 1
|
||||
# minAvailable: 1
|
||||
|
||||
# Annotations for the StatefulSet
|
||||
statefulsetAnnotations: {}
|
||||
|
||||
# Additional labels for the StatefulSet
|
||||
statefulsetLabels: {}
|
||||
|
||||
# Configuration for secrets that should be created
|
||||
secrets: {}
|
||||
# mysecret:
|
||||
# type: {}
|
||||
# annotations: {}
|
||||
# labels: {}
|
||||
# stringData: {}
|
||||
# data: {}
|
||||
|
||||
service:
|
||||
# Annotations for HTTP service
|
||||
annotations: {}
|
||||
# Additional labels for HTTP Service
|
||||
labels: {}
|
||||
# key: value
|
||||
# The Service type
|
||||
type: ClusterIP
|
||||
# Optional IP for the load balancer. Used for services of type LoadBalancer only
|
||||
loadBalancerIP: ""
|
||||
# The http Service port
|
||||
httpPort: 80
|
||||
# The HTTP Service node port if type is NodePort
|
||||
httpNodePort: null
|
||||
# The HTTPS Service port
|
||||
httpsPort: 8443
|
||||
# The HTTPS Service node port if type is NodePort
|
||||
httpsNodePort: null
|
||||
# Additional Service ports, e. g. for custom admin console
|
||||
extraPorts: []
|
||||
# When using Service type LoadBalancer, you can restrict source ranges allowed
|
||||
# to connect to the LoadBalancer, e. g. will result in Security Groups
|
||||
# (or equivalent) with inbound source ranges allowed to connect
|
||||
loadBalancerSourceRanges: []
|
||||
# When using Service type LoadBalancer or NodePort, you can preserve the source IP seen in the container
|
||||
# by changing the default (Cluster) to be Local.
|
||||
# See https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip
|
||||
externalTrafficPolicy: "Cluster"
|
||||
# Controls how traffic from internal sources is routed. Valid values: Cluster, Local.
|
||||
# See https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/
|
||||
internalTrafficPolicy: ""
|
||||
# Session affinity
|
||||
# See https://kubernetes.io/docs/concepts/services-networking/service/#proxy-mode-userspace
|
||||
sessionAffinity: ""
|
||||
# Session affinity config
|
||||
sessionAffinityConfig: {}
|
||||
|
||||
serviceHeadless:
|
||||
# Annotations for headless service
|
||||
annotations: {}
|
||||
# Additional labels for headless service
|
||||
labels: {}
|
||||
# Add additional ports to the headless service, e. g. for admin console or exposing JGroups ports
|
||||
extraPorts: []
|
||||
|
||||
# -- Expose the service via gateway-api HTTPRoute
|
||||
# Requires Gateway API resources and suitable controller installed within the cluster
|
||||
# (see: https://gateway-api.sigs.k8s.io/guides/)
|
||||
httpRoute:
|
||||
# HTTPRoute enabled.
|
||||
enabled: false
|
||||
# Additional HTTPRoute labels
|
||||
labels: {}
|
||||
# HTTPRoute annotations.
|
||||
annotations: {}
|
||||
# The Service port targeted by the HTTPRoute, MUST BE AN NUMBER
|
||||
servicePort: 80
|
||||
# Which Gateways this Route is attached to.
|
||||
parentRefs:
|
||||
- name: gateway
|
||||
sectionName: http
|
||||
# namespace: default
|
||||
# Hostnames matching HTTP header.
|
||||
hostnames:
|
||||
- chart-example.local
|
||||
# List of rules and filters applied.
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: '{{ tpl .Values.http.relativePath $ | trimSuffix "/" }}/'
|
||||
|
||||
# -- Create a ListenerSet resource to attach listeners to an existing Gateway
|
||||
# without requiring write access to the Gateway resource itself. Useful for
|
||||
# namespace-level configuration where app owners do not have Gateway write access.
|
||||
# When enabled, the HTTPRoute parentRefs are auto-derived from the ListenerSet name,
|
||||
# and hostnames are derived from listener hostnames; httpRoute.parentRefs and
|
||||
# httpRoute.hostnames are unused.
|
||||
listenerSet:
|
||||
# If `true`, a ListenerSet resource is created alongside the HTTPRoute
|
||||
enabled: false
|
||||
# Additional ListenerSet labels
|
||||
labels: {}
|
||||
# ListenerSet annotations
|
||||
annotations: {}
|
||||
# The Gateway this ListenerSet attaches to
|
||||
parentRef:
|
||||
name: gateway
|
||||
# namespace: envoy-gateway-system
|
||||
# Listeners to attach to the Gateway. Passed through as-is.
|
||||
# Listener hostnames are used to populate the HTTPRoute hostnames field.
|
||||
listeners: []
|
||||
# - name: http
|
||||
# hostname: keycloak.example.com
|
||||
# port: 80
|
||||
# protocol: HTTP
|
||||
# allowedRoutes:
|
||||
# namespaces:
|
||||
# from: Same
|
||||
|
||||
# HTTPRoute for console only (/auth/admin)
|
||||
console:
|
||||
# If `true`, an HTTPRoute is created for console path only
|
||||
enabled: false
|
||||
# Additional HTTPRoute labels
|
||||
labels: {}
|
||||
# HTTPRoute annotations.
|
||||
annotations: {}
|
||||
# Which Gateways this Route is attached to.
|
||||
parentRefs:
|
||||
- name: gateway
|
||||
sectionName: http
|
||||
# namespace: default
|
||||
# Hostnames matching HTTP header.
|
||||
hostnames:
|
||||
- chart-example.local
|
||||
# List of rules and filters applied.
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: '{{ tpl .Values.http.relativePath $ | trimSuffix "/" }}/admin'
|
||||
|
||||
ingress:
|
||||
# If `true`, an Ingress is created
|
||||
enabled: false
|
||||
# The name of the Ingress Class associated with this ingress
|
||||
ingressClassName: ""
|
||||
# The Service port targeted by the Ingress
|
||||
servicePort: http
|
||||
# Ingress annotations
|
||||
annotations: {}
|
||||
## Resolve HTTP 502 error using ingress-nginx:
|
||||
## See https://www.ibm.com/support/pages/502-error-ingress-keycloak-response
|
||||
# nginx.ingress.kubernetes.io/proxy-buffer-size: 128k
|
||||
|
||||
# Additional Ingress labels
|
||||
labels: {}
|
||||
# List of rules for the Ingress
|
||||
rules:
|
||||
-
|
||||
# Ingress host
|
||||
host: '{{ .Release.Name }}.keycloak.example.com'
|
||||
# Paths for the host
|
||||
paths:
|
||||
- path: '{{ tpl .Values.http.relativePath $ | trimSuffix "/" }}/'
|
||||
pathType: Prefix
|
||||
# serviceName: "" # Optional: Override backend service name (e.g., for AWS ALB action annotations)
|
||||
# servicePort: "" # Optional: Override backend service port name
|
||||
# TLS configuration
|
||||
tls: []
|
||||
# - hosts:
|
||||
# - keycloak.example.com
|
||||
# secretName: ""
|
||||
|
||||
# ingress for console only (/auth/admin)
|
||||
console:
|
||||
# If `true`, an Ingress is created for console path only
|
||||
enabled: false
|
||||
# The name of Ingress Class associated with the console ingress only
|
||||
ingressClassName: ""
|
||||
# Ingress annotations for console ingress only
|
||||
# Useful to set nginx.ingress.kubernetes.io/whitelist-source-range particularly
|
||||
annotations: {}
|
||||
# Additional Ingress labels for console path only
|
||||
labels: {}
|
||||
rules:
|
||||
-
|
||||
# Ingress host
|
||||
host: '{{ .Release.Name }}.keycloak.example.com'
|
||||
# Paths for the host
|
||||
paths:
|
||||
- path: '{{ tpl .Values.http.relativePath $ | trimSuffix "/" }}/admin'
|
||||
pathType: Prefix
|
||||
# serviceName: "" # Optional: Override backend service name (e.g., for AWS ALB action annotations)
|
||||
# servicePort: "" # Optional: Override backend service port name
|
||||
|
||||
# Console TLS configuration
|
||||
tls: []
|
||||
# - hosts:
|
||||
# - console.keycloak.example.com
|
||||
# secretName: ""
|
||||
|
||||
## Network policy configuration
|
||||
# https://kubernetes.io/docs/concepts/services-networking/network-policies/
|
||||
networkPolicy:
|
||||
# If true, the Network policies are deployed
|
||||
enabled: false
|
||||
|
||||
# Additional Network policy labels
|
||||
labels: {}
|
||||
|
||||
# Define all other external allowed source
|
||||
# See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#networkpolicypeer-v1-networking-k8s-io
|
||||
extraFrom: []
|
||||
|
||||
# Define egress networkpolicies for the Keycloak pods (external database for example)
|
||||
# See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#networkpolicyegressrule-v1-networking-k8s-io
|
||||
# egress:
|
||||
# - to:
|
||||
# - ipBlock:
|
||||
# cidr: 192.168.1.30/32
|
||||
# ports:
|
||||
# - protocol: TCP
|
||||
# port: 3306
|
||||
egress: []
|
||||
|
||||
route:
|
||||
# If `true`, an OpenShift Route is created
|
||||
enabled: false
|
||||
# Path for the Route
|
||||
path: /
|
||||
# Route annotations
|
||||
annotations: {}
|
||||
# Additional Route labels
|
||||
labels: {}
|
||||
# Host name for the Route
|
||||
host: ""
|
||||
# TLS configuration
|
||||
tls:
|
||||
# If `true`, TLS is enabled for the Route
|
||||
enabled: true
|
||||
# Insecure edge termination policy of the Route. Can be `None`, `Redirect`, or `Allow`
|
||||
insecureEdgeTerminationPolicy: Redirect
|
||||
# TLS termination of the route. Can be `edge`, `passthrough`, or `reencrypt`
|
||||
termination: edge
|
||||
|
||||
dbchecker:
|
||||
enabled: false
|
||||
image:
|
||||
# Docker image used to check Database readiness at startup
|
||||
repository: docker.io/busybox
|
||||
# Image tag for the dbchecker image
|
||||
tag: 1.37
|
||||
# Image pull policy for the dbchecker image
|
||||
pullPolicy: IfNotPresent
|
||||
# SecurityContext for the dbchecker container
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
runAsNonRoot: true
|
||||
# Resource requests and limits for the dbchecker container
|
||||
resources:
|
||||
requests:
|
||||
cpu: "20m"
|
||||
memory: "32Mi"
|
||||
limits:
|
||||
cpu: "20m"
|
||||
memory: "32Mi"
|
||||
|
||||
database:
|
||||
# don't create secret for db password. Instead use existing k8s secret
|
||||
# existingSecret: "my-existent-dbpass-secret"
|
||||
# existingSecretKey: "password"
|
||||
existingSecret: ""
|
||||
existingSecretKey: ""
|
||||
# E.g. dev-file, dev-mem, mariadb, mssql, mysql, oracle or postgres
|
||||
vendor:
|
||||
hostname:
|
||||
port:
|
||||
database:
|
||||
username:
|
||||
password:
|
||||
|
||||
cache:
|
||||
# Use "custom" to disable automatic cache configuration
|
||||
stack: default
|
||||
|
||||
proxy:
|
||||
enabled: true
|
||||
mode: forwarded
|
||||
http:
|
||||
enabled: true
|
||||
|
||||
metrics:
|
||||
enabled: true
|
||||
|
||||
health:
|
||||
enabled: true
|
||||
|
||||
http:
|
||||
# For backwards compatibility reasons we set this to the value used by previous Keycloak versions.
|
||||
relativePath: "/auth"
|
||||
# Set the relative path for Keycloak's management interface (KC_HTTP_MANAGEMENT_RELATIVE_PATH).
|
||||
# This controls the path prefix for health and metrics endpoints served on the management port (9000).
|
||||
# When empty, the env var is not set and Keycloak inherits the value from `http.relativePath`.
|
||||
# Set to "/" to serve management endpoints at the root (e.g. /health, /metrics).
|
||||
managementRelativePath: ""
|
||||
internalPort: http-internal
|
||||
internalScheme: HTTP
|
||||
|
||||
serviceMonitor:
|
||||
# If `true`, a ServiceMonitor resource for the prometheus-operator is created
|
||||
enabled: false
|
||||
# Optionally sets a target namespace in which to deploy the ServiceMonitor resource
|
||||
namespace: ""
|
||||
# Optionally sets a namespace for the ServiceMonitor
|
||||
namespaceSelector: {}
|
||||
# Annotations for the ServiceMonitor
|
||||
annotations: {}
|
||||
# Additional labels for the ServiceMonitor
|
||||
labels: {}
|
||||
# Interval at which Prometheus scrapes metrics
|
||||
interval: 10s
|
||||
# Timeout for scraping
|
||||
scrapeTimeout: 10s
|
||||
# Relabelings for the Servicemonitor
|
||||
relabelings: []
|
||||
# metricRelabelings for the Servicemonitor
|
||||
metricRelabelings: []
|
||||
# The path at which metrics are served
|
||||
path: '{{ tpl (coalesce .Values.http.managementRelativePath .Values.http.relativePath) $ | trimSuffix "/" }}/metrics'
|
||||
# The Service port at which metrics are served
|
||||
port: '{{ .Values.http.internalPort }}'
|
||||
# The scheme to use for scraping metrics ("http" or "https"); if not set, the `http.internalScheme` value is used
|
||||
scheme: ""
|
||||
|
||||
extraServiceMonitor:
|
||||
# If `true`, a ServiceMonitor resource for the prometheus-operator is created
|
||||
enabled: false
|
||||
# Optionally sets a target namespace in which to deploy the ServiceMonitor resource
|
||||
namespace: ""
|
||||
# Optionally sets a namespace for the ServiceMonitor
|
||||
namespaceSelector: {}
|
||||
# Annotations for the ServiceMonitor
|
||||
annotations: {}
|
||||
# Additional labels for the ServiceMonitor
|
||||
labels: {}
|
||||
# Interval at which Prometheus scrapes metrics
|
||||
interval: 10s
|
||||
# Timeout for scraping
|
||||
scrapeTimeout: 10s
|
||||
# Relabelings for the Servicemonitor
|
||||
relabelings: []
|
||||
# metricRelabelings for the Servicemonitor
|
||||
metricRelabelings: []
|
||||
# The path at which metrics are served
|
||||
path: '{{ tpl (coalesce .Values.http.managementRelativePath .Values.http.relativePath) $ | trimSuffix "/" }}/metrics'
|
||||
# The Service port at which metrics are served
|
||||
port: '{{ .Values.http.internalPort }}'
|
||||
# The scheme to use for scraping metrics ("http" or "https"); if not set, the `http.internalScheme` value is used
|
||||
scheme: ""
|
||||
|
||||
prometheusRule:
|
||||
# If `true`, a PrometheusRule resource for the prometheus-operator is created
|
||||
enabled: false
|
||||
# Optionally sets a target namespace in which to deploy the ServiceMonitor resource
|
||||
namespace: ""
|
||||
# Annotations for the PrometheusRule
|
||||
annotations: {}
|
||||
# Additional labels for the PrometheusRule
|
||||
labels: {}
|
||||
# List of rules for Prometheus
|
||||
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
|
||||
|
||||
autoscaling:
|
||||
# If `true`, an autoscaling/v2 HorizontalPodAutoscaler resource is created (requires Kubernetes 1.23 or above)
|
||||
# Autoscaling seems to be most reliable when using KUBE_PING service discovery (see README for details)
|
||||
# This disables the `replicas` field in the StatefulSet
|
||||
enabled: false
|
||||
# Additional HorizontalPodAutoscaler labels
|
||||
labels: {}
|
||||
# The minimum and maximum number of replicas for the Keycloak StatefulSet
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
# The metrics to use for scaling
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 80
|
||||
# The scaling policy to use. This will scale up quickly but only scale down a single Pod per 5 minutes.
|
||||
# This is important because caches are usually only replicated to 2 Pods and if one of those Pods is terminated this will give the cluster time to recover.
|
||||
behavior:
|
||||
scaleDown:
|
||||
stabilizationWindowSeconds: 300
|
||||
policies:
|
||||
- type: Pods
|
||||
value: 1
|
||||
periodSeconds: 300
|
||||
|
||||
test:
|
||||
# If `true`, test resources are created
|
||||
enabled: false
|
||||
image:
|
||||
# The image for the test Pod
|
||||
repository: docker.io/selenium/standalone-chromium
|
||||
# The tag for the test Pod image
|
||||
tag: "147.0"
|
||||
# The image pull policy for the test Pod image
|
||||
pullPolicy: IfNotPresent
|
||||
# SecurityContext for the entire test Pod
|
||||
podSecurityContext:
|
||||
fsGroup: 1200 # UID of seluser in selenium/standalone-chromium
|
||||
# SecurityContext for the test container
|
||||
securityContext:
|
||||
runAsUser: 1200 # UID of seluser in selenium/standalone-chromium
|
||||
runAsNonRoot: true
|
||||
# See https://helm.sh/docs/topics/charts_hooks/#hook-deletion-policies
|
||||
deletionPolicy: before-hook-creation
|
||||
|
||||
## -- Extra Kubernetes objects to deploy with the helm chart
|
||||
extraManifests: []
|
||||
# - |
|
||||
# apiVersion: v1
|
||||
# kind: ConfigMap
|
||||
# metadata:
|
||||
# name: {{ include "keycloak.fullname" . }}-tpl
|
||||
# data:
|
||||
# foo: bar
|
||||
# - apiVersion: v1
|
||||
# kind: ConfigMap
|
||||
# metadata:
|
||||
# name: "{{ include \"keycloak.fullname\" . }}-tpl"
|
||||
# data:
|
||||
# foo: bar
|
||||
Reference in New Issue
Block a user