Airflow 환경 구축을 위한 Docker와 K8s 실습
Airflow 운영 상의 어려움
라이브러리 충돌
- DAG에 따라 실행에 필요한 라이브러리 / 모듈이 달라지면서 충돌 이슈 발생
- DAG 혹은 Task 별로 별도의 독립 공간을 만들어주는 것이 필요 -> Docker
Worker의 부족
- Scale Up : 서버의 사양 업그레이드
- Scale Out : 클라우드 서비스
- K8s와 같은 컨테이너 기술 활용
낮은 Server Utilization 이슈
- 서비스 별로 전용 서버를 할당하는 것은 여러 가지 이슈 발생
- 서비스 별로 Capacity 관리를 해야 함
- 각 서비스에 속한 서버들을 보면 Utilization이 낮은 이슈 발생
- 이 역시 K8s와 같은 컨테이너 기술의 도입으로 해결 가능
해결책
- Task나 DAG 코드를 Docker Image로 만들어 Docker Container 형태로 실행
- 라이브러리 / 모듈 충돌 방지
- 개발 환경과 프로덕션 환경을 동일하게 유지
- Airflow Worker를 K8s에서 필요한 대로 동적으로 할당하여 사용
- 전용 서버를 Airflow에 할당 X
- Container Orchestration 서비스를 통해 사용(할당)하고 리턴
Docker 소개
Docker 개념
- Docker Image : 독립적으로 완전하게 만들어진 패키지
- Docker Container : Docker Image를 독립된 환경에서 실행한 것
Docker 목표
- 소프트웨어를 일관되게 빌드하고 실행하고 배포
Virtual Machines vs Docker Containers
Virtual Machine 소개
- AWS의 EC2가 대표적인 Virtual Machine (VM)
- 하드웨어를 추상화하여 한 컴퓨터 위에 가상 컴퓨터를 올리는 것
- 장점
- 소프트웨어를 실행하기 위한 독립적이고 분리된 공간 제공
- 다수의 소프트웨어를 VM에서 독립적으로 실행 가능
- 단점
- 각 VM은 자신만의 OS 필요
- 유료 OS라면 라이센스 비용이 필요하고 시작하는데 오래 걸림
- 자원을 많이 사용
Docker Container 소개
- 소프트웨어를 실행하기 위한 독립적이고 분리된 공간
- Volume이라는 자체 파일 시스템을 갖고 있음
- 장점
- 다수의 소프트웨어를 각 Container에서 독립적으로 실행 가능
- 자원 소비가 적고 호스트 OS를 사용하여 별도 비용 X
- 단점
- 많은 수의 Docker Container를 관리하는 것이 쉽지 않음
- 호스트 OS를 사용하기에 Cross-platform compatibility를 항상 지원하지 않음
- GUI 소프트웨어 개발에 적합지 않음
Docker 프로그램 개발 프로세스
하이레벨 Docker 사용 프로세스
- 대상 소프트웨어 선택
- Dockerization : Docker Image로 빌드
- Dockerfile : 텍스트 파일로 세부 정보를 기술
- Docker Image : 하나의 Docker Container 안에서 실행
Docker Image의 구성 요소
- 아래 정보와 설치 관련 실행 순서는 Dockerfile에 기술
- 기본 OS와 같은 소프트웨어의 실행 환경
- 소프트웨어 자체 코드
- 소프트웨어가 필요로 하는 라이브러리
- 파일 시스템 스냅샷 : 이는 스택화된 형태로 구현된
- 환경 설정 변수 : 빌드할 때 변수와 실행 때 두 변수 두 가지가 존재
- 메타 데이터 : 이미지 자체에 대한 정보 (버전, 작성자, 설명 등)
Docker Image 실행
- Container를 통해 Docker Image 안의 소프트웨어 실행
Docker Image 등록 : Docker Hub
- Docker Registry는 Docker Image 보관소
- On-prem registry와 Cloud resigtry 존재
- Docker Hub가 가장 유명
- 여기에 등록하면 회사 내 혹은 퍼블릭하게 이미지 공유 가능
실습
Dockerfile
- Dockerfile : Docker에게 소프트웨어 설치 명령 기술
- ARG : Docker Image를 만들 때 사용되는 변수 지정, 최종 이미지에는 안 들어감
- ENV : 컨테이너가 실행될 때 사용되는 환경 변수, 최종 이미지에 저장
- USER : 컨테이너를 실행할 때 사용할 유저 ID
- EXPOSE : 서비스 사용 포트번호
- RUN : 빌드 시 실행돼야 하는 명령 (docker build)
- CMD vs ENTRYPOINT (1)
- 컨테이너가 시작할 때 실행돼야 하는 명령어를 지정하는 데 사용 (docker run)
- 각 키워드가 Dockerfile에 여러 번 실행되면 각각 마지막 것만 사용
- 아래의 경우 docker run 실행 시 동일한 결과가 나옴
# CMD
CMD ['command1.sh']
CMD ['command2.sh'] # 이 명령만 사용
# ENTRYPOINT
ENTRYPOINT ['command1.sh']
ENTRYPOINT ['command2.sh'] # 이 명령만 사용
- CMD vs ENTERYPOINT (2)
- 하나의 Dockerfile에 두 키워드를 같이 지정 가능
- 같이 사용되면 ENTRYPOINT가 기본 명령이 되고 CMD가 인자 제공
- ENTRYPOINT는 --entrypoint 옵션으로 override 가능
- CMD는 옵션 없이 override 가능
- ENTRYPOINT를 사용하면 실행 시 타이핑을 덜 할 수 있으나 혼란 초래
FROM debian:buster
COPY . /myproject
RUN apt-get update …
ENTRYPOINT ["entrypoint1.sh"]
CMD ["param1", "param2"]
>> docker run my-image
-> entrypoint1.sh param1 param2
>> docker run my-image cmd2
-> entrypoint1.sh cmd2
docker run --entrypoint='/cmd3.sh' my-image
-> cmd3.sh param1 param2
Docker Registry 등록 : Docker Hub
- repository 생성
- 터미널로 이동하여 아래 명령 실행
- 여기서 tag는 별칭을 만들어주는 것 (이름을 바꾸는 것이 아님)
docker image ls
docker tag hello-world-docker:latest 'name'/hello-world-docker:latest
docker image ls
docker login --username=jelly878
docker push jelly878/hello-world-docker
Docker tag
- Docker Image의 버전이나 변형을 나타내는 문자열 (default=latest)
- Docker Image 이름에서 ':' 뒤에 해당 ex) ubuntu:18.04 (공식), bitnami/airflow, node:alpine (공식)
- 공식 이미지에는 네임스페이스가 없고, 다운로드할 경우 계정 ID(네임스페이스)를 포함할 수 있음
간단한 Hello world 프로그램
- Dockerfile
FROM node:alpine # OS 종류(alpine)
COPY . /app # 코드 복사
WORKDIR /app # Working Directory
CMD node app.js # 명령 실행
- Docker Registry 등록 (Docker Hub)
docker image ls
docker tag hello-world-docker:latest 'name'/hello-world-docker:latest
docker image ls
docker login --username=jelly878
docker push jelly878/hello-world-docker
- 다른 서버에서 Docker Image 사용
docker pull jelly878/hello-world-docker
docker run jelly878/hello-world-docker
Ubuntu 실행
- 리눅스 커널과 배포판
- 리눅스 커널 : 리눅스의 핵심 부분
- 배포판 : 우분투 (가장 많이 사용), 데비안, 알파인 (경량화), 페도라, 페도라, 센트 OS 등
- pull을 먼저 하지 않고 run을 하면 자동으로 pull이 진행
docker run ubuntu
docker run -it ubuntu # 우분투 접속
MySQL 서버 실행
- --name : 기억하기 쉬운 이름을 docker ps로 찾은 Container ID 대신 사용 가능
- docker log : Container에서 생성된 stdout, stderr 단의 로그를 읽어옴
docker pull mysql/mysql-server:8.0
docker run --name=mysql-container mysql/mysql-server:8.0
docker logs mysql_container 2>&1 | grep GENERATED # window는 select-string
docker exec -it mysql_container mysql -uroot -p
ALTER USER root@localhost IDENTIFIED BY 'password';
'[프로그래머스] 데이터 엔지니어링 데브코스 3기 > TIL(Today I Learn)' 카테고리의 다른 글
[TIL - 48일 차] Docker & K8S 실습 (3) (0) | 2024.05.29 |
---|---|
[TIL - 47일 차] Docker & K8S 실습 (2) (0) | 2024.05.28 |
[TIL - 45일 차] 데이터 파이프라인과 Airflow (5) (0) | 2024.05.24 |
[TIL - 44일 차] 데이터 파이프라인과 Airflow (4) (0) | 2024.05.23 |
[TIL - 43일 차] 데이터 파이프라인과 Airflow (3) (0) | 2024.05.22 |