<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DevOps on cache cascade</title><link>https://blog.taigrr.com/categories/devops/</link><description>Recent content in DevOps on cache cascade</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><managingEditor>tai@taigrr.com (Tai Groot)</managingEditor><webMaster>tai@taigrr.com (Tai Groot)</webMaster><lastBuildDate>Tue, 07 Nov 2023 19:17:25 +0600</lastBuildDate><atom:link href="https://blog.taigrr.com/categories/devops/index.xml" rel="self" type="application/rss+xml"/><item><title>Introducing grlx</title><link>https://blog.taigrr.com/blog/introducing-grlx/</link><pubDate>Tue, 07 Nov 2023 19:17:25 +0600</pubDate><author>tai@taigrr.com (Tai Groot)</author><guid>https://blog.taigrr.com/blog/introducing-grlx/</guid><description>&lt;h2 id="background"&gt;Background&lt;/h2&gt;
&lt;p&gt;In a
&lt;a
href="https://blog.taigrr.com/blog/so-long-salt-project/"
target="_blank"
&gt;recent blog post&lt;/a
&gt;, I discussed a few of the reasons why in 2021, I began working on a new Fleet Configuration Management tool to replace SaltStack.
However, I did not go into much detail about what the replacement is, how it works, or the roadmap into the future.&lt;/p&gt;
&lt;p&gt;As mentioned in the prior post, the first inspiration to build a new tool arose from requirements regarding constrained memory environments.
In our typical install, salt-minion at idle required between 140mb and 300mb of memory.
(This wide variance in metrics results from several factors including the method of measurement, the use case, the system uptime, the service uptime, and the versions of salt-minion and python being run.
Regardless, this is simply too much memory for salt to be usable in many situations.)&lt;/p&gt;
&lt;p&gt;For widely-deployed, 1GB IoT systems, sacrificing between 10-30% of all available memory for a background task is not ideal.
But in a world where even
&lt;a
href="https://www.gsmarena.com/google_pixel_watch_2-12547.php"
target="_blank"
&gt;wrist watches ship with 2GB of RAM&lt;/a
&gt;, and IoT components are getting cheaper by the month, maybe 300mb is not that big of a deal?&lt;/p&gt;
&lt;p&gt;For the virtual machine use case, I’d argue it’s still very important.
Linode (now Akamai) offers VPS systems starting at 1GB/mo.
Amazon Lightsail’s smallest offering comes with only half a gigabyte of memory.
Imagine trying to scale horizontally across many nodes only for half of the memory you paid for to be eaten up by a system management tool running in the background.&lt;/p&gt;
&lt;p&gt;Without repeating too much from the prior blogpost, I challenge the reader to pause for a moment and consider the hurdles with their own configuration management software, memory requirements aside: how easy was it to get started?
What kind of maintenance is required to keep things running and secured?
Does it break?
How often?
What is the DX (Developer eXperience) like?
Is the current solution easy (and safe!) to use at 2am for an emergency rollback from your parents’ house on holiday?&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;When I set out to build this tool from scratch, I saw it as a golden opportunity to not only solve existing problems but also to shape the tool according to my vision.
The goal was clear: to develop a tool that functions seamlessly, aligning to the needs of the landscape, including the creature comforts missing from other options.
It should be low overhead, offer familiarity with existing tools, be secure by default, easily scalable, and resilient to OS upgrades (read: runtime dependency-free).&lt;/p&gt;
&lt;h2 id="introducing-grlx---effective-fleet-configuration-management"&gt;Introducing grlx - Effective Fleet Configuration Management&lt;/h2&gt;
&lt;p&gt;Without any further introduction, here are some of the major issues we are looking to address in &lt;a class="grlx"&gt;&lt;/a&gt; grlx compared to other tools:&lt;/p&gt;
&lt;h4 id="low-overhead"&gt;Low Overhead&lt;/h4&gt;
&lt;p&gt;I&amp;rsquo;ve mentioned this one a lot already, but it bears repeating.
The primary reason that drove us to pursue building &lt;a class="grlx"&gt;&lt;/a&gt; grlx was the unavoidable memory footprint of the interpreted language ecosystems.
While our first choice was to simple take an existing tool and fork it, paring down the featureset and optimizing memory, we quickly realized this would be an exercise in futility&amp;ndash;we might see slight improvement, but nothing on the order of magnitude we were hoping for.
The CPU usage of &lt;a class="grlx"&gt;&lt;/a&gt; grlx should also be lower for the same reason: no JIT compilation or JVM (looking at you, Closure) taking up intermediate cycles.&lt;/p&gt;
&lt;h4 id="dependency-free-by-default"&gt;Dependency-free by default&lt;/h4&gt;
&lt;p&gt;A tool written in Python or Ruby depends on the environment&amp;rsquo;s Python and Ruby packages for its own stability.
When a primary goal of a system and configuration management tool is to keep the system up to date, and updating the system involves updating system libraries such as Python or Ruby libraries, there is always a small but non-zero risk that a breakage in the ecosystem APIs will crash the management tool and prevent it from restarting, leaving the node (or worse, the whole fleet) stranded and unresponsive.
&lt;a
href="https://docs.python.org/3/whatsnew/3.7.html"
target="_blank"
&gt;Python 3.7&lt;/a
&gt; for example, introduced new reserved words to the language (&lt;code&gt;await&lt;/code&gt; and &lt;code&gt;async&lt;/code&gt;) which subsequently broke many packages that hadn&amp;rsquo;t been updated in time.
Typically, these ecosystems move slowly enough for maintainers to update in time, but it&amp;rsquo;s never a good idea to be stuck between waiting for a new software release and keeping your ecosystem out-of-date and vulnerable to prevent breakages.&lt;/p&gt;
&lt;h4 id="scalable-and-fault-tolerant"&gt;Scalable and Fault-tolerant&lt;/h4&gt;
&lt;p&gt;Built using NATS.io, &lt;a class="grlx"&gt;&lt;/a&gt; grlx can take advantage of NATS&amp;rsquo;s clustering and fault-tolerance features.
Using only a single farmer system, you can join several more NATS Server instances to the cluster and have them all share the load of incoming messages.
Read more about NATS clustering
&lt;a
href="https://docs.nats.io/nats-server/configuration/clustering"
target="_blank"
&gt;here&lt;/a
&gt;.&lt;/p&gt;
&lt;p&gt;Future additions to &lt;a class="grlx"&gt;&lt;/a&gt; grlx will allow for a single sprout to connect to multiple independent farmers, to allow for failover across control servers.&lt;/p&gt;
&lt;h4 id="secure-by-default"&gt;Secure by default&lt;/h4&gt;
&lt;p&gt;Did you know that it&amp;rsquo;s a violation of
&lt;a
href="https://docs.saltproject.io/en/latest/topics/hardening.html"
target="_blank"
&gt;SaltStack best practices&lt;/a
&gt; (specifically the linked Hardening Rules page) to use Salt over the internet without taking precautionary encryption measures?
It commonly recommended to use a tool like
&lt;a
href="https://www.stunnel.org/"
target="_blank"
&gt;stunnel&lt;/a
&gt; or
&lt;a
href="https://blog.taigrr.com/blog/provisioning-wireguard/"
target="_blank"
&gt;WireGuard&lt;/a
&gt;® to add an extra layer between minions and the master.&lt;/p&gt;
&lt;p&gt;With &lt;a class="grlx"&gt;&lt;/a&gt; grlx, there&amp;rsquo;s no need for a third-party encryption suite to stay secure.
All communications from cli to farmer, and from farmer to sprout, are encrypted using self-signed
&lt;a
href="https://github.com/gogrlx/grlx/blob/master/certs/tls.go"
target="_blank"
&gt;TLS certificates&lt;/a
&gt; and
&lt;a
href="https://docs.nats.io/running-a-nats-service/configuration/securing_nats/auth_intro/nkey_auth"
target="_blank"
&gt;NATS.io NKey encryption&lt;/a
&gt;.
These certificates are pinned to the clients on first connection as an extra security precaution.&lt;/p&gt;
&lt;h4 id="easy-to-set-up"&gt;Easy to set up&lt;/h4&gt;
&lt;p&gt;Easy to automate.
Need it be said again?
Only one binary (and one configuration file) is required to provision a sprout (node).&lt;/p&gt;
&lt;p&gt;We also offer a
&lt;a
href="https://docs.grlx.dev/docs/bootstrapping"
target="_blank"
&gt;bootstrap script&lt;/a
&gt; hosted at
&lt;a
href="https://bootstrap.grlx.dev"
target="_blank"
&gt;bootstrap.grlx.dev&lt;/a
&gt; that will always get you the latest and greatest release in a simple one-liner, if you so choose.&lt;/p&gt;
&lt;h4 id="easy-to-understand"&gt;Easy to Understand&lt;/h4&gt;
&lt;p&gt;Go is often touted as simple language. All &lt;a class="grlx"&gt;&lt;/a&gt; grlx code is written in Go (except for the Web UI), and we explain how both the overall system and the individual components work in the
&lt;a
href="https://docs.grlx.dev"
target="_blank"
&gt;documentation&lt;/a
&gt;.
Auditing the &lt;a class="grlx"&gt;&lt;/a&gt; grlx codebase is easy, and most of the source code can be read through in a day or so.&lt;/p&gt;
&lt;p&gt;Our non-stdlib build dependencies are selective&amp;ndash;kept to as short a list as reasonably possible, so there&amp;rsquo;s little happening &amp;ldquo;elsewhere.&amp;rdquo;
We follow best practices, strive for high test coverage, and keep an eye on our
&lt;a
href="https://goreportcard.com/report/github.com/gogrlx/grlx"
target="_blank"
&gt;Go report card&lt;/a
&gt;.&lt;/p&gt;
&lt;h4 id="open-source"&gt;Open Source&lt;/h4&gt;
&lt;p&gt;It would be crazy to install a tool on a fleet of systems and give it root access without the ability to do some introspection on what&amp;rsquo;s happening under the hood.
All the source is available
&lt;a
href="https://github.com/gogrlx/grlx"
target="_blank"
&gt;on GitHub&lt;/a
&gt;, where I encourage you to give it a star!&lt;/p&gt;
&lt;p&gt;Not only is &lt;a class="grlx"&gt;&lt;/a&gt; grlx open and free, it&amp;rsquo;s also permissively licensed as
&lt;a
href="https://opensource.org/license/0bsd/"
target="_blank"
&gt;0BSD&lt;/a
&gt; and is therefore compatible with nearly any enterprise company&amp;rsquo;s policy on OSS software.&lt;/p&gt;
&lt;p&gt;Keep in mind, the logos, the mascot (also referred to as &amp;ldquo;Clove&amp;rdquo;), the name &amp;ldquo;grlx&amp;rdquo; itself, and the overall brand are copyrighted, all rights reserved, etc.
Do not try to pass off &lt;a class="grlx"&gt;&lt;/a&gt; grlx as your own&amp;ndash;but forking and renaming is allowed!&lt;/p&gt;
&lt;h4 id="supported-with-corporate-backing-and-buy-in"&gt;Supported with Corporate Backing and Buy-in&lt;/h4&gt;
&lt;p&gt;&lt;a class="grlx"&gt;&lt;/a&gt; grlx has entered into an agreement with
&lt;a
href="https://www.adatomic.com"
target="_blank"
&gt;ADAtomic, Inc.&lt;/a
&gt;, to offer official, commercial support.
If this is something that would be valuable to your company or organization,
&lt;a
href="mailto:grlx@adatomic.com?subject=Commercial%20Support%20Inquiry"
&gt;please contact ADAtomic here&lt;/a
&gt;.&lt;/p&gt;
&lt;p&gt;Additionally, &lt;a class="grlx"&gt;&lt;/a&gt; grlx is already seeing production use from several companies,
&lt;a
href="https://github.com/gogrlx/grlx"
target="_blank"
&gt;listed in the README&lt;/a
&gt;.
As mentioned above, &lt;a class="grlx"&gt;&lt;/a&gt; grlx development is being driven by a real need at our organization, and is seeing heavy usage in our own lineup of products.&lt;/p&gt;
&lt;h4 id="extensible-plugin-system"&gt;Extensible Plugin System&lt;/h4&gt;
&lt;p&gt;To state the obvious, not every possible feature is required by every customer.
To keep &lt;a class="grlx"&gt;&lt;/a&gt; grlx light and fast, all endpoints and features take advantage of dependency injection and there is a well-defined interface already in place for loading plugins at runtime.
These plugins can offer features such as supporting obscure package managers or downloading files from uncommon endpoints.
In short order, two example file endpoint provider plugins will be released, one to download files from IPFS, and another to download from a BitTorrent magnet link.
Hopefully, these examples indicate both the reason for and capability of the plugin system.
Using runtime-loaded plugins is also a boon for development and testing, as mainline code that should be added to &lt;a class="grlx"&gt;&lt;/a&gt; grlx can start as a plugin for development, and get merged over time.&lt;/p&gt;
&lt;p&gt;At first, the plugin interface will only support Go plugins, but support for WASM plugins is on the roadmap, allowing for plugin development in nearly any compiled language.&lt;/p&gt;
&lt;p&gt;To be clear, &lt;a class="grlx"&gt;&lt;/a&gt; grlx &lt;em&gt;is dependency-free by default&lt;/em&gt;, but we recognize there are some use cases where optional plugins may offer increased functionality without adding significant hooks into environmental state.
Both Go and WASM plugins can be distributed as single files, dropped into a directory and hot-reloaded automatically at runtime.&lt;/p&gt;
&lt;h4 id="configurable-message-delivery-rules"&gt;Configurable Message Delivery Rules&lt;/h4&gt;
&lt;p&gt;Some tools only allow for deploys to go out the door to nodes that are online at the time of the push&amp;ndash;if it&amp;rsquo;s not online &lt;em&gt;right now&lt;/em&gt; then you have to either watch and wait for it to come online, or write some scripts to programmatically check for the next time it does come online and push the release then.
In a datacenter, this is not a big deal as you should have extremely high (near 100%) uptime and connectivity between the CNC Server and the nodes.
For an IoT deployment on the other hand, connectivity can be tricky, and the aforementioned scripts must come into use.&lt;/p&gt;
&lt;p&gt;However, once you start writing them, you might realize that there&amp;rsquo;s a lot more involved regarding error checking, reporting, logging, etc., that the simplest &lt;code&gt;while ! online; do sleep 60; done &amp;amp;&amp;amp; push&lt;/code&gt; script cannot handle.
You end up writing a whole deployment framework around trying to catch your node when it&amp;rsquo;s online and push to it at that exact moment, or maybe you add a cron job to the node itself to trigger an agentless or standalone mode periodically.&lt;/p&gt;
&lt;p&gt;This whole mess could have been avoided if the configuration management tool provided a utility for you, which stores the deploy jobs into persistent queues to ensure delivery on next reconnection.
NATS.io&amp;rsquo;s concept of
&lt;a
href="https://docs.nats.io/nats-concepts/jetstream/consumers"
target="_blank"
&gt;Durable Queues&lt;/a
&gt; allows for exactly this behavior.&lt;/p&gt;
&lt;h4 id="rbac"&gt;RBAC&lt;/h4&gt;
&lt;p&gt;&lt;a class="grlx"&gt;&lt;/a&gt; grlx takes a Role-Based Access Control (RBAC) approach for designating who is allowed to deploy what&amp;ndash;and where.
Secured service worker accounts or admins might be allowed root access to all machines.
Your coworker John, who manages some &lt;code&gt;nginx&lt;/code&gt; configurations, can &lt;code&gt;cook&lt;/code&gt; (push out) the &lt;code&gt;nginx&lt;/code&gt; recipe to all sprouts, and Celine has access to &lt;code&gt;cook&lt;/code&gt; all recipes but only on select development/canary nodes.
Future work will allow these roles to come from an LDAP endpoint or other external service provider plugin.&lt;/p&gt;
&lt;p&gt;More information about the RBAC system can be found in the
&lt;a
href="https://docs.grlx.dev/docs/rbac"
target="_blank"
&gt;documentation&lt;/a
&gt;.&lt;/p&gt;
&lt;h3 id="usability-improvement-features"&gt;Usability Improvement Features&lt;/h3&gt;
&lt;p&gt;Below, find some of the small tweaks and differences to make using grlx easier than competing tools:&lt;/p&gt;
&lt;h4 id="advanced-developer-tooling"&gt;Advanced Developer Tooling&lt;/h4&gt;
&lt;p&gt;Our development team is hard at work creating an LSP server and Linter for &lt;a class="grlx"&gt;&lt;/a&gt; grlx.
The roadmap includes support for jumping to import definitions, full syntax highlighting (even in recipe files containing templates!), and property checking.
Our plugin interface also includes definitions to generate custom LSP inputs so that the tools you might need to build in-house are treated as first-class citizens in your editor.&lt;/p&gt;
&lt;h4 id="official-gui-and-tui-built-in"&gt;Official GUI and TUI built-in&lt;/h4&gt;
&lt;p&gt;Many home-grown WebUIs have been built to support existing solutions which don&amp;rsquo;t come with official WebUIs.
The &lt;a class="grlx"&gt;&lt;/a&gt; grlx command line utility will soon support spinning up a local webUI, server over localhost, which can be used to access most functionality.
Communications to the farmer are proxied through the CLI, so there&amp;rsquo;s no need to open up ports on the farmer to access the WebUI.&lt;/p&gt;
&lt;p&gt;A TUI (Terminal UI), built with
&lt;a
href="https://github.com/charmbracelet/bubbletea"
target="_blank"
&gt;BubbleTea&lt;/a
&gt; is on the roadmap.&lt;/p&gt;
&lt;h4 id="optional-dropshell-support"&gt;Optional DropShell Support&lt;/h4&gt;
&lt;p&gt;While &lt;a class="grlx"&gt;&lt;/a&gt; grlx already supports arbitrary command execution, sometimes it happens where you really just need a shell to do some in-depth troubleshooting.
For SaltStack, I developed TunnelBunny, a process for setting up port forwarding and reverse shells to minions, which you can read about
&lt;a
href="https://blog.taigrr.com/blog/tunnelbunny/"
target="_blank"
&gt;here&lt;/a
&gt;.
&lt;a class="grlx"&gt;&lt;/a&gt; grlx will support a similar feature, called DropShell, which will allow you to drop into a shell on a single sprout, from your local machine, without having to open up any ports on the minion, configure SSH, or drop firewall rules.
This feature is still in development, but will be available once RBAC is fully implemented, as it might be a security concern for some organizations.&lt;/p&gt;
&lt;h4 id="high-test-coverage"&gt;High test coverage&lt;/h4&gt;
&lt;p&gt;We strive for 100% test coverage on that parts that matter.
Specifically, all ingredients are thoroughly unit tested, and the core functionality of the platform runs through a suite of integration tests inside of a docker-compose environment.&lt;/p&gt;
&lt;h4 id="no-server-access-required"&gt;No Server Access Required&lt;/h4&gt;
&lt;p&gt;The command line utility is separate from the farmer, and can be run from any machine with network access to the farmer.
All communication is encrypted using TLS and NKey encryption, so there&amp;rsquo;s no need to provide a VPN or SSH tunnel to the farmer.
Depending on company policy or developer preference, the CLI can be run directly on developer machines, or from a dedicated bastion server.
Authentication and authorization is handled on a per-user basis (to support RBAC), so there&amp;rsquo;s no need to share credentials, SSH keys, or configure &lt;code&gt;sudo&lt;/code&gt; access to the main CNC server.&lt;/p&gt;
&lt;h4 id="supports-gitops"&gt;Supports GitOps&lt;/h4&gt;
&lt;p&gt;The command line utility &lt;code&gt;cook&lt;/code&gt; command will soon support a &lt;code&gt;--git&lt;/code&gt; flag, which will tell the &lt;code&gt;farmer&lt;/code&gt; to check out a particular branch, tag, or commit of a git repository, and use the files in that branch as the source of truth for the recipes.
Additionally, the currently checked-out commit, tag, and branch are made available to the recipe files as property variables, so you can use them in your templates should the need arise.
There is also a command to update the recipe&amp;rsquo;s git repository to the latest commit, tag, or branch, and a command to list all available branches, tags, and commits.&lt;/p&gt;
&lt;h4 id="synchronous-job-status-reporting"&gt;Synchronous Job Status reporting&lt;/h4&gt;
&lt;p&gt;One of the most frustrating things about using a configuration management tool is the lack of visibility into what&amp;rsquo;s happening, as it&amp;rsquo;s happening.
When submitting a job, you might get a job ID back for polling, or wait synchronously for the job to finish and see the summary of results but most tools won&amp;rsquo;t let you watch the states finish as they happen.
Most of the time, this is fine, but the few times you need live introspection into why a deploy is stuck, you&amp;rsquo;re out of luck.&lt;/p&gt;
&lt;p&gt;&lt;a class="grlx"&gt;&lt;/a&gt; grlx will soon support a &lt;code&gt;--watch&lt;/code&gt; flag on the &lt;code&gt;cook&lt;/code&gt; command, which will stream the job status to the terminal as it happens, with a live progress bar and summary of results at the end.&lt;/p&gt;
&lt;h4 id="restful-api"&gt;Restful API&lt;/h4&gt;
&lt;p&gt;The farmer exposes a RESTful API for all of its functionality, so you can build your own tools around it.
If you don&amp;rsquo;t like the built-in WebUI, you have the option to build your own!
If you need to build automations around your deployment from a third-party tool, you can do that too!
Everything from &lt;code&gt;cook&lt;/code&gt;ing to command execution is available via the API.&lt;/p&gt;
&lt;p&gt;More information about the API can be found in the
&lt;a
href="https://docs.grlx.dev/docs/api"
target="_blank"
&gt;documentation&lt;/a
&gt;.&lt;/p&gt;
&lt;h4 id="lifecycle-hooks-for-outgoing-webhooks"&gt;Lifecycle Hooks for Outgoing Webhooks&lt;/h4&gt;
&lt;p&gt;Do you need to track one particular step of a deploy for a particular reason?
Maybe you need to know whenever a specific file is created or modified?
Recipe files have a field for providing an upstream webhook URL and JSON body you need sent.
Hooks can also be configured to fire off WebHooks when a deploy starts, fails, or finishes.
Additionally, you can configure a hook to fire when a new sprout is added to the fleet, or when a sprout&amp;rsquo;s online status has changed.&lt;/p&gt;
&lt;p&gt;Introspection and visibility has never been this easy!&lt;/p&gt;
&lt;h4 id="friendly-discord"&gt;Friendly Discord&lt;/h4&gt;
&lt;p&gt;Our Discord invite is open to one and all, where you can chat with the developers of &lt;a class="grlx"&gt;&lt;/a&gt; grlx and get involved in the &lt;a class="grlx"&gt;&lt;/a&gt; grlx community.&lt;/p&gt;
&lt;p&gt;Meet like-minded DevOps professionals and swap ideas about the best way to get something deployed&amp;ndash;or embroil yourself into a flame war over Cloud or On-Prem&amp;ndash;as long as you keep things respectful it&amp;rsquo;s up to you!&lt;/p&gt;
&lt;h4 id="cute-mascot"&gt;Cute Mascot!&lt;/h4&gt;
&lt;center&gt;
&lt;img src="https://blog.taigrr.com/images/post/grlx.jpg" width="200" &gt;
&lt;br&gt;
His name is Clove, isn’t he great?
&lt;/center&gt;
&lt;h3 id="summary"&gt;Summary&lt;/h3&gt;
&lt;p&gt;In summary, I hope this article has presented the litany of reasons for a new tool in the configuration and system management space.
Our roadmap is clear, and we are excited to announce that version 1.0.x is available for download now.
Please see
&lt;a
href="https://www.adatomic.com"
target="_blank"
&gt;ADAtomic.com&lt;/a
&gt; for more information!&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Updating or rolling back production from your parents’ house is not a recommended DevSecOps or GitOps practice, nor am I endorsing it in any way. Ideally, you’ve got canaries and auto-rollbacks, split traffic, staging environments&amp;hellip;
This statement is meant to be humorous, don’t take it literally.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>So Long, Salt Project</title><link>https://blog.taigrr.com/blog/so-long-salt-project/</link><pubDate>Mon, 09 Oct 2023 18:19:25 +0600</pubDate><author>tai@taigrr.com (Tai Groot)</author><guid>https://blog.taigrr.com/blog/so-long-salt-project/</guid><description>&lt;p&gt;This post has been a long time in the making.
Anyone who has followed me and my work for any period of time probably knows by know that I&amp;rsquo;ve been working on &lt;a class="grlx"&gt;&lt;/a&gt;
&lt;a
href="https://grlx.dev/grlx"
target="_blank"
&gt;grlx&lt;/a
&gt; (pronounced &amp;lsquo;garlic&amp;rsquo;) for some time now (since mid-2021).
But why?
What&amp;rsquo;s wrong with SaltStack?
More specifically, what problem am I trying to solve that doesn&amp;rsquo;t already have a solution solved many times over?&lt;/p&gt;
&lt;h4 id="a-note-to-the-salt-project"&gt;A Note to the Salt Project&lt;/h4&gt;
&lt;p&gt;First of all, I want to make something clear: this post is not an attack on Salt, Thomas Hatch, or any of the people involved in the Salt Project.
I&amp;rsquo;ve been a long-time user of SaltStack, going back to the
&lt;a
href="https://docs.saltproject.io/en/latest/topics/releases/2016.3.0.html"
target="_blank"
&gt;Boron release&lt;/a
&gt; in 2016.
SaltStack has gotten me really far, and I owe much of my career&amp;rsquo;s success to Salt, which I have carried with me from job to job.&lt;/p&gt;
&lt;p&gt;I also want to make a call-out here: my use case for Salt is not necessarily the target use case, and it&amp;rsquo;s really unfair to criticize a screwdriver for being a bad hammer, especially when the screwdriver is free.&lt;/p&gt;
&lt;h4 id="real-world-requirements"&gt;Real-world Requirements&lt;/h4&gt;
&lt;p&gt;At my first role as a Salt user, I was not the decision maker.
I was a junior developer, working with the tools selected by peers and higher-ups, and Salt was chosen to be part of our stack.
Without going into too much detail, here was our problem statement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We are building IoT, embedded Linux boards&lt;/li&gt;
&lt;li&gt;We need a way to update the software and packages remotely&lt;/li&gt;
&lt;li&gt;We are using field-prototypes, which don&amp;rsquo;t have fixed or public IPs and therefore need to be the Client in a Client-Server model (agentless solutions won&amp;rsquo;t work)&lt;/li&gt;
&lt;li&gt;We are not just updating application code, our environments are going through rapid updates (emphasis on field &lt;em&gt;prototypes&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Our distribution is a custom Yocto build, without a package manager, so we need a way to declaratively replace system-level packages transactionally&lt;/li&gt;
&lt;li&gt;The ability to remotely run shell commands and return the output is a plus (we might need to trigger fswebcam and snap a photo as a one-off)&lt;/li&gt;
&lt;li&gt;Rolling out instant updates to targeted devices (where a &amp;rsquo;target&amp;rsquo; could be a small sampling, the whole fleet, or a single device) is a huge boon&lt;/li&gt;
&lt;li&gt;Some devices will connect over 3g cellular as not all of our field installations have WiFi available&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As this platform was a product of its time, here&amp;rsquo;s some additional information to keep in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The year is 2016, and the hardware development went back to 2012 (so pre-Raspberry Pi GA)&lt;/li&gt;
&lt;li&gt;Google IoT Core doesn&amp;rsquo;t exist (yet, and also,
&lt;a
href="https://www.iotworldtoday.com/connectivity/google-cloud-to-shut-down-iot-core-service"
target="_blank"
&gt;RIP&lt;/a
&gt;)&lt;/li&gt;
&lt;li&gt;Amazon GreenGrass is not generally available (until 2017)&lt;/li&gt;
&lt;li&gt;Ubuntu Core IoT was prohibitively expensive and didn&amp;rsquo;t support our custom hardware&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SaltStack, in theory, checked all of our boxes, and allowed us to ship units to the field for testing, with remote, OTA updates.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Full Linux support? Check. [x]&lt;/li&gt;
&lt;li&gt;Remote updates using a client / server model to get around the IP contstraints? Check. [x]&lt;/li&gt;
&lt;li&gt;Ability to upgrade system files in addition to application files? Check. [x]&lt;/li&gt;
&lt;li&gt;Remote command execution? Check. [x]&lt;/li&gt;
&lt;li&gt;Specific device targeting? Check. [x]&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And so, our small team set out to create a configuration management system built on top of SaltStack as the center pillar.
Yes, we even managed the SaltStack installation with SaltStack, by replacing the Python libraries and .egg/wheel files with Salt states.
We were careful in how we did this, and actually added a cron-based backdoor &amp;lsquo;rescue&amp;rsquo; service in case the snake swallowed its own tail, but it was a calculated risk.
In the end, the deployment worked, but it wasn&amp;rsquo;t without headaches.&lt;/p&gt;
&lt;h3 id="issues-and-complaints"&gt;Issues and Complaints&lt;/h3&gt;
&lt;h5 id="dependencies"&gt;Dependencies&lt;/h5&gt;
&lt;p&gt;There were several runtime and compile-time bugs related to the dependencies.
Anybody who&amp;rsquo;s been around SaltStack long enough will shudder at the mention of
&lt;a
href="https://github.com/saltstack/salt/issues?q=tornado"
target="_blank"
&gt;Tornado&lt;/a
&gt; or
&lt;a
href="https://github.com/saltstack/salt/issues?q=pycrypto"
target="_blank"
&gt;PyCrypto&lt;/a
&gt;. We were especially subject to the issues regarding
&lt;a
href="https://github.com/saltstack/salt/issues/52674"
target="_blank"
&gt;pycrypto compilation&lt;/a
&gt;, as our Yocto project build ran on ARMv5 (oh whoops, did I not mention that requirement earlier? That sucks, but we&amp;rsquo;re all engineers here and you just have to learn to roll with it&amp;hellip;) and there weren&amp;rsquo;t precompiled wheels for our architecture&amp;ndash;we had to build them ourselves.
Memory was always running low, as we had less than 1GB of physical memory, and most of that needed to go to the application for some on-device image processing.&lt;/p&gt;
&lt;h5 id="crashing"&gt;Crashing&lt;/h5&gt;
&lt;p&gt;There was a memory leak, somewhere, in either &lt;code&gt;salt-minion&lt;/code&gt; itself, or in a dependency.
It was difficult to isolate, and I&amp;rsquo;m not sure my team actually ever found it.
It was likely patched in a later version of &lt;code&gt;salt-minion&lt;/code&gt; (again, or in a bumped dependency).
Our solution was to
&lt;a
href="https://www.freedesktop.org/software/systemd/man/systemd.unit.html#"
target="_blank"
&gt;limit the memory used by systemd&lt;/a
&gt; and tell the unit to crash and restart if it went over.
This was not ideal.
Systemd had no visibilty into how we were using &lt;code&gt;salt-minion&lt;/code&gt;, whether we were killing the process due to a real memory leak or due to a spike in usage associated with an active software update.
It&amp;rsquo;s reasonable to allocate more memory to &lt;code&gt;salt-minion&lt;/code&gt; and away from our application during a software update, but not at the expense of allowing run-away memory usage during regular runtime.
Allowing systemd to indiscriminately OOM &lt;code&gt;salt-minion&lt;/code&gt; becomes even more dangerous if we are currently applying a state to update the system or python libs themselves&amp;ndash;a crash mid-update for core and critical python libraries might prevent &lt;code&gt;salt-minion&lt;/code&gt; itself from ever coming back up.
In the end, we had to isolate the states for the system by themselves and run those states very selectively, not in the top/high state, which somewhat defeats the purpose of the &amp;lsquo;statefulness&amp;rsquo; Salt brings you&amp;ndash;but that&amp;rsquo;s not Salt&amp;rsquo;s fault, as it certainly wasn&amp;rsquo;t designed for that.
Hammer, screwdriver, all that.
Really the problem here was the memory leak itself, as that&amp;rsquo;s the cascading issue.&lt;/p&gt;
&lt;h5 id="connectivity-issues"&gt;Connectivity issues&lt;/h5&gt;
&lt;p&gt;Memory leaks and crashing aside, we had a lot of trouble keeping the zeroMQ connection active.
Now, we did have many systems connected over 3G cellular, but the problems weren&amp;rsquo;t isolated to those units.
Our WiFi-connected units also had issues maintaining connectivity.
The dreaded &lt;code&gt;Minion did not return. [Not connected]&lt;/code&gt; message was a commonplace error.
More disturbing, early versions of Salt didn&amp;rsquo;t allow you to easily configure the retry logic.
Sometimes, the connection would break, and the client wouldn&amp;rsquo;t ever try to reconnect, so it would stay disconnected until the memory leak would trigger an OOM, which would in-turn restart the &lt;code&gt;salt-minion&lt;/code&gt; daemon.
(
&lt;a
href="https://docs.saltproject.io/en/latest/ref/configuration/minion.html#keepalive-settings"
target="_blank"
&gt;This has since been addressed.&lt;/a
&gt;)&lt;/p&gt;
&lt;h5 id="access-control"&gt;Access control&lt;/h5&gt;
&lt;p&gt;Whoever needed to send the updates out to the units in the field needed to be root (or have sudo access to run &lt;code&gt;salt&lt;/code&gt;) on the Salt master, which means someone needed shell access to the CNC server.
From a security perspective, this is an ick.&lt;/p&gt;
&lt;h4 id="i-loved-saltstack"&gt;I loved SaltStack&lt;/h4&gt;
&lt;p&gt;Yes, I&amp;rsquo;ve had my fair share of problems with SaltStack, but my teams and I made things work.
When working with software of this scale, some
&lt;a
href="https://salt.tips/"
target="_blank"
&gt;tips and tricks&lt;/a
&gt; tend to reveal themselves over time, (like using
&lt;a
href="https://docs.saltproject.io/en/latest/ref/modules/all/salt.modules.cp.html#salt.modules.cp.get_template"
target="_blank"
&gt;get_template&lt;/a
&gt; to pre-render salt states before applying).
Sometimes, you just need the
&lt;a
href="https://github.com/saltstack/salt/issues/55269"
target="_blank"
&gt;tribal knowledge gained through experience&lt;/a
&gt;.
Several issues were fixed by the Salt Project team, others have gone away simply through a revision to requirements on my end, and still others I&amp;rsquo;ve learned to live with or work around.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve brought SaltStack with me to 4 other career roles since my introduction to it, like some kind of DevOps Evangelist (I&amp;rsquo;ll likely write about these projects at a later date).
I didn&amp;rsquo;t have enough good things to say about Salt.
I became very involved in the
&lt;a
href="https://saltstackcommunity.slack.com/"
target="_blank"
&gt;community Slack channels&lt;/a
&gt;.
I answered a question or two on
&lt;a
href="https://stackoverflow.com/questions/42519060/how-to-get-minion-id-from-jinja-script-inside-a-salt-state"
target="_blank"
&gt;Stack Overflow&lt;/a
&gt; regarding SaltStack.
I&amp;rsquo;ve had a minor
&lt;a
href="https://github.com/saltstack/salt-bootstrap/pull/1502"
target="_blank"
&gt;PR merged into salt-bootstrap&lt;/a
&gt;.
I&amp;rsquo;ve been featured on the
&lt;a
href="https://www.youtube.com/watch?v=sl3DxxnYf5M"
target="_blank"
&gt;Salt Community Open Hour podcast&lt;/a
&gt;.
The
&lt;a
href="https://saltproject.io/security-announcements/2020-04-21-advisory/index.html"
target="_blank"
&gt;project called me out&lt;/a
&gt; in an advisory bulletin to thank me for my help on
&lt;a
href="https://saltexploit.com"
target="_blank"
&gt;CVE-2020-11651 and CVE-2020-11652&lt;/a
&gt;.&lt;/p&gt;
&lt;h4 id="acquisition-heartache"&gt;Acquisition Heartache&lt;/h4&gt;
&lt;p&gt;In October, 2020, VMware
&lt;a
href="https://blogs.vmware.com/management/2020/10/vmware-completes-saltstack-acquisition-to-bolster-software-configuration-management-and-infrastructure-automation.html"
target="_blank"
&gt;acquired SaltStack&lt;/a
&gt;, and the branding was changed to
&lt;a
href="https://saltproject.io/"
target="_blank"
&gt;Salt Project&lt;/a
&gt;.
Large portions of the team were made redundant (read: laid off) and the focus of the project seems to have shifted to cloud-native and VMware-related projects.
The name change alone causes a bit of a headache.
The
&lt;a
href="https://www.saltproject.org/"
target="_blank"
&gt;Salt Project&lt;/a
&gt; is already a(n entirely unrelated) thing.
Changing from &amp;ldquo;SaltStack&amp;rdquo; to &amp;ldquo;Salt&amp;rdquo; makes finding security issues difficult when
&lt;a
href="https://salt.security/"
target="_blank"
&gt;SALT&lt;/a
&gt; exists.
The overall &amp;ldquo;Googleability&amp;rdquo; of the project has gone downhill, which really isn&amp;rsquo;t great when some of the
&lt;a
href="https://docs.saltproject.io/topics/releases/2014.1.0.html"
target="_blank"
&gt;page redirects are broken&lt;/a
&gt; for
&lt;a
href="https://github.com/saltstack/salt/releases?page=14"
target="_blank"
&gt;all pre-hydrogen releases&lt;/a
&gt;.&lt;/p&gt;
&lt;p&gt;The number of unresolved issues in the project have skyrocketed (even despite the
&lt;a
href="https://github.com/saltstack/salt/issues?q=label%3Astale&amp;#43;is%3Aclosed"
target="_blank"
&gt;stale bot&lt;/a
&gt; doing numbers on these issues).
It seems the reduced team size and increasing other priorities has prevented development from keeping up with security and bugfixes in some dependencies, and the &amp;lsquo;solution&amp;rsquo; is to freeze the updates and vendor the dependencies.
That&amp;rsquo;s right,
&lt;a
href="https://github.com/saltstack/salt/commit/4baea1a97be0389fabe5307d084579134a1f9b7a"
target="_blank"
&gt;until recently&lt;/a
&gt;, SaltStack has been vendoring a copy of the Tornado library, despite
&lt;a
href="https://security.snyk.io/package/pip/tornado"
target="_blank"
&gt;publicly-known CVEs&lt;/a
&gt;.&lt;/p&gt;
&lt;p&gt;Salt has also recently changed their packaging format to
&lt;a
href="https://docs.saltproject.io/salt/install-guide/en/latest/topics/upgrade-to-onedir.html"
target="_blank"
&gt;Onedir&lt;/a
&gt;, effectively vendoring all dependencies inside of a single folder (including python itself).
While this sounds great on the surface, keep in mind it will prevent non-breaking, API-compliant hotfix changes from making it down to the user through their system package managers, so users are now completely at the mercy of the Salt Project&amp;rsquo;s timelines and priorities, and their responsiveness record there is&amp;hellip;not perfect in my opinion.&lt;/p&gt;
&lt;h4 id="where-to-go-from-here"&gt;Where To Go From Here&lt;/h4&gt;
&lt;p&gt;Perhaps now you see why I&amp;rsquo;ve started &lt;a class="grlx"&gt;&lt;/a&gt;
&lt;a
href="https://grlx.dev"
target="_blank"
&gt;grlx&lt;/a
&gt;.
I need to fill a SaltStack-sized hole in my heart; build a tool that solves all the same problems Salt did for me, but also address my own issues with the tool.
&lt;code&gt;grlx&lt;/code&gt; will never have 1:1 feature parity with SaltStack, especially as the Salt Project focus shifts to VMware first-party products and integrations, but for people like me, that&amp;rsquo;s a pro, not a con.
In &lt;code&gt;grlx&lt;/code&gt;, our goal is to support all the things that make SaltStack great&amp;ndash;the extensibility, human-readable configuration as code, lightning fast remote execution&amp;ndash;and do it with a small footprint, secure by default.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s my feeling that SaltStack probably isn&amp;rsquo;t to blame for its memory usage either&amp;ndash;it is written in Python, and that&amp;rsquo;s just the price paid for an interpeted language.
For this reason, among others, &lt;code&gt;grlx&lt;/code&gt; is written in
&lt;a
href="https://go.dev/"
target="_blank"
&gt;Go&lt;/a
&gt;, a compiled language.
Similarly, the connectivity issues are likely not part of the Salt codebase, and are probably part of the zeroMQ dependency.
For &lt;code&gt;grlx&lt;/code&gt;, we&amp;rsquo;re using
&lt;a
href="https://nats.io/"
target="_blank"
&gt;NATS.io&lt;/a
&gt; instead, and we&amp;rsquo;ve even
&lt;a
href="https://github.com/nats-io/nats-server/pull/2341"
target="_blank"
&gt;submitted code upstream&lt;/a
&gt; in an attempt to be good Open Source stewards.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;d like to follow the development of &lt;a class="grlx"&gt;&lt;/a&gt; grlx, there are several ways you can do so.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We have a
&lt;a
href="https://x.com/gogrlx"
target="_blank"
&gt;Twitter/X account here&lt;/a
&gt;.&lt;/li&gt;
&lt;li&gt;We have a
&lt;a
href="https://discord.com/invite/VruAThf"
target="_blank"
&gt;community discord&lt;/a
&gt;!&lt;/li&gt;
&lt;li&gt;You can also star our project
&lt;a
href="https://github.com/gogrlx/grlx"
target="_blank"
&gt;on GitHub&lt;/a
&gt; using the button below:
&lt;br&gt;
&lt;br&gt;
&lt;a class="github-button" href="https://github.com/gogrlx/grlx" data-size="large" data-show-count="true" aria-label="Star gogrlx/grlx on GitHub"&gt;Star&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ll also be releasing several posts in the coming weeks going into more detail about the features and roadmap for &lt;a class="grlx"&gt;&lt;/a&gt; grlx, so hit that RSS button at the top of the page to make sure you don&amp;rsquo;t miss anything!&lt;/p&gt;
&lt;script async defer src="https://buttons.github.io/buttons.js"&gt;&lt;/script&gt;</description></item></channel></rss>