分享

如何运用Prometheus监控Flink

问题导读:
1.为什么选择Prometheus?
2.使用自动发现的配置方式有什么优点?
3.如何提交作业?

这篇文章介绍了如何利用Apache Flink的内置指标系统以及如何使用Prometheus来高效地监控流式应用程序。
   about1.jpeg
为什么选择Prometheus?
随着深入地了解Prometheus,你会发现一些非常好的功能:
  • 服务发现使配置更加容易。Prometheus支持consul,etcd,kubernetes以及各家公有云厂商自动发现。对于监控目标动态发现,这点特别契合Cloud时代,应用动态扩缩的特点。我们无法想象,在Cloud时代,需要运维不断更改配置。
  • 开源社区建立了数百个exporter。基本上涵盖了所有基础设施和主流中间件。
  • 工具库可从您的应用程序获取自定义指标。基本上主流开发语言都有对应的工具库。
  • 它是CNCF旗下的OSS,是继Kubernetes之后的第二个毕业项目。Kubernetes已经与Promethues深度结合,并在其所有服务中公开了Prometheus指标。
  • Pushgateway,Alermanager等组件,基本上涵盖了一个完整的监控生命周期。


    Flink官方已经提供了对接Prometheus的jar包,很方便就可以集成。由于本系列文章重点在Flink on Kubernetes, 因此我们所有的操作都是基于这点展开。

部署Prometheus
对k8s不熟悉的同学,可以查阅k8s相关文档。由于部署不是本博客的重点,所以我们直接贴出yaml文件:
  1. ---
  2.     apiVersion: v1
  3.     kind: ServiceAccount
  4.     metadata:
  5.       name: monitor
  6.       namespace: kube-system
  7.       labels:
  8.         kubernetes.io/cluster-service: "true"
  9.         addonmanager.kubernetes.io/mode: Reconcile
  10. ---
  11.     apiVersion: rbac.authorization.k8s.io/v1
  12.     kind: ClusterRole
  13.     metadata:
  14.       name: monitor
  15.       labels:
  16.         kubernetes.io/cluster-service: "true"
  17.         addonmanager.kubernetes.io/mode: Reconcile
  18.     rules:
  19.       - apiGroups:
  20.           - ""
  21.         resources:
  22.           - pods
  23.         verbs:
  24.           - get
  25.           - list
  26.           - watch
  27. ---
  28.     apiVersion: rbac.authorization.k8s.io/v1
  29.     kind: ClusterRoleBinding
  30.     metadata:
  31.       name: monitor
  32.       labels:
  33.         kubernetes.io/cluster-service: "true"
  34.         addonmanager.kubernetes.io/mode: Reconcile
  35.     roleRef:
  36.       apiGroup: rbac.authorization.k8s.io
  37.       kind: ClusterRole
  38.       name: monitor
  39.     subjects:
  40.     - kind: ServiceAccount
  41.       name: monitor
  42.       namespace: kube-system
  43. ---
  44.         apiVersion: v1
  45.         kind: ConfigMap
  46.         metadata:
  47.           labels:
  48.             app: monitor
  49.           name: monitor
  50.           namespace: kube-system
  51.         data:
  52.           prometheus.yml: |-
  53.             global:
  54.                 scrape_interval:     10s
  55.                 evaluation_interval: 10s
  56.               
  57.             scrape_configs:
  58.               - job_name: kubernetes-pods
  59.                 kubernetes_sd_configs:
  60.                 - role: pod
  61.                 relabel_configs:
  62.                 - action: keep
  63.                   regex: true
  64.                   source_labels:
  65.                   - __meta_kubernetes_pod_annotation_prometheus_io_scrape
  66.                 - action: replace
  67.                   regex: (.+)
  68.                   source_labels:
  69.                   - __meta_kubernetes_pod_annotation_prometheus_io_path
  70.                   target_label: __metrics_path__
  71.                 - action: replace
  72.                   regex: ([^:]+)(?::\d+)?;(\d+)
  73.                   replacement: $1:$2
  74.                   source_labels:
  75.                   - __address__
  76.                   - __meta_kubernetes_pod_annotation_prometheus_io_port
  77.                   target_label: __address__
  78.                 - action: labelmap
  79.                   regex: __meta_kubernetes_pod_label_(.+)
  80.                 - action: replace
  81.                   source_labels:
  82.                   - __meta_kubernetes_namespace
  83.                   target_label: kubernetes_namespace
  84.                 - action: replace
  85.                   source_labels:
  86.                   - __meta_kubernetes_pod_name
  87.                   target_label: kubernetes_pod_name
  88.         
  89. ---
  90.         apiVersion: apps/v1
  91.         kind: StatefulSet
  92.         metadata:
  93.           labels:
  94.             app: monitor
  95.           name: monitor
  96.           namespace: kube-system
  97.         spec:
  98.           serviceName: monitor
  99.           selector:
  100.             matchLabels:
  101.               app: monitor
  102.           replicas: 1
  103.           template:
  104.             metadata:
  105.               labels:
  106.                 app: monitor
  107.             spec:
  108.               containers:
  109.               - args:
  110.                 - --config.file=/etc/prometheus/prometheus.yml
  111.                 - --storage.tsdb.path=/data/prometheus
  112.                 - --storage.tsdb.retention.time=10d
  113.                 image: prom/prometheus:v2.19.0
  114.                 imagePullPolicy: IfNotPresent
  115.                 name: prometheus
  116.                 ports:
  117.                 - containerPort: 9090
  118.                   protocol: TCP
  119.                 readinessProbe:
  120.                   httpGet:
  121.                     path: /-/ready
  122.                     port: 9090
  123.                   initialDelaySeconds: 30
  124.                   timeoutSeconds: 30
  125.                 livenessProbe:
  126.                   httpGet:
  127.                     path: /-/healthy
  128.                     port: 9090
  129.                   initialDelaySeconds: 30
  130.                   timeoutSeconds: 30
  131.                 resources:
  132.                   limits:
  133.                     cpu: 1000m
  134.                     memory: 2018Mi
  135.                   requests:
  136.                     cpu: 1000m
  137.                     memory: 2018Mi
  138.                 volumeMounts:
  139.                 - mountPath: /etc/prometheus
  140.                   name: config-volume
  141.                 - mountPath: /data
  142.                   name: monitor-persistent-storage
  143.               restartPolicy: Always
  144.               priorityClassName: system-cluster-critical
  145.               serviceAccountName: monitor
  146.               initContainers:
  147.                 - name: "init-chown-data"
  148.                   image: "busybox:latest"
  149.                   imagePullPolicy: "IfNotPresent"
  150.                   command: ["chown", "-R", "65534:65534", "/data"]
  151.                   volumeMounts:
  152.                     - name: monitor-persistent-storage
  153.                       mountPath: /data
  154.                       subPath: ""
  155.               volumes:
  156.               - configMap:
  157.                   defaultMode: 420
  158.                   name: monitor
  159.                 name: config-volume
  160.           volumeClaimTemplates:
  161.             - metadata:
  162.                 name: monitor-persistent-storage
  163.                 namespace: kube-system
  164.               spec:
  165.                 accessModes:
  166.                   - ReadWriteOnce
  167.                 resources:
  168.                   requests:
  169.                     storage: 20Gi
  170.                 storageClassName: gp2
  171. ---
  172.         apiVersion: v1
  173.         kind: Service
  174.         metadata:
  175.           annotations:
  176.             service.beta.kubernetes.io/aws-load-balancer-type: nlb
  177.           labels:
  178.             app: monitor
  179.           name: monitor
  180.           namespace: kube-system
  181.         spec:
  182.           ports:
  183.           - name: http
  184.             port: 9090
  185.             protocol: TCP
  186.             targetPort: 9090
  187.           selector:
  188.             app: monitor
  189.           type: LoadBalancer
复制代码

    这里我们简单说下,由于我们想利用Prometheus的Kubernetes的服务发现的方式,所以需要RBAC授权,授权prometheus 实例对集群中的pod有一些读取权限。

为什么我们要使用自动发现的方式那?
    相比配置文件的方式,自动发现更加灵活。尤其是当你使用的是flink on native kubernetes,整个job manager 和task manager 是根据作业的提交自动创建的,这种动态性,显然是配置文件无法满足的。
由于我们的集群在eks上,所以大家在使用其他云的时候,需要略做调整。

定制镜像
这里我们基本上使用上一篇文章介绍的demo上,增加监控相关,所以Dockerfile如下:
  1. FROM flink
  2. COPY /plugins/metrics-prometheus/flink-metrics-prometheus-1.11.0.jar /opt/flink/lib
  3. RUN mkdir -p $FLINK_HOME/usrlib
  4. COPY ./examples/streaming/WordCount.jar $FLINK_HOME/usrlib/my-flink-job.jar
复制代码
Flink 的 Classpath 位于/opt/flink/lib,所以插件的jar包需要放到该目录下

作业提交
由于我们的Pod必须增加一定的标识,从而让Prometheus实例可以发现。所以提交命令稍作更改,如下:
  1. ./bin/flink run-application -p 8 -t kubernetes-application \
  2.   -Dkubernetes.cluster-id=my-first-cluster \
  3.   -Dtaskmanager.memory.process.size=2048m \
  4.   -Dkubernetes.taskmanager.cpu=2 \
  5.   -Dtaskmanager.numberOfTaskSlots=4 \
  6.   -Dkubernetes.container.image=iyacontrol/flink-world-count:v0.0.2 \
  7.   -Dkubernetes.container.image.pull-policy=Always \
  8.   -Dkubernetes.namespace=stream \
  9.   -Dkubernetes.jobmanager.service-account=flink \
  10.   -Dkubernetes.rest-service.exposed.type=LoadBalancer \
  11.   -Dkubernetes.rest-service.annotations=service.beta.kubernetes.io/aws-load-balancer-type:nlb,service.beta.kubernetes.io/aws-load-balancer-internal:true \
  12.   -Dkubernetes.jobmanager.annotations=prometheus.io/scrape:true,prometheus.io/port:9249 \
  13.   -Dkubernetes.taskmanager.annotations=prometheus.io/scrape:true,prometheus.io/port:9249 \
  14.   -Dmetrics.reporters=prom \
  15.   -Dmetrics.reporter.prom.class=org.apache.flink.metrics.prometheus.PrometheusReporter \
  16.   local:///opt/flink/usrlib/my-flink-job.jar
复制代码
  • 给 jobmanager 和 taskmanager 增加了annotations
  • 增加了metrcis相关的配置,指定使用prometheus reporter     

关于prometheus reporter:
参数:
      port - 可选, Prometheus导出器监听的端口,默认为9249。为了能够在一台主机上运行报告程序的多个实例(例如,当一个TaskManager与JobManager并置时),建议使用这样的端口范围 9250-9260。

      filterLabelValueCharacters - 可选, 指定是否过滤标签值字符。如果启用,则将删除所有不匹配[a-zA-Z0-9:_]的字符,否则将不删除任何字符。禁用此选项之前,请确保您的标签值符合Prometheus要求。


效果
提交任务后,我们看下实际效果
首先查看Prometheus 是否发现了我们的Pod。
about2.jpeg

然后查看具体的metrics,是否被准确抓取
about3.jpeg

指标已经收集,后续大家就可以选择grafana绘图了。或是增加相应的报警规则。例如:
about4.jpeg
总结
    当然除了Prometheus主动发现Pod,然后定期抓取metrcis的方式,flink 也支持向PushGateway 主动push metrcis。Flink 通过 Reporter 来向外部系统提供metrcis。通过在conf/flink-conf.yaml中配置一个或多个Reporter ,可以将metrcis公开给外部系统。这些Reporter在启动时将在每个作业和任务管理器上实例化。

    所有Reporter都必须至少具有class或factory.class属性。可以/应该使用哪个属性取决于Reporter的实现。有关更多信息,请参见各个Reporter 配置部分。一些Reporter允许指定报告间隔。

指定多个Reporter 的示例配置:
  1. metrics.reporters: my_jmx_reporter,my_other_reporter
  2. metrics.reporter.my_jmx_reporter.factory.class: org.apache.flink.metrics.jmx.JMXReporterFactory
  3. metrics.reporter.my_jmx_reporter.port: 9020-9040
  4. metrics.reporter.my_jmx_reporter.scope.variables.excludes:job_id;task_attempt_num
  5. metrics.reporter.my_other_reporter.class: org.apache.flink.metrics.graphite.GraphiteReporter
  6. metrics.reporter.my_other_reporter.host: 192.168.1.1
  7. metrics.reporter.my_other_reporter.port: 10000
复制代码

    启动Flink时,必须可以访问包含reporter的jar。支持factory.class属性的reporter可以作为插件加载。否则,必须将jar放在/lib文件夹中。你可以通过实现org.apache.flink.metrics.reporter.MetricReporter接口来编写自己的Reporter。如果 reporter定期发送报告,则还必须实现Scheduled接口。通过额外实现MetricReporterFactory,你的reporter也可以作为插件加载

最新经典文章,欢迎关注公众号



原文链接:

没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条