Docker Swarm 관리 및 유지보수

Docker Swarm 관리 및 유지보수

Docker 엔진으로 Swarm을 운영할 때 매니저 노드는 Swarm 상태를 관리하고 저장하는 핵심 역할을 담당해요. 매니저 노드의 주요 특징을 제대로 이해해야 Swarm을 안정적으로 배포하고 유지할 수 있답니다. 이 가이드에서는 매니저 노드 운영, 쿼럼 유지, 백업과 복구, 문제 해결 방법까지 차근차근 설명드릴게요.

출처: 공식문서

본문

Swarm에서 매니저 노드 운영하기

Swarm 매니저 노드는 Raft Consensus Algorithm을 사용해서 Swarm 상태를 관리해요. Swarm을 운영하기 위해 Raft의 모든 것을 알 필요는 없고, 몇 가지 핵심 개념만 이해하면 충분해요. Docker Swarm mode와 매니저·워커 노드의 차이에 대한 개요는 How nodes work 문서를 참고하세요.

매니저 노드 수에는 제한이 없어요. 매니저 노드를 몇 개나 둘지는 성능과 내결함성 사이의 트레이드오프라고 볼 수 있어요. 매니저 노드를 추가하면 Swarm이 더 견고해지지만, 그만큼 쓰기 성능은 떨어져요. 왜냐하면 Swarm 상태를 업데이트할 때 더 많은 노드가 제안을 승인해야 하고, 네트워크 왕복 트래픽도 늘어나기 때문이에요.

Raft는 Swarm에 노드를 추가하거나 제거할 때 매니저들의 과반수 동의, 즉 쿼럼(quorum)이 필요해요. 멤버십 변경 작업도 상태 복제와 동일한 제약 조건을 따라요.

매니저 쿼럼 유지하기

Swarm이 매니저 쿼럼을 잃으면 관리 작업을 수행할 수 없어요. 매니저가 여러 개라면 항상 2개보다는 많은 수를 유지하세요. 쿼럼을 유지하려면 매니저의 과반수가 사용 가능해야 해요. 매니저 수는 홀수로 두는 것이 좋아요. 짝수로 늘려봐야 쿼럼 유지가 더 쉬워지지 않기 때문이에요. 예를 들어 매니저가 3개든 4개든, 쿼럼을 유지하면서 잃을 수 있는 매니저는 여전히 1개뿐이에요. 5개든 6개든 마찬가지로 2개까지만 잃어도 쿼럼이 유지돼요.

쿼럼을 잃더라도 기존 워커 노드에서 실행 중인 작업은 계속 동작해요. 다만 Swarm 노드를 추가·업데이트·제거할 수 없고, 새 작업을 시작하거나 기존 작업을 중지·이동·업데이트할 수도 없어요.

쿼럼을 잃었을 때의 문제 해결 방법은 쿼럼 손실 복구 섹션에서 확인하세요.

매니저가 고정 IP 주소로 광고하도록 설정하기

Swarm을 초기화할 때 --advertise-addr 플래그를 지정해서 다른 매니저 노드들에게 자신의 주소를 알려야 해요. 자세한 내용은 Run Docker Engine in swarm mode를 참고하세요. 매니저 노드는 인프라의 안정적인 구성 요소로 설계되었기 때문에, 광고 주소는 고정 IP 주소를 사용해야 해요. 그래야 머신이 재부팅되어도 Swarm이 불안정해지지 않아요.

Swarm 전체가 재시작되고 모든 매니저 노드가 새 IP 주소를 받게 되면, 어떤 노드도 기존 매니저에게 연락할 방법이 없어져요. 노드들이 예전 IP 주소로 서로를 찾으려 하면서 Swarm이 멈춰버리게 돼요.

워커 노드의 경우 동적 IP 주소를 사용해도 괜찮아요.

내결함성을 위한 매니저 노드 추가

매니저 노드 장애에 대비하려면 Swarm에 홀수 개의 매니저를 유지하는 것이 좋아요. 홀수 개의 매니저를 두면 네트워크가 두 개로 분할되는 상황에서도 쿼럼이 살아남아 요청을 처리할 확률이 높아져요. 다만 네트워크 파티션이 3개 이상으로 쪼개지면 쿼럼 유지를 보장할 수 없어요.

