🏠 목록 Istio 1.30.0 — 기존 설치 teardown + Helm 클린 재설치 📄 MD 원본 🌓 테마
istioinstallhelmrunbook

Istio 1.30.0 — 기존 설치 teardown + Helm 클린 재설치

NOTE

홈랩 클러스터의 깨진 Istio 1.30.0 설치를 전부 제거하고 순수 Helm chart(base → istiod → ingress/egress)로 클린 재설치한 런북. 흐름 0단계(설치·구조)의 실제 실행 기록 — 본 아카이브 전체가 이 설치 위에서 동작한다. 하나의 그림: Istio Helm 설치는 의존 스택이다 — base(CRD)istiod(control plane)gateways(data plane), 각 release가 앞 layer를 전제로 한다. 그리고 Helm은 자기가 만든 선언적 리소스만 소유하고, istiod가 런타임에 동적으로 만드는 리소스(CA cert, leader-election cm)는 소유 밖이다. 이 의존 방향 + ownership 경계 두 축이 install 순서·teardown 역순·CRD 잔여물·configmap 수동삭제를 전부 설명한다.

Date: 2026-06-01 호스트: homelab (kubespray bare-metal, k8s v1.30.6, 3노드) 도메인: Kubernetes / Istio 상태: ✅ 완료 — base/istiod/ingress/egress 4개 release 1.30.0 deployed, 전 pod 1/1 Running, analyze 경고 0 대상독자: Istio를 IaC로 굴리려는 DevOps/SRE. 선행개념: Helm release/values, CRD, control plane vs data plane.

⚠️ 선행: 이 작업 전 클러스터 control-plane 장애를 먼저 수리해야 했음. 상세 → control-plane 장애 수리 런북 (그 수리 없이는 istiod가 0/1로 안 뜸 — Deployment가 Pod를 못 만드는 상태였음)


1. 배경 지식 — 왜 "순수 Helm 스택"으로 까는가

Istio를 설치하는 길은 둘이다. istioctl install은 하나의 IstioOperator CR을 받아 control plane과 gateway를 한 번에 깔아주는 편의 경로다. 반면 순수 Helm chartbase/istiod/gateway각각 별도 release로 깐다. 편해 보이는 전자를 두고 굳이 후자를 택하는 이유는 소유권(ownership) 에 있다.

쿠버네티스에서 어떤 도구가 리소스를 "관리한다"는 건 결국 그 리소스에 소유 라벨/애너테이션을 박는 것이다. istioctl은 operator 라벨로, Helm은 release 라벨(app.kubernetes.io/managed-by: Helm + release name)로 소유를 표시한다. 두 도구는 서로의 라벨을 모른다. 그래서 operator로 깐 위에 Helm으로 덮거나 그 반대를 하면, 같은 Deployment를 두 도구가 서로 자기 것이라 주장하며 충돌한다. 프로덕션처럼 GitOps로 굴릴 환경에선 "release/values 파일 = 형상의 단일 소스, 버전은 --version 1.30.0으로 핀"이라는 재현성이 핵심이라, ownership이 명확한 순수 Helm을 택한다.

이 문서가 푸는 문제는 두 가지다. (1) 깨진 기존 설치를 어떻게 깨끗이 들어내는가 — Helm uninstall 한 방으로 안 되는 이유가 있다. (2) 어떤 순서로 다시 까는가 — base→istiod→gw 순서가 단순 관례가 아니라 의존성에서 강제된다는 것. 이 둘을 이해하려면 먼저 Istio 설치가 3개 layer의 의존 스택이라는 그림을 세워야 한다.

layer (release) 무엇 의존
base CRD 15개 + cluster-scope 리소스(clusterrole 등) 없음 (맨 아래)
istiod control plane: deploy/svc/sa + webhook(inject/validate) CRD가 있어야 자기 webhook·config를 등록
gateway data plane: ingress(NodePort)/egress(ClusterIP) Pod istiod가 떠야 xDS로 설정받음

base가 CRD(=Gateway/VirtualService/DestinationRule 등의 타입 정의)를 먼저 깔지 않으면 istiod는 자기가 watch할 타입조차 모른다. gateway Pod는 빈 Envoy로 떠봤자 istiod가 없으면 라우팅 설정을 못 받아 무의미하다. 아래 layer가 위 layer의 전제 — 이게 install이 아래→위로 가는 이유 전부다.


2. 핵심 — 의존 방향 + ownership 경계 (한 장의 그림)

앵커 한 문장: install은 의존 스택을 아래→위로 쌓고, teardown은 정확히 역순으로 허문다 — 단 Helm이 소유한 박스만. 박스 밖(CRD keep + runtime cm)은 손이 안 닿아 수동 삭제가 필요하다.

