Flink 1.10 Container 环境实战

做者 | 唐云(茶干),阿里巴巴高级开发工程师
整理 | 张壮壮(Flink 社区志愿者)node

摘要:本文根据 Apache Flink 系列直播整理而成,由阿里巴巴高级开发工程师唐云(茶干)分享。主要内容以下:docker

  1. 容器管理系统的演变
  2. Flink on K8S intro
  3. Flink on K8S实战分享
  4. Demo

Tips:点击下方可查看更多 1.10 系列直播视频~ api

1.10系列直播:
https://ververica.cn/develope...bash

本文第一部分将简明扼要地介绍容器管理系统的演变;第二部分是 Flink on K8S 简介,包括集群的部署模式调度原理等等;第三部分是咱们这一年以来关于 Flink on K8S 的实战经验分享,介绍咱们遇到的问题、踩过的坑;最后一部分是 Demo,将手把手演示集群部署、任务提交等等。网络

容器管理系统的演变

640 1.jpg

首先是以一个 Kubernetes 非内核开发人员的角度去探讨其和 YARN 之间的关系。众所周知,Apache Hadoop YARN 多是在国内用途最广的一个调度系统,主要缘由在于 Hadoop HDFS 在国内或者是在整个大数据业界,是一个使用最普遍的存储系统。所以,基于其上的 YARN 也天然而然成为了一个广为使用的一个调度系统,包括早期的 Hadoop MapReduce。随着 YARN 2.0 以后 Framework 的开放,Spark on YARN 以及 Flink on YARN 也能够在 YARN 上进行调度。架构

固然 YARN 自己也存在必定的局限性。app

  • 如资源隔离,由于 YARN 是以 Java 为基础开发的,因此它不少资源方面的隔离有一些受限。
  • 另外对 GPU 支持不够,固然如今的 YARN 3.0 已经对 GPU 的调度和管理有必定支持,但以前版本对GPU 支持不是很好。

因此在 Apache 基金会以外,CNCF 基金会基于 Native Cloud 调度的 Kubernetes 出现了。运维

从开发人员角度来看,我认为 Kubernetes 是更像一个操做系统,能够作很是多的事情。固然这也意味着 Kubernetes 更复杂、学习曲线比较陡峭,你须要理解不少定义和概念。相比之下,YARN 主要管理资源调度部分,对整个操做系统而言,它体量要小不少。固然,不可置否,它也是一个大数据生态的先驱。接下来我会将焦点放在 Kubernetes 上面,探讨从 YARN 的 Container 向 Kubernetes 的 Container(或者 POD)的演变过程当中,咱们总结的经验和教训。elasticsearch

Flink on K8S intro

部署集群

640 2.jpg

上图展现了 Flink Standalone Session on K8S 上调度流程图,蓝色虚线框内是运行在 Kubernetes 集群内部组件,灰色框的是 Kubernetes 原生所提供的命令或组件,包括 kubectl 和 K8S Master。左侧罗列了 Flink 官方文档上提供的5个 yaml 文件,能够用来在 K8S 上部署最简单的 Flink Standalone Session 集群。tcp

启动集群所须要执行的 kubectl 命令以下:

kubectl create -f flink-configuration-configmap.yaml
kubectl create -f jobmanager-service.yaml
kubectl create -f jobmanager-deployment.yaml
kubectl create -f taskmanager-deployment.yaml
  • 首先,它会向 K8S Master 申请建立 Flink ConfigMap,在 ConfigMap 中提供了 Flink 集群运行所须要的配置,如:flink-conf.yaml 和 log4j.properties;
  • 其次,建立 Flink JobManager 的 service,经过 service 来打通 TaskManager 和 JobManager之间的联通性;
  • 而后,建立 Flink Jobmanager 的 Deployment,用来启动 JobMaster,包含的组件有 Dispatcher 和 Resource manager。
  • 最后,建立 Flink TaskManager 的 Deployment,用来启动 TaskManager,由于 Flink 官方 taskmanager-deployment.yaml 示例中指定了2个副本,因此图中展现了2个 TM 节点。

另外,还有一个可选操做是建立 JobManager REST service,这样用户就能够经过REST service 来提交做业。

以上就是 Flink Standalone Session 集群的概念图。

做业提交

下图展现了使用 Flink client 向该 Standalone Session 集群提交做业的流程细节。

640 3.jpg

使用 Flink client 提交做业的命令是:

./bin/flink run -m : ./examples/streaming/WordCount.jar

