<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Scott&#39;s Weblog </title>
    <link>https://blog.scottlowe.org/</link>
    <language>en-us</language>
    <author>Scott Lowe</author>
    <rights>(C) 2024</rights>
    <updated>2026-03-04 17:30:00 -0500 EST</updated>

    
      <item>
        <title>Using Mitmproxy to Observe kubectl Traffic</title>
        <link>https://blog.scottlowe.org/2026/03/04/using-mitmproxy-to-observe-kubectl-traffic/</link>
        <pubDate>Wed, 04 Mar 2026 17:30:00 EST</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2026/03/04/using-mitmproxy-to-observe-kubectl-traffic/</guid>
        <description>&lt;p&gt;When I first started learning Kubernetes, I had the idea that observing the network traffic between a client system using &lt;code&gt;kubectl&lt;/code&gt; and the Kubernetes API Server would be a useful thing to do. The source of the idea is unclear; I am unsure why I thought this would be useful as a learning tool. Regardless, I continued on with learning Kubernetes and never really pursued this idea&amp;mdash;until this week. I found it can be a useful troubleshooting technique, but I will leave it up to you to determine if it is a useful learning technique. In this post, I will show you how to observe &lt;code&gt;kubectl&lt;/code&gt; traffic using &lt;code&gt;mitmproxy&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This technique is inspired by/informed by &lt;a href=&#34;https://ahmet.im/blog/kubectl-man-in-the-middle/&#34;&gt;Ahmet Alp Balkan&amp;rsquo;s similarly-named blog post from 2019&lt;/a&gt;. Unfortunately, I found the instructions there to be incomplete (most likely just due to the passage of time and continued evolution of the tools involved).&lt;/p&gt;
