【K8S】【flink on k8s】 之flinkcdc

【K8S】【flink on k8s】 之flinkcdc

一、Flink Kubernetes Operator安装

在正式安装Flink Kubernetes Operator之前,需要先提前准备一套可用的Kubernetes集群环境,这套Kubernetes集群可以是非高可用的,但建议Node节点的个数不少于2个,因为如果Flink集群(对于Application模式,一个作业就是1个Flink集群,对于Session模式,多个Flink作业共享一个Flink集群)开启了HA,也就是JobManager有2个或多个,那么默认情况下,不同的JobManager Pod会调度到不同的K8s Node节点上,但TaskManger不受影响,例如启动了多个TaskManager Pod,多个TaskManager Pod可以调度到同一个K8s Node节点,当然它们也可以与JobManagre在同一个节点。

同时确保集群已安装helm和cert-manager

1.1 Helm安装

Flink Kubernetes Operator的安装需要使用Helm,可以到Helm的官方网站下载Helm,Helm的官网为Helm,也可以使用以下命令下载和安装。

wget https://get.helm.sh/helm-v3.11.2-linux-amd64.tar.gz
 
tar -zxvf helm-v3.11.2-linux-amd64.tar.gz
 
mv linux-amd64/helm /usr/local/bin/

helm安装好后,可以添加常用的helm源。

helm repo add flink-operator-repo https://downloads.apache.org/flink/flink-kubernetes-operator-1.3.1/
 
helm repo add stable http://mirror.azure.cn/kubernetes/charts
 
helm repo add bitnami https://charts.bitnami.com/bitnami
 
helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
1.2安装cert-manager

Flink Webhook默认使用TLS协议进行通信,也就是HTTPS,所以在使用Flink Kubernetes Operator时,需要先安装cert-manager组件,由它提供证书服务。

通常使用cert-manager.yaml来安装cert-manager,cert-manager.yaml可以从cert-manager的官网获取,它的官网地址是 cert-manager ,需要注意的是,官网提供的cert-manager.yaml使用的镜像是国外的镜像仓库,在国内有可能会因为网络原因无法下载镜像,导致无法安装。为此,建议下载cert-manager.yaml后修改它的镜像地址,可以按如下方式将cert-manager.yaml里的image进行替换修改。
registry.cn-hangzhou.aliyuncs.com/cm_ns01/cert-manager-webhook:v1.10.0
registry.cn-hangzhou.aliyuncs.com/cm_ns01/cert-manager-cainjector:v1.10.0
registry.cn-hangzhou.aliyuncs.com/cm_ns01/cert-manager-controller:v1.10.0

kubectl apply -f cert-manager.yaml
1.3Flink Kubernetes Operator安装

Helm和cert-manager安装好后,接下来就可以正式安装Flink Kubernetes Operator。

Flink Kubernetes Operator最简单直接的安装方式就是使用helm在线安装,命令如下:

helm repo add flink-operator-repo https://downloads.apache.org/flink/flink-kubernetes-operator-1.4.0/
helm install flink-kubernetes-operator flink-operator-repo/flink-kubernetes-operator  --namespace flink --create-namespace

此处,我们可以将Flink Kubernetes Operator安装到K8s的flink Namespace下,如果flink Namespace不存在,则创建之。

可以使用如下命令检查安装情况:

kubectl get all -n flink -owide
helm list -n flink

如果需要定制Flink Kubernetes Operator,例如开启HA和修改它的启动参数配置,那么建议采用helm本地安装的方式。此方式需要先下载Flink Kubernetes Operator的Helm包文件,下载网址为https://downloads.apache.org/flink/flink-kubernetes-operator-1.4.0/flink-kubernetes-operator-1.4.0-helm.tgz, 然后解压进入目录,根据需要修改values.yaml文件,并使用如下命令安装:

helm install -f values.yaml flink-kubernetes-operator . --namespace flink --create-namespace

