[부트캠프 - 36일차] 2/10.화 - Docker

developowl·2026년 2월 12일

부트캠프

목록 보기
26/29
post-thumbnail

Docker Compose

Load Balancer

개요

  • 서버에 가해지는 부하(=로드)를 분산(=밸런싱)해주는 장치 또는 기술
  • 클라이언트와 서버풀(Server Pool, 분산 네트워크를 구성하는 서버들의 그룹) 사이에 위치하며 한 대의 서버로 부하가 집중되지 않도록 트래픽을 관리해 각각의 서버가 최적의 퍼포먼스를 보일 수 있도록 해주는 기술
  • 리소스 활용도를 최적화하고 처리량을 최대화하며 지연 시간을 줄이고 내결함성(fault tolerance) 구성을 보장하기 때문에 안정적인 시스템 운영에 도움이 됨
  • docker 는 HaProxy, Nginx/Apache Load Balancer 등 외부 서비스와 컨테이너를 결합한 Load Balancing 기능 구현이 가능

Load Balancing 연결 알고리즘

  • Round-Robin, RR
  • Least Connections
  • IP hash
  • general hash
  • Least Time
  • Random

종류

  • L4 로드밸런싱
  • L7 로드밸런싱

nginx Load Balancing 관련 파라미터

연결 알고리즘설명
weight가중치 설정을 통해 서버 간 요청 분배(기본값=1)
max_conns, queue최대 클라이언트 연결 수 지정과 대기열 생성
max_fails최대 실패 횟수 지정을 통해 임계치 도달 시 해당 서버를 분배 대상에서 제외
fail_timeout응답 최소 시간 지정으로 실패 횟수를 카운트함. 보통 max_fails 와 함께 사용함
backupbackup 키워드가 있는 서버는 평소에 동작하지 않고, 모든 서버가 동작하지 않을 떄 사용
downdown 키워드가 있는 서버는 사용하지 않음. ip_hash인 경우만 사용

nginx 컨테이너가 로드밸런서 역할

환경 변수 삽입 및 관리

환경 변수를 다루는 방법

Compsoe 파일에 직접 입력

  • MySQL 이미지로 컨테이너를 구동시킬 때엔 MySQL의 관리자(root) 계정 비밀번호를 생성할 MYSQL_ROOT__PASSWORD 변수값이 반드시 필요한데 이럴 땐 배포용 Compose 파일에서 services.<서비스명>.environment 부분에 해당 내용을 변수명: 값 또는 - 변수명=값 형태로 넣어주면 됨
# MySQL 8 이미지에 MYSQL_ROOT_PASSWORD 환경 변수값을 password로 지정하여 둔
Compose 파일
services:
	mysql:
		image: mysql:8
		restart: unless-stopped
		ports:
			- 3306:3306
		environment:
			MYSQL_ROOT_PASSWORD: password

쉘 환경 변수로 등록

# 쉘 환경 변수 설정
export MYSQL_ROOT_PASSWORD=password

# MySQL 8 이미지에 MYSQL_ROOT_PASSWORD 환경 변수값을 password로 지정하여 둔 Compose 파일
services:
	mysql:
		image: mysql:8
		restart: unless-stopped
		ports:
			- 3306:3306
		environment:
			MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
			
# 실제 내용 확인
docker-compose convert

환경 변수 파일로 구성

  • 배포용 Compose 파일에 환경 변수를 하나하나 다 적어넣거나 매번 쉘에서 변수로 직접 선언하는 방법은 다소 비효율적

  • 필요한 환경 변수 항목들만 골라내어 별도의 파일로 구성해 둔다면 환경 변ㅅ우 관리를 보다 효율적으로 할 수 있음

  • Docker Compose에서 환경 변수 정보들을 떼어 별도의 파일을 구성할 때 가장 간편한 방법은 Compose 파일이 위치한 동일 경로에 .env 파일을 따로 구성하는 것

  • .env 파일을 이용하는 방식은 간편하기는 하지만 Docker Compose 에서 docker compose up 명령을 수행할 때만 활용 가능

  • env 파일 문법

    • 각 줄마다 변수명=값 의 형태로 입력
    • 주석 처리는 #
    • 비어있는 줄은 무시
    • , “” 는 불팔요한데 입력된 따옴표는 위치에 따라 변수명이나 값의 일부분으로 간주
