

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 将 Apache Livy 与 Amazon EMR on EKS 结合使用
<a name="job-runs-apache-livy"></a>

对于 Amazon EMR 7.1.0 及更高版本，可使用 Apache Livy 在 Amazon EMR on EKS 上提交作业。通过 Apache Livy，您可以设置自己的 Apache Livy REST 端点，在 Amazon EKS 集群上部署和管理 Spark 应用程序。在 Amazon EKS 集群中安装 Livy 后，就可以使用 Livy 端点将 Spark 应用程序提交到 Livy 服务器。服务器会管理 Spark 应用程序的生命周期。

**注意**  
Amazon EMR on EMR 会根据 vCPU 和内存消耗计算 Amazon EKS 的定价。该计算适用于驱动程序和执行程序容器组（pod）。该计算从您下载 Amazon EMR 应用程序映像开始，直至 Amazon EKS 容器组（pod）终止，并四舍五入到最接近的秒。

**Topics**
+ [设置适用于 Amazon EMR on EKS 的 Apache Livy](job-runs-apache-livy-setup.md)
+ [开始使用适用于 Amazon EMR on EKS 的 Apache Livy](job-runs-apache-livy-install.md)
+ [使用适用于 Amazon EMR on EKS 的 Apache Livy 运行 Spark 应用程序](job-runs-apache-livy-run-spark.md)
+ [使用 Amazon EMR on EKS 卸载 Apache Livy](job-runs-apache-livy-uninstall.md)
+ [使用 Amazon EMR on EKS 配置 Apache Livy 的安全性](job-runs-apache-livy-security.md)
+ [Amazon EMR on EKS 发行版上的 Apache Livy 安装属性](job-runs-apache-livy-installation-properties.md)
+ [排查常见的环境变量格式错误](job-runs-apache-livy-troubleshooting.md)

# 设置适用于 Amazon EMR on EKS 的 Apache Livy
<a name="job-runs-apache-livy-setup"></a>

