
직전에 쿠버네티스 Istio(envoy) 설치 및 실습하기 [1]를 했는데,
여전히 Istiod, Envoy 등의 작동 원리가 이해가 되지 않아 심화 문서를 작성합니다.
A. 분석하기
A.1. 사전 준비
Istio 설치하기 [A.1-1], Istio Sample 앱 배포하기 [A.1-2]를 진행해주세요.
A.2. istio-proxy 분석하기
istio-proxy의 설정파일은 크게 3가지로 구분됩니다.
xDS (소켓 파일)
envoy-rev.json Envoy (리비전 파일)
grpc-bootstrap.json (gRPC 부트스트램 파일)
[명령어 1] Envoy 설정파일 리스트업
1. 파드 리스트업
kubectl get pods -n istio-sample -o=custom-columns="KIND:.kind,NS:.metadata.namespace,NAME:.metadata.name"
KIND NS NAME
Pod istio-sample bookinfo-gateway-istio-854cd9bd69-v4q68
Pod istio-sample details-v1-79dfbd6fff-slm95
Pod istio-sample productpage-v1-dffc47f64-5v8l6
Pod istio-sample ratings-v1-65f797b499-hf42z
Pod istio-sample reviews-v1-5c4d6d447c-w74pp
Pod istio-sample reviews-v2-65cb66b45c-vjmpv
Pod istio-sample reviews-v3-f68f94645-bp6v2
2. 파드 컨테이너 명확인하기
kubectl get pods -n istio-sample -o jsonpath="{range .items[*]}{.metadata.namespace}{'\t'}{.metadata.name}{'\t'}{range .spec.initContainers[*]}[init]{.name}{'\t'}{end}{range .spec.containers[*]}{.name}{'\t'}{end}{'\n'}{end}"
istio-sample bookinfo-gateway-istio-854cd9bd69-v4q68 istio-proxy
istio-sample details-v1-79dfbd6fff-slm95 [init]istio-init details istio-proxy
istio-sample productpage-v1-dffc47f64-5v8l6 [init]istio-init productpage istio-proxy
istio-sample ratings-v1-65f797b499-hf42z [init]istio-init ratings istio-proxy
istio-sample reviews-v1-5c4d6d447c-w74pp [init]istio-init reviews istio-proxy
istio-sample reviews-v2-65cb66b45c-vjmpv [init]istio-init reviews istio-proxy
istio-sample reviews-v3-f68f94645-bp6v2 [init]istio-init reviews istio-proxy
3. 파드 접속하기
kubectl exec productpage-v1-dffc47f64-5v8l6 -n istio-sample -it -c istio-proxy -- /bin/sh
$
4. 파드 주요 메타데이터 확인하기
whoami # istio-proxy
pwd # /
cd ~
pwd # /home/istio-proxy
cd /
5. istio-proxy 설정확인하기
cd /etc/istio/proxy
ls -l
total 20
srw-rw-rw- 1 istio-proxy istio-proxy 0 Apr 15 12:22 XDS
-rw-r--r-- 1 istio-proxy istio-proxy 14236 Apr 15 12:22 envoy-rev.json
-rw-r--r-- 1 istio-proxy istio-proxy 2929 Apr 15 12:22 grpc-bootstrap.json
grpc-bootstrap.json 파일에는 몇가지 중요한 설정이 있습니다.
.node (노드 설정)
id → sidecar~10.244.0.211~productpage-v1-dffc47f64-5v8l6.istio-sample~istio-sample.svc.cluster.local
cluster → productpage.istio-sample
xds_servers (xDS 설정)
server_uri → “unix:///etc/istio/proxy/XDS”
channel_creds → [{ type: insecure” }]
server_features: [ “xds_v3” ]
listeners (리스너 설정)
name: “0.0.0.0_15090” → 15090 포트에서 트래픽을 수신
filter_chanins: [… ] → /stats/prometheus 경로로 오는 요청을 promehteus_stats 클러스터로 라우팅
[명령어 2] Envoy 설정파일 조회하기
1. .node (노드 설정)
cat grpc-bootstrap.json | grep node -A 60
"node": {
"id": "sidecar~10.244.0.211~productpage-v1-dffc47f64-5v8l6.istio-sample~istio-sample.svc.cluster.local",
"metadata": {
"ANNOTATIONS": {
"istio.io/rev": "default",
"kubectl.kubernetes.io/default-container": "productpage",
"kubectl.kubernetes.io/default-logs-container": "productpage",
"kubernetes.io/config.seen": "2025-04-15T21:22:43.081122129+09:00",
"kubernetes.io/config.source": "api",
"prometheus.io/path": "/stats/prometheus",
"prometheus.io/port": "15020",
"prometheus.io/scrape": "true",
"sidecar.istio.io/status": "{\"initContainers\":[\"istio-init\"],\"containers\":[\"istio-proxy\"],\"volumes\":[\"workload-socket\",\"credential-socket\",\"workload-certs\",\"istio-envoy\",\"istio-data\",\"istio-podinfo\",\"istio-token\",\"istiod-ca-cert\"],\"imagePullSecrets\":null,\"revision\":\"default\"}"
},
"APP_CONTAINERS": "productpage",
"CLUSTER_ID": "Kubernetes",
"ENVOY_PROMETHEUS_PORT": 15090,
"ENVOY_SKIP_DEPRECATED_LOGS": "true",
"ENVOY_STATUS_PORT": 15021,
"GENERATOR": "grpc",
"INSTANCE_IPS": "10.244.0.211",
"INTERCEPTION_MODE": "REDIRECT",
"ISTIO_PROXY_SHA": "d1333136f077ed86411257320fe37d4b5f8b8ddd",
"ISTIO_VERSION": "1.25.1",
"LABELS": {
"app": "productpage",
"security.istio.io/tlsMode": "istio",
"service.istio.io/canonical-name": "productpage",
"service.istio.io/canonical-revision": "v1",
"version": "v1"
},
"MESH_ID": "cluster.local",
"METADATA_DISCOVERY": "false",
"NAME": "productpage-v1-dffc47f64-5v8l6",
"NAMESPACE": "istio-sample",
"NODE_NAME": "cp-k8s",
"OWNER": "kubernetes://apis/apps/v1/namespaces/istio-sample/deployments/productpage-v1",
"PILOT_SAN": [
"istiod.istio-system.svc"
],
"POD_PORTS": "[{\"containerPort\":9080,\"protocol\":\"TCP\"}]",
"PROXY_CONFIG": {
"binaryPath": "/usr/local/bin/envoy",
"concurrency": 2,
"configPath": "./etc/istio/proxy",
"controlPlaneAuthPolicy": "MUTUAL_TLS",
"discoveryAddress": "istiod.istio-system.svc:15012",
"drainDuration": "45s",
"proxyAdminPort": 15000,
"serviceCluster": "istio-proxy",
"statNameLength": 189,
"statusPort": 15020,
"terminationDrainDuration": "5s"
},
"SERVICE_ACCOUNT": "bookinfo-productpage",
"WORKLOAD_IDENTITY_SOCKET_FILE": "socket",
"WORKLOAD_NAME": "productpage-v1"
},
"locality": {},
"UserAgentVersionType": null
},
2. xds_servers (XDS 설정)
cat grpc-bootstrap.json | grep xds_servers -A 12
"xds_servers": [
{
"server_uri": "unix:///etc/istio/proxy/XDS",
"channel_creds": [
{
"type": "insecure"
}
],
"server_features": [
"xds_v3"
]
}
],
3. listeners (리스너 설정)
cat envoy-rev.json | grep listeners -A 100
즉,
초기 설정(grpc-bootstrap.json), 이후 설정(envoy-rev.json)에는
노드, xDS, 리스너 등의 다양한 설정들이 주입되어 있음을 알 수 있었습니다.
자연스럽게 “주입되는 경로가 어디인가?”라는 의문과 연결되고
그 경로가 되는 친구가 xDS(LDS, CDS, RDS, EDS)입니다.
A.3. Istiod가 동적 구성을 하는 방식 (Delta xDS API)
xDS*는 서비스 검색 및 동적구성을 하는데 사용되는 프로토콜인데,
LDS, RDS, CDS, EDS 등의 다양한 Discovery Service들을 묶어놓은 API입니다.
💡
xDS(Extensible Discovery Service)의 세부 구성의 일부는 다음과 같습니다. 1. CDS : Cluster Discovery Service 2. LDS : Listener Discovery Service 3. EDS : Endpoint Discovery Service 4. SDS : Secret Discovery Service
확장된 xDS들도 몇가지가 있긴한데, 실제로 쓸 일이 있을까 싶습니다.
SotW(State of the World) : ~ @1.22 이전 버전 기본값, 중앙에서 전체값 전송, 각 sidecar istio-proxy(envoy)에서 값 관리
Delta xDS(Incremental xDS) : @1.22 이후 버전 기본값, 중앙에서 변경값 전송, 각 sidecar istio-proxy(envoy)에서 값 관리
ADS(Aggregated Discovery Service) : 중앙의 gRPC 스트림에서 전체값 저장
Delta ADS(Incremetnal ADS) : 중앙의 gRPC 스트림에서 변경값 저장
(다른 방식도 같은 구조인지는 확인해봐야 하지만…)
기본값인 Delta xDS의 경우 istiod 내부에 있는 xDS API을 의미합니다.
Istiod와 istio-proxy(envoy)는 크게 두 가지 통신을 하게 됩니다.
초기 설정 전송
변경 사항 구독 및 반영
A.4. Istio Sidecar Injection 작동 원리
Istio 설치 및 실습 [A.4-1]에서 istio-sample을 위해 라벨을 붙였습니다.
kubectl label namespace istio-sample istio-injection=enabled
이후 istio-sample에서 생성된 파드는 init-istio, istio-proxy가 생겼습니다.
init-istio : istio, istio-proxy 초기화 설정
istio-proxy : istio-proxy 설정 및 envoy 실행
Istio는 어떻게 Sidecard Injection 기능을 구현했을까요?
Istio는 Kubernetes AdmissionController을 활용하여 이를 구현했으며
구체적으로는 MutatingAdmissionWebhook이라는 기능을 사용합니다.
[명령어 3]을 실행해보면,
istio-sidecar-injector라는 MutatingWebhookConfiguration을 통해
istiod.istio-system/inject 요청을 보내는 것을 알 수 있습니다.
[명령어 3] Istio Injector 작동과정
1. MutatingWebhookConfiguration 리스트 조회하기
kubectl get MutatingWebhookConfiguration
NAME WEBHOOKS AGE
istio-revision-tag-default 4 43h
istio-sidecar-injector 4 43h
2. MutatingWebhookConfiguration istio-revision-tag-default* 확인하기
kubectl get MutatingWebhookConfiguration istio-revision-tag-default
3. MutatingWebhookConfiguration istio-sidecar-injector* 확인하기
kubectl get MutatingWebhookConfiguration istio-sidecar-injector
4. MutatingWebhookConfiguration istio-sidecar-injector* 조회하기
kubectl get MutatingWebhookConfiguration istio-sidecar-injector -o yaml | yq e '.webhooks[] | {"name": .name, "rules": .rules}' -
name: rev.namespace.sidecar-injector.istio.io
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
resources:
- pods
scope: '*'
name: rev.object.sidecar-injector.istio.io
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
resources:
- pods
scope: '*'
name: namespace.sidecar-injector.istio.io
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
resources:
- pods
scope: '*'
name: object.sidecar-injector.istio.io
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
resources:
- pods
scope: '*'
istio @1.25.1에서는 총 4종류의 Webhook을 가지고 있는데,
모두 파드가 생길때 실행되며, istiod.istio-system/inject로 요청을 보내게 됩니다.
Webhook Rules | label target | label |
---|---|---|
rev.namespace.sidecar-injector.istio.io | namespace | istio.io/rev |
rev.object.sidecar-injector.istio.io | pod | istio.io/rev |
namespace.sidecar-injector.istio.io | namespace | istio-injection=enabled |
object.sidecar-injector.istio.io | pod | istio-injection=enabled |
지금은 namespace.sidecar-injector.istio.io를 사용하고 있어서
해당 namespace에 있는 모든 파드들에게 init-istio, istio-proxy가 주입됩니다.
A.5. Istio Envoy 작동 원리
[명령어 4]의 1-2을 통해서 Istio Gateway만 배포되어 있음을 알 수 있었습니다.
[명령어 4] Istio CRD 조회하기
1. Istio CRD 리스트 조회하기
kubectl api-resources -o="name" | grep istio
wasmplugins.extensions.istio.io
destinationrules.networking.istio.io
envoyfilters.networking.istio.io
gateways.networking.istio.io
proxyconfigs.networking.istio.io
serviceentries.networking.istio.io
sidecars.networking.istio.io
virtualservices.networking.istio.io
workloadentries.networking.istio.io
workloadgroups.networking.istio.io
authorizationpolicies.security.istio.io
peerauthentications.security.istio.io
requestauthentications.security.istio.io
telemetries.telemetry.istio.io
2. Istio CRD 배포 내역 조회하기
kubectl get wasmplugins,destinationrules,envoyfilters,gateways,proxyconfigs,serviceentries,sidecars,virtualservices,workloadentries,workloadgroups,authorizationpolicies,peerauthentications,requestauthentications,telemetries -A -o=custom-columns="KIND:.kind,NS:.metadata.namespace,NAME:.metadata.name"
KIND NS NAME
Gateway istio-sample bookinfo-gateway
[명령어 5]를 통해서 Istio Listener, Proxy Config을 봤지만,
여러 공식문서에서 말하고 있는 Istio Network 흐름과는 상이했습니다.
아마도 Istio Control Plane이 istiod로 변경되면서 많은 부분이 달라진 것 같습니다.
[명령어 5] Istio Listener, Proxy 확인하기
1. pod 조회하기
kubectl get pods -n istio-sample -o=custom-columns=KIND:.kind,NS:.metadata.namespace,NAME:.metadata.name
KIND NS NAME
Pod istio-sample bookinfo-gateway-istio-854cd9bd69-v4q68
Pod istio-sample details-v1-79dfbd6fff-slm95
Pod istio-sample productpage-v1-dffc47f64-5v8l6
Pod istio-sample ratings-v1-65f797b499-hf42z
Pod istio-sample reviews-v1-5c4d6d447c-w74pp
Pod istio-sample reviews-v2-65cb66b45c-vjmpv
Pod istio-sample reviews-v3-f68f94645-bp6v2
2. istio pc listener 조회하기
istioctl pc listener productpage-v1-dffc47f64-5v8l6 -n istio-sample
3. istio pc listener 세부사항 조회하기
istioctl pc listener productpage-v1-dffc47f64-5v8l6 -n istio-sample --address 0.0.0.0 --port 15001 -o yaml
4. istio proxy-config routes 조회하기
istioctl proxy-config routes productpage-v1-dffc47f64-5v8l6 -n istio-sample
CNCF Ambassador의 게시글에서는
Remote Pod → Local Pod으로 가는 트래픽을 아래와 같이 표현하고 있습니다.
REDROUTING, ISTIO_INBOUND, ISTIO_IN_REDIRECT, Envoy(inbound), OUTPUT → ISTIOU_OUTPUT(RULE 1) → POSTROUTING → Local Pod
Istio 설치 및 실습 [A.4-1]에서 살펴본 바,
네트워크 제어(iptables) 방식은 크게 다르지 않으며
일부 비율 분산*, 도메인 네임 등록* 등의 부분 정도의 차이만 보였습니다.
비율 분산?
Service + kube-proxy(iptables)는 파드에 균등하게 분산함
Sidecar istio-proxy(envoy) + Service + kube-proxy(iptables)는 여러 deploy에 대해서 비율로 분산할 수 있음
도메인 네임 등록
Pod가 도메인을 파악하려면 CoreDNS + Kube-Proxy에 질의해야함
Pod가 갈 수 있는 도메인이 Envoy Listener에 등록되어 있음