8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)

2,995 阅读8分钟

原文链接:blog.51cto.com/keep11/4717…

前几天给大家分享了一篇 ​ ​史上最全干货!Kubernetes 原理+实战总结(全文6万字,90张图,100个知识点)​​教程,详细讲解了 K8S 的架构设计、集群安装部署、资源管理、实战总结等知识点。

今天我们结合 ​​Kubernetes​​​ 和 ​​Flink 1.14​​ 版本,通过 图解 + 实战 教程,为大家全面讲解 Flink on K8S 的安装部署、运行原理、提交流程,并通过案例在 K8S 上提交 Flink 应用。

全文干货满满,大纲如下:

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_flink

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_Pod_02

1 Flink on docker

通过上篇文章我们了解到,Pod 是 K8S 集群进行管理的最小单元,程序要运行必须部署在容器中,而容器必须存在于 Pod 中。

一个 Pod 中可以存在一个或者多个容器,容器在创建时,会先新建 ​​containerd-shim​​,containerd-shim 会建出来最终的 docker 容器。所以 Flink 要被部署到 K8S集群上,需要先被加载到 Docker 镜像中。

1.1 Docker 启动 Flink 方式

本篇文章,我们使用 standalone的方式,详细讲解 如何在 docker 和 K8S 中中部署 Flink 集群。

可以回顾下 Flink 的启动方式。在传统的物理机或者虚拟机中部署 Flink,如果配置了免密和 slave 节点信息,我们可以使用 Flink 的 start-cluster.sh,一条命令启动整个集群。

但是在 docker 中,我们无法这样操作。在镜像中通常不会安装 ssh 服务。此外,docker 镜像的主进程要求使用前台的方式运行,否则该 container 会运行完毕退出。

所以 在 Docker 中需要单独启动 Flink job manager 和 task manager。

1.2 修改 Flink 配置

在 mini1 master 主节点根目录新建 lyz 文件夹。

  1. 因为 Flink Standalone 集群依赖 JDK 就可以,所以将 flink-1.14.0-bin-scala_2.11.tgz,jdk‐8u202‐linux‐x64.tar.gz 安装包下载好,放入 lyz 目录下,如下截图:

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_Pod_03

  1. 解压 flink-1.14.0-bin-scala_2.11.tgz,修改 conf 目录的配置文件:

    #1. 配置jobmanager rpc 地址jobmanager.rpc.address: 192.168.244.131#2. 修改taskmanager内存大小,可改可不改taskmanager.memory.process.size: 2048 m#3. 修改一个taskmanager中对于的taskslot个数,可改可不改taskmanager.numberOfTaskSlots: 4#修改并行度,可改可不改parallelism.default: 41.2.3.4.5.6.7.8.9.10.11.

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_docker_04

  1. 配置 master

    #修改主节点ip地址192.168.244.131:80811.2.

  2. 配置 work

    #修改从节点ip,因为是 standalone,所以主从一样192.168.244.1311.2.

  3. 将修改好的 flink 文件 重新打成 flink-1.14.0-bin-scala_2.11.tgz 压缩包

    tar -zcvf flink-1.14.0-bin-scala_2.11.tar.gz flink-1.14.0/1.

  4. 删除 解压后的 flink 文件夹,最终截图如下:

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_flink_05

1.3 Flink Dockerfile 镜像制作

