프로필사진
DevOps 부트캠프 기록일지
DevOps_04_김재환
2023.05.19(Sprint - 새 버전이 망가졌어요)
2023.05.19(Sprint - 새 버전이 망가졌어요)

2023. 5. 19. 11:00부트캠프/DevOps (TIL)

Getting Started

 

STEP 0: 복습

Docker Hub에 sebcontents/cozserver:1.0 이라는 이름의 파드가 존재합니다.
CozServer는 컨테이너 안에서 8080 포트를 통해 열려 있습니다.

도커를 복습할 겸, 도커를 이용해 한번 열어봅시다.

docker run -p 80:8080 sebcontents/cozserver:1.0

연습을 마쳤으면, 컨테이너는 삭제해도 좋습니다.

STEP 1: 파드

이 단계에서는 파드를 수동으로 만들어볼 것입니다.
하지만 보통 파드는 하나하나 만들지 않으므로, "이렇게 만들 수도 있다"라는 것을 간단하게 배우고 넘어가는 정도의 의미를 갖습니다.

sebcontents/cozserver:1.0 이미지를 바탕으로 파드를 만들어봅시다.

apiVersion: v1
kind: Pod
metadata:
  name: cozserver
spec:
  containers:
    - name: cozserver
      image: sebcontents/cozserver:1.0
      ports:
        - containerPort: 8080

cozserver-pod.yaml 파일을 생성후 위와 같이 작성한다음 apply 명령어를 통해 pod을 생성해야합니다.

물론 시작전에 minikube start 명령어로  로컬 머신에서 Kubernetes 환경을 구축하고 실행할 수 있습니다

minikube start 
kubectl apply -f cozserver-pod.yaml

🏁 cozserver-pod.yaml 에 파드 명세를 적고, 파드가 kubectl에 의해 실행되어야 합니다.
✅ 명세를 성공적으로 만들었다면 git commit을 진행하세요.

STEP 2: 디플로이먼트를 이용한 1.0 배포

(STEP 1에서 만든 파드는 더 이상 사용하지 않으므로 삭제해줍시다.)

앞서 개별 파드를 yaml로 작성된 명세를 통해 생성했습니다.
그러나, 파드는 확장성을 바탕으로 가용성을 위해 언제든 대체될 수 있습니다.
따라서 디플로이먼트로 CozServer를 구성하는 것이 바람직합니다.

1.0 이미지를 바탕으로 파드를 디플로이먼트를 생성해봅시다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cozserver
  labels:
    app: cozserver
spec:
  selector:
    matchLabels:
      app: cozserver
  replicas: 2
  template:
    metadata:
      labels:
        app: cozserver
    spec:
      containers:
      - name: cozserver
        image: sebcontents/cozserver:1.0
        ports:
          - containerPort: 8080

🏁 cozserver-deployment-v1.yaml 에 디플로이먼트 명세를 적고, kubectl에 의해 실행되어야 합니다.
✅ 명세를 성공적으로 만들었다면 git commit을 진행하세요.

배포 이력을 남기기 위해 --record 옵션을 추가해서 배포합시다.
(deprecated 된 옵션이지만, 아직 대안이 없으므로 그냥 사용합니다.)

kubectl apply -f cozserver-deployment-v1.yaml --record
# record는 이제 사용되지 않는 옵션으로 쿠버네티스 최신버전은 자동으로 옵션이 포함되어있습니다
따라서 옵션을 뺀 상태로 적용해도 무관합니다.
kubectl apply -f cozserver-deployment-v1.yaml

STEP 3: 서비스

아무리 클러스터 내에 파드를 만든다해도, 노출시키지 않으면 소용이 없습니다.
서비스 리소스를 만들어서 파드를 외부로 노출시켜줘야 합니다.

이 때 서비스 리소스의 타입은 LoadBalancer를 사용할 것입니다.
앞서 안내한 대로, 컨테이너 포트는 8080을 사용합니다.

apiVersion: v1
kind: Service
metadata:
  name: cozserver
  namespace: default
spec:
  selector:
    app: cozserver
  type: LoadBalancer
  ports:
    - name: cozserver
      protocol: TCP
      port: 80
      targetPort: 8080

🏁 cozserver-service.yaml 에 서비스 명세를 적고, kubectl에 의해 실행되어야 합니다.
✅ 명세를 성공적으로 만들었다면 git commit을 진행하세요.

로컬 환경에서 테스트하기 위해서는 터널이 필요합니다.
minikube tunnel 명령을 이용해 터널을 뚫어줍시다.

http://localhost 를 이용해 다음 그림과 같이 접속이 된다면 성공입니다.

Troubleshooting

minikube tunnel 명령을 이용해 터널을 뚫으려고 했을 때 권한 부족 에러가 발생하여 power shell을 관리자 권한으로 실행하여 명령어를 입력해줬습니다. 시작이 잘되서 호기롭게 http://localhost로 들어가봤지만 연결이 안되서 왜 안될까 고민해보다가 이전에 생성해놓은 nginx 예제 서비스와 포트가 겹쳐 접근에 에러가 발생했다는걸 알 수 있었습니다. nginx 예제 서비스를 지우고 다시 접속해보니 정상적으로 접근이 가능했습니다.

STEP 4: 2.0 배포, 롤아웃

기존의 cozserver-deployment-v1.yaml를 그대로 복사해서 cozserver-deployment-v2.yaml라는 이름으로 새로 생성합시다.