二、使用Flink On Kubernetes不同模式部署及进行作业提交

Flink On Kubernetes支持Apllication和Session这两种部署模式

Application模式和Session模式两者最大区别在于集群的生命周期和资源管理隔离程度的不同,因此,对于核心、优先级高和需要高保障的这类作业推荐使用Application模式。而那些对保障性要求相对不高,或者出于运维管理便利的考量,例如需要通过外部系统通过调用Flink Restful接口管理作业的提交和启停,那么可以考虑使用Session模式。如果对于作业的归属模棱两可,那么建议直接使用Application模式,也就是说,把Application模式作为Flink On K8s运行模式的默认选项。

2.1Application模式

在Application部署模式下,Kubernetes会为每个提交的Flink作业单独创建一个Flink集群,这个Flink集群由JobManager Pod和TaskManager Pod组成,其中拟启动的TaskManager Pod的数量由Flink作业所需的slot数量和每个TaskManager所能提供的可用slot数量决定,例如一个Flink作业需要10个slot,每个TaskManager提供4个slot,那么Kubernetes就会启动3个TaskManager Pod。在Flink作业运行完成的时候,或者终止Flink作业运行时候,Kubernetes会终止集群并释放全部的Pod。
Application部署模式的主要特点是它在不同Flink作业之间提供了资源隔离和负载平衡保证,使得作业间彼此独立,互不影响,此外,它还可以为不同的作业配置不同的资源,以此实现作业的精细化管理。

Application部署模式在Kubernetes上有2种Flink作业的提交方式

  • 方式一是将Flink作业的Jar包打进Flink镜像里,在Flink作业的FlinkDeployment yaml文件里使用该镜像,当Flink作业运行(或称Flink集群创建)的时候,内部就会包含该作业的Jar包。这种方式的显著特点就是每个Flink作业都要创建自己专属的镜像,如果Flink作业的数量较多,那么也会导致镜像过多,从而占用大量镜像仓库空间。
  • 方式二是将作业Jar包放到外部存储上,例如NFS,然后通过Kubernetes的PVC+PV方式挂载到Pod里,好处就是只需维护少数几个Base Flink镜像即可,极大节省镜像仓库空间。

将Flink程序开发完成后,需要打成jar包并上传到K8s集群中。

2.1.1Application模式----方式一(Jar包打进Flink镜像)

第一步,需要编写Dockerfile,并构建Flink作业镜像,Dockerfile如下:

FROM flink:1.13.6
WORKDIR /opt/flink
COPY flink-on-k8s-demo-1.0-SNAPSHOT.jar /opt/flink/flink-on-k8s-demo-1.0-SNAPSHOT.jar
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 6123 8081
CMD ["help"]

此处假定Flink程序的Jar包名字为flink-on-k8s-demo-1.0-SNAPSHOT.jar,并且它与Dockerfile在同一个目录下。Dockerfile有两处地方需要特别注意,一是FROM指令引用了1.13.6版本的Flink基础镜像(Base Image),二是COPY指令会把同目录的flink-on-k8s-demo-1.0-SNAPSHOT.jar拷贝进Flink镜像的/opt/flink目录下。
Dockerfile编写好后,可以使用如下命令构建,此命令将会构建出一个名字为flink-wc,版本为1.13.6的新镜像。

docker build -f Dockerfile -t flink-wc:1.13.6 .

flink-wc镜像构建好后,需要分发到各个Kubernetes Node节点,更推荐的做法是把它发布到自有的镜像仓库,以便后续提交Flink作业yaml文件时能下载该镜像。发布到镜像仓库的命令如下。

docker tag image_id registry_address/flink-wc:1.13.6
docker push registry_address/flink-wc:1.13.6

第二步,编写Flink作业的yaml文件,内容如下参考:

# Flink Session集群 https://bigdataonk8s.com
apiVersion: flink.apache.org/v1beta1
kind: FlinkDeployment
metadata:
  namespace: flink
  name: application-deployment