其中 -m 所需的参数 public-node-IP 和 node-port 正是经过 jobmanager-service.yaml 所暴露 REST service 的 IP 和端口。执行该命令就能够向集群提交一个 Streaming WordCount 做业。此流程与 Flink Standalone 集群所运行的环境无关,不管是运行在 K8S 之上,仍是运行在物理机之上,提交做业的流程是一致的。

Standalone Session on K8S 的优缺点:

  • 优势是无需修改 Flink 源码,仅仅只需预先定义一些yaml 文件,集群就能够启动,互相之间的通讯彻底不通过 K8S Master;
  • 缺点是资源须要预先申请没法动态调整,而 Flink on YARN 是能够在提交做业时声明集群所需的 JM 和 TM 的资源。

所以社区在 Flink 1.10 进程中,也是咱们阿里负责调度的同窗,贡献的整个 native 计算模式的Flink on K8S,也是咱们过去一年在实战中所总结出来的 Native Kubernetes。

640 4.jpg

它最大的区别就是当用户经过 Flink client 提交做业时,整个集群的 JobMaster 经过 K8sResourceManager 向 K8S Master 动态申请资源去建立运行 TaskManager 的 POD,而后 TaskManager 再与 JobMaster 互相之间通讯。有关 Native Kubernetes的细节请参考王阳所分享的《Running Flink on Kubernetes natively》。

总而言之,咱们能够像使用 YARN 同样的去使用 K8S,相关的配置项也尽可能作到与 YARN 相似。不过为了方便讲解,接下来我会使用 Standalone Session集群来展现,而下文介绍的部分功能,在 Flink 1.10 还未实现,预计在 Flink 1.11 完成。

Flink on K8S 实战分享

日志搜集

当咱们在 Flink on K8S 上运行一个做业,有一个功能性问题没法回避,就是日志。若是是运行在 YARN 上,YARN 会帮咱们作这件事,例如在 Container 运行完成时,YARN 会把日志收集起来传到 HDFS,供后期查看。可是 K8S 并未提供日志搜集与存储,因此咱们能够有不少选择去作日志(收集、展现)的事情。尤为是看成业由于异常致使 POD 退出,POD 退出后日志会丢失,这将致使异常排查变得很是困难。

若是是 YARN,咱们能够用命令 yarn logs -applicationId <applicationId> 来查看相关日志。可是在 K8S 上怎么办?

目前咱们比较常见的作法是使用 fluentd 来搜集日志,且已经在部分用户生产环境有所应用。

640 5.png

fluentd 也是一个 CNCF 项目,经过配置一些规则,好比正则匹配,就能够将 logs 目录下的.log 、.out 及 *.gc 日志按期的上传到 HDFS 或者是其余分布存储文件系统,以此来解决咱们的日志收集功能。这也意味着在整个 POD 的里面,除了 TM 或 JM 以外,咱们须要再启动一个运行着 fluentd 进程的 Container(sidecar)。

固然,还有其余办法,好比一个不须要再增长 Container 的方式:咱们可使用logback-elasticsearch-appender 将日志发到 Elasticsearch。其实现原理是经过Elasticsearch REST API 支持的 scoket stream 方式,将日志直接写入Elasticsearch。

相比于以前的 fluentd 来讲,优势是不须要另启一个 Container 来专门收集日志,缺点是没法搜集非 log4j 日志,好比 System.out、System.err 打印的日志,尤为是做业发生 core dump,或者发生 crash 时,相关日志会直接刷到System.out、System.err 里面。从这个角度来看使用 logback-elasticsearch-appender 写入 Elasticsearch 的方案也不是那么完美了。相比之下,fluentd 能够自由地配置各式各样的策略来搜集所须要的日志信息。

Metrics

日志能够帮助咱们观察整个做业运行的状况,尤为是在出问题以后,帮助咱们回溯场景,进行一些排查分析。另一个老生常谈也很是重要的问题就是 Metrics 和监控。业界已经有不少种监控系统解决方案,好比在阿里内部使用比较多的 Druid、开源InfluxDB 或者商用集群版 InfluxDB、CNCF 的 Prometheus 或者 Uber 开源的 M3 等等。

而后咱们这里直接拿 Prometheus 进行讨论,由于 Prometheus 与 Kubernetes 均属于 CNCF 项目,在指标采集领域具有先天优点,从某种程度上来讲Prometheus 是 Kubernetes 的一个标配监控采集系统。Prometheus 能够实现功能不少,不只能够去作报警,也能够定一些规则作按期的多精度管理。