이제, 1.0 대신 새로운 파일을 이용해 기존의 CozServer 1.0 버전이 아닌, 2.0 버전을 롤링 업데이트를 통해 배포할 것입니다.

🏁 cozserver-deployment-v2.yaml 에 2.0 버전을 이용한 디플로이먼트 명세를 적고, kubectl에 의해 적용되어야 합니다.

  • 배포 전략은 RollingUpdate를 사용할 것입니다.
  • sebcontents/cozserver:2.0 이미지를 사용합니다.

kubectl get all 명령어를 통해 적용할 때, 배포되는 과정을 꼭 확인해보세요.
구버전의 파드가 삭제되고, 새로운 버전의 파드가 생기는 것을 확인할 수 있어야 합니다.

반드시 다음 과정을 확인해보세요.

  • Q. 레플리카셋은 어떻게 바뀌나요?

RollingUpdate 전략을 사용하면 ReplicaSet의 "spec.template" 섹션에서 새로운 이미지 버전으로 업데이트됩니다. 이로 인해 ReplicaSet의 해시 값이 변경되고, 새로운 파드가 생성될 준비가 됩니다.

  • Q. DESIRED, CURRENT, READY의 의미는 무엇인가요?
  • DESIRED: 현재 ReplicaSet이 유지해야 하는 파드의 원하는 수입니다. 이 값은 ReplicaSet의 "spec.replicas" 필드에서 설정됩니다.
  • CURRENT: 현재 실행 중인 파드의 수입니다. 이 값은 ReplicaSet에 의해 관리되는 파드 중 현재 실행 중인 파드의 수를 나타냅니다.
  • READY: 준비된 상태의 파드 수입니다. 이 값은 파드가 모든 준비 상태 조건을 충족하고 서비스 요청에 응답할 수 있는 상태인 파드의 수를 나타냅니다.

배포 과정을 확인하기 위해 "kubectl get all" 명령을 실행하면 ReplicaSet의 DESIRED, CURRENT, READY 값이 변경되는 것을 확인할 수 있을 것입니다. 구버전 파드는 삭제되고, 새로운 버전의 파드가 생성되며 READY 상태가 되는 것을 확인할 수 있습니다.

kubectl apply -f cozserver-deployment-v2.yaml --record

다음 그림과 같이 새로운 버전이 배포되었다면 성공입니다.

마지막으로 롤아웃 히스토리를 확인해봅시다. 다음 명령을 통해 이력을 확인할 수 있습니다.

kubectl rollout history deployment cozserver

✅ 명세를 성공적으로 만들었다면 git commit을 진행하세요.

STEP 5: 3.0 배포와 2.0으로의 롤백

3.0 배포를 위해서 cozserver-deployment-v3.yaml 에 3.0 버전을 이용한 디플로이먼트 명세를 적고, kubectl을 통해 배포를 시도합시다.
(이미지 태그만 바꿔주어도 충분합니다)

kubectl get all 명령을 통해 적용 후 현황과, 롤아웃 히스토리를 확인해보세요.

이제 http://localhost 요청을 통해 3.0 버전을 확인해보세요.
몇번 요청을 시도하면, 처음에는 잘 되는 것 같아 보입니다.

현업에서도 비슷한 경우가 매우 많습니다.
배포를 하고 나면, 처음에는 그럴싸하게 잘 된것 같아 보이지만, 사용하다 보면 버그로 인해 internal 에러를 마주치게 되는 경우가 허다합니다.

이처럼 새 버전에 무언가 문제가 발생한다면, 이전 버전으로 롤백을 해야 합니다.

C:\Users\PC\0519\sprint-k8s-rollout> kubectl rollout history deployment cozserver
deployment.apps/cozserver 
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=cozserver-deployment-v1.yaml --record=true
2         kubectl apply --filename=cozserver-deployment-v2.yaml --record=true
3         <none>

롤아웃 히스토리에 따르면, 2번 리비전까지는 정상적으로 작동했습니다.
2번으로 롤백을 시도해야 합니다.

🏁 공식 문서를 이용해 롤백을 시도하고, 터미널 입력 및 출력 결과를 rollback-log.txt 파일에 복사/붙여넣기 해서 넣어주세요.
다음 세가지가 반드시 들어가야 합니다.

  • 롤백을 시도하기 전의 롤아웃 히스토리
  • 롤백을 시도한 결과
  • 롤백 후 롤아웃 히스토리

2번 리비전으로 롤백

kubectl rollout undo deployment/nginx-deployment --to-revision=2


rollback-log.txt의 형식은 다음과 같아야 합니다.

a. 롤백을 시도하기 전의 롤아웃 히스토리
deployment.apps/cozserver 
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=cozserver-deployment-v1.yaml --record=true
2         kubectl apply --filename=cozserver-deployment-v2.yaml --record=true
3         <none>


b. 롤백을 시도한 결과
C:\Users\PC\0519\sprint-k8s-rollout>kubectl rollout undo deployment/cozserver       
deployment.apps/cozserver rolled back


c. 롤백 후 롤아웃 히스토리
C:\Users\PC\0519\sprint-k8s-rollout>kubectl rollout history deployment cozserver  
deployment.apps/cozserver 
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=cozserver-deployment-v1.yaml --record=true
3         <none>
4         kubectl apply --filename=cozserver-deployment-v2.yaml --record=true