AWS EKS 集群可以跨 VPC 中的多个可用区。Spark 应用程序的driver和executor pod 分布在多个可用区中会产生跨AZ的数据传输成本。为了最小化或消除跨AZ的数据传输成本,可以配置应用程序仅在单个可用区内的节点上运行。此外,根据使用情况,可能需要在特定的实例类型上运行 Spark 应用程序。
我们将提交一个Spark作业,只在单AZ的节点上运行。
每个node都有label标签,标志它在哪个AZ运行:
提交作业,只在单AZ运行。在下面的命令中替换AZ的值:
aws emr-containers start-job-run \
--virtual-cluster-id ${EMR_EKS_CLUSTER_ID} \
--name spark-pi-single-az \
--execution-role-arn ${EMR_EKS_EXECUTION_ARN} \
--release-label emr-6.2.0-latest \
--job-driver '{
"sparkSubmitJobDriver": {
"entryPoint": "s3://aws-data-analytics-workshops/emr-eks-workshop/scripts/pi.py",
"sparkSubmitParameters": "--conf spark.kubernetes.node.selector.topology.kubernetes.io/zone='<可用区>' --conf spark.executor.instances=1 --conf spark.executor.memory=2G --conf spark.executor.cores=2 --conf spark.driver.cores=1"
}
}' \
--configuration-overrides '{
"applicationConfiguration": [
{
"classification": "spark-defaults",
"properties": {
"spark.driver.memory":"2G"
}
}
],
"monitoringConfiguration": {
"cloudWatchMonitoringConfiguration": {
"logGroupName": "/emr-containers/jobs",
"logStreamNamePrefix": "emr-eks-workshop"
},
"s3MonitoringConfiguration": {
"logUri": "'"$S3_BUCKET"'/logs/"
}
}
}'
当作业启动时,driver pod和executor pod只会被调度到带有标签topology.kubernetes.io/zone: <az-name>
的EKS工作节点上。这确保了Spark作业在单AZ内运行。
pod运行在30结尾的IP上:
查看这个IP,发现它确实属于us-west-2d
:
参考:
https://spark.apache.org/docs/latest/running-on-kubernetes.html#pod-spec
https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
AZ是EKS分配给每个EKS工作节点的内置标签。上述配置将确保executor pod和driver pod被调度到带有标签topology.kubernetes.io/zone: <az-name>
的EKS工作节点上。
用户定义的标签也可以分配给EKS工作节点并用作节点选择器。
其他常见用例是使用节点标签来强制作业在on-demand/spot
实例或特定机型上运行。
我们将提交一个Spark作业,只在单AZ的节点上运行,并使用特定的实例类型。
提交作业,在下面的命令中替换可用区和实例类型的值:
aws emr-containers start-job-run \
--virtual-cluster-id ${EMR_EKS_CLUSTER_ID} \
--name spark-pi-single-az-instance-type \
--execution-role-arn ${EMR_EKS_EXECUTION_ARN} \
--release-label emr-6.2.0-latest \
--job-driver '{
"sparkSubmitJobDriver": {
"entryPoint": "s3://aws-data-analytics-workshops/emr-eks-workshop/scripts/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 '{
"applicationConfiguration": [
{
"classification": "spark-defaults",
"properties": {
"spark.driver.memory":"2G",
"spark.kubernetes.node.selector.topology.kubernetes.io/zone":"<可用区>",
"spark.kubernetes.node.selector.node.kubernetes.io/instance-type":"<实例类型>"
}
}
],
"monitoringConfiguration": {
"cloudWatchMonitoringConfiguration": {
"logGroupName": "/emr-containers/jobs",
"logStreamNamePrefix": "emr-eks-workshop"
},
"s3MonitoringConfiguration": {
"logUri": "'"$S3_BUCKET"'/logs/"
}
}
}'
当作业启动时,driver pod和executor pod只会被调度到带有标签topology.kubernetes.io/zone: <可用区>
和标签node.kubernetes.io/instance-type: <实例类型>
的EKS工作节点上。这确保了Spark作业在单一可用区和特定实例类型上运行:
由于我们的集群中全部都是c5.xlarge
机型,所以上面任务的pod永远不会被调度:
这个侧面印证了instance-type
这个selector生效了,如果改成c5.xlarge
则任务会正常运行
另外,可以传递多个键值对给spark.kubernetes.node.selector.[labelKey]
来添加筛选条件,以选择EKS工作节点。