본문 바로가기
MLOps/Doker & Kubernetes

[클라우드 스터디잼] Managing Deployments Using Kubernetes Engine

by 공부하는 무니 2022. 7. 12.
반응형

* 클라우드 스터디잼 쿠버네티스 입문반 과정을 수강하면서 정리한 내용입니다.

Overview

Dev Ops 방식에서는 정기적으로 multiple deployments를 사용하여 'Continuous Deployment', 'Blue-Green Deployments', 'Canary Deployments'와 같은 애플리케이션 배포 시나리오를 관리합니다. 이 실습에서는 Heterogeneous deployments 가 사용되는 일반적인 시나리오를 처리할 수 있도록 컨테이너를 확장 및 관리하는 연습이 제공됩니다.

What you'll do

  • Practice with kubectl tool
  • Create deployment yaml files
  • Launch, update, and scale deployments
  • Practice with updating deployments and deployment styles

Prerequisites

Introduction to deployments

Heterogeneous deployments 에서는 일반적으로 특정한 기술적 요구 또는 운영상의 요구를 충족하기 위해 2개 이상의 상이한 인프라 환경 또는 regions을 연결합니다. Heterogeneous deployments 는 배포 특성에 따라 'hybrid', 'multi-cloud' 또는 'public-private'이라고 부릅니다. 이 실습에서 Heterogeneous deployments 에는 단일 클라우드 환경이나 다중 퍼블릭 클라우드 환경(multi-cloud), 또는 온프레미스와 퍼블릭 클라우드가 조합된 환경(hybrid or public-private)에서 진행하는 다수의 리전에 걸친 배포가 포함됩니다.

단일 환경 또는 리전에 한정된 배포에서는 다양한 비즈니스 및 기술적 난점이 발생할 수 있습니다.

  • Maxed out resources (여유 리소스 부족): 단일 환경, 특히 온프레미스 환경에서는 프로덕션 요구를 충족시킬 수 있는 컴퓨팅, 네트워킹, 저장소 리소스가 모자랄 수 있습니다.
  • Limited geographic reach (제한된 지리적 범위): 단일 환경에서의 배포를 위해서는 지리적으로 서로 멀리 떨어진 사용자들이 하나의 배포에 액세스해야 합니다. 이러한 사용자의 트래픽은 특정 위치까지 전 세계를 돌아서 이동합니다.
  • Limited availability (제한된 가용성): Web-scale traffic patterns 에서는 애플리케이션의 fault-tolerantresilient 이 상당히 요구됩니다.
  • Vendor lock-in (공급업체 고착화): 공급업체 수준의 플랫폼 및 인프라 추상화로 인해 애플리케이션 이식이 어려울 수 있습니다.
  • Inflexible resources (유연하지 않은 리소스): 특정 컴퓨팅, 저장소 또는 네트워킹 offerings 등으로 리소스가 제한될 수 있습니다.

Heterogeneous deployments 는 이러한 문제를 해결하는 데 도움이 될 수 있지만, programmatic하며 deterministic인 프로세스와 절차를 사용해서 아키텍처를 구성해야 합니다. 일회성 또는 임시 배포 절차는 배포 또는 프로세스의 취약성을 높이고 내결함성을 저하시킬 수 있습니다. 임시 프로세스는 데이터 손실 또는 트래픽 drop을 일으킬 수 있습니다. 올바른 배포 프로세스는 반복 가능해야 하며, 입증된 프로비저닝, 구성, 유지 관리 방식을 사용해야 합니다.

Heterogeneous deployments를 위한 일반적인 시나리오는 multi-cloud deployments, fronting on-premises data, continuous integration/continuous delivery (CI/CD) processes 입니다.

다음 실습에서는 Kubernetes 및 다른 인프라 리소스를 사용한 잘 구성된 접근 방법과 함께 Heterogeneous deployments를 위한 몇 가지 일반적인 사용 사례를 연습합니다.

 

Setup

Set zone

다음 명령어를 실행하여 GCP 영역을 설정하고, 로컬 영역을 us-central1-a로 대체합니다.

▼ 명령어

gcloud config set compute/zone us-central1-a

▼ 아웃풋

Get sample code for this lab

컨테이너와 deployments를 만들고 실행하기 위한 샘플 코드를 가져옵니다.

▼ 명령어

gsutil -m cp -r gs://spls/gsp053/orchestrate-with-kubernetes .
cd orchestrate-with-kubernetes/kubernetes

▼ 아웃풋

 