640 6.jpg

可是咱们在实际生产中发现一个问题,Prometheus 的水平拓展支持不够好。你们能够看到上图右侧部分,Prometheus 所谓的联邦分布式架构其实就是多层结构,一层套一层,而后它上面节点负责路由转发去下一层查询结果。很明显,不管部署多少层,越往上的节点越容易成为性能瓶颈,并且整个集群的部署也很麻烦。从咱们接触到的用户来讲,在规模不是很大的时候,单点的 Prometheus 就能够承担绝大部分的监控压力,可是一旦用户规模很大,好比几百个节点的 Flink 集群,咱们就会发现单点 Prometheus 会成了一个很是大的性能瓶颈,没法知足监控需求。

咱们怎么作到呢?

640 7.jpg

咱们首先对不一样 Flink 做业的 metrics 作了一致性哈希,固然确定不会是一个做业的metrics 只发了一个 Prometheus,而是面向做业里面不一样 scope 的 metrics,Flink的 metrics 力度从大到小分别是:

  • JobManager/TaskManager metrics
  • Job metrics(checkpoint次数、size和fail次数)
  • task metrics
  • operator metrics(每秒处理多少条record、receive的bytes数目)。

如今方案是先根据不一样的 scope 去作一致性哈希,发到不一样的 Prometheus 上,以后再配合 Thanos (灭霸,对就是在《复仇者联盟3》里面打完响指后去种瓜的农夫)。我我的理解 Thanos 是一个能够支持分布式查询 Prometheus 的加强组件。因此整个 Prometheus 架构,演变成单个 Prometheus 实例所在的 container 会搭载一个 Thanos sidecar。

固然整个架构会致使一些限制,这个限制也是咱们作一致性哈希的缘由,是由于当 Thanos 与 Prometheus 所搭配部署时,若是有一段 metrics数据,由于某些缘由致使它既在 Prometheus A 里面,也在 Prometheus B 里面,那么在 Thanos query 里边它会有必定规则,对数据进行 abandon 处理,即去掉一个以另一个为准, 这会致使 UI 上 metrics 图表的线是断断续续的,致使体验很不友好,因此咱们就须要一致性哈希,并经过 Thanos 去作分布式查询。

可是整个方案实际运行中仍是有一些性能问题,为何 Prometheus 在不少业务级 metrics 上去表现其实很不错,而在 Flink 或者是这种做业级别上,它表现的会有一些压力呢?其实很重要的一个缘由是做业 metrics 变化是很是急剧的。相比于监控HDFS、Hbase,这些组件的指标是有限的、维度也不高。咱们用一个查询场景来解释维度的概念,例如说咱们要查询在某个 hosts 的某个 job 的某个 task 上全部的 taskmanager_job_task_buffers_outPoolUsage,这些所说的查询条件,也就是用 tag 去作查询过滤,那么就有一个问题是 Flink 的 taskAttempId,这个是一个很是不友好的一个 tag,由于它是一个 uuid 且每看成业发生 failover 的时候,taskAttempId 就会发生变化。

若是做业不断 failover,而后不停地持久化新的 tag 到 Prometheus,若是 Prometheus 后面接的 DB 须要对 tag 构建一个索引的话,那么索引的压力会很是大。例如 InfluxDB 的压力就会很是大,可能会致使整个内存 CPU 不可用,这样的结果很是可怕。因此,咱们还须要借助于社区在 report 这边把一些高维度的 tag 过滤掉,有兴趣的同窗能够关注下 FLINK-15110。

性能

■ 网络性能

咱们先介绍 network 性能。不管你用 CNI 或者 Kubernetes 的网络化插件,不可避免的会出现网络性能损耗。比较常见的 flannel,在一些测试项目上会有百分之30左右的性能损耗。也不是很稳定,咱们使用时发现做业常常会报PartitionNotFoundException: Partition xx@host not found,也就是下游没法获取到上游的 Partition。

640 8.jpg

固然,你能够在 Flink 层去增大一些网络容错性,例如把 taskmanager.network.request-backoff.max 调到300秒,默认是10秒,而后把akka 的 timeout 调大一点。

还有一个让咱们特别头疼的问题:

640 9.jpg

