4. Flink on Kubernetes实战:从零搭建到滚动升级

Kubernetes 现在已经是 Flink 部署的“标配”了。我最早接触 Flink on K8s 是在 2020 年,那时候还流行手动写 Deployment 和 Service,后来 Flink Operator 出来之后,整个体验好了不止一个档次。这一章,我们就从 K8s 集群搭建开始,一步步走到 Flink Operator 部署、配置文件编写,最后演示滚动升级。

本章核心脉络: 搭建 K8s 环境 → 安装 Flink Operator → 编写 FlinkDeployment 配置 → 实现滚动升级

4.1 K8s 集群搭建:别在生产环境用 minikube

我个人习惯用 kubeadm 来搭集群。minikube 和 kind 更适合本地开发,生产环境还是老老实实用 kubeadm 或者托管的云服务。

这里我给出一个最小化集群的搭建步骤:

  1. 节点准备:至少 1 台 Master + 2 台 Worker,操作系统 Ubuntu 20.04+ 或 CentOS 7.9+。
  2. 安装容器运行时:我推荐 containerd,Docker 虽然也能用,但 containerd 更轻量。
  3. 安装 kubeadm、kubelet、kubectl:版本要统一,我一般用 1.27 或 1.28。
  4. 初始化 Master 节点:kubeadm init --pod-network-cidr=10.244.0.0/16
  5. 安装网络插件:Flannel 或 Calico,我习惯用 Flannel,简单。
  6. Worker 节点加入:用 kubeadm join 命令。
小技巧: 初始化时如果遇到 kubelet 启动失败,先检查 /var/log/messages 或者 journalctl -u kubelet。我曾经因为 swap 没关,卡了半小时。

集群搭好后,验证一下:

kubectl get nodes
NAME              STATUS   ROLES           AGE   VERSION
k8s-master        Ready    control-plane   12m   v1.28.2
k8s-worker-01     Ready    <none>          8m    v1.28.2
k8s-worker-02     Ready    <none>          8m    v1.28.2

看到所有节点都是 Ready 状态,就说明集群没问题了。

4.2 Flink Operator 部署:别再用 Helm 踩坑了

Flink Operator 本质上是一个 Kubernetes 的 自定义控制器,它监听 FlinkDeployment 这个 CRD(自定义资源),然后自动帮你管理 Flink 集群的生命周期。

部署方式有两种:

方式 命令 适用场景
Helm Chart helm install flink-operator flink-operator/ 生产环境,参数可定制
YAML 直接部署 kubectl apply -f flink-operator.yaml 快速验证,测试环境

我个人推荐用 Helm,因为可以方便地调整资源限制和日志配置。但要注意,Helm 版本和 Operator 版本要匹配,我曾经因为用了最新的 Helm 3.12 搭配旧版 Operator,结果 CRD 注册失败。

安装命令如下:

helm repo add flink-operator https://downloads.apache.org/flink/flink-kubernetes-operator-1.8.0/
helm install flink-kubernetes-operator flink-operator/flink-kubernetes-operator

安装完成后,检查 Pod 状态:

kubectl get pods -n flink
NAME                                         READY   STATUS    RESTARTS   AGE
flink-kubernetes-operator-7d8f9c6b9c-abc12   1/1     Running   0          2m

看到 Running 就说明 Operator 已经就绪了。

4.3 配置文件编写:FlinkDeployment 才是核心

Flink Operator 的核心资源是 FlinkDeployment。你想想看,以前我们部署 Flink 集群,要写 Deployment、Service、ConfigMap、Ingress……现在只需要一个 YAML 文件。

下面是一个典型的配置文件:

apiVersion: flink.apache.org/v1beta1
kind: FlinkDeployment
metadata:
  name: my-flink-job
spec:
  image: flink:1.17.1
  flinkVersion: v1_17
  serviceAccount: flink
  jobManager:
    resource:
      memory: "2048m"
      cpu: 1
  taskManager:
    resource:
      memory: "4096m"
      cpu: 2
  job:
    jarURI: local:///opt/flink/examples/streaming/WordCount.jar
    parallelism: 4
    upgradeMode: stateless

