13 분산 앱 배포

seohan·2022년 3월 19일
0

실제 시스템에서는 관리자에 연결하여 서비스를 실행하는 명령 대신 관리자에게 보낼 yaml 파일에 앱을 설명합니다. 그런 다음 앱을 실행하기 위해 취해야 할 조치를 결정합니다. yaml 파일은 원하는 최종 상태를 지정하고 오케스트레이터는 현재 실행 중인 항목을 보고 해당 상태에 도달하기 위해 수행해야 하는 작업을 파악합니다.

Swarm은 Docker Compose 구문을 사용하여 앱의 모든 구성 요소를 정의하고, yaml을 관리자에게 보낼 때 네트워크와 서비스 및 사용자가 선언하는 모든 것을 생성합니다. Compose 형식은 클러스터 배포를 위한 분산 앱을 설명하는 데 적합하지만 Swarm 모드에서만 의미가 있는 개념과 단일 서버에서만 의미가 있는 개념이 있습니다.

이 장에서는 클러스터에서 분산 앱을 실행하기 위해 Docker Compose 및 Docker Swarm에 대한 지식을 구축합니다.

13.1 프로덕션 배포

Docker Swarm의 진정한 힘은 Compose에서 나옵니다. 프로덕션 배포는 개발 및 테스트 환경에서 사용하는 것과 동일한 파일 형식을 사용하므로 모든 환경과 모든 프로젝트에 대한 아티팩트와 도구 간에 일관성이 있습니다. Swarm을 위한 가장 간단한 배포는 간단한 Compose 파일과 동일합니다. 목록 13.1은 이미지 이름과 게시할 포트만 지정하는 6장의 todo-list 앱에 대한 기본 배포를 보여줍니다.

목록 13.1 Swarm에 배포할 수 있는 Compose 파일

version: "3.7"
services:
   todo-web:
       image: diamol/ch06-todo-list
       ports:
             - 8080:80

Compose를 사용하여 단일 서버에 배포하고 게시된 포트로 실행되는 하나의 컨테이너를 얻을 수 있습니다. Swarm에 정확히 동일한 파일을 배포할 수 있으며 게시된 포트에 대한 수신 네트워크를 사용하여 단일 복제본이 실행되는 서비스를 얻을 수 있습니다.

서비스, 네트워크 및 볼륨과 같은 많은 다른 리소스를 함께 그룹화하는 리소스인 stack을 생성하여 앱을 배포합니다.

TRY Compose 파일을 스택으로 배포합니다. Swarm을 초기화한 다음 ch13/exercises 폴더로 이동합니다.

스택을 배포합니다.

$ docker stack deploy -c ./todo-list/v1.yml todo

새 스택을 확인합니다.

$ docker stack ls

NAME      SERVICES   ORCHESTRATOR
todo      1          Swarm

배포로 만들어진 서비스를 확인:

$ docker service ls

70t188mmp480   todo_todo-web   replicated   1/1 diamol/ch06-todo-list:latest          *:8080->80/tcp

Compose 파일을 클러스터로 보냈고 관리자는 서비스를 연결할 기본 네트워크를 만든 다음 앱에 대한 서비스를 만들었습니다. 스택은 Swarm 모드의 일급 리소스입니다. CLI를 사용하여 생성, 나열 및 제거할 수 있습니다.

컨테이너를 실행 중인 경우 http://localhost:8080으로 이동하여 앱을 볼 수 있습니다. 여기서 얻은 것은 Swarm에 배포할 추가 구성 없이 Docker Compose 파일을 사용했다는 것입니다. Swarm에 여러 노드가 있는 경우 고가용성을 갖게 됩니다. 서비스 복제본을 실행하는 노드가 오프라인이 될 수 있고 Swarm은 앱을 계속 사용할 수 있도록 다른 노드에서 교체를 시작합니다.

Swarm 모드에는 Compose 파일의 서비스에 deploy 섹션을 추가하여 앱에서 사용할 수 있습니다. 이러한 속성은 클러스터에서 실행할 때만 의미가 있으므로 스택을 배포할 때 적용되지만 단일 서버에서 Docker Compose와 동일한 파일을 사용할 수 있으며 deploy 설정은 무시됩니다.

목록 13.2는 여러 복제본을 실행하고 리소스를 제한하는 deploy 속성이 포함된 todo-list 앱에 대한 업데이트된 서비스 정의입니다.

