Tutorial: Self Hosted Ververica Platform (VVP)

Tutorial: Self Hosted Ververica Platform (VVP)

十一月 23, 2022

流式处理在大数据场景下已然是一个大趋势, 是实时数据处理、实时数仓的代名词. 与离线的、批处理方式相较, 在获得数据处理的时效性上优势时, 流式处理也会带来技术架构方面的复杂性、开发周期长之类的不足. 在流式处理领域, Flink 目前可以说是一个事实上的标准, 因为其流批一体的特质, 直接避免了 Lambda 架构的混合数仓的复杂性问题.

当我们已经决定好采用流式处理后, 就面临一个问题, 是直接使用 开源版 Apache Flink 还是各个云厂商的实时计算产品? 就国内的厂商来说, 就有以下选择:

云厂商 云产品
阿里云 实时计算 Flink 版
腾讯云 流计算 Oceanus
华为云 实时流计算服务 CS

当然, 决定最终选择的主要因素还是取决于既有业务运行在哪个平台.

显而易见, 我选择了阿里云, 否则也就不会有这篇自建 VVP 的文章了. 这里, 就得说一下 Ververica Platform (abbr. VVP) 跟 Flink 的关系了. 来, 上图:

需要注意到的其实也就一点, 在 2019 年, 阿里收购了 Flink 的创始公司, 而后开发了 Ververica. 有兴趣的, 可以 往这儿跳.

什么是 VVP ?

The Enterprise Stream Processing Platform by the Original Creators of Apache Flink®

Ververica Platform enables every enterprise to take advantage and derive immediate insight from its data in real-time.

Powered by Apache Flink’s robust streaming runtime, Ververica Platform makes this possible by providing an integrated solution for stateful stream processing and streaming analytics at scale.

简单来说, VVP 就是以 Flink 为基石, 打造的一个企业版的实时计算平台. 再白话一点, 利用 VVP 你可以在 Kubernetes 环境下, 快速拉起来一套可用的 Flink 环境. 至于是否能达到企业版的水准, 其实还取决于两个方面:

是用的 VVP Community Edition 还是 Stream Edition ?

Stream Edition 就是收费版

社区版 与 收费版 最能影响到使用的主要差别在于以下几点:

  • 社区版只能使用 local database
  • 社区版只能建立一个 namespace, 这意味着如果我们想 dev、uat、prod 环境做资源隔离, 只能再部署一个 VVP
  • 社区版不能自动伸缩容

更详细的对比, 可以 往这里跳.

开源版 Flink 是不直接支持 CDC 的, 更不用说当业务上用了 某某云平台 的 某某存储中间件, 所以如果有这些需求, 那其实还得自定义 Connector. 与在 Flink 上添加自定义 Connector 不同的是, VVP 社区版 虽然是免费使用, 但并不开源, 所以这抬高了在 VVP 上 DIY 的门槛.

即便通过 VVP 能够快速拉起一个可用的 Flink, 部署一些简单的计算任务, 但离一个实用的实时计算平台其实还很远.

Anyway, let’s do it!

我们将要做些什么?

我们将搭建一个 这样的 VVP:

可以看到, 我们将要部署以下内容:

  • MinIO
  • VVP

而要部署 MinIO, 我们又需要便捷的 Kubernetes存储卷, 比方说:

  • NFS

NFS

想要了解什么是 NFS? 往这里跳 .

Setup NFS Server

安装 nfs 需要的包:

1
$ yum install nfs-utils

新建将用于共享的文件目录:

1
$ mkdir /var/nfsshare

按以下权限设置该目录:

1
2
3
4
$ chmod -R 755 /var/nfsshare

# user `nfsnobody` will be created by previous yum package
$ chown nfsnobody:nfsnobody /var/nfsshare

然后, 启动服务并允许开机启动:

1
2
3
4
$ systemctl enable --now rpcbind
$ systemctl enable --now nfs-server
$ systemctl enable --now nfs-lock
$ systemctl enable --now nfs-idmap

为了让上述目录 /var/nfsshare 共享出去, 编辑 /etc/exports 文件, 比如:

1
/var/nfsshare  *(rw,sync,no_root_squash,no_all_squash)

想要了解更多关于 /etc/exports 文件, 往这里跳 .

最后, 重启 NFS service:

1
$ systemctl restart nfs-server

Setup NFS Client

在 Kubernetes 集群内的机器上安装 nfs-utils 包:

1
$ yum install nfs-utils

创建 NFS 共享目录的挂载点:

1
$ mkdir -p /mnt/data/nfsshare

然后, 将 NFS 共享目录 /var/nfsshare 进行挂载:

1
$ mount -t nfs 172.17.84.63:/var/nfsshare /mnt/data/nfsshare/

检查共享目录下能否顺利进行读写操作:

1
$ touch /mnt/data/nfsshare/test

如果要开机自动挂载, 添加以下内容到 /etc/fstab :
172.17.84.63:/var/nfsshare /mnt/data/nfsshare nfs defaults 0 0

若是要卸载, 使用:

1
2
# i.e., umount mount_point
$ umount /mnt/data/nfsshare

NFS subdir provisioner

Helm chart: NFS subdir external provisioner

当 NFS 就绪后, 我们就可以在 Kubernetes 上部署了 provisioner 了.

1
$ helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/

配置以下 helm chart 参数至 nfs-custom-values.yaml :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
image:
# this is my personal docker image mirror
#
# the original image is:
# k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner
repository: registry.cn-beijing.aliyuncs.com/viclau/k8s-gcr-io.sig-storage.nfs-subdir-external-provisioner
tag: v4.0.2

nfs:
server: 172.17.84.63
path: /mnt/data/nfsshare

