230612 MON
학습 주제 - Airflow 환경 구축을 위한 Docker와 K8S 실습 (1)
Airflow를 운영할 때 겪는 어려움과 해결책 - Docker를 왜 사용하지?
관리해야 하는 DAG의 수가 100개를 넘어간다면?
데이터 품질이나 데이터 리니지 이슈 이외에도 다양한 이슈들이 발생한다.
1. 라이브러리 충돌
- Dag에 따라 실행에 필요한 라이브러리/모듈이 달라지기 시작 (ex. Python version ...) -> Dag 혹은 Task 별로 별도의 독립공간을 만들어주는 것이 필요하다.
2. Worker의 부족
- Scale up, Scale out, K8s(공용 서버 클러스터)
3. Worker 서버들의 관리와 활용도 이슈 (낮은 Server Utilization 이슈)
- K8s와 같은 컨테이너 기술의 도입으로 해결 가능
🧩 해결책
1. Dag 혹은 Task 코드를 Docker Image로 만들고 이를 독립된 공간(Docker Container) 안에서 실행하기
2. Airflow Worker를 K8s에서 필요한 대로 동적으로 할당하여 사용하기
=> Airflow에서 이를 해결하는 방법은 3가지가 있다.
- Airflow Operator로 KubernetesPodOperator 사용 : 특정 task를 Docker Image로 만들어 K8s에서 실행
- Airflow Operator로 DockerOperator 사용 : 특정 task를 Docker Image로 만들어 Docker Container 위에서 실행
- Airflow Executor 사용(KubernetesExecutor, CeleryKubernetesExecutor, LocalKubernetesExecutor, Sequential Executor 등등..) : task들을 관리하고 실행하는 역할 수행
Docker란?
내가 만든 프로그램이 다른 사람의 컴퓨터에서 안 돌아간다! => 내 컴퓨터 환경을 그대로 패키징 해서 다른 사람에게 줄 수 있다면?
=> 소프트웨어를 일관되게 빌드하고 실행하고 배포!
- Docker Image : 독립적으로 완전하게 만들어진 패키지
- Docker Container : Docker Image를 독립된 환경에서 실행한 것
Docker 공식 문서 ↓↓↓
https://docs.docker.com/get-started/overview/
Docker overview
docs.docker.com
Virtual Machines vs Docker Containers
Virtual Machines | Docker Containers | |
특징 | - 하드웨어를 추상화하여 하나의 컴퓨터 위에 가상 컴퓨터를 올리는 것 - 보통 하나의 컴퓨터 위에 다수의 VM을 실행하는 것이 일반적 - VM 생성/관리 소프트웨어 : VMWare, VirtualBox, Hyper-v ... |
- 소프트웨어를 실행하기 위한 독립적이고 분리된 공간 - 자체 파일 시스템(Volume)을 가지고 있음 |
장점 | - 소프트웨어를 실행하기 위한 독립적이고 분리된 공간을 제공 - 다수의 소프트웨어를 각 VM단에서 독립적으로 실행 가능 |
- 다수의 소프트웨어를 각 컨테이너 단에서 독립적으로 실행 가능 - 자원 소비 적음(light weight) - 호스트 OS를 사용하기 때문에 별도의 OS 비용 없음 => 속도 빠름 |
단점 | - 각 VM은 가상 하드웨어 위에서 돌기 때문에 자신만의 OS를 필요로함 => 유료 OS라면 라이센스 비용 필요, 속도 느림 - 자원을 많이 사용함(VM들끼리 자원을 나눠 사용) |
- 많은 수의 Docker Container를 관리하기 쉽지 않음 - Host OS를 사용하기에 Cross-platform compatibility를 항상 지원하지 않음 - GUI 소프트웨어 개발에 적합하지 않음 |
Docker 프로그램 개발 프로세스
먼저 대상 소프트웨어를 선택하고, Dockerfile을 Docker Image로 빌드하고(Dockerization), Image를 Container 안에서 실행!
- Dockerfile : 선택한 소프트웨어를 이미지로 바꾸기 위해 Docker에게 주는 명령들을 포함한 텍스트파일 (도커 파일의 확장자는 특정하게 정해져 있지 않으며, 파일 이름으로 "Dockerfile"을 사용하는 것이 일반적인 관례이다.)
- Docker Image : Dockerfile을 기준으로 만들어지며, 소프트웨어를 실행하기 위해 필요한 모든 것을 포함
- Docker Image의 구성 요소
- 기본 OS (리눅스라면 우분투, 데비안 등등)와 같은 소프트웨어의 실행 환경
- 소프트웨어 자체 (코드)
- 소프트웨어가 필요로 하는 라이브러리
- 파일 시스템 스냅샷: 스택화된 형태로 구현
- 환경 설정 변수: 빌드할 때 변수와 실행 때 변수 두 가지가 존재
- 메타 데이터: 이미지 자체에 대한 정보 (버전, 작성자, 설명 등등)
- Docker Image는 Docker Registry에 등록이 가능하다. 대표적인 Docker Registry에는 Docker Hub(Docker가 제공하는 서비스)가 있다.(GitHub 같은 느낌!)
- Docker Hub
- Teams & Organizations
- Public과 Private Repo 제공
- Official Images
- Github과 연동을 통한 Automated Build 제공

