

# 使用针对目录存储桶的 S3 生命周期
<a name="directory-buckets-objects-lifecycle"></a>

 S3 生命周期通过代表您删除已过期对象，助力您以更具成本效益的方式在目录存储桶中的 S3 Express One Zone 内存储对象。要管理对象的生命周期，请为目录存储桶创建 S3 生命周期配置。S3 生命周期配置 是一组规则，用于定义 Amazon S3 对一组对象应用的操作。您可以使用 AWS 命令行界面（AWS CLI）、AWS SDK、Amazon S3 REST API 和 AWS CloudFormation，在目录存储桶上设置 Amazon S3 生命周期配置。

在生命周期配置中，您可以使用规则来定义希望 Amazon S3 在对象上执行的操作。对于存储在目录存储桶中的对象，您可以创建生命周期规则，以便随着对象存在时间的增长而使其过期。您还可以创建生命周期规则，以每天一次的频率删除目录存储桶中未完成的分段上传。

当您向存储桶添加生命周期配置时，配置规则将应用到现有对象以及您在以后添加的对象。例如，如果您在今天添加带有过期操作的生命周期配置规则，而该规则使带有特定前缀的对象在创建 30 天后过期，S3 会将任何超过 30 天且具有指定前缀的现有对象加入移除队列。

## 目录存储桶的 S3 生命周期有何不同
<a name="directory-bucket-lifecycle-differences"></a>

对于目录存储桶中的对象，您可以创建生命周期规则，使对象过期并删除未完成的分段上传。但是，目录存储桶的 S3 生命周期不支持存储类之间的转换操作。

**CreateSession**

生命周期使用公共 `DeleteObject` 和 `DeleteObjects` API 操作来使目录存储桶中的对象过期。要使用这些 API 操作，S3 生命周期将使用 `CreateSession` API 建立临时安全凭证，以访问目录存储桶中的对象。有关更多信息，请参阅[《Amazon S3 API Reference》**中的 `CreateSession`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateSession.html)。

如果您具有拒绝向生命周期主体授予删除权限的有效策略，这将阻止您允许 S3 生命周期代表您删除对象。

### 使用存储桶策略向 S3 生命周期服务主体授予权限
<a name="lifecycle-directory-bucket-policy"></a>

以下存储桶策略向 S3 生命周期服务主体授予创建会话以执行 `DeleteObject` 和 `DeleteObjects` 等操作的权限。如果未在 `CreateSession` 请求中指定会话模式，则会使用权限（先尝试 `ReadWrite`，如果不允许 `ReadWrite`，则再尝试 `ReadOnly`）所支持的最大权限创建会话。但是，对于修改或删除对象的生命周期操作，`ReadOnly` 会话是不够的。因此，此示例使用 `s3express:SessionMode` 条件键明确要求使用 `ReadWrite` 会话模式。

**Example – 存储桶策略，支持使用显式 `ReadWrite` 会话模式进行 `CreateSession` 调用以执行生命周期操作**  

```
 { 
   "Version":"2008-10-17",		 	 	  
   "Statement":[
      {
         "Effect":"Allow",
         "Principal": {
            "Service":"lifecycle.s3.amazonaws.com"
          },
          "Action":"s3express:CreateSession", 
          "Condition": { 
             "StringEquals": {
                "s3express:SessionMode": "ReadWrite"
              }
           }, 
           "Resource":"arn:aws:s3express:us-east-2:412345678921:bucket/amzn-s3-demo-bucket--use2-az2--x-s3"
       }
   ] 
}
```

### 监控生命周期规则
<a name="lifecycle-directory-bucket-monitoring"></a>

对于存储在目录存储桶中的对象，S3 生命周期会生成 AWS CloudTrail 管理和数据事件日志。有关更多信息，请参阅 [S3 Express One Zone 的 CloudTrail 日志文件示例](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-log-files.html)。

