Istio Hands-on Study [1기]
[3주차] 트래픽 제어(세밀한 트래픽 라우팅) : Istio의 서비스 검색을 사용하여 클러스터 외부의 서비스로 라우팅하기
구구달스
2025. 4. 20. 21:10
CloudNet@ 가시다님이 진행하는 Istio Hands-on Study [1기]
🚀Istio로
클러스터 외부 서비스 호출 관리하기
- Istio의 서비스 디스커버리 기능을 활용해 클러스터 외부 서비스와 안전하게 통신하는 방법
- 외부 트래픽을 차단하고, 필요한 외부 서비스만 허용하도록 ServiceEntry를 설정하는 과정
🔒 외부 트래픽 차단 설정하기
- 기본적으로 Istio는 서비스 메시에서 외부로 나가는 트래픽을 모두 허용하지만, 보안을 강화하려면 이를 차단할 수 있습니다.
외부 트래픽을 차단하면 악의적인 행위자가 메시 내부의 서비스를 통해 데이터를 유출하는 걸 방지할 수 있죠. 이는 defense-in-depth 전략의 일환입니다. - webapp 파드에서 외부 다운로드 성공
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~$ kubectl exec -it deploy/webapp -n istioinaction -c webapp -- wget https://raw.githubusercontent.com/gasida/KANS/refs/heads/main/msa/sock-shop-demo.yaml
Connecting to raw.githubusercontent.com (185.199.108.133:443)
saving to 'sock-shop-demo.yaml'
sock-shop-demo.yaml 100% |*******************************************************************************************| 17782 0:00:00 ETA
'sock-shop-demo.yaml' saved
- 다음 명령어로 Istio의 기본 정책을 ALLOW_ANY에서 REGISTRY_ONLY로 변경해, 서비스 메시 레지스트리에 명시적으로 등록된 서비스로만 트래픽이 나가도록 설정합니다:
이 설정은 메시 외부로 나가는 트래픽을 차단하고, Istio의 서비스 레지스트리에 등록된 외부 서비스로만 통신을 허용
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~$ docker exec -it myk8s-control-plane bash
root@myk8s-control-plane:/# istioctl install --set profile=default --set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY
This will install the Istio 1.17.8 default profile with ["Istio core" "Istiod" "Ingress gateways"] components into the cluster. Proceed? (y/N) y
✔ Istio core installed
✔ Istiod installed
✔ Ingress gateways installed
✔ Installation complete Making this installation the default for injection and validation.
Thank you for installing Istio 1.17. Please take a few minutes to tell us about your install/upgrade experience! https://forms.gle/hMHGiwZHPU7UQRWe9
root@myk8s-control-plane:/# exit
exit
- webapp 파드에서 외부 다운로드 실패
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~$ kubectl exec -it deploy/webapp -n istioinaction -c webapp -- wget https://raw.githubusercontent.com/gasida/KANS/refs/heads/main/msa/sock-shop-demo.yaml
Connecting to raw.githubusercontent.com (185.199.110.133:443)
wget: error getting response: Connection reset by peer
command terminated with exit code 1
실습에서는 istioctl install로 설정을 변경하지만,
실제 환경에서는 IstioOperator나 istio-system의 configmap을 수정하는 게 일반적입니다.
Istio의 outboundTrafficPolicy를 REGISTRY_ONLY로 설정해 외부 트래픽을 차단합니다.
이는 보안을 강화하는 기본적인 방어 전략입니다!
📋 ServiceEntry로 외부 서비스 등록하기
- 메시 내부 서비스가 외부 서비스(예: 데이터베이스, 캐시, 외부 API)와 통신하려면, Istio의 서비스 레지스트리에 해당 서비스를 등록해야 해요. 이를 위해 ServiceEntry 리소스를 사용합니다.
ServiceEntry는 외부 서비스의 메타데이터를 정의해 Istio가 이를 인식하도록 돕습니다. - Istio는 Kubernetes의 Service 객체를 기반으로 내부 서비스 레지스트리를 구축하지만, 외부 서비스는 ServiceEntry로 수동 등록해야 합니다.
- 예를 들어, 우리 가상의 스토어에서 고객 피드백 포럼으로 사용하는 외부 서비스 jsonplaceholder.typicode.com을 등록해보겠습니다.
- 다음은 ServiceEntry 설정입니다:
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: jsonplaceholder #ServiceEntry의 이름
spec:
hosts:
- jsonplaceholder.typicode.com #ServiceEntry가 적용될 외부 서비스의 도메인 이름
#이 도메인으로 향하는 모든 요청은 이 ServiceEntry 규칙의 영향을 받습니다.
ports:
- number: 80 #외부 서비스가 사용하는 포트 번호
name: http
protocol: HTTP
resolution: DNS #외부 서비스의 엔드포인트를 어떻게 찾을지 정의
#'DNS'는 도메인 이름 시스템을 통해 서비스의 IP 주소를 찾는다는 의미
location: MESH_EXTERNAL #서비스의 위치
#서비스가 Istio 서비스 메시 외부에 있음을 나타냅니다.
# 즉, 서비스 메시에 속하지 않은 외부 서비스임을 명시
- 이 설정은:
- hosts: 외부 서비스의 도메인(jsonplaceholder.typicode.com)을 지정합니다.
- ports: HTTP 프로토콜로 포트 80을 사용합니다.
- resolution: DNS: 도메인 이름을 DNS로 확인합니다.
- location: MESH_EXTERNAL: 서비스가 메시 외부에 있음을 나타냅니다.
- 이 ServiceEntry는 Istio 레지스트리에 jsonplaceholder.typicode.com을 추가해 메시 내부에서 호출을 허용합니다.
ServiceEntry를 사용해 외부 서비스를 Istio 서비스 레지스트리에 등록하세요.
이는 메시 내부에서 외부 서비스 호출을 허용하는 핵심 단계입니다!
🛠️ 외부 서비스 호출 테스트하기
- 이제 실제로 외부 서비스 호출을 테스트해볼게요.
- 먼저 jsonplaceholder.typicode.com과 통신하는 forum 애플리케이션을 배포하고, ServiceEntry 적용 전후의 동작을 비교해봅시다.
- forum 애플리케이션을 배포합니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl apply -f services/forum/kubernetes/forum-all.yaml -n istioinaction
service/forum created
deployment.apps/forum created
- 배포 후 상태를 확인합니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl get deploy,svc -n istioinaction -l app=webapp
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/webapp 1/1 1 1 167m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/webapp ClusterIP 10.200.1.15 <none> 80/TCP 167m
- forum 서비스를 호출해봅니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ curl -s http://webapp.istioinaction.io:30000/api/users
error calling Forum service
- 이때 REGISTRY_ONLY 정책 때문에 외부 트래픽이 차단되어 있어 error calling Forum service 같은 오류가 발생합니다.
- 이제 ServiceEntry를 적용해 jsonplaceholder.typicode.com을 허용합니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl apply -f ch5/forum-serviceentry.yaml -n istioinaction
serviceentry.networking.istio.io/jsonplaceholder created
- 적용 후 다시 호출해봅니다: 이제 호출이 성공하며 사용자 목록이 반환됩니다
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ curl -s http://webapp.istioinaction.io:30000/api/users | jq
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874"
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
...
ServiceEntry 적용 전후로 forum 서비스를 호출해 외부 트래픽 차단과 허용 동작을 확인합니다.
ServiceEntry로 외부 서비스 호출이 성공합니다!
📌핵심 요약
- 외부 트래픽 차단: Istio의 outboundTrafficPolicy를 REGISTRY_ONLY로 설정해 메시 외부로 나가는 트래픽을 차단
- ServiceEntry 설정: ServiceEntry 리소스를 사용해 jsonplaceholder.typicode.com을 Istio 서비스 레지스트리에 등록해 메시 내부에서 호출을 허용
- 외부 서비스 테스트: forum 애플리케이션을 배포하고, ServiceEntry 적용 전후로 호출을 테스트해 트래픽 차단과 허용 동작을 확인 => ServiceEntry 적용 후 외부 API 호출이 성공했습니다.