최근 진행 중인 Kubernetes 기반 프로젝트에서 서비스 메시(Service Mesh) 구성을 위해 Istio를 도입하게 되었다.
Istio는 Kubernetes 환경에서 트래픽 관리, 보안, 관측성을 제공하는 대표적인 Service Mesh 솔루션이다.
특히 MSA 환경에서 서비스 간 통신을 제어하고 모니터링하기 위해 많이 사용된다.
Istio 설치 방법
Istio를 설치하는 방법은 크게 두 가지가 있다.
- istioctl
- Helm
공식 문서에서는 istioctl을 사용한 설치 예제가 많지만, 실제 운영 환경에서는 GitOps를 사용하고 있었기 때문에 Helm 기반으로 설치를 진행했다.
이번 글에서는 Kubernetes 환경에서 Helm을 이용해 Istio를 설치하고 Gateway까지 구성한 과정을 정리해보려고 한다.
왜 istioctl 대신 Helm을 선택했을까?
처음에는 공식 문서에 있는 istioctl 설치 방식을 고려했다.
하지만 운영 환경에서는 ArgoCD를 이용한 GitOps 방식을 사용하고 있었고, 다음과 같은 이유로 Helm을 선택했다.
istioctl의 단점
- CLI 의존성이 높음
- 설치한 사용자의 환경 및 명령어에 따라 결과가 달라질 수 있음
- 설치 이력을 Git으로 관리하기 어려움
- 설치 옵션과 설정이 Git 저장소에 남지 않음
- GitOps와 궁합이 좋지 않음
- ArgoCD와 같은 Git 기반 배포 방식으로 관리하기 어려움
- 운영 환경 재현성이 떨어짐
- 동일한 환경을 다시 구성할 때 사용한 명령어를 알아야 함
Helm의 장점
- Git 저장소에서 관리 가능
- ArgoCD와 연동 가능
- 버전 관리 용이
- 운영 환경 재현 가능
실제 운영 환경에서는 Helm 방식이 훨씬 관리하기 편했다.
전체 구성도
Internet
↓
NCP ALB
↓
Istio Ingress Gateway (Envoy)
↓
Gateway
↓
VirtualService
↓
Application Service
이번 환경에서는 NCP ALB를 앞단에 두고 Istio Ingress Gateway로 트래픽을 전달하는 구조를 사용했다.
Helm 설치
먼저 Helm을 설치한다.
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm version
설치 후 정상적으로 버전이 출력되는지 확인한다.
Istio Repository 등록
helm repo add istio https://istio-release.storage.googleapis.com/charts
helm repo update
정상적으로 등록되었는지 확인한다.
helm repo list
Istio Namespace 생성
kubectl create namespace istio-system
Istio Base (CRD) 설치
Istio는 Gateway, VirtualService와 같은 Custom Resource를 사용한다.
따라서 관련 리소스를 Kubernetes가 인식할 수 있도록 CRD(Custom Resource Definition)를 먼저 설치해야 한다.
이를 위해 Base Chart를 가장 먼저 설치한다.
helm install istio-base istio/base \
-n istio-system \
--create-namespace
설치 확인
helm ls -n istio-system
Istiod(Control Plane) 설치
다음으로 Control Plane을 설치한다.
helm install istiod istio/istiod \
-n istio-system \
--wait
확인
kubectl get deployment -n istio-system
정상적으로 설치되면 istiod Deployment가 Running 상태로 표시된다.
Ingress Gateway 설치
Ingress Gateway는 외부에서 들어오는 트래픽을 받아 내부 서비스로 전달하는 역할을 한다.
현재 환경에서는 NCP Load Balancer가 앞단에 위치하고 있었기 때문에 Service Type을 `NodePort`로 설정하였다.
status-port : 15021
-> Istio Ingress Gateway의 상태 확인(Health Check)을 위한 포트
HTTP : 80 → 8080
-> 외부 사용자는 80 포트로 접속하지만 실제 Envoy Proxy는 컨테이너 내부에서 8080 포트를 사용
80 → 8080 으로 포트 매핑을 구성
HTTPS : 443 → 8443
-> 외부 HTTPS 요청을 처리하기 위한 포트
Envoy Proxy는 HTTPS 트래픽을 8443 포트에서 수신하기 때문에 443 → 8443으로 연결
values.yaml
service:
type: NodePort
ports:
- name: status-port
port: 15021
targetPort: 15021
nodePort: 30021
- name: http2
port: 80
targetPort: 8080
nodePort: 30080
- name: https
port: 443
targetPort: 8443
nodePort: 30443
설치
helm install istio-ingressgateway istio/gateway \
-n istio-system \
-f values.yaml
왜 LoadBalancer 대신 NodePort를 사용했을까?
처음에는 Istio Gateway를 LoadBalancer 타입으로 노출할 생각이었다.
하지만 실제 운영 환경에서는 다음 요구사항이 있었다.
- WAF 사용
- SSL 인증서 관리
- 공인 도메인 관리
이 기능들은 NCP ALB에서 제공하고 있었다.
따라서 구조를 다음과 같이 변경했다.
Internet
↓
NCP ALB
↓
NodePort
↓
Istio Ingress Gateway
이 구조를 사용하면 SSL 종료와 WAF 정책을 ALB에서 처리할 수 있다.
Istio Gateway 생성
Gateway는 어떤 Host를 받을지 정의한다.
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: sample-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
protocol: HTTP
name: http
hosts:
- "service.example.com"
- "argocd.example.com"
VirtualService 생성
Gateway로 들어온 요청을 실제 서비스로 라우팅한다.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
spec:
hosts:
- argocd.example.com
gateways:
- istio-system/sample-gateway
http:
- route:
- destination:
host: argocd-server
port:
number: 80
ArgoCD를 별도 Host로 분리한 이유
ArgoCD는 내부적으로 다음과 같은 경로를 사용한다.
/api
/applications
/settings
/login
만약
/service/argocd
같은 Sub Path 방식으로 구성하면
- Static Resource 경로 오류
- Redirect URL 오류
- WebSocket 연결 오류
등이 발생할 수 있다.
그래서 실제 운영 환경에서는 다음과 같이 Host를 분리했다.
argocd.example.com
grafana.example.com
service.example.com
운영 경험상 이 방식이 훨씬 관리가 편했다.
Namespace에 Sidecar 자동 주입 설정
kubectl label namespace sample istio-injection=enabled
# pod 조회
kubectl get pod -n sample
NAME READY STATUS
sample-back-service-xxxx 2/2 Running
sample-service-xxxx 2/2 Running
sample-socket-xxxx 2/2 Running
# pod 상세 조회
kubectl describe pod sample-back-service-xxxx -n sample
Annotations:
sidecar.istio.io/status
security.istio.io/tlsMode=istio
설정 이후 생성되는 Pod에는 Envoy Sidecar가 자동으로 주입된다.
실제로 Pod 상태를 확인하면 READY가 2/2로 표시되며, Istio 관련 Annotation이 추가된 것을 확인할 수 있다.
Gateway vs VirtualService 차이
VirtualService는 수신된 요청을 어떤 서비스로 전달할지 정의한다.
즉, Gateway가 입구라면 VirtualService는 라우팅 규칙이라고 볼 수 있다.
마무리
이번 글에서는 Helm을 이용해 Istio를 설치하고 Gateway 및 VirtualService를 구성하는 과정을 정리해봤다.
실제 운영 환경에서는 단순 설치보다도
- GitOps와의 연계
- ALB 연동
- Gateway 설계
- Host 기반 라우팅
을 어떻게 구성할지가 더 중요했다.
이번 글에서는 Istio의 기본 구성까지 진행했고, 다음 글에서는 Kiali를 설치하여 서비스 간 통신과 트래픽 흐름을 시각적으로 확인해보려고 한다.
'infra > Kubernetes' 카테고리의 다른 글
| kubernetes ELK 설치 - Elasticsearch Node, Cluster 설계 (0) | 2025.04.12 |
|---|---|
| Kubernetes ELK 설치 - ELK vs Grafana (0) | 2025.03.20 |
| kubernetes Object란? (0) | 2025.03.15 |
| kubernetes (Cluster, Node, Pod) 란? (0) | 2025.03.13 |