docker service create 명령어를 사용하여 서비스 배포 및 관리하는 방법

DockerBeginner
지금 연습하기

소개

이 랩에서는 docker service create 명령을 사용하여 Docker Swarm 내에서 서비스를 배포하고 관리하는 실습을 진행합니다. 고가용성 및 확장성을 위해 간단한 복제 서비스와 모든 노드에서 실행되는 글로벌 서비스를 포함하여 다양한 유형의 서비스를 생성하고 검사하는 방법을 배우게 됩니다.

또한, 원활한 배포를 위한 롤링 업데이트 정책 구현, 데이터 지속성 및 구성을 위한 바인드 마운트 (bind mount) 및 환경 변수 활용, 그리고 스웜 내에서 서비스 태스크가 실행되는 위치를 제어하기 위한 배치 제약 조건 및 선호도 적용과 같은 고급 서비스 구성을 탐구할 것입니다. 이러한 단계를 완료함으로써 Docker Swarm 환경에서 컨테이너화된 애플리케이션을 효과적으로 관리하는 방법에 대한 확실한 이해를 얻게 될 것입니다.

간단한 복제 서비스 생성

이 단계에서는 Docker Swarm 에서 간단한 복제 서비스를 생성하는 방법을 배우게 됩니다. 복제 서비스는 스웜 전체에서 여러 개의 동일한 태스크를 실행하는 서비스입니다. 이는 고가용성 및 확장성을 제공합니다.

먼저, Docker 가 실행 중인지 확인하고 올바른 디렉토리에 있는지 확인합니다.

docker version
pwd

Docker 버전과 현재 디렉토리가 /home/labex/project로 표시되는 출력을 확인해야 합니다.

서비스를 생성하기 전에 필요한 Docker 이미지를 가져와야 합니다. 이 예제에서는 nginx 이미지를 사용합니다.

docker pull nginx:latest

이 명령은 Docker Hub 에서 nginx 이미지의 최신 버전을 다운로드합니다.

이제 my-nginx-service라는 이름의 간단한 복제 서비스를 3 개의 복제본으로 생성해 보겠습니다.

docker service create --name my-nginx-service --replicas 3 nginx:latest

이 명령은 nginx:latest 이미지를 사용하여 my-nginx-service라는 새 서비스를 생성하고 원하는 복제본 수를 3 으로 설정합니다. 그런 다음 Docker Swarm 은 이러한 3 개의 태스크를 스웜의 사용 가능한 노드에 분산시킵니다.

서비스 및 해당 태스크의 상태를 확인하려면 docker service lsdocker service ps 명령을 사용할 수 있습니다.

docker service ls
docker service ps my-nginx-service

docker service ls 명령은 스웜에서 실행 중인 모든 서비스를 나열하여 ID, 이름, 모드, 복제본 및 이미지를 표시합니다. docker service ps my-nginx-service 명령은 my-nginx-service와 관련된 태스크를 표시하며, 상태 (예: Running, Shutdown), 원하는 상태 및 실행 중인 노드를 포함합니다. "Running" 상태의 3 개의 태스크를 확인해야 합니다.

글로벌 서비스 생성 및 작업 검사

이 단계에서는 Docker Swarm 에서 글로벌 서비스를 생성하는 방법을 배우게 됩니다. 지정된 수의 태스크를 실행하는 복제 서비스와 달리, 글로벌 서비스는 서비스의 제약 조건을 충족하는 스웜의 모든 노드에서 정확히 하나의 태스크를 실행합니다. 이는 모든 노드에서 실행해야 하는 모니터링 에이전트 또는 로그 수집기와 같은 서비스에 유용합니다.

이 예제에서는 busybox 이미지를 사용합니다. 먼저 이미지를 가져오겠습니다.

docker pull busybox:latest

이 명령은 busybox 이미지의 최신 버전을 다운로드합니다.

이제 my-global-service라는 이름의 글로벌 서비스를 생성해 보겠습니다.

docker service create --name my-global-service --mode global busybox:latest sleep infinity

이 명령은 busybox:latest 이미지를 사용하여 my-global-service라는 새 서비스를 생성합니다. --mode global 플래그는 이것이 글로벌 서비스임을 지정합니다. sleep infinity 명령은 컨테이너를 무기한으로 실행 상태로 유지하는 데 사용됩니다.