Swarm 크기 과반수 내결함성
1 1 0
2 2 0
3 2 1
4 3 1
5 3 2
6 4 2
7 4 3
8 5 3
9 5 4

예를 들어 5개 노드로 구성된 Swarm에서 3개 노드를 잃으면 쿼럼이 성립되지 않아요. 따라서 사용 불가능한 매니저 노드 중 하나를 복구하거나 재해 복구 명령으로 Swarm을 복원하기 전까지는 노드를 추가하거나 제거할 수 없어요. 자세한 내용은 재해 복구를 참고하세요.

Swarm을 매니저 1개로 줄이는 것은 가능하지만, 마지막 매니저 노드를 demote(강등)하는 것은 불가능해요. 이는 Swarm에 대한 접근 권한을 유지하고 Swarm이 계속 요청을 처리할 수 있도록 보장하기 위해서예요. 매니저 1개로 줄이는 것은 안전하지 않은 작업이므로 권장하지 않아요. demote 작업 중에 마지막 노드가 예기치 않게 Swarm을 떠나면, 노드를 재부팅하거나 --force-new-cluster로 재시작할 때까지 Swarm을 사용할 수 없게 돼요.

Swarm 멤버십은 docker swarmdocker node 하위 시스템으로 관리해요. 워커 노드를 추가하고 워커를 매니저로 승격하는 방법은 Add nodes to a swarm에서 자세히 알아보세요.

매니저 노드 분산 배치

홀수 개의 매니저를 유지하는 것과 함께, 매니저를 배치할 때 데이터센터 토폴로지도 고려해야 해요. 최적의 내결함성을 위해 매니저 노드를 최소 3개의 가용 영역(availability zone)에 분산 배치하세요. 그래야 특정 영역의 전체 머신이 실패하거나 일반적인 유지보수 상황에서도 대응할 수 있어요. 어느 한 영역에서 장애가 발생해도 Swarm은 쿼럼을 유지하면서 요청을 처리하고 워크로드를 리밸런싱할 수 있어야 해요.

Swarm 매니저 노드 수 3개 가용 영역 분산
3 1-1-1
5 2-2-1
7 3-2-2
9 3-3-3

매니저 전용 노드로 운영하기

기본적으로 매니저 노드는 워커 노드 역할도 겸해요. 즉 스케줄러가 매니저 노드에 작업을 할당할 수 있다는 뜻이에요. 소규모이거나 중요도가 낮은 Swarm에서는 CPU와 메모리 리소스 제약 조건으로 서비스를 스케줄링한다면 매니저에 작업을 할당해도 비교적 위험이 낮아요.

하지만 매니저 노드는 Raft 합의 알고리즘으로 데이터를 일관되게 복제하기 때문에 리소스 부족에 민감해요. Swarm 하트비트나 리더 선출 같은 Swarm 운영을 방해할 수 있는 프로세스로부터 매니저를 격리하는 것이 좋아요.

매니저 노드의 운영을 방해하지 않도록 drain(드레인) 상태로 만들어 워커로 사용되지 않게 할 수 있어요:

$ docker node update --availability drain <NODE>

노드를 drain하면 스케줄러가 해당 노드에서 실행 중인 모든 작업을 다른 사용 가능한 워커 노드로 재할당해요. 또한 스케줄러가 그 노드에 새 작업을 할당하지 못하게 막아줘요.

로드 밸런싱을 위한 워커 노드 추가

Swarm에 노드를 추가해서 Swarm의 부하를 분산하세요. 워커 노드가 서비스 요구 사항에 부합한다면, 복제된 서비스 작업은 시간이 지남에 따라 Swarm 전체에 최대한 고르게 분산돼요. 특정 유형의 노드(예: 특정 CPU 수나 메모리 크기를 가진 노드)에서만 실행되도록 서비스를 제한할 때는, 요구 사항을 충족하지 못하는 워커 노드에서는 해당 작업을 실행할 수 없다는 점을 기억하세요.

Swarm 상태 모니터링

