LabHub
学习 学习路径 课程

CCA — Cilium 认证助理

亲眼看 Cilium 真的挡住了什么

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

이 실습은 진짜 Cilium 에서 돕니다

VM 안에 k3s + Cilium 이 실제로 떠 있습니다. kube-proxy 를 끄고 Cilium 이 그 일을 대신하며(kubeProxyReplacement), L7 정책은 Envoy 가 실제로 강제하고, Hubble 이 흐름을 모읍니다.

CCA 과정의 다른 실습은 CRD 만 적재된 가짜 클러스터에서 돕니다. 거기서는 kubectl apply 가 통과할 뿐 아무것도 막지 않습니다. 여기서는 막힙니다.

처음 뜨는 데 4~5분 걸립니다. Cilium 을 설치하기 때문입니다.

목표

아이덴티티가 무엇인지 눈으로 확인하고, L3 정책과 L7 정책을 차례로 쌓은 뒤, Hubble 로 "무엇이 왜 막혔는지" 를 읽습니다.

왜 중요한가

쿠버네티스 기본 NetworkPolicy도 파드·네임스페이스의 라벨 선택자ipBlock으로 통신 상대를 고릅니다. podSelectornamespaceSelector는 ingress의 from과 egress의 to 모두에서 사용할 수 있습니다. IP만 직접 나열해야 하는 API가 아닙니다. 실제 강제는 이를 지원하는 네트워크 플러그인이 합니다.

Cilium은 이 정책 의도를 구현하면서 보안 관련 라벨 집합을 아이덴티티 번호에 대응시킵니다. app=tgt 하나만 같다고 같은 신원인 것은 아닙니다. 네임스페이스 등 다른 보안 관련 라벨도 비교해야 합니다. 같은 집합의 엔드포인트는 신원을 공유하므로 파드 IP를 정책에 일일이 고정하지 않아도 됩니다. 번호 자체를 영구 식별자로 삼기보다 어떤 라벨 집합이 그 번호에 대응하는지 확인하세요.

그리고 Cilium 은 HTTP 경로·메서드까지 봅니다. "이 서비스는 /api/read 만 호출할 수 있다" 를 네트워크 계층에서 강제할 수 있고, 막히면 연결이 끊기는 것이 아니라 403 이 돌아옵니다 — 애플리케이션 입장에서 훨씬 다루기 쉽습니다.

단계

  1. cilium status/root/cca/status.txt 에 저장하세요. KubeProxyReplacement: True 가 보여야 하고, kube-proxy 데몬셋은 없어야 합니다.
  2. mesh 네임스페이스에 tgt(app=tgt, nginx)와 client(app=client, curl)를 만들고, tgt아이덴티티 번호와 그 번호가 어떤 라벨에서 나왔는지를 /root/cca/identity.txt 에 저장하세요.
  3. l3-allow CiliumNetworkPolicy 로 app=clienttgt 에 닿게 하고, 허용된 쪽과 아닌 쪽을 둘 다 시험해 /root/cca/l3.txt 에 저장하세요.
  4. l7-allow 정책으로 /allowed 경로만 허용하세요. /secret403 을 받는 것을 /root/cca/l7.txt 에 기록합니다.
  5. 막히는 요청을 한 번 보낸 뒤 hubble observe 로 흐름을 관찰해 /root/cca/hubble.txt 에 저장하세요. FORWARDEDDROPPED 가 함께 보여야 합니다.
  6. egress-fqdn 정책으로 tgt 가 특정 이름으로만 나갈 수 있게 하세요. 결과를 /root/cca/dnspolicy.txt 에 저장합니다.
  7. hubble observe --type policy-verdict 막혔는지 판정 로그를 뽑아 /root/cca/verdict.txt 에 저장하세요.
  8. /root/cca/report.mdtgt_identity=, l7_denied_code=, policies= 세 줄과 설명을 쓰세요.

참고

kube-proxy 없는 클러스터

cilium status/root/cca/status.txt 에 저장하세요. KubeProxyReplacement: True 가 보여야 하고, kube-proxy 데몬셋은 없어야 합니다.

cilium statusKubeProxyReplacement 줄을 봅니다. True 라면 Service 의 부하 분산을 iptables 가 아니라 eBPF 가 하고 있다는 뜻입니다.

정책은 IP 가 아니라 번호로 판단한다

mesh 네임스페이스에 tgt(app=tgt, nginx)와 client(app=client, curl)를 만들고, tgt아이덴티티 번호와 그 번호가 어떤 라벨에서 나왔는지를 /root/cca/identity.txt 에 저장하세요.

kubectl get ciliumendpoint -n mesh tgt -o yamlstatus.identity 를 봅니다. 그 번호가 어떤 라벨 조합에서 나왔는지도 함께 담으세요.

L3 — 누가 닿을 수 있는가

l3-allow CiliumNetworkPolicy 로 app=clienttgt 에 닿게 하고, 허용된 쪽과 아닌 쪽을 둘 다 시험해 /root/cca/l3.txt 에 저장하세요.

endpointSelector 가 보호받는 파드를, ingress.fromEndpoints 가 허용할 출처를 고릅니다. 쿠버네티스 NetworkPolicy 와 방향 규칙이 같습니다.

L7 — 어느 경로까지 허용하는가

l7-allow 정책으로 /allowed 경로만 허용하세요. /secret403 을 받는 것을 /root/cca/l7.txt 에 기록합니다.

HTTP 규칙은 toPorts[].rules.http 안에 씁니다. 막히면 연결이 끊기는 것이 아니라 403 이 돌아옵니다.

흐름을 눈으로 본다

막히는 요청을 한 번 보낸 뒤 hubble observe 로 흐름을 관찰해 /root/cca/hubble.txt 에 저장하세요. FORWARDEDDROPPED 가 함께 보여야 합니다.

cilium hubble port-forward & 를 먼저 띄우고 hubble observe -n mesh --last 30 을 씁니다. 막히는 요청을 보낸 뒤에 관찰해야 DROPPED 가 보입니다.

이름으로 나가는 곳을 고른다

egress-fqdn 정책으로 tgt 가 특정 이름으로만 나갈 수 있게 하세요. 결과를 /root/cca/dnspolicy.txt 에 저장합니다.

toFQDNs 는 Cilium 이 DNS 응답을 들여다봐야 동작합니다. 그래서 DNS 자체를 toEndpoints + rules.dns.matchPattern 으로 먼저 열어야 합니다.

왜 막혔는지를 묻는다

hubble observe --type policy-verdict 막혔는지 판정 로그를 뽑아 /root/cca/verdict.txt 에 저장하세요.

hubble observe --type policy-verdict 는 각 흐름이 어느 정책에 걸려 어떻게 판정됐는지를 보여 줍니다.

무엇을 배웠나

/root/cca/report.mdtgt_identity=, l7_denied_code=, policies= 세 줄과 설명을 쓰세요.

tgt_identity=, l7_denied_code=, policies= 세 줄과 함께, 아이덴티티가 IP 보다 나은 이유와 L7 거부가 403 인 이유를 설명하세요.