글로벌 서비스의 태스크를 검사하려면 docker service ps 명령을 사용할 수 있습니다.

docker service ps my-global-service

이 명령은 my-global-service와 관련된 태스크를 표시합니다. 이것은 글로벌 서비스이므로 스웜의 각 노드에 대해 하나의 태스크가 실행 중인 것을 볼 수 있습니다. 이 Lab 환경에서는 노드가 하나뿐이므로 하나의 태스크만 표시될 가능성이 높습니다. 출력은 태스크의 상태, 원하는 상태 및 실행 중인 노드를 보여줍니다.

docker service inspect 명령을 사용하여 서비스 구성을 검사할 수도 있습니다.

docker service inspect my-global-service

이 명령은 서비스 모드, 복제본 (서비스 목록에서는 글로벌 서비스의 경우 0 이지만, docker service ps는 노드당 태스크를 표시함) 및 기타 구성 세부 정보를 포함하여 서비스에 대한 자세한 정보를 제공합니다.

복제본 및 롤링 업데이트 정책을 사용한 서비스 생성

이 단계에서는 복제 서비스를 생성하고 롤링 업데이트 정책을 구성하는 방법을 배우게 됩니다. 롤링 업데이트를 사용하면 새 버전으로 태스크를 점진적으로 교체하여 서비스 중단 없이 새 버전으로 서비스를 업데이트할 수 있습니다.

nginx 이미지를 계속 사용합니다. 5 개의 복제본과 롤링 업데이트 정책을 사용하여 my-nginx-update-service라는 복제 서비스를 생성해 보겠습니다.

docker service create \
  --name my-nginx-update-service \
  --replicas 5 \
  --update-delay 10s \
  --update-parallelism 2 \
  nginx:latest

이 명령은 다음과 같은 구성으로 서비스를 생성합니다.

  • --name my-nginx-update-service: 서비스 이름을 설정합니다.
  • --replicas 5: 원하는 복제본 수를 5 로 설정합니다.
  • --update-delay 10s: 각 태스크 그룹을 업데이트하는 사이의 지연 시간을 10 초로 설정합니다.
  • --update-parallelism 2: 동시에 업데이트할 태스크 수를 2 로 설정합니다.

이러한 업데이트 매개변수는 새 버전의 이미지를 배포할 때 서비스가 업데이트되는 방식을 정의합니다. Docker Swarm 은 한 번에 2 개의 태스크를 업데이트하고 다음 배치를 업데이트하기 전에 10 초를 기다립니다.

docker service lsdocker service ps 명령을 사용하여 서비스 상태 및 해당 태스크를 확인할 수 있습니다.

docker service ls
docker service ps my-nginx-update-service

5/5 복제본과 "Running" 상태의 태스크가 있는 my-nginx-update-service가 나열된 것을 볼 수 있습니다.

이제 이미지를 다른 버전으로 변경하여 업데이트를 시뮬레이션해 보겠습니다. nginx:1.21 이미지를 사용합니다. 먼저 이미지를 가져옵니다.

docker pull nginx:1.21

이제 nginx:1.21 이미지를 사용하도록 서비스를 업데이트합니다.

docker service update --image nginx:1.21 my-nginx-update-service

이 명령은 롤링 업데이트를 시작합니다. Docker Swarm 은 이전에 구성한 --update-parallelism--update-delay 설정에 따라 nginx:latest 태스크를 nginx:1.21 태스크로 교체하기 시작합니다.

docker service ps my-nginx-update-service를 반복적으로 실행하여 롤링 업데이트 프로세스를 관찰할 수 있습니다.

docker service ps my-nginx-update-service

이전 이미지를 사용하여 "Running"에서 "Shutdown"으로 전환된 태스크와 새 이미지를 사용하여 시작하여 "Running" 상태로 들어가는 새 태스크를 볼 수 있습니다. 업데이트는 배치당 10 초의 지연 시간으로 2 개의 태스크 배치로 수행됩니다.

바인드 마운트 및 환경 변수를 사용한 서비스 생성

