일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- grafana
- JavaScript
- Python
- Packet
- log
- MAC address
- kubernetes
- Vision
- Spring
- aws s3
- CSV
- EC2
- Operating System
- tcp
- Network
- helm
- Trino
- java
- OS
- ip
- Kafka
- kubectl
- docker
- jvm
- kubeadm
- zookeeper
- CVAT
- airflow
- PostgreSQL
- AWS
- Today
- Total
JUST WRITE
Kubernetes환경에서 Airflow를?!?! 본문
Kubernetes환경에서 Airflow를?!?!
요즘 가장 핫한 Workflow Tool은 Airflow입니다.
python으로 개발되어서 설치도 PyPl로 간편하게 설치할 수 있습니다.
하지만 디테일하게 사용하려면 Metastore, Celery Worker 등 설정할게 많습니다.
이러던 중 Kubernetes에 Airflow를 설치해야 될 업무를 맡게 되었습니다.
이번 포스팅에서는 Airflow를 Kubernetes 환경에 설치하는 것을 정리해 보았습니다.
Helm으로 Airflow 설치
Airflow에서 공식 Helm을 제공해 주기 때문에 해당 Helm으로 설치를 진행하였습니다.
다른 버전인 User-community Helm도 존재하니 참고해 주시길 바랍니다.
Airflow Helm Chart를 다운로드합니다.
$ helm repo add apache-airflow https://airflow.apache.org
"apache-airflow" has been added to your repositories
$ helm repo list
NAME URL
apache-airflow https://airflow.apache.org
$ helm search repo apache-airflow
NAME CHART VERSION APP VERSION DESCRIPTION
apache-airflow/airflow 1.9.0 2.5.3 The official Helm chart to deploy Apache Airflo...
$ helm pull apache-airflow/airflow
$ ll
total 180K
drwxrwxr-x 6 ec2-user ec2-user 84 Jun 26 15:59 .
drwx------ 14 ec2-user ec2-user 4.0K Jun 26 15:27 ..
-rw-r--r-- 1 ec2-user ec2-user 166K Jun 26 15:59 airflow-1.9.0.tgz
$ tar xzf airflow-1.9.0.tgz
git-sync 설정
Airflow는 dag 파일들을 git Repository에 연계해서 관리할 수 있습니다.
기본은 Airflow가 설치된 local path에서 dag 파일을 저장합니다.
dag 파일을 local path에서 관리하게 되면 삭제돼도 복구가 힘듭니다.
하지만 git Repository에서 관리하게 되면 복구는 물론 히스토리 관리까지 가능합니다.
이번 포스팅에서는 개인 github과 연계해 보겠습니다.
SSH Key 생성
SSH로 Github과 연결해야 되기 때문에 SSH Key를 먼저 생성하겠습니다.
Key 생성과 관련해서는 공식 Document에서 잘 정리되어 있습니다.
RSA 알고리즘으로 Key를 생성하도록 하겠습니다.
$ ssh-keygen -t rsa -b 4096 -C "perfectwan8765@gmail.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ec2-user/.ssh/id_rsa): /home/ec2-user/1_k8s_deploy/airflow-1.9.0-2.5.3/ssh/id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ec2-user/1_k8s_deploy/airflow-1.9.0-2.5.3/ssh/id_rsa.
Your public key has been saved in /home/ec2-user/1_k8s_deploy/airflow-1.9.0-2.5.3/ssh/id_rsa.pub.
The key fingerprint is:
SHA256:sgqv3PLFVyKzI9dm/8pQZBueMeuxCl5DbfRnJJFpZGY perfectwan8765@gmail.com
The key's randomart image is:
+---[RSA 4096]----+
| .Eo |
| ++. |
| B.. . |
| * O o |
| + S @ . o |
| . O * o o |
| . . O O o |
| ..+ * B * |
| o+= . . +o. |
+----[SHA256]-----+
$ ll
total 12K
drwxrwxr-x 2 ec2-user ec2-user 38 Jun 27 16:22 .
drwxrwxr-x 8 ec2-user ec2-user 4.0K Jun 27 16:19 ..
-rw------- 1 ec2-user ec2-user 1.7K Jun 27 16:22 id_rsa
-rw-r--r-- 1 ec2-user ec2-user 389 Jun 27 16:22 id_rsa.pub
그럼 Private Key와 Public Key가 생성됩니다.
Public Key를 복사하여 Github에 등록해 줍니다.
그리고 dag 파일을 관리할 Repository를 생성합니다.
예시 dag 파일(example.py)도 하나 생성하였습니다.
Private Key는 secret object로 생성합니다.
# namespace 생성
$ kubectl create namespace airflow
namespace/airflow created
$ kubectl get ns
NAME STATUS AGE
airflow Active 3s
default Active 124d
kube-flannel Active 124d
kube-node-lease Active 124d
kube-public Active 124d
kube-system Active 124d
kubernetes-dashboard Active 124d
# secret 생성
$ kubectl create secret generic \
airflow-ssh-git-secret \
--from-file=gitSshKey=/home/ec2-user/1_k8s_deploy/airflow-1.9.0-2.5.3/ssh/id_rsa \
--namespace airflow
$ kubectl describe secret -n airflow airflow-ssh-git-secret
Name: airflow-ssh-git-secret
Namespace: airflow
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
gitSshKey: 1679 byte
Webserver Secret Key 생성
Airflow에서 WebServer로 flask를 사용합니다.
flask에서 session ID를 관리하기 위해서 필요합니다.
난수를 만들어서 secret object로 생성합니다.
$ python3 -c 'import secrets; print(secrets.token_hex(16))'
bc318d8aec88278e583ac029d99a6627
$ kubectl create secret generic airflow-webserver-secret --from-literal="webserver-secret-key=bc318d8aec88278e583ac029d99a6627" -n airflow
$ k get secret -n airflow
NAME TYPE DATA AGE
airflow-ssh-git-secret Opaque 1 2m43s
airflow-webserver-secret Opaque 1 2m29s
values-override yaml 생성
이제 helm 설정값인 values 파일을 세팅합니다.
values-override.yaml을 생성해서 필요한 부분만 override 되도록 합니다.
$ vi values-override.yaml
executor: "KubernetesExecutor"
webserverSecretKey: webserver-secret-key
webserverSecretKeySecretName: airflow-webserver-secret
data:
metadataConnection:
user: user
pass: password
db: airflow
dags:
gitSync:
enabled: true
repo: git@github.com:test/airflow-test.git
branch: main
rev: HEAD
depth: 1
maxFailures: 3
subPath: dags
sshKeySecret: "airflow-ssh-git-secret"
wait: 60
scheduler:
livenessProbe:
initialDelaySeconds: 10
timeoutSeconds: 120
failureThreshold: 20
periodSeconds: 60
replicas: 2
webserver:
service:
type: NodePort
ports:
- name: airflow-ui
port: "{{ .Values.ports.airflowUI }}"
targetPort: "{{ .Values.ports.airflowUI }}"
nodePort: 31151
postgresql:
enabled: true
image:
tag: 11.22.0
auth:
enablePostgresUser: true
postgresPassword: postgres
username: user
password: password
database: "airflow"
primary:
service:
type: NodePort
nodePorts:
postgresql: 30032
persistence:
size: 20Gi
redis:
enabled: false
env:
- name: "AIRFLOW__LOGGING_REMOTE_LOGGING"
value: "True"
- name: "AIRFLOW__LOGGING__REMOTE_LOG_CONN_ID"
value: "S3Conn"
- name: "AIRFLOW__LOGGING__REMOTE_BASE_LOG_FOLDER"
value: "s3://{bucket명}/airflow/logs"
- name: "AIRFLOW__LOGGING__ENCRYPT_S3_LOGS"
value: "False"
- name: "AIRFLOW__CORE__DEFAULT_TIMEZONE"
value: "Asia/Seoul"
executor는 LocalExecutor, LocalKubernetesExecutor, CeleryExecutor, KubernetesExecutor, CeleryKubernetesExecutor 등이 있습니다.
이번 포스팅에서는 KubernetesExecutor로 진행하겠습니다.
아까 생성한 Webserver secret도 설정합니다.
executor: "KubernetesExecutor"
webserverSecretKey: webserver-secret-key
webserverSecretKeySecretName: airflow-webserver-secret
dag 파일을 git repository인 github에서 가져오도록 설정합니다.
Private Key로 생성한 secret를 설정합니다.
dags:
gitSync:
enabled: true
repo: git@github.com:test/irflow-test.git
branch: main
rev: HEAD
depth: 1
maxFailures: 3
subPath: dags
sshKeySecret: "airflow-ssh-git-secret"
wait: 60
Metastore는 PostgreSQL를 사용합니다.
Production으로 사용하는 거면 외부 PostgreSQL로 사용하는 것을 권장합니다.
이번 포스팅에서는 Airflow helm chart dependency로 설정된 bitnami PostgreSQL로 구성하였습니다.
data:
metadataConnection:
user: user
pass: password
db: airflow
postgresql:
enabled: true
image:
tag: 11.22
auth:
enablePostgresUser: true
postgresPassword: postgres
username: user
password: password
database: "airflow"
primary:
service:
type: NodePort
nodePorts:
postgresql: 30032
persistence:
size: 20Gi
Scheduler의 설정값을 일부 조정하였습니다.
default값으로 scheduler가 자주 restart가 되었습니다.
airflow scheduler의 liveness 응답이 늦어져 죽었다고 판단해 restart가 빈번하게 발생하였습니다.
아래 airflow github issue를 참고해서 설정하였습니다.
scheduler:
livenessProbe:
initialDelaySeconds: 10
timeoutSeconds: 120
failureThreshold: 20
periodSeconds: 60
replicas: 2
WebServer의 Service를 NodePort로 설정하여 외부에서도 접근하도록 설정하였습니다.
webserver:
service:
type: NodePort
ports:
- name: airflow-ui
port: "{{ .Values.ports.airflowUI }}"
targetPort: "{{ .Values.ports.airflowUI }}"
nodePort: 31151
Airflow log를 Kubernetes pv가 아닌 바로 remote로 S3 같은 Storage에 저장 가능합니다.
환경변수로 아래 설정값들을 추가해 줍니다.
- AIRFLOW__LOGGING_REMOTE_LOGGING
- AIRFLOW__LOGGING_REMOTE_LOG_CONN_ID
- AIRFLOW__LOGGING_REMOTE_BASE_LOG_FOLDER
- AIRFLOW__LOGGING_ENBRYPT_S3_LOGS
추가적으로 환경변수 설정을 통해서 Timezone 설정을 합니다.
env:
- name: "AIRFLOW__LOGGING_REMOTE_LOGGING"
value: "True"
- name: "AIRFLOW__LOGGING__REMOTE_LOG_CONN_ID"
value: "S3Conn"
- name: "AIRFLOW__LOGGING__REMOTE_BASE_LOG_FOLDER"
value: "s3://{bucket명}/airflow/logs"
- name: "AIRFLOW__LOGGING__ENCRYPT_S3_LOGS"
value: "False"
- name: "AIRFLOW__CORE__DEFAULT_TIMEZONE"
value: "Asia/Seoul"
Helm Install
이제 설정이 끝나고 Helm으로 Install 하겠습니다.
$ helm install airflow -n airflow -f values-override.yaml ./
NAME: airflow
LAST DEPLOYED: Tue Jun 27 16:56:31 2023
NAMESPACE: airflow
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Thank you for installing Apache Airflow 2.5.3!
Your release is named airflow.
You can now access your dashboard(s) by executing the following command(s) and visiting the corresponding port at localhost in your browser:
Airflow Webserver: kubectl port-forward svc/airflow-webserver 8080:8080 --namespace airflow
Default Webserver (Airflow UI) Login credentials:
username: *****
password: *****
Default Postgres connection credentials:
username: ********
password: ********
port: 5432
You can get Fernet Key value by running the following:
echo Fernet Key: $(kubectl get secret --namespace airflow airflow-fernet-key -o jsonpath="{.data.fernet-key}" | base64 --decode)
WARNING:
Kubernetes workers task logs may not persist unless you configure log persistence or remote logging!
Logging options can be found at: https://airflow.apache.org/docs/helm-chart/stable/manage-logs.html
(This warning can be ignored if logging is configured with environment variables or secrets backend)
###########################################################
# WARNING: You should set a static webserver secret key #
###########################################################
You are using a dynamically generated webserver secret key, which can lead to
unnecessary restarts of your Airflow components.
Information on how to set a static webserver secret key can be found here:
https://airflow.apache.org/docs/helm-chart/stable/production-guide.html#webserver-secret-key
$ kubectl get all -n airflow
NAME READY STATUS RESTARTS AGE
pod/airflow-postgresql-0 1/1 Running 1 (4m21s ago) 9h
pod/airflow-scheduler-6fd5969f4b-x5skw 3/3 Running 3 (4m21s ago) 9h
pod/airflow-statsd-59cf4979b6-9cb8n 1/1 Running 1 (4m21s ago) 9h
pod/airflow-triggerer-876bb488d-jq2nx 3/3 Running 3 (4m21s ago) 9h
pod/airflow-webserver-84cdfb5dc9-xlrs6 1/1 Running 1 (4m21s ago) 9h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/airflow-postgresql NodePort 10.97.226.10 <none> 5432:30032/TCP 9h
service/airflow-postgresql-hl ClusterIP None <none> 5432/TCP 9h
service/airflow-statsd ClusterIP 10.97.74.187 <none> 9125/UDP,9102/TCP 9h
service/airflow-webserver NodePort 10.103.30.10 <none> 8080:31151/TCP 9h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/airflow-scheduler 1/1 1 1 9h
deployment.apps/airflow-statsd 1/1 1 1 9h
deployment.apps/airflow-triggerer 1/1 1 1 9h
deployment.apps/airflow-webserver 1/1 1 1 9h
NAME DESIRED CURRENT READY AGE
replicaset.apps/airflow-scheduler-6fd5969f4b 1 1 1 9h
replicaset.apps/airflow-statsd-59cf4979b6 1 1 1 9h
replicaset.apps/airflow-triggerer-876bb488d 1 1 1 9h
replicaset.apps/airflow-webserver-84cdfb5dc9 1 1 1 9h
NAME READY AGE
statefulset.apps/airflow-postgresql 1/1 9h
admin 계정의 default password는 admin입니다.
WebServer에 접속하면 git Repository에 있는 dag를 확인할 수 있습니다.
구성한 Airflow를 활용해 보면서 좀 더 Airflow에 대해서 살펴보도록 하겠습니다.
[참고사이트]
'MLOps > Airflow' 카테고리의 다른 글
뭐야?! No Space left on device?! - Airflow db clean (0) | 2023.09.20 |
---|---|
Airflow Variables 세팅 - 전역변수 설정 (0) | 2023.07.23 |
How Airflow works? (0) | 2022.03.24 |
What is Airflow? (0) | 2022.03.23 |