diff --git a/apis/v1alpha1/common.go b/apis/v1alpha1/common.go
index 79489da4..6edccc05 100644
--- a/apis/v1alpha1/common.go
+++ b/apis/v1alpha1/common.go
@@ -573,7 +573,7 @@ func (in *TLSSpec) GetSecretName() string {
// ObjectStorageProviderSpec defines the object storage provider for the cluster. The data will be stored in the storage.
type ObjectStorageProviderSpec struct {
- // S3 is the S3 storage configuration.
+ // S3 is the AWS S3 storage configuration.
// +optional
S3 *S3Storage `json:"s3,omitempty"`
@@ -581,10 +581,14 @@ type ObjectStorageProviderSpec struct {
// +optional
OSS *OSSStorage `json:"oss,omitempty"`
- // GCS is the Google GCS storage configuration.
+ // GCS is the Google cloud storage configuration.
// +optional
GCS *GCSStorage `json:"gcs,omitempty"`
+ // AZBlob is the Azure Blob storage configuration.
+ // +optional
+ AZBlob *AZBlobStorage `json:"azblob,omitempty"`
+
// Cache is the cache storage configuration for object storage.
// +optional
Cache *CacheStorage `json:"cache,omitempty"`
@@ -596,6 +600,7 @@ type ObjectStorageProviderAccessor interface {
GetS3Storage() *S3Storage
GetGCSStorage() *GCSStorage
GetOSSStorage() *OSSStorage
+ GetAZBlobStorage() *AZBlobStorage
GetCacheFileStorage() *FileStorage
}
@@ -629,6 +634,13 @@ func (in *ObjectStorageProviderSpec) GetOSSStorage() *OSSStorage {
return nil
}
+func (in *ObjectStorageProviderSpec) GetAZBlobStorage() *AZBlobStorage {
+ if in != nil {
+ return in.AZBlob
+ }
+ return nil
+}
+
func (in *ObjectStorageProviderSpec) getSetObjectStorageCount() int {
count := 0
if in.S3 != nil {
@@ -640,6 +652,9 @@ func (in *ObjectStorageProviderSpec) getSetObjectStorageCount() int {
if in.GCS != nil {
count++
}
+ if in.AZBlob != nil {
+ count++
+ }
return count
}
@@ -782,6 +797,41 @@ func (in *GCSStorage) GetRoot() string {
return ""
}
+// AZBlobStorage defines the Azure Blob storage specification.
+type AZBlobStorage struct {
+ // The data will be stored in the container.
+ // +required
+ Container string `json:"container"`
+
+ // The secret of storing the credentials of account name and account key.
+ // The secret should contain keys named `account-name` and `account-key`.
+ // The secret must be the same namespace with the GreptimeDBCluster resource.
+ // +optional
+ SecretName string `json:"secretName,omitempty"`
+
+ // The Blob directory path.
+ // +required
+ Root string `json:"root"`
+
+ // The Blob Storage endpoint.
+ // +optional
+ Endpoint string `json:"endpoint,omitempty"`
+}
+
+func (in *AZBlobStorage) GetSecretName() string {
+ if in != nil {
+ return in.SecretName
+ }
+ return ""
+}
+
+func (in *AZBlobStorage) GetRoot() string {
+ if in != nil {
+ return in.Root
+ }
+ return ""
+}
+
// PrometheusMonitorSpec defines the PodMonitor configuration.
type PrometheusMonitorSpec struct {
// Enabled indicates whether the PodMonitor is enabled.
diff --git a/apis/v1alpha1/constants.go b/apis/v1alpha1/constants.go
index 7998c973..74945ecc 100644
--- a/apis/v1alpha1/constants.go
+++ b/apis/v1alpha1/constants.go
@@ -93,4 +93,10 @@ const (
// ServiceAccountKey is the key for the service account in the secret.
ServiceAccountKey = "service-account-key"
+
+ // AccountName is the name for the account in the secret.
+ AccountName = "account-name"
+
+ // AccountKey is the key for the account in the secret.
+ AccountKey = "account-key"
)
diff --git a/apis/v1alpha1/validate.go b/apis/v1alpha1/validate.go
index c3231a55..5aaf9e76 100644
--- a/apis/v1alpha1/validate.go
+++ b/apis/v1alpha1/validate.go
@@ -98,6 +98,12 @@ func (in *GreptimeDBCluster) Check(ctx context.Context, client client.Client) er
}
}
+ if secretName := in.GetObjectStorageProvider().GetAZBlobStorage().GetSecretName(); secretName != "" {
+ if err := checkAZBlobCredentialsSecret(ctx, client, in.GetNamespace(), secretName); err != nil {
+ return err
+ }
+ }
+
return nil
}
@@ -195,6 +201,12 @@ func (in *GreptimeDBStandalone) Check(ctx context.Context, client client.Client)
}
}
+ if secretName := in.GetObjectStorageProvider().GetAZBlobStorage().GetSecretName(); secretName != "" {
+ if err := checkAZBlobCredentialsSecret(ctx, client, in.GetNamespace(), secretName); err != nil {
+ return err
+ }
+ }
+
return nil
}
@@ -282,6 +294,10 @@ func checkS3CredentialsSecret(ctx context.Context, client client.Client, namespa
return checkSecretData(ctx, client, namespace, name, []string{AccessKeyIDSecretKey, SecretAccessKeySecretKey})
}
+func checkAZBlobCredentialsSecret(ctx context.Context, client client.Client, namespace, name string) error {
+ return checkSecretData(ctx, client, namespace, name, []string{AccountName, AccountKey})
+}
+
// checkPodMonitorExists checks if the PodMonitor CRD exists.
func checkPodMonitorExists(ctx context.Context, client client.Client) error {
const (
diff --git a/apis/v1alpha1/zz_generated.deepcopy.go b/apis/v1alpha1/zz_generated.deepcopy.go
index a374937c..f61e5608 100644
--- a/apis/v1alpha1/zz_generated.deepcopy.go
+++ b/apis/v1alpha1/zz_generated.deepcopy.go
@@ -24,6 +24,21 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AZBlobStorage) DeepCopyInto(out *AZBlobStorage) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AZBlobStorage.
+func (in *AZBlobStorage) DeepCopy() *AZBlobStorage {
+ if in == nil {
+ return nil
+ }
+ out := new(AZBlobStorage)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CacheStorage) DeepCopyInto(out *CacheStorage) {
*out = *in
@@ -880,6 +895,11 @@ func (in *ObjectStorageProviderSpec) DeepCopyInto(out *ObjectStorageProviderSpec
*out = new(GCSStorage)
**out = **in
}
+ if in.AZBlob != nil {
+ in, out := &in.AZBlob, &out.AZBlob
+ *out = new(AZBlobStorage)
+ **out = **in
+ }
if in.Cache != nil {
in, out := &in.Cache, &out.Cache
*out = new(CacheStorage)
diff --git a/config/crd/resources/greptime.io_greptimedbclusters.yaml b/config/crd/resources/greptime.io_greptimedbclusters.yaml
index 4c0bc286..06a804f4 100644
--- a/config/crd/resources/greptime.io_greptimedbclusters.yaml
+++ b/config/crd/resources/greptime.io_greptimedbclusters.yaml
@@ -18318,6 +18318,20 @@ spec:
type: integer
objectStorage:
properties:
+ azblob:
+ properties:
+ container:
+ type: string
+ endpoint:
+ type: string
+ root:
+ type: string
+ secretName:
+ type: string
+ required:
+ - container
+ - root
+ type: object
cache:
properties:
cacheCapacity:
@@ -18528,6 +18542,20 @@ spec:
type: integer
objectStorage:
properties:
+ azblob:
+ properties:
+ container:
+ type: string
+ endpoint:
+ type: string
+ root:
+ type: string
+ secretName:
+ type: string
+ required:
+ - container
+ - root
+ type: object
cache:
properties:
cacheCapacity:
diff --git a/config/crd/resources/greptime.io_greptimedbstandalones.yaml b/config/crd/resources/greptime.io_greptimedbstandalones.yaml
index 39fdc736..b88cd30a 100644
--- a/config/crd/resources/greptime.io_greptimedbstandalones.yaml
+++ b/config/crd/resources/greptime.io_greptimedbstandalones.yaml
@@ -3082,6 +3082,20 @@ spec:
type: integer
objectStorage:
properties:
+ azblob:
+ properties:
+ container:
+ type: string
+ endpoint:
+ type: string
+ root:
+ type: string
+ secretName:
+ type: string
+ required:
+ - container
+ - root
+ type: object
cache:
properties:
cacheCapacity:
diff --git a/docs/api-references/docs.md b/docs/api-references/docs.md
index 8fdb0d8e..821e1887 100644
--- a/docs/api-references/docs.md
+++ b/docs/api-references/docs.md
@@ -15,6 +15,25 @@
+#### AZBlobStorage
+
+
+
+AZBlobStorage defines the Azure Blob storage specification.
+
+
+
+_Appears in:_
+- [ObjectStorageProviderSpec](#objectstorageproviderspec)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `container` _string_ | The data will be stored in the container. | | |
+| `secretName` _string_ | The secret of storing the credentials of account name and account key.
The secret should contain keys named `account-name` and `account-key`.
The secret must be the same namespace with the GreptimeDBCluster resource. | | |
+| `root` _string_ | The Blob directory path. | | |
+| `endpoint` _string_ | The Blob Storage endpoint. | | |
+
+
#### CacheStorage
@@ -691,9 +710,10 @@ _Appears in:_
| Field | Description | Default | Validation |
| --- | --- | --- | --- |
-| `s3` _[S3Storage](#s3storage)_ | S3 is the S3 storage configuration. | | |
+| `s3` _[S3Storage](#s3storage)_ | S3 is the AWS S3 storage configuration. | | |
| `oss` _[OSSStorage](#ossstorage)_ | OSS is the Aliyun OSS storage configuration. | | |
-| `gcs` _[GCSStorage](#gcsstorage)_ | GCS is the Google GCS storage configuration. | | |
+| `gcs` _[GCSStorage](#gcsstorage)_ | GCS is the Google cloud storage configuration. | | |
+| `azblob` _[AZBlobStorage](#azblobstorage)_ | AZBlob is the Azure Blob storage configuration. | | |
| `cache` _[CacheStorage](#cachestorage)_ | Cache is the cache storage configuration for object storage. | | |
diff --git a/examples/README.md b/examples/README.md
index ecf21848..90c95a23 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -8,6 +8,7 @@ The following examples suppose that you have installed the etcd cluster in the `
- [S3](./cluster/s3/cluster.yaml): Create a GreptimeDB cluster with S3 storage.
- [GCS](./cluster/gcs/cluster.yaml): Create a GreptimeDB cluster with Google GCS storage.
- [OSS](./cluster/oss/cluster.yaml): Create a GreptimeDB cluster with Aliyun OSS storage.
+- [AZBlob](./cluster/azblob/cluster.yaml): Create a GreptimeDB cluster with Azure Blob storage.
- [Flownode](./cluster/flownode/cluster.yaml): Create a GreptimeDB cluster with `flownode` enabled. By adding the `flownode` configuration, you can use [continuous aggregation](https://docs.greptime.com/user-guide/continuous-aggregation/overview) in the GreptimeDB cluster.
- [TLS Service](./cluster/tls-service/cluster.yaml): Create a GreptimeDB cluster with TLS service.
- [Prometheus Monitoring](./cluster/prometheus-monitor/cluster.yaml): Create a GreptimeDB cluster with Prometheus monitoring. Please ensure you have already installed prometheus-operator and created a Prometheus instance with the label `release=prometheus`.
@@ -24,3 +25,4 @@ The following examples suppose that you have installed the etcd cluster in the `
- [S3](./standalone/s3/standalone.yaml): Create a GreptimeDB standalone with S3 storage.
- [GCS](./standalone/gcs/standalone.yaml): Create a GreptimeDB standalone with Google GCS storage.
- [OSS](./standalone/oss/standalone.yaml): Create a GreptimeDB standalone with Aliyun OSS storage.
+- [AZBlob](./standalone/azblob/standalone.yaml): Create a GreptimeDB standalone with Azure Blob storage.
diff --git a/examples/cluster/azblob/azblob-credentials.yaml b/examples/cluster/azblob/azblob-credentials.yaml
new file mode 100644
index 00000000..00b7d8ea
--- /dev/null
+++ b/examples/cluster/azblob/azblob-credentials.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: Secret
+type: Opaque
+metadata:
+ name: azblob-credentials
+stringData:
+ account-name: "your-blob-account-name"
+ account-key: "your-blob-account-key"
diff --git a/examples/cluster/azblob/cluster.yaml b/examples/cluster/azblob/cluster.yaml
new file mode 100644
index 00000000..8bf92f25
--- /dev/null
+++ b/examples/cluster/azblob/cluster.yaml
@@ -0,0 +1,22 @@
+apiVersion: greptime.io/v1alpha1
+kind: GreptimeDBCluster
+metadata:
+ name: cluster-with-blob
+spec:
+ base:
+ main:
+ image: greptime/greptimedb:latest
+ frontend:
+ replicas: 1
+ meta:
+ replicas: 1
+ etcdEndpoints:
+ - "etcd.etcd-cluster.svc.cluster.local:2379"
+ datanode:
+ replicas: 1
+ objectStorage:
+ azblob:
+ container: "greptimedb"
+ secretName: "azblob-credentials"
+ endpoint: "https://.blob.core.windows.net"
+ root: "cluster-with-blob-data"
diff --git a/examples/cluster/oss/oss-credentials.yaml b/examples/cluster/oss/oss-credentials.yaml
index fa3b893a..e529480c 100644
--- a/examples/cluster/oss/oss-credentials.yaml
+++ b/examples/cluster/oss/oss-credentials.yaml
@@ -3,6 +3,6 @@ kind: Secret
type: Opaque
metadata:
name: oss-credentials
-data:
+stringData:
access-key-id: "your-access-key-id"
secret-access-key: "your-secret-access-key"
diff --git a/examples/cluster/s3/s3-credentials.yaml b/examples/cluster/s3/s3-credentials.yaml
index 06af313b..eafb9195 100644
--- a/examples/cluster/s3/s3-credentials.yaml
+++ b/examples/cluster/s3/s3-credentials.yaml
@@ -3,6 +3,6 @@ kind: Secret
type: Opaque
metadata:
name: s3-credentials
-data:
- access-key-id: "your-access-key-id-in-base64"
- secret-access-key: "your-secret-access-key-in-base64"
+stringData:
+ access-key-id: "your-access-key-id"
+ secret-access-key: "your-secret-access-key"
diff --git a/examples/standalone/azblob/azblob-credentials.yaml b/examples/standalone/azblob/azblob-credentials.yaml
new file mode 100644
index 00000000..00b7d8ea
--- /dev/null
+++ b/examples/standalone/azblob/azblob-credentials.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: Secret
+type: Opaque
+metadata:
+ name: azblob-credentials
+stringData:
+ account-name: "your-blob-account-name"
+ account-key: "your-blob-account-key"
diff --git a/examples/standalone/azblob/standalone.yaml b/examples/standalone/azblob/standalone.yaml
new file mode 100644
index 00000000..554c84ed
--- /dev/null
+++ b/examples/standalone/azblob/standalone.yaml
@@ -0,0 +1,14 @@
+apiVersion: greptime.io/v1alpha1
+kind: GreptimeDBStandalone
+metadata:
+ name: standalone-with-blob
+spec:
+ base:
+ main:
+ image: greptime/greptimedb:latest
+ objectStorage:
+ azblob:
+ container: "greptimedb"
+ secretName: "azblob-credentials"
+ endpoint: "https://.blob.core.windows.net"
+ root: "standalone-with-blob"
diff --git a/examples/standalone/oss/oss-credentials.yaml b/examples/standalone/oss/oss-credentials.yaml
index 9f8fc49d..c0fdb180 100644
--- a/examples/standalone/oss/oss-credentials.yaml
+++ b/examples/standalone/oss/oss-credentials.yaml
@@ -3,6 +3,6 @@ kind: Secret
type: Opaque
metadata:
name: oss-credentials
-data:
+stringData:
access-key-id: "your-access-key-id-in-base64"
secret-access-key: "your-secret-access-key-in-base64"
diff --git a/examples/standalone/s3/s3-credentials.yaml b/examples/standalone/s3/s3-credentials.yaml
index 06af313b..eafb9195 100644
--- a/examples/standalone/s3/s3-credentials.yaml
+++ b/examples/standalone/s3/s3-credentials.yaml
@@ -3,6 +3,6 @@ kind: Secret
type: Opaque
metadata:
name: s3-credentials
-data:
- access-key-id: "your-access-key-id-in-base64"
- secret-access-key: "your-secret-access-key-in-base64"
+stringData:
+ access-key-id: "your-access-key-id"
+ secret-access-key: "your-secret-access-key"
diff --git a/manifests/bundle.yaml b/manifests/bundle.yaml
index a1a8742a..189b64e6 100644
--- a/manifests/bundle.yaml
+++ b/manifests/bundle.yaml
@@ -18324,6 +18324,20 @@ spec:
type: integer
objectStorage:
properties:
+ azblob:
+ properties:
+ container:
+ type: string
+ endpoint:
+ type: string
+ root:
+ type: string
+ secretName:
+ type: string
+ required:
+ - container
+ - root
+ type: object
cache:
properties:
cacheCapacity:
@@ -18534,6 +18548,20 @@ spec:
type: integer
objectStorage:
properties:
+ azblob:
+ properties:
+ container:
+ type: string
+ endpoint:
+ type: string
+ root:
+ type: string
+ secretName:
+ type: string
+ required:
+ - container
+ - root
+ type: object
cache:
properties:
cacheCapacity:
@@ -21843,6 +21871,20 @@ spec:
type: integer
objectStorage:
properties:
+ azblob:
+ properties:
+ container:
+ type: string
+ endpoint:
+ type: string
+ root:
+ type: string
+ secretName:
+ type: string
+ required:
+ - container
+ - root
+ type: object
cache:
properties:
cacheCapacity:
diff --git a/manifests/crds.yaml b/manifests/crds.yaml
index 76a6573a..ca24ee65 100644
--- a/manifests/crds.yaml
+++ b/manifests/crds.yaml
@@ -18317,6 +18317,20 @@ spec:
type: integer
objectStorage:
properties:
+ azblob:
+ properties:
+ container:
+ type: string
+ endpoint:
+ type: string
+ root:
+ type: string
+ secretName:
+ type: string
+ required:
+ - container
+ - root
+ type: object
cache:
properties:
cacheCapacity:
@@ -18527,6 +18541,20 @@ spec:
type: integer
objectStorage:
properties:
+ azblob:
+ properties:
+ container:
+ type: string
+ endpoint:
+ type: string
+ root:
+ type: string
+ secretName:
+ type: string
+ required:
+ - container
+ - root
+ type: object
cache:
properties:
cacheCapacity:
@@ -21836,6 +21864,20 @@ spec:
type: integer
objectStorage:
properties:
+ azblob:
+ properties:
+ container:
+ type: string
+ endpoint:
+ type: string
+ root:
+ type: string
+ secretName:
+ type: string
+ required:
+ - container
+ - root
+ type: object
cache:
properties:
cacheCapacity:
diff --git a/pkg/dbconfig/common.go b/pkg/dbconfig/common.go
index 60952f63..d373d59e 100644
--- a/pkg/dbconfig/common.go
+++ b/pkg/dbconfig/common.go
@@ -40,6 +40,9 @@ type StorageConfig struct {
StorageEndpoint *string `tomlmapping:"storage.endpoint"`
StorageScope *string `tomlmapping:"storage.scope"`
StorageCredential *string `tomlmapping:"storage.credential"`
+ Container *string `tomlmapping:"storage.container"`
+ AccountName *string `tomlmapping:"storage.account_name"`
+ AccountKey *string `tomlmapping:"storage.account_key"`
}
// ConfigureObjectStorage configures the storage config by the given object storage provider accessor.
@@ -56,6 +59,10 @@ func (c *StorageConfig) ConfigureObjectStorage(namespace string, accessor v1alph
if err := c.configureGCS(namespace, gcs); err != nil {
return err
}
+ } else if blob := accessor.GetAZBlobStorage(); blob != nil {
+ if err := c.configureAZBlob(namespace, blob); err != nil {
+ return err
+ }
}
return nil
@@ -133,6 +140,28 @@ func (c *StorageConfig) configureGCS(namespace string, gcs *v1alpha1.GCSStorage)
return nil
}
+func (c *StorageConfig) configureAZBlob(namespace string, azblob *v1alpha1.AZBlobStorage) error {
+ if azblob == nil {
+ return nil
+ }
+
+ c.StorageType = pointer.String("Azblob")
+ c.Container = pointer.String(azblob.Container)
+ c.StorageRoot = pointer.String(azblob.Root)
+ c.StorageEndpoint = pointer.String(azblob.Endpoint)
+
+ if azblob.SecretName != "" {
+ data, err := k8sutil.GetSecretsData(namespace, azblob.SecretName, []string{v1alpha1.AccountName, v1alpha1.AccountKey})
+ if err != nil {
+ return err
+ }
+ c.AccountName = pointer.String(string(data[0]))
+ c.AccountKey = pointer.String(string(data[1]))
+ }
+
+ return nil
+}
+
// WALConfig is the configuration for the WAL.
type WALConfig struct {
// The wal file directory.