카페인 중독자
Projects
microservice project
개발환경이슈
개요
example
week1
week2
cs-note
Abstract
쉬운코드
Web
개요
API
State
Transfer_Resource
dev-log
backjoon
Home
tech-review
AI
BE
docker
nginx
Communicate
Git
Contact
Copyright © 2024 |
Yankos
Home
>
tech-review
>
BE
> docker
Now Loading ...
docker
docker와 k8s
개요 백엔드 시스템을 gRPC 기반의 MSA로 구성을 완료하고, 각 코드 베이스가 분리되었으므로 이를 관리하기 위한 수단으로 docker-compose와 k8s 둘을 비교하고 선택하기 위한 인사이트를 공부한 포스트이다. Docker Docker란? 운영체제는 하드웨어를 직접적으로 다루는 커널과, 그 외의 부분으로 구성되어있다. 일반적인 소프트웨어는 이러한 운영체제를 통해 간접적으로 하드웨어를 동작하게 만들 수 있는데, 도커 엔진은 이러한 운영체제 그 중에서도 Linux 운영체제를 기반으로 동작한다. Linux 운영체제의 커널 외의 부분을 컨테이너 안에 같이 구성하고, 도커 엔진이 Linux 커널과 컨테이너를 연결해준다. 이렇듯 운영체제 전체를 가상화하는 VirtualBox 등과 다르게 커널 외의 부분만 컨테이너 안에 넣어 같은 컴퓨터 안의 독립된 격리환경을 만들기에 상대적으로 가볍다. 또한 Linux 운영체제를 기반으로 환경을 구성하기에 윈도우 등에서 도커를 사용할 때 wsl이나 Hyper-V 등이 설치되야 하는 것이다. Docker의 구성 Docker Image와 Container 도커는 기본적으로 이미지라는 읽기 전용 파일을 통해 컨테이너를 생성한다. 그렇다면 이 이미지라는 것이 정확히 어떤 역할을 수행해주는 것일까? 우리가 DockerFile 등의 Build를 정의하는 파일들을 보면 RUN, FROM, COPY, ADD 등 다양한 명령들로 어떤 파일을 복사해올지, 어떤 걸 설치할지 등을 정의할 수 있다. 이러한 명령이 하나 실행될 때마다 도커는 Layer라는 각 명령이 실행된 후의 파일 시스템의 스냅샷을 저장한다. 이렇게 명령어 별로 스냅샷인 Layer를 기록하기에 같은 명령어 구조를 공유하는 이미지가 많으면 이미지를 저장하는 용량을 줄일 수 있는 소소한 팁이 있다. 도커 이미지에서 RUN 명령에 pip를 엄청 뭉쳐서 실행하는 경우가 있는데, RUN을 각각 따로 실행해버리면 Layer 저장량이 많아지기에 한꺼번에 설치를 해버리는 것이다. 즉 중복된 Layer의 용량을 절약할 수 있는 점과, Layer가 많아지면 저장공간이 더 필요한 점을 각각 따져서 도커파일을 구성하는 것이 좋다. 즉 이런 구성으로 컨테이너 : 우리가 실제 도커를 실행하는 시스템 이 시작되는 시점의 스냅샷이 이미지의 역할이다. 그런데 이러한 Layer는 이미지에만 존재하지 않는다. 우리가 실제 격리된 환경을 구현하는 Container에서 Layer가 존재한다. 물론 차이는 존재한다. Docker Image의 Layer는 읽기전용으로 한번 빌드가 완료된 후 수정되지 않는다. 하지만 Container별로 존재하는 Layer는 writable Layer를 각각 갖는다. 스냅샷 이후의 수정사항을 새로운 Layer로 저장하는 것이다. 여기서 어떤 강점이 보일까? 사전에 파일을 복사하고, 다른 프로그램을 설치하고 빌드라는 과정의 결과인 스냅샷을 복사할 필요 없이 모든 컨테이너가 하나의 이미지로 공유가 가능한 점이다. Pytorch 등 무거운 라이브러리를 사용하면 이미지의 용량이 10GB가 넘어가기도 하는데, 이런 이미지를 사용하는 컨테이너를 n개 띄워도 하나의 이미지로 공유하여 사용이 가능한 것이다. 우리가 흔히 이미지를 틀러 컨테이너를 찍어낸다라는 비유가 있는데, 사전에 공유되는 스냅샷을 만드는 과정과 저장한 결과를 모두 컨테이너가 공유하여 자기 자신들의 수정사항을 반영하는 Writiable Layer로 가볍게 찍어낼 수 있기 때문에 이러한 비유가 있는 것이다. 이러한 기능을 구현하는 근간은 Linux의 UnionFS(Union File System)이다. 또한 도커는 만들어진 container를 기반으로 이미지를, 이미지를 컨테이너로, 컨테이너 재실행, 허브에 올리기 등 이미지와 컨테이너를 기반으로 다양한 명령을 가지는데 구조는 아래와 같다. 다만 도커 허브로 이미지를 가져올 때, 베이스 이미지의 코드를 수정하여 공격하는 기법도 존재하므로, 항상 베이스 이미지를 신뢰할 수 있는 사용자에 이미지를 사용하도록 하자. Docker-Compose 도커 컨테이너를 생성할 때, 볼륨, 네트워크, 호스트 자원할당, 환경변수 설정 등 다양한 설정을 하나의 컨테이너를 생성하고 실행할 때 사용할 수 있다. 이러한 컨테이너를 일일히 명령어로 적는 것은 힘들기 때문에 이를 한꺼번에 yaml 파일로 정리해서 실행할 수 있게 만든 것이 docker compose 이다. Docker-Compose 기능을 활용하여 얻을 수 있는 이점은 아래와 같다. 컨테이너 단위로 실행하는 것이 아닌, 여러 개의 컨테이너가 모인 Application 단위로 정의 및 관리가 가능하다. 서비스간 자동으로 네트워크를 연결해주고, 서비스를 실행할 때 depends_on 옵션으로 실행 순서(의존관계)의 정의도 가능하다. docker-compose.dev , docker-compose.prod 등으로 설정파일을 여러개를 만들어 실행 가능하다. 동일한 서비스의 컨테이너를 여러 개 띄울 수 있다. Compose의 설정 파일 정리 주 항목 명령어 이름 설명 services 컨테이너를 정의한다 networks 도커 네트워크를 정의한다 volumes 볼륨을 정의한다 secrets 각 비밀이 보장되어야하는 정보들이 기록된 파일을 이름을 붙여서 저장할 수 있게 한다 서비스 정의 항목 명령어 이름 설명 구체적인 옵션 CLI 대체 여부(docker run 기준) image 해당 서비스가 어떠한 이미지를 사용할지를 결정 이미지 이름:이미지 버전 CLI에 고정으로 사용 networks 해당 서비스가 어떠한 도커 네트워크에 속할지를 결정 x –net build 해당 서비스가 어떠한 Dockerfile을 빌드하여 사용할지를 결정 context : 해당 도커 빌드 시작 폴더 위치를 지정, dockerfile : 어떤 도커파일로 빌드할지를 결정 x volumes 스토리지 마운트를 결정 여러개 지정 가능 -v, –mount ports 호스트와 연결될 포트를 지정 호스트 포트번호:컨테이너 포트번호 -p environment 환경변수 설정 여러개 지정 가능 -e depends on 다른 서비스에 대한 의존 관계 설정(먼저 실행되야 하는 서비스) 여러개 지정 가능 없음 restart 컨테이너 종료 시 재시작 여부를 설정 1. no (재시작 x) 2.always (항상 재시작) 3. on-failure (프로세스가 0 외의 상태로 종료될 시 재시작) 4. unless-stopped (종료시 재시작 x, 그 외엔 재시작) 없음 command 커맨드 시작 시 기존 커맨드를 오버라이드 실행될 명령 CLI에 고정으로 사용 container_name 실행될 컨테이너의 이름을 지정 x –name dns DNS 서버를 명시적으로 지정 x –dns env_file 환경설정 정보를 기재한 파일을 로드 x 없음 entrypoint 컨테이너 시작 시 ENTRYPOINT 설정을 오버라이드 x –entrypoint links 네트워크 없이 컨테이너를 다른 컨테이너와 연결되어 사용하게 해줌, etc/hosts/ 에서 각 컨테이너의 ip를 확인 가능 여러개 지정 가능 x external_links 컴포즈 외부의 컨테이너와 연결되어 사용하게 해줌 여러개 지정 가능 –link extra_hosts 컨테이너 내의 /etc/hosts/에 외부 호스트 정보를 추가, DNS를 지정할 때, 특정 IP를 도메인으로 매핑할 떄 사용 “host.docker.internal:host-gateway” 를 지정해야 외부 DNS 서버를 통해 통신 가능하다, 여러개 지정 가능 –add-host secret 사전에 구성된 secret에 서비스가 접근하도록 한다, /run/secrets 디렉토리에서 secret 이름으로 접근 여러개 지정 가능 x logging 컨테이너의 로그가 어떻게 저장될지 옵션을 설정한다 1. json-file : 컨테이너 내부에서 자체적으로 저장 2. syslog : 각 서비스의 로그를 통합해서 관리하는 서버로 전송 3. none : 로그 저장 안함 x kubernates k8s란? 쿠버네티스란 오케스트레이션 도구의 일종으로, 오케스트레이션 도구는 여러 개의 호스트를 가지는 서버를 관리할 떄 쓰이는 도구이다. Docker compose와 같은 도구는 여러개의 컨테이너를 한꺼번에 띄울 수는 있지만, 만약 물리적인 서버가 여러대라면 이 작업을 반복해서 수행하고, 여러개의 물리적 서버를 통합 관리할 수는 없다. 이러한 상황에 도움을 주는 도구가 쿠버네티스와 같은 오케스트레이션 도구이다. k8s의 구성 1. 노드 마스터 노드 : 컨테이너를 직접 실행시키진 않지만 각 워커 노드를 관리하여 이상적인 상태(컨테이너 개수, 볼륨 개수)를 유지하도록 관리하는 주체 워커 노드 : 실제 컨테이너가 실행되는 주체, 도커 등의 엔진 프로그램이 필요하다. 2. 관리 단위 포드(pod) : 컨테이너 하나 혹은 여러 개로 이루어진 같은 로컬 네트워크 ip, 포트 번호, 생명주기를 공유하는 쿠버네티스의 최소 관리 단위이다. docker compose 등을 보면 컨테이너끼리 link 등을 통해 묶여있는데 실제로 어플리케이션에서는 하나의 컨테이너만 사용되는게 아닌, 여러개의 컨테이너가 모여 하나의 서비스를 구성한다. nginx, 로깅, metric 컨테이너 등은 실제 핵심 로직 컨테이너와 함께 움직인다. 이러한 밀접하게 연결된 컨테이너들을 하나의 관리 대상으로 만들어 줄 수 있는게 pod라는 단위이다. 서비스(service) : 같은 구성을 가지는 pod들을 여러개 모은 단위를 서비스라고 한다. 여러 개의 pod가 여러 개의 워커 노드(물리적 서버)에 존재하더라도 한꺼번에 관리해주는 단위이다. 서비스는 고정적인 ip 주소(cluster ip)를 부여받으며 같은 구성의 pod에 로드밸런서 역할을 수행해준다. 하지만 서비스가 분배하는 통신은 한 워커 노드 안으로 국한되며, 워커 노드간의 분배는 실제 로드밸런서 혹은 인그레스(ingress)가 담당한다. 이들은 마스터 노드도 워커 노드도 아닌 별도의 노드에서 동작한다. 디플로이먼트(deployment)와 레플리카세트(replicaset) : pod의 수를 관리하는 주체이다. 정의파일에 의해 정의된 pod의 수에 따라 실제 pod의 수를 줄이고 늘린다. 이런 ReplicaSet의 관리하는 동일한 구성의 pod를 Replica라고 부른다. Deployment는 Pod의 Deploy를 관리하는 요소로, Pod가 사용하는 이미지 등의 정보를 가지고 있다. ReplicaSet은 이러한 Deployment와 함께 사용된다. 결론 쿠버네티스같은 오케스트레이션 시스템은 기본적으로 서버가 여러개가 필요할 정도로 대규모 트래픽이 필요한 서비스에서 제 역할을 할 수 있는 시스템이다. 현재 우리의 백엔드 서버는 하나의 물리적 서버를 가지고 있으며, MSA로 나눠진 AI 컨테이너 등의 로깅 수집, 자동 재시작 등의 필요한 기능은 Docker Compose 내부의 설정만으로도 어느정도 대체가 가능하기에, 현재 시스템에는 k8s 채택을 미루기로 결정하였다. 참고자료 1. 도커 컴포즈 정리 블로그 글 2. 그림과 실습으로 배우는 도커와 쿠버네티스 3. 도커 secret에 대해 4. 도커 logging 옵션에 대하여 5. 도커 syslog 서버 구축
tech-review
· 2025-10-13
<
>
Touch background to close