COSI Driver for Nutanix

COSI (Container Object Storage Interface) เป็น driver ที่ช่วย deploy และ config Object Storage ทำหน้าที่เหมือนกับ CSI (Container Storage Interface) เพื่อสร้าง volume ทั้งที่เป็น block และ file storage ให้กับ container หน้าที่ของ COSI จะสร้าง Bucket และ Access/Secret key ให้อัตโนมัติ ทำให้การใช้งาน object storage ทำได้อัตโนมัติผ่าน deployment metadata (yaml) ลดงาน operation ในการจัดการ object storage ให้กับ container application

COSI vs CSI Comparison

ConceptCSI (Block/File)COSI(Object)
Storage ClassStorageClassBucketClass
ClaimPersistentVolumeClaimBucketClaim
AccessBuilt into PVCBucketAccess + BucketAccessClass
MountVolume mount in podCredentials secret in pod
ProtocalBlock/NFS/etcS3, GCS, Azure Blob
StatusStable (v1)Alpha (v1alpha1)

Provider ที่ support COSI driver เช่น

ProviderDriver
MinIOminio.objectstorage.k8s.io
AWS S3s3.amazonaws.com
Ceph/RadosGWceph.objectstorage.k8s.io
Nutanix Objectsnutanix.objectstorage.k8s.io

เปิดใช้งาน COSI ใน NKP สามารถทำได้ผ่าน Application Catalog โดยเข้าไปที่ COSI Driver for Nutanix

เข้าไปที่ enable option และกรอกข้อมูลที่จำเป็นตามตัวอย่าง

หลังจากกดปุ่ม Save ระบบจะติดตั้ง COSI CRD และ COSI Controller ไปยัง Kubernetes Cluster ที่เลือก โดยสามารถตรวจสอบได้จากตัวอย่าง

[root@guest-bastion-server-1 nutanix]# kubectl get crds | grep objectstorage
bucketaccessclasses.objectstorage.k8s.io 2026-02-13T14:37:53Z
bucketaccesses.objectstorage.k8s.io 2026-02-13T14:37:53Z
bucketclaims.objectstorage.k8s.io 2026-02-13T14:37:53Z
bucketclasses.objectstorage.k8s.io 2026-02-13T14:37:53Z
buckets.objectstorage.k8s.io 2026-02-13T14:37:53Z
[root@guest-bastion-server-1 nutanix]# kubectl get pod -n container-object-storage-system
NAME READY STATUS RESTARTS AGE
container-object-storage-controller-667886cd7f-l658v 1/1 Running 0 12h

NKP จะติดตั้ง BucketClass ให้อัตโนมัติ โดยตรวจสอบได้จาก cli

[root@guest-bastion-server-1 nutanix]# kubectl get bucketclasses
NAME AGE
cosi-nutanix-nkp 47m
[root@guest-bastion-server-1 nutanix]# kubectl get bucketclasses cosi-nutanix-nkp -o yaml
apiVersion: objectstorage.k8s.io/v1alpha1
deletionPolicy: Delete
driverName: ntnx.objectstorage.k8s.io
kind: BucketClass
metadata:
annotations:
meta.helm.sh/release-name: cosi-resources-nutanix
meta.helm.sh/release-namespace: develop
creationTimestamp: "2026-02-14T02:16:04Z"
generation: 1
labels:
app.kubernetes.io/managed-by: Helm
helm.toolkit.fluxcd.io/name: cosi-resources-nutanix
helm.toolkit.fluxcd.io/namespace: develop
name: cosi-nutanix-nkp
resourceVersion: "642878"
uid: 58023be3-9179-40c7-be4d-24219c4a7735

ตรวจสอบว่า NKP ได้สร้าง BucketAccessClass ให้

[root@guest-bastion-server-1 nutanix]# kubectl get BucketAccessClass
NAME AGE
cosi-nutanix-nkp 50m
[root@guest-bastion-server-1 nutanix]# kubectl get BucketAccessClass cosi-nutanix-nkp -o yaml
apiVersion: objectstorage.k8s.io/v1alpha1
authenticationType: KEY
driverName: ntnx.objectstorage.k8s.io
kind: BucketAccessClass
metadata:
annotations:
meta.helm.sh/release-name: cosi-resources-nutanix
meta.helm.sh/release-namespace: develop
creationTimestamp: "2026-02-14T02:16:04Z"
generation: 1
labels:
app.kubernetes.io/managed-by: Helm
helm.toolkit.fluxcd.io/name: cosi-resources-nutanix
helm.toolkit.fluxcd.io/namespace: develop
name: cosi-nutanix-nkp
resourceVersion: "642877"
uid: 4bd6a0e8-0a16-4039-8746-66e2c7c00a87

ทำการสร้าง BucketClaim (เหมือน PVC สำหรับ object storage)

YAML
apiVersion: objectstorage.k8s.io/v1alpha1
kind: BucketClaim
metadata:
name: test-bucketclaim
spec:
bucketClassName: cosi-nutanix-nkp
protocols:
- s3

สร้าง BucketAccess เพื่อให้ COSI Controller สร้าง credential สำหรับ connect ไปยัง S3 Bucket อัตโนมติ

YAML
apiVersion: objectstorage.k8s.io/v1alpha1
kind: BucketAccess
metadata:
name: nkp-test-bucketaccess
spec:
bucketAccessClassName: cosi-nutanix-nkp
bucketClaimName: test-bucketclaim
credentialsSecretName: nkp-test-objectstore-credentials

