Kubernetes Tools/Cilium

EP10. CIDR, Entity 기반 정책 구성 | 외부 접근 정밀 제어

ygtoken 2025. 3. 22. 23:47
728x90

 

이 글에서는 Cilium의 CIDR과 Entity 기반 네트워크 정책을 통해 외부 접근을 정밀하게 제어하는 방법을 살펴봅니다. 앞서 살펴본 L3/L4 및 L7 정책들이 주로 클러스터 내부 통신을 제어하는 데 중점을 두었다면, 이번에는 외부 네트워크와의 통신을 세밀하게 관리하는 방법을 실습합니다. 특정 IP 대역만 허용하거나, world, host, remote-node와 같은 사전 정의된 엔터티들에 대한 접근 제어를 수행하는 방법을 배우고, 이를 통해 쿠버네티스 클러스터의 보안을 한층 더 강화할 수 있습니다.


📌 CIDR 기반 정책의 이해

Cilium CIDR 기반 정책

✅ CIDR(Classless Inter-Domain Routing)이란?

CIDR은 IP 주소를 할당하고 라우팅하기 위한 방법으로, IP 주소와 그 뒤에 슬래시('/')와 함께 따라오는 접두사 길이로 표현됩니다. 예를 들어:

  • 10.0.0.0/8: 10.0.0.0부터 10.255.255.255까지의 IP 범위
  • 192.168.1.0/24: 192.168.1.0부터 192.168.1.255까지의 IP 범위
  • 203.0.113.1/32: 단일 IP 주소 203.0.113.1만 포함

Cilium은 이러한 CIDR 표기법을 사용하여 특정 IP 범위에 대한 정책을 정의할 수 있습니다.

✅ CIDR 정책이 필요한 상황

다음과 같은 경우에 CIDR 기반 정책을 사용할 수 있습니다:

  1. 특정 외부 서비스만 접근 허용: 특정 API 제공자나 파트너사의 IP 범위만 접근을 허용
  2. 공용 클라우드 서비스 접근 제어: AWS, GCP, Azure 등 특정 클라우드 서비스의 IP 범위 허용
  3. 기업 네트워크 통합: 회사 내부 네트워크 범위와의 통신 허용
  4. 지리적 접근 제한: 특정 지역/국가의 IP 범위만 허용 또는 차단
  5. DDoS 방어: 알려진 악성 IP 범위 차단

📌 CIDR 기반 정책 실습

✅ 테스트 환경 구성

먼저 CIDR 정책을 테스트할 환경을 구성합니다:

# cidr-test.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: cidr-test  # 테스트를 위한 격리된 네임스페이스 생성
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server  # 웹 서버 애플리케이션
  namespace: cidr-test
spec:
  selector:
    matchLabels:
      app: web-server  # 이 라벨을 가진 Pod를 관리
  replicas: 1
  template:
    metadata:
      labels:
        app: web-server  # Pod에 적용되는 라벨 (Cilium 정책에서 참조됨)
    spec:
      containers:
      - name: nginx
        image: nginx:1.19  # 기본 웹 서버로 Nginx 사용
        ports:
        - containerPort: 80  # 웹 서버 포트
---
apiVersion: v1
kind: Service
metadata:
  name: web-server  # 웹 서버 서비스
  namespace: cidr-test
spec:
  type: NodePort      # 클러스터 외부에서 접근 가능하도록 NodePort 타입 사용
  selector:
    app: web-server   # 이 라벨을 가진 Pod로 트래픽 전달
  ports:
  - port: 80          # 서비스 포트
    targetPort: 80    # 대상 Pod 포트
    nodePort: 30080   # 노드 포트 (외부에서 접근 가능)
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: client  # 테스트용 클라이언트
  namespace: cidr-test
spec:
  selector:
    matchLabels:
      app: client
  replicas: 1
  template:
    metadata:
      labels:
        app: client  # 클라이언트 Pod 라벨
    spec:
      containers:
      - name: curl
        image: curlimages/curl:7.80.0  # curl이 설치된 이미지
        command:
        - sleep
        - "3600"  # 컨테이너를 1시간 동안 실행 상태로 유지

