Skip to main content

Kubernetes Deployment

Chart: curvine/curvine, version 0.3.2-alpha.

Prerequisites​

  • Kubernetes 1.20+
  • Helm 3.x
  • A default StorageClass for master/worker PVCs

Architecture​

Helm release curvine is deployed in namespace curvine:

ResourceDescription
StatefulSet curvine-masterMetadata and Raft journal
StatefulSet curvine-workerData nodes
Service curvine-masterHeadless, RPC 8995
Service curvine-workerHeadless, RPC 8997
Deployment curvine-transferLoad / Export service, created only when enabled
Service curvine-transferInternal Transfer RPC and web endpoint, created only when enabled

openKruise.enabled defaults to false. StatefulSets use apps/v1.

Transfer Service​

Transfer is an optional service for independent Load and Export scheduling. It is not created by the current Helm chart and does not require changing the running Master or Worker configuration. Deploy it separately after the cluster is healthy; see Deploy Transfer on Kubernetes.

Deployment​

Add repository​

helm repo add curvine https://curvineio.github.io/helm-charts
helm repo update

Install​

helm upgrade --install curvine curvine/curvine \
--version 0.3.2-alpha \
-n curvine \
--create-namespace \
--wait --timeout 10m

Enable Transfer​

Use a Curvine image release that contains the Transfer binary. Do not use an older chart image tag just because the chart itself supports the values below. For high availability or more than one Transfer replica, MySQL must be reachable before the Transfer Pod starts:

transfer-values.yaml
transfer:
enabled: true
storeUrl: "mysql://transfer_user:password@mysql.curvine.svc:3306/curvine_transfer"
replicas: 1
helm upgrade --install curvine curvine/curvine \
-n curvine \
-f transfer-values.yaml \
--wait --timeout 10m

The chart creates curvine-transfer as an internal ClusterIP Service and writes its Service FQDN to [transfer].hostname. Curvine infers the RPC endpoint from that hostname and transfer.rpcPort; do not configure endpoints in normal Helm deployments.

An empty transfer.storeUrl uses the single-Pod SQLite default. The chart creates a ReadWriteOnce PVC for its data directory without setting storageClassName, so Kubernetes uses the default StorageClass. The PVC persists across Pod replacement. MySQL is mandatory when transfer.replicas > 1 and recommended for high availability.

For SQLite, the Transfer Deployment uses Recreate so the old Pod detaches its ReadWriteOnce volume before a replacement starts. Helm retains the SQLite PVC on uninstall; delete it explicitly only when discarding Transfer metadata.

The generated ConfigMap is used by Master, Worker, and Transfer. External CLI hosts must also use a cluster config with [transfer] enabled = true; the CLI commands remain cv load, cv export, cv load-status, and cv cancel-load.

Verify​

kubectl get pods,svc,pvc -n curvine

Web UI:

kubectl port-forward -n curvine svc/curvine-master 9000:9000

Master addresses​

Single replica:

curvine-master.curvine.svc.cluster.local:8995

Three replicas:

curvine-master-0.curvine-master.curvine.svc.cluster.local:8995,curvine-master-1.curvine-master.curvine.svc.cluster.local:8995,curvine-master-2.curvine-master.curvine.svc.cluster.local:8995

Upgrade​

helm upgrade curvine curvine/curvine \
--version 0.3.2-alpha \
-n curvine \
--reuse-values \
--set worker.replicas=3

master.replicas cannot be changed after install.

Uninstall​

helm uninstall curvine -n curvine
kubectl delete pvc -n curvine -l app.kubernetes.io/instance=curvine
kubectl delete namespace curvine

Troubleshooting​

SymptomCommandCause
Pod Pendingkubectl describe pod -n curvine <name>Insufficient resources; no StorageClass
Slow master startupkubectl logs curvine-master-0 -n curvineRaft replay in progress
PVC Pendingkubectl get scNo available StorageClass

Configuration Reference​