매니저 노드의 상태는 /nodes HTTP 엔드포인트를 통해 JSON 형식의 docker nodes API를 조회해서 모니터링할 수 있어요. 자세한 내용은 nodes API documentation을 참고하세요.

명령줄에서는 docker node inspect <id-node>를 실행해서 노드를 조회할 수 있어요. 예를 들어, 노드가 매니저로서 연결 가능한지(reachability) 확인하려면:

$ docker node inspect manager1 --format "{{ .ManagerStatus.Reachability }}"
reachable

워커로서 작업을 받을 수 있는 상태인지 확인하려면:

$ docker node inspect manager1 --format "{{ .Status.State }}"
ready

이 명령들을 통해 manager1이 매니저로서 reachable 상태이고 워커로서 ready 상태임을 알 수 있어요.

unreachable 상태는 해당 매니저 노드가 다른 매니저 노드에서 접근할 수 없다는 뜻이에요. 이 경우 다음 조치를 취해서 복구해야 해요:

  • 데몬을 재시작해서 매니저가 다시 reachable 상태가 되는지 확인하세요.
  • 머신을 재부팅하세요.
  • 재시작이나 재부팅으로 해결되지 않으면, 매니저 노드를 추가하거나 워커를 매니저로 승격하세요. 그리고 docker node demote <NODE>docker node rm <id-node> 명령으로 실패한 노드 항목을 매니저 집합에서 깔끔하게 제거해야 해요.

또는 매니저 노드에서 docker node ls 명령으로 Swarm 상태 개요를 확인할 수도 있어요:

$ docker node ls
ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
1mhtdwhvsgr3c26xxbnzdc3yp node05 Accepted Ready Active
516pacagkqp2xc3fk9t1dhjor node02 Accepted Ready Active Reachable
9ifojw8of78kkusuc4a6c23fx * node01 Accepted Ready Active Leader
ax11wdpwrrb6db3mfjydscgk7 node04 Accepted Ready Active
bb1nrq2cswhtbg4mrsqnlx1ck node03 Accepted Ready Active Reachable
di9wxgz8dtuh9d2hn089ecqkf node06 Accepted Ready Active

매니저 노드 문제 해결

다른 노드에서 raft 디렉토리를 복사해서 매니저 노드를 재시작하면 절대 안 돼요. 데이터 디렉토리는 노드 ID에 고유하기 때문이에요. 노드는 한 번 사용한 노드 ID로만 Swarm에 다시 조인할 수 있어요. 노드 ID 공간은 전역적으로 고유해야 해요.

매니저 노드를 클러스터에 깔끔하게 다시 조인하려면:

  1. docker node demote <NODE> 명령으로 노드를 워커로 강등하세요.
  2. docker node rm <NODE> 명령으로 노드를 Swarm에서 제거하세요.
  3. docker swarm join 명령으로 새 상태로 노드를 Swarm에 다시 조인하세요.

매니저 노드를 Swarm에 조인하는 방법에 대한 자세한 내용은 Join nodes to a swarm을 참고하세요.

노드 강제 제거

대부분의 경우 docker node rm 명령으로 Swarm에서 노드를 제거하기 전에 노드를 종료해야 해요. 노드가 unreachable 상태가 되거나 응답하지 않거나 손상(compromised)된 경우에는 --force 플래그를 사용해서 종료하지 않고 강제로 제거할 수 있어요. 예를 들어 node9가 손상된 경우:

$ docker node rm node9

Error response from daemon: rpc error: code = 9 desc = node node9 is not down and can't be removed

$ docker node rm --force node9

Node node9 removed from swarm

매니저 노드를 강제로 제거하기 전에 먼저 워커 역할로 강등해야 해요. 매니저를 강등하거나 제거할 때는 항상 홀수 개의 매니저를 유지하도록 하세요.

Swarm 백업

Docker 매니저 노드는 Swarm 상태와 매니저 로그를 /var/lib/docker/swarm/ 디렉토리에 저장해요. 이 데이터에는 Raft 로그를 암호화하는 데 사용되는 키도 포함되어 있어요. 이 키가 없으면 Swarm을 복원할 수 없어요.