在 Amazon EKS 集群上安装 Apache Livy 之前，必须先安装并配置一组必备工具。其中包括用于处理 AWS 资源的基本命令行工具 AWS CLI、用于使用 Amazon EKS 的命令行工具，以及在本用例中用于使您的集群应用程序可用于 Internet 和路由网络流量的控制器。
+ **[安装或更新到最新版本的 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)** — 如果您已经安装了 AWS CLI，请确认您安装的是最新版本。
+ **[设置 kubectl 和 eksctl](https://docs.aws.amazon.com/eks/latest/userguide/install-kubectl.html)**：eksctl 是用来与 Amazon EKS 通信的命令行工具。
+ **[Install Helm](https://docs.aws.amazon.com/eks/latest/userguide/helm.html)**：Kubernetes 的 Helm 包管理器可帮助您在 Kubernetes 集群上安装和管理应用程序。
+ **[开始使用 Amazon EKS - eksctl](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html)**：按照以下步骤在 Amazon EKS 中创建带有节点的新 Kubernetes 集群。
+ **[选择 Amazon EMR 发行版标签](docker-custom-images-tag.md)**：Amazon EMR 7.1.0 及更高版本支持 Apache Livy。
+ **[安装 ALB 控制器 — ALB 控制器](https://docs.aws.amazon.com/eks/latest/userguide/aws-load-balancer-controller.html)**管理 Kubernetes 集群的 AWS Elastic Load Balancing。当你在设置 Apache Livy 时创建 Kubernetes 入口时，它会创建一个 AWS 网络负载均衡器 (NLB)。

# 开始使用适用于 Amazon EMR on EKS 的 Apache Livy
<a name="job-runs-apache-livy-install"></a>

完成以下步骤安装 Apache Livy。包括配置软件包管理器、为运行 Spark 工作负载创建命名空间、安装 Livy、设置负载均衡和验证步骤。要使用 Spark 运行批处理作业，必须完成以下步骤。

1. 设置[适用于 Amazon EMR on EKS 的 Apache Livy](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-setup.html)。

1. 向 Amazon ECR 注册表验证您的 Helm 客户端。您可以[按地区 AWS 区域 从 Amazon ECR 注册账户](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/docker-custom-images-tag.html#docker-custom-images-ECR)中找到相应的`ECR-registry-account`值。

   ```
   aws ecr get-login-password \--region <AWS_REGION> | helm registry login \
   --username AWS \
   --password-stdin <ECR-registry-account>.dkr.ecr.<region-id>.amazonaws.com
   ```

1. 设置 Livy 会为 Livy 服务器创建一个服务账户，为 Spark 应用程序创建另一个账户。要为服务账户设置 IRSA，请参阅[使用服务账户的 IAM 角色（IRSA）设置访问权限](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-irsa.html)。

1. 创建一个命名空间来运行 Spark 工作负载。

   ```
   kubectl create ns <spark-ns>
   ```

1. 使用以下命令安装 Livy。

   此 Livy 端点仅在 EKS 集群的 VPC 内可用。要启用 VPC 之外的访问，请在 Helm 安装命令中设置 `—-set loadbalancer.internal=false`。
**注意**  
默认情况下，该 Livy 端点未启用 SSL，且该端点仅在 EKS 集群的 VPC 内可见。如果您设置了 `loadbalancer.internal=false` 和 `ssl.enabled=false`，就会将不安全的端点在 VPC 外部公开。要设置安全的 Livy 端点，请参阅[使用 TLS/SSL 配置安全的 Apache Livy 端点](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-secure-endpoint.html)。

   ```
   helm install livy-demo \
     oci://895885662937.dkr.ecr.region-id.amazonaws.com/livy \
     --version 7.12.0 \
     --namespace livy-ns \
     --set image=ECR-registry-account.dkr.ecr.region-id.amazonaws.com/livy/emr-7.12.0:latest \
     --set sparkNamespace=<spark-ns> \
     --create-namespace
   ```

   您应当看到如下输出。

   ```
   NAME: livy-demo
   LAST DEPLOYED: Mon Mar 18 09:23:23 2024
   NAMESPACE: livy-ns
   STATUS: deployed
   REVISION: 1
   TEST SUITE: None
   NOTES:
   The Livy server has been installed.
   Check installation status:
   1. Check Livy Server pod is running
     kubectl --namespace livy-ns get pods -l "app.kubernetes.io/instance=livy-demo"
   2. Verify created NLB is in Active state and it's target groups are healthy (if loadbalancer.enabled is true)
   
   Access LIVY APIs:
       # Ensure your NLB is active and healthy
       # Get the Livy endpoint using command:
       LIVY_ENDPOINT=$(kubectl get svc -n livy-ns -l app.kubernetes.io/instance=livy-demo,emr-containers.amazonaws.com/type=loadbalancer -o jsonpath='{.items[0].status.loadBalancer.ingress[0].hostname}' |  awk '{printf "%s:8998\n", $0}')
       # Access Livy APIs using http://$LIVY_ENDPOINT or https://$LIVY_ENDPOINT (if SSL is enabled)
       # Note: While uninstalling Livy, makes sure the ingress and NLB are deleted after running the helm command to avoid dangling resources
   ```

   Livy 服务器和 Spark 会话的默认服务账户名称为 `emr-containers-sa-livy` 和 `emr-containers-sa-spark-livy`。要使用自定义名称，请使用 `serviceAccounts.name` 和 `sparkServiceAccount.name` 参数。

   ```
   --set serviceAccounts.name=my-service-account-for-livy
   --set sparkServiceAccount.name=my-service-account-for-spark
   ```

1. 验证是否已安装 Helm 图表。

   ```
   helm list -n livy-ns -o yaml
   ```

   `helm list` 命令应返回有关新 Helm 图表的信息。

   ```
   app_version: 0.7.1-incubating
   chart: livy-emr-7.12.0
   name: livy-demo
   namespace: livy-ns
   revision: "1"
   status: deployed
   updated: 2024-02-08 22:39:53.539243 -0800 PST
   ```

1. 验证网络负载均衡器是否处于活动状态。

   ```
   LIVY_NAMESPACE=<livy-ns>
   LIVY_APP_NAME=<livy-app-name>
   AWS_REGION=<AWS_REGION>
   
   # Get the NLB Endpoint URL
   NLB_ENDPOINT=$(kubectl --namespace $LIVY_NAMESPACE get svc -l "app.kubernetes.io/instance=$LIVY_APP_NAME,emr-containers.amazonaws.com/type=loadbalancer" -o jsonpath='{.items[0].status.loadBalancer.ingress[0].hostname}') 
   
   # Get all the load balancers in the account's region
   ELB_LIST=$(aws elbv2 describe-load-balancers --region $AWS_REGION)
   
   # Get the status of the NLB that matching the endpoint from the Kubernetes service
   NLB_STATUS=$(echo $ELB_LIST | grep -A 8 "\"DNSName\": \"$NLB_ENDPOINT\"" | awk '/Code/{print $2}/}/' | tr -d '"},\n')
   echo $NLB_STATUS
   ```

1. 现在，验证网络负载均衡器中的目标组是否运行正常。

   ```
   LIVY_NAMESPACE=<livy-ns>
   LIVY_APP_NAME=<livy-app-name>
   AWS_REGION=<AWS_REGION>
   
   # Get the NLB endpoint
   NLB_ENDPOINT=$(kubectl --namespace $LIVY_NAMESPACE get svc -l "app.kubernetes.io/instance=$LIVY_APP_NAME,emr-containers.amazonaws.com/type=loadbalancer" -o jsonpath='{.items[0].status.loadBalancer.ingress[0].hostname}') 
   
   # Get all the load balancers in the account's region
   ELB_LIST=$(aws elbv2 describe-load-balancers --region $AWS_REGION)
   
   # Get the NLB ARN from the NLB endpoint
   NLB_ARN=$(echo $ELB_LIST | grep -B 1 "\"DNSName\": \"$NLB_ENDPOINT\"" | awk '/"LoadBalancerArn":/,/"/'| awk '/:/{print $2}' | tr -d \",)
   
   # Get the target group from the NLB. Livy setup only deploys 1 target group
   TARGET_GROUP_ARN=$(aws elbv2 describe-target-groups --load-balancer-arn $NLB_ARN --region $AWS_REGION | awk '/"TargetGroupArn":/,/"/'| awk '/:/{print $2}' | tr -d \",)
   
   # Get health of target group
   aws elbv2 describe-target-health --target-group-arn $TARGET_GROUP_ARN
   ```

   以下是显示目标组状态的示例输出：

   ```
   {
       "TargetHealthDescriptions": [
           {
               "Target": {
                   "Id": "<target IP>",
                   "Port": 8998,
                   "AvailabilityZone": "us-west-2d"
               },
               "HealthCheckPort": "8998",
               "TargetHealth": {
                   "State": "healthy"
               }
           }
       ]
   }
   ```

   一旦 NLB 的状态变为 `active`，且目标群体变为 `healthy`，就可以继续。该过程可能需要几分钟的时间。

1. 从 Helm 安装中检索 Livy 端点。Livy 端点是否安全取决于是否启用了 SSL。

   ```
   LIVY_NAMESPACE=<livy-ns>
    LIVY_APP_NAME=livy-app-name
    LIVY_ENDPOINT=$(kubectl get svc -n livy-ns -l app.kubernetes.io/instance=livy-app-name,emr-containers.amazonaws.com/type=loadbalancer -o jsonpath='{.items[0].status.loadBalancer.ingress[0].hostname}' |  awk '{printf "%s:8998\n", $0}')
    echo "$LIVY_ENDPOINT"
   ```

1. 从 Helm 安装中检索 Spark 服务账户

   ```
   SPARK_NAMESPACE=spark-ns
   LIVY_APP_NAME=<livy-app-name>
   SPARK_SERVICE_ACCOUNT=$(kubectl --namespace $SPARK_NAMESPACE get sa -l "app.kubernetes.io/instance=$LIVY_APP_NAME" -o jsonpath='{.items[0].metadata.name}')
   echo "$SPARK_SERVICE_ACCOUNT"
   ```

   您应该可以看到类似于如下输出的内容：

   ```
   emr-containers-sa-spark-livy
   ```

1. 如果您设置为`internalALB=true`允许从 VPC 外部进行访问，请创建一个 Amazon EC2 实例，并确保 Network Load Balancer 允许来自该 EC2 实例的网络流量。必须这样做，实例才能访问 Livy 端点。有关在 VPC 外部安全公开端点的更多信息，请参阅[使用 TLS/SSL 设置安全的 Apache Livy 端点](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-secure-endpoint.html)。

1. 安装 Livy 会创建服务账户 `emr-containers-sa-spark` 来运行 Spark 应用程序。如果您的 Spark 应用程序使用诸如 S3 之类的任何 AWS 资源或调用 AWS API 或 CLI 操作，则必须将具有必要权限的 IAM 角色关联到您的 spark 服务账户。有关更多信息，请参阅[使用服务账户的 IAM 角色（IRSA）设置访问权限](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-irsa.html)。

Apache Livy 支持其他配置，您可以在安装 Livy 时使用这些配置。有关更多信息，请参阅 Amazon EMR on EKS 发行版上的 Apache Livy 安装属性。

# 使用适用于 Amazon EMR on EKS 的 Apache Livy 运行 Spark 应用程序
<a name="job-runs-apache-livy-run-spark"></a>

在使用 Apache Livy 运行 Spark 应用程序之前，请确保已完成[设置适用于 Amazon EMR on EKS 的 Apache Livy](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-setup.html) 和[开始使用适用于 Amazon EMR on EKS 的 Apache Livy](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-install.html) 中的步骤。

您可以使用 Apache Livy 运行两种类型的应用程序：
+ 批处理会话：一种 Livy 工作负载，用于提交 Spark 批处理作业。
+ 交互式会话：一种 Livy 工作负载，提供了运行 Spark 查询的编程和可视化界面。

**注意**  
来自不同会话的驱动程序和执行程序容器组（pod）可以相互通信。命名空间不能保证容器组（pod）之间的任何安全性。Kubernetes 不允许对给定命名空间内的容器组（pod）子集进行选择性许可。

## 运行批处理会话
<a name="job-runs-apache-livy-run-spark-batch"></a>

要提交批处理作业，请运行以下命令。

```
curl -s -k -H 'Content-Type: application/json' -X POST \
      -d '{
            "name": "my-session",
            "file": "entryPoint_location (S3 or local)",
            "args": ["argument1", "argument2", ...],
            "conf": {
                "spark.kubernetes.namespace": "<spark-namespace>",
                "spark.kubernetes.container.image": "public.ecr.aws/emr-on-eks/spark/emr-7.12.0:latest",
                "spark.kubernetes.authenticate.driver.serviceAccountName": "<spark-service-account>"
            }
          }' <livy-endpoint>/batches
```

要监控批处理作业，请运行以下命令。

```
curl -s -k -H 'Content-Type: application/json' -X GET <livy-endpoint>/batches/my-session
```

## 运行交互式会话
<a name="job-runs-apache-livy-run-spark-interactive"></a>

要使用 Apache Livy 运行交互式会话，请参阅以下步骤。

1. 确保您可以访问自托管或托管的 Jupyter 笔记本，例如 SageMaker AI Jupyter 笔记本。您的 Jupyter Notebook 必须安装了 [sparkmagic](https://github.com/jupyter-incubator/sparkmagic/blob/master/README.md)。

1. 为 Spark 配置 `spark.kubernetes.file.upload.path` 创建一个存储桶。确保 Spark 服务账户拥有对存储桶的读写权限。有关如何配置 Spark 服务账户的更多详细信息，请参阅“使用服务账户的 IAM 角色（IRSA）设置访问权限”

1. 使用 `%load_ext sparkmagic.magics` 命令在 Jupyter Notebook 中加载 sparkmagic。

1. 运行 `%manage_spark` 命令以使用 Jupyter Notebook 设置 Livy 端点。选择**添加端点**选项卡，选择配置的身份验证类型，将 Livy 端点添加到笔记本，然后选择**添加端点**。

1. 再次运行 `%manage_spark` 以创建 Spark 上下文，然后转到**创建会话**。选择 Livy 端点，指定唯一的会话名称，选择语言，然后添加以下属性。

   ```
   {
     "conf": {
       "spark.kubernetes.namespace": "livy-namespace",
       "spark.kubernetes.container.image": "public.ecr.aws/emr-on-eks/spark/emr-7.12.0:latest",
       "spark.kubernetes.authenticate.driver.serviceAccountName": "<spark-service-account>", 
       "spark.kubernetes.file.upload.path": "<URI_TO_S3_LOCATION_>"
     }
   }
   ```

1. 提交应用程序，等待其创建 Spark 上下文。

1. 要监控交互式会话的状态，请运行以下命令。

   ```
   curl -s -k -H 'Content-Type: application/json' -X GET livy-endpoint/sessions/my-interactive-session
   ```

## 监控 Spark 应用程序
<a name="job-runs-apache-livy-run-ui"></a>

要使用 Livy UI 监控 Spark 应用程序的进度，请使用链接 `http://<livy-endpoint>/ui`。

# 使用 Amazon EMR on EKS 卸载 Apache Livy
<a name="job-runs-apache-livy-uninstall"></a>

按照以下步骤卸载 Apache Livy。

1. 使用命名空间名称和应用程序名称删除 Livy 设置。在此示例中，应用程序名称为 `livy-demo`，命名空间为 `livy-ns`。

   ```
   helm uninstall livy-demo -n livy-ns
   ```

1. 卸载时，EKS 上的 Amazon EMR 会删除 Livy 中的 Kubernetes 服务、 AWS 负载均衡器和您在安装期间创建的目标组。删除资源可能需要几分钟时间。再次在命名空间上安装 Livy 之前，确保已删除资源。

1. 删除 Spark 命名空间。

   ```
   kubectl delete namespace spark-ns
   ```

# 使用 Amazon EMR on EKS 配置 Apache Livy 的安全性
<a name="job-runs-apache-livy-security"></a>

有关使用 Amazon EMR on EKS 配置 Apache Livy 安全性的更多信息，请参阅以下主题。这些选项包括使用传输层安全性、基于角色的访问控制（基于个人在组织中的角色进行访问）以及使用 IAM 角色（根据授予的权限提供对资源的访问）。

**Topics**
+ [使用 TLS/SSL 设置安全的 Apache Livy 端点](job-runs-apache-livy-secure-endpoint.md)
+ [使用基于角色的访问控制（RBAC）设置 Apache Livy 和 Spark 应用程序权限](job-runs-apache-livy-rbac.md)
+ [使用服务账户的 IAM 角色（IRSA）设置访问权限](job-runs-apache-livy-irsa.md)

# 使用 TLS/SSL 设置安全的 Apache Livy 端点
<a name="job-runs-apache-livy-secure-endpoint"></a>

请参阅以下章节，详细了解如何在 EKS 上使用 TLS 和 SSL 加密设置 Apache end-to-end Livy for Amazon EMR。

## 设置 TLS 和 SSL 加密
<a name="job-runs-apache-livy-security-tls"></a>

要在 Apache Livy 端点上设置 SSL 加密，请按照以下步骤操作。
+ [安装 Secrets Store CSI 驱动程序以及机 AWS 密和配置提供程序 (ASCP)](https://docs.aws.amazon.com/secretsmanager/latest/userguide/integrating_csi_driver.html) — Secrets Store CSI 驱动程序和 ASCP 可以安全地存储 Livy 的 JKS 证书和密码，Livy 服务器舱需要这些证书和密码才能启用 SSL。您也可以只安装 Secrets Store CSI Driver，然后使用任何其他受支持的密钥提供程序。
+ [创建 ACM 证书](https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request-public.html)：该证书是确保客户端与 ALB 端点之间安全连接所必需的。
+ 为 AWS Secrets Manager — 设置 JKS 证书、密钥密码和密钥库密码，这是保护 ALB 端点和 Livy 服务器之间连接所必需的。
+ 向 Livy 服务帐户添加从中检索机密的权限 AWS Secrets Manager — Livy 服务器需要这些权限才能从 ASCP 检索机密并添加 Livy 配置来保护 Livy 服务器。要向服务账户添加 IAM 权限，请参阅“使用服务账户的 IAM 角色（IRSA）设置访问权限”。

### 使用密钥和密钥库密码设置 JKS 证书 AWS Secrets Manager
<a name="job-runs-apache-livy-jks-certificate"></a>

按照以下步骤使用密钥和密钥库密码设置 JKS 证书

1. 为 Livy 服务器生成密钥库文件。

   ```
   keytool -genkey -alias <host> -keyalg RSA -keysize 2048 –dname CN=<host>,OU=hw,O=hw,L=<your_location>,ST=<state>,C=<country> –keypass <keyPassword> -keystore <keystore_file> -storepass <storePassword> --validity 3650
   ```

1. 创建证书。

   ```
   keytool -export -alias <host> -keystore mykeystore.jks -rfc -file mycertificate.cert -storepass <storePassword>
   ```

1. 创建信任存储库文件。

   ```
   keytool -import -noprompt -alias <host>-file <cert_file> -keystore <truststore_file> -storepass <truststorePassword>
   ```

1. 将 JKS 证书保存在中。 AWS Secrets Manager将 `livy-jks-secret` 替换为您的密钥，将 `fileb://mykeystore.jks` 替换为密钥库 JKS 证书的路径。

   ```
   aws secretsmanager create-secret \ 
   --name livy-jks-secret \
   --description "My Livy keystore JKS secret" \
   --secret-binary fileb://mykeystore.jks
   ```

1. 将密钥库和密钥密码保存在 Secrets Manager 中。确保使用您自己的参数。

   ```
   aws secretsmanager create-secret \
   --name livy-jks-secret \
   --description "My Livy key and keystore password secret" \
   --secret-string "{\"keyPassword\":\"<test-key-password>\",\"keyStorePassword\":\"<test-key-store-password>\"}"
   ```

1. 使用以下命令创建 Livy 服务器命名空间。

   ```
   kubectl create ns <livy-ns>
   ```

1. 为具有 JKS 证书和密码的 Livy 服务器创建 `ServiceProviderClass` 对象。

   ```
   cat >livy-secret-provider-class.yaml << EOF
   apiVersion: secrets-store.csi.x-k8s.io/v1
   kind: SecretProviderClass
   metadata:
     name: aws-secrets
   spec:
     provider: aws
     parameters:
       objects: |
           - objectName: "livy-jks-secret"
             objectType: "secretsmanager"
           - objectName: "livy-passwords"
             objectType: "secretsmanager"
                        
   EOF
   kubectl apply -f livy-secret-provider-class.yaml -n <livy-ns>
   ```

## 开始使用启用 SSL 的 Apache Livy
<a name="job-runs-apache-livy-ssl-enabled-getting-started"></a>

在 Livy 服务器上启用 SSL 后，必须设置 `serviceAccount` 才能访问 AWS Secrets Manager上的 `keyStore` 和 `keyPasswords` 密钥。

1. 创建 Livy 服务器命名空间。

   ```
   kubectl create namespace <livy-ns>
   ```

1. 设置 Livy 服务账户以访问 Secrets Manager 中的密钥。有关设置 IRSA 的更多信息，请参阅[在安装 Apache Livy 过程中设置 IRSA](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-irsa.html#job-runs-apache-livy-irsa)。

   ```
   aws ecr get-login-password \--region region-id | helm registry login \
   --username AWS \
   --password-stdin ECR-registry-account.dkr.ecr.region-id.amazonaws.com
   ```

1. 安装 Livy。对于 Helm 图表 --version 参数，请使用 Amazon EMR 发行版标签，例如： `7.1.0`您还必须将自己的 Amazon ECR 注册账户编号和地区编号替换为自己 IDs的。您可以[按地区 AWS 区域 从 Amazon ECR 注册账户](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/docker-custom-images-tag.html#docker-custom-images-ECR)中找到相应的`ECR-registry-account`值。

   ```
   helm install <livy-app-name> \
     oci://895885662937.dkr.ecr.region-id.amazonaws.com/livy \
     --version 7.12.0 \
     --namespace livy-namespace-name \
     --set image=<ECR-registry-account.dkr.ecr>.<region>.amazonaws.com/livy/emr-7.12.0:latest \
     --set sparkNamespace=spark-namespace \
     --set ssl.enabled=true
     --set ssl.CertificateArn=livy-acm-certificate-arn
     --set ssl.secretProviderClassName=aws-secrets
     --set ssl.keyStoreObjectName=livy-jks-secret
     --set ssl.keyPasswordsObjectName=livy-passwords
     --create-namespace
   ```

1. 继续执行[在 Amazon EMR on EKS 上安装 Apache Livy](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-setup.html#job-runs-apache-livy-install) 的第 5 步。

# 使用基于角色的访问控制（RBAC）设置 Apache Livy 和 Spark 应用程序权限
<a name="job-runs-apache-livy-rbac"></a>

为了部署 Livy，Amazon EMR on EKS 会创建一个服务器服务账户和角色，以及一个 Spark 服务账户和角色。这些角色必须具有必要的 RBAC 权限才能完成设置和运行 Spark 应用程序。

**服务器服务账户和角色的 RBAC 权限**

Amazon EMR on EKS 会创建 Livy 服务器服务账户和角色，来管理 Spark 作业的 Livy 会话，以及路由进出入口和其他资源的流量。

此服务账户的默认名称为 `emr-containers-sa-livy`。必须拥有以下权限。

```
rules:
- apiGroups:
  - ""
  resources:
  - "namespaces"
  verbs:
  - "get"
- apiGroups:
  - ""
  resources:
  - "serviceaccounts"
    "services"
    "configmaps"
    "events"
    "pods"
    "pods/log"
  verbs:
  - "get"
    "list"
    "watch"
    "describe"
    "create"
    "edit"
    "delete"
    "deletecollection"
    "annotate"
    "patch"
    "label"
 - apiGroups:
   - ""
   resources:
   - "secrets"
   verbs:
   - "create"
     "patch"
     "delete"
     "watch"
 - apiGroups:
   - ""
   resources:
   - "persistentvolumeclaims"
   verbs:
   - "get"
     "list"
     "watch"
     "describe"
     "create"
     "edit"
     "delete"
     "annotate"
     "patch"
     "label"
```

**Spark 服务账户和角色的 RBAC 权限**

Spark 驱动程序 Pod 需要一个与该 Pod 位于同一命名空间的 Kubernetes 服务账户。该服务账户需要拥有权限才能管理执行程序容器组（pod）和驱动程序容器组（pod）所需的任何资源。除非命名空间中的默认服务账户具有所需的权限，否则驱动程序会失败并退出。需要以下 RBAC 权限。

```
rules:
- apiGroups:
  - ""
    "batch"
    "extensions"
    "apps"
  resources:
  - "configmaps"
    "serviceaccounts"
    "events"
    "pods"
    "pods/exec"
    "pods/log"
    "pods/portforward"
    "secrets"
    "services"
    "persistentvolumeclaims"
    "statefulsets"
  verbs:
  - "create"
    "delete"
    "get"
    "list"
    "patch"
    "update"
    "watch"
    "describe"
    "edit"
    "deletecollection"
    "patch"
    "label"
```

# 使用服务账户的 IAM 角色（IRSA）设置访问权限
<a name="job-runs-apache-livy-irsa"></a>

默认情况下，Livy 服务器和 Spark 应用程序的驱动程序和执行器无权访问 AWS 资源。服务器服务帐户和 spark 服务帐户控制 Livy 服务器和 Spark 应用程序的 pod 对 AWS 资源的访问权限。要授予访问权限，您需要将服务账户映射到具有必要 AWS 权限的 IAM 角色。

您可以在安装 Apache Livy 之前、安装过程中或安装完成后设置 IRSA 映射。

## 在安装 Apache Livy 过程中设置 IRSA（适用于服务器服务账户）
<a name="job-runs-apache-livy-irsa"></a>

**注意**  
只有服务器服务账户支持此映射。

1. 确保已完成[设置适用于 Amazon EMR on EKS 的 Apache Livy](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-setup.html)，并正在[使用 Amazon EMR on EKS 安装 Apache Livy](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-install.html)。

1. 为 Livy 服务器创建 Kubernetes 命名空间。在此示例中，应用程序名称为 `livy-ns`。

1. 创建一个 IAM 策略，其中包含您希望 Pod 访问的权限。 AWS 服务 以下示例创建了一个 IAM 策略，用于获取 Spark 入口点的 Amazon S3 资源。

   ```
   cat >my-policy.json <<EOF{
   "Version": "2012-10-17",		 	 	 
       "Statement": [
           {
   "Effect": "Allow",
               "Action": "s3:GetObject",
               "Resource": "arn:aws:s3:::my-spark-entrypoint-bucket"
           }
       ]
   }
   EOF
   
   aws iam create-policy --policy-name my-policy --policy-document file://my-policy.json
   ```

1. 使用以下命令将您的 AWS 账户 ID 设置为变量。

   ```
   account_id=$(aws sts get-caller-identity --query "Account" --output text)
   ```

1. 将集群的 OpenID Connect（OIDC）身份提供程序设置为环境变量。

   ```
   oidc_provider=$(aws eks describe-cluster --name my-cluster --region $AWS_REGION --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")
   ```

1. 为服务账户的命名空间和名称设置变量。务必使用您自己的值。

   ```
   export namespace=default
   export service_account=my-service-account
   ```

1. 使用以下命令创建信任策略文件。如果要向命名空间内的所有服务账户授予角色访问权限，请复制以下命令，将 `StringEquals` 替换为 `StringLike`，将 `$service_account` 替换为 `*`。

   ```
   cat >trust-relationship.json <<EOF
   {
     "Version": "2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Federated": "arn:aws:iam::$account_id:oidc-provider/$oidc_provider"
         },
         "Action": "sts:AssumeRoleWithWebIdentity",
         "Condition": {
           "StringEquals": {
             "$oidc_provider:aud": "sts.amazonaws.com",
             "$oidc_provider:sub": "system:serviceaccount:$namespace:$service_account"
           }
         }
       }
     ]
   }
   EOF
   ```

1. 创建角色。

   ```
   aws iam create-role --role-name my-role --assume-role-policy-document file://trust-relationship.json --description "my-role-description"
   ```

1. 使用以下 Helm install 命令设置 `serviceAccount.executionRoleArn` 以映射 IRSA。以下是 Helm install 命令的示例。您可以[按地区 AWS 区域 从 Amazon ECR 注册账户](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/docker-custom-images-tag.html#docker-custom-images-ECR)中找到相应的`ECR-registry-account`值。

   ```
   helm install livy-demo \
     oci://895885662937.dkr.ecr.us-west-2.amazonaws.com/livy \
     --version 7.12.0 \
     --namespace livy-ns \
     --set image=ECR-registry-account.dkr.ecr.region-id.amazonaws.com/livy/emr-7.12.0:latest \
     --set sparkNamespace=spark-ns \
     --set serviceAccount.executionRoleArn=arn:aws:iam::123456789012:role/my-role
   ```

## 将 IRSA 映射到 Spark 服务账户
<a name="job-runs-apache-livy-irsa-spark"></a>

将 IRSA 映射到 Spark 服务账户之前，请确保已完成以下项目：
+ 确保已完成[设置适用于 Amazon EMR on EKS 的 Apache Livy](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-setup.html)，并正在[使用 Amazon EMR on EKS 安装 Apache Livy](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-install.html)。
+ 您的集群必须具有现有的 IAM OpenID Connect（OIDC）提供程序。要查看您是否拥有提供程序或如何创建，请参阅[为集群创建 IAM OIDC 提供程序](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html)。
+ 确保您已安装 0.171.0 或更高版本的 `eksctl` CLI 或 AWS CloudShell。要安装或更新 `eksctl`，请参阅 `eksctl` 文档中的[安装](https://eksctl.io/installation/)。

按照以下步骤将 IRSA 映射到 Spark 服务账户：

1. 使用以下命令获取 Spark 服务账户。

   ```
   SPARK_NAMESPACE=<spark-ns>
   LIVY_APP_NAME=<livy-app-name>
   kubectl --namespace $SPARK_NAMESPACE describe sa -l "app.kubernetes.io/instance=$LIVY_APP_NAME" | awk '/^Name:/ {print $2}'
   ```

1. 为服务账户的命名空间和名称设置变量。

   ```
   export namespace=default
   export service_account=my-service-account
   ```

1. 使用以下命令为 IAM 角色创建信任策略文件。下面的示例允许命名空间内的所有服务账户使用该角色。为此，请将 `StringEquals` 替换为 `StringLike`，将 `$service_account` 替换为 \$1。

   ```
   cat >trust-relationship.json <<EOF
   {
     "Version": "2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Federated": "arn:aws:iam::$account_id:oidc-provider/$oidc_provider"
         },
         "Action": "sts:AssumeRoleWithWebIdentity",
         "Condition": {
           "StringEquals": {
             "$oidc_provider:aud": "sts.amazonaws.com",
             "$oidc_provider:sub": "system:serviceaccount:$namespace:$service_account"
           }
         }
       }
     ]
   }
   EOF
   ```

1. 创建角色。

   ```
   aws iam create-role --role-name my-role --assume-role-policy-document file://trust-relationship.json --description "my-role-description"
   ```

1. 使用以下 `eksctl` 命令映射服务器或 Spark 服务账户。务必使用您自己的值。

   ```
    eksctl create iamserviceaccount --name spark-sa \
    --namespace spark-namespace --cluster livy-eks-cluster \
    --attach-role-arn arn:aws:iam::0123456789012:role/my-role \
    --approve --override-existing-serviceaccounts
   ```

# Amazon EMR on EKS 发行版上的 Apache Livy 安装属性
<a name="job-runs-apache-livy-installation-properties"></a>

Apache Livy 安装允许您选择 Livy Helm 图表的版本。Helm 图表提供了各种属性来自定义您的安装和设置体验。Amazon EMR on EKS 7.1.0 及更高版本支持这些属性。

**Topics**
+ [Amazon EMR 7.1.0 安装属性](#job-runs-apache-livy-installation-properties-710)

## Amazon EMR 7.1.0 安装属性
<a name="job-runs-apache-livy-installation-properties-710"></a>

下表列出了所有支持的 Livy 属性。安装 Apache Livy 时，可以选择 Livy Helm 图表版本。要在安装过程中设置属性，请使用命令 `--set <property>=<value>`。


| 属性 | 说明 | 默认 | 
| --- | --- | --- | 
| image | Livy 服务器的 Amazon EMR 发行版 URI。这是必要的配置。 | "" | 
| sparkNamespace | 运行 Livy Spark 会话的命名空间。例如，指定 "livy"。这是必要的配置。 | "" | 
| nameOverride | 提供名称而不是 livy。该名称设置为所有 Livy 资源的标签 | "livy" | 
| fullnameOverride | 提供要使用的名称，而不是资源的全名。 | "" | 
| ssl.enabled | 启用从 end-to-end Livy 端点到 Livy 服务器的 SSL。 | FALSE | 
| ssl.certificateArn | 如果启用了 SSL，该属性为服务创建的 NLB 的 ACM 证书 ARN。 | "" | 
| ssl。 secretProviderClass姓名 | 如果启用了 SSL，该属性为使用 SSL 保护 Livy 服务器连接的 NLB 的密钥提供程序类名。 | "" | 
| ssl。 keyStoreObject姓名 | 如果启用了 SSL，该属性为密钥提供程序类中密钥库证书的对象名称。 | "" | 
| ssl。 keyPasswordsObject姓名 | 如果启用了 SSL，该属性为包含密钥库和密钥密码的密钥对象名称。 | "" | 
| rbac.create | 如果为 true，则创建 RBAC 资源。 | FALSE | 
| serviceAccount.create | 如果为 true，则创建 Livy 服务账户。 | TRUE | 
| serviceAccount.name | 用于 Livy 的服务账户名称。如果未设置此属性并创建了服务账户，则 Amazon EMR on EKS 会自动使用 fullname 覆盖属性生成名称。 | "emr-containers-sa-livy" | 
| 服务账户。 executionRoleArn | Livy 服务账户的执行角色 ARN。 | "" | 
| sparkServiceAccount.create | 如果为 true，则在 .Release.Namespace 中创建 Spark 服务账户 | TRUE | 
| sparkServiceAccount.name | 用于 Spark 的服务账户名称。如果在未设置此属性的情况下创建了 Spark 服务账户，则 Amazon EMR on EKS 会自动生成一个名称，其属性为 fullnameOverride 后缀为 -spark-livy。 | “emr-containers-sa-spark-livy” | 
| service.name | Livy 服务名称 | "emr-containers-livy" | 
| service.annotations | Livy 服务注释 | \$1\$1 | 
| loadbalancer.enabled | 是否为 Livy 服务创建一个负载均衡器，用于将 Livy 端点在 Amazon EKS 集群外部公开。 | FALSE | 
| loadbalancer.internal | 是否将 Livy 端点配置为 VPC 内部端点或外部端点。 将此属性设置为 `FALSE`，则会将端点向 VPC 外部的源公开。我们建议使用 TLS/SSL 保护端点。有关更多信息，请参阅[设置 TLS 和 SSL 加密](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-security.html#job-runs-apache-livy-security-tls)。 | FALSE | 
| imagePullSecrets | 用于从私有存储库中提取 Livy 映像的 imagePullSecret 名称列表。 | [] | 
| 资源 | Livy 容器的资源请求和限制。 | \$1\$1 | 
| nodeSelector | 要为其调度 Livy 容器组（pod）的节点。 | \$1\$1 | 
| tolerations | 包含要定义的 Livy 容器组（pod）容差的列表。 | [] | 
| affinity | Livy 容器组（pod）亲和力规则。 | \$1\$1 | 
| persistence.enabled | 如果为 true，则为会话目录启用持久性。 | FALSE | 
| persistence.subPath | 要挂载到会话目录的 PVC 子路径。 | "" | 
| persistence.existingClaim | 要使用的 PVC，而不是创建新的 PVC。 | \$1\$1 | 
| persistence.storageClass | 要使用的存储类。要定义此参数，请使用格式 storageClassName: <storageClass>。将该参数设置为 "-" 将禁用动态配置。如果您将此参数设置为空或未指定任何内容，则 EKS 上的 Amazon EMR 不会设置 storageClassName 并使用默认配置程序。 | "" | 
| persistence.accessMode | PVC 访问模式。 | ReadWriteOnce | 
| persistence.size | PVC 大小。 | 20Gi | 
| persistence.annotations | PVC 的附加注释。 | \$1\$1 | 
| env.\$1 | 要设置为 Livy 容器的其他环境。有关更多信息，请参阅[在安装 Livy 时输入您自己的 Livy 和 Spark 配置](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/job-runs-apache-livy-troubleshooting.html)。 | \$1\$1 | 
| envFrom.\$1 | 要从 Kubernetes 配置映射或密钥设置为 Livy 的其他环境。 | [] | 
| livyConf.\$1 | 要从挂载的 Kubernetes 配置映射或密钥设置的其他 livy.conf 条目。 | \$1\$1 | 
| sparkDefaultsConf.\$1 | 要从挂载的 Kubernetes 配置映射或密钥设置的其他 spark-defaults.conf 条目。 | \$1\$1 | 

# 排查常见的环境变量格式错误
<a name="job-runs-apache-livy-troubleshooting"></a>

在输入 Livy 和 Spark 配置时，某些环境变量格式不受支持，可能会导致错误。该过程将引导您完成一系列步骤，以确保使用正确的格式。

**在安装 Livy 时输入您自己的 Livy 和 Spark 配置**

您可以使用 `env.*` Helm 属性配置任何 Apache Livy 或 Apache Spark 环境变量。按照以下步骤将示例配置 `example.config.with-dash.withUppercase` 转换为支持的环境变量格式。

1. 将大写字母替换为 1 和小写字母。例如，`example.config.with-dash.withUppercase` 改为 `example.config.with-dash.with1uppercase`。

1. 将破折号（-）替换为 0。例如，`example.config.with-dash.with1uppercase` 改为 `example.config.with0dash.with1uppercase`。

1. 将点（.）替换为下划线（\$1）。例如，`example.config.with0dash.with1uppercase` 改为 `example_config_with0dash_with1uppercase`。

1. 将所有小写字母替换为大写字母。

1. 为变量名添加前缀 `LIVY_`。

1. 在通过掌舵图安装 Livy 时使用该变量，格式为--set env。 *YOUR\$1VARIABLE\$1NAME*.value= *yourvalue*

例如，要设置 Livy 和 Spark 配置 `livy.server.recovery.state-store = filesystem` 和 `spark.kubernetes.executor.podNamePrefix = my-prefix`，请使用以下 Helm 属性：

```
—set env.LIVY_LIVY_SERVER_RECOVERY_STATE0STORE.value=filesystem
—set env.LIVY_SPARK_KUBERNETES_EXECUTOR_POD0NAME0PREFIX.value=myprefix
```