1. 알파 워크숍
워크숍 Codelab 링크 bit.ly/asm-workshop
2. 개요
아키텍처 다이어그램

이 워크숍은 프로덕션 환경에서 GCP에 전 세계에 분산된 서비스를 설정하는 방법을 직접 체험해 볼 수 있는 몰입형 환경입니다. 사용되는 주요 기술은 컴퓨팅을 위한 Google Kubernetes Engine (GKE)과 보안 연결, 관측 가능성, 고급 트래픽 셰이핑을 생성하기 위한 Istio 서비스 메시입니다. 이 워크숍에서 사용되는 모든 실습과 도구는 프로덕션에서 사용되는 것과 동일합니다.
주제
- 모듈 0 - 소개 및 플랫폼 설정
- 소개 및 아키텍처
- 서비스 메시 및 Istio/ASM 소개
- 실습: 인프라 설정: 사용자 워크플로
- 휴식 시간
- QnA
- 모듈 1 - ASM으로 애플리케이션 설치, 보안 유지, 모니터링
- 저장소 모델: 인프라 및 Kubernetes 저장소 설명
- 실습: 샘플 애플리케이션 배포
- 분산 서비스 및 관측 가능성
- 점심
- 실습: Stackdriver를 사용한 관측 가능성
- QNA
- 모듈 2 - DevOps - 카나리아 출시, 정책/RBAC
- 멀티 클러스터 서비스 검색 및 보안/정책
- 실습: 상호 TLS
- 카나리아 배포
- 실습: 카나리아 배포
- 보안 멀티 클러스터 전역 부하 분산
- 휴식 시간
- 실습: 승인 정책
- QNA
- 모듈 3 - 인프라 운영 - 플랫폼 업그레이드
- 분산 서비스 빌딩 블록
- 실습: 인프라 확장
- 다음 단계
Slides
이 워크숍의 슬라이드는 다음 링크에서 확인할 수 있습니다.
기본 요건
이 워크숍을 진행하려면 다음이 필요합니다.
- GCP 조직 노드
- 결제 계정 ID (이 결제 계정의 결제 관리자여야 함)
- 사용자의 조직 수준에서 조직 관리자 IAM 역할
3. 인프라 설정 - 관리자 워크플로
부트스트랩 워크숍 스크립트 설명
bootstrap_workshop.sh라는 스크립트는 워크숍의 초기 환경을 설정하는 데 사용됩니다. 이 스크립트를 사용하여 나를 위한 단일 환경을 설정하거나 여러 사용자에게 이 워크숍을 교육으로 제공하는 경우 여러 사용자를 위한 여러 환경을 설정할 수 있습니다.
부트스트랩 워크숍 스크립트에는 다음이 입력으로 필요합니다.
- 조직 이름 (예:
yourcompany.com): 워크숍 환경을 만드는 조직입니다. - 결제 ID (예:
12345-12345-12345) - 이 결제 ID는 워크숍 중에 사용된 모든 리소스에 대한 청구에 사용됩니다. - 워크숍 번호 (예:
01) - 두 자리 숫자입니다. 하루에 여러 워크숍을 진행하고 이를 별도로 추적하려는 경우에 사용됩니다. 워크숍 번호는 프로젝트 ID를 파생하는 데도 사용됩니다. 워크숍 번호를 별도로 사용하면 매번 고유한 프로젝트 ID를 쉽게 확보할 수 있습니다. 프로젝트 ID에는 워크숍 번호 외에도 현재 날짜 (YYMMDD형식)가 사용됩니다. 날짜와 워크숍 번호의 조합은 고유한 프로젝트 ID를 제공합니다. - 시작 사용자 번호 (예:
1) - 이 번호는 워크숍의 첫 번째 사용자를 나타냅니다. 예를 들어 사용자 10명을 위한 워크숍을 만들려면 시작 사용자 번호가 1이고 종료 사용자 번호가 10일 수 있습니다. - 최종 사용자 번호 (예:
10) - 이 번호는 워크숍의 마지막 사용자를 나타냅니다. 예를 들어 사용자 10명을 위한 워크숍을 만들려면 시작 사용자 번호가 1이고 종료 사용자 번호가 10일 수 있습니다. 단일 환경 (예: 자신을 위한 환경)을 설정하는 경우 시작 및 종료 사용자 수를 동일하게 설정하세요. 이렇게 하면 단일 환경이 생성됩니다.
- 관리자 GCS 버킷 (예:
my-gcs-bucket-name) - GCS 버킷은 워크숍 관련 정보를 저장하는 데 사용됩니다. 이 정보는 cleanup_workshop.sh 스크립트가 부트스트랩 워크숍 스크립트 중에 생성된 모든 리소스를 정상적으로 삭제하는 데 사용됩니다. 워크숍을 만드는 관리자에게는 이 버킷에 대한 읽기/쓰기 권한이 있어야 합니다.
부트스트랩 워크숍 스크립트는 위에 제공된 값을 사용하며 setup-terraform-admin-project.sh 스크립트를 호출하는 래퍼 스크립트 역할을 합니다. setup-terraform-admin-project.sh 스크립트는 단일 사용자를 위한 워크숍 환경을 만듭니다.
워크숍 부트스트랩에 필요한 관리자 권한
이 워크숍에는 두 가지 유형의 사용자가 있습니다. 이 워크숍의 리소스를 만들고 삭제하는 ADMIN_USER 두 번째는 워크숍에서 단계를 실행하는 MY_USER입니다. MY_USER는 자체 리소스에만 액세스할 수 있습니다. ADMIN_USER는 모든 사용자 설정에 액세스할 수 있습니다. 자체적으로 이 설정을 만드는 경우 ADMIN_USER와 MY_USER는 동일합니다. 여러 학생을 위해 이 워크숍을 만드는 강사인 경우 ADMIN_USER 및 MY_USER이 다릅니다.
ADMIN_USER에는 다음 조직 수준 권한이 필요합니다.
- 소유자 - 조직의 모든 프로젝트에 대한 프로젝트 소유자 권한입니다.
- 폴더 관리자 - 조직에서 폴더를 만들고 삭제할 수 있습니다. 모든 사용자에게 프로젝트 내 모든 리소스가 포함된 단일 폴더가 제공됩니다.
- 조직 관리자
- 프로젝트 생성자 - 조직에서 프로젝트를 생성할 수 있습니다.
- 프로젝트 삭제자 - 조직의 프로젝트를 삭제할 수 있습니다.
- 프로젝트 IAM 관리자 - 조직의 모든 프로젝트에서 IAM 규칙을 만들 수 있습니다.
이 외에도 ADMIN_USER는 워크숍에 사용되는 결제 ID의 결제 관리자여야 합니다.
워크숍을 수행하는 사용자 스키마 및 권한
조직의 사용자 (본인 제외)를 위해 이 워크숍을 만들 계획이라면 MY_USERs에 대해 특정 사용자 이름 지정 체계를 따라야 합니다. bootstrap_workshop.sh 스크립트 중에 시작 및 종료 사용자 번호를 제공합니다. 이러한 숫자는 다음 사용자 이름을 만드는 데 사용됩니다.
user<3 digit user number>@<organization_name>
예를 들어 시작 사용자 번호가 1이고 종료 사용자 번호가 3인 부트스트랩 워크숍 스크립트를 yourcompany.com이라는 조직에서 실행하면 다음 사용자의 워크숍 환경이 생성됩니다.
user001@yourcompany.comuser002@yourcompany.comuser003@yourcompany.com
이러한 사용자 이름에는 setup_terraform_admin_project.sh 스크립트 중에 생성된 특정 프로젝트에 대한 프로젝트 소유자 역할이 할당됩니다. 부트스트랩 스크립트를 사용할 때는 이 사용자 이름 지정 스키마를 준수해야 합니다. G Suite에서 한 번에 여러 사용자를 추가하는 방법을 참고하세요.
워크숍에 필요한 도구
이 워크숍은 Cloud Shell에서 부트스트랩하도록 설계되었습니다. 이 워크숍에는 다음 도구가 필요합니다.
- gcloud (버전 >= 270)
- kubectl
- sed (Cloud Shell/Linux의 sed와 호환되며 Mac OS와는 호환되지 않음)
- git (최신 버전인지 확인)
sudo apt updatesudo apt install git- jq
- envsubst
- kustomize
나를 위한 워크숍 설정 (단일 사용자 설정)
- Cloud Shell을 열고 아래의 모든 작업을 Cloud Shell에서 실행합니다. 아래 링크를 클릭하세요.
- 원하는 관리자 사용자로 gcloud에 로그인했는지 확인합니다.
gcloud config list
WORKDIR를 만들고 워크숍 저장소를 클론합니다.
mkdir asm-workshop
cd asm-workshop
export WORKDIR=`pwd`
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git asm
- 조직 이름, 결제 ID, 워크숍 번호, 워크숍에 사용할 관리자 GCS 버킷을 정의합니다. 위 섹션에서 워크숍 설정에 필요한 권한을 검토하세요.
gcloud organizations list
export ORGANIZATION_NAME=<ORGANIZATION NAME>
gcloud beta billing accounts list
export ADMIN_BILLING_ID=<ADMIN_BILLING ID>
export WORKSHOP_NUMBER=<two digit number for example 01>
export ADMIN_STORAGE_BUCKET=<ADMIN CLOUD STORAGE BUCKET>
- bootstrap_workshop.sh 스크립트를 실행합니다. 이 스크립트를 완료하는 데 몇 분 정도 걸릴 수 있습니다.
cd asm
./scripts/bootstrap_workshop.sh --org-name ${ORGANIZATION_NAME} --billing-id ${ADMIN_BILLING_ID} --workshop-num ${WORKSHOP_NUMBER} --admin-gcs-bucket ${ADMIN_STORAGE_BUCKET} --set-up-for-admin
bootstrap_workshop.sh 스크립트가 완료되면 조직 내 각 사용자에 대해 GCP 폴더가 생성됩니다. 폴더 내에 Terraform 관리자 프로젝트가 생성됩니다. Terraform 관리 프로젝트는 이 워크숍에 필요한 나머지 GCP 리소스를 만드는 데 사용됩니다. Terraform 관리자 프로젝트에서 필요한 API를 사용 설정합니다. Cloud Build를 사용하여 Terraform 계획을 적용합니다. Cloud Build 서비스 계정에 GCP에서 리소스를 만들 수 있는 적절한 IAM 역할을 부여합니다. 마지막으로 모든 GCP 리소스의 Terraform 상태를 저장할 Google Cloud Storage (GCS) 버킷에 원격 백엔드를 구성합니다.
Terraform 관리 프로젝트에서 Cloud Build 작업을 보려면 Terraform 관리 프로젝트 ID가 필요합니다. 이 값은 asm 디렉터리의 vars/vars.sh 파일에 저장됩니다. 이 디렉터리는 관리자로 워크숍을 직접 설정하는 경우에만 유지됩니다.
- 변수 파일을 소싱하여 환경 변수 설정
echo "export WORKDIR=$WORKDIR" >> $WORKDIR/asm/vars/vars.sh
source $WORKDIR/asm/vars/vars.sh
여러 사용자를 위한 워크숍 설정 (다중 사용자 설정)
- Cloud Shell을 열고 아래의 모든 작업을 Cloud Shell에서 실행합니다. 아래 링크를 클릭하세요.
- 원하는 관리자 사용자로 gcloud에 로그인했는지 확인합니다.
gcloud config list
WORKDIR를 만들고 워크숍 저장소를 클론합니다.
mkdir asm-workshop
cd asm-workshop
export WORKDIR=`pwd`
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git asm
- 조직 이름, 결제 ID, 워크숍 번호, 시작 및 종료 사용자 번호, 워크숍에 사용할 관리 GCS 버킷을 정의합니다. 위 섹션에서 워크숍 설정에 필요한 권한을 검토하세요.
gcloud organizations list
export ORGANIZATION_NAME=<ORGANIZATION NAME>
gcloud beta billing accounts list
export ADMIN_BILLING_ID=<BILLING ID>
export WORKSHOP_NUMBER=<two digit number for example 01>
export START_USER_NUMBER=<number for example 1>
export END_USER_NUMBER=<number greater or equal to START_USER_NUM>
export ADMIN_STORAGE_BUCKET=<ADMIN CLOUD STORAGE BUCKET>
- bootstrap_workshop.sh 스크립트를 실행합니다. 이 스크립트를 완료하는 데 몇 분 정도 걸릴 수 있습니다.
cd asm
./scripts/bootstrap_workshop.sh --org-name ${ORGANIZATION_NAME} --billing-id ${ADMIN_BILLING_ID} --workshop-num ${WORKSHOP_NUMBER} --start-user-num ${START_USER_NUMBER} --end-user-num ${END_USER_NUMBER} --admin-gcs-bucket ${ADMIN_STORAGE_BUCKET}
- 관리자 GCS 버킷에서 workshop.txt 파일을 가져와 Terraform 프로젝트 ID를 검색합니다.
export WORKSHOP_ID="$(date '+%y%m%d')-${WORKSHOP_NUMBER}"
gsutil cp gs://${ADMIN_STORAGE_BUCKET}/${ORGANIZATION_NAME}/${WORKSHOP_ID}/workshop.txt .
4. 실습 설정 및 준비
실습 과정 선택
이 워크숍의 실습은 다음 두 가지 방법 중 하나로 수행할 수 있습니다.
- '빠른 추적 대화형 스크립트' 방식
- '각 안내를 수동으로 복사하여 붙여넣기' 방법
빠른 트랙 스크립트 메서드를 사용하면 각 실습에 대해 하나의 대화형 스크립트를 실행하여 해당 실습의 명령어를 자동으로 실행하여 실습을 안내할 수 있습니다. 명령어는 각 단계와 달성하는 작업에 대한 간결한 설명과 함께 일괄적으로 실행됩니다. 각 배치 후 다음 명령어 배치로 이동하라는 메시지가 표시됩니다. 이렇게 하면 원하는 속도로 실습을 실행할 수 있습니다. 패스트 트랙 스크립트는 멱등성이므로 이러한 스크립트를 여러 번 실행해도 결과는 동일합니다.
패스트 트랙 스크립트는 아래와 같이 모든 실습의 상단에 녹색 상자로 표시됩니다.
복사 후 붙여넣기 방법은 명령에 대한 설명과 함께 개별 명령 블록을 복사 후 붙여넣기하는 기존 방식입니다. 이 메서드는 한 번만 실행해야 합니다. 이 방법으로 명령어를 다시 실행해도 동일한 결과가 나온다고 보장할 수 없습니다.
실습을 수행할 때는 두 가지 방법 중 하나를 선택하세요.
Fast Track 스크립트 설정
사용자 정보 가져오기
이 워크숍은 워크숍 관리자가 만든 임시 사용자 계정 (또는 실습 계정)을 사용하여 진행됩니다. 실습 계정은 워크숍의 모든 프로젝트를 소유합니다. 워크숍 관리자는 워크숍을 수행하는 사용자에게 실습 계정 사용자 인증 정보 (사용자 이름 및 비밀번호)를 제공합니다. 모든 사용자 프로젝트에는 실습 계정의 사용자 이름이 접두사로 붙습니다. 예를 들어 실습 계정 user001@yourcompany.com의 경우 Terraform 관리자 프로젝트 ID는 user001-200131-01-tf-abcde이 됩니다. 나머지 프로젝트도 마찬가지입니다. 각 사용자는 워크숍 관리자가 제공한 실습 계정으로 로그인하고 실습 계정을 사용하여 워크숍을 진행해야 합니다.
- 아래 링크를 클릭하여 Cloud Shell을 엽니다.
- 실험실 계정 사용자 인증 정보로 로그인합니다 (회사 또는 개인 계정으로 로그인하지 않음). 실습 계정은
userXYZ@<workshop_domain>.com와 같습니다.
- 새 계정이므로 Google 서비스 약관에 동의하라는 메시지가 표시됩니다. '수락'을 클릭합니다.
4. 다음 화면에서 체크박스를 선택하여 Google 서비스 약관에 동의하고 Start Cloud Shell을 클릭합니다.