위의 매니페스트를 적용합니다:

kubectl apply -f cidr-test.yaml

✅ 기본 CIDR 정책 구성

다음은 특정 IP 범위에서만 웹 서버에 접근을 허용하는 기본 CIDR 정책입니다:

# cidr-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "cidr-rule"  # 정책 이름
  namespace: cidr-test
spec:
  endpointSelector:  # 정책이 적용될 대상 Pod 선택
    matchLabels:
      app: web-server  # web-server 라벨을 가진 Pod에 적용
  ingress:  # 인바운드(들어오는) 트래픽 규칙
  - fromCIDR:  # CIDR 기반 출발지 정의
    - "10.0.0.0/8"    # 내부 네트워크 범위 허용
    - "192.168.0.0/16"  # 일반적인 사설 네트워크 범위 허용
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "80"  # 웹 서버 포트(80)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용

정책을 적용합니다:

kubectl apply -f cidr-policy.yaml

✅ 정책 테스트

클라이언트 Pod에서 웹 서버에 접근해 봅시다:

# 클라이언트 Pod 이름 가져오기
CLIENT_POD=$(kubectl get pods -n cidr-test -l app=client -o jsonpath='{.items[0].metadata.name}')

# Pod에서 웹 서버로 요청 보내기
kubectl exec -n cidr-test $CLIENT_POD -- curl -I http://web-server

클라이언트 Pod의 IP 주소가 정책에서 허용하는 범위에 있다면 접근이 성공하고, 그렇지 않다면 차단됩니다. 이는 클러스터 내부 IP 할당 방식에 따라 달라질 수 있습니다.

다음으로 클러스터 외부에서의 접근을 테스트합니다. 로컬 머신에서 노드 포트를 통해 접근해 보세요:

# 클러스터 노드 IP 확인 (Docker Desktop 사용 시 localhost)
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}')

# 웹 서버에 접근
curl -I http://$NODE_IP:30080

로컬 머신의 IP가 정책에서 허용하는 범위에 없으면 접근이 차단됩니다. 이를 통해 CIDR 기반 정책이 특정 IP 범위의 접근만 허용하는 것을 확인할 수 있습니다.


📌 복합 CIDR 정책 구성

 

복합 네트워크 정책 구조

✅ 인그레스(Ingress)와 이그레스(Egress) 모두 제어

다음 정책은 인바운드와 아웃바운드 트래픽 모두에 CIDR 규칙을 적용합니다:

# complex-cidr-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "complex-cidr-rule"  # 정책 이름
  namespace: cidr-test
spec:
  endpointSelector:  # 정책이 적용될 대상 Pod 선택
    matchLabels:
      app: web-server  # web-server 라벨을 가진 Pod에 적용
  ingress:  # 인바운드(들어오는) 트래픽 규칙
  - fromCIDR:  # CIDR 기반 출발지 정의
    - "10.0.0.0/8"  # 내부 네트워크 범위 허용
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "80"  # 웹 서버 포트(80)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
  egress:  # 아웃바운드(나가는) 트래픽 규칙
  - toCIDR:  # CIDR 기반 목적지 정의
    - "8.8.8.8/32"  # Google DNS 서버로의 접근 허용
    - "8.8.4.4/32"  # Google 보조 DNS 서버로의 접근 허용
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "53"  # DNS 포트(53)로의 접근 허용
        protocol: UDP  # UDP 프로토콜 사용
  - toCIDRSet:  # 좀 더 복잡한 CIDR 규칙 집합 정의
    - cidr: "0.0.0.0/0"  # 모든 IP 주소
      except:  # 예외 항목
      - "10.96.0.0/12"  # 쿠버네티스 서비스 CIDR 제외
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "443"  # HTTPS 포트(443)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용

이 정책은:

  • 인바운드 트래픽은 10.0.0.0/8 범위의 출발지에서 오는 경우만 허용
  • 아웃바운드 트래픽은 다음과 같이 제한:
    • Google DNS 서버(8.8.8.8, 8.8.4.4)로의 DNS 쿼리만 허용
    • 쿠버네티스 서비스 CIDR(10.96.0.0/12)을 제외한 모든 목적지로의 HTTPS 접근 허용

