sudo sed -i 's/kr.archive.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list
sudo apt update
우분투 레포지토리 변경 -> 다운로드 속도향상
CPU RAM NIC (VMnet10) manager(private-registry) 2 4 211.183.3.100 worker1 2 2 101 worker2 2 2 102 worker3 2 2 103
- 가상머신 생성 (manager, worker1 ~ worker3)
- 각 노드 IP 주소 및 호스트이름 변경하기
rapa@manager:~$ hostnamectl set-hostname 이름
rapa@manager:~$ sudo vi /etc/netplan/01-network-manager-all.yaml
rapa@manager:~$ sudo netplan apply
- 모든 노드의 /etc/hosts 에 아래의 추가한다.
211.183.3.100 manager 211.183.3.101 worker1 211.183.3.102 worker2 211.183.3.103 worekr3
- ping manager -c 3 ; ping worker1 -c 3 ; ping worker2 -c 3 ; ping worker3 -c 3
mkdir 0824; cd 0824 touch ctn.py
- sudo apt install -y pip
- pip install docker
- 파일 작성 (ctn.py)
rapa@manager:~/0824$ chmod +x ctn.py rapa@manager:~/0824$ cat ctn.py
3.1.
rapa@worker1:~/0824$ cat ctn.py #!/usr/bin/python3 import docker client = docker.from_env() print(client.containers.run("alpine", ["echo", "hello", "all"]))
3.2 nginx 컨테이너 생성
rapa@worker1:~/0824$ cat ctn1.py #!/usr/bin/python3 import docker client = docker.from_env() test = client.containers.run("nginx", detach=True) print(test.id)
3.3 for 문으로 컨테이너 리스트 출력
rapa@worker1:~/0824$ cat ctn2.py #!/usr/bin/python3 import docker client = docker.from_env() for ctn in client.containers.list(): print(ctn.id)
3.4 for 문으로 컨테이너 이미지 출력
rapa@worker1:~/0824$ cat ctn2.py #!/usr/bin/python3 import docker client = docker.from_env() for img in client.images.list(): print(img.id)
- 각 노드에서 /etc/hosts 파일을 열고 아래의 내용이 추가되어 있는지 여부를 확인하세요
211.183.3.100 manager 211.183.3.101 worker1 211.183.3.102 worker2 211.183.3.103 worker3
- 모든 노드에서 동작중인 컨테이너 중지 -> 삭제
- 모든 노드에서 시간을 확인하여 동일한 시간인지 여부 확인
- cluster 환경에서는 자원을 pool에 담아 하나의 자원(computing, network,storage)으로 활용될 수 있다.
기능적으로 두가지 기능이 호스트에 부여된다.- manager (master@k8s)
-> controller의 역할을 수행 -> manager는 worker의 기능을 포함한다. -> 일반적로 매니저는 컨테이너 배포에서 제외시키고 주로 컨트롤, 관리, 모니터링 역할에 주력해야 한다.
- worker (node@k8s)
-> 컨트롤로 부터 명령을 전달받고 이를 수행하는 역할
- manager, worker는 처음 클러스터 생성시 자동으로 node.role이 각 노드에 부여된다.
- 또는 추가적으로 label을 각 노드에 부여하여 컨테이너 배포시 활용할 수 있다.
- 쿠버네티스의 master는 worker의 기능을 수행하지 않는다.
- 고도화를 위해 다수의 컨테이너나 VM을 이용하여 개발을 진행 할 수 있다. 개발 속도를 향상 시키고 모듈 형식으로 기능을 구분하여 개발하므로 문제 발생시 해당 컨테이너나 코드, VM만 확인하면 되므로 관리가 용이하다.
- 또한 수평적 확장에도 유용하다.
- 각 기능 개발에서 언어를 지정하지 않으므로 필요한 언어를 선택하여 개발하면 된다.
- 각 기능별 데이터는 api 를 통해 주고 받으면 된다.
매니저 역할을 수행할 노드에서 토큰을 발행하고 워커는 해당 토큰을 이용하여 매니저에 조인한다
AVAILABILITY
-> Active 는 컨테이너 생성이 가능한 상태
drain
-> 동작중인 모든 컨테이너가 종료되고 새로운 컨테이너를 생성할 수도 없는 상태
pause
-> 새로운 컨테이너를 생성할 수는 없다. 하지만 , drain 과는 달리 기존 컨테이너가 종료되지는 않는다. 유지보수를 위해 해당 모드를 drain 또는 pause 로 변경한다.
docker swarm join-token worker | manager
0 처음 매니저가 토큰을 발행하면 manager 용, worker 용 토큰이 발행된다.
- 워커 외에 추가로 manager 를 두고 싶다면 별도의 노드에서는 manager 용 토큰으로 스웜 클러스터에 join 한다.
manager1(leader), manager2 , worker1, worker2
- 만약 manager 가 한개인 상태에서 해당 매니저가 다운된다면 전체 클러스터를 관리할 수 없으므로 실제 환경에서는 최소한 2대의 매니저를 두어야 한다.
- 상태 확인
rapa@manager:~/0824$ docker node inspect manager --format "{{.Spec.Role}}" manager rapa@manager:~/0824$ docker node inspect worker1 --format "{{.Spec.Role}}" worker rapa@manager:~/0824$ docker node inspect worker2 --format "{{.Spec.Role}}" worker
- manager로 상태 승격
rapa@manager:~/0824$ docker node promote worker1 Node worker1 promoted to a manager in the swarm.
rapa@manager:~/0824$ docker node inspect worker1 --format "{{.Spec.Role}}" manager
- worker로 상태 다운
rapa@manager:~/0824$ docker node demote worker1 Manager worker1 demoted in the swarm.
rapa@manager:~/0824$ docker node inspect worker1 --format "{{.Spec.Role}}" worker
- 도커 스웜 모드 의 노드가 매니저 노드에 접근하기 위한 IP 입력
rapa@manager:~$ docker swarm init --advertise-addr ens32
- 토큰 발행
rapa@manager:~$ docker swarm join-token worker
- 발행된 토큰으로 worker 연결
docker swarm join-token worker | manager
- 연결 확인
rapa@manager:~$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION qetnw53j04x0r93phk11qjrim * manager Ready Active Leader 20.10.17 q0ykem8jc4bmmg1bv2akm6xs5 worker1 Ready Active 20.10.17 mp287ff2flki2r0tr0siuwxad worker2 Ready Active 20.10.17 oqfoncccjqshle8jj67omuk9f worker3 Ready Active 20.10.17
- 워커에서 docker swarm leave, manager에서는 docker node rm worker1
- leave 하게 되면 status가 Down 상태가 된다
rapa@worker1:~$ docker swarm leave rapa@worker2:~$ docker swarm leave rapa@worker3:~$ docker swarm leave
- rm 하게 되면 연결이 해제 된다
rapa@manager:~/0824$ docker node rm manager
- compose, swarm 에서 서비스(다수개의 컨테이너 가능) 단위로 배포
rapa@manager:~/0824$ docker service create --name web --constraint node.role==worker --replicas 3 -p 80:80 nginx
- docker service ls - 클러스터에 동작중인 서비스의 목록확인, 동작컨테인개수/요청컨테이너개수
- docker service ps web - 각 컨테이너가 어떤 노드에서 동작중인가?
- Service 목록을 확인
rapa@manager:~/0824$ docker service ls ID NAME MODE REPLICAS IMAGE PORTS p9sh2zh06n2z web replicated 3/3 nginx:latest *:80->80/tcp
- 생성된 Service가 정상적으로 가동하는지 확인
rapa@manager:~/0824$ docker service ps web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS hgkvwgdlwi10 web.1 nginx:latest worker1 Running Running 13 minutes ago k9reh2dbx874 web.2 nginx:latest worker2 Running Running 13 minutes ago gg674blo0ep3 web.3 nginx:latest worker3 Running Running 13 minutes ago
- 생성한 서비스의 레플리카 수를 1개로 스케일 아웃
rapa@manager:~/0824$ docker service scale web=1
레플리카 수를 1개로 조정해도 100,101,102,103 전부 nginx에 접속이 가능하다 그 이유는 overlay 때문이다.
- 생성한 서비스의 레플리카 수를 4개로 스케일 아웃
rapa@manager:~/0824$ docker service scale web=4 ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS hgkvwgdlwi10 web.1 nginx:latest worker1 Running Running 24 minutes ago ttfqgrsrewxl web.2 nginx:latest worker3 Running Running 53 seconds ago m4gezuumdto7 web.3 nginx:latest worker3 Running Running 53 seconds ago sxdgs3x8fgfl web.4 nginx:latest worker2 Running Running 44 seconds ago
- 각 worker에서 docker container ls (manager에서는 확인 불가)
rapa@worker1:~$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b7c3b2f15c90 b692a91e4e15 "/docker-entrypoint.…" 25 minutes ago Up 25 minutes 80/tcp web.1.hgkvwgdlwi109it9aok10570m
rapa@worker2:~$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7c471132510a nginx:latest "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp web.4.sxdgs3x8fgflmagu0phwl5x39
rapa@worker3:~$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ff42e8c3b8c1 nginx:latest "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp web.3.m4gezuumdto78un39bzno11r5 684dc8689e14 nginx:latest "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp web.2.ttfqgrsrewxlpohfqm1bshnps
- 이미지가 다운되지 않은 상태에서 생성하려고 할때
- 이미지 다운로드를 위한 인증정보가 없을 경우
-> 자원 사용의 불균형이 발생할 수 있다. 즉, 한대의 노드에서 여러 컨테이너가 동작하고 몇 노드에서는 컨테이너 생성이 되지 않는 문제
- manager 에서 로그인을 하고 config.json 정보를 일일이 각 노드의 config.json 에 붙여넣기한다.
- manager 에서 로그인을 하고 config.json 정보를 docker serivce create 시 넘겨준다.
--with-registry-auth
- 내가 가지고 있는 명령전달을 보낼 때 인증정보도 같이 보내겠다.
rapa@worker1:~$ cat ~/.docker/config.json { "auths": { "https://index.docker.io/v1/": { "auth": "토큰" } }
- 동작중인 모든 서비스 컨테이너 삭제
rapa@manager:~/0824$ docker service rm web
rapa@manager:~/0824$ docker service create --name web --constraint node.role!=manager --replicas 3 -p 80:80 nginx
- --replicas 3 - 항상 최솟값을 3으로 유지해야한다.
- swarm은 2가지 모드가 있다.
도커 스웜(스웜 클래식) VS 스웜 모드도커 스웜 클래식
- zookeeper, etcd와 같은 별도의 분산 코디네이터를 두고 이를 통해 노드, 컨테이너들의 정보를 관리한다.
- 또한 컨테이너의 정보를 확인하기 위하여 각 노드에 agent를 두고 이를 통해 통신하게 된다.
스웜 모드
- manager 자체에 분산 코디네이터가 내장되어 있어 추가 설치 패키지등이 없다.
- 일반적으로 이야기하는 스웜 클러스터는 스웜 모드를 지칭한다.
롤링 업데이트
- 동작중인 컨테이너를 새로운 컨테이너로 업데이트 할 수 있다.
- 컨테이너 내부의 내용을 바꾸는 것이 아니라, 기존 컨테이너는 중지되고 새로운 컨테이너로 대체되는 것이다.
- 홀드 스탠바이
rapa@manager:~/0824$ mkdir blue green
rapa@manager:~/0824$ touch blue/Dockerfile green/Dockerfile
rapa@manager:~/0824$ touch blue/index.html green/index.html
rapa@manager:~/0824$ echo "<h2>BLUE yang PAGE</h2>" > blue/index.html rapa@manager:~/0824$ echo "<h2>GREEN yang PAGE</h2>" > green/index.html
rapa@manager:~/0824$ cat blue/Dockerfile > green/Dockerfile
rapa@manager:~/0824$ cat blue/Dockerfile FROM httpd ADD index.html /usr/local/apache2/htdocs/index.html CMD httpd -D FOREGROUND
rapa@manager:~/0824$ cat green/Dockerfile FROM httpd ADD index.html /usr/local/apache2/htdocs/index.html CMD httpd -D FOREGROUND
도커 허브 저장소에 저장
- blue 이미지
rapa@manager:~/0824/blue$ docker build -t blue .
rapa@manager:~/0824/blue$ docker image tag blue gnon5367/myweb:blue
rapa@manager:~/0824/blue$ docker push gnon5367/myweb:blue
- green 이미지
위와 동일
- 도커 허브에 저장된 blue 이미지를 사용해 서비스 배포
rapa@manager:~/0824$ docker service create --name web --replicas 6 --update-delay 3s --update-parallelism 3 --constraint node.role==worker -p 80:80 gnon5367/myweb:blue
- task(작업) 에 동시에 3개의 컨테이너를 업데이트하고 3초를 쉬고 난뒤 다음 테스트를 진행한다.
rapa@manager:~/0824$ docker service update --image gnon5367/myweb:green web
- 업데이트를 하게 되면 기존에 동작하고 있던 컨테이너는 down 상태가 되고 새로운 이미지로 생성한 컨테이너 외부에 서비스를 제공하게 된다.
- 기존 컨테이너의 내용을 업데이트 하는
rapa@manager:~/0824$ docker service rollback web
- compose 파일이나 Dockerfile 에서 변수 지정(-e MYSQL_DATABASE, -e MYSQL_ROOT_PASSWORD) 을 한 적이 있다.
- 해당 내용은 민감한 정보를 포함하고 있음에도 이미지에서 해당 내용을 직접 볼 수 있다는 단점이 있다.
- 모든 사용자별로 별도의 환경변수, index.html, DB 패스워드를 다르게 하고싶다면 그때마다 별도의이미지를 만들어야 하는 불편함이 있다.
- 이 경우 사용자별로 별도의 config, secret 을 사용하면 추가 이미지를 생성하는 작업 없이 패스워드나 변수 전달이 가능해 진다.
변수, 파일 -> config password, key -> secret
- Docker Secret을 사용하면 아래와 같은 민감한 데이터를 안전하게 관리할 수 있다.
echo "test123" | docker secret create mysql_password - v8mg82wh48r6ckznyw2zre6ab
- Secret를 이용해 service 배포하기
- Docker Secret은 메모리에 저장되어 있는 정보이기 때문에 컨테이너 내에서 특정 경로에 마운트가 불가능하고 /run/secrets 디렉토리에서 참조할 수 있다.
rapa@manager:~/0824$ docker service create --name sql --secret source=mysql_password,target=mysql_root_password --secret source=mysql_password,target=mysql_password -e MYSQL_ROOT_PASSWORD_FILE="/run/secrets/mysql_root_password" -e MYSQL_PASSWORD_FILE="/run/secrets/mysql_password" -e MYSQL_DATABASE="testdb" mysql:5.7
- 생성된 Docker Secret을 확인
rapa@manager:~/0824$ docker secret ls
- service 확인
rapa@manager:~/0824$ docker service ls
rapa@manager:~/0824$ docker container ls --all CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6e0e39cb90b1 mysql:5.7 "docker-entrypoint.s…" 47 minutes ago Up 47 minutes 3306/tcp, 33060/tcp sql.1.1b402fhwb65wxu7jurjt1e0pv
rapa@manager:~/0824$ docker container exec 6e0e39cb90b1 ls /run/secrets/ mysql_password mysql_root_password
rapa@manager:~/0824$ docker container exec 6e0e39cb90b1 cat /run/secrets/mysql_password test123
rapa@manager:~/0824$ docker container exec 6e0e39cb90b1 cat /run/secrets/mysql_root_password test123
rapa@manager:~/0824$ curl -L http://www.naver.com > index.html
rapa@manager:~/0824$ docker config create webconfig index.html
rapa@manager:~/0824$ echo "hello world" > index.html
rapa@manager:~/0824$ docker config create webcfg index.html
rapa@manager:~/0824$ docker config inspect webcfg [ { "ID": "nny59ujcvm76wpnjf2859pbm7", "Version": { "Index": 2526 }, "CreatedAt": "2022-08-24T08:06:40.829867581Z", "UpdatedAt": "2022-08-24T08:06:40.829867581Z", "Spec": { "Name": "webcfg", "Labels": {}, "Data": "aGVsbG8gd29ybGQK" } } ]
rapa@manager:~/0824$ docker service create --replicas 1 --constraint node.role==manager --name webcfg -p 8888:80 --config source=webcfg,target=/usr/share/nginx/html/index.html nginx
- http://211.183.3.100:8888/에 접속해 보면 "hello world" 가 보인다
- docker_gwbridge brdge local
-> 각 호스트에서만 영향을 미친다. -> 스웜에서 오버레이 네트워크 사용. -> 외부로 나가는 통신 및 오버레이 네트워크 트래픽의 종단 점 역할
- ingress overlay swarm
-> 클러스터 전체에 하나의 네트워크로 동작한다. -> 로드밸런싱과 라우팅 메시에 사용되며 서비스 내의 컨테이너에 대한 접근을 라운드 로빈 방식으로 분산하는 로드밸런싱을 담당한다.
- 스웜모드로 생선된 모든 서비스의 컨테이너가 외부로 노출되기 위해서는 무조건 ingress 네트워크를 사용해야 하는 것은 아니다.
- docker run -p를 사용해 외부에 노출했던 것처럼 특정 포트를 사용하도록 설정 할 수도 있다.
- 다음은 ingress 를 사용하지 않고 호스트의 8888 포트를 직접 컨테이너의 80 포트에 연결하는 방식이다.
- 아래처럼 인그레스를 사용하지 않고도 외부랑 통신할 수 있다.
rapa@manager:~/0824$ docker service create --publish mode=host,target=80,published=8080,protocol=tcp --name web nginx
- 네트워크 생성
rapa@manager:~/0824$ docker network create --subnet 192.168.123.0/24 -d overlay myoverlay
- 네트워크 목록 확인
rapa@manager:~/0824$ docker network ls NETWORK ID NAME DRIVER SCOPE 06tivcjjndjp myoverlay overlay swarm
- overlay nerwork를 이용한 service 생성
rapa@manager:~/0824$ docker service create --name ovctn --network myoverlay --replicas 1 --constraint node.role==manager ubuntu:18.04