はじめに
本ドキュメントでは、Kubernetes v1.21 にAlphaとして登場予定のContainer Object Storage Interface(COSI)について紹介します。
なお、本内容は2020/10/20にマージされたKEPの内容をベースにしており、Kubernetes v1.21 or later向けには大きく変更される可能性があります。
KubernetesコミュニティのSIG-StorageのCo-Chairの発表ではCOSIを「コーズィー」と発音していました。
COSIの概要
これまでKubernetesではブロックストレージとファイルストレージをターゲットにCSIが提供されてきました。
これに加え Kubernetes v1.21 からはAlphaとしてオブジェクトストレージをターゲットにしたCOSIが登場する予定です。
ブロックストレージ・ファイルストレージ・オブジェクトストレージの違いは下図をご参照ください。
SIG-Storageでは、COSIをサポートすることで、あるKubernetesクラスタ上で動作しているPod, DeploymentやConfigMapなどのリソースを別のKubernetesクラスタへオブジェクトストレージ経由で移動(マイグレーション)するようなユースケースも視野にいれ、COSIの策定を進めています。(※)
2020/12時点でのステータスとしては、2020/10/20にCOSIのKEPがマージされ、KubeCon+CloudNativeCon NA 2020 Virtual でもCOSIについて発表されました。仕様は叩き台ができあがり、サンプル実装も並行して開発中(cosi-controller-manager, consi-provisioner-sidecar, api)の状況です。
※ Kubernetes クラスタ間のマイグレーションなどはKubernetesコミュニティのData Protection WGでも議論されています。
APIs
COSIではAPIとして以下の6つのAPIが提供される予定です。
なお、オブジェクトストレージでは、データの格納先をBucketという単位で管理します。ブロックストレージやファイルストレージのVolume相当だと思ってもらっても良いかと思います。
- Storage APIs
- BucketRequest (Bucketの要求仕様、CSIのPVCに相当)
- Bucket (Bucket、CSIのPVに相当)
- BucketClass (Bucketの生成元、CSIのStorageClassに相当)
- Access APIs
- BucketAccessRequest (Bucketへのアクセス権(クレデンシャル)の要求仕様)
- BucketAccess (Bucketへのアクセス権(クレデンシャル))
- BucketAccessClass (Bucketへのアクセス権(クレデンシャル)の生成元)
COSIのアーキテクチャについては下図をご参照ください。
各ストレージベンダは、COSI-Sidecar-ControllerからGRPC経由で呼びされるVendor-Provisionerを独自に開発することになります。
以下に、それぞれのAPIについて詳細に紹介します。
BucketRequest (BR)
BucketRequestは、Bucketの生成やBucketへのアクセス時に必要となるクレデンシャルの生成する際の要求をまとめたリソースです。
Namespaceごとのリソースになります。
BucketRequestとBucketは1:1でマッピングされます。
以下に、リソースの定義を示します。
apiVersion: cosi.io/v1alpha1
kind: BucketRequest
metadata:
name:
namespace:
labels:
cosi.io/provisioner: [1]
finalizers:
- cosi.io/finalizer [2]
spec:
protocol:
name: [3]
version: [4]
bucketPrefix: [5]
bucketClassName: [6]
bucketInstanceName: [7]
status:
bucketAvailable: [8]
- Provisionerの名前
- 削除時に呼び出されるFinalizer
- プロトコル名 (例:
S3
,gs
,azureBlob
など) - プロトコルバージョン (例:
S3
の場合、v2
やv4
など) - Buketにつける接頭辞
- Bucketの生成元となるBucketClassの名前
- Buketの名前
-
True
の場合、Bucketが生成済み
Bucket
データの格納先となるBuketを示すリソースです。
Kubernetesクラスタでユニークなリソースになります(cluster-scoped)。
また、COSIでもCSIと同じくDynamic Volume Provisioning相当の機能があります。
COSIではDynamic Volume Provisioningに相当するものをgreenfiled
, Manually Volume Provisioningに相当するものを brownfield
と呼んでいます。
つまり、greenfiled
の場合、Bucketのリソースは、BucketRequestとBuketClassにより自動生成されます。
以下に、リソースの定義を示します。
apiVersion: cosi.io/v1alpha1
kind: Bucket
metadata:
name: [1]
labels: [2]
cosi.io/provisioner:
cosi.io/bucket-prefix:
finalizers:
- cosi.io/finalizer [3]
spec:
provisioner: [4]
retentionPolicy: [5]
anonymousAccessMode: [6]
bucketClassName: [7]
bucketRequest: [8]
allowedNamespaces: [9]
- name:
protocol: [10]
name:
version:
azureBlob:
containerName:
storageAccount:
s3:
endpoint:
bucketName:
region:
signatureVersion:
gs:
bucketName:
privateKeyName:
projectId:
serviceAccount:
parameters: [11]
status:
bucketAvailable: [12]
- Bucket名
- Provisionerの名前とBucketの接頭辞。
- 削除時に呼び出されるFinalizer
- Provisionerの名前(BucketClassから伝搬)
- BucketRequestの削除時のポリシー
-
Retain
(default): Bucketとデータは保存されたまま(削除されない) -
Delete
: BucketRequestが削除されるとBucketも削除
-
- Bucketへアクセス時にクレデンシャルが指定されていない時の(uncredentialed access)のアクセス権限
-
private
(default): Bucketへのアクセス禁止 -
publicReadOnly
: Readのみ可能(Listも可) -
publicWriteOnly
: Writeのみ可能 -
publicReadWrite
: Read/Write
-
- 生成元のBuketClass名
- マッピングされたBucketRequest
- アクセスが許可されているNamespace
- プロトコルの情報(プロトコル名やバージョンなど)
- パラメータ。BucketClassから伝搬
-
True
の場合、Bucketが生成済み
BucketClass
Bucketの生成元となるリソースです。
Kubernetesクラスタでユニークなリソースになります(cluster-scoped)。
以下にリソースの定義を示します。
apiVersion: cosi.io/v1alpha1
kind: BucketClass
metadata:
name:
provisioner: [1]
isDefaultBucketClass: [2]
protocol:
name: [3]
version: [4]
anonymousAccessMode: [5]
retentionPolicy: {"Delete", "Retain"} [6]
allowedNamespaces: [7]
- name:
parameters: [8]
-
Provisioner名
-
defaultのBucketClassか否かを示すフラグ。
true
の場合、BucketRequestにてbucketClassName
が省略された場合、自動で選択される(デフォルト値はfalse
) -
プロトコル名 (例:
S3
,gs
,azureBlob
など) -
プロトコルバージョン (例:
S3
の場合、v2
やv4
など) -
Bucketへアクセス時にクレデンシャルが指定されていない時の(uncredentialed access)のアクセス権限
-
private
(default): Bucketへのアクセス禁止 -
publicReadOnly
: Readのみ可能(Listも可) -
publicWriteOnly
: Writeのみ可能 -
publicReadWrite
: Read/Write
-
-
BucketRequestの削除時のポリシー
-
Retain
(default): Bucketとデータは保存されたまま(削除されない) -
Delete
: BucketRequestが削除されるとBucketも削除
-
-
アクセスが許可されているNamespace
-
パラメータ。Provisionerへ渡す設定値
BucketAccessRequest (BAR)
Buketへのアクセスの要求をまとめたリソースです。
BucketRequestと同じNamespaceに作成します。
以下に、リソースの定義を示します。
apiVersion: cosi.io/v1alpha1
kind: BucketAccessRequest
metadata:
name:
namespace:
labels:
cosi.io/provisioner: [1]
finalizers:
- cosi.io/finalizer [2]
spec:
serviceAccountName: [3]
bucketRequestName: [4]
bucketAccessClassName: [5]
bucketAccessName: [6]
status:
accessGranted: [7]
- Provisionerの名前
- 削除時に呼び出されるFinalizer
- アクセス権を与えるKubernetesのService Account名
- 関連付けるBucketRequest名
- BuketAccessの生成元となるBucketAccessClass名
- BucketAccess名 (COSIにより自動で設定)
-
true
の場合、bucketにアクセス権が付与されています
BucketAccess (BA)
Buketへのアクセス権限を示すリソースです。
Kubernetesクラスタでユニークなリソースになります(cluster-scoped)。
BucketAccessRequestとBucketAccessは1:1でマッピングされます。
以下にリソースの定義を示します。
apiVersion: cosi.io/v1alpha1
kind: BucketAccess
metadata:
name: [1]
labels:
cosi.io/provisioner: [2]
finalizers:
- cosi.io/finalizer [3]
spec:
provisioner: [4]
bucketInstanceName: [5]
bucketAccessRequest: [6]
serviceAccount: [7]
mintedSecretName: [8]
policyActionsConfigMapData: [9]
principal: [10]
parameters: [11]
status:
accessGranted: [12]
- BucketAccess名
- Provisionerの名前
- 削除時に呼び出されるFinalizer
- Provisionerの名前(BucketAccessClassから伝搬)
- BucketAccessに関連付けられたBuketリソースの名前
- マッピングされたBucketAccessRequestへの参照
- BucketAccessRequestで指定されたKubernetesのService Accountへの参照
- アクセス時のクレデンシャル情報を含むSecretの名前 (provisionerがSecretを生成)
- 特定のユーザーIDに対するポリシーアクション。
例
{“Effect”:“Allow”,“Action”:“s3:PutObject”,“Resource”:“arn:aws:s3:::profilepics/*“},
{“Effect”:“Allow”,“Action”:“s3:GetObject”,“Resource”:“arn:aws:s3:::profilepics/*“},
{“Effect”:“Deny”,“Action”:“s3:*“,”NotResource”:“arn:aws:s3:::profilepics/*“}
- Buketにアクセスできるユーザを一意に識別するためのオブジェクトストレージプロバイダーのユーザー名/アクセスキー
- パラメータ。BuketAccessClassから伝搬
-
true
の場合、Bucketへのアクセスが可能
BucketAccessClass
BucketAccessの生成元となるリソースです。
Kubernetesクラスタでユニークなリソースになります(cluster-scoped)。
以下にリソースの定義を示します。
apiVersion: cosi.io/v1alpha1
kind: BucketAccessClass
metadata:
name:
provisioner: [1]
policyActionsConfigMap: [2]
name:
namespace:
parameters: [3]
- Provisioner名
- BuketAccessの
policyActionsConfigMapData
に設定されるポリシーアクションを設定したConfigMapの名前とNamespace名 - パラメータ。Provisionerへ渡す設定値
以上、COSIのAPIリソースを紹介しました。
Podからのマウント方法
次に、PodからオブジェクトストレージのBuketをマウントする場合のManifestについて紹介します。
まだまだ仕様が柔らかいCOSIの中でも、さらに柔らかい状態のものになります。
以下に、PodのサンプルのManifestを示します。
kind: Pod
metadata:
name: my-app-pod
namespace: dev-ns
spec:
serviceAccountName: hoge
containers:
- name: my-app
image: ...
volumeMounts:
- mountPath: /cosi
name: cosi-vol
volumes:
- name: cosi-vol
csi: [3]
driver: cosi.sigs.k8s.io
volumeAttributes:
bucketAccessRequestName: <my-bar-name>
マウントの指定(volumeMounts
)は、CSIのPVCと同様の指定になります。
volumes
に関しては、CSIのinline ephemeral volumeを利用し指定しています。
感想
遂にオブジェクトストレージのインターフェースであるCOSIのKEPがまとまり、Kubernetes v1.21でAlphaとして登場してくるようです。
オブジェクトストレージは、ストレージ業界からみても業界標準化が進んでいない領域のため、各クラウドベンダやストレージベンダで似ているけど若干違うといった所があります。
そのためか、COSIでもBucketAccess周りで何とかしようと詰め込んでいる感じが、ひしひしと伝わってきます。
BucketAccess周り以外は、従来のCSIのPVC/PV/StorageClassと似た設計となっており、PVC/PV/StorageClassを使っているKubernetesのユーザにとっては分かりやすいのではないかと思います。
また、特にPodへマウントさせる時の仕様は暫定的な印象のため、Kubernetes v1.21までには変更が入るだろうと予測しています。
まだまだ、COSIは大幅に仕様が変更するかもしれませんが、スタートは切られましたので、これからどのように仕様が成長していくのか楽しみです。