본문 바로가기
Airflow

[Airflow] KubernetesPodOperator 로컬 테스트를 위한 환경 구축(feat. KIND(Kubernetes In Docker) | LIM

by forestlim 2023. 9. 17.
728x90
반응형

docker image를 활용해 airflow에서 실행시키기 위해서 KubernetesPodOperator를 사용하게 되었는데 이는 기존 로컬 환경에서 테스트가 바로 안 된다는 단점이 있었다. 

 

이번에 한국데이터 엔지니어 모임 3회에 참여해 발표를 들었던 내용 중에 로컬 환경에서 KubernetesPodOperator 를 사용할 수 있게끔

로컬 Airflow on K8S 구축에 Vault 곁들이기

설명을 들었는데 그 블로그를 참조해서 테스트해보았다.

 

🚀 KIND(Kubernetes in Docker) 활용하기

Kubernetes In Docker는 Kubernetes 클러스터를 Docker 컨테이너 내에서 실행할 수 있게 해주는 도구다. 이를 활용해 빠르고 쉽게 로컬 환경에서 Kubernetes 클러스터를 구축할 수 있다. 전통적으로 minikube 가 로컬 kubernetes 환경을 구축하기 위한 주요 도구였으나 minikube는 VM 또는 로컬 호스트에 클러스터를 생성하며, 리소스 소모가 많고 설정이 복잡할 수 있다. 이런 복잡성을 피하고 Docker와의 간결함과 가벼움을 이용하려는 필요성으로 KIND 가 나왔다. 

 

 

💻 KIND 설치하기(MAC 기준)

일단 도커가 먼저 설치되어 있어야 한다. 

맥의 경우 brew install kind 로 설치할 수 있다. 

 

 

🚗 KIND 를 활용해 본격적으로  Airflow Cluster 구축하기

클러스터 구축을 위한 Config 코드는 아래와 같습니다. 

로컬에 있는 DAG 코드를 클러스터에서 사용하기 위해서는 로컬과 클러스터 간에 폴더를 공유해야 합니다.

이를 위해 볼륨 마운트를 사용하여 클러스터가 로컬 폴더와 공유가 가능하도록 설정했습니다.

apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
nodes:
  - role: control-plane
    extraMounts:
      - hostPath: ./
        containerPath: /opt/airflow/dags

 

해당 yaml 파일을 통해서 kind는 클러스터를 생성할 때 다양한 설정을 할 수 있습니다.

현재 yaml은 컨트롤 플레인 역할을 하는 노드 하나로 구성되어 있는 클러스터입니다.

단순히 로컬에서 테스트 용도로 사용할 클러스터라 여러 워커 노드를 설정하진 않았습니다.

 

추가적으로 worker node를 생성해서 작업할 수도 있습니다. 

관련해서는 해당 영상을 참고하면 쉽게 구축할 수 있습니다. 

https://www.youtube.com/watch?v=GDOw8ByzMyY 

 

본격적으로 클러스터 기본 세팅이 끝났으니 클러스터를 생성해 보도록 합시다.

kind create cluster --name airflow --config kind-cluster.yaml --image kindest/node:v1.25.11

해당 명령어를 통해 이름이 airflow이고, 위에서 정의한 config를 바탕으로 cluster 가 생성되게 됩니다.

kind get clusters

 



docker desktop을 열어서 확인해 보면 kindest/node:v1.25.11라는 이름으로 컨테이너가 띄워진 걸 확인할 수 있습니다.

 

🚗 Airflow를 클러스터에 설치하기

Airflow 를 helm 차트를 이용해서 설치해 주었습니다. 

https://airflow.apache.org/docs/helm-chart/stable/index.html

 

Helm Chart for Apache Airflow — helm-chart Documentation

 

airflow.apache.org

처음에 볼륨 마운트를 해준 건 kubernetes 클러스터와 로컬이었는데 Airflow는 클러스터 내부에서 다시 또 컨테이너(Pod)로 실행되기 때문에 이번엔 클러스터와 컨테이너 사이의 볼륨 마운트가 한 번 더 필요하다. 

 

해당 config 파일은 다음 명령어로 가져올 수 있다. 

helm show values apache-airflow/airflow > values.yaml

나는 다음과 같은 것들을 설정했다. 

 

먼저, 위에서 말했던 것처럼 클러스터와 컨테이너 사이의 볼륨 마운트가 필요하기 때문에
다음 dag 파일을 worker, scheduler, webservesr에 모두 마운트 시켜주었다.

  extraVolumeMounts:
    - name: dags
      mountPath: /opt/airflow/dags

  extraVolumes:
    - name: dags
      hostPath:
        path: /opt/airflow/dags

 

다음으로는 airflow version을 변경할 수 있다. 

현재 회사 내 airflow version 은 2.4.3을 사용하고 있기 때문에 airflowVersion을 변경해 주었다. 

 

다음으로 로그 설정을 해주었다. KubernetesPodOperator의 특성상 workerpod를 띄우고 실행시킨 다음 pod가 사라지기 때문에  pod에 남아있는 로그를 가져올 수 없게 된다. 따라서 웹에서 확인할 수 없었다. 

 

따라서 pod의 로그를 지속적으로 보기 위해 gcs와 연동시켜 주는 작업을 진행했다. 

    remote_logging: 'True'
    remote_base_log_folder: 'gs://로그/저장/경로'
    remote_log_conn_id: 'google_cloud_default'

 

마지막으로 extraEnv 설정에 gcp와 연결할 수 있는 service account 파일 경로를 매핑해 주었다. 

extraEnv: |
  - name: GOOGLE_APPLICATION_CREDENTIALS
    value: /opt/airflow/dags/service_account.json 파일 경로

 

이로써 세팅은 모두 끝났다. 이 작업까지 하는데 장장 하루가 걸렸다..

 

이제 설치를 해보도록 하자

helm upgrade --install airflow apache-airflow/airflow -n airflow --create-namespace -f values.yaml --debug

- upgrade 옵션

- name space는 airflow

- name space 가 없을 경우 create

- config 파일은 values.yaml 

- debug 옵션을 통해 과정을 확인할 수 있다. 

 

배포가 모두 끝났다면 Airflow web pod와 포트포워딩을 해주면 된다.

1. webserver pod의 이름을 가져오기

kubectl get pods -n airflow

2. port forwading 해주기

kubectl port-forward -n airflow pod/{webserver pod 이름} 8080:8080

3. localhost:8080으로 airflow web ui 접속

 

 

 

 

🧐 추후 더 진행해봐야 하는 것

- KubernetesExecutor를 사용하면 worker pod에 대한 로그는 바로 확인할 수 있는데 그 안에서 실행되는 kubernetespod에 대한 로그는 바로 확인할 수 없다. 

- 현재 회사에서 사용하고 있는 airflow docker image 가 있는데 그 이미지를 helm chart에 넣고 싶은데 왜인지 계속 실패한다. 

->  + 이 문서를 참고해 docker image를 Kind 로 load 해서 해결

- 구성원들이 로컬에서 쉽게 테스트할 수 있도록 supportability 추가하기

->  + Makefile 을 활용해 모든 구성원들이 간단한 make 명령어를 통해 한 번에 환경을 구축할 수 있도록 진행

 

이번 과정을 통해 kubernetes에 대한 이해도도 높아졌고, airflow executor에 대한 이해도도 많이 높아져서 매우 의미 있는 시간이었다.

 

728x90
반응형

댓글