LabHub
はじめる
배우기 러닝패스 코스

Istio 実測ラボ

取引先のログが見た送信元

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

진짜 Istio 메시에서 Sidecar 범위·REGISTRY_ONLY·ServiceEntry·이그레스 게이트웨이·게이트웨이 인가를 차례로 걸고, 각각이 무엇을 막고 무엇을 못 막는지 받는 쪽의 로그와 상태 코드로 확인한다.

왜 중요한가

나가는 트래픽은 기본값이 '어디로든 통과' 라서 아무것도 하지 않으면 메시는 누가 어디로 나가는지 모른다. 장치를 걸어도 그것이 네임스페이스 설정인지, 게이트웨이의 강제인지 구분하지 않으면 '막았다' 고 믿는 빈틈이 남는다. 받는 쪽(협력사)이 본 출발지로 확인하는 습관이 그 빈틈을 보여 준다.

단계

  1. kubectl apply -f /opt/fixtures/istlab/egress-app.yaml 로 재료(메시 밖 outside 의 partner, 메시 안 shop 의 client, other 의 intruder)를 올리고 파드가 준비될 때까지 기다리세요. 그다음 /root/istlab-egress/01-baseline.txt 에 세 줄을 적으세요 — client 에서 http://partner.outside/ 의 상태 코드 svc=, partner 파드 IP 로 직접 부른 상태 코드 podip=, client 사이드카가 아는 클러스터 수 clusters=(istioctl proxy-config clusters client.shop -o json | jq length).
  2. /root/istlab-egress/sidecar.yaml 에 네임스페이스 shopSidecar default 를 적어 적용하세요 — egress hosts 는 ./*(같은 네임스페이스)와 istio-system/* 둘뿐입니다. 적용 뒤 client 의 클러스터 수를 /root/istlab-egress/02-scope.txtclusters= 로 적으세요.
  3. /root/istlab-egress/sidecar.yaml 의 Sidecar 에 outboundTrafficPolicy.mode: REGISTRY_ONLY 를 더해 다시 적용하세요. 그다음 client 에서 partner 파드 IP 로 x-request-id 를 붙여 부르고, 그 요청이 남긴 client 사이드카의 접근 로그 한 줄을 그대로 /root/istlab-egress/03-blocked.log 에 저장하세요.
  4. /root/istlab-egress/serviceentry.yaml 에 네임스페이스 shopServiceEntry partner-api 를 적어 적용하세요 — 호스트 api.partner.test, location: MESH_EXTERNAL, 포트 80 HTTP, resolution: DNS, 엔드포인트 주소 partner.outside.svc.cluster.local. 적용 뒤 client 에서 api.partner.test 를 이름 풀이한 주소를 /root/istlab-egress/04-se.txtvip= 로, http://api.partner.test/ 의 상태 코드를 code= 로 적으세요.
  5. /root/istlab-egress/egress.yaml 에 세 리소스를 적어 적용하세요 — (1) 네임스페이스 shop 의 Istio Gateway partner-egress(셀렉터 istio: egressgateway, 포트 80 · 프로토콜 HTTPS · tls.mode: ISTIO_MUTUAL, 호스트 api.partner.test), (2) istio-systemDestinationRule egressgateway-for-partner(호스트 istio-egressgateway.istio-system.svc.cluster.local, 부분집합 partner 의 포트 80 에 ISTIO_MUTUAL·sni: api.partner.test), (3) shopVirtualService partner-via-egress(호스트 api.partner.test, gateways partner-egress·meshmesh 에서 온 것은 이그레스 게이트웨이의 부분집합 partner 80 으로, 게이트웨이에서 온 것은 api.partner.test 80 으로). 적용 뒤 /root/istlab-egress/05-path.txt 에 이그레스 게이트웨이 파드 IP egress_pod_ip= 와, 경로에 표식을 붙여 보낸 요청에 대해 partner 로그가 남긴 출발지 partner_saw= 를 적으세요.
  6. other 네임스페이스의 intruder 에서 두 번 부르고 /root/istlab-egress/06-bypass.txt 에 적으세요 — http://partner.outside/ 를 직접 부른 상태 코드 intruder_direct=, http://api.partner.test/ 의 상태 코드 intruder_via_egress=. 같은 직접 호출을 client 에서 한 결과도 client_direct= 로 덧붙입니다.
  7. /root/istlab-egress/egress-authz.yamlistio-systemAuthorizationPolicy partner-only-shop 을 적어 적용하세요 — 셀렉터 istio: egressgateway, action: ALLOW, 출발지 주체 cluster.local/ns/shop/sa/client, 목적지 호스트 api.partner.test. 적용 뒤 client 의 api.partner.test 는 200, intruder 의 같은 요청은 403 이어야 합니다.
  8. /root/istlab-egress/08-report.md 에 여섯 줄 — clusters_before=·clusters_after=(1·2단계), blocked_code=(3단계 로그 줄의 상태 코드), partner_saw=(5단계에서 partner 가 본 출발지가 이그레스 게이트웨이면 egressgateway, client 면 client), intruder_direct=·intruder_via_egress=(6단계) — 을 적고 그 아래 배운 것을 네 줄 이상 적으세요.

참고

기본값에서는 어디로든 나간다

kubectl apply -f /opt/fixtures/istlab/egress-app.yaml 로 재료(메시 밖 outside 의 partner, 메시 안 shop 의 client, other 의 intruder)를 올리고 파드가 준비될 때까지 기다리세요. 그다음 /root/istlab-egress/01-baseline.txt 에 세 줄을 적으세요 — client 에서 http://partner.outside/ 의 상태 코드 svc=, partner 파드 IP 로 직접 부른 상태 코드 podip=, client 사이드카가 아는 클러스터 수 clusters=(istioctl proxy-config clusters client.shop -o json | jq length).

메시의 기본 바깥 정책은 ALLOW_ANY 입니다. 사이드카가 모르는 목적지(서비스가 아닌 파드 IP, 외부 주소)로 가는 요청은 PassthroughCluster 로 그대로 흘려보냅니다. 그리고 사이드카는 기본으로 클러스터의 모든 서비스를 알고 있어서, 서비스가 늘면 모든 프록시의 설정이 함께 커집니다. 두 사실을 숫자로 남겨 두면 뒤 단계에서 무엇이 바뀌었는지 비교할 수 있습니다.

Sidecar 리소스로 프록시가 아는 범위를 줄인다

/root/istlab-egress/sidecar.yaml 에 네임스페이스 shopSidecar default 를 적어 적용하세요 — egress hosts 는 ./*(같은 네임스페이스)와 istio-system/* 둘뿐입니다. 적용 뒤 client 의 클러스터 수를 /root/istlab-egress/02-scope.txtclusters= 로 적으세요.

이름이 default 이고 셀렉터가 없는 Sidecar 는 그 네임스페이스의 모든 사이드카에 걸립니다. egress hosts 는 '이 프록시가 알아야 할 서비스' 목록이라, 여기 없는 네임스페이스의 서비스는 설정에서 빠집니다 — 수천 개 서비스가 있는 메시에서 프록시 메모리와 istiod 의 밀어 넣기 부담을 줄이는 주된 방법입니다. 줄어든 클러스터 목록에 partner.outside 가 없는지도 보세요.

모르는 목적지는 막는다 — REGISTRY_ONLY

/root/istlab-egress/sidecar.yaml 의 Sidecar 에 outboundTrafficPolicy.mode: REGISTRY_ONLY 를 더해 다시 적용하세요. 그다음 client 에서 partner 파드 IP 로 x-request-id 를 붙여 부르고, 그 요청이 남긴 client 사이드카의 접근 로그 한 줄을 그대로 /root/istlab-egress/03-blocked.log 에 저장하세요.

REGISTRY_ONLY 는 '서비스 레지스트리에 있는 곳으로만' 이라는 뜻입니다. 사이드카가 모르는 목적지는 PassthroughCluster 대신 BlackHoleCluster 로 가고 502 가 납니다. 이 네임스페이스의 레지스트리는 2단계에서 줄였으므로 partner.outside 서비스도 이제 '모르는 곳' 입니다. 로그에서 요청을 찾으려면 요청 id 를 직접 붙이세요 — kubectl -n shop logs client -c istio-proxy | grep <id>.

협력사를 레지스트리에 올린다 — ServiceEntry

/root/istlab-egress/serviceentry.yaml 에 네임스페이스 shopServiceEntry partner-api 를 적어 적용하세요 — 호스트 api.partner.test, location: MESH_EXTERNAL, 포트 80 HTTP, resolution: DNS, 엔드포인트 주소 partner.outside.svc.cluster.local. 적용 뒤 client 에서 api.partner.test 를 이름 풀이한 주소를 /root/istlab-egress/04-se.txtvip= 로, http://api.partner.test/ 의 상태 코드를 code= 로 적으세요.

ServiceEntry 는 메시 밖 목적지를 레지스트리에 올려 REGISTRY_ONLY 아래에서도 나갈 수 있게 합니다. 그런데 api.partner.test 라는 이름은 클러스터 DNS 에 없습니다. 이 메시는 사이드카의 DNS 프록시를 켜 두어서, 사이드카가 이 이름에 자동으로 할당한 가상 IP(240.240.x.x)를 답합니다. 그 값은 ServiceEntry 의 status.addresses 에도 있습니다. 파드 안에서 nslookup api.partner.test 로 확인하세요.

나가는 길을 이그레스 게이트웨이 하나로 모은다

/root/istlab-egress/egress.yaml 에 세 리소스를 적어 적용하세요 — (1) 네임스페이스 shop 의 Istio Gateway partner-egress(셀렉터 istio: egressgateway, 포트 80 · 프로토콜 HTTPS · tls.mode: ISTIO_MUTUAL, 호스트 api.partner.test), (2) istio-systemDestinationRule egressgateway-for-partner(호스트 istio-egressgateway.istio-system.svc.cluster.local, 부분집합 partner 의 포트 80 에 ISTIO_MUTUAL·sni: api.partner.test), (3) shopVirtualService partner-via-egress(호스트 api.partner.test, gateways partner-egress·meshmesh 에서 온 것은 이그레스 게이트웨이의 부분집합 partner 80 으로, 게이트웨이에서 온 것은 api.partner.test 80 으로). 적용 뒤 /root/istlab-egress/05-path.txt 에 이그레스 게이트웨이 파드 IP egress_pod_ip= 와, 경로에 표식을 붙여 보낸 요청에 대해 partner 로그가 남긴 출발지 partner_saw= 를 적으세요.

VirtualService 하나가 두 구간을 맡습니다. 사이드카(mesh)에서는 목적지를 이그레스 게이트웨이로 바꾸고, 게이트웨이에서는 진짜 목적지로 보냅니다. 사이드카 → 게이트웨이 구간의 mTLS 는 저절로 걸리지 않습니다 — Gateway 를 평문 HTTP 로 두면 요청은 지나가도 게이트웨이가 보낸 쪽의 신원을 모릅니다(7단계에서 필요합니다). DestinationRule 을 istio-system 에 두는 것은 다른 네임스페이스의 사이드카도 부분집합 partner 를 찾게 하려는 것입니다 — shop 에 두면 shop 의 사이드카만 봅니다. 거쳤는지는 받는 쪽에서 보세요. 게이트웨이는 x-request-id 를 새로 매기므로 http://api.partner.test/<표식> 처럼 경로에 표식을 붙여 partner 로그에서 찾고, 그 줄의 출발지가 이그레스 게이트웨이 파드 IP 인지 봅니다.

게이트웨이를 거치지 않는 길이 아직 남아 있다

other 네임스페이스의 intruder 에서 두 번 부르고 /root/istlab-egress/06-bypass.txt 에 적으세요 — http://partner.outside/ 를 직접 부른 상태 코드 intruder_direct=, http://api.partner.test/ 의 상태 코드 intruder_via_egress=. 같은 직접 호출을 client 에서 한 결과도 client_direct= 로 덧붙입니다.

Sidecar 리소스와 REGISTRY_ONLY 는 shop 의 프록시 설정일 뿐입니다. 다른 네임스페이스의 프록시는 여전히 ALLOW_ANY 이고, 사이드카가 없는 파드라면 아예 이 설정을 모릅니다. Istio 문서도 이그레스 게이트웨이만으로는 '모든 바깥 트래픽이 게이트웨이를 지난다' 를 강제할 수 없고, 네트워크 정책 같은 다른 장치를 함께 써야 한다고 밝힙니다. 그 빈틈을 숫자로 남기세요.

게이트웨이에서 누가 나갈 수 있는지 정한다

/root/istlab-egress/egress-authz.yamlistio-systemAuthorizationPolicy partner-only-shop 을 적어 적용하세요 — 셀렉터 istio: egressgateway, action: ALLOW, 출발지 주체 cluster.local/ns/shop/sa/client, 목적지 호스트 api.partner.test. 적용 뒤 client 의 api.partner.test 는 200, intruder 의 같은 요청은 403 이어야 합니다.

사이드카에서 이그레스 게이트웨이까지는 mTLS 라서, 게이트웨이는 요청을 보낸 워크로드의 신원(SPIFFE)을 압니다. 그래서 '어느 네임스페이스·서비스어카운트가 이 협력사로 나갈 수 있는가' 를 게이트웨이 한 곳에서 정할 수 있습니다 — 이그레스 게이트웨이를 두는 진짜 이유가 이것입니다. ALLOW 정책이 하나라도 있으면 맞지 않는 요청은 모두 거절됩니다.

나가는 길을 어디서 막았는지 정리한다

/root/istlab-egress/08-report.md 에 여섯 줄 — clusters_before=·clusters_after=(1·2단계), blocked_code=(3단계 로그 줄의 상태 코드), partner_saw=(5단계에서 partner 가 본 출발지가 이그레스 게이트웨이면 egressgateway, client 면 client), intruder_direct=·intruder_via_egress=(6단계) — 을 적고 그 아래 배운 것을 네 줄 이상 적으세요.

값은 앞 단계 파일에서 옮기세요. 설명 줄에는 'Sidecar·REGISTRY_ONLY·이그레스 게이트웨이·인가 정책이 각각 무엇을 막고 무엇을 못 막는가' 를 자기 말로 적어 두세요.