Listing 13.2 Compose 파일에 Swarm 설정

 services:
   todo-web:
       image: diamol/ch06-todo-list
       ports:
           - 8080:80
       deploy:
           replicas: 2
           resources:
               limits:
                   cpus: "0.50"
                     memory: 100M

프로덕션 배포에 포함할 기본 속성입니다. 여러 복제본을 실행하면 앱에서 더 많은 로드를 관리할 수 있으며, 서버 오류 또는 서비스 업데이트로 인해 다른 복제본이 오프라인이 되는 경우 하나의 복제본을 트래픽에 사용할 수 있음을 의미합니다. 또한 모든 처리 능력과 메모리를 소모하는 불량 복제본으로부터 클러스터를 보호하기 위해 모든 서비스가 가동될 때 컴퓨팅 제한을 지정해야 합니다.

한도를 계산하려면 앱이 가장 많이 작동할 때 필요한 CPU와 메모리의 양을 알아야 합니다. 리소스 제한은 각 복제본을 CPU 코어 1개의 최대 50% 및 메모리 100MB로 제한합니다.

Swarm 스택에 업데이트 배포는 새 앱의 배포와 동일합니다. 업데이트된 yaml 파일을 관리자에게 보내면 자동으로 변경됩니다. v2 Compose 파일을 배포하면 Swarm이 하나의 새 복제본을 만들고 기존 복제본을 교체합니다.

TRY 새 Compose 파일을 사용하여 docker stack deploy 명령을 실행하지만 원래 스택 이름은 기존 스택의 업데이트처럼 동작합니다.

$ docker stack deploy -c ./todo-list/v2.yml todo

Updating service todo_todo-web (id: 70t188mmp4804ehnvxnvrtacm)

서비스 작업을 나열하면 업데이트가 어떻게 발생했는지 확인할 수 있습니다.

$ docker service ps todo_todo-web


todo_todo-web.1       diamol/ch06-todo-list:latest   docker-desktop   Running           
\_ todo_todo-web.1   diamol/ch06-todo-list:latest   docker-desktop   Shutdown             
todo_todo-web.2       diamol/ch06-todo-list:latest   docker-desktop   Running

스택이 서비스를 업데이트하고 서비스에 두 개의 새 복제본이 있음을 알 수 있습니다. Compose 파일에 리소스 제한을 추가하면 컨테이너 정의가 변경되고 새 컨테이너로 조치를 취해야 하기 때문에 원본 복제본이 교체되었습니다.

Docker 컨테이너는 제한을 지정하지 않으면 모든 호스트의 CPU와 메모리에 액세스할 수 있습니다. 이것이 기본값이며 가능한 한 많은 앱을 서버에 넣고 필요한 리소스를 사용하도록 하려는 비 프로덕션 환경에 적합합니다. 그러나 프로덕션에서는 나쁜 코드나 시스템을 최대한 활용하려는 악의적인 사용자로부터 보호하기 위한 제한을 원하지만 이러한 제한은 컨테이너가 시작될 때 설정되므로 업데이트하면 새 컨테이너를 얻게 됩니다.

Swarm 스택은 클러스터가 일반적으로 많은 앱을 실행하기 때문에 필요한 앱을 그룹화하는 깔끔한 방법입니다. 개별 서비스 및 서비스 복제본을 나열하거나 앱을 모두 제거하여 Docker CLI의 스택 명령을 사용하여 애플리케이션을 전체적으로 관리할 수 있습니다.

TRY 스택은 앱을 위한 관리 단위입니다. 각각 여러 복제본이 있는 여러 서비스를 실행할 수 있는 앱으로 작업하는 간단한 방법을 제공합니다. todo-list 앱 스택에서 실행 중인 항목을 확인한 다음 제거합니다.

스택에 있는 모든 서비스를 확인합니다

$ docker stack services todo

스택에 있는 모든 서비스에 대한 복제 목록:

$ docker stack ps todo

스택을 제거합니다.

$ docker stack rm todo

이 앱은 도커 네트워크 하나, 서비스 하나, 두 개의 복제가 있습니다. 대규모 분산 앱은 Swarm에서 수백개의 복제에서 수십개의 서비스를 실행하더라도 동일한 방식으로 관리할 수 있습니다.

모든 사양이 클러스터 DB 내부에 저장되기 때문에 Compose 파일 없이도 스택의 모든 리소스를 관리할 수 있습니다. 공유 DB는 Swarm 관리자 간에 복제되므로 다른 리소스도 안전하게 저장할 수 있습니다. Swarm에 앱 구성 파일을 저장하는 방법이며 Compose 파일의 서비스에서 사용할 수 있습니다.

