Docker Swarm 2026.09.04 6 min read

정적 IP 전환부터 Docker Swarm 5노드까지

Netplan의 실제 renderer와 NIC 이름을 확인한 뒤 IP를 한 대씩 바꿨다. Swarm 5노드 배치와 업데이트 정책을 구성하며 생긴 제약을 정리했다.

Swarm 노드 주소와 DB 경로, NFS export, 모니터링 대상이 IP에 의존하고 있어 네트워크부터 고정했다. 시작부터 예상과 다른 부분이 있었다. Ubuntu라는 이유로 NetworkManager를 쓰는 환경이라고 생각했는데 실제 설정은 달랐다.

nmtui에 NIC가 보이지 않았던 이유

NetworkManager와 nmtui를 설치해도 NIC가 나타나지 않았다. 확인해 보니 Netplan renderer가 systemd-networkd였다. 현재 네트워크를 관리하는 서비스를 확인하지 않고 도구부터 설치한 것이 원인이었다.

기존 systemd-networkd를 유지하고 Netplan 설정을 수정했다. 먼저 서버별 인터페이스 이름과 게이트웨이, DNS, 라우팅 정보를 모았다.

NIC 이름은 장비마다 ens33, ens36, eno4처럼 달랐다. 원격에서 설정을 적용하다 접속을 잃을 수 있어 예제의 이름을 복사하지 않고 실제 이름으로 작성했다.

IP 변경은 한 대씩 진행했다

Swarm 주소를 동시에 바꾸면 Manager 정족수와 오버레이 통신을 함께 잃을 수 있었다. 한 대씩 변경하고 아래 명령으로 주소, 경로와 노드 상태를 확인했다.

ip -br -4 addr
ip route
docker node ls
docker info

Manager 3대 중 과반수의 통신을 유지하는 순서로 진행했다. Worker도 클러스터 재참여와 오버레이 통신을 확인한 뒤 다음 노드를 변경했다.

Manager 3대와 Worker 2대를 선택했다

Manager는 Raft 정족수를 고려해 3대로 구성했다. 2대 구성에서는 한 대만 내려가도 과반수가 사라진다. 3대면 한 대가 중단돼도 나머지 2대로 제어 영역을 유지할 수 있다.

애플리케이션은 Worker 2대에 배치했다. 최종 점검에서 노드 5대가 모두 Ready/Active였고 Manager는 Leader 1대와 Reachable 2대였다.

App 복제본 2개에 max_replicas_per_node: 1을 적용했다. 두 태스크가 Worker 1과 Worker 2에 하나씩 배치됐다.

App replica 1 → Worker 1
App replica 2 → Worker 2
Endpoint mode → VIP

한 줄의 placement가 해결한 것과 해결하지 못한 것

처음에는 두 복제본이 같은 Worker에 올라갈 수 있었다. spread: node.hostname은 분산을 선호하는 설정이었다. 노드당 최대 복제본 수를 1로 제한해 배치를 강제했다.

이 제한은 업데이트에도 영향을 줬다. Worker 두 대에 기존 태스크가 하나씩 있으니 start-first로 새 태스크를 먼저 띄울 자리가 없었다. 이 경우 새 태스크가 Pending에 머물 수 있었다.

이 환경에서는 stop-first와 parallelism: 1을 선택했다. 기존 태스크 하나를 내리고 새 태스크를 시작한 뒤 다음 태스크를 갱신하는 방식이다. 교체 중에는 복제본이 하나로 줄지만 현재 Worker 수에 맞춰 업데이트를 진행할 수 있었다.

Worker 한 대가 중단되면 남은 복제본이 요청을 받는다. 다만 max_replicas_per_node: 1 때문에 남은 Worker에 두 번째 복제본을 띄울 수는 없다. 장애 후에도 2/2 용량을 유지하려면 Worker를 한 대 더 추가해야 한다.

Service DNS와 VIP를 연결점으로 사용했다

개별 컨테이너 IP는 태스크가 재배치되면 달라질 수 있다. 외부 커넥터와 NPM이 고정된 연결 대상을 사용하도록 meetback-edge, meetback-backend 오버레이를 만들고 서비스 이름과 VIP로 연결했다.

cloudflared, NPM, App은 각자 필요한 오버레이에 참여시켰다. DB는 전용망에 두고 Worker가 VyOS를 거쳐 MySQL에 접근하도록 했다.

Swarm에서 실제로 막혔던 지점

구축 중 다음 문제를 만났다.

  • Worker에서 docker service 명령을 실행해 Manager 권한 오류가 발생했다.
  • Worker가 사설 레지스트리 이미지를 받지 못해 태스크가 Rejected 상태가 됐다.
  • NFS 마운트 권한 문제로 태스크가 시작 전에 실패했다.
  • start-first와 노드당 복제본 1개 제한이 충돌했다.
  • Compose 들여쓰기가 잘못돼 의도한 deploy 설정이 적용되지 않았다.

docker service ls의 현재 상태와 함께 docker service ps --no-trunc로 이전 태스크도 확인했다. Rejected, Shutdown 상태와 오류 이유가 남아 있었다. Swarm이 새 태스크를 계속 만들기 때문에 최신 Running 행만 보면 앞서 실패한 원인을 놓칠 수 있었다.

최종 검증

최종 캡처 시점에는 다음 상태를 확인했다.

  • 노드 5/5 Ready
  • Manager 정족수 정상
  • App 2/2 Running
  • App 태스크가 Worker 두 대에 하나씩 배치
  • cloudflared global 서비스 5/5
  • 오버레이 네트워크와 서비스 VIP 존재
  • 업데이트 순서 stop-first

Swarm이 태스크를 다시 만들어도 이미지 인증이나 저장소 권한이 맞지 않으면 계속 실패했다. 배치 제한과 업데이트할 자리까지 준비돼 있어야 원하는 복제본 수를 유지할 수 있었다. 이번 구축에서는 이 조건들을 하나씩 맞췄다.

main 변경을 일회용 MySQL로 검증한 뒤 이미지를 빌드·업로드하고 스택에 적용한 과정은 별도 배포 글에 정리했다.

실제 검증 화면

  1. 최종 점검 때 실행한 docker node ls 결과다. Manager 정족수와 Worker 상태를 확인했다.
    Docker Swarm의 관리자 3대와 Worker 2대가 모두 Ready·Active이고 Leader가 한 대인 노드 목록

  2. App 복제본이 두 Worker에 하나씩 올라간 상태와 서비스별 복제본 수를 함께 확인했다.
    앱 복제본 2개가 Worker에 분산되고 cloudflared가 5개 노드에서 실행 중인 서비스 배치 결과

  3. meetback-backend와 meetback-edge 오버레이, App이 각 네트워크에서 받은 VIP를 확인했다.
    Swarm의 ingress·backend·edge overlay 네트워크와 앱 서비스의 두 VIP 조회 결과

SEARCH JOURNAL

기록 검색

글 제목, 요약, 태그에서 찾습니다.

검색을 준비하고 있어요.

검색어를 입력해 주세요.

    Ctrl/⌘ K 검색 Esc 닫기 ↑ ↓ 결과 이동