背景
Data on Kubernetes
在现代化数据策略的推动下,我们看到越来越多的客户将大数据工作负载从传统的虚拟机迁移到容器化环境。客户被 Kubernetes 所带来的动态扩展、快速构建和资源编排能力所吸引。同时,流行的大数据流/批处理引擎如 Apache Spark、Apache Flink 等也开始支持 Kubernetes 作为资源管理器。
Amazon EMR on EKS
Amazon EMR on EKS 为 Amazon EMR 提供了部署选项,可让您在 Amazon Elastic Kubernetes Service(Amazon EKS)上运行开源大数据框架。借助此部署选项,您可以专注于运行分析工作负载,同时 Amazon EMR on EKS 为开源应用程序构建、配置和管理容器。截止至 2024 年 4 月,Amazon EMR on EKS 已经支持 Apache Spark 和 Apache Flink 引擎,并且计划支持 Trino。
Apache Kyuubi
Apache Kyuubi 的目标是提供一个高度并发、可扩展且支持多租户的 SQL 引擎,以满足大数据分析的需求。它由 Apache Spark、Apache Flink 和 Trino 等流行计算框架提供支持,提供高效的查询功能。用户可以通过 JDBC/ODBC 访问 Kyuubi,从而能够直接或通过 BI 工具运行 SQL 查询。 Kyuubi 促进资源共享并提供快速响应。它与各种来源无缝集成,包括 Apache Hive/HDFS 等传统数据仓库和 Apache Iceberg、Apache Hudi 和 Delta Lake 等现代 Lakehouse 标准。
Kyuubi 与不同的资源管理器(包括 K8s 和 YARN)集成开箱即用,因此这使我们能够轻松地与 EKS 上的 EMR 和 EC2 上的 EMR 集成。在此之前,我们通过“使用 EMR Hue 整合 Apache Kyuubi 提升 Spark SQL 开发效率”一文来介绍 Apache Kyuubi 和 EMR on EC2 的集成,在此文中,我们会继续探索 Apache Kyuubi 和 EMR on EKS 集成的方式和体验。
方案架构总览
方案搭建步骤
预置 EMR on EKS 环境
git clone https://github.com/aws-samples/aws-emr-utilities.git
cd aws-emr-utilities/utilities/emr-on-eks-kyuubi
使用脚本进行工具预置。
使用脚本进行 EMR on EKS 环境预置:
该脚本在 emr 命名空间中设置了一个 EMR on EKS virtual cluster,Kyuubi 组件安装在名为 kyuubi 的单独命名空间中。为了允许 Kyuubi 跨不同命名空间 emr 创建 Spark 集群,该脚本在 emr 命名空间中构建了一个服务帐户 emr-kyuubi,该帐户映射到预构建的 EMR on EKS role emr-containers-role-spark-driver。
使用 kubectl get role -n emr 查看,若环境中没有 emr-containers-role-spark-driver 存在若没有,请将此文件下载, 并运行 kubectl apply -f emr-containers-driver-role.yaml -n emr
构建包含 Apache Kyuubi的EMR on EKS 自定义镜像
注意:下述以 us-east-1 区域为例,其他区域要注意更改到对应 Amazon ECR 镜像仓库的账号,列表如下: https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/docker-custom-images-tag.html
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
AWS_REGION=us-east-1
ECR_URL=$ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 755674844232.dkr.ecr.us-east-1.amazonaws.com
aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $ECR_URL
# create a new repository in your ECR, **ONE-OFF task**
aws ecr create-repository --repository-name kyuubi-emr-eks --image-scanning-configuration scanOnPush=true
docker buildx build --platform linux/amd64,linux/arm64 \
-t $ECR_URL/kyuubi-emr-eks:emr6.15_kyuubi1.8 \
-f dockers/kyuubi/Dockerfile \
--build-arg SPARK_BASE_IMAGE=755674844232.dkr.ecr.us-east-1.amazonaws.com/spark/emr-6.15.0 \
--build-arg KYUUBI_VERSION=1.8.0 \
--build-arg SPARK_VERSION=3.4.1 \
--build-arg RANGER_VERSION=2.4.0 \
--push .
从 Docker Engine 23.0 和 Docker Desktop 4.19 开始,Buildx 是默认的构建客户端。但是,如果您使用的是旧版本,请参阅此链接以获取完整的设置说明:
docker buildx 完整命令可以参考此链接。
Dockerfile 内容请见链接。
安装 Apache Kyuubi
git clone https://github.com/aws-samples/aws-emr-utilities.git
cd aws-emr-utilities/utilities/emr-on-eks-kyuubi
helm install kyuubi charts/kyuubi -n kyuubi --create-namespace -f charts/my-kyuubi-values.yaml --debug
# check the installation progress
kubectl get all -n kyuubi
my-kyuubi-values.yaml 文件模板可以从此链接下载。
注意配置 cross namespace service account,如上述链接 17 行开始的示例:
serviceAccount:
create: false
name: cross-ns-kyuubi
my-kyuubi-values.yaml 文件需要修改的配置项
repository 的内容改成推送到自己 ECR 仓库的 kyuubi-emr-eks 镜像地址:
replicaCount: 2
image:
repository: 02173xxx.dkr.ecr.us-west-2.amazonaws.com/kyuubi-emr-eks
tag: "6.15"
spark.kubernetes.container.image 参数修改成和上述一样的 kyuubi-emr-eks 镜像地址
spark.kubernetes.container.image=02173xxx.dkr.ecr.us-west-2.amazonaws.com/kyuubi-emr-eks:6.15
修改 spark.kubernetes.file.upload.path 参数到您的 S3 桶下。
查看 kyuubi namespaces 下的资源
kubectl get all -n kyuubi
NAME READY STATUS RESTARTS AGE
pod/kyuubi-0 1/1 Running 0 15d
pod/kyuubi-1 1/1 Running 0 134m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kyuubi-headless ClusterIP None <none> 3309/TCP,10099/TCP,10009/TCP,10010/TCP 16d
service/kyuubi-rest ClusterIP 10.100.88.166 <none> 10099/TCP 16d
service/kyuubi-thrift-binary ClusterIP 10.100.239.139 <none> 10009/TCP 16d
NAME READY AGE
statefulset.apps/kyuubi 2/2 16d
kubectl describe rolebinding kyuubi-emr -n emr
Name: kyuubi-emr
............
Role:
Kind: Role
Name: kyuubi-emr
Subjects:
Kind Name Namespace
---- ---- ---------
ServiceAccount cross-ns-kyuubi kyuubi
功能验证
1. 登录 Kyuubi Server
kubectl exec -it pod/kyuubi-0 -n kyuubi -- bash
1.1 从 Kyuubi Server 提交任务到 EMR on EKS namespace
/usr/lib/spark/bin/spark-submit \
--master k8s://https://kubernetes.default.svc:443 \
--deploy-mode cluster \
--class org.apache.spark.examples.SparkPi \
--conf spark.executor.instances=5 \
local:///usr/lib/spark/examples/jars/spark-examples.jar 100
查看 SparkPi 的资源运行情况
kubectl get pod -namespace emr -w
NAME READY STATUS RESTARTS AGE
org-apache-spark-examples-sparkpi-1dc1958e8b4c5001-driver 1/1 Running 0 8s
spark-pi-0672778e8b4c63ed-exec-1 1/1 Running 0 3s
spark-pi-0672778e8b4c63ed-exec-2 1/1 Running 0 3s
spark-pi-0672778e8b4c63ed-exec-3 1/1 Running 0 3s
spark-pi-0672778e8b4c63ed-exec-4 1/1 Running 0 3s
spark-pi-0672778e8b4c63ed-exec-5 1/1 Running 0 3s
1.2 通过 Thrift(HiveServer2 Compatible)连接到 Kyuubi
./bin/beeline -u 'jdbc:hive2://kyuubi-0.kyuubi-headless.kyuubi.svc.cluster.local:10009?spark.app.name=testdelta' -n hadoop
成功连接后,可以进行简单的 SQL 验证。
查看库:
0: jdbc:hive2://kyuubi-thrift-binary.kyuubi:10009> show databases;
查看表:
0: jdbc:hive2://kyuubi-0.kyuubi- headless.kyuu>SHOW TABLES IN ods;
查询数据:
select * from customer limit 10;
配置 Hue 访问 Kyuubi
本文使用 EMR(on EC2)的 Hue 访问 EKS 部署的 Kyuubi(也可进行额外搭建Hue)。首先给 Kyuubi 配置一个负载均衡器,用来建立公网访问方式。
cat <<EOF > kyuubi-loadbalance.yaml
apiVersion: v1
kind: Service
metadata:
name: kyuubi-loadbalance
namespace: kyuubi
spec:
ports:
- name: thrift-binary
port: 10009
protocol: TCP
targetPort: 10009
selector:
app.kubernetes.io/instance: kyuubi
app.kubernetes.io/name: kyuubi
type: LoadBalancer
EOF
kubectl apply -f kyuubi-loadbalance.yaml -n kyuubi
kubectl get svc -n kyuubi
SSH 到 EMR on EC2 的 master node 更新 Hue 的 Spark 访问配置(/etc/hue/conf/hue.ini),将 sql_server_host 的地址配置为负载均衡器的地址,将 sql_server_port 配置为 10009。
重启 Hue 服务
sudo systemctl restart hue
访问 Hue 的 SparkSql 时会出现异常
此时 Spark driver 的 pod 状态如下图所示
进一步查看 spark driver pod 的 log 会发现如下错误信息
针对上述问题,kyuubi 官方提供了 kyuubi.kubernetes.spark.forciblyRewriteDriverPodName.enabled 和 kyuubi.kubernetes.spark.forciblyRewriteExecutorPodNamePrefix.enabled 两个参数来解决,具体描述请参考配置介绍。这两个参数是在 Kyuubi 1.8.1 版本开始支持。
更新为
kyuubi.kubernetes.spark.forciblyRewriteDriverPodName.enabled |
true |
kyuubi.kubernetes.spark.forciblyRewriteExecutorPodNamePrefix.enabled |
true |
完成后,再次访问 Hue 的 SparkSql 页面,可以正常加载 database 信息:
查询数据:
select * from customer limit 10;
总结
本文探讨了如何将 Apache Kyuubi 和 EMR on EKS 结合,发掘其在数据处理和分析领域的潜力。通过将它们结合起来,我们可以利用 Kyuubi 作为统一的多租户 JDBC 接口,同时充分发挥 EMR on EKS 在大规模数据处理和分析方面的优势。这种结合不仅仅能够提供更强大、更灵活的数据分析平台,同时也为企业提供了更高效的解决方案。
本篇作者