# For creating the StorageClass automatically:
storageClass:
create: true

# Set StorageClass as the default StorageClass
# Ignored if storageClass.create is false
defaultClass: true

鉴于 Persistence Volume Provivisioner 一般都是公用的, 所以安装到 kube-system :

1
$ helm install -n kube-system nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --values nfs-custom-values.yaml

MinIO

想要了解什么是 MinIO? 往这里跳 .

Helm chart: minio

配置以下 helm chart 参数至 minio-custom-values.yaml :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
## Set default rootUser, rootPassword
## AccessKey and secretKey is generated when not set
## Distributed MinIO ref: https://min.io/docs/minio/linux/operations/install-deploy-manage/deploy-minio-multi-node-multi-drive.html
##
rootUser: god
rootPassword: god_bless

# Number of MinIO containers running
replicas: 3

persistence:
size: 10Gi

resources:
requests:
memory: 1Gi
  • rootUserrootPassword 用于访问 MinIO UI 时登录.
  • persistence.size 设置整个 MinIO 使用的磁盘大小. 这里仅仅作为示例环境, 所以只分配了 10Gi 的空间.
1
2
$ helm repo add minio https://charts.min.io/
$ helm install --namespace minio --generate-name minio/minio --values minio-custom-values.yaml
  • --generate-name 会随机生成工作负载(Workload)的名称. 因此, 如果是较正式的环境使用, 最好不要指定该选项

要访问 MinIO UI, 有两种方式:

  • 通过 port-forward 暴露 9001 端口
  • 通过 ingress

Ingress 示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
name: ingress-minio-minio
namespace: minio
spec:
rules:
- host: your.domain.name
http:
paths:
- path: /
backend:
serviceName: minio-1667986518-console
servicePort: 9001

可以看到, 这里的 serviceName 是随机的, 是因为先前通过 helm 安装 minio 的时候指定了 --generate-name 选项.

Hey, VVP comes at last!

1
$ helm repo add ververica https://charts.ververica.com

配置以下 Helm chart 参数至 vvp-custom-values.yaml:

1
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
## Either a license must be provided under `vvp.license.data` or you must
## accept the Ververica Platform Community Edition License Agreement by setting
##
## Please read the documentation regarding features of Ververica Platform that are not available
## when using the Community Edition.
##
acceptCommunityEditionLicense: true

##
## Ververica Platform application configuration
##
vvp:

## Platform metadata persistence configuration.
##
## This section configures how Ververica Platform stores metadata such as Deployments and
## Namespace information.
##
## Note: `vvp.persistence.type` is a required setting.
persistence:
## REQUIRED: The type of persistence to use. Must be one of:
## * jdbc: store data in the database configured in the `datasource` section below
## * Supported JDBC drivers: `sqlite`, `postgresql`, `mysql`
## * local: a preset for JDBC storage using SQLite on a local volume (required for Community
## edition)
type: local

blobStorage:
## The base URI for universal blob storage.
##
## If unset, universal blob storage is disabled. If credentials are required, add them to the
## "Blob storage credentials" section below.
#baseUri: oss://viclau-vvp
baseUri: s3://vvp

## Additional config options for supported blob storage providers.
s3:
endpoint: http://minio-1667986518.minio.svc:9000
#oss:
# endpoint: https://oss-cn-beijing-internal.aliyuncs.com


##
## Blob storage credentials
##
blobStorageCredentials:
# ## Use an existing Kubernetes secret instead of providing credentials in this file. The keys
# ## within the secret must follow the format: `<provider>.<credential>`
# ##
# ## For example: `s3.accessKeyId` or `azure.connectionString`
existingSecret: minio-as-s3-secret
# existingSecret: aliyun-oss-secret
#
# s3:
# accessKeyId: ""
# secretAccessKey: ""
# oss:
# accessKeyId: ""
# accessKeySecret: ""


##
## Kubernetes RBAC configuration
##
rbac:

## Additional namespaces that the created ServiceAccount can access. The
## ServiceAccount will be granted the same set of permissions across all
## these namespaces. The namespace of the Application Manager pod should be
## omitted.
additionalNamespaces:
- vvp-jobs
  • blobStorageCredentials.existingSecret 可通过 secret 来提供 MinIO 的账号信息, 即安装 MinIO 时配置的 rootUserrootPassword . 如果不想额外再创建 secret 的话, 也可以通过下方注释掉的 blobStorageCredentials.s3.accessKeyIdblobStorageCredentials.s3.secretAccessKey 达到同样的效果.
  • secret 中的属性名应按 <provider>.<credential> 格式, 比如 s3.accessKeyId, s3.secretAccessKey
  • rbac.additionalNamespaces 该配置项很关键, 否则在后续使用 VVP 的时候会没有权限拉起 Flink

最后一步, 安装:

1
2
3
4
5
6
$ kubectl create ns vvp
$ kubectl create ns vvp-jobs
$ helm install vvp ververica/ververica-platform \
--namespace vvp \
--values vvp-custom-values.yaml \
--version 5.4.1

访问 UI:

1
$ kubectl --namespace vvp port-forward services/vvp-ververica-platform 8080:80

由于 VVP 社区版不提供登录机制, 所以在开放到公网时, 最好通过 ingress 并配合 http basic auth 做一个基本的认证.

总结

通过这篇文章, 相信各位能够看到自建VVP还是挺简单的. 依然不得不强调一下, 单纯的一个 VVP 社区版 离实用的实时计算平台还差得比较远. 比如 Connector 缺失、Python Job 缺失(Flink可以支持, 但这里说的是我们无法通过 VVP 进行 Python Job 的开发和运维).