n1-standard-1 노드 5개로 클러스터를 만듭니다. 이 작업은 완료하는 데 몇 분 정도 걸릴 수 있습니다.

▼ 명령어

gcloud container clusters create bootcamp --num-nodes 5 --scopes "https://www.googleapis.com/auth/projecthosting,storage-rw"

▼ 아웃풋

Learn about the deployment object

배포를 시작해 보겠습니다. 먼저 배포 객체를 살펴보겠습니다. kubectl explain 명령어를 통해 배포 객체에 관해 알 수 있습니다.

▼ 명령어

kubectl explain deployment

▼ 아웃풋

--recursive 옵션을 사용하여 모든 필드를 볼 수도 있습니다.

▼ 명령어

kubectl explain deployment --recursive

▼ 아웃풋

실습을 진행하는 과정에서 explain 명령어를 사용하면 배포 객체의 구조를 이해하고 개별 필드의 기능을 이해하는 데 도움이 됩니다.

▼ 명령어

kubectl explain deployment.metadata.name

▼ 아웃풋

Create a deployment

deployments/auth.yaml configuration file을 업데이트합니다.

▼ 명령어

vi deployments/auth.yaml

편집기를 시작합니다.

▼ 아웃풋

▼ 명령어

i

Deployment의 containers 섹션에 있는 image를 다음과 같이 변경합니다.

▼ 명령어

...
containers:
- name: auth
  image: "kelseyhightower/auth:1.0.0"
...

▼ 아웃풋

auth.yaml 파일을 저장하고 <Esc>를 누릅니다.

▼ 명령어

:wq

<Enter>를 누릅니다. 이제 간단한 deployment를 만들겠습니다. deployment configuration file을 검사합니다.

▼ 명령어

cat deployments/auth.yaml

▼ 아웃풋

apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth
spec:
  replicas: 1
  selector:
    matchLabels:
      app: auth
  template:
    metadata:
      labels:
        app: auth
        track: stable
    spec:
      containers:
        - name: auth
          image: "kelseyhightower/auth:1.0.0"
          ports:
            - name: http
              containerPort: 80
            - name: health
              containerPort: 81
...

deployment를 통해 어떻게 하나의 replica가 생성되고 버전 1.0.0의 auth 컨테이너를 사용하는지 확인하세요.

kubectl create 명령어를 실행하여 auth deployment를 만들면 Deployment manifest의 데이터에 따라 하나의 pod가 생성됩니다. 즉, replicas 필드에 지정된 숫자를 변경하여 pod의 수를 조정할 수 있습니다.

 

kubectl create를 사용하여 deployment 객체를 만듭니다.

▼ 명령어

kubectl create -f deployments/auth.yaml

▼ 아웃풋

deployment를 만들면 생성 여부를 확인할 수 있습니다.

▼ 명령어

kubectl get deployments

▼ 아웃풋

deployment가 생성되면, Kubernetes에서는 Deployment에 관한 ReplicaSet를 만듭니다. Deployment에 관한 ReplicaSet이 생성되었는지 확인할 수 있습니다.

▼ 명령어

kubectl get replicasets

▼ 아웃풋

이름이 auth-xxxxxxx인 ReplicaSet이 표시되어야 합니다.

 

마지막으로, Deployment의 일부로 생성된 Pods를 볼 수 있습니다. ReplicaSet이 생성될 때 Kubernetes에서 단일 Pod를 생성합니다.

▼ 명령어

kubectl get pods

▼ 아웃풋

이제 auth deployment를 위한 서비스를 만들 차례입니다. 서비스 매니페스트 파일은 이미 살펴보았으므로 여기서는 자세히 설명하지 않겠습니다. kubectl create 명령어를 사용하여 auth 서비스를 만듭니다.

▼ 명령어

kubectl create -f services/auth.yaml

▼ 아웃풋

이제 같은 방법으로 hello Deployment를 만들고 노출합니다.

▼ 명령어

kubectl create -f deployments/hello.yaml
kubectl create -f services/hello.yaml

▼ 아웃풋

 

한번 더 frontend Deployment를 만들고 노출합니다.

▼ 명령어

kubectl create secret generic tls-certs --from-file tls/
kubectl create configmap nginx-frontend-conf --from-file=nginx/frontend.conf
kubectl create -f deployments/frontend.yaml
kubectl create -f services/frontend.yaml

Note: You created a ConfigMap for the frontend.

▼ 아웃풋

외부 IP를 가져와서 프런트엔드와 연결함으로써 프런트엔드와 상호작용합니다.

▼ 명령어

kubectl get services frontend

▼ 아웃풋

