Overview

At this point the HPE COSI Driver and HPE Alletra Storage MP X10000 should be installed and configured.

Important

All examples below assumes there's a Secret with the necessary credentials to connect to the backend object storage system and HPE Data Services Cloud Console. Learn how to create the Secret in the Deployment section.

Configure a BucketClass

The BucketClass defines a set of properties that can be used to configure buckets. The BucketClass has a variety of fields that you can configure. An example of BucketClass is below. BucketClasses are clustered resources normally created by Kubernetes administrators.

kind: BucketClass
apiVersion: objectstorage.k8s.io/v1alpha1
metadata:
  name: hpe-standard-object
driverName: cosi.hpe.com
deletionPolicy: Delete
parameters:
  cosiUserSecretName: hpe-object-backend
  cosiUserSecretNamespace: default

Clarification of deletionPolicy

The deletionPolicy is used to delete a bucket. It can be set to Delete or Retain, depending on whether the actual bucket in HPE Alletra Storage MP X10000 should be removed or retained. The associated COSI API resources BucketClaim and Bucket will be deleted regardless of the deletionPolicy. The Bucket resource can only be removed once all BucketAccess resources have been removed.

The kubectl create command can be used to create this resource.

kubectl create -f hpe-standard-object.yaml

Important

The Secret should be created before referring to it in the BucketClass.

Optional BucketClass Parameters

Optional BucketClass .parameters.

Parameter String Description
bucketTags Text The tags to be applied on a bucket. The key-value pairs must be comma separated. In a tag, the key is required while the value is optional. Example: .parameters.bucketTags: mytag1=myval1, mytag2, mytag3=myval3.

Create a BucketClaim

The BucketClaim resource will be used to create a Bucket in COSI according to the properties specified in the BucketClass it refers to. Examples of Greenfield and Brownfield provisioning have been provided below. BucketClaims are namespaced resources normally created by applications and Kubernetes users.

Greenfield Bucket Provisioning

You can use the following manifest to create a new bucket on the object storage system.

kind: BucketClaim
apiVersion: objectstorage.k8s.io/v1alpha1
metadata:
  name: my-first-bucketclaim
spec:
  bucketClassName: hpe-standard-object
  protocols:
  - s3

The kubectl create command can be used to create this resource.

kubectl create -f my-first-bucketclaim.yaml

The kubectl create command will create the BucketClaim and Bucket on the cluster. Check the Status and Events field of the resources' description to verify if the bucket was created successfully.

kubectl get bucketclaim,bucket
NAME                               AGE
bucketclaim/my-first-bucketclaim   10d

NAME                                             AGE
bucket/bc199dde004-4f8d-4a20-900b-e5d61e3facb9   10d

Important

The Secret and BucketClass should be created before provisioning a new bucket.

The Bucket created by COSI can be deleted by deleting the associated BucketClaim using the kubectl delete command.

kubectl delete bucketclaim my-first-bucketclaim

Brownfield Bucket Provisioning

To map an existing bucket to a BucketClaim and Bucket, refer the following manifests. In the examples provided here the name of the existing bucket is "brownfield-bucket-name".

apiVersion: objectstorage.k8s.io/v1alpha1
kind: Bucket
metadata:
  name: my-existing-bucket
spec:
  bucketClaim: {}
  bucketClassName: hpe-standard-object
  deletionPolicy: Delete
  driverName: cosi.hpe.com
  existingBucketID: my-existing-bucket
  parameters:
    cosiUserSecretName: hpe-object-backend
    cosiUserSecretNamespace: default
  protocols:
  - s3

Note

A Bucket is a clustered resource and is normally created by a Kubernetes administrator.

Create a BucketClaim referring to the pre-existing Bucket.

apiVersion: objectstorage.k8s.io/v1alpha1
kind: BucketClaim
metadata:
  name: my-brownfield-bucketclaim
spec:
  bucketClassName: hpe-standard-object
  existingBucketName: my-existing-bucket
  protocols:
  - s3

The kubectl create command can be used to create this resource.

kubectl create -f my-existing-bucket.yaml -f my-brownfield-bucketclaim.yaml

