ACKO Deployment Guide
Deploy Aerospike Community Edition clusters on Kubernetes using the ACKO operator.
1. Quick Deploy: 1-Node Dev Cluster in 3 Steps
Step 1: Check Prerequisites
Run these commands to verify your environment is ready:
# Verify kubectl is connected to a cluster
kubectl cluster-info
# Verify the ACKO operator is running
kubectl get pods -n aerospike-operator -l control-plane=controller-manager
# Verify the AerospikeCluster CRD is installed
kubectl api-resources | grep aerospikeclusters
# Create the target namespace (if it does not exist)
kubectl create namespace aerospike --dry-run=client -o yaml | kubectl apply -f -
If the operator is not running, install it first:
kubectl apply -f https://raw.githubusercontent.com/aerospike-ce-ecosystem/aerospike-ce-kubernetes-operator/main/config/deploy/operator.yaml
Step 2: Apply the Minimal CR
apiVersion: acko.io/v1alpha1
kind: AerospikeCluster
metadata:
name: aerospike-basic
namespace: aerospike
spec:
size: 1
image: aerospike:ce-8.1.1.1
aerospikeConfig:
namespaces:
- name: test
replication-factor: 1
storage-engine:
type: memory
data-size: 1073741824 # 1 GiB
logging:
- name: /var/log/aerospike/aerospike.log
context: any info
Save this as aerospike-basic.yaml and apply:
kubectl apply -f aerospike-basic.yaml
Step 3: Verify Deployment
# Wait for phase=Completed (typically 30-90 seconds)
kubectl wait --for=jsonpath='{.status.phase}'=Completed asc/aerospike-basic -n aerospike --timeout=120s
# Check cluster status (should show PHASE=Completed, HEALTH=1/1)
kubectl get asc aerospike-basic -n aerospike
# Check pod status (should show 1/1 Running)
kubectl get pods -n aerospike
# Verify Aerospike is responding
kubectl exec -n aerospike aerospike-basic-0-0 -c aerospike-server -- asinfo -v status
# Expected output: ok
2. CE Constraints (Webhook-Enforced)
These constraints are enforced by the ACKO validating webhook. Violating any of them causes the CR to be rejected at apply time.
- Cluster size:
spec.size must be between 1 and 8 (inclusive).
- Namespaces: Maximum 2 namespaces in
aerospikeConfig.namespaces.
- No XDR:
aerospikeConfig must not contain an xdr section (Enterprise-only).
- No TLS:
aerospikeConfig must not contain a tls section (Enterprise-only).
- No Enterprise images:
spec.image must not contain enterprise, ee-, or ent-.
- Mesh heartbeat only:
network.heartbeat.mode must be mesh.
- Byte values as integers: All size values in
aerospikeConfig (such as data-size, filesize) must be specified as integer byte counts, not human-readable strings.
- Replication factor: Must be between 1 and 4, and must not exceed
spec.size.
- No Enterprise namespace keys: The following keys are forbidden in namespace config:
compression, compression-level, durable-delete, fast-restart, index-type, sindex-type, rack-id, strong-consistency, tomb-raider-eligible-age, tomb-raider-period.
- No Enterprise security keys: Only
enable-security and default-password-file are allowed in aerospikeConfig.security. The keys tls, ldap, log, syslog are forbidden.
- Strengthened map/list shapes (April 2026):
aerospikeConfig.service and aerospikeConfig.network must be YAML maps; aerospikeConfig.logging must be a YAML list; each namespaces[] entry must be a map with a name key. MetricLabels values are TOML-escaped — control characters are rejected. Within one update, namespace rack-id may be added OR removed but not both (prevents data loss on rename).
- Operations spec invariants:
spec.operations[].kind must be WarmRestart or PodRestart; spec.operations[].id length 1–20 chars; the operations list cannot be modified while one operation is InProgress. spec.overrides only valid when spec.templateRef is set.
3. Deployment Scenarios
Choose the scenario that matches your needs. Each links to a ready-to-use YAML example.
Scenario 1: Minimal In-Memory (Dev/Test)
- File: ./examples/01-minimal.yaml
- Use when: Quick local dev, CI tests, learning ACKO
- Key features: 1 node, in-memory storage, no persistence, no ACL
Scenario 2: 3-Node with Persistent Volume (Staging/Production Baseline)
- File: ./examples/02-3node-pv.yaml
- Use when: You need data persistence across pod restarts
- Key features: 3 nodes, PVC-backed device storage, resource limits, cascadeDelete
Scenario 3: ACL (Access Control)
- File: ./examples/03-acl.yaml
- Use when: You need authentication and role-based access control
- Key features: security stanza, admin user (sys-admin + user-admin required), K8s Secrets for passwords
Scenario 4: Prometheus Monitoring
- File: ./examples/04-monitoring.yaml
- Use when: You need metrics, dashboards, and alerting
- Key features: Exporter sidecar, ServiceMonitor, PrometheusRule, metric labels
Scenario 5: Multi-Rack (Zone-Aware Topology)
- File: ./examples/05-multirack.yaml
- Use when: You need high availability across availability zones
- Key features: 3 racks pinned to zones, rack-aware replication
Scenario 6: Advanced Storage
- File: ./examples/06-storage-advanced.yaml
- Use when: You need block devices, hostPath, CSI, local PV, or sidecar mounts
- Key features: Volume policies, block volumes, mount propagation, sidecar sharing
Scenario 7: Template-Based
- File: ./examples/07-template.yaml
- Use when: You manage multiple clusters with shared configuration
- Key features: AerospikeClusterTemplate, templateRef, overrides, resync annotation
Scenario 8: Full-Featured
- File: ./examples/08-full-featured.yaml
- Use when: Production deployment with all features enabled
- Key features: ACL + monitoring + multi-rack + PV + PDB + dynamic config
Scenario 9: On-Demand Operations (WarmRestart / PodRestart)
- File: ./examples/09-operations.yaml
- Use when: You need to manually restart pods (warm via SIGUSR1, or full pod recreate) without changing spec
- Key features:
spec.operations[] with WarmRestart (SIGUSR1) or PodRestart (delete+recreate); optional podList to target specific pods; webhook prevents modifying the operations list while one is InProgress
Monitoring sample note (04-monitoring.yaml): Recent fix — metricLabels values are TOML-escaped (double-quote-wrapped, backslash-escaped, control chars rejected) and the demo emptyDir mount points to /opt/aerospike/work instead of accidentally overlaying /opt/aerospike. If you cloned this example before April 2026, verify both.
4. CR Spec Reference
Detail: ./reference/cr-spec-fields.md
5. Webhook Auto-Settings
Webhook auto-settings and CRD field mapping: See acko-config-reference skill's reference/crd-mapping.md
6. Verification Commands
Run these after deploying or modifying a cluster.
# List all Aerospike clusters with their phase
kubectl get asc -n aerospike
# Check specific cluster phase
kubectl get asc <name> -n aerospike -o jsonpath='{.status.phase}'
# Check phase reason (useful when phase is Error or InProgress)
kubectl get asc <name> -n aerospike -o jsonpath='{.status.phaseReason}'
# Check all conditions
kubectl get asc <name> -n aerospike -o jsonpath='{.status.conditions}' | jq .
# Check pod status details
kubectl get asc <name> -n aerospike -o jsonpath='{.status.pods}' | jq .
# Check ready pod count
kubectl get asc <name> -n aerospike -o jsonpath='{.status.size}'
# Check cluster events (most recent last)
kubectl get events -n aerospike --field-selector involvedObject.name=<name> --sort-by='.lastTimestamp'
# Verify Aerospike service is responding
kubectl exec -n aerospike <pod-name> -c aerospike-server -- asinfo -v status
# Check cluster membership
kubectl exec -n aerospike <pod-name> -c aerospike-server -- asinfo -v 'statistics' | tr ';' '\n' | grep cluster_size
# Check namespace stats
kubectl exec -n aerospike <pod-name> -c aerospike-server -- asinfo -v 'namespace/<namespace-name>'
7. Byte Value Reference
Byte values: See acko-config-reference skill's reference/byte-values.md
8. CE 8.1 Configuration Notes
CE 8.1 notes: See acko-config-reference skill
9. Template Fix Notice (April 2026)
A recent operator fix re-applies the resolved template to the in-memory cluster spec after every Status().Update/Patch, so template-derived fields (PodSpec.PodAntiAffinity, Resources, Storage) now reach the StatefulSet and persist across reconciles. If you previously worked around this by inlining template values into spec.overrides, you can drop those workarounds. VolumeClaimTemplate updates remain immutable — VCTs are only set at StatefulSet creation time inside buildStatefulSet.
1---2name: acko-deploy3description: MUST USE for deploying Aerospike on Kubernetes. Contains CE-specific YAML templates, validated AerospikeCluster CR examples, and critical constraints that prevent enterprise-only config mistakes (feature-key-file, security sections crash CE pods). Without this skill, deployments fail on first attempt due to CE 8.1 breaking changes (data-size not memory-size, no info port 3003) or webhook map/list shape rules (service/network must be maps; logging must be a list). Triggers on: deploy/create/set up Aerospike on K8s, kind, minikube, EKS, GKE; AerospikeCluster CR; ACKO operator; spec.operations / WarmRestart / PodRestart YAML; NoSQL database on Kubernetes. 9 ready-to-use YAML examples from minimal single-node to full-featured multi-rack.4---56# ACKO Deployment Guide78Deploy Aerospike Community Edition clusters on Kubernetes using the ACKO operator.910---1112## 1. Quick Deploy: 1-Node Dev Cluster in 3 Steps1314### Step 1: Check Prerequisites1516Run these commands to verify your environment is ready:1718```bash19# Verify kubectl is connected to a cluster20kubectl cluster-info2122# Verify the ACKO operator is running23kubectl get pods -n aerospike-operator -l control-plane=controller-manager2425# Verify the AerospikeCluster CRD is installed26kubectl api-resources | grep aerospikeclusters2728# Create the target namespace (if it does not exist)29kubectl create namespace aerospike --dry-run=client -o yaml | kubectl apply -f -30```3132If the operator is not running, install it first:33```bash34kubectl apply -f https://raw.githubusercontent.com/aerospike-ce-ecosystem/aerospike-ce-kubernetes-operator/main/config/deploy/operator.yaml35```3637### Step 2: Apply the Minimal CR3839```yaml40apiVersion: acko.io/v1alpha141kind: AerospikeCluster42metadata:43 name: aerospike-basic44 namespace: aerospike45spec:46 size: 147 image: aerospike:ce-8.1.1.148 aerospikeConfig:49 namespaces:50 - name: test51 replication-factor: 152 storage-engine:53 type: memory54 data-size: 1073741824 # 1 GiB55 logging:56 - name: /var/log/aerospike/aerospike.log57 context: any info58```5960Save this as `aerospike-basic.yaml` and apply:61```bash62kubectl apply -f aerospike-basic.yaml63```6465### Step 3: Verify Deployment6667```bash68# Wait for phase=Completed (typically 30-90 seconds)69kubectl wait --for=jsonpath='{.status.phase}'=Completed asc/aerospike-basic -n aerospike --timeout=120s7071# Check cluster status (should show PHASE=Completed, HEALTH=1/1)72kubectl get asc aerospike-basic -n aerospike7374# Check pod status (should show 1/1 Running)75kubectl get pods -n aerospike7677# Verify Aerospike is responding78kubectl exec -n aerospike aerospike-basic-0-0 -c aerospike-server -- asinfo -v status79# Expected output: ok80```8182---8384## 2. CE Constraints (Webhook-Enforced)8586These constraints are enforced by the ACKO validating webhook. Violating any of them causes the CR to be rejected at apply time.87881. **Cluster size**: `spec.size` must be between 1 and 8 (inclusive).892. **Namespaces**: Maximum 2 namespaces in `aerospikeConfig.namespaces`.903. **No XDR**: `aerospikeConfig` must not contain an `xdr` section (Enterprise-only).914. **No TLS**: `aerospikeConfig` must not contain a `tls` section (Enterprise-only).925. **No Enterprise images**: `spec.image` must not contain `enterprise`, `ee-`, or `ent-`.936. **Mesh heartbeat only**: `network.heartbeat.mode` must be `mesh`.947. **Byte values as integers**: All size values in `aerospikeConfig` (such as `data-size`, `filesize`) must be specified as integer byte counts, not human-readable strings.958. **Replication factor**: Must be between 1 and 4, and must not exceed `spec.size`.969. **No Enterprise namespace keys**: The following keys are forbidden in namespace config: `compression`, `compression-level`, `durable-delete`, `fast-restart`, `index-type`, `sindex-type`, `rack-id`, `strong-consistency`, `tomb-raider-eligible-age`, `tomb-raider-period`.9710. **No Enterprise security keys**: Only `enable-security` and `default-password-file` are allowed in `aerospikeConfig.security`. The keys `tls`, `ldap`, `log`, `syslog` are forbidden.9811. **Strengthened map/list shapes (April 2026)**: `aerospikeConfig.service` and `aerospikeConfig.network` must be YAML maps; `aerospikeConfig.logging` must be a YAML list; each `namespaces[]` entry must be a map with a `name` key. `MetricLabels` values are TOML-escaped — control characters are rejected. Within one update, namespace `rack-id` may be added OR removed but not both (prevents data loss on rename).9912. **Operations spec invariants**: `spec.operations[].kind` must be `WarmRestart` or `PodRestart`; `spec.operations[].id` length 1–20 chars; the operations list cannot be modified while one operation is `InProgress`. `spec.overrides` only valid when `spec.templateRef` is set.100101---102103## 3. Deployment Scenarios104105Choose the scenario that matches your needs. Each links to a ready-to-use YAML example.106107### Scenario 1: Minimal In-Memory (Dev/Test)108- **File**: [./examples/01-minimal.yaml](./examples/01-minimal.yaml)109- **Use when**: Quick local dev, CI tests, learning ACKO110- **Key features**: 1 node, in-memory storage, no persistence, no ACL111112### Scenario 2: 3-Node with Persistent Volume (Staging/Production Baseline)113- **File**: [./examples/02-3node-pv.yaml](./examples/02-3node-pv.yaml)114- **Use when**: You need data persistence across pod restarts115- **Key features**: 3 nodes, PVC-backed device storage, resource limits, cascadeDelete116117### Scenario 3: ACL (Access Control)118- **File**: [./examples/03-acl.yaml](./examples/03-acl.yaml)119- **Use when**: You need authentication and role-based access control120- **Key features**: security stanza, admin user (sys-admin + user-admin required), K8s Secrets for passwords121122### Scenario 4: Prometheus Monitoring123- **File**: [./examples/04-monitoring.yaml](./examples/04-monitoring.yaml)124- **Use when**: You need metrics, dashboards, and alerting125- **Key features**: Exporter sidecar, ServiceMonitor, PrometheusRule, metric labels126127### Scenario 5: Multi-Rack (Zone-Aware Topology)128- **File**: [./examples/05-multirack.yaml](./examples/05-multirack.yaml)129- **Use when**: You need high availability across availability zones130- **Key features**: 3 racks pinned to zones, rack-aware replication131132### Scenario 6: Advanced Storage133- **File**: [./examples/06-storage-advanced.yaml](./examples/06-storage-advanced.yaml)134- **Use when**: You need block devices, hostPath, CSI, local PV, or sidecar mounts135- **Key features**: Volume policies, block volumes, mount propagation, sidecar sharing136137### Scenario 7: Template-Based138- **File**: [./examples/07-template.yaml](./examples/07-template.yaml)139- **Use when**: You manage multiple clusters with shared configuration140- **Key features**: AerospikeClusterTemplate, templateRef, overrides, resync annotation141142### Scenario 8: Full-Featured143- **File**: [./examples/08-full-featured.yaml](./examples/08-full-featured.yaml)144- **Use when**: Production deployment with all features enabled145- **Key features**: ACL + monitoring + multi-rack + PV + PDB + dynamic config146147### Scenario 9: On-Demand Operations (WarmRestart / PodRestart)148- **File**: [./examples/09-operations.yaml](./examples/09-operations.yaml)149- **Use when**: You need to manually restart pods (warm via SIGUSR1, or full pod recreate) without changing spec150- **Key features**: `spec.operations[]` with `WarmRestart` (SIGUSR1) or `PodRestart` (delete+recreate); optional `podList` to target specific pods; webhook prevents modifying the operations list while one is `InProgress`151152> **Monitoring sample note (`04-monitoring.yaml`)**: Recent fix — `metricLabels` values are TOML-escaped (double-quote-wrapped, backslash-escaped, control chars rejected) and the demo `emptyDir` mount points to `/opt/aerospike/work` instead of accidentally overlaying `/opt/aerospike`. If you cloned this example before April 2026, verify both.153154---155156## 4. CR Spec Reference157158Detail: `./reference/cr-spec-fields.md`159160---161162## 5. Webhook Auto-Settings163164Webhook auto-settings and CRD field mapping: See acko-config-reference skill's `reference/crd-mapping.md`165166---167168## 6. Verification Commands169170Run these after deploying or modifying a cluster.171172```bash173# List all Aerospike clusters with their phase174kubectl get asc -n aerospike175176# Check specific cluster phase177kubectl get asc <name> -n aerospike -o jsonpath='{.status.phase}'178179# Check phase reason (useful when phase is Error or InProgress)180kubectl get asc <name> -n aerospike -o jsonpath='{.status.phaseReason}'181182# Check all conditions183kubectl get asc <name> -n aerospike -o jsonpath='{.status.conditions}' | jq .184185# Check pod status details186kubectl get asc <name> -n aerospike -o jsonpath='{.status.pods}' | jq .187188# Check ready pod count189kubectl get asc <name> -n aerospike -o jsonpath='{.status.size}'190191# Check cluster events (most recent last)192kubectl get events -n aerospike --field-selector involvedObject.name=<name> --sort-by='.lastTimestamp'193194# Verify Aerospike service is responding195kubectl exec -n aerospike <pod-name> -c aerospike-server -- asinfo -v status196197# Check cluster membership198kubectl exec -n aerospike <pod-name> -c aerospike-server -- asinfo -v 'statistics' | tr ';' '\n' | grep cluster_size199200# Check namespace stats201kubectl exec -n aerospike <pod-name> -c aerospike-server -- asinfo -v 'namespace/<namespace-name>'202```203204---205206## 7. Byte Value Reference207208Byte values: See acko-config-reference skill's `reference/byte-values.md`209210---211212## 8. CE 8.1 Configuration Notes213214CE 8.1 notes: See acko-config-reference skill215216---217218## 9. Template Fix Notice (April 2026)219220A recent operator fix re-applies the resolved template to the in-memory cluster spec **after** every `Status().Update`/`Patch`, so template-derived fields (`PodSpec.PodAntiAffinity`, `Resources`, `Storage`) now reach the StatefulSet and persist across reconciles. If you previously worked around this by inlining template values into `spec.overrides`, you can drop those workarounds. `VolumeClaimTemplate` updates remain immutable — VCTs are only set at StatefulSet creation time inside `buildStatefulSet`.