기존 정책을 삭제하고 새 정책을 적용합니다:

kubectl delete ciliumnetworkpolicies cidr-rule -n cidr-test
kubectl apply -f complex-cidr-policy.yaml

✅ 복합 정책 테스트

웹 서버 Pod에서 다양한 외부 서비스에 접근해 봅시다:

# 웹 서버 Pod 이름 가져오기
SERVER_POD=$(kubectl get pods -n cidr-test -l app=web-server -o jsonpath='{.items[0].metadata.name}')

# Pod에 접속
kubectl exec -it -n cidr-test $SERVER_POD -- bash

# Google DNS 서버에 DNS 쿼리 (허용됨)
nslookup kubernetes.io 8.8.8.8

# HTTPS 요청 (허용됨)
apt-get update && apt-get install -y curl
curl -I https://kubernetes.io

# 쿠버네티스 서비스로의 HTTPS 요청 (차단됨)
curl -I https://kubernetes-dashboard.svc.cluster.local

# HTTP 요청 (차단됨 - 정책에서 허용하지 않음)
curl -I http://example.com

이 테스트를 통해 CIDR 기반 정책이 인바운드와 아웃바운드 트래픽을 어떻게 제어하는지 확인할 수 있습니다.


📌 Entity 기반 정책의 이해

✅ Entity란?

Cilium에서 Entity는 특별한 의미를 가진 레이블 집합으로, 클러스터 내의 특정 구성 요소나 리소스 그룹을 나타냅니다. 이를 통해 IP 주소나 CIDR을 직접 지정하지 않고도 정책을 정의할 수 있습니다.

Cilium에서 제공하는 주요 Entity는 다음과 같습니다:

  1. world: 클러스터 외부의 모든 엔드포인트 (인터넷 전체)
  2. host: 엔드포인트가 실행 중인 로컬 호스트
  3. remote-node: 로컬 호스트를 제외한 클러스터의 모든 노드
  4. kube-apiserver: 쿠버네티스 API 서버
  5. cluster: 클러스터 내의 모든 엔드포인트
  6. health: Cilium 상태 확인 엔드포인트

 

Cilium Entity 기반 정책 구조

 

✅ Entity 정책이 필요한 상황

다음과 같은 경우에 Entity 기반 정책을 사용하면 편리합니다:

  1. 인터넷 접근 제어: world Entity를 사용하여 인터넷 접근을 허용하거나 차단
  2. 호스트 통신 관리: host Entity를 사용하여 Pod와 노드 간 통신 제어
  3. 클러스터 내부 통신: cluster Entity를 사용하여 클러스터 내 모든 통신 관리
  4. 쿠버네티스 API 접근: kube-apiserver Entity를 사용하여 API 서버 접근 제어

Entity를 사용하면 IP 주소가 변경되더라도 정책이 유효하게 유지됩니다.


📌 Entity 기반 정책 실습

✅ World Entity 사용 정책

외부 인터넷과의 통신을 제어하는 정책입니다:

# world-entity-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "world-access"  # 정책 이름
  namespace: cidr-test
spec:
  endpointSelector:  # 정책이 적용될 대상 Pod 선택
    matchLabels:
      app: client  # client 라벨을 가진 Pod에 적용
  egress:  # 아웃바운드(나가는) 트래픽 규칙
  - toEntities:  # Entity 기반 목적지 정의
    - world      # 클러스터 외부 모든 엔드포인트(인터넷)
    toPorts:     # 특정 포트에 대한 접근 허용
    - ports:
      - port: "443"  # HTTPS 포트(443)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
      - port: "80"   # HTTP 포트(80)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
  - toEntities:  # 다른 Entity 기반 목적지 정의
    - kube-apiserver  # 쿠버네티스 API 서버
    toPorts:          # 특정 포트에 대한 접근 허용
    - ports:
      - port: "443"  # HTTPS 포트(443)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용