13.2 앱 구성 관리

컨테이너에서 실행되는 앱은 컨테이너를 실행하는 플랫폼에서 구성 설정을 로드할 수 있어야 합니다. 환경 변수와 함께 Compose를 사용하는 로컬 개발/테스트 환경에서 이를 다루었습니다. 이제 클러스터에 저장된 도커 config 객체를 사용하는 프로덕션으로 마무리할 수 있습니다. 그림 13.4는 이것이 어떻게 작동하는지 보여주며 여기서 중요한 것은 모든 환경에서 정확히 동일한 Docker 이미지이고 변경되는 것은 앱의 동작일 뿐입니다.

그림 13.4 플랫폼에서 구성 적용. Swarm 모드는 config 객체와 secrets을 사용합니다.

구성은 배포의 매우 중요한 부분이므로 모든 오케스트레이터는 앱 구성을 보관할 1급 리소스를 보유합니다. Swarm에서 이들은 Docker config 객체입니다. 컨테이너가 클러스터에서 config를 로드할 수 있기 때문에 강력하지만 구성 관리에서 앱 배포의 역할을 분리 합니다.

조직에는 API 키, 데이터베이스 서버 암호, SSL 인증서와 같은 모든 비밀에 액세스할 수 있는 구성 관리 팀이 있는 경우가 많으며 이러한 비밀은 모두 보안 시스템에 저장됩니다. 해당 시스템은 종종 앱이 실행되는 환경과 완전히 분리되어 있으므로 팀은 중앙 시스템의 구성을 앱 플랫폼에 적용하는 방법이 필요합니다. Swarm은 기존 구성 파일에서 클러스터로 로드하는 config 객체를 사용하여 해당 워크플로우를 지원합니다.

TRY todo-list 앱은 구성에 JSON을 사용합니다. 이미지의 기본 구성은 저장을 위해 로컬 DB 파일을 사용하지만 많은 복제본을 실행하면 작동하지 않습니다. 각 컨테이너에는 자체 DB가 있고 사용자는 요청을 처리하는 복제본에 따라 다른 목록을 볼 수 있습니다. 이 문제를 해결하기 위한 첫 번째 단계는 클러스터에 새 구성 파일을 배포하는 것입니다.

JSON 파일로부터 config 객체 생성:

$ docker config create todo-list-config ./todo-list/configs/config.json

클러스터의 config를 확인:

$ docker config ls

todo-list-config   8 seconds ago   8 seconds ago

다른 Docker 리소스와 같은 config 객체를 생성, 제거 및 검사하는 명령이 있습니다. inspect는 config 파일의 내용을 보여주기 때문에 유용합니다. 파일 내용은 Swarm DB에서 암호화되지 않으며 관리자에서 복제본을 실행하는 노드로 이동할 때 전송 중에도 암호화되지 않습니다.

TRY config 객체를 검사하여 전체 내용을 읽을 수 있습니다. 이것은 구성 객체를 사용할 때 복제본이 컨테이너 파일 시스템에서 볼 수 있는 것을 보여줍니다.

$ docker config inspect --pretty todo-list-config

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Database": {
    "Provider": "Postgres"
  }
}

config 객체 관리는 해당 객체를 사용하는 앱 관리와 별도의 워크플로우입니다. DevOps 워크플로우에서는 동일한 팀이나 하나의 자동화된 파이프라인에서 이 모든 작업을 수행할 수 있지만 대기업에서는 기존 프로세스와 일치하는 경우 기능을 별도로 유지할 수 있습니다.

서비스는 config 객체를 Compose 파일에 지정하여 사용합니다. 목록 13.3은 config 객체에서 구성을 로드하는 todo-list 앱에 대한 업데이트된 정의를 보여줍니다.

Listing 13.3 서비스에서 config 객체는 컨테이너 파일시스템에서 드러납니다.

 services:
   todo-web:
       image: diamol/ch06-todo-list
       ports:
           - 8080:80
       configs:
           - source: todo-list-config
             target: /app/config/config.json
 
 #...
 configs:
   todo-list-config:
         external: true

컨테이너가 이 서비스의 복제본으로 실행되면 Swarm에서 앱이 구성 소스로 사용하는 경로 중 하나인/app/config/config.json 파일로 로드된 config 객체의 콘텐츠를 갖게 됩니다. config 객체의 이름을 지정하고 Docker가 기본 대상 경로를 사용하는 경우 파일의 위치를 명시적으로 지정하는 것이 좋습니다.

