<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>William Denniss</title>
		<link>https://wdenniss.com/</link>
		<description>Recent content on William Denniss</description>
		<generator>Hugo</generator>
		<language>en-us</language>
		
		
		
		
			<lastBuildDate>Wed, 02 Sep 2026 18:44:54 -0700</lastBuildDate>
		
			<atom:link href="https://wdenniss.com/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Deploying an ADK agent for Gemini Enterprise: Agent Runtime or Cloud Run?</title>
				<link>https://wdenniss.com/agents/runtime-choice/</link>
				<pubDate>Wed, 02 Sep 2026 18:44:54 -0700</pubDate>
				<guid>https://wdenniss.com/agents/runtime-choice/</guid>
				<description>&lt;p&gt;Comment: After iterating on the &lt;a href=&#34;https://wdenniss.com/agents/ap-api-contract/&#34;&gt;API Contract&lt;/a&gt;&#xA;post, I asked Codex 5.6 Sol Ultra to form an opinion about when to use Agent&#xA;Runtime and when to use Cloud Run in the context of a GE app connected&#xA;agent, and then write a post. I specifically instructed it to avoid the cloudpickle &lt;a href=&#34;https://wdenniss.com/agents/5-ways-to-deploy/&#34;&gt;deployment options&lt;/a&gt; (which only work on Agent Runtime), to focus on the other trade-offs.&#xA;This is the resulting post, presented unmodified. I think it captures the nuances well and presents a balanced view.&#xA;–William&lt;/p&gt;</description>
			</item>
			<item>
				<title>Running stateful ADK agents on Substrate and GKE</title>
				<link>https://wdenniss.com/agents/substrate-demo/</link>
				<pubDate>Tue, 01 Sep 2026 21:56:54 -0700</pubDate>
				<guid>https://wdenniss.com/agents/substrate-demo/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://github.com/agent-substrate/substrate&#34;&gt;Agent Substrate&lt;/a&gt; can run stateful&#xA;Google ADK agents across a shared pool of GKE worker Pods. After an agent&#xA;responds, the harness can suspend its whole process—including its conversation,&#xA;in-memory working state, and files—and Substrate can restore it on whichever&#xA;compatible worker is free for the next request.&lt;/p&gt;&#xA;&lt;p&gt;The neat part is that this doesn&amp;rsquo;t require cold-starting ADK again. A Python ADK&#xA;agent can easily take ten seconds or more to initialize, but Substrate&amp;rsquo;s golden&#xA;snapshot pays that cost just once per template. Each actor then resumes from its&#xA;own latest snapshot instead of rebuilding its process and session. This also&#xA;makes it stateful. It picks up&#xA;where it left off, while its previous worker is free to run another agent. It&amp;rsquo;s&#xA;really performant, and great for agents that can benefit from a persistant state.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Serving the Agent Platform API contract</title>
				<link>https://wdenniss.com/agents/serving-the-ap-api-contract/</link>
				<pubDate>Mon, 13 Jul 2026 21:41:56 +0000</pubDate>
				<guid>https://wdenniss.com/agents/serving-the-ap-api-contract/</guid>
				<description>&lt;p&gt;With Agent Platform&amp;rsquo;s bring your own container (BYOC) deployment option, you need to serve the standard API contract yourself. In &lt;a href=&#34;https://wdenniss.com/agents/ap-api-contract/&#34;&gt;The Agent Platform API contract: what your agent must expose, and why&lt;/a&gt;, I covered why the contract exists and walked through the thirteen methods that &lt;code&gt;AdkApp&lt;/code&gt; exposes. Now let&amp;rsquo;s put a serving layer around them and call the deployed agent end to end.&lt;/p&gt;&#xA;&lt;p&gt;On the managed paths (the pickle, stub, and source options from &lt;a href=&#34;https://wdenniss.com/agents/5-ways-to-deploy/&#34;&gt;the deploy post&lt;/a&gt;), the platform builds the serving layer for you — &lt;code&gt;AdkApp&lt;/code&gt; already has all thirteen methods, and the platform either introspects the list or you declare it. You never see the plumbing.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The Agent Platform API contract: what your agent must expose, and why</title>
				<link>https://wdenniss.com/agents/ap-api-contract/</link>
				<pubDate>Mon, 13 Jul 2026 21:41:56 +0000</pubDate>
				<guid>https://wdenniss.com/agents/ap-api-contract/</guid>
				<description>&lt;p&gt;Agent Runtime can host a container with arbitrary HTTP endpoints. To use it&#xA;through the Agent Platform Python SDK or the Google Cloud console playground —&#xA;or through Gemini Enterprise&amp;rsquo;s native ADK integration — the container must also&#xA;implement the operations those integrations expect. These routes and request&#xA;formats are the HTTP side of the &lt;a href=&#34;https://docs.cloud.google.com/gemini-enterprise-agent-platform/scale/runtime/runtime-contract&#34;&gt;Agent Platform runtime&#xA;contract&lt;/a&gt;.&#xA;Agent Platform builds the serving layer for object and source deployments; with&#xA;a custom Dockerfile or prebuilt container, you serve it yourself. I covered&#xA;those choices in &lt;a href=&#34;https://wdenniss.com/agents/5-ways-to-deploy/&#34;&gt;5 ways to deploy agents on Agent&#xA;Platform&lt;/a&gt;. This post explains why the contract exists&#xA;and what an ADK agent exposes through it.&lt;/p&gt;</description>
			</item>
			<item>
				<title>5 ways to deploy agents on Agent Platform</title>
				<link>https://wdenniss.com/agents/5-ways-to-deploy/</link>
				<pubDate>Wed, 01 Jul 2026 17:52:38 +0000</pubDate>
				<guid>https://wdenniss.com/agents/5-ways-to-deploy/</guid>
				<description>&lt;p&gt;So you&amp;rsquo;ve built an ADK agent—in my case the &lt;a href=&#34;https://wdenniss.com/ap/&#34;&gt;Trading Agent&lt;/a&gt; from my post series, an agent that reads S&amp;amp;P 500 news, scores the sentiment, and places paper trades on Alpaca—and now you want it running on Agent Platform&amp;rsquo;s managed runtime instead of on your laptop. It turns out there are actually &lt;em&gt;five&lt;/em&gt; different ways to package your agent in runtime, each with some trade offs. This post explores those options and when you might want to use each one.&lt;/p&gt;</description>
			</item>
			<item>
				<title>About</title>
				<link>https://wdenniss.com/about/</link>
				<pubDate>Fri, 19 Jun 2026 12:00:00 -0700</pubDate>
				<guid>https://wdenniss.com/about/</guid>
				<description>&lt;p&gt;Hi, I’m William. I like to build things. This is my blog where I mostly post about my professional work.&lt;/p&gt;&#xA;&lt;p&gt;You can learn more about what I’ve created on &lt;a href=&#34;https://www.linkedin.com/in/williamdenniss/&#34;&gt;LinkedIn&lt;/a&gt;, and what I’m doing now on &lt;a href=&#34;https://twitter.com/williamdenniss&#34;&gt;Twitter&lt;/a&gt; (and, this blog!). If you want to get in touch, best way is to DM me on one of those two networks 🙂&lt;/p&gt;</description>
			</item>
			<item>
				<title>OAuth Device Flow</title>
				<link>https://wdenniss.com/deviceflow/</link>
				<pubDate>Fri, 19 Jun 2026 18:01:56 +0000</pubDate>
				<guid>https://wdenniss.com/deviceflow/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc8628&#34;&gt;https://datatracker.ietf.org/doc/html/rfc8628&lt;/a&gt;&lt;/p&gt;</description>
			</item>
			<item>
				<title>Security Event Token (SET)</title>
				<link>https://wdenniss.com/set/</link>
				<pubDate>Fri, 19 Jun 2026 18:01:26 +0000</pubDate>
				<guid>https://wdenniss.com/set/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc8417&#34;&gt;https://datatracker.ietf.org/doc/html/rfc8417&lt;/a&gt;&lt;/p&gt;</description>
			</item>
			<item>
				<title>AppAuth</title>
				<link>https://wdenniss.com/appauth/</link>
				<pubDate>Thu, 18 Jun 2026 16:57:11 +0000</pubDate>
				<guid>https://wdenniss.com/appauth/</guid>
				<description>&lt;p&gt;See: &lt;a href=&#34;http://appauth.io/&#34;&gt;http://appauth.io/&lt;/a&gt;&lt;/p&gt;</description>
			</item>
			<item>
				<title>Videos</title>
				<link>https://wdenniss.com/videos/</link>
				<pubDate>Wed, 17 Jun 2026 19:40:26 +0000</pubDate>
				<guid>https://wdenniss.com/videos/</guid>
				<description>&lt;h2 id=&#34;google-next-2025&#34;&gt;Google Next 2025&lt;/h2&gt;&#xA;&lt;p&gt;Transforming your Business with AI: The Google Kubernetes Engine (GKE) Advantage. Spotlight session highlighting major updates. Autopilot content starts at XYZ.&lt;/p&gt;&#xA;&lt;div class=&#34;wp-block-embed__wrapper&#34; style=&#34;position:relative;padding-top:56.25%;&#34;&gt;&#xA;  &lt;iframe&#xA;    src=&#34;https://www.youtube.com/embed/8lveNvUEdGk?start=146&#34;&#xA;    title=&#34;Transforming your business with AI: The Kubernetes advantage&#34;&#xA;    style=&#34;position:absolute;top:0;left:0;width:100%;height:100%;border:0;&#34;&#xA;    allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34;&#xA;    referrerpolicy=&#34;strict-origin-when-cross-origin&#34;&#xA;    allowfullscreen&gt;&lt;/iframe&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;How Shopify runs Black Friday, Cyber Monday on GKE. Highlights usage of CCC (at XYZ), and Autopilot&amp;rsquo;s new container-optimized compute platform (at ZYC).&lt;/p&gt;&#xA;&lt;div class=&#34;wp-block-embed__wrapper&#34; style=&#34;position:relative;padding-top:56.25%;&#34;&gt;&#xA;  &lt;iframe&#xA;    src=&#34;https://www.youtube.com/embed/1RSgI4kwfOY&#34;&#xA;    title=&#34;How Shopify runs their biggest business event of the year with GKE&#34;&#xA;    style=&#34;position:absolute;top:0;left:0;width:100%;height:100%;border:0;&#34;&#xA;    allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34;&#xA;    referrerpolicy=&#34;strict-origin-when-cross-origin&#34;&#xA;    allowfullscreen&gt;&lt;/iframe&gt;&#xA;&lt;/div&gt;</description>
			</item>
			<item>
				<title>Launches</title>
				<link>https://wdenniss.com/launches/</link>
				<pubDate>Wed, 17 Jun 2026 19:36:56 +0000</pubDate>
				<guid>https://wdenniss.com/launches/</guid>
				<description>&lt;p&gt;In addition to the &lt;a href=&#34;https://wdenniss.com/&#34;&gt;self-published blog posts&lt;/a&gt; on this site, here is a selection of launch posts relevant to my work, published on Google blog channels, and elsewhere.&lt;/p&gt;&#xA;&lt;h2 id=&#34;gke-autopilot&#34;&gt;GKE Autopilot&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://cloud.google.com/blog/products/containers-kubernetes/gke-autopilot-now-available-to-all-qualifying-clusters&#34;&gt;Meet the new GKE: Extending Autopilot to all qualifying clusters&lt;/a&gt;, September 2025&lt;/p&gt;&#xA;&lt;p&gt;eBook: &lt;a href=&#34;https://cloud.google.com/resources/content/kubernetes-for-developers-ebook&#34;&gt;Kubernetes for Developers, A clear and practical beginner&amp;rsquo;s guide to Kubernetes&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://cloud.google.com/blog/products/containers-kubernetes/container-optimized-compute-delivers-autoscaling-for-autopilot&#34;&gt;GKE under the hood: Container-optimized compute delivers fast autoscaling for Autopilot&lt;/a&gt;, August 2025&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://cloud.google.com/blog/products/containers-kubernetes/gke-gets-new-pricing-and-capabilities-on-10th-birthday&#34;&gt;Happy birthday, GKE! Let&amp;rsquo;s celebrate with new features and better pricing&lt;/a&gt;, August 2025&lt;/p&gt;</description>
			</item>
			<item>
				<title>Deterministic memories</title>
				<link>https://wdenniss.com/ap/2-memories/2.2-deterministic-memories/</link>
				<pubDate>Mon, 15 Jun 2026 18:37:26 +0000</pubDate>
				<guid>https://wdenniss.com/ap/2-memories/2.2-deterministic-memories/</guid>
				<description>&lt;p&gt;The Trading agent we deployed earlier will automatically have session persistence when deployed on Agent Platform. You can test this by asking it a day later “What trades did you execute” from the same session that you executed the trades from. The full conversation history is preserved, even while the agent is suspended (you’re not paying for it to run continuously).&lt;/p&gt;&#xA;&lt;p&gt;You can also inspect the saved session data from the console.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Creating an Agent Platform resource identifier</title>
				<link>https://wdenniss.com/ap/3-containerizing/3.2-creating-an-ap-resource/</link>
				<pubDate>Tue, 09 Jun 2026 13:54:14 -0700</pubDate>
				<guid>https://wdenniss.com/ap/3-containerizing/3.2-creating-an-ap-resource/</guid>
				<description>&lt;p&gt;To use Agent Platform services like Memory Bank, and Sessions from other environments, you need to first create a resource that is currently known as an “agent engine”.&lt;/p&gt;&#xA;&lt;p&gt;Note: if you are familiar with the Python ADK libraries, you can follow &lt;a href=&#34;https://clouddocs.devsite.corp.google.com/gemini-enterprise-agent-platform/scale/memory-bank/setup#setup-sdk-client&#34;&gt;these instructions&lt;/a&gt; instead, to create an instance via the SDK.&lt;/p&gt;&#xA;&lt;p&gt;Here’s a single API call to create a resource identifier that you can use right away:&lt;/p&gt;&#xA;&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;-webkit-text-size-adjust:none;&#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;# 1. Set your variables&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PROJECT_ID&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;LOCATION&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;us-west1&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# Replace with your target region&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;RESOURCE_DISPLAY_NAME&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;My Memory Bank&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&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;# 2. Execute the REST API request&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -X POST &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -H &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;gcloud auth print-access-token&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -H &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&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;https://&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;LOCATION&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;-aiplatform.googleapis.com/v1/projects/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;PROJECT_ID&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/locations/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;LOCATION&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/reasoningEngines&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -d &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{&#xA;&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;displayName\&amp;#34;: \&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;RESOURCE_DISPLAY_NAME&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\&amp;#34;&#xA;&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;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The creation returns immediately with an operation id, and executes async, you can query the API with the operation, or look up the Deployments UI to get the resource.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Agent memories with ADK</title>
				<link>https://wdenniss.com/ap/2-memories/2.1-add-memories/</link>
				<pubDate>Mon, 01 Jun 2026 16:16:44 -0700</pubDate>
				<guid>https://wdenniss.com/ap/2-memories/2.1-add-memories/</guid>
				<description>&lt;p&gt;ADK Agents will automatically have &lt;em&gt;session&lt;/em&gt; persistence when deployed on Agent Platform. You can test this by asking follow up questions in the running sessions like “What trades did you execute?”. The full conversation history is preserved, even while the agent is suspended (you’re not paying for it to run continuously), and is visibile in the &lt;a href=&#34;https://console.cloud.google.com/agent-platform/sessions&#34;&gt;console&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;When you start a new session however, that context is gone. It&amp;rsquo;s common to want some level of&#xA;memory and personalization for an agent. For example, if the user says &amp;ldquo;I never want to&#xA;buy ___ stock&amp;rdquo;, ideally we would remember this and factor that in to trading decisions.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Deploy an ADK agent to Agent Platform Runtime</title>
				<link>https://wdenniss.com/ap/1-agent/1.2-deploy-to-ap-runtime/</link>
				<pubDate>Fri, 15 May 2026 11:03:02 -0700</pubDate>
				<guid>https://wdenniss.com/ap/1-agent/1.2-deploy-to-ap-runtime/</guid>
				<description>&lt;p&gt;In my &lt;a href=&#34;https://wdenniss.com/ap/1-agent/1.1-create-an-adk-agent/&#34;&gt;previous post&lt;/a&gt;, we created an agent with ADK and ran it locally. The next step is to deploy it to Agent Platform runtime.&lt;/p&gt;&#xA;&lt;p&gt;You can deploy to the runtime using a Python script that imports your agent, and configures the remote resource, and performs the deployment. This approach serializes your live object graph which is simple, but not suitable for production. We&amp;rsquo;ll cover production hardening later.&lt;/p&gt;&#xA;&lt;p&gt;Create the following script in the root project folder (the one containing &lt;code&gt;trading_agent&lt;/code&gt; from the previous example). There’s nothing to edit in it: the project ID is read from your environment (via Application Default Credentials), and the staging bucket name is derived from it (&lt;code&gt;gs://${PROJECT_ID}-trading-agent&lt;/code&gt;), with the bucket created on first run if it doesn’t exist. Just point gcloud at the right project first:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Building a stock-trading agent with ADK</title>
				<link>https://wdenniss.com/ap/1-agent/1.1-create-an-adk-agent/</link>
				<pubDate>Wed, 22 Apr 2026 11:17:03 -0700</pubDate>
				<guid>https://wdenniss.com/ap/1-agent/1.1-create-an-adk-agent/</guid>
				<description>&lt;p&gt;The &lt;a href=&#34;https://adk.dev/&#34;&gt;Agent Development Kit&lt;/a&gt; (ADK) is Google’s open-source Python framework for building AI agents. You write the agent’s logic and the tools it can call, and ADK handles orchestrating everything — with evaluation and deployment built in too.&lt;/p&gt;&#xA;&lt;p&gt;I wanted a slightly more interesting app than Hello World to exercise more parts of the platform, so I figured I’d write a little stock trading agent that applies a sentiment momentum trading strategy. We’ll use ADK and the Gemini API to execute trades on &lt;a href=&#34;https://alpaca.markets/&#34;&gt;Alpaca&lt;/a&gt;, chosen for its REST API and free paper-trading account.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Upgrading a GKE cluster to use Autopilot Compute Class</title>
				<link>https://wdenniss.com/k8s/upgrading-a-gke-cluster-to-use-autopilot-compute-class/</link>
				<pubDate>Fri, 12 Dec 2025 15:41:36 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/upgrading-a-gke-cluster-to-use-autopilot-compute-class/</guid>
				<description>&lt;p&gt;Autopilot is now available in GKE clusters via Compute Class. See the &lt;a href=&#34;https://cloud.google.com/blog/products/containers-kubernetes/gke-autopilot-now-available-to-all-qualifying-clusters?e=48754805&#34;&gt;official announcement&lt;/a&gt;, and &lt;a href=&#34;https://docs.cloud.google.com/kubernetes-engine/docs/how-to/autopilot-classes-standard-clusters&#34;&gt;documentation&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Versions with this feature are now available for clusters in the Regular release channel. Here’s how to upgrade early and get these features today.&lt;/p&gt;&#xA;&lt;p&gt;Per the docs, the feature is in version 1.34.1-gke.1829001 or later. To upgrade we need to find a valid version for our control plane (master) equal or later to this version and upgrade to it.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Programmable Spend-based CUD Purchase</title>
				<link>https://wdenniss.com/tech/programmable-spend-based-cud-purchase/</link>
				<pubDate>Wed, 15 Oct 2025 12:00:00 -0700</pubDate>
				<guid>https://wdenniss.com/tech/programmable-spend-based-cud-purchase/</guid>
				<description>&lt;p&gt;Did you know it’s possible to &lt;a href=&#34;https://cloud.google.com/marketplace/docs/commitment-api-purchasing&#34;&gt;purchase spend-based CUDs programmatically&lt;/a&gt;, including (for now) the legacy Autopilot CUD and the new Compute flexible CUD?&lt;/p&gt;&#xA;&lt;p&gt;Let’s take it for a spin.&lt;/p&gt;&#xA;&lt;p&gt;Firstly, you’ll need the &lt;a href=&#34;https://console.developers.google.com/apis/api/cloudcommerceconsumerprocurement.googleapis.com/overview&#34;&gt;procurement API&lt;/a&gt; enabled and IAM permissions setup. Follow the steps in &lt;a href=&#34;https://cloud.google.com/marketplace/docs/commitment-api-purchasing#before_you_begin&#34;&gt;Before you begin&lt;/a&gt; in the official doc.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;strong&gt;&lt;code&gt;gcloud&lt;/code&gt;&lt;/strong&gt; CLI will need to be authenticated in order to generate the needed access token (&lt;code&gt;gcloud auth print-access-token&lt;/code&gt; should print out an auth token)&lt;/p&gt;</description>
			</item>
			<item>
				<title>Using C4A and C4D with Compute Class</title>
				<link>https://wdenniss.com/k8s/gke-c4a-c4d-with-compute-class/</link>
				<pubDate>Sun, 17 Aug 2025 12:40:09 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/gke-c4a-c4d-with-compute-class/</guid>
				<description>&lt;p&gt;I’ve been following Arm for a while, so was glad that the &lt;a href=&#34;https://cloud.google.com/blog/products/compute/try-c4a-the-first-google-axion-processor&#34;&gt;C4A VM&lt;/a&gt; was &lt;a href=&#34;https://cloud.google.com/blog/products/compute/first-google-axion-processor-c4a-now-ga-with-titanium-ssd&#34;&gt;GA’d&lt;/a&gt; earlier this year. These machines run Google silicon &lt;a href=&#34;https://cloud.google.com/products/axion&#34;&gt;Axion&lt;/a&gt; chip. It’s also great to see &lt;a href=&#34;https://cloud.google.com/compute/docs/regions-zones&#34;&gt;broad geographical availability&lt;/a&gt; including regions like Tokyo. Feels like Arm is finally ready for prime time.&lt;/p&gt;&#xA;&lt;p&gt;C4D running 5th Gen AMD EPYC processors (Turin) was even more &lt;a href=&#34;https://cloud.google.com/blog/products/compute/c4d-vms-unparalleled-performance-for-business-workloads&#34;&gt;recently released&lt;/a&gt;. Let’s try them both out!&lt;/p&gt;&#xA;&lt;h2 id=&#34;arm-on-gke&#34;&gt;Arm on GKE&lt;/h2&gt;&#xA;&lt;p&gt;Here’s how to deploy an Arm workload on GKE using Compute Class. I’ll be using Autopilot mode.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Simulate a zonal failure on Autopilot</title>
				<link>https://wdenniss.com/k8s/simulate-a-zonal-failure-on-autopilot/</link>
				<pubDate>Fri, 30 May 2025 22:58:52 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/simulate-a-zonal-failure-on-autopilot/</guid>
				<description>&lt;p&gt;GKE’s Autopilot mode is designed to be safer to operate and prevents many issues that can lead to sudden outages like misconfigured firewalls. However, if you’re trying to actually simulate a failure like when performing a zonal failure simulation, Autopilot’s safeguards can sometimes get in the way, blocking some of the potential ways to run such a test.&lt;/p&gt;&#xA;&lt;p&gt;It is possibile still though to simulate the loss of compute capacity in a zone and see how your load balancing and workload will respond. Given that this is one of the key attributes in your control (e.g. number of replicas, zonal spread topology, etc), I believe this is a useful test. We can achieve this through &lt;code&gt;kubectl cordon&lt;/code&gt;, &lt;code&gt;kubectl delete pods&lt;/code&gt; and a little scripting.&lt;/p&gt;</description>
			</item>
			<item>
				<title>From an Unsupported macOS to Supported Windows</title>
				<link>https://wdenniss.com/tech/from-an-unsupported-macos-to-supported-windows/</link>
				<pubDate>Sun, 11 May 2025 12:00:00 -0700</pubDate>
				<guid>https://wdenniss.com/tech/from-an-unsupported-macos-to-supported-windows/</guid>
				<description>&lt;p&gt;I had some old MacBooks, one upgradable to Big Sur (&lt;a href=&#34;https://endoflife.date/macos&#34;&gt;no longer supported&lt;/a&gt;), one &lt;a href=&#34;https://www.macworld.com/article/673697/what-version-of-macos-can-my-mac-run.html&#34;&gt;upgradable to Ventura&lt;/a&gt; (supported, but soon to be obsolete). My family needed some windows machines, and remarkably I was able to move from unsupported and old macOS to completely supported Windows 11. Who knows how many more years of support these old machines can get, but presumably till Windows 11 EOL which is impressive.&lt;/p&gt;&#xA;&lt;p&gt;Steps&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Move/backup/delete all data from the Macbook and any existing Bootcamp installs (your MacBook will be completely wiped during this process)&lt;/li&gt;&#xA;&lt;li&gt;Update to the very latest macOS (so that your firmware is up to date; once you do this you can’t update your firmware again which is fine because it likely won’t get any more updates anyway)&lt;/li&gt;&#xA;&lt;li&gt;Download your Windows Support Software (very important). Boot Camp -&amp;gt; Action -&amp;gt; Download Windows Support.&lt;/li&gt;&#xA;&lt;li&gt;Get an 8GB thumb drive and create a Windows 11 installable boot&lt;/li&gt;&#xA;&lt;li&gt;Copy the Windows Support Software onto the same thumb drive, there should be room. Else, use another.&lt;/li&gt;&#xA;&lt;li&gt;Boot into the Windows 11 installer. (Did you save your Windows Support Software? Go back and do this if you didn’t).&lt;/li&gt;&#xA;&lt;li&gt;You need to add some &lt;a href=&#34;https://techcommunity.microsoft.com/discussions/windows11/help-needed-install-windows-11-without-tpm-on-my-pc/4181724&#34;&gt;bypass options&lt;/a&gt; for the TPM check. Shift F10. &lt;code&gt;regedit&lt;/code&gt;.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Navigate to &lt;strong&gt;HKEY_LOCAL_MACHINE\SYSTEM\Setup&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;Edit -&amp;gt; New -&amp;gt; Key, named &lt;code&gt;LabConfig&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Open that key, create two DWORD (32-bit) values:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;BypassTPMCheck&lt;/li&gt;&#xA;&lt;li&gt;BypassSecureBootCheck.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Modify both DWORDs and set the value to 1&lt;/li&gt;&#xA;&lt;li&gt;BypassCPUCheck and BypassRAMCheck are also options, but I didn’t need them for my macbooks (and it was good to know that with the check still active, they apparently pass the minimum bar for those.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Start installer&lt;/li&gt;&#xA;&lt;li&gt;Format the disk. There is no need to install drivers at this step, it works without them. This is the part that wipes all data on the disk.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Delete Disk 0, Partition 2 (and all partitions on Disk 0, except Partition 1). Should eventually read “Unallocated space”. You may need to hit “Refresh” a few times.&lt;/li&gt;&#xA;&lt;li&gt;Create a partition on the unallocated space. If you get an error (I did), just refresh, it seemed to actually work. Then format the new partition (the largest one on Disk 0)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Select the newly created partition to install Windows 11&lt;/li&gt;&#xA;&lt;li&gt;Install&lt;/li&gt;&#xA;&lt;li&gt;When prompted to install the Wifi driver, you can’t. Don’t try to load drivers from your thumb drive, they don’t work. Instead &lt;a href=&#34;https://answers.microsoft.com/en-us/windows/forum/all/how-do-i-set-up-windows-11-without-internet/e348329d-f136-4460-b2f7-bc2bfa32c4e7&#34;&gt;bypass the Wifi requirement&lt;/a&gt;, press Shift+F10 and run &lt;code&gt;OOBE\BYPASSNRO&lt;/code&gt; in the command prompt.&lt;/li&gt;&#xA;&lt;li&gt;Once windows is setup, then run bootcamp Setup.exe (which will install your Wifi and other drivers)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;You now have a pure Windows 11 machine!&lt;/p&gt;</description>
			</item>
			<item>
				<title>Running Docker in Docker on GKE Autopilot with gVisor</title>
				<link>https://wdenniss.com/k8s/running-docker-in-docker-on-gke-autopilot-with-gvisor/</link>
				<pubDate>Mon, 05 May 2025 18:43:04 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/running-docker-in-docker-on-gke-autopilot-with-gvisor/</guid>
				<description>&lt;p&gt;Docker in Docker is an interesting workload to run on GKE in Autopilot mode, as for Autopilot you’re limited to userland programs, and Docker in Docker likes to run as root. This is a bit of a legacy from the days when docker was actually running on the host (now it’s containerd), so it “made sense” to just punch out of the container into the host’s docker environment to execute there, since, why not. Of course, this presents some security and supportability issues, as now that process is root. Fortunately there is a way to run Docker in Docker completely in userland, in a way compatible with GKE Autopilot. Here’s my test.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Running DeepSeek open reasoning models on GKE</title>
				<link>https://wdenniss.com/k8s/deepseek-on-gke/</link>
				<pubDate>Wed, 26 Feb 2025 15:52:00 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/deepseek-on-gke/</guid>
				<description>&lt;p&gt;DeepSeek’s R1 open model launch caused quite a stir with one of the first open reasoning models. Here’s how to run a demo of it locally on GKE!&lt;/p&gt;&#xA;&lt;p&gt;We can use an Nvidia L4 (or A100 40GB) to run the 8B Llama distilled model, or a A100 80GB to run the 14 and 32B Quen distilled models. I’ll be pairing this with a &lt;a href=&#34;https://github.com/WilliamDenniss/autopilot-examples/tree/master/llm/gradio&#34;&gt;sample Gradio application&lt;/a&gt; that can stream responses, and handles the “&amp;lt;/think&amp;gt;” block (unique to the reasoning models) by adding a horizontal line to the output to delineate where the thinking ends, and the final response begins. In your own application of course, you may choose to hide the “&amp;lt;/think&amp;gt;” block entirely, or display it in a different manner, like the current LLM chat apps do.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Kubernetes History Inspector</title>
				<link>https://wdenniss.com/k8s/kubernetes-history-inspector/</link>
				<pubDate>Thu, 30 Jan 2025 14:56:30 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/kubernetes-history-inspector/</guid>
				<description>&lt;p&gt;GKE users get access to an awesome new tool this week: the &lt;a href=&#34;https://github.com/GoogleCloudPlatform/khi&#34;&gt;Kubernetes History Inspector&lt;/a&gt;. This product, released as open source, parses Kubernetes and GKE logs to generate a timeline with all events in the cluster.&lt;/p&gt;&#xA;&lt;p&gt;Kubernetes is a complicated system with multiple objects, and various automated processes. A single Deployment results in at least 3 objects: the Deployment, ReplicaSet (one for each app version), and Pods (one for each replica). Nodes come and go. Pods may fail and be re-created. Horizontal Pod Autoscaling might add and remove Pods, etc, etc. Kubernetes History Inspector enables you to view all the interactions of this system with a single pane of glass. Brilliant.&lt;/p&gt;</description>
			</item>
			<item>
				<title>In-app browsers and RFC 8252</title>
				<link>https://wdenniss.com/appauth/in-app-browsers-and-rfc-8252/</link>
				<pubDate>Fri, 15 Nov 2024 16:57:47 +0000</pubDate>
				<guid>https://wdenniss.com/appauth/in-app-browsers-and-rfc-8252/</guid>
				<description>&lt;p&gt;In 2016 I wrote &lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc8252&#34;&gt;RFC 8252&lt;/a&gt; seeking to codify a new best practice on using the system browser (or in-app browser tabs) to perform OAuth flows, rather than a built-in WebView.&lt;/p&gt;&#xA;&lt;p&gt;A little history: you don’t see this embedded WebView OAuth pattern much any more, but when I joined the Identity team at Google in 2014, it was everywhere, and there was a popular OSS client library which helped developers do it this way. With the WebView pattern, the user would login to their identity provider in a view inside the app during the OAuth flow (as documented in &lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc6749#section-9&#34;&gt;section 9 of RFC 6749&lt;/a&gt;). This had some problems including security (the containing app can take the session authentication token, which is typically more privileged than the OAuth token), and usability (the user has to login again every time), a full list of issues can be found in &lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc8252#section-8.12&#34;&gt;section 8.12 of RFC 8252&lt;/a&gt;. My work on 8252 was to codify a new approach by using the system browser. As for that old client library? Together with my colleagues, I created a &lt;a href=&#34;http://appauth.io&#34;&gt;better one&lt;/a&gt; to provide a reference implementation of 8252. In 2016, Google &lt;a href=&#34;https://developers.googleblog.com/en/modernizing-oauth-interactions-in-native-apps-for-better-usability-and-security/&#34;&gt;formally required&lt;/a&gt; developers to adopt this modern approach for better security and usability.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Getting resource recommendations from VPA</title>
				<link>https://wdenniss.com/k8s/vpa-in-advisory-mode/</link>
				<pubDate>Wed, 06 Nov 2024 12:07:06 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/vpa-in-advisory-mode/</guid>
				<description>&lt;p&gt;Setting appropriate resource requirements in Pods is one of the most critical tasks of a developer deploying in Kubernetes. In &lt;a href=&#34;https://livebook.manning.com/book/kubernetes-for-developers/chapter-5/62&#34;&gt;section 5.2 of my book&lt;/a&gt;, I discuss how you can use &lt;code&gt;kubectl top pods&lt;/code&gt; to analyze and set resource values. If you’re fortunate enough to use GKE where the VPA component is offered out of the box, there is another option for analyzing usage which makes this even easier and more accurate: running VPA in advisory mode.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Scaling container resources automatically with VPA</title>
				<link>https://wdenniss.com/k8s/scaling-container-resources-automatically-with-vpa/</link>
				<pubDate>Tue, 05 Nov 2024 12:47:51 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/scaling-container-resources-automatically-with-vpa/</guid>
				<description>&lt;p&gt;Vertical Pod Autoscaling is a system that measures Pod utilization and attempts to set the right resource requests. For example, if the Pod is constantly using more CPU, VPA will increase the CPU requests. Contrasting Horizontal Pod Autoscaling (HPA) which can create more replicas as your Pods use more resources, VPA changes the resources of each replica.&lt;/p&gt;&#xA;&lt;p&gt;In the past, GKE in Autopilot mode had a 250 milliCPU resource increment (meaning valid Pod sizes were 250m, 500m, 750m, etc). Now that Autopilot &lt;a href=&#34;https://cloud.google.com/blog/products/containers-kubernetes/introducing-gke-autopilot-burstable-workloads/&#34;&gt;supports burstable QoS and fine-grained resource increments&lt;/a&gt;, VPA should be even more useful, so let’s give it a spin.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Using Node-based pricing on GKE Autopilot</title>
				<link>https://wdenniss.com/k8s/using-node-based-pricing-on-gke-autopilot/</link>
				<pubDate>Tue, 03 Sep 2024 11:19:49 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/using-node-based-pricing-on-gke-autopilot/</guid>
				<description>&lt;p&gt;New this year, Autopilot &lt;a href=&#34;https://cloud.google.com/blog/products/containers-kubernetes/new-features-to-run-ai-more-efficiently-on-fully-managed-gke&#34;&gt;now has&lt;/a&gt; two pricing models: the original Pod-based model, and the new node-based option. The &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/pricing#autopilot_mode&#34;&gt;pricing page&lt;/a&gt; does a pretty good job of explaining the difference (at least I hope it explains it well, as I wrote it), and how best to utilize each option, but here’s a quick recap anyway:&lt;/p&gt;&#xA;&lt;p&gt;The &lt;strong&gt;Pod model&lt;/strong&gt; is great for when you don’t want to think about or worry about bin-packing of nodes—allow GKE to take of everything. It uses an all-inclusive pricing model where you don’t need to be concerned with underutilized nodes, or odd-shaped workloads. The &lt;strong&gt;node model&lt;/strong&gt; is useful when you have specific hardware requirements (like a particular GPU, or CPU), or have large workloads that bin-pack well and you just want to buy some VMs. The node model is billed by the node at Compute Engine prices, with a small added premium. The node model can work out cheaper, provided you fill the nodes. The most optimal way to use Autopilot is typically with a mix of both strategies, taking advantage of whichever pricing model works better for the workload in question.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Serving Stable Diffusion with RayServe on GKE Autopilot</title>
				<link>https://wdenniss.com/k8s/serving-stable-diffusion-with-rayserve-on-gke-autopilot/</link>
				<pubDate>Tue, 03 Sep 2024 11:12:25 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/serving-stable-diffusion-with-rayserve-on-gke-autopilot/</guid>
				<description>&lt;p&gt;Now that you’ve &lt;a href=&#34;https://wdenniss.com/k8s/stable-diffusion-webui-on-gke-autopilot/&#34;&gt;tried out Stable Diffusion on GKE Autopilot via the WebUI&lt;/a&gt;, you might be wondering how you’d go about adding stable diffusion as a proper micro-service that other components of your application can call. One popular way is via Ray. Let’s try this tutorial: &lt;a href=&#34;https://docs.ray.io/en/latest/cluster/kubernetes/examples/stable-diffusion-rayservice.html&#34;&gt;Serve a StableDiffusion text-to-image model on Kubernetes&lt;/a&gt;, on GKE Autopilot. Here goes:&lt;/p&gt;&#xA;&lt;h2 id=&#34;create-an-autopilot-cluster&#34;&gt;Create an Autopilot Cluster&lt;/h2&gt;&#xA;&lt;p&gt;You’ll want version 1.28 or later for this, to get the newer CUDA drivers. This will do the trick:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Clearing macOS Desktop Clutter</title>
				<link>https://wdenniss.com/tech/clearing-macos-desktop-clutter/</link>
				<pubDate>Tue, 23 Apr 2024 12:00:00 -0700</pubDate>
				<guid>https://wdenniss.com/tech/clearing-macos-desktop-clutter/</guid>
				<description>&lt;p&gt;Every year I create a folder on my macOS desktop with the current year, like &lt;code&gt;2024&lt;/code&gt; and move all the desktop items into it (so it contains a folder named &lt;code&gt;2023&lt;/code&gt; and so on). The reason? To clear my desktop, as for some reason macOS defaults to it for saving various files.&lt;/p&gt;&#xA;&lt;p&gt;This two-liner is better. Simply turns off the display of the files on your desktop. Perfect 👌&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;defaults write com.apple.finder CreateDesktop false&#xA;killall Finder&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And to change the default screenshot location:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Stable Diffusion WebUI on GKE Autopilot</title>
				<link>https://wdenniss.com/k8s/stable-diffusion-webui-on-gke-autopilot/</link>
				<pubDate>Thu, 15 Feb 2024 15:30:20 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/stable-diffusion-webui-on-gke-autopilot/</guid>
				<description>&lt;p&gt;I recently set out to run Stable Diffusion on GKE in Autopilot mode, building a container from scratch using the &lt;a href=&#34;https://github.com/AUTOMATIC1111/stable-diffusion-webui&#34;&gt;AUTOMATIC1111&lt;/a&gt;‘s &lt;a href=&#34;https://github.com/AUTOMATIC1111/stable-diffusion-webui&#34;&gt;webui&lt;/a&gt;. This is likely &lt;em&gt;not&lt;/em&gt; how you’d host a stable diffusion service for production (which would make for a good topic of another blog post), but it’s a fun way to try out the tech.&lt;/p&gt;&#xA;&lt;p&gt;My first key learning was to start with a &lt;a href=&#34;https://cloud.google.com/deep-learning-containers&#34;&gt;Google Deep Learning Container&lt;/a&gt; which provides a useful base image with CUDA 12 support and is &lt;a href=&#34;https://cloud.google.com/deep-learning-containers/docs/release-notes#August_10_2023&#34;&gt;based on Debian&lt;/a&gt;. This provides the perfect operating environment for running a CUDA 12 application on Google Cloud. I first attempted to create my own image using Debian, but Stable Diffusion couldn’t find the GPU—better just to use the Google ones that are preconfigured with everything I need!&lt;/p&gt;</description>
			</item>
			<item>
				<title>LLM Model Serving on Autopilot</title>
				<link>https://wdenniss.com/k8s/llm-model-serving-on-autopilot/</link>
				<pubDate>Thu, 21 Dec 2023 00:10:16 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/llm-model-serving-on-autopilot/</guid>
				<description>&lt;p&gt;When building your business using LLMs as a key component, you may wish to be a master of your own domain and run your own model. Running your own LLM protects you from changes like pricing increases or API availability with third-party services, guarantees the privacy of your data (no data needs to leave your VPC), and lets you experiment with advanced topics like fine-tuning. GKE, and in particular Autopilot mode is a great place to run your own LLM, as it takes care of much of the compute orchestration for you, allowing you to focus your energy on providing the LLM API for your business.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Cordoning nodes in GKE Autopilot</title>
				<link>https://wdenniss.com/k8s/cordoning-nodes-in-gke-autopilot/</link>
				<pubDate>Wed, 20 Dec 2023 20:03:27 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/cordoning-nodes-in-gke-autopilot/</guid>
				<description>&lt;p&gt;Occasionally you may wish to remove and replace a node in GKE Autopilot.&lt;/p&gt;&#xA;&lt;p&gt;That can be done with&lt;/p&gt;&#xA;&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;-webkit-text-size-adjust:none;&#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;kubectl cordon $NODE_NAME&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you want to immediate drain the Pods and put them in the pending state, you can further drain the node:&lt;/p&gt;&#xA;&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;-webkit-text-size-adjust:none;&#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;kubectl drain $NODE_NAME --delete-emptydir-data --ignore-daemonsets&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What about if you need to do all nodes? Be aware that this is pretty disruptive, and lot more aggressive than if you leave Autopilot to handle the upgrade itself (which is recommended), but you can apply this technique to the cluster as a whole like so:&lt;/p&gt;</description>
			</item>
			<item>
				<title>CUDA 12 on GKE Autopilot</title>
				<link>https://wdenniss.com/k8s/cuda-12-on-gke-autopilot/</link>
				<pubDate>Wed, 20 Dec 2023 00:29:00 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/cuda-12-on-gke-autopilot/</guid>
				<description>&lt;p&gt;Per the &lt;a href=&#34;https://docs.nvidia.com/deploy/cuda-compatibility/&#34;&gt;NVIDIA docs&lt;/a&gt;, CUDA 12 applications require driver 525.60.04+. This driver is available as part of GKE 1.28. To upgrade an existing cluster to the latest version of 1.28:&lt;/p&gt;&#xA;&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;-webkit-text-size-adjust:none;&#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;VERSION&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1.28&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;REGION&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;us-central1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CLUSTER_NAME&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;autopilot-cluster-1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gcloud container clusters upgrade $CLUSTER_NAME &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --region $REGION &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --master --cluster-version $VERSION&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This upgrades the control plane, and schedules the nodes to follow, which generally completes within a day or two (depending on how many nodes you have).&lt;/p&gt;</description>
			</item>
			<item>
				<title>Using Image Streaming with DockerHub</title>
				<link>https://wdenniss.com/k8s/using-image-streaming-with-dockerhub/</link>
				<pubDate>Wed, 20 Dec 2023 00:23:58 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/using-image-streaming-with-dockerhub/</guid>
				<description>&lt;p&gt;Image streaming is a really great way to speed up workload scaling on GKE. Take for example the deep learning image from Google. In my testing, the container is created in just 20s, instead of 3m50s. While there is slightly higher latency on reads while the image streams, the 3m30s head start is going to well make up for that.&lt;/p&gt;&#xA;&lt;p&gt;If you use GKE in Autopilot mode, and Artifact Registry for your images, then you’re already using image streaming (to verify, look for the &lt;code&gt;ImageStreaming&lt;/code&gt; event with &lt;code&gt;kubectl get events&lt;/code&gt;, if it’s not there, then check your settings such as the API enablement).&lt;/p&gt;</description>
			</item>
			<item>
				<title>Finding the NVIDIA Driver Version on GKE</title>
				<link>https://wdenniss.com/k8s/finding-the-nvidia-driver-version-on-gke/</link>
				<pubDate>Tue, 19 Dec 2023 18:56:01 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/finding-the-nvidia-driver-version-on-gke/</guid>
				<description>&lt;p&gt;&lt;em&gt;Update: this information is now available in the &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/how-to/autopilot-gpus#check-driver-version&#34;&gt;official docs&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;If you want to know what version of your GPU drivers are active on GKE, here’s a one-liner:&lt;/p&gt;&#xA;&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;-webkit-text-size-adjust:none;&#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;kubectl logs -l k8s-app&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;nvidia-gpu-device-plugin &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -c &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;nvidia-gpu-device-plugin&amp;#34;&lt;/span&gt; --tail&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;-1 -n kube-system &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    | grep Driver&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What this command does is get all the logs of Pods with the label &lt;code&gt;k8s-app=nvidia-gpu-device-plugin&lt;/code&gt; (there are several different DaemonSets that can install the drivers depending on the size of the node, but they all share this label). It will print the logs for the container named &lt;code&gt;nvidia-gpu-device-plugin&lt;/code&gt;, and uses &lt;code&gt;--tail=-1&lt;/code&gt; to output &lt;em&gt;all&lt;/em&gt; log messages. The final grep command isolates just the line we care about.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Testing Namespace Isolation using NetworkPolicy</title>
				<link>https://wdenniss.com/k8s/testing-networkpolicy/</link>
				<pubDate>Mon, 06 Nov 2023 11:17:26 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/testing-networkpolicy/</guid>
				<description>&lt;p&gt;In my post &lt;a href=&#34;https://wdenniss.com/k8s/isolating-namespaces-with-networkpolicy/&#34;&gt;&lt;em&gt;Isolating namespaces with NetworkPolicy&lt;/em&gt;&lt;/a&gt;, I presented a pattern for isolating namespaces from each other in a cluster using NetworkPolicy. Let’s put those concepts in to practice.&lt;/p&gt;&#xA;&lt;h2 id=&#34;trying-it-out&#34;&gt;Trying it out&lt;/h2&gt;&#xA;&lt;h3 id=&#34;cluster-requirements&#34;&gt;Cluster requirements&lt;/h3&gt;&#xA;&lt;p&gt;This example is designed to run on GKE, using &lt;strong&gt;DPv2&lt;/strong&gt; and &lt;strong&gt;CloudDNS&lt;/strong&gt;. This is the default for Autopilot, so the following is enough to get you a working environment:&lt;/p&gt;&#xA;&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;-webkit-text-size-adjust:none;&#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;gcloud container clusters create-auto autopilot-cluster-3 &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--region us-west1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For the node-based version of GKE, enable both options. On the command line, add &lt;code&gt;--enable-dataplane-v2 --cluster-dns=clouddns&lt;/code&gt;&lt;/p&gt;</description>
			</item>
			<item>
				<title>Isolating namespaces with NetworkPolicy</title>
				<link>https://wdenniss.com/k8s/isolating-namespaces-with-networkpolicy/</link>
				<pubDate>Mon, 06 Nov 2023 11:16:16 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/isolating-namespaces-with-networkpolicy/</guid>
				<description>&lt;p&gt;Kubernetes allows for multi-tenancy within the cluster using namespaces. You can host multiple different applications each in their own namespace that at times can feel almost like a separate cluster. If you configure RBAC you can grant users and service accounts access to specific namespaces and even control what objects they can modify within.&lt;/p&gt;&#xA;&lt;p&gt;However, by default every Pod can communicate with every other Pod, cluster wide. This is actually a really nice design property of Kubernetes, which allows different teams to publish their own services, but it doesn’t give you any network isolation at all. While a team may want to allow internal access of a particular service from other namespaces, they may not want all their internal services exposed.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Editing IP Masquerading rules for GKE Autopilot</title>
				<link>https://wdenniss.com/k8s/editing-ip-masquerading-rules-for-gke-autopilot/</link>
				<pubDate>Thu, 05 Oct 2023 10:30:00 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/editing-ip-masquerading-rules-for-gke-autopilot/</guid>
				<description>&lt;p&gt;IPs are masqueraded by default in Autopilot to use the node IP for egress traffic. which is just a fancy way of saying, the Pod traffic looks like it comes from the node’s IP.&lt;/p&gt;&#xA;&lt;p&gt;This is handy when using non-RFC1918 ranges in GKE to avoid IP exhaustion, since your Node IP range is typically in RFC 1918 space which is what other services may be expecting. However, GKE does &lt;em&gt;not&lt;/em&gt; masquerade traffic to internal addresses (like 10.0.0.0/8) by default. If you have a service that is expecting IPs in the RFC 1918 range, you may need to adjust the masquerade rules to include those destinations.&lt;/p&gt;</description>
			</item>
			<item>
				<title>GKE Network Planning (2023)</title>
				<link>https://wdenniss.com/k8s/gke-network-planning/</link>
				<pubDate>Wed, 04 Oct 2023 05:30:22 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/gke-network-planning/</guid>
				<description>&lt;p&gt;GKE operates on a flat VPC structure. That means that every Node and Pod has an identity within your VPC, and their IPs are not re-used. This is convenient, as Pods are addressable within the VPC, but unless you create multiple VPCs to isolate resources, you can end up using a lot of IPs very quickly. Fortunately, the system is pretty flexible and there are some steps you can take to optimize.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Adding Pod IP ranges to GKE clusters</title>
				<link>https://wdenniss.com/k8s/adding-pod-ip-ranges-to-gke-clusters/</link>
				<pubDate>Mon, 02 Oct 2023 22:40:44 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/adding-pod-ip-ranges-to-gke-clusters/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;Adding-a-Pod-IP-range-to-GKE.png&#34; alt=&#34;DALL-E: &amp;ldquo;An image super realistic with lots of color of adding a Pod IP range to a GKE cluster&amp;rdquo;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Did you know that you can now &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/how-to/multi-pod-cidr#add_more_pod_ranges_autopilot&#34;&gt;add Pod IP ranges to GKE clusters&lt;/a&gt;? Pods use a lot of IPs, which in the past forced you to compromise. Do you allocate a lot of IPs to the cluster allowing for growth while reserving a big group of IPs, or do you allocate just a little to conserve IPs but risking the need to recreate the cluster if you expand.&lt;/p&gt;</description>
			</item>
			<item>
				<title>BYO Service Mesh on GKE Autopilot</title>
				<link>https://wdenniss.com/k8s/byo-service-mesh-on-gke-autopilot/</link>
				<pubDate>Mon, 25 Sep 2023 16:53:05 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/byo-service-mesh-on-gke-autopilot/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;BYO-Service-Mesh.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Did you know you can now run any service mesh on Autopilot? That’s right! Even though Autopilot is a fully managed Kubernetes platform which by nature means you don’t have full root access to the node, that doesn’t mean you’re limited in what service mesh you can install.&lt;/p&gt;&#xA;&lt;p&gt;How does it work? Service Meshes require the &lt;code&gt;NET_ADMIN&lt;/code&gt; Linux permission. While NET_ADMIN isn’t a super high privileged permission, it has occasionally been the source of CVEs, so to keep things safe, the permission is off by default. For those who want to run their own service mesh though, now you can use it. Just add &lt;code&gt;--workload-policies=allow-net-admin&lt;/code&gt; when creating a cluster (CLI only for now), or at any time update the cluster as follows:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Mapping Machine Types to Autopilot Compute Classes</title>
				<link>https://wdenniss.com/k8s/autopilot-machine-mapping/</link>
				<pubDate>Fri, 12 May 2023 02:03:15 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/autopilot-machine-mapping/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;Machine-Types.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Autopilot offers a slightly more abstract view of compute infrastructure than GKE’s Standard mode. The idea is to focus more on the different use-cases than the minutiae of individual machine configurations. However, if you’re coming from GKE Standard or GCE, and know those machine types well, you might want to understand the mapping between the two.&lt;/p&gt;&#xA;&lt;p&gt;Here’s a quick reference for the resulting machine type from an Autopilot nodeSelector.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Multi-Cluster Services on GKE</title>
				<link>https://wdenniss.com/k8s/multi-cluster-services/</link>
				<pubDate>Fri, 05 May 2023 04:29:27 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/multi-cluster-services/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;MCS.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Connect internal services from multiple clusters together in one logical namespace. Easily connect services running in Autopilot to Standard and vice versa, share services between teams running on their own services, and back an internal service by replicas in multiple clusters for cross-regional availability. All with the Multi-cluster Service support in GKE.&lt;/p&gt;&#xA;&lt;p&gt;For this demo, let’s create a service in a GKE Autopilot cluster, and access it from a GKE Standard cluster.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Strict Pod Co-location</title>
				<link>https://wdenniss.com/k8s/strict-pod-co-location/</link>
				<pubDate>Thu, 30 Mar 2023 02:44:22 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/strict-pod-co-location/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;Strict-Co-location.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Pod affinity is a useful technique in Kubernetes for expressing a requirement that a pod, say with the “reader” role, is co-located with another pod, say with the “writer’ role. You can express that requirement by adding something like the following to the reader pod.&lt;/p&gt;&#xA;&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;-webkit-text-size-adjust:none;display:grid;&#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;affinity&lt;/span&gt;:&#xA;&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;podAffinity&lt;/span&gt;:&#xA;&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;requiredDuringSchedulingIgnoredDuringExecution&lt;/span&gt;:&#xA;&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;labelSelector&lt;/span&gt;:&#xA;&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;matchExpressions&lt;/span&gt;:&#xA;&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;key&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;pod&lt;/span&gt;&#xA;&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;operator&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;In&lt;/span&gt;&#xA;&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;values&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#3c3d38&#34;&gt;&lt;span&gt;                - &lt;span style=&#34;color:#ae81ff&#34;&gt;writer-pod&lt;/span&gt;&#xA;&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;topologyKey&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;kubernetes.io/hostname&amp;#34;&lt;/span&gt;   &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The catch is, if there is no space on the node, and nothing that can be evicted, this reader pod may never schedule.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Reducing GKE Log Ingestion</title>
				<link>https://wdenniss.com/k8s/reducing-gke-log-ingestion/</link>
				<pubDate>Fri, 10 Mar 2023 20:23:43 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/reducing-gke-log-ingestion/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;Logging.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;[Update (2023-12-20): You can now turn off workload logging in Autopilot. That is the recommended approach if you want to remove all workload logs. To disable workload logs for Autopilot (for example, if you use a third-party logging agent like DataDog), pass this value at cluster creation:&lt;/p&gt;&#xA;&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;-webkit-text-size-adjust:none;&#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;gcloud container clusters create-auto $CLUSTER_NAME &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --logging&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;SYSTEM&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or update&lt;/p&gt;&#xA;&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;-webkit-text-size-adjust:none;&#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;gcloud container clusters update $CLUSTER_NAME &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --logging&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;SYSTEM&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The remainder of this blog post is as originally posted, and shows you how to fine-tune the logs that that you keep]&lt;/p&gt;</description>
			</item>
			<item>
				<title>HA 3-zone Deployments with PodSpreadTopology on Autopilot</title>
				<link>https://wdenniss.com/k8s/ha-3-zone-autopilot-deployment/</link>
				<pubDate>Thu, 01 Dec 2022 04:59:08 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/ha-3-zone-autopilot-deployment/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;HA-Pods.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/&#34;&gt;PodSpreadTopology&lt;/a&gt; is a way to get Kubernetes to spread out your pods across a failure domain, typically nodes or zones. Kubernetes platforms typically have some default spread built in, although it may not be as aggressive as you want (meaning, it might be more tolerant of imbalanced spread).&lt;/p&gt;&#xA;&lt;p&gt;Here’s an example Deployment with a PodSpreadToplogy that will result in an even spread over all zones (I also have a writeup on this topic which you can &lt;a href=&#34;https://livebook.manning.com/book/kubernetes-for-developers/chapter-8/v-11/87&#34;&gt;preview in my book&lt;/a&gt;).&lt;/p&gt;</description>
			</item>
			<item>
				<title>SSD Ephemeral Storage on GKE (including Autopilot)</title>
				<link>https://wdenniss.com/k8s/ssd-ephemeral-storage-on-autopilot/</link>
				<pubDate>Mon, 28 Nov 2022 17:13:41 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/ssd-ephemeral-storage-on-autopilot/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;Ephemeral-Storage.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Do you need to provision a whole bunch of ephemeral storage to your Autopilot Pods? For example, as part of a data processing pipeline? In the past with Kubernetes, you might have used &lt;a href=&#34;https://kubernetes.io/docs/concepts/storage/volumes/#emptydir&#34;&gt;&lt;code&gt;emptyDir&lt;/code&gt;&lt;/a&gt; as a way to allocate a bunch of storage (taken from the node’s boot disk) to your containers. This however requires that you carefully plan your node’s boot disks to ensure the disk has enough total storage to handle the Pods you plan to schedule, and may result in overprovisioning (i.e. unused storage capacity) if the Pods that end up being scheduled don’t use it all. Lots of inflexible, upfront planning combined with potential wastage 🤮.&lt;/p&gt;</description>
			</item>
			<item>
				<title>TensorFlow on GKE Autopilot with GPU acceleration</title>
				<link>https://wdenniss.com/k8s/tensorflow-on-gke-autopilot-with-gpu-acceleration/</link>
				<pubDate>Mon, 03 Oct 2022 16:16:57 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/tensorflow-on-gke-autopilot-with-gpu-acceleration/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;wdenniss-TensorflowxAutopilot-1.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Last week, GKE &lt;a href=&#34;https://cloud.google.com/blog/products/containers-kubernetes/run-gpu-workloads-on-gke-autopilot&#34;&gt;announced GPU support for Autopilot&lt;/a&gt;. Here’s a fun way to try it out: a TensorFlow-enabled Jupyter Notebook with GPU-acceleration! We can even add state, so you can save your work between sessions. Autopilot makes all this really, &lt;em&gt;really&lt;/em&gt; easy, as you can configure everything as a Kubernetes object.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Update: this post is now on the &lt;a href=&#34;https://cloud.google.com/blog/products/containers-kubernetes/automate-tensorflow-ml-workloads-on-cloud-with-autopilot&#34;&gt;Google Cloud blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;setup&#34;&gt;Setup&lt;/h2&gt;&#xA;&lt;p&gt;First, create a GKE Autopilot cluster running 1.24 (1.24.2-gke.1800+ to be &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/release-notes#September_30_2022&#34;&gt;exact&lt;/a&gt;). Be sure you’re in one of the regions with GPUs (the pricing table helpfully shows which region.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Migrating an IP-based service in GKE</title>
				<link>https://wdenniss.com/k8s/migrating-an-ip-based-service-in-gke/</link>
				<pubDate>Tue, 23 Aug 2022 22:06:00 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/migrating-an-ip-based-service-in-gke/</guid>
				<description>&lt;p&gt;Let’s say you want to migrate a service in GKE from one cluster to another (including between Standard and Autopilot clusters), and keep the same external IP while you do. DNS might be the ideal way to update your service address, for whatever reason you need to keep the IP the same. Fortunately, it is possible to preserve the IP and assign it to a new service in a different cluster in Kubernetes.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Running GKE Autopilot at Scale</title>
				<link>https://wdenniss.com/k8s/running-gke-autopilot-at-scale/</link>
				<pubDate>Sun, 21 Aug 2022 00:07:09 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/running-gke-autopilot-at-scale/</guid>
				<description>&lt;p&gt;If you like what you see with Autopilot (now the &lt;a href=&#34;https://twitter.com/WilliamDenniss/status/1560313692448624640&#34;&gt;recommended way to use GKE&lt;/a&gt;), and want to run it at scale, there are a few things to know when setting up the cluster, and scaling your workload.&lt;/p&gt;&#xA;&lt;h2 id=&#34;cluster-creation&#34;&gt;Cluster Creation&lt;/h2&gt;&#xA;&lt;p&gt;To run a large Autopilot cluster, it’s advisable to do two things: 1) create the cluster with private networking (while not compulsory, public IPs are in short supply, and you may run into quota issues with public networking at large scale). 2) provision a &lt;a href=&#34;https://wdenniss.com/k8s/choosing-the-right-network-size-for-autopilot/&#34;&gt;large enough CIDR range&lt;/a&gt; for your nodes as this can’t be changed later (&lt;code&gt;/13&lt;/code&gt; to really future proof the cluster).&lt;/p&gt;</description>
			</item>
			<item>
				<title>Provisioning one-off spare capacity for GKE Autopilot</title>
				<link>https://wdenniss.com/k8s/autopilot-capacity-reservation/</link>
				<pubDate>Sun, 21 Aug 2022 00:03:31 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/autopilot-capacity-reservation/</guid>
				<description>&lt;p&gt;I previously documented how to &lt;a href=&#34;https://wdenniss.com/k8s/gke-autopilot-spare-capacity/&#34;&gt;add spare capacity to an Autopilot Kubernetes cluster&lt;/a&gt;, whereby you create a placeholder Deployment to provision some scheduling headroom. This works to constantly give you a certain amount of headroom, so for example if you have a 2vCPU placeholder (a.k.a. balloon) Deployment, and use that capacity it will get rescheduled. A useful concept to add some rapid scaling capabilities to Autopilot.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Update: GKE now has an official guide for &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/how-to/capacity-provisioning&#34;&gt;provisioning spare capacity&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</description>
			</item>
			<item>
				<title>Kubernetes for Developers: Reader Discount</title>
				<link>https://wdenniss.com/k8s/kubernetes-for-developers-discount/</link>
				<pubDate>Sat, 20 Aug 2022 23:41:14 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/kubernetes-for-developers-discount/</guid>
				<description>&lt;p&gt;Readers of my blog can score a special 35% discount for my book &lt;a href=&#34;https://wdenniss.com/kubernetes-for-developers&#34;&gt;Kubernetes for Developers&lt;/a&gt;! Simply enter this code at checkout: &lt;strong&gt;au35den&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;wdenniss.com-35-off.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;</description>
			</item>
			<item>
				<title>High-Performance Compute on Autopilot</title>
				<link>https://wdenniss.com/k8s/high-performance-compute-on-autopilot/</link>
				<pubDate>Wed, 27 Jul 2022 04:47:07 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/high-performance-compute-on-autopilot/</guid>
				<description>&lt;p&gt;This week, Autopilot announced support for the &lt;a href=&#34;https://cloud.google.com/blog/products/containers-kubernetes/deploying-arm-workloads-on-gke-autopilot-with-the-scale-out-compute-class&#34;&gt;Scale-Out Compute Class&lt;/a&gt;, for both x86 and Arm architectures. The point of this compute class is to give you cores for better single-threaded performance, and improved price/performance for “scale-out” workloads — basically for when you are saturating the CPU, and/or need faster single-threaded performance (e.g. remote compilation, etc).&lt;/p&gt;&#xA;&lt;p&gt;To use, simply add “compute-class: Scale-Out” to your workloads. They can be Arm, or x86 — but pay attention to the available regions. Also note that you need to be using a very new version of Autopilot (see this blog for a CLI command to get you a Scale-Out qualified cluster).&lt;/p&gt;</description>
			</item>
			<item>
				<title>Building Arm Images with Cloud Build</title>
				<link>https://wdenniss.com/k8s/building-arm-images-with-cloud-build/</link>
				<pubDate>Fri, 15 Jul 2022 18:51:53 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/building-arm-images-with-cloud-build/</guid>
				<description>&lt;p&gt;This week’s big news in Google Cloud was the addition to Arm across a wide range of products, including &lt;a href=&#34;https://cloud.google.com/blog/products/compute/tau-t2a-is-first-compute-engine-vm-on-an-arm-chip&#34;&gt;GCE VMs&lt;/a&gt;, and &lt;a href=&#34;https://cloud.google.com/blog/products/containers-kubernetes/gke-supports-new-arm-based-tau-t2a-vms&#34;&gt;GKE&lt;/a&gt; (both Standard and Autopilot). In an earlier post, I covered how to get an &lt;a href=&#34;https://wdenniss.com/k8s/arm-on-autopilot/&#34;&gt;Arm-ready Autopilot cluster&lt;/a&gt; on day 1.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;https://developer.arm.com/documentation/102475/0100/Multi-architecture-images&#34;&gt;recommended&lt;/a&gt; way to build images for Arm is with &lt;a href=&#34;https://docs.docker.com/buildx/working-with-buildx/&#34;&gt;buildx&lt;/a&gt;. This is also how you can build multi-arch Docker images (ones that can run on both Arm and x86), which is a good idea to do for the time being due to the limited availability of Arm at launch.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Arm on Autopilot</title>
				<link>https://wdenniss.com/k8s/arm-on-autopilot/</link>
				<pubDate>Wed, 13 Jul 2022 18:27:14 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/arm-on-autopilot/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://cloud.google.com/blog/products/compute/tau-t2a-is-first-compute-engine-vm-on-an-arm-chip&#34;&gt;Arm was made available in Preview on Google Cloud&lt;/a&gt;, and &lt;a href=&#34;https://cloud.google.com/blog/products/containers-kubernetes/gke-supports-new-arm-based-tau-t2a-vms&#34;&gt;GKE Autopilot&lt;/a&gt; today! As this is an early stage Preview, there’s a few details to pay attention to if you want to try it out, like the version, regions and quota. I put together this quickstart for trying out Arm in Autopilot today.&lt;/p&gt;&#xA;&lt;p&gt;Arm nodes are available in 3 regions, so be sure to use one from this list:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;us-central&lt;/li&gt;&#xA;&lt;li&gt;europe-west4&lt;/li&gt;&#xA;&lt;li&gt;asia-southeast1&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;You’ll also need to create a cluster with a version greater than &lt;code&gt;1.24.1-gke.1400&lt;/code&gt;. This version isn’t the default today, even in the Rapid channel, so you’ll need to create a cluster at a specific version. The following command works at the time of writing, but in the future (once the patch version has been retired), you’ll need to &lt;a href=&#34;https://wdenniss.com/k8s/creating-an-autopilot-cluster-at-a-specific-version/&#34;&gt;specify a currently valid version&lt;/a&gt; newer than that one.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Minimizing Pod Disruption on Autopilot</title>
				<link>https://wdenniss.com/k8s/minimizing-pod-disruption/</link>
				<pubDate>Tue, 14 Jun 2022 07:58:06 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/minimizing-pod-disruption/</guid>
				<description>&lt;p&gt;There are 3 common reasons why a Pod may be terminated on Autopilot: node upgrades, a cluster scale-down, and a node repair. &lt;a href=&#34;https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#how-disruption-budgets-work&#34;&gt;PDBs&lt;/a&gt; and &lt;a href=&#34;https://kubernetes.io/docs/concepts/workloads/pods/#termination-of-pods&#34;&gt;graceful termination periods&lt;/a&gt; modify the disruption to pods when these events happen, and &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/concepts/maintenance-windows-and-exclusions&#34;&gt;maintenance windows and exclusions&lt;/a&gt; control when upgrade events can occur.&lt;/p&gt;&#xA;&lt;h2 id=&#34;upgrade&#34;&gt;Upgrade&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;gracefulTerminationPeriod&lt;/strong&gt;: limited to one hour&lt;br&gt;&#xA;&lt;strong&gt;PDB&lt;/strong&gt;: is respected for up to one hour&lt;br&gt;&#xA;&lt;strong&gt;Maintenance windows&lt;/strong&gt;: respected&lt;br&gt;&#xA;&lt;strong&gt;Unmanaged Pod&lt;/strong&gt;: no impact (won’t prevent upgrade)&lt;/p&gt;&#xA;&lt;p&gt;Note: under the hood, Autopilot performs upgrades using a &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/concepts/cluster-upgrades#node_pool_upgrades&#34;&gt;node pool upgrade&lt;/a&gt; with surge enabled, the documentation of that behavior applies. Unmanaged Pods are those not managed by a higher-order workload controller like Deployment, Job, StatefulSet.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Building GKE Autopilot</title>
				<link>https://wdenniss.com/k8s/building-gke-autopilot/</link>
				<pubDate>Wed, 08 Jun 2022 22:33:26 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/building-gke-autopilot/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;FTDPPXgXwAE6jzk.jpeg&#34; alt=&#34;The audience at my KubeCon talk Building a Nodeless Kubernetes Platform.&#34;&gt;&#xA;&lt;em&gt;Building a Nodeless Kubernetes Platform&lt;/em&gt;. Photo Credit: &lt;a href=&#34;https://twitter.com/kaslinfields/status/1526948164305035265&#34;&gt;Kaslin Fields&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Last month gave a presentation at KubeCon Europe in Valencia on “Building a Nodeless Kubernetes Platform”. In it, I shared the details about the creation of GKE Autopilot including some key decisions that we made, how the product was implemented, and why I believe that the design leads to an ideal fully managed platform.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Transferring a Google Fi eSIM on iOS</title>
				<link>https://wdenniss.com/tech/transferring-a-google-fi-esim-on-ios/</link>
				<pubDate>Fri, 03 Jun 2022 12:00:00 -0700</pubDate>
				<guid>https://wdenniss.com/tech/transferring-a-google-fi-esim-on-ios/</guid>
				<description>&lt;p&gt;Google Fi, despite being originally designed for Android supports iOS, and works really well there. I’ve been using it for years. The only drawback is the lack of 5G (update: it now has 5G!), but for international travel I don’t think there is anything better. The &lt;a href=&#34;https://support.google.com/fi/answer/9823429?hl=en&#34;&gt;Fi eSIM option&lt;/a&gt; is useful too, especially since Fi is the line I never want to remove (since it works everywhere). I found the transfer of eSIM a bit confusing though, so wanted to share the steps that I’ve used a few times now, and found works every time (no pSIM required!):&lt;/p&gt;</description>
			</item>
			<item>
				<title>Preferring Spot in GKE Autopilot</title>
				<link>https://wdenniss.com/k8s/preferring-spot/</link>
				<pubDate>Thu, 26 May 2022 03:41:56 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/preferring-spot/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/how-to/autopilot-spot-pods&#34;&gt;Spot Pods&lt;/a&gt; are a &lt;a href=&#34;https://cloud.google.com/blog/products/containers-kubernetes/announcing-spot-pods-for-gke-autopilot&#34;&gt;great way&lt;/a&gt; to save money on Autopilot, currently 70% off the regular price. The catch is two-fold:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Your workload can be disrupted&lt;/li&gt;&#xA;&lt;li&gt;There may not always be spot capacity available&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;For workload disruption, this is simply a judgement call. You should only run workloads that can accept disruption (abrupt termination). If you have a batch job that would lose hours of work, it’s not a good fit. Generally StatefulSet shouldn’t be run on spot compute, as most stateful workloads are less tolerant to disruption.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Separating Workloads in Autopilot</title>
				<link>https://wdenniss.com/k8s/autopilot-workload-separation/</link>
				<pubDate>Thu, 26 May 2022 02:14:20 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/autopilot-workload-separation/</guid>
				<description>&lt;p&gt;Autopilot while being operationally nodeless, still creates nodes for your workloads behind the scenes. Sometimes it may be desirable as an operator to separate your workloads so that certain workloads are scheduled on their separates nodes, a technique known as &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/how-to/workload-separation&#34;&gt;workload separation&lt;/a&gt;. One example I heard recently was a cluster that primarily processes large batch jobs. In addition to these spikey workloads that cause a lot of scale-up and scale-downs (something that Autopilot takes care of for you), there are a few “stable” workloads that need to run consistently and are better to have placed by themselves.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Developing in Rails via Docker</title>
				<link>https://wdenniss.com/k8s/developing-in-rails-via-docker/</link>
				<pubDate>Sat, 09 Apr 2022 20:23:40 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/developing-in-rails-via-docker/</guid>
				<description>&lt;p&gt;One of the neat things about Docker is that you don’t need to install any dev tools on your local machine.&lt;/p&gt;&#xA;&lt;p&gt;Sometimes though you’ll need to run commands in the dev environment without your app being built (say if there is an error building the app, or you want to run a command like rails new). The way I do this is to have a separate Dockerfile and docker-compose config that configures the dev environment, rather than the app.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Kubernetes Nodes and Autopilot</title>
				<link>https://wdenniss.com/k8s/kubernetes-nodes-and-autopilot/</link>
				<pubDate>Tue, 14 Dec 2021 20:20:57 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/kubernetes-nodes-and-autopilot/</guid>
				<description>&lt;p&gt;One of the key design decisions of GKE Autopilot is the fact that we kept the same semantic meaning of the Kubernetes node object.&lt;/p&gt;&#xA;&lt;p&gt;It’s “nodeless” in the sense that you don’t need to care about, or plan for nodes—they are provisioned and managed automatically based on your PodSpec. However, the node object still exists and has the same meaning. Each node is still backed by a single VM under the hood.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Testing Knative on GKE Autopilot</title>
				<link>https://wdenniss.com/k8s/testing-knative-on-gke-autopilot/</link>
				<pubDate>Mon, 13 Dec 2021 08:24:38 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/testing-knative-on-gke-autopilot/</guid>
				<description>&lt;p&gt;Ahmet’s blog &lt;a href=&#34;https://ahmet.im/blog/knative-positioning/&#34;&gt;&lt;em&gt;Did we market Knative wrong?&lt;/em&gt;&lt;/a&gt; got me interested to try out Knative again. I’ll confess that I found the original Istio requirement a bit of a heavy one just to run serverless, and it looked like the project has matured a lot since the early days. Version 1.0.0 was also just released, so it seems like pretty good timing to give it a go.&lt;/p&gt;&#xA;&lt;p&gt;Naturally, I wanted to see if it worked on Autopilot. Autopilot is a “nodeless” Kubernetes platform, and Knative offers a serverless layer for Kubernetes, so in theory this can be a pretty good match. I was a bit worried that Knative might require root access to nodes, and thus but up against some Autopilot restrictions. The good news is that despite some complications, it &lt;strong&gt;does work&lt;/strong&gt;!&lt;/p&gt;</description>
			</item>
			<item>
				<title>Install kn on Cloud Shell</title>
				<link>https://wdenniss.com/k8s/install-kn-on-cloud-shell/</link>
				<pubDate>Mon, 13 Dec 2021 06:34:23 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/install-kn-on-cloud-shell/</guid>
				<description>&lt;p&gt;Want to run the &lt;a href=&#34;https://knative.dev/docs/install/client/install-kn/&#34;&gt;Knative CLI&lt;/a&gt; tool &lt;code&gt;kn&lt;/code&gt; in Google Cloud’s Cloud Shell? It’s easy:&lt;/p&gt;&#xA;&lt;p&gt;Download the latest release from &lt;a href=&#34;https://github.com/knative/client/releases&#34;&gt;github&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;linux-amd64 is the platform you want for CloudShell. Here I download version 1.3.0:&lt;/p&gt;&#xA;&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;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;wget&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://github.com/knative/client/releases/download/knative-v1.3.0/kn-linux-amd64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, move it into place, and add it to your PATH:&lt;/p&gt;&#xA;&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;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;chmod&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;kn&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;amd64&lt;/span&gt;&#xA;&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;mkdir&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;local&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;bin&lt;/span&gt;&#xA;&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;mv&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;kn&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;amd64&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;local&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;bin&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;kn&lt;/span&gt;&#xA;&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;echo&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;export PATH=&amp;#34;.local/bin:$PATH&amp;#34;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;bashrc&lt;/span&gt;&#xA;&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;.&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;bashrc&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;[Updated 2024-02-15 with version 1.3.0]&lt;/p&gt;</description>
			</item>
			<item>
				<title>Understanding Kubernetes Node Resource Allocation</title>
				<link>https://wdenniss.com/k8s/understanding-kubernetes-node-resource-allocation/</link>
				<pubDate>Wed, 15 Sep 2021 19:08:37 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/understanding-kubernetes-node-resource-allocation/</guid>
				<description>&lt;p&gt;The question often comes up: where do my node resources go in Kubernetes? In this post, I share how to use &lt;code&gt;kubectl describe node&lt;/code&gt; to look at resource usage by different categories (system, user, etc).&lt;/p&gt;&#xA;&lt;p&gt;The way I think about Kubernetes node resource usage is to assign resource allocations into 4 categories:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;OS and Kubernetes overhead&lt;/li&gt;&#xA;&lt;li&gt;System pods&lt;/li&gt;&#xA;&lt;li&gt;User pods&lt;/li&gt;&#xA;&lt;li&gt;Empty space&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The OS &amp;amp; Kubernetes overhead includes the Linux kernel, the kubelet, and for memory, an allocation known as the “eviction threshold” which allows the kubelet a chance to catch Pods that are going over their memory allocation and take action according to their Kubernetes priorities before the kernel OOM handling kicks in which is a blunter instrument.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Creating an Autopilot cluster at a specific version</title>
				<link>https://wdenniss.com/k8s/creating-an-autopilot-cluster-at-a-specific-version/</link>
				<pubDate>Mon, 16 Aug 2021 23:02:40 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/creating-an-autopilot-cluster-at-a-specific-version/</guid>
				<description>&lt;p&gt;Sometimes you may wish to create or update a GKE Autopilot cluster with a specific version. For example, the big news this week is that mutating webhooks are &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview&#34;&gt;supported in Autopilot&lt;/a&gt; (from version &lt;code&gt;1.21.3-gke.900&lt;/code&gt;). Rather than waiting for your desired version to be the default in your cluster’s &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/concepts/release-channels&#34;&gt;release channel&lt;/a&gt;, you can update ahead of time.&lt;/p&gt;&#xA;&lt;p&gt;Through the UI, you can choose the Autopilot release channel but each release channel actually has a few different versions. “Rapid” is the obvious release channel to use for testing new features, but you can be even more bleeding-edge than the default version in the Rapid channel by specifying the version.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Choosing the right network size for Autopilot</title>
				<link>https://wdenniss.com/k8s/choosing-the-right-network-size-for-autopilot/</link>
				<pubDate>Tue, 03 Aug 2021 22:57:32 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/choosing-the-right-network-size-for-autopilot/</guid>
				<description>&lt;p&gt;&lt;strong&gt;Update (2023-09)&lt;/strong&gt;: Autopilot now supports the ability to add additional Pod IP ranges, so you no longer need to plan this up front. Read the &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/how-to/multi-pod-cidr#add_more_pod_ranges_autopilot&#34;&gt;official docs&lt;/a&gt;, and my test run.&lt;/p&gt;&#xA;&lt;p&gt;One of the most important decisions you can make for your Autopilot cluster is selecting the right network size. Too small and you’ll constraint your potential growth. Too large and you might run out of IPs if you have a lot of cluster. You can’t change the Pod address size after creation, so it’s important to get it right.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Using GKE Autopilot in specific zones</title>
				<link>https://wdenniss.com/k8s/autopilot-specific-zones/</link>
				<pubDate>Wed, 14 Apr 2021 23:02:33 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/autopilot-specific-zones/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;Zonal-Workloads-1.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;GKE Autopilot is deployed using the regional cluster architecture. This has a number of advantages such as giving you 3 master nodes for high availability of the control plane, and the ability to spread pods among zones for high availability of your workloads. But sometimes this may be more than what you need, and zonal pattern would work better.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Update: there is now an &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/how-to/gke-zonal-topology&#34;&gt;official doc&lt;/a&gt; on this topic.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;If you’re dealing with zonal resources, say for example you want to mount a persistent disk into a Pod, where the disk is a zonal disk — you’ll want to target your zone explicitly.&lt;/p&gt;</description>
			</item>
			<item>
				<title>GKE Autopilot: how to know if Pending pods will be scheduled</title>
				<link>https://wdenniss.com/k8s/autopilot-pending-pods/</link>
				<pubDate>Fri, 12 Mar 2021 22:15:55 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/autopilot-pending-pods/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;Debug-Pending-Pods.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;GKE Autopilot is pretty magical. You create a cluster just by picking a region and giving it a name, schedule Kubernetes workloads and the compute resources are provisioned automatically.&lt;/p&gt;&#xA;&lt;p&gt;While Kubernetes is provisioning resources, your Pods will be in the &lt;code&gt;Pending&lt;/code&gt; state. This is all well and good, except… there are other reasons that your Pods can be pending.&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;NAME READY STATUS RESTARTS AGE&#xA;example-deploy-84576c8598-7jbqc 1/1 Pending 0 34s&#xA;example-deploy-84576c8598-7mbfh 1/1 Pending 0 33s&#xA;example-deploy-84576c8598-bhfqt 1/1 Pending 0 34s&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;Pods that are &lt;code&gt;Pending&lt;/code&gt;. Will they be provisioned, or won’t they?&lt;/em&gt;&lt;/p&gt;</description>
			</item>
			<item>
				<title>Configuring phpMyAdmin with CloudSQL, RDS, and Docker</title>
				<link>https://wdenniss.com/k8s/configuring-phpmyadmin-with-cloudsql-rds-and-docker/</link>
				<pubDate>Thu, 04 Mar 2021 07:36:39 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/configuring-phpmyadmin-with-cloudsql-rds-and-docker/</guid>
				<description>&lt;p&gt;I still have a place in my heart for phpMyAdmin, that tool that I was introduced when developing PHP on my shared hosting provider many moons ago. It’s just a great way to inspect your MariaDB/MySQL databases.&lt;/p&gt;&#xA;&lt;p&gt;These days I don’t install any web applications (or databases) on my local machine, I use Docker for everything, and Docker Compose in particular, to get repeatable environments.&lt;/p&gt;&#xA;&lt;p&gt;Here’s what I use for phpMyAdmin:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Provisioning spare capacity in GKE Autopilot with placeholder balloon pods</title>
				<link>https://wdenniss.com/k8s/gke-autopilot-spare-capacity/</link>
				<pubDate>Wed, 24 Feb 2021 06:37:05 -0700</pubDate>
				<guid>https://wdenniss.com/k8s/gke-autopilot-spare-capacity/</guid>
				<description>&lt;p&gt;Autopilot is a new mode of operation for Google Kubernetes Engine (GKE) where compute capacity is dynamically provisioned based on your pod’s requirements. Among other innovations, it essentially functions as a fully automatic cluster autoscaler.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Update: GKE now has an official guide for &lt;a href=&#34;https://cloud.google.com/kubernetes-engine/docs/how-to/capacity-provisioning&#34;&gt;provisioning spare capacity&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;When you deploy a new pod in this environment, sometimes they’ll be existing spare capacity on the cluster and it will start booting right away, other times more compute capacity (nodes) will need to be added. Autopilot is quick to respond when more resources are needed, provisioning new capacity in around 60 to 80 seconds, after which the pod will boot.&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
