<?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://dev.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://dev.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://dev.wdenniss.com/agents/deploy-choice/</link>
      <pubDate>Wed, 02 Sep 2026 18:44:54 -0700</pubDate>
      <guid>https://dev.wdenniss.com/agents/deploy-choice/</guid>
      <description>&lt;p&gt;Let&amp;rsquo;s say you&amp;rsquo;ve built an agent with ADK and want to make it available in the&#xA;Gemini Enterprise app. You don&amp;rsquo;t want to pickle the agent — you want to deploy&#xA;its source or a container — and both Agent Runtime and Cloud Run look like&#xA;reasonable places to run it. Which should you choose?&lt;/p&gt;&#xA;&lt;p&gt;For that specific case, I would deploy the source to Agent Runtime with&#xA;&lt;code&gt;adk deploy agent_engine&lt;/code&gt;, then register the resulting &lt;code&gt;reasoningEngine&lt;/code&gt; with&#xA;Gemini Enterprise using the native ADK integration. I would choose Cloud Run&#xA;and Agent2Agent (A2A) if serving clients beyond Gemini Enterprise, or keeping&#xA;the endpoint portable, were actual requirements.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Running stateful ADK agents on Substrate and GKE</title>
      <link>https://dev.wdenniss.com/agents/substrate-demo/</link>
      <pubDate>Tue, 01 Sep 2026 21:56:54 -0700</pubDate>
      <guid>https://dev.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>Agent Platform BYOC without the wrapper: new in ADK 2.2</title>
      <link>https://dev.wdenniss.com/agents/agent-platform-byoc/</link>
      <pubDate>Wed, 15 Jul 2026 04:56:08 +0000</pubDate>
      <guid>https://dev.wdenniss.com/agents/agent-platform-byoc/</guid>
      <description>&lt;p&gt;In &lt;a href=&#34;https://dev.wdenniss.com/agents/ap-api-contract/&#34;&gt;The Agent Platform API contract&lt;/a&gt; I walked through the two routes a bring-your-own-container agent has to serve — &lt;code&gt;/api/reasoning_engine&lt;/code&gt; and &lt;code&gt;/api/stream_reasoning_engine&lt;/code&gt; — and the FastAPI wrapper I wrote to dispatch them onto an &lt;code&gt;AdkApp&lt;/code&gt;. It worked, but it was 117 lines of plumbing that had nothing to do with the agent itself.&lt;/p&gt;&#xA;&lt;p&gt;Comment: Draft generated from my working session migrating the book samples to ADK 2.2. –William&lt;/p&gt;&#xA;&lt;p&gt;Good news: as of ADK 2.2.0 you can delete that wrapper. A new flag, &lt;code&gt;--gemini_enterprise_app_name&lt;/code&gt;, teaches the plain &lt;code&gt;adk api_server&lt;/code&gt; to serve those exact routes itself. The name is a little misleading for our purposes — the flag exists so you can register a self-hosted ADK server as an agent in Gemini Enterprise — but Gemini Enterprise speaks the Agent Engine wire protocol, and that&amp;rsquo;s precisely the protocol Agent Runtime forwards to a BYOC container. Set the flag, and the same container image from &lt;a href=&#34;https://dev.wdenniss.com/agents/4-ways-to-deploy/&#34;&gt;4 ways to deploy agents on Agent Platform&lt;/a&gt; (option 4) serves the whole contract with no custom code.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Serving the Agent Platform API contract</title>
      <link>https://dev.wdenniss.com/agents/serving-the-ap-api-contract/</link>
      <pubDate>Mon, 13 Jul 2026 21:41:56 +0000</pubDate>
      <guid>https://dev.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://dev.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://dev.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://dev.wdenniss.com/agents/ap-api-contract/</link>
      <pubDate>Mon, 13 Jul 2026 21:41:56 +0000</pubDate>
      <guid>https://dev.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://dev.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>Containerizing an ADK agent</title>
      <link>https://dev.wdenniss.com/ap/3-containerizing/3.1-adk-container/</link>
      <pubDate>Sat, 20 Jun 2026 20:39:04 +0000</pubDate>
      <guid>https://dev.wdenniss.com/ap/3-containerizing/3.1-adk-container/</guid>
      <description>&lt;p&gt;So far we’ve run the trading agent two ways: locally with &lt;code&gt;adk run&lt;/code&gt;, and &lt;a href=&#34;https://dev.wdenniss.com/ap/1-agent/1.2-deploy-to-ap-runtime/&#34;&gt;deployed to Agent Platform runtime&lt;/a&gt; with a little Python script that packages the code and hosts it for us. Both are handy, but in each case something else is deciding how your agent gets hosted. Sometimes you just want a plain container — one image you can run on your laptop today, and on Cloud Run, GKE, or Agent Platform runtime (in bring-your-own-container mode) tomorrow. Same artifact, runs anywhere Docker does.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Agent Container for Agent Platform runtime</title>
      <link>https://dev.wdenniss.com/ap/3-containerizing/3.5-container-for-ap-runtime/</link>
      <pubDate>Mon, 15 Jun 2026 18:39:04 +0000</pubDate>
      <guid>https://dev.wdenniss.com/ap/3-containerizing/3.5-container-for-ap-runtime/</guid>
      <description></description>
    </item>
    <item>
      <title>Deploy Agent Container to Agent Platform runtime</title>
      <link>https://dev.wdenniss.com/ap/3-containerizing/3.6-deploy-container-to-ap-runtime/</link>
      <pubDate>Mon, 15 Jun 2026 18:39:04 +0000</pubDate>
      <guid>https://dev.wdenniss.com/ap/3-containerizing/3.6-deploy-container-to-ap-runtime/</guid>
      <description></description>
    </item>
    <item>
      <title>Deploy an ADK Agent container to Cloud Run</title>
      <link>https://dev.wdenniss.com/ap/3-containerizing/3.3-deploy-to-cloud-run/</link>
      <pubDate>Mon, 15 Jun 2026 18:39:04 +0000</pubDate>
      <guid>https://dev.wdenniss.com/ap/3-containerizing/3.3-deploy-to-cloud-run/</guid>
      <description></description>
    </item>
    <item>
      <title>Deploy an ADK Agent container to GKE</title>
      <link>https://dev.wdenniss.com/ap/3-containerizing/3.4-deploy-to-gke/</link>
      <pubDate>Mon, 15 Jun 2026 18:39:04 +0000</pubDate>
      <guid>https://dev.wdenniss.com/ap/3-containerizing/3.4-deploy-to-gke/</guid>
      <description></description>
    </item>
    <item>
      <title>Deterministic memories</title>
      <link>https://dev.wdenniss.com/ap/2-memories/2.2-deterministic-memories/</link>
      <pubDate>Mon, 15 Jun 2026 18:37:26 +0000</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/ap/3-containerizing/3.2-creating-an-ap-resource/</link>
      <pubDate>Tue, 09 Jun 2026 13:54:14 -0700</pubDate>
      <guid>https://dev.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>Other Services</title>
      <link>https://dev.wdenniss.com/agents/other-services/</link>
      <pubDate>Wed, 03 Jun 2026 18:26:38 -0700</pubDate>
      <guid>https://dev.wdenniss.com/agents/other-services/</guid>
      <description>&lt;p&gt;Did you know that Agent Platform offers a leading memory bank service, that can be used even if you’re deploying your agentic workload to GKE or Cloud Run? Memory Bank is a fully managed service that in addition to being able to save specific memories you give it, can review the entire session history and derive .&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Memory Bank lets you make any agent a &lt;em&gt;personal agent&lt;/em&gt; by automatically extracting pertinent information to build a profile of the user’s preferences.&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Agent memories with ADK</title>
      <link>https://dev.wdenniss.com/ap/2-memories/2.1-add-memories/</link>
      <pubDate>Mon, 01 Jun 2026 16:16:44 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/ap/1-agent/1.2-deploy-to-ap-runtime/</link>
      <pubDate>Fri, 15 May 2026 11:03:02 -0700</pubDate>
      <guid>https://dev.wdenniss.com/ap/1-agent/1.2-deploy-to-ap-runtime/</guid>
      <description>&lt;p&gt;In my &lt;a href=&#34;https://dev.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://dev.wdenniss.com/ap/1-agent/1.1-create-an-adk-agent/</link>
      <pubDate>Wed, 22 Apr 2026 11:17:03 -0700</pubDate>
      <guid>https://dev.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://dev.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://dev.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>Using C4A and C4D with Compute Class</title>
      <link>https://dev.wdenniss.com/k8s/gke-c4a-c4d-with-compute-class/</link>
      <pubDate>Sun, 17 Aug 2025 12:40:09 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/simulate-a-zonal-failure-on-autopilot/</link>
      <pubDate>Fri, 30 May 2025 22:58:52 -0700</pubDate>
      <guid>https://dev.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>Running Docker in Docker on GKE Autopilot with gVisor</title>
      <link>https://dev.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://dev.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://dev.wdenniss.com/k8s/deepseek-on-gke/</link>
      <pubDate>Wed, 26 Feb 2025 15:52:00 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/kubernetes-history-inspector/</link>
      <pubDate>Thu, 30 Jan 2025 14:56:30 -0700</pubDate>
      <guid>https://dev.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>Getting resource recommendations from VPA</title>
      <link>https://dev.wdenniss.com/k8s/vpa-in-advisory-mode/</link>
      <pubDate>Wed, 06 Nov 2024 12:07:06 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/scaling-container-resources-automatically-with-vpa/</link>
      <pubDate>Tue, 05 Nov 2024 12:47:51 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/using-node-based-pricing-on-gke-autopilot/</link>
      <pubDate>Tue, 03 Sep 2024 11:19:49 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/serving-stable-diffusion-with-rayserve-on-gke-autopilot/</link>
      <pubDate>Tue, 03 Sep 2024 11:12:25 -0700</pubDate>
      <guid>https://dev.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://dev.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>Stable Diffusion WebUI on GKE Autopilot</title>
      <link>https://dev.wdenniss.com/k8s/stable-diffusion-webui-on-gke-autopilot/</link>
      <pubDate>Thu, 15 Feb 2024 15:30:20 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/llm-model-serving-on-autopilot/</link>
      <pubDate>Thu, 21 Dec 2023 00:10:16 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/cordoning-nodes-in-gke-autopilot/</link>
      <pubDate>Wed, 20 Dec 2023 20:03:27 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/cuda-12-on-gke-autopilot/</link>
      <pubDate>Wed, 20 Dec 2023 00:29:00 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/using-image-streaming-with-dockerhub/</link>
      <pubDate>Wed, 20 Dec 2023 00:23:58 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/finding-the-nvidia-driver-version-on-gke/</link>
      <pubDate>Tue, 19 Dec 2023 18:56:01 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/testing-networkpolicy/</link>
      <pubDate>Mon, 06 Nov 2023 11:17:26 -0700</pubDate>
      <guid>https://dev.wdenniss.com/k8s/testing-networkpolicy/</guid>
      <description>&lt;p&gt;In my post &lt;a href=&#34;https://dev.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://dev.wdenniss.com/k8s/isolating-namespaces-with-networkpolicy/</link>
      <pubDate>Mon, 06 Nov 2023 11:16:16 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/editing-ip-masquerading-rules-for-gke-autopilot/</link>
      <pubDate>Thu, 05 Oct 2023 10:30:00 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/gke-network-planning/</link>
      <pubDate>Wed, 04 Oct 2023 05:30:22 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/adding-pod-ip-ranges-to-gke-clusters/</link>
      <pubDate>Mon, 02 Oct 2023 22:40:44 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/byo-service-mesh-on-gke-autopilot/</link>
      <pubDate>Mon, 25 Sep 2023 16:53:05 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/autopilot-machine-mapping/</link>
      <pubDate>Fri, 12 May 2023 02:03:15 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/multi-cluster-services/</link>
      <pubDate>Fri, 05 May 2023 04:29:27 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/strict-pod-co-location/</link>
      <pubDate>Thu, 30 Mar 2023 02:44:22 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/reducing-gke-log-ingestion/</link>
      <pubDate>Fri, 10 Mar 2023 20:23:43 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/ha-3-zone-autopilot-deployment/</link>
      <pubDate>Thu, 01 Dec 2022 04:59:08 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/ssd-ephemeral-storage-on-autopilot/</link>
      <pubDate>Mon, 28 Nov 2022 17:13:41 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/tensorflow-on-gke-autopilot-with-gpu-acceleration/</link>
      <pubDate>Mon, 03 Oct 2022 16:16:57 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/migrating-an-ip-based-service-in-gke/</link>
      <pubDate>Tue, 23 Aug 2022 22:06:00 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/running-gke-autopilot-at-scale/</link>
      <pubDate>Sun, 21 Aug 2022 00:07:09 -0700</pubDate>
      <guid>https://dev.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://dev.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://dev.wdenniss.com/k8s/autopilot-capacity-reservation/</link>
      <pubDate>Sun, 21 Aug 2022 00:03:31 -0700</pubDate>
      <guid>https://dev.wdenniss.com/k8s/autopilot-capacity-reservation/</guid>
      <description>&lt;p&gt;I previously documented how to &lt;a href=&#34;https://dev.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://dev.wdenniss.com/k8s/kubernetes-for-developers-discount/</link>
      <pubDate>Sat, 20 Aug 2022 23:41:14 -0700</pubDate>
      <guid>https://dev.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://dev.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://dev.wdenniss.com/k8s/high-performance-compute-on-autopilot/</link>
      <pubDate>Wed, 27 Jul 2022 04:47:07 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/building-arm-images-with-cloud-build/</link>
      <pubDate>Fri, 15 Jul 2022 18:51:53 -0700</pubDate>
      <guid>https://dev.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://dev.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://dev.wdenniss.com/k8s/arm-on-autopilot/</link>
      <pubDate>Wed, 13 Jul 2022 18:27:14 -0700</pubDate>
      <guid>https://dev.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://dev.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://dev.wdenniss.com/k8s/minimizing-pod-disruption/</link>
      <pubDate>Tue, 14 Jun 2022 07:58:06 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/building-gke-autopilot/</link>
      <pubDate>Wed, 08 Jun 2022 22:33:26 -0700</pubDate>
      <guid>https://dev.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>Preferring Spot in GKE Autopilot</title>
      <link>https://dev.wdenniss.com/k8s/preferring-spot/</link>
      <pubDate>Thu, 26 May 2022 03:41:56 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/autopilot-workload-separation/</link>
      <pubDate>Thu, 26 May 2022 02:14:20 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/developing-in-rails-via-docker/</link>
      <pubDate>Sat, 09 Apr 2022 20:23:40 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/kubernetes-nodes-and-autopilot/</link>
      <pubDate>Tue, 14 Dec 2021 20:20:57 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/testing-knative-on-gke-autopilot/</link>
      <pubDate>Mon, 13 Dec 2021 08:24:38 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/install-kn-on-cloud-shell/</link>
      <pubDate>Mon, 13 Dec 2021 06:34:23 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/understanding-kubernetes-node-resource-allocation/</link>
      <pubDate>Wed, 15 Sep 2021 19:08:37 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/creating-an-autopilot-cluster-at-a-specific-version/</link>
      <pubDate>Mon, 16 Aug 2021 23:02:40 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/choosing-the-right-network-size-for-autopilot/</link>
      <pubDate>Tue, 03 Aug 2021 22:57:32 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/autopilot-specific-zones/</link>
      <pubDate>Wed, 14 Apr 2021 23:02:33 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/autopilot-pending-pods/</link>
      <pubDate>Fri, 12 Mar 2021 22:15:55 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/configuring-phpmyadmin-with-cloudsql-rds-and-docker/</link>
      <pubDate>Thu, 04 Mar 2021 07:36:39 -0700</pubDate>
      <guid>https://dev.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://dev.wdenniss.com/k8s/gke-autopilot-spare-capacity/</link>
      <pubDate>Wed, 24 Feb 2021 06:37:05 -0700</pubDate>
      <guid>https://dev.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>