이 단계에서는 데이터를 유지하기 위해 바인드 마운트를 사용하고 컨테이너 내부의 애플리케이션을 구성하기 위해 환경 변수를 사용하는 서비스를 생성하는 방법을 배우게 됩니다. 바인드 마운트를 사용하면 호스트 머신의 파일 또는 디렉토리를 컨테이너에 마운트하여 컨테이너에서 데이터에 액세스할 수 있도록 하고 컨테이너가 제거되더라도 데이터를 유지할 수 있습니다. 환경 변수는 애플리케이션에 구성 정보를 전달하는 일반적인 방법입니다.

먼저 컨테이너에 바인드 마운트할 호스트 머신에 디렉토리를 생성해 보겠습니다.

mkdir -p ~/project/html

이 명령은 ~/project 디렉토리 내에 html이라는 디렉토리를 생성합니다.

이제 이 디렉토리 내에 간단한 HTML 파일을 생성해 보겠습니다.

echo "<h1>Hello from Bind Mount!</h1>" > ~/project/html/index.html

이 명령은 ~/project/html 디렉토리에 "

Hello from Bind Mount!

" 내용이 있는 index.html이라는 파일을 생성합니다.

다시 nginx 이미지를 사용합니다. 1 개의 복제본으로 my-nginx-volume-service라는 복제 서비스를 생성하고, ~/project/html 디렉토리를 컨테이너 내부의 기본 Nginx 웹루트 디렉토리 (/usr/share/nginx/html) 에 바인딩하고, 환경 변수를 설정합니다.

docker service create \
  --name my-nginx-volume-service \
  --replicas 1 \
  --publish published=8080,target=80 \
  --mount type=bind,source=/home/labex/project/html,target=/usr/share/nginx/html \
  --env MY_VARIABLE=hello \
  nginx:latest

새 옵션을 자세히 살펴보겠습니다.

  • --publish published=8080,target=80: 호스트의 포트 8080 을 컨테이너 내부의 포트 80 에 매핑하여 호스트 머신에서 Nginx 웹 서버에 액세스할 수 있도록 합니다.
  • --mount type=bind,source=/home/labex/project/html,target=/usr/share/nginx/html: 바인드 마운트를 생성합니다. type=bind는 마운트 유형을 지정합니다. source=/home/labex/project/html은 호스트 머신의 경로입니다. target=/usr/share/nginx/html은 호스트 디렉토리가 마운트될 컨테이너 내부의 경로입니다.
  • --env MY_VARIABLE=hello: 컨테이너 내부에 값 hello가 있는 MY_VARIABLE이라는 환경 변수를 설정합니다.

서비스 상태 및 태스크를 확인합니다.

docker service ls
docker service ps my-nginx-volume-service

태스크가 "Running" 상태가 될 때까지 기다립니다.

이제 웹 브라우저에서 http://localhost:8080을 방문하거나 curl을 사용하여 컨테이너에서 실행 중인 Nginx 웹 서버에 액세스할 수 있습니다.

curl http://localhost:8080

생성한 index.html 파일의 내용인 <h1>Hello from Bind Mount!</h1>를 볼 수 있습니다. 이는 바인드 마운트가 올바르게 작동하고 있음을 확인합니다.

환경 변수를 확인하려면 실행 중인 컨테이너 내에서 명령을 실행할 수 있습니다. 먼저 실행 중인 서비스의 태스크 ID 를 찾습니다.

docker service ps my-nginx-volume-service

출력에서 태스크 ID 를 기록해 둡니다. 그런 다음 docker exec를 사용하여 컨테이너 내에서 명령을 실행합니다. <task_id>를 실제 태스크 ID 로 바꿉니다.

docker exec < task_id > env | grep MY_VARIABLE

이 명령은 태스크 ID 와 관련된 컨테이너 내에서 env 명령을 실행하고 출력을 grep MY_VARIABLE로 파이프하여 환경 변수를 찾습니다. 출력에서 MY_VARIABLE=hello를 볼 수 있습니다.

배치 제약 조건 및 선호도를 사용한 서비스 생성

이 단계에서는 Docker Swarm 내에서 서비스 태스크가 배포되는 위치를 제어하기 위해 배치 제약 조건 및 선호도를 사용하는 방법을 배우게 됩니다. 배치 제약 조건은 태스크가 해당 노드에서 예약되기 위해 노드가 충족해야 하는 엄격한 요구 사항입니다. 배치 선호도는 스케줄링에 영향을 미치지만 선호도를 충족하는 노드가 없는 경우 태스크가 예약되는 것을 방지하지 않는 유연한 요구 사항입니다.

