Kubernetes

GKE로 배포 관리하기

하마롱크 2021. 11. 13. 08:42

DevOps 방식에서는 정기적으로 여러 배포를 사용하여 '지속적 배포', 'Blue/Green 배포', 'Canary 배포'와 같은 애플리케이션 배포 시나리오를 관리한다. 여러 이기종 배포가 사용되는 일반적인 시나리오를 처리할 수 있도록 컨테이너를 확장해보고, 관리해보았다.

 

영역 설정

#영역을 us-central1-a로 설정
gcloud config set compute/zone us-central1-a

 

이 실습에서 사용할 샘플 코드 가져오기

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

 

#n1-standard-1 노드 3개로 클러스터 생성
gcloud container clusters create bootcamp --num-nodes 3 --scopes "https://www.googleapis.com/auth/projecthosting,storage-rw"

 

배포 만들기

#deployments/auth.yaml 구성 파일 업데이트
vi deployments/auth.yaml

 

#배포의 containers 섹션에 있는 image를 다음과 같이 변경
...
containers:
- name: auth
  image: kelseyhightower/auth:1.0.0
...
#배포 구성 파일 확인
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
...

 

배포를 통해 어떻게 하나의 복제본이 생성되고 버전 1.0.0의 인증 컨테이너를 사용하는지 확인한다.

kubectl create 명령어를 실행하여 인증 배포를 만들면 배포 매니페스트의 데이터에 따라 하나의 포드가 생성되며, replicas 필드에 지정된 숫자를 변경하여 포드의 수를 조정할 수 있다.

#배포 객체 생성
kubectl create -f deployments/auth.yaml

#배포 생성여부 확인
kubectl get deployments

 

배포가 생성되면, Kubernetes에서는 배포에 관한 ReplicaSet를 만든다. 배포에 관한 ReplicaSet가 생성되었는지 확인할 수 있다.

kubectl get replicasets

배포의 일부로 생성된 포드를 볼 수 있다. ReplicaSet가 생성될 때 Kubernetes에서 단일 포드를 생성한다.

kubectl get pods
#인증 서비스 생성
kubectl create -f services/auth.yaml
#hello 배포 생성 및 노출
kubectl create -f deployments/hello.yaml
kubectl create -f services/hello.yaml

 

#frontend 배포 생성 및 노출
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

#프런트엔드용 ConfigMap 생성
#외부 IP를 가져와서 프런트엔드와 연결함으로써 프런트엔드와 상호작용
# 서비스 확인
kubectl get services frontend

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

