The platform team retires the NATS cluster prod-east: it rolls out prod-east-2 beside it in the same supercluster, moves every movable stream across, and only then deletes prod-east.
The evacuation #
The NATS cluster to retire:
01-natscluster-prod-east.yaml
# The NATS cluster being retired: story 9's prod-east, whose gateway list, like
# every member's, now names prod-east-2 as well.
apiVersion: cluster.nats.mikluko.io/v1beta1
kind: NatsCluster
metadata:
name: prod-east
namespace: nats-system
spec:
version: 2.15.0
replicas: 5
resources:
requests:
cpu: "6"
memory: 29Gi
limits:
memory: 29Gi
jetstream:
# Overrides the memory store derived from limits.memory.
limits:
maxMemoryStore: 10Gi
volumeClaimTemplate:
spec:
storageClassName: gp3
resources:
requests:
storage: 500Gi
serverTags:
cluster: prod-east
region: us-east-2
auth:
trustRef:
name: acme
systemCredentials:
secretKeyRef:
name: cluster-controller-creds
gateway:
discovery: Explicit
remotes:
- name: prod-east
url: tls://nats.prod-east.acme.example:7222
- name: dev-east
url: tls://nats.dev-east.acme.example:7222
- name: prod-west
url: tls://nats.prod-west.acme.example:7222
- name: prod-east-2
url: tls://nats.prod-east-2.acme.example:7222
tls:
certManager:
issuerRef:
kind: Issuer
name: nats-gateway-ca
service:
type: LoadBalancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: external
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
external-dns.alpha.kubernetes.io/hostname: nats.prod-east.acme.example
advertise: nats.prod-east.acme.example:7222
kubectl apply -f https://nats-operator.io/docs/stories/11-evacuation/01-natscluster-prod-east.yamlIts replacement, with a tag of its own, and one system-level evacuation of the whole of prod-east.
01-evacuation.yaml
# The replacement NATS cluster, prod-east-2, a member beside prod-east with a
# placement tag no other server carries; otherwise as prod-east.
apiVersion: cluster.nats.mikluko.io/v1beta1
kind: NatsCluster
metadata:
name: prod-east-2
namespace: nats-system
spec:
version: 2.15.0
replicas: 5
resources:
requests:
cpu: "6"
memory: 29Gi
limits:
memory: 29Gi
jetstream:
# Overrides the memory store derived from limits.memory.
limits:
maxMemoryStore: 10Gi
volumeClaimTemplate:
spec:
storageClassName: gp3
resources:
requests:
storage: 500Gi
serverTags:
cluster: prod-east-2
region: us-east-2
auth:
trustRef:
name: acme
systemCredentials:
secretKeyRef:
name: cluster-controller-creds
gateway:
discovery: Explicit
remotes:
- name: prod-east
url: tls://nats.prod-east.acme.example:7222
- name: dev-east
url: tls://nats.dev-east.acme.example:7222
- name: prod-west
url: tls://nats.prod-west.acme.example:7222
- name: prod-east-2
url: tls://nats.prod-east-2.acme.example:7222
tls:
certManager:
issuerRef:
kind: Issuer
name: nats-gateway-ca
service:
type: LoadBalancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: external
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
external-dns.alpha.kubernetes.io/hostname: nats.prod-east-2.acme.example
advertise: nats.prod-east-2.acme.example:7222
---
# Empties prod-east of every stream, key-value bucket and object store, in every
# account, with their consumers, save those whose resource sets
# placement.cluster. System-level and whole NATS cluster only. Each stream is
# moved by $JS.API.ACCOUNT.STREAM.MOVE with the target tags.
apiVersion: jetstream.nats.mikluko.io/v1beta1
kind: NatsClusterEvacuation
metadata:
name: retire-prod-east
namespace: nats-system
spec:
connectionRef:
name: prod-east-sys # system credentials
from:
cluster: prod-east
# Must match servers of the target NATS cluster only; refused before any move
# if a server of `from` carries them too.
to:
serverTags: ["cluster:prod-east-2"]
kubectl apply -f https://nats-operator.io/docs/stories/11-evacuation/01-evacuation.yamlResources whose own spec pins prod-east are left alone and listed; the evacuation is not Ready until their owners move them. A moved stream that no resource owns keeps a config naming prod-east, and is listed under stalePlacement: while prod-east exists, an update that changes that stream’s placement moves it back there.
01-status-natsclusterevacuation.yaml
# Balancers skip streams an evacuation is moving.
status:
observedGeneration: 1
conditions:
- type: Ready
status: "False"
reason: PinnedObjects
message: 2 resources pin placement.cluster prod-east
- type: Progressing
status: "False"
reason: NothingMovable
moved: 41
inFlight: 0
pinned:
- kind: NatsStream
namespace: orders
name: orders
- kind: NatsKeyValue
namespace: payments
name: sessions
stalePlacement:
- account: ADTWXTPEOI65FGIGO36XGZBDFOYDDPV6XZPRQWDIRXIYCAJD6TBP76JN
name: audit
Deleting prod-east
#
Deletion waits while its NATS cluster still holds JetStream data.
02-delete-natscluster-prod-east.yaml
# kubectl delete natscluster prod-east
apiVersion: cluster.nats.mikluko.io/v1beta1
kind: NatsCluster
metadata:
name: prod-east
namespace: nats-system
kubectl delete -f https://nats-operator.io/docs/stories/11-evacuation/02-delete-natscluster-prod-east.yaml02-status-natscluster-prod-east.yaml
# prod-east once deleted: deletion waits while its NATS cluster still holds
# JetStream data. The annotation cluster.nats.mikluko.io/force-delete
# overrides it.
status:
conditions:
- type: Deleting
status: "True"
reason: JetStreamDataRemains
message: 2 stream groups still placed in prod-east (orders/ORDERS, payments/KV_sessions)