SW-PRODUCT/개발-데이터분석

[후기] Docker로 Airbnb Airflow 띄우기

굴돌 2016. 4. 21. 13:46


 Docker든 Docker Toolbox든 적절한거 설치하시고 그대로 따라하시면 됩니다~


 cahna/airflow 기반으로 시작하기

 

Default 상태의 airflow 띄우기



docker run --name airflow -p 9090:9090 -v ~/airflow:/airflow -d cahna/airflow
 
# OS X에서는 -v 옵션을 줘도 OS X의 디렉토리가 아닌 VirtualBox에서 도는
#가상머신의 디렉토리로 마운트 되기 때문에 한번 들어가줘야 한다... 인셉션!
docker-machine ssh
cd ~/airflow
# OS X의 Docker Toolbox 문제일 수도 있으나, 권한이 귀찮아서 바꿔줌.
sudo chown docker:staff -R .
mkdir dags; cd dags

# 공식가이드의 tutorial.py를 실행시켜보자. 다만, 이미 있는 dag랑 이름충돌 피하기 위해 2를 붙여줌.
# copy tutorial.py from http://pythonhosted.org/airflow/tutorial.html
# modify 'tutorial' -> 'tutorial2'
vi tutorial2.py
 
# webserver가 'tutorial2'를 등록하려면 시간이 좀 걸린다..기다리자...
# ㄴ scheduler를 미리 띄워 놓으면 scheduler가 퍼 올리기도 하는 듯 한데,
#   이럴경우 webserver 캐시가 갱신이 안되서 이름이 까맣게 나오고 클릭이 안되는 상태가
#   되기도 한다. 이때는 그냥 기다리거나 webserver 재시작하면 됨.
# ㄴ 빠르게 적용시키고 싶으면 아래처럼 restart 해줘도 된다. 혹은 띄울때 -d 옵션을
#   줘도 되는데..이건 아래에서 다시 다룸.
docker restart airflow
 
# 이 상태에서 아래와 같이 튜토리얼에 있는 backfill을 실행할 수 있다.
docker exec airflow airflow backfill tutorial2 -s 2015-06-01 -e 2015-06-07
 
# 여기까지 해 놓고 webserver에 붙어서 refresh 해보면 진행상태가 보인다....우와~
# 이제 실행중인 backfill을 종료시키고 다음으로 넘어가자.
 
# backfill 돌리면 작업 도는게 잘 보이긴 한데... cron을 대체한다는 놈이 지가 알아서
#돌지는 않는다....scheduler 실행을 안해줘서...;;
 
# 아래와 같이 scheduler를 실행시켜준다.
docker exec -d airflow airflow scheduler
 
# list_dags를 실행해보면 언제 디비에 들어갔는지 보인다. 그런데, db에 들어가도
#웹서버에 바로 적용되진 않고 dag 이름이 까만색에 클릭 안되는 상태로 보인다.
docker exec airflow airflow list_dags
 
# webserver를 계속 refresh 해주면 진행 상태가 눈에 보인다!!!
 
# tip!! "airflow webserver -d"와 같이 -d 옵션을 주면 debug모드로 뜨게 되는데,
#debug모드에서는 파일 변경사항을 추적해서 바로 webserver를 갱신해준다.
#ㄴ 즉, 기달리 필요가 없음.
 
# scheduler 띄울때나 이런저런 이유로 컨테이너 안에 들어가보고 싶으면
#아래 명령어 날려주면 된다. 다들 알겠지만 난 docker 1도 모르고 덤볐더래서..;;
docker exec -i -t airflow /bin/bash

 

  • 여기까지하면 SequentialExecutor 모드에서 db는 SQLLite를 사용하는 airflow를 돌릴 수 있는 상태가 된다.
  • 얼핏보면 이 상태로 간단한 서비스는 가능할것 같기는 한데.. SQLLite 문제때문인지 안되는 기능들이 여럿 있다.
  • 이것만 가뿐하게 mysql로 바꾸면 되려나?...흠...이건 pass.


Tips

 

  • 원래 docker는 host와 container의 volumn을 연결할때, host의 디렉토리를 container에 mount한다.
  • 즉, container에 지정된 directory에 내용물이 있어도 host의 내용물로 덮어 써진다. 물론 mount 해제하면 복구되고.
  • 그런데 airflow는 container에 있어야할 파일들이 host의 volumn 위치에 들어있네???
  • 사실 이건 Docker가 volumn mount를 끝낸 후에 airflow를 띄우면 그때 airflow가 파일을 생성하는 것이기 때문에 그렇다.
  • 즉, image 혹은 container에 있던 파일이 host의 디렉토리에 보여지는게 아니라, host의 내용을 container에 덮어쓴 후에 airflow가 생성하는거다.

 

