이그레스 게이트웨이

이그레스 게이트웨이 (Egress gateways)

이그레스 게이트웨이는 외부 서비스로 가는 모든 아웃바운드 트래픽이 반드시 통과하는 전용 프록시예요. 메시를 떠나는 트래픽에 대한 단일하고 검증 가능한 출구 지점을 제공하며, 여기서 인가 정책을 적용하고, 가시성을 활성화하고, TLS를 시작(originate)할 수 있어요.

출처: Istio 문서

본문

사이드카 모드에서 단일 호스트에 대한 이그레스 게이트웨이를 구성하려면 다섯 개의 별도 오브젝트를 조정해야 해요. ServiceEntry, Gateway, 두 개의 HTTPRoute 리소스(하나는 메시 트래픽을 게이트웨이로 보내고, 다른 하나는 게이트웨이에서 목적지로 트래픽을 전달), 그리고 DestinationRule이에요. 외부 호스트가 새로 추가될 때마다 그 작업의 대부분을 반복해야 해요.

앰비언트 모드에서 웨이포인트 프록시는 자연스럽게 이그레스 게이트웨이 역할을 해요. ztunnel은 트래픽을 목적지로 전달하기 전에 자동으로 서비스의 웨이포인트로 라우팅해요. 웨이포인트를 사용하도록 등록된 네임스페이스에 ServiceEntry를 배치하면, 그 외부 호스트로의 모든 메시 트래픽은 추가 라우팅 규칙 없이 자동으로 웨이포인트를 통과해요.

시작하기 전에 (Before you begin)

Zip

$ kubectl apply -f @samples/curl/curl.yaml@
  • ztunnel이 그 트래픽을 가로채도록 워크로드의 네임스페이스에 앰비언트 모드 레이블을 붙이세요:
$ kubectl label namespace default istio.io/dataplane-mode=ambient

이그레스 네임스페이스 설정하기 (Set up the egress namespace)

이그레스 리소스 전용 네임스페이스를 생성하세요. 외부 서비스 정의와 그 정책을 애플리케이션 네임스페이스에서 격리하면 관리가 단순해지고 잘못된 구성으로 인한 피해 범위(blast radius)가 줄어들어요.

$ kubectl create namespace istio-egress
$ kubectl label namespace istio-egress istio.io/dataplane-mode=ambient

이그레스 웨이포인트 배포하기 (Deploy the egress waypoint)

이그레스 네임스페이스에 웨이포인트 프록시를 배포하고 네임스페이스를 그것을 사용하도록 등록하세요. --enroll-namespace 플래그는 네임스페이스에 istio.io/use-waypoint 레이블을 추가해서, ServiceEntry가 지원하는 것을 포함한 그곳에 정의된 모든 서비스가 웨이포인트를 통해 라우팅되도록 해요.

쿠버네티스 Gateway API CRD는 대부분의 쿠버네티스 클러스터에 기본으로 설치되어 있지 않다는 점을 명심하세요. Gateway API를 사용하기 전에 설치되어 있는지 확인하세요:

$ kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
  kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.0/experimental-install.yaml
$ istioctl waypoint apply --for service --enroll-namespace --namespace istio-egress
✅ waypoint istio-egress/waypoint applied
✅ namespace istio-egress labeled with "istio.io/use-waypoint: waypoint"

웨이포인트가 준비되었는지 확인하세요:

$ istioctl waypoint list -n istio-egress
NAME       REVISION  TRAFFIC TYPE  PROGRAMMED
waypoint   default   service       True

외부 서비스 정의하기 (Define an external service)

외부 호스트를 나타내는 ServiceEntry를 이그레스 네임스페이스에 생성하세요. 네임스페이스가 웨이포인트를 사용하도록 등록되어 있으므로, ztunnel은 이 호스트로의 모든 메시 트래픽을 웨이포인트를 통해 자동으로 라우팅해요. ServiceEntry는 기본적으로 클러스터 전체(exportTo: *)에 보이므로, 모든 노드의 ztunnel이 추가 구성 없이 httpbin.org를 istio-egress 웨이포인트로 해석해요.

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: httpbin-org
  namespace: istio-egress
spec:
  hosts:
  - httpbin.org
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS
EOF