이 단계에서는 GCP 리소스에 액세스하는 데 사용할 수 있는 작은 Linux Debian VM을 프로비저닝합니다. 각 계정에는 Cloud Shell VM이 할당됩니다. 실습 계정으로 로그인하면 실습 계정 사용자 인증 정보를 사용하여 프로비저닝되고 로그인됩니다. Cloud Shell 외에도 코드 편집기가 프로비저닝되어 구성 파일 (Terraform, YAML 등)을 더 쉽게 수정할 수 있습니다. 기본적으로 Cloud Shell 화면은 Cloud Shell 셸 환경 (하단)과 Cloud Code 편집기 (상단)로 분할됩니다.
오른쪽 상단의 연필
및 셸 프롬프트
아이콘을 사용하면 셸과 코드 편집기 간에 전환할 수 있습니다. 중간 구분선 막대를 위 또는 아래로 드래그하여 각 창의 크기를 수동으로 변경할 수도 있습니다. 5. 이 워크숍의 WORKDIR을 만듭니다. WORKDIR은 이 워크숍의 모든 실습을 실행하는 폴더입니다. Cloud Shell에서 다음 명령어를 실행하여 WORKDIR을 만듭니다.
mkdir -p ${HOME}/asm-workshop
cd ${HOME}/asm-workshop
export WORKDIR=`pwd`
- 이 워크숍에 사용할 변수로 실습 계정 사용자를 내보냅니다. 이 계정은 Cloud Shell에 로그인한 계정과 동일합니다.
export MY_USER=<LAB ACCOUNT EMAIL PROVIDED BY THE WORKSHOP ADMIN>
# For example export MY_USER=user001@gcpworkshops.com
- 다음 명령어를 실행하여 WORKDIR 및 MY_USER 변수가 모두 올바르게 설정되었는지 확인합니다.
echo "WORKDIR set to ${WORKDIR}" && echo "MY_USER set to ${MY_USER}"
- 워크숍 저장소를 클론합니다.
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git ${WORKDIR}/asm
5. 인프라 설정 - 사용자 워크플로
목표: 인프라 및 Istio 설치 확인
- 워크숍 도구 설치
- 워크숍 저장소 클론
Infrastructure설치 확인k8s-repo설치 확인- Istio 설치 확인
복사 후 붙여넣기 방법 실습 안내
사용자 정보 가져오기
워크숍을 설정하는 관리자는 사용자에게 사용자 이름과 비밀번호 정보를 제공해야 합니다. 모든 사용자 프로젝트에는 사용자 이름이 접두사로 붙습니다. 예를 들어 사용자 user001@yourcompany.com의 경우 Terraform 관리 프로젝트 ID는 user001-200131-01-tf-abcde이 됩니다. 나머지 프로젝트도 마찬가지입니다. 각 사용자는 자신의 워크숍 환경에만 액세스할 수 있습니다.
워크숍에 필요한 도구
이 워크숍은 Cloud Shell에서 부트스트랩하도록 설계되었습니다. 이 워크숍에는 다음 도구가 필요합니다.
- gcloud (버전 >= 270)
- kubectl
- sed (Cloud Shell/Linux의 sed와 호환되며 Mac OS와는 호환되지 않음)
- git (최신 버전인지 확인)
sudo apt updatesudo apt install git- jq
- envsubst
- kustomize
- pv
Terraform 관리 프로젝트 액세스
bootstrap_workshop.sh 스크립트가 완료되면 조직 내 각 사용자에 대해 GCP 폴더가 생성됩니다. 폴더 내에 Terraform 관리자 프로젝트가 생성됩니다. Terraform 관리 프로젝트는 이 워크숍에 필요한 나머지 GCP 리소스를 만드는 데 사용됩니다. setup-terraform-admin-project.sh 스크립트는 Terraform 관리 프로젝트에서 필요한 API를 사용 설정합니다. Cloud Build는 Terraform 계획을 적용하는 데 사용됩니다. 스크립트를 통해 Cloud Build 서비스 계정에 GCP에서 리소스를 만들 수 있는 적절한 IAM 역할을 부여합니다. 마지막으로 모든 GCP 리소스의 Terraform 상태를 저장하기 위해 Google Cloud Storage (GCS) 버킷에 원격 백엔드가 구성됩니다.
Terraform 관리 프로젝트에서 Cloud Build 작업을 보려면 Terraform 관리 프로젝트 ID가 필요합니다. 이는 부트스트랩 스크립트에 지정된 관리자 GCS 버킷에 저장됩니다. 여러 사용자에 대해 부트스트랩 스크립트를 실행하면 모든 Terraform 관리 프로젝트 ID가 GCS 버킷에 있습니다.
- 아래 링크를 클릭하여 Cloud Shell을 엽니다 (실습 설정 및 준비 섹션에서 아직 열려 있지 않은 경우).
$HOME/bin폴더에 kustomize를 설치하고 (아직 설치하지 않은 경우) $PATH에$HOME/bin폴더를 추가합니다.
mkdir -p $HOME/bin
cd $HOME/bin
curl -s "https://raw.githubusercontent.com/\
kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
cd $HOME
export PATH=$PATH:${HOME}/bin
echo "export PATH=$PATH:$HOME/bin" >> $HOME/.bashrc
- pv를 설치하고 $HOME/bin/pv로 이동합니다.
sudo apt-get update && sudo apt-get -y install pv
sudo mv /usr/bin/pv ${HOME}/bin/pv
- bash 프롬프트를 업데이트합니다.
cp $WORKDIR/asm/scripts/krompt.bash $HOME/.krompt.bash
echo "export PATH=\$PATH:\$HOME/bin" >> $HOME/.asm-workshop.bash
echo "source $HOME/.krompt.bash" >> $HOME/.asm-workshop.bash
alias asm-init='source $HOME/.asm-workshop.bash' >> $HOME/.bashrc
echo "source $HOME/.asm-workshop.bash" >> $HOME/.bashrc
source $HOME/.bashrc
- 원하는 사용자 계정으로 gcloud에 로그인했는지 확인합니다.
echo "Check logged in user output from the next command is $MY_USER"
gcloud config list account --format=json | jq -r .core.account
- 다음 명령어를 실행하여 Terraform 관리 프로젝트 ID를 가져옵니다.
export TF_ADMIN=$(gcloud projects list | grep tf- | awk '{ print $1 }')
echo $TF_ADMIN
- 워크숍과 연결된 모든 리소스는 terraform 관리 프로젝트의 GCS 버킷에 저장된 vars.sh 파일에 변수로 저장됩니다. Terraform 관리 프로젝트의 vars.sh 파일을 가져옵니다.
mkdir $WORKDIR/asm/vars
gsutil cp gs://$TF_ADMIN/vars/vars.sh $WORKDIR/asm/vars/vars.sh
echo "export WORKDIR=$WORKDIR" >> $WORKDIR/asm/vars/vars.sh
- 표시된 링크를 클릭하여 Terraform 관리 프로젝트의 Cloud Build 페이지를 열고 빌드가 완료되었는지 확인합니다.
source $WORKDIR/asm/vars/vars.sh
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_ADMIN}"
Cloud 콘솔에 처음 액세스하는 경우 Google 서비스 약관에 동의합니다.
- 이제 Cloud Build 페이지를 보고 있으므로 왼쪽 탐색에서
History링크를 클릭하고 최신 빌드를 클릭하여 초기 Terraform 적용의 세부정보를 확인합니다. 다음 리소스는 Terraform 스크립트의 일부로 생성됩니다. 위의 아키텍처 다이어그램을 참고할 수도 있습니다.
- 조직에 4개의 GCP 프로젝트가 있습니다. 제공된 결제 계정은 각 프로젝트와 연결됩니다.
- 한 프로젝트는 공유 VPC의
network host project입니다. 이 프로젝트에는 다른 리소스가 생성되지 않습니다. - 한 프로젝트는 Istio 제어 영역 GKE 클러스터에 사용되는
ops project입니다. - 두 프로젝트는 각 서비스에서 작업하는 두 개의 서로 다른 개발팀을 나타냅니다.
ops,dev1,dev2프로젝트 각각에 GKE 클러스터 2개가 생성됩니다.- Kubernetes 매니페스트 파일용 폴더 6개가 포함된 CSR 저장소
k8s-repo가 생성됩니다. GKE 클러스터당 하나의 폴더 이 저장소는 Kubernetes 매니페스트를 GitOps 방식으로 클러스터에 배포하는 데 사용됩니다. k8s-repo의 마스터 브랜치에 커밋이 있을 때마다 각 폴더에서 Kubernetes 매니페스트를 GKE 클러스터에 배포하도록 Cloud Build 트리거가 생성됩니다.
terraform admin project에서 빌드가 완료되면 운영 프로젝트에서 다른 빌드가 시작됩니다. 표시된 링크를 클릭하여ops project의 Cloud Build 페이지를 열고 k8s-repo Cloud Build가 성공적으로 완료되었는지 확인합니다.
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
설치 확인
- 모든 클러스터의 kubeconfig 파일을 만듭니다. 다음 스크립트를 실행합니다.
$WORKDIR/asm/scripts/setup-gke-vars-kubeconfig.sh
이 스크립트는 gke 폴더에 kubemesh라는 새 kubeconfig 파일을 만듭니다.
KUBECONFIG변수가 새 kubeconfig 파일을 가리키도록 변경합니다.
source $WORKDIR/asm/vars/vars.sh
export KUBECONFIG=$WORKDIR/asm/gke/kubemesh
- Cloud Shell이 다시 시작될 때마다 소싱되도록 Cloud Shell의.bashrc에 vars .sh 및 KUBECONFIG 변수를 추가합니다.
echo "source ${WORKDIR}/asm/vars/vars.sh" >> $HOME/.bashrc
echo "export KUBECONFIG=${WORKDIR}/asm/gke/kubemesh" >> $HOME/.bashrc
- 클러스터 컨텍스트를 나열합니다. 6개의 클러스터가 표시됩니다.
kubectl config view -ojson | jq -r '.clusters[].name'
`Output (do not copy)`
gke_tf05-01-ops_us-central1_gke-asm-2-r2-prod gke_tf05-01-ops_us-west1_gke-asm-1-r1-prod gke_tf05-02-dev1_us-west1-a_gke-1-apps-r1a-prod gke_tf05-02-dev1_us-west1-b_gke-2-apps-r1b-prod gke_tf05-03-dev2_us-central1-a_gke-3-apps-r2a-prod gke_tf05-03-dev2_us-central1-b_gke-4-apps-r2b-prod
Istio 설치 확인
- 모든 포드가 실행 중이고 작업이 완료되었는지 확인하여 두 클러스터에 Istio가 설치되어 있는지 확인합니다.
kubectl --context ${OPS_GKE_1} get pods -n istio-system
kubectl --context ${OPS_GKE_2} get pods -n istio-system
`Output (do not copy)`
NAME READY STATUS RESTARTS AGE grafana-5f798469fd-z9f98 1/1 Running 0 6m21s istio-citadel-568747d88-qdw64 1/1 Running 0 6m26s istio-egressgateway-8f454cf58-ckw7n 1/1 Running 0 6m25s istio-galley-6b9495645d-m996v 2/2 Running 0 6m25s istio-ingressgateway-5df799fdbd-8nqhj 1/1 Running 0 2m57s istio-pilot-67fd786f65-nwmcb 2/2 Running 0 6m24s istio-policy-74cf89cb66-4wrpl 2/2 Running 1 6m25s istio-sidecar-injector-759bf6b4bc-mw4vf 1/1 Running 0 6m25s istio-telemetry-77b6dfb4ff-zqxzz 2/2 Running 1 6m24s istio-tracing-cd67ddf8-n4d7k 1/1 Running 0 6m25s istiocoredns-5f7546c6f4-g7b5c 2/2 Running 0 6m39s kiali-7964898d8c-5twln 1/1 Running 0 6m23s prometheus-586d4445c7-xhn8d 1/1 Running 0 6m25s
`Output (do not copy)`
NAME READY STATUS RESTARTS AGE grafana-5f798469fd-2s8k4 1/1 Running 0 59m istio-citadel-568747d88-87kdj 1/1 Running 0 59m istio-egressgateway-8f454cf58-zj9fs 1/1 Running 0 60m istio-galley-6b9495645d-qfdr6 2/2 Running 0 59m istio-ingressgateway-5df799fdbd-2c9rc 1/1 Running 0 60m istio-pilot-67fd786f65-nzhx4 2/2 Running 0 59m istio-policy-74cf89cb66-4bc7f 2/2 Running 3 59m istio-sidecar-injector-759bf6b4bc-grk24 1/1 Running 0 59m istio-telemetry-77b6dfb4ff-6zr94 2/2 Running 4 60m istio-tracing-cd67ddf8-grs9g 1/1 Running 0 60m istiocoredns-5f7546c6f4-gxd66 2/2 Running 0 60m kiali-7964898d8c-nhn52 1/1 Running 0 59m prometheus-586d4445c7-xr44v 1/1 Running 0 59m
- 두
dev1클러스터 모두에 Istio가 설치되어 있는지 확인합니다. Citadel, sidecar-injector, coredns만dev1클러스터에서 실행됩니다. ops-1 클러스터에서 실행되는 Istio 제어 영역을 공유합니다.
kubectl --context ${DEV1_GKE_1} get pods -n istio-system
kubectl --context ${DEV1_GKE_2} get pods -n istio-system
- 두
dev2클러스터 모두에 Istio가 설치되어 있는지 확인합니다. Citadel, sidecar-injector, coredns만dev2클러스터에서 실행됩니다. ops-2 클러스터에서 실행되는 Istio 제어 영역을 공유합니다.
kubectl --context ${DEV2_GKE_1} get pods -n istio-system
kubectl --context ${DEV2_GKE_2} get pods -n istio-system
`Output (do not copy)`
NAME READY STATUS RESTARTS AGE istio-citadel-568747d88-4lj9b 1/1 Running 0 66s istio-sidecar-injector-759bf6b4bc-ks5br 1/1 Running 0 66s istiocoredns-5f7546c6f4-qbsqm 2/2 Running 0 78s
공유 컨트롤 플레인의 서비스 검색 확인
- 필요한 경우 보안 비밀이 배포되었는지 확인합니다.
kubectl --context ${OPS_GKE_1} get secrets -l istio/multiCluster=true -n istio-system
kubectl --context ${OPS_GKE_2} get secrets -l istio/multiCluster=true -n istio-system
`Output (do not copy)`
For OPS_GKE_1: NAME TYPE DATA AGE gke-1-apps-r1a-prod Opaque 1 8m7s gke-2-apps-r1b-prod Opaque 1 8m7s gke-3-apps-r2a-prod Opaque 1 44s gke-4-apps-r2b-prod Opaque 1 43s For OPS_GKE_2: NAME TYPE DATA AGE gke-1-apps-r1a-prod Opaque 1 40s gke-2-apps-r1b-prod Opaque 1 40s gke-3-apps-r2a-prod Opaque 1 8m4s gke-4-apps-r2b-prod Opaque 1 8m4s
이 워크숍에서는 모든 GKE 클러스터가 생성되는 단일 공유 VPC를 사용합니다. 클러스터 간에 서비스를 검색하려면 ops 클러스터에서 보안 비밀로 생성된 kubeconfig 파일 (각 애플리케이션 클러스터용)을 사용합니다. Pilot은 이러한 보안 비밀을 사용하여 애플리케이션 클러스터의 Kube API 서버 (위의 보안 비밀을 통해 인증됨)를 쿼리하여 서비스를 검색합니다. kubeconfig로 생성된 보안 비밀을 사용하여 두 운영 클러스터 모두 모든 앱 클러스터에 인증할 수 있습니다. 운영 클러스터는 kubeconfig 파일을 보안 비밀 메서드로 사용하여 서비스를 자동으로 검색할 수 있습니다. 이를 위해서는 운영 클러스터의 Pilot이 다른 모든 클러스터의 Kube API 서버에 액세스할 수 있어야 합니다. Pilot이 Kube API 서버에 연결할 수 없는 경우 원격 서비스를 ServiceEntries로 수동으로 추가합니다. ServiceEntry는 서비스 레지스트리의 DNS 항목으로 생각할 수 있습니다. ServiceEntry는 정규화된 DNS 이름 ( FQDN)과 연결할 수 있는 IP 주소를 사용하여 서비스를 정의합니다. 자세한 내용은 Istio 멀티 클러스터 문서를 참고하세요.
6. 인프라 저장소 설명
인프라 Cloud Build
워크숍의 GCP 리소스는 Cloud Build와 infrastructure CSR 저장소를 사용하여 빌드됩니다. 로컬 터미널에서 부트스트랩 스크립트 (scripts/bootstrap_workshop.sh에 있음)를 실행했습니다. 부트스트랩 스크립트는 GCP 폴더, Terraform 관리 프로젝트, Cloud Build 서비스 계정에 적절한 IAM 권한을 만듭니다. Terraform 관리 프로젝트는 Terraform 상태, 로그, 기타 스크립트를 저장하는 데 사용됩니다. 여기에는 infrastructure 및 k8s_repo CSR 저장소가 포함됩니다. 이러한 저장소는 다음 섹션에서 자세히 설명합니다. 다른 워크숍 리소스는 Terraform 관리 프로젝트에 빌드되지 않습니다. Terraform 관리 프로젝트의 Cloud Build 서비스 계정은 워크숍의 리소스를 빌드하는 데 사용됩니다.
infrastructure 폴더에 있는 cloudbuild.yaml 파일은 워크숍의 GCP 리소스를 빌드하는 데 사용됩니다. GCP 리소스를 만드는 데 필요한 모든 도구가 포함된 맞춤 빌더 이미지를 만듭니다. 이러한 도구에는 gcloud SDK, Terraform, 기타 유틸리티(예: Python, Git, jq)가 포함됩니다. 맞춤 빌더 이미지는 각 리소스에 대해 terraform plan 및 apply를 실행합니다. 각 리소스의 Terraform 파일은 별도의 폴더에 있습니다 (자세한 내용은 다음 섹션 참고). 리소스는 일반적으로 빌드되는 순서대로 한 번에 하나씩 빌드됩니다 (예: GCP 프로젝트는 프로젝트에서 리소스가 생성되기 전에 빌드됨). 자세한 내용은 cloudbuild.yaml 파일을 참고하세요.
infrastructure 저장소에 커밋이 있을 때마다 Cloud Build가 트리거됩니다. 인프라에 적용된 모든 변경사항은 코드형 인프라 (IaC)로 저장되고 저장소에 커밋됩니다. 워크숍의 상태는 항상 이 저장소에 저장됩니다.
폴더 구조 - 팀, 환경, 리소스
인프라 저장소는 워크숍의 GCP 인프라 리소스를 설정합니다. 폴더와 하위 폴더로 구성되어 있습니다. 저장소 내의 기본 폴더는 특정 GCP 리소스를 소유하는 team를 나타냅니다. 다음 폴더 계층은 팀의 특정 environment (예: dev, stage, prod)를 나타냅니다. 환경 내의 다음 폴더 계층은 특정 resource (예: host_project, gke_clusters 등)를 나타냅니다. 필요한 스크립트와 Terraform 파일은 리소스 폴더 내에 있습니다.

