canonical / microceph

Ceph for a one-rack cluster and appliances
https://snapcraft.io/microceph
GNU Affero General Public License v3.0
193 stars 25 forks source link

MicroCeph fails to detect public IP as accessible on join #329

Closed jonathansnell closed 2 months ago

jonathansnell commented 3 months ago

Issue report

What version of MicroCeph are you using ?

18.2.0+snap0a1f14ce2a from latest/stable

What are the steps to reproduce this issue ?

  1. On node-1: sudo microceph cluster bootstrap
  2. On node-1: sudo microceph cluster add node-2
  3. On node-2: sudo microceph cluster join $JOIN_KEY

What happens (observed behaviour) ?

The node joins the cluster with the following error: Error: failed to generate the configuration: failed to locate IP on public network $NODE_1_PUBLIC_IP/32: no IP belongs to provided subnet $NODE_1_PUBLIC_IP/32

Running sudo microceph cluster list will then list both nodes as expected, however operations such as sudo microceph disk add /dev/sdX --wipe result in the following error:

+----------+---------+
|   PATH   | STATUS  |
+----------+---------+
| /dev/sdX | Failure |
+----------+---------+
Error: failed to generate OSD keyring: Failed to run: ceph auth get-or-create osd.3 mgr allow profile osd mon allow profile osd osd allow * -o /var/snap/microceph/common/data/osd/ceph-3/keyring: exit status 1 (Error initializing cluster client: ObjectNotFound('RADOS object not found (error calling conf_read_file)'))

What were you expecting to happen ?

I expect the node to join without error and the disk to be added to node-2 without error.

Relevant logs, error output, etc.

Mar 18 10:14:53 node-2 sudo[2376817]: jonathan : TTY=pts/0 ; PWD=/home/jonathan ; USER=root ; COMMAND=/snap/bin/microceph cluster join $JOIN_KEY
Mar 18 10:14:53 node-2 systemd[1]: Started snap.microceph.microceph-5f2124ff-4d20-4662-b0b8-2fba5a48db33.scope.
Mar 18 10:14:53 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:53Z" level=debug msg="{{node-2 $NODE_2_PUBLIC_IP:7443 -----BEGIN CERTIFICATE-----$CERTIFICATE_CONTENTS-----END CERTIFICATE-----\n}  4 0001-01-01 00:00:00 +0000 UTC  $CRYPTO_HASH}"
Mar 18 10:14:53 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:53Z" level=debug msg="Got response struct from microcluster daemon" endpoint="https://$NODE_1_PUBLIC_IP:7443/cluster/1.0/cluster" method=POST
Mar 18 10:14:53 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:53Z" level=info msg=" - binding https socket" network="$NODE_2_PUBLIC_IP:7443"
Mar 18 10:14:54 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:54Z" level=debug msg="Dqlite connected outbound" local="$NODE_2_PUBLIC_IP:53210" remote="$NODE_1_PUBLIC_IP:7443"
Mar 18 10:14:54 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:54Z" level=debug msg="Dqlite connected outbound" local="$NODE_2_PUBLIC_IP:60518" remote="$NODE_2_PUBLIC_IP:7443"
Mar 18 10:14:54 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:54Z" level=debug msg="Matched trusted cert" fingerprint=$FINGERPRINT subject="CN=root@node-2,O=LXD"
Mar 18 10:14:54 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:54Z" level=debug msg="Dqlite connected outbound" local="$NODE_2_PUBLIC_IP:53224" remote="$NODE_1_PUBLIC_IP:7443"
Mar 18 10:14:54 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:54Z" level=debug msg="Dqlite connected outbound" local="$NODE_2_PUBLIC_IP:53240" remote="$NODE_1_PUBLIC_IP:7443"
Mar 18 10:14:54 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:54Z" level=info msg="Preparing statements for Go project \"\""
Mar 18 10:14:54 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:54Z" level=debug msg="{true 0 map[]}"
Mar 18 10:14:54 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:54Z" level=debug msg="Dqlite connected outbound" local="$NODE_2_PUBLIC_IP:53258" remote="$NODE_1_PUBLIC_IP:7443"
Mar 18 10:14:54 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:54Z" level=debug msg="{{node-2 $NODE_2_PUBLIC_IP:7443 -----BEGIN CERTIFICATE-----$CERTIFICATE_CONTENTS-----END CERTIFICATE-----\n}  0 0001-01-01 00:00:00 +0000 UTC  }"
Mar 18 10:14:54 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:54Z" level=debug msg="Got response struct from microcluster daemon" endpoint="https://$NODE_1_PUBLIC_IP:7443/cluster/1.0/cluster" method=POST
Mar 18 10:14:54 node-2 systemd[1]: snap.microceph.microceph-5f2124ff-4d20-4662-b0b8-2fba5a48db33.scope: Deactivated successfully.
Mar 18 10:14:56 node-2 microceph.daemon[81647]: time="2024-03-18T10:14:56Z" level=error msg="start: failed to update config, retrying: failed to locate IP on public network $NODE_1_PUBLIC_IP/32: no IP belongs to provided subnet $NODE_1_PUBLIC_IP/32"