# 이전에 만든 환경 변수 삭제
unset MYSQL_ROOT_PASSWORD

# docker-compsoe 파일과 동일한 위치에 .env 파일을 생성하고 작성
MYSQL_ROOT_PASSWORD=password

# 실행 시 파일 지정하기
docker compose --env-file ./config/.env.dev config
  • 실행 시 파일 지정하기

    • 경우에 따라 여러 개의 환경변수 파일로 나누는 일이 필요할 수 있는데 개발 환경(dev)과 운영 환경(prod)에 따라 주입해야 할 값들이 다른 경우엔 각각의 환경에 맞는 별도의 env_file을 구성한 뒤 배포할 때 --env-file <파일경로> 플래그로 불러올 파일을 직접 지정할 수 있음
  • 서비스 별로 환경 변수 파일 설정

  • 각 서비스(컨테이너)에 대한 환경 변수 파일을 별도로 관리해야 할 수도 있는데 이런 경우에는 Compose 파일에 명시된 각 서비스 안에 env_file 항목을 함께 포함시키게 되는데 이 항목을 따로 명시하지 않았다면 기본적으로는 env_file: .env이 적용된 상태

Dockerfile에 환경 변수를 직접 삽입

  • 환경 변수를 YAML이나 별도의 외부 파일로 담아두는 것이 꺼려지는 경우 Dockerfile 에 ARG 또는 ENV를 이용하여 환경 변수를 직접 삽입한 뒤 나만의 이미지를 빌드하여 사용
# Dockerfile
FORM mysql:8
ENV MYSQL_ROOT_PASSWORD password

우선 순위

  1. Compose 파일에 직접 입력한 값
  2. 쉘 환경변수로 등록한 값
  3. 환경변수 파일로 입력된 값(.env 등)
  4. Dockerfile을 통해 삽입된 값

한계점

  • Docker Compose 에서의 환경변수 관리 방법에는 공통적인 단점이 하나 있는데, 모든 정보가 plain text로 저장된다는 것
  • 이처럼 중요한 보안 정보가 평문 상태로 호스트에 남아있도록 하는 것은 보안 측면에서 결코 바람직하지 않음
  • 운영 환경에서 보완하는 방법
    • 프라이빗 레지스트리 구축
    • 오케스트레이션 도구의 시크릿 사용
    • HashiCorp Vault 등의 보안 솔루션 사용

신뢰성 확보

Health Check

개요

  • 도커는 컨테이너를 시작할 때마다 애플리케이션의 기본적인 상태를 확인
  • 컨테이너를 실행하면 내부에서 애플리케이션 실행 파일이나 특정 프로세스가 실행됨
    • 도커가 확인하는 것은 이 프로세스의 실행 상태인데 만약 이 프로세스가 종료됐다면 컨테이너도 종료 상태가 되는데, 이것만으로도 환경과 상관없이 기본적인 헬스 체크는 가능
  • 해당 프로세스가 비정장 종료됐거나 컨테이너가 종료됐다면 개발자도 애플리케이션의 상태가 비정상임을 알 수 있음
  • 클러스터 환경에서는 플랫폼이 종료된 컨테이너를 재시작하거나 새 컨테이너로 교체하는 작업을 대신 수행
  • 애플리케이션이 동작을 멈췄어도 도커는 컨테이너를 정상이라 판단

헬스 체크

# 이미지 빌드
docker build -t my-health-app .

# 컨테이너 실행
docker run -d --name health-test-my-health-app

# 상태 확인
docker ps
  • docker ps를 입력했을 때 STATUS 항목
    • starting : 컨테이너가 막 실행되어 헬스체크를 기다리는 중
    • healthy : curl 명령이 성공하여 정상 작동 중
    • unhealthy : 설정된 횟수만큼 헬스체크가 실패함