&lt;p&gt;I used the following tools and environments in my testing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The tests were conducted on a Linux system running &lt;a href=&#34;https://ubuntu.com/&#34;&gt;Ubuntu&lt;/a&gt; 24.04.4. The commands should work similarly on macOS.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.mitmproxy.org/&#34;&gt;Mitmproxy&lt;/a&gt; was installed from the Ubuntu repositories using &lt;code&gt;apt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kubectl&lt;/code&gt; version 1.33.3 was used to communicate to a self-managed cluster on AWS (in other words, &lt;em&gt;not&lt;/em&gt; Amazon EKS) running &lt;a href=&#34;https://kubernetes.io/&#34;&gt;Kubernetes&lt;/a&gt; 1.32.9. The cluster was bootstrapped using &lt;code&gt;kubeadm&lt;/code&gt;. I wouldn&amp;rsquo;t expect any major/significant differences with other versions of &lt;code&gt;kubectl&lt;/code&gt; or Kubernetes.&lt;/li&gt;
&lt;li&gt;I was using a client certificate to authenticate to Kubernetes. It&amp;rsquo;s unclear to me how this might work&amp;mdash;if it works at all&amp;mdash;with alternate authentication mechanisms.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;prepare-client-certificates&#34;&gt;Prepare Client Certificates&lt;/h2&gt;
&lt;p&gt;Before you can start mitmproxy, you&amp;rsquo;ll first need to extract the client certificates from the Kubeconfig file. A couple of ways exist to do this; &lt;a href=&#34;https://blog.scottlowe.org/2022/08/09/revisiting-x509-certificates-in-kubeconfig-files/&#34;&gt;a blog post of mine from 2022&lt;/a&gt; contains what I believe is the &lt;em&gt;easiest&lt;/em&gt; way. The method involves &lt;code&gt;yq&lt;/code&gt; (to extract information from the Kubeconfig) and &lt;code&gt;base64&lt;/code&gt; (to decode the client certificate and client key). Refer to the linked blog post for full details.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First, extract the client certificate (adjust the &lt;code&gt;users[0]&lt;/code&gt; as needed based on the Kubeconfig file):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.users[0].user.client-certificate-data&amp;#39;&lt;/span&gt; &amp;lt; kubeconfig | base64 -d &amp;gt;&amp;gt; client-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next, extract the client key:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;users[0].user.client-key-data&amp;#39;&lt;/span&gt;&amp;lt; kubeconfig | base64 -d &amp;gt;&amp;gt; client-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;running-mitmproxy-and-watching-traffic&#34;&gt;Running Mitmproxy and Watching Traffic&lt;/h2&gt;
&lt;p&gt;Now that you have the client certificate and key in hand, you&amp;rsquo;re ready to launch mitmproxy and observe some traffic. Mitmproxy requires a few specific configuration flags for this use case:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You&amp;rsquo;ll need to disable HTTP/2 support with &lt;code&gt;--set http2=false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Mitmproxy must be configured with the client certificate you extracted above (using &lt;code&gt;--set client_certs=client-cert.pem&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;In this particular case, since the cluster CA isn&amp;rsquo;t trusted, mitmproxy also has to be told not to verify the upstream certificate with &lt;code&gt;--set ssl_insecure=true&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Putting all this together, the full command looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mitmproxy -p &lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt; --set ssl_insecure&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;true --set http2&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;false --set client_certs&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;client-cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, in a separate window, run your &lt;code&gt;kubectl&lt;/code&gt; command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTPS_PROXY&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;:5000 kubectl get po -A --insecure-skip-tls-verify
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You should see the traffic pop up in the window running mitmproxy, and can review the traffic flow(s) in detail.&lt;/p&gt;
&lt;p&gt;As explanation: the &lt;code&gt;HTTPS_PROXY&lt;/code&gt; part redirects traffic through the instance of mitmproxy you just launched, and &lt;code&gt;--insecure-skip-tls-verify&lt;/code&gt; tells &lt;code&gt;kubectl&lt;/code&gt; not to verify the upstream certificate&amp;mdash;which it can&amp;rsquo;t do because it&amp;rsquo;s seeing mitmproxy&amp;rsquo;s certificate, &lt;em&gt;not&lt;/em&gt; the cluster&amp;rsquo;s certificate.&lt;/p&gt;
&lt;p&gt;There you go&amp;mdash;now you can observe traffic between &lt;code&gt;kubectl&lt;/code&gt; and the Kubernetes API server. As I mentioned at the start of this post, this technique is useful for troubleshooting. I did not find it useful as a learning tool, but others might.&lt;/p&gt;
&lt;p&gt;I hope you find this useful. Thanks to Ahmet for setting me down the right path! If you have questions, feel free to reach out. I&amp;rsquo;m available on social platforms (&lt;a href=&#34;https://x.com/scott_lowe&#34;&gt;X/Twitter&lt;/a&gt;, &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;Mastodon&lt;/a&gt;, &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;Bluesky&lt;/a&gt;, and &lt;a href=&#34;https://www.linkedin.com/in/scottslowe&#34;&gt;LinkedIn&lt;/a&gt;), or you can drop me an email. I&amp;rsquo;d be happy to help if I&amp;rsquo;m able.&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Running the Azure CLI in a Container</title>
        <link>https://blog.scottlowe.org/2026/03/02/running-azure-cli-in-container/</link>
        <pubDate>Mon, 02 Mar 2026 08:00:00 EST</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2026/03/02/running-azure-cli-in-container/</guid>
        <description>&lt;p&gt;Like perhaps some readers, I am quite particular about what gets installed on my systems. I try to keep my systems as &amp;ldquo;clean&amp;rdquo; as possible, doing my best to avoid tools that have an extensive list of dependencies that must be installed and updated. Where that isn&amp;rsquo;t possible&amp;mdash;such as with the Azure CLI, which has a massive number of Python modules that are required in order for the tool to function&amp;mdash;I will use various isolation mechanisms. For the Azure CLI, that&amp;rsquo;s typically been a Python virtual environment. Somewhat recently, though, I had an idea to try using a container. In this post, I&amp;rsquo;ll share what worked and what did not work when trying to run the Azure CLI in a container.&lt;/p&gt;
&lt;p&gt;First, though, a disclaimer: I am not an Azure expert, nor am I a Python expert. I know enough to get by. If I share something here that&amp;rsquo;s incorrect, please contact me and constructively show me my errors so that I can fix them.&lt;/p&gt;
&lt;p&gt;Before I started down this path, I was sure this would be a slam dunk. I mean, this is what containers are for, right? If you do some web searches for running the &lt;a href=&#34;https://github.com/Azure/azure-cli&#34;&gt;Azure CLI&lt;/a&gt; in a container, you&amp;rsquo;ll find articles that give you this command line:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -it mcr.microsoft.com/azure-cli
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(Note that this assumes you are using Docker instead of something like &lt;a href=&#34;https://podman.io/&#34;&gt;Podman&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;This &lt;em&gt;does&lt;/em&gt; work, as long as you&amp;rsquo;re willing to operate in an interactive shell in the container. I was looking for something a bit different: I wanted to create an alias for &lt;code&gt;az&lt;/code&gt; that executed the container in my current shell instead of putting me into a separate shell inside the container. Something like this, for example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;alias az&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;docker container run --rm mcr.microsoft.com/azure-cli az&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I quickly found that you need to map in your Azure configuration directory from outside the container, or your configuration won&amp;rsquo;t persist. (In theory you could remove the &lt;code&gt;--rm&lt;/code&gt; parameter and keep the container around.) Now the &lt;code&gt;docker&lt;/code&gt; command in your alias starts to look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker container run --rm -v &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;HOME&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;/.azure:/root/.azure mcr.microsoft.com/azure-cli az
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Oh, you need access to your SSH keys? You&amp;rsquo;ll have to map those in, too:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker container run --rm -v &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;HOME&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;/.azure:/root/.azure &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;-v &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;HOME&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;/.ssh:/root/.ssh mcr.microsoft.com/azure-cli az
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Except that then I remember that I am running as root in the container, and so any files created by the Azure CLI will be owned as root outside the container, too. No worries; I&amp;rsquo;ll just run it as a different user ID. Unfortunately, that involves building and maintaining my own container image to specify that the Azure CLI should run as something other than root. At this point, you&amp;rsquo;ll likely come to the same conclusion I did, and decide that a Python virtual environment is fine.&lt;/p&gt;
&lt;p&gt;I was about to classify this experiment as &amp;ldquo;Death by a Thousand Cuts&amp;rdquo;, because every time I turned around I was finding some annoyance or blocker caused by Docker and containers. And then I remembered &lt;a href=&#34;https://distrobox.it&#34;&gt;Distrobox&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Distrobox uses a container, but the container is &amp;ldquo;tightly integrated&amp;rdquo; with the host. For example, a Distrobox container shares the home directory of the user. For this use case, this makes the situation appreciably simpler&amp;mdash;I no longer need to map in volumes for the Azure configuration or for my SSH keys.&lt;/p&gt;
&lt;p&gt;Getting this working with Distrobox was only a few steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a new Distrobox container (I chose to use Debian 13):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;distrobox create -n azcli -i debian:13
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enter the new container with &lt;code&gt;distrobox enter azcli&lt;/code&gt; and install a few tools. (This is one oddity of Distrobox: it will use the &lt;code&gt;~/.bashrc&lt;/code&gt; from your host, which may references tools that don&amp;rsquo;t exist in the container. In my situation, I needed to install &lt;a href=&#34;https://starship.rs&#34;&gt;Starship&lt;/a&gt; and a few command-line tools.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install the Azure CLI in the Distrobox container by following &lt;a href=&#34;https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux&#34;&gt;the Linux installation instructions&lt;/a&gt;. (One side note here: I chose Debian 13, but technically Debian 13 isn&amp;rsquo;t yet supported.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the Distrobox container, export the Azure CLI so it is accessible from the host system:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;distrobox-export -b /usr/bin/az
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you omit step 4, then you are &lt;em&gt;sort of&lt;/em&gt; back to where I was earlier in this article&amp;mdash;you&amp;rsquo;ll enter the Distrobox container and run the &lt;code&gt;az&lt;/code&gt; commands from a separate shell. However, once you complete step 4 (which is done from within the Distrobox container), then &lt;strong&gt;on the host&lt;/strong&gt; you will run &lt;code&gt;az&lt;/code&gt;. That&amp;rsquo;s it! All of the files, all the dependencies, etc., are all stored in the Distrobox container. Your system remains &amp;ldquo;clean.&amp;rdquo;&lt;/p&gt;
&lt;h2 id=&#34;wrapping-up-and-additional-resources&#34;&gt;Wrapping Up and Additional Resources&lt;/h2&gt;
&lt;p&gt;After trying to use a &amp;ldquo;standard&amp;rdquo; Docker container, I was convinced that trying to run the Azure CLI in a container was more work than just falling back to a plain old Python virtual environment. With Distrobox, though, it&amp;rsquo;s a piece of cake! Just create the Distrobox container, install the Azure CLI, export it, and you&amp;rsquo;re done.&lt;/p&gt;
&lt;p&gt;I hope you&amp;rsquo;ve found this article helpful. I encourage you to check out Distrobox, either via &lt;a href=&#34;https://distrobox.it&#34;&gt;the Distrobox web site&lt;/a&gt; or via &lt;a href=&#34;https://github.com/89luca89/distrobox&#34;&gt;the GitHub repository&lt;/a&gt;. Feel free to find me online (&lt;a href=&#34;https://twitter.com/scott_lowe&#34;&gt;X/Twitter&lt;/a&gt;, &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;Mastodon&lt;/a&gt;, &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;Bluesky&lt;/a&gt;, or &lt;a href=&#34;https://www.linkedin.com/in/scottslowe/&#34;&gt;LinkedIn&lt;/a&gt;) and let me know what sort of cool things you end up doing with Distrobox!&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Technology Short Take 191</title>
        <link>https://blog.scottlowe.org/2026/02/27/technology-short-take-191/</link>
        <pubDate>Fri, 27 Feb 2026 09:00:00 EST</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2026/02/27/technology-short-take-191/</guid>
        <description>&lt;p&gt;Welcome to Technology Short Take #191! This is my semi-regular collection of links related to technology disciplines, including networking, security, cloud computing, storage, and programming/development. I hope that I&amp;rsquo;ve managed to curate an interesting and useful set of links for readers. Enjoy!&lt;/p&gt;
&lt;h2 id=&#34;networking&#34;&gt;Networking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I learned a new acronym from Ivan Pepelnjak in his article on &lt;a href=&#34;https://blog.ipspace.net/2026/02/iosxr-ospfv2-not-so-passive/&#34;&gt;&amp;ldquo;not so passive&amp;rdquo; OPSFv2 interfaces in Cisco IOS/XR&lt;/a&gt;: QDS (Quick and Dirty Solution). I am totally using that from now on.&lt;/li&gt;
&lt;li&gt;Via Ivan (hat tip to my colleague Russ for pointing me in this direction), I also learned that &lt;a href=&#34;https://blog.ipspace.net/2025/11/ansible-12-different/&#34;&gt;all is not well in network automation land with Ansible&lt;/a&gt;. Although some parts of it are apparently now resolved, this does &lt;a href=&#34;https://blog.ipspace.net/2025/12/ansible-abandoned-network-automation/&#34;&gt;raise questions about the viability of Ansible for network automation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Doug Dawson &lt;a href=&#34;https://potsandpansbyccg.com/2026/02/24/cellular-backup-for-broadband/&#34;&gt;talks about the new Amazon Eero Signal&lt;/a&gt;, a cellular backup to a primary broadband connection for users using their Eero mesh systems. I agree with Doug&amp;mdash;the pricing seems high to me. I &lt;em&gt;generally&lt;/em&gt; like the Eero devices, although there have been times when I really could use a bit more control over the settings.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;security&#34;&gt;Security&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The APNIC blog features a guest article discussing &lt;a href=&#34;https://blog.apnic.net/2026/01/16/from-spoofing-to-tunnelling-new-red-team-networking-techniques-for-initial-access-and-evasion/&#34;&gt;the use of tunneling protocols to infiltrate networks&lt;/a&gt;. The article specifically discusses Generic Routing Encapsulation (GRE) and Virtual Extensible LAN (VXLAN). It&amp;rsquo;s worth a read if your network uses either of these technologies.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cloud-computingcloud-management&#34;&gt;Cloud Computing/Cloud Management&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Somewhere along the way I missed &lt;a href=&#34;https://www.pulumi.com/blog/cdktf-is-deprecated-whats-next-for-your-team/&#34;&gt;the CDK deprecation announcement&lt;/a&gt;. If I am not mistaken, this leaves Pulumi as the only cloud-independent IaC tool that lets you use a general purpose programming language.&lt;/li&gt;
&lt;li&gt;Managing dependencies between containers can be difficult at times; &lt;a href=&#34;https://blog.frankel.ch/subtle-art-waiting/&#34;&gt;this blog post by Nicolas Fränkel&lt;/a&gt; introduced me to &lt;code&gt;wait4x&lt;/code&gt;, a tool one can use to help simplify these types of situations.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;operating-systemsapplications&#34;&gt;Operating Systems/Applications&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I appreciated reading &lt;a href=&#34;https://mitchellh.com/writing/my-ai-adoption-journey&#34;&gt;Mitchell Hashimoto&amp;rsquo;s AI adoption journey&lt;/a&gt;. I feel it does provide a more realistic approach to how someone in a role like his might leverage an LLM or coding agent.&lt;/li&gt;
&lt;li&gt;Michael Christofides taught me about bloat in this article on &lt;a href=&#34;https://www.pgmustard.com/blog/read-efficiency-issues-in-postgres-queries&#34;&gt;read efficiency issues in Postgres queries&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Ricardo Katz discusses &lt;a href=&#34;https://dev.to/rkatz/the-kgateway-vulnerabilities-explained-and-why-i-disagree-on-its-score-339e&#34;&gt;a few somewhat-recent security vulnerabilities in kgateway&lt;/a&gt;, an open source Gateway API implementation that leverages Envoy Proxy.&lt;/li&gt;
&lt;li&gt;I am squarely in agreement with Martin Fowler on &lt;a href=&#34;https://martinfowler.com/bliki/AgenticEmail.html&#34;&gt;the topic of agentic email&lt;/a&gt;&amp;mdash;this seems like a dangerous combination, so tread carefully. (I am squarely in disagreement with Martin&amp;rsquo;s &lt;a href=&#34;https://martinfowler.com/bliki/HostLeadership.html&#34;&gt;characterization of servant leadership as gaslighting&lt;/a&gt;, but that&amp;rsquo;s another topic for another day.)&lt;/li&gt;
&lt;li&gt;You know AI has gone too far when you find it has &lt;a href=&#34;https://nvie.com/posts/15-years-later/&#34;&gt;&amp;ldquo;continvoucly morged&amp;rdquo; your content&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Earlier this week I stumbled across &lt;a href=&#34;https://github.com/ricardodantas/hazelnut/&#34;&gt;&lt;code&gt;hazelnut&lt;/code&gt;, a terminal-based file organizer for Linux systems&lt;/a&gt;. The macOS app Hazel inspired &lt;code&gt;hazelnut&lt;/code&gt;. Neat!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;programmingdevelopment&#34;&gt;Programming/Development&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Tuan Nguyen&amp;rsquo;s article on &lt;a href=&#34;https://www.golinuxcloud.com/golang-parse-yaml-file/&#34;&gt;parsing a YAML file in Golang&lt;/a&gt; was helpful for me recently. I had struggled with how to do this without a struct, and the article provides a couple of examples of using a map instead of a struct for this purpose.&lt;/li&gt;
&lt;li&gt;Simon Willison is &lt;a href=&#34;https://simonwillison.net/2026/Feb/23/agentic-engineering-patterns/&#34;&gt;starting to write about agentic engineering patterns&lt;/a&gt;&amp;mdash;that is, patterns for software engineering when working with agents.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;virtualization&#34;&gt;Virtualization&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Lightweight Linux VMs (sometimes called &amp;ldquo;micro-VMs&amp;rdquo;) are gaining in popularity. Deno recently &lt;a href=&#34;https://deno.com/blog/introducing-deno-sandbox&#34;&gt;introduced Deno Sandbox&lt;/a&gt;, built on lightweight Linux VMs, to provide code security for untrusted code.&lt;/li&gt;
&lt;li&gt;William Lam provides some information on &lt;a href=&#34;https://williamlam.com/2026/02/cross-vcenter-vmotion-workloads-from-vsphere-7-0-to-vsphere-9-0.html&#34;&gt;using cross-vCenter vMotion to help with migrating away from vSphere 7&lt;/a&gt; (which is now reached end of support).&lt;/li&gt;
&lt;li&gt;Who out there is messing around with &lt;a href=&#34;https://linuxcontainers.org/incus/&#34;&gt;Incus&lt;/a&gt;? I am considering trying it out.&lt;/li&gt;
&lt;li&gt;I noticed this past week that you can now &lt;a href=&#34;https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/amazon-ec2-nested-virtualization.html&#34;&gt;use nested virtualization to run hypervisors on &amp;ldquo;regular&amp;rdquo; EC2 instances&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;careersoft-skills&#34;&gt;Career/Soft Skills&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Tom Hollingsworth writes about &lt;a href=&#34;https://networkingnerd.net/2026/02/12/the-inattention-economy/&#34;&gt;managing your attention&lt;/a&gt;, which is something I&amp;rsquo;m increasingly seeing. I spoke about this some time ago when I advised folks to turn off new email notifications and switch to checking your email less frequently so you could focus on getting work done.&lt;/li&gt;
&lt;li&gt;I also saw this post by Scott H Young about &lt;a href=&#34;https://www.scotthyoung.com/blog/2026/01/14/manage-energy-not-time/&#34;&gt;managing your energy instead of your time&lt;/a&gt;, which&amp;mdash;to me, at least&amp;mdash;relates to Tom&amp;rsquo;s post in the previous bullet. In &lt;a href=&#34;https://www.scotthyoung.com/blog/2026/01/21/what-exactly-is-energy/&#34;&gt;the follow-up post explaining what energy is&lt;/a&gt;, Young (or one of the linked articles/studies) refers to energy as a &amp;ldquo;mental resource.&amp;rdquo; It seems to me, as an uneducated layman, that managing your energy levels would also entail managing the cognitive zap you get from constant context switches due to notifications. I could be wrong (it wouldn&amp;rsquo;t be the first time, nor will it be the last).&lt;/li&gt;
&lt;li&gt;One final thought in this thread: Scott Young&amp;rsquo;s article on &lt;a href=&#34;https://www.scotthyoung.com/blog/2026/02/12/make-hard-work-feel-easy/&#34;&gt;how to make hard work feel less hard&lt;/a&gt; talks about making tasks less effortful. This sounds a lot like &amp;ldquo;reducing the friction&amp;rdquo; for common tasks, which I have discussed in the past (here is &lt;a href=&#34;https://blog.scottlowe.org/2013/05/31/reducing-the-friction-bbedit-to-marsedit/&#34;&gt;one example&lt;/a&gt;). Friction is something that &lt;a href=&#34;https://muratbuffalo.blogspot.com/2026/02/friction.html&#34;&gt;Murat Demirbas has also recently discussed&lt;/a&gt;, although his example is more organizational than personal. Either way, the concept of friction in our work is definitely a valid concept, and something we should take into account as we work toward managing both our attention and our energy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s all for now. I will return in a couple of weeks with the next installation, and a fresh set of links from around the internet. In the meantime, I invite you to drop me a line (my email is not hard to find) or hit me up on social media (&lt;a href=&#34;https://twitter.com/scott_lowe&#34;&gt;X/Twitter&lt;/a&gt;, &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;Mastodon&lt;/a&gt;, &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;Bluesky&lt;/a&gt;, or &lt;a href=&#34;https://www.linkedin.com/in/scottslowe/&#34;&gt;LinkedIn&lt;/a&gt;) and let me know if you&amp;rsquo;ve found something useful. I love to hear from readers!&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Technology Short Take 190</title>
        <link>https://blog.scottlowe.org/2026/02/06/technology-short-take-190/</link>
        <pubDate>Fri, 06 Feb 2026 08:00:00 EST</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2026/02/06/technology-short-take-190/</guid>
        <description>&lt;p&gt;Welcome to Technology Short Take #190! This is the first Tech Short Take of 2026, and it has been nearly three months (wow!) since the last one. I can&amp;rsquo;t argue that I fell off the blogging bandwagon over the end of 2025 and early 2026. I won&amp;rsquo;t get into all the reasons why (if you&amp;rsquo;re interested then feel free to reach out and I&amp;rsquo;ll fill you in). Enough about me&amp;mdash;let&amp;rsquo;s get to the technical content! Here&amp;rsquo;s hoping you find something useful.&lt;/p&gt;
&lt;h2 id=&#34;networking&#34;&gt;Networking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Here&amp;rsquo;s a little something on the lighter side about &lt;a href=&#34;https://potsandpansbyccg.com/2026/01/19/rats-attack-fiber/&#34;&gt;what causes network outages&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;As the lead-in to &lt;a href=&#34;https://blog.apnic.net/2025/12/17/investigating-starlinks-performance-during-the-may-2024-solar-superstorm/&#34;&gt;this article on Starlink&amp;rsquo;s performance during a solar superstorm&lt;/a&gt; says, &amp;ldquo;It&amp;rsquo;s not science fiction.&amp;rdquo; Solar storms can have a real impact on Earth, and satellites in low-Earth orbit (LEO) are not exempt from that impact.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;servershardware&#34;&gt;Servers/Hardware&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;William Lam &lt;a href=&#34;https://williamlam.com/2026/01/every-mini-pc-sff-hardware-announced-at-ces-2026.html&#34;&gt;reviews the Mini PC and SFF (small form factor) hardware announcements from CES 2026&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;security&#34;&gt;Security&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The scale of DDoS attacks continues to grow, as evidenced by &lt;a href=&#34;https://www.bleepingcomputer.com/news/microsoft/microsoft-aisuru-botnet-used-500-000-ips-in-15-tbps-azure-ddos-attack/&#34;&gt;this report of a 15 Tbps attack on Microsoft Azure&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Microsoft having the ability to &lt;a href=&#34;https://www.windowscentral.com/microsoft/windows-11/microsoft-bitlocker-encryption-keys-give-fbi-legal-order-privacy-nightmare&#34;&gt;give away your Windows PC&amp;rsquo;s data encryption key&lt;/a&gt; is horrifying.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cloud-computingcloud-management&#34;&gt;Cloud Computing/Cloud Management&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;While doing some reading on Terragrunt, I also came across &lt;a href=&#34;https://github.com/gruntwork-io/git-xargs&#34;&gt;this open source tool for performing operations against multiple Git repositories&lt;/a&gt;. I don&amp;rsquo;t have a use case for it, but it is cool!&lt;/li&gt;
&lt;li&gt;While on the topic of Terragrunt: let me say that I appreciate the work that went into &lt;a href=&#34;https://terragrunt.gruntwork.io/docs/getting-started/quick-start/&#34;&gt;their online docs&lt;/a&gt;! From what I&amp;rsquo;ve read so far, they are well-written, clear, concise, and informative. Well done!&lt;/li&gt;
&lt;li&gt;And while still on the topic of Terragrunt: it was this article from Axel Mendoza on why they &lt;a href=&#34;https://www.axelmendoza.com/posts/terraform-vs-terragrunt/&#34;&gt;use Terragrunt over Terraform/OpenTofu&lt;/a&gt; that sent me down the Terragrunt rabbit hole.&lt;/li&gt;
&lt;li&gt;The most recent installation of &lt;a href=&#34;https://dev.to/aws/aws-open-source-newsletter-218-3e3m&#34;&gt;Ricardo Sueiras&amp;rsquo; AWS open source newsletter&lt;/a&gt; pointed me to a couple of tools that look really handy: &lt;code&gt;s3sh&lt;/code&gt; (available &lt;a href=&#34;https://github.com/dacort/s3sh&#34;&gt;from GitHub&lt;/a&gt;) and &lt;code&gt;taws&lt;/code&gt; (also available &lt;a href=&#34;https://github.com/huseyinbabal/taws&#34;&gt;from GitHub&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Nick Buraglio has &lt;a href=&#34;https://www.forwardingplane.net/post/2025-12-26-hosted-email-options-2026/&#34;&gt;a great comparison of hosted email options&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;operating-systemsapplications&#34;&gt;Operating Systems/Applications&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Howard Oakley&amp;rsquo;s &lt;a href=&#34;https://eclecticlight.co/2025/11/30/last-week-on-my-mac-losing-confidence/&#34;&gt;&amp;ldquo;loss of confidence&amp;rdquo; in macOS&lt;/a&gt; is one reason why I started using Linux more. I just kept finding things in macOS that didn&amp;rsquo;t work like they should, which was made worse by the fact that Apple (the company) just doesn&amp;rsquo;t seem to care.&lt;/li&gt;
&lt;li&gt;It is still kind of raw, but I found &lt;a href=&#34;https://github.com/Inlyne-Project/inlyne&#34;&gt;a Markdown preview tool for Linux called Inlyne&lt;/a&gt;. Pretty cool! I am looking forward to seeing how it develops.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.mikeswanson.com/backseat-software/&#34;&gt;This treatise from Mike Swanson on &amp;ldquo;backseat software&amp;rdquo;&lt;/a&gt; is absolute gold. Go read it. Now. Seriously, this is good stuff. I was nodding so vigorously as I was reading it that I almost gave myself a headache!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;storage&#34;&gt;Storage&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Looking for some information on vSAN Encryption in VMware Cloud Foundation? I think Eric Sloof has &lt;a href=&#34;https://www.ntpro.nl/blog/archives/3849-A-Technical-Overview-of-vSAN-Encryption-in-VMware-Cloud-Foundation.html&#34;&gt;exactly the document you need&lt;/a&gt;. (You may also find &lt;a href=&#34;https://www.ntpro.nl/blog/archives/3831-vSAN-Encryption-Services-in-VMware-Cloud-Foundation-9.0.html&#34;&gt;this related article from Eric&lt;/a&gt; useful as well.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;virtualization&#34;&gt;Virtualization&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Eric Sloof writes about &lt;a href=&#34;https://www.ntpro.nl/blog/archives/3845-Introducing-the-VMware-Certified-Distinguished-Expert-VCDX-A-New-Era-for-Elite-Private-Cloud-Professionals.html&#34;&gt;the evolution of the VCDX&lt;/a&gt;. As an early VCDX (number 39), I am of two minds regarding this change. On one hand, it makes sense; they need more than just architects to pursue this certification. On the other hand, they are (in some ways) &amp;ldquo;softening&amp;rdquo; the certification. It will be interesting to see if this helps the designation grow, or if it continues to fade into obscurity.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;careersoft-skills&#34;&gt;Career/Soft Skills&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Murat Demirbas &lt;a href=&#34;https://muratbuffalo.blogspot.com/2025/12/optimize-for-momentum.html&#34;&gt;talks a bit about momentum&lt;/a&gt;, and how maintaining momentum (the &amp;ldquo;the messy daily pushes&amp;rdquo; as he puts it) should be how you organize and structure your workflows. I can see his point, certainly, although I would warn folks against interpreting his &amp;ldquo;produce something every day&amp;rdquo; advice as meaning that you need to &lt;em&gt;publish&lt;/em&gt; something every day. That path leads to burn out. Produce something, sure, but allow for that something to be something that only you&amp;rsquo;ll see.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.seangoedecke.com/technical-communication/&#34;&gt;This article about getting better at technical writing&lt;/a&gt; contains some good guidelines.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.allthingsdistributed.com/2025/12/a-little-bit-uncomfortable.html&#34;&gt;This discussion of feeling uncomfortable and how it relates to growing personally&lt;/a&gt; really resonated with me. No, not because of Werner&amp;rsquo;s fear of public speaking; rather, it was about how it is necessary to move outside of your comfort zone in order to grow. I am getting ready to potentially embark on something that really pushes me outside my comfort zone, and it is scary. I also know, though, that it is the only way to grow.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s all, folks! (Bonus points for you if you recognize that reference.) I am always up to hear from readers, so I invite you to reach out using various social media platforms (&lt;a href=&#34;https://twitter.com/scott_lowe&#34;&gt;X/Twitter&lt;/a&gt;, &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;Mastodon&lt;/a&gt;, &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;Bluesky&lt;/a&gt;, &lt;a href=&#34;https://www.linkedin.com/in/scottslowe/&#34;&gt;LinkedIn&lt;/a&gt;), Slack, or old-fashioned email. Thanks for reading!&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Setting up a VPC Route Server with Pulumi</title>
        <link>https://blog.scottlowe.org/2026/01/28/setting-up-a-vpc-route-server-with-pulumi/</link>
        <pubDate>Wed, 28 Jan 2026 09:00:00 -0400</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2026/01/28/setting-up-a-vpc-route-server-with-pulumi/</guid>
        <description>&lt;p&gt;If you need to work with BGP in your AWS VPCs&amp;mdash;so that BGP-learned routes can be injected into a VPC route table&amp;mdash;then you will likely need a VPC Route Server. While you &lt;em&gt;could&lt;/em&gt; set up a VPC Route Server manually, what&amp;rsquo;s the fun in that? In this post, I will walk you through a Pulumi program that will set up a VPC Route Server. Afterward, I will discuss some ways you could check the functionality of the VPC Route Server to show that it is indeed working as expected.&lt;/p&gt;
&lt;p&gt;To make things as easy as possible, I have added a simple &lt;a href=&#34;https://www.pulumi.com&#34;&gt;Pulumi&lt;/a&gt; program to &lt;a href=&#34;https://github.com/scottslowe/learning-tools&#34;&gt;my GitHub &amp;ldquo;learning-tools&amp;rdquo; repository&lt;/a&gt; in the &lt;code&gt;aws/vpc-route-server&lt;/code&gt; directory. This program sets up a VPC Route Server and its associated components for you, and I will walk through this program in this blog post.&lt;/p&gt;
&lt;p&gt;The first step is creating the VPC Route Server itself. The VPC Route Server has no prerequisities, and the primary configuration needed is setting the ASN (Autonomous System Number) the Route Server should use:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;rs&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;vpc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewRouteServer&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;rs&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;vpc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerArgs&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;AmazonSideAsn&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Int&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;65534&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;Tags&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;StringMap&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;:    &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;rs&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Project&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vpc-route-server&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, you will need to associate the Route Server with a VPC. This requires a VPC ID, as you might expect; this ID could come from a configuration value passed in by the user, or from a VPC created earlier in this or another Pulumi program.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;rsa&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;vpc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewRouteServerVpcAssociation&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;rsa&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;vpc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerVpcAssociationArgs&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerId&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;rs&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ID&lt;/span&gt;(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;VpcId&lt;/span&gt;:         &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;userSuppliedVpcId&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With that association in place, the next component is a Route Server Endpoint. This endpoint is created in a subnet, and will have an IP address assigned from that subnet. This IP address is what your BGP peer will use to establish a peering relationship to exchange routes.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;rse&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;vpc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewRouteServerEndpoint&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;rse&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;vpc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerEndpointArgs&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerId&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;rs&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerId&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;SubnetId&lt;/span&gt;:      &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;userSuppliedPrivateSubnetId&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;Tags&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;StringMap&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;:    &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;rse&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Project&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vpc-route-server&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}, &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;DependsOn&lt;/span&gt;([]&lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Resource&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;rsa&lt;/span&gt;}))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In working with the VPC Route Server, I&amp;rsquo;ve found that sometimes the dependencies between components don&amp;rsquo;t quite work as expected. Because the endpoint references the &lt;code&gt;rs&lt;/code&gt; resource (the Route Server itself), the endpoint has a implicit dependency on that resource. However, if the VPC association isn&amp;rsquo;t complete, then you can run into errors. To address that problem, the code above uses &lt;code&gt;pulumi.DependsOn&lt;/code&gt; to create an explicit dependency on the VPC association. This way, both the Route Server and the association of the Route Server to a VPC are complete before the program attempts to create the endpoint.&lt;/p&gt;
&lt;p&gt;The Route Server needs to know where to inject the routes it learns, and that&amp;rsquo;s handled by creating a propagation. The propagation links the Route Server to a route table in the associated VPC. Here&amp;rsquo;s the Pulumi code from the example in the &amp;ldquo;learning-tools&amp;rdquo; repository:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;vpc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewRouteServerPropagation&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;rs-prop&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;vpc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerPropagationArgs&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerId&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;rs&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerId&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;RouteTableId&lt;/span&gt;:  &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;userSuppliedPrivateRouteTableId&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}, &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;DependsOn&lt;/span&gt;([]&lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Resource&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;rsa&lt;/span&gt;}))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The use of &lt;code&gt;pulumi.DependsOn&lt;/code&gt; makes the propagation, like the endpoint, dependent on the VPC association. This helps eliminate errors related to the order of resource creation or deletion.&lt;/p&gt;
&lt;p&gt;The last step is creating a peer for the Route Server. This tells the Route Server what the &amp;ldquo;other side&amp;rdquo; of a BGP peering relationship looks like. The &amp;ldquo;other side&amp;rdquo; could be an EC2 instance running a BGP daemon, or it could be a Kubernetes node on a cluster running a CNI that supports BGP (like &lt;a href=&#34;https://cilium.io&#34;&gt;Cilium&lt;/a&gt;). Whatever the &amp;ldquo;other side&amp;rdquo; is, you&amp;rsquo;ll need to be sure the configuration you pass to the Route Server peer matches the configuration in use by the other side. Otherwise, establishing the BGP peering relationship will fail.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;vpc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewRouteServerPeer&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;rs-peer-01&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;vpc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerPeerArgs&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;BgpOptions&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;vpc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerPeerBgpOptionsArgs&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;PeerAsn&lt;/span&gt;:               &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Int&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;65001&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;PeerLivenessDetection&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;bgp-keepalive&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;PeerAddress&lt;/span&gt;:           &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;userSuppliedPeerIpAddress&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerEndpointId&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;rse&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RouteServerEndpointId&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;Tags&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;StringMap&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;:    &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;rs-peer-01&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Project&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vpc-route-server&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}, &lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;DependsOn&lt;/span&gt;([]&lt;span style=&#34;color:#a6e22e&#34;&gt;pulumi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Resource&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;rs&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;rse&lt;/span&gt;}))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the definition of the Route Server peer, you point it to the IP address of some other device or instance running BGP. In the other device or instance, you will point it to the IP address of the Route Server endpoint. This way, each member of the BGP peering relationship knows how to connect to the other member.&lt;/p&gt;
&lt;p&gt;All of the code above is found in the &lt;code&gt;aws/vpc-route-server&lt;/code&gt; directory in &lt;a href=&#34;https://github.com/scottslowe/learning-tools&#34;&gt;my GitHub &amp;ldquo;learning-tools&amp;rdquo; repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Once you run &lt;code&gt;pulumi up&lt;/code&gt; to create all the resources, verifying the creation is a matter of using the AWS CLI:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws ec2 describe-route-servers &lt;span style=&#34;color:#75715e&#34;&gt;# to get the Route Server ID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws ec2 describe-route-server-endpoints
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws ec2 get-route-server-propagations --route-server-id &amp;lt;id&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws ec2 describe-route-server-peers 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some of these commands don&amp;rsquo;t (yet) support some of the same filtering mechanisms as other AWS CLI commands, so you may find it necessary to use &lt;code&gt;jq&lt;/code&gt; to filter the output on the client side.&lt;/p&gt;
&lt;p&gt;Verifying the operation of the Route Server is a bit more complex&amp;mdash;you will need &lt;em&gt;something&lt;/em&gt; to run BGP and peer with the Route Server to exchange routes. As I mentioned earlier, Cilium can do this for a Kubernetes cluster, but you could also use an EC2 instance running &lt;a href=&#34;https://frrouting.org/&#34;&gt;FRR&lt;/a&gt; or some other BGP daemon. This is a topic I might explore in a future blog post; if it&amp;rsquo;s something you&amp;rsquo;re interested in seeing, please let me know.&lt;/p&gt;
&lt;p&gt;If you have any questions or comments, please reach out to me. I love hearing from readers and would be happy to do my best to answer any queries or respond to feedback. You can reach me via email (my address is on this site), via various social media sites (&lt;a href=&#34;https://x.com/scott_lowe&#34;&gt;X/Twitter&lt;/a&gt;, &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;Bluesky&lt;/a&gt;, &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;Mastodon&lt;/a&gt;), or via Slack (I&amp;rsquo;m in several Slack communities, including the Kubernetes Slack community). I hope you found this information helpful, and thanks for reading!&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Technology Short Take 189</title>
        <link>https://blog.scottlowe.org/2025/10/31/technology-short-take-189/</link>
        <pubDate>Fri, 31 Oct 2025 09:00:00 EDT</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2025/10/31/technology-short-take-189/</guid>
        <description>&lt;p&gt;Welcome to Technology Short Take #189, Halloween Edition! OK, you caught me&amp;mdash;this Tech Short Take is not scary. I&amp;rsquo;ll try harder next year. In the meantime, enjoy this collection of links about data center-related technologies. Although this installation is lighter on content than I would prefer, I am publishing anyway in the hopes of trying to get back to a somewhat-regular cadence. Here&amp;rsquo;s hoping you find something useful and informative!&lt;/p&gt;
&lt;h2 id=&#34;networking&#34;&gt;Networking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Kevin Myers dissects &lt;a href=&#34;https://stubarea51.net/2025/09/22/evpn-vxlan-interop-ipv4-ipv6-mikrotik-ip-infusion/&#34;&gt;EVPN/VXLAN interoperability with MicroTik and IP Infusion&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Ivan Pepelnjak has a new project: &lt;a href=&#34;https://blog.ipspace.net/2025/10/vxlan-evpn-labs/&#34;&gt;open source EVPN/VXLAN labs&lt;/a&gt;. I plan to tackle these myself in the near future!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;servershardware&#34;&gt;Servers/Hardware&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Kevin Houston takes a look at &lt;a href=&#34;https://bladesmadesimple.com/2025/09/xeon-6-cpus-available-today/&#34;&gt;the availability of Xeon 6 CPUs across blade server vendors&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;security&#34;&gt;Security&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Security researchers recently published some research on a new microarchitectural exploit called &amp;ldquo;VMScape.&amp;rdquo; The TL;DR on VMScape is that it allows hypervisor information to leak from a malicious VM. Oops! Olivier Lambert has &lt;a href=&#34;https://virtualize.sh/blog/vmscape-and-why-xen-dodged-it/&#34;&gt;a write-up that explains why the Xen hypervisor is not affected by this exploit&lt;/a&gt;. (Side note: be sure to read the comments&amp;mdash;Olivier shares some useful information there.)&lt;/li&gt;
&lt;li&gt;The leaking of source code for F5 appliances by a &amp;ldquo;nation-state affiliated cyber threat actor&amp;rdquo; has lead &lt;a href=&#34;https://www.cisa.gov/news-events/alerts/2025/10/15/cisa-directs-federal-agencies-mitigate-vulnerabilities-f5-devices&#34;&gt;the CISA to call on all federal agencies to mitigate vulnerabilities in F5 appliances&lt;/a&gt; due to &amp;ldquo;an imminent threat to federal networks using F5 devices and software.&amp;rdquo; That&amp;rsquo;s not good.&lt;/li&gt;
&lt;li&gt;In early October of this year, Red Hat &lt;a href=&#34;https://www.bleepingcomputer.com/news/security/red-hat-confirms-security-incident-after-hackers-breach-gitlab-instance/&#34;&gt;confirmed the breach of one of its GitLab instances&lt;/a&gt;, leading to the theft of nearly 570GB of data across 28,000 repositories. Oof.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cloud-computingcloud-management&#34;&gt;Cloud Computing/Cloud Management&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Iain Smart &lt;a href=&#34;https://blog.amberwolf.com/blog/2025/september/kubernetes_namespace_boundaries/&#34;&gt;reviews some common exploit paths when trying to build multi-tenant Kubernetes clusters&lt;/a&gt;. As Iain says, multi-tenancy is hard.&lt;/li&gt;
&lt;li&gt;Digital Society discusses &lt;a href=&#34;https://digitalsociety.coop/posts/migrating-to-hetzner-cloud/&#34;&gt;their migration off AWS and Digital Ocean to Hetzner&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Just this past week I learned of &lt;a href=&#34;https://www.pulumi.com/blog/resource-hooks/&#34;&gt;Pulumi&amp;rsquo;s resource hooks&lt;/a&gt;, a feature made available back in June of this year.&lt;/li&gt;
&lt;li&gt;Hrittik Roy &lt;a href=&#34;https://www.vcluster.com/blog/vcluster-standalone-multi-tenancy-kubernetes&#34;&gt;discusses vCluster Standalone&lt;/a&gt;, a multi-tenancy solution for Kubernetes that now no longer requires an underlying host cluster.&lt;/li&gt;
&lt;li&gt;Mattis Fjellström discusses Terraform-related options for &lt;a href=&#34;https://mattias.engineer/blog/2025/managing-aws-tags/&#34;&gt;managing tags in AWS&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;operating-systemsapplications&#34;&gt;Operating Systems/Applications&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Do you, like Cory Doctorow, believe &lt;a href=&#34;https://pluralistic.net/2025/09/27/econopocalypse/#subprime-intelligence&#34;&gt;an AI economic apocalypse is near&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;I recently published &lt;a href=&#34;https://blog.scottlowe.org/2025/10/20/using-git-pre-commit-hooks/&#34;&gt;a post on Git pre-commit hooks&lt;/a&gt;. The next day I wake up to an email from Ivan Pepelnjak, who has&amp;mdash;not surprisingly&amp;mdash;already explored Git pre-commit hooks and found &lt;a href=&#34;https://pre-commit.com/&#34;&gt;a framework for making them easier to work with&lt;/a&gt;. Ivan uses this framework to perform a variety of checks against his blog posts. Now he has inspired me to go even farther with my pre-commit script!&lt;/li&gt;
&lt;li&gt;Anthropic, along with the UK AI Institute and the Alan Turing Institute, have found that as few as 250 malicious documents can produce a &amp;ldquo;backdoor&amp;rdquo; vulnerability in a large language model (LLM). You can get more details, as well as a link to the paper published from their research, by reading &lt;a href=&#34;https://www.anthropic.com/research/small-samples-poison&#34;&gt;the associated Anthropic blog post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Here is &lt;a href=&#34;https://github.com/RoseSecurity/Terramaid&#34;&gt;a handy tool to generate a Mermaid diagram from your Terraform configuration&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Familiar with &lt;code&gt;pwru&lt;/code&gt;? If not, read this &lt;a href=&#34;https://bitpuff.io/tutorials/networking/pwru/intro/&#34;&gt;guide to getting started with &lt;code&gt;pwru&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s it for this time around. As always, I welcome your feedback&amp;mdash;I&amp;rsquo;d love to hear from you! Feel free to reach me on &lt;a href=&#34;https://x.com/scott_lowe&#34;&gt;Twitter/X&lt;/a&gt;, &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;Mastodon&lt;/a&gt;, or &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;Bluesky&lt;/a&gt;. Or email me, that is fine too (my address is here on the site, it is not too hard to find). I truly do enjoy hearing from readers. You can also find me in a variety of Slack communities, so feel free to DM me there if you would prefer. Thanks for reading!&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Posts from the Past, October 2025</title>
        <link>https://blog.scottlowe.org/2025/10/22/posts-from-the-past-october-2025/</link>
        <pubDate>Wed, 22 Oct 2025 12:00:00 -0600</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2025/10/22/posts-from-the-past-october-2025/</guid>
        <description>&lt;p&gt;Every now and then, I publish one of these &amp;ldquo;Posts from the Past&amp;rdquo; articles that looks back on content I&amp;rsquo;ve created and posted over the life of this site. This year marks &lt;strong&gt;20 years&lt;/strong&gt; of content&amp;mdash;I can hardly believe it! Don&amp;rsquo;t worry, though; you won&amp;rsquo;t have to go through 20 years of past posts. Here is a selection of posts from mid- to late October over the last decade or so. I hope you find something useful, informative, or at least entertaining!&lt;/p&gt;
&lt;h2 id=&#34;october-2024&#34;&gt;October 2024&lt;/h2&gt;
&lt;p&gt;Last year I shared information on &lt;a href=&#34;https://blog.scottlowe.org/2024/10/10/eks-bottlerocket-cilium-with-pulumi/&#34;&gt;how to use Pulumi to stand up an Amazon Elastic Kubernetes Service (EKS) cluster with Bottlerocket OS on the Kubernetes nodes&lt;/a&gt;&amp;mdash;without using any higher-level Pulumi components.&lt;/p&gt;
&lt;h2 id=&#34;october-2022&#34;&gt;October 2022&lt;/h2&gt;
&lt;p&gt;In 2022, after getting irritated with what I felt was a poor user experience when accessing Azure Kubernetes Service (AKS) clusters created with Pulumi, I published this post on &lt;a href=&#34;https://blog.scottlowe.org/2022/10/06/streamlining-the-user-experience-for-accessing-aks-clusters/&#34;&gt;how to change the Kubeconfig file for a more streamlined user experience&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;october-2021&#34;&gt;October 2021&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://cluster-api.sigs.k8s.io/&#34;&gt;Cluster API&lt;/a&gt; is the name of the game for multiple posts in October 2021. First I wrote this article on &lt;a href=&#34;https://blog.scottlowe.org/2021/10/11/kustomize-transformer-configurations-for-cluster-api-v1beta1/&#34;&gt;&lt;code&gt;kustomize&lt;/code&gt; transformer configurations for Cluster API v1beta1&lt;/a&gt; (so that you can use &lt;code&gt;kustomize&lt;/code&gt; to manipulate Cluster API manifests), followed up later that month with an article on &lt;a href=&#34;https://blog.scottlowe.org/2021/10/25/influencing-cluster-api-ami-selection/&#34;&gt;influencing Cluster API AMI selection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I also touched upon &lt;a href=&#34;https://blog.scottlowe.org/2021/10/12/using-the-external-aws-cloud-provider-for-kubernetes/&#34;&gt;using the external (out of tree) cloud provider for AWS&lt;/a&gt; that month, a topic I am revisiting soon as I explore integrating Talos Linux with AWS.&lt;/p&gt;
&lt;h2 id=&#34;october-2020&#34;&gt;October 2020&lt;/h2&gt;
&lt;p&gt;More Cluster API content&amp;mdash;this time discussing &lt;a href=&#34;https://blog.scottlowe.org/2020/10/08/considerations-for-using-iac-with-cluster-api/&#34;&gt;IaC considerations for Cluster API&lt;/a&gt; (think things like integrating workload clusters with existing AWS workloads or services).&lt;/p&gt;
&lt;h2 id=&#34;october-2019&#34;&gt;October 2019&lt;/h2&gt;
&lt;p&gt;In October 2019 I explored &lt;a href=&#34;https://blog.scottlowe.org/2019/10/29/programmatically-creating-kubernetes-manifests/&#34;&gt;using &lt;code&gt;jk&lt;/code&gt; to programmatically create Kubernetes&lt;/a&gt; manifests, and discussed &lt;a href=&#34;https://blog.scottlowe.org/2019/10/16/using-kustomize-with-kubeadm-configuration-files/&#34;&gt;how to use &lt;code&gt;kustomize&lt;/code&gt; with &lt;code&gt;kubeadm&lt;/code&gt; configuration files&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;october-2018&#34;&gt;October 2018&lt;/h2&gt;
&lt;p&gt;Plenty of articles discuss the use of &lt;code&gt;kubeadm&lt;/code&gt; to bootstrap Kubernetes clusters (including a few I wrote!), but what of talking about &lt;a href=&#34;https://blog.scottlowe.org/2018/10/29/more-on-setting-up-etcd-with-kubeadm/&#34;&gt;using &lt;code&gt;kubeadm&lt;/code&gt; to stand up an etcd cluster&lt;/a&gt;? I&amp;rsquo;ve got you covered!&lt;/p&gt;
&lt;h2 id=&#34;october-2017&#34;&gt;October 2017&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s get recursive: check out this &lt;a href=&#34;https://blog.scottlowe.org/2017/10/26/posts-from-the-past-october-2017/&#34;&gt;&amp;ldquo;Posts from the Past&amp;rdquo; article from October 2017&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id=&#34;october-2016&#34;&gt;October 2016&lt;/h2&gt;
&lt;p&gt;Amid a bunch of content related to Vagrant, I found this gem on &lt;a href=&#34;https://blog.scottlowe.org/2016/10/23/managing-aws-infrastructure-ansible/&#34;&gt;using Ansible to manage your AWS infrastructure&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;october-2015&#34;&gt;October 2015&lt;/h2&gt;
&lt;p&gt;Flashing back an entire decade, the OpenStack Summit was happening in Tokyo, Japan, and I was liveblogging sessions. Among the sessions I attended and liveblogged was a session on Carina, a containers-as-a-service offering. Read &lt;a href=&#34;https://blog.scottlowe.org/2015/10/28/quick-look-at-carina/&#34;&gt;my liveblog of the Carina session&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Interested in finding more posts from the past? Feel free to browse the site archives, which have a link to every single post I&amp;rsquo;ve ever published. If you find something interesting, share it on social media and tag me! I&amp;rsquo;m on &lt;a href=&#34;https://twitter.com/scott_lowe&#34;&gt;Twitter/X&lt;/a&gt;, &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;Mastodon&lt;/a&gt;, and &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;Bluesky&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thanks for reading!&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Using Git Pre-Commit Hooks</title>
        <link>https://blog.scottlowe.org/2025/10/20/using-git-pre-commit-hooks/</link>
        <pubDate>Mon, 20 Oct 2025 09:00:00 -0600</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2025/10/20/using-git-pre-commit-hooks/</guid>
        <description>&lt;p&gt;A while ago I wrote an article about &lt;a href=&#34;https://blog.scottlowe.org/2024/03/01/linting-your-markdown-files/&#34;&gt;linting Markdown files&lt;/a&gt; with &lt;code&gt;markdownlint&lt;/code&gt;. In that article, I presented the use case of linting the Markdown source files for this site. While manually running linting checks is fine&amp;mdash;there are times and situations when this is appropriate and necessary&amp;mdash;this is the sort of task that is ideally suited for &lt;a href=&#34;https://git-scm.com/docs/githooks#_pre_commit&#34;&gt;a Git pre-commit hook&lt;/a&gt;. In this post, I&amp;rsquo;ll discuss Git pre-commit hooks in the context of using them to run linting checks.&lt;/p&gt;
&lt;p&gt;Before moving on, a disclaimer: I am not an expert on Git hooks. This post shares my limited experience and provides an example based on what I use for this site. I have no doubt that my current implementation will improve over time as my knowledge and experience grow.&lt;/p&gt;
&lt;h2 id=&#34;what-is-a-git-hook&#34;&gt;What is a Git Hook?&lt;/h2&gt;
&lt;p&gt;As &lt;a href=&#34;https://git-scm.com/docs/githooks&#34;&gt;this page&lt;/a&gt; explains, a hook is a program &amp;ldquo;you can place in a hooks directory to trigger actions at certain points in git&amp;rsquo;s execution.&amp;rdquo; Generally, a hook is a script of some sort. Git supports different hooks that get invoked in response to specific actions in Git; in this particular instance, I&amp;rsquo;m focusing on the pre-commit hook. This hook gets invoked by &lt;code&gt;git-commit&lt;/code&gt; (i.e., the user running a &lt;code&gt;git commit&lt;/code&gt; command) and allows users to perform a series of checks or tests before actually making a commit. If the pre-commit script exits with a non-zero status, then Git aborts the commit.&lt;/p&gt;
&lt;h2 id=&#34;using-a-pre-commit-hook-to-lint-markdown&#34;&gt;Using a Pre-Commit Hook to Lint Markdown&lt;/h2&gt;
&lt;p&gt;For my use case, I wanted to run Markdownlint to lint the Markdown files (as described in &lt;a href=&#34;https://blog.scottlowe.org/2024/03/01/linting-your-markdown-files/&#34;&gt;the previous article on linting Markdown&lt;/a&gt;) before the commit. To do that, I came up with the following script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MDLINT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/usr/local/bin/markdownlint&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; file in &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;git diff --cached --name-only --diff-filter&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;ACM | grep &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\.md&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; ! $MDLINT &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$file&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Lint check failed on file &amp;#39;&lt;/span&gt;$file&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Run markdownlint to identify the errors and try again.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        exit &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To make this script active as a pre-commit hook, you must name it &lt;code&gt;pre-commit&lt;/code&gt;, you must place it into Git&amp;rsquo;s hook directory (which defaults to &lt;code&gt;.git/hooks&lt;/code&gt; in the current repository), and you must make it executable.&lt;/p&gt;
&lt;p&gt;This script is readable enough for most folks to understand what it is doing, but there are a couple of things that might be helpful to point out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;git diff --cached --name-only&lt;/code&gt; command will return a list of the files staged for commit using &lt;code&gt;git add&lt;/code&gt;. This list of files is what will Markdownlint will check.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;--diff-filter=ACM&lt;/code&gt; parameter tells &lt;code&gt;git diff&lt;/code&gt; to return only Added, Copied, and Modified files. This prevents &lt;code&gt;git diff&lt;/code&gt; from returning the filename of a deleted file, which would then generate an error from Markdownlint.&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;grep&lt;/code&gt; here further restricts the list of files to include only Markdown files.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;exit 1&lt;/code&gt; command is critical; without returning a non-zero exit code, Git wouldn&amp;rsquo;t know to abort the commit.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the script in the right place and marked as executable, it&amp;rsquo;s automatically invoked by Git when I try commit any Markdown files. If the check succeeds, the commit proceeds as normal (my editor opens for me to edit the commit message); if the check fails, then I see an error message and the commit aborts. Exactly what I needed!&lt;/p&gt;
&lt;h2 id=&#34;additional-resources&#34;&gt;Additional Resources&lt;/h2&gt;
&lt;p&gt;I found the following articles useful when I was learning about pre-commit hooks and how to use them:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://verdantfox.com/blog/how-to-use-git-pre-commit-hooks-the-hard-way-and-the-easy-way&#34;&gt;How to use git pre-commit hooks, the hard way and the easy way&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.slingacademy.com/article/git-pre-commit-hook-a-practical-guide-with-examples/&#34;&gt;Git Pre-Commit Hook: A Practical Guide (with Examples)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I hope you&amp;rsquo;ve found this post helpful in some fashion. As I previously mentioned, I don&amp;rsquo;t pretend to be an expert on this topic. If you spot an error or mistake in this post, then please reach out and let me know. You can reach me &lt;a href=&#34;https://twitter.com/scott_lowe&#34;&gt;on Twitter&lt;/a&gt;, on &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;the Fediverse&lt;/a&gt;, or in a variety of Slack communities. Positive feedback is also welcome&amp;mdash;thanks for reading!&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Technology Short Take 188</title>
        <link>https://blog.scottlowe.org/2025/09/19/technology-short-take-188/</link>
        <pubDate>Fri, 19 Sep 2025 09:00:00 -0500</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2025/09/19/technology-short-take-188/</guid>
        <description>&lt;p&gt;Welcome to Technology Short Take #188! I&amp;rsquo;m back once again with a small collection of articles and links related to a variety of data center-related technologies. I hope you find something useful!&lt;/p&gt;
&lt;h2 id=&#34;networking&#34;&gt;Networking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Scott Hogg discusses &lt;a href=&#34;https://hoggnet.com/blogs/news/why-you-should-dual-stack-your-dns-nameservers&#34;&gt;using dual-stack network configurations on your DNS name servers&lt;/a&gt; as part of an overall IPv6 deployment plan.&lt;/li&gt;
&lt;li&gt;Leon Adato explains why &lt;a href=&#34;https://www.adatosystems.com/2025/08/11/knowing-whats-under-the-hood-helps/&#34;&gt;knowing what&amp;rsquo;s under the hood helps&lt;/a&gt; when it comes to networking telemetry.&lt;/li&gt;
&lt;li&gt;Via Ivan Pepelnjak, I found &lt;a href=&#34;https://www.packetswitch.co.uk/netlab-the-fastest-way-to-build-network-labs/&#34;&gt;Suresh Vina&amp;rsquo;s article on using netlab to build network labs&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;security&#34;&gt;Security&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The use of malicious software packages continues to be a vector for attacks; here&amp;rsquo;s &lt;a href=&#34;https://thehackernews.com/2025/08/malicious-go-npm-packages-deliver-cross.html&#34;&gt;the latest discovery of malicious Go and &lt;code&gt;npm&lt;/code&gt; packages&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;James Kettle explains &lt;a href=&#34;https://portswigger.net/research/http1-must-die&#34;&gt;why HTTP/1.1 must die&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Gary Marcus and Nathan Hamiel discuss &lt;a href=&#34;https://garymarcus.substack.com/p/llms-coding-agents-security-nightmare&#34;&gt;why the combination of LLMs plus coding agents has the potential to result in a security nightmare&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gbhackers.com/stealth-threat-unpacked-weaponized-rar-files/&#34;&gt;Weaponized RAR files are delivering a backdoor to Linux systems&lt;/a&gt; using only a filename&amp;mdash;more details in the linked article.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://thehackernews.com/2025/08/whatsapp-issues-emergency-update-for.html&#34;&gt;WhatsApp patches a zero-click exploit targeting iOS and macOS devices&lt;/a&gt;. I don&amp;rsquo;t use WhatsApp, but I know lots of folks that do (it&amp;rsquo;s especially popular among my international friends). If you&amp;rsquo;re a WhatsApp user, be sure to update.&lt;/li&gt;
&lt;li&gt;More software supply chain attacks, this time &lt;a href=&#34;https://socket.dev/blog/ongoing-supply-chain-attack-targets-crowdstrike-npm-packages&#34;&gt;targeting CrowdStrike&amp;rsquo;s &lt;code&gt;npm&lt;/code&gt; packages&lt;/a&gt;, have been observed as part of a larger campaign known as &amp;ldquo;Shai-Hulud.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cloud-computingcloud-management&#34;&gt;Cloud Computing/Cloud Management&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Mike Roberts explains why &lt;a href=&#34;https://blog.symphonia.io/posts/2025-08-08_aws_lambda_deploy_github_action&#34;&gt;you probably don&amp;rsquo;t want to use AWS&amp;rsquo; new GitHub Actions Lambda Deployment action&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;What would you do if &lt;a href=&#34;https://www.seuros.com/blog/aws-deleted-my-10-year-account-without-warning/&#34;&gt;AWS deleted your account and all your data&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;AWS has &lt;em&gt;finally&lt;/em&gt; released &lt;a href=&#34;https://aws.amazon.com/blogs/devops/introducing-universal-installers-for-aws-cli-v2-on-macos/&#34;&gt;universal macOS installers for the AWS CLI&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;operating-systemsapplications&#34;&gt;Operating Systems/Applications&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Adam Thompson shares &lt;a href=&#34;https://hackeradam.com/improve-logitech-mx-master-3-mouse-support-on-arch-linux/&#34;&gt;how to improve Logitech MX Master 3 mouse support on Arch Linux&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Mitchell Hashimoto shares some lessons learned when they &lt;a href=&#34;https://mitchellh.com/writing/ghostty-gtk-rewrite&#34;&gt;rewrote the Ghostty GTK application&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.openpolicyagent.org/note-from-teemu-tim-and-torin-to-the-open-policy-agent-community-2dbbfe494371&#34;&gt;Some of the creators of Open Policy Agent (OPA) are joining Apple.&lt;/a&gt; Interesting.&lt;/li&gt;
&lt;li&gt;Simon Späti shares details on their &lt;a href=&#34;https://www.ssp.sh/blog/macbook-to-arch-linux-omarchy/&#34;&gt;journey from macOS to Arch Linux with Omarchy&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Here is a useful post on &lt;a href=&#34;https://roguesecurity.dev/blog/systemd-hardening&#34;&gt;systemd service hardening&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The details of &lt;a href=&#34;https://security.apple.com/blog/memory-integrity-enforcement/&#34;&gt;this post on Apple&amp;rsquo;s new Memory Integrity Enforcement (MIE)&lt;/a&gt; are a bit beyond me, I&amp;rsquo;ll be honest. I&amp;rsquo;m of two minds on the new technology. On one hand, it&amp;rsquo;s nice to see progress at fixing memory safety-related bugs and exploits. On the other hand, this progress could only be achieved, as the article states, through combining &amp;ldquo;the unique strengths of Apple silicon hardware with our advanced operating system security.&amp;rdquo; In other words, more tightly coupling the hardware and the OS.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;programmingdevelopment&#34;&gt;Programming/Development&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Go has &lt;a href=&#34;https://go.dev/blog/container-aware-gomaxprocs&#34;&gt;changed the way the language handles &lt;code&gt;GOMAXPROCS&lt;/code&gt; in the 1.25 release&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;virtualization&#34;&gt;Virtualization&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;In advance of VMware Explore 2025&amp;mdash;which apparently is/was this week in Las Vegas&amp;mdash;William Lam shares &lt;a href=&#34;https://williamlam.com/2025/08/updated-nested-esxi-8-x-9-0-virtual-appliance.html&#34;&gt;an update on the nested ESXi 8.0 and ESXi 9.0 virtual appliance&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;careersoft-skills&#34;&gt;Career/Soft Skills&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ashley Willis talks about &lt;a href=&#34;https://ashley.dev/posts/the-quiet-season/&#34;&gt;the value and importance of the quiet season&lt;/a&gt;. I particularly found this sentence applicable to my own life: &amp;ldquo;So yes, I&amp;rsquo;m writing again. And maybe I&amp;rsquo;m less &amp;rsquo;everywhere&amp;rsquo; than I used to be. But I&amp;rsquo;d rather show up less often and have something worth saying than burn myself out trying to convince the world I&amp;rsquo;m still here.&amp;rdquo; Well said, IMO.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://churchofturing.github.io/the-enterprise-experience.html&#34;&gt;All too true.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I don&amp;rsquo;t know if I would go so far as to say &lt;a href=&#34;https://anthonymoser.github.io/writing/ai/haterdom/2025/08/26/i-am-an-ai-hater.html&#34;&gt;I am an AI hater&lt;/a&gt;, but I am most definitely opposed to AI in its current form. (I don&amp;rsquo;t even like calling it &amp;ldquo;AI&amp;rdquo; when it&amp;rsquo;s really nothing more than a statistical model for putting words together. But that&amp;rsquo;s another discussion for another day&amp;hellip;) As the author says, being a hater is a &amp;ldquo;kind of integrity&amp;rdquo; all its own&amp;mdash;so I say, if you&amp;rsquo;re an AI hater, don&amp;rsquo;t be afraid to say so.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s time to wrap up now&amp;mdash;but don&amp;rsquo;t be sad, I&amp;rsquo;ll be back soon with more content. In the meantime, if you&amp;rsquo;d like to reach out to me to provide some feedback on this article or any article, I&amp;rsquo;d love to hear from you! Feel free to contact me via &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;Bluesky&lt;/a&gt;, via &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;Mastodon&lt;/a&gt;, via &lt;a href=&#34;https://twitter.com/scott_lowe&#34;&gt;X/Twitter&lt;/a&gt;, via Slack (I frequent a number of different communities, including the Kubernetes Slack instance) or even via email. Thanks for reading!&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>Creating a Talos Linux Cluster on AWS with Pulumi, 2025 Edition</title>
        <link>https://blog.scottlowe.org/2025/09/08/creating-a-talos-linux-cluster-on-aws-with-pulumi-2025-edition/</link>
        <pubDate>Mon, 08 Sep 2025 09:35:00 EDT</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2025/09/08/creating-a-talos-linux-cluster-on-aws-with-pulumi-2025-edition/</guid>
        <description>&lt;p&gt;A little over two years ago, I wrote a post on &lt;a href=&#34;https://blog.scottlowe.org/2023/02/24/creating-a-talos-linux-cluster-on-aws-with-pulumi/&#34;&gt;creating a Talos Linux cluster on AWS using Pulumi&lt;/a&gt;. At the time of that post, the Pulumi provider for Talos was still a prerelease version. Since then, the Talos provider has undergone some notable changes necessitating an update to the example code I have on GitHub. For your reading pleasure, therefore, I present you with the 2025 edition of a tutorial for using Pulumi to create a Talos Linux cluster on AWS.&lt;/p&gt;
&lt;p&gt;The updated &lt;a href=&#34;https://www.pulumi.com/&#34;&gt;Pulumi&lt;/a&gt; code can be found in &lt;a href=&#34;https://github.com/scottslowe/talos-aws-pulumi/&#34;&gt;this GitHub repository&lt;/a&gt;. Note that I&amp;rsquo;ve tagged the original version from the 2023 blog post with the &amp;ldquo;2023-post&amp;rdquo; tag, in the event you&amp;rsquo;d like to see the original code. While I chose to write my Pulumi code in &lt;a href=&#34;https://go.dev&#34;&gt;Go&lt;/a&gt;, note that Pulumi supports a number of different languages (such as JavaScript/TypeScript, Python, one of the .NET languages, Java, or even YAML). I leave it as an exercise for the reader to re-implement this functionality in a different language. This Pulumi program is based on &lt;a href=&#34;https://www.talos.dev/v1.11/talos-guides/install/cloud-platforms/aws/&#34;&gt;the Talos documentation for standing up a cluster on AWS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Pulumi program has four major sections:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, it creates the underlying base infrastructure needed for a Talos Linux cluster to run. This includes a VPC (and all the assorted other pieces, like subnets, gateways, routes, and route tables) and a load balancer. The load balancer is needed for the Kubernetes control plane, which we will bootstrap later in the program. This portion also creates the EC2 instances for the control plane.&lt;/li&gt;
&lt;li&gt;Next, it uses the Talos Pulumi provider to generate the Talos configuration that will be applied to the instances after they are created. This configuration needs information from step 1; specifically, it needs the DNS name of the load balancer and the IP addresses of the control plane nodes.&lt;/li&gt;
&lt;li&gt;Third, it applies the correct configuration to the control plane nodes, and launches some EC2 instances to serve as worker nodes in the Kubernetes cluster. The program then takes the Talos configuration from step 2 and applies it to the worker nodes.&lt;/li&gt;
&lt;li&gt;The fourth and final step is to bootstrap the cluster.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For those who need a &amp;ldquo;TL;DR&amp;rdquo;: you can clone &lt;a href=&#34;https://github.com/scottslowe/talos-aws-pulumi/&#34;&gt;the associated repository&lt;/a&gt;, run &lt;code&gt;pulumi up&lt;/code&gt;, and have a working Talos Linux cluster in a few minutes.&lt;/p&gt;
&lt;p&gt;For those who want a bit more detail, read on.&lt;/p&gt;
&lt;h2 id=&#34;creating-the-aws-infrastructure&#34;&gt;Creating the AWS Infrastructure&lt;/h2&gt;
&lt;p&gt;The first part of the Pulumi program (running through about line 270) creates the necessary AWS infrastructure. The program leverages &lt;a href=&#34;https://www.pulumi.com/docs/iac/clouds/aws/guides/&#34;&gt;Crosswalk for AWS&lt;/a&gt; to simplify the creation of the underlying VPC and associated components. Most of the code involves creating security groups and security group rules.&lt;/p&gt;
&lt;p&gt;This part of the program also creates the load balancer that will be used for the Kubernetes API.&lt;/p&gt;
&lt;p&gt;Finally, the program launches three EC2 instances using one of the official Talos AMIs. In the original version of the code, you had to supply the AMI ID as a configuration value; this version looks up the AMI when it runs. The IDs and the private IP addresses for these EC2 instances are stored in two different arrays; we&amp;rsquo;ll need this information later.&lt;/p&gt;
&lt;h2 id=&#34;creating-the-talos-configuration&#34;&gt;Creating the Talos Configuration&lt;/h2&gt;
&lt;p&gt;The next part of the Pulumi program builds the Talos configuration, using the  Pulumi provider and information (outputs) from the resources created earlier. Specifically, the Talos configuration uses the DNS name of the load balancer created earlier, and the IP addresses of the EC2 instances (which will become the control plane nodes for the Kubernetes cluster).&lt;/p&gt;
&lt;p&gt;There are three parts to the configuration:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A client configuration file, which the &lt;code&gt;talosctl&lt;/code&gt; command-line utility uses to connect to the Talos Linux nodes&lt;/li&gt;
&lt;li&gt;Machine configuration for the control plane nodes&lt;/li&gt;
&lt;li&gt;Machine configuration for the worker nodes&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;configuring-the-nodes&#34;&gt;Configuring the Nodes&lt;/h2&gt;
&lt;p&gt;Once the Talos provider builds the correct machine configurations, the program then applies the configuration to each of the control plane nodes (worker nodes are handled later). The most efficient way would be to &lt;code&gt;range&lt;/code&gt; over the array with the instance IP addresses and apply the configuration to each instance. However, in this particular case we need to build a dependency on applying the machine configuration, so the program does it &amp;ldquo;manually.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Once the machine configuration has been applied to the control plane nodes, three more EC2 instances are launched for worker nodes, and then the correct machine configuration is applied to those nodes (this time iterating through the array).&lt;/p&gt;
&lt;h2 id=&#34;bootstrapping-the-cluster&#34;&gt;Bootstrapping the Cluster&lt;/h2&gt;
&lt;p&gt;Finally, it comes down to bootstrapping the cluster (see line 397), which&amp;mdash;again using the Talos provider for Pulumi&amp;mdash;is accomplished with calling &lt;code&gt;machine.NewBootstrap&lt;/code&gt; against the first control plane node to be created. The Pulumi program will complete after this; it doesn&amp;rsquo;t wait for the bootstrap process to complete (which will take a few more minutes).&lt;/p&gt;
&lt;p&gt;At this point, you can use &lt;code&gt;pulumi stack output&lt;/code&gt; to retrieve a configuration file for the &lt;code&gt;talosctl&lt;/code&gt; command-line utility, and then run &lt;code&gt;talosctl health&lt;/code&gt; to watch the cluster bootstrap. Once the cluster is up and running, &lt;code&gt;talosctl kubeconfig&lt;/code&gt; will get you a Kubeconfig file you can use to access the Kubernetes API via &lt;code&gt;kubectl&lt;/code&gt;. Nice!&lt;/p&gt;
&lt;h2 id=&#34;additional-resources&#34;&gt;Additional Resources&lt;/h2&gt;
&lt;p&gt;The updated Pulumi code is available on GitHub in &lt;a href=&#34;https://github.com/scottslowe/talos-aws-pulumi/&#34;&gt;this repository&lt;/a&gt;. Please note that I tested the code and it works for me, but it is supplied &amp;ldquo;as-is&amp;rdquo;. Don&amp;rsquo;t use this for your production environment without performing your own testing and validation!&lt;/p&gt;
&lt;p&gt;Thanks for reading! I hope this post is helpful. If you have questions, you&amp;rsquo;re welcome to open an issue in &lt;a href=&#34;https://github.com/scottslowe/talos-aws-pulumi/&#34;&gt;the GitHub repository&lt;/a&gt;, or you can contact me directly. If you have a potential enhancement to the code, you&amp;rsquo;re invited to open a pull request. For more in-depth discussions, it&amp;rsquo;s not hard to get in touch with me&amp;mdash;you can find me &lt;a href=&#34;https://twitter.com/scott_lowe&#34;&gt;on Twitter&lt;/a&gt;, &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;on Mastodon&lt;/a&gt;, and on various Slack communities (including the &lt;a href=&#34;https://kubernetes.slack.com&#34;&gt;Kubernetes&lt;/a&gt; and &lt;a href=&#34;https://slack.pulumi.com&#34;&gt;Pulumi&lt;/a&gt; Slack communities).&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Technology Short Take 187</title>
        <link>https://blog.scottlowe.org/2025/08/08/technology-short-take-187/</link>
        <pubDate>Fri, 08 Aug 2025 09:00:00 EDT</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2025/08/08/technology-short-take-187/</guid>
        <description>&lt;p&gt;Welcome to Technology Short Take #187! In this Technology Short Take, I have a curated collection of links on topics ranging from BGP to blade server hardware to writing notes using a &amp;ldquo;zettelkasten&amp;rdquo;-style approach, along with a few other topics thrown in here and there for fun. I hope you find something useful!&lt;/p&gt;
&lt;h2 id=&#34;networking&#34;&gt;Networking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Jason Gintert justifies the value behind &lt;a href=&#34;https://www.bitsinflight.com/keeping-public-bgp-routing-in-check-with-irr-and-rpsl/&#34;&gt;using IRRs and RPSL to keep your public BGP routing working well&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;IPv6 has a new documentation prefix, as outlined &lt;a href=&#34;https://blog.ipspace.net/2025/01/rfc9637-ipv6-documentation-prefix/&#34;&gt;by Ivan Pepelnjak in his blog post&lt;/a&gt; as well as &lt;a href=&#34;https://forwardingplane.net/post/2024-12-21-new-ipv6-doc-space-rfc9637/&#34;&gt;by Nick Buraglio in his blog post&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;servershardware&#34;&gt;Servers/Hardware&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Kevin Houston takes &lt;a href=&#34;https://bladesmadesimple.com/2025/07/taking-a-look-at-the-newest-blade-server-offerings/&#34;&gt;a look at the latest blade server offerings&lt;/a&gt; from Cisco and HPE.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;security&#34;&gt;Security&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;This is an older article dating back to the start of 2025, but it &lt;a href=&#34;https://www.bleepingcomputer.com/news/security/subaru-starlink-flaw-let-hackers-hijack-cars-in-us-and-canada/&#34;&gt;outlines a potential security flaw&lt;/a&gt; that allowed hackers to hijack Subaru cars in the US and Canada.&lt;/li&gt;
&lt;li&gt;Rory McCune &lt;a href=&#34;https://securitylabs.datadoghq.com/articles/kubernetes-security-fundamentals-part-7/&#34;&gt;tackles PKI in this post of his series on Kubernetes security fundamentals&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Daniel Stenberg (of &lt;code&gt;curl&lt;/code&gt; fame) explains &lt;a href=&#34;https://daniel.haxx.se/blog/2025/01/23/cvss-is-dead-to-us/&#34;&gt;why the &lt;code&gt;curl&lt;/code&gt; project doesn&amp;rsquo;t use CVSS scores&lt;/a&gt; and describes some of the problems that result from this decision.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cloud-computingcloud-management&#34;&gt;Cloud Computing/Cloud Management&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I&amp;rsquo;ve spoken about Cedar before here on this site. The first mention of Cedar was in &lt;a href=&#34;https://blog.scottlowe.org/2023/02/17/technology-short-take-165/&#34;&gt;TST 165&lt;/a&gt;; later, in &lt;a href=&#34;https://blog.scottlowe.org/2023/05/12/technology-short-take-168/&#34;&gt;TST 168&lt;/a&gt;, I pondered why AWS went through the effort of creating and open-sourcing Cedar. In a paper on Cedar (linked to via &lt;a href=&#34;https://muratbuffalo.blogspot.com/2025/03/cedar-new-language-for-expressive-fast.html&#34;&gt;this post&lt;/a&gt;), I learned that consistent performance at scale was one benefit of Cedar when compared to other policy solutions, including Open Policy Agent (OPA). Good to know!&lt;/li&gt;
&lt;li&gt;Also on the topic of Cedar: here&amp;rsquo;s &lt;a href=&#34;https://github.com/cedar-policy/cedar-access-control-for-k8s&#34;&gt;an implementation of Kubernetes RBAC in Cedar&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;This blog post provides some insight on &lt;a href=&#34;https://aws.amazon.com/blogs/containers/under-the-hood-amazon-eks-ultra-scale-clusters/&#34;&gt;how Amazon scaled EKS to support up to 100,000 nodes&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The Infisical team &lt;a href=&#34;https://infisical.com/blog/terraform-modules-organization-scaling&#34;&gt;provides a case for using Terraform modules&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Looking for &lt;a href=&#34;https://nubis.ma/blog/terraform_infrastructure_as_code_essential_tools_for_clean_maintainable_production_environments/&#34;&gt;a list of useful, IaC-adjacent tools&lt;/a&gt;? Look no further.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;operating-systemsapplications&#34;&gt;Operating Systems/Applications&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Marcus Hutchins &lt;a href=&#34;https://malwaretech.com/2025/08/every-reason-why-i-hate-ai.html&#34;&gt;explains his stance on AI&lt;/a&gt;. It&amp;rsquo;s a bit of a long read, but he goes into great detail for all the reasons why he&amp;rsquo;s opposed to AI in its current form (LLMs).&lt;/li&gt;
&lt;li&gt;Julian Hofer &lt;a href=&#34;https://julianhofer.eu/blog/03-git-forges/&#34;&gt;discusses&lt;/a&gt; CLI tools (&lt;code&gt;gh&lt;/code&gt; and &lt;code&gt;glab&lt;/code&gt;, for GitHub and GitLab, respectively) and how they enhance the &lt;code&gt;git&lt;/code&gt; CLI experience when working with these online services (which he calls &amp;ldquo;Git forges&amp;rdquo;).&lt;/li&gt;
&lt;li&gt;The Register &lt;a href=&#34;https://www.theregister.com/2025/03/08/kernel_sanders_apple_rearranges_xnu/&#34;&gt;clues its readers in&lt;/a&gt; on some security changes Apple is supposedly making in iOS and macOS, leveraging a feature called &amp;ldquo;exclaves&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Stig Brautaset &lt;a href=&#34;https://www.brautaset.org/posts/yaml-exponent-problem.html&#34;&gt;describes YAML&amp;rsquo;s exponent problem&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;storage&#34;&gt;Storage&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ben Dicken of PlanetScale has a good primer on &lt;a href=&#34;https://planetscale.com/blog/io-devices-and-latency&#34;&gt;IO devices and latency&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;virtualization&#34;&gt;Virtualization&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;William Lam takes readers through the steps necessary to &lt;a href=&#34;https://williamlam.com/2025/08/quick-tip-how-to-rename-a-vsan-virtual-machine-and-its-files.html&#34;&gt;rename a vSAN virtual machine and its files&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;ve been thinking recently that I need to give &lt;a href=&#34;https://linuxcontainers.org/incus/docs/main/&#34;&gt;Incus&lt;/a&gt; a deeper look. This article on &lt;a href=&#34;http://serverascode.com//2024/10/19/incus-installation-and-use.html&#34;&gt;Incus installation and use (focused on storage pools and networking)&lt;/a&gt; will likely come in handy.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;careersoft-skills&#34;&gt;Career/Soft Skills&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ruben Schade explains why &lt;a href=&#34;https://rubenerd.com/boring-tech-is-mature-not-old/&#34;&gt;calling a technology &amp;ldquo;boring&amp;rdquo; is actually a compliment&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Scott Young provides some guidance to know &lt;a href=&#34;https://www.scotthyoung.com/blog/2025/07/08/strengths/&#34;&gt;when focusing on your strengths isn&amp;rsquo;t the best approach&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Over the past year or two, I&amp;rsquo;ve been experimenting with a &amp;ldquo;zettelkasten&amp;rdquo; style of note taking. Accordingly, I&amp;rsquo;ve been reading various articles and resources about this approach, what makes it work, and how to use it effectively. Among other articles, this article by Bob Doto &lt;a href=&#34;https://writing.bobdoto.computer/what-do-we-mean-when-we-say-bottom-up/&#34;&gt;on &amp;ldquo;bottom up&amp;rdquo; versus &amp;ldquo;top down&amp;rdquo; in note-taking&lt;/a&gt; was helpful.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s all for now. I welcome all feedback as long as it is constructive; feel free to reach out and tell me what I could improve! There are a variety of ways to get in touch with me; you can reach me via various social media sites (&lt;a href=&#34;https://twitter.com/scott_lowe&#34;&gt;Twitter&lt;/a&gt;, &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;Mastodon&lt;/a&gt;, and &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;Bluesky&lt;/a&gt;), via Slack (I frequent &lt;a href=&#34;https://kubernetes.slack.com/&#34;&gt;the Kubernetes Slack community&lt;/a&gt;, among others), or via email (my address is on this site and it&amp;rsquo;s not too hard to guess). I&amp;rsquo;d love to hear from you!&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Technology Short Take 186</title>
        <link>https://blog.scottlowe.org/2025/07/11/technology-short-take-186/</link>
        <pubDate>Fri, 11 Jul 2025 10:00:00 EDT</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2025/07/11/technology-short-take-186/</guid>
        <description>&lt;p&gt;Welcome to Technology Short Take #186! Yes, it&amp;rsquo;s been quite a while since I published a Technology Short Take; life has &amp;ldquo;gotten in the way,&amp;rdquo; so to speak, of gathering links to share with all of you. However, I think this crazy phase of my life is about to start settling down (I hope so, anyway), and I&amp;rsquo;m cautiously optimistic that I&amp;rsquo;ll be able to pick up the blogging pace once again. For now, though, here&amp;rsquo;s a collection of links I&amp;rsquo;ve gathered since the last Technology Short Take. I hope you find something useful here!&lt;/p&gt;
&lt;h2 id=&#34;networking&#34;&gt;Networking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Nick Buraglio explains &lt;a href=&#34;https://www.forwardingplane.net/post/2025-01-11-cloudflared-tunnel-ipv6/&#34;&gt;how to use Cloudflare Tunnel for IPv6-only connectivity&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A colleague recently introduced me to &lt;a href=&#34;https://ultraethernet.org/&#34;&gt;Ultra Ethernet&lt;/a&gt;, which is (as I understand it) designed for AI and HPC workloads and intends to &amp;ldquo;close the gap&amp;rdquo; between InfiniBand and Ethernet. Although, in reading &lt;a href=&#34;https://www.wwt.com/blog/the-battle-of-ai-networking-ethernet-vs-infiniband&#34;&gt;this comparison between InfiniBand and Ethernet by WWT&lt;/a&gt;, it looks like the gap isn&amp;rsquo;t necessarily all that large. (Hat tip to Drew for the links.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;security&#34;&gt;Security&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;CSO Online briefly touches on &lt;a href=&#34;https://www.csoonline.com/article/3632044/more-telecom-firms-were-breached-by-chinese-hackers-than-previously-reported.html&#34;&gt;the scope of the Salt Typhoon hacking campaign&lt;/a&gt;, now revealed to include even more companies than previously thought.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://krebsonsecurity.com/2025/01/microsoft-happy-2025-heres-161-security-updates/&#34;&gt;161 security vulnerabilities, including three actively exploited zero-day vulnerabilities&lt;/a&gt;? Holy broken software! I know that &lt;em&gt;no&lt;/em&gt; software is without security vulnerabilities, but this is just&amp;hellip;wow. Be sure to read the linked article for more details on all the patched vulnerabilities to make sure you are appropriately protected.&lt;/li&gt;
&lt;li&gt;Here&amp;rsquo;s an article describing &lt;a href=&#34;https://oddlama.org/blog/bypassing-disk-encryption-with-tpm2-unlock/&#34;&gt;how to bypass disk encryption on systems with automatic TPM2 unlock&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cloud-computingcloud-management&#34;&gt;Cloud Computing/Cloud Management&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;There&amp;rsquo;s some good real-world experience contained in Jon Spriggs&amp;rsquo; post about &lt;a href=&#34;https://jon.sprig.gs/blog/post/8078&#34;&gt;a few weird issues in his custom AWS EKS workers&lt;/a&gt;. I love that Jon also included the workarounds for each issue; this is really helpful.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;operating-systemsapplications&#34;&gt;Operating Systems/Applications&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Matt of NSHipster explains how to use the 1Password CLI (&lt;code&gt;op&lt;/code&gt;) to &lt;a href=&#34;https://nshipster.com/1password-cli/&#34;&gt;automatically inject secrets into environment files&lt;/a&gt; in conjunction with &lt;code&gt;op run&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I appreciate Julia Evans&amp;rsquo; post on &lt;a href=&#34;https://jvns.ca/blog/2025/01/11/getting-a-modern-terminal-setup/&#34;&gt;what&amp;rsquo;s involved in getting a &amp;ldquo;modern&amp;rdquo; terminal setup&lt;/a&gt;. Julia&amp;rsquo;s approach is &lt;code&gt;fish&lt;/code&gt; plus &lt;code&gt;neovim&lt;/code&gt; plus a terminal emulator with 24-bit color support. While the autocomplete suggestions from &lt;code&gt;fish&lt;/code&gt; look really appealing, I&amp;rsquo;ve settled into &lt;code&gt;bash&lt;/code&gt; plus &lt;code&gt;starship&lt;/code&gt; plus &lt;code&gt;exa&lt;/code&gt; (or &lt;code&gt;eza&lt;/code&gt;) and a handful of very useful other CLI tools (&lt;code&gt;rg&lt;/code&gt;, &lt;code&gt;fd&lt;/code&gt;, and &lt;code&gt;fzf&lt;/code&gt;, notably).&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s no secret that I have not (thus far) been a fan of LLMs; I suppose there&amp;rsquo;s just too much hype and not enough reality for my tastes. In spite of that&amp;mdash;or perhaps because of that?&amp;mdash;I appreciated David Crawshaw&amp;rsquo;s balanced and down to earth discussion of &lt;a href=&#34;https://crawshaw.io/blog/programming-with-llms&#34;&gt;his personal experience using generative models while programming&lt;/a&gt;. I particularly appreciated David&amp;rsquo;s very honest acknowledgement of some of the flaws of LLMs, as well as how he shared both the good and the bad he&amp;rsquo;s uncovered in his experimentation.&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;ll be honest, I love seeing stuff like &lt;a href=&#34;https://marcusb.org/hacks/quixotic.html&#34;&gt;these anti-LLM scraping tools&lt;/a&gt; start to emerge.&lt;/li&gt;
&lt;li&gt;What&amp;rsquo;s this&amp;mdash;someone &lt;a href=&#34;https://blog.tjll.net/the-systemd-revolution-has-been-a-success/&#34;&gt;speaking &lt;em&gt;in favor&lt;/em&gt; of systemd&lt;/a&gt;? Unthinkable!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s all for now! I know, this one is shorter than the typical Technology Short Take. Nevertheless, hopefully I shared something useful. If you have any feedback, please feel free to reach out! I don&amp;rsquo;t use Twitter/X very much these days, but I&amp;rsquo;m still &lt;a href=&#34;https://twitter.com/scott_lowe&#34;&gt;there&lt;/a&gt;; you can also reach me &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;on Mastodon&lt;/a&gt;, &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;on Bluesky&lt;/a&gt;, or through one of the various Slack communities I frequent (such as &lt;a href=&#34;https://kubernetes.slack.com/&#34;&gt;the Kubernetes Slack instance&lt;/a&gt;). Thanks for reading!&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Bootstrapping Dual-Stack Kubernetes on Flatcar with Kubeadm</title>
        <link>https://blog.scottlowe.org/2025/06/03/bootstrapping-dual-stack-kubernetes-on-flatcar-with-kubeadm/</link>
        <pubDate>Tue, 03 Jun 2025 09:00:00 EDT</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2025/06/03/bootstrapping-dual-stack-kubernetes-on-flatcar-with-kubeadm/</guid>
        <description>&lt;p&gt;Recently I needed to be able to stand up a dual-stack (IPv4/IPv6) Kubernetes cluster on Flatcar Container Linux using &lt;code&gt;kubeadm&lt;/code&gt;. At first glance, this seemed like it would be relatively straightforward, but as I dug deeper into it there were a few quirks that emerged. Given these quirks, it seemed like a worthwhile process to write up and publish here. In this post, you&amp;rsquo;ll see how to use Butane and &lt;code&gt;kubeadm&lt;/code&gt; to bootstrap a dual-stack IPv4/IPv6 Kubernetes cluster on AWS.&lt;/p&gt;
&lt;p&gt;For those who are unfamiliar, &lt;a href=&#34;https://www.flatcar.org/&#34;&gt;Flatcar Container Linux&lt;/a&gt; is a container-optimized Linux distribution considered to be the spiritual successor to CoreOS. For configuring OS instances during provisioning, Flatcar uses Ignition (see &lt;a href=&#34;https://github.com/coreos/ignition&#34;&gt;here&lt;/a&gt; or &lt;a href=&#34;https://www.flatcar.org/docs/latest/provisioning/ignition/&#34;&gt;here&lt;/a&gt; for more information). Ignition is intended to be machine-friendly, but not human-friendly. Users can use &lt;a href=&#34;https://www.flatcar.org/docs/latest/provisioning/config-transpiler/&#34;&gt;Butane&lt;/a&gt; to write human-friendly YAML configurations that then get transpiled into Ignition. So, when bootstrapping Kubernetes on Flatcar, users will generally use a Butane configuration that leverages &lt;code&gt;kubeadm&lt;/code&gt;, as described &lt;a href=&#34;https://www.flatcar.org/docs/latest/container-runtimes/getting-started-with-kubernetes/&#34;&gt;in the Flatcar documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While the Butane configurations in the documentation are a good start for bootstrapping Kubernetes on Flatcar, they don&amp;rsquo;t address the dual-stack use case. As outlined &lt;a href=&#34;https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/dual-stack-support/#create-a-dual-stack-cluster&#34;&gt;in the Kubernetes documentation for dual-stack support with &lt;code&gt;kubeadm&lt;/code&gt;&lt;/a&gt;, you need to tell &lt;code&gt;kubeadm&lt;/code&gt; to have the Kubernetes nodes register themselves with &lt;em&gt;both&lt;/em&gt; the IPv4 and the IPv6 addresses, like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;nodeRegistration&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;kubeletExtraArgs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;node-ip&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;value&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;10.100.0.2,fd00:1:2:3::2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can also use this syntax:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;nodeRegistration&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;kubeletExtraArgs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;node-ip&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;10.100.0.2,fd00:1:2:3::2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you don&amp;rsquo;t specifically instruct the Kubelet to use both addresses, it will register with only one of the addresses (typically the IPv4 address), and you won&amp;rsquo;t have dual-stack support.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re in a situation where you are bootstrapping Kubernetes with &lt;code&gt;kubeadm&lt;/code&gt; after the OS boots, then you&amp;rsquo;re able to find out what IP addresses the instance is using and configure your &lt;code&gt;kubeadm&lt;/code&gt; configuration file accordingly. In this case, however, we are running &lt;code&gt;kubeadm&lt;/code&gt; immediately after boot (by supplying the Butane configuration as user data via &lt;a href=&#34;https://developer.hashicorp.com/terraform&#34;&gt;Terraform&lt;/a&gt; with &lt;a href=&#34;https://registry.terraform.io/providers/poseidon/ct/latest&#34;&gt;the terraform-ct provider&lt;/a&gt;). How are we going to know what addresses were picked up by the OS when it booted? How can we tell &lt;code&gt;kubeadm&lt;/code&gt; which addresses to use? This is the first challenge I encountered when working out how to bootstrap a dual-stack cluster with Flatcar.&lt;/p&gt;
&lt;p&gt;Fortunately, there is a solution: enter &lt;a href=&#34;https://github.com/coreos/afterburn/&#34;&gt;Afterburn&lt;/a&gt;. Afterburn dates from the CoreOS days but is supported for use on Flatcar (although some of the variable names change slightly; be sure to refer &lt;a href=&#34;https://www.flatcar.org/docs/latest/provisioning/ignition/dynamic-data/&#34;&gt;to the Flatcar documentation&lt;/a&gt; for the exact changes). Among other things, Afterburn enables users to get IP addresses in use by the system by using specific environment variables&amp;mdash;perfect for this use case.&lt;/p&gt;
&lt;p&gt;To use Afterburn, a few changes are needed to the Butane configuration that invokes &lt;code&gt;kubeadm&lt;/code&gt;. Specifically:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The systemd unit for &lt;code&gt;kubeadm&lt;/code&gt; needs to be dependent upon the Afterburn service (referenced as &amp;ldquo;coreos-metadata.service&amp;rdquo;).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;kubeadm&lt;/code&gt; systemd unit needs to load the environment file created by Afterburn.&lt;/li&gt;
&lt;li&gt;An additional line is needed to invoke &lt;code&gt;envsubst&lt;/code&gt; to supply the dynamic values provided by Afterburn.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first change involves modifying the &lt;code&gt;Requires=&lt;/code&gt; and &lt;code&gt;After=&lt;/code&gt; lines in the &lt;code&gt;[Unit]&lt;/code&gt; section of the systemd unit definition, like this (this is the Butane configuration creating the &lt;code&gt;kubeadm&lt;/code&gt; systemd unit):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;systemd&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;units&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;kubeadm.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;enabled&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Unit]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Description=Kubeadm service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Requires=containerd.service coreos-metadata.service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        After=containerd.service coreos-metadata.service&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The second change requires the addition of an &lt;code&gt;EnvironmentFile=&lt;/code&gt; line at the beginning of the &lt;code&gt;[Service]&lt;/code&gt; section. Building on the previous example, here&amp;rsquo;s what that looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;systemd&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;units&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;kubeadm.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;enabled&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Unit]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Description=Kubeadm service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Requires=containerd.service coreos-metadata.service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        After=containerd.service coreos-metadata.service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ConditionPathExists=!/etc/kubernetes/kubelet.conf
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Service]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        EnvironmentFile=/run/metadata/flatcar&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This sources the &lt;code&gt;/run/metadata/flatcar&lt;/code&gt; file created by Afterburn. This simple text file contains environment variable definitions of various pieces of metadata gathered by Afterburn. Of particular interest in this case are the &lt;code&gt;COREOS_EC2_IPV4_LOCAL&lt;/code&gt; and &lt;code&gt;COREOS_EC2_IPV6&lt;/code&gt; variables&amp;mdash;these contain the local IPv4 and IPv6 addresses in use. These environment variables are now available for use by any of the rest of the commands in the systemd unit.&lt;/p&gt;
&lt;p&gt;The third and final change uses &lt;code&gt;envsubst&lt;/code&gt; to replace placeholders in the &lt;code&gt;kubeadm&lt;/code&gt; configuration with the dynamic values gathered by Afterburn. Before looking at that, let&amp;rsquo;s examine the &lt;code&gt;kubeadm&lt;/code&gt; configuration file being supplied by Butane:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;storage&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;files&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;path&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;/etc/kubeadm.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;inline&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          ---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          apiVersion: kubeadm.k8s.io/v1beta3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          kind: InitConfiguration
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          bootstrapTokens:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          - groups:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            - system:bootstrappers:kubeadm:default-node-token
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            token: ${token}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            ttl: 24h0m0s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            usages:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            - signing
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            - authentication
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          certificateKey: ${certificate_key}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          nodeRegistration:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            kubeletExtraArgs:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;              volume-plugin-dir: ${volume_plugin_dir}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;              cloud-provider: ${cloud_provider}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;              node-ip: &amp;#34;$COREOS_EC2_IPV4_LOCAL,$COREOS_EC2_IPV6&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          skipPhases:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          - addon/kube-proxy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          ---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          apiVersion: kubeadm.k8s.io/v1beta3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          kind: ClusterConfiguration
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          apiServer:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            certSANs:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;              - ${external_kube_apiserver_host}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;              - ${internal_kube_apiserver_host}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            extraArgs:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;              cloud-provider: ${cloud_provider}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            timeoutForControlPlane: 5m0s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          controlPlaneEndpoint: &amp;#34;${internal_kube_apiserver_host}:${internal_kube_apiserver_port}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          controllerManager:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            extraArgs:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;              flex-volume-plugin-dir: ${volume_plugin_dir}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;              cloud-provider: ${cloud_provider}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          kubernetesVersion: ${version_bare}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          networking:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            podSubnet: ${pod_cidr}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            serviceSubnet: ${service_cidr}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          clusterName: ${cluster_name}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          ---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          apiVersion: kubelet.config.k8s.io/v1beta1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          kind: KubeletConfiguration
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          cgroupDriver: systemd&lt;/span&gt;          
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some values in this configuration file are being supplied by the terraform-ct provider (these are referenced as &lt;code&gt;${variable}&lt;/code&gt;); they are templated in the Terraform configuration and variables are replaced. However, Terraform won&amp;rsquo;t know what the IP addresses are going to be until after the resource is created, at which point it&amp;rsquo;s too late. Hence, the &lt;code&gt;node-ip&lt;/code&gt; line uses &lt;code&gt;$VARIABLE&lt;/code&gt; syntax that will be picked up by &lt;code&gt;envsubst&lt;/code&gt; and replaced with the dynamic values retrieved by Afterburn. So there are essentially &lt;em&gt;two&lt;/em&gt; templating passes that take place: one at the Terraform layer, and a second one at the systemd/Butane layer. Confused yet?&lt;/p&gt;
&lt;p&gt;With this configuration in mind, the third change needed in the &lt;code&gt;kubeadm&lt;/code&gt; systemd unit created by Butane has to invoke &lt;code&gt;envsubst&lt;/code&gt;. This change looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;systemd&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;units&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;kubeadm.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;enabled&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Unit]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Description=Kubeadm service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Requires=containerd.service coreos-metadata.service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        After=containerd.service coreos-metadata.service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ConditionPathExists=!/etc/kubernetes/kubelet.conf
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Service]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        EnvironmentFile=/run/metadata/flatcar
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Environment=&amp;#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/bin&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/bin/bash -c &amp;#39;envsubst &amp;lt; /etc/kubeadm.yml &amp;gt; /etc/kubeadm-final.yml&amp;#39;&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The last line shown above is the key change. &lt;a href=&#34;https://www.man7.org/linux/man-pages/man5/systemd.service.5.html#COMMAND_LINES&#34;&gt;Shell redirection and pipes aren&amp;rsquo;t supported&lt;/a&gt; directly in systemd unit files, so it&amp;rsquo;s necessary to use &lt;code&gt;/bin/bash -c&lt;/code&gt; (or &lt;code&gt;/bin/sh -c&lt;/code&gt;) when invoking &lt;code&gt;envsubst&lt;/code&gt; in order for it to work correctly. Making &lt;code&gt;envsubst&lt;/code&gt; work properly in a systemd unit file was the second key challenge I ran into during this process.&lt;/p&gt;
&lt;p&gt;Finally, the &lt;code&gt;kubeadm&lt;/code&gt; systemd unit needs to invoke &lt;code&gt;kubeadm&lt;/code&gt; itself to bootstrap the cluster. I did find at least one change from the Flatcar examples that was useful here, which is the inclusion of the &lt;code&gt;--upload-certs&lt;/code&gt; flag. Here&amp;rsquo;s the final systemd unit for &lt;code&gt;kubeadm&lt;/code&gt; for the first control plane node:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;systemd&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;units&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;kubeadm.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;enabled&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Unit]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Description=Kubeadm service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Requires=containerd.service coreos-metadata.service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        After=containerd.service coreos-metadata.service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ConditionPathExists=!/etc/kubernetes/kubelet.conf
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Service]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        EnvironmentFile=/run/metadata/flatcar
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Environment=&amp;#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/bin&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/bin/bash -c &amp;#39;envsubst &amp;lt; /etc/kubeadm.yml &amp;gt; /etc/kubeadm-final.yml&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/opt/bin/kubeadm config images pull
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/opt/bin/kubeadm init --upload-certs --config /etc/kubeadm-final.yml
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/usr/bin/mkdir /home/${ssh_user}/.kube
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/usr/bin/cp /etc/kubernetes/admin.conf /home/${ssh_user}/.kube/config
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStart=/usr/bin/chown -R ${ssh_user}:${ssh_user} /home/${ssh_user}/.kube
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Install]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        WantedBy=multi-user.target&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And here&amp;rsquo;s the systemd unit for &lt;code&gt;kubeadm&lt;/code&gt; for additional control plane nodes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;systemd&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;units&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;kubeadm.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;enabled&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Unit]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Description=Kubeadm service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Requires=containerd.service coreos-metadata.service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        After=containerd.service coreos-metadata.service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ConditionPathExists=!/etc/kubernetes/kubelet.conf
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Service]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        EnvironmentFile=/run/metadata/flatcar
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Environment=&amp;#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/bin&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/bin/bash -c &amp;#39;envsubst &amp;lt; /etc/kubeadm.yml &amp;gt; /etc/kubeadm-final.yml&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/opt/bin/kubeadm config images pull
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=sleep 10
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/opt/bin/kubeadm join --config /etc/kubeadm-final.yml
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/usr/bin/mkdir /home/${ssh_user}/.kube
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/usr/bin/cp /etc/kubernetes/admin.conf /home/${ssh_user}/.kube/config
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStart=/usr/bin/chown -R ${ssh_user}:${ssh_user} /home/${ssh_user}/.kube
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Install]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        WantedBy=multi-user.target&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, here&amp;rsquo;s the systemd unit for &lt;code&gt;kubeadm&lt;/code&gt; for any worker nodes joined to the cluster:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;systemd&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;units&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;kubeadm.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;enabled&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Unit]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Description=Kubeadm service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Requires=containerd.service coreos-metadata.service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        After=containerd.service coreos-metadata.service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ConditionPathExists=!/etc/kubernetes/kubelet.conf
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Service]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        EnvironmentFile=/run/metadata/flatcar
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        Environment=&amp;#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/bin&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/bin/bash -c &amp;#39;envsubst &amp;lt; /etc/kubeadm.yml &amp;gt; /etc/kubeadm-final.yml&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStartPre=/opt/bin/kubeadm config images pull
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        ExecStart=/opt/bin/kubeadm join --config /etc/kubeadm-final.yml
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        [Install]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        WantedBy=multi-user.target&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The last step is supplying the full Butane configuration, including the &lt;code&gt;kubeadm&lt;/code&gt; configuration file and the &lt;code&gt;kubeadm&lt;/code&gt; systemd unit, as user data to the AWS instance when it boots. I did this in Terraform via &lt;a href=&#34;https://registry.terraform.io/providers/poseidon/ct/latest&#34;&gt;the &lt;code&gt;terraform-ct&lt;/code&gt; provider&lt;/a&gt;, but really just about any method you want to use will work.&lt;/p&gt;
&lt;p&gt;Whew! That was a lot&amp;mdash;let&amp;rsquo;s recap things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Bootstrapping Kubernetes on Flatcar generally involves the use of a Butane configuration to perform certain tasks, create files, and define systemd unit when the system boots up. On AWS, you&amp;rsquo;ll pass this Butane configuraiton to the EC2 instance(s) as user data.&lt;/li&gt;
&lt;li&gt;The Butane configuration needs to define both a &lt;code&gt;kubeadm&lt;/code&gt; configuration file and a &lt;code&gt;kubeadm&lt;/code&gt; systemd unit.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;kubeadm&lt;/code&gt; configuration file needs to include placeholders for the Afterburn-defined environment variables &lt;code&gt;$COREOS_EC2_IPV4_LOCAL&lt;/code&gt; and &lt;code&gt;$COREOS_EC2_IPV6&lt;/code&gt; in the nodeRegistration portion of the InitConfiguration section.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;kubeadm&lt;/code&gt; systemd unit needs to be told to depend on Afterburn (aka &amp;ldquo;coreos-metadata.service&amp;rdquo;), needs to read in the environment file created by Afterburn, and needs to use &lt;code&gt;envsubst&lt;/code&gt; (or whatever tool you choose) to replace the placeholders mentioned in step 3 with the actual values. This ensures that the Kubelet registers both an IPv4 &lt;em&gt;and&lt;/em&gt; and IPv6 address, making dual-stack support active.&lt;/li&gt;
&lt;li&gt;Shell redirection doesn&amp;rsquo;t work in systemd units, so you&amp;rsquo;ll need to use &lt;code&gt;/bin/bash -c&lt;/code&gt; or &lt;code&gt;/bin/sh -c&lt;/code&gt; to run whatever tool is needed to replace the placeholders.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With all this in place, you should be able to stand up Flatcar Container Linux on EC2 instances and have them bootstrap into a Kubernetes cluster with dual-stack IPv4/IPv6 support.&lt;/p&gt;
&lt;p&gt;I hope this proves useful to other folks out there. If you have any questions, feel free to find me either &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;on Mastodon&lt;/a&gt; or &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;on Bluesky&lt;/a&gt; (I don&amp;rsquo;t really use Twitter/X any longer). You&amp;rsquo;re also welcome to hit me up on &lt;a href=&#34;https://kubernetes.slack.com&#34;&gt;the Kubernetes Slack instance&lt;/a&gt;; I&amp;rsquo;m in both the &lt;code&gt;#flatcar&lt;/code&gt; and &lt;code&gt;#kubeadm&lt;/code&gt; channels. I also welcome feedback or suggested improvements to the information provided in this post, so don&amp;rsquo;t hesitate to reach out. Thanks for reading!&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Technology Short Take 185</title>
        <link>https://blog.scottlowe.org/2025/01/10/technology-short-take-185/</link>
        <pubDate>Fri, 10 Jan 2025 09:00:00 -0600</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2025/01/10/technology-short-take-185/</guid>
        <description>&lt;p&gt;Welcome to Technology Short Take #185, the first of 2025! I&amp;rsquo;m excited for the opportunity to continue to bring readers articles and links of interest across data center- and cloud-related technologies (along with some original content along the way). I had originally intended for this post to be my last post of 2024, but personal challenges got in the way. Enough of that, though&amp;mdash;on to the content!&lt;/p&gt;
