Networking
This guide covers the operator's networking features: Aerospike network access policies, automatic Kubernetes NetworkPolicy generation, CNI bandwidth shaping, external seed discovery via LoadBalancer, and custom service metadata.
AerospikeNetworkPolicy
spec.aerospikeNetworkPolicy controls how Aerospike advertises its addresses to clients and peer nodes. This is critical for hybrid environments where clients connect from outside the Kubernetes cluster.
Access Types
Each field accepts one of four values:
| Value | Description |
|---|---|
pod | Use the Pod IP (default). Best for in-cluster clients. |
hostInternal | Use the Kubernetes node's internal IP. For clients on the same private network. |
hostExternal | Use the Kubernetes node's external IP. For clients outside the cloud VPC. |
configuredIP | Use a custom IP from pod annotations. For advanced multi-network setups (e.g., Multus). |
Fields
| Field | Default | Description |
|---|---|---|
accessType | pod | How clients reach the Aerospike service port (3000). |
alternateAccessType | pod | How clients from alternate networks reach the service port. |
fabricType | pod | How Aerospike nodes communicate with each other (fabric/heartbeat). |
Example: In-Cluster Only (Default)
apiVersion: acko.io/v1alpha1
kind: AerospikeCluster
metadata:
name: my-cluster
namespace: aerospike
spec:
size: 3
image: aerospike:ce-8.1.1.1
aerospikeNetworkPolicy:
accessType: pod
fabricType: pod
Example: External Client Access via Host Network
When clients connect from outside the cluster, advertise the node's external IP:
spec:
aerospikeNetworkPolicy:
accessType: hostExternal
alternateAccessType: hostInternal
fabricType: pod
In this setup:
- External clients connect using the node's external IP.
- Internal clients (alternate network) use the node's internal IP.
- Inter-node fabric traffic stays on the pod network for performance.
Example: ConfiguredIP with Custom Network Names
For environments using secondary network interfaces (e.g., Multus CNI), use configuredIP with custom network names. The operator reads the IP from the pod's k8s.v1.cni.cncf.io/network-status annotation matching the specified network name.
spec:
aerospikeNetworkPolicy:
accessType: configuredIP
customAccessNetworkNames:
- "aerospike-sriov-network"
alternateAccessType: configuredIP
customAlternateAccessNetworkNames:
- "aerospike-macvlan-network"
fabricType: configuredIP
customFabricNetworkNames:
- "aerospike-sriov-network"
When using configuredIP, you must provide the corresponding custom*NetworkNames field. The operator will fail to resolve the IP if the network name does not match an entry in the pod's network-status annotation.
NetworkPolicyConfig
spec.networkPolicyConfig enables automatic creation of Kubernetes NetworkPolicy or Cilium CiliumNetworkPolicy resources. This restricts network traffic to only what the Aerospike cluster needs.
Generated Rules
When enabled, the operator creates a NetworkPolicy with these ingress rules:
- Intra-cluster traffic: Fabric (3001) and heartbeat (3002) ports are allowed only from pods matching the cluster's selector labels.
- Client access: Service port (3000) is open to all sources.
- Metrics (if monitoring is enabled): The configured metrics port is open to all sources for Prometheus scraping.
Standard Kubernetes NetworkPolicy
spec:
networkPolicyConfig:
enabled: true
type: kubernetes
Cilium CiliumNetworkPolicy
If your cluster uses Cilium as the CNI, you can generate a CiliumNetworkPolicy instead:
spec:
networkPolicyConfig:
enabled: true
type: cilium
If the CiliumNetworkPolicy CRD is not installed in the cluster, the operator logs a message and skips creation gracefully. No error is raised.
Disabling
Set enabled: false (or remove the field entirely) to delete any previously created NetworkPolicy:
spec:
networkPolicyConfig:
enabled: false
BandwidthConfig
spec.bandwidthConfig injects CNI bandwidth annotations on pod templates for traffic shaping. This is useful for limiting network throughput per pod to prevent noisy-neighbor issues in shared clusters.
The operator sets the standard kubernetes.io/ingress-bandwidth and kubernetes.io/egress-bandwidth annotations, which are recognized by CNI plugins such as the Cilium bandwidth manager and the bandwidth CNI plugin.
Example
spec:
bandwidthConfig:
ingress: "1Gbps"
egress: "500Mbps"
Both fields are optional. You can set only ingress, only egress, or both:
spec:
bandwidthConfig:
egress: "200Mbps"
Bandwidth shaping requires a CNI plugin that supports these annotations. If your CNI does not support them, the annotations are ignored.
SeedsFinderServices
spec.seedsFinderServices creates a LoadBalancer service for external seed discovery. This allows clients outside the Kubernetes cluster to discover Aerospike seed nodes via the LoadBalancer's external IP.
LoadBalancer Configuration
| Field | Default | Description |
|---|---|---|
annotations | — | Custom annotations on the LoadBalancer service (e.g., for cloud provider configuration). |
labels | — | Custom labels on the LoadBalancer service. |
externalTrafficPolicy | — | Cluster or Local. Use Local to preserve client source IP. |
port | 3000 | External port on the LoadBalancer. |
targetPort | 3000 | Container port to forward traffic to. |
loadBalancerSourceRanges | — | Restrict traffic to specific CIDRs for security. |
Example: Basic LoadBalancer
spec:
seedsFinderServices:
loadBalancer:
port: 3000
Example: Production LoadBalancer with Restrictions
spec:
seedsFinderServices:
loadBalancer:
port: 3000
targetPort: 3000
externalTrafficPolicy: Local
loadBalancerSourceRanges:
- "10.0.0.0/8"
- "172.16.0.0/12"
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internal"
labels:
environment: production
HeadlessService
spec.headlessService allows you to attach custom annotations and labels to the headless service that the operator creates for each cluster. The headless service (named <cluster-name>-headless) enables DNS-based pod discovery and is always created.
Example
spec:
headlessService:
metadata:
annotations:
prometheus.io/scrape: "true"
external-dns.alpha.kubernetes.io/hostname: "aerospike.example.com"
labels:
team: platform
Operator-managed labels (e.g., app.kubernetes.io/name, app.kubernetes.io/instance) cannot be overridden by custom labels. If you specify a label key that conflicts with an operator-managed key, the operator's value takes precedence.
PodService
spec.podService creates an individual Service for each Aerospike pod. This is useful when you need stable, per-pod DNS names, service mesh integration, or external client access via LoadBalancer/NodePort.
When configured, the operator creates a Service named <pod-name>-pod for each pod, selecting that specific pod via statefulset.kubernetes.io/pod-name.
Service Type
| Value | Description |
|---|---|
ClusterIP | Default. Internal access only. Exposes only the service port (3000). |
NodePort | Exposes the pod on each node's IP at a random port. All Aerospike ports (service, fabric, heartbeat) are exposed. |
LoadBalancer | Creates a cloud LoadBalancer with a unique external IP per pod. All Aerospike ports are exposed. |
When serviceType is LoadBalancer or NodePort, the operator automatically:
- Creates a Role/RoleBinding granting the pod's service account permission to read its own Service
- Enables
automountServiceAccountTokenon the pod spec - Injects
EXTERNAL_SERVICE_TYPEandPOD_NAMESPACEenvironment variables into the init container - The init container queries the Kubernetes API at startup to discover its LoadBalancer external IP or NodePort, and injects it as
alternate-access-addressintoaerospike.conf
Example: ClusterIP (Default)
spec:
podService:
metadata:
labels:
visibility: internal
Example: LoadBalancer for External Access
spec:
podService:
serviceType: LoadBalancer
metadata:
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
Example: NodePort for External Access
spec:
podService:
serviceType: NodePort
The operator automatically cleans up stale pod services after scale-down or when podService is removed from the spec.
External Client Access
To allow clients outside the Kubernetes cluster to connect to Aerospike, configure per-pod LoadBalancer services and a seeds finder LoadBalancer.
How It Works
Aerospike uses a smart client protocol: the client connects to a seed node, receives the full cluster topology (all node addresses), and then connects directly to each node. For external access, every node must advertise an externally reachable address.
1. Client connects to Seeds LB (single entry point)
2. Aerospike returns cluster topology with alternate-access-address (LB IPs)
3. Client connects directly to each node via its per-pod LB IP
Configuration
spec:
# Per-pod LoadBalancer services — each pod gets a unique external IP
podService:
serviceType: LoadBalancer
# Seeds finder LB — single entry point for initial client connection
seedsFinderServices:
loadBalancer:
port: 3000
Client Connection
Use the Seeds LB IP with the --services-alternate flag:
# aql
aql -h <seeds-lb-ip> -p 3000 --services-alternate
# asinfo
asinfo -h <seeds-lb-ip> -p 3000
# Python
client = aerospike.client({
"hosts": [("<seeds-lb-ip>", 3000)],
"policies": {"use_services_alternate": True},
}).connect()
Discovering Endpoints
# Seeds LB endpoint (shown in default output)
kubectl get asc
# NAME RACKSIZE HEALTH PHASE SEED
# my-aerospike 3 3/3 Completed 10.177.200.247:3000
# All per-pod endpoints (shown in wide output)
kubectl get asc -o wide
# ENDPOINTS: 10.177.200.244:3000,10.177.200.245:3000,10.177.200.246:3000
The init container queries the Kubernetes API to resolve LoadBalancer IPs. If the LoadBalancer IP is not assigned within 120 seconds, the init container will fail and the pod will enter CrashLoopBackOff. Ensure your cloud provider or LB controller assigns IPs promptly.
Full Networking Example
Here is a comprehensive example combining multiple networking features:
apiVersion: acko.io/v1alpha1
kind: AerospikeCluster
metadata:
name: production-cluster
namespace: aerospike
spec:
size: 4
image: aerospike:ce-8.1.1.1
aerospikeNetworkPolicy:
accessType: hostExternal
alternateAccessType: hostInternal
fabricType: pod
networkPolicyConfig:
enabled: true
type: kubernetes
bandwidthConfig:
ingress: "2Gbps"
egress: "1Gbps"
seedsFinderServices:
loadBalancer:
port: 3000
externalTrafficPolicy: Local
loadBalancerSourceRanges:
- "10.0.0.0/8"
headlessService:
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: "aerospike-headless.example.com"
podService:
serviceType: LoadBalancer
metadata:
labels:
mesh.istio.io/managed: "true"
aerospikeConfig:
service:
proto-fd-max: 15000
namespaces:
- name: test
replication-factor: 2
storage-engine:
type: memory
data-size: 1073741824
network:
service:
port: 3000
fabric:
port: 3001
heartbeat:
mode: mesh
port: 3002
interval: 150
timeout: 10