이 정책은 클라이언트 Pod가 다음에 접근할 수 있도록 합니다:

  • 인터넷(world)의 HTTP(80) 및 HTTPS(443) 서비스
  • 쿠버네티스 API 서버(kube-apiserver)의 HTTPS(443) 서비스

정책을 적용합니다:

kubectl apply -f world-entity-policy.yaml

✅ Host 및 Remote-Node Entity 정책

노드 간 통신을 제어하는 정책입니다:

# host-entity-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "node-access"  # 정책 이름
  namespace: cidr-test
spec:
  endpointSelector:  # 정책이 적용될 대상 Pod 선택
    matchLabels:
      app: web-server  # web-server 라벨을 가진 Pod에 적용
  ingress:  # 인바운드(들어오는) 트래픽 규칙
  - fromEntities:  # Entity 기반 출발지 정의
    - host         # 로컬 호스트
    - remote-node  # 원격 노드
    toPorts:       # 특정 포트에 대한 접근 허용
    - ports:
      - port: "80"  # 웹 서버 포트(80)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
  egress:  # 아웃바운드(나가는) 트래픽 규칙
  - toEntities:  # Entity 기반 목적지 정의
    - host       # 로컬 호스트
    toPorts:     # 특정 포트에 대한 접근 허용
    - ports:
      - port: "53"  # DNS 포트(53)로의 접근 허용
        protocol: UDP  # UDP 프로토콜 사용

이 정책은:

  • 웹 서버 Pod로의 인바운드 트래픽이 로컬 호스트(host)와 다른 노드(remote-node)에서 오는 경우만 허용
  • 웹 서버 Pod에서 로컬 호스트(host)의 DNS 서비스(53/UDP)로의 아웃바운드 트래픽 허용

정책을 적용합니다:

kubectl apply -f host-entity-policy.yaml

✅ Entity 정책 테스트

클라이언트 Pod에서 다양한 목적지로의 접근을 테스트합니다:

# 클라이언트 Pod에 접속
kubectl exec -it -n cidr-test $CLIENT_POD -- sh

# 외부 HTTP/HTTPS 접근 (허용됨)
curl -I https://kubernetes.io
curl -I http://example.com

# 쿠버네티스 API 서버 접근 (허용됨)
curl -k https://kubernetes.default.svc.cluster.local

# 다른 프로토콜/포트 접근 (차단됨)
nc -zv 8.8.8.8 53

웹 서버 Pod에서도 정책을 테스트합니다:

# 웹 서버 Pod에 접속
kubectl exec -it -n cidr-test $SERVER_POD -- bash

# 호스트의 DNS 접근 (허용됨)
nslookup kubernetes.io

# 외부 HTTP 접근 (차단됨 - 정책에서 허용하지 않음)
apt-get update && apt-get install -y curl
curl -I http://example.com

📌 CIDR 및 Entity 정책 조합

✅ CIDR, Entity, 라벨 기반 정책 통합

실무에서는 CIDR, Entity, 라벨 기반 선택자를 조합하여 복잡한 네트워크 정책을 구성할 수 있습니다:

# combined-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "combined-policy"  # 정책 이름
  namespace: cidr-test