Chart version 0.3.2-alpha. Defaults below match helm show values curvine/curvine --version 0.3.2-alpha.

Global​

ParameterDefaultDescription
global.clusterDomaincluster.localKubernetes cluster domain

Cluster​

ParameterDefaultDescription
cluster.idcurvineCluster ID
cluster.formatMasterfalseFormat master data on startup
cluster.formatWorkerfalseFormat worker data on startup
cluster.formatJournalfalseFormat journal data on startup

Image​

ParameterDefaultDescription
image.repositoryghcr.io/curvineio/curvineImage repository
image.tag""Empty uses v{Chart.AppVersion}
image.pullPolicyIfNotPresentImage pull policy
image.pullSecrets[]Image pull secrets

OpenKruise​

openKruise.enabled defaults to false. Master and worker use standard apps/v1 StatefulSets.

Set openKruise.enabled=true to install the kruise subchart and switch master/worker to Advanced StatefulSet (apps.kruise.io/v1beta1).

ParameterDefaultDescription
openKruise.enabledfalseEnable Advanced StatefulSet
openKruise.podUpdatePolicyInPlaceOnlyInPlaceOnly | InPlaceIfPossible | ReCreate
openKruise.persistentPodState.autoGeneratetrueAuto-generate PersistentPodState
openKruise.persistentPodState.preferredPersistentTopologykubernetes.io/hostnamePreferred topology key
openKruise.persistentPodState.requiredPersistentTopology""Required topology key (optional)
kruise.installation.namespacekruise-systemKruise subchart namespace (when enabled)
kruise.installation.createNamespacetrueCreate Kruise namespace

Master​

ParameterDefaultDescription
master.replicas1Must be odd (1, 3, 5, â€Ļ)
master.rpcPort8995RPC port
master.journalPort8996Journal/Raft port
master.webPort9000Web UI port
master.web1Port9001Additional web port
master.startupProbe.enabledtrueStartup probe
master.startupProbe.failureThreshold90Allow long Raft replay
master.storage.meta.enabledtrueEnable metadata PVC
master.storage.meta.storageClass""Empty uses default StorageClass
master.storage.meta.size5GiMetadata PVC size
master.storage.meta.hostPath""hostPath when no StorageClass
master.storage.meta.mountPath/opt/curvine/data/metaMount path
master.storage.journal.enabledtrueEnable journal PVC
master.storage.journal.storageClass""Empty uses default StorageClass
master.storage.journal.size10GiJournal PVC size
master.storage.journal.hostPath""hostPath when no StorageClass
master.storage.journal.mountPath/opt/curvine/data/journalMount path
master.resources.requests.cpu500mCPU request
master.resources.requests.memory1GiMemory request
master.resources.limits.cpu1000mCPU limit
master.resources.limits.memory2GiMemory limit
master.antiAffinity.enabledfalsePod anti-affinity
master.antiAffinity.typerequiredrequired or preferred
master.persistentTopology.enabledtruePersistentPodState topology
master.persistentTopology.keykubernetes.io/hostnameTopology key
master.nodeSelector{}Node selector
master.tolerations[]Tolerations
master.affinity{}Affinity rules

Worker​