咱们发现做业运行过程当中常常遇到 Connection reset by peer 问题,缘由是 Flink 在设计时,对网络的稳定要求很高。由于要保证 Exactly once,若是数据传输失败,那么 Flink 就要 fail 整个 task 并从新启动,而后咱们会发现常常会出现使人头疼的Connection reset by peer 问题,咱们有几个的解决方案方式:

  • 不要有异构网络环境(尽可能不要跨机房访问)
  • 云服务商的机器配置网卡多队列 (将实例中的网络中断分散给不一样的CPU处理,从而提高性能)
  • 选取云服务商提供的高性能网络插件:例如阿里云的 Terway
  • Host network,绕开 k8s 的虚拟化网络(须要必定的开发量)

第一个要排查的问题就是集群不要有异构网络环境,由于有可能 Kubernetes 的宿主机在不一样机房,而后跨机房访问遇到网络抖动的时候都就会比较头疼。而后是云服务商机器配置网卡多队列,由于 ECS 虚拟机,它是须要耗必定的 CPU 去作网络虚拟化。那么若是网卡不配置成多队列的话,有可能网卡只用了1到2个 core,而后虚拟化会把这2个 core 用光,用光的话会致使丢包,也就会遇到这种比较头疼的Connection reset by peer 问题。

还有一种方案是选取云服务商提供的高性能网络插件,固然这须要云服务商支持,好比阿里云的 Terway,Terway 对外描述是能够支持与 host network 同样的性能,而不是像 flannel 会带来必定的性能损耗。

最后一种,若是没法使用 Terway,咱们能够用 host network 来绕开 K8S 虚拟化网络。不过这种方案首先是对 Flink 有一些开发工做,其次是若是你已经使用了Kubernetes,却还要使用 host network,从某种意义上来讲,有一点奇怪,很不符合 K8S style。固然咱们也在一些没法用 Terway 的机器,而后又遇到这个头疼的问题是,也提供了相应工程,部署时采用 host network,而不是使用 overlay 的flannel 方案。

■ 磁盘性能

接下来谈磁盘性能,前文提到过:全部虚拟化的东西都会带来一些性能损耗。对于 RocksDB 须要读写本地磁盘的场景,就很头疼,由于 overlay 的 file system 会有大概30%的性能损耗。

640 10.jpg

那怎么办呢?咱们选择一种方式,就是使用 hostPath。简单来讲,POD 能够访问到宿主机的物理盘。上图右侧部分就定义了 hostPath,固然须要预先保证 Flink 镜像的用户是具有访问宿主机目录权限,因此最好把这里目录改为 777 或者 775。

你们若是想用这个功能的话,能够查看 Flink-15656,它提供一个 POD 的 template,意味着你能够自行调整。由于咱们知道 K8S 的功能特别多,特别繁杂,Flink 不可能为了每个功能都去作个适配。你能够在 template 里面,好比定义 hostPath,而后你所写 POD 的就能够基于这个模板下面的 hostPath 就能够去访问目录了。

OOM killed

OOM killed 也是个比较头疼的问题。由于在容器环境下,部署服务的时候,咱们须要预先设置 POD 所需 memory 和 CPU 的资源,而后 Kubernetes 会指定配置去相关 node (宿主机)上面申请调度资源。申请资源除了要设置 request 以外,还有会设置 limit——通常都会打开 limit——它会对申请的 memory 和 CPU 进行限制。

好比说 node 的物理内存是 64G,而后申请运行8个8G内存的 POD,看着好像没有问题,可是若是对这8个 POD的没有任何 limit的话,假如每一个用到10G,那么就会致使 POD 之间出现资源竞争,现象是一个 POD 运行正常另一个 POD 突然被 Kill,因此就要作一个memory limit。memory limit 带来的问题是:POD 莫名其妙退出,而后查看 Kubernetes 的 event 发现是由于 POD 被 OOM killed 了。我相信若是用过Kubernetes 的同窗确定遇到过相关问题。

咱们是怎么排查的呢?

640 11.jpg

第一个是咱们能够在 JVM 端开启 native 内存追踪,能够按期去查看,但这只能看到 JVM 所申请的 native 内存,包括如 Metaspace,非 JVM 就没法分析了;还有一个就是万能的 Jemalloc 和 jeprof 去作按期 dump 内存进行分析。

老实说第2个功能咱们可能用的比较少,由于咱们之前在 YARN 上面会这样用,就是说发现有的做业内存很大,由于 JVM 对最大内存会作限制,因此确定是 native 这边出的问题,那么究竟是哪一个 native 出问题,就能够 Jemalloc+jeprof 做内存分析。好比咱们以前遇到过用户本身去解析 config 文件,结果每次都要解压一下,最后把内存撑爆了。

