Kubetail is a new project I've been working on. It's a private, real-time log viewer for Kubernetes clusters. You deploy it inside your cluster and access it via a web browser, like the Kubernetes Dashboard.
Using kubetail, you can view logs in real-time from multiple Workload containers simultaneously. For example, you can view all the logs from the Pod containers running in a Deployment and the UI will update automatically as the pods come into and out of existence. Kubetail uses your in-cluster Kubernetes API so your logs are always in your possession and it's private by default.
Currently you can filter logs based on node properties such as availability zone, CPU architecture or node ID and we have plans for a lot more features coming up.
Here's a live demo: https://www.kubetail.com/demo
Check it out and let me know what you think!
Andres
The niche between "easy to get but single-container and no search" on one side and "install with helm but search all containers including historical with full-text and metrics" on the other... seems like a tiny niche to me.
edit: oh you need to install Kubetail cluster-wide too. At least no DaemonSet I guess.
Kibana needs Elasticsearch
I'm not sure if this has good enough log viewing https://github.com/kubernetes/dashboard
Personally I don't see the point of doing a little less work (still a Helm chart) to install Kubetail instead, if I'm trading search, metrics, and history.
Which is also cool! You're obviously both inspired by Unix `tail`. I wonder if we will get a POSIX/Linux layer on top of Kubernetes ... where pods/services somehow map to processes/systemd etc. ;)
I believe there is no persistence, or does it cache in local storage or anything on the client? Would be awesome to have that option for client side storage for perhaps 24 hours.
Currently, there's no persistence. I'll think about how to enable client-side.
Take a look at using the more performant and powerful IndexedDB instead of local storage.
https://github.com/kubetail-org/kubetail
as an open source repo?
I suppose it is never too late :)
- it supports `ETag`s, with ETags derived from
a file's st_dev, st_ino, and inode generation
number
- it supports setting *some* response headers via
xattrs (e.g., ETag, Content-Type, Vary,
Cache-Control, etc.)
- it supports conditional requests (i.e.,
`If-Match:`, `If-None-Match:`,
`If-Modified-Since:`)
- it supports `Range:` requests
- for `Range: bytes=${offset}-` `GET`s
the response does not finish (i.e.,
final chunk is not sent) until one of
- the file is unlinked
- the file is renamed
- the server is terminated
using inotify to find out about file
unlinks/renames
It does this using `epoll`, `inotify`, and `sendfile()`, with multiple fully-evented, async-I/O-using processes, each process being single-threaded. It is written in C in continuation passing style (CPS) with tiny continuations, so its memory footprint per client is also tiny. As a result it is blazingly fast, though it needs to be fronted with a reverse proxy for HTTPS (e.g., Nginx, Envoy, ...), sadly, but maybe I could teach it to use kssl.I use it for tailing logs remotely, naturally, and as a poor man's Kafka. Between regular file byte offsets, ETags, and conditional requests one can build a reliable event publication system with this `tailfhttpd`. For example, and event stream can name the next instance ({local-part, ETag}) then be renamed out of the way to end in-progress `GET`s, and clients can resume from the new file.
With a few changes it could "tail" (watch) directories, and even allow `POST`ing events (which could be done by writing to a pipe the reader of which routes events to files that get served by `tailfhttpd`).
Because `tailfhttpd` just serves files, and because of the ETag thing, conditional requests, and xattrs, it's very easy to build more complex systems on top of it -- even shell scripts will suffice.
This chunked-encoding, "hanging-GET" thing is so unreasonably effective and cheap that I'm surprised how few systems support it.
I've visions of rewriting it in Rust and supporting H2 and especially H3/QUIC to reduce the per-client load (think of TCP TCBs and buffers) even more, and using io_uring instead of epoll for even better performance.
Oh, and this approach is fully standards-compliant. It's just a chunked-encoding, indefinite-end ("hanging") GET with all the relevant (but optional) behaviors (ETags, conditional requests, range requests, even the right end of the byte-range being left unspecified is within spec!).