이 한 문장에서 이후 모든 절차가 따라 나온다. 그림으로 고정하자.

Helm-owned release/values로 선언적 관리 base chart CRD 15 + cluster role resource-policy: keep istiod chart control plane: deploy/svc/sa webhook inject/validate gateway charts ingress NodePort / egress ClusterIP data plane runtime-created Helm 소유 밖 istio-ca-root-cert istio-leader ip-autoallocate namespace-controller 동적 생성 install: base→istiod→gw (아래→위) teardown: 위→아래 (+ CRD/cm 수동)
그림 1. ownership 경계. Helm은 차트로 apply한 base→istiod→gateway 체인만 소유한다. CRD(keep-policy)와 istiod가 런타임에 만든 configmap은 소유 밖이라 uninstall이 못 건드려 수동 삭제가 필요하다 — install은 아래→위, teardown은 참조 역순(위→아래).

왜 teardown은 역순인가 (참조 순서). base를 먼저 지우면 istiod가 참조하던 CRD가 사라진다. 그러면 istiod release를 정리할 때 finalizer/cleanup 로직이 참조 대상을 못 찾아 순서가 꼬일 수 있다. DB에서 외래키 걸린 행을 부모부터 지우면 깨지는 것과 같은 원리 — 그래서 자식(istiod)부터, 부모(base)는 나중에. (비유의 한계: Istio엔 진짜 FK 제약이 강제돼 있진 않다. "참조가 끊겨도 대개 견디지만 cleanup 경로에서 비결정적으로 꼬일 수 있다"가 정확한 표현.)

helm uninstall 한 방으로 안 끝나는가 (ownership 경계). 위 그림의 두 박스가 답이다. Helm은 자기가 chart로 렌더해 apply한 선언적 리소스만 소유한다. 그런데 teardown을 막는 두 부류는 그 소유 밖에 있다.

이 경계가 곧 teardown이 2단계로 쪼개지는 이유다: ① Helm-owned 박스는 helm uninstall이 깔끔히 → ② 박스 밖(CRD + cm)은 kubectl delete로 손수.


3. 예시 — 실제 teardown → 재설치 → 검증

3.1 사전 상태 (teardown 직전)

$ helm -n istio-system list
istio-base  base-1.30.0    deployed      # CRD만
istiod      istiod-1.30.0  deployed      # 0/1, RS/Pod 없음(= control-plane 장애 탓)
# gateway chart 미설치
$ kubectl get crd | grep -c istio.io     # 15
$ webhook: mutating istio-sidecar-injector, validating istio-validator/istiod-default-validator
# 전 네임스페이스 istio CR(Gateway/VS/DR/SE/PA/AP 등): 0개  ← teardown이 사용자 리소스에 영향 없음

보존 대상: service-a/backend(2/2, plain Deployment — CRD 삭제 무관), istioinaction ns(injection 라벨만). CR이 0개라 CRD를 통째로 지워도 cascade로 사라질 사용자 설정이 없다 — 그래서 완전 초기화가 안전한 타이밍이다.

3.2 Teardown — 2단계(Helm 역순 → 수동)

CTX=homelab; NS=istio-system

# (1) helm release 제거 — istiod 먼저, 그 다음 base (의존 역순)
helm --kube-context $CTX uninstall istiod     -n $NS
helm --kube-context $CTX uninstall istio-base -n $NS
#  → base 차트는 CRD를 'resource-policy: keep'로 남김(데이터 보호). 아래서 수동 삭제.
#  → istiod 차트가 소유한 webhook/clusterrole/sa/deploy/svc 는 함께 제거됨.

# (2) CRD 15개 수동 삭제 (완전 초기화. CR 0개라 안전)
kubectl --context $CTX get crd -o name | grep 'istio.io' | xargs -r kubectl --context $CTX delete

# (3) istiod 런타임 생성 잔여 configmap 정리 (helm 미소유 → 수동)
kubectl --context $CTX -n $NS delete cm \
  istio-ca-crl istio-ca-root-cert istio-ip-autoallocate \
  istio-leader istio-namespace-controller-election

(1)은 그림의 Helm-owned 박스를, (2)는 keep-policy로 남은 CRD를, (3)은 박스 밖 runtime cm을 처리한다 — §2의 경계가 명령 3줄에 1:1로 대응한다.

teardown 검증:

istio CRD: 0 / helm release: 0 / istio webhook: 0 / clusterrole(istio): 0
istio-system: No resources found
service-a/backend: 2/2 (보존 OK)

3.3 재설치 — Helm, base → istiod → gateways (의존 정순)

repo IaC: install/helm/values-*.yaml. 동일 명령이 Makefile(make install) 및 install/helm/README.md에도 정리돼 있음. 버전 핀: --version 1.30.0.