spec:
  endpointSelector:  # 정책이 적용될 대상 Pod 선택
    matchLabels:
      app: web-server  # web-server 라벨을 가진 Pod에 적용
  ingress:  # 인바운드(들어오는) 트래픽 규칙
  - fromEndpoints:  # 라벨 기반 출발지
    - matchLabels:
        app: client   # client 라벨을 가진 Pod에서 오는 트래픽 허용
    toPorts:         # 특정 포트에 대한 접근 허용
    - ports:
      - port: "80"   # 웹 서버 포트(80)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
  - fromCIDR:  # CIDR 기반 출발지
    - "10.0.0.0/8"  # 내부 네트워크 범위
    toPorts:        # 특정 포트에 대한 접근 허용
    - ports:
      - port: "80"  # 웹 서버 포트(80)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
  - fromEntities:  # Entity 기반 출발지
    - host  # 로컬 호스트
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "80"  # 웹 서버 포트(80)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
  egress:  # 아웃바운드(나가는) 트래픽 규칙
  - toEndpoints:  # 라벨 기반 목적지
    - matchLabels:
        "k8s:io.kubernetes.pod.namespace": kube-system
        "k8s:k8s-app": kube-dns
    toPorts:      # 특정 포트에 대한 접근 허용
    - ports:
      - port: "53"  # DNS 포트(53)로의 접근 허용
        protocol: UDP  # UDP 프로토콜 사용
  - toCIDR:  # CIDR 기반 목적지
    - "8.8.8.8/32"  # Google DNS 서버
    toPorts:        # 특정 포트에 대한 접근 허용
    - ports:
      - port: "53"  # DNS 포트(53)로의 접근 허용
        protocol: UDP  # UDP 프로토콜 사용
  - toEntities:  # Entity 기반 목적지
    - world  # 클러스터 외부 모든 엔드포인트(인터넷)
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "443"  # HTTPS 포트(443)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용

이 정책은 다양한 유형의 선택자를 조합하여 복잡한 네트워크 정책을 구성하는 예시입니다. 기존 정책을 삭제하고 새 정책을 적용합니다:

kubectl delete ciliumnetworkpolicies world-access -n cidr-test
kubectl delete ciliumnetworkpolicies node-access -n cidr-test
kubectl delete ciliumnetworkpolicies complex-cidr-rule -n cidr-test
kubectl apply -f combined-policy.yaml

📌 외부 서비스 접근 제어를 위한 실무 패턴

외부 접근 제어 아키텍처

 

✅ 클라우드 서비스 접근 관리

클라우드 제공자의 서비스에 대한 접근을 관리하는 정책입니다:

# cloud-access-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "cloud-access"  # 정책 이름
  namespace: cidr-test
spec:
  endpointSelector:  # 정책이 적용될 대상 Pod 선택
    matchLabels:
      app: client  # client 라벨을 가진 Pod에 적용
  egress:  # 아웃바운드(나가는) 트래픽 규칙
  - toFQDNs:  # 도메인 이름 기반 목적지
    - matchName: "*.s3.amazonaws.com"  # Amazon S3 서비스
    - matchName: "*.amazonaws.com"     # 기타 AWS 서비스
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "443"  # HTTPS 포트(443)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
  - toCIDR:  # CIDR 기반 목적지 (AWS 서비스 일부 IP 범위 예시)
    - "52.216.0.0/15"  # AWS S3 일부 IP 범위
    - "54.231.0.0/17"  # AWS S3 일부 IP 범위
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "443"  # HTTPS 포트(443)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용

이 정책은 AWS 서비스에 대한 접근을 허용하는 예시입니다. 실제 AWS IP 범위는 Amazon에서 공식적으로 제공하는 최신 정보를 참고해야 합니다.

✅ 업데이트 및 모니터링 서버 접근 정책

시스템 업데이트 및 모니터링 서버에 대한 접근을 관리하는 정책입니다:

# system-access-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "system-access"  # 정책 이름
  namespace: cidr-test
spec:
  endpointSelector:  # 정책이 적용될 대상 Pod 선택
    matchLabels: {}  # 모든 Pod에 적용 (네임스페이스 내)
  egress:  # 아웃바운드(나가는) 트래픽 규칙
  - toFQDNs:  # 도메인 이름 기반 목적지
    - matchName: "archive.ubuntu.com"      # Ubuntu 저장소
    - matchName: "security.ubuntu.com"     # Ubuntu 보안 업데이트
    - matchName: "apt.kubernetes.io"       # 쿠버네티스 패키지
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "80"   # HTTP 포트(80)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
      - port: "443"  # HTTPS 포트(443)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
  - toEntities:  # Entity 기반 목적지
    - kube-apiserver  # 쿠버네티스 API 서버
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "443"  # HTTPS 포트(443)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
  - toEndpoints:  # 라벨 기반 목적지
    - matchLabels:  # kube-system 네임스페이스의 모니터링 구성요소
        "k8s:io.kubernetes.pod.namespace": kube-system
        "k8s:k8s-app": "prometheus-operator"
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "9090"  # Prometheus 포트(9090)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용

 

 