목록 13.3에 있는 Compose 파일의 두 번째 부분은 이름과 external 플래그와 함께 config 객체 자체를 보여줍니다. external은 이 리소스가 클러스터에 이미 존재해야 함을 의미합니다.

배포 워크플로우는 먼저 config 객체를 배포한 다음 이를 사용하는 앱을 배포하는 것입니다. 여러 웹 컨테이너가 동일한 DB를 공유할 수 있도록 SQL DB에 대한 서비스도 포함하는 v3 Compose 파일을 배포하여 이를 수행할 수 있습니다.

TRY yaml 파일을 배포하여 앱을 업데이트합니다. Swarm은 데이터베이스 서비스를 위한 새 복제본과 웹 애플리케이션을 위한 새 복제본을 생성합니다.

v3로 업데이트된 앱을 배포합니다

 docker stack deploy -c ./todo-list/v3.yml todo
 
Creating network todo_app-net
Creating service todo_todo-web
Creating service todo_todo-db

스택의 서비스를 확인

docker stack services todo

todo_todo-db    replicated   1/1 diamol/postgres:11.5  
todo_todo-web   replicated   1/1 diamol/ch06-todo-list:latest   *:8080->80/tcp

이전 연습에서 이전 스택을 제거했으므로 이것은 새 배포입니다. 생성 중인 네트워크와 두 개의 서비스가 표시됩니다. 각 서비스는 이제 단일 복제본을 실행합니다.

이제 앱이 Postgres DB를 사용하도록 구성되었으며, 이는 config 객체가 복제본에 로드하는 설정입니다. http://localhost:8080으로 이동하면 앱이 작동하지 않는 것을 볼 수 있습니다. 웹 서비스의 로그를 확인하면 그 이유를 알 수 있으며 데이터베이스에 연결하는 데 많은 오류가 표시됩니다.

이 배포는 Postgres를 사용하도록 웹 앱을 구성하지만 config 객체는 DB에 대한 연결 정보를 제공하지 않으므로 연결이 실패합니다.

민감한 데이터는 암호화되지 않고 클러스터에 액세스할 수 있는 모든 사람이 읽을 수 있으므로 config 객체에 보관해서는 안 됩니다. 여기에는 사용자 이름과 암호가 있을 수 있는 데이터베이스 연결 문자열과 프로덕션 서비스 및 API 키에 대한 URL이 포함됩니다.

프로덕션 환경에서는 클러스터 내부의 중요한 데이터를 암호화해야 합니다. Docker Swarm은 이 config 클래스를 저장하기 위한 secrets을 제공합니다.

13.3 secrets로 자격증명 설정 관리

secrets은 클러스터가 관리하는 Swarm의 리소스이며 config 객체와 거의 동일하게 작동합니다. 로컬 파일에서 secret을 생성하면 클러스터 DB에 저장됩니다. 그런 다음 서비스 사양에서 secret을 참조하면 비밀의 내용이 런타임에 컨테이너 파일 시스템에 로드됩니다. 비밀과의 주요 차이점은 워크플로우의 한 지점에서만 일반 텍스트로 읽을 수 있다는 것입니다.

secrets은 클러스터에서 생명주기 내내 암호화됩니다. 데이터는 관리자가 공유하는 DB에 암호화되어 저장되며 secret은 비밀이 필요한 복제본을 실행하도록 예약된 노드에만 전달됩니다. secret은 관리자 노드에서 작업자로 전송되는 동안 암호화되며 원래 파일 내용과 함께 표시되는 컨테이너 내부에서만 암호화되지 않습니다. todo-list 앱에 대한 DB 컨넥션 스트링을 저장하기 위해 secret을 사용할 것입니다.

TRY 로컬 파일에서 secret을 만든 다음 검사하여 Docker가 비밀에 대해 제공하는 정보를 확인하십시오.

$ docker secret create todo-list-secret ./todo-list/secrets/secrets.json

secret을 검사:

docker secret inspect --pretty todo-list-secret

Name:              todo-list-secret
Driver:            
Created at:        2022-03-19 12:12:55.103851847 +0000 utc
Updated at:        2022-03-19 12:12:55.103851847 +0000 utc

이제 Swarm에 secret이 저장되었으므로 이것을 사용하는 서비스 사양으로 앱의 새 버전을 배포할 수 있습니다. secret에 대한 Compose 구문은 config 객체와 매우 유사합니다. 서비스 정의에서 secret의 source와 target 경로를 지정하면 secret 자체가 자신의 정의를 얻습니다.

목록 13.4 v4 앱 구성을 위한 secrets 및 config 지정

 services:
   todo-web:
       image: diamol/ch06-todo-list
       ports:
           - 8080:80
       configs:
           - source: todo-list-config
             target: /app/config/config.json
       secrets:
           - source: todo-list-secret
             target: /app/config/secrets.json
 
 #...
 secrets:
   todo-list-secret:

secrets의 콘텐츠는 앱이 구성 소스를 찾는 다른 경로에 로드되는 더 많은 JSON입니다. 이렇게 하면 데이터 저장소에 Postgres 컨테이너를 사용하도록 연결 세부 정보가 있는 앱이 설정되므로 앱을 배포할 때 사용자는 웹 복제본이 제공하는 동일한 항목 목록을 받게 됩니다.

TRY 누락된 DB 컨넥션 스트링을 제공하고 웹 앱을 수정하는 최신 버전의 앱을 배포하면 서비스가 업데이트됩니다.

$ docker stack deploy -c ./todo-list/v4.yml todo

스택의 복제본을 확인합니다.

$ docker stack ps todo
 
 sbxc7z78fpcc   todo_todo-db.1        diamol/postgres:11.5           docker-desktop   Running         Running 13 minutes ago             
c8e24gd7yukv   todo_todo-web.1       diamol/ch06-todo-list:latest   docker-desktop   Running         Running 1 second ago               
uznbydizfzf9    \_ todo_todo-web.1   diamol/ch06-todo-list:latest   docker-desktop   Shutdown        Shutdown 2 seconds ago 

Compose 파일에서 웹 서비스 정의만 변경되었지만 이를 실행하면 두 서비스를 모두 업데이트하는 Docker 상태를 볼 수 있습니다. 실제로 DB 서비스를 업데이트하지 않으므로 이는 CLI에서 약간 잘못된 출력입니다. 모든 서비스가 변경되지는 않더라도 Compose 파일의 모든 서비스를 "업데이트 중"으로 나열합니다.

이제 앱이 올바르게 작동하며 http://localhost:8080 으로 이동하면 확인할 수 있습니다. 그림 13.10은 Docker 네트워크에 연결된 컨테이너와 Swarm에서 로드된 secret이 있는 인프라 설정을 보여줍니다.

그림 13.10에서 누락된 중요한 것은 하드웨어 보기이며, 이는 이 앱이 모든 규모의 Swarm에서 동일한 배포 아키텍처를 갖고 있기 때문입니다. secret 및 config 객체는 관리자의 분산 DB에 저장되며 모든 노드에서 사용할 수 있습니다. 스택은 오버레이 네트워크를 생성하여 컨테이너가 실행 중인 노드에 상관없이 서로 연결할 수 있으며, 서비스는 수신 네트워크를 사용하므로 소비자는 트래픽을 모든 노드로 보내고 웹 복제본 중 하나에서 작업을 수행할 수 있습니다.


그림 13.10 스택으로 실행되는 todo-list 앱은 Docker Swarm의 주요 기능을 사용합니다.

Config 객체와 secret은 업데이트할 수 없습니다. 클러스터에서 생성할 때 내용은 항상 동일하며 앱에 대한 구성을 업데이트해야 하는 경우 교체해야 합니다. 여기에는 세 단계가 포함됩니다.

  • 이전 객체와 다른 이름으로 새 config 객체 또는 secret을 만듭니다.
  • 새 이름을 지정하여 앱이 Compose 파일에서 사용하는 config 객체 또는 secret의 이름을 업데이트합니다.
  • 업데이트된 Compose 파일에서 스택을 배포합니다.

이 프로세스는 구성을 변경할 때마다 서비스를 업데이트해야 함을 의미합니다. 즉, 실행 중인 컨테이너가 새 컨테이너로 교체됩니다. 이것은 오케스트레이터가 다른 접근 방식을 취하는 영역 중 하나입니다. Kubernetes를 사용하면 클러스터의 기존 config 및 secret 객체를 업데이트할 수 있습니다. 하지만 일부 앱 플랫폼은 구성 파일의 변경 사항을 감시하고 다른 플랫폼은 감시하지 않기 때문에 자체 문제가 발생합니다. 따라서 변경 사항이 무시될 수 있으며 어쨌든 컨테이너를 교체해야 합니다. Swarm은 구성 변경을 롤아웃할 때 항상 서비스를 업데이트해야 합니다.