puckel/docker-airflow 기반으로 All-in-One 띄우기.

 

실행 절차

# docker-compose.yml 다운받은 후에
wget https://raw.githubusercontent.com/puckel/docker-airflow/master/docker-compose.yml
 
# 아래 명령어만 실행시키면 된다.
# 무려 6개 컨테이너를 띄운다!! 사용하는 이미지는 3개! rabbitmq랑 mysql을 추가로 사용함.
docker-compose up -d
# default로 띄우는 예제와 다르게 8080 포트를 사용한다.
http://(localhost|boot2docker_ip):8080/admin
 
# 하지만... default yml에서는 volumn 설정이 안되어 있어서 dag를 추가할 수 없다!!! 한번 해보자..
# 일단 떠있는것들 지워야 하니 아래 명령어로 6개를 한큐에 깔끔하게 지울 수 있다...
#사실은 모든 컨테이너를 한큐에 날려버리기 때문에 production에서 이짓하면 곤란하다.
docker rm -f $(docker ps -a -q)
 
# docker-compose.yml 파일에서 volumes 설정을 바꿔준다; 모든 설정값은 동일해야 한다!!
#ㄴ host의 지정된 경로를 webserver, scheduler, worker 세 모듈이 같이 봐야한다!!
#ㄴ 컨테이너는 각각 따로 놀지만, host의 디렉토리를 공유하기 때문에 일관성이 유지된다!
#ㄴ 다시말해, 여러 서버에 띄울때도 이 디렉토리는 모두 동기화 시켜줘야한다!
#ㄴ 이 예제에서는 ${AIRFLOW_HOME}을 마운트하는게 아니라 ${AIRFLOW_HOME}/dags를 마운트한다.
#  로그도 공유 안되고, 설정도 공유 안된다.
volumes:
- /usr/local/airflow/dags:/usr/local/airflow/dags
# 다시 띄움.
docker-compose up -d
 
# tutorial2 dag를 추가하기 위해 cahna/docker 예제에서의 아래 커맨드 위치부터 따라해본다.
docker-machine ssh
cd /usr/local/airflow/dags
sudo vi tutorial2.py
docker exec airflow_webserver_1 airflow list_dags
 
# 시간이 지나면 webserver에서 보인다.

Tips

volume이 mount가 안될 때

 

  • 아래 inspect 명령어로 내용을 까본다.
  • docker inspect airflow_webserver_1
  • OS X에서 Docker compose로 실행하는 경우, OS X에서 실행해야 하는데 이때 volume을 아래와 같이 ~로 해주면 Docker VM의 ~가 아니라 OS X의 ~로 지정한다!
  • 이때문에 Docker VM에 들어가서 아래 경로를 찾아가야 파일이 들어있다.
    • 기대한곳: /home/docker/airflow/dags
    • 마운트된곳: /Users/cmpark/airflow/dags
  • docker toolbelt의 문제인듯.

 

 container들간의 통신

 

  • 의문이 들만한 점.
    • 여러 컨테이너들은 실질적으로 서로 다른 장비에 떠서 ip 통신을 하는 상태인다.
    • 그런데, ip는 컨테이너가 뜰 때 할당되는데, 상대방 컨테이너가 어떤 ip를 가지게 될지 어떻게 알고 연결해주는걸까??
  • 구현방식
    • 각 컨테이너 /etc/hosts에 들어가보면 다른 컨테이너들의 ip가 등록되어 있다!
  • how?
    • docker는 --link 옵션을 제공하며, 이걸 통해 하나의 컨테이너 안에서 다른 컨테이너의 ip를 어떤 이름으로 /etc/hosts에 등록할지 결정할 수 있다.
    • 즉, 아래와 같이 mysql을 띄우고 webserver를 띄우면 webserver의 /etc/hosts에 mysql이 등록된다.
      • docker run --name airflow-db -d mysql
      • docker run --link airflow-db:mysql puckel/docker-airflow webserver
    • 문제는... airflow-db 컨테이너를 재시작할때 ip가 바뀌어 버려도 webserver의 /etc/hosts는 안바뀌기 때문에 주의해야함... 둘 다 리붓하던가... ip 안바뀌길 기도하던가... 혹은 용빼는 재주가 있을지도?