본문으로 바로가기 본문 바로가기
WIKI 기술 지식 베이스

Istio 서비스 메시에 Calico 네트워크 정책 적용하기

원문 보기 위키 갱신

Istio 서비스 메시 트래픽에 Calico Open Source 네트워크 정책을 적용하는 방법을 다룹니다. Dikastes 사이드카를 사용해 HTTP 메서드와 경로까지 매칭하는 세밀한 레이어 7 정책을 강제할 수 있습니다. 설치 방식부터 문제 해결까지 실무에 필요한 내용을 모두 담았습니다.

출처: 문서

본문

개요

Dikastes 사이드카를 사용하면 Istio 애플리케이션 레이어 정책에 Calico 네트워크 정책을 적용할 수 있습니다. Dikastes는 Calico가 Istio의 Envoy 프록시와 통합해 세밀한 레이어 7(HTTP) 정책을 강제할 수 있게 해 줍니다.

가치

  • Istio 활성 앱을 위한 pod 트래픽 제어: pod 안팎의 ingress 트래픽을 제한하고 Istio 활성 앱에 대한 일반적인 위협을 완화할 수 있습니다.
  • 제로 트러스트와의 보안 정합성: 트래픽 암호화, 다중 강제 지점, 인증을 위한 다중 신원 기준을 통해 제로 트러스트 네트워크 모델을 지원합니다.
  • 익숙한 정책 언어: 이미 알고 있는 Kubernetes 네트워크 정책과 Calico 네트워크 정책을 그대로 적용합니다.

시작하기 전에

필수 조건

  • Calico CNI가 설치·구성되어 있어야 합니다
  • kubectl과 istioctl CLI 도구가 설치되어 있어야 합니다
  • MutatingAdmissionWebhook 어드미션 컨트롤러가 활성화되어 있어야 합니다

지원되는 Istio 버전

  • Istio v1.28.1 (권장)
  • Istio v1.22+ (Kubernetes 네이티브 사이드카 지원에 필요한 최소 버전)

참고: 이 가이드는 Kubernetes 네이티브 사이드카를 사용하는 Istio 1.22+가 필요합니다. 전통적인 사이드카 주입은 지원하지 않습니다. 구버전 Istio(v1.15.2, v1.10.2)는 레거시 설치를 참고하세요.

필수 Kubernetes 버전

  • Kubernetes v1.29+: 네이티브 사이드카 지원에 필요합니다

방법

이 가이드는 IstioOperator 사용법을 다룹니다.

ConfigMap 패칭 방법은 레거시 설치를 참고하세요.

1. 애플리케이션 레이어 정책 활성화하기

Felix에서 Policy Sync API를 활성화해 Dikastes가 정책 결정을 조회할 수 있게 합니다.

탭: kubectl

kubectl patch felixconfiguration default --type merge -p '{"spec":{"policySyncPathPrefix":"/var/run/nodeagent"}}'

탭: calicoctl

calicoctl patch FelixConfiguration default --patch \
  '{"spec": {"policySyncPathPrefix": "/var/run/nodeagent"}}'

선택 사항: Calico operator를 사용하는 경우 지원 중단된 Flex Volumes를 비활성화합니다:

kubectl patch installation default --type=merge -p '{"spec": {"flexVolumePath": "None"}}'

2. Istio 설치하기

아직 Istio가 설치되어 있지 않다면 Istio 업스트림 설치 문서를 따라 설치합니다.

테스트용으로는 다음을 사용할 수 있습니다:

curl -L https://istio.io/downloadIstio -o install-istio.sh
# Review the script before running it, then install:
ISTIO_VERSION=1.28.1 sh install-istio.sh
cd istio-1.28.1
export PATH=$PWD/bin:$PATH

참고: 설치 중 Dikastes 템플릿을 구성하려면 아직 istioctl install을 실행하지 마세요. 다음 단계를 참고하세요.

3. Dikastes 주입 템플릿으로 Istio 구성하기

