创建并运行 EMR on EKS 集群
Posted bluishglc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了创建并运行 EMR on EKS 集群相关的知识,希望对你有一定的参考价值。
文章目录
EMR on EKS的创建工作完全是命令行驱动的,目前尚无对应的UI界面来完成相关操作。本文将通过命令行演示如何创建并运行一个EMR on EKS集群。创建EMR on EKS的过程可以分为两个阶段:第一阶段是先创建出一个EKS集群,第二阶段是在这个EKS集群之上创建EMR的虚拟集群,以下是具体操作步骤。
注:在操作过程中,我们将会陆续得到一些值,例如EKS集群的名称,虚拟集群的ID,这些变量在后续的操作中会再次使用,为了便于提升文中脚本的可复用性,我们会单独将这些值抽取出来,赋给一个变量,同时用export导出,便于后续的引用。以下是操作过程中将会生成并被引用到的一些变量,以及本例我们将采用的值:
变量名称 | 本例取值 | 描述 |
---|---|---|
REGION | us-east-1 | 当前所处的AWS REGION |
ZONES | us-east-1a,us-east-1b,us-east-1c | 分配给将要创建的EKS集群的可用区 |
EKS_CLUSTER_NAME | it-infrastructure | 将要创建的EKS集群的名称 |
DATALAKE_NAMESPACE | datalake | 将要在EKS上创建的面向数据系统的Kubenetes命名空间,将要创建的EMR on EKS虚拟集群会被置于该空间下 |
VIRTUAL_CLUSTER_NAME | emr-cluster-1 | 将要创建的EMR on EKS虚拟集群的名字 |
SSH_PUBLIC_KEY | <从EC2->Kye Pairs处查找> | 将要创建的EKS集群需要指定公钥 |
EXECUTION_ROLE_ARN | <从IAM的Admin Role处查找> | 用于运行EMR on EKS的IAM Role |
VIRTUAL_CLUSTER_ID | <过程中产生> | 将要创建的EMR on EKS虚拟集群的ID |
以下是为上述全局变量赋值的命令(VIRTUAL_CLUSTER_ID将在后续操作中产生,暂不赋值):
export REGION="us-east-1"
export ZONES="us-east-1a,us-east-1b,us-east-1c"
export EKS_CLUSTER_NAME="it-infrastructure"
export DATALAKE_NAMESPACE="datalake"
export VIRTUAL_CLUSTER_NAME="emr-cluster-1"
export SSH_PUBLIC_KEY="<your-pub-key-name>"
export EXECUTION_ROLE_ARN="<your-admin-role-arn>"
0. 前置条件
- 确保有你有一台Linux主机,并已安装awscli命令行
- 确保配置给awscli的access_key属于一个Admin账号
1. 安装ekscli
ekscli是用于操作eks的命令行工具,我们需要使用到该工具,须先行安装,安装命令如下:
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin
2. 安装kubectl
kubectl是用于管理kubenetes集群的命令行工具,我们需要使用到该工具,须先行安装,安装命令如下:
curl -o kubectl https://amazon-eks.s3.us-west-2.amazonaws.com/1.20.4/2021-04-12/bin/linux/amd64/kubectl
chmod +x ./kubectl
mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$PATH:$HOME/bin
echo 'export PATH=$PATH:$HOME/bin' >> ~/.bashrc
3. 创建EKS集群
接下来,我们要在美东1创建名为ABC_IT_INFRASTRUCTURE
的EKS集群,命令如下:
eksctl create cluster \\
--region $REGION \\
--name $EKS_CLUSTER_NAME \\
--zones $ZONES \\
--node-type m5.xlarge \\
--nodes 5 \\
--with-oidc \\
--ssh-access \\
--ssh-public-key $SSH_PUBLIC_KEY \\
--managed
上述命令行需要注意如下几点:
$SSH_PUBLIC_KEY
为你在AWS上的公钥key的ID,这个字符串可在EC2控制台->Key Pairs处查找,name列即是;--zones
并不是必选项,如不指定,会随机选择AZ,但是有时随机选择的AZ在创建时并没有足够的资源支撑请求创建的EKS集群,这时就需要显式地指定zone来避开不可用的zone;--node-type
和--nodes
也不是必选项,如不指定,集群默认部署在2个m5.large节点上,对于EMR来说,这个集群的配置太低了,所以必须显式配置这两项,赋予集群更大的资源;
上述命令行需要执行较长时间(约20分钟左右),当最后出现:
EKS cluster "ABC_IT_INFRASTRUCTURE" in "us-east-1" region is ready
表明EKS集群已经建好。需要注意的是,该命令在执行过程中会通过Cloud Formation创建大量的基础设施,包括IAM Role,VPC,EC2等等,中途发生错误的可能性较大,且很多操作是不能自动回滚的,所以需要打开Cloud Formation的控制台并持续关注,如发现未清理的Stack,须手动删除Stack后再重新执行上述命令。
eksctl create cluster
还有很多可配置的选项,可以通过如下命令查看详细说明:
eksctl create cluster -h
4. 查看EKS集群状态
EKS集群创建完成后,为确保集群是否健康,可通过命令行查看一下集群状况(该步骤非必须,可跳过)。
- 查看集群各物理节点状况
kubectl get nodes -o wide
- 查看集群POD的状况
kubectl get pods --all-namespaces -o wide
5. 创建Namespace
为便于对资源进行管理,我们可以在Kubenetes集群上为数据相关的系统创建单独的namespace,取名ABC_DATALAKE
,后续创建的EMR虚拟集群将被置于该namespace下:
kubectl create namespace $DATALAKE_NAMESPACE
6. 授权访问Namespace
默认情况下,EMR on EKS是无权直接访问和使用EKS上的namespace的,需要我们创建一个Kubernetes role,然后将该Role绑定到一个Kubernetes user上,同时将一个服务角色AWSServiceRoleForAmazonEMRContainers映射到这个user上,这样才能桥接Kubenetes端和EMR on EKS服务端之间的权限认证,幸运的是我们不需要手动逐一完成这些操作,通过一条eksctl命令可以直接实现:
eksctl create iamidentitymapping \\
--region $REGION \\
--cluster $EKS_CLUSTER_NAME \\
--namespace $DATALAKE_NAMESPACE \\
--service-name "emr-containers"
控制台的输出也会印证上面的论述:
2021-06-02 12:39:49 [ℹ] created "datalake:Role.rbac.authorization.k8s.io/emr-containers"
2021-06-02 12:39:49 [ℹ] created "datalake:RoleBinding.rbac.authorization.k8s.io/emr-containers"
2021-06-02 12:39:49 [ℹ] adding identity "arn:aws:iam::1234567898765:role/AWSServiceRoleForAmazonEMRContainers" to auth ConfigMap
7. 创建Job Execution Role
运行EMR on EKS需要一个IAM Role,在这个Role中要配置授权EMR on EKS可以使用的资源有哪些,例如s3上某些桶,cloudwatch等服务,这些被称之为Role Policies,官方文档给出过一份Role Policies的参考配置,可参见:https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/creating-job-execution-role.html。
为方便起见,本文将直接使用Admin角色作为job execution role。
8. 创建Role的Trust Relationship
如果通过第7步创建了一个role,还需要对这个role进行编辑,添加这个role和EMR服务账号(EMR managed service account)之间的互信。这里所谓的EMR服务账号(EMR managed service account)是在job提交时自动创建的,所以在配置中在EMR服务账号部分会使用统配符。
不过幸运的是,我们不需要手动编辑Role的Trust Relationships部分,我们可以如下命令行自动添加这个Trust Relationship:
aws emr-containers update-role-trust-policy \\
--cluster-name $EKS_CLUSTER_NAME \\
--namespace $DATALAKE_NAMESPACE \\
--role-name <Admin or the-job-excution-role-name-you-created>
其中,你需要将<Admin or the-job-excution-role-name-you-created>
替换为Admin或者是在第7步中创建的role的名称。当创建成功之后,可以在Role的Trust Relationships页面看到生成的类似下面的相关配置:
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::1234567898765:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/1C2DF227CD8E011A693BCF03D7EBD581"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"oidc.eks.us-east-1.amazonaws.com/id/1C2DF227CD8E011A693BCF03D7EBD581:sub": "system:serviceaccount:kube-system:emr-containers-sa-*-*-1234567898765-3l0vgne6"
}
}
}
即使我们在第7步选择使用Admin角色作为job execution role,该步操作依然需要执行,–role-name取值Admin, 否则在作业执行过程中无权完成创建Log Group以及在s3上存储日志等操作。
9. 在EKS上创建EMR虚拟集群
接下来我们就将创建EMR集群了,其实更准确的叫法应该是“注册”,因为这一步执行完成后并不会在EKS上生成一个EMR集群,这里创建的是一个虚拟的集群,集群要在第一次提交作业时才会创建。创建集群的命令如下:
# create virtual cluster description file
tee $VIRTUAL_CLUSTER_NAME.json <<EOF
{
"name": "$VIRTUAL_CLUSTER_NAME",
"containerProvider": {
"type": "EKS",
"id": "$EKS_CLUSTER_NAME",
"info": {
"eksInfo": {
"namespace": "$DATALAKE_NAMESPACE"
}
}
}
}
EOF
# create virtual cluster
aws emr-containers create-virtual-cluster --cli-input-json file://./$VIRTUAL_CLUSTER_NAME.json
上述命令先创建一个集群描述文件$VIRTUAL_CLUSTER_NAME.json
, 这个文件描述了EMR集群的名称以及要建在哪个EKS集群的哪个Namespace上,然后通过aws emr-containers create-virtual-cluster
创建出这个文件描述的虚拟集群。
上述命令如果执行成功,会在控制台输出一份描述集群的json数据,其中的id
字段较为重要,后续提交作业时都会使用到这个id,如果没有保存下来,也可以通过如下命令随时查询:
aws emr-containers list-virtual-clusters
将获得的id付给全局变量VIRTUAL_CLUSTER_ID
,后续操作将会多次引用到该ID:
export VIRTUAL_CLUSTER_ID='<cluster-id>'
10. 向EMR on EKS提交作业
虚拟集群建好之后,就可以提交大数据作业了,EMR on EKS是基于容器的,不同于EMR通过shell登录进行操作(可以但不方便),常规的使用方式是将其视为一个计算资源的黑盒,向其提交作业即可。以下是一条向EMR on EKS提交作业的示例命令,它执行的是spark自带的example程序pi.py
aws emr-containers start-job-run \\
--virtual-cluster-id $VIRTUAL_CLUSTER_ID \\
--name sample-job-name \\
--execution-role-arn $EXECUTION_ROLE_ARN \\
--release-label emr-6.2.0-latest \\
--job-driver '{"sparkSubmitJobDriver": {"entryPoint": "local:///usr/lib/spark/examples/src/main/python/pi.py","sparkSubmitParameters": "--conf spark.executor.instances=2 --conf spark.executor.memory=2G --conf spark.executor.cores=2 --conf spark.driver.cores=1"}}' \\
--configuration-overrides '{"monitoringConfiguration": {"cloudWatchMonitoringConfiguration": {"logGroupName": "/emr-on-eks/$VIRTUAL_CLUSTER_NAME", "logStreamNamePrefix": "pi"}}}'
start-job-run
这条命令最需要关注的是--job-driver
这个参数,所有关于作业本身的相关信息都在这个参数里了。基于文档可知,目前的EMR on EKS仅支持sparkSubmitJobDriver
一种形式的作业提交,即只能是以spark-submit可接受的形式提交作业,也就是通过jar包+class或pyspark脚本的形式提交作业。jar包及其依赖jar文件可部署在s3上。
一种更加优雅的作业提交方式是提供一份job run的json描述文件,把所有集群、作业和作业配置相关的信息集中配置在这份json文件中,然后通过命令执行,如下所示:
# create job description file
tee start-job-run-request.json <<EOF
{
"name": "sample-job-name",
"virtualClusterId": "$VIRTUAL_CLUSTER_ID",
"executionRoleArn": "$EXECUTION_ROLE_ARN",
"releaseLabel": "emr-6.2.0-latest",
"jobDriver": {
"sparkSubmitJobDriver": {
"entryPoint": "local:///usr/lib/spark/examples/src/main/python/pi.py",
"sparkSubmitParameters": "--conf spark.executor.instances=2 --conf spark.executor.memory=2G --conf spark.executor.cores=2 --conf spark.driver.cores=1"
}
},
"configurationOverrides": {
"applicationConfiguration": [
{
"classification": "spark-defaults",
"properties": {
"spark.driver.memory":"2G"
}
}
],
"monitoringConfiguration": {
"persistentAppUI": "ENABLED",
"cloudWatchMonitoringConfiguration": {
"logGroupName": "/emr-on-eks/$VIRTUAL_CLUSTER_NAME",
"logStreamNamePrefix": "pi"
},
"s3MonitoringConfiguration": {
"logUri": "s3://glc-emr-on-eks-logs/"
}
}
}
}
EOF
# start job
aws emr-containers start-job-run --cli-input-json file://./start-job-run-request.json
关于json文件的编写,可以参考:https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/emr-eks-jobs-CLI.html#emr-eks-jobs-submit
最后是关于EMR集群的配置,与纯EMR集群类似,集群配置也是通过json文件提交的,写到applicationConfiguration
里面,例如上述配置中的"classification": "spark-defaults"
部分。由于EMR on EKS目前仅支持Spark,所以也只有如下几类classification可配置
Classifications | Descriptions |
---|---|
core-site | Change values in Hadoop’s core-site.xml file. |
emrfs-site | Change EMRFS settings. |
spark-metrics | Change values in Spark’s metrics.properties file. |
spark-defaults | Change values in Spark’s spark-defaults.conf file. |
spark-env | Change values in the Spark environment. |
spark-hive-site | Change values in Spark’s hive-site.xml file. |
spark-log4j | Change values in Spark’s log4j.properties file. |
11. 删除与清理
删除与清理集群的顺序应与创建过程相反,先删除ERM虚拟集群,然后再删除EKS集群:
# 1. list all jobs
aws emr-containers list-job-runs --virtual-cluster-id $VIRTUAL_CLUSTER_ID
# 2. cancel running jobs
aws emr-containers cancel-job-run --id <job-run-id> --virtual-cluster-id $VIRTUAL_CLUSTER_ID
# 3. delete virtual cluster
aws emr-containers delete-virtual-cluster --id $VIRTUAL_CLUSTER_ID
# 4. delete eks cluster
eksctl delete cluster --region $REGION --name $EKS_CLUSTER_NAME
注意:第4步在删除EKS集群时,须找到对应Cloud Formation模板里的一项资源NodeInstanceRole
,手动dettach 该Role上的所有policies,命令才能执行成功。
12. 常见错误
-
通过eksctl create cluster创建的eks集群默认是两个m5.large节点,这个配置很难支撑一个EMR集群,所以务必要指定一下节点数量和节点类型:
-
如果在第3步创建EKS集群遇到类似如下的错误:
AWS::EKS::Cluster/ControlPlane: CREATE_FAILED – "Cannot create cluster 'my-bigdata-infra-cluster' because us-east-1e, the targeted availability zone, does not currently have sufficient capacity to support the cluster. Retry and choose from these availability zones: us-east-1a, us-east-1b, us-east-1c, us-east-1d, us-east-1f (Service: AmazonEKS; Status Code: 400; Error Code: UnsupportedAvailabilityZoneException; Request ID: 61028748-0cc1-4100-9152-aab79a475fe6; Proxy: null)"
说明自动分配或指定的某一个AZ目前不可用,可在--zones
参数列表中取其他AZ替换。
关于作者:架构师,15年IT系统开发和架构经验,对大数据、企业级应用架构、SaaS、分布式存储和领域驱动设计有丰富的实践经验,热衷函数式编程。对Hadoop/Spark 生态系统有深入和广泛的了解,参与过Hadoop商业发行版的开发,曾带领团队建设过数个完备的企业数据平台,个人技术博客:https://laurence.blog.csdn.net/ 作者著有《大数据平台架构与原型实现:数据中台建设实战》一书,该书已在京东和当当上线。
以上是关于创建并运行 EMR on EKS 集群的主要内容,如果未能解决你的问题,请参考以下文章