티스토리 뷰
참조글 :
도커스웜 기초 및 예제
클러스터란?
먼저 클러스터 개념을 소개하기전에 라즈베리파이 컴퓨터에 대해서 알아보겠습니다.
라즈베리파이 재단에서 만든 초소형/초저가의 컴퓨터를 라즈베리파이라고 하는데요,
2012년 3월에 첫 버전을 출시하여, 현재 버전 4까지 이어져오고 있습니다.
가격이 저렴한 만큼 성능이 제한적이라서, 개인 실험용이나 임베디드 리눅스 개발보드로 사용되고 있습니다.
(IoT 프로젝트할때, 많이 쓰는 편!)
출처: https://www.devicemart.co.kr/goods/view?no=12234534
인간들은 라즈베리파이를 진짜 프로덕션에서 쓸 수 없을까? 성능을 어떻게 끌어올려볼까? 이런 호기심이 생기기 시작합니다.
사람들은 이 작고 가벼운 성능의 라즈베리파이를 괴롭혀보기로 합니다.
다수의 라즈베리파이를 병렬로 묶어서 사용해보자. 즉, 클러스터를 만들어보기로 합니다...
처음에는 3대
조금만 더 ...
인간의 욕심은 끝이 없죠
결국 144노드를 클러스터링한 상용 모듈까지 나오게 됩니다..
심지어 버지니아 공대에서는 SeeMore라는 256노드의 창작품까지 만들었습니다.
seeMore at SXSW from Sam Blanchard on Vimeo.
출처: https://magpi.raspberrypi.com/articles/seemore
하지만 이렇게 클러스터링한다고 해서 성능이 무작정 좋아지는건 아닙니다.
4대의 클러스터와 라즈베리파이 한대의 Run-time과 Speed Up 비교를 보면 라즈베리파이 한대가 오히려 성능이 더 좋게 나옵니다.
이유는 클러스터링된 노드간 통신에 사용하는 이더넷 속도(10/100Mbps)의 한계인 것으로 보입니다.
출처: https://magpi.raspberrypi.com/articles/benchmarking-raspberry-pi-cluster
정리하자면, 컴퓨터의 클러스터라는 개념은 다수의 노드(컴퓨터)를 묶어서, 병렬처리가 가능하게 하여 성능을 올려주는 기술을 말합니다.
도커 스웜이란?
도커에도 클러스터를 위한 도커 스웜이라는 기술이 있습니다.
도커 스웜은 노드들의 집합에 서비스형태로 도커컨테이너를 배포하고 관리할 수 있게 하는 기술입니다.
쉽게 말해서, 클러스터용 컨테이너 서비스 관리 툴이라고 보면 됩니다.
도커스웜을 쓰는 이유?
RAM 8GB 서버로 도커를 운영하고 있는데, 가용램을 넘어서, 더이상 서비스를 올릴 수가 없다면 어떻게 해야할까요?
RAM 8GB 짜리 서버가 한대 더 있다고, 가정해봅시다. 그러면 이 한대를 더 추가해서 운영할 것 입니다. 그런데, 이 두대를 하나의 자원으로 쓰고 싶다고 가정해봅시다.
마치 RAM 16GB의 서버 한대처럼 동작하도록 말이죠. 이럴때 필요한게 병렬확장인 클러스터입니다.
하지만 이런 병렬처리 컴퓨팅을 개인이 만드는 것은 쉽지 않습니다. 하지만 다행하게도 그걸 도와주는 툴이 존재하죠! 바로 도커 스웜 입니다.
스웜모드 구조
도커와 차이점?
스웜모드가 아닌 도커와의 차이는 서비스 개념 입니다.
도커에서는 컨테이너가 단위었다면, 스웜에서는 서비스가 단위입니다.
서비스는 한개의 컨테이너 또는 다수의 컨테이너가 조합될 수 있는 단위입니다.
도커 스웜 설정
이 포스팅에서는 도커 스웜의 기초를 다지기 위해서, 클러스터 사용없이, 단일 노드 스웜 모드를 사용하도록 하겠습니다.
아래 명령어로 스웜 모드 초기화를 진행해봅시다.
docker swarm init
싱글노드로 사용하기 위한 준비는 끝났습니다! 엄청 간단하죠?
도커 스웜용 컴포즈 작성 방법
도커 스웜에서는 서비스를 배포하기 위해서 docker-compose 형식의 파일을 사용합니다.
하지만 도커 컴포즈와는 다르게 deploy라는 옵션이 있고, docker stack에서는 제한되는 옵션들이 있습니다.
제한되는 목록
build
cgroup_parent
container_name
devices
tmpfs
external_links
links
network_mode
restart
security_opt
userns_mode
deploy
도커스택에서 사용하는 기본적인 옵션들에 대해서 알아보겠습니다.
replicas
version: "3.9"
services:
mysql:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=rootpw
deploy:
replicas: 1
adminer:
image: adminer
ports:
- "8080:8080"
deploy:
replicas: 1
resources
limits: 최대 리소스 성능 제한
reservations: 점유할 리소스 예약
version: "3.9"
services:
redis:
image: redis:alpine
deploy:
resources:
limits:
cpus: '0.50'
memory: 50M
reservations:
cpus: '0.25'
memory: 20M
restart_policy
이 옵션은 컨테이너가 어떻게 다시 켜질 것인지에 대한 옵션입니다.
condition: none, on-failure, any (default: any)
delay: 재시작 시도 시간 간격 (default: 5s)
max_attempts: 재시작 시도 횟수 (default: never give up)
window: 재시작 성공시, 서비스를 다시 실행하는데 걸리는 시간 (default: decide immediately)
version: "3.9"
services:
redis:
image: redis:alpine
deploy:
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 10s
update_config
parallelism: 한 번에 업데이트할 컨테이너 수입니다.
delay: 컨테이너 그룹 업데이트 사이에 대기하는 시간입니다.
failure_action: 업데이트에 실패한 경우 수행할 작업. 중 하나 continue, rollback또는 pause
(기본값 : pause)
monitor: 실패 모니터링을 위한 각 작업 업데이트 후의 기간 (ns|us|ms|s|m|h)(기본값 5초)
(참고 : 0으로 설정하면 기본값 5초가 사용됩니다.)
max_failure_ratio: 업데이트 중 허용되는 실패율입니다.
order: 업데이트 중 작업 순서입니다. 하나는 stop-first(이전 작업은 새로운 하나를 시작하기 전에 정지)
또는 start-first(새 작업이 먼저 시작되고 실행중인 작업 간략하게 중복)
(기본값 stop-first) (참고 : compose V3.4 이상에서 지원.)
version: "3.9"
services:
redis:
image: redis:alpine
deploy:
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
vote:
image: dockersamples/examplevotingapp_vote:before
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
order: stop-first
도커 스웜 기초 명령어
스웜모드가 활성화되면 아래와 같은 명령어를 실행할 수 있습니다.
docker service
docker service create로 컴포즈 파일없이 즉시 서비스를 올릴 수 있다.
예제
docker service create --name registry --publish published=5000,target=5000 registry:2
docker service ls 로 실행중인 서비스들을 확인할 수 있다.
docker stack
docker stack 명령어는 -c or --compose-file 옵션으로 컴포즈파일을 지정해주어야 한다.
예제에 사용할 yaml파일은 아래와 같다.
version: "3.9"
services:
mysql:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=rootpw
deploy:
replicas: 1
adminer:
image: adminer
ports:
- "8080:8080"
deploy:
replicas: 1
docker stack deploy --compose-file <compose 파일경로> <stack 이름>
예제는 아래와 같다.
docker stack deploy --compose-file docker-compose.yml stackdemo or
docker stack deploy -c docker-compose.yml stackdemo
docker stack services stackdemo 로 실행중인 서비스를 확인할 수 있다.
docker stack rm stackdemo로 스택을 없앨 수 있다.
도커 스웜 기본 예제
로드 밸런싱 (HA Proxy)
var http = require('http');
var os = require('os');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(`<h1>I'm ${os.hostname()}</h1>`);
console.log(os.hostname())
}).listen(8080);
FROM node
RUN mkdir -p /usr/src/app
COPY index.js /usr/src/app
EXPOSE 8080
CMD [ "node", "/usr/src/app/index" ]
docker-compose.yaml
version: '3.9'
services:
node:
image: api-example
ports:
- 8080
environment:
- SERVICE_PORTS=8080
deploy:
replicas: 5
update_config:
parallelism: 5
delay: 10s
restart_policy:
condition: on-failure
max_attempts: 3
window: 120s
networks:
- web
proxy:
image: dockercloud/haproxy
depends_on:
- node
environment:
- BALANCE=leastconn
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- 80:80
networks:
- web
deploy:
placement:
constraints: [ node.role == manager ]
networks:
web:
driver: overlay
위의 세개파일을 만들어 놓고, 순서대로 설정해보자
일단 도커파일로 이미지를 만든다.
docker build -t api-example .
다음으로 스택을 배포 할 수 있도록 도커스웜 초기화 명령어인
docker swarm init을 실행해보자
도커 스웜 init이 제대로 실행되었다면,
docker stack deploy --compose-file=docker-compose.yaml study 으로 서비스를 실행시켜보자
docker ps로 확인해보면 5개의 컨테이너와 하나의 haproxy 서버가 올라가 있는것을 확인할 수 있다.
docker service ls로 조금 더 정리된 화면을 확인할 수 있다.
docker service logs -f study_node로 로그를 확인해보자.
*********************************************************
containerd는 무엇이고 왜 중요할까?
Docker의 기본 아이디어는 프로세스와 CPU, memory, disk I/O, network 등의 리소스들을 컨테이너라는 하나의 그룹으로 묶어서 관리하자는 것으로 namespace, cgroup 등 Linux의 여러 커널기능들을 조합하여 만들어졌습니다.
이 무렵 구글 내부에서도 컨테이너를 활용해 대규모 서비스를 구축해보는 프로젝트가 진행중이었습니다. 프로젝트의 이름은 Project 7이었으나 나중에 Kubernetes로 바뀌게 됩니다. Kubernetes 역시 등장과 함께 업계의 환영을 받으며 구글을 시작으로 많은 기업들에서 채택되게 됩니다. 참고로 Kubernetes 로고의 방향타 손잡이가 7개인 것은 바로 원래 프로젝트 이름인 Project 7에서 따온 것이라고 합니다.
이렇게 Docker와 Kubernetes가 나란히 성공신화를 써내려가고 있는 가운데 Docker 측에서는 기존 Docker Engine의 Monolithic한 구조를 나누는 작업을 시작했습니다. 초기 Docker를 개발하면서 하나의 완성된 컨테이너 사용자경험을 만드는 것에 집중하다보니 Docker Engine이라는 하나의 패키지에 API, CLI, 네트워크, 스토리지 등 여러 기능들을 모두 담게 되었고, Docker에 의존하고 있던 Kubernetes에서는 Docker 버전이 새로 나올때마다 Kubernetes가 크게 영향을 받는 일들이 생겨났기 때문입니다.
그래서 Docker를 중심으로 구글 등 컨테이너 기술에 관심있는 여러 집단들이 한데 모여 Open Container Initiative, 이하 OCI라는 프로젝트를 시작하여 컨테이너에 관한 표준을 정하는 일들을 시작하게 됩니다. 그래서 Docker에서는 OCI 표준을 준수하는 containerd라는 Container Runtime을 만들고, Kubernetes에서는 OCI 표준을 준수하는 이미지들을 실행할 수 있는 Container Runtime Interface, 이하 CRI 스펙을 버전 1.5부터 제공함으로써 Docker 버전과 무관하게 OCI 표준을 준수하기만 하면 어떤 컨테이너 이미지도 Kubernetes에서 실행가능한 환경이 만들어지게 되었습니다.
요약하자면 컨테이너를 빌드하고, 실행하고 거기에 네트워크, 스토리지, CLI까지 제공해주는 Docker Engine이라는 패키지가 있었는데, 이게 하나의 패키지로 묶여있다보니 여러 불편함들이 생겨났고 이를 해소하기 위해 여러 사람들이 모여 OCI라는 Container Runtime 표준을 만들고 이 표준대로 각자 Container Runtime을 만들기 시작했는데 Docker에서 만든 Container Runtime이 바로 containerd (https://containerd.io/)라는 이야기입니다. 참고로 containerd의 d는 daemon의 d입니다.
한편, Red Hat, Intel, SUSE, Hyper, IBM 쪽에서도 OCI 표준에 따라 Kubernetes 전용 Container Runtime을 만들었는데 이것이 CRI-O (https://cri-o.io/)입니다. containerd와 CRI-O 이 두가지 Container Runtime이 현재 가장 널리 사용되고 있으며 containerd는 Docker Engine에 기본으로 탑재되어 있어서 지금도 Docker를 사용한다면 내부적으로 사용되는 Container Runtime은 containerd 를 사용하게 됩니다. 참고로 `docker build` 커맨드로 생성되는 이미지들 역시 OCI Image Spec을 준수하기 때문에 별도의 작업없이 containerd로 실행시킬 수 있습니다.
이렇게 Container Runtime이 Monolithic 아키텍처에서 분리되어 나오면서 Java 어플리케이션을 배포할 때 JDK보다 가벼운 JRE를 사용하는 것처럼 (물론 이 경우에는 보안과 같은 다른 이유도 있습니다만) 컨테이너를 실행할 때 무거운 Docker Engine이 아닌 containerd나 CRI-O와 같은 가벼운 Container Runtime을 사용하게 되면서 다음과 같은 장점도 나타나게 되었습니다.
쉽게 말해 containerd로의 전환을 통해 Pod은 더 빨리 시작되고, CPU와 메모리의 사용량은 더 줄었다는 이야기로, containerd로의 전환이 왜 일어나고 있는지를 잘 설명해주고 있습니다.
하지만, containerd를 사용하는 방법은 분명히 Docker에 비해 까다롭습니다. 개발자 입장에서는 예전과 같이 docker build만 실행하면 되기 때문에 크게 달라지는 것이 없다고는 하나, Kubernetes 클러스터를 운영하는 입장에서는 Docker로 한번에 모든 것을 제어할 수 있었던 예전과는 달리, 이제는 runc, containerd, ctr 등 낯선 라이브러리들과 익숙해져야 하는 부담이 생겼습니다.
물론 이 부담은 containerd로의 전환을 망설일만한 부담은 아닐 것입니다 게다가 이제 2021년 하반기 출시예정인 kubernetes 1.23과 함께 Container Runtime으로써의 Docker의 지원이 중단되는 것이 결정된만큼 새로운 흐름을 빨리 받아들이고 혜택을 누리는 것이 필요한 것 같습니다.
참고자료
- Kubernetes Documentation | Dockershim Deprecation FAQ
- Kubernetes Documentation | Don't Panic: Kubernetes and Docker
- Docker Blog | What is containerd?
- Docker Blog | Introducing runC: a lightweight universal container runtime
- CNCF | Introduction to containerd - Phil Estes, IBM & Derek McGowan, Docker
- CNCF | Lessons Learned Migrating Kubernetes from Docker to containerd Runtime - Ana Calin, Paybase
- Total
- Today
- Yesterday
- (InstantClient) 설치하기(HP-UX)
- directory copy 후 startup 에러
- 설치하기(HP-UX)
- CVE 취약점 점검
- 오라클 인스턴트클라이언트(InstantClient) 설치하기(HP-UX)
- 오라클 트러블 슈팅(성능 고도화 원리와 해법!)
- ORACLE 트러블 슈팅(성능 고도화 원리와 해법!)
- 5.4.0.1072
- [오라클 튜닝] sql 튜닝
- 커널
- 튜닝
- MSA
- 테라폼
- startup 에러
- 키알리
- 앤시블
- ubuntu
- 오라클
- 트리이스
- 오라클 홈디렉토리 copy 후 startup 에러
- 여러서버 컨트롤
- 코로나19
- [오라클 튜닝] instance 튜닝2
- Oracle
- pod 상태
- 우분투
- 버쳐박스
- K8s
- 쿠버네티스
- 스토리지 클레스
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |