Airflow EC2에 구축하기

Airflow EC2에 구축하기

Airflow를 AWS EC2에서 실행시켜 보자!

AWS EC2 위에 Airflow 구축하기

Airflow를 로컬에 구축할 수도 있지만 안정성을 위해서라면 꺼지지 않는 컴퓨터에 Airflow를 구축하는 것이 좋을 것입니다. 이번 글에서는 실제 서비스를 위해서 Airflow를 EC2 위에 구축하는 내용을 담아보겠습니다.

Airflow에 대한 기본 개념이 궁금하신 분들은 Airflow Basic 을 확인하시면 좋습니다.

준비물

Airflow를 구축하기 위해서는 준비물이 필요합니다. 첫번째로는 EC2 서버입니다. 인스턴스 사이즈가 작아도 크게 상관은 없겠지만 여유롭게 t3.large를 선택하도록 하겠습니다. 인스턴스 설정이 끝나면 인스턴스를 생성하고 바로 인스턴스 안으로 들어가 보도록 합니다.

ssh 명령어를 이용해서 인스턴스 주소를 입력해 접속합니다. 접속이 안된다면 보안그룹에서 22번 포트를 열어줍시다.

이제 본격적으로 Airflow를 구축해 볼 것입니다. 구축 시에 확인해야 할 체크리스트를 만들어 둡니다.

  • Airflow 기본 세팅
  • Redis
  • MySQL
  • 기타 라이브러리 설치
  • AMI 이미지 생성하기

마지막에 이미지를 생성하는 이유는 이 작업을 반복하려면 너무 귀찮고 힘들기 때문입니다. 완벽히 구축이 되고 잘 돌아가는 Airflow 이미지를 생성해 두면 나중에 활용할 일이 많습니다. Airflow를 클러스터화 한다던가 그런 곳에 이미지를 사용하면 쉽게 구축할 수 있습니다.

레크리스트에는 Redis와 MySQL이 포함되어있습니다. 기본 세팅으로 실행해도 상관없지만 기본 세팅의 Executor는 Sequential Executor로 병렬로 Task를 수행할 수밖에 없습니다. 실제 서비스에는 많은 Task가 동시에 실행해야 할 경우가 자주 발생하므로 병렬 처리가 가능한 Celery Executor를 사용할 것이고 이 Executor는 메시지 브로커를 사용합니다. 메시지 브로커에는 RabbitMQ나 Redis 등이 사용되는데 이번 글에서는 Redis를 사용해 보겠습니다.


기본 세팅에 대한 의문점

Redis vs RabbitMQ?

Redis는 NoSQL DB로 잘 알려져 있습니다. In Memeory 방식이며 key-value데이터 구조 스토어 이기 때문에 빠른 Read, Write 성능을 보장합니다.

RabbitMQ는 DB보다는 메세징 브로커로 잘 알려져 있습니다. 메시지의 우선순위를 지원하며 크고 복잡한 메시지를 다룰때 적합합니다.

Airflow의 브로커로 어떤걸 사용할지는 현재 서비스할 비즈니스 프로세스에 따라 판단하면 됩니다. 제가 구축할 서비스의 비즈니스 프로세스에는 복잡한 메시지를 다루지는 않습니다. 제가 판단하기에 이 서비스에는 속도가 더 중요하다고 생각했습니다. 그래서 In Memory 방식의 Redis은 성능이 보장되기 때문에 Redis로 선택을 했습니다. Airflow를 구축하시는 분들도 무작정 따라하기보다는 비즈니스 프로세스를 생각해보시고 알맞는 로직에 따라 어떤걸 사용할지 선택하시면 좋을 것 같습니다.

참고! Celery란?
Celery 는 Python 으로 작성된 분산 메시지 전달을 기반으로 한 비동기 작업 큐로, Worker 의 한 종류입니다.
별도로 실행 중인 Worker Process가 Broker로부터 Message를 전달 받아 작업을 대신 수행해 주는 라이브러리입니다.
출처 : https://velog.io/@jisoo1170/Redis-RabbitMQ-%EC%B0%A8%EC%9D%B4%EC%A0%90%EC%9D%84-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90

Sqlite vs MySQL?

