도커, 컨테이너, 쿠버네티스 개념
이번에는 도커와 관련하여 배포에 대해 공부해볼 것이다. 곧 프로젝트에서 실무를 경험할 수도 있으니, 미리 개념은 확실하게 잡아두고자 한다.
01 로컬, VM 기반의 배포
일단 첫 번재로, 로컬 환경에서의 배포 문제를 살펴본다. 개발 환경과 배포 환경이 다르면 문제가 발생할 수 있다. 예를 들어, 로컬에서 개발한 JAVA 11 기반의 Spirng Boot 애플리케이션이, 배포 환경에서는 JAVA 8만 지원될 때 오류가 발생한다.
이 문제를 해결하기 위해 등장한 것이 가상 머신(Virtual Machine) 기반 배포이다. VM을 사용하면 격리된 환경을 제공할 수 있고, 서로 다른 서비스가 서로 다른 VM에서 실행되므로 충돌 없이 동작이 가능하다. OS 및 라이브러리 충돌이 없고, 여러 개의 VM을 띄울 수 있다는 장점이 있지만, 무겁다는 큰 장점이 존재한다. 그만큼 속도도 느릴 뿐더러, 하나의 서비스를 확장하기 위해선 새로운 VM을 실행해야하는 등 비효율인 측면이 존재한다.
02 컨테이너 기반의 배포
VM의 무거운 단점을 해결하기 위해 컨테이너(Container) 개념이 등장한다. 컨테이너는 OS 전체가 아니라 애플리케이션과 실행 환경만 포함한다. 하나의 OS 위에서 여러 개의 컨테이너를 실행할 수 있고, VM보다 훨씬 가볍고 빠르다. VM과 같이 격리된 환경이고, 확장성이 높다.
VM의 하이퍼바이저 위에서 여러 개의 GuestOS를 실행하는 대신, 컨테이너는 호스트OS 커널을 사용하여 격리된 여러 개의 컨테이너를 실행한다. 즉, 컨테이너는 GuestOS를 사용하지 않고, HostOS에 컨테이너형 가상화 소프트웨어를 설치한다.
03 도커
컨테이너를 쉽게 만들고 실행할 수 있도록 도와주는 도구가 도커(Docker)다. Linux 컨테이너를 만들고 사용할 수 있도록 하는 컨테이너화 기술이다. 도커를 사용하면 실행 환경을 손쉽게 표준화할 수 있다. 도커 이미지를 만들면 어디서든 동일한 환경에서 실행 가능하다.
- 도커 이미지 (Image): 실행 환경을 포함한 패키지
- 도커 컨테이너 (container): 도커 이미지를 실행한 인스턴스(상태)
- 도커 파일 (Dokerfile): 컨테이너를 만들기 위한 스크립트
컨테이너 실행에 필요한 파일과 설정값 등을 포함하고 있는 도커 파일을 생성하고, 도커 이미지로 빌드하여 도커 컨테이너를 실행하는 순서로 진행된다.
도커 이미지를 도넛 레시피에 비유한다면, 도커 컨테이너는 해당 레시피를 이용해 만든 도넛으로 비유할 수 있다. 하나의 도넛 레시피에서 여러 가지 맛의 도넛을 만들 수 있는 것과 같이, 하나의 도커 이미지로 여러 개의 도커 컨테이너를 만들 수 있다. 또한, 기존의 도넛 레시피를 수정해도, 다른 도넛에는 영향이 없듯이 도커 컨테이너는 격리된 환경이다.
도커 파일 예제
# 1. 기본 이미지 설정 (Python 3.9 사용)
FROM python:3.9
# 2. 작업 디렉토리 설정
WORKDIR /app
# 3. 필요한 파일 복사
COPY . .
# 4. 필요한 패키지 설치
RUN pip install -r requirements.txt
# 5. 컨테이너가 실행될 때 실행할 명령어
CMD ["python", "app.py"]
# 6. 컨테이너가 사용할 포트 지정
EXPOSE 5000
04 도커 컴포즈
도커 컴포즈 (Docker Compose)는 여러 개의 컨테이너를 한꺼번에 관리하고 실행할 수 있도록 도와주는 도구이다. 예를 들어, 웹 서비스와 데이터베이스를 함께 실행한다면 웹 서버, 데이터베이스, 캐시 서버 이렇게 세 개이상의 컨테이너가 필요하다. 도커 컴포즈는 이를 한 번의 명령어로 모든 컨테이너를 실행하고 설정할 수 있다.
도커가 개별 컨테이너를 실행하는 방식이라면, 도커 컴포즈는 여러 개의 컨테이너를 정의하고 한꺼번에 실행한다. 개별 Dockerfile을 사용하는 것이 아닌, docker-compose.yml 파일을 사용하여 설정할 수 있다.
도커 컴포즈 파일 예제
version: '3.8' # Docker Compose 파일 버전
services:
web:
image: my-web-app:latest # 웹 애플리케이션 컨테이너
ports:
- "5000:5000" # 호스트의 5000번 포트를 컨테이너의 5000번 포트에 연결
depends_on:
- db # db 서비스가 먼저 실행된 후 web 실행
db:
image: mysql:latest # MySQL 데이터베이스 컨테이너
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mydatabase
MYSQL_USER: user
MYSQL_PASSWORD: password
ports:
- "3306:3306" # MySQL 기본 포트 매핑
volumes:
- db_data:/var/lib/mysql # 데이터베이스 데이터를 저장하는 볼륨
volumes:
db_data: # 데이터베이스 데이터를 저장할 볼륨 정의
05 쿠버네티스의 역할
쿠버네티스(Kubernetes)는 여러 개의 컨테이너를 관리하는 자동화된 배포 및 운영 시스템이다. 컨테이너를 자동으로 확장하고, 트래픽을 분배하며, 장애 복구까지 지원한다. 크게 세 가지 핵심 기능이 있다.
- 오토스케일링 (Auto Scaling)
- 트래픽(사용자로부터의 요청, 접속 수 등)이 급증할 경우 서버가 과부하에 걸려 서비스가 느려지거나 다운될 수 있다. 이를 위해 최대 트래픽을 감당하기 위해 항상 많은 서버를 유지해야 하므로 리소스 낭비가 심하다.
- 예를 들어, 웹 서비스에서 평소 트래픽이 1,000명 수준으로 가정하는데, 특정 시간 트래픽이 10배로 증가하면 느린 서버를 그대로 유지하거나, 최대 트래픽을 감당할 수 있도록 서버를 많이 배치하는 등으로 대응할 수 있다.
- 오토스케일링은 트래픽이 몰릴 때 자동으로 컨테이너 개수를 증가시켜 부하를 분산할 수 있다. 반대로 트래픽이 줄어들면 컨테이너를 줄여 리소스를 절약한다.
- 오토힐링 (Self-Healing)
- 장애가 발생한 컨테이너를 자동으로 감지하고 새로운 컨테이너를 생성한다.
- 서버에 장애가 발생(예를 들어 Pod 하나가 갑자기 종료됨)했을 경우, 사용자가 접속 할 수 없어서 Pod를 다시 실행해야 한다. 컨테이너가 죽으면 자동으로 생성해주는 것이 바로 오토힐링 기능이다.
- 롤링 업데이터 (Rolling Update)
- 서비스 중단 없이 새로운 버전으로 컨테이너를 업데이트한다.
- 기존 버전을 삭제하고 새 버전을 배포할 때 서비스를 중단해야하거나, 새로운 버전에 버그가 있으면 전체 서비스에 장애가 발생하는 등의 문제를 해결할 수 있다.
- 기존 버전을 천천히 교체하면서 서비스가 중단되지 않는다. 한 번에 모든 Pod를 업데이트하는 것이 아니라, 일부 교체 후 문제 없으면 나머지도 변경하는 등 이전 버전으로 쉽게 롤백이 가능하다.
06 쿠버네티스 기본 개념
쿠버네티스는 여러 개의 서버(노드)로 구성된 클러스터로 동작한다.
노드(Node) | 컨테이너가 실행되는 서버 |
파드(Pod) | 하나 이상의 컨테이너를 포함하는 최소 배포 단위 |
레플리카셋(ReplicaSet) | 파드 개수를 유지하고 자동 복구 |
디플로이먼트(Deployment) | 파드를 새로운 버전으로 업데이트 |
서비스(Service) | 트래픽을 적절한 파드로 분배 |
인그레스(Ingress) | 외부 요청을 API 서비스로 연결 |
네임스페이스(Namespace) | 여러 개의 환경(개발/운영 등) 분리 |
클러스터 생성 → Deployment 정의 → 클러스터에 배포
07 CI/CD (Continuous Integration & Continuous Deployment)
CI/CD는 애플리케이션을 자동으로 빌드, 테스트, 배포하는 파이프라인을 의미한다. 즉, 개발자가 코드 변경을 하면, 자동으로 새로운 버전이 배포되는 시스템이다.
CI(지속적 통합)은 개발자가 코드를 변ㅇ경하면 자동으로 빌드 & 테스트를 수행하고, 변경 사항을 빠르게 검증하여 문제를 사전에 방지하는 것을 말한다.
CD(지속적 배포)는 CI 이후 테스트를 통과한 코드를 자동으로 배포한다. 배포 과정이 자동화되므로 빠르게 배포가 가능하다.
CI/CD를 활용하면 코드를 자주 변경해도 안정적인 배포가 가능하고, 버그를 초기에 발견할 수 있다. 또한, 사람이 직접 배포하는 것보다 훨씬 빠르고 안정적이다.
대표적인 도구는 세 가지이다.
- Jenkins: 가장 널리 쓰이는 오픈소스 CI/CD 도구
- GitHub Actions: GitHub에서 제공하는 CI/CD 도구
- ArgoCd: 쿠버네티스 전용 CD(배포) 자동화 도구
예를 들어, 개발자가 GitHub에 코드를 푸시하면, CI 도구(Jenkins, GitHub Actions)가 변경감지 후 자동으로 빌드&테스트를 수행한다. 빌드에 성공하면 Docker 이미지 생성 후 Docker Hub에 업로드한다. CD 도구(ArgoCD)가 최신 버전의 이미지를 쿠버네티스 클러스테에 배포한다.
Reference
[Docker] 그래서 도커(Docker)랑 컨테이너(Container)가 뭐냐구요
쿠버네티스 알아보기 1편: 쿠버네티스와 컨테이너, 도커에 대한 기본 개념
https://aws.amazon.com/ko/compare/the-difference-between-kubernetes-and-docker/