데이터엔지니어링

[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를 독립된 환경에서 실행한 것

https://www.harness.io/blog/best-practices-for-docker/

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를 실행하기 위해 필요한 모든 것을 포함

  • Docker Image의 실행
    • Container를 통해 Docker Image 안의 SW를 실행
    • Image를 Container 안에서 실행
      • docker run ... : Container를 새로 실행
      • docker exec ... : 이미 실행된 Container에 작업 - Container ID가 필요
  • Docker Image의 등록: 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