또한 Airflow의 meta store는 sqlite인데 sqlite로는 Hello World 정도만 테스트할 정도의 수준이기 때문에 MySQL을 DB로 사용해 볼 것입니다. 보통 sqlite는 로컬에서 혼자 사용하는 용도이며 많은 요청을 처리하기에는 버겁습니다. 반면 MySQL은 여러 개의 작업과 사용자의 SQL을 처리할 수 있도록 구현되어 있기 때문에 실제 서비스에 sqlite보다 적합할 것입니다.

의문점이 해결되었다면 본격적으로 Airflow를 구축해보도록 하겠습니다.


1. Airflow 기본 세팅

Airflow 구축 전에 반드시 해야할 것 중에 하나는 Airflow Home 경로를 설정하는 것입니다. 저의 경우에는 항상 경로 세팅을 나중에 하다가 잊어버려서 에러가 나는 경우가 많아서 꼭 먼저 설정해두곤 합니다.

Airflow Quick Start

출처 : https://airflow.apache.org/docs/apache-airflow/stable/start.html

Airflow 공식 문서에 따르면 기본 경로는 위 사진에 나와있는 것과 같습니다. 그냥 놔둬도 되지만 나중에 경로를 옮길 때를 대비해서 한번 세팅해봅시다.

1
2
# EC2
export AIRFLOW_HOME=/home/ec2-user/airflow

EC2 인스턴스라면 기본 경로를 다음과 같이 설정해 줍니다.

(여기서 airflow를 바로 설치해도 되긴 하지만 pip3 install apache-airflow로 설치를 하게되면 자잘한 에러들을 만날 수 있습니다. 아래 과정을 마친 뒤 명령을 실행하면 깔끔하게 설치되니 잘 따라가보도록 합니다. )


2. Redis 세팅

이제 브로커로 사용할 Redis를 설치해 줍시다. 먼저 AWS Linux의 패키지 설치 도구인 yum을 업데이트하고 필요한 라이브러리를 설치합니다.

1
2
$ sudo yum -y update
$ sudo yum -y install gcc make

이제 Redis를 다운 받습니다.

1
2
3
4
5
$ cd /tmp
$ wget http://download.redis.io/releases/redis-4.0.0.tar.gz
$ tar xzf redis-4.0.0.tar.gz
$ cd redis-4.0.0
$ make

Redis 디렉토리를 만들고 파일을 복사합니다.

1
2
3
4
$ sudo mkdir /etc/redis 
$ sudo mkdir /var/lib/redis
$ sudo cp src/redis-server src/redis-cli /usr/local/bin/
$ sudo cp redis.conf /etc/redis/

Redis의 configure 파일을 수정합니다.

1
$ sudo vim /etc/redis/redis.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#/etc/redis/redis.conf
[..]
daemonize yes
[..]

[..]
bind 0.0.0.0
[..]

[..]
dir /var/lib/redis
[..]

logfile /var/log/redis_6379.log

Redis-Server initializize 스크립트를 세팅합니다.

1
2
$ cd /tmp
$ wget https://raw.github.com/saxenap/install-redis-amazon-linux-centos/master/redis-server
1
2
3
4
5
$ sudo mv redis-server /etc/init.d
$ sudo chmod 755 /etc/init.d/redis-server
$ sudo vim /etc/init.d/redis-server

-> redis="/usr/local/bin/redis-server" 확인
1
2
$ sudo chkconfig --add redis-server
$ sudo chkconfig --level 345 redis-server on

서버 실행!

1
2
3
4
5
$ sudo service redis-server start
$ redis-cli ping -> PONG

# 강제 종료시
$sudo service redis-server stop

sudo service redis-server start를 해도 별 반응이 없다면 ctrl+c로 종료하고 실제로 돌아가는 프로세스가 있는지 확인합니다.

1
ps -ef|grep redis

제대로 세팅이 되었다면 다음과 같이 나올 것입니다.

Redis가 돌아가고 있다

브로커는 구축이 되었습니다.


3. MySQL 세팅

Airflow 구축을 하면서 가장 삽질도 많이 하고 시간을 많이 낭비한 부분입니다. 익숙하지 않아서인지 이상하게 MySQL을 다룰 때마다 에러핸들링을 오래 하게 되는 것 같습니다.

MySQL 설치

1
$ sudo yum install mysql56-server

웹에 검색하면 위와 같은 명령어가 많이 등장합니다. 예전 버전의 AWS CLI였으면 명령어가 적용되었을 것 같은데 mysql이 설치가 되지 않습니다.