ตรวจสอบว่า cosi controller ได้ทำการสร้าง secret ตามที่กำหนดใน BucketAccess metadata

[root@guest-bastion-server-1 nutanix]# kubectl get secret nkp-test-objectstore-credentials
NAME TYPE DATA AGE
nkp-test-objectstore-credentials Opaque 1 47m
[root@guest-bastion-server-1 nutanix]# k get secret nkp-test-objectstore-credentials -o yaml
apiVersion: v1
data:
BucketInfo: eyJtZXRhZGF0YSI6eyJuYW1lIjoiYmMtNTM3OTBlOGQtZDMzMC00N2QzLWE2MjAtOWI4ODVmYTEwNTQ3IiwiY3JlYXRpb25UaW1lc3RhbXAiOm51bGx9LCJzcGVjIjp7ImJ1Y2tldE5hbWUiOiJjb3NpLW51dGFuaXgtbmtwYjE5Y2EwZTItNzRjNC00YmNmLWE3YjctMmUzN2U2MDY5YWM2IiwiYXV0aGVudGljYXRpb25UeXBlIjoiS0VZIiwic2VjcmV0UzMiOnsiZW5kcG9pbnQiOiJodHRwczovLzE5Mi4xNjguMTAuNTI6NDQzIiwicmVnaW9uIjoidXMtZWFzdC0xIiwiYWNjZXNzS2V5SUQiOiJMc2pDRG9ZeTREX09wRl9sVmo5UkNQRERnUS1SOG1NXyIsImFjY2Vzc1NlY3JldEtleSI6ImVpZW45bjdUM1pHZ2oxSGtydVZvVmNOM1VuUlAybnBjIn0sInNlY3JldEF6dXJlIjpudWxsLCJwcm90b2NvbHMiOlsiIl19fQ==
kind: Secret
metadata:
creationTimestamp: "2026-02-14T03:46:44Z"
finalizers:
- cosi.objectstorage.k8s.io/secret-protection
name: nkp-test-objectstore-credentials
namespace: default
resourceVersion: "727116"
uid: 1d6c999c-6605-4580-9db4-e18c7fe1a41c
type: Opaque
[root@guest-bastion-server-1 nutanix]# kubectl get secret nkp-test-objectstore-credentials -o jsonpath='{.data.BucketInfo}' | base64 -d | jq .
{
"metadata": {
"name": "bc-53790e8d-d330-47d3-a620-9b885fa10547",
"creationTimestamp": null
},
"spec": {
"bucketName": "cosi-nutanix-nkpb19ca0e2-74c4-4bcf-a7b7-2e37e6069ac6",
"authenticationType": "KEY",
"secretS3": {
"endpoint": "https://192.168.10.52:443",
"region": "us-east-1",
"accessKeyID": "LsjCDoYy4D_OpF_lVj9RCPDDgQ-R8mM_",
"accessSecretKey": "eien9n7T3ZGgj1HkruVoVcN3UnRP2npc"
},
"secretAzure": null,
"protocols": [
""

Deploy cosi-test container เพื่อทดสอบอ่านเขียนข้อมูลลงใน bucket storage ได้ถูกต้อง

YAML
apiVersion: v1
kind: Pod
metadata:
name: cosi-test
namespace: default
spec:
containers:
- name: test
image: amazon/aws-cli:latest
command: ["/bin/sh", "-c"]
args:
- |
echo "=== COSI Bucket Test ==="
# Install jq
yum install -y jq 2>/dev/null || apk add jq 2>/dev/null
# Parse BucketInfo JSON
BUCKET_INFO=$(cat /cosi/BucketInfo)
export AWS_ACCESS_KEY_ID=$(echo $BUCKET_INFO | jq -r '.spec.secretS3.accessKeyID')
export AWS_SECRET_ACCESS_KEY=$(echo $BUCKET_INFO | jq -r '.spec.secretS3.accessSecretKey')
BUCKET_NAME=$(echo $BUCKET_INFO | jq -r '.spec.bucketName')
ENDPOINT=$(echo $BUCKET_INFO | jq -r '.spec.secretS3.endpoint')
echo "Bucket: $BUCKET_NAME"
echo "Endpoint: $ENDPOINT"
# Write test
echo "Hello from COSI!" > /tmp/testfile.txt
aws s3 cp /tmp/testfile.txt s3://$BUCKET_NAME/testfile.txt \
--endpoint-url $ENDPOINT --no-verify-ssl
# List bucket
aws s3 ls s3://$BUCKET_NAME/ --endpoint-url $ENDPOINT --no-verify-ssl
# Read test
aws s3 cp s3://$BUCKET_NAME/testfile.txt /tmp/downloaded.txt \
--endpoint-url $ENDPOINT --no-verify-ssl
cat /tmp/downloaded.txt
echo "=== Test Complete ==="
sleep 3600
volumeMounts:
- name: cosi-credentials
mountPath: /cosi
readOnly: true
volumes:
- name: cosi-credentials
secret:
secretName: nkp-test-objectstore-credentials

ตรวจสอบการทำงาน จาก log ของ pod cosi-test

[root@guest-bastion-server-1 nutanix]# kubectl logs cosi-test
=== COSI Bucket Test ===
Amazon Linux 2023 repository 23 MB/s | 54 MB 00:02
Last metadata expiration check: 0:00:09 ago on Sat Feb 14 04:46:32 2026.
Package jq-1.7.1-51.amzn2023.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!
Bucket: cosi-nutanix-nkpb19ca0e2-74c4-4bcf-a7b7-2e37e6069ac6
Endpoint: https://192.168.10.52:443