&lt;h2 id=&#34;networking&#34;&gt;Networking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Rasika Nayanajith has &lt;a href=&#34;https://mrncciew.com/2024/12/14/wi-fi-7-overview/&#34;&gt;a detailed overview of Wi-Fi 7&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Just before the end of 2024, John Howard (whose blog I only recently discovered&amp;mdash;lots of great content there!) posted a write-up on &lt;a href=&#34;https://www.problemofnetwork.com/posts/vault-tls-with-network-appliances/&#34;&gt;using Vault to provision TLS certificates onto a network appliance&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Federico Paolinelli shared information on &lt;a href=&#34;https://fedepaol.github.io/blog/2025/01/06/enabling-evpn-termination-with-podman-pods-as-systemd-units/&#34;&gt;running Podman pods as systemd units&lt;/a&gt; in the context of an architecture to terminate EVPN inside Kubernetes nodes. Federico&amp;rsquo;s blog is another one I only recently discovered; there&amp;rsquo;s lots of great networking content here.&lt;/li&gt;
&lt;li&gt;Julio Perez has a nice write-up on &lt;a href=&#34;https://juliopdx.com/2024/11/25/codespaces-for-network-engineers-and-educators/&#34;&gt;Codespaces for network engineers and educators&lt;/a&gt;. (Hat tip to &lt;a href=&#34;https://ipspace.net&#34;&gt;Ivan Pepelnjak&lt;/a&gt; for pointing me to Julio&amp;rsquo;s site.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;servershardware&#34;&gt;Servers/Hardware&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Bryan Cantrill shares some thoughts on &lt;a href=&#34;https://bcantrill.dtrace.org/2024/12/08/why-gelsinger-was-wrong-for-intel/&#34;&gt;why Gelsinger was wrong for Intel&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;security&#34;&gt;Security&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Brian Krebs&amp;rsquo; article on &lt;a href=&#34;https://krebsonsecurity.com/2025/01/a-day-in-the-life-of-a-prolific-voice-phishing-crew/&#34;&gt;the operations of a prolific voice phishing crew&lt;/a&gt; was both enlightening and frightening.&lt;/li&gt;
&lt;li&gt;ESET has an article with &lt;a href=&#34;https://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/&#34;&gt;information on Bootkitty&lt;/a&gt;, which they label as &amp;ldquo;the first UEFI bootkit designed for Linux systems.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cloud-computingcloud-management&#34;&gt;Cloud Computing/Cloud Management&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I haven&amp;rsquo;t personally used &lt;code&gt;mirrord&lt;/code&gt;, but this article on &lt;a href=&#34;https://metalbear.co/blog/there-and-back-again-port-forwarding-with-mirrord/&#34;&gt;port forwarding with &lt;code&gt;mirrord&lt;/code&gt;&lt;/a&gt; piqued my interest. I might have to give this a try soon.&lt;/li&gt;
&lt;li&gt;Rory McCune asks the question, &lt;a href=&#34;https://raesene.github.io/blog/2024/11/11/When-Is-Read-Only-Not-Read-Only/&#34;&gt;&amp;ldquo;When is read-only not read-only?&amp;rdquo;&lt;/a&gt; (This is in the context of a Kubernetes RBAC and, in Rory&amp;rsquo;s words, &amp;ldquo;a possible sharp corner&amp;rdquo;.)&lt;/li&gt;
&lt;li&gt;Frederic Branczyk with Polar Signals &lt;a href=&#34;https://www.polarsignals.com/blog/posts/2025/01/09/introducing-kubezonnet&#34;&gt;discusses &lt;code&gt;kubezonnet&lt;/code&gt;&lt;/a&gt;, a tool for identifying and measuring cross-zone pod network traffic in Kubernetes clusters.&lt;/li&gt;
&lt;li&gt;This article is a good write-up on &lt;a href=&#34;https://flakm.com/posts/phantom_leak/&#34;&gt;troubleshooting/identifying a memory leak that wasn&amp;rsquo;t actually there&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Dan Slimmon reviews &lt;a href=&#34;https://blog.danslimmon.com/2019/03/25/latency-and-throughput-optimized-clusters-under-load/&#34;&gt;the metrics that are relevant to latency- and throughput-optimized clusters&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;operating-systemsapplications&#34;&gt;Operating Systems/Applications&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.wheresyoured.at/godot-isnt-making-it/&#34;&gt;This article from Edward Zitron&lt;/a&gt; is a scathing indictment of generative AI, but I can&amp;rsquo;t really disagree with any of it. My hope&amp;mdash;and the hope of others I&amp;rsquo;ve talked to that share the same perspective&amp;mdash;is that the fall of GenAI doesn&amp;rsquo;t mean the fall of the entire tech economy.&lt;/li&gt;
&lt;li&gt;Matthew Sanabria shares a list of &lt;a href=&#34;https://matthewsanabria.dev/posts/tools-worth-changing-to-in-2025/&#34;&gt;tools worth changing to in 2025&lt;/a&gt;. None of these tools are new to me, but it&amp;rsquo;s nice to hear about another user&amp;rsquo;s direct experience. I will say that I have thus far dismissed LLMs&amp;mdash;see my thoughts about generative AI in the previous bullet&amp;mdash;but I may reconsider local use of an LLM via &lt;a href=&#34;https://ollama.com/&#34;&gt;Ollama&lt;/a&gt;. I don&amp;rsquo;t have a GPU to throw at it, so the experience may be subpar.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;virtualization&#34;&gt;Virtualization&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;William Lam kicks off his 2025 blogging content with an article on an &lt;a href=&#34;https://williamlam.com/2025/01/easier-method-to-simulate-custom-esxi-smbios-hardware-strings.html&#34;&gt;easier way to simulate custom ESXi SMBIOS hardware strings&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;careersoft-skills&#34;&gt;Career/Soft Skills&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Does social media count as a soft skill? I&amp;rsquo;m going to say &amp;ldquo;Yes&amp;rdquo; so that I can put Virginia Craft&amp;rsquo;s article on &lt;a href=&#34;https://unboundroutes.com/2024/11/29/quit-social-media-join-mastodon/&#34;&gt;how to quit mainstream social media and join Mastodon&lt;/a&gt; in this section. Twitter/X is the only &amp;ldquo;mainstream social media&amp;rdquo; platform I use, and&amp;mdash;if I&amp;rsquo;m honest&amp;mdash;I&amp;rsquo;m using it less these days in favor of &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;Mastodon&lt;/a&gt; and &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;Bluesky&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Something Tom Hollingsworth said in &lt;a href=&#34;https://networkingnerd.net/2025/01/01/a-year-of-consistency-again/&#34;&gt;his recent post looking back at 2024&lt;/a&gt; really stuck with me: &amp;ldquo;I want to make sure I’m bringing you the kind of content that you want to read instead of just posting because I need to create something.&amp;rdquo; That really resonated with me. I know my blogging &lt;em&gt;frequency&lt;/em&gt; has gone down in recent years, but I don&amp;rsquo;t want to sacrifice blogging &lt;em&gt;quality&lt;/em&gt; just for the sake of posting more often. Thanks, Tom&amp;mdash;it&amp;rsquo;s nice to know that other writers have the same struggles I do.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s all for now. If you have any feedback, or if you just want to reach out and say hello, you can find me online in a variety of places. My email address isn&amp;rsquo;t too hard to find, so you&amp;rsquo;re welcome to drop me an email message if that&amp;rsquo;s your preference. Otherwise, find me &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;on Bluesky&lt;/a&gt;, &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;on Mastodon&lt;/a&gt;, &lt;a href=&#34;https://twitter.com/scott_lowe&#34;&gt;on Twitter&lt;/a&gt;, and in a variety of Slack communities. I&amp;rsquo;d love to hear from you!&lt;/p&gt;</description>
      </item>
    
      <item>
        <title>Using Multiple AWS Regions with Pulumi and S3 Backend</title>
        <link>https://blog.scottlowe.org/2024/12/19/using-multiple-aws-regions-with-pulumi-and-s3-backend/</link>
        <pubDate>Thu, 19 Dec 2024 12:00:00 -0600</pubDate>
        <author>Scott Lowe</author>
        <guid>https://blog.scottlowe.org/2024/12/19/using-multiple-aws-regions-with-pulumi-and-s3-backend/</guid>
        <description>&lt;p&gt;For a while now, I&amp;rsquo;ve been using &lt;a href=&#34;https://direnv.net/&#34;&gt;Direnv&lt;/a&gt; to manage environment variables when I enter or leave certain directories. Since I have to work with more than one AWS account, one of the use cases for me has been populating AWS-specific environment variables, like &lt;code&gt;AWS_REGION&lt;/code&gt; or &lt;code&gt;AWS_PROFILE&lt;/code&gt;. This generally works really well for me, but recently I ran into a bit of a corner case involving multiple AWS regions, &lt;a href=&#34;https://www.pulumi.com/&#34;&gt;Pulumi&lt;/a&gt;, and using S3 as the Pulumi backend. In this post, I&amp;rsquo;ll share the workaround that allows this configuration to work as expected.&lt;/p&gt;
