12 KiB
Ingress / Traefik 운영
dev 환경은 K3s packaged Traefik 을 그대로 유지한다. 단 /var/lib/rancher/k3s/server/manifests/traefik.yaml 는 수정하지 않는다. 운영 설정은 k8s/overlays/dev/platform/traefik/ 의 HelmChartConfig 로만 오버라이드한다.
현재 구성
| 위치 | 역할 |
|---|---|
k8s/overlays/dev/platform/traefik/helmchartconfig.yaml |
Traefik replica, 기본 ingressClass, HTTP→HTTPS redirect, metrics, 기본 TLS option 연결 |
k8s/overlays/dev/platform/traefik/middleware.yaml |
공용 security-headers Middleware + modern-tls TLSOption |
k8s/overlays/dev/auth/ingress.yaml |
project.com → auth-server |
k8s/overlays/dev/keycloak/ingress-public.yaml |
keycloak.dev.example.com → Keycloak 공개 path (/realms/, /resources/, /.well-known/, /js/) |
k8s/overlays/dev/platform/cert-manager/ |
cert-manager v1.20.2 CRD/controller 설치 overlay |
k8s/overlays/dev/platform/cert-manager-issuers/ |
letsencrypt-staging / letsencrypt-prod ClusterIssuer |
k8s/overlays/dev/platform/keycloak-operator/ |
Keycloak Operator 26.6.1. dev 제약상 mnt 에 설치해 mnt 의 Keycloak CR 을 watch. K8s API egress NetworkPolicy 포함 |
k8s/overlays/dev/tls/*.yaml |
cert-manager 설치 후 발급할 Certificate 리소스 |
k8s/components/forward-auth/ |
oauth2-proxy + Traefik ForwardAuth 재사용 component |
k8s/overlays/dev/ |
기본 dev overlay. 현재 forward-auth component 를 직접 포함 |
k8s/overlays/dev/keycloak-realm/ |
KeycloakRealmImport 로 realm/client 를 Git 관리 |
설계 원칙
- 앱은
Ingress만 선언하고, 공통 보안 정책은 Traefik Middleware / TLSOption 으로 재사용 - Keycloak 은 외부 전체 공개가 아니라 최소 공개 path 만 연다.
/admin,/metrics,/health는 비공개 - TLS 리소스는 cert-manager + ClusterIssuer 적용 후
tls/overlay 에서 발급 - north-south ingress 는
kube-system의 Traefik Pod 에서만 시작 → app NetworkPolicy 도 그에 맞춰 작성
ForwardAuth variant
k8s/components/forward-auth/ 는 oauth2-proxy + ForwardAuth Middleware 를 담은 Kustomize component 다. 현재 k8s/overlays/dev/ 가 이 component 를 직접 포함한다.
구성:
oauth2-proxyDeployment / Service / ConfigMap / VaultStaticSecretproject.com/oauth2/*경로용 Ingressoauth2-proxy-authTraefik Middlewareauth-serverIngress patch —project.com/요청은 oauth2-proxy 를 거친 인증된 사용자만 통과
흐름: Traefik ForwardAuth → oauth2-proxy → Keycloak.
적용 전제
k8s/overlays/dev/keycloak-realm/또는 동등한 방법으로platformrealm +auth-server-ingressclient 가 준비됨- redirect URI:
https://project.com/oauth2/callback - Vault path
secret/oauth2-proxy/forward-auth에client_secret,cookie_secret저장 project.com,keycloak.dev.example.com이 실제 Traefik 진입점으로 해석됨
브라우저 접속 전제
curl 검증은 --resolve project.com:443:<ingress-ip> 와 -k 로 DNS/TLS 문제를 우회할 수 있다. 브라우저는 이 옵션이 없으므로 dev 환경에서 직접 접속하려면 운영자가 아래를 별도로 맞춰야 한다.
<ingress-ip> project.com
<ingress-ip> keycloak.dev.example.com
예: Traefik LoadBalancer IP 중 하나가 10.208.141.123 이면 로컬 /etc/hosts 에 두 host 를 추가한다. dev overlay 는 현재 외부 ACME 발급 대신 dev-selfsigned ClusterIssuer 를 사용하므로 브라우저에서는 인증서 경고를 허용하거나 해당 인증서를 로컬 trust store 에 등록해야 한다. 공인 DNS 가 Traefik 진입점으로 향하고 ACME 인증서가 Ready 가 되면 이 임시 조치는 제거한다.
Chrome 에서 계속 실패하면 먼저 boundary 를 나눈다.
| Boundary | 확인 |
|---|---|
| 로컬 DNS | getent hosts project.com keycloak.dev.example.com 이 Traefik IP 를 반환해야 한다. |
| 브라우저 DNS cache | /etc/hosts 수정 후 Chrome 재시작 또는 chrome://net-internals/#dns 에서 cache clear. |
| TLS trust | ERR_CERT_* 가 나오면 dev self-signed 인증서를 허용하거나 trust store 에 등록한다. |
| 인증 redirect | curl -k -D - --resolve project.com:443:<ingress-ip> https://project.com/swagger-ui.html 가 302 Location: https://keycloak... 를 반환해야 한다. |
| 로그인 후 app route | 인증 후 404 PRES-005 는 ForwardAuth 실패가 아니라 auth-server 에 해당 route 가 없다는 뜻이다. |
브라우저 검증 순서
dev ForwardAuth 를 브라우저에서 직접 확인할 때는 아래 순서로 진행한다. 중간 단계를 건너뛰면 "Chrome 이 안 된다" 만 보이고 어느 boundary 가 깨졌는지 알기 어렵다.
1. Traefik 진입 IP 확인
kubectl -n kube-system get svc traefik \
-o jsonpath='{.status.loadBalancer.ingress[*].ip}{"\n"}'
예상 예시:
10.208.141.123 10.208.141.14
이 문서의 예시는 10.208.141.123 을 사용한다. 실제 클러스터에서 나온 IP 중 하나를 선택한다.
2. curl 로 클러스터 경로 먼저 확인
브라우저를 열기 전에 curl 로 Traefik / oauth2-proxy / Keycloak boundary 가 살아있는지 확인한다.
curl -k -sS -L \
-D /tmp/project-infra-login.headers \
-o /tmp/project-infra-login.body \
--resolve project.com:443:10.208.141.123 \
--resolve keycloak.dev.example.com:443:10.208.141.123 \
https://project.com/swagger-ui.html
정상 신호:
sed -n '1,80p' /tmp/project-infra-login.headers
grep -o '<title>[^<]*' /tmp/project-infra-login.body
정상이라면 헤더에는 첫 응답 HTTP/2 302 와 location: https://keycloak.dev.example.com/.../auth 가 보이고, body title 은 아래처럼 나온다.
<title>Sign in to platform
이 단계가 실패하면 브라우저를 볼 필요가 없다. 먼저 docs/troubleshooting.md 의 ForwardAuth 로그인 E2E 검증 실패 사건에서 해당 boundary 를 찾는다.
3. 빠른 Chrome 임시 프로필로 확인
로컬 /etc/hosts 와 인증서 trust 를 건드리기 전에, Chrome 실행 옵션으로 DNS/TLS 를 임시 우회해 본다.
google-chrome \
--user-data-dir=/tmp/project-infra-chrome \
--ignore-certificate-errors \
--host-resolver-rules="MAP project.com 10.208.141.123, MAP keycloak.dev.example.com 10.208.141.123" \
https://project.com/swagger-ui.html
정상 흐름:
https://project.com/swagger-ui.html접속- Traefik ForwardAuth 가 미인증 요청을 감지
302로 Keycloak 로그인 화면 이동Sign in to platform화면 표시- 로그인 성공 후
project.com으로 callback
이 방식으로 성공하면 Kubernetes / Traefik / oauth2-proxy / Keycloak 경로는 정상이다. 평소 Chrome 에서 안 되는 원인은 로컬 DNS cache, /etc/hosts, 인증서 trust, 기존 쿠키 중 하나다.
4. 일반 Chrome 으로 볼 수 있게 hosts 등록
임시 Chrome 이 성공하면 로컬 OS resolver 를 맞춘다.
sudo tee -a /etc/hosts >/dev/null <<'EOF'
# Project-Infra dev ingress
10.208.141.123 project.com
10.208.141.123 keycloak.dev.example.com
EOF
확인:
getent hosts project.com keycloak.dev.example.com
두 host 가 선택한 Traefik IP 를 반환해야 한다.
5. Chrome DNS cache / 기존 세션 정리
hosts 를 바꾼 뒤에도 Chrome 이 이전 DNS / 쿠키를 들고 있을 수 있다.
권장 순서:
chrome://net-internals/#dns에서 DNS cache clearchrome://net-internals/#sockets에서 socket pools flushproject.com,keycloak.dev.example.com사이트 데이터 삭제- Chrome 완전 종료 후 재시작
그래도 헷갈리면 아래처럼 새 임시 프로필을 쓰는 게 가장 빠르다.
google-chrome --user-data-dir=/tmp/project-infra-normal https://project.com/swagger-ui.html
6. 인증서 경고 처리
dev overlay 는 현재 dev-selfsigned ClusterIssuer 로 TLS Secret 을 만든다. 따라서 일반 Chrome 에서는 인증서 경고가 뜰 수 있다.
검증 목적이면 고급 옵션에서 예외를 허용한다. 장기적으로 반복 검증할 예정이면 project-com-tls, keycloak-dev-example-com-tls 인증서를 로컬 trust store 에 등록한다.
이 경고는 dev self-signed 인증서 때문에 생기는 것으로, ForwardAuth 실패와는 다른 boundary 다.
7. 로그인 후 결과 해석
로그인 후 swagger-ui.html 이 열리면 브라우저 검증은 성공이다.
로그인 후 /api/me 를 열어 404 PRES-005 가 나오면 이것도 ForwardAuth 실패가 아니다. 인증은 통과했고 auth-server 애플리케이션에 /api/me route 가 없다는 뜻이다.
판단 기준:
| 결과 | 의미 |
|---|---|
| Keycloak 로그인 화면이 뜸 | 미인증 redirect 정상 |
로그인 후 project.com 으로 돌아옴 |
callback / token exchange / session cookie 정상 |
/oauth2/auth 가 202 |
oauth2-proxy 세션 인증 정상 |
auth-server 가 404 PRES-005 반환 |
인증 통과 후 application route 없음 |
auth-server 가 401 반환 |
Authorization header 또는 JWT validation boundary 문제 |
인증 실패 처리
Traefik ForwardAuth 는 /oauth2/auth 를 호출한다. oauth2-proxy 가 401 또는 403 을 반환하면 oauth2-proxy-errors Middleware 가 /oauth2/start?rd={url} 로 넘겨 로그인 흐름을 시작한다.
중요: Traefik errors middleware 는 기본적으로 원래 status code 를 유지할 수 있다. 그러면 oauth2-proxy 가 Location 을 내려도 브라우저는 401 응답을 자동 redirect 로 처리하지 않는다. dev 구성은 statusRewrites 로 401/403 을 302 로 바꿔 브라우저가 바로 Keycloak 로그인 화면으로 이동하게 한다.
cert-manager / ClusterIssuer
repo 에 k8s/overlays/dev/platform/cert-manager/ 와 k8s/overlays/dev/platform/cert-manager-issuers/ 가 추가되어 있다.
- 설치 overlay: 공식 static install
v1.20.2 - issuer overlay: ACME HTTP-01 용
letsencrypt-staging/letsencrypt-prod
source-of-truth 관점에서 cert-manager 도 이 repo 의 선언형 관리 대상. 단, 실제 인증서 발급은 DNS 가 Traefik 외부 진입점을 가리키고 80/443 도달이 가능해야 완료된다.
kubectl apply -k k8s/overlays/dev/platform/cert-manager
kubectl apply -k k8s/overlays/dev/platform/cert-manager-issuers
kubectl apply -k k8s/overlays/dev/tls
운영 보정 필요: admin@project.com 은 실제 운영 수신 가능한 메일로 교체.
Keycloak realm / client Git 관리
k8s/overlays/dev/keycloak-realm/ 는 KeycloakRealmImport 로 platform realm 과 auth-server-ingress client 를 선언한다. k8s/overlays/dev/keycloak/ 도 수제 Deployment 가 아니라 Keycloak CR 기반으로 전환되어 있다.
KeycloakRealmImport 는 같은 mnt namespace 의 Keycloak/keycloak 을 대상으로 동작한다.
적용 순서
kubectl apply -k k8s/overlays/dev/platform/keycloak-operator
# 기존 수제 Deployment/Service/ConfigMap/ServiceAccount keycloak* 정리
kubectl apply -k k8s/overlays/dev
kubectl apply -k k8s/overlays/dev/keycloak-realm
적용 범위
repo 가 커버하는 것:
- Traefik 운영 정책의 Git 관리
- app ingress host / path / policy 정의
- Traefik → app 방향 ingress allow NetworkPolicy
- TLS
Certificate선언 준비 - ForwardAuth variant 와 KeycloakRealmImport 선언
미완 항목(DNS / ACME 발급 / end-to-end 테스트)은 README 의 Limitations 섹션을 참고.