PromleeBlog
sitemap
aboutMe

posting thumbnail
쿠버네티스 고급 활용 오토스케일링과 무중단 배포 - DevOps 컨테이너에서 클러스터까지 6편
Kubernetes Advanced Features Autoscaling and Zero-Downtime Deployment - DevOps from Containers to Clusters Part 6

📅

🚀

들어가기 전에 🔗

지난 시간에는 YAML 파일을 이용해 Deployment와 Service를 만들어 Nginx 웹 서버를 외부에 노출시키는 방법을 배웠습니다.
이제 우리는 쿠버네티스에서 애플리케이션을 배포하는 표준적인 방법을 익혔습니다.

하지만 실제 운영 환경에서는
예상치 못한 상황
들이 발생합니다.
갑자기 사용자가 몰려 서비스가 느려지거나, 새로운 버전으로 업데이트하는 동안 서비스가 잠시 멈추는 일도 생길 수 있습니다.

이번 시간에는 이러한 문제들을 해결하기 위한 쿠버네티스의 고급 기능들을 알아보겠습니다.
먼저 트래픽에 따라 자동으로 Pod의 개수를 조절해주는
HPA(Horizontal Pod Autoscaler)
에 대해 배우고, 서비스를 중단하지 않고 안전하게 업데이트하는
롤링 업데이트와 롤백
방법을 알아봅니다.
마지막으로, 여러 개의 서비스를 하나의 입구(IP 주소)로 연결해주는
Ingress
를 직접 실습해보겠습니다.

🚀

자동으로 늘어나는 Pod: HPA (Horizontal Pod Autoscaler) 🔗

5편에서 우리는 Deployment YAML 파일에 replicas: 3 이라고 직접 Pod의 개수를 정해주었습니다.
하지만 사용자가 거의 없는 새벽 시간에는 3개는 낭비일 수 있고, 이벤트로 사용자가 몰리는 낮 시간에는 3개로는 부족할 수 있습니다.

HPA (Horizontal Pod Autoscaler)
는 이렇게 고정된 Pod 개수의 비효율을 해결해주는 기능입니다.
HPA는 Pod들의 CPU 사용량이나 메모리 사용량 같은 자원 사용률을 지켜보다가, 우리가 설정한 기준치를 넘으면 자동으로 Pod의 개수를 늘리고 (Scale-out), 기준치보다 낮아지면 다시 줄여주는 (Scale-in) 역할을 합니다.

마치 마트 계산대에 손님이 길게 줄을 서면(CPU 사용량 증가) 임시 계산대를 열고(Pod 추가), 손님이 없으면 다시 닫는(Pod 감소) 것과 같은 원리입니다.
이를 통해 우리는 자원을 효율적으로 사용하면서도 안정적인 서비스 품질을 유지할 수 있습니다.
CPU 사용량과 pod 개수
CPU 사용량과 pod 개수

Minikube에서 HPA 사용 준비하기 🔗

HPA가 Pod의 자원 사용량을 측정하려면
Metrics Server
라는 부품이 필요합니다.
Minikube 환경에서는 간단한 명령어로 활성화할 수 있습니다.
minikube addons enable metrics-server

🚀

중단 없이 배포하기: 롤링 업데이트와 롤백 🔗

새로운 버전의 애플리케이션을 배포할 때, 기존 버전의 Pod를 모두 삭제하고 새 버전의 Pod를 한 번에 띄우면 그 사이 서비스가 잠시 중단되는 시간이 발생합니다.
쿠버네티스의 Deployment는 이러한 문제를 막기 위해 기본적으로
롤링 업데이트(Rolling Update)
전략을 사용합니다.

롤링 업데이트는 마치 움직이는 자동차의 바퀴를 하나씩 갈아 끼우는 것과 같습니다.
새 버전의 Pod를 하나 만들어서 정상적으로 실행되는 것을 확인한 뒤, 기존 버전의 Pod를 하나 삭제하는 과정을 반복합니다.
이런 식으로 점진적으로 교체하기 때문에 사용자는 업데이트가 진행되는 중에도 서비스를 끊김 없이 이용할 수 있습니다.

롤링 업데이트 실행하기 🔗

롤링 업데이트를 실행하는 방법은 아주 간단합니다.
그저 nginx-deployment.yaml 파일의 이미지 버전을 바꾸고 다시 kubectl apply를 실행하면 됩니다.

예를 들어, image: nginx:1.21 부분을 image: nginx:1.22로 수정하고 저장한 뒤, 아래 명령어를 실행하면 쿠버네티스가 알아서 롤링 업데이트를 시작합니다.
kubectl apply -f nginx-deployment.yaml

롤백: 이전 버전으로 돌아가기 🔗

만약 새로 배포한 1.22 버전에 심각한 버그가 있다면 어떻게 해야 할까요?
걱정할 필요 없습니다. Deployment는 변경 이력을 기억하고 있기 때문에 간단한 명령어로 이전 버전으로 되돌릴 수 있습니다.
 # 이전 버전으로 롤백
