Istio 서비스 메시 · 메시 밖의 서버를 안으로 · 이론
메시 밖의 서버를 구성원으로 들이는 법
한 줄 요약
메시 확장은 쿠버네티스 밖의 서버에 신원을 주고 메시의 서비스 지도에 올리는 일이며, WorkloadGroup(무리의 틀),
WorkloadEntry(서버 한 대), ServiceEntry(부를 이름) 세 오브젝트로 표현된다.
왜 이 문제가 남아 있나
메시를 도입한 조직에서 마지막까지 남는 것은 옮기지 못한 서버다. 인증을 다시 받아야 하는 결제 시스템,
라이선스가 하드웨어에 묶인 소프트웨어, 아무도 빌드 방법을 모르는 오래된 서비스. 이들을 메시 바깥에 두면
겉보기에는 아무 문제가 없다 — 호출은 잘 되고 화면도 멀쩡하다. 문제는 거기서부터 메시가 주는 것들이
끊긴다는 점이다. 그 구간에는 mTLS 가 없고, 호출자 신원 기반 인가가 걸리지 않고, 메시의 서비스 지도와
메트릭에도 나타나지 않는다. 사고가 나면 "여기서부터는 우리가 볼 수 없습니다" 가 된다.
바깥으로 나가는 호출을 등록하는 일(ServiceEntry 로 외부 API 를 적어 두는 것)과 이 일은 다르다.
전자는 손님을 문 앞까지 안내하는 것이고, 후자는 그 서버를 구성원 명부에 올리는 것이다.
세 오브젝트가 나누어 맡는 일
| 오브젝트 | 대응하는 쿠버네티스 개념 | 무엇을 적나 |
| --- | --- | --- |
| WorkloadGroup | Deployment 의 파드 템플릿 | 무리 공통의 라벨, 서비스어카운트, 네트워크, 포트, 헬스 확인 |
| WorkloadEntry | 파드 하나 | 그 서버의 주소, 네트워크, 신원, 지역(locality), 포트 |
| ServiceEntry | Service | 메시 안에서 부를 호스트 이름과, 그 뒤에 설 워크로드를 고르는 셀렉터 |
여기서 가장 자주 빠뜨리는 것이 ServiceEntry 다. WorkloadEntry 만 만들어 두면 등록은 됐지만 **부를 이름이
없다.** ServiceEntry 의 workloadSelector 가 라벨로 WorkloadEntry 를 골라 그 이름 뒤에 세운다. 이때
셀렉터가 보는 것은 WorkloadEntry 의 metadata.labels 다 — spec 안에 라벨을 적으면 아무것도 잡히지 않는다.
location 도 의미가 크다. MESH_INTERNAL 이면 메시 구성원으로 취급돼 mTLS 와 정책의 대상이 되고,MESH_EXTERNAL 이면 바깥 서비스로 취급된다. 같은 ServiceEntry 라도 이 한 값이 보안 모델을 가른다.
resolution 은 목적지를 어떻게 찾을지를 정하는데, 값마다 endpoint 규칙이 다르고 그 규칙을 CRD 스키마가
강제한다. NONE 은 원래 목적지 주소를 그대로 쓰므로 endpoint 를 적으면 거절된다. DNS_ROUND_ROBIN 은
하나의 이름을 한 번 풀어 그 결과를 돌려쓰는 방식이라 endpoint 가 0개나 1개여야 한다. STATIC 은 적어 준
endpoint 나 셀렉터가 잡은 WorkloadEntry 를 쓴다.
신원은 어떻게 그 서버에 도착하나
쿠버네티스 안에서는 kubelet 이 파드에 토큰을 넣어 주고 프록시가 그것으로 자기를 증명한다. VM 에는
kubelet 이 없으니 사람이 넣어 줘야 한다. 그 서버가 필요로 하는 것은 세 가지다.
- 메시 설정 — 어디에 붙을지(
discoveryAddress), 무엇을 기본값으로 쓸지 - 루트 인증서 — 누구를 믿을지. 네임스페이스의 ConfigMap
istio-ca-root-cert에서 온다 - 토큰 — 자기가 누구인지. WorkloadGroup 에 적힌 서비스어카운트로 발급한다
istioctl x workload entry configure 가 이 셋을 모아 한 디렉터리로 만들어 준다. 결과의 cluster.env 를
열어 보면 SERVICE_ACCOUNT, ISTIO_META_NETWORK, ISTIO_INBOUND_PORTS 같은 값이 WorkloadGroup 에서
그대로 내려온 것을 볼 수 있다. 즉 WorkloadGroup 은 선언이 아니라 실제 부팅 설정의 원본이다.
network 값도 여기서 의미가 생긴다. 같은 network 이름을 가진 워크로드끼리는 직접 통하고, 다르면 게이트웨이를
거쳐야 한다고 메시가 판단한다. 값이 틀리면 연결이 안 되는 게 아니라 엉뚱한 경로로 간다.
현장에서 만나는 모습
가장 흔한 신고는 "등록했는데 아무 데서도 안 보인다" 이다. 원인의 대부분은 라벨 불일치다. WorkloadEntry 의
라벨과 ServiceEntry 의 셀렉터가 한 글자 다르면 오류가 나지 않고 그냥 아무것도 잡히지 않는다. 그래서
셀렉터가 실제로 몇 개를 잡는지 세어 보는 스크립트를 등록 절차에 붙여 두는 팀이 많다.
두 번째는 주소 오타다. WorkloadEntry 의 address 는 IP 도 FQDN 도 될 수 있어서 CRD 스키마가 형식을
강제하지 않는다. 그래서 공백이 섞인 값도 그대로 만들어진다. 이런 것을 잡아 주는 쪽은 API 서버가 아니라istioctl analyze 다 — 스키마 검사와 설정 분석은 서로 다른 그물이고, 둘 다 있어야 구멍이 메워진다.
이 실습 환경의 한계
실습 파드에서는 VM 을 실제로 띄울 수 없다. 그래서 만들어진 설정 묶음을 서버에 넣고 프록시를 올려
메시에 붙는 장면은 볼 수 없고, 자동 등록(VM 이 스스로 WorkloadEntry 를 만드는 것)도 확인할 수 없다.
대신 세 오브젝트의 스키마 강제, 셀렉터가 실제로 잡는 것, 그리고 설정 묶음이 WorkloadGroup 에서 어떻게
만들어지는지는 전부 진짜 API 서버를 상대로 확인할 수 있다.
다음 실습에서 할 것
서버가 받을 신원 문자열을 먼저 적어 보고, WorkloadGroup 과 WorkloadEntry 와 ServiceEntry 를 차례로 만든다.
스키마가 거절하는 값들(probe 를 둘 다 적기, template 빼기, resolution 별 endpoint 규칙)을 직접 받아 보고,
마지막에는 VM 이 받아 갈 설정 묶음을 실제로 만들어 셀렉터가 몇 대를 잡는지 세는 보고서를 남긴다.