Infra

도커를 활용하여 배포 프로세스 개선하기

dcho 2024. 7. 29. 14:21
SMALL

회사에 들어와 기능을 만들어야 하는데 제대로 된 서버 구성도 없고 배포 프로세스도 없어 오히려 좋다는 마인드로 이 기회에 한번 우당탕탕 배포 프로세스를 만들고 무중단 배포까지 진행을 해보았다.

1. 문제 상황

  • 서비스 업데이트 번거로움: 기존 서비스를 nohup으로 실행한 후 업데이트 시 기존 프로세스를 찾아서 종료하고 다시 실행해야 하는 번거로움이 발생했다.
    • 데몬 사용: 데몬을 사용하여 서비스 실행과 중지 과정을 스크립트로 자동화했다. 이를 통해 프로세스를 종료하고 다시 시작하는 작업을 자동화하여 업데이트 과정을 간소화했다.
  • 환경 종속성 문제: 패키지 추가 시 환경에 따라 동작이 달라지는 이슈가 발생했다. 운영서버에서는 문제가 없지만, 개발서버의 OS가 달라서 생기는 문제로 인해 복잡한 환경 설정이 필요했다. (운영서버와 개발서버가 다른것은 이해가 잘 되지 않았다.)
    • 도커 도입: 도커를 도입하여 환경에 독립적인 컨테이너를 사용함으로써, 개발서버와 운영서버 간의 차이로 인한 문제를 해결하고 확장 가능성을 높였다.

이러한 문제 상황들을 해결하고자 계속 개선의지를 선보였고 결국 나의 행동력이 도커를 쓰지 않는 조직에 도커까지 사용하게 되었다.

2. Docker / Docker Compose

개념은 간단하게 짚고 넘어간다. (워낙 잘되어있는 설명이 많기 때문에)

도커컨테이너 기반의 오픈소스 플랫폼이다.
컨테이너운영체제 수준의 가상화 기술로 리눅스 커널을 공유하면서 프로세스를 격리된 환경에서 실행하는 기술이다.

흔히 알고 있는 컨테이너라 하면 배에 싣는 네모난 화물 수송용 박스를 생각할 수 있는데 각각의 컨테이너 안에는 옷, 신발, 전자제품, 술, 과일 등 다양한 화물을 넣을 수 있고 규격화되어 컨테이너선이나 트레일러 등 다양한 운송수단으로 쉽게 옮길 수 있다.
이러한 개념으로 도커 컨테이너를 활용하면 기존에 직접 서버에 필요한 것들을 설치해야 하는 번거로운 작업들이 훤씬 편해진다.
예를 들어, 특정 애플리케이션이 필요로 하는 모든 라이브러리와 종속성을 하나의 컨테이너 이미지에 담아 배포함으로써, 어디서나 일관된 환경에서 실행될 수 있다.

도커 컴포즈는 여러 도커 컨테이너들을 정의하고 실행시키는 도커 오케스트레이션 툴이다.

일반적으로 도커 컨테이너 안에서는 하나의 프로세스가 동작한다. 각 프로세스 간 통신이 필요한 시스템을 도커 환경에서 구동하기 위해서는 각각의 컨테이너들의 설정을 관리해야 하는데, 도커 컴포즈를 이용하면 서비스에 필요한 컨테이너 이미지와 설정들을 쉽게 관리할 수 있다.

왜 도커(Docker)를 써야할까?

"도커 없이도 배포/운영 하고 있는데, 아무 불편을 느끼지 못합니다. 왜 도커를 써야 하죠?"

운영하면서 만들어지는 눈송이 서버들(Snowflake Servers)

서버 운영을 오래 해 본 사람이라도, 처음 들어가는 서버에서는 마음먹은 대로 문제를 해결하기가 어렵다. 이는 서버를 다루는 기술과는 별개로, 각 서버마다 운영 기록이 다르기 때문이다.
똑같은 일을 하는 두 서버가 있다 해도, A 서버는 한 달 전에 구성했고 B 서버는 이제 막 구성 했다면, 운영체제부터 컴파일러, 설치된 패키지까지 완벽하게 같기는 쉽지 않다.
이러한 차이점들이 종종 장애를 일으킨다. "A 서버는 잘 되는데 B 서버는 왜 죽었지?"와 같은 상황이 발생한다.
이렇게 서로 모양이 다른 서버들이 존재하는 상황을 눈송이 서버(Snowflake Server)라고도 한다. 모든 눈송이의 모양이 다르듯, 서버들도 서로 다른 모습이라는 의미이다.

서버 코드화의 장점

도커를 이용하여 서버를 구성할 때 명령어를 이용할 수도 있지만 매번 명령어를 치는 것은 불편하다.
그래서 Dockerfile을 이용하여 서버 구성하는 명령어를 집어넣고 관리할 수 있고 Dockerfile을 이용하여 시행착오를 줄여 나가 서버를 유연하고 견고하게 만들어 나갈 수 있다.

환경 일관성