固然这是一种引发 OOM 的场景,但更多的多是 RocksDB 引起 OOM,固然若是是使用了 RocksDB 这种省 native 内存的 state backend。因此咱们在 Flink 1.10 作了一个功能贡献给社区,就是对 RocksDB 的 memory 进行管理,由参数state.backend.rocksdb.memory.managed 控制是否进行管理,默认是开启。

咱们下面这个图是什么呢?

640 12.jpg

是在 RocksDB 没有使用 memory 控制,这里一共定了4个 state,分别是 value、list、map 和 window,你们能够看到最顶端的线是 block cache usage 加上RocksDB 的 write buffer 就构成了 RocksDB 当前所使用总内存的大小。你们看到这4个加起来的话差很少超过400M了。

缘由是 Flink 目前的 RocksDB 对 state 数没有限制,一个 state 的就是一个 Column Family,而 Column Family 就会额外独占所用的 write buffer 和 block cache。默认状况下,一个 Column Family 最多拥有2个64MB write buffer 和一个 8MB block cache,你们能够算一算,一个 state 就是136MB,四个 state 就是544MB。

若是咱们开启了 state.backend.rocksdb.memory.managed,咱们会看到4个 state所使用的 block cache 折线走势基本一致:

640 13.jpg

为何呢?是由于实现了 cache share 功能。就是说,咱们在一个 state 里面咱们先建立一个 LRU cache,以后不管是什么情景都会从 LRU cache 里面去作内存的分发和调度,而后借助 LRU cache,最近最少被用的内存会被释放掉。因此在 Flink 1.10以后,咱们说开启 state.backend.rocksdb.memory.managed 能够解决大部分问题。

640 14.jpg

可是,固然万事都有可是,咱们开发过程当中发现:RocksDB cache share 的功能作的不是特别好。这涉及到一些实现原理细节,好比无法去作 strict cache,若是你开启的话可能会碰到奇怪的NPE问题,因此说在某些特定场景下可能作的不是很好。这时你可能就要适当增大taskmanager.memory.task.off-heap.size 以提供更多的缓冲空间。

固然咱们首先要知道它大概用多少内存空间。刚才咱们展现的内存监控图里面,是须要打开参数 state.backend.rocksdb.metrics.block-cache-usage:true,打开以后,咱们能够在 metrics 监控上面去获取到相关的指标,观察一下大概超用到多少。好比说1GB一个 state TM 默认的 manager 是 294MB。

因此说你发现好比说你可能超过不少,好比说偶尔会到300MB,或者310MB,你这时候就能够考虑配置参数taskmanager.memory.task.off-heap.size (默认是0)来再增长一部份内存,好比说再加64MB,表示在 Flink 所申请的 off-heap 里面再额外开辟出来一块空间,给RocksDB 作一段 Buffer,以避免他被 OOM killed。这个是目前所能掌握的一个解决方案,但根本的解决方案可能须要跟 RocksDB 社区去一块儿去协同处理。

咱们也但愿若是有同窗遇到相似问题能够跟咱们进行交流,咱们也很是乐意和你一块儿去观察、追踪相关问题。

Demo

