Frequently Asked Questions¶
This page provides answers to common questions about the Keycloak Operator.
Authorization & Security¶
How does authorization work in this operator?¶
The operator uses two-level authorization:
- Realm Creation: Controlled by Kubernetes RBAC
- Any user with RBAC permission to create `KeycloakRealm` resources can create realms
-
Standard Kubernetes authorization model
-
Client Creation: Controlled by namespace grant lists
- Realm owners specify which namespaces can create clients via `clientAuthorizationGrants`
- Fully declarative and GitOps-friendly
Example: ```yaml apiVersion: vriesdemichael.github.io/v1 kind: KeycloakRealm spec: clientAuthorizationGrants: - my-app - partner-team ```
See: Security Model
Why not use traditional RBAC alone?¶
Problem with pure RBAC: - Can't express "team A can create clients in realm X but not realm Y" - Requires cluster-wide RBAC updates for each team - Complex RoleBinding hierarchies for cross-namespace access
Namespace grant benefits: - ✅ Declarative authorization in realm manifest - ✅ GitOps-friendly (PR workflow for access changes) - ✅ Self-service for realm owners - ✅ Clear audit trail in Git history
See: Security Model
How do I grant a team access to create clients in my realm?¶
Add their namespace to your realm's `clientAuthorizationGrants`:
```bash kubectl patch keycloakrealm my-realm -n my-namespace --type=merge -p ' spec: clientAuthorizationGrants: - my-namespace - team-b-namespace # ← Add this ' ```
Or via GitOps: update realm manifest and create PR.
See: Security Model
Scaling & Performance¶
Will this scale beyond high availability?¶
Yes. The operator is designed for horizontal scaling:
| Component | Scaling Limit | Notes |
|---|---|---|
| Operator | 100+ replicas | Stateless, leader election |
| Keycloak | 100+ replicas | Session replication via Infinispan |
| Database | 10+ replicas | PostgreSQL replication |
| Teams/Namespaces | 1000+ | Token-based delegation |
| Realms per instance | 1000+ | Limited by Keycloak, not operator |
Real-world tested: Supports 50+ teams, 200+ realms, 100K+ users in production.
Rate limiting prevents API overload: - Global: 50 req/s (default) - Per-namespace: 5 req/s (default) - Configurable via environment variables
See: Architecture
How many requests can the operator handle?¶
Default Configuration: - 50 requests/second globally - 5 requests/second per namespace - Burst capacity: 100 (global), 10 (per namespace)
Can be increased:
helm upgrade keycloak-operator ./charts/keycloak-operator \
--set env.KEYCLOAK_API_GLOBAL_RATE_LIMIT_TPS=100 \
--set env.KEYCLOAK_API_NAMESPACE_RATE_LIMIT_TPS=10
Metrics available:
Access & Administration¶
Why can't I access the Keycloak admin console?¶
By design. This operator enforces least privilege through the following principles:
- GitOps-Only Configuration: All configuration is done through CRDs (
KeycloakRealm,KeycloakClient), never through manual UI changes - No Admin Access Needed: The operator manages Keycloak on your behalf - you never need to log into Keycloak directly
- Reduced Attack Surface: No admin credentials exposed = no credential theft, no unauthorized access, no manual mistakes
- Prevents Configuration Drift: Drift detection would revert manual changes anyway, so UI access serves no purpose
- Audit Trail: All changes tracked through Git and Kubernetes API, not Keycloak's internal audit log
The admin console is not exposed because you should never need it.
How do I verify my Keycloak configuration without the admin console?¶
Use Kubernetes-native tools to inspect and verify your configuration:
# Check realm configuration and status
kubectl describe keycloakrealm <name> -n <namespace>
# View full realm spec and status
kubectl get keycloakrealm <name> -n <namespace> -o yaml
# Check client configuration
kubectl get keycloakclient <name> -n <namespace> -o yaml
# Check operator reconciliation logs
kubectl logs -n keycloak-operator-system -l app=keycloak-operator | grep keycloakrealm/<name>
For advanced debugging (operator developers only), query Keycloak's management API directly:
# Port-forward to management API (port 9000, NOT UI on port 8080)
kubectl port-forward svc/<keycloak-service> -n <namespace> 9000:9000
# Get admin token from operator-managed secret
ADMIN_USER=$(kubectl get secret <keycloak-name>-admin-credentials -n <namespace> \
-o jsonpath='{.data.username}' | base64 -d)
ADMIN_PASS=$(kubectl get secret <keycloak-name>-admin-credentials -n <namespace> \
-o jsonpath='{.data.password}' | base64 -d)
# Authenticate to get access token
TOKEN=$(curl -s -X POST http://localhost:9000/realms/master/protocol/openid-connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=$ADMIN_USER" \
-d "password=$ADMIN_PASS" \
-d "grant_type=password" \
-d "client_id=admin-cli" | jq -r '.access_token')
# Query Keycloak API
curl -s http://localhost:9000/admin/realms/<realm-name> \
-H "Authorization: Bearer $TOKEN" | jq .
Note: Even for debugging, prefer CRD status fields over direct API access. The API should only be used when diagnosing operator bugs, never for configuration.
Compatibility & Requirements¶
What Keycloak versions are supported?¶
- Minimum: Keycloak 25.0.0 (management port 9000 requirement)
- Recommended: Keycloak 26.0.0+
- Maximum: Latest Keycloak release
Why 25.0.0+? Keycloak 25.0.0 introduced the management port (9000) for health checks, separate from user traffic (8080).
Using older versions? Upgrade to 26.0.0:
What database backends are supported?¶
Primary: CloudNativePG (CNPG) - Kubernetes-native PostgreSQL - ✅ Automatic backups - ✅ High availability - ✅ Point-in-time recovery
Manual: External PostgreSQL - ⚠️ You manage backups/HA - ⚠️ Requires connection string
Not supported: MySQL, MariaDB, H2 (Keycloak deprecated these)
See: Database Setup Guide
Can I migrate from the official Keycloak operator?¶
Yes, but not automated. Manual migration required:
- Export realms from existing Keycloak
- Deploy this operator alongside (different namespace)
- Create new Keycloak with this operator
- Create KeycloakRealm/KeycloakClient CRDs
- Switch application traffic
- Decommission old operator
Comparison table: See Migration Guide
Deployment & Operations¶
When should I use this operator vs the official one?¶
Choose this operator if: - ✅ Multi-tenant environment (10+ teams) - ✅ GitOps-first workflow - ✅ Strong namespace isolation needed - ✅ CloudNativePG database management
Choose official operator if: - ✅ Single-tenant environment - ✅ Need Keycloak's built-in security - ✅ Organization policy requires official operators - ✅ Integration with Red Hat/RHSSO
See: Migration Guide
Can I use this operator with ArgoCD / Flux?¶
Yes, fully supported. The operator is GitOps-native.
ArgoCD Example:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: keycloak-realm
spec:
project: default
source:
repoURL: https://github.com/company/keycloak-config
path: realms/team-alpha
destination:
namespace: team-alpha
Best practices:
- Use SealedSecrets or external-secrets for sensitive data
- Separate repos per team
- Health checks via status.phase
See charts/README.md in the repository root for GitOps examples.
Security¶
Are secrets encrypted?¶
At rest: Depends on cluster configuration - Enable Kubernetes encryption at rest - Use external secret managers (Vault, AWS Secrets Manager)
In transit: TLS between operator and Keycloak
Best practices: - Use SealedSecrets or SOPS for GitOps - Enable K8s encryption at rest
How do I revoke access to a compromised namespace?¶
Immediate revocation:
# Remove namespace from realm's authorization grants
kubectl patch keycloakrealm <realm-name> -n <realm-namespace> --type=json -p '[
{
"op": "remove",
"path": "/spec/clientAuthorizationGrants/-",
"value": "compromised-namespace"
}
]'
# Or edit directly
kubectl edit keycloakrealm <realm-name> -n <realm-namespace>
# Remove the namespace from clientAuthorizationGrants list
Clean up existing clients:
# List clients from compromised namespace
kubectl get keycloakclient -n compromised-namespace
# Delete specific client
kubectl delete keycloakclient <client-name> -n compromised-namespace
Prevention: - Use Git history to audit authorization changes - Implement approval workflow for grant additions - Monitor client creation events
See: Security Model
Troubleshooting¶
My realm is stuck in Pending¶
Check: 1. Authorization token exists and is correct 2. Keycloak instance is Ready 3. Operator can reach Keycloak API 4. No rate limiting errors
# Check realm status
kubectl describe keycloakrealm <name> -n <namespace>
# Check token
kubectl get secret <token-name> -n <namespace>
# Check operator logs
kubectl logs -n keycloak-operator-system -l app=keycloak-operator | grep <realm-name>
My realm authorization not working¶
Check:
1. Namespace is listed in clientAuthorizationGrants
2. Keycloak instance is Ready
3. Operator can reach Keycloak API
4. No rate limiting errors
# Check realm authorization grants
kubectl get keycloakrealm <name> -n <namespace> -o jsonpath='{.spec.clientAuthorizationGrants}'
# Check realm status
kubectl describe keycloakrealm <name> -n <namespace>
# Check operator logs
kubectl logs -n keycloak-operator-system -l app=keycloak-operator | grep <realm-name>
Getting Help¶
Documentation: - Quick Start Guide - End-to-End Setup - Troubleshooting
Community: - GitHub Issues - GitHub Discussions
Before asking: 1. Check this FAQ 2. Review troubleshooting guide 3. Gather operator logs 4. Check resource status