The Mesh Install Manifest and the Sidecar Dissected
한국어 원문으로 표시합니다.
목표
메시를 설치할 때 실제로 무엇이 클러스터에 들어가는지 확인하고, 사이드카가 주입된 파드가 원래 파드와 어떻게 다른지 구조로 설명할 수 있게 됩니다.
왜 중요한가
메시 도입 실패의 상당수는 "무엇이 설치됐는지 모르는 상태"에서 시작합니다. istioctl install 한 줄로 끝나는 것처럼 보이지만, 그 뒤에서는 CRD 수십 개, 웹훅 설정, ConfigMap, 컨트롤 플레인 워크로드가 한꺼번에 들어갑니다. 그래서 실무에서는 설치 전에 manifest generate 로 먼저 눈으로 보고 저장소에 커밋하는 방식을 씁니다. 그래야 업그레이드 때 diff 를 볼 수 있습니다. 주입도 마찬가지입니다. 주입은 파드가 생성될 때 웹훅이 스펙을 고치는 일이라, 라벨만 붙이고 롤아웃을 걸지 않으면 아무 일도 일어나지 않습니다. 이 사실을 손으로 확인해 두면 "라벨을 붙였는데 메시에 안 들어와요"라는 질문에 몇 초 만에 답할 수 있습니다.
이 실습 환경에는 진짜 Envoy 가 트래픽을 나르지 않습니다. 그래서 채점은 매니페스트와 정적 분석을 봅니다. 그 대신 주입 결과 매니페스트를 해부하는 훈련은 실제 환경에서도 그대로 쓰입니다.
단계
istioctl version출력을/root/istio/out/version.txt에 저장하세요(버전 번호가 들어 있어야 합니다). 이어서 설치 전 점검(istioctl x precheck)을 표준 에러까지 포함해/root/istio/out/precheck.txt에 저장하세요.istioctl manifest generate결과를/root/istio/manifest.yaml로 저장하세요.CustomResourceDefinition과istiod가 들어 있어야 하고kind:로 시작하는 줄이 10개 이상이어야 합니다. 그다음 종류별 개수 집계를/root/istio/out/manifest-kinds.txt에 저장하세요(CustomResourceDefinition이 집계에 보여야 합니다).- 매니페스트를 클러스터에 적용해 메시 API 타입을 등록하세요.
virtualservices.networking.istio.io,destinationrules.networking.istio.io,gateways.networking.istio.io,peerauthentications.security.istio.io,authorizationpolicies.security.istio.io다섯 개가 모두 있어야 하고,istio.io그룹 CRD 가 5개 이상이어야 합니다. - 네임스페이스
mesh-lab을 만들고 라벨istio-injection=enabled를 붙이세요. 네임스페이스legacy도 만들되 주입 라벨을 붙이지 마세요. 그리고/root/istio/out/injection-note.txt에 "라벨을 붙여도 기존 파드는 그대로이고 롤아웃으로 재생성돼야 사이드카가 들어간다"는 내용을 적으세요. /opt/lab/fixtures/istio/inject-target.yaml에istioctl kube-inject를 돌려 결과를/root/istio/injected.yaml로 저장하세요. Deployment 의 컨테이너에payments와istio-proxy가 둘 다 있어야 하고, 초기화 컨테이너(istio-init또는istio-validation)가 있어야 하며, 파드 템플릿에sidecar.istio.io/status어노테이션이 있어야 합니다.istioctl analyze -n mesh-lab결과를/root/istio/out/analyze.txt에 저장하세요(Error [가 남아 있으면 안 됩니다). 그리고/root/istio/out/analyze-note.txt에 analyze 가 트래픽이 아니라 설정을 적용 전/후에 정적으로 검사한다는 내용을 두 줄로 적으세요./root/istio/out/sidecar.json을 만드세요. 키는containers(컨테이너 이름 배열,istio-proxy포함),init_containers(1개 이상 배열),container_count(주입 후 컨테이너 개수),proxy_image(injected.yaml의istio-proxy컨테이너 이미지와 문자열이 정확히 같아야 합니다),interception(트래픽을 어떻게 가로채는지 한 문장 —iptables라는 단어가 들어가야 합니다) 다섯 개입니다./root/istio/out/mesh-readiness.json을 만드세요.istio_crds(클러스터의istio.io그룹 CRD 실제 개수),injection_namespaces(주입 라벨이 붙은 네임스페이스 배열 —mesh-lab은 있고legacy는 없어야 합니다),analyze_errors(0) 세 키입니다. 또한istioctl validate -f /root/istio/injected.yaml결과를/root/istio/out/validate.txt에 저장하세요.
참고
- 3번:
yq 'select(.kind == "CustomResourceDefinition")' /root/istio/manifest.yaml | kubectl apply -f -로 CRD 만 먼저 적용할 수 있습니다. 다만 매니페스트 전체를 적용해 두는 편이 편합니다 — 5번이 쓸 주입 설정이istio-system의 ConfigMap 두 개(istio-sidecar-injector,istio)에 들어 있기 때문입니다.kubectl create ns istio-system을 먼저 하세요. - 5번: 이 환경에는 진짜 istiod 파드가 없습니다. 그래서
kube-inject를 그냥 실행하면 istiod 로 port-forward 를 시도하다 실패합니다. 3번에서 적용한 ConfigMap 에서 주입 템플릿(.data.config)·메시 설정(.data.mesh)·값(.data.values)을 각각 파일로 뽑아--injectConfigFile,--meshConfigFile,--valuesFile로 넘기세요. 세 개를 다 줘야 합니다 — 둘만 주면 나머지 하나를 찾아 다시 클러스터로 갑니다. (istioctl kube-inject --help의 예제에 이 방법이 그대로 나와 있습니다.) - 8번의 CRD 개수는 손으로 세지 말고
kubectl get crd -o json | jq '[.items[] | select(.spec.group | test("istio.io"))] | length'로 뽑으세요. istioctl validate는 통과했을 때 출력이 짧거나 비어 있을 수 있습니다. 비면 결과 한 줄(검증 통과등)을 덧붙여 파일이 비지 않게 하세요.- 흔한 실수 1: 7번의
proxy_image를 기억으로 적는 것. 반드시injected.yaml에서 뽑아 넣으세요. - 흔한 실수 2: 4번에서
legacy네임스페이스를 아예 만들지 않는 것. 주입되지 않는 대조군이 있어야 라벨의 의미가 증명됩니다.
istioctl 버전과 설치 전 점검
istioctl version 출력을 /root/istio/out/version.txt 에 저장하세요(버전 번호가 들어 있어야 합니다). 이어서 설치 전 점검(istioctl x precheck)을 표준 에러까지 포함해 /root/istio/out/precheck.txt 에 저장하세요.
istioctl version 은 클라이언트 버전을 먼저 찍습니다. 설치 전 점검은 experimental 하위 명령에 있고, 오류 메시지도 결과이므로 표준 에러까지 함께 저장하세요.
설치 매니페스트 생성하고 내용 세기
istioctl manifest generate 결과를 /root/istio/manifest.yaml 로 저장하세요. CustomResourceDefinition 과 istiod 가 들어 있어야 하고 kind: 로 시작하는 줄이 10개 이상이어야 합니다. 그다음 종류별 개수 집계를 /root/istio/out/manifest-kinds.txt 에 저장하세요(CustomResourceDefinition 이 집계에 보여야 합니다).
istioctl manifest generate 는 클러스터에 아무것도 만들지 않고 YAML 만 뱉습니다. 무엇이 몇 개인지는 kind: 로 시작하는 줄을 세면 됩니다.
메시 API 타입을 클러스터에 등록하기
매니페스트를 클러스터에 적용해 메시 API 타입을 등록하세요. virtualservices.networking.istio.io, destinationrules.networking.istio.io, gateways.networking.istio.io, peerauthentications.security.istio.io, authorizationpolicies.security.istio.io 다섯 개가 모두 있어야 하고, istio.io 그룹 CRD 가 5개 이상이어야 합니다.
VirtualService 같은 타입은 CRD 로 등록돼야 kubectl 이 알아봅니다. 매니페스트 전체를 적용하거나 CustomResourceDefinition 만 골라 적용하세요. Established 조건은 API 서버가 붙여 줍니다.
주입 대상 네임스페이스와 대조군 만들기
네임스페이스 mesh-lab 을 만들고 라벨 istio-injection=enabled 를 붙이세요. 네임스페이스 legacy 도 만들되 주입 라벨을 붙이지 마세요. 그리고 /root/istio/out/injection-note.txt 에 "라벨을 붙여도 기존 파드는 그대로이고 롤아웃으로 재생성돼야 사이드카가 들어간다"는 내용을 적으세요.
라벨 이름과 값이 정확해야 웹훅의 namespaceSelector 에 걸립니다. 대조군에는 라벨을 붙이지 마세요. 그리고 라벨이 언제 효력을 갖는지 메모에 적으세요.
픽스처 워크로드에 사이드카 주입하기
/opt/lab/fixtures/istio/inject-target.yaml 에 istioctl kube-inject 를 돌려 결과를 /root/istio/injected.yaml 로 저장하세요. Deployment 의 컨테이너에 payments 와 istio-proxy 가 둘 다 있어야 하고, 초기화 컨테이너(istio-init 또는 istio-validation)가 있어야 하며, 파드 템플릿에 sidecar.istio.io/status 어노테이션이 있어야 합니다.
istioctl kube-inject 는 파일을 입력받아 주입된 매니페스트를 출력합니다. 원래 컨테이너가 사라지면 안 되고, 초기화 컨테이너가 하나 늘어야 정상입니다.
설정을 정적으로 분석하기
istioctl analyze -n mesh-lab 결과를 /root/istio/out/analyze.txt 에 저장하세요(Error [ 가 남아 있으면 안 됩니다). 그리고 /root/istio/out/analyze-note.txt 에 analyze 가 트래픽이 아니라 설정을 적용 전/후에 정적으로 검사한다는 내용을 두 줄로 적으세요.
analyze 는 클러스터의 설정 리소스를 읽어 서로 어긋난 곳을 찾습니다. 트래픽을 보내는 것이 아니라는 점이 핵심이고, 결과에 Error 가 남아 있으면 안 됩니다.
주입 결과를 JSON 으로 해부하기
/root/istio/out/sidecar.json 을 만드세요. 키는 containers(컨테이너 이름 배열, istio-proxy 포함), init_containers(1개 이상 배열), container_count(주입 후 컨테이너 개수), proxy_image(injected.yaml 의 istio-proxy 컨테이너 이미지와 문자열이 정확히 같아야 합니다), interception(트래픽을 어떻게 가로채는지 한 문장 — iptables 라는 단어가 들어가야 합니다) 다섯 개입니다.
직접 눈으로 세지 말고 주입된 파일에서 값을 뽑아 적으세요. 이미지 문자열은 한 글자만 달라도 실제 값과 다릅니다.
메시 준비 상태 요약 만들기
/root/istio/out/mesh-readiness.json 을 만드세요. istio_crds(클러스터의 istio.io 그룹 CRD 실제 개수), injection_namespaces(주입 라벨이 붙은 네임스페이스 배열 — mesh-lab 은 있고 legacy 는 없어야 합니다), analyze_errors(0) 세 키입니다. 또한 istioctl validate -f /root/istio/injected.yaml 결과를 /root/istio/out/validate.txt 에 저장하세요.
앞 단계에서 만든 것들을 한 파일로 모읍니다. 숫자는 클러스터에서 다시 세어 채우고, 주입되지 않는 네임스페이스가 목록에 들어가면 안 됩니다.