K8s 와 Kafka 상의 Apache Flink: PyFlink, Go, 운영, 그리고 관리형 가격 정책
상태 유지 스트리밍, 체크포인트, K8s, PyFlink, Go.
Apache Flink 는 유계 및 무계 데이터 스트림에 대한 상태 기반 연산을 위한 프레임워크입니다.
팀들은 이벤트 타임 시맨틱스 (워터마크), 장애 허용 (체크포인트), 제어된 업그레이드 (세이브포인트), 운영 인터페이스 (메트릭 및 REST) 를 통해 정확하고, 저지연 스트리밍을 위해 이를 채택합니다.

이 가이드는 DevOps 및 Go/Python 개발자를 대상으로 합니다. 배포 모델 (셀프 매니지드 vs 관리형) 을 비교하고, 핵심 아키텍처를 설명하며, Kubernetes(Helm 및 Operator) 와 스탠드얼론 구성을 다루고, Spark, Kafka Streams, Beam, 스트리밍 데이터베이스와의 Flink 비교를 제시하며, LLM 과 AI 중심 파이프라인을 포함한 PyFlink 와 Go 통합 패턴을 보여줍니다.
객체 스토리지, 데이터베이스, 메시징을 포함한 데이터 인프라 패턴에 대한 더 넓은 맥락은 AI 시스템용 데이터 인프라: 객체 스토리지, 데이터베이스, 검색 및 AI 데이터 아키텍처 를 참조하십시오.
Apache Flink 란 무엇이며 왜 팀들이 실시간 처리에 사용하는가
Apache Flink 는 상태 기반 스트림 처리 엔진으로 명시적으로 포지셔닝되어 있습니다: 로직을 연산자 파이프라인으로 모델링하면 Flink 가 관리되는 상태와 시간 시맨틱스를 가진 분산 데이터플로우로 실행합니다. 최신 Flink 문서에서 프로젝트는 자신을 유계 및 무계 데이터 스트림에 대한 상태 기반 연산을 위한 프레임워크 및 분산 처리 엔진으로 설명합니다.
실용적인 DevOps/소프트웨어 엔지니어링 관점에서, Flink 는 다음 중 적어도 하나의 속성이 필요할 때 적합합니다:
저지연으로 정확성 보장과 함께 조인/집계/보강이 필요하면, Flink 의 이벤트 타임 처리를 사용하되, 여기서 “시간"은 이벤트가 발생한 시점 (도착한 시점이 아님) 이며, 워터마크는 파이프라인을 통해 이벤트 타임 진행 상황을 전달합니다.
규모에 따른 상태 기반 연산 (롤링 카운터, 세션, 사기 방지 규칙, 피처 엔지니어링) 이 필요하면, Flink 는 상태를 프로그래밍 모델의 일류 시민으로 취급하고 체크포인트를 통해 장애 허용성을 제공합니다.
운영적으로 강력한 스트리밍 (장애, 롤링 업그레이드, 재시작) 이 필요하면, Flink 는 상태와 스트림 위치를 체크포인트하여 작업이 실패 없는 실행과 동일한 시맨틱스로 복구되고 계속될 수 있게 합니다.
DevOps, Go, Python, AI 팀을 위한 일반적인 사용 사례
Flink 는 “데이터 파이프라인 및 ETL”, “스트리밍 분석”, “이벤트 기반 애플리케이션”(Flink 문서에서 사용하는 카테고리) 에 광범위하게 사용됩니다.
DevOps + Go/Python 스택의 경우 일반적인 패턴은 다음과 같습니다:
Go 서비스는 Kafka 로 이벤트를 생성합니다. Flink 는 해당 이벤트를 소비하고 상태 기반 처리 (예: 중복 제거, 윈도우화 집계, 보강) 를 수행한 다음 유도된 사실을 Kafka 나 데이터베이스로 다시 씁니다. Flink 의 연산자 및 체크포인트 메커니즘은 이러한 상태 기반 파이프라인을 프로덕션에 안전하게 만드는 데 존재합니다.
ML/LLM 팀의 경우, PyFlink 는 명시적으로 “기계 학습 예측” 시나리오와 Python UDF 내부에서 기계 학습 모델 로드 (의존성 관리 동기) 를 언급하며, 이는 “Flink 작업을 온라인 추론/피처 엔지니어링 런타임” 패턴에 대한 직접적인 지지입니다.
Apache Flink 아키텍처 및 핵심 기능
프로덕션 배포를 위한 Apache Flink 클러스터 아키텍처
Flink 런타임은 두 가지 프로세스 유형으로 구성됩니다: JobManager 와 TaskManagers. 문서는 클라이언트가 JobManager 로 데이터플로우를 제출한다는 것을 강조하며, 클라이언트는 이후 연결을 끊을 수 있습니다 (detached mode) 또는 연결된 상태를 유지할 수 있습니다 (attached mode).
JobManager 는 분산 실행을 조정합니다: 스케줄링, 작업 완료/실패에 대한 반응, 체크포인트 조정, 복구 조정입니다. 내부적으로는 ResourceManager (슬롯/리소스), Dispatcher (REST + Web UI + 작업별 JobMaster 생성), JobMaster (하나의 작업 관리) 를 포함합니다.
TaskManagers 는 연산자/작업을 실행하고 데이터 스트림을 교환/버퍼링합니다. 가장 작은 스케줄링 단위는 task slot이며, 여러 연산자가 하나의 슬롯에서 실행될 수 있습니다 (연산자 체이닝 및 슬롯 공유가 이에 영향을 줌).
성능 및 비용 제어를 위한 연산자 체이닝 및 태스크 슬롯
Flink 는 연산자 서브태스크를 태스크로 체이닝하며, 각 태스크는 단일 스레드로 실행됩니다. 이는 스레드 인수인계 및 버퍼링 오버헤드를 줄이고 처리량을 늘리며 지연 시간을 줄이는 성능 최적화라고 설명됩니다.
슬롯은 운영적으로 리소스 스케줄링/격리의 단위이기 때문에 중요합니다. Flink 는 각 TaskManager 가 하나 이상의 태스크 슬롯을 가질 수 있다고 밝히며, 슬롯은 슬롯당 관리 메모리를 예약하지만 CPU 를 격리하지는 않습니다.
이벤트 타임 처리, 워터마크, 및 늦은 데이터
Flink 는 이벤트 타임, 인제션 타임, 프로세싱 타임 등 여러 시간 개념을 지원하며 워터마크를 사용하여 이벤트 타임에서의 진행 상황을 모델링합니다.
이벤트 타임으로 작업하려면 Flink 가 이벤트에 타임스탬프를 할당하고 워터마크를 생성해야 합니다. 공식 “워터마크 생성” 문서는 타임스탬프 할당과 워터마크 생성을 핵심 구성 요소로 설명하며, WatermarkStrategy 는 일반적인 전략을 구성하는 표준 방식을 제공합니다.
장애 허용: 실제 시스템에서 체크포인트 vs 세이브포인트
체크포인트는 “Flink 의 모든 함수와 연산자가 상태를 가질 수 있기 때문에” 존재하며, 상태를 체크포인트해야 장애 허용이 됩니다. 체크포인트는 상태와 스트림 위치의 복구를 가능하게 하여 실패 없는 시맨틱스로 실행을 재개할 수 있게 합니다.
Flink 는 세이브포인트가 “스트리밍 작업의 실행 상태에 대한 일관된 이미지로, Flink 의 체크포인트 메커니즘을 통해 생성됨"이며, 중지-재개, 포크, 또는 작업 업데이트에 사용된다고 매우 명시적으로 밝힙니다. 세이브포인트는 안정적인 스토리지 (예: HDFS, S3) 에 보관됩니다.
공식 “체크포인트 vs 세이브포인트” 페이지는 차이점을 백업 vs 복구 로그처럼 설명합니다: 체크포인트는 장애 복구를 위해 Flink 가 관리하는 빈번하고 경량의 것이지만, 세이브포인트는 사용자가 관리하며 업그레이드와 같은 제어된 운영에 사용됩니다.
Apache Flink 배포 옵션 및 가격 플랜
무료/셀프 매니지드 Apache Flink 옵션
오픈소스 Flink 런타임은 라이선스 관점에서 “무료"이지만, 프로덕션에서는 인프라와 운영 노력에 비용을 지불합니다.
Flink 는 일반적인 리소스 매니저 (예: YARN 과 Kubernetes) 와 통합되도록 설계되었으며 스탠드얼론 클러스터 또는 라이브러리로도 실행될 수 있습니다.
Apache Flink 셀프 매니지드 비용 요인
컴퓨팅 및 메모리 비용은 JobManager 와 TaskManagers, 그리고 병렬성/슬롯 레이아웃에 의해 결정됩니다. Flink 구성 문서는 jobmanager.memory.process.size, taskmanager.memory.process.size, taskmanager.numberOfTaskSlots, parallelism.default 를 분산 설정을 위한 핵심 조절 장치로 명시합니다.
로컬 디스크는 상태 기반 작업에서 빈번한 숨겨진 비용입니다. Flink 는 io.tmp.dirs 가 RocksDB 파일, 넘쳐나는 중간 결과, 캐시된 JAR 를 포함한 로컬 데이터를 저장한다고 밝히며, 이 데이터가 삭제되면 “무거운 복구 작업"을 강제할 수 있으므로 주기적으로 정리가되지 않는 스토리지에 보관해야 합니다.
내구성이 있는 객체/파일 스토리지 비용은 체크포인트/세이브포인트 디렉토리에 의해 결정됩니다. Flink 2.x 구성에서 체크포인트와 세이브포인트는 execution.checkpointing.dir 과 execution.checkpointing.savepoint-dir 를 통해 구성되며 s3://… 또는 hdfs://… 와 같은 URI 를 허용합니다.
관리형 Apache Flink 플랜 및 일반적인 청구 모델
관리형 서비스는 운영 비용을 줄이지만 플랫폼 수수료와 제약을 추가합니다. 구체적인 사항은 제공자에 따라 다릅니다.
Amazon Managed Service for Apache Flink 는 KPU(1 vCPU + 4GB 메모리) 로 청구되며, 기간과 KPU 수에 따라 1 초 단위로 청구됩니다. AWS 는 또한 애플리케이션마다 추가 “오케스트레이션” KPU 와 별도의 스토리지/백업 요금을 청구합니다.
Confluent Cloud for Apache Flink 는 사용량 기반이며 서버리스입니다: 컴퓨팅 풀을 생성하고, 문장이 실행되는 동안 소비된 CFU에 대해 청구됩니다. 청구 페이지에는 CFU 시간당 $0.21 (지역에 따라 다름) 의 예시 CFU 가격이 포함되어 있으며 컴퓨팅 풀 최대치를 통해 지출을 제한할 수 있음을 강조합니다.
Aiven 과 Alibaba Cloud 는 시장에서 주목할 만한 관리형 Flink 제공자이지만, 공개된 가격 및 청구 세부 사항은 플랜/지역에 따라 다르며 계산기 또는 영업 문의가 필요할 수 있습니다; 정확한 비용은 현재 문서에서 지역+플랜을 명시하지 않는 한 지정되지 않음으로 간주하십시오.
Ververica 는 Flink 를 중심으로 셀프 매니지드 및 관리형 배포 옵션을 모두 제공합니다. 공개 페이지는 배포 선택과 관리형 서비스 포지셔닝을 강조하며, 정확한 가격은 일반적으로 “문의/가격 세부 사항” 흐름을 통해 처리되므로 구체적인 숫자는 공개적으로 지정되지 않음이 일반적입니다.
프로덕션에서 Apache Flink 배포 옵션 표
| 배포 옵션 | 적합 대상 | 운영 복잡성 | 주요 이점 | 주요 위험/트레이드오프 |
|---|---|---|---|---|
| 스탠드얼론 클러스터 (VM/베어 메탈) | 소규모 팀, 고정 용량 | 중~높음 | 완전한 제어; 가장 단순한 정신 모델 | HA, 오토스케일링, 업그레이드는 DIY (더 많은 수고) |
| Flink Kubernetes Operator 와 함께한 Kubernetes | 대부분의 현대 플랫폼 팀 | 중간 | 선언적 배포; 제어 루프를 통한 수명 주기 관리; 연산자가 Application/Session/Job 배포 지원 | Kubernetes + 오퍼레이터 전문성 필요 |
| 네이티브 Kubernetes (오퍼레이터 없이) | 직접 통합을 원하는 K8s 팀 | 중~높음 | 직접 리소스 통합; Flink-on-K8s 문서에 설명된 동적 TaskManager 할당/해제 | 오퍼레이터보다 더 맞춤형 자동화 필요 |
| YARN | Hadoop 중심 플랫폼 | 중간 | YARN 리소스 관리 통합 | Hadoop 스택 복잡성 |
| AWS Managed Service for Apache Flink | AWS 네이티브 데이터 스택 | 낮음~중간 | 관리형 오케스트레이션 + 스케일링 옵션; 예측 가능한 청구 단위 (KPU) | 플랫폼 결합; 앱당 추가 오버헤드 KPU + 스토리지 요금 |
| Confluent Cloud for Apache Flink | Kafka 우선, SQL 우선 스트림 앱 | 낮음 | 서버리스 사용량 청구; CFU 분 단위 회계; 지출 제한을 위한 컴퓨팅 풀 | CFU 비용 + Kafka 네트워킹 비용; 서비스 전용 API |
| Ververica 관리형 제품 | Flink 전문가 운영이 필요한 기업 | 낮음~중간 | “Flink 전문가” 관리형 서비스 포지셔닝 | 가격이 종종 투명하지 않음 (지정되지 않음) |
관리형 제공자 및 비용 표
가격은 지역과 시간에 따라 변합니다. 해당 지역의 정확한 숫자가 필요하면 시작점으로 간주하고 제공자의 현재 가격 페이지와 검증하십시오 (인용되지 않은 지역은 지정되지 않음).
| 제공자 | “플랜” 형태 | 청구 단위 | 예시 컴퓨팅 가격 | 주목할 만한 추가 비용 요인 |
|---|---|---|---|---|
| Amazon Managed Service for Apache Flink | 관리형 런타임 | KPU (1 vCPU + 4 GB) | 예시: KPU 시간당 $0.11 (US East N. Virginia) | 앱당 +1 오케스트레이션 KPU; 실행 중인 스토리지; 선택적 내구성 백업 |
| Confluent Cloud for Apache Flink | 서버리스 SQL/처리 | CFU 분/CFU 시간 | 예시: CFU 시간당 $0.21 (지역에 따라 다름) | Kafka 네트워킹 요금이 여전히 적용; 지출 제한을 위한 컴퓨팅 풀 최대치 |
| Ververica (관리형) | 관리형 “통합 스트리밍 데이터 플랫폼” | 지정되지 않음 (공개 페이지) | 지정되지 않음 | 플랫폼 기능/SLA; 가격은 일반적으로 영업 통해 (지정되지 않음) |
| Aiven for Apache Flink | 관리형 서비스 | 시간별 사용량 청구 모델 (플랫폼 전반) | 플랜/지역 없이 지정되지 않음 | 플랜 티어 + 클라우드 지역 + 추가 기능 (지정되지 않음) |
| Alibaba Cloud Realtime Compute for Apache Flink | 관리형/서버리스 | 하이브리드 청구 (사용량 기반 + 구독 혼합) | 지역/워크스페이스 세부 사항 없이 지정되지 않음 | CU 기반 제한 및 워크스페이스 모델 (세부 사항 다양; 여기서는 지정되지 않음) |
Apache Flink vs 경쟁자 비교
Flink 는 붐비는 생태계에 자리 잡고 있습니다. “최고"의 선택은 지연 시간, 상태성, 운영 선호도, 작성 모델에 따라 다릅니다.
경쟁자 비교 표: Flink vs Spark vs Kafka Streams vs Beam 및 새로운 옵션
| 도구 | 무엇인가 | 스트리밍 실행 모델 | 상태 및 정확히 한 번 스토리 | 빛나는 곳 | 일반적인 통증 지점 |
|---|---|---|---|---|---|
| Apache Flink | 상태 기반 연산을 위한 분산 스트림 처리 엔진 | 워터마크를 통한 이벤트 타임 + 연속 스트리밍 | 체크포인트 기반 장애 허용; 제어된 업그레이드를 위한 세이브포인트 | 저지연 상태 기반 파이프라인; 복잡한 이벤트 타임 로직 | 상태, 체크포인트, 업그레이드를 올바르게 운영하려면 규율 필요 |
| Apache Spark Structured Streaming | DataFrame/Datasets 을 중심으로 구축된 Spark 의 스트리밍 엔진 | 기본 마이크로 배치 모델 (연속 모드는 별도로 논의됨) | 분석 파이프라인에 강력함; 상태는 존재하지만 종종 더 높은 지연 시간 | 통합 배치+스트림 API; Spark 생태계 | 마이크로 배치 지연 시간 및 “스트리밍을 증분 배치로"라는 정신 모델 |
| Kafka Streams | Kafka 위에서 스트림 처리 앱을 구축하기 위한 라이브러리 | 레코드 단위 처리 | 정확히 한 번 처리 시맨틱스 (EOS) 지원 | 간단한 Kafka 네이티브 앱; JVM 서비스에 임베드 | JVM 전용; 대규모 분산 컴퓨팅 패턴에 덜 유연함 |
| Apache Beam | 통합 프로그래밍 모델 + SDK; 런너 (Flink, Spark, Dataflow 등) 를 통해 실행됨 | 런너에 따라 다름; Beam 파이프라인은 런너 작업으로 변환됨 | 시맨틱스는 런너 능력 행렬에 따라 다름 (런너 전용) | 이식성, 다국어 파이프라인; 엔진 종속 방지 | 운영 튜닝은 결국 런너 전용으로 귀결됨 |
| Materialize | “라이브 데이터 레이어”/스트리밍 SQL DB; 데이터가 도착함에 따라 결과를 증분적으로 업데이트 | 연속 증분 뷰 유지 관리 | 제품 문서에서 강한 일관성 주장 (세부 사항은 제품 전용) | 앱/AI 에이전트에 신선한 유도된 뷰 제공 | Flink 작업과 다른 운영 모델; 일반적인 연산자 API 런타임이 아님 |
| RisingWave | 스트림 처리가 물질화된 뷰로 표현되는 스트리밍 데이터베이스 | 연속 물질화된 뷰 유지 관리 | SQL 우선; 엔진 전용 시맨틱스 | Flink 작업을 구축하지 않고 SQL 중심 스트리밍 앱 | 임의의 코드 중심 파이프라인에 덜 유연함 |
유용한 휴리스틱: 복잡한 상태 기반 스트리밍 작업을 위한 런타임이 필요하고 이벤트 타임, 연산자 로직, 배포에 대해 깊은 제어를 원한다면 Flink 가 주요 후보입니다. SQL 우선 증분 뷰를 제공을 위해 원한다면 스트리밍 데이터베이스가 대안이 될 수 있습니다. 서비스에 임베드된 라이브러리를 원한다면 Kafka Streams 가 경쟁력이 있습니다. 엔진 간 하나의 이식 가능한 파이프라인 정의를 원한다면 Beam 이 매력적입니다.
AWS 를 사용하는 클라우드 네이티브 이벤트 기반 아키텍처의 경우, AWS Kinesis 를 사용한 이벤트 기반 마이크로서비스 구축 은 실시간 처리 및 서비스 해결을 위한 Kinesis Data Streams 패턴을 다룹니다.
맞춤형 시스템에서 Apache Flink 사용 방법
이 섹션은 의도적으로 실용적입니다: 구성, 배포, 그리고 Go/Python 서비스가 일반적으로 Flink 와 상호작용하는 방식.
권장 아키텍처 패턴: Go 서비스 + Kafka + Flink + 서빙 레이어