옵션 A: IstioOperator 직접 사용

istio-operator-dikastes.yaml이라는 이름의 파일을 만듭니다:

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: istio-with-dikastes
  namespace: istio-system
spec:
  profile: minimal  # or 'default' if you need gateways

  values:
    sidecarInjectorWebhook:
      templates:
        # Template for workload pods
        dikastes: |
          spec:
            containers:
            - name: dikastes
              image: calico/calico:v3.33.0
              command: ["/usr/bin/calico", "component", "dikastes"]
              args:
              - server
              - -l
              - /var/run/dikastes/dikastes.sock
              - -d
              - /var/run/felix/nodeagent/socket
              securityContext:
                allowPrivilegeEscalation: false
                runAsGroup: 999
                runAsNonRoot: true
                runAsUser: 999
              livenessProbe:
                exec:
                  command:
                  - /healthz
                  - liveness
                initialDelaySeconds: 3
                periodSeconds: 3
              readinessProbe:
                exec:
                  command:
                  - /healthz
                  - readiness
                initialDelaySeconds: 3
                periodSeconds: 3
              volumeMounts:
              - mountPath: /var/run/dikastes
                name: dikastes-sock
              - mountPath: /var/run/felix
                name: felix-sync
            initContainers:
            - name: istio-proxy
              volumeMounts:
              - mountPath: /var/run/dikastes
                name: dikastes-sock
            volumes:
            - name: dikastes-sock
              emptyDir:
                medium: Memory
            - name: felix-sync
              csi:
                driver: csi.tigera.io

        # Template for gateway pods (runs as root)
        dikastes-gateway: |
          spec:
            containers:
            - name: dikastes
              image: calico/calico:v3.33.0
              command: ["/usr/bin/calico", "component", "dikastes"]
              args:
              - server
              - -l
              - /var/run/dikastes/dikastes.sock
              - -d
              - /var/run/felix/nodeagent/socket
              securityContext:
                allowPrivilegeEscalation: false
                runAsGroup: 0
                runAsNonRoot: false
                runAsUser: 0
              livenessProbe:
                exec:
                  command:
                  - /healthz
                  - liveness
                initialDelaySeconds: 3
                periodSeconds: 3
              readinessProbe:
                exec:
                  command:
                  - /healthz
                  - readiness
                initialDelaySeconds: 3
                periodSeconds: 3
              volumeMounts:
              - mountPath: /var/run/dikastes
                name: dikastes-sock
              - mountPath: /var/run/felix
                name: felix-sync
            initContainers:
            - name: istio-proxy
              volumeMounts:
              - mountPath: /var/run/dikastes
                name: dikastes-sock
            volumes:
            - name: dikastes-sock
              emptyDir:
                medium: Memory
            - name: felix-sync
              csi:
                driver: csi.tigera.io

Dikastes 템플릿으로 Istio를 설치하거나 업데이트합니다:

istioctl install -f istio-operator-dikastes.yaml -y

이 작업은 다음을 수행합니다:

  • Istio를 설치합니다(아직 설치되어 있지 않다면)
  • Dikastes 템플릿으로 istio-sidecar-injector ConfigMap을 업데이트합니다
  • pod 어노테이션 기반 주입에 템플릿을 사용할 수 있게 만듭니다

템플릿이 로드되었는지 확인합니다:

kubectl get configmap -n istio-system istio-sidecar-injector -o yaml | grep "dikastes:" -A 5

dikastes와 dikastes-gateway 템플릿이 모두 보여야 합니다.

옵션 B: GitOps를 위한 매니페스트 생성

직접 적용하는 대신 Kubernetes 매니페스트를 생성하고 싶다면:

istioctl manifest generate -f istio-operator-dikastes.yaml > istio-with-dikastes.yaml
kubectl apply -f istio-with-dikastes.yaml

4. Envoy 인증 서비스 추가하기

