

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

# 在 Deadline Cloud 中提交带有作业附件的工作
<a name="run-jobs-job-attachments"></a>

许多服务器场使用共享文件系统在提交作业的主机和运行作业的主机之间共享文件。例如，在前面的`simple_file_job`示例中，本地文件系统在终端窗口之间共享， AWS CloudShell 终端窗口在您提交作业的选项卡一和运行工作代理的选项卡二中运行。

当提交者工作站和工作主机位于同一个局域网中时，共享文件系统更具优势。如果您将数据存储在本地访问数据的工作站附近，那么使用基于云的服务器场意味着您必须通过高延迟 VPN 共享文件系统或在云中同步文件系统。这两个选项都不容易设置或操作。

AWS Deadline Cloud 提供了一个带有*作业附件*的简单解决方案，类似于电子邮件附件。使用作业附件，您可以将数据附加到作业中。然后，Deadline Cloud 会处理在亚马逊简单存储服务 (Amazon S3) 存储桶中传输和存储任务数据的细节。

内容创建工作流程通常是迭代的，这意味着用户提交作业时会包含一小部分修改过的文件。由于 Amazon S3 存储桶将任务附件存储在内容可寻址的存储中，因此每个对象的名称都基于对象数据的哈希值，并且目录树的内容以任务所附的清单文件格式存储。

在按照本节中的步骤进行操作之前，必须完成以下操作：
+ [创建截止日期云场](create-a-farm.md)
+ [运行 Deadline 云端工作者代理](run-worker.md)

要运行带有作业附件的作业，请完成以下步骤。

