12.3.도커 스웜 서비스로 애플리케이션 실행하기

서비스와 컨테이너 * 도커 스웜 환경에서는 서비스를 배포하면 스웜이 대신 컨테이너를 실행해 준다. * 서비스는 컨테이너를 추상화한 개념으로 컨테이너와 같은 정보로 정의된다. * 사용되는 이미지 * 환경 변수 * 공개되는 포트 등 * 여기에 서비스의 이름이 도커 네트워크상에서 그대로 도메인으로 사용된다는 점도 컨테이너와 같다. * 차이점이라면, 서비스는 여러 개의 레플리카(서비스와 똑같이 설정되지만 스웜상의 여러 노드에 흩어져 배치될 수 있다)를 가질 수 있다 는 점이다.

실습 도커 허브에 있는 이미지로 컨테이너 하나를 실행하는 서비스를 만들어라. 그리고 서비스 목록을 확인해 새로 실행한 서비스가 제대로 실행 중인지 확인해 보자.

  • 서비스는 도커 스웜의 일급 객체이지만, 서비스를 다루려면 도커 엔진이 스웜 모드이거나 스웜 매니저에 연결된 상태여야 한다.
001)  docker service create --name timecheck --replicas 1 diamol/ch12-timecheck:1.0
002) verify: Service converged
003) 
004)  docker service ls
005) ID             NAME        MODE         REPLICAS   IMAGE                       PORTS
006) uair352b8mg3   timecheck   replicated   1/1        diamol/ch12-timecheck:1.0
  1. 001: 단일 컨테이너로 실행되는 서비스 timecheck를 스웜상에 생성한다.
  2. 004~006: 서비스 목록에는 실행 중인 레플리카 수, 도커 이미지 등 서비스에 대한 기본적인 정보가 함께 출력된다.

레플리카(replica) * 서비스를 구성하는 컨테이너를 레플리카라고 부른다. * 레플리카를 실행 중인 노드에 접속하면, 지금까지 컨테이너를 다룰 때와 마찬가지로 docker container 명령을 사용할 수 있다. * 노드가 하나뿐인 스웜에서는 모든 레플리카가 같은 서버에서 실행되므로 지금 만든 서비스 컨테이너를 바로 다룰 수 있다. * 컨테이너 관리를 스웜이 대신해 주니 컨테이너를 직접 다룰 일이 많지는 않겠지만, 그럴 필요가 있다면 직접 다룰 수 있다.

실습 서비스 레플리카가 현재 실행 중이지만, 스웜이 레플리카의 관리를 맏고 있다. 직접 컨테이너를 삭제해 보면 스웜이 레플리카 수가 부족해졌다고 판단하고 새로운 컨테이너를 실행한다.

001) # 이 서비스의 레플리카 목록을 확인한다.
002)  docker service ps timecheck
003) ID             NAME          IMAGE                       NODE             DESIRED STATE   CURRENT STATE           ERROR     PORTS
004) ympow8yhkugp   timecheck.1   diamol/ch12-timecheck:1.0   docker-desktop   Running         Running 6 minutes ago
005) 
006) # 현재 컴퓨터에서 실행 중인 컨테이너를 확인한다.
007)  docker container ls
008) CONTAINER ID   IMAGE                       COMMAND                   CREATED         STATUS         PORTS   NAMES
009) 88e2fd5d910e   diamol/ch12-timecheck:1.0   "dotnet TimeCheck.dll"    6 minutes ago   Up 6 minutes           timecheck.1.ympow8yhkugpyyf57cmxkc6q4
010) 
011) # 가장 최근에 생성한 컨테이너(레플리카)를 삭제한다.
012)  docker container ls --last 1 -q
013) 88e2fd5d910e
014) 
015) # 가장 최근에 생성한 컨테이너(레플리카)를 삭제한다.
016)  docker container rm -f $(docker container ls --last 1 -q)
017) 88e2fd5d910e
018) 
019) # 레플리카 목록을 다시 확인한다.
020)  docker service ps timecheck
021) ID             NAME              IMAGE                       NODE             DESIRED STATE   CURRENT STATE           ERROR                         PORTS
022) uiko76xirpn4   timecheck.1       diamol/ch12-timecheck:1.0   docker-desktop   Running         Running 5 seconds ago
023) ympow8yhkugp    \_ timecheck.1   diamol/ch12-timecheck:1.0   docker-desktop   Shutdown        Failed 10 seconds ago   "task: non-zero exit (137)"
  1. 002: service ps 명령은 해당 서비스의 레플리카 목록을 출력한다.
  2. 009: 컨테이너 이름은 서비스 이름, 레플리카 번호, 레플리카 식별자를 붙여 짓는다.
  3. 022~023: 레플리카 컨테이너를 직접 삭제하면, 스웜은 서비스의 레플리카가 부족하다고 판단하고 새 레플리카를 실행한다.

