만약 관리해야 하는 DAG의 수가 100개를 넘어간다면 어떨까. 아마 다음과 같은 이슈들이 발생할 것이다.
- 데이터 품질 및 데이터 리니지 이슈.
- 라이브러리 충돌.
- Worker의 부족.
- Worker 서버들의 관리와 활용도 이슈.
라이브러리 충돌
Worker의 부족
낮은 Server Utilization 이슈
해결책.
- 태스크나 대그 코드를 Docker Image로 만들어서 Docker Container 형태로 실행.
- Airflow Worker를 K8s에서 필요한 대로 동적으로 할당하여 사용.
Airflow Executor란?
- 태스크들을 관리하고 실행하는 역할 수행.
- 병렬 혹은 직렬 실행, 어느 worker에서 실행할 지 등등.
- 다양한 Executor 타입이 존재함.
-
- Sequential Executor : 디폴트로 설치되면 sqlite와 같은 싱글 스레드 디비에서만 사용 가능.
- Local Executor : 태스크들을 airflow 마스터 노드 안에서 실행.
- Celery Executor : 다수의 worker 노드의 경우, Celery 큐를 사용해 태스크 분산.
- Kubernetes Executor : K8s 클러스터를 사용하여 태스크 분산.
- Local Kubernetes Executor와 Celery Kubernetes Executor도 존재함.
Docker Desktop vs. Docker Engine
- Docker Desktop은 Docker Engine과 더불어 여러 편리한 기능들도 같이 실행 가능한 앱이다.
하이 레벨에서의 프로세스.
1. 대상 소프트웨어 선택. (다수의 컴포넌트(이미지)가 필요한 소프트웨어인지 하나의 컴포넌트가 필요한 소프트웨어인지)
2. 이를 Docker Image로 빌드. Dockerization.
-
- Dockerfile이라는 텍스트 파일로 세부 정보를 기술.
- 하나의 Docker Container 안에서 실행.
Docker Image의 구성 요소.
- 기본 OS 혹은 기본 소프트웨어 환경.
- 코드.
- 라이브러리.
- 파일 시스템 스냅샷(필요한 파일).
- 환경 설정 변수. 빌드용과 실행용 두 가지.
- 메타 데이터. 이미지에 대한 정보.
Docker Image의 실행.
- 독립된 공간인 Container에서 실행.
docker run ...
으로 실행.
Docker Image의 등록 : Docker Hub.
- Docker Registry라는 Docker Image들의 보관소가 있음. (docker hub이 가장 유명함.)
- 개발자 서버에서 Docker Image 개발 -> Registry에 등록 -> 프로덕션 서버에서 실행.
Docker Hub.
- https://hub.docker.com/
- 계정이 필요하며, Docker Desktop과 연동해 주어야 함.
- Public 혹은 Private Repo. 제공.
- Official Images라는 인증 태그가 있음.
- Github과 연동을 통해 자동화된 빌드 기능 제공.
// app.js
console.log("Hello Docker!");
Dockerfile 생성.
- Docker에게 소프트웨어 설치 명령을 기술.
- 베이스 이미지(OS, 언어 등) 기술. (FROM)
- 코드 복사.
- 코드 실행.
FROM node:alpine # node의 alpine이라는 OS type을 베이스 이미지로 지정. 해당 이미지를 Registry에서 다운로드 받아서 사용함. COPY ./app # 코드 복사 명령어. WORKDIR /app # 실행 디렉토리. CMD node app.js # "node app.js" 명령어 실행.
Dockerfile 기타 키워드.
- ARG : 최종 이미지에 저장되지 않는 컨테이너가 실행될 때 사용되는 환경 변수.
- ENV : 최종 이미지에 저장되는 컨테이너가 실행될 때 사용되는 환경 변수.
- USER : 컨테이너를 실행하는 (리눅스) 유저 ID.
- EXPOSE : 웹 서비스의 경우 사용되는 포트 번호.
- RUN : 이미지를 빌드할 때 필수적으로 실행되어야 하는 명령어(docker build). (RUN apt-get update && apt-get install -y curl)
CMD vs. ENTRYPOINT.
- 두 개 모두 컨테이너가 시작할 때 실행되어야 하는 명령어 지정.
- 두 개 모두 한 dockerfile에서 여러 번 실행되면 마지막 것만 실행됨.
- 우선 순위는 ENTRYPOINT가 더 높음.
- 웬만하면 CMD만 사용하는 것을 권장함.
CMD 예시.
FROM debian:buster COPY ./myproject RUN apt-get upgrade ... CMD ["./cmd1.sh"]
라는 dockerfile에 대해서,
docker run my-image
라고 실행하면, ./cmd1.sh가 실행됨.docker run my-image cmd2.sh
라고 실행하면, cmd2.sh가 실행됨.
CMD + ENTRRYPOINT 예시.
FROM debian:buster COPY ./myproject RUN apt-get upgrade ... ENTRYPOINT ["entrypoint.sh"] CMD ["param1", "param2"]
라는 dockerfile에서,
docker run my-image
: "entrypoint.sh param1 param2"docker run my-image cmd2
: "entrypoint.sh cmd2"docker run --entrypoint="/cmd3.sh" my-image
: "/cmd3.sh param1 param2"
웬만하면 CMD만 사용하는 것을 권장.
Docker Image 생성.
docker build --platform linux/amd64 -t hello-world-docker:{버전. default="latest"}.
- --platform : Apple M1 chip 관련 이슈.
- -t : 태그 지정.
- docker build 명령이 실행되면 RUN 명령이 실행됨.
docker image ls
로 Docker Image 생성 확인.
Docker Container로 실행.
docker run hello-world-docker
.
Docker Registry에 등록.
- 위 이미지를 생성한 상태에서, Docker Hub에 Repo를 생성.
docker tag hello-world-docker:latest ho99/hello-world-docker:latest
로 현재 이미지의 repo 이름을 jaeho/hello-world-docker로 변경.docker login --username=ho99
로 유저 정보 저장.docker push ho99/hello-world-docker
로 docker hub에 푸시함.
docker run vs. docker exec.
- docker run은 새로운 Container를 실행하는 것.
- docker exec는 실행된 Container에 작업을 하는 것.
- 두 명령 모두 --user root 혹은 -u root로 루트 유저로 연결 가능.ㄹ
우분투는 리눅스의 가벼운 버전이며, 다음과 같이 docker로 실행 가능하다.
docker run ubuntu
docker ps
: 현재 실행 중인 프로세스.docker ps -a
: 현재 + 이전에 실행된 프로세스.docker run -it ubuntu
: 우분투 배쉬 실행.
docker pull mysql/mysql-server:8.0
으로 MySQL 도커 이미지 설치.docker run --name=mysql_container mysql/mysql-server:8.0
으로 이미지 이름을 mysql_container로 수정.docker logs mysql_container 2>&1 | grep GENERATED
로 루트 계정 패스워드 확인.docker exec -it mysql_container mysql -uroot -p
로 MySQL shell 실행.