Programming-[Infra]/Docker

도커 교과서(엘튼 스톤맨, 심효섭) - 11. 스택, 컨피그, 시크릿, 스웜에서의 볼륨

컴퓨터 탐험가 찰리 2023. 4. 30. 14:31
728x90
반응형

 

 

1. 스택과 배포

스택은 여러 애플리케이션(서비스)와 그 애플리케이션의 레플리카, 네트워크 등을 관리하는 단위다. 스택도 일급 객체라서 명령어로 직접 호출이 가능하다. 컴포즈 파일을 이용해서 stack deploy를 해본다.

 

기본 배포

cd ./ch13/exercises
docker stack deploy -c ./todo-list/v1.yml todo
docker stack ls
docker service ls

 

stack deploy 명령어를 이용하여 배포하면, '_default'라는 이름이 붙은 네트워크가 생성되고 yml 파일의 내용을 따라 서비스가 실행되는 것을 볼 수 있다.  -c 부옵션은 서비스, 네트워크, 볼륨 등의 정보를 정의한 컴포즈 파일의 path를 입력한다는 의미이다.

 

저자의 애플리케이션 설정에 따라 리눅스 컨테이너를 사용 중인 경우 localhost:8080에 접속하면 애플리케이션의 웹페이지를 확인할 수 있다. 이전에 실행했던 TODO List와 같은 앱이다.

 

 

자원 제한 옵션 추가

컴포즈 파일에 아래처럼 resources 프로퍼티로 cpu, memory 용량을 제한하는 설정을 추가할 수 있다.

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

이렇게 하면 각 레플리카가 코어의 CPU의 50%, 100MB까지만 점유할 수 있도록 설정한다.

docker stack deploy -c ./todo-list/v2.yml todo
docker service ps todo_todo-web

 

새로운 컴포즈 파일로 배포하면 기존 서비스는 shutdown되고, 새로운 서비스가 Running된다. 여기서 유의할 점은 새로운 환경 설정으로 변경하기 위해서는 기존 서비스를 내리고 새로 배포해야한다 는 것이다.

 

 

스택 삭제, 설정값 저장

  • 스택을 삭제하면 스택에 포함된 네트워크 등 모든 자원이 삭제된다.
  • 클러스터 데이터베이스에 애플리케이션에 대한 정의가 저장되어 있다. 매니저 노드에서도 이 복사본을 갖고 있기 때문에 컴포즈 파일이 없어도 스택의 모든 리소스를 관리할 수 있다.

스택 삭제

docker stack rm todo

 

 

2. 컨피그(Config) 객체

 

컨피그 객체는 비밀값을 제외한 애플리케이션의 모든 설정 정보를 포함하고 있으므로 매우 중요하다. 그렇기 때문에 모든 오케스트레이션 도구가 1등급 리소스로 취급한다. 그래서 아래처럼 cli에서 명령어로 바로 사용할 수 있다.

 

docker config create todo-list-config ./todo-list/configs/config.json # 로컬에 있는 config 파일로 컨피그 객체 생성. create 뒤 인자는 각각 생성할 config 파일 이름, 로컬에 존재하는 config 파일 경로
docker config ls

 

  • JSON이 아니라 XML, key-value 등으로도 config를 정의할 수 있다.
  • 컨피그 객체는 확인 및 접근이 자유롭다. 따라서 컨피그 객체에 민감 정보를 넣으면 안된다. 민감정보는 뒤에서 다룰 시크릿 객체에 넣는다.

컨피그 객체를 확인할려면 inspect --pretty 부명령을 주면 된다.

docker config inspect --pretty todo-list-config

 

컨피그 객체의 정의와 배포

 

v3.yml 파일의 일부

source, target 설정에 따라 컨피그 파일의 설정이 각 실행되는 레플리카의 target 위치로 옮겨진다. 그리고 설정 파일에 대한 정의를 아래쪽에 따로 해주었다. external: true 형식은 해당 컨피그 객체가 이미 클러스터에 저장되어 있음을 나타낸다.

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

 

컨피그 파일이 먼저 배포되고 나서 애플리케이션이 배포되는 것이 규칙이다.

 

 

3. 시크릿 객체(비밀값) 

앞서 언급했듯이 데이터베이스 접속을 위한 url, id, password와 같이 주요 민감 정보는 시크릿 객체에 저장된다.

  • 로컬에서 생성되어 클러스터로 전달되는 비밀값은 암호화되어 클러스터의 데이터베이스에 저장된다.
  • 매니저 노드에서 워커 노드로 전달될 때도 암호화된 상태로 전달된다.
  • 최종 비밀값을 사용하는 레플리카에서만 복호화된다.

 

docker secret create todo-list-secret ./todo-list/secrets/secrets.json
docker secret inspect --pretty todo-list-secret

 

컨피그 객체와 거의 똑같이 로컬의 비밀값 정보를 바탕으로 시크릿 객체를 생성했다. 그리고 확인을 하는데, 컨피그 객체와는 다르게 상세 정보가 조회되지 않고 암호화된 ID 값과 부가 정보들만 확인이 가능하다.

 