실습 스웜 모드에서는 docker service 명령을 사용해 애플리케이션을 관리한다. 이 명령으로 레플리카의 로그 같은 각 레플리카의 정보나 서비스에 대한 전반적인 정보 를 확인할 수 있다.

  • docker service 명령을 사용해 레플리카의 로그를 확인하거나 서비스의 구성을 확인할 수 있다.
001) # 최근 10초간의 로그를 출력
002)  docker service logs --since 10s timecheck
003) timecheck.1.uiko76xirpn4@docker-desktop    | App version: 1.0; time check: 00:38.39
004) timecheck.1.uiko76xirpn4@docker-desktop    | App version: 1.0; time check: 00:38.44
005) 
006) # 서비스의 정보 중 이미지 정보를 출력한다.
007)  docker service inspect timecheck -f '{{.Spec.TaskTemplate.ContainerSpec.Image}}'
008) diamol/ch12-timecheck:1.0@sha256:9d3010a572344c988da8e28444ed345c63662a5c211886e670a8ef3c84689b4e
  1. 002: 서비스에 속한 모든 레플리카의 ~ 컨테이너 로그를 출력한다. 파라미터 since를 사용해 출력 범위를 최근 10초로 제한했다.
  2. 003~004: 로그 엔트리는 레플리카 식별자와 함께 출력되므로 로그를 생성한 컨테이너를 추적할 수 있다.

  3. 서비스 전체의 구성 정보는 클러스터에 저장돼 있으므로, service inspect 명령을 입력하면 확인할 수 있다.

  4. 클러스터 데이터베이스에는 상당히 많은 정보가 들어 있는데, 이들 정보는 안전하게 암호화돼 모든 매니저 노드마다 복제본이 위치한다.
  5. 도커 컴포즈가 도커 스웜과 가장 크게 다른 점은 애플리케이션 정의를 저장할 공간을 갖지 않는다는 것이다.

실습 timecheck 서비스의 이미지 버전을 변경하라. 새 버전은 이전 버전과 마찬가지로 몇 초에 한 번씩 타임스탬프 값을 출력하지만, 로그에 애플리케이션 버전이 삽입된다.

001) # 서비스에 사용된 이미지 버전을 수행한다.
002)  docker service update --image diamol/ch12-timecheck:2.0 timecheck
003) timecheck
004) overall progress: 1 out of 1 tasks
005) 1/1: running   [==================================================>]
006) verify: Service converged
007) 
008) # 서비스의 레플리카 목록을 확인한다.
009)  docker service ps timecheck
010) ID             NAME              IMAGE                       NODE             DESIRED STATE   CURRENT STATE             ERROR                         PORTS
011) o8hb0zg18qjv   timecheck.1       diamol/ch12-timecheck:2.0   docker-desktop   Running         Running 13 seconds ago
012) uiko76xirpn4    \_ timecheck.1   diamol/ch12-timecheck:1.0   docker-desktop   Shutdown        Shutdown 15 seconds ago
013) ympow8yhkugp    \_ timecheck.1   diamol/ch12-timecheck:1.0   docker-desktop   Shutdown        Failed 17 minutes ago     "task: non-zero exit (137)"
014) 
015) # 레플리카 로그도 확인한다.
016)  docker service logs --since 20s timecheck
017) timecheck.1.o8hb0zg18qjv@docker-desktop    | App version: 2.0; time check: 00:47.49
018) timecheck.1.o8hb0zg18qjv@docker-desktop    | App version: 2.0; time check: 00:47.54
019) timecheck.1.o8hb0zg18qjv@docker-desktop    | App version: 2.0; time check: 00:47.59
020) timecheck.1.o8hb0zg18qjv@docker-desktop    | App version: 2.0; time check: 00:48.04
  1. 009~013: 태그가 1.0인 이미지로 실행된 컨테이너는 내려갔고, 새로 실행된 컨테이너는 태그가 2.0인 이미지로 실행된 것이다.
  2. 016~020: 각 로그에는 레플리카의 식별자가 달려 있어 어느 레플리카에서 출력한 것인지 알 수 있다. 로그는 애플리케이션에서 컨테이너에 남긴 것으로, 스웜이 이를 다시 수집하고 레플리카 식별자를 달아 보여 주는 것이다