spec:
  image: flink-wc:1.13.6  # 使用自行构建的镜像
  flinkVersion: v1_13
  imagePullPolicy: IfNotPresent   # 镜像拉取策略,本地没有则从仓库拉取
  ingress:   # ingress配置,用于访问flink web页面
    template: "flink.k8s.io/{{namespace}}/{{name}}(/|$)(.*)"
    className: "nginx"
    annotations:
      nginx.ingress.kubernetes.io/rewrite-target: "/$2"
  flinkConfiguration:
    taskmanager.numberOfTaskSlots: "2"
  serviceAccount: flink
  jobManager:
    replicas: 1
    resource:
      memory: "1024m"
      cpu: 1
  taskManager:
    replicas: 1
    resource:
      memory: "1024m"
      cpu: 1
  job:
    jarURI: local:///opt/flink/flink-on-k8s-demo-1.0-SNAPSHOT.jar
    entryClass: com.bigdataonk8s.StreamWordCount
    args:
    parallelism: 1
    upgradeMode: stateless

在yaml文件里有三处地方需要特别注意,首先是开头部分定义了资源的类型为FlinkDeployment,这是Flink Kubernetes Operator为Flink集群所定义的自定义资源类型(CRD);其次,images引用了我们自行构建的Flink作业镜像;最后,job.jarURI指向了我们Flink作业Jar包在镜像内的路径,job.entryClass则为Flink作业的启动类名称。

第三步,运行Fink作业。

使用以下命令提交Flink作业的yaml文件到Kubernetes运行,并查看Pod的创建情况。

kubectl apply -f application-deployment.yaml
 
kubectl get all -n flink
2.1.1Application模式----方式一(Jar包通过PV挂载到镜像)

第一步,需要先创建Kubernetes PVC,申请分配PV存储,把Flink作业Jar包上传放置到该PV对应的实际储存的路径下。可采用动态PVC申请PV的方式,存储设施是NFS,因此需要提前在Kubernetes上安装配置好NFS的组件服务,并创建好StorageClass资源。

PVC的yaml文件内容示例如下:

#  Flink 作业jar 持久化存储pvc https://bigdataonk8s.com
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: flink-jar-pvc  # jar pvc名称
  namespace: flink
spec:
  storageClassName: nfs-storage   #sc名称
  accessModes:
    - ReadOnlyMany   #采用ReadOnlyMany的访问模式
  resources:
    requests:
      storage: 1Gi    #存储容量,根据实际需要更改

在PVC yaml文件里有2处地方需要特别注意,一是由于PVC是Kubernetes命名空间层面的资源,所以namespace需要指定为Flink Kubernetes Operator和Flink作业所在的命名空间,在示例中命名空间是flink;二是storageClassName需要指定为Kubernetes上已有的StorageClass名字,可以使用kubectl get sc查看。
使用以下命令创建和查看PVC和PV,并将Flink作业Jar包上传到PV所对应的实际路径下。

kubectl apply -f flink-jar-pvc.yaml
kubectl get pvc -n flink
kubectl get pv -n flin

第二步,编写Flink作业的yaml文件(application-deployment-with-pv.yaml),yaml文件的内容如下图所示。

# Flink Application集群 源码请到 https://bigdataonk8s.com 获取
apiVersion: flink.apache.org/v1beta1
kind: FlinkDeployment
metadata:
  namespace: flink
  name: application-deployment
