Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Kubernetes Operator

The Nervix Kubernetes Operator watches namespaced NervixCluster resources across a Kubernetes cluster. For each resource, it creates the services, StatefulSet, and one persistent volume claim per Nervix node. It also coordinates one-time initialization of the default user before scaling the StatefulSet to the requested replica count.

Prerequisites

Before installing the operator, ensure that:

  • kubectl and Helm 3 can reach the Kubernetes cluster.
  • The cluster has a default StorageClass that can provision persistent volumes.
  • Your Kubernetes identity can create custom resource definitions and cluster-wide RBAC resources.
  • Cluster nodes can pull images from ghcr.io.

Install The Operator With Helm

The Helm chart is currently distributed in the operator repository rather than as a versioned chart release. Clone the repository and install its bundled chart:

git clone --depth 1 https://github.com/nervix-io/nervix-k8s-operator.git

helm upgrade --install nervix-k8s-operator \
  ./nervix-k8s-operator/charts/nervix-k8s-operator \
  --namespace nervix-system \
  --create-namespace

Wait for the operator to become available:

kubectl --namespace nervix-system rollout status \
  deployment/nervix-k8s-operator

The chart installs the NervixCluster custom resource definition and deploys one operator that can manage Nervix clusters in any namespace.

Create The Initial User Secret

Create a namespace and a Secret containing the initial password for the default user. Use a password file that contains the exact password without a trailing newline, and do not commit that file:

kubectl create namespace nervix

kubectl --namespace nervix create secret generic nervix-initial-password \
  --from-file=password=/secure/path/to/password

The operator exposes this credential only to the first bootstrap pod. After authentication proves that Nervix committed the user, the operator restarts that pod without the credential and then scales the cluster to the requested replica count.

Create A Nervix Cluster

Save the following resource as nervix-cluster.yaml:

apiVersion: nervix.io/v1alpha1
kind: NervixCluster
metadata:
  name: nervix
  namespace: nervix
spec:
  image: ghcr.io/nervix-io/nervix:debian-latest
  replicas: 3
  clusterId: nervix-kube
  initialDefaultUserPasswordSecretRef:
    name: nervix-initial-password
    key: password
  storage: 5Gi

Apply it and watch the cluster become ready:

kubectl apply --filename nervix-cluster.yaml
kubectl --namespace nervix get nervixcluster nervix --watch

The READY count should eventually match REPLICAS. Inspect the objects owned by the operator with:

kubectl --namespace nervix get pods,services,persistentvolumeclaims

One operator can manage multiple Nervix clusters. Create each cluster as a separate NervixCluster, usually in a separate namespace or with a distinct name in the same namespace.

Enable Local Access

For development clusters that need direct access from outside Kubernetes, add this to the NervixCluster spec:

  localAccess:
    enabled: true

Apply the updated resource:

kubectl apply --filename nervix-cluster.yaml

The default NodePorts are 31390 for the gRPC entry point, 31420 for the web console, and 31090 for health and metrics. The operator also creates per-node NodePorts so clients redirected to the leader can reach it.

Connect the CLI to the gRPC entry point:

nervix-cli --server http://<node-address>:31390

The web console is available at http://<node-address>:31420/console/. Omit localAccess for an in-cluster-only deployment.

Shutdown And Grace Periods

Deleting a pod, draining a Kubernetes node, or rolling the StatefulSet sends SIGTERM, which starts graceful shutdown. A Nervix node ends its own shutdown within its shutdown timeout, 50 seconds by default, which covers the 30-second default drain timeout and the services that stop after it. The operator sets terminationGracePeriodSeconds: 60 so the kubelet waits longer than that, and a node that cannot finish exits on its own rather than being killed partway through its drain. If you raise NERVIX_SHUTDOWN_TIMEOUT, raise the grace period with it.

Note that /readyz reports whether the node currently knows a Raft leader; it does not turn negative when a node begins terminating. A draining node is therefore not removed from Service endpoints by readiness alone. It stops accepting new client connections itself in the first shutdown phase, and it keeps serving already-admitted work until its drain finishes.

A terminating node moves its scheduled work to a live peer when one is available, and otherwise completes everything it has admitted in place. Rolling one pod at a time keeps a peer available to receive that work, so ownership moves instead of waiting for the pod to come back. See Shutdown And Recovery for the phases, the drain guarantees, and what each ending preserves.

Production Considerations

Both the chart and the example currently default to rolling latest image tags. Pin reviewed operator and Nervix image tags or digests before using this setup in production. Also choose storage, resource requests, NodePort exposure, and Secret management appropriate for the cluster.