새로 업데이트할 v4.yml 파일에는 v3의 컨피그 객체와 유사하게 secret 객체의 전달방식을 정의하였다.

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:
    external: true

 

v4로 배포 시 서비스가 업데이트 된다. 예제의 설정상 이제 데이터베이스에 접속하기 위한 정보가 secret으로 전달되어 todo 웹 앱에서 정상적으로 데이터베이스를 참조하고 서비스가 가능해진다고 설명한다.

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

 

 

컨피그, 비밀값의 변경 시 컨테이너를 업데이트해야할 수 있다.

컨피그, 비밀값은 기본적으로 컨테이너를 업데이트하지 않고는 변경이 불가하다. 읽기 전용이라는 뜻이다. 쿠버네티스의 경우 컨테이너 업데이트 없이 변경이 가능할 수도 있으나, 사용 중인 애플리케이션이 자동으로 변경된 값을 참조하지 않는다면 쿠버네티스도 컨테이너를 업데이트 해야만 한다. 변경을 위한 단계는 아래와 같다.

  • 컨피그, 비밀값의 이름을 변경한다.
  • yml 파일의 컨피그, 비밀값의 각 정의 부분에 변경된 이름을 적는다.
  • 변경된 컴포즈 파일로 스택을 배포한다.

 

 

 

4. 볼륨

 

앞서 배운 바와 같이 볼륨은 컨테이너와 별도의 생애주기를 갖는다. 볼륨에 데이터를 저장해놓은 상태로 새로운 컨테이너를 만든다면, 볼륨의 데이터를 참조하기 위해서 새로운 컨테이너와 볼륨을 연결시켜줘야한다.

 

노드에 레이블 부여

물리적으로 볼륨은 특정 노드의 디스크를 참조하므로 여러 노드가 있는 상태에서 컨테이너가 특정 볼륨을 참조하는 경우 문제가 발생할 수 있다. 이런 상황이 예상된다면 노드에 레이블을 부여하고 컴포즈 파일에서 해당 노드에서만 레플리카를 실행하도록 정의해야한다.

 

docker node update --label-add storage=raid $(docker node ls -q)

 

여기서 -q는 ID값만 출력하도록 하는 플래그이다. 로컬 컴퓨터는 단일 노드이므로 id값 1개만 출력될 것이다. 이 노드에 key=value 형태로 storage=raid라는 레이블 값을 부여했다.

 

예제 v5.yml 파일의 일부

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
    deploy:
      replicas: 1
      resources:
        limits:
          cpus: "0.50"
          memory: 100M
    networks:
      - app-net

  todo-db:
    image: diamol/postgres:11.5
    environment:
      PGDATA: "/var/lib/postgresql/data/pgdata"
    volumes:
      - todo-db-data:/var/lib/postgresql/data
    deploy:
      replicas: 1
      resources:
        limits:
          cpus: "0.50"
          memory: 500M
      placement:
        constraints:
          - node.labels.storage == raid
    networks:
      - app-net
      
      
   ## 중략
volumes:
  todo-db-data:

 

맨 아래 volume 정의 부분에서는 이름만 적어서 스웜의 기본 볼륨 드라이버를 사용하도록 했다. 그리고 volumes: -todo... 부분은 todo-db-data로 정의된 볼륨과 새로 생성될 컨테이너의 /var/lib... 경로를 연결하여 마운트하겠다는 뜻이 된다.

 

중요한 부분은 deploy > placement > constraints에서 노드의 레이블을 앞서 설정한대로 storage==raid 값인 부분으로 설정하여 해당 노드에서만 컨테이너가 생성되도록 한 부분이다.

 

레이블을 붙인 볼륨은 유지된다

이렇게 레이블을 붙인 볼륨은 스택을 제거하더라도 데이터를 유실하지 않는다. 다시 말해 볼륨에 레이블을 지정하면 컨테이너에 문제가 생겨 새 컨테이너로 교체하더라도 같은 노드에서 같은 볼륨을 연결하여 데이터 를 유지시킬 수 있다.

 

 

스택과 관련한 몇 가지 사항을 더 기록해놓는다.

  • 네트워크는 사용자가 직접 정의할 수도 있다. 스웜이 네트워크를 자동으로 생성하기도 한다. 모든 스택은 컴포즈 파일에 네트워크가 정의되어 있지 않더라도 배포할 서비스와 연결된 서비스가 있다면 그와 연결된 네트워크로 배포된다.
  • 서비스가 실행 중일때는 스웜이 서비스를 모니터링 하면서 헬스 체크를 한다. 그리고 스웜이 자동으로 컨테이너를 교체해준다.
  • 스택에서는 서비스간 의존관계를 알지 못한다. 개발자는 애플리케이션이 무작위로 생성된다고 가정해야한다. 디펜던시 체크와 컨테이너 실행 실패 duration 시간을 잘 조절하여 오케스트레이션 도구가 스스로 컨테이너를 재시작시켜 정상적으로 모든 컨테이너들을 실행하지 못할 수도 있다는 것을 고려해야한다.

 

 

728x90
반응형