간단한 Docker 예제
실습 1 - node.js로 만든 간단한 Hello World 프로그램
app.js
console.log("Hello Docker!");
Dockerfile
FROM node:alpine # OS 종류
COPY ./app # 코드 복사
WORKDIR /app # Working directory 지정
CMD node app.js # 실행하는 명령
* Dockerfile 기타 키워드
- ARG : Docker Image를 만들 때 사용되는 변수 지정. 최종 이미지에 저장되지 않음
- ENV : 컨테이너가 실행될 때 사용되는 환경변수. 최종 이미지에 저장됨
- USER : 컨테이너를 실행할 때 사용할 유저 ID
- EXPOSE : 서비스 사용 포트 번호
- RUN : 빌드 시 실행되어야 하는 명령들이 지정됨 (ex. RUN apt-get update && apt-get install -y curl)
* CMD vs ENTRYPOINT
- 최대한 CMD만 사용
- ENTRYPOINT가 있으면 CMD값이 파라미터로 실행됨
Docker Image 생성
$ docker build --platform linux/amd64 -t hello-world-docker .
# 빌드한 Docker image의 태그를 hello-world-docker로 지정해주었다.
# 맨 뒤에 . 은 현재 디렉토리를 의미한다. 현재 디렉토리에 Dockerfile과 app.js가 존재하고 있다.
"""
docker build를 실행하면 Dockerfile에서 RUN 명령이 실행됨.
만일 Apple M1 chip 기반 맥에서 빌드하는 경우 그 이미지는 ARM 기반 아키텍처로 만들어지기 때문에
일반 리눅스에서 안 돌아감.
그래서 --platform 옵션을 사용해서 linux/amd64로 지정.
나는 Intel 기반 Mac이지만 그냥 명시해줬음
"""
Docker Container로 실행, RUN
$ docker run hello-world-docker
"""
만일 이 이미지를 내 로컬 pc가 아닌 다른 컴퓨터에서 실행하고자 한다면?
Docker Registry(예를 들면 Docker Hub)에 먼저 등록! - Github이라 생각하자
"""
Docker Hub에 upload
# 먼저 Docker Hub에서 이름이 hello-world-docker인 repo를 하나 생성.
$ docker image ls
$ docker tag hello-world-docker:latest seungeonkim/hello-world-docker:latest
$ docker image ls
$ docker login --username=seungeonkim
# 이때 패스워드를 별도 프롬프트에서 물어봄
# 본인 pc의 docker desktop에 같은 계정으로 이미 로그인이 되어있다면, 이 과정을 건너뛰고 바로 push해도 됨.
$ docker push seungeonkim/hello-world-docker
# Docker Hub에서 이미지가 잘 업로드 되었는지 확인!
다른 컴퓨터에서 Docker Hub로부터 Image를 받아 실행해 보기
* 아래 링크에 접속하면 무료 리눅스 서버를 4시간 동안 이용 가능하다!
https://labs.play-with-docker.com/
Play with Docker
Play with Docker A simple, interactive and fun playground to learn Docker Login
labs.play-with-docker.com
# 위 링크에 접속하여 새로운 instance를 하나 생성한 후 다음 명령어 진행.
$ docker version
$ docker pull seungeonkim/hello-world-docker
$ docker image ls
$ docker run seungeonkim/hello-world-docker
# 로컬에 이미지가 없더라도 Docker Hub에서 pull을 알아서 수행함! (신기)
* docker run vs docker exec
- run은 container를 새로 실행하는 것
- exec는 이미 실행된 container에 작업을 하는 것
실습 2 - Docker위에서 Ubuntu를 컨테이너로 실행해 보기
Ubuntu: 데미안에 기반해서 만들어진 가장 많이 사용되는 리눅스 배포판
# ubuntu는 docker 공식 이미지이기 때문에 이미지를 pull하지 않아도 docker hub에서 가져옴.
$ docker run ubuntu
$ docker ps
$ docker ps -a
$ docker run -it ubuntu
# ubuntu 서버 내부에서.
# ubuntu에서 리눅스 운영 체제용 명령줄 텍스트 편집기인 nano 설치하고 삭제해보기
$ nano
$ apt list
$ apt install nano
$ apt update
$ apt install nano
$ nano
$ apt remove nano
실습 3 - MySQL 8.0 실행해 보기
# Docker Engine 실행 후 터미널 켜기
# MySQL docker image 다운로드
$ docker pull mysql/mysql-server:8.0
# Docker container 실행
$ docker run --name=mysql_container mysql/mysql-server:8.0
# MySQL root 계정의 패스워드 찾기
$ docker logs mysql_container 2>&1 | grep GENERATED
# MySQL shell 실행
$ docker exec -it mysql_container mysql -uroot -p
- docker run --name : 기억하기 쉬운 이름을 docker ps로 찾은 container ID 대신 사용 가능
- docker logs : container 쪽에서 생성된 stdout, stderr단의 로그를 읽어옴, --follow 옵션을 사용하면 로그가 계속적으로 스트리밍 됨
TMI
도커 댕 어렵다...........................
'[프로그래머스] 데이터엔지니어링 데브코스 1기 > TIL (Today I Learned)' 카테고리의 다른 글
TIL_day48 Docker Volume (0) | 2023.06.15 |
---|---|
TIL_day47 CI/CD, Docker와 Github Actions (1) | 2023.06.13 |
TIL_day41 Data Pipeline, ETL 코드 (0) | 2023.06.06 |
TIL_day36 공공데이터포탈의 OpenAPI 사용방법 (0) | 2023.06.04 |
TIL_day26 AWS EC2, Elastic Beanstalk (0) | 2023.05.15 |