트래픽이 이그레스 웨이포인트를 통해 라우팅되는지 검증하기 (Verify traffic routes through the egress waypoint)

curl 파드에서 외부 호스트로 요청을 보내고 목적지에 도달하는지 확인하세요:

$ kubectl exec deploy/curl -- curl -s -o /dev/null -w "%{http_code}" http://httpbin.org/get
200

트래픽이 웨이포인트를 통과했는지 확인하려면 웨이포인트의 Envoy stats를 확인하세요:

$ kubectl exec -n istio-egress deploy/waypoint -c istio-proxy -- pilot-agent request GET stats | grep upstream_rq_total

0이 아닌 upstream_rq_total 개수(웨이포인트가 업스트림으로 전달한 요청 수)는 웨이포인트가 이그레스 게이트웨이 역할을 하고 있음을 확인해줘요.

접근 정책 적용하기 (Enforce access policies)

트래픽이 웨이포인트를 통과하므로, Layer 7 인가 정책을 ServiceEntry에 직접 부착할 수 있어요. 아래 정책은 어떤 소스든 /get에 대해서만 GET 요청을 발행하도록 허용해요:

$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: httpbin-org
  namespace: istio-egress
spec:
  targetRefs:
  - kind: ServiceEntry
    group: networking.istio.io
    name: httpbin-org
  action: ALLOW
  rules:
  - to:
    - operation:
        methods: ["GET"]
        paths: ["/get"]
EOF

정책을 적용한 후, 허용된 요청이 성공하는지 확인하세요:

$ kubectl exec deploy/curl -- curl -s -o /dev/null -w "%{http_code}" http://httpbin.org/get
200

허용되지 않은 요청이 거부되는지 확인하세요:

$ kubectl exec deploy/curl -- curl -s -o /dev/null -w "%{http_code}" -X POST http://httpbin.org/post
403

이그레스 게이트웨이에서 TLS 시작하기 (Originate TLS at the egress gateway)

애플리케이션 파드는 이그레스 게이트웨이에 평문 HTTP를 보낼 수 있고, 게이트웨이는 외부 호스트로 전달하기 전에 HTTPS로 업그레이드해요. 이는 TLS 자격 증명 관리를 게이트웨이에 집중시키고 각 애플리케이션 파드에 인증서를 배포하는 것을 피하게 해줘요.

평문 포트를 TLS 포트로 매핑하도록 ServiceEntry를 업데이트하고, TLS 연결을 시작할 DestinationRule을 추가하세요:

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: httpbin-org
  namespace: istio-egress
spec:
  hosts:
  - httpbin.org
  ports:
  - number: 80
    name: http
    protocol: HTTP
    targetPort: 443
  resolution: DNS
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: httpbin-org-tls
  namespace: istio-egress
spec:
  host: httpbin.org
  trafficPolicy:
    tls:
      mode: SIMPLE
EOF

애플리케이션이 이제 게이트웨이가 HTTPS로 보낸 응답을 여전히 받는지 확인하세요:

$ kubectl exec deploy/curl -- curl -s http://httpbin.org/get | head -5

TLS 시작 없는 외부 서비스 추가하기 (Add an external service without TLS origination)

같은 이그레스 웨이포인트를 통해 추가 외부 호스트를 노출하려면 같은 네임스페이스에 또 다른 ServiceEntry를 생성하세요. 네임스페이스가 이미 등록되어 있으므로 추가 웨이포인트 구성이 필요 없어요:

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: example-com
  namespace: istio-egress
spec:
  hosts:
  - example.com
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS
EOF

새 호스트로의 트래픽도 웨이포인트를 통해 라우팅되는지 확인하세요:

$ kubectl exec deploy/curl -- curl -s -o /dev/null -w "%{http_code}" http://example.com
200

네임스페이스의 각 ServiceEntry는 자동으로 웨이포인트를 통해 라우팅되고 자기만의 AuthorizationPolicy를 가질 수 있어요.

정리 (Cleanup)

$ kubectl delete namespace istio-egress
$ kubectl delete -f @samples/curl/curl.yaml@
$ kubectl label namespace default istio.io/dataplane-mode-

함께 보기 (See also)

더 알아보기 (Learn more)