Istio를 사용하여 Google Kubernetes Engine에 ASP.NET Core 앱 배포 (2부)

1. 개요

실습 1부에서는 ASP.NET Core 애플리케이션을 만들어 컨테이너화하여 Google Kubernetes Engine (GKE)에 배포하고 Istio에서 관리하도록 트래픽을 구성했습니다.

실습의 두 번째 부분에서는 Kubernetes 클러스터와 첫 번째 실습의 애플리케이션이 이미 실행 중이라고 가정합니다. Istio가 최소한의 코드 변경으로 서비스를 관리, 모니터링, 보호하는 데 어떻게 도움이 되는지 살펴보겠습니다. 특히 측정항목, 추적, 서비스 시각화, 동적 트래픽 관리, 결함 주입과 같은 Istio의 기능을 살펴봅니다.

학습할 내용

  • Prometheus로 측정항목을 쿼리하는 방법을 설명합니다.
  • Grafana로 측정항목을 시각화하는 방법
  • 서비스의 새 버전을 만드는 방법
  • 서비스를 특정 버전으로 고정하는 방법
  • 여러 버전 간에 트래픽을 분할하는 방법
  • 서비스 호출에 결함을 주입하는 방법

필요한 항목

본 가이드를 어떻게 사용하실 계획인가요?

읽기만 할 계획입니다. 읽은 다음 연습 활동을 완료할 계획입니다.

귀하의 Google Cloud Platform 사용 경험을 평가해 주세요.

<ph type="x-smartling-placeholder"></ph> 초보자 중급 숙련도

2. 설정 및 요구사항

자습형 환경 설정

  1. Cloud Console에 로그인하고 새 프로젝트를 만들거나 기존 프로젝트를 다시 사용합니다. (Gmail 또는 G Suite 계정이 없으면 만들어야 합니다.)

H_hgylo4zxOllHaAbPKJ7VyqCKPDUnDhkr-BsBIFBsrB6TYSisg6LX-uqmMhh4sXUy_hoa2Qv87C2nFmkg-QAcCiZZp0qtpf6VPaNEEfP_iqt29KVLD-gklBWugQVeOWsFnJmNjHDw

dcCPqfBIwNO4R-0fNQLUC4aYXOOZhKhjUnakFLZJGeziw2ikOxGjGkCHDwN5x5kCbPFB8fiOzZnX-GfuzQ8Ox-UU15BwHirkVPR_0RJwl0oXrhqZmMIvZMa_uwHugBJIdx5-bZ6Z8Q

jgLzVCxk93d6E2bbonzATKA4jFZReoQ-fORxZZLEi5C3D-ubnv6nL-eP-iyh7qAsWyq_nyzzuEoPFD1wFOFZOe4FWhPBJjUDncnTxTImT3Ts9TM54f4nPpsAp52O0y3Cb19IceAEgQ

모든 Google Cloud 프로젝트에서 고유한 이름인 프로젝트 ID를 기억하세요(위의 이름은 이미 사용되었으므로 사용할 수 없습니다). 이 ID는 나중에 이 Codelab에서 PROJECT_ID라고 부릅니다.

  1. 그런 후 Google Cloud 리소스를 사용할 수 있도록 Cloud Console에서 결제를 사용 설정해야 합니다.

이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 가이드를 마친 후 비용이 결제되지 않도록 리소스 종료 방법을 알려주는 '삭제' 섹션의 안내를 따르세요. Google Cloud 새 사용자에게는 $300USD 상당의 무료 체험판 프로그램 참여 자격이 부여됩니다.

Cloud Shell 시작

Google Cloud를 노트북에서 원격으로 실행할 수도 있지만 이 Codelab에서는 Google Cloud에서 실행되는 명령줄 환경인 Google Cloud Shell을 사용합니다.

Cloud Shell 활성화

  1. Cloud Console에서 Cloud Shell 활성화dnDTxS9j60RcXdTjea12HLB9paS9Gzf7PfFLE9RW8g0Qx1bz7nmCzyCu4rjluX3bOEwavOpDwioXEkzOf6xtZp6-ZbJa08jwJqtv3WjFwDqOXtZp6-ZbJa08jwJqtv3WjFwDqOZqtv3Wfi0Fq를 클릭합니다.

yzBQBp2RC1EFvSSLYVkMA2m6LHqGsp22O81rUS5tGb9Y1FqlVhoRj_ka8V_uEjtpcirZRULMy1IjNr848uYvb9mC9RcGGqeayaLcXFfRwUGeXWChZPtWkHzUshTcqx_wJHis0X8viA