서비스에 대해 ExternalIP 필드가 채워지는 데 몇 초 정도 걸릴 수 있습니다. 이것은 정상입니다. 필드가 채워질 때까지 몇 초마다 위의 명령을 다시 실행하십시오.

▼ 명령어

curl -ks https://<EXTERNAL-IP>

▼ 아웃풋

그러면 hello 응답을 받게 됩니다.

kubectl의 출력 템플릿 기능을 사용하여 curl을 한 줄 명령어로 사용할 수도 있습니다.

▼ 명령어

curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`

▼ 아웃풋

 

Scale a Deployment

이제 Deployment가 생성되었으므로 확장할 수 있습니다. spec.replicas 필드를 업데이트하면 됩니다. kubectl explain 명령어를 다시 사용하여 이 필드에 관한 설명을 볼 수 있습니다.

▼ 명령어

kubectl explain deployment.spec.replicas

▼ 아웃풋

replicas 필드를 가장 쉽게 업데이트하는 방법은 kubectl scale 명령어를 사용하는 것입니다.

▼ 명령어

kubectl scale deployment hello --replicas=5

참고: 새 pod가 모두 시작되는 데는 1~2분 정도 걸릴 수 있습니다.

▼ 아웃풋

Deployment가 업데이트된 후, Kubernetes는 연결된 ReplicaSet를 자동으로 업데이트하고 새로운 pod를 시작하여 pod의 총 개수를 5로 만듭니다.

현재 hello Pods가 5개 실행되고 있는지 확인합니다.

▼ 명령어

kubectl get pods | grep hello- | wc -l

▼ 아웃풋

이제 애플리케이션을 다시 축소합니다.

▼ 명령어

kubectl scale deployment hello --replicas=3

▼ 아웃풋

Pods개수가 맞는지 다시 확인합니다.

▼ 명령어

kubectl get pods | grep hello- | wc -l

▼ 아웃풋

지금까지 Kubernetes deployments와 Pod 그룹을 관리하고 확장하는 방법을 알아보았습니다.

 

Rolling update

Deploymentsrolling update 메커니즘을 통해 이미지를 새 버전으로 업데이트하도록 지원합니다. Deployment가 새 버전으로 업데이트되면 새 ReplicaSet가 만들어지고, 이전 ReplicaSet의 replicas가 감소하면서 새 ReplicaSet의 replicas 수가 천천히 증가합니다.

Trigger a rolling update

Deployment를 업데이트하려면 다음 명령어를 실행합니다.

▼ 명령어

kubectl edit deployment hello

▼ 아웃풋

Deployment의 containers 섹션에 있는 image를 다음과 같이 변경합니다.

▼ 명령어

...
containers:
  image: kelseyhightower/hello:2.0.0
...

저장 후 종료합니다.

편집기에서 저장하면, 업데이트된 Deployment가 클러스터에 저장되고 Kubernetes에서 rolling update가 시작됩니다.

 

Kubernetes에서 생성한 새로운 ReplicaSet를 확인합니다.

▼ 명령어

kubectl get replicaset

▼ 아웃풋

rollout history에 새로운 entry가 표시될 수도 있습니다.

▼ 명령어

kubectl rollout history deployment/hello

▼ 아웃풋

Pause a rolling update

실행 중인 rollout에 문제가 발생하면 일시중지하여 업데이트를 중지합니다. 지금 중지해보세요.

▼ 명령어

kubectl rollout pause deployment/hello

▼ 아웃풋

현재 rollout 상태를 확인합니다.

▼ 명령어

kubectl rollout status deployment/hello

▼ 아웃풋

Pods에서 직접 확인할 수도 있습니다.

▼ 명령어

kubectl get pods -o jsonpath --template='{range .items[*]}{.metadata.name}{"\t"}{"\t"}{.spec.containers[0].image}{"\n"}{end}'

▼ 아웃풋

Resume a rolling update

rollout이 일시중지되었으므로 일부 pods는 새 버전이고 일부 pods는 이전 버전입니다. resume 명령어를 사용하여 rollout을 계속 진행할 수 있습니다.

▼ 명령어

kubectl rollout resume deployment/hello

▼ 아웃풋

rollout이 완료되면 status 명령어를 실행할 때 다음이 표시됩니다.

▼ 명령어

kubectl rollout status deployment/hello

▼ 아웃풋

deployment "hello" successfully rolled out

Rollback an update

새 버전에서 버그가 발견되었다고 가정해 보겠습니다. 새 버전에 문제가 있는 것으로 간주되므로 새 Pods에 연결된 모든 사용자가 문제를 경험하게 됩니다.

이전 버전으로 롤백하여 문제를 조사한 다음 제대로 수정된 버전을 출시할 수 있습니다.

rollout 명령어를 사용하여 이전 버전으로 롤백합니다.

▼ 명령어

kubectl rollout undo deployment/hello

▼ 아웃풋

history에서 롤백을 확인합니다.

▼ 명령어

kubectl rollout history deployment/hello

▼ 아웃풋

마지막으로, 모든 Pods가 이전 버전으로 롤백되었는지 확인합니다.

▼ 명령어

kubectl get pods -o jsonpath --template='{range .items[*]}{.metadata.name}{"\t"}{"\t"}{.spec.containers[0].image}{"\n"}{end}'

▼ 아웃풋

축하합니다. 지금까지 Kubernetes deployments rolling updates 및 다운타임 없이 애플리케이션을 업데이트하는 방법을 알아보았습니다.

 

Canary deployments

프로덕션 환경에서 일부 사용자를 대상으로 새 배포를 테스트하려면 Canary 배포를 사용하세요. Canary 배포를 사용하면 작은 규모의 일부 사용자에게만 변경 사항을 릴리스하여 새로운 릴리스와 관련된 위험을 완화할 수 있습니다.

Canary 배포 만들기

Canary 배포는 새 버전의 별도 배포와, 기존 안정화 배포 및 Canary 배포를 동시에 대상으로 삼는 서비스로 구성됩니다.

먼저 새 버전의 새로운 Canary deployment를 만듭니다.

▼ 명령어

cat deployments/hello-canary.yaml

▼ 아웃풋

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      labels:
        app: hello
        track: canary
        # Use ver 2.0.0 so it matches version on service selector
        version: 2.0.0
    spec:
      containers:
        - name: hello
          image: kelseyhightower/hello:2.0.0
          ports:
            - name: http
              containerPort: 80
            - name: health
              containerPort: 81
...

이제 Canary deployment를 만듭니다.

▼ 명령어

kubectl create -f deployments/hello-canary.yaml

▼ 아웃풋

Canary deployment를 만들면 hello  hello-canary의 두 가지 deployments가 생깁니다. 다음 kubectl 명령어로 확인하세요.

▼ 명령어

kubectl get deployments

▼ 아웃풋

hello 서비스에서 selector는 프로덕션 배포 및 Canary 배포의 pod에 모두 맞는 app:hello 선택기를 사용합니다. 그러나 Canary 배포가 파드 수가 더 적기 때문에 더 적은 수의 사용자에게 표시됩니다.

Verify the canary deployment

request에서 제공되는 hello 버전을 확인할 수 있습니다.

▼ 명령어

curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`/version

