MSP업체는 타 업체의 서비스를 클라우드에 올리고 운영하는 역활을 하게 된다.
DC 자체를 보유하고 있는회사
MSP 업체 : DC에 입점해서 클라우드 서비스 제공
일반 업체 : 클라우드 서비스 운용능력은 없고 그걸 중계하는 업체가 필요
MSP업체도 public cloud를 가지었거나 private cloud를 가진것으로 나뉜다.
---
현재는 서버를 여러대 두고 컨테이너 형태로 외부에 서비스를 제공해줄 계획이다. 이 서비스들을 클러스터로 묶는다.
여기에서 삼성만을 위한 네트워크를 worker1, worker2에 부여하고 싶다면 worker에 label을 붙여주어야 한다. 그러면 worker3에는 삼성 컨테이너가 배치되지 않을 것이다.
이 상태에서 LG까지 유치한다고하자. overlay 네트워크를 새로 구성하고 worker2, worker3에 새로운 라벨을 붙여준다.
문제는 이렇게 했을때 문제가 생길 수 있다. 같은 포트를 쓰기 때문인데... 외부와의 연결을 위해서는 연결된 업체별로 다른 포트를 부여해주어야 한다.
container 배포시 docker service create -d -p 8001:80 --constraint "node.labels.company==samsung"
외부에서 LB의 공인 ip로 들어오는 경우 HAProxy로 포트를 나누어서 보내주면 된다.
---
Quiz.
우리회사는 MSP 업체이다. 우리회사가 관리하는 업체중에 samsung 이 있다.
삼성의 홈페이지는 https://www.samsung.com/sec/ 이다.
위 홈페이지 내용을 curl https://www.samsung.com/sec/ > samsungv1.html
파일의 title 을 수정하여 samsungv2.html 로 수정하라.
우리회사에서 삼성 홈페이지는 worker1, worker2 에서 관리하고 있다.
우리는 삼성 페이지를 centos:7 의 /var/www/html/ 아래에 samsungv1.html 로 첫번째 이미지(211.183.3.100:5000/samsung:1.0)를 만들고 samsungv2.html 로 두번째 이미지(211.183.3.100:5000/samsung:2.0)를 생성하여 사설 저장소에 미리 업로드 해 둔다.
먼저 첫번째 이미지를 이용하여 worker1, worker2 에 배포하고 외부에서 접속 상태를 확인한다. 이후 업데이트를 통해 타이틀이 변경되었는지를 확인한다.
단, 삼성을 위한 오버레이 네트워크는 samsung 으로 만들고 주소 대역은 10.10.3.0/24 로 할당한다.
===
이제 우리가 해결해야하는 것은 인터페이스는 1개인데 공인 ip 2개를 넣는것이다.
haproxy.cfg 안에 F-B, F-B 각각 한세트씩 준비해준다.
MSP에서 어떻게 처리하는지 봐보자
ip 2개에 인터페이스 한개를 구성해버렸다.
Assign multiple IP addresses to single Network card in Linux (ostechnix.com)
Assign multiple IP addresses to single Network card in Linux
This comprehensive tutorial describes how to assign multiple IP addresses to single Network card in Linux operating systems.
ostechnix.com
대충 위와같이 IP는 두개인데 1번 네트워크는 인터넷으로 나갈 게이트웨이가 있는데 2번 네트워크는 그게 없다.
암튼 서로 다른 IP를 하나의 인터페이스에 부여를 할 수 있다.
HAProxy의 구성도 필요하다
Configuration | Configuration Section Basics | Frontend | HAProxy Enterprise 2.4r1
Configuration | Configuration Section Basics | Frontend | HAProxy Enterprise 2.4r1
HAProxy Enterprise 2.4r1 Documentation HAProxy Enterprise 2.4r1 Documentation Configuration Configuration Section Basics Frontend HAProxy Enterprise Documentation 2.4r1 Frontend When HAProxy Enterprise is used as a reverse proxy in front of your backend se
www.haproxy.com
참고자료를 확인해보자
프론트엔드 두개가 보인다.
foo.com은 80번 웹접속용인데
db.foo.com은 DB 접속용으로 사용된다.
위와같이 IP들을 할당해주면 HAProxy가 알아서 필요한 그룹으로 패킷을 던지게 된다.
다시한번 정리하자
외부접속자는 이렇게 들어온다. 얘가 들어온것은 10.5.1.101으로 접속했다.
LB에는 삼성과 LG의 IP가 분리되어 들어가 있다.
그리고 HAProxy에는 samsung을 처리하기 위한 물리서버가 적혀있다.
LB 뒤에는 worker 들이 있다.
worker들에는 각각 label을 붙여놓은 상태이다. 그래서 8001번 포트로 들어오면 그 내부에 컨테이너 80번 포트로 들어온다. 이렇게 할 수 있는 이유는 constraint를 통해서 samsung 라벨에만 서비스를 배포했기 때문이다.
이 상황에서 추가적으로 LG를 받아들였다고하자. 이것에 대해서는 8002번 포트를 뚫어서 LG label이 붙은 컨테이너에만 배포해주는 것이다.
나중에 컨테이너가 추가되더라도 LB에 추가적으로 등록해서 연결해주면된다.
그런데 사용하다보니 트래픽이 많아서 물리자원이 많이 소모된다면 이때는 요금을 받고 물리자원을 늘려주어야 한다.
이때 쓰는 것이 cgroup이다.
동일 서버위에 두개의 컨테이너가 배포되었다.
cgroup을 통하여 리소스에 대한 제한 작업이 없다면 한대의 컨테이너가 물리자원의 대부분을 사용하는 일이 발생할 수 있을 것이다.
우리는 각 컨테이너 별로 리소스에 대한 용량 산정을 할 수 있다.
1. RAM
docker run -d --memory="200m" --memory-swap=""
# --memory="1g"
일반적으로 swap(가상메모리)을 지정하지 않으면 200m의 2배가 자동 지정됨
2. CPU
--cpu-shares : 비중을 지정하는 방법. 아무런 설정이 없다면 컨테이너가 가지는 값은 1024
그러면 위와같은 비율로 나중에 가질 수 있다. 비율대로 운용되기 때문에 2:2:1:4 만큼 할당하여 사용할 수 있게 하겠다는 의미이다.
--cpuset-cpu : 물리 호스트에 CPU가 여러개 있다면 특정 CPU만을 사용하도록 설정할 수 있다.
예를 들어 위와같이 특정 CPU만 쓰라고 지정할 수 있다.
```
docker container run -d --name cpuset --cpuset-cpus=2 nginx
```
0번, 1번, 2번, 3번 -> 3번째 CPU를 점유하여 사용할 수 있음
--cpus
직관적으로 CPU의 개수를 정해준다.
docker container run -d --name cpustest --cpus=0.5 nginx
python
```
sudo apt-get install python3-pip
pip install docker
python3
```
```
>>> import docker
>>> client = docker.from_env()
>>> client.images.list()
```
```
>>> client.containers.list()
>>> client.containers.list(all)
```
Docker SDK for Python — Docker SDK for Python 5.0.3 documentation (docker-py.readthedocs.io)
Docker SDK for Python — Docker SDK for Python 5.0.3 documentation
Docker SDK for Python A Python library for the Docker Engine API. It lets you do anything the docker command does, but from within Python apps – run containers, manage containers, manage Swarms, etc. For more information about the Engine API, see its doc
docker-py.readthedocs.io
보다 자세한 자료는 위의 사이트에서 확인할 수 있다.
import docker
client = docker.from_env()
print(client.services.list())
client.containers.run('nginx',detach=True)
client.containers.logs()
client.containers.run('alpine','echo created')
도커 스웜을 통한 웹서비스 환경 구축(docker stack)
스택은 하나 이상의 서비스를 그룹으로 묶은 단위로, 애플리케이션 전체 구성을 정의한다. 서비스는 애플리케이션 이미지를 하나밖에 다루지 못하지만, 여러 서비스가 협조해 동작하는 형태로는 다양한 애플리케이션을 구성할 수 있는데 이를 스택이라고 한다.
docker stack은 docker compose와 다르다.
docker compose는 한 서버내에서 컨테이너를 정의하지만 docker stack은 서비스를 정의한다.
서비스 환경(도커 스웜)에서 웹서버와 DB 서버를 연결하여 외부에 서비스를 제공하고 싶다면?
1. DB 서비스를 생성 배포 -> replicas 5
2. WEB 서비스 배포 -> replicas 5 -> link : db -> export -p 8001:80 --network gildong
이 과정이 너무 복잡하다.
사전에 네트워크도 생성해 두어야 한다.
docker-compose -> 한대의 서버에서만 가능했다.
그래서 이 두가지 장점을 합치고 싶다.
docker swarm + docker-compose(yaml) => yaml 파일에 필요한 환경 구성 정보 등을 작성하고 이를 이용하여 서비스를 배포하는 형식
docker-compose는 생성하다가 문제가 발생하면 종료된다. 하지만 swarm의 경우 replicas 4를 지정하면 4개가 설치될때까지 계속해서 설치를 시도한다. 즉, 환경 모니터링을 지속적으로 진행하게된다. -> 매니페스트(manifest) 파일이라고 호칭.
쿠버네티스에서는 Manifest file 이라고 부른다.
쿠버네티스는 web과 DB를 한세트로 묶는다. 이 부분이 k8s와 docker swarm의 가장 큰 차이점이다.
swarm에서는 DB와 web의 갯수가 달라도 괜찮다.
갯수를 따로따로 조정해서 생성할수는 있지만 web이 타 서버의 DB를 건들이다보니 속도저하 문제가 생길 수 있다.
그럼 매번 서비스를 받으러 오는 사용자들은 바로 옆에 서비스가 없어서 다른곳에 가서 연결할 수 밖에 없다.
하지만 스웜은 web과 db를 따로 보지만
k8s는 pod라는 개념이 존재 -> 완벽한 서비스를 제공하기 위한 최소 단위로 "Pod"라는 개념을 사용한다.
Pod는 1개 이상의 컨테이너로 구성되며 만약 2개 이상의 컨테이너가 하나의 포드를 구성할 경우 두 컨테이너는 각각 서로 다른 호스트에 배치안된다. 무조건 붙어다닌다.
그래서 위와같이 다른 호스트에 배치되는 것을 막는다.
k8s에서 지정하는 replicas는 pod를 의미한다. 반면 swarm에서는 서비스를 의미한다(분리 가능하다)
스택이 다루는 애플리케이션 하나하나는 컴포즈와 같다. 스택은 결국 스웜에서 동작하는 스케일 인/아웃, 제약조건 부여가 가능한 컴포즈다. 스택은 docker stack 하위 명령으로 조작 한다.
스택을 사용해 배포된 서비스 그룹은 overlay 네트워크에 속한다. 만약 스택에서 overlay 네트워크를 설정하지 않으면 스택마다 서로 다른 overlay 네트워크를 생성하고 그안에 서비스 그룹이 속하게 되어 다른 overlay 네트워크에 속한 서비스간 연결이 불가능해 진다.
위와같이 추가 옵션들이 있는데 기존 네트워크에 추가해서 사용할 수 있다.
deploy 같은 경우 스택을 새로 배포 혹은 업데이트 함이라고 적혀있다. 그래서 이런기능이 k8s에도 있다.
(kubectl apply)
도커 스웜, HAproxy, Nginx를 활용한 웹서비스와 로드밸런싱
지금 구성하는 것은 worker01 ~ worker03까지 nginx를 배포하는 것이다. 그리고 manager에 HAproxy를 배포한다. 이게 안정적인 방식은 아니다. LB가 앞에 있어야 하기 때문이니 안좋은 구조이다.
HAproxy도 컨테이너로 제공된다.
haproxy와 컨테이너를 연결하기 위한 overlay 네트워크 생성한다. --driver=overlay로 하면 모든 클러스터환경에 똑같이 배치가 된다.
--attachable 이라고 하면 docker container run 명령어로 만든 컨테이너가 overlay 네트워크에 연결된다. 이 옵션이 없으면 docker container run 명령어로 --network 을 넣어도 web에 연결불가능하다. 하지만 이 방식으로 연결이 가능해진다.
2번은 아무 이름이나 지어서 yml 파일을 만들어낸 모습이다.
위와같이 있다고 하자.
version은 composer version 3과 같다.
services에는 nginx와 proxy가 있다.
배포하기 위해서는 다음 명령어를 넣어주자
```
docker stack deploy --compose-file=web.yml web
```
CADVisor을 써도 된다.
추가조건 :
nginx서비스에서 environment를 사용하지 말고 nginx의 80번 포트를 공개하라 (외부에 연결하는 옵션은 ports)
각 nginx는 cpu 0.5개 RAM은 64mb를 할당하라
단, 여유자원이 풍부할 경우에는 최대 1개, 128MB까지 제공하라
예를 들어 위와같이 작성했다고하자.
이떄 특이한게 linits와 reservations인데... limits는 최대치이고 reservations는 최소치이다.
---
Quiz.
각 nginx는 cpu 0.5개 RAM은 64mb를 할당하라 단, 여유자원이 풍부할 경우에는 최대 1개, 128MB까지 제공
version: '3'
services:
nginx:
image: nginx
deploy:
replicas: 3
placement:
constraints: [node.role != manager]
restart_policy:
condition: on-failure
max_attempts: 3
environment:
SERVICE_PORTS: 80
networks:
- web
proxy:
image: dockercloud/haproxy
depends_on:
- nginx
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- 80:80
networks:
- web
deploy:
mode: global
placement:
constraints: [node.role == manager]
networks:
web:
external: true
일단 간단하게 성능제한을 두지 않고 작성했다.
잘된다.
version: '3'
services:
nginx:
image: nginx
deploy:
replicas: 3
placement:
constraints: [node.role != manager]
restart_policy:
condition: on-failure
max_attempts: 3
resources:
limits:
cpus: '1'
memory: 128M
reservations:
cpus: '0.5'
memory: 64M
environment:
SERVICE_PORTS: 80
networks:
- web
proxy:
image: dockercloud/haproxy
depends_on:
- nginx
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- 80:80
networks:
- web
deploy:
mode: global
placement:
constraints: [node.role == manager]
networks:
web:
external: true
자원할당까지 성공했다.
위와같이 예쁘게 사원을 확인할 수도 있다.
GCP
aws -> ECS
gcp -> GKE(GCE)
라이브러리로 가자