앱에 배포할 새로운 기능이 있을 때마다 또는 사용하는 종속성 또는 이미지의 기반이 되는 운영 체제에 보안 업데이트가 있을 때마다 컨테이너 업데이트를 롤아웃할 것입니다. 최소한 매월 업데이트를 출시할 것으로 예상해야 합니다. 이는 대부분의 운영 체제 기반 이미지가 Docker Hub에서 업데이트되는 빈도입니다.

이는 Swarm 모드의 상태 저장 앱을 제공합니다. 컨테이너를 정기적으로 교체할 예정이므로 영구 저장소에 Docker 볼륨을 사용해야 하며 볼륨은 Swarm에서 약간 다르게 작동합니다.

13.4 Swarm에 볼륨이 있는 데이터 저장

도커 볼륨은 컨테이너와 별도의 수명 주기가 있는 스토리지 단위입니다. 컨테이너화하려는 모든 상태 저장 앱은 스토리지에 볼륨을 사용할 수 있습니다. 볼륨은 컨테이너 파일 시스템의 일부로 나타나지만 실제로는 컨테이너 외부에 저장됩니다. 앱 업그레이드는 컨테이너를 교체하고 볼륨을 새 컨테이너에 연결하므로 새 컨테이너는 이전 컨테이너에 있던 모든 데이터로 시작됩니다.

볼륨은 오케스트레이터에서도 개념적으로 동일합니다. Compose 파일에서 서비스에 대한 볼륨 마운트 사양을 추가하고 복제본은 해당 볼륨을 로컬 디렉토리로 봅니다. 하지만 데이터가 저장되는 방식에는 큰 차이가 있습니다. 클러스터에는 컨테이너를 실행할 수 있는 여러 노드가 있으며 각 노드에는 로컬 볼륨을 저장하는 자체 디스크가 있습니다.

업데이트 간에 상태를 유지하는 가장 간단한 방법은 로컬 볼륨을 사용하는 것입니다. 하지만 그 접근 방식에는 문제가 있습니다. 교체 복제본이 원본과 다른 노드에서 실행되도록 예약될 수 있으므로 원본 노드의 데이터에 액세스할 수 없습니다. 특정 노드에 서비스를 고정할 수 있습니다. 즉, 업데이트는 항상 데이터가 있는 노드에서 실행됩니다. 이는 애플리케이션 데이터를 컨테이너 외부에 저장하여 업데이트 후에도 유지되기를 원하지만 여러 복제본을 실행할 필요가 없고 서버 오류를 허용할 필요가 없는 시나리오에서 작동합니다. 노드에 레이블을 적용하고 Compose 파일에서 복제본이 해당 노드에서 실행되도록 제한합니다.

TRY 단일 노드 Swarm이 있으므로 모든 복제본은 어쨌든 이 노드에서 실행되지만 레이블 지정 프로세스는 다중 노드 Swarm에 대해 동일한 방식으로 작동합니다. 레이블은 모든 키/값 쌍이 될 수 있습니다. 이것을 사용하여 가짜 스토리지 클래스를 할당합니다.

 # find the ID for your node and update it, adding a label:
 docker node update --label-add storage=raid $(docker node ls -q)

노드ID가 있으므로 클러스터에서 노드를 식별하여 서비스 복제본이 예약되는 위치를 제한할 수 있습니다. 목록 13.5는 todo-list DB에 대한 서비스의 제약 조건을 보여줍니다. 이 제약 조건에는 이제 볼륨도 지정되어 있습니다. 이것은 v5.yml 배포 파일에 있습니다.

목록 13.5 Swarm의 서비스에 대한 제약 조건 및 볼륨 구성

 services:
   todo-db:
       image: diamol/postgres:11.5
       volumes:
         - todo-db-data:/var/lib/postgresql/data
       deploy:
           placement:
               constraints:
                   - node.labels.storage == raid
 
 #...
 volumes:
     todo-db-data:

Compose 파일 끝에 있는 volumes는 로컬 디스크를 사용하는 Swarm의 기본 볼륨 드라이버를 사용하여 생성됩니다. 이것을 클러스터에 배포하면 스토리지 레이블과 일치하는 노드에서 DB 복제본이 실행되고 해당 노드는 데이터 파일이 저장되는 todo-db-data 라는 로컬 볼륨을 생성합니다.

TRY Compose 파일의 제약 조건은 Swarm 노드에 추가한 레이블과 일치하므로 DB 컨테이너가 해당 노드에서 실행되고 해당 노드의 로컬 볼륨을 사용합니다. 다음 명령은 배포 전후에 노드의 볼륨을 탐색합니다.

노드의 모든 볼륨 ID를 확인:

