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과istioctlCLI 도구가 설치되어 있어야 합니다- 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-injectorConfigMap을 업데이트합니다 - 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 업그레이드 후 다시 적용해야 합니다
- 감사와 리뷰가 어렵습니다
추가 리소스
- Istio 튜토리얼로 네트워크 정책 강제하기
- 정책 규칙에서 HTTP 메서드와 경로 사용하기
- Istio 문서
- IstioOperator API 참조
- Kubernetes 네이티브 사이드카
더 알아보기 (Learn more)
403이 나오면 정책이 없어서일 가능성이 가장 큽니다 — 정책을 만들기 전까지는 기본 거부가 정상입니다. HTTP 메서드와 경로를 활용한 정책 규칙 문서에서 레이어 7 제어를 더 깊이 익혀 보세요.