본문으로 건너뛰기

Keycloak

Keycloak은 내부 운영자 도구를 위한 인프라 SSO를 제공합니다. 현재 저장소 상태에서는 주로 Coder, Vault, Zot, Gitea, RabbitMQ 같은 애플리케이션을 위한 infra realm이 핵심입니다.

책임

  • keycloak 네임스페이스에서 Keycloak 실행
  • 브라우저 기반 흐름을 위해 auth.lumie-edu.com에서 직접 OIDC 엔드포인트 제공
  • 공유 infra-db PostgreSQL 클러스터에 realm 상태 저장
  • kc.sh import 대신 post-sync job으로 선언적 realm 구성을 수렴

소스 경로

경로역할
lumie-infra/security/keycloak/argocd.yaml차트 values, 공통 차트 values, 추가 매니페스트를 포함하는 ArgoCD Application
lumie-infra/security/keycloak/helm-values.yaml서버 시작, DB, metrics, health 설정
lumie-infra/security/keycloak/common-values.yaml외부 ingress, realm import ConfigMap, Vault 시크릿 렌더링
lumie-infra/security/keycloak/manifests/realm-sync-job.yamlkeycloak-config-cli를 사용하는 PostSync realm 수렴 job
lumie-infra/charts/common/templates/additional-ingresses.yamlauth.lumie-edu.com을 렌더링하는 템플릿
lumie-infra/charts/common/templates/vault-static-secrets.yaml로컬 Vault 시크릿 선언이 사용하는 템플릿
lumie-infra/security/teleport/agent/helm-values.yamlKeycloak UI용 별도 Teleport 앱 진입점

퍼블릭 표면과 계약

표면계약
직접 OIDC ingresshttps://auth.lumie-edu.com
인클러스터 HTTP 서비스keycloak-keycloakx-http.keycloak.svc.cluster.local
데이터베이스공유 infra-db, 데이터베이스 keycloak, 사용자 keycloak
Admin bootstrap 시크릿keycloak-secrets
Realm sync 시크릿keycloak-oauth-secrets
Teleport 앱keycloak

직접 ingress가 중요한 이유는 Coder와 Vault 같은 클라이언트의 브라우저 OIDC 흐름이 Teleport 앱 프록시만으로는 종료될 수 없기 때문입니다.

런타임 흐름

선언된 렐름 계약

체크인된 infra-realm.json은 다음을 정의합니다.

  • realm infra
  • realm 역할 admin, developer
  • client scope rabbitmq-admin, groups
  • OIDC client:
    • coder
    • vault
    • zot
    • gitea
    • rabbitmq
  • realm 역할 admin, developer를 가진 사용자 bluemayne

client secret은 Git에 하드코딩되지 않습니다. keycloak-realm-sync job이 keycloak-oauth-secrets에서 이를 읽어 realm JSON에 치환한 뒤 라이브 admin REST API로 적용합니다.

렐름 동기화가 Job인 이유

저장소는 realm 관리를 위해 의도적으로 kc.sh import --override를 피합니다. realm-sync-job.yaml의 post-sync job이 존재하는 이유는 다음과 같습니다.

  • REST 기반 생성이 Keycloak의 표준 client-scope 초기화를 보존하기 때문
  • secret placeholder를 realm JSON이 데이터베이스에 기록되기 전에 클라이언트 측에서 치환할 수 있기 때문
  • 부분 실패 후에도 재실행이 멱등적이고 안전하기 때문

장애 동작과 운영 리스크

  • OAuth 시크릿이 누락되면 Keycloak pod 자체는 healthy여도 로그인 시 invalid_client 실패가 발생합니다.
  • PostSync job이 중간에 실패하면 realm이 부분적으로만 업데이트될 수 있으며, 문서화된 복구 경로는 데이터베이스를 수동 롤백하는 것이 아니라 job을 재실행하는 것입니다.
  • 데이터베이스 bootstrap 또는 admin-password 시크릿 장애는 realm sync가 실행되기 전에 시작 자체를 막습니다.
  • 직접 ingress가 Teleport 앱 경로와 분리되어 있으므로, ingress나 인증서 장애로 Teleport 프록시 UI는 살아 있어도 OIDC는 깨질 수 있습니다.

계약 드리프트

주의해야 할 실제 체크인 불일치가 있습니다.

  • security/keycloak/helm-values.yaml 주석은 realm infra, lumie, lumie-dev를 설명합니다.
  • security/keycloak/manifests/realm-sync-job.yaml 주석도 ConfigMap이 infra-realm.json, lumie-realm.json, lumie-dev-realm.json을 마운트한다고 말합니다.
  • 하지만 현재 security/keycloak/common-values.yamlinfra-realm.json만 렌더링하고, 현재 Vault 시크릿 템플릿도 그 파일이 사용하는 infra client secret만 노출합니다.

추가 realm JSON 파일이 다시 추가되기 전까지는 현재 저장소 상태를 infra realm 전용으로 취급하세요.

관측성

  • serviceMonitor.enabled: true가 Keycloak 메트릭을 Prometheus에 노출합니다.
  • health.enabled: true/health startup probe가 부팅 readiness를 커버합니다.
  • keycloak-realm-sync job 로그가 realm 수렴 실패의 단일 출처입니다.

검증

kubectl get applications.argoproj.io -n argocd keycloak
kubectl get statefulset,pods,svc,ingress,secrets -n keycloak
kubectl get jobs -n keycloak -l app.kubernetes.io/component=realm-sync
kubectl logs -n keycloak job/keycloak-realm-sync
kubectl port-forward -n keycloak svc/keycloak-keycloakx-http 8080:80
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/health
curl -sS -o /dev/null -w "%{http_code}\n" \
https://auth.lumie-edu.com/realms/infra/.well-known/openid-configuration

성공 신호:

  • keycloak Argo CD application이 HealthySynced 상태입니다.
  • StatefulSet keycloak이 준비 상태이고 auth.lumie-edu.com용 직접 ingress Ingress가 존재합니다.
  • keycloak-realm-sync Job이 성공적으로 완료되고, 로그에 반복적인 invalid_client 또는 import substitution 오류가 없습니다.
  • 인클러스터 서비스의 GET /health가 HTTP 200을 반환합니다.
  • realm infra의 퍼블릭 OIDC discovery 엔드포인트가 HTTP 200을 반환합니다.

관련 페이지