Transitioning data to Azure cloud service

You can transition data to a remote cloud service as part of the lifecycle configuration using storage classes to reduce cost and improve manageability. The transition is unidirectional and data cannot be transitioned back from the remote zone. This feature is to enable data transition to multiple cloud providers such as Azure. One of the key differences with the AWS configuration is that you need to configure the multi-cloud gateway (MCG) and use MCG to translate from the S3 protocol to Azure Blob.

Use cloud-s3 as tier-type to configure the remote cloud S3 object store service to which the data needs to be transitioned. These do not need a data pool and are defined in terms of the zonegroup placement targets.

Prerequisites

  • A running IBM Storage Ceph cluster with Ceph Object Gateway installed.

  • User credentials for the remote cloud service, Azure.

  • Azure configured locally to download data.

  • s3cmd installed on the bootstrapped node.

  • Azure container for the for MCG namespace created. In this example, it is mcgnamespace.

Procedure

  1. Create a user with access key and secret key:

    Syntax
    radosgw-admin user create --uid=USER_NAME --display-name="DISPLAY_NAME" [--access-key ACCESS_KEY --secret-key SECRET_KEY]
    Example
    [ceph: root@host01 /]# radosgw-admin user create --uid=test-user --display-name="test-user" --access-key a21e86bce636c3aa1 --secret-key cf764951f1fdde5e
    {
        "user_id": "test-user",
        "display_name": "test-user",
        "email": "",
        "suspended": 0,
        "max_buckets": 1000,
        "subusers": [],
        "keys": [
            {
                "user": "test-user",
                "access_key": "a21e86bce636c3aa1",
                "secret_key": "cf764951f1fdde5e"
            }
        ],
        "swift_keys": [],
        "caps": [],
        "op_mask": "read, write, delete",
        "default_placement": "",
        "default_storage_class": "",
        "placement_tags": [],
        "bucket_quota": {
            "enabled": false,
            "check_on_raw": false,
            "max_size": -1,
            "max_size_kb": 0,
            "max_objects": -1
        },
        "user_quota": {
            "enabled": false,
            "check_on_raw": false,
            "max_size": -1,
            "max_size_kb": 0,
            "max_objects": -1
        },
        "temp_url_keys": [],
        "type": "rgw",
        "mfa_ids": []
    }
  2. As a root user, configure AWS CLI with the user credentials and create a bucket with default placement:

    Syntax
    aws s3 --ca-bundle CA_PERMISSION --profile rgw  --endpoint ENDPOINT_URL --region default mb s3://BUCKET_NAME
    Example
    [root@host01 ~]$ aws s3   --ca-bundle  /etc/pki/ca-trust/source/anchors/myCA.pem --profile rgw  --endpoint https://host02.example.com:8043 --region default mb s3://transition
  3. Verify that the bucket is using default-placement with the placement rule:

    Example
    [root@host01 ~]# radosgw-admin bucket stats --bucket transition
    {
        "bucket": "transition",
        "num_shards": 11,
        "tenant": "",
        "zonegroup": "b29b0e50-1301-4330-99fc-5cdcfc349acf",
        "placement_rule": "default-placement",
        "explicit_placement": {
            "data_pool": "",
            "data_extra_pool": "",
            "index_pool": ""
        },
  4. Log into the OpenShift Container Platform (OCP) cluster with OpenShift Data Foundation (ODF) deployed:

    Example
    [root@host01 ~]$ oc project openshift-storage
    [root@host01 ~]$ oc get clusterversion
    NAME      VERSION   AVAILABLE   PROGRESSING   SINCE   STATUS
    version   4.11.6    True        False         4d1h    Cluster version is 4.11.6
    
    [root@host01 ~]$ oc get storagecluster
    NAME                 AGE   PHASE   EXTERNAL   CREATED AT             VERSION
    ocs-storagecluster   4d    Ready              2023-06-27T15:23:01Z   4.11.0
  5. Configure the multi-cloud gateway (MCG) namespace Azure bucket running on an OCP cluster in Azure:

    Syntax
    noobaa namespacestore create azure-blob az --account-key='ACCOUNT_KEY' --account-name='ACCOUNT_NAME' --target-blob-container='AZURE_CONTAINER_NAME'
    Example
    [root@host01 ~]$ noobaa namespacestore create azure-blob  az --account-key='iq3+6hRtt9bQ46QfHKQ0nSm2aP+tyMzdn8dBSRW4XWrFhY+1nwfqEj4hk2q66nmD85E/o5OrrUqo+AStkKwm9w==' --account-name='transitionrgw' --target-blob-container='mcgnamespace'
  6. Create an MCG bucket class pointing to the namespacestore:

    Example
    [root@host01 ~]$ noobaa bucketclass create namespace-bucketclass single aznamespace-bucket-class --resource az -n openshift-storage
  7. Create an object bucket claim (OBC) for the transition to cloud:

    Syntax
    noobaa obc create OBC_NAME --bucketclass aznamespace-bucket-class -n openshift-storage
    Example
    [root@host01 ~]$ noobaa obc create rgwobc --bucketclass aznamespace-bucket-class -n openshift-storage
    Note: Use the credentials provided by OBC to configure zonegroup placement on the Ceph Object Gateway.
  8. On the bootstrapped node, create a storage class with the tier type as cloud-s3 on the default placement within the default zonegroup on the previously configured MCG in Azure:

    Note: Once a storage class is created with the --tier-type=cloud-s3 option , it cannot be later modified to any other storage class type.
    Syntax
    radosgw-admin zonegroup placement add --rgw-zonegroup =ZONE_GROUP_NAME \
                                --placement-id=PLACEMENT_ID \
                                --storage-class =STORAGE_CLASS_NAME \
                                --tier-type=cloud-s3
    Example
    [ceph: root@host01 /]# radosgw-admin zonegroup placement add --rgw-zonegroup=default \
                                                     --placement-id=default-placement \
                                                     --storage-class=AZURE \
                                                     --tier-type=cloud-s3
    [
        {
            "key": "default-placement",
            "val": {
                "name": "default-placement",
                "tags": [],
                "storage_classes": [
                    "AZURE",
                    "STANDARD"
                ],
                "tier_targets": [
                    {
                        "key": "AZURE",
                        "val": {
                            "tier_type": "cloud-s3",
                            "storage_class": "AZURE",
                            "retain_head_object": "false",
                            "s3": {
                                "endpoint": "",
                                "access_key": "",
                                "secret": "",
                                "host_style": "path",
                                "target_storage_class": "",
                                "target_path": "",
                                "acl_mappings": [],
                                "multipart_sync_threshold": 33554432,
                                "multipart_min_part_size": 33554432
                            }
                        }
                    }
                ]
            }
        }
    ]
  9. Configure the cloud S3 cloud storage class:

    Syntax
    radosgw-admin zonegroup placement modify --rgw-zonegroup ZONE_GROUP_NAME \
                                             --placement-id PLACEMENT_ID \
                                             --storage-class STORAGE_CLASS_NAME  \
                                             --tier-config=endpoint=ENDPOINT_URL,\
                                             access_key=ACCESS_KEY,secret=SECRET_KEY,\
                                             target_path="TARGET_BUCKET_ON",\
                                             multipart_sync_threshold=44432,\
                                             multipart_min_part_size=44432,\
                                             retain_head_object=true
                                             region=REGION_NAME
    Important: Setting the retain_head_object parameter to true retains the metadata or the head of the object to list the objects that are transitioned.
  10. Example
    [ceph: root@host01 /]# radosgw-admin zonegroup placement modify --rgw-zonegroup default
                                                                    --placement-id default-placement \
                                                                    --storage-class AZURE \
                                                                    --tier-config=endpoint="https://s3-openshift-storage.apps.ocp410.0e73azopenshift.com",\
                                                                    access_key=a21e86bce636c3aa2,secret=cf764951f1fdde5f,\
                                                                    target_path="dfqe-bucket-01",\
                                                                    multipart_sync_threshold=44432,\
                                                                    multipart_min_part_size=44432,\
                                                                    retain_head_object=true
                                                                    region= us-east-1
    
    [
        {
            "key": "default-placement",
            "val": {
                "name": "default-placement",
                "tags": [],
                "storage_classes": [
                    "AZURE",
                    "STANDARD",
                    "cold.test",
                    "hot.test"
                ],
                "tier_targets": [
                    {
                        "key": "AZURE",
                        "val": {
                            "tier_type": "cloud-s3",
                            "storage_class": "AZURE",
                            "retain_head_object": "true",
                            "s3": {
                                "endpoint": "https://s3-openshift-storage.apps.ocp410.0e73azopenshift.com",
                                "access_key": "a21e86bce636c3aa2",
                                "secret": "cf764951f1fdde5f",
                                "region": "",
                                "host_style": "path",
                                "target_storage_class": "",
                                "target_path": "dfqe-bucket-01",
                                "acl_mappings": [],
                                "multipart_sync_threshold": 44432,
                                "multipart_min_part_size": 44432
                            }
                        }
                    }
                ]
            }
        }
    ]
  11. Restart the Ceph Object Gateway:

    Syntax
    ceph orch restart CEPH_OBJECT_GATEWAY_SERVICE_NAME
    Example
    [ceph: root@host 01 /]# ceph orch restart client.rgw.objectgwhttps.host02.udyllp
    
    Scheduled to restart client.rgw.objectgwhttps.host02.udyllp on host 'host02
  12. Create the lifecycle configuration transition policy for the bucket created previously. In this example, the bucket is transition:

    Syntax
    cat transition.json
    {
        "Rules": [
            {
                "Filter": {
                    "Prefix": ""
                },
                "Status": "Enabled",
                "Transitions": [
                    {
                        "Days": 30,
                        "StorageClass": "STORAGE_CLASS"
                    }
                ],
                "ID": "TRANSITION_ID"
            }
        ]
            }
    Note: All the objects in the bucket older than 30 days are transferred to the cloud storage class called AZURE.
    Example
    [root@host01 ~]$ cat transition.json
    {
        "Rules": [
            {
                "Filter": {
                    "Prefix": ""
                },
                "Status": "Enabled",
                "Transitions": [
                    {
                        "Days": 30,
                        "StorageClass": "AZURE"
                    }
                ],
                "ID": "Transition Objects in bucket to AZURE Blob after 30 days"
            }
        ]
            }
  13. Apply the bucket lifecycle configuration using AWS CLI:

    Syntax
     aws s3api --ca-bundle CA_PERMISSION --profile rgw --endpoint ENDPOINT_URL --region default put-bucket-lifecycle-configuration --lifecycle-configuration  file://BUCKET.json --bucket BUCKET_NAME
    Example
    [root@host01 ~]$ aws s3api --ca-bundle  /etc/pki/ca-trust/source/anchors/myCA.pem --profile rgw  --endpoint https://host02.example.com:8043 --region default put-bucket-lifecycle-configuration --lifecycle-configuration  file://transition.json --bucket transition
  14. Optional: Get the lifecycle configuration:

    Syntax
     aws s3api --ca-bundle CA_PERMISSION --profile rgw --endpoint ENDPOINT_URL--region default get-bucket-lifecycle-configuration --lifecycle-configuration  file://BUCKET.json --bucket BUCKET_NAME
    Example
    [root@host01 ~]$ aws s3api   --ca-bundle  /etc/pki/ca-trust/source/anchors/myCA.pem --profile rgw  --endpoint https://host02.example.com:8043 --region default get-bucket-lifecycle-configuration --bucket transition
    {
        "Rules": [
            {
                "ID": "Transition Objects in bucket to AZURE Blob after 30 days",
                "Prefix": "",
                "Status": "Enabled",
                "Transitions": [
                    {
                        "Days": 30,
                        "StorageClass": "AZURE"
                    }
                ]
            }
        ]
    }
  15. Optional: Get the lifecycle configuration with the radosgw-admin lc list command:

    [root@host 01 ~]# radosgw-admin lc list
    [
        {
            "bucket": ":transition:d9c4f708-5598-4c44-9d36-849552a08c4d.169377.1",
            "started": "Thu, 01 Jan 1970 00:00:00 GMT",
            "status": "UNINITIAL"
        }
    ]
    Note: The UNINITAL status implies that the lifecycle configuration is not processed. It moves to COMPLETED state after the transition process is complete.
  16. Log in to cephadm shell:

    [root@host 01 ~]# cephadm shell
  17. Restart the Ceph Object Gateway daemon:

    Syntax
    ceph orch daemon CEPH_OBJECT_GATEWAY_DAEMON_NAME
    Example
    [ceph: root@host 01 /]# ceph orch daemon restart rgw.objectgwhttps.host02.udyllp
    [ceph: root@host 01 /]# ceph orch daemon restart rgw.objectgw.host02.afwvyq
    [ceph: root@host 01 /]# ceph orch daemon restart rgw.objectgw.host05.ucpsrr
  18. Migrate data from the source cluster to Azure:

    Example
    [root@host 01 ~]# for i in 1 2 3 4 5
    do
    aws s3 --ca-bundle  /etc/pki/ca-trust/source/anchors/myCA.pem --profile rgw --endpoint https://host02.example.com:8043 --region default cp /etc/hosts s3://transition/transition$i
    done
  19. Verify transition of data:

    Example
    [root@host 01 ~]# aws s3 --ca-bundle  /etc/pki/ca-trust/source/anchors/myCA.pem --profile rgw  --endpoint https://host02.example.com:8043 --region default ls s3://transition
    2023-06-30 10:24:01       3847 transition1
    2023-06-30 10:24:04       3847 transition2
    2023-06-30 10:24:07       3847 transition3
    2023-06-30 10:24:09       3847 transition4
    2023-06-30 10:24:13       3847 transition5
  20. Verify if the data has moved to Azure with rados ls command:

    Example
    [root@host 01 ~]# rados ls -p default.rgw.buckets.data | grep transition
    d9c4f708-5598-4c44-9d36-849552a08c4d.169377.1_transition1
    d9c4f708-5598-4c44-9d36-849552a08c4d.169377.1_transition4
    d9c4f708-5598-4c44-9d36-849552a08c4d.169377.1_transition2
    d9c4f708-5598-4c44-9d36-849552a08c4d.169377.1_transition3
    d9c4f708-5598-4c44-9d36-849552a08c4d.169377.1_transition5
  21. If the data is not transitioned, you can run the lc process command:

    Example
    [root@host 01 ~]# radosgw-admin lc process

    This will force the lifecycle process to start and evaluates all the bucket lifecycle policies configured. It then starts the transition of data wherever needed.

Verification

  1. Run the radosgw-admin lc list command to verify the completion of the transition:

    Example
    [root@host 01 ~]# radosgw-admin lc list
    [
        {
            "bucket": ":transition:d9c4f708-5598-4c44-9d36-849552a08c4d.170017.5",
            "started": "Mon, 30 Jun 2023-06-30 16:52:56 GMT",
            "status": "COMPLETE"
        }
    ]
  2. List the objects in the bucket:

    Example
    [root@host01 ~]$ aws s3api list-objects --bucket awstestbucket --endpoint=http://10.0.209.002:8080
    {
        "Contents": [
            {
                "Key": "awstestbucket/test",
                "LastModified": "2023-06-25T16:14:23.118Z",
                "ETag": "\"378c905939cc4459d249662dfae9fd6f\"",
                "Size": 29,
                "StorageClass": "STANDARD",
                "Owner": {
                    "DisplayName": "test-user",
                    "ID": "test-user"
                }
            }
        ]
    }
  3. List the objects on the cluster:

    Example
    [root@host01 ~]$ aws s3 --ca-bundle  /etc/pki/ca-trust/source/anchors/myCA.pem --profile rgw  --endpoint https://host02.example.com:8043 --region default ls s3://transition
    2023-06-30 17:52:56          0 transition1
    2023-06-30 17:51:59          0 transition2
    2023-06-30 17:51:59          0 transition3
    2023-06-30 17:51:58          0 transition4
    2023-06-30 17:51:59          0 transition5

    The objects are 0 in size. You can list the objects, but cannot copy them since they are transitioned to Azure.

  4. Check the head of the object using the S3 API:

    Example
    [root@host01 ~]$ aws s3api --ca-bundle  /etc/pki/ca-trust/source/anchors/myCA.pem --profile rgw  --endpoint https://host02.example.com:8043 --region default head-object --key transition1 --bucket transition
    {
        "AcceptRanges": "bytes",
        "LastModified": "2023-06-31T16:52:56+00:00",
        "ContentLength": 0,
        "ETag": "\"46ecb42fd0def0e42f85922d62d06766\"",
        "ContentType": "binary/octet-stream",
        "Metadata": {},
        "StorageClass": "CLOUDTIER"
    }

    You can see that the storage class has changed from STANDARD to CLOUDTIER.