有关创建生命周期配置以及排查 S3 生命周期相关问题的更多信息，请参阅以下主题：

**Topics**

# 为目录存储桶创建和管理生命周期配置
<a name="directory-bucket-create-lc"></a>

您可以通过使用 AWS Command Line Interface（AWS CLI）、AWS SDK 和 REST API，为目录存储桶创建生命周期配置。

## 使用 AWS CLI
<a name="set-lifecycle-config-cli"></a>

您可以使用以下 AWS CLI 命令管理 S3 生命周期配置：
+ `put-bucket-lifecycle-configuration`
+ `get-bucket-lifecycle-configuration`
+ `delete-bucket-lifecycle`

有关设置 AWS CLI 的说明，请参阅《Amazon S3 API 参考》**中的 [Developing with Amazon S3 using the AWS CLI](https://docs.aws.amazon.com/AmazonS3/latest/API/setup-aws-cli.html)。

Amazon S3 生命周期配置是一个 XML 文件。但在使用 AWS CLI 时，您不能指定 XML 格式。您必须改为指定 JSON 格式。以下是您可在 AWS CLI 命令中指定的示例 XML 生命周期配置和等效 JSON 配置。

以下 AWS CLI 示例在目录存储桶上放置生命周期配置策略。此策略指定，所有带有标记前缀（myprefix）且符合规定对象大小的对象，将在 7 天后过期。要使用此示例，请将每个*用户输入占位符*替换为您自己的信息。

将生命周期配置策略保存到 JSON 文件中。在本示例中，文件命名为 lifecycle1.json。

**Example**  

```
{
    "Rules": [
        {
        "Expiration": {
            "Days": 7
        },
        "ID": "Lifecycle expiration rule",
        "Filter": {
            "And": {
                "Prefix": "myprefix/",
                "ObjectSizeGreaterThan": 500,
                "ObjectSizeLessThan": 64000
            }
        },
        "Status": "Enabled"
    }
    ]
}
```
将 JSON 文件作为`put-bucket-lifecycle-configuration` CLI 命令的一部分提交。要使用此命令，请将每个*用户输入占位符*替换为您自己的信息。  

```
aws s3api put-bucket-lifecycle-configuration --region us-west-2 --profile default --bucket amzn-s3-demo-bucket--usw2-az1--x-s3 --lifecycle-configuration file://lc-policy.json --checksum-algorithm crc32c 
```

**Example**  

```
<LifecycleConfiguration>
    <Rule>
        <ID>Lifecycle expiration rule</ID>
        <Filter>
            <And>
                <Prefix>myprefix/</Prefix>
                <ObjectSizeGreaterThan>500</ObjectSizeGreaterThan>
                <ObjectSizeLessThan>64000</ObjectSizeLessThan>
            </And>
        </Filter>
        <Status>Enabled</Status>     
        <Expiration>
             <Days>7</Days>
        </Expiration>
    </Rule>
</LifecycleConfiguration>
```

## 使用 AWS SDK
<a name="directory-bucket-upload-sdks"></a>

------
#### [ SDK for Java ]

**Example**  

```
import software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationRequest;
import software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationResponse;
import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm;
import software.amazon.awssdk.services.s3.model.BucketLifecycleConfiguration;
import software.amazon.awssdk.services.s3.model.LifecycleRule;
import software.amazon.awssdk.services.s3.model.LifecycleRuleFilter;
import software.amazon.awssdk.services.s3.model.LifecycleExpiration;
import software.amazon.awssdk.services.s3.model.LifecycleRuleAndOperator;
import software.amazon.awssdk.services.s3.model.GetBucketLifecycleConfigurationResponse;
import software.amazon.awssdk.services.s3.model.GetBucketLifecycleConfigurationRequest;
import software.amazon.awssdk.services.s3.model.DeleteBucketLifecycleRequest;
import software.amazon.awssdk.services.s3.model.DeleteBucketLifecycleResponse;
import software.amazon.awssdk.services.s3.model.AbortIncompleteMultipartUpload;

// PUT a Lifecycle policy
LifecycleRuleFilter objectExpirationFilter = LifecycleRuleFilter.builder().and(LifecycleRuleAndOperator.builder().prefix("dir1/").objectSizeGreaterThan(3L).objectSizeLessThan(20L).build()).build();
LifecycleRuleFilter mpuExpirationFilter = LifecycleRuleFilter.builder().prefix("dir2/").build();
       
LifecycleRule objectExpirationRule = LifecycleRule.builder().id("lc").filter(objectExpirationFilter).status("Enabled").expiration(LifecycleExpiration.builder()
                    .days(10)
                    .build())
                .build();
LifecycleRule mpuExpirationRule = LifecycleRule.builder().id("lc-mpu").filter(mpuExpirationFilter).status("Enabled").abortIncompleteMultipartUpload(AbortIncompleteMultipartUpload.builder()
                        .daysAfterInitiation(10)
                        .build())
                .build();
        
PutBucketLifecycleConfigurationRequest putLifecycleRequest = PutBucketLifecycleConfigurationRequest.builder()
                .bucket("amzn-s3-demo-bucket--usw2-az1--x-s3")
                .checksumAlgorithm(ChecksumAlgorithm.CRC32)
                .lifecycleConfiguration(
                        BucketLifecycleConfiguration.builder()
                                .rules(objectExpirationRule, mpuExpirationRule)
                                .build()
                ).build();

PutBucketLifecycleConfigurationResponse resp = client.putBucketLifecycleConfiguration(putLifecycleRequest);

// GET the Lifecycle policy 
GetBucketLifecycleConfigurationResponse getResp = client.getBucketLifecycleConfiguration(GetBucketLifecycleConfigurationRequest.builder().bucket("amzn-s3-demo-bucket--usw2-az1--x-s3").build());

// DELETE the Lifecycle policy
DeleteBucketLifecycleResponse delResp = client.deleteBucketLifecycle(DeleteBucketLifecycleRequest.builder().bucket("amzn-s3-demo-bucket--usw2-az1--x-s3").build());
```

------
#### [ SDK for Go ]

**Example**  

```
package main

import (
    "context"
    "log"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/s3"
    "github.com/aws/aws-sdk-go-v2/service/s3/types"
)
// PUT a Lifecycle policy
func putBucketLifecycleConfiguration(client *s3.Client, bucketName string ) error {
    lifecycleConfig := &s3.PutBucketLifecycleConfigurationInput{
        Bucket: aws.String(bucketName),
        LifecycleConfiguration: &types.BucketLifecycleConfiguration{
            Rules: []types.LifecycleRule{
                {
                    ID:     aws.String("lc"),
                    Filter: &types.LifecycleRuleFilter{
                        And: &types.LifecycleRuleAndOperator{
                            Prefix: aws.String("foo/"), 
                            ObjectSizeGreaterThan: aws.Int64(1000000), 
                            ObjectSizeLessThan:    aws.Int64(100000000), 
                            },
                        },
                    
                    Status: types.ExpirationStatusEnabled,
                    Expiration: &types.LifecycleExpiration{
                        Days: aws.Int32(int32(1)), 
                    },
                },
                {
                    ID:     aws.String("abortmpu"),
                    Filter: &types.LifecycleRuleFilter{
                        Prefix: aws.String("bar/"), 
                    },
                    Status: types.ExpirationStatusEnabled,
                    AbortIncompleteMultipartUpload: &types.AbortIncompleteMultipartUpload{
                        DaysAfterInitiation: aws.Int32(int32(5)), 
                    },
                },
            },
        },
    }
    _, err := client.PutBucketLifecycleConfiguration(context.Background(), lifecycleConfig)
    return err
}
// Get the Lifecycle policy
func getBucketLifecycleConfiguration(client *s3.Client, bucketName string) error {
    getLifecycleConfig := &s3.GetBucketLifecycleConfigurationInput{
        Bucket: aws.String(bucketName),
    }

    resp, err := client.GetBucketLifecycleConfiguration(context.Background(), getLifecycleConfig)
    if err != nil {
        return err
    }
    return nil
}
// Delete the Lifecycle policy
func deleteBucketLifecycleConfiguration(client *s3.Client, bucketName string) error {
    deleteLifecycleConfig := &s3.DeleteBucketLifecycleInput{
        Bucket: aws.String(bucketName),
    }
    _, err := client.DeleteBucketLifecycle(context.Background(), deleteLifecycleConfig)
    return err
}
func main() {
    cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRegion("us-west-2")) // Specify your region here
    if err != nil {
        log.Fatalf("unable to load SDK config, %v", err)
    }
    s3Client := s3.NewFromConfig(cfg)
    bucketName := "amzn-s3-demo-bucket--usw2-az1--x-s3" 
    putBucketLifecycleConfiguration(s3Client, bucketName)
    getBucketLifecycleConfiguration(s3Client, bucketName)
    deleteBucketLifecycleConfiguration(s3Client, bucketName)
    getBucketLifecycleConfiguration(s3Client, bucketName)
}
```

------
#### [ SDK for .NET ]

**Example**  

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class LifecycleTest
    {
        private const string bucketName = "amzn-s3-demo-bucket--usw2-az1--x-s3";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 client;
        public static void Main()
        {
            client = new AmazonS3Client(bucketRegion);
            AddUpdateDeleteLifecycleConfigAsync().Wait();
        }

        private static async Task AddUpdateDeleteLifecycleConfigAsync()
        {
            try
            {
                var lifeCycleConfiguration = new LifecycleConfiguration()
                {
                    Rules = new List <LifecycleRule>
                        {
                            new LifecycleRule
                            {
                                 Id = "delete rule",
                                  Filter = new LifecycleFilter()
                                 {
                                     LifecycleFilterPredicate = new LifecyclePrefixPredicate()
                                     {
                                         Prefix = "projectdocs/"
                                     }
                                 },
                                 Status = LifecycleRuleStatus.Enabled,
                                 Expiration = new LifecycleRuleExpiration()
                                 {
                                       Days = 10
                                 }
                            }
                        }
                };

                // Add the configuration to the bucket. 
                await AddExampleLifecycleConfigAsync(client, lifeCycleConfiguration);

                // Retrieve an existing configuration. 
                lifeCycleConfiguration = await RetrieveLifecycleConfigAsync(client);

                // Add a new rule.
                lifeCycleConfiguration.Rules.Add(new LifecycleRule
                {
                    Id = "mpu abort rule",
                    Filter = new LifecycleFilter()
                    {
                        LifecycleFilterPredicate = new LifecyclePrefixPredicate()
                        {
                            Prefix = "YearlyDocuments/"
                        }
                    },
                    Expiration = new LifecycleRuleExpiration()
                    {
                        Days = 10
                    },
                    AbortIncompleteMultipartUpload = new LifecycleRuleAbortIncompleteMultipartUpload()
                    {
                        DaysAfterInitiation = 10
                    }
                });

                // Add the configuration to the bucket. 
                await AddExampleLifecycleConfigAsync(client, lifeCycleConfiguration);

                // Verify that there are now two rules.
                lifeCycleConfiguration = await RetrieveLifecycleConfigAsync(client);
                Console.WriteLine("Expected # of rulest=2; found:{0}", lifeCycleConfiguration.Rules.Count);

                // Delete the configuration.
                await RemoveLifecycleConfigAsync(client);

                // Retrieve a nonexistent configuration.
                lifeCycleConfiguration = await RetrieveLifecycleConfigAsync(client);

            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered ***. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }

        static async Task AddExampleLifecycleConfigAsync(IAmazonS3 client, LifecycleConfiguration configuration)
        {

            PutLifecycleConfigurationRequest request = new PutLifecycleConfigurationRequest
            {
                BucketName = bucketName,
                Configuration = configuration
            };
            var response = await client.PutLifecycleConfigurationAsync(request);
        }

        static async Task <LifecycleConfiguration> RetrieveLifecycleConfigAsync(IAmazonS3 client)
        {
            GetLifecycleConfigurationRequest request = new GetLifecycleConfigurationRequest
            {
                BucketName = bucketName
            };
            var response = await client.GetLifecycleConfigurationAsync(request);
            var configuration = response.Configuration;
            return configuration;
        }

        static async Task RemoveLifecycleConfigAsync(IAmazonS3 client)
        {
            DeleteLifecycleConfigurationRequest request = new DeleteLifecycleConfigurationRequest
            {
                BucketName = bucketName
            };
            await client.DeleteLifecycleConfigurationAsync(request);
        }
    }
}
```

------
#### [ SDK for Python ]

**Example**  

```
import boto3

client = boto3.client("s3", region_name="us-west-2")
bucket_name = 'amzn-s3-demo-bucket--usw2-az1--x-s3'

client.put_bucket_lifecycle_configuration(
    Bucket=bucket_name,
    ChecksumAlgorithm='CRC32',
    LifecycleConfiguration={
        'Rules': [
            {
                'ID': 'lc',
                'Filter': {
                    'And': {
                        'Prefix': 'foo/',
                        'ObjectSizeGreaterThan': 1000000,
                        'ObjectSizeLessThan': 100000000,
                    }
                },
                'Status': 'Enabled',
                'Expiration': {
                    'Days': 1
                }
            },
            {
                'ID': 'abortmpu',
                'Filter': {
                    'Prefix': 'bar/'
                },
                'Status': 'Enabled',
                'AbortIncompleteMultipartUpload': {
                    'DaysAfterInitiation': 5
                }
            }
        ]
    }
)

result = client.get_bucket_lifecycle_configuration(
    Bucket=bucket_name
)

client.delete_bucket_lifecycle(
    Bucket=bucket_name
)
```

------

# 目录存储桶的 S3 生命周期问题排查
<a name="directory-buckets-lifecycle-troubleshooting"></a>

**Topics**
+ [我设置了生命周期配置，但是我的目录存储桶中的对象没有过期](#troubleshoot-directory-bucket-lifecycle-1)
+ [如何监控生命周期规则执行的操作？](#troubleshoot-directory-bucket-lifecycle-2)

## 我设置了生命周期配置，但是我的目录存储桶中的对象没有过期
<a name="troubleshoot-directory-bucket-lifecycle-1"></a>

针对目录存储桶的 S3 生命周期利用公共 API 来删除 S3 Express One Zone 中的对象。要使用对象级公共 API，您必须授予 `CreateSession` 权限并允许 S3 生命周期删除您的对象。如果您具有拒绝执行删除的有效策略，这将阻止您允许 S3 生命周期代表您删除对象。

请务必正确配置存储桶策略，以确保要删除的对象符合过期条件。您可以在 AWS CloudTrail 日志中查看 CloudTrail 中是否针对 `CreateSession` API 调用的 `AccessDenied` 跟踪，以验证访问是否被拒绝。查看 CloudTrail 日志有助于您排查访问问题，并确定访问遭拒绝错误的根本原因。然后，您可以通过更新相关策略来修复错误的访问控制。

如果您确认存储桶策略设置正确，但仍遇到问题，我们建议您查看生命周期规则，确保它们适用于正确的对象子集。

## 如何监控生命周期规则执行的操作？
<a name="troubleshoot-directory-bucket-lifecycle-2"></a>

 您可以使用 AWS CloudTrail 数据事件日志，来监控 S3 生命周期在目录存储桶中执行的操作。有关更多信息，请参阅 [CloudTrail 日志文件示例](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-log-files.html)。