6 Feb 2026
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’t argue that I fell off the blogging bandwagon over the end of 2025 and early 2026. I won’t get into all the reasons why (if you’re interested then feel free to reach out and I’ll fill you in). Enough about me—let’s get to the technical content! Here’s hoping you find something useful.
Networking
Servers/Hardware
Security
Cloud Computing/Cloud Management
Operating Systems/Applications
Storage
Virtualization
- Eric Sloof writes about the evolution of the VCDX. 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) “softening” the certification. It will be interesting to see if this helps the designation grow, or if it continues to fade into obscurity.
Career/Soft Skills
- Murat Demirbas talks a bit about momentum, and how maintaining momentum (the “the messy daily pushes” 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 “produce something every day” advice as meaning that you need to publish something every day. That path leads to burn out. Produce something, sure, but allow for that something to be something that only you’ll see.
- This article about getting better at technical writing contains some good guidelines.
- This discussion of feeling uncomfortable and how it relates to growing personally really resonated with me. No, not because of Werner’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.
That’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 (X/Twitter, Mastodon, Bluesky, LinkedIn), Slack, or old-fashioned email. Thanks for reading!
28 Jan 2026
If you need to work with BGP in your AWS VPCs—so that BGP-learned routes can be injected into a VPC route table—then you will likely need a VPC Route Server. While you could set up a VPC Route Server manually, what’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.
To make things as easy as possible, I have added a simple Pulumi program to my GitHub “learning-tools” repository in the aws/vpc-route-server 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.
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:
rs, err := vpc.NewRouteServer(ctx, "rs", &vpc.RouteServerArgs{
AmazonSideAsn: pulumi.Int(65534),
Tags: pulumi.StringMap{
"Name": pulumi.String("rs"),
"Project": pulumi.String("vpc-route-server"),
},
})
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.
rsa, err := vpc.NewRouteServerVpcAssociation(ctx, "rsa", &vpc.RouteServerVpcAssociationArgs{
RouteServerId: rs.ID(),
VpcId: pulumi.String(userSuppliedVpcId),
})
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.
rse, err := vpc.NewRouteServerEndpoint(ctx, "rse", &vpc.RouteServerEndpointArgs{
RouteServerId: rs.RouteServerId,
SubnetId: pulumi.String(userSuppliedPrivateSubnetId),
Tags: pulumi.StringMap{
"Name": pulumi.String("rse"),
"Project": pulumi.String("vpc-route-server"),
},
}, pulumi.DependsOn([]pulumi.Resource{rsa}))
In working with the VPC Route Server, I’ve found that sometimes the dependencies between components don’t quite work as expected. Because the endpoint references the rs resource (the Route Server itself), the endpoint has a implicit dependency on that resource. However, if the VPC association isn’t complete, then you can run into errors. To address that problem, the code above uses pulumi.DependsOn 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.
The Route Server needs to know where to inject the routes it learns, and that’s handled by creating a propagation. The propagation links the Route Server to a route table in the associated VPC. Here’s the Pulumi code from the example in the “learning-tools” repository:
_, err = vpc.NewRouteServerPropagation(ctx, "rs-prop", &vpc.RouteServerPropagationArgs{
RouteServerId: rs.RouteServerId,
RouteTableId: pulumi.String(userSuppliedPrivateRouteTableId),
}, pulumi.DependsOn([]pulumi.Resource{rsa}))
The use of pulumi.DependsOn makes the propagation, like the endpoint, dependent on the VPC association. This helps eliminate errors related to the order of resource creation or deletion.
The last step is creating a peer for the Route Server. This tells the Route Server what the “other side” of a BGP peering relationship looks like. The “other side” 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 Cilium). Whatever the “other side” is, you’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.
_, err = vpc.NewRouteServerPeer(ctx, "rs-peer-01", &vpc.RouteServerPeerArgs{
BgpOptions: &vpc.RouteServerPeerBgpOptionsArgs{
PeerAsn: pulumi.Int(65001),
PeerLivenessDetection: pulumi.String("bgp-keepalive"),
},
PeerAddress: pulumi.String(userSuppliedPeerIpAddress),
RouteServerEndpointId: rse.RouteServerEndpointId,
Tags: pulumi.StringMap{
"Name": pulumi.String("rs-peer-01"),
"Project": pulumi.String("vpc-route-server"),
},
}, pulumi.DependsOn([]pulumi.Resource{rs, rse}))
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.
All of the code above is found in the aws/vpc-route-server directory in my GitHub “learning-tools” repository.
Once you run pulumi up to create all the resources, verifying the creation is a matter of using the AWS CLI:
aws ec2 describe-route-servers # to get the Route Server ID
aws ec2 describe-route-server-endpoints
aws ec2 get-route-server-propagations --route-server-id <id>
aws ec2 describe-route-server-peers
Some of these commands don’t (yet) support some of the same filtering mechanisms as other AWS CLI commands, so you may find it necessary to use jq to filter the output on the client side.
Verifying the operation of the Route Server is a bit more complex—you will need something 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 FRR or some other BGP daemon. This is a topic I might explore in a future blog post; if it’s something you’re interested in seeing, please let me know.
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 (X/Twitter, Bluesky, Mastodon), or via Slack (I’m in several Slack communities, including the Kubernetes Slack community). I hope you found this information helpful, and thanks for reading!
31 Oct 2025
Welcome to Technology Short Take #189, Halloween Edition! OK, you caught me—this Tech Short Take is not scary. I’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’s hoping you find something useful and informative!
Networking
Servers/Hardware
Security
Cloud Computing/Cloud Management
Operating Systems/Applications
That’s it for this time around. As always, I welcome your feedback—I’d love to hear from you! Feel free to reach me on Twitter/X, Mastodon, or Bluesky. 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!
22 Oct 2025
Every now and then, I publish one of these “Posts from the Past” articles that looks back on content I’ve created and posted over the life of this site. This year marks 20 years of content—I can hardly believe it! Don’t worry, though; you won’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!
October 2024
Last year I shared information on how to use Pulumi to stand up an Amazon Elastic Kubernetes Service (EKS) cluster with Bottlerocket OS on the Kubernetes nodes—without using any higher-level Pulumi components.
October 2022
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 how to change the Kubeconfig file for a more streamlined user experience.
October 2021
Cluster API is the name of the game for multiple posts in October 2021. First I wrote this article on kustomize transformer configurations for Cluster API v1beta1 (so that you can use kustomize to manipulate Cluster API manifests), followed up later that month with an article on influencing Cluster API AMI selection.
I also touched upon using the external (out of tree) cloud provider for AWS that month, a topic I am revisiting soon as I explore integrating Talos Linux with AWS.
October 2020
More Cluster API content—this time discussing IaC considerations for Cluster API (think things like integrating workload clusters with existing AWS workloads or services).
October 2019
In October 2019 I explored using jk to programmatically create Kubernetes manifests, and discussed how to use kustomize with kubeadm configuration files.
October 2018
Plenty of articles discuss the use of kubeadm to bootstrap Kubernetes clusters (including a few I wrote!), but what of talking about using kubeadm to stand up an etcd cluster? I’ve got you covered!
October 2017
Let’s get recursive: check out this “Posts from the Past” article from October 2017!
October 2016
Amid a bunch of content related to Vagrant, I found this gem on using Ansible to manage your AWS infrastructure.
October 2015
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 my liveblog of the Carina session.
Interested in finding more posts from the past? Feel free to browse the site archives, which have a link to every single post I’ve ever published. If you find something interesting, share it on social media and tag me! I’m on Twitter/X, Mastodon, and Bluesky.
Thanks for reading!
20 Oct 2025
A while ago I wrote an article about linting Markdown files with markdownlint. In that article, I presented the use case of linting the Markdown source files for this site. While manually running linting checks is fine—there are times and situations when this is appropriate and necessary—this is the sort of task that is ideally suited for a Git pre-commit hook. In this post, I’ll discuss Git pre-commit hooks in the context of using them to run linting checks.
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.
What is a Git Hook?
As this page explains, a hook is a program “you can place in a hooks directory to trigger actions at certain points in git’s execution.” 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’m focusing on the pre-commit hook. This hook gets invoked by git-commit (i.e., the user running a git commit 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.
Using a Pre-Commit Hook to Lint Markdown
For my use case, I wanted to run Markdownlint to lint the Markdown files (as described in the previous article on linting Markdown) before the commit. To do that, I came up with the following script:
#!/usr/bin/env bash
MDLINT="/usr/local/bin/markdownlint"
for file in $(git diff --cached --name-only --diff-filter=ACM | grep "\.md"); do
if ! $MDLINT "$file"; then
echo "Lint check failed on file '$file'."
echo "Run markdownlint to identify the errors and try again."
exit 1
fi
done
To make this script active as a pre-commit hook, you must name it pre-commit, you must place it into Git’s hook directory (which defaults to .git/hooks in the current repository), and you must make it executable.
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:
- The
git diff --cached --name-only command will return a list of the files staged for commit using git add. This list of files is what will Markdownlint will check.
- The
--diff-filter=ACM parameter tells git diff to return only Added, Copied, and Modified files. This prevents git diff from returning the filename of a deleted file, which would then generate an error from Markdownlint.
- Using
grep here further restricts the list of files to include only Markdown files.
- The
exit 1 command is critical; without returning a non-zero exit code, Git wouldn’t know to abort the commit.
With the script in the right place and marked as executable, it’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!
Additional Resources
I found the following articles useful when I was learning about pre-commit hooks and how to use them:
How to use git pre-commit hooks, the hard way and the easy way
Git Pre-Commit Hook: A Practical Guide (with Examples)
I hope you’ve found this post helpful in some fashion. As I previously mentioned, I don’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 on Twitter, on the Fediverse, or in a variety of Slack communities. Positive feedback is also welcome—thanks for reading!
Recent Posts
19 Sep 2025
Welcome to Technology Short Take #188! I’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!
Networking
Security
Cloud Computing/Cloud Management
Operating Systems/Applications
Programming/Development
Virtualization
Career/Soft Skills
- Ashley Willis talks about the value and importance of the quiet season. I particularly found this sentence applicable to my own life: “So yes, I’m writing again. And maybe I’m less ’everywhere’ than I used to be. But I’d rather show up less often and have something worth saying than burn myself out trying to convince the world I’m still here.” Well said, IMO.
- All too true.
- I don’t know if I would go so far as to say I am an AI hater, but I am most definitely opposed to AI in its current form. (I don’t even like calling it “AI” when it’s really nothing more than a statistical model for putting words together. But that’s another discussion for another day…) As the author says, being a hater is a “kind of integrity” all its own—so I say, if you’re an AI hater, don’t be afraid to say so.
It’s time to wrap up now—but don’t be sad, I’ll be back soon with more content. In the meantime, if you’d like to reach out to me to provide some feedback on this article or any article, I’d love to hear from you! Feel free to contact me via Bluesky, via Mastodon, via X/Twitter, via Slack (I frequent a number of different communities, including the Kubernetes Slack instance) or even via email. Thanks for reading!
Read more...
8 Sep 2025
A little over two years ago, I wrote a post on creating a Talos Linux cluster on AWS using Pulumi. 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.
Read more...
8 Aug 2025
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 “zettelkasten”-style approach, along with a few other topics thrown in here and there for fun. I hope you find something useful!
Read more...
11 Jul 2025
Welcome to Technology Short Take #186! Yes, it’s been quite a while since I published a Technology Short Take; life has “gotten in the way,” 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’m cautiously optimistic that I’ll be able to pick up the blogging pace once again. For now, though, here’s a collection of links I’ve gathered since the last Technology Short Take. I hope you find something useful here!
Read more...
3 Jun 2025
Recently I needed to be able to stand up a dual-stack (IPv4/IPv6) Kubernetes cluster on Flatcar Container Linux using kubeadm. 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’ll see how to use Butane and kubeadm to bootstrap a dual-stack IPv4/IPv6 Kubernetes cluster on AWS.
Read more...
10 Jan 2025
Welcome to Technology Short Take #185, the first of 2025! I’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—on to the content!
Read more...
19 Dec 2024
For a while now, I’ve been using Direnv 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 AWS_REGION or AWS_PROFILE. This generally works really well for me, but recently I ran into a bit of a corner case involving multiple AWS regions, Pulumi, and using S3 as the Pulumi backend. In this post, I’ll share the workaround that allows this configuration to work as expected.
Read more...
27 Nov 2024
Welcome to Technology Short Take #184! This Tech Short Take is a bit shorter than the usual ones, but then again this week—at least in the US—is a bit shorter than most weeks due to the Thanksgiving holiday. Even so, I hope that I’ve managed to include some information that folks find useful. Also, thanks to some feedback from readers, I’ve tried hard to ensure that links are more descriptive and informative than they’ve sometimes been in the past; let me know how I did. Now, on to the content!
Read more...
10 Oct 2024
In late 2023, I added some Go code for use with Pulumi to stand up an Amazon Elastic Kubernetes Service (EKS) cluster “from scratch,” meaning without using any prebuilt Pulumi components (like the AWSX VPC component or the EKS component). The code is largely illustrative for newer users, written to show how to stitch together all the components needed for an EKS cluster. In this post, I’ll show you how to modify that code to use Bottlerocket OS as the node OS for your EKS cluster—and share some information on installing Cilium into (onto?) the cluster.
Read more...
4 Oct 2024
Welcome to Technology Short Take #183! Fall is in the air; the nights and mornings are cooler and the leaves are turning (or have already turned in some areas!). I’ve got a slightly smaller collection of links for you this time around, but I do hope that you’ll find something shared here useful. Enjoy!
Read more...
6 Sep 2024
Welcome to Technology Short Take #182! I have a slightly bulkier list of links for you today, bolstered by some recent additions to my RSS feeds and supplemented by some articles I found through social media. There should be enough here to keep folks entertained this weekend—enjoy!
Read more...
30 Aug 2024
The Image Builder project is a set of tools aimed at automating the creation of Kubernetes disk images—such as VM templates or Amazon Machine Images (AMIs). (Interesting side note: Image Builder is the evolution of a much older Heptio project where I was a minor contributor.) I recently had a need to build a custom AMI with some extra container images preloaded, and in this post I’ll share with you how to configure Image Builder to preload additional container images.
Read more...
23 Aug 2024
Pulumi, like Terraform and OpenTofu, has the ability to store its state in a supported backend. You can store the state in one of the blob/object storage services offered by the major cloud providers, via Pulumi’s SaaS offering (called Pulumi Cloud), or even locally. It’s this last option I’ll explore a little bit in this post, where I’ll show you how to configure Pulumi to store the state in the project directory instead of somewhere else.
Read more...
21 Aug 2024
I’ve recently had the opportunity to start using a Lenovo ThinkPad X1 Carbon (X1C) Gen11 as my primary work system. Since I am not a Windows person—I don’t think I’ve used Windows as a daily driver since before the turn of the century—I’m running Linux on the X1C Gen11. Now that I’ve had a few weeks of regular use, in this post I’ll provide my review of this laptop.
Read more...
16 Aug 2024
Welcome to Technology Short Take #181! The summer of 2024 is nearly over, and Labor Day rapidly approaches. Take heart, though; here is some reading material for your weekend. From networking to security and from hardware to the cloud, there’s something in here for just about everyone. Enjoy!
Read more...
Older Posts
Find more posts by browsing the
post categories,
content tags, or
site archives pages. Thanks for visiting!