ParameterDefaultDescription
worker.replicas1Worker replica count
worker.rpcPort8997RPC port
worker.webPort9001Web UI port
worker.s3Gateway.enabledfalseEnable S3 gateway
worker.s3Gateway.listen0.0.0.0:9900S3 gateway listen address
worker.s3Gateway.enableDistributedAuthtrueDistributed auth for S3
worker.s3Gateway.service.typeClusterIPS3 service type
worker.hostNetworkfalseUse host network
worker.dnsPolicyClusterFirstDNS policy
worker.usePodIPAsHostnamefalseUse Pod IP as worker hostname
worker.privilegedtruePrivileged mode (FUSE)
worker.storage.dataDirs[0].namedata1Data directory name
worker.storage.dataDirs[0].typeSSDStorage type
worker.storage.dataDirs[0].enabledtrueEnable data directory
worker.storage.dataDirs[0].size20GiPVC size
worker.storage.dataDirs[0].storageClass""Empty uses default StorageClass
worker.storage.dataDirs[0].hostPath""hostPath when no StorageClass
worker.storage.dataDirs[0].mountPath/data/data1Mount path
worker.resources.requests.cpu500mCPU request
worker.resources.requests.memory1GiMemory request
worker.resources.limits.cpu1000mCPU limit
worker.resources.limits.memory2GiMemory limit
worker.antiAffinity.enabledtruePod anti-affinity
worker.antiAffinity.typepreferredrequired or preferred
worker.nodeSelector{}Node selector
worker.tolerations[]Tolerations
worker.affinity{}Affinity rules

Transfer​

ParameterDefaultDescription
transfer.enabledfalseCreates no Transfer resources until enabled; disabled mode preserves the legacy Master Load API.
transfer.storeUrl""Empty infers local SQLite backed by a chart-managed PVC. Use mysql://... for high availability or multiple replicas.
transfer.storage.size1GiRequested capacity for the SQLite PVC. Kubernetes selects the default StorageClass.
transfer.replicas1Transfer Pod replicas. Values greater than one require a MySQL storeUrl.
transfer.rpcPort9010Transfer RPC Service and container port.
transfer.webPort9011Transfer /healthz, /readyz, and /metrics port.
transfer.resources.requests.cpu500mCPU request.
transfer.resources.requests.memory1GiMemory request.
transfer.resources.limits.cpu1000mCPU limit.
transfer.resources.limits.memory2GiMemory limit.

Service​

ParameterDefaultDescription
service.master.typeClusterIPHeadless (ClusterIP: None)
service.worker.typeClusterIPHeadless (ClusterIP: None)
service.masterExternal.enabledfalseExternal master access
service.masterExternal.typeClusterIPExternal service type
service.masterExternal.loadBalancerIP""LoadBalancer IP

Service account and RBAC​

ParameterDefaultDescription
serviceAccount.createtrueCreate ServiceAccount
serviceAccount.name""Auto-generated when empty
rbac.createtrueCreate RBAC resources

Curvine config (config.*)​

ParameterDefaultDescription
config.master.metaDir/opt/curvine/data/metaMaster metadata directory
config.journal.enabletrueEnable journal
config.journal.journalDir/opt/curvine/data/journalJournal directory
config.journal.snapshotInterval6hSnapshot interval
config.journal.snapshotEntries1000000Snapshot entry threshold
config.client.blockSizeStr64MBClient block size
config.log.levelINFOLog level
config.log.logDir/opt/curvine/logsLog directory
config.log.consoletrueRoute logs to stdout

Config overrides (configOverrides.*)​

Override individual TOML sections without replacing the full config:

ParameterDefaultDescription
configOverrides.master{}Master section overrides
configOverrides.journal{}Journal section overrides
configOverrides.worker{}Worker section overrides
configOverrides.client{}Client section overrides
configOverrides.transfer{}Additional public [transfer] settings such as max_running_transfers, lease_timeout, and terminal_retention. Chart-managed enabled, hostname, ports, and store_url cannot be overridden here.
configOverrides.log{}Log section overrides

Storage modes​

ModeConfiguration
PVC (default)storageClass: "" uses cluster default StorageClass
Named StorageClassmaster.storage.*.storageClass, worker.storage.dataDirs[].storageClass
hostPathstorageClass: "" with hostPath set

Examples​

Lower resource requests:

helm upgrade curvine curvine/curvine -n curvine --reuse-values \
--set master.resources.requests.cpu=200m \
--set master.resources.requests.memory=512Mi \
--set worker.resources.requests.cpu=200m \
--set worker.resources.requests.memory=512Mi

Full parameter list:

helm show values curvine/curvine --version 0.3.2-alpha