헬스 체크가 중요한 이유

  • 자동 복구
    • Docker Swarm 이나 Kubernetes 같은 오케스트레이션 도구는 unhealthy 상태의 컨테이너를 자동으로 재시작하거나 교체
  • 무중단 배포
    • 로드밸런서와 연동할 때 새 컨테이너가 healthy 가 될 때까지 트래픽을 보내지 않도록 제어할 수 있음

Docker Compose 헬스 체크

  • docker-compose.yml 파일에서 서비스 하위에 healthcheck 항목을 추가하면 Dockerfile 에 이미 헬스 체크가 있더라도 Compose 파일에 작성한 내용이 우선순위를 가짐
# 기본 형식
services:
	web:
		image: my-health-app
		ports:
			- "8080:8080"
		healthcheck:
			test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
			interval: 10s
			timeout: 5s
			retries: 3
			start_period: 5s
  • test
    • 실행할 명령어
  • interval
    • 헬스 체크를 수행하는 주기
  • timeout
    • 이 시간 안에 응답이 없으면 실패로 간주
  • retries
    • 연속으로 몇 번 실패해야 unhealthy 로 바꿀지 결정
  • start_period
    • 앱 초기회 시간을 벌어주는 것으로 이 시간 동안의 실패는 횟수에 포함하지 않음
  • 기존의 depends_on 은 컨테이너가 시작만 되면 바로 다음 컨테이너를 실행하지만 condition: service_healthy 를 사용하면, DB가 내부 설정을 마치고 실제 쿼리를 받을 준비가 끝날 때까지 웹 서버 실행을 우직하게 기다려주는데 덕분에 “DB 연결 실패” 로 웹 서버가 동작하지 않는 현상을 방지할 수 있음

Docker Swarm

Container Orchestration

개요

  • 수많은 컨테이너의 배포, 관리, 확장, 네트워킹을 자동화하는 프로세스

필요한 이유

  • 대규모 관리
    • 수천 개의 컨테이너를 하나하나 수동으로 실행하고 끄는 것은 비효율적
  • 장애 복구(Self-healing)
    • 특정 컨테이너가 죽었을 때 즉시 감지하고 새 컨테이너를 띄워야 함
  • 확장성(Scaling)
    • 사용자가 몰릴 때 컨테이너 수를 자동으로 늘리고 한산해지면 줄여야 함
  • 로드 밸런싱
    • 트래픽을 여러 컨테이너에 골고루 분산시켜야 함

핵심 기능

  • 프로비저닝 및 배포
    • 어떤 서버에 컨테이너를 띄울지 결정하고 실행
  • 리소스 할당
    • 컨테이너가 필요로 하는 CPU나 메모리를 적절히 배정
  • 상태 모니터링
    • 컨테이너가 건강하게 돌아가고 있는지 감시
  • 서비스 디스커버리
    • 컨테이너끼리 서로를 찾아서 통신할 수 있게 연결
  • 보안
    • 컨테이너 간의 접근 권한을 관리

대표적인 도구

  • Kubernetes : 사실상 표준인데 기능이 매우 강력하고 생태게가 넓지만 배우기가 다소 어려움
  • Docker Swarm : 도커에서 직접 만든 도구로 설치가 쉽고 간단한 환경에 적합
  • Amazon ECS : AWS 전용 컨테이너 관리 서비스로 AWS 환경을 쓰고 있다면 연동성이 매우 뛰어난데 현재는 다양한 CSP에서 제공

Docker Swarm