▼ 아웃풋

이 명령어를 여러 번 실행하면, 일부 requests는 hello 1.0.0에서 제공하고 small subset(1/4=25%)은 2.0.0에서 제공함을 알 수 있습니다.

Canary deployments in production - session affinity

이 실습의 사례에서는 Nginx 서비스로 전송된 모든 request가 Canary deployment에서 처리될 가능성이 있었습니다. 어떤 사용자가 Canary deployment를 통해 서비스를 받지 못하도록 하려면 다른 접근 방식이 필요합니다. 예를 들어, 애플리케이션의 UI가 변경되어 특정 사용자에게 혼동을 주지 않으려는 경우가 있을 수 있습니다. 이와 같은 경우에는 해당 사용자를 한 deployment 또는 다른 deployment에 '고정'해야 합니다.

서비스와 함께 세션 어피티니를 만들면 동일한 사용자에게 항상 동일한 버전을 제공할 수 있습니다. 아래 예제에서 서비스는 이전과 동일하지만 새로운 sessionAffinity 필드가 추가되어 ClientIP가 설정됩니다. IP 주소가 동일한 모든 클라이언트는 동일한 버전의 hello 애플리케이션으로 request를 보냅니다.

kind: Service
apiVersion: v1
metadata:
  name: "hello"
spec:
  sessionAffinity: ClientIP
  selector:
    app: "hello"
  ports:
    - protocol: "TCP"
      port: 80
      targetPort: 80

이를 테스트하기 위한 환경을 설정하기가 어렵기 때문에 여기에서는 테스트할 필요가 없지만, 프로덕션 환경의 Canary deployments에는 sessionAffinity를 사용할 수 있습니다.

 

Blue-green deployments