#kubectl의 출력 템플릿 기능을 사용하여 curl을 한 줄 명령어로 사용가능
curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`

 

 

배포 확장

이제 배포가 생성되었으므로 확장할 수 있다. spec.replicas 필드를 업데이트하면 된다. 

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

#hello 포드를 5개로 확장
kubectl scale deployment hello --replicas=5

#hello 포드 5개가 실행되고 있는지 확인
kubectl get pods | grep hello- | wc -l

#hello 포드를 3개로 축소
kubectl scale deployment hello --replicas=3

#포드 개수 다시 확인
kubectl get pods | grep hello- | wc -l

 

 

순차적 업데이트

배포는 순차적 업데이트 메커니즘을 통해 이미지를 새 버전으로 업데이트하도록 지원한다. 배포가 새 버전으로 업데이트되면 새 ReplicaSet가 만들어지고, 이전 ReplicaSet의 복제본이 감소하면서 새 ReplicaSet의 복제본 수가 천천히 증가한다.

순차적 업데이트 트리거하기

배포를 업데이트하려면 다음 명령어를 실행한다.

kubectl edit deployment hello

배포의 containers 섹션에 있는 image를 다음과 같이 변경한다.

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

 

편집기에서 저장하면, 업데이트된 배포가 클러스터에 저장되고 Kubernetes에서 순차적 업데이트가 시작된다.

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

kubectl get replicaset

출시 기록에 새로운 항목이 표시된다.

kubectl rollout history deployment/hello

 

순차적 업데이트 일시중지하기

실행 중인 출시에 문제가 발생하면 일시중지하여 업데이트를 중지한다.

kubectl rollout pause deployment/hello

현재 출시 상태를 확인한다.

kubectl rollout status deployment/hello

포드에서 직접 확인할 수도 있다.

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

 

순차적 업데이트 재개하기

출시가 일시중지되었으므로 일부 포드는 새 버전이고 일부 포드는 이전 버전이다. resume 명령어를 사용하여 출시를 계속 진행할 수 있다.

kubectl rollout resume deployment/hello

출시가 완료되면 status 명령어를 실행할 때 다음이 표시된다.

kubectl rollout status deployment/hello

(출력 내용)

deployment "hello" successfully rolled out

업데이트 롤백하기

새 버전에서 버그가 발견되었다면, 새 버전에 문제가 있는 것으로 간주되므로 이전 버전으로 롤백하여 문제를 조사한 다음 제대로 수정된 버전을 출시할 수 있다.

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

kubectl rollout undo deployment/hello

기록에서 롤백을 확인한다.

kubectl rollout history deployment/hello

 

모든 포드가 이전 버전으로 롤백되었는지 확인한다.

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

 

 

Canary 배포

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

Canary 배포 만들기

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

 

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
        # 2.0.0 버전을 사용하여 서비스 선택기의 버전과 일치시킨다
        version: 2.0.0
    spec:
      containers:
        - name: hello
          image: kelseyhightower/hello:2.0.0
          ports:
            - name: http
              containerPort: 80
            - name: health
              containerPort: 81
...

Canary 배포 생성

kubectl create -f deployments/hello-canary.yaml

Canary 배포를 만들면 hello  hello-canary의 두 가지 배포가 생긴다.

kubectl get deployments

hello 서비스에서 선택기는 프로덕션 배포 및 Canary 배포의 pod에 모두 맞는 app:hello 선택기를 사용하지만, Canary 배포가 포드 수가 더 적기 때문에 더 적은 수의 사용자에게 표시된다.

Canary 배포 확인하기

요청에서 제공되는 hello 버전을 확인할 수 있다.

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

이 명령어를 여러 번 실행하면, 일부 요청은 hello 1.0.0에서 제공하고 소규모 하위 집합(1/4=25%)은 2.0.0에서 제공함을 알 수 있다.

 

프로덕션 환경의 Canary 배포 - 세션 어피니티

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

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

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

 

Blue/Green 배포

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

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

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

 

서비스

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

#서비스 업데이트
kubectl apply -f services/hello-blue.yaml

 

Blue/Green 배포를 사용하여 업데이트하기

Blue/Green 배포 스타일을 지원하기 위해 새 버전용으로 새로운 'green' 배포를 만들고, Green 배포에서 버전 라벨과 이미지 경로를 업데이트한다.

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 배포를 생성다.

kubectl create -f deployments/hello-green.yaml

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

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

서비스가 새 버전을 가리키도록 업데이트한다.

kubectl apply -f services/hello-green.yaml

서비스가 업데이트되면 'green' 배포가 즉시 사용되고, 항상 새 버전이 사용되고 있는지 확인할 수 있다.

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

 

Blue/Green 롤백

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

kubectl apply -f services/hello-blue.yaml

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

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

 

 

클러스터 삭제

gcloud container clusters delete bootcamp --zone us-central1-a

 

 

[출처]

https://www.cloudskillsboost.google/focuses/639?parent=catalog 

 

Kubernetes Engine으로 배포 관리 | Google Cloud Skills Boost

Dev Ops 권장사항에서는 여러 배포를 사용하여 애플리케이션 배포 시나리오를 관리합니다. 이 실습에서는 여러 이기종 배포가 사용되는 일반적인 시나리오를 처리할 수 있도록 컨테이너를 확장

www.cloudskillsboost.google