개요

  • 여러 호스트를 클러스터로 묶어주는 컨테이너 오케스트레이션 도구의 한 종류

  • 컨테이너 오케스트레이션 도구 없이는 도커 호스트 여러 대를 사용하는 확장성 있는 애플리케이션을 만들기 매우 어려움

  • 어느 도커 호스트에 어떤 컨테이너를 배치해야 하는지 서로 다른 호스트에 위치한 컨테이너 간의 통신은 어떻게 제어하는지 등의 조율을 오케스트레이션 도구 없이 하기는 무리

  • 오케스트레이션 도구를 도입하면 이러한 조율에 수고를 절감할 뿐만 아니라 호스트가 여러 대로 나뉘어 있다는 점을 신경 쓰지 않고 클러스터를 투명ㅎ게 다룰 수 있다는 이점도 있읍

  • docker-compose

    • 여러 컨테이너로 구성된 도커 애플리케이션을 관리(주로 단일 호스트)
  • docker swarm

    • 클러스터 구축 및 관리(주로 멀티 호스트)
  • docker service

    • 스웜에서 클러스터 안의 서비스(컨테이너 하나 이상의 집합)를 관리
  • docker stack

    • 스웜에서 여러 개의 서비스를 합한 전체 애플리케이션을 관리

여러 대의 도커 호스트로 스웜 클러스터 구성

  • 윈도우용/맥용 도커를 설치하면 호스트가 1대 뿐이므로 여러 대의 호스트를 갖추려면 클라우드 서비스 등을 사용해야 함
  • Docker Machines 를 사용하면 여러 대의 도커 호스트를 만들 수 있지만 Docker Machines 를 사용하려면 맥에서는 virtualbox 드라이버, 윈도우에서는 hyperv 드라이브가 각각 필요
  • Docker in Docker 라는 기능을 사용하면 도커 컨테이너 안에서 도커 호스트를 실행할 수 있음
  • 가상 머신을 사용하면 가상 머신 시작 및 정지에 시간이 걸리고 오버헤드로 소모되는 머신 리소스도 큼

주요 기능

  • 도커 엔진과 통합된 다중 서버 클러스터 환경

    • 도커 엔진에 포함됨 도커 스웜 모드를 통해 별도의 오케스트레이션 도구를 설치하지 않아도 컨테이너 애플리케이션 서비스를 배포하고 관리할 수 있음
  • 서비스 확장과 원하는 상태 조정

    • 도커 스웜 모드에서 서비스 생성 시 안정적인 서비스를 위해 Replicas Option(중복) 인 서비스 배포를 할 수 있고, 초기 구성 후 스웜 관리자를 통해 애플리케이션 가용성에 영향을 주지 않고도 서비스 확장 및 축소를 수행할 수 있음
    • 배포된 서비스는 매니저 노드를 통해 지속적으로 모니터링
    • 사용자가 요청한 상태와 다르게 서비스 장애(노드 장애 및 서비스 실패 등)가 생길 경우 장애가 발생한 서비스를 대체할 새로운 복제본을 자동으로 생성하여 사용자 요구를 지속하게 되는데 이것이 요구 상태 관리(desire state management)
    • 대부분의 오케스트레이션 도구는 요구 상태 관리를 기본 목적으로 함
  • 서비스 스케줄링

    • 구성한 도커 스웜 모드 클러스터 내의 노드에 작업 단위의 서비스 컨테이너를 배포하는 작업
    • 도커 클래식 스웜 엔진의 노드 선택 전략은 swarm manage --strategy (option) 방식을 통해 선택
      • 모든 작업자 노드에 균등하게 할당하는 spread(분산) 전략
      • 작업자 노드의 자원 사용량을 고려하여 할당하는 binpack(자원대비) 전략
      • 임의의 노드에 할당하는 random(무작위) 전략
    • 도커 스웜 모드는 단일 옵션으로 고가용성 분산 알고리즘(HA spread algorithm)을 사용하는데 이 방식은 생성되는 서비스의 복제본을 분산 배포하기 위해 현재 복제본이 가장 적은 작업자 노드 중에서 이미 스케줄링된 다른 서비스 컨테이너 수가 가장 적은 작업자 노드를 우선 선택
  • 로드 밸런싱

    • 도커 스웜 모드를 초기화(docker swarm init) 하면 자동으로 생성되는 네트워크 드라이버 중 하나가 Ingress network
    • 인그레스 네트워크는 서비스의 노드 간 load balancing 과 외부에 서비스를 노출하기 위해 사용되는 overlay network
    • 워커 노드1에 nginx 웹 서비스 컨테이너가 실행 중이라고 가정하면 워커 노드2에서 노출된 포트로 접속해도 워커 노드 1의 nginx 웹 서비스에 접속이 가능한데 인그레스 네트워크를 통해 자동 로드 밸런싱이 수행되는 것
  • 서비스 검색

    • 도커 스웜 모드는 서비스 검색을 위해 자체 DNS 서버를 통한 서비스 검색 기능을 제공
    • 도커 스웜 모드 매니저 노드는 클러스터에 합류된 모든 노드의 서비스에 고유한 DNS 이름을 할당하고 할당된 DNS 이름은 도커 스웜 모드에 내장된 DNS 서버를 통해 스웜 모드에서 실행 중인 모든 컨테이너를 조회할 수 있게 되는데 이것을 service discovery 라고 함
  • Rolling Update

    • 도커 스웜 모드 매니저 노드를 통해 현재 실행 중인 서비스 컨테이너늬 업데이트를 노드 단위로 점진적으로 적용할 수 있는 Rolling update를 할 수 있음
    • 롤링 업데이트는 각 작업자 노드에서 실행 중인 서비스 컨테이너를 노드 단위의 지연적 업데이트를 수행하는 것
    • 롤링 업데이트는 새 버전 서비스 컨테이너를 하나씩 늘려가고 이전 버전 서비스 컨테이너를 하나씩 줄여가는 방식인 것
    • 업데이트가 실패할 경우 다양한 기능을 통해 재시도 및 업데이트 중지 등을 수행할 수도 있고 잘못된 업데이트를 취소하기 위해 rollback 기능도 제공

