LabHub
学习 学习路径 课程

Istio 服务网格

把迁不走的服务器接进网格——WorkloadGroup 与 WorkloadEntry

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

목표

WorkloadGroup 으로 메시 밖 서버 무리의 틀을 잡고, WorkloadEntry 로 서버 한 대씩 등록하고, ServiceEntry 로 메시 안의 서비스 이름에 묶는다. 마지막에는 그 서버가 받아 갈 설정 묶음을 istioctl x workload entry configure 로 실제로 만들어 보고, 셀렉터가 무엇을 잡는지 세는 보고서를 남긴다.

왜 중요한가

메시를 도입해도 쿠버네티스로 옮기지 못한 서버는 남는다. 이들을 바깥으로 두면 메시가 주는 것들이 거기서 끊긴다 — 신원, 암호화, 접근 정책, 그리고 무엇보다 한 장의 서비스 지도. 메시 확장은 그 서버를 손님이 아니라 구성원으로 들이는 일이다. 핵심은 신원이다. 쿠버네티스 안에서는 파드가 서비스어카운트로 신원을 받지만 VM 에는 그런 것이 없다. 그래서 WorkloadGroup 에 어느 서비스어카운트를 쓸지 적어 두고, 그 서버에는 클러스터가 발급한 토큰과 루트 인증서를 미리 넣어 준다. 이 세 가지가 맞아야 VM 의 프록시가 컨트롤 플레인에 붙어 자기 신원을 증명할 수 있다. 세 오브젝트의 관계도 헷갈리기 쉬운데, 무리의 틀이 WorkloadGroup, 서버 한 대가 WorkloadEntry, 부를 이름이 ServiceEntry 라고 보면 정리된다.

단계

  1. /root/ist-expansion 와 네임스페이스 expansion 를 만들고 그 안에 ServiceAccount billing-sa 를 만드세요. 그리고 이 서비스어카운트를 쓰는 워크로드가 메시에서 받게 될 신원 문자열을 /root/ist-expansion/identity.txt 에 한 줄로 적으세요 — 신뢰 도메인은 기본값 cluster.local 입니다.
  2. /root/ist-expansion/wg.yaml 에 WorkloadGroup legacy-billing 을 쓰고 expansion 에 적용하세요 — spec.metadata.labelsapp: billing, spec.templateserviceAccount: billing-sa, network: onprem, ports.http: 8080 이고, spec.probeperiodSeconds: 5httpGet 으로 포트 8080 의 /healthz 를 봅니다.
  3. /root/ist-expansion/wg-bad-probe.yaml 에 WorkloadGroup bad-probe 를 쓰되 spec.probehttpGettcpSocket둘 다 넣으세요. /root/ist-expansion/wg-no-template.yaml 에는 no-template 을 쓰되 spec.template 을 아예 빼세요. 둘 다 서버 쪽 시험 적용만 해서 거절 문장을 /root/ist-expansion/wg-reject.txt 에 순서대로 모으세요.
  4. /root/ist-expansion/we.yaml 에 WorkloadEntry billing-1 을 쓰고 적용하세요 — 메타데이터 라벨 app: billing, address10.20.30.41, networkonprem, serviceAccountbilling-sa, localitydc1/rack2, ports.http 는 8080 입니다. 그다음 /root/ist-expansion/we-typo.yamlbilling-typo 를 쓰되 주소를 10.20.30 .41 처럼 띄어 써서 적용하고, istioctl analyze -n expansion -o json 의 출력을 /root/ist-expansion/analyze-address.json 에 저장하세요. 라벨은 app: billing-broken 으로 둡니다.
  5. /root/ist-expansion/se.yaml 에 ServiceEntry billing-svc 를 쓰고 적용하세요 — hostsbilling.expansion.internal 하나, locationMESH_INTERNAL, resolutionSTATIC, 포트는 번호 8080 에 이름 http, 프로토콜 HTTP 이고, workloadSelector.labelsapp: billing 입니다.
  6. 세 개의 ServiceEntry 파일을 만들어 서버 쪽 시험 적용으로 규칙을 확인하세요 — /root/ist-expansion/se-none-endpoints.yaml(resolution: NONE 인데 endpoints 가 있음), /root/ist-expansion/se-roundrobin-two.yaml(resolution: DNS_ROUND_ROBINendpoints 두 개), /root/ist-expansion/se-roundrobin-one.yaml(resolution: DNS_ROUND_ROBINendpoints 하나). 결과를 /root/ist-expansion/resolution-rules.tsv<파일이름>\t<accepted|rejected> 로 위 순서대로 적고, 거절 문장들은 /root/ist-expansion/resolution-reject.txt 에 모으세요. 세 파일 모두 실제로 적용하지는 마세요.
  7. 먼저 istio-system 네임스페이스를 만들고, istioctl manifest generate --set profile=minimal 렌더에서 ConfigMap istio 만 뽑아 /root/ist-expansion/istio-cm.yaml 에 저장한 뒤 적용하세요. 그다음 expansion 에 ConfigMap istio-ca-root-cert 를 만드세요 — 키 이름은 root-cert.pem 이고 값은 openssl 로 만든 자체 서명 루트 인증서입니다(/root/ist-expansion/root-cert.pem). 마지막으로 istioctl x workload entry configure -f /root/ist-expansion/wg.yaml -o /root/ist-expansion/vmcfg --clusterID lab-cluster 를 돌려 설정 묶음을 만드세요.
  8. /root/ist-expansion/we2.yaml 에 두 번째 서버 billing-2 를 쓰고 적용하세요 — 라벨 app: billing, 주소 10.20.30.42, network: onprem, serviceAccount: billing-sa, locality: dc1/rack3, ports.http 8080 입니다. 그다음 /root/ist-expansion/se-match.sh 를 만들어 expansion 의 ServiceEntry 중 workloadSelector 가 있는 것마다 <ServiceEntry 이름>\t<잡힌 WorkloadEntry 수>\t<이름들 쉼표> 를 이름순으로 표준출력에만 찍게 하고, 그 출력을 /root/ist-expansion/match-result.txt 에 저장하세요.