이 정책은 시스템 업데이트 서버, 쿠버네티스 API 서버, 모니터링 서버에 대한 접근을 허용합니다.

✅ 내부 서비스와 외부 접근 통합 정책

내부 서비스와 제한된 외부 접근을 통합한 정책입니다:

# comprehensive-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "comprehensive-access"  # 정책 이름
  namespace: cidr-test
spec:
  endpointSelector:  # 정책이 적용될 대상 Pod 선택
    matchLabels:
      app: web-server  # web-server 라벨을 가진 Pod에 적용
  ingress:  # 인바운드(들어오는) 트래픽 규칙
  - fromEndpoints:  # 라벨 기반 출발지
    - matchLabels:  # 동일한 네임스페이스의 다른 Pod
        app: client  # client 라벨을 가진 Pod에서 오는 트래픽 허용
  - fromCIDR:  # CIDR 기반 출발지
    - "10.0.0.0/8"  # 내부 네트워크 범위
    - "192.168.0.0/16"  # 일반적인 사설 네트워크 범위
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "80"  # 웹 서버 포트(80)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
  egress:  # 아웃바운드(나가는) 트래픽 규칙
  - toEndpoints:  # 라벨 기반 목적지
    - matchLabels:  # kube-system 네임스페이스의 DNS 서비스
        "k8s:io.kubernetes.pod.namespace": kube-system
        "k8s:k8s-app": kube-dns
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "53"  # DNS 포트(53)로의 접근 허용
        protocol: UDP  # UDP 프로토콜 사용
  - toFQDNs:  # 도메인 이름 기반 목적지
    - matchName: "api.github.com"  # GitHub API
    - matchName: "registry.hub.docker.com"  # Docker Hub
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "443"  # HTTPS 포트(443)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용
  - toCIDR:  # CIDR 기반 목적지
    - "192.168.1.0/24"  # 내부 백엔드 서비스 네트워크 (예시)
    toPorts:  # 특정 포트에 대한 접근 허용
    - ports:
      - port: "8080"  # 백엔드 서비스 포트(8080)로의 접근 허용
        protocol: TCP  # TCP 프로토콜 사용

이 정책은 내부 서비스(DNS, 백엔드 서비스)와 특정 외부 서비스(GitHub API, Docker Hub)에 대한 접근을 통합적으로 관리합니다.


📌 정책 최적화 및 관리 팁

✅ CIDR 정책 최적화

  1. 적절한 CIDR 블록 크기 선택:
    • 너무 광범위한 CIDR 블록은 보안 위험을 증가시킵니다.
    • 너무 세분화된 CIDR 블록은 관리 복잡성을 증가시킵니다.
    • 비즈니스 요구사항에 맞는 적절한 균형을 찾으세요.
  2. CIDR 그룹화:
    • 유사한 목적을 가진 IP 범위는 함께 그룹화하세요.
    • 클라우드 제공자, 지역, 기능별로 CIDR 정책을 조직화하세요.
  3. toCIDRSet 활용:
    • 광범위한 범위에서 특정 IP를 제외해야 할 때 toCIDRSet의 except 필드를 사용하세요.
    • 예: 인터넷 전체에서 내부 네트워크만 제외

✅ Entity 정책 모범 사례

  1. 적절한 Entity 선택:
    • 가능한 한 구체적인 Entity를 사용하세요.
    • world는 모든 외부 엔드포인트를 허용하므로 주의해서 사용하세요.
  2. Entity와 다른 선택자 조합:
    • Entity와 CIDR, 라벨 기반 선택자를 조합하여 세밀한 정책을 만드세요.
    • 각 선택자 유형의 장점을 활용하세요.
  3. 정책 분리:
    • 너무 복잡한 정책은 디버깅과 관리가 어렵습니다.
    • 목적에 따라 여러 작은 정책으로 분리하세요.