Istio의 Envoy 프록시가 Dikastes를 외부 인증 서비스로 사용하도록 구성합니다.

kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.33.0/manifests/alp/istio-app-layer-policy-envoy-v3.yaml

샘플 매니페스트 보기

이 매니페스트는 다음을 만듭니다:

  • ServiceEntry: Unix 소켓 통신을 위한 dikastes.calico.cluster.local을 정의합니다
  • DestinationRule: 로컬 소켓 통신에서 mTLS를 비활성화합니다
  • EnvoyFilter: Envoy의 External Authorization 필터가 Dikastes를 호출하도록 구성합니다

5. 네임스페이스에 Istio 주입 활성화하기

Istio 활성 워크로드를 배포할 네임스페이스에 레이블을 붙입니다:

kubectl label namespace <your-namespace> istio-injection=enabled

6. Dikastes 주입을 위한 pod 어노테이션 추가하기

pod에 Dikastes 사이드카를 주입하려면 pod 템플릿에 다음 어노테이션을 추가합니다:

일반 워크로드:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  template:
    metadata:
      annotations:
        inject.istio.io/templates: sidecar,dikastes
    spec:
      # ... your pod spec

게이트웨이 워크로드:

metadata:
  annotations:
    inject.istio.io/templates: sidecar,dikastes-gateway

주요 차이점은 다음과 같습니다:

  • dikastes: non-root 사용자(999)로 실행됩니다 — 애플리케이션 워크로드용
  • dikastes-gateway: root(0)로 실행됩니다 — ingress/egress 게이트웨이용

7. Dikastes 주입 확인하기

어노테이션을 붙여 워크로드를 배포한 후:

# Check that Dikastes container is present
kubectl get pod -l app=<your-app> -n <your-namespace> -o jsonpath='{.items[0].spec.containers[*].name}'

dikastes <your-app-container> ... 형태로 보여야 합니다.

pod 상태 확인 (모든 컨테이너가 ready로 표시되어야 합니다):

kubectl get pods -n <your-namespace>

Dikastes 로그 확인:

kubectl logs -n <your-namespace> -l app=<your-app> -c dikastes

다음이 보여야 합니다:

Successfully connected to Policy Sync server
Starting synchronization with Policy Sync server

8. (선택 사항) 엄격한 mTLS 활성화하기

보안을 강화하려면 서비스 간에 엄격한 상호 TLS를 활성화합니다:

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default-strict-mode
  namespace: istio-system
spec:
  mtls:
    mode: STRICT

적용합니다:

kubectl apply -f <filename>.yaml

Calico 네트워크 정책 만들기

Dikastes가 배포되면 이제 Calico 네트워크 정책을 만들어 레이어 7 접근 제어를 강제할 수 있습니다.

참고: 사용할 수 있는 정책 커스텀 리소스 정의는 Calico 배포판(OSS 대 Enterprise)에 따라 다릅니다. 정책 문법은 사용 중인 Calico 문서를 참고하세요.

예시 개념 정책(문법은 다를 수 있습니다):

apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: allow-http-get
  namespace: default
spec:
  selector: app == "myapp"
  types:
  - Ingress
  ingress:
  - action: Allow
    protocol: TCP
    destination:
      ports:
      - 80

기본 동작

명시적인 허용 정책이 없으면 Dikastes는 보안을 위해 기본 거부(default-deny) 자세를 강제합니다. 트래픽을 명시적으로 허용하는 정책을 만들기 전까지 모든 HTTP 요청은 403 Forbidden 응답을 받습니다.

문제 해결

Dikastes 컨테이너가 주입되지 않음

네임스페이스 레이블 확인:

kubectl get namespace <your-namespace> -o jsonpath='{.metadata.labels.istio-injection}'

enabled가 표시되어야 합니다.

pod 어노테이션 확인:

kubectl get pod <pod-name> -n <your-namespace> -o yaml | grep inject.istio.io/templates

inject.istio.io/templates: sidecar,dikastes가 표시되어야 합니다.

