Keeping an iSCSI target reachable through a single storage IP simplifies initiator configuration and shortens outages during node maintenance or failure. A floating IP provides a stable endpoint so initiators reconnect to the same address after failover, even when the active target node changes.
A Pacemaker and Corosync cluster managed through pcs treats the storage endpoint as a set of resources. An IPaddr2 resource assigns the floating IP, and a systemd resource manages the iSCSI target daemon; grouping the resources keeps ordering and colocation consistent so the IP comes up before the target starts.
Backing storage and target definitions must match across nodes so the same LUNs and ACLs are presented after a move. Keep LIO configuration (commonly /etc/target/saveconfig.json) or tgt configuration (commonly /etc/tgt/targets.conf) identical across nodes. Storage services require fencing (STONITH) to avoid a split-brain exporting the same block devices from multiple nodes, which can corrupt data, and failover interrupts existing iSCSI sessions until initiators reconnect.
$ sudo pcs status Cluster name: clustername Stack: corosync Current DC: node-02 (version 2.1.7) - partition with quorum Last updated: Tue Dec 30 10:11:07 2025 Last change: Tue Dec 30 09:55:18 2025 by hacluster via crmd on node-02 2 nodes configured 0 resource instances configured Online: [ node-01 node-02 ]
$ systemctl list-unit-files --type=service | grep -E '^(target|targetctl|tgtd|tgt)\.service' target.service enabled enabled tgtd.service disabled disabled
$ sudo systemctl disable --now target Removed "/etc/systemd/system/multi-user.target.wants/target.service".
Replace target with the unit name identified earlier.
Stopping the target disconnects iSCSI sessions and interrupts active I/O.
$ sudo pcs resource create iscsi_ip ocf:heartbeat:IPaddr2 ip=192.168.111.68 cidr_netmask=24 op monitor interval=30s
Use an unused address in the storage subnet so initiators keep a stable target IP.
$ sudo pcs resource create iscsi_service systemd:target op monitor interval=30s
Use systemd:tgtd or systemd:tgt when those units are present.
$ sudo pcs resource group add iscsi-stack iscsi_ip iscsi_service
Resources in a group start in listed order and stop in reverse order.
If the exported LUN depends on a clustered device activation or a mount, place that resource in the same group before iscsi_service so the backstore is available before the target starts.
$ sudo pcs status resources Resource Group: iscsi-stack iscsi_ip (ocf::heartbeat:IPaddr2): Started node-02 iscsi_service (systemd:target): Started node-02
$ ip -br address show | grep -F '192.168.111.68' ens192 UP 192.168.111.10/24 192.168.111.68/24
$ sudo ss -ltn sport = :3260 State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 256 192.168.111.68:3260 0.0.0.0:*
$ sudo pcs resource move iscsi-stack node-01
Replace node-01 with the desired failover node name.
Failover drops existing iSCSI sessions until initiators reconnect.
$ sudo pcs status resources Resource Group: iscsi-stack iscsi_ip (ocf::heartbeat:IPaddr2): Started node-01 iscsi_service (systemd:target): Started node-01
$ sudo pcs resource clear iscsi-stack
Clearing the move returns placement decisions to the cluster scheduler.