본문 바로가기
문서 목차
ORKESTRIX설치

Keycloak (통합 인증·SSO)

사용자 통합 인증, SSO(Single Sign On) 및 OAuth2/OIDC 통합 관리를 제공하는 Keycloak 을 설치하고, 쿠버네티스 API 서버가 Keycloak 계정으로 로그인을 인증하도록 연동합니다.

QUANTUM C&S

사용자 통합 인증, SSO(Single Sign-On) 및 OAuth2/OIDC 통합 관리를 제공하는 Keycloak을 설치하고, 쿠버네티스 API 서버가 Keycloak 계정으로 로그인을 인증하도록 연동합니다.

이 컴포넌트는 설치 과정에서 쿠버네티스 API 서버 설정(/etc/kubernetes/manifests/kube-apiserver.yaml)을 자동으로 변경합니다. 기존 인증서 기반 kubectl 접속은 그대로 유지되니 접속이 끊기진 않지만, 컨트롤플레인 설정이 바뀐다는 점은 알고 있어야 합니다.

설정값

inventory/qks/group_vars/all/all-k8s.yaml:

qks_keycloak_enabled: true
qks_keycloak_version: 25.2.0
qks_keycloak_fqdn: "iam.{{ kube_default_domain }}"
qks_keycloak_admin_name: admin
qks_keycloak_internal_db_enabled: true   # 내장 PostgreSQL 사용(외부 DB 불필요)
qks_cluster_oidc_enabled: true           # API 서버 OIDC 인증 연동
내장 PostgreSQL을 사용하므로 별도 데이터베이스 준비가 필요 없습니다. Traefik 인그레스(설치 완료 전제)를 통해 노출됩니다. iaas.yaml 번들에도 포함되어 있지만, 아래는 plays/qks-keycloak.yaml을 단독 실행하는 방법입니다.

실행

./install.sh ubuntu plays/qks-keycloak.yaml

설치 흐름

./install.sh ubuntu plays/qks-keycloak.yaml
  ├─ 1. istio-system과 별개인 qks-keycloak 네임스페이스 생성 + TLS Secret 생성
  ├─ 2. Helm으로 Keycloak + 내장 PostgreSQL 배포, Ingress(Traefik) 등록
  ├─ 3. Keycloak이 응답 가능해질 때까지 대기 후 관리자 토큰 발급
  ├─ 4. "kosmos" Realm 생성 + 관리자(admin) 계정 생성
  └─ 5. 전 마스터 노드의 kube-apiserver.yaml에 OIDC 인증 플래그 추가
        (--oidc-issuer-url, --oidc-client-id, --oidc-username-claim, --oidc-groups-claim)
       → API 서버가 재기동되어 이 설정을 반영할 때까지 자동 대기

설치 확인

kubectl get pods -n qks | grep keycloak
helm list -n qks | grep keycloak
kubectl get ingress -n qks | grep keycloak

Keycloak 파드와 내장 PostgreSQL 파드가 Running, Helm 릴리즈가 deployed, Ingress가 qks_keycloak_fqdn로 등록되어 있어야 합니다.

kubectl get nodes   # 기존 인증서 기반 kubectl 접속이 여전히 정상인지 확인
sudo grep oidc /etc/kubernetes/manifests/kube-apiserver.yaml   # 각 마스터마다 4개 플래그 확인

실제 동작 확인

1. Keycloak 로그인(SSO) 확인

curl -k -s -X POST https://iam.<도메인>/realms/master/protocol/openid-connect/token \
  -d "grant_type=password" -d "client_id=admin-cli" -d "username=admin" \
  --data-urlencode "password=<관리자 비밀번호>"

access_token이 포함된 응답이 오면 SSO 로그인이 정상 동작하는 것입니다.

비밀번호에 특수문자(+ 등)가 있으면 -d 대신 --data-urlencode를 써야 합니다 — +가 공백으로 잘못 해석되어 인증이 실패할 수 있습니다.

2. Kubernetes API 서버의 OIDC 인증 확인

TOKEN=$(curl -k -s -X POST https://iam.<도메인>/realms/kosmos/protocol/openid-connect/token \
  -d "grant_type=password" -d "client_id=kosmos" -d "client_secret=<클라이언트 시크릿>" \
  -d "username=admin" --data-urlencode "password=<비밀번호>" \
  | python3 -c "import json,sys;print(json.load(sys.stdin)['access_token'])")

curl -k -s -o /dev/null -w "%{http_code}\n" \
  -H "Authorization: Bearer $TOKEN" \
  https://<로드밸런서 FQDN>:8443/api/v1/namespaces/qks/pods
kubectl --token=...으로 테스트하지 마세요 — kubeconfig에 이미 클라이언트 인증서가 설정되어 있으면 TLS 단계에서 먼저 인증이 끝나버려 Bearer 토큰이 무시됩니다(--token이 조용히 무시되고 항상 성공하는 것처럼 보임). curl로 인증서 없이 순수하게 토큰만 보내야 정확히 검증됩니다.

403(Forbidden)이 나오면 정상입니다 — API 서버가 이 토큰을 실제 사용자로 인증(authentication) 했다는 뜻이고, 아직 그 사용자에게 권한(RBAC)을 안 줘서 인가(authorization) 만 거부된 것입니다. 401이 나오면 실제 인증 자체가 실패한 것이니 아래를 점검하세요.

3. 권한 부여까지 포함한 전체 확인 (선택)

kubectl create clusterrolebinding oidc-test --clusterrole=view --user="admin@<도메인>"
curl -k -s -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer $TOKEN" \
  https://<로드밸런서 FQDN>:8443/api/v1/namespaces/qks/pods
# 200
kubectl delete clusterrolebinding oidc-test

200이 나오면 Keycloak SSO 계정으로 쿠버네티스 API에 인증+인가 전체가 정상 동작하는 것입니다.

트러블슈팅

401이 나오는 경우, 토큰을 직접 디코딩해서 클레임을 확인해보세요:

python3 -c "
import base64, json, os
token = os.environ['TOKEN']
payload_b64 = token.split('.')[1]
payload_b64 += '=' * (-len(payload_b64) % 4)
print(json.loads(base64.urlsafe_b64decode(payload_b64)))
"
  • iss가 --oidc-issuer-url과 정확히 일치하는지
  • aud(audience) 클레임에 --oidc-client-id로 지정한 값이 포함되어 있는지 — Keycloak은 기본적으로 클라이언트 자신을 audience에 안 넣으므로, 해당 클라이언트에 "Audience" 프로토콜 매퍼가 필요합니다(이 저장소의 kosmos 클라이언트엔 이미 반영되어 있음).

알려진 제약사항

OIDC 그룹 클레임(--oidc-groups-claim)은 설정되어 있지만, 기본 관리자 계정이 Keycloak 그룹에 소속되어 있지 않아 groups 클레임이 비어있습니다. 그룹 기반 권한 부여가 필요하면 Keycloak에서 사용자를 그룹에 추가해야 합니다.

다음 단계