Skip to content

Add remote syslog forwarding for deployed nodes - #236

Open
Obihoernchen wants to merge 9 commits into
xcat2:masterfrom
Obihoernchen:rsyslog
Open

Add remote syslog forwarding for deployed nodes#236
Obihoernchen wants to merge 9 commits into
xcat2:masterfrom
Obihoernchen:rsyslog

Conversation

@Obihoernchen

@Obihoernchen Obihoernchen commented Jul 12, 2026

Copy link
Copy Markdown
Member

Implements xCATs syslog postscript functionality. But more advanced.

New node attributes

Adds logging.servers, logging.method and logging.tls node attributes. During deployment the node is configured to forward its logs via rsyslog (default) or systemd-journal-upload, optionally TLS-encrypted and mutually authenticated through the confluent CA.

Architecture

  • Per-node filing on the receiver (rsyslog: /var/log/confluent/nodes/<node>.log, named by the receiver's view of the sender, not the client-supplied hostname or systemd-journal-remote: /var/log/journal/remote/remote-<nodeip>.journal (filename hardcoded in systemd-journal-remote).
  • rsyslog comes with a logrotate example.
  • confluent-logging-receiver-setup helper + example receiver configs, tuned for up to 4K nodes
  • Bounded client-side action queues, so a dead or hung log server can never stall a node's local logging
  • Automatic certificate renewal (daily randomized systemd timer, renews once less than half the validity remains), so the default 47-day pubkeys.tls_lifetime just works and short lifetimes double as the revocation substitute

rsyslog vs systemd-journal-remote

Overall rsyslog can handle ~x10 times the messages/s systemd-journal-remote can. systemd-journal-remote has no tuning options and was not built for scale. Furthermore, some OSs can't verify the client TLS cert (see below). But there is another big benefit in using it: The additional journalctl metadata you can use with commands like journalctl _HOSTNAME=node001 -u sshd.service -D /var/log/journal/remote

systemd-journal-remote TLS client certificate verification

systemd-journal-remote only verifies client certificates when systemd is built with gnutls; otherwise TrustedCertificateFile= is silently ignored. The transport is still encrypted and the node still verifies the server, but uploads from any client are accepted. The setup helper detects this and warns; use the rsyslog method where client verification is required.

OS support for systemd-journal-remote TLS client certificate verification looks like this:

  • EL 9 ✅
  • EL 10 ❌
  • Ubuntu 24.04 ❌
  • Ubuntu 26.04 ❌
  • SLES 15 ✅
  • SLES 16 ✅

rsyslog transports

  • Plain: TCP/514 via imptcp. Core modules only (imptcp/omfwd, nothing extra to install on nodes), and imptcp imposes no session cap, so every node holds one persistent connection (bounded only by the receiver's open-file limit). Unlike UDP, TCP back-pressures senders under load instead of dropping, and a bounded client-side queue spools during outages. Under a simulated ~4K-sender burst the difference is:

    Tested on 8 core receiver VM, 32 core sender VM:

    receiver Messages
    imudp (UDP) ~230k msg/s, 5–7% lost
    imptcp (TCP) ~750k msg/s, lossless

    UDP has no backpressure, so a synchronized burst (a rack booting, a reconnect storm after the receiver restarts) simply overruns the receiver's socket buffer; imptcp delivered every message losslessly and scales to 4K connections cheaply.

  • TLS: TCP/6514 via imtcp, openssl driver with gnutls fallback. The standard syslog-over-TLS transport; both driver modules are packaged on all supported distributions, and x509/certvalid/x509/name map directly onto the confluent CA model (accept any node certificate from the CA, pin the server identity).

  • RELP was rejected: an extra package on every node, and its only mutual-auth modes (fingerprint/name pinning) cannot express CA-chain trust. This is unmanageable with short-lived, per-deployment node certificates; its delivery acks also gain little while journald rate-limiting drops messages upstream anyway.

  • DTLS requires rsyslog ≥ 8.2402 (Ubuntu 24.04 ships 8.2312).

@Obihoernchen

Obihoernchen commented Jul 13, 2026

Copy link
Copy Markdown
Member Author

Thoughts:

  • Compare rsyslog to systemd-journal-remote and syslog-ng (EPEL only)
    • Add them as additional alternatives or have just one default?
  • Try to use Confluents TLS CA for secure log forwarding. How to implement this?

@Obihoernchen

Copy link
Copy Markdown
Member Author

On a 16 CPU VM on EPYC I get:

Receiver messages/s
journal-http 35,000
journal-https 77,500
rsyslog-tls 361,000

@Obihoernchen
Obihoernchen marked this pull request as draft July 15, 2026 17:59
A new `logging.servers` attribute, when set, makes OS deployment configure the node to forward its logs to the given servers. It is surfaced as loggingservers/loggingmethod in confluent.deploycfg and applied by the new common `setuplogging` script, which is invoked in the profiles of all OSes shipping rsyslog by default and does nothing when the attribute is unset or the selected forwarder is absent.

The forwarding method is selected by `logging.method`: `rsyslog` (the default) writes an rsyslog drop-in forwarding syslog to the given servers over UDP port 514; `journal-remote` configures systemd-journal-upload to upload the journal to systemd-journal-remote on port 19532 (a single destination only - the first server is used). A `logging.tls` attribute is defined to encrypt the forwarding with TLS authenticated via the confluent certificate authority (not implemented yet)

Example receiver configurations for the confluent server side (rsyslog per-node logs plus logrotate, journal-remote drop-in) are shipped under `/opt/confluent/share/examples/logging`.
When the logging.tls attribute is set, the log forwarding configured from logging.servers is now encrypted and mutually authenticated via the confluent TLS certificate authority. During deployment, setuplogging requests a node certificate from the deployment API (/confluent-api/self/tlscert, validity governed by pubkeys.tls_lifetime, 47 days unless raised) and trusts /etc/confluent/ca.pem. With the rsyslog method, logs are forwarded over TCP port 6514 using the rsyslog-openssl or rsyslog-gnutls stream driver with x509/certvalid authentication; with journal-remote, systemd-journal-upload uploads over HTTPS port 19532 with explicit key, certificate and trust anchor settings. If TLS is requested but prerequisites are missing, the node is left unconfigured.

The certificate material is stored in dedicated directories readable by the consuming service (/etc/rsyslog.d/confluent-tls for rsyslog, /etc/ssl/confluent-logging for the journal tools).

The receiving side is handled by a new confluent-logging-receiver-setup helper shipped with the examples under /opt/confluent/share/examples/logging. It issues a server certificate signed offline by the local confluent CA (SANs covering the server names and addresses), installs the mutual TLS reception configuration for either method, setting TrustedCertificateFile explicitly for systemd-journal-remote, and can alternatively install the plaintext example configurations.

Note: Some distros (e.g., EL10, Ubuntu 24.04) build systemd-journal-remote without GnuTLS. This silently disables client certificate verification (accepting any client), though encryption remains active.
The helper warns of this issue. If client verification is required, use rsyslog (as noted in logging.tls).
The per-node log files on the receiving server were named after the client-supplied syslog HOSTNAME, which any authenticated sender can forge, allowing one node to inject entries into another node's log file. Name the files by FROMHOST instead (the sender identity as resolved by the receiving server from the peer address) so injected entries always land under the actual sender.
The log transports offer no certificate revocation, so note in the logging.tls attribute description that pubkeys.tls_lifetime should be chosen with node decommissioning in mind when raising it.
The confluent CA issues certificates to every node and BMC, all technically usable for TLS server authentication, so validating only the certificate chain allows any of them to pose as the logging server towards forwarding nodes if traffic can be redirected. When a logging.servers entry is a DNS name, forward with x509/name authentication pinning that name as the only permitted peer. The receiver certificates issued by confluent-logging-receiver-setup already carry the server names as DNS-type subject alternative names. rsyslog matches pinned peers only against DNS-type names, so address-valued entries keep chain validation (x509/certvalid); the logging.servers documentation now recommends names for this reason. The journal-remote method needs no distinction, as systemd-journal-upload verifies the URL host against the certificate either way.
The TLS forwarding actions run in rsyslog's main queue by default, so a
log server that stops reading (as opposed to one that is down, which
merely suspends the action) blocks the omfwd send and with it every
other action on the node, including local log files. Give each
forwarding action a bounded in-memory queue so an unreachable or hung
receiver costs at most the queued messages: local logging continues,
messages buffer across shorter outages and are dropped only once the
queue fills. The non-TLS UDP method needs no queue, as it cannot block.
The minimal receiver examples run into two rsyslog defaults well below
the cluster sizes confluent deploys: imtcp refuses more than 200
concurrent connections, so most of a larger cluster of TLS forwarders
(one persistent connection each) cannot connect at all, and omfile
caches only 10 dynafile handles, reopening a file for nearly every
message once logs from many nodes interleave. Size both for clusters on
the order of 4k nodes, reap dead sessions with TCP keepalive, absorb
bursts (whole racks booting, reconnect storms after a receiver restart)
with more UDP receiver threads, a larger receive buffer and a dedicated
queue that also keeps node traffic and the server's own logging from
delaying each other, and batch the file writing asynchronously. All
parameters are accepted by the oldest rsyslog among the supported
distributions (8.2312 in Ubuntu 24.04); imtcp workerthreads is not, so
the receiver setup helper probes for it and enables it where available
rather than placing it in the example.
The forwarding certificate was issued once during deployment, so with
the default 47 day pubkeys.tls_lifetime the log forwarding silently
stopped when it expired, and the documented workaround of a multi-year
lifetime directly worsened the lack of revocation in the log
transports. Have setuplogging install a renewal script and a daily
randomized systemd timer that requests a fresh certificate through the
deployment API once less than half of the validity remains.
A failed renewal never disturbs the material in use: the replacement
is staged beside the live files and only swapped in, and the consuming
service only restarted, on success.
The plaintext log-forwarding path used UDP (imudp receiver, omfwd
protocol="udp"), which silently drops messages once a burst outruns the
receiver's socket buffer -- exactly the synchronized bursts a large cluster
produces (a whole rack booting, a reconnect storm after the receiver
restarts). Switch it to plain TCP: imptcp on the receiver and protocol="tcp"
on the node side. TCP back-pressures the senders instead of dropping, so
bursts are absorbed rather than lost, and imptcp (unlike imtcp) imposes no
session limit, so every node can hold a persistent connection up to the
receiver's open-file limit. The node side gains the same bounded async retry
queue the TLS path already uses, since a TCP action can block where UDP could
not.

Measured on ~4k simulated senders, imptcp delivered every message losslessly
where imudp shed 50-75% under the same overload, for the cost of one
persistent connection per node.
@Obihoernchen
Obihoernchen marked this pull request as ready for review July 16, 2026 11:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant