Part 2 of 2: Reading wsrep status, killing the writer, and proving zero data loss

In Part 1 we built a 3-node K3s cluster, installed OpenEverest, and created a 3-node Percona XtraDB Cluster (PXC) named mysql-vjg. In this post we look inside that cluster.

  • Section A explains how to read Galera’s wsrep_* status variables, so you can tell at a glance whether the cluster is healthy.
  • Section B is a live failover test. We delete the writer pod while a client inserts a row every second, then watch HAProxy switch writers, the pod rejoin, and all three nodes end up with identical data.

All output shown in this post is real output from a lab cluster whose nodes are named controlplane, worker1 and worker2. Your node names, pod IPs, timestamps and IDs will differ.

Important: The commands use the example cluster name mysql-vjg from Part 1. Replace it with your own cluster name everywhere (find it with kubectl get pxc -n everest). If you created your database in a namespace other than everest, replace -n everest as well.

Before You Start

Where to run: every command runs on the control plane node, where kubectl is configured, unless a step says otherwise. Some commands run inside a temporary client pod; those steps say so explicitly.

Several commands need the MySQL root password. Load it from the Kubernetes Secret into a shell variable:

$Command (control plane)

export ROOT_PW=$(kubectl get secret everest-secrets-mysql-vjg -n everest -o jsonpath='{.data.root}' | base64 --decode) echo ${#ROOT_PW}    # prints the password length; 0 means the variable is empty

📝 Note: Shell variables belong to one shell session. Run the export line again in every new terminal, and again after switching users with sudo su or sudo -i. If you see Access denied for user 'root'@'localhost' (using password: NO), the variable is empty.

Section A: Understanding Galera Health

PXC replicates data with the Galera library. Galera reports its state through status variables whose names start with wsrep_, short for write-set replication. A write-set is the bundle of row changes one transaction produces. At commit time, the write-set is sent to every node and checked for conflicts (certification) before the commit succeeds.

Step A1: Take a Status Snapshot

Connect through HAProxy (Part 1, Step 6.5) or into a pod (Part 1, Step 6.8) and run:

SQL

SHOW STATUS LIKE '%wsrep%stat%'; SHOW STATUS LIKE '%wsrep%siz%';

Output. 

wsrep_local_state_uuid       | c1319eb6-d354-11f1-8a79-0ff80b37e565 wsrep_monitor_status (L/A/C) | [ (20, 20), (44, 44), (44, 44) ] wsrep_flow_control_status    | OFF wsrep_local_state            | 4 wsrep_local_state_comment    | Synced wsrep_ist_receive_status     | wsrep_evs_state              | OPERATIONAL wsrep_cluster_state_uuid     | c1319eb6-d354-11f1-8a79-0ff80b37e565 wsrep_cluster_status         | Primary wsrep_cert_index_size        | 1 wsrep_gcache_pool_size       | 15624 wsrep_cluster_size           | 3

Step A2: What Each Value Means

Variable Healthy value What it means
wsrep_local_state / _comment 4 / Synced This node is fully caught up and serving traffic.
wsrep_cluster_status Primary This node is part of the group that holds quorum (a majority). A non-Primary node has lost quorum and refuses queries, which protects you from split-brain.
wsrep_cluster_size 3 Number of nodes currently in the group. All three PXC pods are members.
wsrep_evs_state OPERATIONAL EVS (Extended Virtual Synchrony) is Galera’s group-communication layer. OPERATIONAL means the members are exchanging messages normally.
wsrep_flow_control_status OFF No node is asking the cluster to pause. ON means a slow node has a full apply queue and is throttling writes on every node.
wsrep_local_state_uuid and wsrep_cluster_state_uuid identical This node has the same data history as the cluster. A mismatch means the node needs a state transfer.
wsrep_monitor_status (L/A/C) pairs equal PXC-specific. Each pair is (last entered, last left) for the Local, Apply and Commit monitors. When both numbers match, no write-sets are in flight.
wsrep_ist_receive_status empty Shows progress only while the node is receiving an IST (see Step A4).
wsrep_cert_index_size small Entries in the certification index used to detect conflicts between concurrent transactions.
wsrep_gcache_pool_size varies Bytes of memory the gcache (the cache of recent write-sets) currently uses.

Step A3: The Node State Machine

Every time a node joins the cluster, it moves through these states. wsrep_local_state shows the number, and wsrep_local_state_comment shows the name.

State Name What is happening
1 Joining The node has joined the group and is requesting the data it is missing.
2 Donor/Desynced The node is sending a state transfer to a joining node. HAProxy takes it out of rotation while this runs.
3 Joined The node has received the data and is applying queued write-sets to catch up.
4 Synced The node is fully caught up. Only nodes in this state receive traffic from HAProxy.

Step A4: IST vs SST: How a Node Catches Up

A node that rejoins after a restart needs the write-sets it missed. There are two ways to get them:

  • IST (Incremental State Transfer): a donor node replays only the missing write-sets from its gcache, a ring buffer of recent write-sets. It takes seconds and puts little load on the donor.
  • SST (State Snapshot Transfer): a full copy of the dataset, taken with Percona XtraBackup. It can take a long time on large databases, and the donor does extra work while it runs.

The joining node gets an IST if a donor’s gcache still contains every write-set it missed. Otherwise it needs an SST. This is why gcache size matters: a larger gcache lets a node stay away longer and still rejoin with a fast IST. You will see a real IST in Section B.

Step A5: Other Variables Worth Monitoring

These are not part of the snapshot above, but they are the first places to look when a cluster is slow or applications see unexpected errors.

SQL

SHOW GLOBAL STATUS WHERE Variable_name IN (   'wsrep_flow_control_paused', 'wsrep_local_recv_queue_avg', 'wsrep_local_send_queue_avg',   'wsrep_local_cert_failures', 'wsrep_local_bf_aborts', 'wsrep_last_committed',   'wsrep_incoming_addresses');

Variable What to look for
wsrep_flow_control_paused Fraction of time (0.0 to 1.0) replication was paused by flow control. Keep it close to 0.
wsrep_local_recv_queue_avg Average length of the apply queue. Values above about 1 mean this node is falling behind.
wsrep_local_send_queue_avg Average outbound queue length. High values usually point to network problems.
wsrep_local_cert_failures Transactions that failed certification because another node changed the same rows. These are the “deadlock” errors described in Part 1.
wsrep_local_bf_aborts Local transactions aborted by a replicated write-set (“brute-force” aborts).
wsrep_last_committed Sequence number of the last committed write-set. It should be equal or very close on all nodes.
wsrep_incoming_addresses Addresses of all current cluster members.

Step A6: One-Shot Health Check Across All Pods

Instead of logging into each node, this loop runs one query on each of the three PXC pods with kubectl exec and prints the results side by side. How it works:

  • for i in 0 1 2 loops over the pod numbers, so mysql-vjg-pxc-$i becomes mysql-vjg-pxc-0, -1 and -2.
  • -c pxc selects the database container in each pod.
  • — separates kubectl‘s own options from the command to run inside the pod. Without it, kubectl tries to parse -uroot itself and fails with unknown shorthand flag: ‘u’.
  • env MYSQL_PWD=”$ROOT_PW” passes the password to the MySQL client as an environment variable, so it does not appear in the command line.
  • -Nse runs the SQL without column headers (-N), in silent tab-separated mode (-s).
$Command (control plane)

for i in 0 1 2; do kubectl exec mysql-vjg-pxc-$i -n everest -c pxc -- env MYSQL_PWD="$ROOT_PW" mysql -uroot -Nse "SELECT @@hostname, (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME='wsrep_local_state_comment'), (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME='wsrep_cluster_status'), (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME='wsrep_cluster_size'), (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME='wsrep_last_committed')"; done

Output

mysql-vjg-pxc-0    Synced    Primary    3    1057 mysql-vjg-pxc-1    Synced    Primary    3    1057 mysql-vjg-pxc-2    Synced    Primary    3    1057

Every node reports Synced, Primary, a cluster size of 3, and the same wsrep_last_committed value (1057). All three nodes have applied exactly the same write-sets.

Section B: Live Failover Test

In this test, a client inserts one row per second through HAProxy. While it runs, we delete the writer pod, mysql-vjg-pxc-0, and observe what happens. The client runs inside the cluster, so that an SSH tunnel or kubectl port-forward dropping cannot be confused with the failover itself.

Open three SSH sessions to the control plane and use them like this:

Terminal Runs on Used for
A Control plane, then inside the mysql-client pod Steps B1 to B3: start the client and the write loop
B Control plane Step B4: watch the PXC pods
C Control plane Step B5 onward: delete the pod and run the checks

Step B1: Start a Temporary MySQL Client Pod (Terminal A)

kubectl run starts a throwaway pod from the percona/percona-server:8.0 image, which includes the mysql client. The options:

  • -it attaches your terminal to the pod, and –command — bash starts a shell instead of a MySQL server.
  • –rm –restart=Never deletes the pod as soon as you exit the shell.
  • –env=”MYSQL_PWD=$ROOT_PW” puts the root password into the pod’s environment, so mysql commands inside the pod do not need -p.
$Command (control plane, Terminal A)

kubectl run mysql-client -n everest -it --rm --restart=Never \   --image=percona/percona-server:8.0 \   --env="MYSQL_PWD=$ROOT_PW" \   --command -- bash

Output

All commands and output from this session will be recorded in container logs, including credentials and sensitive information passed through the command prompt. If you don't see a command prompt, try pressing enter. [mysql@mysql-client /]$

The prompt changes to [mysql@mysql-client /]$: you are now inside the pod. The warning is a reminder that anything typed here ends up in the pod’s logs. The password is also visible in the pod spec, which is acceptable for a short-lived lab pod but not for production.

Step B2: Create a Test Table (Terminal A, inside the pod)

mysql-vjg-haproxy is the Kubernetes DNS name of the HAProxy Service. It resolves only inside the cluster, which is why these commands run from the client pod. The table records which node served each insert (served_by) and when (ts, with millisecond precision).

$ Command (inside the mysql-client pod)

mysql -h mysql-vjg-haproxy -uroot -e "   CREATE DATABASE IF NOT EXISTS demo;   CREATE TABLE IF NOT EXISTS demo.failover_test (     id        INT AUTO_INCREMENT PRIMARY KEY,     served_by VARCHAR(64),     ts        TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3)   );"

📝 Note: The primary key is required. PXC runs with pxc_strict_mode=ENFORCING, which rejects writes to tables without a primary key, because Galera needs one to replicate rows reliably.

Step B3: Start the Write Loop (Terminal A, inside the pod)

Every second, the loop opens a new connection through HAProxy, inserts one row, and prints the time, the node that served the request, and the ID it generated. –connect-timeout=2 stops a failed connection from hanging the loop, and 2>&1 makes any error message appear in the output.

$ Command (inside the mysql-client pod)

while true; do   out=$(mysql -h mysql-vjg-haproxy -uroot --connect-timeout=2 -Nse "         INSERT INTO demo.failover_test (served_by) VALUES (@@hostname);         SELECT @@hostname, LAST_INSERT_ID();" 2>&1 | tr '\n\t' '  ')   echo "$(date +%T)  $out"   sleep 1 done 09:07:07  mysql-vjg-pxc-0 743 09:07:08  mysql-vjg-pxc-0 746 09:07:10  mysql-vjg-pxc-0 749 ... 09:07:39  mysql-vjg-pxc-0 824 09:07:40  mysql-vjg-pxc-0 827

Leave it running. Before the failover, every line shows mysql-vjg-pxc-0, the current writer.

Step B4: Watch the PXC Pods (Terminal B)

-w (watch) keeps the command running and prints a new line every time a pod changes state. -o wide adds the pod IP and the node it runs on, and grep –line-buffered pxc keeps only PXC pods while printing each line immediately.

$Command (control plane, Terminal B)

root@arunopeneverestcontrolplanenode:/home/arunjith.aravindan# kubectl get pods -n everest -o wide -w | grep --line-buffered pxc mysql-vjg-pxc-0                                    1/1     Running   0               82s     10.42.2.16   arunjithopeneverestworkernode2    <none>           <none> mysql-vjg-pxc-1                                    1/1     Running   0               10d     10.42.1.7    arunjithopeneverestworkernode1    <none>           <none> mysql-vjg-pxc-2                                    1/1     Running   0               10d     10.42.0.10   arunopeneverestcontrolplanenode   <none>           <none>

Step B5: Delete the Writer Pod (Terminal C)

Make sure Terminals A and B are both running, then delete the writer. kubectl delete pod sends the pod a SIGTERM, which simulates a planned restart or node maintenance. The StatefulSet that owns the pod immediately creates a replacement with the same name.

$Command (control plane, Terminal C)

kubectl delete pod mysql-vjg-pxc-0 -n everest

Output

pod "mysql-vjg-pxc-0" deleted from everest namespace

Step B6: What the Application Saw (Terminal A)

Here is the write loop output around the failover, trimmed (… marks removed lines):

Output (trimmed, annotations added)

09:07:38  mysql-vjg-pxc-0 821 09:07:39  mysql-vjg-pxc-0 824 09:07:40  mysql-vjg-pxc-0 827    <- pod deleted around here 09:07:41  mysql-vjg-pxc-2 829    <- HAProxy switched the writer to pxc-2 09:07:42  mysql-vjg-pxc-2 832 ... 09:07:46  mysql-vjg-pxc-2 841 09:07:47  mysql-vjg-pxc-2 845    <- pxc-0 left the cluster: IDs now step by 2 09:07:48  mysql-vjg-pxc-2 847 09:07:49  mysql-vjg-pxc-2 849 ... 09:08:15  mysql-vjg-pxc-2 895 09:08:16  mysql-vjg-pxc-2 898    <- pxc-0 rejoined: IDs step by 3 again 09:08:17  mysql-vjg-pxc-2 901

Zero failed writes

The write at 09:07:40 went to pxc-0, and the next one, one second later, went to pxc-2. Not a single insert failed. Three things made this possible:

  • Graceful shutdown. SIGTERM let mysqld leave the Galera cluster cleanly instead of crashing.
  • Health-checked routing. HAProxy checks every node’s Galera state and stopped sending new connections to pxc-0 as soon as it began shutting down.
  • Short connections. Each loop iteration opens a new connection, so no connection was open on pxc-0 when it went away.

Important: HAProxy fails over routing, not sessions. Connections that are open on the stopped node are closed, and transactions that were not yet committed are rolled back. Applications need reconnect-and-retry logic. Connection pools that check connections before use handle this for you. Step B11 shows this in action.

The auto-increment step follows cluster membership

Look at the IDs. Galera sets auto_increment_increment to the current cluster size and gives each node a different auto_increment_offset (the wsrep_auto_increment_control setting). Two nodes can then never generate the same ID, even when both accept writes. As a side effect, the IDs show cluster membership changing in real time:

Time Writer IDs Step Why
09:07:07 – 09:07:40 pxc-0 743, 746, 749 … 827 3 Three nodes in the cluster
09:07:41 – 09:07:46 pxc-2 829, 832 … 841 3 pxc-0 is shutting down but is still a cluster member
09:07:47 – 09:08:15 pxc-2 845, 847, 849 … 895 2 pxc-0 has left: wsrep_cluster_size = 2
09:08:16 onward pxc-2 898, 901, 904 … 3 pxc-0 rejoined the group: size is back to 3

Gaps in auto-increment IDs are normal in Galera. Applications should never assume IDs are consecutive.

Step B7: What Kubernetes Did (Terminal B)

Output (columns and duplicate lines trimmed)

NAME              READY  STATUS           AGE   IP          NODE mysql-vjg-pxc-0   1/1    Running          82s   10.42.2.16  worker2 mysql-vjg-pxc-1   1/1    Running          10d   10.42.1.7   worker1 mysql-vjg-pxc-2   1/1    Running          10d   10.42.0.10  controlplane mysql-vjg-pxc-0   1/1    Terminating      93s   10.42.2.16  worker2 mysql-vjg-pxc-0   0/1    Completed        107s  10.42.2.16  worker2 mysql-vjg-pxc-0   0/1    Pending          0s    <none>      worker2 mysql-vjg-pxc-0   0/1    Init:0/1         1s    10.42.2.17  worker2 mysql-vjg-pxc-0   0/1    PodInitializing  8s    10.42.2.17  worker2 mysql-vjg-pxc-0   0/1    Running          9s    10.42.2.17  worker2 mysql-vjg-pxc-0   1/1    Running          39s   10.42.2.17  worker2

Reading it from top to bottom:

  • The three PXC pods run on three different nodes. OpenEverest uses pod anti-affinity so that losing one node never takes out two database replicas.
  • Terminating to Completed (about 14 seconds): mysqld shut down gracefully and the container exited cleanly.
  • Pending to Init to Running: the StatefulSet created a new pod with the same name on the same node. The local-path volume (Part 1, Step 4.3) lives on that node’s disk, so the pod has to come back there to reattach its data.
  • Running 0/1 to 1/1 (about 30 seconds): the container was running but did not pass its readiness check until mysqld had rejoined the cluster and reached Synced. The pod also got a new IP (10.42.2.17), which is why applications must use Service names and never pod IPs.

Step B8: How pxc-0 Rejoined: IST or SST? (Terminal C)

First confirm the node is back in the Synced state:

$Command (control plane, Terminal C)

kubectl exec mysql-vjg-pxc-0 -n everest -c pxc -- env MYSQL_PWD="$ROOT_PW" \   mysql -uroot -Nse "SHOW STATUS LIKE 'wsrep_local_state_comment'"

Output

wsrep_local_state_comment    Synced

Then search the pod’s logs for state-transfer messages. –all-containers covers the case where the error log is collected by a separate logging container.

$Command (control plane, Terminal C)

kubectl logs mysql-vjg-pxc-0 -n everest --all-containers | grep -Ei 'IST|SST' | tail -20

Output (trimmed)

2026-11-08T09:08:21.792709Z 1 [Note] [Galera] Receiving IST: 27 writesets, seqnos 341-367 2026-11-08T09:08:21.792853Z 0 [Note] [Galera] ####### IST applying starts with 341 ... 2026-11-08T09:08:21.975953Z 0 [Note] [Galera] Receiving IST... 100.0% (80/80 events) complete. 2026-11-08T09:08:22.018967Z 1 [Note] [Galera] Draining apply monitors after IST up to 367 2026-11-08T09:08:22.022710Z 1 [Note] [Galera] IST received: c1319eb6-d354-11f1-8a79-0ff80b37e565:367 ... 2026-11-08T09:08:22.026879Z 0 [Note] [Galera] SST leaving flow control

The node rejoined with an IST: it received the 27 write-sets it missed (sequence numbers 341 to 367) in about 0.2 seconds. This was possible because the pod reattached its existing volume, so it only lacked the writes from the few seconds it was down, and those were still in the donor’s gcache. If the volume had been lost, the node would have needed a full SST.

Put together with the auto-increment table, the timeline is: pxc-0 rejoined the Galera group at about 09:08:16 (cluster size back to 3), received the IST at 09:08:21 to 09:08:22, reached Synced, and then passed its Kubernetes readiness check.

📝 Note: Despite the word “SST” in the last line, no snapshot transfer happened. Galera reuses some SST-named code paths when finishing an IST. The IST received line is what tells you which method was used.

Step B9: Where Did the Writes Go? (Terminal A)

Stop the loop with Ctrl+C, then summarize which node accepted the writes:

$ Command (inside the mysql-client pod)

mysql -h mysql-vjg-haproxy -uroot -e "   SELECT served_by, COUNT(*) AS writes, MIN(ts) AS first, MAX(ts) AS last   FROM demo.failover_test GROUP BY served_by ORDER BY first;"

Output

+-----------------+--------+-------------------------+-------------------------+ | served_by       | writes | first                   | last                    | +-----------------+--------+-------------------------+-------------------------+ | mysql-vjg-pxc-0 |    904 | 2026-11-08 09:02:08.207 | 2026-11-08 09:21:27.210 | | mysql-vjg-pxc-2 |    103 | 2026-11-08 09:05:51.026 | 2026-11-08 09:08:35.249 | +-----------------+--------+-------------------------+-------------------------+

Two things stand out:

  • Writes moved back to pxc-0. The last write on pxc-2 was at 09:08:35, about 13 seconds after pxc-0 finished its IST. From then on, pxc-0 served every write. HAProxy prefers pxc-0 as the writer and switches back to it once it is healthy again. The write loop kept running past 09:08:21, which is why the totals go on until 09:21.
  • The totals include an earlier practice run. pxc-2‘s first write at 09:05:51 comes from a previous failover test, so the counts cover both runs.

Step B10: Verify That All Nodes Hold Identical Data (Terminal C)

The final check: query each PXC pod directly, bypassing HAProxy, and compare the row count, the highest ID, and a checksum of the whole table. CHECKSUM TABLE computes a hash over every row, so even one different value on one node would change it.

$Command (control plane, one line)

for i in 0 1 2; do kubectl exec mysql-vjg-pxc-$i -n everest -c pxc -- env MYSQL_PWD="$ROOT_PW" mysql -uroot -Nse "SELECT @@hostname, COUNT(*), MAX(id) FROM demo.failover_test; CHECKSUM TABLE demo.failover_test;"; done

Output

mysql-vjg-pxc-0    1007    2960 demo.failover_test    3133448865 mysql-vjg-pxc-1    1007    2960 demo.failover_test    3133448865 mysql-vjg-pxc-2    1007    2960 demo.failover_test    3133448865

All three nodes have 1007 rows and the same checksum, including pxc-0, which was deleted in the middle of the test. Galera replication is virtually synchronous: a transaction commits only after every node has received and certified its write-set. So an acknowledged write cannot be lost when a single node fails.

Also note that MAX(id) is 2960 for only 1007 rows. That is the auto-increment step at work: with 3 nodes, IDs advance by 3, so the highest ID is roughly three times the row count.

Step B11 (Optional): What Happens to a Running Query?

The write loop opened a new connection every second, so no connection was open when the writer stopped. What happens to a query that is running at that moment? In the client pod, start a query that sleeps for 20 minutes:

$ Command (inside the mysql-client pod)

mysql -h mysql-vjg-haproxy -uroot -e "SELECT @@hostname; SELECT SLEEP(1200);"

While it is sleeping, delete the pod it printed (the current writer) from Terminal C:

$Command (control plane, Terminal C)

kubectl delete pod mysql-vjg-pxc-0 -n everest

The query ended right away, without an error:

Output

+-----------------+ | @@hostname      | +-----------------+ | mysql-vjg-pxc-0 | +-----------------+ +-------------+ | SLEEP(1200) | +-------------+ |           1 | +-------------+

SLEEP() returns 0 when it sleeps the full time and 1 when it is interrupted. Here is what happened:

  • kubectl delete pod sends a normal stop signal (SIGTERM), so MySQL shuts down gracefully.
  • During a graceful shutdown, MySQL first interrupts every running query and sends the client a result. That is why SLEEP returned 1.
  • Then MySQL closes all connections. Our client had no more statements to run, so it exited normally and no error was shown.

The connection was still closed. You see an error if you try to keep using the same connection. To see this, open an interactive session and start a transaction:

$ Command (inside the mysql-client pod)

mysql -h mysql-vjg-haproxy -uroot

SQL

mysql> SELECT @@hostname; +-----------------+ | @@hostname      | +-----------------+ | mysql-vjg-pxc-0 | +-----------------+ 1 row in set (0.00 sec) mysql> BEGIN; Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO demo.failover_test (served_by) VALUES ('open-transaction-test'); Query OK, 1 row affected (0.01 sec)

Delete the pod that @@hostname printed from Terminal C, wait about 20 seconds, then run COMMIT; in the same session. The client should report an error such as ERROR 2013 (HY000): Lost connection to MySQL server during query. The client may then reconnect to the new writer by itself, but the open transaction is gone. The row was not saved, which you can check with:

SQL

mysql> SELECT COUNT(*) FROM demo.failover_test WHERE served_by = 'open-transaction-test'; ERROR 2013 (HY000): Lost connection to MySQL server during query No connection. Trying to reconnect... Connection id:    1414734 Current database: *** NONE *** +----------+ | COUNT(*) | +----------+ |        0 | +----------+ 1 row in set (0.09 sec)

The lesson: a failover never gives you corrupt or half-written data, but open connections and transactions are lost. Applications must reconnect and retry the whole transaction.

Step B12 (Optional): Take a Whole Server Offline

So far we deleted one pod. Now we take a whole server out of service, as you would for maintenance such as an OS update or a reboot.

kubectl drain stops all the pods on a server and blocks new pods from starting there. The server keeps running and its data stays on disk. It stays blocked until you run kubectl uncordon.

Where to run: all commands in this step run on the control plane node. kubectl acts on the worker node through the Kubernetes API, so you don’t need to log in to the worker.

B12.1:  Pick a node

Check which PXC pod runs on which node:

root@arunopeneverestcontrolplanenode:/home/arunjith.aravindan# kubectl get pods -n everest -o wide | grep -E 'pxc|mysql-client' mysql-client                       ...