Flink 는 종종 고량 이벤트를 내구성이 있는 신호 (카운터, 세션, 이상 현상, 보강된 레코드) 로 변환하는 “상태 기반 중간"입니다. 체크포인트와 상태 백엔드가 프로덕션에서 그 중간을 신뢰할 수 있게 만듭니다.
Apache Flink 2.x 를 위한 스탠드얼론 구성 예시
중요 버전 참고: Flink 2.0 부터 지원되는 구성 파일은 conf/config.yaml 이며, 이전 flink-conf.yaml 은 “더 이상 지원되지 않습니다”.
작은 셀프 매니지드 클러스터를 위한 최소 (시각적) conf/config.yaml:
# conf/config.yaml (Flink 2.x 스타일)
rest:
address: flink-jobmanager.example.internal
port: 8081
jobmanager:
rpc:
address: flink-jobmanager.example.internal
port: 6123
memory:
process:
size: 2048m
taskmanager:
memory:
process:
size: 4096m
numberOfTaskSlots: 2
parallelism:
default: 2
# 체크포인트 기본값 (작업은 코드에서 오버라이드 가능)
state:
backend:
type: rocksdb
execution:
checkpointing:
dir: s3://my-bucket/flink/checkpoints
savepoint-dir: s3://my-bucket/flink/savepoints
interval: 60 s
# 주기적으로 정리되는 tmp 디렉토리 방지 (RocksDB 파일, 캐시된 jar 등)
io:
tmp:
dirs: ["/var/lib/flink/tmp"]
이 키들의 이유: Flink 구성 참조는 명시적으로 rest.* 와 jobmanager.rpc.* 발견 세부 사항, 프로세스 메모리 키, 슬롯/병렬성 키, state.backend.type, execution.checkpointing.dir, execution.checkpointing.savepoint-dir, execution.checkpointing.interval 을 포함한 기본 체크포인트 설정을 문서화합니다.
io.tmp.dirs 선택은 Flink 가 로컬 RocksDB 파일 및 캐시된 아티팩트에 이를 사용하므로 운영적으로 중요합니다; 삭제하면 무거운 복구가 발생할 수 있습니다.
Flink 1.x 를 위한 레거시 스탠드얼론 구성 예시
Flink 1.x 를 사용 중이라면 (일부 관리형 환경에서 여전히 흔함), 실제 세계에서 flink-conf.yaml 을 볼 것입니다. 이는 Flink 2.x 사용자에게 레거시입니다.
# conf/flink-conf.yaml (레거시 1.x 스타일; Flink 2.x 에서 지원되지 않음)
jobmanager.rpc.address: flink-jobmanager
rest.port: 8081
taskmanager.numberOfTaskSlots: 2
parallelism.default: 2
# 레거시 체크포인트 키는 버전마다 다름; 시각적으로 취급하십시오.
state.backend.type: rocksdb
state.checkpoints.dir: s3://my-bucket/flink/checkpoints
state.savepoints.dir: s3://my-bucket/flink/savepoints
마이그레이션 중인 경우, Flink 는 flink-conf.yaml 을 config.yaml 로 변환하는 마이그레이션 스크립트 (bin/migrate-config-file.sh) 를 제공합니다.
Flink Kubernetes Operator 와 함께한 Kubernetes/Helm 배포
Flink Kubernetes Operator 는 Flink 애플리케이션 수명 주기 관리를 위한 제어 평면으로 작동하며 Helm 을 사용하여 설치됩니다.
공식 오퍼레이터 Helm 문서에 따르면, 소스 트리 차트 또는 Apache 호스팅 차트 저장소에서 설치할 수 있습니다:
# 소스 트리의 번들된 차트에서 설치
helm install flink-kubernetes-operator helm/flink-kubernetes-operator
# Apache 다운로드 Helm 저장소에서 설치 (<OPERATOR-VERSION> 치환)
helm repo add flink-operator-repo https://downloads.apache.org/flink/flink-kubernetes-operator-<OPERATOR-VERSION>/
helm install flink-kubernetes-operator flink-operator-repo/flink-kubernetes-operator
이 정확한 명령은 오퍼레이터의 Helm 설치 문서에서 표시됩니다.
예시 FlinkDeployment CR (시각적)
이는 일반적으로 사용자화할 통합 포인트 (이미지, 리소스, 체크포인트 위치, 로깅/메트릭) 를 보여주기 위한 단순화된 예시입니다. 오퍼레이터는 제어 루프를 통해 이 원하는 상태를 조정합니다.
apiVersion: flink.apache.org/v1beta1
kind: FlinkDeployment
metadata:
name: realtime-sessions
namespace: flink
spec:
image: my-registry.example.com/flink/realtime-sessions:2026-03-06
flinkVersion: v2_2
serviceAccount: flink
flinkConfiguration:
taskmanager.numberOfTaskSlots: "2"
state.backend.type: "rocksdb"
execution.checkpointing.dir: "s3://my-bucket/flink/checkpoints/realtime-sessions"
execution.checkpointing.savepoint-dir: "s3://my-bucket/flink/savepoints/realtime-sessions"
execution.checkpointing.interval: "60 s"
rest.port: "8081"
jobManager:
resource:
cpu: 1
memory: "2048m"
taskManager:
resource:
cpu: 2
memory: "4096m"
job:
jarURI: local:///opt/flink/usrlib/realtime-sessions.jar
parallelism: 4
upgradeMode: savepoint
state: running
upgradeMode: savepoint 패턴은 안전한 상태 기반 업그레이드를 원할 때 일반적이며, 세이브포인트는 중지/재개/포크/업데이트 워크플로우를 위해 설계되며 안정적인 스토리지 위치를 가리킵니다.
PyFlink 개발: 체크포인트 및 RocksDB 상태를 갖춘 현실적인 Kafka 스트리밍 작업
PyFlink 는 Apache Flink 의 Python API 이며 ML 파이프라인 및 ETL 을 포함한 확장 가능한 배치/스트림 워크로드를 위해 명시적으로 제안됩니다.
PyFlink Kafka 작업의 의존성 패키징
PyFlink 에서 JVM 커넥터 (Kafka, JDBC 등) 를 사용할 때, 관련 JAR 이 작업에 사용 가능해야 합니다. Flink 의 Python “의존성 관리” 문서는 세 가지 표준 메커니즘을 보여줍니다:
pipeline.jars 설정 (Table API), add_jars() 호출 (DataStream API), 또는 제출 시 CLI --jarfile.
PyFlink Kafka 작업 예시 (DataStream API + 이벤트 타임 + 상태 + 체크포인트)
이 예시는 Kafka 에서 JSON 이벤트를 읽고, 이벤트 타임 타임스탬프를 할당하며 (제한된 순서 불일치를 포함), 키된 상태에서 사용자별 롤링 카운트를 유지하고, 보강된 이벤트를 출력 토픽에 씁니다.
참고:
- KafkaSource 는
KafkaSource.builder()를 통해 구축되며 부트스트랩 서버, 토픽, 시리얼라이저가 필요합니다. - PyFlink 에서 정확히 한 번 Kafka 싱크 구성은 배달 보장 및 트랜잭션 ID 접두사를 설정해야 합니다.
- 체크포인트 기본값은 Flink 구성 (
execution.checkpointing.*) 과/또는 코드에서 구성할 수 있으며, 구성 키는 Flink 구성 참조에 문서화되어 있습니다.
import json
from typing import Any
from pyflink.common import Duration, Types
from pyflink.common.serialization import SimpleStringSchema
from pyflink.common.watermark_strategy import WatermarkStrategy, TimestampAssigner
from pyflink.common.configuration import Configuration
from pyflink.datastream import StreamExecutionEnvironment
from pyflink.datastream.functions import KeyedProcessFunction, RuntimeContext
from pyflink.datastream.state import ValueStateDescriptor
from pyflink.datastream.connectors import DeliveryGuarantee
from pyflink.datastream.connectors.kafka import (
KafkaSource,
KafkaOffsetsInitializer,
KafkaSink,
KafkaRecordSerializationSchema,
)
class EventTimeFromJson(TimestampAssigner):
"""
JSON 페이로드에서 event_time_ms 추출.
기대: {"user_id":"u1","event_time_ms":1710000000000,"event":"click",...}
"""
def extract_timestamp(self, value: str, record_timestamp: int) -> int:
try:
obj = json.loads(value)
return int(obj["event_time_ms"])
except Exception:
# 예외: 잘못 형성된 경우 기록 타임스탬프 (인제션) 사용
return record_timestamp
class RollingCount(KeyedProcessFunction):
def open(self, runtime_context: RuntimeContext):
desc = ValueStateDescriptor("rolling_count", Types.LONG())
self.count_state = runtime_context.get_state(desc)
def process_element(self, value: str, ctx: 'KeyedProcessFunction.Context'):
obj = json.loads(value)
current = self.count_state.value()
if current is None:
current = 0
current += 1
self.count_state.update(current)
# 보강된 이벤트 발행
obj["rolling_count"] = current
obj["event_time_ms"] = int(obj.get("event_time_ms", 0))
yield json.dumps(obj)
def build_env() -> StreamExecutionEnvironment:
# 클러스터/작업 기본값 (config.yaml 에서도 설정 가능)
cfg = Configuration()
cfg.set_string("state.backend.type", "rocksdb")
cfg.set_string("execution.checkpointing.dir", "s3://my-bucket/flink/checkpoints/realtime-sessions")
cfg.set_string("execution.checkpointing.interval", "60 s")
env = StreamExecutionEnvironment.get_execution_environment(cfg)
# PyFlink 에서, 커넥터 JAR 가 사용 가능해야 함; 필요시 env.add_jars(...) 사용.
# env.add_jars("file:///opt/flink/lib/flink-connector-kafka-<VERSION>.jar")
# 명시적으로 체크포인트 활성화 (작업은 기본값을 오버라이드 가능)
env.enable_checkpointing(60_000)
env.set_parallelism(4)
return env
def main():
env = build_env()
source = (
KafkaSource.builder()
.set_bootstrap_servers("kafka:9092")
.set_topics("events.raw")
.set_group_id("realtime-sessions-v1")
.set_value_only_deserializer(SimpleStringSchema())
.set_starting_offsets(KafkaOffsetsInitializer.earliest())
.build()
)
watermark_strategy = (
WatermarkStrategy.for_bounded_out_of_orderness(Duration.of_seconds(10))
.with_timestamp_assigner(EventTimeFromJson())
)
stream = (
env.from_source(source, watermark_strategy=watermark_strategy, source_name="kafka-events-raw")
.key_by(lambda s: json.loads(s)["user_id"])
.process(RollingCount(), output_type=Types.STRING())
)
record_serializer = (
KafkaRecordSerializationSchema.builder()
.set_topic("events.enriched")
.set_value_serialization_schema(SimpleStringSchema())
.build()
)
sink = (
KafkaSink.builder()
.set_bootstrap_servers("kafka:9092")
.set_record_serializer(record_serializer)
.set_delivery_guarantee(DeliveryGuarantee.EXACTLY_ONCE)
.set_transactional_id_prefix("realtime-sessions-txn")
.build()
)
stream.sink_to(sink)
env.execute("realtime-sessions-pyflink")
if __name__ == "__main__":
main()
위 API 호출은 PyFlink 의 KafkaSource 빌더 사용 패턴과 필수 필드와 일치합니다.
배달 보장에 대해, PyFlink 의 KafkaSinkBuilder 문서는 DeliveryGuarantee.EXACTLY_ONCE 에 대해 트랜잭션 ID 접두사를 설정해야 한다고 명시적으로 말합니다.
타임스탬핑/워터마킹에 대해, Flink 의 워터마크 문서는 이벤트 타임 처리를 위한 메커니즘으로 타임스탬프 할당과 워터마크 생성을 설명하며, PyFlink 는 이 모델을 거울하는 WatermarkStrategy API 를 제공합니다.
Go 통합: Kafka 프로듀서/컨슈머 + Flink REST 작업 제출
Go 는 Java/Python 과 같은 네이티브 Flink 작업 작성 API 를 갖지 않으므로, Go 시스템은 일반적으로 다음을 통해 Flink 와 통합합니다:
- Kafka (또는 다른 브로커) 를 인제션/이그레스로 사용.
- Flink REST API 를 운영 동작 (JAR 업로드, 작업 시작, 작업 상태 쿼리, 세이브포인트 트리거, 리스케일링) 에 사용.
Kafka 설정 및 로컬 개발 패턴에 대해서는 Apache Kafka 빠른 시작 - CLI 와 로컬 예시와 함께 Kafka 4.2 설치 을 참조하십시오.
Go Kafka 프로듀서/컨슈머 예시 (kafka-go)
package main
import (
"context"
"log"
"time"
"github.com/segmentio/kafka-go"
)
func main() {
ctx := context.Background()
// 프로듀서: 원시 이벤트 작성
writer := &kafka.Writer{
Addr: kafka.TCP("kafka:9092"),
Topic: "events.raw",
RequiredAcks: kafka.RequireAll,
}
defer writer.Close()
err := writer.WriteMessages(ctx, kafka.Message{
Key: []byte("user:u1"),
Value: []byte(`{"user_id":"u1","event_time_ms":1710000000000,"event":"click"}`),
Time: time.Now(),
})
if err != nil {
log.Fatal(err)
}
// 컨슈머: 보강된 이벤트 읽기
reader := kafka.NewReader(kafka.ReaderConfig{
Brokers: []string{"kafka:9092"},
Topic: "events.enriched",
GroupID: "go-debug-consumer",
MinBytes: 1e3,
MaxBytes: 10e6,
})
defer reader.Close()
msg, err := reader.ReadMessage(ctx)
if err != nil {
log.Fatal(err)
}
log.Printf("enriched key=%s value=%s\n", string(msg.Key), string(msg.Value))
}
이는 “배관” 코드이지만, 가장 일반적인 실용적 통합 표면입니다: Kafka 토픽은 Flink 와 커스텀 서비스 사이의 경계입니다.
Flink REST API: Go 로부터 JAR 업로드 및 실행
Flink 의 REST API 는 JobManager 웹 서버의 일부이며 기본적으로 포트 8081 에서 수신 대기합니다 (rest.port 를 통해 구성 가능).
디스패처를 위한 공식 OpenAPI 규격은 /jars/upload 를 포함하며 명시적으로 다음과 같이 밝힙니다:
- JAR 업로드는 멀티파트 데이터로 보내야 함
Content-Type헤더를application/x-java-archive로 설정해야 함-F jarfile=@path/to/flink-job.jar를 사용한 curl 예시 제공
JAR 를 업로드하기 위한 실용적인 Go 스니펫:
package flink
import (
"bytes"
"context"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
func UploadJar(ctx context.Context, flinkBaseURL, jarPath string) (*http.Response, error) {
f, err := os.Open(jarPath)
if err != nil {
return nil, err
}
defer f.Close()
var body bytes.Buffer
w := multipart.NewWriter(&body)
part, err := w.CreateFormFile("jarfile", "job.jar")
if err != nil {
return nil, err
}
if _, err := io.Copy(part, f); err != nil {
return nil, err
}
if err := w.Close(); err != nil {
return nil, err
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, flinkBaseURL+"/jars/upload", &body)
if err != nil {
return nil, err
}
// 중요: 멀티파트 바운더리
req.Header.Set("Content-Type", w.FormDataContentType())
// 일부 클라이언트는 규격의 curl 예시와 유사하게 "Expect:" 도 설정합니다.
req.Header.Set("Expect", "")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode >= 300 {
return resp, fmt.Errorf("upload failed: %s", resp.Status)
}
return resp, nil
}
이 코드는 /jars/upload 에 대한 REST API OpenAPI 설명, 멀티파트 요구사항 및 curl 참조에 의해 안내됩니다.
이전에 업로드된 JAR 를 실행하려면, Flink 는 /jars/{jarid}/run 을 노출하며 쿼리 매개변수 (및/또는 JSON 바디) 를 통해 프로그램 인수를 전달합니다.
운영적으로 유용한 엔드포인트 (자동화할 것):
- 작업 상태를 나열 및 검사하기 위한
/jobs와/jobs/{jobid} - 세이브포인트를 트리거하기 위한
/jobs/{jobid}/savepoints(비동기 트리거 + 폴링) - 리스케일링을 트리거하기 위한
/jobs/{jobid}/rescaling
코드 스니펫 비교 표: Flink 기반 플랫폼에서 PyFlink vs Go
| 관심사 | PyFlink (Python 작업) | Go (Flink 주변 서비스) |
|---|---|---|
| Flink 로직 작성 | DataStream/Table API 를 통한 네이티브 작성; 상태 + 타이머 지원 | 네이티브 Flink API 없음; Flink(Java/Python) 에서 로직 구현 및 외부 통합 |
| 커넥터/의존성 | pipeline.jars, add_jars, 또는 --jarfile 를 통해 커넥터 JAR 배포 필요 |
적용되지 않음 (Flink 내부에서 실행하지 않음), 하지만 Kafka/DB 클라이언트 관리 |
| 인제션/이그레스 | PyFlink 의 KafkaSource/KafkaSink 빌더 | Kafka 프로듀서/컨슈머 라이브러리; 표준 마이크로서비스 패턴 |
| 운영 자동화 | Flink REST 엔드포인트 호출 가능 | 종종 자동화 소유: JAR 업로드, 배포, 리스케일링, REST 를 통한 세이브포인트 트리거 |
DevOps 가이드: Apache Flink 모니터링, 스케일링, 백업 및 CI/CD
Kubernetes 와 VM 에서 Apache Flink 모니터링
Flink 는 Flink 구성 파일에서 메트릭 리포터를 구성하여 메트릭을 내보내는 것을 지원합니다; 이 리포터는 JobManager 와 TaskManagers 에서 인스턴스화됩니다.
Prometheus 의 경우, Flink 는 지원되는 Flink 버전 환경에서 metrics.reporter.prom.factory.class: org.apache.flink.metrics.prometheus.PrometheusReporterFactory 로 구성될 때 Prometheus 형식 메트릭을 노출합니다.
일반적으로 Kubernetes ServiceMonitors (Prometheus Operator) 또는 관리형 모니터링 스택과 함께 결합합니다.
스케일링: 병렬성, 슬롯, 연산자 기반 오토스케일링
Flink 의 스케줄링 모델은 태스크 슬롯을 통해 실행 리소스를 정의하며, 각 슬롯은 병렬 태스크 파이프라인을 실행할 수 있습니다.
수동 스케일링을 위해, REST API 는 작업 (/jobs/{jobid}/rescaling) 을 위한 리스케일링 엔드포인트를 비동기 작업으로 제공합니다.
Kubernetes 와 Flink Kubernetes Operator 를 사용 중이라면, 오퍼레이터 프로젝트는 워크로드가 상당히 변하는 경우 평가할 가치가 있는 “Flink Job Autoscaler"를 기능 세트의 일부로 홍보합니다.
백업 및 안전한 업그레이드: 체크포인트 및 세이브포인트
체크포인트는 자동 복구를 위해 존재하며 Flink 가 관리하고, 세이브포인트는 사용자가 주도하는 수명 주기 운영 (중지/재개/포크/업그레이드) 을 위해 사용됩니다.
SRE 관점에서:
- “장애를 통해 파이프라인을 계속 실행"하기 위해 체크포인트 사용.
- “상태를 잃지 않고 새 버전 배포"하기 위해 세이브포인트 사용.
Flink 의 REST API 는 또한 비동기적으로 세이브포인트를 트리거하는 것을 지원하며, 이는 GitOps 스타일 “배포 → 세이브포인트 트리거 → 업그레이드” 워크플로우에 유용합니다.
CI/CD: GitOps + Helm + REST 작업 제출
Kubernetes 의 경우:
- 오퍼레이터 설치와 FlinkDeployment CR 을 Git 에 유지하고, Argo CD/Flux 를 통해 배포하며, 빌드마다 컨테이너 이미지를 버전 관리하십시오. 오퍼레이터 Helm 문서는 명시적으로 “Argo CD 와 작업"을 논의합니다.
스탠드얼론/세션 클러스터의 경우:
- 불변 아티팩트 배포를 위한 Flink REST API JAR 업로드 및 실행 엔드포인트 사용.
또한 미묘하지만 가치 있는 보안/운영 토글에 주목하십시오: web.submit.enable 은 Web UI 를 통한 업로드를 통제하지만, 문서는 비활성화되어 있더라도 세션 클러스터가 여전히 REST 요청을 통해 작업 제출을 수락한다고 밝힙니다; 이는 CI/CD 자동화를 유지하면서 UI 표면을 강화할 때 관련이 있습니다.
Apache Flink 를 사용한 실시간 파이프라인을 위한 LLM/AI 통합 패턴
LLM 시스템은 종종 실시간 컨텍스트만큼 좋습니다. Flink 는 “항상 신선한” 피처, 임베딩, 행동 집계를 생성하는 컴포넌트로 LLM/AI 스택에 들어갑니다.
Flink 를 사용한 실시간 임베딩 파이프라인
일반적인 패턴은 다음과 같습니다:
- 사용자 동작/이벤트 인제션,
- 세션 및 선호도 집계,
- 임베딩 생성 작업 생성,
- 임베딩을 벡터 스토어 및/또는 피처 스토어에 작성.
PyFlink 의 의존성 관리 문서는 명시적으로 “기계 학습 예측"과 Python UDF 내부에서 ML 모델 로드 (원격 클러스터 실행을 위해) 를 언급하며, 이는 “Flink 연산자 내부의 온라인 추론” 접근법으로 직접 매핑됩니다.
추천 및 랭킹을 위한 온라인 피처 스토어 업데이트
Flink 의 키된 상태와 체크포인트 모델은 이벤트 간 연산자 상태를 유지하고 신뢰할 수 있게 복구하도록 구축되었습니다. 이는 하위 추천기가 필요한 연속 피처 계산 (롤링 속도, 카운트, 시간 감쇠된 메트릭) 과 자연스러운 매칭입니다.
AI 파이프라인을 위한 실용적 지연 시간/일관성 트레이드오프
아키텍처가 끝에서 끝으로 정확히 한 번 시맨틱스를 요구한다면 (예: 중복 피처 업데이트 또는 중복 청구 이벤트 방지), 싱크와 소스를 체크포인트와 트랜잭션 보장을 중심으로 구성할 것입니다.
Kafka 기반 스택의 경우 특히:
- Flink 의 Kafka 커넥터는 체크포인트가 활성화되고 배달 보장 옵션이 구성되면 정확히 한 번 보장을 제공할 수 있습니다.
- Kafka Streams 도 정확히 한 번 시맨틱스 (EOS) 를 지원하며, 이는 “AI 피처 파이프라인"이 Flink 클러스터가 아닌 애플리케이션 코드 내부에 머무를 만큼 작을 경우 관련이 있습니다.
“Flink 를 실시간 AI 컨텍스트 빌더로” 아키텍처 뷰

이 다이어그램은 Flink 의 핵심 원리에 근거합니다: 이벤트 타임 처리 (워터마크), 상태 백엔드 (state.backend.type 및 시스템 관리 로컬 상태), 그리고 장애 허용 및 운영을 위한 체크포인트/세이브포인트 메커니즘.