Kubernetes 환경에 배포된 Airflow에서 SSHOperator를 테스트하던 중, 파드(Pod)가 재시작되거나 작업이 종료된 후 로그가 사라지는 현상을 확인했다. 이를 해결하기 위해 로그 영구 저장(Persistence) 설정을 적용하는 과정과, 그 과정에서 발생한 airflow-triggerer StatefulSet 업데이트 에러를 해결하는 방법을 정리한다.
1. SSHOperator 테스트 환경 구성
먼저 외부 서버에 명령을 수행하기 위해 Admin Connection을 생성하고 DAG를 작성한다.
1-1. Connection 생성

1-2. DAG 작성
DAG PVC를 nfs로 지정했기 때문에 해당 nfs 위치에서 파일 생성 진행함.
from datetime import datetime
from airflow import DAG
from airflow.providers.ssh.operators.ssh import SSHOperator
with DAG(
dag_id="ssh_test_dag",
start_date=datetime(2024, 1, 1), # DAG의 시작 기준일 (과거 날짜여야 실행 가능)
schedule=None, # 자동 스케줄링 없이 수동으로만 실행
catchup=False, # start_date부터 현재 사이의 누락된 구간을 실행하지 않음
tags=["ssh"], # UI에서 DAG를 쉽게 검색/필터링하기 위한 태그
) as dag:
run_remote_cmd = SSHOperator(
task_id="run_remote_cmd",
ssh_conn_id="ssh-test", # Admin > Connections에 설정한 SSH connection ID
command="hostname && whoami && date && sleep 20",
get_pty=True, # 타임아웃 발생 시 원격 프로세스도 함께 종료, 명령어가 실행되는 즉시 로그를 출력
cmd_timeout=30, # 명령어 실행 타임아웃 설정
)
run_remote_cmd # 태스크 인스턴스 생성 (의존성이 있다면 >> 연산자로 연결)
1-3. 실행 결과 확인
DAG를 실행하면 태스크가 정상적으로 수행된다. XCom을 확인해보면 실행 결과가 base64로 인코딩 되어 저장된 것을 확인할 수 있다.

그런데 Airflow Web UI의 Logs 탭을 확인했을 때, 파드가 정리되면서 로그가 함께 사라졌다.
2. 로그 저장(Persistence) 설정
Kubernetes 환경에서 워커 파드는 일시적이므로, 로그를 영구적으로 보존하기 위해서는 별도의 PVC(Persistent Volume Claim) 설정이 필요하다. values.yaml 파일에서 로그 관련 설정을 수정하여 NFS 스토리지와 연결했다.
logs:
persistence:
enabled: true
size: 50Gi
annotations: {}
storageClassName: nfs-airflow
existingClaim: airflow-logs
3. 배포 및 에러 확인
수정한 설정을 적용하기 위해 Helm Upgrade 명령어를 실행했다.
helm upgrade --install airflow apache-airflow/airflow --namespace airflow --values ./values.yaml --debug
배포 과정에서 airflow-triggerer 리소스 업데이트 중 다음과 같은 에러가 발생하며 배포가 실패했다.
client.go:425: ... error updating the resource "airflow-triggerer":
cannot patch "airflow-triggerer" with kind StatefulSet: StatefulSet.apps "airflow-triggerer" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'ordinals', 'template', 'updateStrategy', 'persistentVolumeClaimRetentionPolicy' and 'minReadySeconds' are forbidden
Airflow의 Triggerer 컴포넌트는 StatefulSet 형태로 배포된다. Kubernetes의 StatefulSet 명세(Spec) 중 스토리지 볼륨과 관련된 필드는 생성 후 수정이 불가능(Forbidden)하다. values.yaml에서 로그 관련 설정을 변경하면서 Triggerer가 참조하는 볼륨 설정에도 변경이 생겼고, 이를 기존 StatefulSet에 덮어씌우려다 실패한 것이다.
4. 문제 해결 및 재배포
StatefulSet의 스펙을 변경하기 위해서는 기존 StatefulSet 리소스를 삭제한 후 재생성해야 한다.
kubectl delete statefulset airflow-triggerer -n airflow
기존 리소스를 삭제한 후 다시 배포 명령을 수행하면 정상적으로 새로운 설정이 적용된 StatefulSet이 생성된다.
helm upgrade --install airflow apache-airflow/airflow --namespace airflow --values ./values.yaml --debug
5. 결과 검증
배포가 완료된 후 다시 DAG를 실행하여 로그 저장 여부를 확인한다.
- Airflow UI: 이전과 달리 태스크가 종료된 후에도 로그가 정상적으로 조회된다.

- NFS 스토리지: 실제 PVC 경로(
existingClaim: airflow-logs)에 들어가 보면 로그 파일이 물리적으로 저장되어 있음을 확인할 수 있다.
'Data > Airflow' 카테고리의 다른 글
| Airflow에서 GitSync를 이용한 DAG 동기화 설정 (0) | 2025.12.30 |
|---|---|
| Airflow 실습 - Upbit 분봉 데이터 수집 및 S3 적재 파이프라인 구축 (0) | 2025.12.18 |
| Helm으로 Airflow 배포하기 (0) | 2025.11.10 |