✅ 정책 관리 팁

  1. 정책 테스트:
    • 새로운 정책을 프로덕션에 적용하기 전에 테스트 환경에서 검증하세요.
    • Hubble을 사용하여 트래픽 흐름을 모니터링하고 정책 효과를 확인하세요.
  2. 문서화:
    • 각 정책의 목적과 범위를 명확히 문서화하세요.
    • IP 범위나 도메인의 의미와 사용 이유를 주석으로 설명하세요.
  3. 정기적인 검토:
    • CIDR 범위가 여전히 유효한지 정기적으로 검토하세요.
    • 불필요하게 된 정책은 제거하세요.
  4. IP 주소 변경 대비:
    • 가능한 한 CIDR 대신 toFQDNs나 Entity를 사용하세요.
    • IP 주소는 변경될 수 있지만, 도메인 이름과 Entity는 더 안정적입니다.

📌 Hubble을 활용한 CIDR 및 Entity 정책 모니터링

✅ Hubble로 정책 효과 모니터링

Hubble을 사용하여 CIDR 및 Entity 기반 정책의 효과를 모니터링할 수 있습니다:

# CIDR 관련 트래픽 흐름 관찰
hubble observe --cidr 10.0.0.0/8

# 특정 IP 주소에 대한 트래픽 흐름 관찰
hubble observe --ip 8.8.8.8

# 거부된 트래픽 관찰
hubble observe --verdict DROPPED

# 특정 포트로의 트래픽 관찰
hubble observe --port 443

# JSON 형식으로 출력하여 추가 분석
hubble observe --output json > traffic_logs.json

Hubble UI에서도 다음과 같은 필터를 사용하여 트래픽을 시각적으로 모니터링할 수 있습니다:

  • ip 8.8.8.8: 특정 IP 주소와의 통신
  • from-cidr 10.0.0.0/8: 특정 CIDR에서 오는 트래픽
  • to-cidr 192.168.0.0/16: 특정 CIDR로 가는 트래픽
  • verdict DROPPED: 차단된 트래픽

✅ 문제 해결 사례

  1. 예상치 못한 연결 차단:
    • Hubble로 차단된 트래픽을 확인: hubble observe --verdict DROPPED
    • 정책과 실제 트래픽 패턴 비교
    • 필요한 CIDR 범위나 Entity가 정책에 포함되어 있는지 확인
  2. 외부 서비스 접근 문제:
    • DNS 조회가 성공하는지 확인: hubble observe --protocol dns
    • DNS 응답에서 반환된 IP가 정책의 허용된 CIDR 범위에 포함되는지 확인
    • toFQDNs 정책이 제대로 적용되었는지 확인
  3. 노드 간 통신 문제:
    • host 및 remote-node Entity에 대한 정책 확인
    • 클러스터 네트워크 CIDR과 정책의 CIDR 일치 여부 확인
    • 시스템 구성요소에 필요한 포트가 열려 있는지 확인

📌 Summary

이번 글에서는 Cilium의 CIDR 및 Entity 기반 네트워크 정책을 통해 외부 접근을 정밀하게 제어하는 방법을 살펴보았습니다:

CIDR 기반 정책의 주요 특징:

  • 특정 IP 주소 범위에 대한 접근 제어 가능
  • fromCIDR(인바운드) 및 toCIDR(아웃바운드) 규칙 지원
  • toCIDRSet을 통한 예외 처리 가능

Entity 기반 정책의 주요 특징:

  • world, host, remote-node 등 사전 정의된 Entity 지원
  • IP 주소가 변경되어도 정책이 유효하게 유지
  • 쿠버네티스 구성요소와의 통신 제어 용이

실무 적용 패턴:

  • 클라우드 서비스 접근 관리
  • 업데이트 및 모니터링 서버 접근 제어
  • 내부 서비스와 외부 접근 통합 관리

정책 최적화 및 관리 팁:

  • 적절한 CIDR 블록 크기와 Entity 선택
  • 목적에 맞는 정책 분리
  • Hubble을 활용한 정책 모니터링 및 문제 해결

 

728x90