이전에 Cloud Shell을 시작하지 않았으면 설명이 포함된 중간 화면(스크롤해야 볼 수 있는 부분)이 제공됩니다. 이 경우 계속을 클릭합니다(이후 다시 표시되지 않음). 이 일회성 화면은 다음과 같습니다.

VgsaqGbKPRiqK24CqAKjSXjepuJT96PmiDqQMcySmWKx8QyW5F3G2D8JH2d08ek-YM77wWKxPvggpOFER8Hbq3aaZipTDU2o0il7A0kSqD3FXY_NcdFhrtGbj

Cloud Shell을 프로비저닝하고 연결하는 데 몇 분 정도만 걸립니다.

7RuYr-LCKzdiE1veTFmL_lYrVxsMZ6-xDoxAnfwPPc5uFA0utmFGejvu81jGmTdbqnqxrytW3KcHT6xrMIRc3bskctnDZC5nJdpqw-LRxu3r35hL4A0BSBTtbtirfh3PKv-eOKt8Rg

가상 머신에는 필요한 개발 도구가 모두 들어있습니다. 영구적인 5GB 홈 디렉터리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 Codelab에서 대부분의 작업은 브라우저나 Chromebook만 사용하여 수행할 수 있습니다.

Cloud Shell에 연결되면 인증이 완료되었고 프로젝트가 해당 프로젝트 ID로 이미 설정된 것을 볼 수 있습니다.

  1. Cloud Shell에서 다음 명령어를 실행하여 인증되었는지 확인합니다.
gcloud auth list

명령어 결과

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
gcloud config list project

명령어 결과

[core]
project = <PROJECT_ID>

또는 다음 명령어로 설정할 수 있습니다.

gcloud config set project <PROJECT_ID>

명령어 결과

Updated property [core/project].

3. 애플리케이션 테스트

실습을 시작하기 전에 애플리케이션이 이전 실습에서 계속 작동하는지 확인합니다. 참고로 EXTERNAL-IP 아래에 나열된 게이트웨이의 외부 IP 및 포트는 다음과 같습니다.

kubectl get svc istio-ingressgateway -n istio-system

애플리케이션을 보려면 브라우저를 열고 http://<gatewayurl>로 이동하면 됩니다.

f579a9baedc108a9.png

애플리케이션이 표시되지 않으면 이전 실습으로 돌아가서 모든 단계를 따랐고 애플리케이션과 Istio가 모두 설치되어 제대로 실행되고 있는지 확인합니다.

이 시점에서 ' Istio의 이점은 무엇인가요?'가 궁금할 수 있습니다. Istio에서 애플리케이션 트래픽을 관리하도록 하여 측정항목, 추적, 동적 트래픽 관리, 서비스 시각화, 결함 주입 등의 기능을 무료로 사용할 수 있습니다.

다음 단계에서는 측정항목 살펴보기로 시작합니다.

4. Grafana 및 Prometheus를 사용한 측정항목

기본적으로 Istio는 일부 측정항목을 생성합니다. 부가기능을 사용하여 이러한 기본 측정항목을 쿼리하고 시각화할 수 있습니다.

Prometheus

Prometheus는 오픈소스 모니터링 솔루션입니다. Prometheus를 사용하여 Istio에서 생성된 측정항목을 쿼리할 수 있지만 먼저 Prometheus 부가기능을 설치해야 합니다.

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/prometheus.yaml

Prometheus가 실행 중인지 확인합니다.

kubectl get svc prometheus -n istio-system

NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
prometheus   ClusterIP   10.31.243.62   <none>        9090/TCP   1d

http://<gatewayurl>을 몇 번 방문하거나 curl 명령어를 실행하여 애플리케이션에 일부 트래픽을 전송합니다.

Prometheus UI의 포트 전달을 설정합니다.

kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=prometheus -o jsonpath='{.items[0].metadata.name}') 8080:9090

이제 Cloud Shell의 오른쪽 상단에 있는 웹 미리보기 버튼을 클릭하고 포트 8080에서 미리보기를 클릭하여 쿼리를 실행할 수 있습니다.

772a5248aa493025.png

새 탭에 Prometheus UI가 표시됩니다.

272ee63c1fe0be16.png

Prometheus에 대한 자세한 내용은 Prometheus로 측정항목 쿼리를 참조하세요.

Grafana

Grafana는 측정항목 시각화를 위한 또 다른 부가기능입니다.

Grafana를 설치합니다. istio-version를 현재 Istio 버전(예: 1.0.3-gke.3)으로 바꿉니다.

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/grafana.yaml

Grafana가 실행 중인지 확인합니다.

kubectl get svc grafana -n istio-system

NAME      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
grafana   ClusterIP   10.31.248.230   <none>        3000/TCP   1d

http://<gatewayurl>을 몇 번 방문하거나 curl 명령어를 실행하여 애플리케이션에 일부 트래픽을 전송합니다.

