github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/docs/bucket/versioning/README.md (about)

     1  # Bucket Versioning Guide [![Slack](https://slack.min.io/slack?type=svg)](https://slack.min.io) [![Docker Pulls](https://img.shields.io/docker/pulls/minio/minio.svg?maxAge=604800)](https://hub.docker.com/r/minio/minio/)
     2  
     3  MinIO versioning is designed to keep multiple versions of an object in one bucket. For example, you could store `spark.csv` (version `ede336f2`) and `spark.csv` (version `fae684da`) in a single bucket. Versioning protects you from unintended overwrites, deletions, protect objects with retention policies.
     4  
     5  To control data retention and storage usage, use object versioning with [object lifecycle management](https://github.com/minio/minio/blob/master/docs/bucket/lifecycle/README.md).  If you have an object expiration lifecycle policy in your non-versioned bucket and you want to maintain the same permanent delete behavior when on versioning-enabled bucket, you must add a noncurrent expiration policy. The noncurrent expiration lifecycle policy will manage the deletes of the noncurrent object versions in the versioning-enabled bucket. (A version-enabled bucket maintains one current and zero or more noncurrent object versions.)
     6  
     7  Versioning must be explicitly enabled on a bucket, versioning is not enabled by default. Object locking enabled buckets have versioning enabled automatically. Enabling and suspending versioning is done at the bucket level.
     8  
     9  Only MinIO generates version IDs, and they can't be edited. Version IDs are simply of `DCE 1.1 v4 UUID 4` (random data based), UUIDs are 128 bit numbers which are intended to have a high likelihood of uniqueness over space and time and are computationally difficult to guess. They are globally unique identifiers which can be locally generated without contacting a global registration authority. UUIDs are intended as unique identifiers for both mass tagging objects with an extremely short lifetime and to reliably identifying very persistent objects across a network.
    10  
    11  When you PUT an object in a versioning-enabled bucket, the noncurrent version is not overwritten. The following figure shows that when a new version of `spark.csv` is PUT into a bucket that already contains an object with the same name, the original object (ID = `ede336f2`) remains in the bucket, MinIO generates a new version (ID = `fae684da`), and adds the newer version to the bucket.
    12  
    13  ![put](https://raw.githubusercontent.com/minio/minio/master/docs/bucket/versioning/versioning_PUT_versionEnabled.png)
    14  
    15  This protects against accidental overwrites or deletes of objects, allows previous versions to be retrieved.
    16  
    17  When you DELETE an object, all versions remain in the bucket and MinIO adds a delete marker, as shown below:
    18  
    19  ![delete](https://raw.githubusercontent.com/minio/minio/master/docs/bucket/versioning/versioning_DELETE_versionEnabled.png)
    20  
    21  Now the delete marker becomes the current version of the object. GET requests by default always retrieve the latest stored version. So performing a simple GET object request when the current version is a delete marker would return `404` `The specified key does not exist` as shown below:
    22  
    23  ![get](https://raw.githubusercontent.com/minio/minio/master/docs/bucket/versioning/versioning_GET_versionEnabled.png)
    24  
    25  GET requests by specifying a version ID as shown below, you can retrieve the specific object version `fae684da`.
    26  
    27  ![get_version_id](https://raw.githubusercontent.com/minio/minio/master/docs/bucket/versioning/versioning_GET_versionEnabled_id.png)
    28  
    29  To permanently delete an object you need to specify the version you want to delete, only the user with appropriate permissions can permanently delete a version.  As shown below DELETE request called with a specific version id permanently deletes an object from a bucket. Delete marker is not added for DELETE requests with version id.
    30  
    31  ![delete_version_id](https://raw.githubusercontent.com/minio/minio/master/docs/bucket/versioning/versioning_DELETE_versionEnabled_id.png)
    32  
    33  ## Concepts
    34  
    35  - All Buckets on MinIO are always in one of the following states: unversioned (the default) and all other existing deployments, versioning-enabled, or versioning-suspended.
    36  - Versioning state applies to all of the objects in the versioning enabled bucket. The first time you enable a bucket for versioning, objects in the bucket are thereafter always versioned and given a unique version ID.
    37  - Existing or newer buckets can be created with versioning enabled and eventually can be suspended as well. Existing versions of objects stay as is and can still be accessed using the version ID.
    38  - All versions, including delete-markers should be deleted before deleting a bucket.
    39  - **Versioning feature is only available in erasure coded and distributed erasure coded setups**.
    40  
    41  ## How to configure versioning on a bucket
    42  
    43  Each bucket created has a versioning configuration associated with it. By default bucket is unversioned as shown below
    44  
    45  ```
    46  <VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    47  </VersioningConfiguration>
    48  ```
    49  
    50  To enable versioning, you send a request to MinIO with a versioning configuration with Status set to `Enabled`.
    51  
    52  ```
    53  <VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    54    <Status>Enabled</Status>
    55  </VersioningConfiguration>
    56  ```
    57  
    58  Similarly to suspend versioning set the configuration with Status set to `Suspended`.
    59  
    60  ```
    61  <VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    62    <Status>Suspended</Status>
    63  </VersioningConfiguration>
    64  ```
    65  
    66  ## MinIO extension to Bucket Versioning
    67  
    68  ### Idempotent versions on directory objects
    69  
    70  All directory objects such as objects that end with `/`, will only have one versionId (i.e `null`). A delete marker will never be created on these directory objects, instead a DELETE will delete the directory objects. This is done to ensure that directory objects even with multiple overwrites - do not ever need multiple versions in the first place. All overwrite calls on these directory objects are idempotent.
    71  
    72  > NOTE: Server side replication is supported for idempotent versions on directory objects.
    73  
    74  ### Idempotent versions on delete markers
    75  
    76  Duplicate delete markers are not created on MinIO buckets with versioning, if an application performs a soft delete on an object repeatedly - that object will only ever have a single DELETE marker for all such successive attempts. This is done to ensure that repeated soft deletes do not ever need multiple versions in the first place.
    77  
    78  > NOTE: Server side replication is supported for idempotent versions on delete marked objects.
    79  
    80  ### Motivation
    81  
    82  **PLEASE READ: This feature is meant for advanced usecases only where the setup is using bucket versioning or with replicated buckets, use this feature to optimize versioning behavior for some specific applications. MinIO experts will evaluate and guide on the benefits for your application, please reach out to us on <https://subnet.min.io>.**
    83  
    84  Spark/Hadoop workloads which use Hadoop MR Committer v1/v2 algorithm upload objects to a temporary prefix in a bucket. These objects are 'renamed' to a different prefix on Job commit. Object storage admins are forced to configure separate ILM policies to expire these objects and their versions to reclaim space.
    85  
    86  ### Solution
    87  
    88  To exclude objects under a list of prefix (glob) patterns from being versioned, you can send the following versioning configuration with Status set to `Enabled`.
    89  
    90  ```
    91  <VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    92          <Status>Enabled</Status>
    93          <ExcludedPrefixes>
    94            <Prefix>*/_temporary</Prefix>
    95          </ExcludedPrefixes>
    96          <ExcludedPrefixes>
    97            <Prefix>*/__magic</Prefix>
    98          </ExcludedPrefixes>
    99          <ExcludedPrefixes>
   100            <Prefix>*/_staging</Prefix>
   101          </ExcludedPrefixes>
   102  
   103          <!-- .. up to 10 prefixes in all -->
   104  </VersioningConfiguration>
   105  ```
   106  
   107  ### Features
   108  
   109  - Objects matching these prefixes will behave as though versioning were suspended. These objects **will not** be replicated if bucket has replication configured.
   110  - Objects matching these prefixes will also not leave `null` delete markers, dramatically reduces namespace pollution while keeping the benefits of replication.
   111  - Users with explicit permissions or the root credential can configure the versioning state of any bucket.
   112  
   113  ## Examples of enabling bucket versioning using MinIO Java SDK
   114  
   115  ### EnableVersioning() API
   116  
   117  ```
   118  import io.minio.EnableVersioningArgs;
   119  import io.minio.MinioClient;
   120  import io.minio.errors.MinioException;
   121  import java.io.IOException;
   122  import java.security.InvalidKeyException;
   123  import java.security.NoSuchAlgorithmException;
   124  
   125  public class EnableVersioning {
   126    /** MinioClient.enableVersioning() example. */
   127    public static void main(String[] args)
   128        throws IOException, NoSuchAlgorithmException, InvalidKeyException {
   129      try {
   130        /* play.min.io for test and development. */
   131        MinioClient minioClient =
   132            MinioClient.builder()
   133                .endpoint("https://play.min.io")
   134                .credentials("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG")
   135                .build();
   136  
   137        /* Amazon S3: */
   138        // MinioClient minioClient =
   139        //     MinioClient.builder()
   140        //         .endpoint("https://s3.amazonaws.com")
   141        //         .credentials("YOUR-ACCESSKEY", "YOUR-SECRETACCESSKEY")
   142        //         .build();
   143  
   144        // Enable versioning on 'my-bucketname'.
   145        minioClient.enableVersioning(EnableVersioningArgs.builder().bucket("my-bucketname").build());
   146  
   147        System.out.println("Bucket versioning is enabled successfully");
   148  
   149      } catch (MinioException e) {
   150        System.out.println("Error occurred: " + e);
   151      }
   152    }
   153  }
   154  ```
   155  
   156  ### isVersioningEnabled() API
   157  
   158  ```
   159  public class IsVersioningEnabled {
   160    /** MinioClient.isVersioningEnabled() example. */
   161    public static void main(String[] args)
   162        throws IOException, NoSuchAlgorithmException, InvalidKeyException {
   163      try {
   164        /* play.min.io for test and development. */
   165        MinioClient minioClient =
   166            MinioClient.builder()
   167                .endpoint("https://play.min.io")
   168                .credentials("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG")
   169                .build();
   170  
   171        /* Amazon S3: */
   172        // MinioClient minioClient =
   173        //     MinioClient.builder()
   174        //         .endpoint("https://s3.amazonaws.com")
   175        //         .credentials("YOUR-ACCESSKEY", "YOUR-SECRETACCESSKEY")
   176        //         .build();
   177  
   178        // Create bucket 'my-bucketname' if it doesn`t exist.
   179        if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket("my-bucketname").build())) {
   180          minioClient.makeBucket(MakeBucketArgs.builder().bucket("my-bucketname").build());
   181          System.out.println("my-bucketname is created successfully");
   182        }
   183  
   184        boolean isVersioningEnabled =
   185            minioClient.isVersioningEnabled(
   186                IsVersioningEnabledArgs.builder().bucket("my-bucketname").build());
   187        if (isVersioningEnabled) {
   188          System.out.println("Bucket versioning is enabled");
   189        } else {
   190          System.out.println("Bucket versioning is disabled");
   191        }
   192        // Enable versioning on 'my-bucketname'.
   193        minioClient.enableVersioning(EnableVersioningArgs.builder().bucket("my-bucketname").build());
   194        System.out.println("Bucket versioning is enabled successfully");
   195  
   196        isVersioningEnabled =
   197            minioClient.isVersioningEnabled(
   198                IsVersioningEnabledArgs.builder().bucket("my-bucketname").build());
   199        if (isVersioningEnabled) {
   200          System.out.println("Bucket versioning is enabled");
   201        } else {
   202          System.out.println("Bucket versioning is disabled");
   203        }
   204  
   205      } catch (MinioException e) {
   206        System.out.println("Error occurred: " + e);
   207      }
   208    }
   209  }
   210  ```
   211  
   212  ## Explore Further
   213  
   214  - [Use `minio-java` SDK with MinIO Server](https://min.io/docs/minio/linux/developers/java/minio-java.html)
   215  - [Object Lock and Immutablity Guide](https://min.io/docs/minio/linux/administration/object-management/object-retention.html)
   216  - [MinIO Admin Complete Guide](https://min.io/docs/minio/linux/reference/minio-mc-admin.html)
   217  - [The MinIO documentation website](https://min.io/docs/minio/linux/index.html)