아래의 명령어를 사용해서 설치를 해야합니다.

1
2
3
$ sudo wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
$ sudo yum localinstall mysql57-community-release-el7-11.noarch.rpm
$ sudo yum install mysql-community-server

설치가 완료되면 mysql 데몬을 실행합니다.

1
systemctl start mysqld.service

왜 안되지

답답하면 직접 하면 된다

이렇게 실행하라는 소리가 많은데 역시나 실행이 되지 않습니다. 왜 꼭 한번에 되게 정리해 놓은 문서는 없을까요? 답답하면 제가 정리해서 글을 올리면 됩니다. 묵-직하게!

에러가 난다면 코드를 다음과 바꿔서 쳐봅니다.

1
sudo service mysqld start

mysqld가 실행되었고 이제 mysql 명령어를 이용하는 게 가능해졌습니다.

Airflow에서 MySQL을 DB로 사용하기 때문에 해주어야 할 작업이 남았습니다. Airflow 유저를 만들어 줘야하고 airflow database를 만들어줘야 합니다. 유저가 없다면 database에 접근이 불가능하며, airflow database가 없다면 Airflow 실행에 필요한 테이블들을 만들지 못합니다.

따라서 root유저로 접속해서 유저를 만들고 데이터베이스를 만들어줘야 합니다.

MySQL 세부 세팅

1
2
3
$ mysql -u root -p
# 패스워드를 입력
Enter Password :

루트 유저로 접속하려면 비밀번호를 요구합니다. 하지만 방금 MySQL을 설치했기 때문에 비밀번호를 설정한 적이 없습니다. 그래서 그냥 엔터를 쳐봅니다.

왜 않되2

될리가 없습니다.

MySQL은 설치가 될때 root 유저에 대한 임시 비밀번호를 만들어 놓기 때문에 접속이 안되는 것입니다. 임시 비밀번호를 찾아 와야 합니다. 임시 비밀번호는 휴대폰 인증을 통해서 이메일로 받는게 정석이지만 MySQL은 조금 다릅니다.

1
sudo vim /var/log/mysqld.log

/var/log/mysqld.log 여기에 임시비밀번호가 있습니다. 비밀번호를 복사해 놓은 후 다시 입력해 봅니다.

mysql 프롬포트가 나왔다면 성공입니다.

이제 root 유저의 비밀번호를 다시 설정해주고 airflow 유저를 생성하고 database를 만들어 주면 세팅은 끝납니다.

1
2
UPDATE mysql.user SET Password=PASSWORD('패스워드')
WHERE User='root';

검색해서 나온 위 명령어로 비밀번호를 세팅해줍니다.

여기서 에러가 발생하는데 두 가지 에러가 발생합니다.

  1. syntax 에러
  2. Your password does not satisfy the current policy requirements

1번 에러의 경우에는 ' 를 잘 살펴보고 모양이 맞는지 한번 잘 확인해 봅니다. 혹은 mysql 버전에 맞지 않는 명령어일 가능성이 있습니다. mysql 5.7이상의 명령어인지 확인을 다시 해봅니다.

2번 에러의 경우에는 비밀번호가 너무 쉽다는 것입니다. mysql에는 비밀번호 정책이 상 중 하로 나누어져 있는데 기본 설정은 MEDIUM입니다. 복잡한 비밀번호를 사용하기는 싫었기 때문에 저는 이것을 LOW로 변경할 것입니다.

1
2
set global validate_password_policy='LOW';
# 쿼리 성공!

LOW로 설정되었다면 비밀번호는 8자 이상으로만 세팅하면 됩니다.

1
2
3
alter user 'root'@'localhost' identified by '8자 이상 패스워드';
use mysql;
flush privileges;

이제 airflow 사용자를 만들어주고 database도 만들어줍니다.

1
2
3
4
5
6
7
8
9
10
11
# 사용자 생성
create user 'airflow'@'localhost' identified by '비밀번호';

# DB 권한 부여
$ grant all privileges on *.* to 'airflow'@'localhost';
$ grant all privileges on DB이름.* to 'airflow'@'localhost';

# database 생성
create database airflow;

flush privileges;
1
sudo pip3 install 'apache-airflow[mysql]'

험난 했던 MySQL 세팅은 완료되었습니다.


4. Airflow 설치 및 세팅

