Skip to content

Sharding + TLS: each shard gets its own self-signed CA, so peer TLS between shards can never validate #10756

Description

@dudizimber

Describe the bug

When TLS is enabled on a Cluster that uses a sharding, KubeBlocks issues a
separate self-signed CA per Component. Every shard of a sharding is its own
Component, so each shard receives a certificate signed by a CA that none of its
peers trusts.

Any engine whose cluster bus performs certificate chain validation between nodes
(Redis/Valkey/FalkorDB tls-cluster yes, and by extension any sharded engine
doing mTLS between shards) therefore cannot form a cluster at all when
issuer: {name: KubeBlocks} is used.

Version

KubeBlocks v1.2.0-alpha.1 (also reproduces on v1.2.0-alpha.3).

To Reproduce

apiVersion: apps.kubeblocks.io/v1
kind: Cluster
metadata:
  name: fdb-shtls
spec:
  terminationPolicy: WipeOut
  clusterDef: falkordb
  topology: cluster
  shardings:
    - name: shard
      shards: 3
      template:
        name: falkordb-cluster
        replicas: 1
        tls: true
        issuer:
          name: KubeBlocks
        ...

Then compare the CA that each shard received:

$ for c in fdb-shtls-shard-4xv fdb-shtls-shard-c96 fdb-shtls-shard-gc5; do
    kubectl get secret "$c-tls-certs" -o jsonpath='{.data.ca\.crt}' \
      | base64 -d | openssl x509 -noout -fingerprint
  done
SHA1 Fingerprint=17:26:3B:9F:34:CE:AC:37:...
SHA1 Fingerprint=98:EB:BD:AB:50:CA:19:7A:...
SHA1 Fingerprint=1D:7C:5F:8A:38:A1:48:10:...

Three distinct CAs, all with issuer=CN=KubeBlocks.

Expected behavior

All Components that belong to the same sharding (and arguably all Components of
the same Cluster) should be issued certificates from one CA, so that
peer-to-peer TLS between them can validate.

Actual behavior

Each shard trusts only its own CA. The engine's cluster bus rejects every peer:

[falkordb] - Connection with Node 8372627c19fdb381504bfd9e303ca04f8ae49d1d
  at 10.42.0.101:16379 failed: error:0A000086:SSL routines::certificate verify failed

The nodes never leave the handshake state:

127.0.0.1:6379> CLUSTER NODES
... master - 0 0 0 handshake - 0 0 0 disconnected
127.0.0.1:6379> CLUSTER INFO
cluster_state:fail
cluster_known_nodes:2

redis-cli --tls --insecure --cluster create then blocks forever in "Waiting
for the cluster to join", the postProvision lifecycle action is killed by
kbagent at its 30s budget (cost: 30003, result: timedOut), and the Component
stays in Creating:

Available=False/PhaseCheckFail
Progressing=True/PostProvision
Healthy=False/WorkloadNotReady

Proof that the CA is the only blocker

Copying shard c96's ca.crt into shard 4xv and connecting to c96 with it:

$ openssl s_client -connect 10.42.0.101:6379 -CAfile /tmp/peer-ca.crt </dev/null
...
Verification: OK
Verify return code: 0 (ok)

So the certificates themselves are fine — the cluster bus does chain validation
only, with no hostname/IP verification. The single reason the handshake fails is
that the peers do not share a trust root. Nothing else about the generated
certificates needs to change.

Workaround

Switch to issuer: {name: UserProvided} and supply one Secret containing a CA
shared by every shard. With that change the identical test goes from a 20-minute
timeout to passing in 163s.

Impact

issuer: KubeBlocks is unusable for any sharded engine that authenticates
peers over TLS. It is the default issuer, so this is a silent trap: the Cluster
simply never becomes ready and the only diagnostic is inside the engine's own
debug log.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions