一次在K8s上运行Flink的实录

本文先介绍一下K8s的ConfigMap资源和Ingress的基本概念,然后讲一下如何在K8s上部署Flink,最后看一下Flink的Operator又是怎么编写的

ConfigMap

问题背景:

生产环境可能需要多个Config文件,命令行参数和环境变量进行配置组合,因此容器部署的时候,应该把配置从应用程序的镜像中解耦出来,以保证镜像的可移植性.

ConfigMap是用来存储通用的配置变量的,类似于配置文件,使得用户可以将分布式系统中用于不同模块的环境变量统一到一个对象中进行管理.

他可以看做K8s的一个基本资源类型,是一个键值组类型,存储被Pod或者其他资源对象访问的信息.但与secret相比,主要区别在于其不存储敏感信息,只存储简单的文本信息

简而言之: 在创建pod的时候对configmap进行绑定,pod内的应用可以直接引用ConfigMap的配置,相当于configmap为应用/运行环境封装配置.

创建pod的时候要绑定ConfigMap,通常用于: 设置环境变量的值,设置命令行参数等

ConfigMap的核心是把配置数据注入容器的方式,同时保证这个机制对容器来说是透明的.

ConfigMap可以用来保存单个属性,也可以用来保存整个配置文件或者JSON二进制大对象

eg;

ConfigMap可以包含细粒度的配置项,如:example.property.1;也可以包含粗粒度的配置文件,如:example.property.file

kind: ConfigMap
apiVersion: v1
metadata:
  creationTimestamp: 2016-02-18T19:14:38Z
  name: example-config
  namespace: default
data:
  # example of a simple property defined using --from-literal
  example.property.1: hello
  example.property.2: world
  # example of a complex property defined using --from-file
  example.property.file: |-
    property.1=value-1
    property.2=value-2

Ingress

LoadBalancer和NodePort都是Svc向外暴露服务的方法,那么Ingress有什么不同呢?

根据官方文档,Ingress公开了从集群外部到集群内Services的HTTP和HTTPS路由,流量路由由Ingress资源上定义的规则来控制.

Ingress的作用:

  • 为服务提供外部可访问的URL
  • 流量的负载均衡
  • 虚拟主机服务??

Ingress controller 负责来实现Ingress,经常是使用一个负载均衡器来实现的.

那如果要把HTTP或者HTTPS以外的服务公开给外部的时候,通常使用Service.Type=NodePort或者Service.Type=LoadBalancer

eg:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test
          servicePort: 80

选一些独特的来介绍:
1.annotations:
注解,用于配置一些选项
2.Ingress规则

  • 可选主机

上面的yaml文件没有注明,说明规则适用于通过特定IP地址进站的HTTP流量,如果指定了主机,那么规则只会适用于该主机

  • 路径列表
    每一个路径对应一个后端

  • 后端
    一个后端由serviceNameservicePort来定义,与规则的主机和路径匹配的对Ingress的HTTP请求将会发送到后端.

Flink的部署架构

组成

Flink由Job Manager和Task Manager两部分组成,Job Manager负责协调流处理作业,管理作业的提交以及生命周期,并且把工作分配给任务管理器.任务管理器执行实际的流处理逻辑,同一个时间只能有一个活跃的Job Manager,但是可以有多个Task Manager

Flink还引入了Checkpoint机制,来周期性记录各种流处理操作的状态,并且进行持久化存储.在从故障中恢复的时候,流处理作业可以从最新的检查点继续执行.

Checkpoint也是由Job Manager进行协调和更新的

具体配置文件

Job Manager和Task Manager都采用deployment来进行部署
另外还需要定义相应的configmap和service文件,使其能够暴露一个端口供外界访问

首先配置ConfigMap
configMap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: flink-config
  labels:
    app: flink
data:
  flink-conf.yaml: |+
    jobmanager.rpc.address: flink-jobmanager
    taskmanager.numberOfTaskSlots: 1
    blob.server.port: 6124
    jobmanager.rpc.port: 6123
    taskmanager.rpc.port: 6122
    jobmanager.heap.size: 1024m
    taskmanager.heap.size: 1024m
  log4j.properties: |+
    log4j.rootLogger=INFO, file
    log4j.logger.akka=INFO
    log4j.logger.org.apache.kafka=INFO
    log4j.logger.org.apache.hadoop=INFO
    log4j.logger.org.apache.zookeeper=INFO
    log4j.appender.file=org.apache.log4j.FileAppender
    log4j.appender.file.file=${log.file}
    log4j.appender.file.layout=org.apache.log4j.PatternLayout
    log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
    log4j.logger.org.apache.flink.shaded.akka.org.jboss.netty.channel.DefaultChannelPipeline=ERROR, file

主要是把日志文件以及配置文件和创建Pod解耦开来

那相应的deployment要怎么和configMap绑定呢?

jobManager-deployment.yaml
在volumes那里,configMap指定定义好的configMap的名称,items项,并且指定好key:path键值对

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flink-jobmanager
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: flink
        component: jobmanager
    spec:
      containers:
      - name: jobmanager
        image: flink:latest
        workingDir: /opt/flink
        command: ["/bin/bash", "-c", "$FLINK_HOME/bin/jobmanager.sh start;\
          while :;
          do
            if [[ -f $(find log -name '*jobmanager*.log' -print -quit) ]];
              then tail -f -n +1 log/*jobmanager*.log;
            fi;
          done"]
        ports:
        - containerPort: 6123
          name: rpc
        - containerPort: 6124
          name: blob
        - containerPort: 8081
          name: ui
        livenessProbe:
          tcpSocket:
            port: 6123
          initialDelaySeconds: 30
          periodSeconds: 60
        volumeMounts:
        - name: flink-config-volume
          mountPath: /opt/flink/conf
      volumes:
      - name: flink-config-volume
        configMap:
          name: flink-config
          items:
          - key: flink-conf.yaml
            path: flink-conf.yaml
          - key: log4j.properties
            path: log4j.properties

taskmanager-deployment.yaml
同理,设置task-manager的镜像

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flink-taskmanager
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: flink
        component: taskmanager
    spec:
      containers:
      - name: taskmanager
        image: 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/
      volumes:
      - name: flink-config-volume
        configMap:
          name: flink-config
          items:
          - key: flink-conf.yaml
            path: flink-conf.yaml
          - key: log4j.properties
            path: log4j.properties
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

然后可以使用多种方式访问UI

  • kubectl proxy
    1.运行kubectl proxy
    2.前往 http://localhost:8001/api/v1/namespaces/default/services/flink-jobmanager:ui/proxy

  • kubectl port-forward
    kubectl port-forward flink-jobmanager-845f844595-lcpxw 8081:8081
    访问 http://localhost:8081

那我们分别写了Deployment和Service的yaml文件,很容易就能联想到,我们是否能干脆写一个Flink的K8s operator呢?这样管理应用状态会更加地方便

https://github.com/lyft/flinkk8soperator

Flink-k8s-operator

最后我们再来看一下如何利用Lyft开源的flink operator来定义一个Flink
的Job

先占个坑,以后更新

ref

https://blog.csdn.net/bbwangj/article/details/81776648
https://blog.csdn.net/cpongo3/article/details/89027097

你可能感兴趣的:(k8s)