이제 Airflow를 설치해봅시다.

1
2
3
4
5
6
7
8
9
$ sudo yum update -y

$ sudo yum install group "Development tools" -y

$ sudo yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel python3-devel.x86_64 cyrus-sasl-devel.x86_64 -y

$ sudo yum install libevent-devel -y

$ sudo pip3 install apache-airflow

설치가 완료되었다면 airflow 폴더애 있는 airflow.cfg를 수정해서 앞서 설치한 redis와 mysql을 airflow와 이어줘야 합니다.

하지만 아무리 찾아봐도 airflow 폴터가 보이지 않습니다. 분명히 설치를 했는데!

airflow를 입력해서 airflow 명령어가 동작하는지 먼저 확인합니다. 만약 명령어가 작동한다면 아까 설정해둔 AIRFLOW_HOME경로에 airflow 폴더가 생성될 것입니다. 그 안에 configuration 파일이 있습니다.

만약 airflow: command not found에러가 발생한다면

1
export PATH=$PATH:~/.local/bin

환경변수를 조정해서 airflow가 bin에서 실행되도록 합니다.

airflow.cfg 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 사용할 dag 폴더 지정
# subfolder in a code repository. This path must be absolute. 꼭 절대경로!
dags_folder = /home/ec2-user/airflow/dags

# executor = SequentialExecutor
executor = CeleryExecutor

# sql_alchemy_conn = sqlite:////home/airflow/airflow/airflow.db
sql_alchemy_conn = mysql+pymysql://airflow:비밀번호@127.0.0.1:3306/airflow

# catchup_by_default = True
catchup_by_default = False

# broker_url = sqla+mysql://airflow:airflow@127.0.0.1:3306/airflow
broker_url = redis://airflow@127.0.0.1:6379/0

# result_backend = db+mysql://airflow:airflow@localhost:3306/airflow
result_backend = db+mysql://airflow:비밀번호@127.0.0.1:3306/airflow

# load_examples = True
load_examples = False

이 정도만 세팅 해줍니다.

1
2
3
sudo pip3 install boto3
sudo pip3 install celery
sudo pip3 install redis

실행에 필요한 라이브러를 설치해주고 airflow db를 초기화 해봅시다.

1
airflow initdb

Done!이 나왔다면 성공입니다.




Airflow 실행

Airflow는 스케쥴러, 웹서버, 워커로 구성되어있습니다. 하나하나 백그라운드로 실행시켜줍니다.

1
2
3
4
5
nohup airflow webserver > /dev/null 2>&1 &
nohup airflow scheduler > /dev/null 2>&1 &

# queue를 설정했다면 -q를 통해 추가한다
nohup airflow worker > /dev/null 2>&1 &

됐다!!!!!

웹 UI가 예쁘게 뜬다면 성공입니다!

example dag를 실행해보고 안된다면 백그라운드로 실행된 프로세스를 종료한 뒤 nohup명령어를 빼고 실행합니다. 로그가 나오므로 해당 에러를 모두 해결한 뒤에 백그라운드로 실행시켜 주면 완료가 됩니다.




자잘한 에러 핸들링

  1. Exception: Global variable explicit_defaults_for_timestamp needs to be on (1) for mysql

    위 에러가 등장한다면 mysql에서 timestamp 설정을 변경해 주어야 한다.

    root 계정으로 들어가서 아래 명령어를 실행해준다.

    1
    SET GLOBAL explicit_defaults_for_timestamp = 1;
  2. ModuleNotFoundError: No module named 'MySQLdb'

    또는 OSError: mysql_config not found 이런 에러 메세지로 등장할 수 있다.

    아래 명령어로 해결한다.

    1
    2
    3
    sudo yum install mysql-devel

    pip3 install 'apache-airflow[mysql]'

Reference

https://airflow.apache.org/docs/

https://boomkim.github.io/2020/01/08/airflow-install-amazon-linux-2/

https://openmind8735.com/aws/redis/2017/07/21/aws-ec2-인스턴스에-redis-설치하기/

https://serverfault.com/questions/894457/amazon-linux-2-ami-aws-how-to-install-mysql-in-amazon-linux-2

https://lemontia.tistory.com/943

https://m.blog.naver.com/aim4u/221766568746

Author

SangHyub Lee, Jose

Posted on

2020-12-13

Updated on

2023-12-08

Licensed under

Comments