아무 매니저에서나 Swarm을 백업할 수 있어요. 절차는 다음과 같아요.

  1. Swarm에 auto-lock이 활성화되어 있다면 백업에서 Swarm을 복원하려면 잠금 해제 키(unlock key)가 필요해요. 필요한 경우 잠금 해제 키를 확인해서 안전한 곳에 보관하세요. 확실하지 않다면 Lock your swarm to protect its encryption key를 읽어보세요.

  2. 백업 중에 데이터가 변경되지 않도록 매니저에서 Docker를 중지하세요. 매니저가 실행 중인 상태에서도 백업("hot" 백업)이 가능하지만 권장하지 않아요. 복원 시 결과를 예측하기 어렵기 때문이에요. 매니저가 중지된 동안 다른 노드들은 이 백업에 포함되지 않은 Swarm 데이터를 계속 생성한다는 점도 유의하세요.

Note

Swarm 매니저 쿼럼을 유지해야 해요. 매니저 하나가 종료된 동안 추가로 노드를 잃으면 쿼럼을 잃을 위험이 더 커져요. 매니저 수는 트레이드오프예요. 백업을 위해 정기적으로 매니저를 내리는 상황이라면 매니저 5개로 운영하는 것을 고려해보세요. 백업이 진행되는 동안 매니저 하나를 더 잃어도 서비스에 지장 없이 쿼럼을 유지할 수 있으니까요.

  1. /var/lib/docker/swarm 디렉토리 전체를 백업하세요.

  2. 매니저를 다시 시작하세요.

복원 방법은 백업에서 복원을 참고하세요.

재해 복구

백업에서 복원

Swarm 백업에서 설명한 대로 백업한 후, 다음 절차로 새 Swarm에 데이터를 복원할 수 있어요.

  1. 복원 대상 호스트 머신에서 Docker를 종료하세요.

  2. 새 Swarm의 /var/lib/docker/swarm 디렉토리 내용을 제거하세요.

  3. 백업 내용으로 /var/lib/docker/swarm 디렉토리를 복원하세요.

Note

새 노드는 이전 노드와 동일한 디스크 저장 암호화 키를 사용해요. 현재로서는 디스크 저장 암호화 키를 변경할 수 없어요.

auto-lock이 활성화된 Swarm의 경우 잠금 해제 키도 이전 Swarm과 동일하며, Swarm을 복원하려면 잠금 해제 키가 필요해요.

  1. 새 노드에서 Docker를 시작하세요. 필요한 경우 Swarm 잠금을 해제하세요. 다음 명령으로 Swarm을 다시 초기화하세요. 이렇게 하면 이 노드가 이전 Swarm에 속했던(아마 더 이상 존재하지 않는) 노드들에 연결을 시도하지 않아요.
$ docker swarm init --force-new-cluster
  1. Swarm 상태가 예상대로인지 확인하세요. 애플리케이션별 테스트를 수행하거나 docker service ls 출력을 확인해서 모든 예상 서비스가 존재하는지 확인하면 돼요.

  2. auto-lock을 사용한다면 잠금 해제 키를 순환(rotate)하세요.

  3. 매니저와 워커 노드를 추가해서 새 Swarm이 운영 능력을 갖추도록 하세요.

  4. 새 Swarm에서 이전 백업 일정을 다시 적용하세요.

쿼럼 손실 복구

Swarm은 장애에 강해서 일시적인 노드 장애(머신 재부팅이나 크래시 후 재시작)나 기타 일시적인 오류는 어떤 것이든 복구할 수 있어요. 하지만 쿼럼을 잃으면 자동으로 복구되지 않아요. 기존 워커 노드의 작업은 계속 실행되지만, 서비스 확장이나 업데이트, 노드 조인·제거 같은 관리 작업은 수행할 수 없어요. 가장 좋은 복구 방법은 누락된 매니저 노드를 다시 온라인 상태로 만드는 거예요. 그것이 불가능하다면, 계속 읽어서 Swarm을 복구할 수 있는 몇 가지 옵션을 확인해보세요.