Docker Swarm 클러스터 구성

서버 구성

  • 서버 기본 구성
swarm-manager: 192.168.56.100
swarm-worker1: 192.168.56.101
swarm-worker2: 192.168.56.102
  • Ubuntu 에서 IP 설정 방법
# 인터페이스 확인
ip link show

# netplan 설정 파일 편집
sudo nano /etc/netplan/00-installer-config.yaml
network:
 version: 2
 renderer: networkd
 ethernets:
	 enp0s3:
		 dhcp4: no
		 addresses: [192.168.56.101/24]
		 gateway4: 192.168.56.1
		 nameservers:
			 addresses: [8.8.8.8, 1.1.1.1]

# netplan 변경 내용 적용
sudo netplan apply

# 확인
ip addr show
  • 호스트명 수정
sudo hostnamectl set-hostname swarm-manager

cat /etc/hostname
# >>> swarm-manager

# 호스트 이름과 IP 연결
sudo vi /etc/hosts
	127.0.0.1 localhost
	127.0.1.1 swarm-manager
	192.168.56.100 swarm-manager
	192.168.56.101 swarm-worker1
	192.168.56.102 swarm-worker2
  • 도커 스웜은 도커 엔진에 포함돼 있어 별도의 설치가 필요 없음
  • 도커 엔진을 스웜 모드로 전환해 클러스터를 초기화하면 됨
  • 도커 스웜 모드 초기화
    • docker swarm init [옵션]
    • 보통은 아무 인자 없이 사용하는 명령이지만 호스트 컴퓨터가 하나 이상의 네트워크에 접속돼 있다면 스웜 통신에 사용할 IP 주소를 선택하라는 메시지와 함께 오류를 발생시킴
    • 도커 엔진 1.24 이상에서만 구성 가능하며 이 작업을 수행하는 서버가 자동으로 관리자 역할을 수행하는 매니저 노드가 됨
# 네트워크 확인
sudo netstat -nlp | grep dockerd

# 조인 토큰을 복사하여 작업자 노드에서 사용
docker swarm join --token SWMTKN-1-
1fg7u28amdxbhrcyikttyxb3zt3vkmohfie0bkf2no366tqk39-
ceyhpl97r6ddamirdfxkp8p9k 192.168.56.100:2377

# 조인 토큰 조화(manager node에서 수행)
docker swarm join-token worker