ConfigMap의 템플릿 확인:

kubectl get configmap -n istio-system istio-sidecar-injector -o jsonpath='{.data.values}' | grep -o "dikastes:" | wc -l

2가 반환되어야 합니다(템플릿당 하나씩).

Pod가 PodInitializing 또는 CrashLoopBackOff에서 멈춤

pod 이벤트 확인:

kubectl describe pod <pod-name> -n <your-namespace>

Dikastes 로그 확인:

kubectl logs <pod-name> -n <your-namespace> -c dikastes

CSI 드라이버 확인 (Calico와 함께 자동 설치됩니다):

kubectl get pods -n calico-system -l k8s-app=csi-node-driver

모든 CSI 드라이버 pod이 Running이어야 합니다. Dikastes가 Felix Policy Sync API에 접근하려면 CSI 드라이버가 필요합니다.

Felix Policy Sync API 확인:

kubectl get felixconfiguration default -o yaml | grep policySyncPathPrefix

policySyncPathPrefix: /var/run/nodeagent가 표시되어야 합니다.

모든 요청이 403을 반환함

허용 정책이 구성되어 있지 않을 때 이는 정상 동작입니다. Dikastes는 보안을 위해 기본 거부를 강제합니다.

트래픽을 허용하려면 원하는 트래픽을 명시적으로 허용하는 Calico 네트워크 정책을 만드세요.

Envoy가 istio-pilot에 도달하지 못함

pod에 egress 정책이 적용되어 있다면 Envoy가 Istio 컨트롤 플레인에 접근할 수 있어야 합니다.

허용 정책을 적용합니다:

kubectl apply -f https://docs.tigera.io/files/allow-istio-pilot.yaml

BPF 로드 밸런싱 경고

설치 중 다음 경고가 보인다면:

detected Calico CNI with 'bpfConnectTimeLoadBalancing=TCP';
this must be set to 'bpfConnectTimeLoadBalancing=Disabled'

이는 연결 수준 로드 밸런싱에 영향을 줄 수 있지만 기본 기능을 막지는 않습니다. 프로덕션 배포에서는 BPF connect-time 로드 밸런싱을 비활성화합니다:

kubectl patch felixconfiguration default --type merge -p '{"spec":{"bpfConnectTimeLoadBalancing":"Disabled"}}'

레거시 설치(ConfigMap 패칭)

참고: 이 방법은 지원되지만 새 배포에는 권장되지 않습니다. 대신 IstioOperator 방법을 사용하세요.

Istio 1.15 또는 1.10에 레거시 ConfigMap 패칭 방법을 사용해야 한다면:

Istio v1.15.x:

curl https://raw.githubusercontent.com/projectcalico/calico/v3.33.0/manifests/alp/istio-inject-configmap-1.15.yaml -o istio-inject-configmap.yaml
kubectl patch configmap -n istio-system istio-sidecar-injector --patch "$(cat istio-inject-configmap.yaml)"

샘플 매니페스트 보기

Istio v1.10.x:

curl https://raw.githubusercontent.com/projectcalico/calico/v3.33.0/manifests/alp/istio-inject-configmap-1.10.yaml -o istio-inject-configmap.yaml
kubectl patch configmap -n istio-system istio-sidecar-injector --patch "$(cat istio-inject-configmap.yaml)"

샘플 매니페스트 보기

ConfigMap 패칭의 단점:

  • 선언적이지 않습니다(명령형 명령)
  • 버전 관리가 되지 않습니다
  • Istio 업그레이드 후 다시 적용해야 합니다
  • 감사와 리뷰가 어렵습니다

추가 리소스

더 알아보기 (Learn more)

403이 나오면 정책이 없어서일 가능성이 가장 큽니다 — 정책을 만들기 전까지는 기본 거부가 정상입니다. HTTP 메서드와 경로를 활용한 정책 규칙 문서에서 레이어 7 제어를 더 깊이 익혀 보세요.