이 워크숍에는 다음과 같은 네 가지 유형의 팀이 참여합니다.
- infrastructure - 클라우드 인프라팀을 나타냅니다. 이 팀은 다른 모든 팀의 GCP 리소스를 만드는 일을 담당합니다. 리소스에 Terraform 관리 프로젝트를 사용합니다. 인프라 저장소 자체는 Terraform 관리 프로젝트에 있으며 Terraform 상태 파일도 마찬가지입니다 (아래 설명 참고). 이러한 리소스는 부트스트랩 프로세스 중에 bash 스크립트에 의해 생성됩니다 (자세한 내용은 모듈 0 - 관리자 워크플로 참고).
- network - 네트워킹팀을 나타냅니다. VPC 및 네트워킹 리소스를 담당합니다. 다음 GCP 리소스를 소유합니다.
host project- 공유 VPC 호스트 프로젝트를 나타냅니다.shared VPC- 공유 VPC, 서브넷, 보조 IP 범위, 경로, 방화벽 규칙을 나타냅니다.- ops - 운영/DevOps팀을 나타냅니다. 다음 리소스를 소유합니다.
ops project- 모든 ops 리소스의 프로젝트를 나타냅니다.gke clusters- 리전당 ops GKE 클러스터 Istio 컨트롤 플레인은 각 ops GKE 클러스터에 설치됩니다.k8s-repo- 모든 GKE 클러스터의 GKE 매니페스트가 포함된 CSR 저장소입니다.- apps - 애플리케이션 팀을 나타냅니다. 이 워크숍에서는
app1및app2라는 두 팀을 시뮬레이션합니다. 다음 리소스를 소유합니다. app projects- 모든 앱 팀에 자체 프로젝트 세트가 제공됩니다. 이를 통해 특정 프로젝트의 결제 및 IAM을 제어할 수 있습니다.gke clusters- 애플리케이션 컨테이너/포드가 실행되는 애플리케이션 클러스터입니다.gce instances- 선택사항으로, GCE 인스턴스에서 실행되는 애플리케이션이 있는 경우 이 워크숍에서 app1에는 애플리케이션의 일부가 실행되는 GCE 인스턴스가 몇 개 있습니다.
이 워크숍에서는 동일한 앱 (Hipster Shop 앱)이 app1과 app2를 모두 나타냅니다.
제공자, 상태, 출력 - 백엔드 및 공유 상태
google 및 google-beta 제공자는 gcp/[environment]/gcp/provider.tf에 있습니다. provider.tf 파일은 모든 리소스 폴더에서 symlinked됩니다. 이렇게 하면 각 리소스의 제공업체를 개별적으로 관리하는 대신 한곳에서 제공업체를 변경할 수 있습니다.
모든 리소스에는 리소스의 tfstate 파일 위치를 정의하는 backend.tf 파일이 포함되어 있습니다. 이 backend.tf 파일은 스크립트 (scripts/setup_terraform_admin_project에 있음)를 사용하여 템플릿 (templates/backend.tf_tmpl에 있음)에서 생성된 후 해당 리소스 폴더에 배치됩니다. Google Cloud Storage (GCS) 버킷은 백엔드에 사용됩니다. GCS 버킷 폴더 이름이 리소스 이름과 일치합니다. 모든 리소스 백엔드는 Terraform 관리자 프로젝트에 있습니다.
상호 종속 값이 있는 리소스에는 output.tf 파일이 포함됩니다. 필요한 출력 값은 특정 리소스의 백엔드에 정의된 tfstate 파일에 저장됩니다. 예를 들어 프로젝트에서 GKE 클러스터를 만들려면 프로젝트 ID를 알아야 합니다. 프로젝트 ID는 GKE 클러스터 리소스의 terraform_remote_state 데이터 소스를 통해 사용할 수 있는 tfstate 파일에 output.tf를 통해 출력됩니다.
shared_state 파일은 리소스의 tfstate 파일을 가리키는 terraform_remote_state 데이터 소스입니다. 다른 리소스의 출력이 필요한 리소스 폴더에 shared_state_[resource_name].tf 파일이 있습니다. 예를 들어 ops_gke 리소스 폴더에는 ops_project 및 shared_vpc 리소스의 shared_state 파일이 있습니다. ops 프로젝트에서 GKE 클러스터를 만들려면 프로젝트 ID와 VPC 세부정보가 필요하기 때문입니다. shared_state 파일은 스크립트 (scripts/setup_terraform_admin_project에 있음)를 사용하여 템플릿 (templates/shared_state.tf_tmpl에 있음)에서 생성됩니다. 모든 리소스의 shared_state 파일은 gcp/[environment]/shared_states 폴더에 배치됩니다. 필수 shared_state 파일은 각 리소스 폴더에 심볼릭 링크되어 있습니다. 모든 shared_state 파일을 하나의 폴더에 배치하고 적절한 리소스 폴더에 심볼릭 링크하면 한곳에서 모든 상태 파일을 쉽게 관리할 수 있습니다.
변수
모든 리소스 값은 환경 변수로 저장됩니다. 이러한 변수는 terraform 관리 프로젝트의 GCS 버킷에 있는 vars.sh이라는 파일에 내보내기 문으로 저장됩니다. 여기에는 조직 ID, 결제 계정, 프로젝트 ID, GKE 클러스터 세부정보 등이 포함됩니다. 터미널에서 vars.sh을 다운로드하고 소싱하여 설정 값을 가져올 수 있습니다.
Terraform 변수는 vars.sh에 TF_VAR_[variable name]로 저장됩니다. 이러한 변수는 각 리소스 폴더에서 variables.tfvars 파일을 생성하는 데 사용됩니다. variables.tfvars 파일에는 모든 변수와 값이 포함되어 있습니다. variables.tfvars 파일은 스크립트 (scripts/setup_terraform_admin_project에 있음)를 사용하여 동일한 폴더의 템플릿 파일에서 생성됩니다.
K8s 저장소 설명
k8s_repo는 Terraform 관리 프로젝트에 있는 CSR 저장소 (인프라 저장소와 별도)입니다. 모든 GKE 클러스터에 GKE 매니페스트를 저장하고 적용하는 데 사용됩니다. k8s_repo는 인프라 Cloud Build에 의해 생성됩니다 (자세한 내용은 이전 섹션 참고). 초기 인프라 Cloud Build 프로세스 중에 총 6개의 GKE 클러스터가 생성됩니다. k8s_repo에 6개의 폴더가 생성됩니다. 각 폴더 (GKE 클러스터 이름과 일치하는 이름)는 각 리소스 매니페스트 파일을 포함하는 GKE 클러스터에 해당합니다. 인프라를 빌드하는 것과 마찬가지로 Cloud Build는 k8s_repo를 사용하여 모든 GKE 클러스터에 Kubernetes 매니페스트를 적용하는 데 사용됩니다. k8s_repo 저장소에 커밋이 있을 때마다 Cloud Build가 트리거됩니다. 인프라와 마찬가지로 모든 Kubernetes 매니페스트는 k8s_repo 저장소에 코드로 저장되고 각 GKE 클러스터의 상태는 항상 해당 폴더에 저장됩니다.
초기 인프라 빌드의 일부로 k8s_repo가 생성되고 모든 클러스터에 Istio가 설치됩니다.
프로젝트, GKE 클러스터, 네임스페이스
이 워크숍의 리소스는 여러 GCP 프로젝트로 나뉩니다. 프로젝트는 회사의 조직 (또는 팀) 구조와 일치해야 합니다. 서로 다른 프로젝트/제품/리소스를 담당하는 팀 (조직 내)에서 서로 다른 GCP 프로젝트를 사용합니다. 별도의 프로젝트를 사용하면 별도의 IAM 권한 집합을 만들고 프로젝트 수준에서 결제를 관리할 수 있습니다. 또한 할당량은 프로젝트 수준에서도 관리됩니다.
이 워크숍에는 5개 팀이 참여하며 각 팀은 자체 프로젝트를 보유하고 있습니다.
- GCP 리소스를 빌드하는 인프라팀은
Terraform admin project를 사용합니다. 이 팀은 CSR 저장소 (infrastructure)에서 코드형 인프라를 관리하고 GCP에서 빌드된 리소스와 관련된 모든 Terraform 상태 정보를 GCS 버킷에 저장합니다. CSR 저장소 및 Terraform 상태 GCS 버킷에 대한 액세스를 제어합니다. - 공유 VPC를 빌드하는 네트워크팀은
host project를 사용합니다. 이 프로젝트에는 VPC, 서브넷, 경로, 방화벽 규칙이 포함되어 있습니다. 공유 VPC를 사용하면 GCP 리소스의 네트워킹을 중앙에서 관리할 수 있습니다. 모든 프로젝트가 네트워킹에 이 단일 공유 VPC를 사용했습니다. - GKE 클러스터와 ASM/Istio 컨트롤 플레인을 빌드하는 운영/플랫폼팀은
ops project를 사용합니다. GKE 클러스터와 서비스 메시의 수명 주기를 관리합니다. 이들은 클러스터를 강화하고 Kubernetes 플랫폼의 복원력과 확장성을 관리합니다. 이 워크숍에서는 Kubernetes에 리소스를 배포하는 gitops 방법을 사용합니다. CSR 저장소 (k8s_repo라고 함)가 ops 프로젝트에 있습니다. - 마지막으로 애플리케이션을 빌드하는 dev1 및 dev2팀 (두 개발팀을 나타냄)은 자체
dev1및dev2 projects를 사용합니다. 고객에게 제공하는 애플리케이션 및 서비스입니다. 이는 운영팀이 관리하는 플랫폼을 기반으로 빌드됩니다. 리소스 (배포, 서비스 등)가k8s_repo에 푸시되고 적절한 클러스터에 배포됩니다. 이 워크숍에서는 CI/CD 권장사항과 도구에 중점을 두지 않습니다. Cloud Build를 사용하여 Kubernetes 리소스를 GKE 클러스터에 직접 배포하는 작업을 자동화합니다. 실제 프로덕션 시나리오에서는 적절한 CI/CD 솔루션을 사용하여 GKE 클러스터에 애플리케이션을 배포합니다.
이 워크숍에는 두 가지 유형의 GKE 클러스터가 있습니다.
- 운영 클러스터 - 운영팀이 DevOps 도구를 실행하는 데 사용됩니다. 이 워크숍에서는 ASM/Istio 컨트롤 플레인을 실행하여 서비스 메시를 관리합니다.
- 애플리케이션 (앱) 클러스터 - 개발팀에서 애플리케이션을 실행하는 데 사용됩니다. 이 워크숍에서는 Hipster Shop 앱을 사용합니다.
애플리케이션을 실행하는 클러스터에서 운영/관리 도구를 분리하면 각 리소스의 수명 주기를 독립적으로 관리할 수 있습니다. 또한 두 유형의 클러스터는 이를 사용하는 팀/제품과 관련된 서로 다른 프로젝트에 있으므로 IAM 권한을 더 쉽게 관리할 수 있습니다.
총 6개의 GKE 클러스터가 있습니다. 운영 프로젝트에 두 개의 리전 운영 클러스터가 생성됩니다. ASM/Istio 제어 영역이 두 ops 클러스터에 모두 설치되어 있습니다. 각 ops 클러스터는 서로 다른 리전에 있습니다. 또한 4개의 영역 애플리케이션 클러스터가 있습니다. 이러한 리소스는 자체 프로젝트에서 생성됩니다. 이 워크숍에서는 각자 자체 프로젝트를 보유한 두 개발팀을 시뮬레이션합니다. 각 프로젝트에는 앱 클러스터가 두 개 포함됩니다. 앱 클러스터는 서로 다른 영역에 있는 영역 클러스터입니다. 4개의 앱 클러스터는 2개의 리전과 4개의 영역에 있습니다. 이렇게 하면 리전 및 영역 중복이 제공됩니다.
이 워크숍에서 사용되는 애플리케이션인 Hipster Shop 앱은 4개의 앱 클러스터 모두에 배포됩니다. 각 마이크로서비스는 모든 앱 클러스터의 자체 네임스페이스에 있습니다. Hipster Shop 앱 배포 (포드)가 ops 클러스터에 배포되지 않습니다. 하지만 모든 마이크로서비스의 네임스페이스와 서비스 리소스도 ops 클러스터에 생성됩니다. ASM/Istio 제어 영역은 서비스 검색에 Kubernetes 서비스 레지스트리를 사용합니다. 운영 클러스터에 서비스가 없으면 앱 클러스터에서 실행되는 각 서비스에 대해 ServiceEntry를 수동으로 만들어야 합니다.
이 워크숍에서는 10등급 마이크로서비스 애플리케이션을 배포합니다. 이 애플리케이션은 웹 기반 전자상거래 앱인 'Hipster Shop'이며, 사용자는 이 앱에서 상품을 둘러보고 장바구니에 추가하고 구매할 수 있습니다.
Kubernetes 매니페스트 및 k8s_repo
k8s_repo를 사용하여 모든 GKE 클러스터에 Kubernetes 리소스를 추가합니다. Kubernetes 매니페스트를 복사하고 k8s_repo에 커밋하면 됩니다. k8s_repo에 대한 모든 커밋은 Kubernetes 매니페스트를 해당 클러스터에 배포하는 Cloud Build 작업을 트리거합니다. 각 클러스터의 매니페스트는 클러스터 이름과 동일한 이름의 별도 폴더에 있습니다.
6개의 클러스터 이름은 다음과 같습니다.
- gke-asm-1-r1-prod - 리전 1의 리전 작업 클러스터
- gke-asm-2-r2-prod - 리전 2의 리전별 ops 클러스터
- gke-1-apps-r1a-prod - 리전 1 영역 a의 앱 클러스터
- gke-2-apps-r1b-prod - 리전 1 영역 b의 앱 클러스터
- gke-3-apps-r2a-prod - region 2 zone a의 앱 클러스터
- gke-4-apps-r2b-prod - 리전 2 영역 b의 앱 클러스터
k8s_repo에는 이러한 클러스터에 해당하는 폴더가 있습니다. 이러한 폴더에 배치된 매니페스트는 해당 GKE 클러스터에 적용됩니다. 각 클러스터의 매니페스트는 관리의 용이성을 위해 클러스터의 기본 폴더 내에 있는 하위 폴더에 배치됩니다. 이 워크숍에서는 Kustomize를 사용하여 배포되는 리소스를 추적합니다. 자세한 내용은 Kustomize 공식 문서를 참고하세요.
7. 샘플 앱 배포
목표: 앱 클러스터에 Hipster Shop 앱 배포
k8s-repo복사- Hipster Shop 매니페스트를 모든 앱 클러스터에 복사
- 운영 클러스터에서 Hipster Shop 앱의 서비스 만들기
- 운영 클러스터에서
loadgenerators을 설정하여 전역 연결 테스트 - Hipster Shop 앱에 대한 보안 연결 확인
복사 후 붙여넣기 방법 실습 안내
운영 프로젝트 소스 저장소 클론
초기 Terraform 인프라 빌드의 일부로 k8s-repo가 이미 ops 프로젝트에 생성되어 있습니다.
- Git 저장소의 빈 디렉터리를 만듭니다.
mkdir $WORKDIR/k8s-repo
- Git 저장소를 초기화하고 원격을 추가하고 원격 저장소에서 마스터를 가져옵니다.
cd $WORKDIR/k8s-repo
git init && git remote add origin \
https://source.developers.google.com/p/$TF_VAR_ops_project_name/r/k8s-repo
- 로컬 git 로컬 구성을 설정합니다.
git config --local user.email $MY_USER
git config --local user.name "K8s repo user"
git config --local \
credential.'https://source.developers.google.com'.helper gcloud.sh
git pull origin master
매니페스트 복사, 커밋, 푸시
- Hipster Shop 네임스페이스와 서비스를 모든 클러스터의 소스 저장소에 복사합니다.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app/.
- 앱 폴더 kustomization.yaml을 모든 클러스터에 복사합니다.
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app/
- Hipster Shop 배포, RBAC, PodSecurityPolicy를 앱 클러스터의 소스 저장소에 복사합니다.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/deployments \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/deployments \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/deployments \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/deployments \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/rbac \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/rbac \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/rbac \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/rbac \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/podsecuritypolicies \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/podsecuritypolicies \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/podsecuritypolicies \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/podsecuritypolicies \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/
- 하나의 개발 클러스터를 제외한 모든 클러스터에서 cartservice 배포, rbac, podsecuritypolicy를 삭제합니다. Hipstershop은 멀티 클러스터 배포를 위해 빌드되지 않았으므로 일관되지 않은 결과를 방지하기 위해 하나의 cartservice만 사용합니다.
rm $WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/deployments/app-cart-service.yaml
rm $WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/podsecuritypolicies/cart-psp.yaml
rm $WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/rbac/cart-rbac.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/deployments/app-cart-service.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/podsecuritypolicies/cart-psp.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/rbac/cart-rbac.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/deployments/app-cart-service.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/podsecuritypolicies/cart-psp.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/rbac/cart-rbac.yaml
- 첫 번째 개발 클러스터의 kustomization.yaml에 cartservice 배포, rbac, podsecuritypolicy를 추가합니다.
cd ${WORKDIR}/k8s-repo/${DEV1_GKE_1_CLUSTER}/app
cd deployments && kustomize edit add resource app-cart-service.yaml
cd ../podsecuritypolicies && kustomize edit add resource cart-psp.yaml
cd ../rbac && kustomize edit add resource cart-rbac.yaml
cd ${WORKDIR}/asm
- ops 클러스터 kustomization.yaml에서 podsecuritypolicies, deployments, rbac 디렉터리 삭제
sed -i -e '/- deployments\//d' -e '/- podsecuritypolicies\//d' \
-e '/- rbac\//d' \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app/kustomization.yaml
sed -i -e '/- deployments\//d' -e '/- podsecuritypolicies\//d' \
-e '/- rbac\//d' \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app/kustomization.yaml
- RBAC 매니페스트에서 PROJECT_ID를 바꿉니다.
sed -i 's/\${PROJECT_ID}/'${TF_VAR_dev1_project_name}'/g' \
${WORKDIR}/k8s-repo/${DEV1_GKE_1_CLUSTER}/app/rbac/*
sed -i 's/\${PROJECT_ID}/'${TF_VAR_dev1_project_name}'/g' \
${WORKDIR}/k8s-repo/${DEV1_GKE_2_CLUSTER}/app/rbac/*
sed -i 's/\${PROJECT_ID}/'${TF_VAR_dev2_project_name}'/g' \
${WORKDIR}/k8s-repo/${DEV2_GKE_1_CLUSTER}/app/rbac/*
sed -i 's/\${PROJECT_ID}/'${TF_VAR_dev2_project_name}'/g' \
${WORKDIR}/k8s-repo/${DEV2_GKE_2_CLUSTER}/app/rbac/*
- IngressGateway 및 VirtualService 매니페스트를 ops 클러스터의 소스 저장소에 복사합니다.
cp -r $WORKDIR/asm/k8s_manifests/prod/app-ingress/* \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-ingress/
cp -r $WORKDIR/asm/k8s_manifests/prod/app-ingress/* \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-ingress/
- Config Connector 리소스를 각 프로젝트의 클러스터 중 하나에 복사합니다.
cp -r $WORKDIR/asm/k8s_manifests/prod/app-cnrm/* \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-cnrm/
cp -r $WORKDIR/asm/k8s_manifests/prod/app-cnrm/* \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app-cnrm/
cp -r $WORKDIR/asm/k8s_manifests/prod/app-cnrm/* \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app-cnrm/
- Config Connector 매니페스트에서 PROJECT_ID를 바꿉니다.
sed -i 's/${PROJECT_ID}/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-cnrm/*
sed -i 's/${PROJECT_ID}/'$TF_VAR_dev1_project_name'/g' \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app-cnrm/*
sed -i 's/${PROJECT_ID}/'$TF_VAR_dev2_project_name'/g' \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app-cnrm/*
loadgenerator매니페스트 (배포, PodSecurityPolicy, RBAC)를 ops 클러스터에 복사합니다. Hipster Shop 앱은 전역 Google Cloud 부하 분산기 (GCLB)를 사용하여 노출됩니다. GCLB는 클라이언트 트래픽 (frontend로 향함)을 수신하여 서비스의 가장 가까운 인스턴스로 전송합니다. 두 운영 클러스터에loadgenerator를 배치하면 운영 클러스터에서 실행되는 두 Istio 인그레스 게이트웨이로 트래픽이 전송됩니다. 부하 분산은 다음 섹션에서 자세히 설명합니다.
cp -r $WORKDIR/asm/k8s_manifests/prod/app-loadgenerator/. \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-loadgenerator/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app-loadgenerator/. \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-loadgenerator/.
- 두 운영 클러스터의
loadgenerator매니페스트에서 운영 프로젝트 ID를 바꿉니다.
sed -i 's/OPS_PROJECT_ID/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-loadgenerator/loadgenerator-deployment.yaml
sed -i 's/OPS_PROJECT_ID/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-loadgenerator/loadgenerator-rbac.yaml
sed -i 's/OPS_PROJECT_ID/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-loadgenerator/loadgenerator-deployment.yaml
sed -i 's/OPS_PROJECT_ID/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-loadgenerator/loadgenerator-rbac.yaml
- 두 운영 클러스터의 kustomization.yaml에
loadgenerator리소스를 추가합니다.
cd $WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-loadgenerator/
kustomize edit add resource loadgenerator-psp.yaml
kustomize edit add resource loadgenerator-rbac.yaml
kustomize edit add resource loadgenerator-deployment.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-loadgenerator/
kustomize edit add resource loadgenerator-psp.yaml
kustomize edit add resource loadgenerator-rbac.yaml
kustomize edit add resource loadgenerator-deployment.yaml
k8s-repo에 커밋합니다.
cd $WORKDIR/k8s-repo
git add . && git commit -am "create app namespaces and install hipster shop"
git push --set-upstream origin master
- 이전에 연 탭에서 또는 다음 링크를 클릭하여 Ops 프로젝트 Cloud Build의 상태를 확인합니다.
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
애플리케이션 배포 확인
- cart를 제외한 모든 애플리케이션 네임스페이스의 포드가 모든 개발 클러스터에서 실행 중 상태인지 확인합니다.
for ns in ad checkout currency email frontend payment product-catalog recommendation shipping; do
kubectl --context $DEV1_GKE_1 get pods -n $ns;
kubectl --context $DEV1_GKE_2 get pods -n $ns;
kubectl --context $DEV2_GKE_1 get pods -n $ns;
kubectl --context $DEV2_GKE_2 get pods -n $ns;
done;
Output (do not copy)
NAME READY STATUS RESTARTS AGE currencyservice-5c5b8876db-pvc6s 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE currencyservice-5c5b8876db-xlkl9 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE currencyservice-5c5b8876db-zdjkg 2/2 Running 0 115s NAME READY STATUS RESTARTS AGE currencyservice-5c5b8876db-l748q 2/2 Running 0 82s NAME READY STATUS RESTARTS AGE emailservice-588467b8c8-gk92n 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE emailservice-588467b8c8-rvzk9 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE emailservice-588467b8c8-mt925 2/2 Running 0 117s NAME READY STATUS RESTARTS AGE emailservice-588467b8c8-klqn7 2/2 Running 0 84s NAME READY STATUS RESTARTS AGE frontend-64b94cf46f-kkq7d 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE frontend-64b94cf46f-lwskf 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE frontend-64b94cf46f-zz7xs 2/2 Running 0 118s NAME READY STATUS RESTARTS AGE frontend-64b94cf46f-2vtw5 2/2 Running 0 85s NAME READY STATUS RESTARTS AGE paymentservice-777f6c74f8-df8ml 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE paymentservice-777f6c74f8-bdcvg 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE paymentservice-777f6c74f8-jqf28 2/2 Running 0 117s NAME READY STATUS RESTARTS AGE paymentservice-777f6c74f8-95x2m 2/2 Running 0 86s NAME READY STATUS RESTARTS AGE productcatalogservice-786dc84f84-q5g9p 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE productcatalogservice-786dc84f84-n6lp8 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE productcatalogservice-786dc84f84-gf9xl 2/2 Running 0 119s NAME READY STATUS RESTARTS AGE productcatalogservice-786dc84f84-v7cbr 2/2 Running 0 86s NAME READY STATUS RESTARTS AGE recommendationservice-5fdf959f6b-2ltrk 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE recommendationservice-5fdf959f6b-dqd55 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE recommendationservice-5fdf959f6b-jghcl 2/2 Running 0 119s NAME READY STATUS RESTARTS AGE recommendationservice-5fdf959f6b-kkspz 2/2 Running 0 87s NAME READY STATUS RESTARTS AGE shippingservice-7bd5f569d-qqd9n 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE shippingservice-7bd5f569d-xczg5 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE shippingservice-7bd5f569d-wfgfr 2/2 Running 0 2m NAME READY STATUS RESTARTS AGE shippingservice-7bd5f569d-r6t8v 2/2 Running 0 88s
- cart 네임스페이스의 포드가 첫 번째 개발 클러스터에서만 실행 중 상태인지 확인합니다.
kubectl --context $DEV1_GKE_1 get pods -n cart;
Output (do not copy)
NAME READY STATUS RESTARTS AGE cartservice-659c9749b4-vqnrd 2/2 Running 0 17m
Hipster Shop 앱에 액세스
글로벌 부하 분산
이제 Hipster Shop 앱이 4개의 앱 클러스터 모두에 배포되었습니다. 이러한 클러스터는 2개의 리전과 4개의 영역에 있습니다. 클라이언트는 frontend 서비스에 액세스하여 Hipster Shop 앱에 액세스할 수 있습니다. frontend 서비스는 4개의 앱 클러스터 모두에서 실행됩니다. Google Cloud 부하 분산기 ( GCLB)는 frontend 서비스의 네 인스턴스 모두에 클라이언트 트래픽을 전달하는 데 사용됩니다.
Istio 인그레스 게이트웨이는 ops 클러스터에서만 실행되며 리전 내 두 영역 애플리케이션 클러스터에 대한 리전 부하 분산기 역할을 합니다. GCLB는 두 작업 클러스터에서 실행되는 두 Istio 인그레스 게이트웨이를 전역 프런트엔드 서비스의 백엔드로 사용합니다. Istio 인그레스 게이트웨이는 GCLB에서 클라이언트 트래픽을 수신한 다음 애플리케이션 클러스터에서 실행되는 프런트엔드 포드로 클라이언트 트래픽을 전송합니다.

또는 애플리케이션 클러스터에 직접 Istio 인그레스 게이트웨이를 배치하고 GCLB가 이를 백엔드로 사용할 수 있습니다.
GKE Autoneg 컨트롤러
Istio 인그레스 게이트웨이 Kubernetes 서비스는 네트워크 엔드포인트 그룹 (NEG)을 사용하여 GCLB에 백엔드로 등록됩니다. NEG를 사용하면 GCLB를 사용하여 컨테이너 기반 부하 분산을 사용할 수 있습니다. NEG는 Kubernetes 서비스의 특수 주석을 통해 생성되므로 NEG 컨트롤러에 등록할 수 있습니다. Autoneg 컨트롤러는 서비스 주석을 사용하여 NEG 생성을 자동화하고 이를 GCLB에 백엔드로 할당하는 특수 GKE 컨트롤러입니다. Istio 인그레스 게이트웨이를 포함한 Istio 컨트롤 플레인은 초기 인프라 Terraform Cloud Build 중에 배포됩니다. GCLB 및 autoneg 구성은 초기 Terraform 인프라 Cloud Build의 일부로 실행됩니다.
Cloud Endpoints 및 관리 인증서를 사용하여 인그레스 보안
GCP 관리 인증서는 frontend GCLB 서비스에 대한 클라이언트 트래픽을 보호하는 데 사용됩니다. GCLB는 전역 frontend 서비스에 관리 인증서를 사용하며 인증서는 GCLB에서 종료됩니다. 이 워크숍에서는 Cloud Endpoints를 관리형 인증서의 도메인으로 사용합니다. 또는 도메인과 frontend의 DNS 이름을 사용하여 GCP 관리 인증서를 만들 수 있습니다.
- Hipster shop에 액세스하려면 다음 명령어의 링크 출력을 클릭합니다.
echo "https://frontend.endpoints.$TF_VAR_ops_project_name.cloud.goog"
- Chrome 탭의 URL 표시줄에 있는 자물쇠 기호를 클릭하여 인증서가 유효한지 확인할 수 있습니다.

전역 부하 분산 확인
애플리케이션 배포의 일환으로 GCLB Hipster Shop Cloud Endpoints 링크에 테스트 트래픽을 생성하는 로드 생성기가 두 운영 클러스터에 모두 배포되었습니다. GCLB가 트래픽을 수신하고 두 Istio 인그레스 게이트웨이 모두로 전송하는지 확인합니다.
- Hipster Shop GCLB가 생성된 운영 프로젝트의 GCLB > 모니터링 링크를 가져옵니다.
echo "https://console.cloud.google.com/net-services/loadbalancing/details/http/istio-ingressgateway?project=$TF_VAR_ops_project_name&cloudshell=false&tab=monitoring&duration=PT1H"
- 아래와 같이 백엔드 드롭다운 메뉴에서 모든 백엔드를 istio-ingressgateway로 변경합니다.

istio-ingressgateways에 트래픽이 전달되고 있습니다.

istio-ingressgateway당 3개의 NEG가 생성됩니다. 운영 클러스터는 리전 클러스터이므로 리전의 각 영역에 NEG가 하나씩 생성됩니다. 하지만 istio-ingressgateway 포드는 리전당 단일 영역에서 실행됩니다. 트래픽이 istio-ingressgateway 포드로 이동하는 것으로 표시됩니다.
부하 생성기는 두 운영 클러스터에서 실행되어 클라이언트 트래픽을 시뮬레이션합니다. 운영 클러스터 리전 1에서 생성된 부하가 리전 2의 istio-ingressgateway로 전송됩니다. 마찬가지로 ops 클러스터 리전 2에서 생성된 부하가 리전 2의 istio-ingressgateway로 전송됩니다.
8. Stackdriver를 사용한 관측 가능성
목표: Istio 원격 분석을 Stackdriver에 연결하고 검증합니다.
istio-telemetry리소스 설치- Istio 서비스 대시보드 생성/업데이트
- 컨테이너 로그 보기
- Stackdriver에서 분산 추적 보기
복사 후 붙여넣기 방법 실습 안내
Istio의 주요 기능 중 하나는 기본 제공 모니터링 가능성 ('o11y')입니다. 즉, 블랙박스 계측되지 않은 컨테이너를 사용하더라도 운영자는 이러한 컨테이너를 오가는 트래픽을 관찰하여 고객에게 서비스를 제공할 수 있습니다. 이 관찰은 측정항목, 로그, 트레이스 등 몇 가지 다른 방법으로 이루어집니다.
또한 Hipster Shop의 내장 부하 생성 시스템을 활용합니다. 관측 가능성은 트래픽이 없는 정적 시스템에서는 제대로 작동하지 않으므로 부하 생성을 통해 작동 방식을 확인할 수 있습니다. 이 로드는 이미 실행 중이므로 이제 확인할 수 있습니다.
- istio to stackdriver 구성 파일을 설치합니다.
cd $WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/istio-telemetry
kustomize edit add resource istio-telemetry.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/istio-telemetry
kustomize edit add resource istio-telemetry.yaml
- k8s-repo에 커밋합니다.
cd $WORKDIR/k8s-repo
git add . && git commit -am "Install istio to stackdriver configuration"
git push
- 이전에 연 탭에서 또는 다음 링크를 클릭하여 Ops 프로젝트 Cloud Build의 상태를 확인합니다.
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
- Istio → Stackdriver 통합 확인 Stackdriver 핸들러 CRD를 가져옵니다.
kubectl --context $OPS_GKE_1 get handler -n istio-system
출력에 stackdriver라는 핸들러가 표시되어야 합니다.
NAME AGE kubernetesenv 12d prometheus 12d stackdriver 69s # <== NEW!
- Stackdriver로의 Istio 측정항목 내보내기가 작동하는지 확인합니다. 이 명령어에서 출력된 링크를 클릭합니다.
echo "https://console.cloud.google.com/monitoring/metrics-explorer?cloudshell=false&project=$TF_VAR_ops_project_name"
Ops 프로젝트의 이름을 딴 새 작업공간을 만들라는 메시지가 표시되면 확인을 선택합니다. 새 UI에 관한 메시지가 표시되면 대화상자를 닫으면 됩니다.
측정항목 탐색기의 '리소스 유형 및 측정항목 찾기'에 'istio'을 입력하면 'Kubernetes 컨테이너' 리소스 유형에 '서버 요청 수'와 같은 옵션이 표시됩니다. 이를 통해 측정항목이 메쉬에서 Stackdriver로 흐르는 것을 확인할 수 있습니다.
(아래 선을 보려면 destination_service_name 라벨로 그룹화해야 합니다.)

대시보드로 측정항목 시각화:
이제 측정항목이 Stackdriver APM 시스템에 있으므로 이를 시각화할 방법이 필요합니다. 이 섹션에서는 트래픽 (초당 요청 수), 지연 시간 (이 경우 99번째 백분위수 및 50번째 백분위수), 오류 (이 예에서는 포화도 제외)의 네 가지 '골든 시그널' 측정항목 중 세 가지를 보여주는 사전 빌드된 대시보드를 설치합니다.
Istio의 Envoy 프록시는 여러 측정항목을 제공하지만, 이 측정항목은 시작하기에 적합합니다. (전체 목록은 여기에서 확인하세요.) 각 측정항목에는 destination_service, source_workload_namespace, response_code, istio_tcp_received_bytes_total 등 필터링 및 집계에 사용할 수 있는 라벨 집합이 있습니다.
- 이제 사전 정의된 측정항목 대시보드를 추가해 보겠습니다. 대시보드 API를 직접 사용할 예정입니다. 일반적으로 API 호출을 직접 생성하지는 않으며 자동화 시스템의 일부이거나 웹 UI에서 대시보드를 수동으로 빌드합니다. 이렇게 하면 빠르게 시작할 수 있습니다.
sed -i 's/OPS_PROJECT/'${TF_VAR_ops_project_name}'/g' \
$WORKDIR/asm/k8s_manifests/prod/app-telemetry/services-dashboard.json
OAUTH_TOKEN=$(gcloud auth application-default print-access-token)
curl -X POST -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json" \
https://monitoring.googleapis.com/v1/projects/$TF_VAR_ops_project_name/dashboards \
-d @$WORKDIR/asm/k8s_manifests/prod/app-telemetry/services-dashboard.json
- 아래 출력 링크로 이동하여 새로 추가된 '서비스 대시보드'를 확인합니다.
echo "https://console.cloud.google.com/monitoring/dashboards/custom/servicesdash?cloudshell=false&project=$TF_VAR_ops_project_name"
UX를 사용하여 대시보드를 인플레이스로 수정할 수 있지만, 이 경우 API를 사용하여 새 그래프를 빠르게 추가할 것입니다. 이렇게 하려면 최신 버전의 대시보드를 가져와서 수정사항을 적용한 다음 HTTP PATCH 메서드를 사용하여 다시 푸시해야 합니다.
- Monitoring API를 쿼리하여 기존 대시보드를 가져올 수 있습니다. 방금 추가된 기존 대시보드를 가져옵니다.
curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json" \
https://monitoring.googleapis.com/v1/projects/$TF_VAR_ops_project_name/dashboards/servicesdash > /tmp/services-dashboard.json
- 새 그래프 추가(50번째 백분위수 지연 시간): [API 참조] 이제 코드에서 대시보드에 새 그래프 위젯을 추가할 수 있습니다. 이 변경사항은 동료가 검토하고 버전 관리로 확인할 수 있습니다. 다음은 50%백분위수 지연 시간 (중앙값 지연 시간)을 표시하는 위젯입니다.
방금 가져온 대시보드를 수정하여 새 스탠자를 추가해 보세요.
NEW_CHART=${WORKDIR}/asm/k8s_manifests/prod/app-telemetry/new-chart.json
jq --argjson newChart "$(<$NEW_CHART)" '.gridLayout.widgets += [$newChart]' /tmp/services-dashboard.json > /tmp/patched-services-dashboard.json
- 기존 서비스 대시보드를 업데이트합니다.
curl -X PATCH -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json" \
https://monitoring.googleapis.com/v1/projects/$TF_VAR_ops_project_name/dashboards/servicesdash \
-d @/tmp/patched-services-dashboard.json
- 다음 출력 링크로 이동하여 업데이트된 대시보드를 확인합니다.
echo "https://console.cloud.google.com/monitoring/dashboards/custom/servicesdash?cloudshell=false&project=$TF_VAR_ops_project_name"
- 간단한 로그 분석을 수행합니다.
Istio는 모든 메시 내 네트워크 트래픽에 대해 구조화된 로그를 제공하고 이를 Stackdriver Logging에 업로드하여 하나의 강력한 도구에서 교차 클러스터 분석을 지원합니다. 로그에는 클러스터, 컨테이너, 앱, connection_id 등의 서비스 수준 메타데이터가 주석으로 추가됩니다.
로그 항목의 예 (이 경우 Envoy 프록시의 액세스 로그)는 다음과 같습니다 (잘림).
*** DO NOT PASTE ***
logName: "projects/PROJECTNAME-11932-01-ops/logs/server-tcp-accesslog-stackdriver.instance.istio-system"
labels: {
connection_id: "fbb46826-96fd-476c-ac98-68a9bd6e585d-1517191"
destination_app: "redis-cart"
destination_ip: "10.16.1.7"
destination_name: "redis-cart-6448dcbdcc-cj52v"
destination_namespace: "cart"
destination_owner: "kubernetes://apis/apps/v1/namespaces/cart/deployments/redis-cart"
destination_workload: "redis-cart"
source_ip: "10.16.2.8"
total_received_bytes: "539"
total_sent_bytes: "569"
...
}
여기에서 로그를 확인하세요.
echo "https://console.cloud.google.com/logs/viewer?cloudshell=false&project=$TF_VAR_ops_project_name"
리소스 > Kubernetes 컨테이너를 선택하고 'pilot'을 검색하여 Istio의 컨트롤 플레인 로그를 볼 수 있습니다.

여기에서 Istio 컨트롤 플레인이 각 샘플 앱 서비스의 사이드카 프록시에 프록시 구성을 푸시하는 것을 확인할 수 있습니다. 'CDS', 'LDS', 'RDS'는 서로 다른 Envoy API를 나타냅니다 ( 자세히 알아보기).
Istio 로그 외에도 동일한 인터페이스에서 컨테이너 로그와 인프라 또는 기타 GCP 서비스 로그를 모두 확인할 수 있습니다. 다음은 GKE의 샘플 로그 쿼리입니다. 로그 뷰어를 사용하면 로그에서 측정항목을 만들 수도 있습니다 (예: '특정 문자열과 일치하는 모든 오류를 집계'). 이 측정항목은 대시보드에서 사용하거나 알림의 일부로 사용할 수 있습니다. 로그를 BigQuery와 같은 다른 분석 도구로 스트리밍할 수도 있습니다.
힙스터 상점의 샘플 필터는 다음과 같습니다.
resource.type="k8s_container" labels.destination_app="productcatalogservice"
resource.type="k8s_container" resource.labels.namespace_name="cart"
- 분산 추적을 확인하세요.
이제 분산 시스템을 사용하므로 디버깅에는 새로운 도구인 분산 추적이 필요합니다. 이 도구를 사용하면 서비스가 상호작용하는 방식에 관한 통계를 파악할 수 있으며 (예: 아래 그림에서 이상치인 느린 이벤트 찾기) 원시 샘플 트레이스를 자세히 살펴보고 실제로 어떤 일이 일어나고 있는지 조사할 수 있습니다.
타임라인 뷰에는 시간이 지남에 따라 모든 요청이 표시되며, 지연 시간 또는 초기 요청부터 Hipster 스택을 거쳐 최종적으로 최종 사용자에게 응답하는 데 걸린 시간별로 그래프로 표시됩니다. 점이 위로 올라갈수록 사용자 환경이 느려지고 불만족스러워집니다.
점을 클릭하면 해당 요청의 상세 워터폴 뷰를 확인할 수 있습니다. 특정 요청의 원시 세부정보 (집계 통계뿐만 아니라)를 찾는 기능은 서비스 간의 상호작용을 이해하는 데 매우 중요합니다. 특히 서비스 간의 드물지만 좋지 않은 상호작용을 추적할 때 그렇습니다.
워터폴 뷰는 디버거를 사용해 본 사람이라면 익숙할 것입니다. 하지만 이 경우 단일 애플리케이션의 여러 프로세스에서 소요된 시간을 표시하는 대신 별도의 컨테이너에서 실행되는 서비스 간에 메시를 탐색하는 데 소요된 시간을 표시합니다.
여기에서 추적을 확인할 수 있습니다.
echo "https://console.cloud.google.com/traces/overview?cloudshell=false&project=$TF_VAR_ops_project_name"
도구의 예시 스크린샷:

9. 상호 TLS 인증
목표: 마이크로서비스 간 연결 보안 (인증)
- 메시 전체 mTLS 사용 설정
- 로그를 검사하여 mTLS 확인
복사 후 붙여넣기 방법 실습 안내
이제 앱이 설치되고 관측 가능성이 설정되었으므로 서비스 간 연결을 보호하고 계속 작동하는지 확인할 수 있습니다.
예를 들어 Kiali 대시보드에서 서비스가 MTLS를 사용하지 않는 것을 확인할 수 있습니다('잠금' 아이콘 없음). 하지만 트래픽이 흐르고 시스템은 제대로 작동합니다. StackDriver 골든 메트릭 대시보드를 통해 전반적으로 시스템이 작동하고 있다는 안심을 얻을 수 있습니다.
- 운영 클러스터에서 MeshPolicy를 확인합니다. mTLS는 암호화된 트래픽과 비 mTLS 트래픽을 모두 허용하는
PERMISSIVE입니다.
kubectl --context $OPS_GKE_1 get MeshPolicy -o json | jq '.items[].spec'
kubectl --context $OPS_GKE_2 get MeshPolicy -o json | jq '.items[].spec'
`Output (do not copy)`
{
"peers": [
{
"mtls": {
"mode": "PERMISSIVE"
}
}
]
}
Istio는 IstioControlPlane 커스텀 리소스 (CR)를 사용하는 Istio 연산자를 사용하여 모든 클러스터에서 구성됩니다. IstioControlPlane CR을 업데이트하고 k8s-repo를 업데이트하여 모든 클러스터에서 mTLS를 구성합니다. IstioControlPlane CR에서 global > mTLS > enabled: true를 설정하면 Istio 제어 영역에 다음과 같은 두 가지 변경사항이 적용됩니다.
- MeshPolicy는 모든 클러스터에서 실행되는 모든 서비스에 대해 메시 전체 mTLS를 사용 설정하도록 설정됩니다.
- 모든 클러스터에서 실행되는 서비스 간에 ISTIO_MUTUAL 트래픽을 허용하도록 DestinationRule이 생성됩니다.
- istioControlPlane CR에 kustomize 패치를 적용하여 mTLS를 클러스터 전체에 사용 설정합니다. 모든 클러스터의 관련 디렉터리에 패치를 복사하고 kustomize 패치를 추가합니다.
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-replicated.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-replicated.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-shared.yaml \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-shared.yaml \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-shared.yaml \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-shared.yaml \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
- k8s-repo에 커밋합니다.
cd $WORKDIR/k8s-repo
git add . && git commit -am "turn mTLS on"
git push
- 이전에 연 탭에서 또는 다음 링크를 클릭하여 Ops 프로젝트 Cloud Build의 상태를 확인합니다.
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
mTLS 확인
- 운영 클러스터에서 MeshPolicy를 다시 한번 확인합니다. mTLS는 더 이상
PERMISSIVE이 아니며 mTLS 트래픽만 허용합니다.
kubectl --context $OPS_GKE_1 get MeshPolicy -o json | jq .items[].spec
kubectl --context $OPS_GKE_2 get MeshPolicy -o json | jq .items[].spec
출력(복사 금지):
{
"peers": [
{
"mtls": {}
}
]
}
- Istio 연산자 컨트롤러에서 생성된 DestinationRule을 설명합니다.
kubectl --context $OPS_GKE_1 get DestinationRule default -n istio-system -o json | jq '.spec'
kubectl --context $OPS_GKE_2 get DestinationRule default -n istio-system -o json | jq '.spec'
출력(복사 금지):
{
host: '*.local',
trafficPolicy: {
tls: {
mode: ISTIO_MUTUAL
}
}
}
로그에서 HTTP에서 HTTPS로의 이동도 확인할 수 있습니다.
로그 항목을 클릭한 다음 표시할 필드의 값을 클릭하여 UI의 로그에서 이 특정 필드를 노출할 수 있습니다. 이 경우 'protocol:' 옆에 있는 'http'를 클릭합니다.

이렇게 하면 전환을 시각화하는 좋은 방법이 됩니다.

10. 카나리아 배포
목표: 프런트엔드 서비스의 새 버전을 출시합니다.
- 한 리전에
frontend-v2(다음 프로덕션 버전) 서비스를 출시합니다. DestinationRules및VirtualServices을 사용하여 트래픽을frontend-v2로 천천히 유도k8s-repo에 대한 일련의 커밋을 검사하여 GitOps 배포 파이프라인을 확인합니다.
복사 후 붙여넣기 방법 실습 안내
카나리아 배포는 새 서비스를 점진적으로 출시하는 것입니다. 카나리아 배포에서는 새 버전으로 전송되는 트래픽의 양이 증가하는 반면 나머지 비율은 현재 버전으로 계속 전송됩니다. 일반적인 패턴은 트래픽 분할의 각 단계에서 카나리아 분석을 실행하고 새 버전의 '골든 시그널'(지연 시간, 오류율, 포화도)을 기준과 비교하는 것입니다. 이렇게 하면 서비스 중단을 방지하고 트래픽 분할의 모든 단계에서 새로운 'v2' 서비스의 안정성을 보장할 수 있습니다.
이 섹션에서는 Cloud Build 및 Istio 트래픽 정책을 사용하여 새 버전의 프런트엔드 서비스에 대한 기본 카나리아 배포를 만드는 방법을 알아봅니다.
먼저 DEV1 리전 (us-west1)에서 카나리아 파이프라인을 실행하고 해당 리전의 두 클러스터에 프런트엔드 v2를 출시합니다. 두 번째로 DEV2 리전 (us-central)에서 카나리아 파이프라인을 실행하고 해당 리전의 두 클러스터에 v2를 배포합니다. 모든 리전에서 병렬로 파이프라인을 실행하는 대신 리전에서 순서대로 실행하면 잘못된 구성이나 v2 앱 자체의 버그로 인해 발생하는 전역 중단을 방지할 수 있습니다.
참고: 두 리전 모두에서 카나리아 파이프라인을 수동으로 트리거하지만 프로덕션에서는 레지스트리에 푸시된 새 Docker 이미지 태그를 기반으로 하는 자동 트리거를 사용합니다.
- Cloud Shell에서 나머지 명령어 실행을 간소화하기 위해 몇 가지 환경 변수를 정의합니다.
CANARY_DIR="$WORKDIR/asm/k8s_manifests/prod/app-canary/"
K8S_REPO="$WORKDIR/k8s-repo"
- repo_setup.sh 스크립트를 실행하여 기준 매니페스트를 k8s-repo에 복사합니다.
$CANARY_DIR/repo-setup.sh
다음 매니페스트가 복사됩니다.
- frontend-v2 배포
- frontend-v1 패치('v1' 라벨과 '/version' 엔드포인트가 있는 이미지를 포함)
- HTTP 응답 분포를 출력하고 카나리아 배포를 실시간으로 시각화하는 데 도움이 되는 작은 포드인 respy
- 프런트엔드 Istio DestinationRule - 'version' 배포 라벨을 기반으로 프런트엔드 Kubernetes 서비스를 v1과 v2라는 두 개의 하위 집합으로 분할합니다.
- 프런트엔드 Istio VirtualService - 트래픽의 100% 를 프런트엔드 v1로 라우팅합니다. 이렇게 하면 모든 Dev1 리전 트래픽의 50% 를 프런트엔드 v2로 즉시 전송하는 Kubernetes 서비스 기본 라운드 로빈 동작이 재정의됩니다.
- k8s_repo에 변경사항 커밋:
cd $K8S_REPO
git add . && git commit -am "frontend canary setup"
git push
- 이전에 연 탭에서 또는 다음 링크를 클릭하여 Ops 프로젝트 Cloud Build의 상태를 확인합니다.
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
- OPS1 프로젝트의 콘솔에서 Cloud Build로 이동합니다. Cloud Build 파이프라인이 완료될 때까지 기다린 후 DEV1 클러스터 모두에서 프런트엔드 네임스페이스의 포드를 가져옵니다. 아래와 같이 표시됩니다.
watch -n 1 kubectl --context $DEV1_GKE_1 get pods -n frontend
Output (do not copy)
NAME READY STATUS RESTARTS AGE frontend-578b5c5db6-h9567 2/2 Running 0 59m frontend-v2-54b74fc75b-fbxhc 2/2 Running 0 2m26s respy-5f4664b5f6-ff22r 2/2 Running 0 2m26s
tmux를 사용하여 Cloud Shell 창을 두 개의 창으로 분할합니다.
- 하단 창에서는 프런트엔드 서비스의 HTTP 응답 분포를 관찰하기 위해 watch 명령어가 실행됩니다.
- 상단 창에서는 실제 카나리아 파이프라인 스크립트가 실행됩니다.
- 명령어를 실행하여 Cloud Shell 창을 분할하고 하단 창에서 watch 명령어를 실행합니다.
RESPY_POD=$(kubectl --context $DEV1_GKE_1 get pod \
-n frontend -l app=respy -o jsonpath='{..metadata.name}')
export TMUX_SESSION=$(tmux display-message -p '#S')
tmux split-window -d -t $TMUX_SESSION:0 -p33 \
-v "export KUBECONFIG=$WORKDIR/asm/gke/kubemesh; \
kubectl --context $DEV1_GKE_1 exec -n frontend -it \
$RESPY_POD -c respy /bin/sh -- -c 'watch -n 1 ./respy \
--u http://frontend:80/version --c 10 --n 500'; sleep 2"
출력(복사 금지)
500 requests to http://frontend:80/version... +----------+-------------------+ | RESPONSE | % OF 500 REQUESTS | +----------+-------------------+ | v1 | 100.0% | | | | +----------+-------------------+
- Dev1 리전에서 카나리아 파이프라인을 실행합니다. VirtualService에서 frontend-v2 트래픽 비율을 업데이트하는 스크립트 (가중치를 20%, 50%, 80%, 100%로 업데이트)를 제공합니다. 업데이트 사이에 스크립트는 Cloud Build 파이프라인이 완료될 때까지 기다립니다. Dev1 리전의 카나리아 배포 스크립트를 실행합니다. 참고: 이 스크립트는 완료하는 데 약 10분이 걸립니다.
K8S_REPO=$K8S_REPO CANARY_DIR=$CANARY_DIR \
OPS_DIR=$OPS_GKE_1_CLUSTER OPS_CONTEXT=$OPS_GKE_1 \
${CANARY_DIR}/auto-canary.sh
respy 명령어를 실행하는 하단 창에서 트래픽 분할을 실시간으로 확인할 수 있습니다. 예를 들어 20% 지점에서는 다음과 같습니다.
출력(복사 금지)
500 requests to http://frontend:80/version... +----------+-------------------+ | RESPONSE | % OF 500 REQUESTS | +----------+-------------------+ | v1 | 79.4% | | | | | v2 | 20.6% | | | | +----------+-------------------+
- frontend-v2의 Dev2 출시가 완료되면 스크립트 끝에 성공 메시지가 표시됩니다.
Output (do not copy)
✅ 100% successfully deployed 🌈 frontend-v2 Canary Complete for gke-asm-1-r1-prod
- Dev2 포드의 모든 프런트엔드 트래픽은 frontend-v2로 이동해야 합니다.
Output (do not copy)
500 requests to http://frontend:80/version... +----------+-------------------+ | RESPONSE | % OF 500 REQUESTS | +----------+-------------------+ | v2 | 100.0% | | | | +----------+-------------------+
- 분할 창을 닫습니다.
tmux respawn-pane -t ${TMUX_SESSION}:0.1 -k 'exit'
- 생성된 링크에서 Cloud Source Repos로 이동합니다.
echo https://source.developers.google.com/p/$TF_VAR_ops_project_name/r/k8s-repo
각 트래픽 비율에 대해 별도의 커밋이 표시되며, 가장 최근 커밋이 목록 상단에 표시됩니다.

이제 Dev2 리전에 대해 동일한 프로세스를 반복합니다. Dev2 지역은 여전히 v1으로 '잠겨' 있습니다. 이는 기준 repo_setup 스크립트에서 모든 트래픽을 v1로 명시적으로 전송하는 VirtualService를 푸시했기 때문입니다. 이러한 방식으로 Dev1에서 지역 카나리아를 안전하게 실행하고 새 버전을 전 세계에 출시하기 전에 성공적으로 실행되는지 확인할 수 있었습니다.
- 명령어를 실행하여 Cloud Shell 창을 분할하고 하단 창에서 watch 명령어를 실행합니다.
RESPY_POD=$(kubectl --context $DEV2_GKE_1 get pod \
-n frontend -l app=respy -o jsonpath='{..metadata.name}')
export TMUX_SESSION=$(tmux display-message -p '#S')
tmux split-window -d -t $TMUX_SESSION:0 -p33 \
-v "export KUBECONFIG=$WORKDIR/asm/gke/kubemesh; \
kubectl --context $DEV2_GKE_1 exec -n frontend -it \
$RESPY_POD -c respy /bin/sh -- -c 'watch -n 1 ./respy \
--u http://frontend:80/version --c 10 --n 500'; sleep 2"
출력(복사 금지)
500 requests to http://frontend:80/version... +----------+-------------------+ | RESPONSE | % OF 500 REQUESTS | +----------+-------------------+ | v1 | 100.0% | | | | +----------+-------------------+
- Dev2 리전에서 카나리아 파이프라인을 실행합니다. VirtualService에서 frontend-v2 트래픽 비율을 업데이트하는 스크립트 (가중치를 20%, 50%, 80%, 100%로 업데이트)를 제공합니다. 업데이트 사이에 스크립트는 Cloud Build 파이프라인이 완료될 때까지 기다립니다. Dev1 리전의 카나리아 배포 스크립트를 실행합니다. 참고: 이 스크립트는 완료하는 데 약 10분이 걸립니다.
K8S_REPO=$K8S_REPO CANARY_DIR=$CANARY_DIR \
OPS_DIR=$OPS_GKE_2_CLUSTER OPS_CONTEXT=$OPS_GKE_2 \
${CANARY_DIR}/auto-canary.sh
출력(복사 금지)
500 requests to http://frontend:80/version... +----------+-------------------+ | RESPONSE | % OF 500 REQUESTS | +----------+-------------------+ | v1 | 100.0% | | | | +----------+-------------------+
- Dev2의 Respy 포드에서 Dev2 포드의 트래픽이 frontend v1에서 v2로 점진적으로 이동하는 것을 확인합니다. 스크립트가 완료되면 다음이 표시됩니다.
출력(복사 금지)
500 requests to http://frontend:80/version... +----------+-------------------+ | RESPONSE | % OF 500 REQUESTS | +----------+-------------------+ | v2 | 100.0% | | | | +----------+-------------------+
- 분할 창을 닫습니다.
tmux respawn-pane -t ${TMUX_SESSION}:0.1 -k 'exit'
이 섹션에서는 리전 카나리아 배포에 Istio를 사용하는 방법을 소개했습니다. 프로덕션에서는 수동 스크립트 대신 컨테이너 레지스트리에 푸시된 새 태그 이미지와 같은 트리거를 사용하여 이 카나리아 스크립트를 Cloud Build 파이프라인으로 자동 트리거할 수 있습니다. 또한 각 단계 사이에 카나리아 분석을 추가하여 더 많은 트래픽을 전송하기 전에 미리 정의된 안전 임계값에 대해 v2의 지연 시간과 오류율을 분석하는 것이 좋습니다.
11. 승인 정책
목표: 마이크로서비스 간 RBAC 설정 (AuthZ)
- 마이크로서비스에 대한 액세스를 거부하는
AuthorizationPolicy만들기 AuthorizationPolicy를 생성하여 마이크로서비스에 대한 특정 액세스 허용
복사 후 붙여넣기 방법 실습 안내
한 곳에서 실행될 수 있는 모놀리식 애플리케이션과 달리 글로벌 분산 마이크로서비스 앱은 네트워크 경계를 넘어 호출합니다. 즉, 애플리케이션에 더 많은 진입점이 있으며 악의적인 공격에 대한 기회가 많아집니다. Kubernetes 포드에는 일시적 IP가 있기 때문에 워크로드 간 액세스를 보호하려면 기존 IP 기반 방화벽 규칙은 더 이상 적합하지 않습니다. 마이크로서비스 아키텍처에서는 새로운 보안 방식이 필요합니다. 서비스 계정과 같은 Kubernetes 보안 빌딩 블록을 기반으로 Istio는 애플리케이션을 위한 유연한 보안 정책을 제공합니다.
Istio 정책은 인증과 승인을 모두 다룹니다. 인증은 신원을 확인하고 (이 서버가 밝힌 신원을 신뢰할 수 있는가?), 승인은 권한을 확인합니다 (이 클라이언트가 해당 작업을 실행할 수 있는가?). 모듈 1 (MeshPolicy)의 상호 TLS 섹션에서 Istio 인증을 다뤘습니다. 이 섹션에서는 Istio 승인 정책을 사용하여 애플리케이션 워크로드 중 하나인 currencyservice에 대한 액세스를 제어하는 방법을 알아봅니다.
먼저 4개의 모든 개발 클러스터에 AuthorizationPolicy를 배포하여 currencyservice에 대한 모든 액세스를 차단하고 프런트엔드에서 오류를 트리거합니다. 그런 다음 프런트엔드 서비스만 currencyservice에 액세스하도록 허용합니다.
currency-deny-all.yaml의 콘텐츠를 검사합니다. 이 정책은 배포 라벨 선택기를 사용하여 currencyservice에 대한 액세스를 제한합니다.spec필드가 없습니다. 즉, 이 정책은 선택한 서비스에 대한 모든 액세스를 거부합니다.
cat $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-deny-all.yaml
출력(복사 금지)
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
name: "currency-policy"
namespace: currency
spec:
selector:
matchLabels:
app: currencyservice
- 두 지역의 운영 클러스터에 대해 k8s-repo에 통화 정책을 복사합니다.
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-deny-all.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-authorization/currency-policy.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-authorization
kustomize edit add resource currency-policy.yaml
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-deny-all.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-authorization/currency-policy.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-authorization
kustomize edit add resource currency-policy.yaml
- 변경사항을 푸시합니다.
cd $WORKDIR/k8s-repo
git add . && git commit -am "AuthorizationPolicy - currency: deny all"
git push
- 이전에 연 탭에서 또는 다음 링크를 클릭하여 Ops 프로젝트 Cloud Build의 상태를 확인합니다.
echo https://console.cloud.google.com/cloud-build/builds?project=$TF_VAR_ops_project_name
- 빌드가 성공적으로 완료되면 다음 링크의 브라우저에서 hipstershop 프런트엔드에 연결해 보세요.
echo "https://frontend.endpoints.$TF_VAR_ops_project_name.cloud.goog"
currencyservice에서 승인 오류가 표시됩니다.

- 통화 서비스가 이 AuthorizationPolicy를 어떻게 적용하는지 살펴보겠습니다. 먼저 차단된 승인 호출은 기본적으로 로깅되지 않으므로 통화 포드 중 하나의 Envoy 프록시에서 추적 수준 로그를 사용 설정합니다.
CURRENCY_POD=$(kubectl --context $DEV1_GKE_2 get pod -n currency | grep currency| awk '{ print $1 }')
kubectl --context $DEV1_GKE_2 exec -it $CURRENCY_POD -n \
currency -c istio-proxy -- curl -X POST \
"http://localhost:15000/logging?level=trace"
- 통화 서비스의 사이드카 프록시에서 RBAC (승인) 로그를 가져옵니다. currencyservice가 모든 인바운드 요청을 차단하도록 설정되어 있음을 나타내는 '시행 거부' 메시지가 표시됩니다.
kubectl --context $DEV1_GKE_2 logs -n currency $CURRENCY_POD \
-c istio-proxy | grep -m 3 rbac
출력(복사 금지)
[Envoy (Epoch 0)] [2020-01-30 00:45:50.815][22][debug][rbac] [external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:67] checking request: remoteAddress: 10.16.5.15:37310, localAddress: 10.16.3.8:7000, ssl: uriSanPeerCertificate: spiffe://cluster.local/ns/frontend/sa/frontend, subjectPeerCertificate: , headers: ':method', 'POST' [Envoy (Epoch 0)] [2020-01-30 00:45:50.815][22][debug][rbac] [external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:118] enforced denied [Envoy (Epoch 0)] [2020-01-30 00:45:50.815][22][debug][http] [external/envoy/source/common/http/conn_manager_impl.cc:1354] [C115][S17310331589050212978] Sending local reply with details rbac_access_denied
- 이제 다른 백엔드 서비스가 아닌 프런트엔드만 currencyservice에 액세스하도록 허용해 보겠습니다.
currency-allow-frontend.yaml을 열고 콘텐츠를 검사합니다. 다음 규칙이 추가되었습니다.
cat ${WORKDIR}/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend.yaml
출력(복사 금지)
rules:
- from:
- source:
principals: ["cluster.local/ns/frontend/sa/frontend"]
여기서는 통화 서비스에 액세스할 수 있도록 특정 source.principal (클라이언트)을 허용 목록에 추가합니다. 이 source.principal은 Kubernetes 서비스 계정으로 정의됩니다. 이 경우 화이트리스트에 추가할 서비스 계정은 프런트엔드 네임스페이스의 프런트엔드 서비스 계정입니다.
참고: Istio AuthorizationPolicies에서 Kubernetes 서비스 계정을 사용하는 경우 모듈 1에서와 같이 먼저 클러스터 전체 상호 TLS를 사용 설정해야 합니다. 이는 서비스 계정 사용자 인증 정보가 요청에 마운트되도록 하기 위한 것입니다.
- 업데이트된 통화 정책 복사
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-authorization/currency-policy.yaml
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-authorization/currency-policy.yaml
- 변경사항을 푸시합니다.
cd $WORKDIR/k8s-repo
git add . && git commit -am "AuthorizationPolicy - currency: allow frontend"
git push
- 이전에 연 탭에서 또는 다음 링크를 클릭하여 Ops 프로젝트 Cloud Build의 상태를 확인합니다.
echo https://console.cloud.google.com/cloud-build/builds?project=$TF_VAR_ops_project_name
- 빌드가 완료되면 Hipstershop 프런트엔드를 다시 엽니다. 이번에는 홈페이지에 오류가 표시되지 않습니다. 프런트엔드가 현재 서비스에 액세스하도록 명시적으로 허용되었기 때문입니다.
- 이제 장바구니에 상품을 추가하고 '주문하기'를 클릭하여 결제를 실행해 보세요. 이번에는 통화 서비스에서 가격 변환 오류가 표시됩니다. 프런트엔드만 허용 목록에 추가했기 때문에 checkoutservice가 여전히 currencyservice에 액세스할 수 없기 때문입니다.

- 마지막으로 currencyservice AuthorizationPolicy에 다른 규칙을 추가하여 결제 서비스가 통화에 액세스하도록 허용합니다. 통화에 액세스해야 하는 두 서비스(프런트엔드 및 결제)에만 통화 액세스 권한이 부여됩니다. 다른 백엔드는 계속 차단됩니다.
currency-allow-frontend-checkout.yaml을 열고 콘텐츠를 검사합니다. 규칙 목록은 논리적 OR로 작동합니다. currency는 이러한 두 서비스 계정 중 하나가 있는 워크로드의 요청만 수락합니다.
cat ${WORKDIR}/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend-checkout.yaml
출력(복사 금지)
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
name: "currency-policy"
namespace: currency
spec:
selector:
matchLabels:
app: currencyservice
rules:
- from:
- source:
principals: ["cluster.local/ns/frontend/sa/frontend"]
- from:
- source:
principals: ["cluster.local/ns/checkout/sa/checkout"]
- 최종 승인 정책을 k8s-repo에 복사합니다.
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend-checkout.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-authorization/currency-policy.yaml
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend-checkout.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-authorization/currency-policy.yaml
- 변경사항 푸시
cd $WORKDIR/k8s-repo
git add . && git commit -am "AuthorizationPolicy - currency: allow frontend and checkout"
git push
- 이전에 연 탭에서 또는 다음 링크를 클릭하여 Ops 프로젝트 Cloud Build의 상태를 확인합니다.
echo https://console.cloud.google.com/cloud-build/builds?project=$TF_VAR_ops_project_name
- 빌드가 성공적으로 완료되면 결제를 실행해 보세요. 결제가 성공적으로 작동해야 합니다.
이 섹션에서는 Istio 승인 정책을 사용하여 서비스 수준에서 세분화된 액세스 제어를 적용하는 방법을 살펴보았습니다. 프로덕션에서는 서비스당 하나의 AuthorizationPolicy를 만들고 (예를 들어) allow-all policy를 사용하여 동일한 네임스페이스의 모든 워크로드가 서로 액세스하도록 할 수 있습니다.
12. 인프라 확장
목표: 새 리전, 프로젝트, 클러스터를 추가하여 인프라를 확장합니다.
infrastructure저장소를 클론합니다.- Terraform 파일을 업데이트하여 새 리소스 만들기
- 새 리전의 서브넷 2개 (운영 프로젝트용 1개, 새 프로젝트용 1개)
- 새 리전의 새 ops 클러스터 (새 서브넷에 있음)
- 새 리전의 새 Istio 컨트롤 플레인
- 새 리전의 새 프로젝트에 있는 2개의 앱 클러스터
infrastructure저장소에 커밋- 설치 확인
복사 후 붙여넣기 방법 실습 안내
플랫폼을 확장하는 방법에는 여러 가지가 있습니다. 기존 클러스터에 노드를 추가하여 컴퓨팅을 추가할 수 있습니다. 리전에 클러스터를 더 추가할 수 있습니다. 또는 플랫폼에 더 많은 지역을 추가할 수 있습니다. 플랫폼의 어떤 측면을 확장할지는 요구사항에 따라 다릅니다. 예를 들어 리전의 세 영역 모두에 클러스터가 있는 경우 기존 클러스터에 노드 (또는 노드 풀)를 추가하는 것으로 충분할 수 있습니다. 하지만 단일 리전의 세 영역 중 두 영역에 클러스터가 있는 경우 세 번째 영역에 새 클러스터를 추가하면 확장과 추가 장애 도메인 (즉, 새 영역)이 제공됩니다. 규제 또는 규정 준수 이유 (예: PCI 또는 PII 정보를 저장하는 데이터베이스 클러스터)로 인해 단독 테넌트 클러스터를 만들어야 하는 경우에도 리전에 새 클러스터를 추가할 수 있습니다. 비즈니스와 서비스가 확장됨에 따라 고객에게 더 가까운 서비스를 제공하기 위해 새로운 지역을 추가하는 것이 불가피해집니다.
현재 플랫폼은 리전 2개와 리전당 영역 2개의 클러스터로 구성되어 있습니다. 플랫폼을 확장하는 방법은 두 가지입니다.
- 수직: 각 리전 내에서 컴퓨팅을 추가합니다. 이는 기존 클러스터에 노드 (또는 노드 풀)를 추가하거나 리전 내에 새 클러스터를 추가하여 수행됩니다. 이는
infrastructure저장소를 통해 이루어집니다. 가장 간단한 방법은 기존 클러스터에 노드를 추가하는 것입니다. 추가 구성은 필요하지 않습니다. 새 클러스터를 추가하려면 추가 서브넷 (및 보조 범위)을 추가하고, 적절한 방화벽 규칙을 추가하고, 새 클러스터를 리전 ASM/Istio 서비스 메시 컨트롤 플레인에 추가하고, 새 클러스터에 애플리케이션 리소스를 배포해야 할 수 있습니다. - 수평으로 - 더 많은 지역을 추가합니다. 현재 플랫폼에서는 지역 템플릿을 제공합니다. ASM/Istio 컨트롤 플레인이 상주하는 리전 ops 클러스터와 애플리케이션 리소스가 배포되는 두 개 이상의 영역 애플리케이션 클러스터로 구성됩니다.
이 워크숍에서는 수직 사용 사례 단계도 포함하므로 플랫폼을 '수평'으로 확장합니다. 플랫폼에 새 리전 (r3)을 추가하여 플랫폼을 수평으로 확장하려면 다음 리소스를 추가해야 합니다.
- 새 운영 및 애플리케이션 클러스터의 r3 리전에 있는 호스트 프로젝트 공유 VPC의 서브넷
- ASM/Istio 컨트롤 플레인이 있는 r3 리전의 리전 ops 클러스터
- r3 리전의 두 영역에 있는 두 개의 영역 애플리케이션 클러스터
- k8s-repo 업데이트:
- r3 리전의 ops 클러스터에 ASM/Istio 제어 영역 리소스를 배포합니다.
- ASM/Istio 공유 제어 영역 리소스를 r3 리전의 앱 클러스터에 배포합니다.
- 새 프로젝트를 만들 필요는 없지만 워크숍의 단계에서는 플랫폼에 새 팀을 추가하는 사용 사례를 다루기 위해 새 프로젝트 dev3을 추가하는 방법을 보여줍니다.
인프라 저장소는 위에 명시된 새 리소스를 추가하는 데 사용됩니다.
- Cloud Shell에서 WORKDIR로 이동하여
infrastructure저장소를 클론합니다.
mkdir -p $WORKDIR/infra-repo
cd $WORKDIR/infra-repo
git init && git remote add origin https://source.developers.google.com/p/${TF_ADMIN}/r/infrastructure
git config --local user.email ${MY_USER}
git config --local user.name "infra repo user"
git config --local credential.'https://source.developers.google.com'.helper gcloud.sh
git pull origin master
- 워크숍 소스 저장소
add-proj브랜치를add-proj-repo디렉터리에 클론합니다.
cd $WORKDIR
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git add-proj-repo -b add-proj
- 소스 워크숍 저장소의
add-proj브랜치에서 파일을 복사합니다.add-proj브랜치에는 이 섹션의 변경사항이 포함되어 있습니다.
cp -r $WORKDIR/add-proj-repo/infrastructure/* $WORKDIR/infra-repo/
- 분기의 스크립트가 실행되도록 add-proj 저장소 디렉터리의
infrastructure디렉터리를infra-repo디렉터리의 심볼릭 링크로 바꿉니다.
rm -rf $WORKDIR/add-proj-repo/infrastructure
ln -s $WORKDIR/infra-repo $WORKDIR/add-proj-repo/infrastructure
add-project.sh스크립트를 실행하여 공유 상태와 변수를 새 프로젝트 디렉터리 구조에 복사합니다.
$WORKDIR/add-proj-repo/scripts/add-project.sh app3 $WORKDIR/asm $WORKDIR/infra-repo
- 변경사항을 커밋하고 푸시하여 새 프로젝트 만들기
cd $WORKDIR/infra-repo
git add .
git status
git commit -m "add new project" && git push origin master
- 커밋은
infrastructure저장소가 새 리소스로 인프라를 배포하도록 트리거합니다. 다음 링크의 출력을 클릭하고 상단의 최신 빌드로 이동하여 Cloud Build 진행 상황을 확인합니다.
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_ADMIN}"
infrastructure Cloud Build의 마지막 단계에서는 k8s-repo에 새 Kubernetes 리소스를 만듭니다. 이렇게 하면 k8s-repo (운영 프로젝트)에서 Cloud Build가 트리거됩니다. 새 Kubernetes 리소스는 이전 단계에서 추가된 세 개의 새 클러스터용입니다. ASM/Istio 컨트롤 플레인 및 공유 컨트롤 플레인 리소스가 k8s-repo Cloud Build를 사용하여 새 클러스터에 추가됩니다.
- 인프라 Cloud Build가 성공적으로 완료되면 다음 출력 링크를 클릭하여
k8s-repo최신 Cloud Build 실행으로 이동합니다.
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
- 다음 스크립트를 실행하여 새 클러스터를 vars 및 kubeconfig 파일에 추가합니다.
$WORKDIR/add-proj-repo/scripts/setup-gke-vars-kubeconfig-add-proj.sh $WORKDIR/asm
KUBECONFIG변수가 새 kubeconfig 파일을 가리키도록 변경합니다.
source $WORKDIR/asm/vars/vars.sh
export KUBECONFIG=$WORKDIR/asm/gke/kubemesh
- 클러스터 컨텍스트를 나열합니다. 8개의 클러스터가 표시됩니다.
kubectl config view -ojson | jq -r '.clusters[].name'
`Output (do not copy)`
gke_user001-200204-05-dev1-49tqc4_us-west1-a_gke-1-apps-r1a-prod gke_user001-200204-05-dev1-49tqc4_us-west1-b_gke-2-apps-r1b-prod gke_user001-200204-05-dev2-49tqc4_us-central1-a_gke-3-apps-r2a-prod gke_user001-200204-05-dev2-49tqc4_us-central1-b_gke-4-apps-r2b-prod gke_user001-200204-05-dev3-49tqc4_us-east1-b_gke-5-apps-r3b-prod gke_user001-200204-05-dev3-49tqc4_us-east1-c_gke-6-apps-r3c-prod gke_user001-200204-05-ops-49tqc4_us-central1_gke-asm-2-r2-prod gke_user001-200204-05-ops-49tqc4_us-east1_gke-asm-3-r3-prod gke_user001-200204-05-ops-49tqc4_us-west1_gke-asm-1-r1-prod
Istio 설치 확인
- 모든 포드가 실행 중이고 작업이 완료되었는지 확인하여 새 ops 클러스터에 Istio가 설치되어 있는지 확인합니다.
kubectl --context $OPS_GKE_3 get pods -n istio-system
`Output (do not copy)`
NAME READY STATUS RESTARTS AGE grafana-5f798469fd-72g6w 1/1 Running 0 5h12m istio-citadel-7d8595845-hmmvj 1/1 Running 0 5h12m istio-egressgateway-779b87c464-rw8bg 1/1 Running 0 5h12m istio-galley-844ddfc788-zzpkl 2/2 Running 0 5h12m istio-ingressgateway-59ccd6574b-xfj98 1/1 Running 0 5h12m istio-pilot-7c8989f5cf-5plsg 2/2 Running 0 5h12m istio-policy-6674bc7678-2shrk 2/2 Running 3 5h12m istio-sidecar-injector-7795bb5888-kbl5p 1/1 Running 0 5h12m istio-telemetry-5fd7cbbb47-c4q7b 2/2 Running 2 5h12m istio-tracing-cd67ddf8-2qwkd 1/1 Running 0 5h12m istiocoredns-5f7546c6f4-qhj9k 2/2 Running 0 5h12m kiali-7964898d8c-l74ww 1/1 Running 0 5h12m prometheus-586d4445c7-x9ln6 1/1 Running 0 5h12m
- 두
dev3클러스터 모두에 Istio가 설치되어 있는지 확인합니다. Citadel, sidecar-injector, coredns만dev3클러스터에서 실행됩니다.ops-3클러스터에서 실행되는 Istio 제어 영역을 공유합니다.
kubectl --context $DEV3_GKE_1 get pods -n istio-system
kubectl --context $DEV3_GKE_2 get pods -n istio-system
`Output (do not copy)`
NAME READY STATUS RESTARTS AGE istio-citadel-568747d88-4lj9b 1/1 Running 0 66s istio-sidecar-injector-759bf6b4bc-ks5br 1/1 Running 0 66s istiocoredns-5f7546c6f4-qbsqm 2/2 Running 0 78s
공유 컨트롤 플레인의 서비스 검색 확인
- 보안 비밀이 6개 애플리케이션 클러스터의 모든 ops 클러스터에 배포되었는지 확인합니다.
kubectl --context $OPS_GKE_1 get secrets -l istio/multiCluster=true -n istio-system
kubectl --context $OPS_GKE_2 get secrets -l istio/multiCluster=true -n istio-system
kubectl --context $OPS_GKE_3 get secrets -l istio/multiCluster=true -n istio-system
`Output (do not copy)`
NAME TYPE DATA AGE gke-1-apps-r1a-prod Opaque 1 14h gke-2-apps-r1b-prod Opaque 1 14h gke-3-apps-r2a-prod Opaque 1 14h gke-4-apps-r2b-prod Opaque 1 14h gke-5-apps-r3b-prod Opaque 1 5h12m gke-6-apps-r3c-prod Opaque 1 5h12m
13. 회로 차단
목표: 배송 서비스에 회로 차단기를 구현합니다.
- 서킷 브레이커를 구현하기 위해
shipping서비스의DestinationRule만들기 fortio(부하 생성 유틸리티)를 사용하여 회로를 강제로 트리핑하여shipping서비스의 회로 차단기를 검증합니다.
Fast Track 스크립트 실습 안내
Fast Track Script Lab이 곧 출시됩니다.
복사 후 붙여넣기 방법 실습 안내
Istio 지원 서비스의 기본 모니터링 및 문제 해결 전략을 알아봤으니 이제 Istio가 서비스의 복원력을 개선하여 문제 해결을 해야 하는 양을 줄이는 방법을 살펴보겠습니다.
마이크로서비스 아키텍처는 한 서비스의 장애가 종속 항목과 해당 종속 항목의 종속 항목으로 전파되어 최종 사용자에게 영향을 미칠 수 있는 '파급 효과' 중단을 일으키는 연쇄 장애의 위험을 도입합니다. Istio는 서비스 격리를 지원하는 서킷 브레이커 트래픽 정책을 제공하여 실패한 서비스를 기다리지 않도록 다운스트림 (클라이언트 측) 서비스를 보호하고, 다시 온라인 상태가 되었을 때 다운스트림 트래픽이 갑자기 몰리지 않도록 업스트림 (서버 측) 서비스를 보호합니다. 전반적으로 회로 차단기를 사용하면 하나의 백엔드 서비스가 멈춰서 모든 서비스가 SLO를 충족하지 못하는 상황을 방지할 수 있습니다.
회로 차단기 패턴은 과도한 전기가 흐를 때 '트립'되어 기기를 과부하로부터 보호하는 전기 스위치의 이름을 따서 지어졌습니다. Istio 설정에서 이는 Envoy가 회로 차단기이며 서비스의 대기 중인 요청 수를 추적한다는 의미입니다. 이 기본 닫힘 상태에서는 요청이 Envoy를 통해 중단 없이 흐릅니다.
하지만 대기 중인 요청 수가 정의된 기준점을 초과하면 서킷 브레이커가 트립 (열림)되고 Envoy가 즉시 오류를 반환합니다. 이렇게 하면 서버가 클라이언트에 대해 빠르게 실패할 수 있으며 과부하 시 서버 애플리케이션 코드가 클라이언트의 요청을 수신하지 못하게 됩니다.
그런 다음 정의된 제한 시간이 지나면 Envoy는 서버가 다시 시험적으로 요청을 수신할 수 있는 반개방 상태로 이동합니다. 요청에 성공적으로 응답할 수 있으면 회로 차단기가 다시 닫히고 서버에 대한 요청이 다시 흐르기 시작합니다.
이 다이어그램은 Istio 회로 차단기 패턴을 요약한 것입니다. 파란색 직사각형은 Envoy를 나타내고, 파란색 원은 클라이언트를 나타내며, 흰색 원은 서버 컨테이너를 나타냅니다.

Istio DestinationRule을 사용하여 회로 차단기 정책을 정의할 수 있습니다. 이 섹션에서는 배송 서비스에 회로 차단기를 적용하기 위해 다음 정책을 적용합니다.
Output (do not copy)
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "shippingservice-shipping-destrule"
namespace: "shipping"
spec:
host: "shippingservice.shipping.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
connectionPool:
tcp:
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
outlierDetection:
consecutiveErrors: 1
interval: 1s
baseEjectionTime: 10s
maxEjectionPercent: 100
여기서 주목해야 할 DestinationRule 필드는 두 개입니다. connectionPool는 이 서비스에서 허용할 연결 수를 정의합니다. outlierDetection 필드는 Envoy가 서킷 브레이커를 열 임계값을 결정하는 방법을 구성하는 곳입니다. 여기서 Envoy는 매초 (간격) 서버 컨테이너에서 수신한 오류 수를 집계합니다. consecutiveErrors 기준점을 초과하면 Envoy 서킷 브레이커가 열리고 productcatalog 포드의 100% 가 10초 동안 새 클라이언트 요청에서 차단됩니다. Envoy 서킷 브레이커가 열리면 (즉, 활성화됨) 클라이언트에 503 (서비스를 사용할 수 없음) 오류가 표시됩니다. 예를 보면서 살펴보겠습니다.
- 명령어를 간소화하기 위해 k8s-repo 및 asm 디렉터리의 환경 변수를 설정합니다.
export K8S_REPO="${WORKDIR}/k8s-repo"
export ASM="${WORKDIR}/asm"
- k8s-repo 업데이트
cd $WORKDIR/k8s-repo
git pull
cd $WORKDIR
- 두 Ops 클러스터에서 배송 서비스 DestinationRule을 업데이트합니다.
cp $ASM/k8s_manifests/prod/istio-networking/app-shipping-circuit-breaker.yaml ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/app-shipping-circuit-breaker.yaml
cp $ASM/k8s_manifests/prod/istio-networking/app-shipping-circuit-breaker.yaml ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/app-shipping-circuit-breaker.yaml
cd ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/; kustomize edit add resource app-shipping-circuit-breaker.yaml
cd ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/; kustomize edit add resource app-shipping-circuit-breaker.yaml
- Fortio 부하 생성기 포드를 Dev1 리전의 GKE_1 클러스터에 복사합니다. 배송 서비스의 회로 차단기를 '트립'하는 데 사용할 클라이언트 포드입니다.
cp $ASM/k8s_manifests/prod/app/deployments/app-fortio.yaml ${K8S_REPO}/${DEV1_GKE_1_CLUSTER}/app/deployments/
cd ${K8S_REPO}/${DEV1_GKE_1_CLUSTER}/app/deployments; kustomize edit add resource app-fortio.yaml
- 변경사항을 커밋합니다.
cd $K8S_REPO
git add . && git commit -am "Circuit Breaker: shippingservice"
git push
cd $ASM
- Cloud Build가 완료될 때까지 기다립니다.
- Cloud Shell로 돌아가 fortio 포드를 사용하여 동시 연결 1개, 총 요청 1,000개로 shippingservice에 gRPC 트래픽을 보냅니다. 아직
connectionPool설정을 초과하지 않았으므로 서킷 브레이커가 작동하지 않습니다.
FORTIO_POD=$(kubectl --context ${DEV1_GKE_1} get pod -n shipping | grep fortio | awk '{ print $1 }')
kubectl --context ${DEV1_GKE_1} exec -it $FORTIO_POD -n shipping -c fortio /usr/bin/fortio -- load -grpc -c 1 -n 1000 -qps 0 shippingservice.shipping.svc.cluster.local:50051
출력(복사 금지)
Health SERVING : 1000 All done 1000 calls (plus 0 warmup) 4.968 ms avg, 201.2 qps
- 이제 동시 연결 수를 2로 늘리고 총 요청 수는 일정하게 유지한 상태로 fortio를 다시 실행합니다. 정의된 정책에서 1초 간격으로 동시 연결이 1개만 허용되므로 서킷 브레이커가 작동하여 요청의 최대 2/3가 '오버플로' 오류를 반환합니다.
kubectl --context ${DEV1_GKE_1} exec -it $FORTIO_POD -n shipping -c fortio /usr/bin/fortio -- load -grpc -c 2 -n 1000 -qps 0 shippingservice.shipping.svc.cluster.local:50051
출력(복사 금지)
18:46:16 W grpcrunner.go:107> Error making grpc call: rpc error: code = Unavailable desc = upstream connect error or disconnect/reset before headers. reset reason: overflow ... Health ERROR : 625 Health SERVING : 375 All done 1000 calls (plus 0 warmup) 12.118 ms avg, 96.1 qps
- Envoy는 서킷 브레이커가 활성 상태일 때 중단된 연결 수를 upstream_rq_pending_overflow 측정항목으로 추적합니다. fortio 포드에서 이를 찾아보겠습니다.
kubectl --context ${DEV1_GKE_1} exec -it $FORTIO_POD -n shipping -c istio-proxy -- sh -c 'curl localhost:15000/stats' | grep shipping | grep pending
출력(복사 금지)
cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.circuit_breakers.default.rq_pending_open: 0 cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.circuit_breakers.high.rq_pending_open: 0 cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.upstream_rq_pending_active: 0 cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.upstream_rq_pending_failure_eject: 9 cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.upstream_rq_pending_overflow: 565 cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.upstream_rq_pending_total: 1433
- 두 리전에서 서킷 브레이커 정책을 삭제하여 정리합니다.
kubectl --context ${OPS_GKE_1} delete destinationrule shippingservice-circuit-breaker -n shipping
rm ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/app-shipping-circuit-breaker.yaml
cd ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/; kustomize edit remove resource app-shipping-circuit-breaker.yaml
kubectl --context ${OPS_GKE_2} delete destinationrule shippingservice-circuit-breaker -n shipping
rm ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/app-shipping-circuit-breaker.yaml
cd ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/; kustomize edit remove resource app-shipping-circuit-breaker.yaml
cd $K8S_REPO; git add .; git commit -m "Circuit Breaker: cleanup"; git push origin master
이 섹션에서는 서비스에 단일 서킷 브레이커 정책을 설정하는 방법을 보여주었습니다. 잠재적으로 중단될 수 있는 업스트림 (백엔드) 서비스에 서킷 브레이커를 설정하는 것이 좋습니다. Istio 서킷 브레이커 정책을 적용하면 마이크로서비스를 격리하고, 아키텍처에 내결함성을 빌드하고, 높은 부하에서 연속 장애의 위험을 줄일 수 있습니다.
14. 결함 주입
목표: 프로덕션에 푸시되기 전에 지연을 도입하여 추천 서비스의 복원력을 테스트합니다.
recommendation서비스의VirtualService를 만들어 5초 지연 도입fortio부하 생성기를 사용하여 지연 시간 테스트VirtualService에서 지연 삭제 및 검증
Fast Track 스크립트 실습 안내
Fast Track Script Lab이 곧 출시됩니다.
복사 후 붙여넣기 방법 실습 안내
서비스에 회로 차단기 정책을 추가하는 것은 프로덕션의 서비스에 대한 복원력을 구축하는 한 가지 방법입니다. 하지만 서킷 브레이킹은 오류(사용자에게 표시되는 오류일 수 있음)를 발생시키므로 바람직하지 않습니다. 이러한 오류 사례를 미리 파악하고 백엔드에서 오류를 반환할 때 다운스트림 서비스가 어떻게 응답할지 더 잘 예측하려면 스테이징 환경에서 카오스 테스트를 채택하면 됩니다. 카오스 테스트는 시스템의 약점을 분석하고 내결함성을 개선하기 위해 의도적으로 서비스를 중단하는 방법입니다. 또한 혼돈 테스트를 사용하여 백엔드가 실패할 때 사용자에게 표시되는 오류를 완화하는 방법을 식별할 수 있습니다(예: 프런트엔드에 캐시된 결과를 표시).
Istio를 사용하여 오류를 삽입하면 소스 코드를 수정하는 대신 프로덕션 출시 이미지를 사용하고 네트워크 레이어에서 오류를 추가할 수 있으므로 유용합니다. 프로덕션에서는 네트워크 계층 외에도 Kubernetes/컴퓨팅 계층에서 복원력을 테스트하기 위해 본격적인 카오스 테스트 도구를 사용할 수 있습니다.
'fault' 필드가 있는 VirtualService를 적용하여 카오스 테스트에 Istio를 사용할 수 있습니다. Istio는 지연 오류 (시간 제한 삽입)와 중단 오류 (HTTP 오류 삽입)의 두 가지 오류를 지원합니다. 이 예시에서는 추천 서비스에 5초 지연 결함을 삽입합니다. 하지만 이번에는 서킷 브레이커를 사용하여 이 중단된 서비스에 대해 '빠르게 실패'하는 대신 다운스트림 서비스가 전체 제한 시간을 견디도록 강제합니다.
- 결함 삽입 디렉터리로 이동합니다.
export K8S_REPO="${WORKDIR}/k8s-repo"
export ASM="${WORKDIR}/asm/"
cd $ASM
k8s_manifests/prod/istio-networking/app-recommendation-vs-fault.yaml을 열어 내용을 검사합니다. Istio에는 요청의 일정 비율에 오류를 삽입하는 옵션이 있습니다. 여기서는 모든 recommendationservice 요청에 시간 제한을 도입합니다.
출력(복사 금지)
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: recommendation-delay-fault
spec:
hosts:
- recommendationservice.recommendation.svc.cluster.local
http:
- route:
- destination:
host: recommendationservice.recommendation.svc.cluster.local
fault:
delay:
percentage:
value: 100
fixedDelay: 5s
- VirtualService를 k8s_repo에 복사합니다. 두 리전 모두에 전역적으로 장애를 삽입합니다.
cp $ASM/k8s_manifests/prod/istio-networking/app-recommendation-vs-fault.yaml ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/app-recommendation-vs-fault.yaml
cd ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/; kustomize edit add resource app-recommendation-vs-fault.yaml
cp $ASM/k8s_manifests/prod/istio-networking/app-recommendation-vs-fault.yaml ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/app-recommendation-vs-fault.yaml
cd ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/; kustomize edit add resource app-recommendation-vs-fault.yaml
- 변경사항 푸시
cd $K8S_REPO
git add . && git commit -am "Fault Injection: recommendationservice"
git push
cd $ASM
- Cloud Build가 완료될 때까지 기다립니다.
- 서킷 브레이커 섹션에 배포된 fortio 포드로 실행하고 recommendationservice로 일부 트래픽을 보냅니다.
FORTIO_POD=$(kubectl --context ${DEV1_GKE_1} get pod -n shipping | grep fortio | awk '{ print $1 }')
kubectl --context ${DEV1_GKE_1} exec -it $FORTIO_POD -n shipping -c fortio /usr/bin/fortio -- load -grpc -c 100 -n 100 -qps 0 recommendationservice.recommendation.svc.cluster.local:8080
Once the fortio command is complete, you should see responses averaging 5s:
출력(복사 금지)
Ended after 5.181367359s : 100 calls. qps=19.3 Aggregated Function Time : count 100 avg 5.0996506 +/- 0.03831 min 5.040237641 max 5.177559818 sum 509.965055
- 삽입한 결함을 확인하는 또 다른 방법은 웹브라우저에서 프런트엔드를 열고 제품을 클릭하는 것입니다. 제품 페이지는 페이지 하단에 표시되는 추천을 가져오므로 로드하는 데 5초가 추가로 걸립니다.
- 두 Ops 클러스터에서 장애 주입 서비스를 삭제하여 정리합니다.
kubectl --context ${OPS_GKE_1} delete virtualservice recommendation-delay-fault -n recommendation
rm ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/app-recommendation-vs-fault.yaml
cd ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/; kustomize edit remove resource app-recommendation-vs-fault.yaml
kubectl --context ${OPS_GKE_2} delete virtualservice recommendation-delay-fault -n recommendation
rm ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/app-recommendation-vs-fault.yaml
cd ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/; kustomize edit remove resource app-recommendation-vs-fault.yaml
- 변경사항 푸시:
cd $K8S_REPO
git add . && git commit -am "Fault Injection cleanup / restore"
git push
cd $ASM
15. Istio 컨트롤 플레인 모니터링
ASM은 Pilot, Mixer, Galley, Citadel이라는 네 가지 중요한 제어 영역 구성요소를 설치합니다. 각각 관련 모니터링 측정항목을 Prometheus로 전송하고 ASM은 운영자가 이 모니터링 데이터를 시각화하고 제어 영역의 상태와 성능을 평가할 수 있는 Grafana 대시보드와 함께 제공됩니다.
대시보드 보기
- Istio로 설치된 Grafana 서비스 포트 전달
kubectl --context ${OPS_GKE_1} -n istio-system port-forward svc/grafana 3000:3000 >> /dev/null
- 브라우저에서 Grafana 열기
- Cloud Shell 창의 오른쪽 상단에 있는 '웹 미리보기' 아이콘을 클릭합니다.
- 포트 3000에서 미리보기를 클릭합니다. 포트가 3000이 아닌 경우 포트 변경을 클릭하고 포트 3000을 선택합니다.
- 그러면 브라우저에 'BASE_URL/?orgId=1&authuser=0&environment_id=default'와 비슷한 URL이 있는 탭이 열립니다.
- 사용 가능한 대시보드 보기
- URL을 'BASE_URL/dashboard'로 수정합니다.
- 'istio' 폴더를 클릭하여 사용 가능한 대시보드를 확인합니다.
- 이러한 대시보드 중 하나를 클릭하여 해당 구성요소의 실적을 확인할 수 있습니다. 다음 섹션에서는 각 구성요소의 중요한 측정항목을 살펴보겠습니다.
모니터링 파일럿
Pilot은 네트워킹 및 정책 구성을 데이터 영역 (Envoy 프록시)에 배포하는 컨트롤 플레인 구성요소입니다. 파일럿은 워크로드 및 배포 수에 따라 확장되는 경향이 있지만, 해당 워크로드로의 트래픽 양에 따라 확장되는 것은 아닙니다. 비정상 상태의 파일럿은 다음을 할 수 있습니다.
- 필요 이상으로 리소스를 소비합니다 (CPU 및/또는 RAM).
- 업데이트된 구성 정보가 Envoy에 푸시되는 데 지연이 발생할 수 있습니다.
참고: 파일럿이 다운되거나 지연이 발생하더라도 워크로드는 계속 트래픽을 처리합니다.
- 브라우저에서 'BASE_URL/dashboard/db/istio-pilot-dashboard'로 이동하여 파일럿 측정항목을 확인합니다.
중요한 모니터링 측정항목
리소스 사용량
허용되는 사용량에 대한 가이드로 Istio 성능 및 확장성 페이지를 사용하세요. 이보다 훨씬 더 지속적인 리소스 사용량이 표시되면 GCP 지원팀에 문의하세요.

파일럿 푸시 정보
이 섹션에서는 Envoy 프록시에 대한 구성의 파일럿 푸시를 모니터링합니다.
- 파일럿 푸시에는 특정 시점에 푸시된 구성 유형이 표시됩니다.
- ADS 모니터링에는 시스템의 가상 서비스, 서비스, 연결된 엔드포인트 수가 표시됩니다.
- 알려진 엔드포인트가 없는 클러스터에는 구성되었지만 실행 중인 인스턴스가 없는 엔드포인트가 표시됩니다 (예: *.googleapis.com과 같은 외부 서비스를 나타낼 수 있음).
- 파일럿 오류는 시간 경과에 따라 발생한 오류 수를 보여줍니다.
- 충돌은 리스너의 모호한 구성인 충돌 수를 보여줍니다.
오류 또는 충돌이 있는 경우 하나 이상의 서비스 구성이 잘못되었거나 일관되지 않습니다. 자세한 내용은 데이터 플레인 문제 해결을 참고하세요.
Envoy 정보
이 섹션에는 컨트롤 플레인에 연결하는 Envoy 프록시에 관한 정보가 포함되어 있습니다. XDS 연결 실패가 반복되면 GCP 지원팀에 문의하세요.
믹서 모니터링
믹서는 Envoy 프록시의 원격 분석을 원격 분석 백엔드 (일반적으로 Prometheus, Stackdriver 등)로 전달하는 구성요소입니다. 이 경우 데이터 영역에 없습니다. 두 개의 서로 다른 서비스 이름 (istio-telemetry 및 istio-policy)으로 배포된 두 개의 Kubernetes 작업 (믹서라고 함)으로 배포됩니다.
믹서를 사용하여 정책 시스템과 통합할 수도 있습니다. 이러한 이유로 Mixer는 서비스에 대한 액세스를 차단하는 Mixer에 대한 정책 검사가 실패하므로 데이터 영역에 영향을 미칩니다.
믹서는 트래픽 양에 따라 확장되는 경향이 있습니다.
- 브라우저에서 'BASE_URL/dashboard/db/istio-mixer-dashboard'로 이동하여 믹서 측정항목을 확인합니다.
중요한 모니터링 측정항목
리소스 사용량
허용되는 사용량에 대한 가이드로 Istio 성능 및 확장성 페이지를 사용하세요. 이보다 훨씬 더 지속적인 리소스 사용량이 표시되면 GCP 지원팀에 문의하세요.

믹서 개요
- 응답 시간은 중요한 측정항목입니다. Mixer 원격 분석에 대한 보고서는 데이터 경로에 없지만 이러한 지연 시간이 높으면 사이드카 프록시 성능이 확실히 느려집니다. 90번째 백분위수는 한 자릿수 밀리초이고 99번째 백분위수는 100ms 미만일 것으로 예상됩니다.

- 어댑터 디스패치 기간은 Mixer가 원격 분석 및 로깅 시스템에 정보를 전송하는 어댑터를 호출할 때 발생하는 지연 시간을 나타냅니다. 여기에서 지연 시간이 높으면 메시의 성능에 영향을 미칩니다. 다시 말하지만 p90 지연 시간은 10ms 미만이어야 합니다.

모니터링 갤러리
Galley는 Istio의 구성 검증, 수집, 처리, 배포 구성요소입니다. Kubernetes API 서버에서 Pilot으로 구성을 전달합니다. Pilot과 마찬가지로 시스템의 서비스 및 엔드포인트 수에 따라 확장되는 경향이 있습니다.
- 브라우저에서 'BASE_URL/dashboard/db/istio-galley-dashboard'로 이동하여 Galley 측정항목을 확인합니다.
중요한 모니터링 측정항목
리소스 유효성 검사
유효성 검사를 통과하거나 실패하는 대상 규칙, 게이트웨이, 서비스 항목과 같은 다양한 유형의 리소스 수를 나타내는 가장 중요한 측정항목입니다.
연결된 클라이언트
Galley에 연결된 클라이언트 수를 나타냅니다. 일반적으로 3개 (파일럿, istio-telemetry, istio-policy)이며 이러한 구성요소가 확장됨에 따라 확장됩니다.
16. Istio 문제 해결
데이터 영역 문제 해결
파일럿 대시보드에 구성 문제가 표시되면 파일럿 로그를 검사하거나 istioctl을 사용하여 구성 문제를 찾아야 합니다.
Pilot 로그를 검사하려면 kubectl -n istio-system logs istio-pilot-69db46c598-45m44 discovery를 실행하여 istio-pilot-... 을 문제 해결하려는 Pilot 인스턴스의 포드 식별자로 바꿉니다.
결과 로그에서 푸시 상태 메시지를 검색합니다. 예를 들면 다음과 같습니다.
2019-11-07T01:16:20.451967Z info ads Push Status: {
"ProxyStatus": {
"pilot_conflict_outbound_listener_tcp_over_current_tcp": {
"0.0.0.0:443": {
"proxy": "cartservice-7555f749f-k44dg.hipster",
"message": "Listener=0.0.0.0:443 AcceptedTCP=accounts.google.com,*.googleapis.com RejectedTCP=edition.cnn.com TCPServices=2"
}
},
"pilot_duplicate_envoy_clusters": {
"outbound|15443|httpbin|istio-egressgateway.istio-system.svc.cluster.local": {
"proxy": "sleep-6c66c7765d-9r85f.default",
"message": "Duplicate cluster outbound|15443|httpbin|istio-egressgateway.istio-system.svc.cluster.local found while pushing CDS"
},
"outbound|443|httpbin|istio-egressgateway.istio-system.svc.cluster.local": {
"proxy": "sleep-6c66c7765d-9r85f.default",
"message": "Duplicate cluster outbound|443|httpbin|istio-egressgateway.istio-system.svc.cluster.local found while pushing CDS"
},
"outbound|80|httpbin|istio-egressgateway.istio-system.svc.cluster.local": {
"proxy": "sleep-6c66c7765d-9r85f.default",
"message": "Duplicate cluster outbound|80|httpbin|istio-egressgateway.istio-system.svc.cluster.local found while pushing CDS"
}
},
"pilot_eds_no_instances": {
"outbound_.80_._.frontend-external.hipster.svc.cluster.local": {},
"outbound|443||*.googleapis.com": {},
"outbound|443||accounts.google.com": {},
"outbound|443||metadata.google.internal": {},
"outbound|80||*.googleapis.com": {},
"outbound|80||accounts.google.com": {},
"outbound|80||frontend-external.hipster.svc.cluster.local": {},
"outbound|80||metadata.google.internal": {}
},
"pilot_no_ip": {
"loadgenerator-778c8489d6-bc65d.hipster": {
"proxy": "loadgenerator-778c8489d6-bc65d.hipster"
}
}
},
"Version": "o1HFhx32U4s="
}
푸시 상태는 구성을 Envoy 프록시에 푸시하려고 할 때 발생한 문제를 나타냅니다. 이 경우 중복 업스트림 대상을 나타내는 '중복 클러스터' 메시지가 여러 개 표시됩니다.
문제 진단에 도움이 필요하면 Google Cloud 지원팀에 문의하세요.
구성 오류 찾기
istioctl을 사용하여 구성을 분석하려면 istioctl experimental analyze -k --context $OPS_GKE_1를 실행하세요. 이렇게 하면 시스템의 구성을 분석하고 문제와 제안된 변경사항을 표시합니다. 이 명령어로 감지할 수 있는 구성 오류의 전체 목록은 문서를 참고하세요.
17. 삭제
관리자가 cleanup_workshop.sh 스크립트를 실행하여 bootstrap_workshop.sh 스크립트로 생성된 리소스를 삭제합니다. 정리 스크립트를 실행하려면 다음 정보가 필요합니다.
- 조직 이름(예:
yourcompany.com) - 워크숍 ID -
YYMMDD-NN형식입니다(예:200131-01). - 관리자 GCS 버킷 - 부트스트랩 스크립트에 정의됩니다.
- Cloud Shell을 열고 아래의 모든 작업을 Cloud Shell에서 실행합니다. 아래 링크를 클릭하세요.
- 원하는 관리자 사용자로 gcloud에 로그인했는지 확인합니다.
gcloud config list
- asm 폴더로 이동합니다.
cd ${WORKDIR}/asm
- 삭제할 조직 이름과 워크숍 ID를 정의합니다.
export ORGANIZATION_NAME=<ORGANIZATION NAME>
export ASM_WORKSHOP_ID=<WORKSHOP ID>
export ADMIN_STORAGE_BUCKET=<ADMIN CLOUD STORAGE BUCKET>
- 다음과 같이 정리 스크립트를 실행합니다.
./scripts/cleanup_workshop.sh --workshop-id ${ASM_WORKSHOP_ID} --admin-gcs-bucket ${ADMIN_STORAGE_BUCKET} --org-name ${ORGANIZATION_NAME}