외부 컨트롤 플레인으로 Istio 설치하기
외부 컨트롤 플레인으로 Istio 설치하기
외부 클러스터에 Istio 컨트롤 플레인을 설치하고, 하나 이상의 remote 클러스터를 그 컨트롤 플레인에 연결하는 방법을 알려드려요.
출처: Istio 문서
본문
이 가이드는 외부 컨트롤 플레인을 설치하고, 그 컨트롤 플레인에 하나 이상의 remote 클러스터를 연결하는 과정을 안내해요. 외부 컨트롤 플레인 배포 모델은 메시 운영자가 메시를 구성하는 데이터 플레인 클러스터(또는 여러 클러스터)와 분리된 외부 클러스터에 컨트롤 플레인을 설치하고 관리할 수 있게 해줘요. 이 배포 모델은 메시 운영자와 메시 관리자를 명확히 분리할 수 있게 해줘요. 메시 운영자는 Istio 컨트롤 플레인을 설치하고 관리하고, 메시 관리자는 메시만 설정하면 돼요.
remote 클러스터에서 실행되는 Envoy 프록시(sidecar 및 게이트웨이)는 discovery, CA, 주입(injection), 검증에 필요한 엔드포인트를 노출하는 ingress 게이트웨이를 통해 외부 istiod에 접근해요.
외부 컨트롤 플레인의 구성과 관리는 메시 운영자가 외부 클러스터에서 수행하지만, 외부 컨트롤 플레인에 연결되는 첫 번째 remote 클러스터는 메시 자체의 config 클러스터 역할을 해요. 메시 관리자는 config 클러스터를 사용해서 메시 서비스들 외에도 메시 리소스(게이트웨이, VirtualService 등)를 설정하게 돼요. 외부 컨트롤 플레인은 위 다이어그램에서 보듯이 Kubernetes API server에서 이 구성을 원격으로 접근해요.
시작하기 전에
클러스터
이 가이드는 지원되는 Kubernetes 버전 1.32, 1.33, 1.34, 1.35, 1.36 중 하나를 갖춘 Kubernetes 클러스터가 두 개 필요해요.
첫 번째 클러스터는 external-istiod 네임스페이스에 설치된 외부 컨트롤 플레인을 호스팅해요. 외부 컨트롤 플레인에 대한 클러스터 간 접근을 제공하기 위해 istio-system 네임스페이스에 ingress 게이트웨이도 설치돼요.
두 번째 클러스터는 메시 애플리케이션 워크로드를 실행할 remote 클러스터예요. 그 Kubernetes API server는 외부 컨트롤 플레인(istiod)이 워크로드 프록시를 설정하는 데 사용하는 메시 구성도 제공해요.
API server 접근
remote 클러스터의 Kubernetes API server는 외부 컨트롤 플레인 클러스터에서 접근 가능해야 해요. 많은 클라우드 제공업체가 네트워크 로드 밸런서(NLB)를 통해 API server를 공개적으로 접근 가능하게 만들어요. API server에 직접 접근할 수 없다면, 접근을 활성화하도록 설치 절차를 수정해야 해요. 예를 들어 멀티클러스터 구성에서 사용되는 east-west 게이트웨이를 API server에 대한 접근을 활성화하는 데도 사용할 수 있어요.
환경 변수
안내를 단순화하기 위해 다음 환경 변수들을 전반에서 사용해요:
| 변수 | 설명 |
|---|---|
CTX_EXTERNAL_CLUSTER |
기본 Kubernetes 설정 파일에서 외부 컨트롤 플레인 클러스터에 접근하는 데 사용하는 컨텍스트 이름 |
CTX_REMOTE_CLUSTER |
기본 Kubernetes 설정 파일에서 remote 클러스터에 접근하는 데 사용하는 컨텍스트 이름 |
REMOTE_CLUSTER_NAME |
remote 클러스터의 이름 |
EXTERNAL_ISTIOD_ADDR |
외부 컨트롤 플레인 클러스터의 ingress 게이트웨이 호스트 이름. remote 클러스터가 외부 컨트롤 플레인에 접근하는 데 사용해요. |
SSL_SECRET_NAME |
외부 컨트롤 플레인 클러스터의 ingress 게이트웨이용 TLS 인증서를 담은 시크릿의 이름 |
지금 CTX_EXTERNAL_CLUSTER, CTX_REMOTE_CLUSTER, REMOTE_CLUSTER_NAME을 설정하세요. 나머지는 나중에 설정할 거예요.
$ export CTX_EXTERNAL_CLUSTER=<your external cluster context>
$ export CTX_REMOTE_CLUSTER=<your remote cluster context>
$ export REMOTE_CLUSTER_NAME=<your remote cluster name>
클러스터 구성
메시 운영자 단계
메시 운영자는 외부 클러스터에 외부 Istio 컨트롤 플레인을 설치하고 관리할 책임이 있어요. 여기에는 remote 클러스터가 컨트롤 플레인에 접근할 수 있게 해주는 외부 클러스터의 ingress 게이트웨이 설정과, remote 클러스터가 외부 컨트롤 플레인을 사용하도록 하는 sidecar 주입기 웹훅 설정 설치가 포함돼요.
외부 클러스터에 게이트웨이 설정
- 외부 컨트롤 플레인 포트를 다른 클러스터에 노출할 ingress 게이트웨이용 Istio 설치 설정을 만들어요:
$ cat <<EOF > controlplane-gateway.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
namespace: istio-system
spec:
components:
ingressGateways:
- name: istio-ingressgateway
enabled: true
k8s:
service:
ports:
- port: 15021
targetPort: 15021
name: status-port
- port: 15012
targetPort: 15012
name: tls-xds
- port: 15017
targetPort: 15017
name: tls-webhook
EOF
그런 다음 외부 클러스터의 istio-system 네임스페이스에 게이트웨이를 설치해요:
$ istioctl install -f controlplane-gateway.yaml --context="${CTX_EXTERNAL_CLUSTER}"
- ingress 게이트웨이가 실행 중인지 다음 명령으로 확인해요:
$ kubectl get po -n istio-system --context="${CTX_EXTERNAL_CLUSTER}"
NAME READY STATUS RESTARTS AGE
istio-ingressgateway-9d4c7f5c7-7qpzz 1/1 Running 0 29s
istiod-68488cd797-mq8dn 1/1 Running 0 38s
istio-system 네임스페이스에 istiod 배포도 생성된 것을 볼 수 있을 거예요. 이는 ingress 게이트웨이를 설정하는 데 사용되며, remote 클러스터가 사용하는 컨트롤 플레인이 아님에 주의하세요.
3. TLS를 사용하는 공개 호스트 이름으로 Istio ingress 게이트웨이 서비스를 노출하도록 환경을 설정해요.
EXTERNAL_ISTIOD_ADDR 환경 변수를 호스트 이름으로, SSL_SECRET_NAME 환경 변수를 TLS 인증서를 담은 시크릿으로 설정해요:
$ export EXTERNAL_ISTIOD_ADDR=<your external istiod host>
$ export SSL_SECRET_NAME=<your external istiod secret>
이 안내는 프로덕션 환경에서 권장되는 접근 방식이므로, 외부 클러스터의 게이트웨이를 올바르게 서명된 DNS 인증서가 있는 호스트 이름으로 노출한다고 가정해요. 보안 게이트웨이 노출에 대한 자세한 내용은 보안 ingress 작업을 참고하세요.
환경 변수는 다음과 비슷해야 해요:
$ echo "$EXTERNAL_ISTIOD_ADDR" "$SSL_SECRET_NAME"
myhost.example.com myhost-example-credential
원격 config 클러스터 설정
remote프로필을 사용해서 remote 클러스터의 Istio 설치를 구성해요. 이것은 로컬에 배포된 주입기가 아니라 외부 컨트롤 플레인의 주입기를 사용하는 주입 웹훅을 설치해요. 이 클러스터가 config 클러스터 역할도 하기 때문에, remote 클러스터에 필요할 Istio CRD와 다른 리소스들도global.configCluster와pilot.configMap을true로 설정해서 설치돼요:
$ cat <<EOF > remote-config-cluster.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
namespace: external-istiod
spec:
profile: remote
values:
global:
istioNamespace: external-istiod
configCluster: true
pilot:
configMap: true
istiodRemote:
injectionURL: https://${EXTERNAL_ISTIOD_ADDR}:15017/inject/cluster/${REMOTE_CLUSTER_NAME}/net/network1
base:
validationURL: https://${EXTERNAL_ISTIOD_ADDR}:15017/validate
EOF
EXTERNAL_ISTIOD_ADDR에 적절한 DNS 호스트 이름 대신 IP 주소를 사용한다면, URL 대신 discovery 주소와 경로를 지정하도록 구성을 수정해요:
$ sed -i'.bk' \
-e "s|injectionURL: https://${EXTERNAL_ISTIOD_ADDR}:15017|injectionPath: |" \
-e "/istioNamespace:/a\
remotePilotAddress: ${EXTERNAL_ISTIOD_ADDR}" \
-e '/base:/,+1d' \
remote-config-cluster.yaml; rm remote-config-cluster.yaml.bk
- remote 클러스터에 구성을 설치해요:
$ kubectl create namespace external-istiod --context="${CTX_REMOTE_CLUSTER}"
$ istioctl install -f remote-config-cluster.yaml --set values.defaultRevision=default --context="${CTX_REMOTE_CLUSTER}"
- remote 클러스터의 주입 웹훅 설정이 설치되었는지 확인해요:
$ kubectl get mutatingwebhookconfiguration --context="${CTX_REMOTE_CLUSTER}"
NAME WEBHOOKS AGE
istio-revision-tag-default-external-istiod 4 2m2s
istio-sidecar-injector-external-istiod 4 2m5s
- remote 클러스터의 검증 웹훅 설정이 설치되었는지 확인해요:
$ kubectl get validatingwebhookconfiguration --context="${CTX_REMOTE_CLUSTER}"
NAME WEBHOOKS AGE
istio-validator-external-istiod 1 6m53s
istiod-default-validator 1 6m53s
외부 클러스터에 컨트롤 플레인 설정
- 외부 컨트롤 플레인을 호스팅할
external-istiod네임스페이스를 만들어요:
$ kubectl create namespace external-istiod --context="${CTX_EXTERNAL_CLUSTER}"
- 외부 클러스터의 컨트롤 플레인은 서비스, 엔드포인트, pod 속성을 발견하려면 remote 클러스터에 접근해야 해요. remote 클러스터의
kube-apiserver에 접근할 수 있는 자격 증명이 담긴 시크릿을 만들어서 외부 클러스터에 설치해요:
$ istioctl create-remote-secret \
--context="${CTX_REMOTE_CLUSTER}" \
--type=config \
--namespace=external-istiod \
--service-account=istiod \
--create-service-account=false | \
kubectl apply -f - --context="${CTX_EXTERNAL_CLUSTER}"
- 외부 클러스터의
external-istiod네임스페이스에 컨트롤 플레인을 설치할 Istio 설정을 만들어요. istiod가 로컬에 마운트된istioconfigmap을 사용하도록 설정되고SHARED_MESH_CONFIG환경 변수가istio로 설정된 것에 주목하세요. 이것은 istiod가 config 클러스터의 configmap에서 메시 관리자가 설정한 값과, 여기에서 메시 운영자가 설정한 로컬 configmap의 값을 병합하도록 지시하며, 충돌이 있으면 로컬 값이 우선합니다:
$ cat <<EOF > external-istiod.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
namespace: external-istiod
spec:
profile: empty
meshConfig:
rootNamespace: external-istiod
defaultConfig:
discoveryAddress: $EXTERNAL_ISTIOD_ADDR:15012
proxyMetadata:
XDS_ROOT_CA: /etc/ssl/certs/ca-certificates.crt
CA_ROOT_CA: /etc/ssl/certs/ca-certificates.crt
components:
pilot:
enabled: true
k8s:
overlays:
- kind: Deployment
name: istiod
patches:
- path: spec.template.spec.volumes[100]
value: |-
name: config-volume
configMap:
name: istio
- path: spec.template.spec.volumes[100]
value: |-
name: inject-volume
configMap:
name: istio-sidecar-injector
- path: spec.template.spec.containers[0].volumeMounts[100]
value: |-
name: config-volume
mountPath: /etc/istio/config
- path: spec.template.spec.containers[0].volumeMounts[100]
value: |-
name: inject-volume
mountPath: /var/lib/istio/inject
env:
- name: INJECTION_WEBHOOK_CONFIG_NAME
value: ""
- name: VALIDATION_WEBHOOK_CONFIG_NAME
value: ""
- name: EXTERNAL_ISTIOD
value: "true"
- name: LOCAL_CLUSTER_SECRET_WATCHER
value: "true"
- name: CLUSTER_ID
value: ${REMOTE_CLUSTER_NAME}
- name: SHARED_MESH_CONFIG
value: istio
values:
global:
externalIstiod: true
caAddress: $EXTERNAL_ISTIOD_ADDR:15012
istioNamespace: external-istiod
operatorManageWebhooks: true
configValidation: false
meshID: mesh1
multiCluster:
clusterName: ${REMOTE_CLUSTER_NAME}
network: network1
EOF
EXTERNAL_ISTIOD_ADDR에 적절한 DNS 호스트 이름 대신 IP 주소를 사용한다면, 구성에서 proxy metadata를 삭제하고 웹훅 구성 환경 변수를 업데이트해요:
$ sed -i'.bk' \
-e '/proxyMetadata:/,+2d' \
-e '/INJECTION_WEBHOOK_CONFIG_NAME/{n;s/value: ""/value: istio-sidecar-injector-external-istiod/;}' \
-e '/VALIDATION_WEBHOOK_CONFIG_NAME/{n;s/value: ""/value: istio-validator-external-istiod/;}' \
external-istiod.yaml ; rm external-istiod.yaml.bk
- 외부 클러스터에 Istio 설정을 적용해요:
$ istioctl install -f external-istiod.yaml --context="${CTX_EXTERNAL_CLUSTER}"
- 외부 istiod가 성공적으로 배포되었는지 확인해요:
$ kubectl get po -n external-istiod --context="${CTX_EXTERNAL_CLUSTER}"
NAME READY STATUS RESTARTS AGE
istiod-779bd6fdcf-bd6rg 1/1 Running 0 70s
- ingress 게이트웨이에서 외부 컨트롤 플레인으로 트래픽을 라우팅할 Istio
Gateway,VirtualService,DestinationRule설정을 만들어요:
$ cat <<EOF > external-istiod-gw.yaml
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: external-istiod-gw
namespace: external-istiod
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 15012
protocol: https
name: https-XDS
tls:
mode: SIMPLE
credentialName: $SSL_SECRET_NAME
hosts:
- $EXTERNAL_ISTIOD_ADDR
- port:
number: 15017
protocol: https
name: https-WEBHOOK
tls:
mode: SIMPLE
credentialName: $SSL_SECRET_NAME
hosts:
- $EXTERNAL_ISTIOD_ADDR
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: external-istiod-vs
namespace: external-istiod
spec:
hosts:
- $EXTERNAL_ISTIOD_ADDR
gateways:
- external-istiod-gw
http:
- match:
- port: 15012
route:
- destination:
host: istiod.external-istiod.svc.cluster.local
port:
number: 15012
- match:
- port: 15017
route:
- destination:
host: istiod.external-istiod.svc.cluster.local
port:
number: 443
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: external-istiod-dr
namespace: external-istiod
spec:
host: istiod.external-istiod.svc.cluster.local
trafficPolicy:
portLevelSettings:
- port:
number: 15012
tls:
mode: SIMPLE
connectionPool:
http:
h2UpgradePolicy: UPGRADE
- port:
number: 443
tls:
mode: SIMPLE
EOF
EXTERNAL_ISTIOD_ADDR에 적절한 DNS 호스트 이름 대신 IP 주소를 사용한다면 구성을 수정해요.DestinationRule을 삭제하고,Gateway에서 TLS를 종료하지 말고,VirtualService에서 TLS 라우팅을 사용해요:
$ sed -i'.bk' \
-e '55,$d' \
-e 's/mode: SIMPLE/mode: PASSTHROUGH/' -e '/credentialName:/d' -e "s/${EXTERNAL_ISTIOD_ADDR}/\"*\"/" \
-e 's/http:/tls:/' -e 's/https/tls/' -e '/route:/i\
sniHosts:\
- "*"' \
external-istiod-gw.yaml; rm external-istiod-gw.yaml.bk
- 외부 클러스터에 구성을 적용해요:
$ kubectl apply -f external-istiod-gw.yaml --context="${CTX_EXTERNAL_CLUSTER}"
메시 관리자 단계
이제 Istio가 실행 중이므로, 메시 관리자는 필요하면 게이트웨이를 포함해 메시 안의 서비스를 배포하고 설정하기만 하면 돼요.
샘플 애플리케이션 배포
- remote 클러스터에
sample네임스페이스를 만들고 주입용으로 라벨을 붙여요:
$ kubectl create --context="${CTX_REMOTE_CLUSTER}" namespace sample
$ kubectl label --context="${CTX_REMOTE_CLUSTER}" namespace sample istio-injection=enabled
helloworld(v1)과curl샘플을 배포해요:
$ kubectl apply -f @samples/helloworld/helloworld.yaml@ -l service=helloworld -n sample --context="${CTX_REMOTE_CLUSTER}"
$ kubectl apply -f @samples/helloworld/helloworld.yaml@ -l version=v1 -n sample --context="${CTX_REMOTE_CLUSTER}"
$ kubectl apply -f @samples/curl/curl.yaml@ -n sample --context="${CTX_REMOTE_CLUSTER}"
helloworld와curlpod가 sidecar와 함께 주입되어 실행될 때까지 몇 초 기다려요:
$ kubectl get pod -n sample --context="${CTX_REMOTE_CLUSTER}"
NAME READY STATUS RESTARTS AGE
curl-64d7d56698-wqjnm 2/2 Running 0 9s
helloworld-v1-776f57d5f6-s7zfc 2/2 Running 0 10s
curlpod에서helloworld서비스로 요청을 보내요:
$ kubectl exec --context="${CTX_REMOTE_CLUSTER}" -n sample -c curl \
"$(kubectl get pod --context="${CTX_REMOTE_CLUSTER}" -n sample -l app=curl -o jsonpath='{.items[0].metadata.name}')" \
-- curl -sS helloworld.sample:5000/hello
Hello version: v1, instance: helloworld-v1-776f57d5f6-s7zfc
게이트웨이 활성화
remote 클러스터에서 ingress 게이트웨이를 활성화해요:
$ cat <<EOF > istio-ingressgateway.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: ingress-install
spec:
profile: empty
components:
ingressGateways:
- namespace: external-istiod
name: istio-ingressgateway
enabled: true
values:
gateways:
istio-ingressgateway:
injectionTemplate: gateway
EOF
$ istioctl install -f istio-ingressgateway.yaml --set values.global.istioNamespace=external-istiod --context="${CTX_REMOTE_CLUSTER}"
$ helm install istio-ingressgateway istio/gateway -n external-istiod --kube-context="${CTX_REMOTE_CLUSTER}"
게이트웨이 설치에 대한 자세한 문서는 게이트웨이 설치를 참고하세요.
선택적으로 다른 게이트웨이도 활성화할 수 있어요. 예를 들어 egress 게이트웨이:
$ cat <<EOF > istio-egressgateway.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: egress-install
spec:
profile: empty
components:
egressGateways:
- namespace: external-istiod
name: istio-egressgateway
enabled: true
values:
gateways:
istio-egressgateway:
injectionTemplate: gateway
EOF
$ istioctl install -f istio-egressgateway.yaml --set values.global.istioNamespace=external-istiod --context="${CTX_REMOTE_CLUSTER}"
$ helm install istio-egressgateway istio/gateway -n external-istiod --kube-context="${CTX_REMOTE_CLUSTER}" --set service.type=ClusterIP
게이트웨이 설치에 대한 자세한 문서는 게이트웨이 설치를 참고하세요.
ingress 게이트웨이 설정 및 테스트
- 클러스터가 게이트웨이를 설정할 준비가 되었는지 확인해요:
Istio ingress 게이트웨이가 실행 중인지 확인해요:
$ kubectl get pod -l app=istio-ingressgateway -n external-istiod --context="${CTX_REMOTE_CLUSTER}"
NAME READY STATUS RESTARTS AGE
istio-ingressgateway-7bcd5c6bbd-kmtl4 1/1 Running 0 8m4s
Kubernetes Gateway API CRD는 대부분의 Kubernetes 클러스터에 기본으로 설치되지 않으므로, Gateway API를 사용하기 전에 설치되어 있는지 확인해요:
$ kubectl get crd gateways.gateway.networking.k8s.io --context="${CTX_REMOTE_CLUSTER}" &> /dev/null || \
{ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.6.0" | kubectl apply -f - --context="${CTX_REMOTE_CLUSTER}"; }
- ingress 게이트웨이에
helloworld애플리케이션을 노출해요:
$ kubectl apply -f @samples/helloworld/helloworld-gateway.yaml@ -n sample --context="${CTX_REMOTE_CLUSTER}"
$ kubectl apply -f @samples/helloworld/gateway-api/helloworld-gateway.yaml@ -n sample --context="${CTX_REMOTE_CLUSTER}"
GATEWAY_URL환경 변수를 설정해요 (자세한 내용은 ingress IP와 포트 확인 참고):
$ export INGRESS_HOST=$(kubectl -n external-istiod --context="${CTX_REMOTE_CLUSTER}" get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ export INGRESS_PORT=$(kubectl -n external-istiod --context="${CTX_REMOTE_CLUSTER}" get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
$ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
$ kubectl -n sample --context="${CTX_REMOTE_CLUSTER}" wait --for=condition=programmed gtw helloworld-gateway
$ export INGRESS_HOST=$(kubectl -n sample --context="${CTX_REMOTE_CLUSTER}" get gtw helloworld-gateway -o jsonpath='{.status.addresses[0].value}')
$ export GATEWAY_URL=$INGRESS_HOST:80
- ingress 게이트웨이를 통해
helloworld애플리케이션에 접근할 수 있는지 확인해요:
$ curl -s "http://${GATEWAY_URL}/hello"
Hello version: v1, instance: helloworld-v1-776f57d5f6-s7zfc
메시에 클러스터 추가 (선택)
이 섹션은 다른 remote 클러스터를 추가해서 기존 외부 컨트롤 플레인 메시를 멀티클러스터로 확장하는 방법을 보여줘요. 이렇게 하면 서비스를 쉽게 분산하고 위치 인식 라우팅 및 장애 조치를 사용해서 애플리케이션의 고가용성을 지원할 수 있어요.
같은 외부 컨트롤 플레인에 추가되는 두 번째 및 그 이후 클러스터는 첫 번째 remote 클러스터와 달리 메시 구성을 제공하지 않아요. 대신 primary-remote Istio 멀티클러스터 구성의 remote 클러스터처럼 단지 endpoint 구성의 원천일 뿐이에요.
진행하려면 메시의 두 번째 remote 클러스터용 Kubernetes 클러스터가 하나 더 필요해요. 클러스터의 컨텍스트 이름과 클러스터 이름으로 다음 환경 변수를 설정해요:
$ export CTX_SECOND_CLUSTER=<your second remote cluster context>
$ export SECOND_CLUSTER_NAME=<your second remote cluster name>
새 클러스터 등록
- 로컬에 배포된 주입기가 아니라 외부 컨트롤 플레인의 주입기를 사용하는 주입 웹훅을 설치하는 원격 Istio 설치 설정을 만들어요:
$ cat <<EOF > second-remote-cluster.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
namespace: external-istiod
spec:
profile: remote
values:
global:
istioNamespace: external-istiod
istiodRemote:
injectionURL: https://${EXTERNAL_ISTIOD_ADDR}:15017/inject/cluster/${SECOND_CLUSTER_NAME}/net/network2
EOF
EXTERNAL_ISTIOD_ADDR에 적절한 DNS 호스트 이름 대신 IP 주소를 사용한다면, 주입 URL 대신 discovery 주소와 경로를 지정하도록 구성을 수정해요:
$ sed -i'.bk' \
-e "s|injectionURL: https://${EXTERNAL_ISTIOD_ADDR}:15017|injectionPath: |" \
-e "/istioNamespace:/a\
remotePilotAddress: ${EXTERNAL_ISTIOD_ADDR}" \
second-remote-cluster.yaml; rm second-remote-cluster.yaml.bk
- remote 클러스터에 시스템 네임스페이스를 만들고 annotation을 붙여요:
$ kubectl create namespace external-istiod --context="${CTX_SECOND_CLUSTER}"
$ kubectl annotate namespace external-istiod "topology.istio.io/controlPlaneClusters=${REMOTE_CLUSTER_NAME}" --context="${CTX_SECOND_CLUSTER}"
topology.istio.io/controlPlaneClusters annotation은 이 remote 클러스터를 관리해야 하는 외부 컨트롤 플레인의 클러스터 ID를 지정해요. 이것은 앞서 외부 클러스터에 외부 컨트롤 플레인을 설치할 때 외부 컨트롤 플레인의 클러스터 ID를 설정하는 데 사용된 첫 번째 remote(config) 클러스터의 이름이라는 점에 주의하세요.
4. remote 클러스터에 구성을 설치해요:
$ istioctl install -f second-remote-cluster.yaml --context="${CTX_SECOND_CLUSTER}"
- remote 클러스터의 주입 웹훅 설정이 설치되었는지 확인해요:
$ kubectl get mutatingwebhookconfiguration --context="${CTX_SECOND_CLUSTER}"
NAME WEBHOOKS AGE
istio-sidecar-injector-external-istiod 4 4m13s
- 컨트롤 플레인이 두 번째 remote 클러스터의 endpoint에 접근할 수 있게 해주는 자격 증명이 담긴 시크릿을 만들고 설치해요:
$ istioctl create-remote-secret \
--context="${CTX_SECOND_CLUSTER}" \
--name="${SECOND_CLUSTER_NAME}" \
--type=remote \
--namespace=external-istiod \
--create-service-account=false | \
kubectl apply -f - --context="${CTX_EXTERNAL_CLUSTER}"
이번에는 config 클러스터 역할도 하는 메시의 첫 번째 remote 클러스터와 달리 --type 인자가 config가 아닌 remote로 설정된다는 점에 주의하세요.
east-west 게이트웨이 설정
- 두 remote 클러스터 모두에 east-west 게이트웨이를 배포해요:
$ @samples/multicluster/gen-eastwest-gateway.sh@ \
--network network1 > eastwest-gateway-1.yaml
$ istioctl manifest generate -f eastwest-gateway-1.yaml \
--set values.global.istioNamespace=external-istiod | \
kubectl apply --context="${CTX_REMOTE_CLUSTER}" -f -
$ @samples/multicluster/gen-eastwest-gateway.sh@ \
--network network2 > eastwest-gateway-2.yaml
$ istioctl manifest generate -f eastwest-gateway-2.yaml \
--set values.global.istioNamespace=external-istiod | \
kubectl apply --context="${CTX_SECOND_CLUSTER}" -f -
- east-west 게이트웨이에 외부 IP 주소가 할당될 때까지 기다려요:
$ kubectl --context="${CTX_REMOTE_CLUSTER}" get svc istio-eastwestgateway -n external-istiod
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-eastwestgateway LoadBalancer 10.0.12.121 34.122.91.98 ... 51s
$ kubectl --context="${CTX_SECOND_CLUSTER}" get svc istio-eastwestgateway -n external-istiod
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-eastwestgateway LoadBalancer 10.0.12.121 34.122.91.99 ... 51s
- east-west 게이트웨이를 통해 서비스를 노출해요:
$ kubectl --context="${CTX_REMOTE_CLUSTER}" apply -n external-istiod -f \
@samples/multicluster/expose-services.yaml@
설치 검증
- remote 클러스터에
sample네임스페이스를 만들고 주입용으로 라벨을 붙여요:
$ kubectl create --context="${CTX_SECOND_CLUSTER}" namespace sample
$ kubectl label --context="${CTX_SECOND_CLUSTER}" namespace sample istio-injection=enabled
helloworld(v2)과curl샘플을 배포해요:
$ kubectl apply -f @samples/helloworld/helloworld.yaml@ -l service=helloworld -n sample --context="${CTX_SECOND_CLUSTER}"
$ kubectl apply -f @samples/helloworld/helloworld.yaml@ -l version=v2 -n sample --context="${CTX_SECOND_CLUSTER}"
$ kubectl apply -f @samples/curl/curl.yaml@ -n sample --context="${CTX_SECOND_CLUSTER}"
helloworld와curlpod가 sidecar와 함께 주입되어 실행될 때까지 몇 초 기다려요:
$ kubectl get pod -n sample --context="${CTX_SECOND_CLUSTER}"
NAME READY STATUS RESTARTS AGE
curl-557747455f-wtdbr 2/2 Running 0 9s
helloworld-v2-54df5f84b-9hxgw 2/2 Running 0 10s
curlpod에서helloworld서비스로 요청을 보내요:
$ kubectl exec --context="${CTX_SECOND_CLUSTER}" -n sample -c curl \
"$(kubectl get pod --context="${CTX_SECOND_CLUSTER}" -n sample -l app=curl -o jsonpath='{.items[0].metadata.name}')" \
-- curl -sS helloworld.sample:5000/hello
Hello version: v2, instance: helloworld-v2-54df5f84b-9hxgw
- ingress 게이트웨이를 통해
helloworld애플리케이션에 여러 번 접근하면 이제v1과v2두 버전이 모두 호출되는지 확인해요:
$ for i in {1..10}; do curl -s "http://${GATEWAY_URL}/hello"; done
Hello version: v1, instance: helloworld-v1-776f57d5f6-s7zfc
Hello version: v2, instance: helloworld-v2-54df5f84b-9hxgw
Hello version: v1, instance: helloworld-v1-776f57d5f6-s7zfc
Hello version: v2, instance: helloworld-v2-54df5f84b-9hxgw
...
정리
외부 컨트롤 플레인 클러스터를 정리해요:
$ kubectl delete -f external-istiod-gw.yaml --context="${CTX_EXTERNAL_CLUSTER}"
$ istioctl uninstall -y --purge -f external-istiod.yaml --context="${CTX_EXTERNAL_CLUSTER}"
$ kubectl delete ns istio-system external-istiod --context="${CTX_EXTERNAL_CLUSTER}"
$ rm controlplane-gateway.yaml external-istiod.yaml external-istiod-gw.yaml
원격 config 클러스터를 정리해요:
$ kubectl delete ns sample --context="${CTX_REMOTE_CLUSTER}"
$ istioctl uninstall -y --purge -f remote-config-cluster.yaml --set values.defaultRevision=default --context="${CTX_REMOTE_CLUSTER}"
$ kubectl delete ns external-istiod --context="${CTX_REMOTE_CLUSTER}"
$ rm remote-config-cluster.yaml istio-ingressgateway.yaml
$ rm istio-egressgateway.yaml eastwest-gateway-1.yaml || true
설치했다면 선택적인 두 번째 remote 클러스터를 정리해요:
$ kubectl delete ns sample --context="${CTX_SECOND_CLUSTER}"
$ istioctl uninstall -y --purge -f second-remote-cluster.yaml --context="${CTX_SECOND_CLUSTER}"
$ kubectl delete ns external-istiod --context="${CTX_SECOND_CLUSTER}"
$ rm second-remote-cluster.yaml eastwest-gateway-2.yaml