When the proxy leaves the pod: ambient components and its two layers
한국어 원문으로 표시합니다.
목표
앰비언트 프로파일을 렌더해 사이드카 모드와 구성요소를 견주고, 네임스페이스 라벨로 데이터플레인을 고르는 법과 두 라벨을 겹쳤을 때 분석기가 무엇을 잡는지 확인한다. waypoint 매니페스트를 생성해 필드를 읽고, 이 클러스터에서 적용이 왜 실패하는지까지 직접 본다. 마지막으로 네임스페이스를 모드별로 세는 점검표를 만든다.
왜 중요한가
앰비언트는 프록시를 파드에서 떼어 노드로 옮기는 설계다. 얻는 것은 분명하다 — 파드마다 프록시가 없으니 자원이 줄고, 워크로드를 재시작하지 않고도 메시에 넣거나 뺄 수 있다. 대신 기능이 두 층으로 갈린다. 노드의 L4 프록시만으로 되는 것은 상호 인증과 L4 인가까지이고, HTTP 경로 기반 라우팅이나 메서드 단위 인가처럼 요청 내용을 봐야 하는 일은 waypoint 라는 별도의 L7 프록시가 있어야 한다. 그래서 마이그레이션 계획은 '사이드카를 끄자' 가 아니라 '이 네임스페이스가 쓰는 기능 중 L7 이 필요한 것은 무엇인가' 에서 시작한다. 그리고 전환 중에는 두 모드가 한 클러스터에 공존하므로, 어느 네임스페이스가 어느 모드인지 기계가 읽을 수 있게 세어 두는 일이 사람의 기억보다 훨씬 믿을 만하다.
단계
/root/ist-ambient를 만들고istioctl manifest generate --set profile=ambient의 출력을/root/ist-ambient/ambient.yaml에 저장하세요. 그 안의 Deployment 와 DaemonSet 을 모두 뽑아/root/ist-ambient/ambient-workloads.tsv에<kind>|<이름>으로 정렬해 적으세요.- default 프로파일도 렌더해
/root/ist-ambient/default.yaml에 저장하고, 두 렌더의 ServiceAccount 이름을 견주어/root/ist-ambient/sa-diff.tsv에only-ambient\t<이름>과only-default\t<이름>줄로 정렬해 적으세요(양쪽에 다 있는 것은 적지 않습니다). - 1단계 렌더에서 이름이
istio인 ConfigMap 의data.mesh만 뽑아/root/ist-ambient/ambient-mesh.yaml에 저장하세요. 그리고 그 렌더에 들어 있는 ConfigMap 이름을 모두/root/ist-ambient/ambient-configmaps.txt에 한 줄씩 정렬해 적으세요. - 네임스페이스 두 개를 만드세요 —
shop-sidecar에는istio-injection=enabled라벨을,shop-ambient에는istio.io/dataplane-mode=ambient라벨을 겁니다. 그리고 두 네임스페이스의 라벨을 클러스터에서 읽어/root/ist-ambient/ns-labels.tsv에<네임스페이스>\t<라벨키>=<값>으로 정렬해 적으세요. - 네임스페이스
shop-both를 만들고istio-injection=enabled와istio.io/dataplane-mode=ambient를 둘 다 거세요.istioctl analyze -n shop-both -o json의 출력을/root/ist-ambient/analyze-conflict.json에 저장하세요 —IST0123이 나와야 합니다. 그다음 사이드카 쪽 라벨만 지우고 같은 명령의 출력을/root/ist-ambient/analyze-fixed.json에 저장하세요. 이번에는IST0123이 없어야 합니다. istioctl waypoint generate --for service -n shop-ambient --name shop-waypoint의 출력을/root/ist-ambient/waypoint.yaml에 저장하세요. 그리고 거기서 읽은 네 가지를/root/ist-ambient/waypoint-fields.tsv에apiVersion·gatewayClassName·port·protocol네 줄로 적으세요.--for workload로도 한 번 생성해/root/ist-ambient/waypoint-workload.yaml에 저장하고, 두 파일의metadata.labels."istio.io/waypoint-for"값을/root/ist-ambient/waypoint-for.tsv에service와workload두 줄로<파일이름>\t<값>형식으로 적으세요(이름은shop-waypoint-wl로 합니다). 그다음 6단계의waypoint.yaml을 실제로 적용해 보고 그 결과를/root/ist-ambient/waypoint-apply.txt에 저장하세요./root/ist-ambient/mode-report.sh를 만들어 클러스터의 모든 네임스페이스를<네임스페이스>\t<모드>로 이름순으로 표준출력에만 찍게 하세요 — 모드는 두 라벨이 다 있으면conflict, 앰비언트 라벨만 있으면ambient,istio-injection이enabled이면sidecar, 그 밖에는none입니다. 출력을/root/ist-ambient/mode-report.txt에 저장하세요.
참고
--set profile=ambient렌더에는 사이드카 프로파일에 없는 DaemonSet 두 개가 나옵니다.- 데이터플레인 라벨은
istio.io/dataplane-mode=ambient, 사이드카 라벨은istio-injection=enabled입니다. - 라벨을 지울 때는
kubectl label ns <이름> <키>-처럼 키 뒤에 빼기 기호를 붙입니다. - 흔한 실수: 두 라벨을 함께 걸어 두고 전환됐다고 생각합니다. 분석기가 IST0123 으로 잡아 줍니다.
- 흔한 실수: waypoint 를 Istio 전용 오브젝트로 생각합니다. Gateway API 의 Gateway 입니다.
- 참고: https://istio.io/v1.24/docs/ambient/architecture/data-plane/
- 참고: https://istio.io/v1.24/docs/ambient/usage/waypoint/
- 참고: https://istio.io/v1.24/docs/ambient/usage/l7-features/
앰비언트 프로파일이 무엇을 띄우는지 센다
/root/ist-ambient 를 만들고 istioctl manifest generate --set profile=ambient 의 출력을 /root/ist-ambient/ambient.yaml 에 저장하세요. 그 안의 Deployment 와 DaemonSet 을 모두 뽑아 /root/ist-ambient/ambient-workloads.tsv 에 <kind>|<이름> 으로 정렬해 적으세요.
앰비언트는 파드마다 프록시를 넣는 대신 노드마다 두 가지를 깝니다 — 트래픽을 가로채는 쪽과 L4 프록시 역할을 하는 쪽입니다. 둘 다 DaemonSet 으로 나옵니다. 렌더에서 뽑을 때는 yq -N e 'select(.kind=="DaemonSet") | .metadata.name' 처럼 종류로 거르면 됩니다.
사이드카 모드와 견주면 신원이 두 개 늘고 하나 준다
default 프로파일도 렌더해 /root/ist-ambient/default.yaml 에 저장하고, 두 렌더의 ServiceAccount 이름을 견주어 /root/ist-ambient/sa-diff.tsv 에 only-ambient\t<이름> 과 only-default\t<이름> 줄로 정렬해 적으세요(양쪽에 다 있는 것은 적지 않습니다).
구성요소가 늘거나 줄면 그 구성요소가 쓰는 서비스어카운트도 함께 움직입니다. 두 목록을 각각 정렬해 comm 으로 비교하면 한쪽에만 있는 이름이 나옵니다. 앰비언트에는 게이트웨이가 기본으로 없다는 점도 여기서 드러납니다.
앰비언트의 메시 설정에는 무엇이 더 켜져 있나
1단계 렌더에서 이름이 istio 인 ConfigMap 의 data.mesh 만 뽑아 /root/ist-ambient/ambient-mesh.yaml 에 저장하세요. 그리고 그 렌더에 들어 있는 ConfigMap 이름을 모두 /root/ist-ambient/ambient-configmaps.txt 에 한 줄씩 정렬해 적으세요.
앰비언트에서는 파드 사이 트래픽이 노드의 L4 프록시를 지나 터널로 전달됩니다. 그 터널을 켜는 값이 프록시 메타데이터에 들어 있으니 defaultConfig.proxyMetadata 아래를 보세요. ConfigMap 목록에는 사이드카 프로파일에 없던 것이 하나 더 있습니다.
네임스페이스 라벨 한 줄이 데이터플레인을 고른다
네임스페이스 두 개를 만드세요 — shop-sidecar 에는 istio-injection=enabled 라벨을, shop-ambient 에는 istio.io/dataplane-mode=ambient 라벨을 겁니다. 그리고 두 네임스페이스의 라벨을 클러스터에서 읽어 /root/ist-ambient/ns-labels.tsv 에 <네임스페이스>\t<라벨키>=<값> 으로 정렬해 적으세요.
두 모드는 서로 다른 라벨 키를 씁니다. 사이드카 쪽은 주입 웹훅이 보는 라벨이고, 앰비언트 쪽은 노드의 CNI 가 보는 라벨입니다. kubectl get ns -o json 에 jq 를 붙이면 라벨을 그대로 꺼낼 수 있습니다.
두 라벨을 함께 걸면 동작이 정의되지 않는다
네임스페이스 shop-both 를 만들고 istio-injection=enabled 와 istio.io/dataplane-mode=ambient 를 둘 다 거세요. istioctl analyze -n shop-both -o json 의 출력을 /root/ist-ambient/analyze-conflict.json 에 저장하세요 — IST0123 이 나와야 합니다. 그다음 사이드카 쪽 라벨만 지우고 같은 명령의 출력을 /root/ist-ambient/analyze-fixed.json 에 저장하세요. 이번에는 IST0123 이 없어야 합니다.
두 라벨은 서로 다른 구성요소가 읽습니다 — 하나는 주입 웹훅, 하나는 노드의 CNI. 둘 다 걸리면 그 파드가 어느 데이터플레인을 쓰는지 정해지지 않습니다. 라벨을 지울 때는 키 뒤에 빼기 기호를 붙입니다.
L7 이 필요하면 waypoint 를 따로 세운다
istioctl waypoint generate --for service -n shop-ambient --name shop-waypoint 의 출력을 /root/ist-ambient/waypoint.yaml 에 저장하세요. 그리고 거기서 읽은 네 가지를 /root/ist-ambient/waypoint-fields.tsv 에 apiVersion·gatewayClassName·port·protocol 네 줄로 적으세요.
waypoint 는 Istio 전용 오브젝트가 아니라 Gateway API 의 Gateway 로 표현됩니다 — 어느 게이트웨이 클래스인지가 이것을 waypoint 로 만듭니다. 리스너의 포트와 프로토콜은 앰비언트가 파드 사이에 쓰는 터널 그대로입니다.
무엇을 위한 waypoint 인가, 그리고 왜 여기서는 적용되지 않는가
--for workload 로도 한 번 생성해 /root/ist-ambient/waypoint-workload.yaml 에 저장하고, 두 파일의 metadata.labels."istio.io/waypoint-for" 값을 /root/ist-ambient/waypoint-for.tsv 에 service 와 workload 두 줄로 <파일이름>\t<값> 형식으로 적으세요(이름은 shop-waypoint-wl 로 합니다). 그다음 6단계의 waypoint.yaml 을 실제로 적용해 보고 그 결과를 /root/ist-ambient/waypoint-apply.txt 에 저장하세요.
waypoint 는 서비스 앞에 세울 수도 있고 워크로드 앞에 세울 수도 있습니다 — 라벨 하나가 그 범위를 말합니다. 적용은 이 클러스터에서 성공하지 않습니다. 왜 그런지는 오류 문장이 그대로 말해 줍니다.
클러스터의 네임스페이스를 모드별로 세는 점검표
/root/ist-ambient/mode-report.sh 를 만들어 클러스터의 모든 네임스페이스를 <네임스페이스>\t<모드> 로 이름순으로 표준출력에만 찍게 하세요 — 모드는 두 라벨이 다 있으면 conflict, 앰비언트 라벨만 있으면 ambient, istio-injection 이 enabled 이면 sidecar, 그 밖에는 none 입니다. 출력을 /root/ist-ambient/mode-report.txt 에 저장하세요.
kubectl get ns -o json 한 번으로 모든 라벨을 받아 jq 로 가릅니다. 라벨 키에 점과 빗금이 섞여 있으니 jq 에서는 대괄호와 따옴표로 꺼내는 편이 안전합니다. istio-injection 은 값이 disabled 일 수도 있으니 켜진 것만 세야 합니다.