**Topics**
+ [向队列中添加作业附件配置](#job-attachments-config)
+ [提交simple\_file\_job时附上工作附件](#submit-job-attachments)
+ [了解任务附件在 Amazon S3 中的存储方式](#job-attachments-in-depth)
+ [后续步骤](#run-jobs-job-attachments-next)

## 向队列中添加作业附件配置
<a name="job-attachments-config"></a>

要在队列中启用作业附件，请向账户中的队列资源添加作业附件配置。

**向队列中添加作业附件配置**

1. 选择您的第一个 CloudShell 选项卡，然后输入以下命令之一，使用 Amazon S3 存储桶存储任务附件。
   + 如果您没有现有的私有 Amazon S3 存储桶，则可以创建和使用新的 S3 存储桶。

     ```
     DEV_FARM_BUCKET=$(echo $DEV_FARM_NAME \
         | tr '[:upper:]' '[:lower:]')-$(xxd -l 16 -p /dev/urandom)
     if [ "$AWS_REGION" == "us-east-1" ]; then LOCATION_CONSTRAINT=
     else LOCATION_CONSTRAINT="--create-bucket-configuration \
         LocationConstraint=${AWS_REGION}"
     fi
     aws s3api create-bucket \
         $LOCATION_CONSTRAINT \
         --acl private \
         --bucket ${DEV_FARM_BUCKET}
     ```
   + 如果您已经拥有私有 Amazon S3 存储桶，则可以通过将其{{`MY_BUCKET_NAME`}}替换为存储桶的名称来使用它。

     ```
     DEV_FARM_BUCKET={{MY_BUCKET_NAME}}
     ```

1. 创建或选择 Amazon S3 存储桶后，将存储桶名称添加到`~/.bashrc`，以使该存储桶可用于其他终端会话。

   ```
   echo "DEV_FARM_BUCKET=$DEV_FARM_BUCKET" >> ~/.bashrc
    source ~/.bashrc
   ```

1. 为队列创建 AWS Identity and Access Management (IAM) 角色。

   ```
   aws iam create-role --role-name "${DEV_FARM_NAME}QueueRole" \
       --assume-role-policy-document \
           '{
               "Version": "2012-10-17",		 	 	 
               "Statement": [
                   {
                       "Effect": "Allow",
                       "Principal": {
                           "Service": "credentials.deadline.amazonaws.com"
                       },
                       "Action": "sts:AssumeRole"
                   }
               ]
           }'
   aws iam put-role-policy \
       --role-name "${DEV_FARM_NAME}QueueRole" \
       --policy-name S3BucketsAccess \
       --policy-document \
               '{
                   "Version": "2012-10-17",		 	 	 
                   "Statement": [
                   {
                       "Action": [
                           "s3:GetObject*",
                           "s3:GetBucket*",
                           "s3:List*",
                           "s3:DeleteObject*",
                           "s3:PutObject",
                           "s3:PutObjectLegalHold",
                           "s3:PutObjectRetention",
                           "s3:PutObjectTagging",
                           "s3:PutObjectVersionTagging",
                           "s3:Abort*"
                       ],
                       "Resource": [
                           "arn:aws:s3:::'$DEV_FARM_BUCKET'",
                           "arn:aws:s3:::'$DEV_FARM_BUCKET'/*"
                       ],
                       "Effect": "Allow"
                   }
               ]
               }'
   ```

1. 更新您的队列以包含任务附件设置和 IAM 角色。

   ```
   QUEUE_ROLE_ARN="arn:aws:iam::$(aws sts get-caller-identity \
           --query "Account" --output text):role/${DEV_FARM_NAME}QueueRole"
   aws deadline update-queue \
       --farm-id $DEV_FARM_ID \
       --queue-id $DEV_QUEUE_ID \
       --role-arn $QUEUE_ROLE_ARN \
       --job-attachment-settings \
           '{
               "s3BucketName": "'$DEV_FARM_BUCKET'",
               "rootPrefix": "JobAttachments"
           }'
   ```

1. 确认您已更新队列。

   ```
   deadline queue get
   ```

   输出如下所示：

   ```
   ...
   jobAttachmentSettings:
     s3BucketName: DEV_FARM_BUCKET
     rootPrefix: JobAttachments
   roleArn: arn:aws:iam::ACCOUNT_NUMBER:role/DeveloperFarmQueueRole
   ...
   ```

## 提交simple\_file\_job时附上工作附件
<a name="submit-job-attachments"></a>

使用作业附件时，任务捆绑包必须为 Deadline Cloud 提供足够的信息，以确定作业的数据流，例如使用`PATH`参数。如果是simple\_file\_job，您编辑`template.yaml`文件是为了告诉 Deadline Cloud 数据流在输入文件和输出文件中。

将作业附件配置添加到队列后，您可以提交带有作业附件的 simple\_file\_job 示例。完成此操作后，您可以查看日志记录和作业输出，以确认simple\_file\_job带有作业附件的运行正常。

**提交带有作业附件的 simple\_file\_job 任务捆绑包**

1. 选择您的第一个 CloudShell 选项卡，然后打开该`JobBundle-Samples`目录。

1. 

   ```
   cd ~/deadline-cloud-samples/job_bundles/
   ```

1. 将 simple\_file\_job 提交到队列。当系统提示您确认上传时，请输入**y**。

   ```
   deadline bundle submit simple_file_job \
       -p InFile=simple_job/template.yaml \
       -p OutFile=hash-jobattachments.txt
   ```

1. 要查看作业附件数据传输会话日志输出，请运行以下命令。

   ```
   JOB_ID=$(deadline config get defaults.job_id)
   SESSION_ID=$(aws deadline list-sessions \
           --farm-id $DEV_FARM_ID \
           --queue-id $DEV_QUEUE_ID \
           --job-id $JOB_ID \
           --query "sessions[0].sessionId" \
           --output text)
   cat ~/demoenv-logs/$DEV_QUEUE_ID/$SESSION_ID.log
   ```

1. 列出在会话中运行的会话操作。

   ```
   aws deadline list-session-actions \
       --farm-id $DEV_FARM_ID \
       --queue-id $DEV_QUEUE_ID \
       --job-id $JOB_ID \
       --session-id $SESSION_ID
   ```

   输出如下所示：

   ```
   {
       "sessionactions": [
           {
               "sessionActionId": "sessionaction-123-0",
               "status": "SUCCEEDED",
               "startedAt": "<timestamp>",
               "endedAt": "<timestamp>",
               "progressPercent": 100.0,
               "definition": {
                   "syncInputJobAttachments": {}
               }
           },
           {
               "sessionActionId": "sessionaction-123-1",
               "status": "SUCCEEDED",
               "startedAt": "<timestamp>",
               "endedAt": "<timestamp>",
               "progressPercent": 100.0,
               "definition": {
                   "taskRun": {
                       "taskId": "task-abc-0",
                       "stepId": "step-def"
                   }
               }
           }
       ]
   }
   ```

   第一个会话操作下载了输入作业附件，而第二个操作则像前面的步骤一样运行任务，然后上传了输出作业附件。

1. 列出输出目录。

   ```
   ls *.txt
   ```

   例如，输出`hash.txt`存在于目录中，但`hash-jobattachments.txt`由于作业的输出文件尚未下载，因此不存在。

1. 下载最近作业的输出。

   ```
   deadline job download-output
   ```

1. 查看已下载文件的输出。

   ```
   cat hash-jobattachments.txt
   ```

   输出如下所示：

   ```
   eaa2df5d34b54be5ac34c56a24a8c237b8487231a607eaf530a04d76b89c9cd3  /tmp/openjd/session-123/assetroot-abc/simple_job/template.yaml
   ```

## 了解任务附件在 Amazon S3 中的存储方式
<a name="job-attachments-in-depth"></a>

您可以使用 AWS Command Line Interface (AWS CLI) 上传或下载任务附件的数据，这些数据存储在 Amazon S3 存储桶中。了解 Deadline Cloud 如何在 Amazon S3 上存储作业附件将有助于您开发工作负载和管道集成。

**检查 Deadline Cloud 作业附件在 Amazon S3 中的存储方式**

1. 选择您的第一个 CloudShell 选项卡，然后打开任务捆绑包示例目录。

   ```
   cd ~/deadline-cloud-samples/job_bundles/
   ```

1. 检查作业属性。

   ```
   deadline job get
   ```

   输出如下所示：

   ```
   parameters:
     Message:
       string: Welcome to AWS Deadline Cloud!
     InFile:
       path: /home/cloudshell-user/deadline-cloud-samples/job_bundles/simple_job/template.yaml
     OutFile:
       path: /home/cloudshell-user/deadline-cloud-samples/job_bundles/hash-jobattachments.txt
   attachments:
     manifests:
     - rootPath: /home/cloudshell-user/deadline-cloud-samples/job_bundles/
       rootPathFormat: posix
       outputRelativeDirectories:
       - .
       inputManifestPath: farm-3040c59a5b9943d58052c29d907a645d/queue-cde9977c9f4d4018a1d85f3e6c1a4e6e/Inputs/f46af01ca8904cd8b514586671c79303/0d69cd94523ba617c731f29c019d16e8_input.xxh128
       inputManifestHash: f95ef91b5dab1fc1341b75637fe987ee
     fileSystem: COPIED
   ```

   附件字段包含清单结构列表，这些清单结构描述了作业运行时使用的输入和输出数据路径。查看`rootPath`提交作业的计算机上的本地目录路径。要查看包含清单文件的 Amazon S3 对象后缀，请查看。`inputManifestFile`清单文件包含任务输入数据的目录树快照的元数据。

1. 漂亮地打印 Amazon S3 清单对象以查看任务的输入目录结构。

   ```
   MANIFEST_SUFFIX=$(aws deadline get-job \
        --farm-id $DEV_FARM_ID \
        --queue-id $DEV_QUEUE_ID \
        --job-id $JOB_ID \
        --query "attachments.manifests[0].inputManifestPath" \
        --output text)
    aws s3 cp s3://$DEV_FARM_BUCKET/JobAttachments/Manifests/$MANIFEST_SUFFIX - | jq .
   ```

   输出如下所示：

   ```
   {
        "hashAlg": "xxh128",
        "manifestVersion": "2023-03-03",
        "paths": [
        {
            "hash": "2ec297b04c59c4741ed97ac8fb83080c",
            "mtime": 1698186190000000,
            "path": "simple_job/template.yaml",
            "size": 445
        }
        ],
        "totalSize": 445
    }
   ```

1. 构造用于保存输出任务附件清单的 Amazon S3 前缀，并在其下列出对象。

   ```
   SESSION_ACTION=$(aws deadline list-session-actions \
       --farm-id $DEV_FARM_ID \
       --queue-id $DEV_QUEUE_ID \
       --job-id $JOB_ID \
       --session-id $SESSION_ID \
       --query "sessionActions[?definition.taskRun != null] | [0]")
   STEP_ID=$(echo $SESSION_ACTION | jq -r .definition.taskRun.stepId)
   TASK_ID=$(echo $SESSION_ACTION | jq -r .definition.taskRun.taskId)
   TASK_OUTPUT_PREFIX=JobAttachments/Manifests/$DEV_FARM_ID/$DEV_QUEUE_ID/$JOB_ID/$STEP_ID/$TASK_ID/
   aws s3api list-objects-v2 --bucket $DEV_FARM_BUCKET --prefix $TASK_OUTPUT_PREFIX
   ```

   输出任务附件不是直接从任务资源中引用的，而是根据服务器场资源放置在 Amazon S3 存储桶中 IDs。

1. 获取特定会话操作 ID 的最新清单对象密钥，然后漂亮地打印清单对象。

   ```
   SESSION_ACTION_ID=$(echo $SESSION_ACTION | jq -r .sessionActionId)
    MANIFEST_KEY=$(aws s3api list-objects-v2 \
        --bucket $DEV_FARM_BUCKET \
        --prefix $TASK_OUTPUT_PREFIX \
        --query "Contents[*].Key" --output text \
        | grep $SESSION_ACTION_ID \
        | sort | tail -1)
    MANIFEST_OBJECT=$(aws s3 cp s3://$DEV_FARM_BUCKET/$MANIFEST_KEY -)
    echo $MANIFEST_OBJECT | jq .
   ```

   您将在输出`hash-jobattachments.txt`中看到该文件的属性，如下所示：

   ```
   {
        "hashAlg": "xxh128",
        "manifestVersion": "2023-03-03",
        "paths": [
        {
            "hash": "f60b8e7d0fabf7214ba0b6822e82e08b",
            "mtime": 1698785252554950,
            "path": "hash-jobattachments.txt",
            "size": 182
        }
        ],
        "totalSize": 182
    }
   ```

   每次运行任务时，您的作业只会有一个清单对象，但一般而言，每次运行的任务可能会有更多的对象。

1. 在前缀下查看可寻址内容的 Amazon S3 存储输出。`Data`

   ```
    FILE_HASH=$(echo $MANIFEST_OBJECT | jq -r .paths[0].hash)
    FILE_PATH=$(echo $MANIFEST_OBJECT | jq -r .paths[0].path)
    aws s3 cp s3://$DEV_FARM_BUCKET/JobAttachments/Data/$FILE_HASH -
   ```

   输出如下所示：

   ```
   eaa2df5d34b54be5ac34c56a24a8c237b8487231a607eaf530a04d76b89c9cd3  /tmp/openjd/session-123/assetroot-abc/simple_job/template.yaml
   ```

## 后续步骤
<a name="run-jobs-job-attachments-next"></a>

在学习了如何使用 Deadline Cloud CLI 提交带有附件的作业后，您可以探索：
+ [使用截止日期云提交](submit-a-job.md)学习如何在工作主机上使用 OpenJD 捆绑包运行作业。
+ [在 Deadline Cloud 中向你的开发者群添加服务管理队列](service-managed-fleet.md)在由 Deadline Cloud 管理的主机上运行作业。
+ [在 Deadline Cloud 中清理农场资源](cleaning-up.md)关闭您在本教程中使用的资源。