먼저 현재 노드를 검사하여 레이블을 확인해 보겠습니다. 레이블은 메타데이터를 제공하기 위해 노드에 연결할 수 있는 키 - 값 쌍입니다.

docker node inspect self --format '{{ .Spec.Labels }}'

이 명령은 현재 노드 (self로 식별됨) 를 검사하고 레이블을 표시하도록 출력을 형식화합니다. 기본적으로 사용자 지정 레이블이 없을 수 있습니다.

현재 노드에 레이블을 추가해 보겠습니다. node_type=app 레이블을 추가합니다.

docker node update --label-add node_type=app self

이 명령은 현재 노드를 업데이트하고 node_type=app 레이블을 추가합니다.

이제 레이블이 추가되었는지 확인해 보겠습니다.

docker node inspect self --format '{{ .Spec.Labels }}'

출력에 map[node_type:app]이 표시되어 레이블이 성공적으로 추가되었음을 나타냅니다.

이제 node_type=app 레이블이 있는 노드가 필요하도록 배치 제약 조건이 있는 my-constrained-service라는 복제 서비스를 생성해 보겠습니다. nginx 이미지를 사용합니다.

docker service create \
  --name my-constrained-service \
  --replicas 1 \
  --constraint 'node.labels.node_type == app' \
  nginx:latest

이 명령은 제약 조건이 있는 서비스를 생성합니다. --constraint 'node.labels.node_type == app'은 이 서비스의 태스크가 node_type 레이블이 app과 같은 노드에서만 예약될 수 있음을 지정합니다. 현재 노드에 이 레이블을 추가했으므로 태스크가 여기에 예약되어야 합니다.

서비스 상태 및 태스크를 확인합니다.

docker service ls
docker service ps my-constrained-service

my-constrained-service가 나열되고 해당 태스크가 현재 노드에서 실행 중인 것을 볼 수 있습니다.

이제 배치 선호도가 있는 다른 서비스를 생성해 보겠습니다. 배치 선호도는 스케줄러를 안내하는 데 사용되지만 엄격하게 적용되지는 않습니다. busybox 이미지를 사용하고 node_type=database 레이블이 있는 노드를 선호합니다. 현재 노드에는 이 레이블이 없으므로 태스크는 여전히 현재 노드에 예약되지만, 해당 레이블이 있는 다른 노드가 있는 경우 스케줄러는 해당 노드를 선호합니다.

먼저 busybox 이미지를 가져옵니다.

docker pull busybox:latest

이제 배치 선호도가 있는 서비스를 생성합니다.

docker service create \
  --name my-preferred-service \
  --replicas 1 \
  --placement-pref 'spread=node.labels.node_type' \
  busybox:latest sleep infinity

--placement-pref 'spread=node.labels.node_type' 옵션은 스케줄러에게 node_type 레이블의 값을 기반으로 노드 간에 태스크를 분산하도록 지시합니다. 서로 다른 node_type 레이블이 있는 다중 노드 swarm 에서 이 작업은 태스크를 보다 균등하게 분산합니다. 이 단일 노드 환경에서는 태스크가 사용 가능한 노드에 간단히 예약됩니다.

서비스 상태 및 태스크를 확인합니다.

docker service ls
docker service ps my-preferred-service

my-preferred-service가 나열되고 해당 태스크가 현재 노드에서 실행 중인 것을 볼 수 있습니다.

요약

이 랩에서는 docker service create 명령을 사용하여 Docker Swarm 에서 서비스를 배포하고 관리하는 방법을 배웠습니다. 먼저 nginx 이미지를 사용하여 간단한 복제 서비스를 생성하여 고가용성 및 확장성을 위해 원하는 복제본 수를 지정했습니다. 그런 다음 docker service lsdocker service ps를 사용하여 서비스의 상태를 확인하고 실행 중인 태스크를 검사했습니다.

이어서, 스웜의 모든 적합한 노드에서 하나의 태스크를 실행하는 글로벌 서비스의 동작을 이해하면서 글로벌 서비스의 생성을 탐구했습니다. 이는 다양한 요구 사항에 따라 서비스를 배포하는 Docker Swarm 의 유연성을 보여주었습니다.