$ docker volume ls -q
 
d7ea940bbc77fbbb1c20ed98ec964dd5b68da955880c844a5422069cbb121fc2
fc9451688d815a01d2cc81d502d89f75f56c7abff751b1999f4f83c33caf1c58

스택을 v5로 업데이트

$ docker stack deploy -c ./todo-list/v5.yml todo

다시 볼륨 ID를 확인

$ docker volume ls -q

v5에서 DB 서비스에 todo-db-data 이름의 볼륨을 지정합니다. 스택을 제거하면 디폴트 볼륨이 제거되고 이 볼륨은 남아 있습니다.

d7ea940bbc77fbbb1c20ed98ec964dd5b68da955880c844a5422069cbb121fc2
fc9451688d815a01d2cc81d502d89f75f56c7abff751b1999f4f83c33caf1c58
todo_todo-db-data

이 배포는 레이블이 지정된 노드 자체를 사용할 수 있는 경우 데이터 가용성을 보장합니다. 컨테이너가 상태 확인에 실패하고 교체되면 새 복제본은 이전 복제본과 동일한 노드에서 실행되고 동일한 이름의 볼륨에 연결됩니다. DB 서비스 사양을 업데이트하면 동일한 보장을 받습니다. 즉, DB 파일이 컨테이너 간에 유지되고 데이터가 안전합니다. 웹 UI를 통해 todo-list에 항목을 추가하고, DB 서비스를 업그레이드하고, 새 DB 컨테이너에서 이전 데이터가 여전히 UI에 있는지 확인할 수 있습니다.

TRY 6장을 작성한 이후로 Postgres 서버의 새 릴리스가 나왔고 최신 상태를 유지하는 것이 좋으므로 DB 서비스를 업데이트하겠습니다. v6.yml의 Compose 사양은 업데이트된 버전의 Postgres를 사용한다는 점을 제외하고 v5.yml과 동일합니다.

업데이트된 DB를 배포:

$ docker stack deploy -c ./todo-list/v6.yml todo

Updating service todo_todo-db (id: 44dy5jaip1ym39w9yb2pprf8w)
Updating service todo_todo-web (id: i3scsopjasl88b6alpk7lvp5a)

스택에 태스크를 확인

$ docker stack ps todo

   todo_todo-db.1        diamol/postgres:11.6           docker-desktop   Running         Running 22 seconds ago              
    \_ todo_todo-db.1    diamol/postgres:11.5           docker-desktop   Shutdown        Shutdown 33 seconds ago             
    \_ todo_todo-db.1    diamol/postgres:11.5           docker-desktop   Shutdown        Shutdown 7 minutes ago              
   todo_todo-web.1       diamol/ch06-todo-list:latest   docker-desktop   Running         Running 16 hours ago                
    \_ todo_todo-web.1   diamol/ch06-todo-list:latest   docker-desktop   Shutdown        Shutdown 16 hours ago 

볼륨을 확인

$ docker volume ls -q

d7ea940bbc77fbbb1c20ed98ec964dd5b68da955880c844a5422069cbb121fc2
fc9451688d815a01d2cc81d502d89f75f56c7abff751b1999f4f83c33caf1c58
todo_todo-db-data

이것은 간단한 예이며 로컬 볼륨의 데이터가 모든 노드에 복제되지 않기 때문에 애플리케이션에 대한 스토리지 요구 사항이 서로 다를 경우 상황이 더 복잡해집니다. 디스크를 데이터 캐시로 사용하는 앱은 데이터가 복제본마다 다를 수 있으므로 로컬 볼륨에서는 문제가 없지만 클러스터 전체에서 공유 상태에 액세스해야 하는 앱에서는 작동하지 않습니다. Docker에는 볼륨 드라이버용 플러그인 시스템이 있으므로 클라우드 스토리지 시스템 또는 데이터 센터의 스토리지 장치를 사용하여 분산 스토리지를 제공하도록 Swarm을 구성할 수 있습니다. 이러한 볼륨을 구성하는 것은 사용 중인 인프라에 따라 다르지만 동일한 방식으로 볼륨을 소비하여 서비스에 볼륨을 연결합니다.

13.5 클러스터가 스택을 관리하는 방법

Docker Swarm의 스택은 클러스터에서 관리하는 리소스 그룹일 뿐입니다. 프로덕션 스택에는 많은 리소스가 포함되며 오케스트레이터가 리소스를 관리하는 방식과 관련하여 모두 약간 다르게 작동합니다.

그림 13.13 스택 배포에서 Docker Swarm 리소스를 관리하는 방법