由于新打的镜像不包含 Linux 的基础命令,所有我们需要使用 centos7 作为基础镜像。

  1. 在 lyz 文件夹下 编写 Dockerfile

    Dockerfile [root@mini1 lyz]# vi DockerfileFROM centos:7MAINTAINER lyzADD flink-1.14.0-bin-scala_2.11.tar.gz /rootADD jdk‐8u202‐linux‐x64.tar.gz /rootARG FLINK_VERSION=1.14.0ARG SCALA_VERSION=2.11ENV FLINK_HOME=/root/flink-1.14.0ENV PATH=FLINKHOME/bin:FLINK_HOME/bin:PATHENV JAVA_HOME=/root/jdk1.8.0_202ENV PATH=JAVAHOME/bin:JAVA_HOME/bin:PATHRUN cd FLINK_HOME \ && echo "env.java.home: /root/jdk1.8.0_202" >> FLINK_HOME/conf/flink-conf.yaml \ && echo "FLINK_HOME=/root/flink-1.14.0" >> /etc/profile \ && echo "PATH=FLINKHOME/bin:FLINK_HOME/bin:PATH" >> /etc/profile \ && echo "JAVA_HOME=/root/jdk1.8.0_202" >> /etc/profile \ && echo "PATH=JAVAHOME/bin:JAVA_HOME/bin:PATH" >> /etc/profile \ && source /etc/profileEXPOSE 80811.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.

上述文件将 JDK 和 Flink1.14.0的安装包加载到 Docker的根目录下,同时会在 Profile 中添加 JDK 和 Flink 的环境变量。

  1. 使用 Dockerfile 文件将压缩包打成镜像放入 docker 中

    docker build -t flink:1.14.0 . -f Dockerfile1.

如下图所示,已经打包成功

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_docker_06

  1. 通过 docker images 查看 docker 中的镜像,发现 flink 镜像已被加载成功。

    [root@mini1 lyz]# docker images1.

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_flink_07

1.4 Flink 集群启动

通过 docker run 命令,使用外部端口 9999 映射容器中 flink 集群的 8081 端口,将端口暴露在外边。

docker run -it -p 9999:8081 flink:1.14.0 /bin/bash1.

进入容器后,可以看到 jdk 和 flink 包全部存放在/root 根目录下。

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_docker_08

  1. 刷新环境配置

    [root@6437e358ba1d ~]# source /etc/profile1.

  2. 启动 jobmanager、taskmanager

    [root@6437e358ba1d ~]# cd flink-1.14.0/bin[root@6437e358ba1d bin]# ./jobmanager.sh startStarting standalonesession daemon on host 6437e358ba1d.[root@6437e358ba1d bin]# ./taskmanager.sh startStarting taskexecutor daemon on host 6437e358ba1d.[root@6437e358ba1d bin]# jps672 TaskManagerRunner712 Jps334 StandaloneSessionClusterEntrypoint1.2.3.4.5.6.7.8.9.10.11.12.13.

启动结果如下图所示:

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_flink_09

  1. 使用浏览器打开 flink 的管理页面 192.168.244.131:9999。

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_flink_10

1.5 Flink on docker 提交任务

使用 Flink 自带 WordCount.jar 提交应用任务,并输入外部映射的IP 和 端口。

[root@e7732776891e bin]# flink run -m 192.168.244.131:9999 \../examples/batch/WordCount.jar --input aaa.txt --output bbb.txt/1.2.

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_flink_11

2 Flink on k8s

2.1 Flink on k8s 流程分析

上述 Flink on Docker 跑通后,下面我们重点研究一下 Flink on K8S Session 的提交流程、安装部署、应用提交案例。

Flink On K8s Session 模式执行原理图如下:

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_Pod_12

在 K8S 集群上使用 Session 模式提交 Flink 作业的过程会分为 3 个阶段,首先在 K8S 上启动 Flink Session 集群;其次通过 Flink Client 提交作业;最后进行作业调度执行。具体步骤如下:

1 启动集群

  1. Flink 客户端使用 Kubectl 或者 K8s 的 Dashboard 提交 Flink 集群的资源描述文件,包含:

flink-configuration-configmap.yaml

jobmanager-service.yaml

jobmanager-rest-service.yaml #可选

jobmanager-deployment.yaml

taskmanager-deployment.yaml

通过这些文件请求 K8s Master。

  1. K8s Master 根据这些资源文件将请求分发给 Slave 节点,创建 Flink Master Deployment、TaskManager Deployment、ConfigMap、SVC 四个角色。同时初始化 Dispatcher 和 KubernetesResourceManager。并通过 K8S 服务对外暴露 Flink Master 端口。