# 매니저 노드를 추가하는 경우 새로운 토큰 생성 (manager node에서 수행)
docker swarm join-token manager

# 연결 확인 (manager node에서 수행)
docker node ls

# 도커 스웜 모드에 대한 세부 정보 확인 (manager ndoe에서 수행)
docker info

# 새로운 네트워크 확인 (manager node에서 실행)
docker network ls

# 운영 중 노드의 확장을 위해 토큰이 필요한 경우 (manager node에서 수행)
docker swarm join-token --rotate worker

# join 토큰만 필요한 경우 (manager node에서 수행)
docker swarm join-token -q worker

# 작업자 노드 제거 (manager node에서 수행)
docker swarm leave swarm-worker2

# 작업자 노드 제거 (!!!{workder}!!! node에서 수행)
docker swarm leave

nginx를 이용한 서비스 컨테이너 배포와 관리

  • 도커 스웜 모드 클러스터는 서비스 컨테이너를 복제 모드로 배포할 경우 구성된 모든 클러스터 노드에서 접속이 가능
  • 서비스 컨테이너 생성 시 노출할 포트를 --publish 옵션으로 구성할 수 있고 서비스 컨테이너가 포트를 오픈하면 동시에 모든 노드에서 동일한 포트가 오픈되기 때문에 클러스터에 합류된 어떤 노드에 요청을 전달해도 실행 중인 서비스 컨테이너에 자동 전달되는데 이것은 모든 노드가 스웜 모드의 라우팅 메시에 참여하기 때문
  • 인그레스 네트워크를 통해 자동 로드 밸런싱을 수행

도커 스웜 클러스터에서 네트워크 트래픽 관리

  • 컨테이너에서 실행되는 애플리케이션의 입장에서 스웜 모드의 네트워크는 표준 TCP/IP 방식
  • 컴포넌트는 도메인 네임으로 서로를 식별하며 도커 DNS 서버가 도메인 네임을 조회해 IP 주소를 알려 주면 이 IP 주소로 트래픽을 전달
  • 스웜 모드에서는 서로 다른 노드에서 실행 중인 컨테이너 간에 요청과 응답을 주고받을 수 있지만 컨테이너와 컨테이너에서 실행 중인 애플리케이션은 이를 신경 쓸 필요가 없음
  • 스웜 모드에서는 오버레이 네트워크(overlay network)라는 새로운 형태의 도커 네트워크를 사용하는데 오버레이 네트워크는 클러스터에 속한 모든 노드를 연결하는 가상 네트워크
  • 오버레이 네트워크에 연결된 서비스는 서비스 이름을 도메인 네임 삼아 다른 서비스와 통신할 수 있음
  • 각 애플리케이션은 여러 노드에 걸쳐 실행되는 여러 개의 서비스로 구성되는데 같은 애플리케이션에 속하는 서비스는 오버레이 네트워크를 통해 통신이 가능하지만 오버레이 네트워크 자체는 서로 독립적이기 때문에 서로 다른 네트워크에 속한 서비스는 통신이 불가능

서비스 유지 관리 기능

  • 기본적으로 대부분의 오케스트래이션 도구는 장애 복구 기능을 내장하고 있음
  • 도커 스웜 모드 클러스터에서는 장애 대비를 할 수 있는 복제 모드(--replicas) 기능을 제공하고, 배포된 서비스 장애 및 노드의 장애가 발생하면 자동으로 복제 수만큼의 서비스를 맞추어 장애에 대한 자동 복구를 수행
  • 패키지 버전 변경 수행 시 서비스를 중단하지 않고 롤링 업데이트 기능을 사용하면 새 버전 서비스 컨테이너는 하나씩 늘려가고 이전 버전 서비스 컨테이너는 하나씩 줄여가는 방식으로 버전 업데이트를 수행할 수 있음
  • 업데이트가 실패할 경우 다양한 기능을 통해 재시도 및 업데이트 중지 등을 선택 수행할 수도 있고 잘못된 업데이트를 취소하기 위해 롤백 기능도 제공
profile
Don’t get mad at the computer.

0개의 댓글