最后一部分演示使用 hostPath 的 demo,大部分 yaml 文件与社区的示例相同,task manager 的部署 yaml 文件须要修改,见下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flink-taskmanager
spec:
  replicas: 2
  selector:
    matchLabels:
      app: flink
      component: taskmanager
  template:
    metadata:
      labels:
        app: flink
        component: taskmanager
    spec:
      containers:
      - name: taskmanager
        image: reg.docker.alibaba-inc.com/chagan/flink:latest
        workingDir: /opt/flink
        command: ["/bin/bash", "-c", "$FLINK_HOME/bin/taskmanager.sh start; \
          while :;
          do
            if [[ -f $(find log -name '*taskmanager*.log' -print -quit) ]];
              then tail -f -n +1 log/*taskmanager*.log;
            fi;
          done"]
        ports:
        - containerPort: 6122
          name: rpc
        livenessProbe:
          tcpSocket:
            port: 6122
          initialDelaySeconds: 30
          periodSeconds: 60
        volumeMounts:
        - name: flink-config-volume
          mountPath: /opt/flink/conf/
        - name: state-volume
          mountPath: /dump/1/state
        securityContext:
          runAsUser: 9999  # refers to user _flink_ from official flink image, change if necessary
      volumes:
      - name: flink-config-volume
        configMap:
          name: flink-config
          items:
          - key: flink-conf.yaml
            path: flink-conf.yaml
          - key: log4j.properties
            path: log4j.properties
      - name: state-volume
        hostPath:
          path: /dump/1/state
          type: DirectoryOrCreate

Q&A 问答

一、Flink 如何在 K8S 的 POD 中与 HDFS 交互?

其与 HDFS 交互很简单,只要把相关依赖打到镜像里面就好了。就是说你把 flink-shaded-hadoop-2-uber-{hadoopVersion}-{flinkVersion}.jar 放到 flink-home/lib目录下,而后把一些 hadoop 的配置好比 hdfs-site.xml、 core-site.xml 等放到能够访问的目录下,Flink 天然而然就能够访问了。这其实和在一个非 HDFS 集群的节点上,要去访问 HDFS 是同样的。

二、Flink on K8S 怎么保证 HA?

其实 Flink 集群的 HA 与是否运行在 K8S 之上没什么关系,社区版的 Flink 集群 HA须要 ZooKeeper 参与。HA 须要 ZooKeeper 去实现 checkpoint Id counter、须要ZooKeeper 去实现 checkpoint stop、还包括 streaming graph 的 stop,因此说HA 的核心就变成如何在 Flink on K8S 的集群之上,提供 ZooKeeper 的服务,ZooKeeper 集群能够部署在 K8S 上或者物理机上。同时社区也有尝试在 K8S 里面借用 etcd 去支持提供一套 HA 方案,目前真正工业级的 HA,暂时只有 zookeeper 这一种实现。

三、Flink on K8S 和 Flink on YARN,哪一个方案更优?怎样选择?

Flink on YARN 是目前比较成熟的一套系统,可是它有点重,不是云原生(cloud native)。在服务上云的大趋势下,Flink on K8S 是一个光明的将来。Flink on YARN 是一个过去很是成熟一套体系,可是它在新的需求、新的挑战之下,可能缺少一些应对措施。例如对不少细致的 GPU 调度,pipeline 的建立等等,概念上没有K8S 作得好。

若是你只是简单运行一个做业,在 Flink on YARN 上能够一直稳定运行下去,它也比较成熟,相比之下 Flink on K8S 够新、够潮、方便迭代。不过目前 Flink on K8S 已知的一些问题,好比学习曲线比较陡峭,须要一个很好的 K8S 运维团队去支撑。另外,K8S 自己虚拟化带来的性能影响,正如先前介绍的不管是磁盘,仍是网络,很难避免必定的性能损耗,这个多是稍微有点劣势的地方,固然相比这些劣势,虚拟化(容器化)带来的优势更明显。

四、 /etc/hosts 文件如何配置的?我理解要跟 HDFS 交互,须要把 HDFS 节点 IP 和 host,映射写到 /etc/hosts 文件。

经过经过 Volume 挂载 ConfigMap 内容并映射到 /etc/hosts 来解决,或者无需修改 /etc/hosts 转而依赖 CoDNS。

五、Flink on K8S 故障排查困难,大家是怎么解决的?

首先 Flink on K8S 与 Flink on YARN 的故障排查有什么区别呢?主要是 K8S 自己可能会有问题,这就是稍微麻烦的地方。K8S 能够认为是一个操做系统,可能有不少复杂的组件在里面。YARN 是一个用 Java 实现的资源调度器,这时更可能是宿主机故障致使集群异常。面对 K8S 可能出问题,我我的感受是相比 YARN 来讲要难查一些。由于它有不少组件,可能 DNS 解析出问题,就须要去查看 CoDNS 日志;网络出问题或者是磁盘出问题你要去查看 kube event;POD 异常退出,须要去查看 event POD 退出的缘由。实话实话,确实须要必定的门槛,最好是须要运维支持。

但若是是说 Flink 故障排查,这在 K8S 或是 YARN 排查手段都同样,

  • 查看日志,检测是否有 exception;
  • 若是是性能就须要用 jstack,查看 CPU、调用栈卡在哪里;
  • 若是发现老是有 OOM 风险,或者老年代老是打的很满,或者 GC 频繁,或者Full GC 致使 Stop the world,就须要 jmap 查看哪块占内存,分析是否存在内存泄露

这些排查方法是与平台是无关的,是一个放之四海而皆准的排查流程。固然须要注意POD 镜像中可能会缺乏一些 Debug 工具,因此建议你们在搭建 Flink on K8S 集群时,构建私有镜像,在构建的过程当中安装好相应的 Debug 工具。

相关文章
相关标签/搜索