以上两个步骤执行完后,Session模式集群创建成功。但此时还没有 JobMaster和 TaskManager,当提交作业需要执行时,才会按需创建。

2 作业提交

  1. Client 用户使用 Flink run 命令,通过指定 Flink Master 的地址,将相应任务提交上来,用户的 Jar 和 JobGrapth 会在 Flink Client 生成,通过 SVC 传给 Dispatcher。

  2. Dispatcher 收到 JobGraph后,会为每个作业启动一个JobMaster,将JobGraph 交给JobMaster进行调度。

3 作业调度

  1. JobMaster 会向 KubernetesResourceManager 申请资源,请求Slot。

  2. KubernetesResourceManager 从 K8S 集群分配 TaskManager。每个 TaskManager 都是具有唯一标识的 Pod。KubernetesResourceManager 会为 TaskManager 生成一份新的配置文件,里面有 Flink Master 的 service name 作为地址,保障在 Flink Master failover 后,TaskManager 仍然可以重新连接上。

  3. K8S 集群分配一个新的 Pod 后,在上面启动 TaskManager。

  4. TaskManager 启动后注册到 SlotManager。

  5. SlotManager 向 TaskManager 请求 Slot。

  6. TaskManager 提供 Slot 给 JobManager,然后任务被分配到 Slot 上运行。

2.2 Flink on k8s Session 集群部署

通过上述流程图,我们已经详细了解了 Flink on K8S Session 模式的提交流程,接下来根据提交流程完成集群部署。

本文采用三节点进行部署,mini1 代表 Master 节点,mini2、mini3 代表 node 节点

总共需要在 mini1 节点创建 5 个文件,其中一个为可选项

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_docker_13

截图如下:

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_flink_14

2.2.1 创建 ConfigMap

ConfigMap 是一个 K-V 数据结构。通常的用法是将 ConfigMap 挂载到 Pod ,作为配置文件提供 Pod 里新的进程使用。在 Flink 中可以将 Log4j 文件或者是 flink-conf 文件写到 ConfigMap 里面,在 JobManager 或者 TaskManger 起来之前将它挂载到 Pod 里,然后 JobManager 去读取相应的 conf 文件,加载其配置,进而再正确地拉起 JobManager 一些相应的组件。

# 新建根目录 k8s_flink[root@mini1 ~]# mkdir k8s_flink# 进入根目录[root@mini1 ~]# cd k8s_flink/# 新建 flink-configuration-configmap.yaml[root@mini1 k8s_flink]# vim flink-configuration-configmap.yamlapiVersion: v1kind: ConfigMapmetadata:  name: flink-config  namespace: lyz  labels:    app: flinkdata:  flink-conf.yaml: |+    jobmanager.rpc.address: 192.168.244.131    taskmanager.numberOfTaskSlots: 4    blob.server.port: 6124    jobmanager.rpc.port: 6123    taskmanager.rpc.port: 6122    queryable-state.proxy.ports: 6125    jobmanager.memory.process.size: 1600m    taskmanager.memory.process.size: 2048m    taskmanager.numberOfTaskSlots: 4    parallelism.default: 41.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.

2.2.2 创建 Service

通过Serveice 对外暴露服务。Service 可以看作是一组同类 Pod 对外的访问接口。借助 Service,应用可以方便地实现服务发现和负载均衡。

# 创建 jobmanager-service.yaml[root@mini1 k8s_flink]# vim jobmanager-service.yamlapiVersion: v1kind: Servicemetadata:  name: flink-jobmanager  namespace: lyzspec:  type: ClusterIP  ports:  - name: rpc    port: 6123  - name: blob-server    port: 6124  - name: webui    port: 8081  selector:    app: flink    component: jobmanager1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.

2.2.3 创建 rest Service(可选)

可选的 service,该 service 将 jobmanager 的 rest 端口暴露为公共 Kubernetes node 的节点端口