spec:
  image: flink:1.13.6
  flinkVersion: v1_13
  imagePullPolicy: IfNotPresent   # 镜像拉取策略,本地没有则从仓库拉取
  ingress:   # ingress配置,用于访问flink web页面
    template: "flink.k8s.io/{{namespace}}/{{name}}(/|$)(.*)"
    className: "nginx"
    annotations:
      nginx.ingress.kubernetes.io/rewrite-target: "/$2"
  flinkConfiguration:
    taskmanager.numberOfTaskSlots: "2"
  serviceAccount: flink
  jobManager:
    replicas: 1
    resource:
      memory: "1024m"
      cpu: 1
  taskManager:
    replicas: 1
    resource:
      memory: "1024m"
      cpu: 1
  podTemplate:
    spec:
      containers:
        - name: flink-main-container
          volumeMounts:
            - name: flink-jar  # 挂载nfs上的jar
              mountPath: /opt/flink/jar
      volumes:
        - name: flink-jar
          persistentVolumeClaim:
            claimName: flink-jar-pvc
  job:
    jarURI: local:///opt/flink/jar/flink-on-k8s-demo-1.0-SNAPSHOT.jar
    entryClass: com.yale.StreamWordCount
    args:
    parallelism: 1
    upgradeMode: stateless

方式二的Flink作业yaml文件与方式一的yaml文件大体类似,但有三处地方需要特别注意,首先是images改为引用Flink的基础镜像,而不是我们自行构建的Flink作业镜像;其次新增了podTemplate的内容,目的是将我们创建的PV挂载到Flink容器里,挂载的路径是/opt/flink/jar;最后,job.jarURI指向了我们Flink作业Jar包的挂载路径,job.entryClass则为Flink作业的启动类名称。

第三步,运行Flink作业。与方式一一样,由于示例Flink程序需要从nc读取字符流数据,因此在运行Flink作业前,需要先运行nc程序,命令是nc -lk 7777,否则Flink作业会运行不起来。
使用以下命令提交Flink作业的yaml文件到Kubernetes运行,并查看Pod的创建情况。

kubectl apply -f application-deployment-with-pv.yaml
kubectl get all -n flink
2.1.3两种方式的选择

关于Application部署模式2种提交方式的选择, 可以参考如下策略。
Application模式的2种作业提交方式的最大区别在于是否需要将作业Jar包打入Flink镜像。
对于方式一,把Jar包打进镜像,这样会使得每个Flink作业都要打一个镜像,容易导致镜像数量过多,既不便于管理,同时也会占用大量镜像仓库空间,通常1个Flink镜像的大小约为600M,当镜像数量很多的时候,需要占有的空间就很大。所以在实际应用中,不太推荐使用这种方式。
对于方式二,Jar包通过PV挂载,这样的好处就是Flink作业Jar包不用打到镜像,既可以省去镜像构建的工作,同时只需维护少数几个Flink基础镜像,这样可以极大地节省镜像仓库空间。综合考量,在实际应用中,若部署Application模式的话,更推荐使用方式二来提交作业。

2.2Session模式

在Session模式下,需要先在Kubernetes上启动一个Flink集群,这个集群初始情况下只有JobManager(如果Flink集群开启了HA,JobManager会有多个实例),没有TaskManager,当客户端向该集群提交作业时,Kubernetes再为每个作业动态创建TaskManager,TaskManager Pod的数量由Flink作业所需的slot数量和每个TaskManager所能提供的可用slot数量决定。所有作业共享该集群的JobManager,作业终止时,如果TaskManager的slot没有被其他的Flink作业占用,那么该TaskManager的Pod会被释放,但JobManager会继续运行,等待后续Flink作业的提交。
Session部署模式的主要特点是所有Flink作业共享集群的JobManager,因此Flink作业的资源隔离比较差,作业间会存在相互影响,极端情况下,个别异常作业会拖垮整个Flink集群,导致集群上的作业一起失败。
Session部署模式在Kubernetes上也有2种Flink作业的提交方式。

  • 方式一是通过Flink Web UI和Restful接口上传Flink作业Jar包方式,在Flink集群启动后,也就是JobManager运行起来后,可以通过人工访问Flink Web UI页面上传Jar包和提交作业,这种方式操作灵活,便于调试,也可以通过编写程序调用Flink Restful接口上传Jar包和提交作业,这样可以使外部系统例如调度系统灵活控制Flink作业的更新和启停。
  • 方式二是通过HTTP下载Flink作业Jar包方式,该方式有利于Flink作业Jar包的统一存放管理,例如可以统一将Flink作业Jar包发布到HTTP文件服务器,例如tomcat或nginx,使用这种方式, Fllink作业需要编写对应的FlinkSessionJob yaml文件, 然后通过Kubernetes的kubectl命令提交,当然,也可以通过编写程序调用Kubernetes API来实现FlinkSessionJob的提交、更新和停止。