Additional comments.

Although the error appears to suggest that the public IP for node-1 cannot be reached by node-2, and looks like a routing error, this is not the case. Observe the following ping output:

$ ping $NODE_1_PUBLIC_IP
PING $NODE_1_PUBLIC_IP ($NODE_1_PUBLIC_IP) 56(84) bytes of data.
64 bytes from $NODE_1_PUBLIC_IP: icmp_seq=1 ttl=53 time=5.48 ms
64 bytes from $NODE_1_PUBLIC_IP: icmp_seq=2 ttl=53 time=4.45 ms
64 bytes from $NODE_1_PUBLIC_IP: icmp_seq=3 ttl=53 time=2.98 ms
64 bytes from $NODE_1_PUBLIC_IP: icmp_seq=4 ttl=53 time=2.90 ms
^C
--- $NODE_1_PUBLIC_IP ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 2.901/3.953/5.480/1.076 ms
jonathansnell commented 3 months ago

Since it looks like the problem here is that the nodes are defaulting to their public IP addresses. I tried forcing the initial cluster boostrap to use the private address space with the following command:

$ sudo microceph cluster bootstrap --microceph-ip 10.24.0.10 --mon-ip 10.24.0.10 --public-network 10.24.0.0/24 --cluster-network 10.24.0.0/24

This completes without error and yields the following:

$ sudo microceph status
MicroCeph deployment summary:
- node-1 (10.24.0.10)
  Services: mds, mgr, mon
  Disks: 0

And I can see that the microceph daemon is bound to the private IP address:

$ ss -tunl | grep 7443
tcp   LISTEN 0      4096            10.24.0.10:7443       0.0.0.0:*

However, there doesn't appear to be a way to specify the IP address that microceph on the joining node should bind to, resulting in the following status after the join:

$ sudo microceph status
MicroCeph deployment summary:
- node-1 (10.24.0.10)
  Services: mds, mgr, mon
  Disks: 0
- node-2 ($NODE_2_PUBLIC_IP)
  Services: mds, mgr, mon
  Disks: 0

And I can see that microceph has bound to the public IP address on this node:

$ ss -tunl | grep 7443
tcp   LISTEN 0      4096        $NODE_2_PUBLIC_IP:7443       0.0.0.0:*

I believe I could work around the issue above, if I could force the joining node to bind to the private address space and advertise itself as such, but there doesn't seem to be a flag for this that I can identify in the documentation.

UtkarshBhatthere commented 3 months ago

@masnax can you please take a look the the comment above ? It appears that the joining nodes do not strictly follow the subnet of microceph-ip parameter passed to the microcluster.App.NewCluster() call, In the output shared by @jonathansnell, the joining node binds to the Public-IP available on the node (which is not ideal where network isolation is required) while the bootstrapped node conforms to the provided microceph-ip.

UtkarshBhatthere commented 3 months ago

@jonathansnell the fix for configuring microceph IP on cluster join was merged.

UtkarshBhatthere commented 2 months ago

Marking this issue as closed, please feel free to reopen this if this doesn't workout for you still (fix should be available in reef)