여기서 얻을 것이 몇가지 있습니다.

  • 볼륨은 Swarm에서 생성 및 제거할 수 있습니다. 서비스 이미지가 하나를 지정하면 스택은 기본 볼륨을 생성하고 해당 볼륨은 스택이 제거될 때 제거됩니다. 스택에 대해 명명된 볼륨을 지정하면 배포할 때 생성되지만 스택을 삭제할 때 제거되지 않습니다.

  • 외부 파일이 클러스터에 업로드되면 secret 및 config가 생성됩니다. 클러스터 DB에 저장되고 서비스 정의에 필요한 컨테이너로 전달됩니다. 그들은 효과적으로 한 번 읽고 많은 객체이며 업데이트할 수 없습니다. Swarm에 앱 구성을 저장하는 관리 프로세스는 앱 배포 프로세스와 별개입니다.

  • 네트워크는 관리자가 앱에서 사용할 네트워크를 명시적으로 생성하여 앱과 독립적으로 관리하거나 필요할 때 생성 및 제거하는 Swarm에서 관리할 수 있습니다. 모든 스택은 Compose 파일에 지정되지 않은 경우에도 서비스를 연결할 네트워크와 함께 배포됩니다.

  • 서비스는 스택이 배포될 때 생성되거나 제거되며, 실행되는 동안 Swarm은 스택을 지속적으로 모니터링하여 원하는 서비스 수준이 충족되고 있는지 확인합니다. 노드가 오프라인 상태가 되면 손실되는 복제본과 마찬가지로 상태 확인에 실패한 복제본이 교체됩니다.

스택은 애플리케이션을 구성하는 논리적 구성 요소 그룹이지만 서비스 간의 종속성 그래프를 매핑하지 않습니다. 클러스터에 스택을 배포할 때 관리자는 클러스터 전체에서 가능한 한 빨리 많은 서비스 복제본을 가동합니다. 클러스터가 다른 서비스를 시작하기 전에 한 서비스를 완전히 시작하도록 제한할 수는 없으며, 가능하다면 배포 성능이 저하될 수 있습니다. 대신 구성 요소가 임의의 순서로 시작된다고 가정하고 이미지에서 상태 및 종속성 검사를 캡처하여 애플리케이션을 실행할 수 없는 경우 컨테이너가 빠르게 실패하도록 해야 합니다. 그렇게 하면 클러스터가 컨테이너를 다시 시작하거나 교체하여 손상을 복구할 수 있으며, 이를 통해 자가 치유 앱을 얻을 수 있습니다.

13.6 Lab

Compose 파일을 작성하여 앱을 정의하고 Swarm에 스택으로 배포하는 경험을 얻을 수 있습니다. 다음 요구 사항과 일치하는 단일 Compose 파일에 있어야 하는 9장의 image-gallery 앱에 대한 프로덕션 배포를 작성했으면 합니다.

  • 액세스 로그 API는 diamol/ch09-access-log 이미지를 사용합니다. 웹 앱에서만 액세스할 수 있는 내부 구성 요소이며 3개의 복제본에서 실행되어야 합니다.

  • NASA API는 diamol/ch09-image-of-the-day 이미지를 사용합니다. 이는 포트 8088에서 공개적으로 액세스할 수 있어야 하며 예상되는 수신 로드를 지원하기 위해 5개의 복제본에서 실행되어야 합니다.

  • 웹 앱은 diamol/ch09-image-gallery 이미지를 사용합니다. 표준 HTTP 포트 80에서 사용할 수 있어야 하며 2개의 복제본에서 실행되어야 합니다.

  • 모든 구성 요소에는 합리적인 CPU 및 메모리 제한이 있어야 합니다(안전한 최대값을 계산하려면 몇 차례의 배포가 필요할 수 있음).

  • 스택을 배포하면 앱이 작동해야 합니다.

TRY:

docker stack deploy -c image-gallery.yml image-gallery

image-gallery.yml

version: "3.7"

services:
  accesslog:
    image: diamol/ch09-access-log
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: "0.50"
          memory: 100M
    networks:
      - app-net

  iotd:
    image: diamol/ch09-image-of-the-day
    ports:
      - 8088:80
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "1"
          memory: 200M
    networks:
      - app-net

  image-gallery:
    image: diamol/ch09-image-gallery
    ports:
      - 80:80
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: "0.75"
          memory: 75M
    networks:
      - app-net

networks:
  app-net:
    name: image-gallery-prod
profile
코드코드

0개의 댓글