순차적 업데이트는 최소한의 오버헤드, 최소한의 성능 영향, 최소한의 다운타임으로 애플리케이션을 배포할 수 있기 때문에 가장 좋은 업데이트 방식입니다. 그러나 배포를 모두 완료한 후에 부하 분산기를 수정하여 새 버전을 가리키도록 하는 것이 유리한 경우가 있습니다. 이 경우에는 Blue/Green 배포가 도움이 됩니다.

Kubernetes에서는 이전의 'blue' 버전용 배포와 새로운 'green' 버전용 배포를 만들어 업데이트할 수 있습니다. 'blue' 버전에 기존 hello 배포를 사용하면 라우터 역할을 하는 서비스를 통해 배포에 액세스하게 됩니다. 새 'green' 버전이 가동 및 실행되면 서비스를 업데이트하여 이 버전을 사용하도록 전환하게 됩니다.

Blue-Green 배포의 주요 단점은 애플리케이션을 호스팅하려면 클러스터에 최소 2배의 리소스가 필요하다는 점입니다. 한 번에 두 버전의 애플리케이션을 배포하려면 먼저 클러스터에 충분한 리소스가 있는지 확인하세요.

 

The service

기존의 hello 서비스를 사용하되 app:hello, version: 1.0.0으로 selector를 업데이트하세요. selector는 기존의 'blue' deployment를 선택하지만 그러나 다른 버전을 사용할 것이기 때문에 'green' deployment는 선택하지 않습니다.

 

먼저 서비스를 업데이트합니다.

▼ 명령어

kubectl apply -f services/hello-blue.yaml

▼ 아웃풋

참고: resource service/hello is missing이라는 경고는 자동으로 패치되므로 무시하세요.

Updating using Blue-Green Deployment

Blue-Green 배포 스타일을 지원하기 위해 새 버전용으로 새로운 'green' deployment를 만들 것입니다. Green deployment에서 version labelimage path를 업데이트합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      labels:
        app: hello
        track: stable
        version: 2.0.0
    spec:
      containers:
        - name: hello
          image: kelseyhightower/hello:2.0.0
          ports:
            - name: http
              containerPort: 80
            - name: health
              containerPort: 81
          resources:
            limits:
              cpu: 0.2
              memory: 10Mi
          livenessProbe:
            httpGet:
              path: /healthz
              port: 81
              scheme: HTTP
            initialDelaySeconds: 5
            periodSeconds: 15
            timeoutSeconds: 5
          readinessProbe:
            httpGet:
              path: /readiness
              port: 81
              scheme: HTTP
            initialDelaySeconds: 5
            timeoutSeconds: 1

Green deployment를 만듭니다.

▼ 명령어

kubectl create -f deployments/hello-green.yaml

▼ 아웃풋

Green deployment가 있고 제대로 시작된 경우 현재 1.0.0 버전이 아직 사용되고 있는지 확인합니다.

▼ 명령어

curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`/version

▼ 아웃풋

 

이제 서비스가 새 version을 가리키도록 업데이트합니다.

▼ 명령어

kubectl apply -f services/hello-green.yaml

▼ 아웃풋

서비스가 업데이트되면 'green' deployment가 즉시 사용됩니다. 이제 항상 새 version이 사용되고 있는지 확인할 수 있습니다.

▼ 명령어

curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`/version

▼ 아웃풋

Blue-Green Rollback

필요한 경우 같은 방법으로 이전 버전으로 롤백할 수 있습니다. 'blue' deployment가 아직 실행 중일 때 서비스를 이전 버전으로 다시 업데이트하면 됩니다.

▼ 명령어

kubectl apply -f services/hello-blue.yaml

▼ 아웃풋

서비스를 업데이트하면 롤백이 성공적으로 완료됩니다. 사용 중인 버전이 정확한지 다시 확인합니다.

▼ 명령어

curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`/version

▼ 아웃풋

축하합니다. 지금까지 blue-green deployments의 개념과 한 번에 버전 switch을 마쳐야 하는 애플리케이션에 업데이트를 배포하는 방법을 알아보았습니다.

Congratulations!

Kubernetes를 이용하여 배포를 관리하는 실습이 완료되었습니다. 이 실습에서는 kubectl 명령줄 도구, 그리고 YAML 파일에 설정된 여러 가지 deployment configurations 스타일을 다양하게 사용하여 배포를 시작하고, 업데이트 및 확장해 볼 수 있었습니다. 이를 기반으로 이제 DevOps 작업에 이러한 기술을 손쉽게 적용할 수 있을 것입니다.

Take your next lab

Continue your Quest with these suggestions:

Next steps / learn more

반응형

댓글