최신글

회고 - Cilium으로 모든 egress 제한하는 방법 중 하나

반응형

배경

아무 맥락 없는 처음 접해본 쿠버네티스 클러스터에 3~4일 정도 시간을 써서 개발환경 egress를 제한해야 하는 상황이었습니다. 해당 쿠버네티스는 국내 CSAP 인증을 받고 있었는데, 이 인증에서 egress 제한이 필요했습니다. 개발환경에서 잘 동작하면 운영팀이 스테이징과 운영환경에 적용할 예정이었습니다.

 

시간도 부족했지만 가장 어려운 점은 클러스터 맥락을 모르는 것이었습니다. 거기에 cilium을 쓰고 있다는 것도 부담이었습니다. cilium을 잘 몰랐지만 hello world 튜토리얼을 공부한 기억이 있어서, cilium을 보자마자 CiliumNetworkPolicy로 egress를 차단하는 방향을 잡았습니다.

 

요구사항 정리

요구사항은 단 하나였습니다.

  • 허용된 곳만 egress가 가능해야 한다.

 

요구사항 구체화하기

저는 요구사항을 구체화했습니다.

  • 쿠버네티스 클러스터에 서로 다른 프로젝트가 있는가? → 없다면 클러스터 내부통신을 전부 허용
  • 앞으로 다른 프로젝트가 이 클러스터에 들어오는가? → 없다면 클러스터 내부통신을 전부 허용
  • whitelist egress 방식은 어떻게 설정할까? → 모든 namespace에 공통 규칙, 각 namespace에 필요한 것은 개별 규칙
  • egress 접근 유형은 무엇인가? → IPv4는 사용 IPv6는 없음, 도메인 사용

 

실제 적용

- 프로젝트 1개만을 위한 전용 쿠버네티스 클러스터여서 클러스터 내부 통신을 허용했습니다.
- 클러스터 공통규칙은 CiliumClusterwideNetworkPolicy로 적용하고, namespace별 규칙은 CiliumNetworkPolicy를 사용했습니다.

 

cilium은 entity를 제공하고 있어서 클러스터 내부 통신은 매우 쉽게 설정할 수 있었습니다.

apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: allow-intra-cluster-egress
spec:
  endpointSelector: {}
  egress:
  - toEntities:
    - cluster
    - kube-apiserver

 

kube-dns가 외부 DNS 질의를 할 수 있도록 egress를 설정했습니다. 그리고 nodelocaldns도 사용하고 있어서 nodelocaldns도 동작하게 egress를 설정했습니다.

apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: allow-external-dns
spec:
  endpointSelector:
    matchExpressions:
    - key: k8s:k8s-app
      operator: In
      values:
      - kube-dns
  egress:
  - toEntities:
    - world
    toPorts:
    - ports:
      - port: "53"
        protocol: UDP
      - port: "53"
        protocol: TCP
      rules:
        dns:
        - matchPattern: "*"
---
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: allow-nodelocal-dns
spec:
  endpointSelector: {}
  egress:
  - toEntities:
    - host
    toPorts:
    - ports:
      - port: "53"
        protocol: UDP
      - port: "53"
        protocol: TCP
      rules:
        dns:
        - matchPattern: "*"

 

운영 고민 사항

과거 차단된 로그를 어떻게 볼 것인가가 가장 큰 운영 이슈였습니다. cilium exporter를 사용하면 쉽게 해결되지만, 이 클러스터는 cilium 설정에 제약이 있었습니다. 어떤 CSP의 managed 쿠버네티스인데 cilium 설정을 변경하면 롤백하는 설정이 있다고 합니다.

 

그래서 짧은 시간에 생각한 방법은 hubble observe를 실행하는 deployment를 생성해서 차단 로그를 보는 것이었습니다. 아래는 수도코드입니다.

hubble status --server hubble-relay.kube-system.svc.cluster.local:80 || exit 1
while true; do
  hubble observe \
    --server hubble-relay.kube-system.svc.cluster.local:80 \
    --follow \
    --output jsonpb \
    --verdict DROPPED \
    --verdict AUDIT || true
  sleep 5
done
반응형