Deploy Transfer on Kubernetes
Transfer runs separately from the Master and Worker workloads. The Curvine Helm
chart creates it when transfer.enabled=true, so a chart-managed deployment is
the normal path. The dedicated manifests below are an alternative for
installations that do not use the chart or that need to customize the workload.
The SQLite manifest is intentionally a single replica with a dedicated RWO
volume.
Helm Chart
transfer:
enabled: true
storeUrl: "mysql://transfer_user:password@mysql.curvine.svc:3306/curvine_transfer"
replicas: 1helm upgrade --install curvine curvine/curvine \
--version 0.5.2-alpha \
-n curvine \
-f transfer-values.yaml \
--wait --timeout 10mThe chart creates the curvine-transfer Deployment and Service, writes its
Service FQDN to [transfer].hostname, and derives the client endpoint from that
hostname and transfer.rpcPort. Leave endpoints unset. An empty
transfer.storeUrl uses the single-Pod SQLite default with a chart-managed PVC.
See Kubernetes Deployment
for the full value list.
Prerequisites
- An existing Curvine Master and Worker deployment in the namespace.
- A ConfigMap containing the existing
curvine-cluster.tomlwith the key name shown below. Replacecurvine-cluster-configif your deployment uses a different name. - A default
StorageClassthat supportsReadWriteOncevolumes, or astorageClassNameadded to the PVC. - An image version that matches the Master and Worker version.
SQLite Single-Replica Manifest
Save this as transfer-sqlite.yaml. Replace the image and namespace to match
your cluster.
apiVersion: v1
kind: ConfigMap
metadata:
name: curvine-transfer-overlay
data:
transfer.toml: |
[transfer]
enabled = true
store_url = "sqlite:///opt/curvine/data/transfer/transfer.db"
hostname = "0.0.0.0"
rpc_port = 9010
web_port = 9011
endpoints = ["curvine-transfer.curvine.svc.cluster.local:9010"]
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: curvine-transfer-data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: curvine-transfer
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: curvine-transfer
template:
metadata:
labels:
app: curvine-transfer
spec:
initContainers:
- name: prepare-config
image: ghcr.io/curvineio/curvine:<version>
command: ["/bin/sh", "-ec"]
args:
- |
cp /base/curvine-cluster.toml /work/curvine-cluster.toml
printf '\n' >> /work/curvine-cluster.toml
cat /overlay/transfer.toml >> /work/curvine-cluster.toml
volumeMounts:
- { name: base-config, mountPath: /base, readOnly: true }
- { name: transfer-overlay, mountPath: /overlay, readOnly: true }
- { name: config-work, mountPath: /work }
containers:
- name: transfer
image: ghcr.io/curvineio/curvine:<version>
command: ["/entrypoint.sh"]
args: ["transfer", "start"]
env:
- { name: CURVINE_HOME, value: /app/curvine }
- { name: CURVINE_CONF_FILE, value: /app/curvine/conf/curvine-cluster.toml }
- { name: ORPC_BIND_HOSTNAME, value: 0.0.0.0 }
ports:
- { name: rpc, containerPort: 9010 }
- { name: web, containerPort: 9011 }
startupProbe:
httpGet: { path: /readyz, port: web }
periodSeconds: 5
failureThreshold: 18
readinessProbe:
httpGet: { path: /readyz, port: web }
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet: { path: /healthz, port: web }
periodSeconds: 10
failureThreshold: 3
resources:
requests: { cpu: "1", memory: 1Gi }
limits: { cpu: "2", memory: 2Gi }
volumeMounts:
- name: config-work
mountPath: /app/curvine/conf/curvine-cluster.toml
subPath: curvine-cluster.toml
readOnly: true
- { name: transfer-data, mountPath: /opt/curvine/data/transfer }
volumes:
- name: base-config
configMap: { name: curvine-cluster-config }
- name: transfer-overlay
configMap: { name: curvine-transfer-overlay }
- name: config-work
emptyDir: {}
- name: transfer-data
persistentVolumeClaim: { claimName: curvine-transfer-data }
---
apiVersion: v1
kind: Service
metadata:
name: curvine-transfer
spec:
selector:
app: curvine-transfer
ports:
- { name: rpc, port: 9010, targetPort: rpc }
- { name: web, port: 9011, targetPort: web }Mount only the generated curvine-cluster.toml file into the main container.
Mounting an emptyDir over the whole /app/curvine/conf directory hides the
image's curvine-env.sh and breaks bundled client scripts.
Apply and verify the service:
kubectl -n curvine apply -f transfer-sqlite.yaml
kubectl -n curvine rollout status deployment/curvine-transfer
kubectl -n curvine get pod,svc,pvc -l app=curvine-transfer
kubectl -n curvine exec deployment/curvine-transfer -- curl --fail http://127.0.0.1:9011/readyzConfigure Clients
For clients inside the Kubernetes cluster, use the Service DNS name. With an
empty endpoints list, the client derives the endpoint from hostname and
rpc_port:
[transfer]
enabled = true
hostname = "curvine-transfer.curvine.svc.cluster.local"
rpc_port = 9010For a client outside the cluster, publish an address that it can reach. A
.svc.cluster.local address is only valid from the cluster network.
MySQL Multi-Replica Deployment
To run more than one Transfer replica, use a shared MySQL store_url supplied
through a Secret, remove the SQLite PVC, and expose all replicas through the
same ClusterIP Service. All replicas must use the same database and compatible
image version. Do not scale the SQLite Deployment above one replica.