CTX=homelab; NS=istio-system; VER=1.30.0

# repo 등록(최초 1회)
helm repo add istio https://istio-release.storage.googleapis.com/charts && helm repo update

# [1] base — CRD + cluster 리소스
helm --kube-context $CTX upgrade --install istio-base istio/base \
  -n $NS --create-namespace --version $VER --wait --timeout 3m

# [2] istiod — control plane (values: access log on, 작은 리소스, autoscale off)
helm --kube-context $CTX upgrade --install istiod istio/istiod \
  -n $NS --version $VER -f install/helm/values-istiod.yaml --wait --timeout 4m

# [3] gateways — ingress(NodePort) + egress(ClusterIP)
helm --kube-context $CTX upgrade --install istio-ingressgateway istio/gateway \
  -n $NS --version $VER -f install/helm/values-ingress-gateway.yaml --wait --timeout 3m
helm --kube-context $CTX upgrade --install istio-egressgateway istio/gateway \
  -n $NS --version $VER -f install/helm/values-egress-gateway.yaml --wait --timeout 3m

각 단계의 --wait는 단순 옵션이 아니라 의존 게이트다: 앞 release의 Pod가 Ready 될 때까지 블록하므로, base가 떠야 istiod로, istiod가 떠야 gw로 넘어간다. --timeout(3m/4m/3m)이 그 게이트의 상한 — 넘으면 다음 단계로 안 가고 실패한다. 즉 명령 나열 순서가 곧 의존 스택을 강제한다.

values 핵심 근거 (왜 이 값인가):

chart 파일 핵심 설정
istiod values-istiod.yaml meshConfig.accessLogFile=/dev/stdout(TEXT), enablePrometheusMerge, pilot.autoscaleEnabled=false replicaCount=1, proxy 리소스 축소 관측성 시나리오 전제(access log on), 홈랩 단일 규모. outboundTrafficPolicy: REGISTRY_ONLY는 주석처리 → egress 시나리오에서 전환
ingress gw values-ingress-gateway.yaml service.type=NodePort (80→31080, 443→31443), istio: ingressgateway 라벨 bare-metal·LB 없음(MetalLB 도입 전). Gateway 리소스 selector와 라벨 일치 필요
egress gw values-egress-gateway.yaml service.type=ClusterIP, 포트 15443(tls) 포함 egress는 외부 노출 불필요, 메시 내부 트래픽만 경유

3.4 결과 검증

$ helm -n istio-system list
istio-base           base-1.30.0     deployed
istiod               istiod-1.30.0   deployed
istio-ingressgateway gateway-1.30.0  deployed
istio-egressgateway  gateway-1.30.0  deployed

$ kubectl -n istio-system get deploy
istiod                 1/1   (registry.istio.io/release/pilot:1.30.0)
istio-ingressgateway   1/1   (worker1)
istio-egressgateway    1/1   (worker2)

$ kubectl -n istio-system get svc
istio-ingressgateway  NodePort    15021:32391, 80:31080, 443:31443
istio-egressgateway   ClusterIP   15021,80,443,15443
istiod                ClusterIP   15010,15012,443,15014

$ istioctl proxy-status      # 데이터플레인 ↔ istiod xDS sync
istio-egressgateway ...  1.30.0  SYNCED(CDS,LDS,EDS)
istio-ingressgateway ... 1.30.0  SYNCED(CDS,LDS,EDS)

$ istioctl analyze -A
Info [IST0102] (Namespace default) ... not enabled for injection   # 무해 Info, 경고 0

검증 합격선 4종: helm 4 release deployed / 전 pod 1/1 / proxy-status SYNCED / analyze 경고 0 — 전부 충족. proxy-status가 SYNCED라는 건 gateway(data plane)가 istiod(control plane)로부터 CDS/LDS/EDS를 정상 수신했다는 뜻 — §2의 스택이 위까지 살아 동작한다는 최종 증거다.

부수 효과: control-plane 수리 후 istioctl proxy-status·kubectl logs/exec의 기존 nodes/proxy 인증 오류도 해소됨(같은 뿌리였음). 데이터플레인 진단이 정상 동작.


4. 정리

멘탈모델 한 줄: Istio Helm 설치 = 의존 스택(base→istiod→gw) × ownership 경계(Helm-owned 박스 vs runtime 박스 밖). 이 2×2 좌표 하나로 install 순서·teardown 역순·CRD 잔여·cm 수동삭제가 전부 연역된다.

다음 작업

관련 개념 / 파일

이 설치의 설계 원리는 → 컨트롤·데이터 플레인 설치 분리 · istiod 성능 4요인 참고.

핵심 정리

What you might be missing