这里有几个关键点:

  • image:Flink 镜像版本,要和 flinkVersion 对应。我踩过坑,镜像用 1.17.0,但 flinkVersion 写 v1_16,结果 JobManager 启动失败。
  • upgradeMode:升级模式,有 stateless、savepoint、last-state 三种。生产环境我建议用 savepoint,保证状态不丢。
  • job.parallelism:并行度,不要超过 TaskManager 的总 slot 数。
注意: 如果 upgradeMode 设置为 savepoint,必须配置 spec.job.savepointTriggerNonce 来触发新的 savepoint,否则升级时不会自动保存状态。

4.4 滚动升级:零停机才是真本事

滚动升级是 Flink Operator 最实用的功能之一。你只需要修改 FlinkDeployment 的配置,然后 kubectl apply,Operator 就会自动完成升级。

升级流程大致如下:

  1. Operator 检测到配置变更。
  2. 如果 upgradeMode 是 savepoint,先触发 savepoint。
  3. 停止旧的 JobManager 和 TaskManager。
  4. 启动新的 JobManager,从 savepoint 恢复。
  5. 启动新的 TaskManager,开始消费数据。

我曾经在生产环境做过一次升级,从 Flink 1.16 升级到 1.17,整个过程大概 3 分钟,业务没有感知。但要注意,如果状态量很大(比如几百 GB),savepoint 的时间会很长,建议提前规划好维护窗口。

下面是一个升级示例:

# 修改镜像版本
kubectl patch flinkdeployment my-flink-job --type='json' \
  -p='[{"op": "replace", "path": "/spec/image", "value": "flink:1.17.2"}]'

或者直接编辑 YAML:

kubectl edit flinkdeployment my-flink-job

升级过程中,可以用 kubectl describe flinkdeployment my-flink-job 查看状态:

Status:
  Job Status:
    State:  RUNNING
    Upgrade History:
      - Mode:          SAVEPOINT
        Savepoint:     s3://my-bucket/savepoints/savepoint-123456
        State:         SUCCEEDED
        Time:          2024-03-15T10:30:00Z

看到 State: SUCCEEDED,就说明升级成功了。

4.5 避坑指南:我踩过的三个坑

  • 坑一:镜像拉取策略。默认是 IfNotPresent,如果你改了镜像 tag 但没改版本号(比如都用 latest),Pod 不会拉取新镜像。我建议显式设置 imagePullPolicy: Always。
  • 坑二:资源限制。TaskManager 的 memory 如果设置得太小,Flink 会频繁 GC 甚至 OOM。我一般给 TaskManager 留 20% 的余量,比如实际需要 3GB,我就设 4GB。
  • 坑三:网络插件冲突。如果 K8s 集群用了 Calico,Flink Operator 的 Pod 之间可能无法通信。解决办法是检查 Calico 的 IPIP 模式是否开启,如果开启,改成 VXLAN 模式。

4.6 本章小结

这一章我们走完了 Flink on Kubernetes 的完整流程:从 K8s 集群搭建,到 Flink Operator 部署,再到配置文件编写和滚动升级。说白了,Flink Operator 把原来需要手动管理的复杂操作都自动化了,你只需要关注业务逻辑和配置。

嗯,这里要提醒一句:生产环境一定要先做压力测试,别直接上大流量。我见过有人没做压测,结果升级后 TaskManager 资源不够,整个集群挂了。

Flink on Kubernetes 部署流程 K8s 集群搭建 Flink Operator 部署 FlinkDeployment 配置 滚动升级 验证与监控 关键说明 • 至少 1 Master + 2 Worker • 推荐 kubeadm 搭建 • 使用 Helm 安装 • 注意版本兼容性 • 核心是 FlinkDeployment • 配置 image、resource • 支持 stateless/savepoint • 零停机升级 • 检查 Pod 状态 • 监控 savepoint 进度 • 生产环境先压测 • 注意资源余量