<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Rafe Murray Blog</title>
        <link>https://rafemurray.ca/blog</link>
        <description>Rafe Murray Blog</description>
        <lastBuildDate>Thu, 10 Sep 2026 16:40:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Setting up Observability for Kubernetes]]></title>
            <link>https://rafemurray.ca/blog/2026/09/10/jma-observability</link>
            <guid>https://rafemurray.ca/blog/2026/09/10/jma-observability</guid>
            <pubDate>Thu, 10 Sep 2026 16:40:00 GMT</pubDate>
            <description><![CDATA[Kubernetes is a great way to host containerized applications across multiple]]></description>
            <content:encoded><![CDATA[<p>Kubernetes is a great way to host containerized applications across multiple
nodes (VMs). However, the distributed nature of these workloads can make them
hard to monitor and debug. That's where an observability stack comes in. It
provides a way of describing application performance and internal state across
distributed architectures using three "pillars": metrics, logs, and traces.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_JcbC" id="opentelemetry">OpenTelemetry<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#opentelemetry" class="hash-link" aria-label="Direct link to OpenTelemetry" title="Direct link to OpenTelemetry" translate="no">​</a></h2>
<p>OpenTelemetry (OTel) is an open standard for logs, metrics, and traces. It
defines a standard format to export these signals, a set of attributes that they
should use, and provides language SDKs for most popular languages. An important
feature compared to other stacks and standards is that it uses the same
attributes (as appropriate) for all three signals. This makes it easy to
correlate between them when debugging an application. Across the industry, it is
being widely adopted. Existing stacks have added support and new stacks ship
with native support out of the box.</p>
<h2 class="anchor anchorTargetStickyNavbar_JcbC" id="notable-observability-stacks">Notable Observability Stacks<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#notable-observability-stacks" class="hash-link" aria-label="Direct link to Notable Observability Stacks" title="Direct link to Notable Observability Stacks" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_JcbC" id="lgtm">LGTM<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#lgtm" class="hash-link" aria-label="Direct link to LGTM" title="Direct link to LGTM" translate="no">​</a></h3>
<p>The LGTM stack consists of Loki, Grafana, Tempo, and Mimir. It, and its
variations swapping out one or more components, is probably the most
industry-standard open source observability stack. Loki handles the logs,
Grafana the visualization, Tempo the traces, and Mimir the metrics. It is
supported by Grafana Labs, and offers enterprise support contracts. Common
substitutions include Jaeger for traces and Prometheus for metrics.</p>
<h3 class="anchor anchorTargetStickyNavbar_JcbC" id="elk">ELK<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#elk" class="hash-link" aria-label="Direct link to ELK" title="Direct link to ELK" translate="no">​</a></h3>
<p>The ELK stack consists of Elasticsearch, Logstash and Kibana. It has been around
for a while, but it primarily focuses on logging. Elasticsearch acts as the
database, indexing, storing, and querying the logs. Logstash is the data
processing pipeline that transforms the various log sources and formats into a
standard set of attributes. Finally, Kibana provides the frontend and
visualization for the logs. ELK is still a useful, industry-standard stack for
logs, but lacks the additional features of a full OTel stack, so users need to
deploy separate services (e.g., Prometheus and Jaeger) if they want to also
collect metrics and traces.</p>
<h3 class="anchor anchorTargetStickyNavbar_JcbC" id="signoz">Signoz<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#signoz" class="hash-link" aria-label="Direct link to Signoz" title="Direct link to Signoz" translate="no">​</a></h3>
<p>Signoz is an all-in-one observability stack. It stores logs, metrics, and traces
in a ClickHouse database, and offers visualization capabilities on top of it.</p>
<h3 class="anchor anchorTargetStickyNavbar_JcbC" id="openobserve">OpenObserve<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#openobserve" class="hash-link" aria-label="Direct link to OpenObserve" title="Direct link to OpenObserve" translate="no">​</a></h3>
<p>OpenObserve is another all-in-one observability stack. It uses a single
rust-based binary to manage all of the observability pillars, storing them
either in a local SQLite database or in Postgres.</p>
<h3 class="anchor anchorTargetStickyNavbar_JcbC" id="datadog">Datadog<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#datadog" class="hash-link" aria-label="Direct link to Datadog" title="Direct link to Datadog" translate="no">​</a></h3>
<p>Datadog is a proprietary, enterprise-level observability platform. It provides
an agent that you install into your cluster which then exports your
observability data to their cloud. It has very easy setup, and you can pay for
extra support. However, this premium support and their hosting comes with a
higher price tag. The price scales per node, user, and feature.</p>
<h3 class="anchor anchorTargetStickyNavbar_JcbC" id="new-relic">New Relic<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#new-relic" class="hash-link" aria-label="Direct link to New Relic" title="Direct link to New Relic" translate="no">​</a></h3>
<p>New Relic is similar to Datadog, but with more of a focus on Application
Performance Monitoring than infrastructure monitoring. Its pricing is
additionally billed per user seat and ingestion volume, rather than also by
host. This means that for complex setups it can be cheaper.</p>
<h2 class="anchor anchorTargetStickyNavbar_JcbC" id="our-implementation">Our Implementation<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#our-implementation" class="hash-link" aria-label="Direct link to Our Implementation" title="Direct link to Our Implementation" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_JcbC" id="requirements">Requirements<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#requirements" class="hash-link" aria-label="Direct link to Requirements" title="Direct link to Requirements" translate="no">​</a></h3>
<p>JMA Consulting is a very small company, which doesn't specialize in Kubernetes.
As such, we had a set of requirements which was slightly different than many
other companies setting up observability. Our requirements were:</p>
<ul>
<li class=""><strong>Industry Standard</strong>. We wanted to be using a widely adopted piece of
software so that if issues arose, we could get community support.</li>
<li class=""><strong>Simple to set up and maintain</strong>. We only have a small number of engineers,
so we can't afford to have someone spend a significant amount of time
maintaining an observability stack</li>
<li class=""><strong>Relatively cheap</strong>. As a small company, JMA Consulting only has so much
budget that it can throw at observability, so ideally we can avoid high costs.</li>
<li class=""><strong>Secure</strong>. Our observability stack contains internal information about our
infrastructure, so we do not want it to be compromised.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_JcbC" id="decision-signoz">Decision: Signoz<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#decision-signoz" class="hash-link" aria-label="Direct link to Decision: Signoz" title="Direct link to Decision: Signoz" translate="no">​</a></h3>
<p>For our requirements, we decided that Signoz was the right choice for us.
Datadog and New Relic were too expensive. An LGTM or ELK stack introduced too
much operational overhead. And OpenObserve was too untested, lacking the size of
community that the other solutions offered. We found that Signoz gave us a good
middle ground: lower up-front costs because we self-hosted, and less operational
overhead since it can be deployed from a single helm chart. It is worth noting
that we determined it would cost less overall than an enterprise solution
because we don't expect to need to significantly scale its deployment, which
might not be the case in other small companies, for example, at a startup.</p>
<h3 class="anchor anchorTargetStickyNavbar_JcbC" id="architecture">Architecture<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#architecture" class="hash-link" aria-label="Direct link to Architecture" title="Direct link to Architecture" translate="no">​</a></h3>
<p>We deployed Signoz on our staging cluster, since we decided to only run two
clusters (we felt we didn't have sizeable enough workloads to justify a third
cluster for observability/tooling). We then deployed the OTel collector as an
agent and deployment in both the production and staging clusters. The agent
(DaemonSet) collects the logs and host metrics from each Node, while the
deployment collects metrics and events from the Kubernetes API Server.</p>
<p>We then needed to get the observability data from the production cluster to the
staging cluster. This requires authentication and authorization so that
malicious actors can't overwhelm our observability stack. We opted for HTTP
basic auth, since it is simple to set up for a small number of users. We
encrypted traffic with TLS terminated at the Gateway level in the staging
cluster. We deployed an additional OTel collector in each cluster: one in the
production cluster to aggregate the data and forward it, and one in the staging
cluster to receive it and export it to Signoz. You can see a diagram of it
below:</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_JcbC" id="conclusion">Conclusion<a href="https://rafemurray.ca/blog/2026/09/10/jma-observability#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" translate="no">​</a></h2>
<p>In this article I shared how we set up observability for our Kubernetes
clusters, our considerations when choosing a stack, and our final architecture.
What would you do differently for your own observability setup?</p>]]></content:encoded>
            <category>Kubernetes</category>
            <category>Observability</category>
        </item>
    </channel>
</rss>