N개의 매니저로 구성된 Swarm에서는 항상 매니저 노드의 쿼럼(과반수)이 사용 가능해야 해요. 예를 들어 매니저 5개로 구성된 Swarm에서는 최소 3개가 정상 작동하면서 서로 통신할 수 있어야 해요. 즉 Swarm은 최대 (N-1)/2개의 영구 장애까지 견딜 수 있고, 그 이상이 되면 Swarm 관리와 관련된 요청을 처리할 수 없어요. 이러한 유형의 장애에는 데이터 손상이나 하드웨어 장애가 포함돼요.

매니저 쿼럼을 잃으면 Swarm을 관리할 수 없어요. 쿼럼을 잃은 상태에서 관리 작업을 시도하면 다음과 같은 오류가 발생해요:

Error response from daemon: rpc error: code = 4 desc = context deadline exceeded

쿼럼 손실에서 복구하는 가장 좋은 방법은 실패한 노드를 다시 온라인 상태로 만드는 것이에요. 그것이 불가능하다면, 매니저 노드에서 --force-new-cluster 옵션을 사용하는 것이 유일한 복구 방법이에요. 이 옵션은 명령을 실행한 매니저를 제외한 모든 매니저를 제거해요. 이제 매니저가 하나뿐이므로 쿼럼이 달성돼요. 원하는 매니저 수가 될 때까지 노드를 매니저로 승격하세요.

복구할 노드에서 다음 명령을 실행하세요:

$ docker swarm init --force-new-cluster --advertise-addr node01:2377

--force-new-cluster 플래그와 함께 docker swarm init 명령을 실행하면, 명령을 실행한 Docker Engine이 서비스를 관리하고 실행할 수 있는 단일 노드 Swarm의 매니저 노드가 돼요. 매니저는 서비스와 작업에 대한 이전 정보를 모두 가지고 있고, 워커 노드는 여전히 Swarm의 일부이며 서비스도 계속 실행되고 있어요. 이전 작업 분산을 달성하고 고가용성을 유지하며 쿼럼 손실을 방지하기 위해 매니저 노드를 추가하거나 다시 추가해야 해요.

Swarm 강제 리밸런싱

일반적으로 Swarm이 작업을 강제로 리밸런싱하도록 할 필요는 없어요. 새 노드를 Swarm에 추가하거나 노드가 일정 기간 사용 불가 상태 후 다시 연결되어도, Swarm은 유휴 노드에 자동으로 워크로드를 할당하지 않아요. 이것은 의도적인 설계 결정이에요. Swarm이 균형을 맞추기 위해 주기적으로 작업을 다른 노드로 옮기면, 해당 작업을 사용하는 클라이언트가 중단될 수 있기 때문이에요. 목표는 Swarm 전체의 균형을 위해 실행 중인 서비스를 방해하지 않는 것이에요. 새 작업이 시작되거나 실행 중인 작업이 있는 노드를 사용할 수 없게 되면, 그 작업들은 덜 바쁜 노드에 할당돼요. 최종적으로는 균형을 이루되, 최종 사용자에게는 최소한의 중단만 발생하도록 하는 것이 목표예요.

docker service update 명령에 --force 또는 -f 플래그를 사용하면 서비스가 사용 가능한 워커 노드 전체에 작업을 재분배하도록 강제할 수 있어요. 이렇게 하면 서비스 작업이 재시작되므로 클라이언트 애플리케이션이 중단될 수 있어요. 롤링 업데이트를 구성했다면 서비스가 그 방식을 사용해요.

이전 버전을 사용 중이고 워커 간에 부하를 균등하게 맞추고 싶은데 실행 중인 작업이 중단되어도 괜찮다면, 서비스를 일시적으로 확장해서 Swarm이 리밸런싱하도록 강제할 수 있어요. docker service inspect --pretty <servicename> 명령으로 서비스의 구성된 스케일을 확인하세요. docker service scale을 사용하면 작업 수가 가장 적은 노드가 새 워크로드를 받게 돼요. Swarm에 부하가 적은 노드가 여러 개 있을 수 있으므로, 원하는 균형을 달성할 때까지 서비스를 적당한 증분으로 여러 번 확장해야 할 수도 있어요.

부하가 만족스럽게 균형을 이루면 서비스를 원래 스케일로 다시 축소할 수 있어요. docker service ps 명령으로 노드 간 서비스의 현재 균형을 평가할 수 있어요.

더 알아보기