환경의 차이가 존재하더라도 도커는 동일한 컨테이너 이미지를 사용하여 모든 환경에서 일관된 실행 환경을 제공한다. 이를 통해 다음과 같은 문제를 해결할 수 있다.

  • 환경 차이로 인한 버그 감소: 개발자는 "내 로컬에서는 잘 작동했는데..."라는 문제를 줄일 수 있다. 도커는 모든 환경에서 동일한 소프트웨어 스택과 설정을 보장한다.
  • 환경 설정 간소화: 도커 이미지를 사용하면 특정 환경 설정을 반복해서 할 필요가 없다. 컨테이너는 동일한 방식으로 작동한다.

도커를 써야 하는 장점을 찾아보면 정말 많다. 그중에서도 지금 현시점에서 혼자서 인프라를 관리를 해야 하고 누군가 인프라를 유지보수를 해야 한다면 위의 장점만으로도 충분히 도입할 만한 가치가 있다고 생각이 들었다.

3. 배포

보고 들은 것들은 많아 배포는 대단하게 해야 해! 그런 느낌이었다. 지금까지 한 것은 그럼 배포인가?라는 의문 계속 들었다. 그래서 한번 찾아보았다.

배포는 단순히 로컬의 소스를 운영 서버로 복사하는 것입니다. FTP로 파일을 복사하는 방식은 가장 기본적이면서도 그럭저럭 잘 작동합니다. 배포 중에 서비스가 잠깐 멈추는 문제가 있다면 새벽에 배포하면 되고, 배포에 신경 쓰기보다는 다른 개발 작업에 집중하고 싶은 생각이 들 수 있습니다.
하지만, 배포 프로세스가 탄탄해지면서 오히려 서비스 개발에 더 집중할 수 있습니다. 하루에 몇 번이라도 배포를 자주, 더 빠르게 하는 것이 서비스의 경쟁력을 높이는 데 중요한 요소가 되는 세상입니다. 서비스가 빠르게 발전하고 있고, 서버를 확장하려면 배포에 미리 신경 쓰는 것이 맞다고 생각합니다.

결국에는 개발했던 소스가 운영 서버에 코드가 적용이 되느냐가 배포이다.
그 과정을 한번 힘을 들여서 개선을 하고 편하게 쓸래?, 과정 개선을 안 하고 불편한 상태로 계속 쓸래? 이건 규모마다 선택에 문제였다.

나는 배포 프로세스를 전자를 택했다. 이왕 하는 거 완벽하진 못하더라도 개선을 하자. 그래야 나도 편하고 다른 사람도 편할 테니까.

무중단 배포

현재 django를 웹애플리케이션 서버를 두고 서비스를 하고 있는데 확장성도 고려해서 도커를 썼다. 배포 프로세스를 만들면서 고민했던 내용이다.

  1. 쉽고 관리하기 편한 방법을 선택하자
  2. 배포 중 서비스가 중단되는 일이 없도록 하자
  3. 하루에도 여러 번 배포하자
  4. 모든 서비스는 가능하면 도커를 이용해서 컨테이너 형태로 표준화하여 배포하자
  5. 운영과 개발서버에 동일한 방법으로 배포하고 테스트하자.

이러한 내용들을 나열해 보았을 때 무중단 배포를 시도해 볼 때가 되었다고 생각했다.

다운 타임(downtime)

다운타임(downtime)

기능을 추가할 일이 생기면 이전 버전은 종료하고 신규 버전을 실행시키는 과정이 필요하다. 그 사이에는 서비스 중단이 일어나게 되는데 이를 다운타임(downtime)이라고 한다.

추후 서비스를 하다 보면 점검 중을 띄워놓고 할 수도 있지만 사용자가 서비스를 이용할 수 없다는 치명적인 단점이 생기게 된다. 이를 개선하지 않고 혹시나 계속 중단을 해서 신규 버전을 올리게 되는 상황이면 혹시 모르는 상황에 대비를 하는 게 불편함을 느낄 것이다. 그래서 이를 보완하고자 서비스의 중단 없이 업데이트를 수행하는 무중단 배포가 있어 적용했다.

무중단 배포 전략에는 롤링, 블루/그린, 카나리 배포 전략이 있다.
현재 서비스가 하나 존재하기에 롤링과 블루/그린 방식 중 고려를 하였고 작은 규모에서 차이가 크게 없고 더 직관적인 블루/그린 방식을 적용하고자 한다.

Blue Green 배포방식

블루/그린 배포방식

블루/그린 방식은 쉽게 말해 각각의 그룹을 이전 버전과 새 버전으로 나눠 배포 시 새 버전을 띄워놓고 문제가 발생하지 않는다면 이전 버전과 교체하는 방식이다.
내가 적용하고자 하는 것에 딱 맞는 방식이었다. 새 버전을 배포하고 테스트한 후 트래픽을 전환만 하면 되기 때문이었다.

4. 현 서버에 적용

무중단 배포를 위해 블루, 그린 2개의 컨테이너가 필요했고 각 컨테이너를 관리하기 위해 도커 컴포즈를 도입을 했다.