롤링 업데이트 * 모든 컨테이너 오케스트레이션 도구는 애플리케이션을 업데이트할 때 애플리케이션을 중단시키지 않고 점진적으로 컨테이너를 교체해 나가는 롤링 업데이트 방식을 사용한다. * 스웜에서는 한 번에 한 레플리카씩 교체하는 방식을 사용하는데, 이는 두 개씩 교체해 나가도록 설정할 수도 있고 새로 투입된 컨테이너의 상태가 정상인지 확인한 후 다음 교체를 시작하도록 할 수도 있다. * 롤링 업데이트 중에는 두 버전이 모두 실행되고 있으므로 사용자도 두 버전 중 한 가지를 마주하게 된다. 이러한 이유로 롤링 업데이트 중의 사용자 경험은 직접 관리해야 한다. * 자동화된 롤링 업데이트는 수동 배포에 비하면 천지 차이라 할 만큼 크게 발전한 방식으로, 자기 수복(self-healing)형 애플리케이션의 또 다른 기능적 축을 담당한다. * 업데이트 과정에서 신규 투입된 컨테이너의 상태를 확인하게 되는데, 새로 투입된 신 버전 컨테이너에서 문제가 발생하면 업데이트가 자동으로 중단돼 전체 애플리케이션으로 문제가 번지지 않도록 막는다. * 스웜의 데이터베이스는 이전 버전의 서비스 정의 내용이 남아 있으므로 명령 한 번으로 이전 버전으로 롤백할 수 있다.

실습 배포 작업 중 이상이 발생하면 이전 상태로 롤백하는 경우가 많다. 도커 스웜도 애플리케이션의 이전 상태를 저장하고 있기 때문에 애플리케이션 롤백 기능을 제공한다.

001) # 이전 버전으로 롤백
002)  docker service update --rollback timecheck
003) timecheck
004) rollback: manually requested rollback 
005) overall progress: rolling back update: 1 out of 1 tasks 
006) 1/1: running   [==================================================>] 
007) verify: Service converged 
008) 
009) # 레플리카의 목록 확인
010)  docker service ps timecheck
011) ID             NAME              IMAGE                       NODE             DESIRED STATE   CURRENT STATE             ERROR                         PORTS
012) 7haak0lncd4u   timecheck.1       diamol/ch12-timecheck:1.0   docker-desktop   Running         Running 22 seconds ago                                  
013) zcrpc052jsa2    \_ timecheck.1   diamol/ch12-timecheck:2.0   docker-desktop   Shutdown        Shutdown 25 seconds ago                                 
014) o8hb0zg18qjv    \_ timecheck.1   diamol/ch12-timecheck:2.0   docker-desktop   Shutdown        Failed 8 hours ago        "task: non-zero exit (255)"   
015) ympow8yhkugp    \_ timecheck.1   diamol/ch12-timecheck:1.0   docker-desktop   Shutdown        Failed 11 hours ago       "task: non-zero exit (137)"   
016) 
017) # 최근 25초 동안 모든 레플리카의 로그 출력
018)  docker service logs --since 25s timecheck
019) timecheck.1.7haak0lncd4u@docker-desktop    | App version: 1.0; time check: 11:44.58
020) timecheck.1.7haak0lncd4u@docker-desktop    | App version: 1.0; time check: 11:45.03
021) timecheck.1.7haak0lncd4u@docker-desktop    | App version: 1.0; time check: 11:45.08
022) timecheck.1.7haak0lncd4u@docker-desktop    | App version: 1.0; time check: 11:45.13
023) timecheck.1.7haak0lncd4u@docker-desktop    | App version: 1.0; time check: 11:45.18
  1. 002: 롤백은 특수한 업데이트의 일종이다. 스웜의 데이터베이스에 남아 있는 이전 버전의 정의대로 애플리케이션을 되돌린다.
  2. 012: 2.0에서 1.0으로 롤백되었다.

  3. 롤백 과정도 업데이트와 같이 롤링을 거친다. 하지만 저장 중인 이전 상태로 돌아가는 것이므로 이미지 태그를 새로이 지정할 필요는 없다.

  4. 업데이트 중 헬스 체크에서 확인할 수 없는 사항 등의 이유로 애플리케이션에 도커에서 파악할 수 없는 이상이 발생했다면 롤백으로 즉시 정상 상태로 회복할 수 있다.

links

social