CCA — 실리움 인증 어소시에이트 · 네트워크 정책 · 실습
새 정책을 걸기 전에 누가 막힐지 먼저 본다
목표
진짜 Cilium 1.20.1(enable-policy=default)에서 정책이 언제부터 무엇을 막는지 확인합니다. 방향별 기본 거부, 엔드포인트 감사 모드로 미리 걸어 보기,
감사 해제 뒤의 실제 차단, ingress: [{}] 의 정반대 의미, enableDefaultDeny=false, 두 정책 종류가 한 저장소에 들어가는 모습을
엔드포인트 적용 열·실제 요청·Hubble 판정으로 함께 봅니다.
왜 중요한가
운영 중인 서비스에 egress 정책을 처음 거는 순간이 가장 위험합니다. 문서에 없던 의존성(이 실습의 legacy)이 있으면 그 호출이 곧바로 끊깁니다.
Cilium 의 감사 모드는 판정을 계산하되 거부하지 않고 흐름에 AUDITED 로 남기므로, 누가 막힐지 먼저 보고 나서 강제할 수 있습니다.
다만 감사 모드는 엔드포인트 단위라 이미 강제 중이던 방향까지 느슨해집니다. 또 같은 모양의 YAML 도 쿠버네티스 NetworkPolicy 와
CiliumNetworkPolicy 에서 뜻이 다를 수 있습니다. 적용 열이 Enabled 라고 해서 기본 거부가 켜졌다는 보장도 없습니다. 이런 차이는
문서만 읽어서는 헷갈리기 쉬워 직접 요청을 보내 확인합니다.
클러스터 전체 모드를 always 로 바꾸면 정책이 없는 엔드포인트(coredns 등)까지 막힙니다. 개발 VM 에서 되돌린 뒤 서비스가 돌아오기까지 약 70초가 걸려
이 실습에서는 바꾸지 않습니다. 감사 모드도 엔드포인트 하나에만 켭니다.
환경 준비에 약 5분이 걸립니다. 세션이 끝나면 /root/cca-audit 의 파일은 사라집니다.
단계
1. kubectl apply -f /opt/fixtures/cca-audit/workload.yaml 로 cca-audit 에 파드 api·ledger·legacy·frontend·batch(모두 8080 서버)와 같은 이름의 서비스를 띄우세요. 정책을 걸기 전에 /root/cca-audit/baseline.json 을 만듭니다 — pods 아래 다섯 앱 이름마다 uid(파드), endpoint_id, identity(CiliumEndpoint 의 status), ingress·egress(에이전트 cilium-dbg endpoint list 의 POLICY 열 값), 그리고 최상위 batch_to_api(batch 파드에서 http://api:8080/ 요청의 HTTP 코드 문자열, 응답이 없으면 "000")와 recorded_at(기록한 순간의 UTC 시각, date -u +%Y-%m-%dT%H:%M:%SZ).
2. cca-audit 에 CiliumNetworkPolicy api-ingress 를 만드세요 — endpointSelector app=api, ingress 한 항목(fromEndpoints app=frontend, toPorts TCP "8080"), egress 는 두지 않습니다. 적용이 반영되면 /root/cca-audit/direction.json 에 frontend_to_api, batch_to_api, api_to_legacy(각 요청의 HTTP 코드 문자열, 응답 없음은 "000")와 api_ingress·api_egress(api 엔드포인트의 POLICY 열 값), recorded_at(기록한 순간의 UTC 시각) 을 기록합니다. 3단계의 egress 정책보다 먼저 기록해야 합니다.
3. api 엔드포인트에 감사 모드를 켜세요(cilium-dbg endpoint config <api 번호> PolicyAuditMode=Enabled). 그다음 CNP api-egress 를 적용합니다 — endpointSelector app=api, egress 두 항목: (1) toEndpoints app=ledger, TCP "8080" (2) toEndpoints k8s:io.kubernetes.pod.namespace: kube-system·k8s:k8s-app: kube-dns, 포트 "53" protocol ANY. api→ledger, api→legacy, batch→api 를 요청한 뒤 에이전트 안에서 hubble observe 로 cca-audit 흐름을 읽어 /root/cca-audit/audit.json 에 기록합니다 — endpoint_id, audit_mode, api_ingress·api_egress(POLICY 열), api_to_legacy·batch_to_api(코드 문자열), flows(api→legacy 와 batch→api 의 AUDITED 흐름이 들어 있는 compact 출력 줄 목록).
4. api 엔드포인트의 감사 모드를 끄세요(PolicyAuditMode=Disabled). 같은 요청을 다시 보내고 /root/cca-audit/enforce.json 에 audit_mode, api_ingress·api_egress, api_to_ledger·api_to_legacy·batch_to_api(코드 문자열), flows(감사를 끈 뒤 api→legacy 와 batch→api 의 DROPPED 흐름이 든 compact 줄 목록) 를 기록합니다.
5. cca-audit 에 두 정책을 만드세요 — 표준 NetworkPolicy np-empty(podSelector app=batch, policyTypes [Ingress], ingress: [{}])와 CiliumNetworkPolicy cnp-empty(endpointSelector app=frontend, ingress: [{}]). ledger 파드에서 batch 와 frontend 로 요청해 /root/cca-audit/empty.json 에 batch_from_ledger·frontend_from_ledger(코드 문자열), batch_ingress·frontend_ingress(각 엔드포인트의 ingress POLICY 열) 를 기록합니다.
6. cca-audit 에 CNP ledger-observe 를 만드세요 — endpointSelector app=ledger, enableDefaultDeny: {ingress: false}, ingress 한 항목(fromEndpoints app=api, TCP "8080"). api→ledger 와 batch→ledger 를 요청하고 흐름을 읽어 /root/cca-audit/observe.json 에 ledger_ingress(POLICY 열), api_to_ledger·batch_to_ledger(코드 문자열), flows(두 요청의 ledger 쪽 INGRESS policy-verdict 줄이 든 compact 줄 목록) 를 기록합니다.
7. 에이전트에서 cilium-dbg policy get -o json 을 읽어 cca-audit 네임스페이스 규칙마다 라벨 io.cilium.k8s.policy.name 과 io.cilium.k8s.policy.derived-from 을 찾으세요. /root/cca-audit/sources.json 에 derived_from(정책 이름 → derived-from 값 사전, 다섯 개)과 revision(출력의 revision 숫자) 을 기록합니다.
8. /root/cca-audit/report.txt 에 키=값 일곱 줄을 씁니다 — api_audit_mode(지금 api 의 PolicyAuditMode), api_policy_columns(api 의 ingress 열/egress 열, 예: A/B 형식), api_to_legacy(allowed 또는 denied), np_empty_ingress_rule·cnp_empty_ingress_rule(각각 allow-all 또는 deny-all), ledger_ingress_column, ledger_default_deny_ingress(ledger-observe 의 enableDefaultDeny.ingress 값, true 또는 false). 값은 모두 지금 상태와 일치해야 합니다.
참고
- 정책 적용 모드와 엔드포인트 기본 정책(enableDefaultDeny): https://docs.cilium.io/en/v1.20/security/policy/intro/
- L3 규칙과 Ingress/Egress Default Deny(
- {}예제): https://docs.cilium.io/en/v1.20/security/policy/layer3/ - 판정에서 정책 만들기(감사 모드, 엔드포인트 단위 설정): https://docs.cilium.io/en/v1.20/security/policy-creation/
- 쿠버네티스 NetworkPolicy: https://kubernetes.io/docs/concepts/services-networking/network-policies/
- Hubble 흐름:
kubectl -n kube-system exec ds/cilium -c cilium-agent -- hubble observe --since <시각> --namespace cca-audit -o compact. - 적용 열:
kubectl -n kube-system exec ds/cilium -c cilium-agent -- cilium-dbg endpoint list. 엔드포인트 번호는kubectl -n cca-audit get cep.
단계 8개
- 정책이 하나도 없을 때의 적용 상태를 먼저 적어 둔다
- 들어오는 쪽만 잠갔는데 나가는 쪽은 그대로다
- 새 egress 정책을 감사 모드로 먼저 걸어 누가 막힐지 본다
- 감사를 풀자 같은 두 요청이 실제로 떨어진다
- 똑같이 ingress: [{}] 라고 썼는데 한쪽은 열리고 한쪽은 닫혔다
- 적용 열은 Enabled 인데 아무도 막히지 않는다
- 두 종류의 정책은 한 저장소에 들어간다
- 적용 모드 사고 보고서