The above command will create the BucketClaim and Bucket on the cluster that maps to the existing bucket. Check the Status and Events field of the resources' description to verify if the mapping was successful.

kubectl get bucketclaim,bucket
NAME                                    AGE
bucketclaim/my-brownfield-bucketclaim   72s

NAME                        AGE
bucket/my-existing-bucket   5s

BucketAccessClass Configuration

The BucketAccessClass defines a set of properties that can be used to request bucket-specific access credentials. The BucketAccessClass has a variety of fields that can be configured according to the user's preferences. An example has been provided below. BucketAccessClasses are clustered resources and normally created by a Kubernetes administrator.

kind: BucketAccessClass
apiVersion: objectstorage.k8s.io/v1alpha1
metadata:
  name: hpe-standard-access
driverName: cosi.hpe.com
authenticationType: Key
parameters:
  cosiUserSecretName: hpe-object-backend
  cosiUserSecretNamespace: default

Important

The .parameters.cosiUserSecretName must reference the same Secret used to provision the BucketClaim and it must exist prior to creating a BucketAccessClass and BucketClass. See add an HPE storage backend for more details.

The kubectl create command can be used to create this resource.

kubectl create -f hpe-standard-access.yaml

BucketAccess Configuration

The BucketAccess resource can be used to create the s3 protocol user credentials to access a particular bucket according to the properties specified in the BucketAccessClass. The BucketAccess has a variety of fields that can be configured according to the user's preferences. An example has been provided below. BucketAccess resources are namespaced and normally created by Kubernetes users to grant BucketClaim access to a workload.

kind: BucketAccess
apiVersion: objectstorage.k8s.io/v1alpha1
metadata:
  name: my-first-bucketaccess
spec:
  bucketAccessClassName: hpe-standard-access
  credentialsSecretName: my-first-access-secret
  bucketClaimName: my-first-bucketclaim
  protocol: s3

The kubectl create command can be used to create this resource.

kubectl create -f my-first-bucketaccess.yaml

The kubectl create will create the BucketAccess and a Secret in the default namespace of the cluster. Check the Status and Events field of the BucketAccess resource's description to verify if the access was granted successfully.

kubectl get bucketaccess,secret
NAME                                  AGE
bucketaccess/my-first-bucketaccess    10d

NAME                              TYPE        DATA   AGE
secret/my-first-access-secret     Opaque      1      10d

To inspect the Secret, retrieve the content with kubectl, decode with base64 and present with jq.

kubectl get secret my-first-access-secret -o jsonpath='{.data.BucketInfo}' | base64 --decode | jq
{
  "metadata": {
    "name": "bc-37fd517f-27ac-45fa-b369-57e645967366",
    "creationTimestamp": null
  },
  "spec": {
    "bucketName": "bc199dde004-4f8d-4a20-900b-e5d61e3facb9",
    "authenticationType": "Key",
    "secretS3": {
      "endpoint": "http://192.168.1.100:8080",
      "region": "us-east-1",
      "accessKeyID": "user_ba-37fd517f-27ac-45fa-b369-57e645967366",
      "accessSecretKey": "qLe3DM0Gyoy5I7AMRqRN1Dv2gNWvvq+9EX2Qul+5tWXxgtL5DJ14i+K5UEdh+Orp"
    },
    "secretAzure": null,
    "protocols": [
      "s3"
    ]
  }
}

Tip

The Secret generated here can be used by any COSI-enabled containerized application on the Kubernetes cluster.

The credentials in this Secret can be revoked by deleting the associated BucketAccess using the kubectl delete command.

kubectl delete bucketaccess my-first-bucketaccess

Attaching an Access Secret to an Object Storage Workload

The Secret specified in credentialsSecretName of the BucketAccess can be mounted as a volume to any containerized application running in a Pod on the Kubernetes cluster. The s3 user credentials and other relevant information will be found in the mountPath to access the bucket. The workload running in the Pod can read this information to create an s3 client, read and write objects to the bucket using the library functions available in the aws sdk package for the programming language of your choice. For more details, refer to official Kubernetes Enhancement Proposals documentation on using the COSI driver with a Pod.

As an example, let us create a Job that runs a Python script to put and get an object in the Bucket using the mounted Secret.

The Python aws package boto3 will be installed in the init container. The Python script is stored in a ConfigMap and is mounted to the init container, which will copy it to PYTHONPATH=/app where boto3 is installed. my-first-access-secret is mounted as a volume to the main container my-cosi-app in the mountPath: /data/cosi from where the script will read the bucket-specific s3 user credentials to create the s3 client session.

apiVersion: batch/v1
kind: Job
metadata:
  name: my-cosi-app
spec:
  template:
    spec:
      restartPolicy: Never
      initContainers:
      - name: install-boto3
        image: python:3.9
        command: ["sh", "-c", "pip install boto3 -t /app && cp /scripts/sample_pod.py /app"]
        env:
        - name: http_proxy
          value: ""
        - name: https_proxy
          value: ""
        volumeMounts:
        - name: app-volume
          mountPath: /app
        - name: script-volume
          mountPath: /scripts
      containers:
      - name: my-cosi-app
        image: python:3.9
        command: ["python", "-u", "/app/sample_pod.py"]
        volumeMounts:
        - name: app-volume
          mountPath: /app
        - name: secret-volume
          mountPath: /data/cosi
        env:
        - name: PYTHONPATH
          value: "/app"
      volumes:
      - name: app-volume
        emptyDir: {}
      - name: script-volume
        configMap:
          name: test-object-script
      - name: secret-volume
        secret:
          secretName: my-first-access-secret
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-object-script
data:
  sample_pod.py: |
    #!/usr/bin/env python3

    import json
    import boto3
    import sys

    try:
        # load the bucket info
        print("Loading bucket info...")
        with open('/data/cosi/BucketInfo', 'r') as f:
            bi = json.load(f)

        # create an s3 client session
        print("Creating S3 client session...")
        session = boto3.Session(
            aws_access_key_id=bi['spec']['secretS3']['accessKeyID'],
            aws_secret_access_key=bi['spec']['secretS3']['accessSecretKey'],
        )

        s3 = session.resource(
            bi['spec']['protocols'][0], # set protocol
            endpoint_url=bi['spec']['secretS3']['endpoint'], # set endpoint
        )

        # create an object
        print("Creating object in S3 bucket...")
        s3.Object(bi['spec']['bucketName'], 'sample.txt').put(Body='Hello, World!')
        print('Object created')

        # read the object
        print('Testing the get-object operation on bucket: ' + bi['spec']['bucketName'] + ', object body: ' + s3.Object(bi['spec']['bucketName'], 'sample.txt').get()['Body'].read().decode('utf-8'))

        # Exit gracefully with zero exit code
        print("Script completed successfully.")
        sys.exit(0)

    except Exception as e:
        print(f"An error occurred: {e}", file=sys.stderr)
        sys.exit(1)

Tip

You may need to set http_proxy and https_proxy environment variables of the init container to pip install the boto3 package.

Create the Job and ConfigMap.

kubectl create -f https://scod.hpedev.io/cosi_driver/examples/using/my-cosi-app.yaml

Wait for the Job to be completed.

kubectl get job
NAME          COMPLETIONS   DURATION   AGE
my-cosi-app   1/1           15s        2m5s

The status of the Pod can also be tracked till completion.

kubectl get pods
NAME                READY   STATUS      RESTARTS       AGE
my-cosi-app-tlr7l   0/1     Completed   0             2m9s

Once the Job has completed, the results of the object operations tested in the script can be found in the logs.

kubectl logs jobs/my-cosi-app
Defaulted container "my-cosi-app" out of: my-cosi-app, install-boto3 (init)
Loading bucket info...
Creating S3 client session...
Creating object in S3 bucket...
Object created
Testing the get-object operation on bucket: bc169822df7-532e-43a2-978d-90631719f78e, object body: Hello, World!
Script completed successfully.

Further Reading

The official Kubernetes documentation contains comprehensive documentation on how the COSI API resources work together.