장점

  • 복잡한 명령어를 일일이 입력하지 않더라도, 하나의 YAML파일로 여러 컨테이너를 정의하고 관리할 수 있다.
  • 컨테이너의 밖의 호스트와도 어떻게 연결할지, 파일 시스템은 어떻게 공유할지(volumes)등 제어를 할 수 있다.
services:
  web-blue:
    build:
      context: .
      dockerfile: ./deploy/${SET}/django/django.dockerfile
    container_name: web-blue
    env_file:
      - .env
    ports:
      - "8001:8000"
    volumes:
      - 로그

  web-green:
    build:
      context: .
      dockerfile: ./deploy/${SET}/django/django.dockerfile
    container_name: web-green
    env_file:
      - .env
    ports:
      - "8002:8000"
    volumes:
      - 로그

각 환경에 맞는 django 애플리케이션 서버 도커파일을 세팅하고 컨테이너를 블루, 그린으로 포트를 나누어 주었다.

그리고 배포 코드를 deploy.py(배포 자동화를 위해 생성)에 넣고 환경에 따라 다르게 실행될 수 있도록 세팅을 해주었다.
자동화코드에서 실행되는 과정은 다음과 같다.

deploy.py 과정

  • 배포 환경 (dev, prod) input
  • 현재 실행 중인 서비스가 그린인지 블루인지 확인
  • 신규 서비스 빌드 및 인스턴스로 배포
  • 도커 컨테이너 실행 대기(sleep 15s)
  • 신규 서비스 health check (실패 시 배포 중지)
  • 웹서버 설정을 새로운 인스턴스로 전환
  • 웹서버 설정 재로드
  • 이전 서비스 중지하고 삭제
  • 미사용 도커 컨테이너 및 이미지 제거

 

마치며

처음에 nohup으로 시작한 배포를 차근차근 개선하여 지금은 무중단 배포로 훨씬 편하게 배포를 할 수 있게 되었다. 
프로세스를 개선한다는 느낌이 매우 즐거웠고 부족한 게 아직 많기 때문에 앞으로도 꾸준하게 개선을 하고 싶다는 생각이 들었다. 
성장을 위해 하나 둘 발을 내디뎌 본다

 

참고

https://subicura.com/2016/06/07/zero-downtime-docker-deployment.html

 

도커를 이용한 웹서비스 무중단 배포하기

홈쇼핑처럼x밀본고기덮밥이 팔리는걸 관리자화면에서 보면서 하루에도 여러번 소스를 업데이트 하고 운영서버로 배포했던 내용이 떠올라 후기로 정리합니다. 배포는 단순히 로컬의 소스를 운

subicura.com

https://kimyu0218.tistory.com/55

 

[CD] 블루/그린 무중단 배포 구현하기 1편 (NGINX/Docker Compose)

야 너두 무중단 배포 할 수 있어 🫵이 글은 도커, 엔진엑스, 깃헙 액션을 한 번도 써본 적 없고, 무중단 배포라는 용어도 처음 들어본 사람의 무모한 무중단 배포 도전기다. 제발 나처럼 고생하

kimyu0218.tistory.com

https://www.44bits.io/ko/post/why-should-i-use-docker-container

 

왜 굳이 도커(컨테이너)를 써야 하나요? - 컨테이너를 사용해야 하는 이유

컨테이너는 서버 애플리케이션을 배포하고 서버를 운영하는 표준적인 기술이 되어가고 있습니다. 하지만 처음 사용해본다면 그 장점이 잘 와닿지 않을 수도 있습니다. 왜 굳이 도커 컨테이너를

www.44bits.io

https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html

 

초보를 위한 도커 안내서 - 도커란 무엇인가?

도커를 처음 접하는 시스템 관리자나 서버 개발자를 대상으로 도커 전반에 대해 얕고 넓은 지식을 담고 있습니다. 도커가 등장한 배경과 도커의 역사, 그리고 도커의 핵심 개념인 컨테이너와 이

subicura.com

https://yjoonjang.medium.com/drf-%EB%B0%B0%ED%8F%AC-1-%EB%B0%B0%ED%8F%AC-%EC%9E%90%EB%8F%99%ED%99%94%EB%B6%80%ED%84%B0-docker-aws-vpc-ec2-rds%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%B4%EB%B3%B4%EC%9E%90-6ba347c700ed

 

[RESUMAI 프로젝트 3] DRF 배포: 밑바닥부터 알아보는 Docker, 배포 자동화 AWS VPC, EC2, RDS [1]

지난 글에서는 DRF를 이용해서 카카오 소셜로그인을 마무리했다. 이렇게 하나의 기능을 추가하고, 프론트와의 개발 병행을 위해 배포를 먼저 해야겠다고 다짐했다.

yjoonjang.medium.com

https://shephexd.github.io/server/2020/06/26/DevOps_from_scratch(3)-Docker_Compose.html

 

밑바닥부터 시작하는 DevOps 생존기(3) - Docker Compose

이전 장에서 Docker를 이용하여 소스코드의 가상환경을 설정하고, 해당 간단한 웹 서비스를 실습하였습니다. 여러 컨테이너 간의 통신을 관리하거나 실행시 파라미터가 많거나 가변적인 경우에

shephexd.github.io