본문 바로가기

D.S/DE

220206일 - apbot airflow 작업 완료

728x90



airflow를 이용해 apbot 의 글발행을 자동화했다.
처음에는 도커로 띄운 로컬 airflow에서 작업하다 worker에서 apbot를 구동하는 데 환경설정 문제에 부딪혔다. 그래서 이리저리 찾다가 apbot app & 환경설정을 도커 이미지로 만든 후 이미지를 실행할 수 있는 operator를 실행하기로 했다.

처음으로 찾은 것은 KubernetePodOperator 였다. airflow 쿠버네티스 환경에서 사용하는 회사들의 글들을 읽어보다가 찾은 것이었는데, 쿠버네티스와 클라우드도 겸사겸사 사용해볼 겸 로컬에서 GKE로 airflow 환경을 옮겼다. 하지만 이 시도는 결국 보류하게 되었다. 쿠버네티스 환경에 익숙치 않으니 테스트와 삽을 들고 있는 시간이 길어지면서 과금문제가 생겼기 때문이다.


다시 도커 로컬 작업환경으로 돌아와 방법을 찾았다.

worker에서 당면한 모든 문제들과 해결책

  • 로그파일 기록 문제 → 로그가 많이 생기지 않기 때문에 로그스태시에 http 방식을 이용해 보냄.
  • 워커 실행 위치로 인한 가상환경 실행 문제/ 환경변수 문제 → worker가 작업하는 디렉토리인 /tmp에 가상환경 만들어서 app이 돌아갈 가상환경 생성
  • 크롬브라우저, 기타 필요한 패키지 문제 → 로컬에서는 worker가 컨테이너로 계속 구동되고 있기 때문에 컴포즈 파일에서 build: 값을 설정해 설치할 수 있도록 수정하거나 커밋해서 새 이미지 생성.
  • 컨테이너에서 atlas 몽고DB 커넥션 connection timeout문제 (free 티어라 그런 것으로 추정)


사용 Operator

위 문제를 해결한 후 BashOperator 로 start_for_worker.sh를 실행하니 드디어 자동발행을 성공할 수 있었다. 이 방법의 문제점은 app을 실행할 때마다 가상환경을 새로 만들어야 해서 시간이 오래 걸린다는 점이었다. worker는 /tmp 밖에서는 작업을 하지 않는 듯 보였다.

또 다른 앱을 실행한다고 했을 때 그 앱이 apt-get 명령어로 패키지를 설치해야 하면 worker airflow를 새로 띄워야 하고 무척 번거로워진다.

이 방법을 성공한 후 찾은 다른 방법은 dockerOperator 였다. 이걸보니 작업할 때 오퍼레이터도 먼저 꼼꼼히 찾아야겠다는 생각이 들었다. 사용자가 많아 다양한 오퍼레이터들이 이미 많이 존재할 테니..로컬에는 도커만 설치된 상태이고, APP을 이미지화하면 앞선 방법에서처럼 매번 환경설정을 해줄 필요가 없으니 훨씬 효율적이라 생각되었다.

참조:

실행은 성공했지만 이 또한 문제가 있었다. airflow volume에 /var/run/docker.sock 을 마운트하는데 권한문제로 worker가 작업을 도커에 대한 권한거부(permission denied)를 일으켰기 때문이다.


이 문제에 대해서는 호스트의 docker.sock 퍼미션을 777로 바꾸라는 등의 답변을 찾을 수 있었는데 그 방법을 쓰고 싶지 않아서 다른 방법을 찾다 docker-proxy 이미지를 사용해 우회해서 docker.sock에 접근하는 방법을 사용했다. 이 방법도 문제가 있는데, 환경변수에 DOCKER_HOST를 등록하면 docker 커멘드가 먹통이 된다.

참조:


내 로컬 /var/run/docker.sock 우회 컨테이너


테스트 DAG의 dockerOperator

 from airflow import DAG from airflow.operators.bash_operator import BashOperator from airflow.operators.docker_operator import DockerOperator from airflow.operators.python_operator import BranchPythonOperator from airflow.operators.dummy_operator import DummyOperator  default_args = { 'owner'                 : 'airflow', 'description'           : 'Use of the DockerOperator', 'depend_on_past'        : False, 'start_date'            : datetime(2021, 5, 1), 'email_on_failure'      : False, 'email_on_retry'        : False, 'retries'               : 1, 'retry_delay'           : timedelta(minutes=5) }  with DAG('lucca_docker_operator_dag', default_args=default_args, schedule_interval="5 * * * *", catchup=False) as dag:     start_dag = DummyOperator(         task_id='start_dag'         )      t2 = DockerOperator(         task_id='docker_command_sleep',         image='lucca_apbot:1.0.0',         container_name='task___command_sleep',         api_version='auto',         auto_remove=True,         #command="/bin/sleep 30",         #docker_url="unix://var/run/docker.sock",         docker_url='tcp://docker-proxy:2375',         network_mode="bridge"         )  


결과 로그



신경써야 할 것들

  • 빌드시 이미지 사이즈 : python3.9 이미지를 기본을 가져다 썼는데 이미지를 만들고 보니 크기가 2GB였다. 패키지 사이즈도 고려해서 빌드를 해야함을 느꼈다.
  • 레이어를 생각한 빌드 스크립트 짜기: 가급적 변동이 없는 스크립트들을 먼저 적고 앱소스 등의 변화가 많은 부분을 적는 부분은 뒤에 넣자.


반응형