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

1. 개요

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

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

학습할 내용

  • Prometheus로 측정항목을 쿼리하는 방법
  • Grafana로 측정항목을 시각화하는 방법
  • 서비스의 새 버전을 만드는 방법
  • 서비스를 특정 버전에 고정하는 방법
  • 여러 버전 간에 트래픽을 분할하는 방법
  • 서비스 호출에 오류를 삽입하는 방법

필요한 항목

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

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

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

초급 중급 고급

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-ZbJa08jwJqtmeeW8jZ1tYfi2lyXqvW3WFHP0eAxDkQDfpO9Ljw를 클릭합니다.

yzBQBp2RC1EFvSSLYVkMA2m6LHqGsp22O81rUS5tGb9Y1FqlVhoRj_ka8V_uEjtpcirZRULMy1IjNr848uYvb9mC9RcGGqeayaLcXFfRwUGeXWChZPtWkHzUshTcqx_wJHis0X8viA

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

VgsaqGbKPRiqK24CqAKjSXjepuJT96PmiDqQMcySmWKx8QyW5F3G2D8JH2d08ek-YM77wWKxPvggpOFER8Hbq3aaZipTDU2o0il7A0kS3FXY_NzuujjEqDF1nsbDKkNMThrqcdMGtQ

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

Grafana에 대해 자세히 알아보려면 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>로 이동합니다.

새로고침하면 'ASP.NET Core로 웹 앱 빌드에 대해 알아보기'라는 메시지가 표시될 수 있습니다.

11d528132dbb6cee.png

'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>.로 이동합니다. 여러 번 새로고침한 후에도 'Google Cloud에서 ASP.NET Core로 웹 앱 빌드 알아보기'라는 메시지가 표시됩니다.

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 400 응답 코드를 반환하는 것을 확인할 수 있습니다.

또는 요청에 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