kubectl rollout undo deployment/nginx-deployment
이 기능 덕분에 우리는 훨씬 더 자신감을 가지고 새로운 버전을 배포할 수 있습니다.

🚀

Ingress 🔗

5편에서 우리는 NodePort 타입의 Service를 이용해 Nginx를 외부에 노출했습니다.
하지만 이 방식은 서비스마다 별도의 포트 번호를 사용해야 해서 관리하기 번거롭고, http://IP주소:31234 와 같은 비친화적인 주소를 사용해야 합니다.

Ingress(인그레스)
는 이러한 문제를 해결하고, 여러 서비스를 하나의 IP 주소와 blog.example.com, shop.example.com 과 같은 도메인 이름을 통해 외부에 노출시켜주는 똑똑한 문지기 역할을 합니다.

Ingress는 크게 두 가지로 구성됩니다.

실습: Ingress로 여러 서비스 라우팅하기 🔗

이제 / 경로로 접속하면 my-web-1 서비스를, /v2 경로로 접속하면 my-web-2 서비스를 보여주는 Ingress를 만들어 보겠습니다.
➡️

1. Ingress Controller 활성화 🔗

먼저 Minikube에 내장된 Nginx Ingress Controller를 활성화해야 합니다.
minikube addons enable ingress
➡️

2. 두 개의 샘플 웹 서버 배포 🔗

라우팅을 테스트하기 위해 각각 다른 페이지를 보여주는 두 개의 Deployment와 Service를 만듭니다.
my-webs.yaml 파일을 만들고 아래 내용을 붙여넣어 주세요.
my-webs.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web1-deployment
spec:
  replicas: 1
  selector: { matchLabels: { app: web1 } }
  template:
    metadata: { labels: { app: web1 } }
    spec:
      containers:
      - name: web1
        image: gcr.io/google-samples/hello-app:1.0
---
apiVersion: v1
kind: Service
metadata:
  name: web1-service
spec:
  selector: { app: web1 }
  ports:
  - port: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web2-deployment
spec:
  replicas: 1
  selector: { matchLabels: { app: web2 } }
  template:
    metadata: { labels: { app: web2 } }
    spec:
      containers:
      - name: web2
        image: gcr.io/google-samples/hello-app:2.0
---
apiVersion: v1
kind: Service
metadata:
  name: web2-service
spec:
  selector: { app: web2 }
  ports:
  - port: 8080
이제 이 파일을 적용합니다.
kubectl apply -f my-webs.yaml
➡️

3. Ingress 규칙(Resource) 작성 🔗

이제 문지기에게 전달할 규칙서를 작성할 차례입니다.
my-ingress.yaml 파일을 만들고 아래 내용을 입력합니다.
my-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web1-service
            port:
              number: 8080
      - path: /v2
        pathType: Prefix
        backend:
          service:
            name: web2-service
            port:
              number: 8080
이 규칙은 / 경로로 오는 요청은 web1-service로, /v2 경로로 오는 요청은 web2-service로 보내라는 의미입니다.
이제 이 규칙서도 적용합니다.
kubectl apply -f my-ingress.yaml
➡️

4. 테스트하기 🔗

터미널에서 Minikube의 IP 주소를 확인합니다.
minikube ip
이제 curl 명령어를 이용해 각 경로로 접속해봅시다. [minikube-ip] 부분은 위에서 확인한 실제 IP로 바꿔주세요.
 # web1-service로 라우팅되는지 확인
curl http://[minikube-ip]/
 
 # web2-service로 라우팅되는지 확인
curl http://[minikube-ip]/v2
각각 다른 버전의 "Hello, world!" 메시지가 출력된다면 성공입니다.
참고로 Ingress는 TLS/HTTPS 적용도 매우 쉽게 할 수 있어 보안을 강화하는 데에도 핵심적인 역할을 합니다.

🚀

결론 🔗

오늘은 쿠버네티스의 강력한 자동화 및 관리 기능들을 배웠습니다.

HPA
를 통해 우리는 더 이상 서버 자원 사용량을 걱정하며 수동으로 Pod 개수를 조절할 필요가 없어졌습니다.
롤링 업데이트와 롤백
기능 덕분에 서비스 중단에 대한 두려움 없이 안전하고 빠르게 애플리케이션을 업데이트할 수 있게 되었습니다.
마지막으로,
Ingress
를 통해 복잡한 마이크로서비스 환경에서도 단 하나의 진입점을 통해 트래픽을 효율적으로 관리하는 방법을 익혔습니다.

다음 시간에는 이렇게 운영되는 서비스의 상태를 어떻게 확인하고(로깅/모니터링), 중요한 정보는 어떻게 안전하게 관리하며(Secret), 이 모든 배포 과정을 어떻게 자동화할 수 있는지(CI/CD) 알아보겠습니다.

참고 🔗