&lt;p&gt;I describe this as a &amp;ldquo;bit of a corner case&amp;rdquo; because it only affects specific configurations (which included my configuration):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You must be setting the &lt;code&gt;AWS_REGION&lt;/code&gt; environment variable and &lt;em&gt;not&lt;/em&gt; setting the &lt;code&gt;aws:region&lt;/code&gt; configuration value used by the Pulumi AWS provider.&lt;/li&gt;
&lt;li&gt;You must be using S3 as the backend for Pulumi, and using an S3 URL of &lt;code&gt;s3://bucket-name&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You want to deploy resources into an AWS region that is &lt;em&gt;different&lt;/em&gt; than the AWS region where the backend state bucket resides.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In my specific situation, my backend state bucket resides in the AWS us-west-2 (Oregon) region, as this offers the lowest latencies from my home office in Colorado. I control this via the &lt;code&gt;PULUMI_BACKEND_URL&lt;/code&gt; environment variable using the &lt;code&gt;s3://bucket-name&lt;/code&gt; syntax. I needed to deploy resources into the us-east-2 (Ohio) region, so I set the &lt;code&gt;AWS_REGION&lt;/code&gt; environment variable accordingly. Because I used &lt;code&gt;AWS_REGION&lt;/code&gt;, I did not set the &lt;code&gt;aws:region&lt;/code&gt; Pulumi provider configuration value.&lt;/p&gt;
&lt;p&gt;When I ran &lt;code&gt;pulumi stack init&lt;/code&gt; to create a Pulumi stack for the Ohio resources, I got an error message containing the text &amp;ldquo;incorrect region, the bucket is not in &amp;lsquo;us-east-2&amp;rsquo; region at endpoint &amp;lsquo;&amp;rsquo;, bucket is in &amp;lsquo;us-west-2&amp;rsquo; region&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;After a bit of Googling, I realized the problem: Pulumi was looking for the backend state bucket in the region specified by &lt;code&gt;AWS_REGION&lt;/code&gt;. How, then, does one deploy to one AWS region when needing to use a backend state bucket in a different region?&lt;/p&gt;
&lt;p&gt;The answer sits buried in &lt;a href=&#34;https://www.pulumi.com/docs/iac/concepts/state-and-backends/#aws-s3&#34;&gt;this section of the Pulumi documentation&lt;/a&gt;; specifically, in this callout (emphasis mine):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As of Pulumi CLI v3.33.1, instead of specifying the AWS Profile, add &lt;code&gt;awssdk=v2&lt;/code&gt; along &lt;strong&gt;with the region&lt;/strong&gt; and profile to the query string.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ah ha! All that&amp;rsquo;s required is to amend the &lt;code&gt;PULUMI_BACKEND_URL&lt;/code&gt; setting to look something more like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;s3://bucket-name?region&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;us-west-2&amp;amp;awssdk&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;v2&amp;amp;profile&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;aws-profile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That worked perfectly&amp;mdash;Pulumi now knew to look for the backend state bucket in the us-west-2 (Oregon) region while deploying resources to the region specified by the &lt;code&gt;AWS_REGION&lt;/code&gt; environment variable. In theory, since I didn&amp;rsquo;t need to use different AWS profiles for the backend state bucket versus where resources live, it might be possible to remove &lt;code&gt;&amp;amp;profile=aws-profile&lt;/code&gt; from the S3 URL. I haven&amp;rsquo;t tested that yet.&lt;/p&gt;
&lt;p&gt;There you have it&amp;mdash;to use different AWS regions for your S3 backend state bucket and the resources you&amp;rsquo;re deploying, make sure your &lt;code&gt;PULUMI_BACKEND_URL&lt;/code&gt; setting properly includes the region in the URL as described above.&lt;/p&gt;
&lt;p&gt;I hope this helps someone else out there! Hit me up &lt;a href=&#34;https://twitter.com/scott_lowe&#34;&gt;on Twitter&lt;/a&gt;, &lt;a href=&#34;https://fosstodon.org/@scottslowe&#34;&gt;on Mastodon&lt;/a&gt;, or &lt;a href=&#34;https://bsky.app/profile/scottslowe.bsky.social&#34;&gt;on Bluesky&lt;/a&gt; if you have any feedback or any questions.&lt;/p&gt;</description>
      </item>
    
  </channel>
</rss>