需要补充说明的是,与FlinkDeployment一样,FlinkSessionJob是Flink Kubernetes Operator为Flink作业创建的K8s自定义资源(CRD),但它只定义了Flink作业相关的信息。在Session部署模式下,FlinkDeployment负责定义Flink集群相关的信息,例如Flink Web UI的Ingress、Flink集群的全局参数配置、JobManager和TaskManager的资源配额等,而FlinkSessionJob则负责定义Flink作业的JarURI、启动类、启动参数等相关的信息。

2.2.1Session模式----方式一(通过Flink Web UI上传Jar包

第一步,需要先启动Flink集群,也就是先运行JobManager,为此需要编写Flink集群的yaml文件,yaml文件的内容如下所示。

# Flink Session集群 源码请到 https://bigdataonk8s.com 获取
apiVersion: flink.apache.org/v1beta1
kind: FlinkDeployment
metadata:
  namespace: flink
  name: session-deployment-only
spec:
  image: flink:1.13.6
  flinkVersion: v1_13
  imagePullPolicy: IfNotPresent   # 镜像拉取策略,本地没有则从仓库拉取
  ingress:   # ingress配置,用于访问flink web页面
    template: "flink.k8s.io/{{namespace}}/{{name}}(/|$)(.*)"
    className: "nginx"
    annotations:
      nginx.ingress.kubernetes.io/rewrite-target: "/$2"
  flinkConfiguration:
    taskmanager.numberOfTaskSlots: "2"
  serviceAccount: flink
  jobManager:
    replicas: 1
    resource:
      memory: "1024m"
      cpu: 1
  taskManager:
    replicas: 1
    resource:
      memory: "1024m"
      cpu: 1

在yaml文件里有三处地方需要特别注意,首先是开头部分定义了资源的类型为FlinkDeployment,这与Application部署模式的资源类型一样;其次,images使用的是Flink的基础镜像,而不是我们在Application部署模式方式一中自行构建的Flink作业镜像;再者,定义了Ingress,以便可以通过网页浏览器或Restful接口访问JobManager,Ingress的模板主要由三部分组成:域名、Flink集群所在的命名空间和Flink集群的名称,因为此处使用了ingress,所以需要提前在Kubernetes上安装配置好Ingress的组件服务。最后,与Application部署模式的yaml相比,Session部署模式的yaml少了job部分的定义。

第二步,启动Flink集群,使用如下命令提交Flink集群yaml文件到Kubernetes运行,并查看Pod的创建情况。

kubectl apply -f session-deployment-only.yaml
kubectl get all -n flink

执行完命令后 可以看到,Flink集群启动后只运行了JobManager,并没有运行TaskManager。此外,它还创建了两个Service,其中session-deployment-only是用于Flink集群内部进程和JobManager与TaskManager通讯使用的,session-deployment-only-rest是用于访问Flink Web UI和Restful接口使用的。

第三步,访问Filnk Web UI。在前面配置了使用Ingress的方式访问Flink Web UI,且Ingress的域名是flink.k8s.io,为此,在Windows的本地测试中,需要先在C:\Windows\System32\drivers\etc\hosts中添加域名和IP的映射关系,此处的IP是Ingress Pod所在的Kubernetes Node节点的IP,对于Ubuntu或Mac,则在/etc/hosts里添加。

kubectl get all -n ingress-nginx -owide

需要特别注意的是,一是Ingress Pod运行的节点,二是Ingress的服务以NodePort的方式暴露,注意暴露的端口。

通过ping Ingress的节点 得到它的IP,为此,在hosts文件中添加以下映射。
Ingress的IP flink.k8s.io
接下来,就可以通过网页浏览器访问Flink Web UI,访问网址是 http://flink.k8s.io:30502/flink/session-deployment-only/#/overview

第四步,通过Flink Web UI上传Flink作业Jar并提交作业。

2.2.1Session模式----方式二(通过HTTP下载Flink作业Jar包方式)

第一步,需要先搭建一个HTTP服务器。例如Tomcat。

将Flink作业Jar包上传到Tomcat的webapps目录下,如将Flink作业Jar包上传到webapps/jars/flink目录下。此处需要注意的是,由于运行Flink作业的时候需要通过HTTP下载Jar包,为此需要确保TaskManager Pod能够访问Tomcat,为了便于测试,建议把Tomcat部署到Kubernetes的Node节点上。

一切就绪后就可以启动Tomcat,同时使用网页浏览器访问Tomcat,确保Flink作业Jar可以下载。

第二步,编写Flink集群的yaml文件,yaml文件的内容如下所示。

# Flink Session集群 源码请到 https://bigdataonk8s.com 获取
apiVersion: flink.apache.org/v1beta1
kind: FlinkDeployment
metadata:
  namespace: flink
  name: session-deployment-only
spec:
  image: flink:1.13.6
  flinkVersion: v1_13
  imagePullPolicy: IfNotPresent   # 镜像拉取策略,本地没有则从仓库拉取
  ingress:   # ingress配置,用于访问flink web页面
    template: "flink.k8s.io/{{namespace}}/{{name}}(/|$)(.*)"
    className: "nginx"
    annotations:
      nginx.ingress.kubernetes.io/rewrite-target: "/$2"
  flinkConfiguration:
    taskmanager.numberOfTaskSlots: "2"
  serviceAccount: flink
  jobManager:
    replicas: 1
    resource:
      memory: "1024m"
      cpu: 1
  taskManager:
    replicas: 1
    resource:
      memory: "1024m"
      cpu: 1

方式二Flink集群的yaml文件与方式一是一样的。

第三步,编写Flink作业yaml文件,如下所示。

# Flink作业  源码请到 https://bigdataonk8s.com 获取
apiVersion: flink.apache.org/v1beta1
kind: FlinkSessionJob
metadata:
  namespace: flink
  name: session-job-only
spec:
  deploymentName: session-deployment-only  # 需要与创建的集群名称一致
  job:
    jarURI: http://192.168.56.85:8080/jars/flink/flink-on-k8s-demo-1.0-SNAPSHOT.jar # 使用http方式下载jar包
    entryClass: com.yale.StreamWordCount
    args:
    parallelism: 1  # 并行度
    upgradeMode: stateless

在yaml文件里有三处地方需要特别注意,首先是开头部分定义了资源的类型为FlinkSessionJob;其次,spec.deploymentName需要与前面创建的Flink集群名字一致,否则Flink作业(或拟启动的TaskManager)会因为找不到JobManager而无法启动;最后,job.jarURI指向了Flink作业Jar包的下载地址,切记TaskManager Pod与Tomcat的网络一定要联通,job.entryClass则为Flink作业的启动类名称。

第四步,运行Flink集群和Flink作业,使用如下命令提交Flink集群和Flink作业yaml文件到Kubernetes运行,并查看Pod的创建情况。

kubectl apply -f session-deployment-only.yaml 
kubectl apply -f session-job-only.yaml
kubectl get all -n flink -owide

如果要终止Flink作业和Flink集群运行,使用如下命令即可。

kubectl delete -f session-deployment-only.yaml 
kubectl delete -f session-job-only.yaml
2.2.2 两种方式的选择

Session部署模式的2种作业提交方式的最大区别在于Flink作业Jar包的获取方式不同,Session部署模式的2种作业提交方式优缺点并不明显,各有适用的场景,按照实际情况选择即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值