Cloud Service Mesh를 사용하여 GKE 비공개 클러스터에서 분산 서비스 실행
이 문서에서는 Cloud Service Mesh를 사용하여 Google Cloud의 여러 Google Kubernetes Engine(GKE) 클러스터에서 분산 서비스를 실행하는 방법을 보여줍니다. 또한 이 문서에서는 멀티 클러스터 인그레스와 Cloud Service Mesh를 사용하여 분산 서비스를 노출하는 방법을 보여줍니다. 이 문서를 사용하여 비공개 GKE 클러스터를 구성할 수 있습니다. 이 문서에서는 비공개 클러스터용으로 엄격하게 사용되는 구성을 강조해서 보여줍니다.
이 문서는 Kubernetes에 대한 기본 지식이 있는 플랫폼 관리자 및 서비스 운영자를 대상으로 합니다. 서비스 메시에 대한 일부 지식도 필수는 아니지만 도움이 됩니다. Cloud Service Mesh는 오픈소스 Istio 기술을 기반으로 합니다. 서비스 메시 및 Istio에 대한 자세한 내용은 istio.io를 참조하세요.
분산 서비스는 단일 논리적 서비스로 작동하는 Kubernetes 서비스입니다. 분산 서비스는 동일한 네임스페이스의 여러 Kubernetes 클러스터에서 실행되기 때문에 Kubernetes 서비스보다 복원력이 우수합니다. 하나 이상의 GKE 클러스터가 작동 중지되더라도 정상 클러스터가 원하는 로드를 제공할 수 있는 한 분산 서비스는 작동 상태를 유지합니다.
Kubernetes 서비스는 실행되는 클러스터의 Kubernetes API 서버를 통해서만 사용 가능합니다. Kubernetes 클러스터가 작동 중지되면(예: 예약된 유지보수 중) 해당 클러스터에서 실행 중인 모든 Kubernetes 서비스도 작동 중지됩니다. 분산 서비스를 실행하면 다른 클러스터가 트래픽을 처리할 때 유지보수 또는 업그레이드를 위해 클러스터를 중지할 수 있으므로 수명 주기 관리가 더 쉬워집니다. 분산 서비스를 만들기 위해 Cloud Service Mesh에서 제공하는 서비스 메시 기능은 여러 클러스터에서 실행되는 서비스를 연결하여 단일 논리 서비스로 작동하는 데 사용됩니다.
GKE 비공개 클러스터를 사용하면 노드와 API 서버를 Virtual Private Cloud(VPC) 네트워크에서만 사용할 수 있는 비공개 리소스로 구성할 수 있습니다. GKE 비공개 클러스터에서 분산 서비스를 실행하면 기업에 안전하고 안정적인 서비스가 제공됩니다.
아키텍처
이 튜토리얼에서는 다음 다이어그램에 표시된 아키텍처를 사용합니다.
위의 다이어그램에서 아키텍처에는 다음 클러스터가 포함됩니다.
- 두 클러스터(
gke-central-priv
및gke-west-priv
)는 서로 다른 두 리전에서 동일한 GKE 비공개 클러스터 역할을 합니다. - 별도의 클러스터(
ingress-config
)는 멀티 클러스터 인그레스를 구성하는 컨트롤 플레인 클러스터 역할을 합니다.
이 튜토리얼에서는 GKE 비공개 클러스터 2개(gke-central-priv
및 gke-west-priv
)에 Bank of Anthos 샘플 애플리케이션을 배포합니다. Bank of Anthos는 온라인 뱅킹 앱을 시뮬레이션하는 마이크로서비스와 SQL 데이터베이스 여러 개로 구성된 샘플 마이크로서비스 애플리케이션입니다. 이 애플리케이션은 클라이언트에서 액세스할 수 있는 웹 프런트엔드와 은행을 시뮬레이션하는 잔액, 원장, 계좌 서비스와 같은 백엔드 서비스 여러 개로 구성됩니다.
애플리케이션에는 Kubernetes에 StatefulSets로 설치된 2개의 PostgreSQL 데이터베이스가 포함되어 있습니다. 한 데이터베이스는 트랜잭션에 사용되고 다른 데이터베이스는 사용자 계정에 사용됩니다. 두 데이터베이스를 제외한 모든 서비스가 분산 서비스로 실행됩니다. 즉, 모든 서비스의 포드가 같은 네임스페이스에 있는 두 애플리케이션 클러스터 모두에서 실행되고 Cloud Service Mesh는 각 서비스가 단일 논리적 서비스로 표시되도록 구성됩니다.
목표
- GKE 클러스터 3개 만듭니다.
- GKE 클러스터 두 개를 비공개 클러스터(
gke-central-priv
및gke-west-priv
)로 구성합니다. - 하나의 GKE 클러스터(
ingress-config
)를 중앙 구성 클러스터로 구성합니다. 이 클러스터는 멀티 클러스터 인그레스의 구성 클러스터로 사용됩니다. - 두 개의 비공개 GKE 클러스터에서 클러스터 간 및 이그레스 트래픽을 허용하도록 네트워킹(NAT 게이트웨이, Cloud Router, 방화벽 규칙)을 구성합니다.
- API 서비스가 Cloud Shell에서 2개의 비공개 GKE 클러스터에 액세스하도록 승인된 네트워크를 구성합니다.
- 멀티 기본 모드에서 멀티 클러스터 Cloud Service Mesh를 비공개 클러스터 2개에 배포하고 구성합니다. 멀티 기본 모드는 Cloud Service Mesh 컨트롤 플레인을 두 클러스터 모두에 배포합니다.
- 두 비공개 클러스터에 Bank of Anthos 애플리케이션을 배포합니다. 데이터베이스를 제외한 모든 서비스가 분산 서비스(두 비공개 클러스터에서 실행되는 포드)로 배포됩니다.
- Cloud Service Mesh를 사용하여 서비스를 모니터링합니다.
- Bank of Anthos
frontend
서비스에서 멀티 클러스터 인그레스를 구성합니다. 이를 통해 외부 클라이언트(예: 웹브라우저)가 일련의 비공개 GKE 클러스터에서 실행되는 분산 서비스에 액세스할 수 있습니다.
비용
이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.
프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요.
시작하기 전에
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
Cloud Shell에서 이 튜토리얼의 모든 명령어를 실행합니다.
이 튜토리얼 전체에서 사용할 환경 변수를 정의합니다. 변수는 이 튜토리얼에서 사용되는 클러스터 이름, 리전, 영역, IP 주소 지정, Cloud Service Mesh 버전을 정의합니다.
YOUR_PROJECT_ID
를 프로젝트 ID로 바꿉니다.export PROJECT_ID=YOUR_PROJECT_ID gcloud config set project ${PROJECT_ID}
나머지 환경 변수를 설정합니다.
export CLUSTER_1=gke-west-priv export CLUSTER_2=gke-central-priv export CLUSTER_1_ZONE=us-west2-a export CLUSTER_1_REGION=us-west2 export CLUSTER_1_MASTER_IPV4_CIDR=172.16.0.0/28 export CLUSTER_2_ZONE=us-central1-a export CLUSTER_2_REGION=us-central1 export CLUSTER_2_MASTER_IPV4_CIDR=172.16.1.0/28 export CLUSTER_INGRESS=gke-ingress export CLUSTER_INGRESS_ZONE=us-west1-a export CLUSTER_INGRESS_REGION=us-west1 export CLUSTER_INGRESS_MASTER_IPV4_CIDR=172.16.2.0/28 export WORKLOAD_POOL=${PROJECT_ID}.svc.id.goog export ASM_VERSION=1.10 export CLOUDSHELL_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
개발 환경 준비
Cloud Shell에서 API를 사용 설정합니다.
gcloud services enable \ --project=${PROJECT_ID} \ container.googleapis.com \ mesh.googleapis.com \ gkehub.googleapis.com
프로젝트에 Cloud Service Mesh Fleet을 사용 설정합니다.
gcloud container fleet mesh enable --project=${PROJECT_ID}
비공개 GKE 클러스터의 네트워킹 준비
이 섹션에서는 분산 서비스 실행을 위해 사용하는 비공개 GKE 클러스터에 대한 네트워킹을 준비합니다.
비공개 GKE 클러스터 노드에는 공개 IP 주소가 할당되지 않습니다. 비공개 GKE 클러스터의 모든 노드에는 비공개 VPC IP 주소(RFC 1918 주소 공간)가 할당됩니다. 즉, 외부 리소스(VPC 네트워크 외부) 액세스가 필요한 포드에 Cloud NAT 게이트웨이가 필요합니다. Cloud NAT 게이트웨이는 내부 IP 주소를 갖는 포드가 인터넷과 통신하도록 허용하는 리전별 NAT 게이트웨이입니다. 이 튜토리얼에서는 각각의 두 리전에서 Cloud NAT 게이트웨이를 구성합니다. 한 리전 내의 여러 클러스터가 동일한 NAT 게이트웨이를 사용할 수 있습니다.
Cloud Shell에서 2개의 NAT 게이트웨이에 대해 2개의 외부 IP 주소를 만들고 예약합니다.
gcloud compute addresses create ${CLUSTER_1_REGION}-nat-ip \ --project=${PROJECT_ID} \ --region=${CLUSTER_1_REGION} gcloud compute addresses create ${CLUSTER_2_REGION}-nat-ip \ --project=${PROJECT_ID} \ --region=${CLUSTER_2_REGION}
IP 주소 및 IP 주소 이름을 변수에 저장합니다.
export NAT_REGION_1_IP_ADDR=$(gcloud compute addresses describe ${CLUSTER_1_REGION}-nat-ip \ --project=${PROJECT_ID} \ --region=${CLUSTER_1_REGION} \ --format='value(address)') export NAT_REGION_1_IP_NAME=$(gcloud compute addresses describe ${CLUSTER_1_REGION}-nat-ip \ --project=${PROJECT_ID} \ --region=${CLUSTER_1_REGION} \ --format='value(name)') export NAT_REGION_2_IP_ADDR=$(gcloud compute addresses describe ${CLUSTER_2_REGION}-nat-ip \ --project=${PROJECT_ID} \ --region=${CLUSTER_2_REGION} \ --format='value(address)') export NAT_REGION_2_IP_NAME=$(gcloud compute addresses describe ${CLUSTER_2_REGION}-nat-ip \ --project=${PROJECT_ID} \ --region=${CLUSTER_2_REGION} \ --format='value(name)')
비공개 GKE 클러스터의 두 리전에 Cloud NAT 게이트웨이를 만듭니다.
gcloud compute routers create rtr-${CLUSTER_1_REGION} \ --network=default \ --region ${CLUSTER_1_REGION} gcloud compute routers nats create nat-gw-${CLUSTER_1_REGION} \ --router=rtr-${CLUSTER_1_REGION} \ --region ${CLUSTER_1_REGION} \ --nat-external-ip-pool=${NAT_REGION_1_IP_NAME} \ --nat-all-subnet-ip-ranges \ --enable-logging gcloud compute routers create rtr-${CLUSTER_2_REGION} \ --network=default \ --region ${CLUSTER_2_REGION} gcloud compute routers nats create nat-gw-${CLUSTER_2_REGION} \ --router=rtr-${CLUSTER_2_REGION} \ --region ${CLUSTER_2_REGION} \ --nat-external-ip-pool=${NAT_REGION_2_IP_NAME} \ --nat-all-subnet-ip-ranges \ --enable-logging
포드간 통신 및 포드-API 서버 통신을 허용하는 방화벽 규칙을 만듭니다. 포드 간 통신은 GKE 클러스터 간에 분산 서비스가 서로 통신할 수 있게 해줍니다. 포드-API 서버 통신을 사용하면 Cloud Service Mesh 컨트롤 플레인에서 서비스 검색을 위해 GKE 클러스터를 쿼리할 수 있습니다.
gcloud compute firewall-rules create all-pods-and-master-ipv4-cidrs \ --project ${PROJECT_ID} \ --network default \ --allow all \ --direction INGRESS \ --source-ranges 10.0.0.0/8,${CLUSTER_1_MASTER_IPV4_CIDR},${CLUSTER_2_MASTER_IPV4_CIDR},${CLUSTER_INGRESS_MASTER_IPV4_CIDR}
네트워킹이 이제 준비되었습니다. 이 튜토리얼에서는 모든 포드 범위가 포함된 전체 10.0.0.0/8
IP 주소 범위를 사용합니다. 프로덕션에서는 조건 및 요구사항에 따라 더 엄격한 방화벽 규칙을 만드는 것이 좋습니다.
비공개 GKE 클러스터 만들기
이 섹션에서는 샘플 앱이 배포되는 2개의 비공개 GKE 클러스터를 만듭니다. 이 튜토리얼에서 비공개 GKE 클러스터 노드에는 비공개 IP 주소가 포함되고 API 서버에는 공개 엔드포인트가 포함됩니다. 하지만 API 서버 액세스는 승인된 네트워크를 사용하여 제한됩니다.
Cloud Shell에서 승인된 네트워크가 있는 2개의 비공개 클러스터를 만듭니다. 터미널에서 클러스터에 액세스할 수 있도록 포드 IP CIDR 범위(Cloud Service Mesh 컨트롤 플레인의 경우) 및 Cloud Shell에서의 액세스를 허용하도록 클러스터를 구성합니다.
gcloud container clusters create ${CLUSTER_1} \ --project ${PROJECT_ID} \ --zone=${CLUSTER_1_ZONE} \ --machine-type "e2-standard-4" \ --num-nodes "3" --min-nodes "3" --max-nodes "5" \ --enable-ip-alias --enable-autoscaling \ --workload-pool=${WORKLOAD_POOL} \ --enable-private-nodes \ --master-ipv4-cidr=${CLUSTER_1_MASTER_IPV4_CIDR} \ --enable-master-authorized-networks \ --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32 gcloud container clusters create ${CLUSTER_2} \ --project ${PROJECT_ID} \ --zone=${CLUSTER_2_ZONE} \ --machine-type "e2-standard-4" \ --num-nodes "3" --min-nodes "3" --max-nodes "5" \ --enable-ip-alias --enable-autoscaling \ --workload-pool=${WORKLOAD_POOL} \ --enable-private-nodes \ --master-ipv4-cidr=${CLUSTER_2_MASTER_IPV4_CIDR} \ --enable-master-authorized-networks \ --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32
승인된 네트워크에는 Cloud NAT 게이트웨이의 공개 IP 주소가 포함됩니다. 비공개 클러스터의 API 서버 엔드포인트는 공개 엔드포인트이므로 비공개 클러스터에서 실행되는 포드는 Cloud NAT 게이트웨이를 사용하여 공개 API 서버 엔드포인트에 액세스해야 합니다.
Cloud Shell IP 주소는 또한 승인된 네트워크의 일부입니다. 이를 통해 Cloud Shell 터미널에서 클러스터를 액세스하고 관리할 수 있습니다. Cloud Shell 공개 IP 주소는 동적으로 지정되므로 Cloud Shell을 시작할 때마다 다른 공개 IP 주소가 사용됩니다. 새 IP 주소를 시작하면 새 IP 주소가 두 클러스터의 승인된 네트워크에 포함되지 않기 때문에 클러스터에 대한 액세스가 손실됩니다.
클러스터에 대한 액세스가 손실되면 새 Cloud Shell IP 주소를 포함하도록 클러스터의 승인된 네트워크를 업데이트합니다.
업데이트된 Cloud Shell 공개 IP 주소를 가져옵니다.
export CLOUDSHELL_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
두 클러스터의 승인된 네트워크를 업데이트합니다.
gcloud container clusters update ${CLUSTER_1} \ --zone=${CLUSTER_1_ZONE} \ --enable-master-authorized-networks \ --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32 gcloud container clusters update ${CLUSTER_2} \ --zone=${CLUSTER_2_ZONE} \ --enable-master-authorized-networks \ --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32
모든 클러스터가 실행 중인지 확인합니다.
gcloud container clusters list
출력은 다음과 같이 표시됩니다.
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS gke-central-priv us-central1-a 1.16.15-gke.6000 35.238.99.104 e2-standard-4 1.16.15-gke.6000 3 RUNNING gke-west-priv us-west2-a 1.16.15-gke.6000 34.94.188.180 e2-standard-4 1.16.15-gke.6000 3 RUNNING
두 클러스터 모두에 연결하여 kubeconfig 파일에 항목을 생성합니다.
touch ~/asm-kubeconfig && export KUBECONFIG=~/asm-kubeconfig gcloud container clusters get-credentials ${CLUSTER_1} --zone ${CLUSTER_1_ZONE} gcloud container clusters get-credentials ${CLUSTER_2} --zone ${CLUSTER_2_ZONE}
kubeconfig 파일을 사용하여 각 클러스터에 대해 사용자 및 컨텍스트를 만들어서 클러스터에 인증을 수행합니다. kubeconfig 파일에서 항목을 생성한 후 클러스터 간에 컨텍스트를 빠르게 전환할 수 있습니다.
편의를 위해 클러스터 컨텍스트 이름을 바꿉니다.
kubectl config rename-context \ gke_${PROJECT_ID}_${CLUSTER_1_ZONE}_${CLUSTER_1} ${CLUSTER_1} kubectl config rename-context \ gke_${PROJECT_ID}_${CLUSTER_2_ZONE}_${CLUSTER_2} ${CLUSTER_2}
두 클러스터 컨텍스트의 이름이 올바르게 변경되고 구성되었는지 확인합니다.
kubectl config get-contexts --output="name"
출력은 다음과 같이 표시됩니다.
gke-central-priv gke-west-priv
클러스터를 Fleet에 등록합니다.
gcloud container fleet memberships register ${CLUSTER_1} --gke-cluster=${CLUSTER_1_ZONE}/${CLUSTER_1} --enable-workload-identity gcloud container fleet memberships register ${CLUSTER_2} --gke-cluster=${CLUSTER_2_ZONE}/${CLUSTER_2} --enable-workload-identity
이제 비공개 GKE 클러스터를 만들고 이름을 바꿨습니다.
Cloud Service Mesh 설치
이 섹션에서는 Cloud Service Mesh를 GKE 클러스터 2개에 설치하고 클러스터 간 서비스 검색에 사용할 클러스터를 구성합니다.
Cloud Shell에서
fleet API
를 사용하여 두 클러스터 모두에 Cloud Service Mesh를 설치합니다.gcloud container fleet mesh update --management automatic --memberships ${CLUSTER_1},${CLUSTER_2}
관리형 Cloud Service Mesh가 클러스터에 사용 설정되면 설치할 메시에 감시를 설정합니다.
watch -g "gcloud container fleet mesh describe | grep 'code: REVISION_READY'"
두 클러스터 모두에 Cloud Service Mesh 인그레스 게이트웨이를 설치합니다.
kubectl --context=${CLUSTER_1} create namespace asm-ingress kubectl --context=${CLUSTER_1} label namespace asm-ingress istio-injection=enabled --overwrite kubectl --context=${CLUSTER_2} create namespace asm-ingress kubectl --context=${CLUSTER_2} label namespace asm-ingress istio-injection=enabled --overwrite cat <<'EOF' > asm-ingress.yaml apiVersion: v1 kind: Service metadata: name: asm-ingressgateway namespace: asm-ingress spec: type: LoadBalancer selector: asm: ingressgateway ports: - port: 80 name: http - port: 443 name: https --- apiVersion: apps/v1 kind: Deployment metadata: name: asm-ingressgateway namespace: asm-ingress spec: selector: matchLabels: asm: ingressgateway template: metadata: annotations: # This is required to tell Anthos Service Mesh to inject the gateway with the # required configuration. inject.istio.io/templates: gateway labels: asm: ingressgateway spec: containers: - name: istio-proxy image: auto # The image will automatically update each time the pod starts. --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: asm-ingressgateway-sds namespace: asm-ingress rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: asm-ingressgateway-sds namespace: asm-ingress roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: asm-ingressgateway-sds subjects: - kind: ServiceAccount name: default EOF kubectl --context=${CLUSTER_1} apply -f asm-ingress.yaml kubectl --context=${CLUSTER_2} apply -f asm-ingress.yaml
Cloud Service Mesh 인그레스 게이트웨이가 배포되었는지 확인합니다.
kubectl --context=${CLUSTER_1} get pod,service -n asm-ingress kubectl --context=${CLUSTER_2} get pod,service -n asm-ingress
두 클러스터 모두 출력이 다음과 같이 표시됩니다.
NAME READY STATUS RESTARTS AGE pod/asm-ingressgateway-5894744dbd-zxlgc 1/1 Running 0 84s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/asm-ingressgateway LoadBalancer 10.16.2.131 34.102.100.138 80:30432/TCP,443:30537/TCP 92s
Cloud Service Mesh 컨트롤 플레인과 인그레스 게이트웨이가 두 클러스터 모두에 설치되면 클러스터 간 서비스 검색이 Fleet API에서 사용 설정됩니다. 클러스터 간 서비스 검색은 두 클러스터가 원격 클러스터의 서비스 엔드포인트를 검색할 수 있게 해줍니다. 분산 서비스는 동일한 네임스페이스에 있는 여러 클러스터에서 실행됩니다.
두 Cloud Service Mesh 컨트롤 플레인이 분산 서비스의 모든 엔드포인트를 검색할 수 있도록 하려면 Cloud Service Mesh에 분산 서비스를 실행하는 모든 클러스터에 대한 액세스 권한이 있어야 합니다. 이 예시에서는 2개의 클러스터가 사용되므로, 두 클러스터 모두 서비스 엔드포인트에 대해 원격 클러스터를 쿼리할 수 있어야 합니다. 관리형 Cloud Service Mesh가 Fleet API에서 사용 설정되면 엔드포인트 검색이 자동으로 구성됩니다.
이제 클러스터와 Cloud Service Mesh가 구성됩니다.
Bank of Anthos 애플리케이션 배포
Cloud Shell에서 Bank of Anthos GitHub 저장소를 클론합니다.
git clone https://github.com/GoogleCloudPlatform/bank-of-anthos.git ${HOME}/bank-of-anthos
두 클러스터 모두에서
bank-of-anthos
네임스페이스를 만들고 라벨을 지정합니다. 라벨은 라벨이 지정된 네임스페이스 내에서 모든 포드에 있는 사이드카 Envoy 프록시의 자동 삽입을 허용합니다.# cluster_1 kubectl create --context=${CLUSTER_1} namespace bank-of-anthos kubectl label --context=${CLUSTER_1} namespace bank-of-anthos istio-injection=enabled # cluster_2 kubectl create --context=${CLUSTER_2} namespace bank-of-anthos kubectl label --context=${CLUSTER_2} namespace bank-of-anthos istio-injection=enabled
bank-of-anthos
네임스페이스의 두 클러스터에 Bank of Anthos 애플리케이션을 배포합니다.# The following secret is used for user account creation and authentication kubectl --context=$CLUSTER_1 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/extras/jwt/jwt-secret.yaml kubectl --context=$CLUSTER_2 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/extras/jwt/jwt-secret.yaml # Deploy all manifests to both clusters kubectl --context=$CLUSTER_1 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/kubernetes-manifests kubectl --context=$CLUSTER_2 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/kubernetes-manifests
Kubernetes 서비스는 서비스 검색을 위해 두 클러스터에 모두 있어야 합니다. 클러스터 중 하나의 서비스가 요청을 수행하려고 시도할 때는 먼저 호스트 이름이 IP 주소를 가져오도록 DNS 조회를 수행합니다. GKE에서는 클러스터에서 실행되는
kube-dns
서버가 이 조회를 처리하므로 구성된 서비스 정의가 필요합니다.두 PostgreSQL 데이터베이스가 클러스터 중 하나에만 존재하도록 한 클러스터에서
StatefulSets
를 삭제합니다.# Delete the two DB statefulSets from Cluster2 kubectl --context=$CLUSTER_2 -n bank-of-anthos delete statefulset accounts-db kubectl --context=$CLUSTER_2 -n bank-of-anthos delete statefulset ledger-db
모든 포드가 두 클러스터 모두에서 실행되는지 확인합니다.
cluster_1
에서 포드를 가져옵니다.kubectl --context=${CLUSTER_1} -n bank-of-anthos get pod
출력은 다음과 같이 표시됩니다.
NAME READY STATUS RESTARTS AGE accounts-db-0 2/2 Running 0 9m54s balancereader-c5d664b4c-xmkrr 2/2 Running 0 9m54s contacts-7fd8c5fb6-wg9xn 2/2 Running 1 9m53s frontend-7b7fb9b665-m7cw7 2/2 Running 1 9m53s ledger-db-0 2/2 Running 0 9m53s ledgerwriter-7b5b6db66f-xhbp4 2/2 Running 0 9m53s loadgenerator-7fb54d57f8-g5lz5 2/2 Running 0 9m52s transactionhistory-7fdb998c5f-vqh5w 2/2 Running 1 9m52s userservice-76996974f5-4wlpf 2/2 Running 1 9m52s
cluster_2
에서 포드를 가져옵니다.kubectl --context=${CLUSTER_2} -n bank-of-anthos get pod
출력은 다음과 같이 표시됩니다.
NAME READY STATUS RESTARTS AGE balancereader-c5d664b4c-bn2pl 2/2 Running 0 9m54s contacts-7fd8c5fb6-kv8cp 2/2 Running 0 9m53s frontend-7b7fb9b665-bdpp4 2/2 Running 0 9m53s ledgerwriter-7b5b6db66f-297c2 2/2 Running 0 9m52s loadgenerator-7fb54d57f8-tj44v 2/2 Running 0 9m52s transactionhistory-7fdb998c5f-xvmtn 2/2 Running 0 9m52s userservice-76996974f5-mg7t6 2/2 Running 0 9m51s
Cloud Service Mesh 구성을 두 클러스터 모두에 배포합니다. 이렇게 하면
asm-ingress
네임스페이스에 Gateway,frontend
서비스의bank-of-anthos
네임스페이스에 VirtualService가 생성되며 이를 사용하여 트래픽을frontend
서비스로 인그레스할 수 있습니다.일반적으로 플랫폼 관리자나 네트워크 관리팀에서
Gateways
를 소유합니다. 따라서Gateway
리소스는 플랫폼 관리자가 소유한 Ingress Gateway 네임스페이스에서 생성되며 자체VirtualService
항목을 통해 다른 네임스페이스에서 사용될 수 있습니다. 이는 '공유 게이트웨이' 모델입니다.cat <<'EOF' > asm-vs-gateway.yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: asm-ingressgateway namespace: asm-ingress spec: selector: asm: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: frontend namespace: bank-of-anthos spec: hosts: - "*" gateways: - asm-ingress/asm-ingressgateway http: - route: - destination: host: frontend port: number: 80 EOF kubectl --context=$CLUSTER_1 apply -f asm-vs-gateway.yaml kubectl --context=$CLUSTER_2 apply -f asm-vs-gateway.yaml
이제 2개의 비공개 GKE 클러스터에 Bank of Anthos 애플리케이션이 배포되었습니다. 데이터베이스를 제외하고 모든 서비스가 분산 서비스로 실행됩니다.
분산 서비스 검사
이 섹션에서는 istioctl
도구를 사용하여 프록시의 프록시 구성을 조사합니다. 이를 수행하면 해당 사이드카 프록시에 모든 서비스에 대해 2개의 포드가 표시되고 각 클러스터에서 하나의 포드가 실행되는지 확인할 수 있습니다.
Cloud Shell에서
cluster_1
의frontend
포드에서 프록시 구성 엔드포인트 목록을 검사합니다.export FRONTEND1=$(kubectl get pod -n bank-of-anthos -l app=frontend \ --context=${CLUSTER_1} -o jsonpath='{.items[0].metadata.name}') istioctl proxy-config endpoints \ --context $CLUSTER_1 -n bank-of-anthos $FRONTEND1 | grep bank-of-anthos
출력은 다음과 같이 표시됩니다.
10.12.0.6:5432 HEALTHY OK outbound|5432||accounts-db.bank-of-anthos.svc.cluster.local 10.12.0.7:8080 HEALTHY OK outbound|8080||balancereader.bank-of-anthos.svc.cluster.local 10.12.0.8:8080 HEALTHY OK outbound|8080||transactionhistory.bank-of-anthos.svc.cluster.local 10.12.0.9:8080 HEALTHY OK outbound|8080||userservice.bank-of-anthos.svc.cluster.local 10.12.1.10:8080 HEALTHY OK outbound|8080||ledgerwriter.bank-of-anthos.svc.cluster.local 10.12.1.9:8080 HEALTHY OK outbound|8080||contacts.bank-of-anthos.svc.cluster.local 10.12.2.11:5432 HEALTHY OK outbound|5432||ledger-db.bank-of-anthos.svc.cluster.local 10.12.2.13:8080 HEALTHY OK outbound|80||frontend.bank-of-anthos.svc.cluster.local 10.76.1.10:8080 HEALTHY OK outbound|8080||transactionhistory.bank-of-anthos.svc.cluster.local 10.76.1.8:8080 HEALTHY OK outbound|8080||balancereader.bank-of-anthos.svc.cluster.local 10.76.1.9:8080 HEALTHY OK outbound|80||frontend.bank-of-anthos.svc.cluster.local 10.76.2.10:8080 HEALTHY OK outbound|8080||userservice.bank-of-anthos.svc.cluster.local 10.76.2.8:8080 HEALTHY OK outbound|8080||contacts.bank-of-anthos.svc.cluster.local 10.76.2.9:8080 HEALTHY OK outbound|8080||ledgerwriter.bank-of-anthos.svc.cluster.local
앞의 출력에서 각 분산 서비스에는 2개의 엔드포인트 IP 주소가 포함됩니다. 이것들은 각 클러스터에 대한 하나씩의 포드 IP 주소입니다.
Bank of Anthos 액세스
Bank of Anthos 애플리케이션에 액세스하려면 두 클러스터 모두에서 asm-ingressgateway
서비스 공개 IP 주소를 사용하면 됩니다.
두 클러스터 모두에서
asm-ingressgateway
IP 주소를 가져옵니다.kubectl --context ${CLUSTER_1} \ --namespace asm-ingress get svc asm-ingressgateway -o jsonpath='{.status.loadBalancer}' | grep "ingress" kubectl --context ${CLUSTER_2} \ --namespace asm-ingress get svc asm-ingressgateway -o jsonpath='{.status.loadBalancer}' | grep "ingress"
출력은 다음과 같이 표시됩니다.
{"ingress":[{"ip":"35.236.4.18"}]} {"ingress":[{"ip":"34.68.94.81"}]}
다음 단계에서 사용하도록 IP 주소 중 하나를 복사합니다.
웹브라우저에서 새 탭을 열고 이전 출력의 IP 주소 중 하나로 이동합니다. Bank of Anthos 프런트엔드가 표시되면 로그인하여 계정에 금액을 입금하고 다른 계정으로 자금을 이체할 수 있습니다. 애플리케이션이 완전히 작동해야 합니다.
분산 서비스 시각화
Cloud Service Mesh에서 분산 서비스를 시각화할 수 있습니다.
서비스를 보려면 Google Cloud 콘솔에서 서비스 메시 페이지로 이동합니다.
테이블 뷰 또는 토폴로지 뷰에서 서비스를 볼 수 있습니다. 기본 뷰는 테이블 뷰로, 테이블 형식으로 실행 중인 모든 분산 서비스를 보여줍니다. 뷰를 변경하려면 표시하려는 뷰를 클릭합니다.
테이블 뷰에서
frontend distributed service
를 클릭합니다. 개별 서비스를 클릭하면 연결된 서비스와 함께 서비스의 세부 뷰가 표시됩니다.서비스 세부정보 뷰에서 타임라인 표시를 클릭하여 SLO를 만들고 서비스의 이전 타임라인을 볼 수 있습니다.
골든 신호를 보려면 측면 패널에서 측정항목을 클릭합니다.
초당 요청 수 차트에서 분류 기준을 클릭한 후 위치를 선택합니다.
2개 리전에 있는 두 클러스터 모두의 초당 요청 수가 결과에 표시됩니다. 분산 서비스가 정상이고 두 엔드포인트 모두 트래픽을 제공합니다.
서비스 메시의 토폴로지를 보려면 사이드 패널에서 Anthos Service Mesh를 클릭한 후 토폴로지 뷰를 클릭합니다.
추가 데이터를 보려면
frontend
서비스 위로 마우스 포인터를 가져갑니다. 그러면 프런트엔드에서 다른 서비스로의 초당 요청 수와 같은 정보가 표시됩니다.자세한 내용을 보려면
frontend
서비스에서 확장을 클릭하세요. 서비스 및 워크로드가 표시됩니다. 워크로드를 2개의 배포로 확장하고, 배포를 ReplicaSets로 확장한 후, ReplicaSets를 포드로 확장할 수 있습니다. 모든 요소를 확장하면 기본적으로 서비스 하나와 포드 2개로 구성되는 분산된frontend
서비스를 확인할 수 있습니다.
멀티 클러스터 인그레스 구성
이 섹션에서는 두 클러스터 모두에서 실행되는 Bank of GKE Enterprise frontend
서비스로 트래픽을 전송하는 멀티 클러스터 인그레스를 만듭니다. Cloud Load Balancing을 사용하여 두 클러스터 모두에서 asm-ingressgateway
서비스를 백엔드로 사용하는 부하 분산기를 만듭니다. ingress-config
클러스터는 멀티 클러스터 인그레스 구성을 조정하기 위해 사용됩니다.
부하 분산기를 만들려면 MultiClusterIngress
및 하나 이상의 MultiClusterServices
를 사용합니다. MultiClusterIngress
및 MultiClusterService
객체는 단일 클러스터 컨텍스트에서 사용되는 기존 Kubernetes 인그레스 및 서비스 리소스의 멀티 클러스터 아날로그입니다.
필요한 GKE Enterprise, GKE Fleet, 멀티 클러스터 인그레스 API를 사용 설정합니다.
gcloud services enable \ anthos.googleapis.com \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com
ingress-config
클러스터를 만듭니다. 어떤 클러스터든 사용할 수 있지만 이 용도로 별도의 클러스터를 만드는 것이 좋습니다.gcloud container clusters create ${CLUSTER_INGRESS} \ --zone ${CLUSTER_INGRESS_ZONE} \ --num-nodes=1 \ --enable-ip-alias \ --workload-pool=${WORKLOAD_POOL}
편의를 위해 클러스터 사용자 인증 정보를 가져오고 컨텍스트 이름을 변경합니다.
gcloud container clusters get-credentials ${CLUSTER_INGRESS} \ --zone ${CLUSTER_INGRESS_ZONE} --project ${PROJECT_ID} kubectl config rename-context \ gke_${PROJECT_ID}_${CLUSTER_INGRESS_ZONE}_${CLUSTER_INGRESS} ${CLUSTER_INGRESS}
멀티 클러스터 인그레스를 사용하려면 참여하는 모든 클러스터를 GKE Enterprise Fleet에 구성 클러스터를 포함하여 등록합니다.
구성 클러스터를 등록합니다.
gcloud container fleet memberships register ${CLUSTER_INGRESS} \ --project=${PROJECT_ID} \ --gke-cluster=${CLUSTER_INGRESS_ZONE}/${CLUSTER_INGRESS} \ --enable-workload-identity
모든 클러스터가 GKE Enterprise Fleet에 등록되었는지 확인합니다.
gcloud container fleet memberships list
출력은 다음과 같이 표시됩니다.
NAME EXTERNAL_ID gke-west 7fe5b7ce-50d0-4e64-a9af-55d37b3dd3fa gke-central 6f1f6bb2-a3f6-4e9c-be52-6907d9d258cd gke-ingress 3574ee0f-b7e6-11ea-9787-42010a8a019c
ingress-config
클러스터에서 멀티 클러스터 인그레스 기능을 사용 설정합니다. 이렇게 하면 클러스터에서MulticlusterService
및MulticlusterIngress
CustomResourceDefinition(CRD)이 생성됩니다.gcloud container fleet ingress enable \ --config-membership=projects/${PROJECT_ID}/locations/global/memberships/${CLUSTER_INGRESS}
ingress-config
클러스터에서 멀티 클러스터 인그레스가 사용 설정되어 있는지 확인합니다.gcloud container fleet ingress describe
출력은 다음과 같이 표시됩니다.
membershipStates: projects/986443280307/locations/global/memberships/gke-central-priv: state: code: OK updateTime: '2022-09-29T13:57:02.972748202Z' projects/986443280307/locations/global/memberships/gke-ingress: state: code: OK updateTime: '2022-09-29T13:57:02.972744692Z' projects/986443280307/locations/global/memberships/gke-west-priv: state: code: OK updateTime: '2022-09-29T13:57:02.972746497Z'
두 CRD가
ingress-config
클러스터에 배포되었는지 확인합니다.kubectl --context=${CLUSTER_INGRESS} get crd | grep multicluster
출력은 다음과 같이 표시됩니다.
multiclusteringresses.networking.gke.io 2020-10-29T17:32:50Z multiclusterservices.networking.gke.io 2020-10-29T17:32:50Z
ingress-config
클러스터에asm-ingress
네임스페이스를 만듭니다.kubectl --context ${CLUSTER_INGRESS} create namespace asm-ingress
MultiClusterIngress
리소스 만들기cat <<EOF > ${HOME}/mci.yaml apiVersion: networking.gke.io/v1beta1 kind: MultiClusterIngress metadata: name: asm-ingressgateway-multicluster-ingress spec: template: spec: backend: serviceName: asm-ingressgateway-multicluster-svc servicePort: 80 EOF
MultiClusterService
리소스 만들기cat <<'EOF' > $HOME/mcs.yaml apiVersion: networking.gke.io/v1beta1 kind: MultiClusterService metadata: name: asm-ingressgateway-multicluster-svc annotations: beta.cloud.google.com/backend-config: '{"ports": {"80":"gke-ingress-config"}}' spec: template: spec: selector: asm: ingressgateway ports: - name: frontend protocol: TCP port: 80 # servicePort defined in Multi Cluster Ingress clusters: - link: "us-west2-a/gke-west-priv" - link: "us-central1-a/gke-central-priv" EOF
상태 확인을 위해
BackendConfig
리소스를 만듭니다.cat <<EOF > $HOME/backendconfig.yaml apiVersion: cloud.google.com/v1beta1 kind: BackendConfig metadata: name: gke-ingress-config spec: healthCheck: type: HTTP port: 15021 requestPath: /healthz/ready EOF
BackendConfig
,MultiClusterService
,MultiClusterIngress
매니페스트를 적용합니다.kubectl --context ${CLUSTER_INGRESS} -n asm-ingress apply -f ${HOME}/backendconfig.yaml kubectl --context ${CLUSTER_INGRESS} -n asm-ingress apply -f ${HOME}/mci.yaml kubectl --context ${CLUSTER_INGRESS} -n asm-ingress apply -f ${HOME}/mcs.yaml
인그레스 클러스터에 배포한
MultiClusterService
는 클러스터 1과 클러스터 2에 '헤드리스'Service
를 만듭니다. '헤드리스'Services
가 생성되었는지 확인합니다.kubectl --context=${CLUSTER_1} -n asm-ingress \ get services | grep multicluster-svc kubectl --context=${CLUSTER_2} -n asm-ingress \ get services | grep multicluster-svc
출력은 다음과 비슷합니다.
mci-frontend-multi-cluster-service-svc-f7rcyqry22iq8nmw ClusterIP None <none> 80/TCP 77s mci-frontend-multi-cluster-service-svc-f7rcyqry22iq8nmw ClusterIP None <none> 80/TCP 78s
다음 명령어를 실행하고 Cloud Load Balancing IP 주소가 표시될 때까지 기다립니다.
watch kubectl --context ${CLUSTER_INGRESS} -n asm-ingress get multiclusteringress \ -o jsonpath="{.items[].status.VIP}"
출력은 다음과 같이 표시됩니다.
35.35.23.11
watch 명령어를 종료하려면 Ctrl+C를 누르세요.
웹브라우저에서 Cloud Load Balancing IP 주소로 이동하여 Bank of Anthos의 프런트엔드로 이동합니다.
kubectl --context ${CLUSTER_INGRESS} \ -n asm-ingress get multiclusteringress \ -o jsonpath="{.items[].status.VIP}"
404 오류(또는 502 오류)가 발생하면 몇 분 정도 기다린 후 웹브라우저에서 페이지를 새로고침하세요.
삭제
계정에 요금이 청구되지 않도록 프로젝트를 삭제하거나 클러스터를 삭제합니다.
프로젝트 삭제
청구되지 않도록 하는 가장 쉬운 방법은 튜토리얼에서 만든 프로젝트를 삭제하는 것입니다.
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
클러스터 삭제
Cloud Shell에서
blue
및green
클러스터를 등록 취소하고 삭제합니다.gcloud container fleet memberships unregister ${CLUSTER_1} \ --project=${PROJECT} \ --gke-uri=${CLUSTER_1_URI} gcloud container clusters delete ${CLUSTER_1} \ --zone ${CLUSTER_1_ZONE} \ --quiet gcloud container fleet memberships unregister ${CLUSTER_2} \ --project=${PROJECT} \ --gke-uri=${CLUSTER_2_URI} gcloud container clusters delete ${CLUSTER_2} \ --zone ${CLUSTER_2_ZONE} \ --quiet
인그레스 구성 클러스터에서
MuticlusterIngress
리소스를 삭제합니다.kubectl --context ${CLUSTER_INGRESS} -n istio-system delete -f $HOME/mci.yaml
이는 프로젝트에서 Cloud Load Balancing 리소스를 삭제합니다.
ingress-config
클러스터를 등록 취소하고 삭제합니다.gcloud container fleet memberships unregister ${CLUSTER_INGRESS} \ --project=${PROJECT} \ --gke-uri=${CLUSTER_INGRESS_URI} gcloud container clusters delete ${CLUSTER_INGRESS} \ --zone ${CLUSTER_INGRESS_ZONE} \ --quiet
모든 클러스터가 삭제되었는지 확인합니다.
gcloud container clusters list
출력은 다음과 같습니다.
<null>
kubeconfig
파일을 재설정합니다.unset KUBECONFIG
다음 단계
- 멀티 클러스터 인그레스 자세히 알아보기
- 클러스터에 멀티 클러스터 인그레스를 배포하는 방법 알아보기