feat(keycloak): install keycloak with official operator
This commit is contained in:
2
keycloak/.gitignore
vendored
2
keycloak/.gitignore
vendored
@@ -1 +1 @@
|
||||
keycloak-values.yaml
|
||||
keycloak-cr.yaml
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
set fallback := true
|
||||
|
||||
# Keycloak Helm chart info:
|
||||
# helm show chart oci://registry-1.docker.io/bitnamicharts/keycloak
|
||||
# Keycloak Operator info:
|
||||
# https://www.keycloak.org/operator/installation
|
||||
|
||||
export KEYCLOAK_NAMESPACE := env("KEYCLOAK_NAMESPACE", "keycloak")
|
||||
export KEYCLOAK_CHART_VERSION := env("KEYCLOAK_CHART_VERSION", "25.0.2")
|
||||
export KEYCLOAK_OPERATOR_VERSION := env("KEYCLOAK_OPERATOR_VERSION", "26.3.4")
|
||||
export KEYCLOAK_REALM := env("KEYCLOAK_REALM", "")
|
||||
export KEYCLOAK_HOST := env("KEYCLOAK_HOST", "")
|
||||
export K8S_OIDC_CLIENT_ID := env('K8S_OIDC_CLIENT_ID', "k8s")
|
||||
@@ -52,23 +52,37 @@ create-credentials:
|
||||
echo "Waiting for ExternalSecret to sync..."
|
||||
kubectl wait --for=condition=Ready externalsecret/keycloak-credentials \
|
||||
-n ${KEYCLOAK_NAMESPACE} --timeout=60s
|
||||
|
||||
# Create bootstrap admin secret for Keycloak Operator (username/password format)
|
||||
kubectl delete secret keycloak-bootstrap-admin -n ${KEYCLOAK_NAMESPACE} --ignore-not-found
|
||||
kubectl create secret generic keycloak-bootstrap-admin -n ${KEYCLOAK_NAMESPACE} \
|
||||
--from-literal=username="${admin_user}" \
|
||||
--from-literal=password="${password}"
|
||||
else
|
||||
echo "External Secrets Operator not found. Creating secret directly..."
|
||||
if kubectl get secret keycloak-credentials -n ${KEYCLOAK_NAMESPACE} &>/dev/null; then
|
||||
kubectl delete --ignore-not-found secret keycloak-credentials -n ${KEYCLOAK_NAMESPACE}
|
||||
fi
|
||||
echo "External Secrets Operator not found. Creating secrets directly..."
|
||||
# Delete existing secrets
|
||||
kubectl delete secret keycloak-credentials -n ${KEYCLOAK_NAMESPACE} --ignore-not-found
|
||||
kubectl delete secret keycloak-bootstrap-admin -n ${KEYCLOAK_NAMESPACE} --ignore-not-found
|
||||
|
||||
# Create keycloak-credentials secret (admin-user/password format for legacy scripts)
|
||||
kubectl create secret generic keycloak-credentials -n ${KEYCLOAK_NAMESPACE} \
|
||||
--from-literal=admin-user="${admin_user}" \
|
||||
--from-literal=password="${password}"
|
||||
|
||||
# Create bootstrap admin secret for Keycloak Operator (username/password format)
|
||||
kubectl create secret generic keycloak-bootstrap-admin -n ${KEYCLOAK_NAMESPACE} \
|
||||
--from-literal=username="${admin_user}" \
|
||||
--from-literal=password="${password}"
|
||||
|
||||
if helm status vault -n ${K8S_VAULT_NAMESPACE} &>/dev/null; then
|
||||
just put-admin-credentials-to-vault "${admin_user}" "${password}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Delete Keycloak secret
|
||||
# Delete Keycloak secrets
|
||||
delete-credentials:
|
||||
@kubectl delete secret keycloak-credentials -n ${KEYCLOAK_NAMESPACE} --ignore-not-found
|
||||
@kubectl delete secret keycloak-bootstrap-admin -n ${KEYCLOAK_NAMESPACE} --ignore-not-found
|
||||
@kubectl delete externalsecret keycloak-credentials -n ${KEYCLOAK_NAMESPACE} --ignore-not-found
|
||||
|
||||
# Create Keycloak database secret
|
||||
@@ -89,31 +103,51 @@ create-database-secret:
|
||||
delete-database-secret:
|
||||
@kubectl delete secret database-config -n ${KEYCLOAK_NAMESPACE} --ignore-not-found
|
||||
|
||||
# Install Keycloak
|
||||
# Install Keycloak Operator
|
||||
install-operator:
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
just create-namespace
|
||||
echo "Installing Keycloak Operator CRDs..."
|
||||
kubectl apply -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/${KEYCLOAK_OPERATOR_VERSION}/kubernetes/keycloaks.k8s.keycloak.org-v1.yml
|
||||
kubectl apply -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/${KEYCLOAK_OPERATOR_VERSION}/kubernetes/keycloakrealmimports.k8s.keycloak.org-v1.yml
|
||||
echo "Installing Keycloak Operator in ${KEYCLOAK_NAMESPACE} namespace..."
|
||||
kubectl apply -n ${KEYCLOAK_NAMESPACE} -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/${KEYCLOAK_OPERATOR_VERSION}/kubernetes/kubernetes.yml
|
||||
kubectl wait --for=condition=available deployment/keycloak-operator -n ${KEYCLOAK_NAMESPACE} --timeout=300s
|
||||
|
||||
# Install Keycloak instance
|
||||
install:
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
# Setup vault environment once at the beginning if vault is enabled
|
||||
just install-operator
|
||||
just create-credentials
|
||||
just postgres::create-db keycloak
|
||||
just create-database-secret
|
||||
just create-namespace
|
||||
KEYCLOAK_ADMIN_USER=$(just admin-username) \
|
||||
gomplate -f keycloak-values.gomplate.yaml -o keycloak-values.yaml
|
||||
helm upgrade --cleanup-on-fail --install \
|
||||
keycloak oci://registry-1.docker.io/bitnamicharts/keycloak \
|
||||
--version ${KEYCLOAK_CHART_VERSION} -n ${KEYCLOAK_NAMESPACE} --wait \
|
||||
-f keycloak-values.yaml
|
||||
gomplate -f keycloak-cr.gomplate.yaml -o keycloak-cr.yaml
|
||||
kubectl apply -f keycloak-cr.yaml
|
||||
kubectl wait --for=condition=Ready keycloak/keycloak -n ${KEYCLOAK_NAMESPACE} --timeout=600s
|
||||
|
||||
# Uninstall Keycloak
|
||||
# Uninstall Keycloak instance
|
||||
uninstall delete-db='true':
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
helm uninstall keycloak -n ${KEYCLOAK_NAMESPACE} --ignore-not-found --wait
|
||||
kubectl delete keycloak keycloak -n ${KEYCLOAK_NAMESPACE} --ignore-not-found
|
||||
kubectl wait --for=delete keycloak/keycloak -n ${KEYCLOAK_NAMESPACE} --timeout=300s || true
|
||||
just delete-namespace
|
||||
if [ "{{ delete-db }}" = "true" ]; then
|
||||
just postgres::delete-db keycloak
|
||||
fi
|
||||
|
||||
# Uninstall Keycloak Operator
|
||||
uninstall-operator:
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
kubectl delete -n ${KEYCLOAK_NAMESPACE} -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/${KEYCLOAK_OPERATOR_VERSION}/kubernetes/kubernetes.yml --ignore-not-found
|
||||
kubectl delete -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/${KEYCLOAK_OPERATOR_VERSION}/kubernetes/keycloakrealmimports.k8s.keycloak.org-v1.yml --ignore-not-found
|
||||
kubectl delete -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/${KEYCLOAK_OPERATOR_VERSION}/kubernetes/keycloaks.k8s.keycloak.org-v1.yml --ignore-not-found
|
||||
|
||||
# Create Keycloak realm
|
||||
create-realm create-client-for-k8s='true' access_token_lifespan='3600' refresh_token_lifespan='14400' sso_session_idle_timeout='7200':
|
||||
#!/bin/bash
|
||||
|
||||
96
keycloak/keycloak-cr.gomplate.yaml
Normal file
96
keycloak/keycloak-cr.gomplate.yaml
Normal file
@@ -0,0 +1,96 @@
|
||||
apiVersion: k8s.keycloak.org/v2alpha1
|
||||
kind: Keycloak
|
||||
metadata:
|
||||
name: keycloak
|
||||
namespace: {{ .Env.KEYCLOAK_NAMESPACE }}
|
||||
spec:
|
||||
instances: 1
|
||||
image: quay.io/keycloak/keycloak:26.3.4
|
||||
startOptimized: false
|
||||
|
||||
# Database configuration for external PostgreSQL
|
||||
db:
|
||||
vendor: postgres
|
||||
host: postgres-cluster-rw.postgres
|
||||
port: 5432
|
||||
database: keycloak
|
||||
usernameSecret:
|
||||
name: database-config
|
||||
key: user
|
||||
passwordSecret:
|
||||
name: database-config
|
||||
key: password
|
||||
|
||||
# Hostname configuration
|
||||
hostname:
|
||||
hostname: {{ .Env.KEYCLOAK_HOST }}
|
||||
strict: false
|
||||
strictBackchannel: false
|
||||
|
||||
# HTTP configuration
|
||||
http:
|
||||
httpEnabled: true
|
||||
httpPort: 8080
|
||||
httpsPort: 8443
|
||||
|
||||
# Proxy configuration for edge proxy
|
||||
proxy:
|
||||
headers: xforwarded
|
||||
|
||||
# Additional options and admin configuration
|
||||
additionalOptions:
|
||||
- name: http-enabled
|
||||
value: "true"
|
||||
- name: hostname-strict
|
||||
value: "false"
|
||||
- name: hostname-strict-https
|
||||
value: "false"
|
||||
- name: proxy
|
||||
value: edge
|
||||
|
||||
# Bootstrap admin configuration
|
||||
bootstrapAdmin:
|
||||
user:
|
||||
secret: keycloak-bootstrap-admin
|
||||
|
||||
# Resources
|
||||
resources:
|
||||
requests:
|
||||
memory: "1.5Gi"
|
||||
cpu: "500m"
|
||||
limits:
|
||||
memory: "2Gi"
|
||||
cpu: "1000m"
|
||||
|
||||
# Ingress configuration (disabled - using separate Ingress resource)
|
||||
ingress:
|
||||
enabled: false
|
||||
|
||||
---
|
||||
# Separate Ingress resource for custom configuration
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: keycloak-ingress
|
||||
namespace: {{ .Env.KEYCLOAK_NAMESPACE }}
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: traefik
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
tls:
|
||||
- hosts:
|
||||
- {{ .Env.KEYCLOAK_HOST }}
|
||||
secretName: keycloak-tls
|
||||
rules:
|
||||
- host: {{ .Env.KEYCLOAK_HOST }}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: keycloak-service
|
||||
port:
|
||||
number: 8080
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
global:
|
||||
security:
|
||||
allowInsecureImages: true
|
||||
|
||||
production: true
|
||||
|
||||
# Enable HTTP for health checks in production mode
|
||||
extraEnvVars:
|
||||
- name: KC_HTTP_ENABLED
|
||||
value: "true"
|
||||
|
||||
auth:
|
||||
adminUser: {{ .Env.KEYCLOAK_ADMIN_USER }}
|
||||
existingSecret: keycloak-credentials
|
||||
passwordSecretKey: password
|
||||
|
||||
postgresql:
|
||||
enabled: false
|
||||
|
||||
externalDatabase:
|
||||
host: postgres-cluster-rw.postgres
|
||||
port: 5432
|
||||
database: keycloak
|
||||
existingSecret: database-config
|
||||
existingSecretUserKey: user
|
||||
existingSecretPasswordKey: password
|
||||
|
||||
tls:
|
||||
enabled: true
|
||||
autoGenerated:
|
||||
enabled: true
|
||||
engine: helm
|
||||
|
||||
# Keycloak pod may not start with the default memory limits
|
||||
resources:
|
||||
limits:
|
||||
memory: 2Gi
|
||||
requests:
|
||||
memory: 1.5Gi
|
||||
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnamilegacy/keycloak
|
||||
# tag: 26.0.5-debian-12-r0
|
||||
# debug: true
|
||||
|
||||
# logging:
|
||||
# level: DEBUG
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
ingressClassName: traefik
|
||||
hostname: {{ .Env.KEYCLOAK_HOST }}
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: traefik
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
tls: true
|
||||
Reference in New Issue
Block a user