Grafana UI에 포트 포워딩을 설정합니다.

kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 8080:3000

웹 미리보기로 이동하여 Grafana 대시보드를 볼 수 있습니다.

806d696d85267a37.png

524cb9f6d66f8655.png

Granfana에 대한 자세한 내용은 Grafana로 측정항목 시각화를 참조하세요.

5. 애플리케이션의 새 버전 만들기

프로덕션에 배포한 애플리케이션에는 버그 수정이나 추가 기능이 필요합니다. 그 과정을 살펴보겠습니다.

먼저 애플리케이션을 수정해 보겠습니다. Cloud Shell에서 코드 편집기를 엽니다.

mxrggIJ2Zz8E47ULCEo4NywjM-EpSkZF5c3TQgfGx4nODwP2obiQXrwQjEEaXuBhJDA2jJ5evR7TuHIy1gsqqDRFm0Wh3xhZUu9tn_xb1ygFlBm1HKJqLdfz_aK7WJS33u2IBDO2oQ

HelloWorldAspNetCore > Views > Home 아래의 Index.cshtml로 이동하여 캐러셀 메시지 중 하나를 업데이트합니다.

다음 줄을 찾습니다.

Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core 

그리고 다음과 같이 변경합니다.

Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core on Google Cloud

변경사항을 저장한 다음 Cloud Shell로 돌아갑니다. HelloWorldAspNetCore, 내에서 Docker 이미지를 빌드합니다.

docker build -t gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v2 . 

Container Registry로 푸시합니다.

docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v2 

컨테이너 이미지를 푸시한 후 다음 단계에서 새 버전을 배포할 수 있습니다.

6. 새 배포 만들기

새 버전을 배포하려면 먼저 Kubernetes에서 새 배포를 만들어야 합니다. aspnetcore.yaml 파일 끝에 다음을 추가합니다.

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: aspnetcore-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: aspnetcore
      version: v2
  template:
    metadata:
      labels:
        app: aspnetcore
        version: v2
    spec:
      containers:
      - name: aspnetcore
        image: gcr.io/YOUR-PROJECT-ID/hello-dotnet:v2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

kubectl를 사용하여 기본 네임스페이스에 새 버전을 배포합니다.

kubectl apply -f aspnetcore.yaml
service "aspnetcore" unchanged
deployment.extensions "aspnetcore-v1" unchanged
deployment.extensions "aspnetcore-v2" created

예상 포드가 실행 중인지 확인합니다.

kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
aspnetcore-v1-6cf64748-mddb   2/2       Running   0          34s
aspnetcore-v2-5d765db-l9xmg   2/2       Running   0          1m

이제 애플리케이션을 다시 테스트합니다. 게이트웨이의 외부 IP를 가져옵니다.

kubectl get svc istio-ingressgateway -n istio-system

외부 IP 아래에 표시되어 있습니다. 시크릿 모드 브라우저를 열고 http://<replace-with-external-ip>로 이동합니다.

새로고침하면 가끔 'Learn about building Web apps with ASP.NET Core'라는 메시지가 표시됩니다.

11d528132dbb6cee.png

다른 경우에는 'Learn about build Web apps with ASP.NET Core on Google Cloud'(Google Cloud에서 ASP.NET Core를 사용하여 웹 앱을 빌드하는 방법 알아보기)

3eb0d5be1b4cb40b.png

이는 v1v2 배포가 모두 동일한 Kubernetes 서비스 (aspnetcore-service) 뒤에 노출되고 이전 실습에서 만든 VirtualService (aspnetcore-virtualservice)가 이 서비스를 호스트로 사용하기 때문입니다.

다음 단계에서는 DestinationRule을 사용하여 v2 배포에 서비스를 고정합니다.

7. 새 버전으로 서비스 고정

이 단계에서는 v2 배포를 사용하도록 서비스를 고정하고 DestinationRule을 사용하여 고정합니다. DestinationRule은 VirtualService 라우팅 작업이 발생한 후 요청에 적용할 정책 집합을 구성합니다.

DestinationRule은 해당 대상 호스트의 주소 지정 가능한 하위 집합(이름이 지정된 버전)을 정의합니다. 이러한 하위 집합은 트래픽을 특정 버전의 서비스로 전송할 때 VirtualService 경로 사양에 사용됩니다.

aspnetcore-destinationrule.yaml라는 새 파일을 만듭니다.

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: aspnetcore-destinationrule
spec:
  host: aspnetcore-service
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

그런 다음 DestinationRule을 만듭니다. 이렇게 하면 VirtualService에서 사용할 수 있는 두 개의 하위 집합 (v1 및 v2)이 생성됩니다.