# 创建 jobmanager-rest-service.yaml[root@mini1 k8s_flink]# vim jobmanager-rest-service.yamlapiVersion: v1kind: Servicemetadata:  name: flink-jobmanager-rest  namespace: lyzspec:  type: NodePort  ports:  - name: rest    port: 8081    targetPort: 8081    nodePort: 30081  selector:    app: flink    component: jobmanager1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.

2.2.4 创建 jobmanager session deployment

创建 jobmanager 运行的 pod 控制器

# 创建 jobmanager-session-deployment.yaml[root@mini1 k8s_flink]# vim jobmanager-session-deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata:  name: flink-jobmanager  namespace: lyzspec:  replicas: 1  selector:    matchLabels:      app: flink      component: jobmanager  template:    metadata:      labels:        app: flink        component: jobmanager    spec:      containers:      - name: jobmanager        image: flink:1.14.0        args: ["jobmanager"]        ports:        - containerPort: 6123          name: rpc        - containerPort: 6124          name: blob-server        - containerPort: 8081          name: webui        livenessProbe:          tcpSocket:            port: 6123          initialDelaySeconds: 30          periodSeconds: 60        volumeMounts:        - name: flink-config-volume          mountPath: /opt/flink/conf        securityContext:          runAsUser: 9999        volumes:      - name: flink-config-volume        configMap:          name: flink-config          items:          - key: flink-conf.yaml            path: flink-conf.yaml1.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.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.

2.2.5 创建 taskmanager session deployment

创建 taskmanager 运行的 pod 控制器

# 创建 taskmanager-session-deployment.yaml[root@mini1 k8s_flink]# vim taskmanager-session-deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata:  name: flink-taskmanager  namespace: lyzspec:  replicas: 2  selector:    matchLabels:      app: flink      component: taskmanager  template:    metadata:      labels:        app: flink        component: taskmanager    spec:      containers:      - name: taskmanager        image: flink:1.14.0        args: ["taskmanager"]        ports:        - containerPort: 6122          name: rpc        - containerPort: 6125          name: query-state        livenessProbe:          tcpSocket:            port: 6122          initialDelaySeconds: 30          periodSeconds: 60        volumeMounts:        - name: flink-config-volume          mountPath: /opt/flink/conf/        securityContext:          runAsUser: 9999        volumes:      - name: flink-config-volume        configMap:          name: flink-config          items:          - key: flink-conf.yaml            path: flink-conf.yaml1.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.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.

2.3 Flink on k8s Session 集群启动

  1. 分别执行下面创建的五个文件:

    Configuration 和 service 的定义[root@mini1 k8s_flink]# kubectl create -f flink-configuration-configmap.yaml[root@mini1 k8s_flink]# kubectl create -f jobmanager-service.yaml[root@mini1 k8s_flink]# kubectl create -f jobmanager-rest-service.yaml# 为集群创建 deployment[root@mini1 k8s_flink]# kubectl create -f jobmanager-session-deployment.yaml[root@mini1 k8s_flink]# kubectl create -f taskmanager-session-deployment.yaml1.2.3.4.5.6.7.8.

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_flink_15

  1. 查看 svc,pod 服务是否启动成功

    [root@mini1 k8s_flink]# kubectl get svc,pods -n lyz -o wide1.

通过截图可以看到Flink on K8S Session 集群已经全部启动成功,启动 2个 taskmanager 启动在 mini2,mini3 服务器上。jobmanager 启动在mini3 服务器上。对外暴露的端口号是30081。

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_docker_16

  1. 通过 DashBoard Web 服务查看启动详情,截图如下:

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_docker_17

通过 DashBoard Web 可以看到服务都正常启动,登录 Flink WEB 页面查看详情 192.168.244.131:30081

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_flink_18

2.4 Flink on k8s 应用提交

通过Flink 官方提供的命令进行应用提交

./bin/flink run -m 192.168.244.131:8081 ./examples/batch/WordCount.jar --input aaa.txt --output bbb.txt/1.

8000字详解Flink on K8S 应用提交流程(超详细,建议收藏~)_flink_11