참고

메시가 그 서버를 뭐라고 부를지 먼저 정한다

/root/ist-expansion 와 네임스페이스 expansion 를 만들고 그 안에 ServiceAccount billing-sa 를 만드세요. 그리고 이 서비스어카운트를 쓰는 워크로드가 메시에서 받게 될 신원 문자열을 /root/ist-expansion/identity.txt 에 한 줄로 적으세요 — 신뢰 도메인은 기본값 cluster.local 입니다.

메시의 신원은 IP 나 호스트 이름이 아니라 서비스어카운트에서 나옵니다. 형식은 spiffe://<신뢰도메인>/ns/<네임스페이스>/sa/<서비스어카운트> 입니다. 메시 밖의 서버도 결국 이 이름표를 받아야 안으로 들어올 수 있습니다.

VM 한 대가 아니라 VM 한 무리의 틀을 만든다

/root/ist-expansion/wg.yaml 에 WorkloadGroup legacy-billing 을 쓰고 expansion 에 적용하세요 — spec.metadata.labelsapp: billing, spec.templateserviceAccount: billing-sa, network: onprem, ports.http: 8080 이고, spec.probeperiodSeconds: 5httpGet 으로 포트 8080 의 /healthz 를 봅니다.

WorkloadGroup 은 파드의 Deployment 에 해당하는 자리입니다 — 개별 서버가 아니라 그 무리가 공통으로 가질 라벨·신원·네트워크·포트·헬스 확인 방법을 적습니다. network 값은 그 서버가 어느 네트워크에 있는지를 가리키고, 나중에 프록시가 그 값으로 경로를 고릅니다.

스키마가 거절하는 두 가지를 직접 받아 본다

/root/ist-expansion/wg-bad-probe.yaml 에 WorkloadGroup bad-probe 를 쓰되 spec.probehttpGettcpSocket둘 다 넣으세요. /root/ist-expansion/wg-no-template.yaml 에는 no-template 을 쓰되 spec.template 을 아예 빼세요. 둘 다 서버 쪽 시험 적용만 해서 거절 문장을 /root/ist-expansion/wg-reject.txt 에 순서대로 모으세요.

probe 는 검사 방법 중 하나만 고르게 돼 있습니다 — 스키마의 oneOf 제약입니다. template 은 없으면 무리의 기본값을 알 수 없으니 필수입니다. 거절 문장이 어느 필드를 가리키는지 읽어 보세요.

서버 한 대를 실제로 등록하고, 오타가 어디서 잡히는지 본다

/root/ist-expansion/we.yaml 에 WorkloadEntry billing-1 을 쓰고 적용하세요 — 메타데이터 라벨 app: billing, address10.20.30.41, networkonprem, serviceAccountbilling-sa, localitydc1/rack2, ports.http 는 8080 입니다. 그다음 /root/ist-expansion/we-typo.yamlbilling-typo 를 쓰되 주소를 10.20.30 .41 처럼 띄어 써서 적용하고, istioctl analyze -n expansion -o json 의 출력을 /root/ist-expansion/analyze-address.json 에 저장하세요. 라벨은 app: billing-broken 으로 둡니다.