kubectl apply -f aspnetcore-destinationrule.yaml
destinationrule.networking.istio.io "aspnetcore-destionationrule" created

이제 aspnetcore-virtualservice.yaml 파일로 돌아가서 v2 하위 집합을 사용하도록 VirtualService를 업데이트합니다.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - route:
    - destination:
        host: aspnetcore-service
        subset: v2

VirtualService를 업데이트합니다.

kubectl apply -f aspnetcore-virtualservice.yaml

브라우저를 열고 http://<replace-with-external-ip>.으로 이동합니다. 여러 번 새로고침한 후에도 'Learn about ASP.NET Core on Google Cloud' 메시지가 표시됩니다.

3eb0d5be1b4cb40b.png

8. 버전 간 트래픽 분할

테스트를 위해 버전 간에 트래픽을 분할해야 하는 경우가 있습니다. 예를 들어 트래픽의 75% 를 v1에 보내고 25% 를 v2 버전으로 보낼 수 있습니다. Istio를 사용하면 이를 쉽게 수행할 수 있습니다. 가중치가 다른 두 하위 집합을 참조하는 새 aspnetcore-virtualservice-weights.yaml 파일을 만듭니다.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - route:
    - destination:
        host: aspnetcore-service
        subset: v1
      weight: 75
    - destination:
        host: aspnetcore-service
        subset: v2
      weight: 25

VirtualService를 업데이트합니다.

kubectl apply -f aspnetcore-virtualservice-weights.yaml

이제 브라우저를 새로고침하면 v1과 v2 버전의 비율이 대략 3:1로 표시됩니다.

자세한 내용은 Istio의 트래픽 분할을 참조하세요.

9. 결함 삽입

테스트를 위해 할 수 있는 또 다른 유용한 개발 작업은 트래픽에 오류나 지연을 주입하고 이에 대응하여 서비스가 어떻게 작동하는지 확인하는 것입니다.

예를 들어 v1 버전으로 트래픽의 50% 에 대해 잘못된 요청 (HTTP 400) 응답을 반환하려고 할 수 있습니다. 다음과 일치하도록 aspnetcore-virtualservice-fault-abort.yaml 파일을 만듭니다.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - fault:
      abort:
        percentage:
          value: 50
        httpStatus: 400
    route:
    - destination:
        host: aspnetcore-service
        subset: v1

VirtualService를 업데이트합니다.

kubectl apply -f aspnetcore-virtualservice-fault-abort.yaml

이제 브라우저를 새로고침하면 v1 서비스가 HTTP 400s 응답 코드를 반환하는 시간의 절반에 해당하는 것을 확인할 수 있습니다.

또는 요청에 5초 지연을 추가할 수 있습니다. 다음과 일치하도록 aspnetcore-virtualservice-fault-delay.yaml 파일을 만듭니다.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - fault:
      delay:
        fixedDelay: 5s
        percentage:
          value: 100
    route:
    - destination:
        host: aspnetcore-service
        subset: v1

VirtualService를 업데이트합니다.

kubectl apply -f aspnetcore-virtualservice-fault-delay.yaml

이제 브라우저를 새로고침하면 요청이 5초 지연되는 것을 확인할 수 있습니다.

시간 초과, 재시도, 조건부 규칙, 회로 차단기 등과 같은 Istio 기능에 대한 자세한 내용은 트래픽 관리 기능을 참조하세요.

10. 축하합니다.

이 실습을 통해 Istio가 서비스에 즉시 수행할 수 있는 작업을 간략하게 살펴보았기를 바랍니다. Istio 및 GKE 자세히 알아보기

다음 단계

라이선스

이 작업물은 Creative Commons Attribution 2.0 일반 라이선스에 따라 사용이 허가되었습니다.

11. 삭제

앱을 삭제하고 Istio를 제거하거나 Kubernetes 클러스터를 삭제할 수 있습니다.

애플리케이션 삭제

애플리케이션을 삭제하려면 다음 안내를 따르세요.

kubectl delete -f aspnetcore-gateway.yaml
kubectl delete -f aspnetcore-virtualservice.yaml
kubectl delete -f aspnetcore-destinationrule.yaml
kubectl delete -f aspnetcore.yaml

애플리케이션이 사라졌는지 확인하려면 다음 단계를 따르세요.

kubectl get gateway 
kubectl get virtualservices
kubectl get destinationrule
kubectl get pods

Istio 제거

Istio를 삭제하려면 다음 안내를 따르세요.

kubectl delete -f install/kubernetes/istio-demo-auth.yaml

Istio가 사라졌는지 확인하려면 다음 안내를 따르세요.

kubectl get pods -n istio-system

Kubernetes 클러스터 삭제

gcloud container clusters delete hello-dotnet-cluster