LabHub
배우기 러닝패스 코스

CCA — 실리움 인증 어소시에이트 · 네트워크 정책 · 실습

새 정책을 걸기 전에 누가 막힐지 먼저 본다

LabHub 에서 이어서 보기

목표

진짜 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.jsonfrontend_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.jsonaudit_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.jsonbatch_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.jsonledger_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.nameio.cilium.k8s.policy.derived-from 을 찾으세요. /root/cca-audit/sources.jsonderived_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). 값은 모두 지금 상태와 일치해야 합니다.

참고

단계 8개

  1. 정책이 하나도 없을 때의 적용 상태를 먼저 적어 둔다
  2. 들어오는 쪽만 잠갔는데 나가는 쪽은 그대로다
  3. 새 egress 정책을 감사 모드로 먼저 걸어 누가 막힐지 본다
  4. 감사를 풀자 같은 두 요청이 실제로 떨어진다
  5. 똑같이 ingress: [{}] 라고 썼는데 한쪽은 열리고 한쪽은 닫혔다
  6. 적용 열은 Enabled 인데 아무도 막히지 않는다
  7. 두 종류의 정책은 한 저장소에 들어간다
  8. 적용 모드 사고 보고서