WorkloadEntry 는 무리 안의 서버 한 대입니다. 주소 형식은 CRD 스키마가 검사하지 않아서 이상한 값도 만들어집니다 — 그런 것을 잡아 주는 쪽은 분석기입니다. 어느 코드로 나오는지 확인해 보세요.

등록한 서버를 메시의 서비스 이름에 묶는다

/root/ist-expansion/se.yaml 에 ServiceEntry billing-svc 를 쓰고 적용하세요 — hostsbilling.expansion.internal 하나, locationMESH_INTERNAL, resolutionSTATIC, 포트는 번호 8080 에 이름 http, 프로토콜 HTTP 이고, workloadSelector.labelsapp: billing 입니다.

WorkloadEntry 만 만들어 두면 부를 이름이 없습니다. ServiceEntry 가 메시 안의 서비스 이름을 만들고 workloadSelector 로 그 이름 뒤에 설 워크로드를 고릅니다. location 이 MESH_INTERNAL 이면 메시 구성원으로 취급돼 mTLS 와 정책이 적용되는 대상이 됩니다.

resolution 마다 endpoint 규칙이 다르다

세 개의 ServiceEntry 파일을 만들어 서버 쪽 시험 적용으로 규칙을 확인하세요 — /root/ist-expansion/se-none-endpoints.yaml(resolution: NONE 인데 endpoints 가 있음), /root/ist-expansion/se-roundrobin-two.yaml(resolution: DNS_ROUND_ROBINendpoints 두 개), /root/ist-expansion/se-roundrobin-one.yaml(resolution: DNS_ROUND_ROBINendpoints 하나). 결과를 /root/ist-expansion/resolution-rules.tsv<파일이름>\t<accepted|rejected> 로 위 순서대로 적고, 거절 문장들은 /root/ist-expansion/resolution-reject.txt 에 모으세요. 세 파일 모두 실제로 적용하지는 마세요.

resolution 은 목적지를 어떻게 찾을지를 정합니다 — NONE 은 원래 목적지 IP 를 그대로 쓰고, STATIC 은 적어 준 endpoint 를, DNS 는 이름을 풀어 씁니다. 그래서 각 방식마다 endpoint 를 몇 개 적을 수 있는지가 다릅니다. 이 규칙은 istioctl 이 아니라 CRD 의 검증 규칙이 강제합니다.

그 서버가 받아 갈 설정 묶음을 실제로 만들어 본다

먼저 istio-system 네임스페이스를 만들고, istioctl manifest generate --set profile=minimal 렌더에서 ConfigMap istio 만 뽑아 /root/ist-expansion/istio-cm.yaml 에 저장한 뒤 적용하세요. 그다음 expansion 에 ConfigMap istio-ca-root-cert 를 만드세요 — 키 이름은 root-cert.pem 이고 값은 openssl 로 만든 자체 서명 루트 인증서입니다(/root/ist-expansion/root-cert.pem). 마지막으로 istioctl x workload entry configure -f /root/ist-expansion/wg.yaml -o /root/ist-expansion/vmcfg --clusterID lab-cluster 를 돌려 설정 묶음을 만드세요.

VM 쪽 프록시가 필요한 것은 세 가지입니다 — 메시 설정(어디로 붙을지), 루트 인증서(누구를 믿을지), 토큰(자기가 누구인지). 앞의 둘은 클러스터의 ConfigMap 에서 오고 토큰은 이 명령이 서비스어카운트로 직접 발급합니다. 발급된 토큰은 짧은 수명이니 화면에 찍지 마세요.

셀렉터가 실제로 무엇을 잡는지 세어 보고 보고서로 남긴다

/root/ist-expansion/we2.yaml 에 두 번째 서버 billing-2 를 쓰고 적용하세요 — 라벨 app: billing, 주소 10.20.30.42, network: onprem, serviceAccount: billing-sa, locality: dc1/rack3, ports.http 8080 입니다. 그다음 /root/ist-expansion/se-match.sh 를 만들어 expansion 의 ServiceEntry 중 workloadSelector 가 있는 것마다 <ServiceEntry 이름>\t<잡힌 WorkloadEntry 수>\t<이름들 쉼표> 를 이름순으로 표준출력에만 찍게 하고, 그 출력을 /root/ist-expansion/match-result.txt 에 저장하세요.

라벨 셀렉터는 kubectl get workloadentry -l app=billing 처럼 그대로 물어볼 수 있습니다. 셀렉터가 여러 라벨이면 쉼표로 이어 붙입니다. 잡힌 것이 없으면 0 과 하이픈을 찍게 해 두면 나중에 라벨이 어긋난 날 바로 보입니다.