데이터엔지니어링
[9주차] Docker & K8s (1)
heecup
2024. 5. 27. 11:35
🙂 Airflow 운영상의 어려움
✔ 관리해야하는 DAG의 수가 100개를 넘어간다면?
🍦 라이브러리 충돌
- DAG에 따라 실행에 필요한 라이브러리/모듈 상이
- 이로 인해 DAG 혹은 Task 별로 별도의 독립공간 확보
- Docker to the rescue
- Dag 혹은 Task 코드를 Docker Image로 만들고 이를 Docker Container 안에서 실행
🍦 Worker의 부족
- Scale Up
- Scale Out - 클라우드 사용
- K8s와 같은 컨테이너 기술 사용
🍦 낮은 Server Utilization 이슈
- Airflow 전용 HW를 지정했는데 서버가 항상 바쁜 게 아니라면?
- 서비스별로 전용 서버를 할당하는 것은 여러가지로 이슈를 만듦
- K8s와 같은 컨테이너 기술의 도입으로 해결 가능
🍦 해결책
- Task나 DAG 코드를 Docker Image로 만들어서 Docker Container 형태로 실행
- 라이브러리/모듈 충돌 방지
- 개발 환경과 프로덕션 환경을 동일하게 유지
- Airflow Worker를 K8s에서 필요한 대로 동적으로 할당하여 사용
- 전용 서버를 Airflow에 할당하지 않고 Container Orchestration 서비스를 통해 할당해서 사용하고 리턴
- Airflow에서 이를 해결하는 방법
- Airflow Operator로 KubernetesPodOperator를 사용: 특정 태스크를 Docker Image로 만들어 K8s에서 실행.
- Airflow Operator로 DockerOperator를 사용: 특정 태스크를 Docker Image로 만들어 Docker Container에서 실행.
- Airflow Executor로 아래를 사용
- KubernetesExecutor: 모든 DAG 코드가 Docker Image로 빌드되어 K8s에서 실행.
- CeleryKubernetesExecutor: CeleryExecutor와 KubernetesExecutor를 동시에 사용.
- LocalKubernetesExecutor: LocalExecutor와 KubernetesExecutor를 동시에 사용
🍦 Airflow Executor
- Task를 관리하고 실행하는 역할
- 다양한 수의 Executor 타입 존재
- Sequential: default. Sqlite와 같은 싱글스레드 DB에서만 사용
- Local: Task를 Airflow 마스터 노드 안에서 실행
- Celery: 다수의 Worker 노드가 있는 경우 사용. Celery 큐를 사용해 Task를 Worker 노드로 분산하여 실행
- Kubernetes: K8s 클러스터를 사용하여 Task를 독립된 환경에서 사용
- Local Kubernetes & Celery Kubernetes 도 존재
🙂 Docker
✔ Docker
소프트웨어를 일관되게 빌드, 실행 및 배포
Docker Image: 독립적으로 완전하게 만들어진 패키지
Docker Container: Docker Image를 독립된 환경에서 실행한 것


✔ Virtual Machines vs. Docker Containers
🍦 Virtual Machine (VM)
- AWS의 EC2가 대표적인 VM
- 하드웨어를 추상화하여 한 컴퓨터 위에 가상 컴퓨터를 올리는 것
- 보통 하나의 컴퓨터 위에 다수의 VM을 실행하는 것이 일반적
장점
- SW를 실행하기 위해 독립적으로 분리된 공간 제공
- 다수의 SW를 각 VM단에서 독립적으로 실행 가능
단점
- 각 VM은 자신만의 OS를 필요로 함 - 유로 OS라면 비용 필요
- 자원을 많이 사용
🍦 Docker Containers
- 소프트웨어를 실행하기 위한 독립적이고 분리된 공간
- 자체 파일 시스템(Volume)을 갖고 있음

장점
- SW를 실행하기 위한 독립적이고 분리된 공간 제공: 다수의 SW를 각 컨테이너단에서 독립적 실행 가능
- 자원 소비가 적음: 몇 십 개에서 몇 백 개의 container를 실행
- 호스트 OS를 사용: 비용 X. 빠른 실행
단점
- 많은 수의 Docker Container를 관리하는 것이 어려움 -> Container Orchestration (K8s)
- Host OS를 사용하기에 Cross-platform compatibility를 항상 지원하지 않음
- GUI 소프트웨어 개발 X

✔ Docker 프로그램 개발 프로세스
- 대상 SW 선택
- 다수의 컴포넌트로 구성되는 SW라면 각각이 Docker Image로 만들어져야할 수도 있음
- Docker Image로 빌드: Dockerization
- Dockerfile이란 텍스트 파일로 세부 정보를 기술 - 해당 SW를 Image로 바꾸기 위한 Docker 명령 포함
- FROM: 기본이 되는 SW가 무엇이냐
- RUN: 어떤 SW를 설치할 것이냐
- ENTRYPOINT / CMD: 이 프로그램을 어떻게 실행할 것이냐
- Docker Image: 하나의 Container 안에서 실행
- 구성 요소: 다수의 파일로 구성
- 기본 OS와 같은 SW 실행환경
- SW 자체 (코드)
- SW가 필요로 하는 라이브러리
- 파일 시스템 스냅샷
- 환경 설정 변수: env + arg
- 메타 데이터: 이미지 자체에 대한 정보 (버전, 작성자, 설명 등)
- Dockerfile을 기준으로 만들어지면 SW를 실행하기 위해 필요한 모든 것을 포함
- 구성 요소: 다수의 파일로 구성
- Dockerfile이란 텍스트 파일로 세부 정보를 기술 - 해당 SW를 Image로 바꾸기 위한 Docker 명령 포함

- Docker Image의 실행
- Container를 통해 Docker Image 안의 SW를 실행
- Image를 Container 안에서 실행
- docker run ... : Container를 새로 실행
- docker exec ... : 이미 실행된 Container에 작업 - Container ID가 필요
- Docker Image의 등록: Docker Hub
- Docker Registry는 DockerImage의 보관소
- On-prem / Cloud
- Docker Hub가 가장 유명
- Docker Registry는 DockerImage의 보관소


✔ Dockerfile 생성
- Docker에게 SW 설치 명령 기술
- 베이스 이미지 기술 FROM
- 코드 복사
- 코드 실행
FROM node:alpine
COPY ./app
WORKDIR /app
CMD node app.js
🍦 CMD vs. ENTRYPOINT
- CONTAINER가 시작할 때 실행되어야 하는 명령어를 지정하는데 사용 (docker run)
- 둘 다 한 DockerFile에서 여러번 실행되면 마지막 것만 사용
- CMD나 ENTRYPOINT 중 하나만 지정되면 그게 container가 실행될 때 실행
- 둘이 같이 사용되면 ENTRYPOINT가 기본 명령이 되고 CMD가 인자를 제공
- 최대한 CMD만 사용
✔ Docker 명령
docker version
docker build -t
docker push
docker tag
docker pull
docker run