<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>rastko</title>
    <description>Head of Architecture. Writing about software, systems, and strategy.
</description>
    <link>https://rastko.tech</link>
    <atom:link href="https://rastko.tech/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 16 Jul 2026 15:35:03 +0000</pubDate>
    <lastBuildDate>Thu, 16 Jul 2026 15:35:03 +0000</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>The Death of the SDKs</title>
        <description>&lt;p&gt;For the most of the systems that ship an SDK , problem they are solving with this is shifting. We are talking dimensional shift - from solving scale problem to solving niche problem.&lt;/p&gt;

&lt;p&gt;An SDK is knowledge about a system expressed as language-specific code — the API surface, the auth model, how to handle pagination, how to parse error responses, what the data model means. The Python library is just how you’ve chosen to ship it.&lt;/p&gt;

&lt;p&gt;And if you ship it as a Python library, you also need a Java library. And a Node library. And something for Go. Every language your consumers use becomes another SDK to maintain, another set of docs to keep in sync, another version to cut when you change something.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-if-you-shipped-the-knowledge-directly&quot;&gt;What if you shipped the knowledge directly?&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;integration skill&lt;/strong&gt;. A centrally maintained, language-agnostic description of how to integrate with your system — the endpoints, the auth flow, the pagination contract, the error handling, the data model, the edge cases that bite people. A consuming team invokes it in whatever language they’re working in.&lt;/p&gt;

&lt;p&gt;Someone needs to integrate in PHP. They invoke the skill. They get a PHP integration. Someone needs Erlang. Same skill, different output.&lt;/p&gt;

&lt;p&gt;The SDK is not the destination — it is what you ship when you cannot yet ship the skill.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;An SDK is a snapshot. You cut a version, consumers pin to it, drift happens. A skill is living knowledge — update it centrally and every consumer gets the current version. You maintain one thing, not N.&lt;/p&gt;

&lt;p&gt;Having the upgrade command in the skill is also easy from this point on.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Once the skill exists, you can just go deeper into the agentic rabbit hole:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A skill tells you how to integrate.&lt;/li&gt;
  &lt;li&gt;An &lt;strong&gt;integration agent&lt;/strong&gt; actually does it — writes the code, wires it into your service, handles the configuration.&lt;/li&gt;
  &lt;li&gt;Then an &lt;strong&gt;integration testing agent&lt;/strong&gt; — verifies correctness against the same knowledge that generated the integration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Skill → agent → testing agent.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;none-of-this-is-a-headstone-for-sdks&quot;&gt;None of this is a headstone for SDKs.&lt;/h2&gt;

&lt;p&gt;If you’re working with something sensitive — financial data, healthcare, anything where you are not comfortable routing integration through an externally hosted model — an SDK is still the right call. The same applies if you have a very specific technology stack and want every integration done identically, with no variance in how the “AI” interprets the knowledge. In those cases the SDK’s predictability is the point.&lt;/p&gt;

&lt;p&gt;What is declining is the &lt;em&gt;range of situations&lt;/em&gt; where an SDK is the right answer. That range is narrowing with every improvement in “AI” tooling, faster than most SDK maintainers are accounting for.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The people integrating with your system are already doing something close to this: feeding your docs and your OpenAPI spec to an “AI” and generating the integration. You’re just not in control of that process, and the quality reflects it.&lt;/p&gt;

&lt;p&gt;You define the knowledge. You maintain it. You decide what the consuming experience looks like, regardless of what language is on the other end.&lt;/p&gt;
</description>
        <pubDate>Thu, 16 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/software/ai/2026/07/16/death-of-the-sdks.html</link>
        <guid isPermaLink="true">https://rastko.tech/software/ai/2026/07/16/death-of-the-sdks.html</guid>
      </item>
    
      <item>
        <title>Mental Models as Medium</title>
        <description>&lt;p&gt;There’s a discipline I’ve practised for a long time that I don’t hear talked about enough: writing down how I think, not what I know.&lt;/p&gt;

&lt;p&gt;I am talking about the actual structure of how I approach a problem — what I look for first, what questions I ask before anyone else has thought to ask them, what lenses I apply and in what order, what the shape of a good answer looks like before I know what the answer is.&lt;/p&gt;

&lt;p&gt;It requires you to catch yourself thinking and then describe the thinking, sort of metacognition, or epistemology if you want academical term.&lt;/p&gt;

&lt;p&gt;Most people, when asked to write down what they know about architecture, produce a list of facts, patterns, principles. That’s knowledge. What I was trying to write down was something else: the engine that produces those facts, patterns, and principles in context, on demand, in response to problems I haven’t seen yet.&lt;/p&gt;

&lt;p&gt;The discipline of making your thinking explicit — of writing it down carefully enough that someone else could follow it — is the discipline of sharpening the thinking itself. You don’t know what you actually think until you’ve tried to write it. And once you’ve written it, you start to see the gaps, the inconsistencies, the places where your intuition outran your ability to explain it.&lt;/p&gt;

&lt;p&gt;I’ve been doing this for years. Rather then accumulating a memory of events and decisions, I  tend ot accumulate structues, mental models — a description of how an experienced architect actually sees: domains, trade-offs, stakeholder dynamics, risk surfaces, the gap between what a system does and what it should do, the difference between what’s technically possible and what’s strategically right.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;the-mental-model&quot;&gt;The Mental model&lt;/h1&gt;

&lt;p&gt;Structured knowledge is important. This should be obvious, but it isn’t always acted on. We very often settle for having knowledge - “documentation exists, and stuff from the checklist is there” at the smaller scale and documentation attached to every service you own at a larger scale.&lt;/p&gt;

&lt;p&gt;But structured knowledge, no matter how well organized, has a gap. The gap between the knowledge existing and applying it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A structured mental model&lt;/strong&gt; — one you’ve articulated carefully, refined against real problems, and organized into something navigatable — is increasing usefulless of your knowledge significantly (would say order of magnitude, but it is not liek there is actual way to measure :)).&lt;/p&gt;

&lt;p&gt;You carry the model. You apply it to each new problem yourself. The model doesn’t meet the problem — you do, using the model. For a broader usage it becomes a bottleneck when you want someone else to benefit from it: a junior architect, a team you’re advising, a domain you’re not embedded in. You can share the documentation. You can’t share the mental model. Not in very efficient way at least… Write a blogpost? Write a book? Give a talk?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gap is the intuition.&lt;/strong&gt; The part of the mental model that operates faster than explanation, that pattern-matches before you’ve consciously engaged, that asks the right question before the meeting has landed on what question to ask.&lt;/p&gt;

&lt;p&gt;You can describe intuition. Describing it doesn’t transfer it.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Every format we’ve had for knowledge transfer — books, talks, blog posts, courses, documentation — runs into this wall. They can describe the model. They cannot enact it. The reader receives the description and then does the work of turning it into practice, alone, without scaffolding, against a learning curve that most people don’t have time or support to climb.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That gap has been there for as long as people have been trying to transfer expertise. For most of history, it was simply the cost of learning — you apprenticed, you paired with someone more experienced, you made mistakes with them watching. The model transferred slowly, through exposure, through correction.&lt;/p&gt;

&lt;p&gt;There was no other way.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;enter-the-ai&quot;&gt;Enter The “AI”&lt;/h1&gt;

&lt;p&gt;What “AI” changes is not that it makes you smarter, or faster, or able to do things you couldn’t do before. What it changes — the thing that matters most — is this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For the first time, a written mental model can be made executable.&lt;/strong&gt; - To a level at least.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This is, of course, LLMs, the “AI” (with large quotation marks), the Large Language Models are aweome at pattern matching and dealing with written prose - this is no brainer. Teach LLM to structure it’s pattern matching areasoning in certain way and you can have it demonstrate the analysis approach and understanding principles you are applying to the very usable level.&lt;strong&gt;Especially if you are not doing “rocket science”, which minimum of 99% of us dont.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You write down how you think. You structure it carefully — the lenses, the analysis frameworks, the sequence of questions, the principles that govern trade-offs. You make it explicit enough that it can be read and internalized. And then an “AI” agent internalizes it and applies it — to your codebase, your system, your problem, in your context — in real time.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt; - for my fellow SciFi freaks out there, this is why I mentioned specific cases (this time code, architecture etc) - no, you cant really generally teach it how to think like you, but for some niche things and one abstract layer you carefully choose…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The model doesn’t sit on the shelf. It works. It meets the problem you bring it. It asks the questions you would ask. It surfaces the considerations your experience would surface (under your control). Not because the “AI” is replacing your judgment — but because the written model is now an active participant in the thinking, not a static reference you consult.&lt;/p&gt;

&lt;p&gt;I am describing potential way to try and cover the gap between structured knowledge and applied expertise — the gap that every knowledge transfer format has always had to leave open may be narrowed using Large Language Models and well crafted harnesses (from industries mega products like Codex, Claude Code to your local machine friendly qwens and gemmas and harness you wrote in python)&lt;/p&gt;

&lt;p&gt;This is what I have tried to build one winter week in 2025.&lt;/p&gt;

&lt;p&gt;I finally found use for the things I tried to wrte before — an architecture book I never finished, a solution architect’s guide that stalled, the article about analysis patterns — weren’t wasted. Turns out they were drafts of the mental model itself.&lt;/p&gt;

&lt;p&gt;These were attempts to make the thinking explicit before the capability to make it executable existed. The &lt;strong&gt;blueprint concept&lt;/strong&gt;, the &lt;strong&gt;two scales&lt;/strong&gt;, the &lt;strong&gt;cognitive load&lt;/strong&gt; argument, the themes that kept recurring in everything I wrote — they’re all now in quantum-toolbox.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;quantum-toolbox&quot;&gt;quantum-toolbox&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;quantum-toolbox&lt;/strong&gt; is a markdown-based executable mental model — no runtime dependencies, no plugins, no API calls — that ships as a git submodule into any project. “AI” “agents” read it at session start and gain the ability to try and do some architecture work.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/quantum-crowbar/quantum-toolbox&quot;&gt;quantum-toolbox on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The core is what I call the &lt;strong&gt;mental model as engine&lt;/strong&gt;. Rather than building dozens of separate skills that each explain architecture from scratch, there’s one foundational layer that encodes the mental model itself — domains, stakeholder analysis, gap analysis, principles, the way an experienced architect actually structures a problem. Every skill inherits from this. The mental model is the engine - &lt;strong&gt;the archtecture thinking core&lt;/strong&gt;; the skills are the gears.&lt;/p&gt;

&lt;p&gt;It covers the full range:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Analysis&lt;/strong&gt; — codebase, architecture, security (OWASP, NIST, NIS2, ISO 27001), nonfunctional requirements, fitness functions&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Architecture&lt;/strong&gt; — the complete TOGAF ADM cycle, C4 modeling&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Development&lt;/strong&gt; — software design, tech stack decisions, code conventions&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Output&lt;/strong&gt; — architecture docs, product specs, ArchiMate, presentations, compliance reports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;27 skills across 4 categories. Pure markdown. Works with any “AI” agent that reads text.&lt;/p&gt;

&lt;p&gt;The research tool, the analysis tool, the creation tool - well, mostly analysis tool, but there is potential (I do use it like this). They’re the same mental model operating at different phases of the work. You research with it, you analyse with it, you create with it. The consistency comes from the engine underneath.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;whats-next&quot;&gt;What’s Next&lt;/h1&gt;

&lt;p&gt;This article is the “why” — the argument for why executable mental models matter and what they change. The interesting stuff is in the how.&lt;/p&gt;

&lt;p&gt;Coming up in this series:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;How the mental model engine actually works — the architecture-thinking layer that makes everything else possible&lt;/li&gt;
  &lt;li&gt;Practical TOGAF through “AI” — what happens when you give an agent the full ADM cycle&lt;/li&gt;
  &lt;li&gt;Security analysis as a thinking framework — not a checklist, a lens&lt;/li&gt;
  &lt;li&gt;How to customize the mental model for your organization&lt;/li&gt;
  &lt;li&gt;The determinism of the result and token economics of teaching an “AI” HOW to “think”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Write things down. Structure the thinking, not just the conclusions. Make it explicit enough that it could be followed.&lt;/p&gt;

&lt;p&gt;That’s been the practice — quantum-toolbox is where it landed.&lt;/p&gt;
</description>
        <pubDate>Sun, 28 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/architecture/ai/2026/06/28/mental-models-as-medium.html</link>
        <guid isPermaLink="true">https://rastko.tech/architecture/ai/2026/06/28/mental-models-as-medium.html</guid>
      </item>
    
      <item>
        <title>Optimizing the Impact of Architects</title>
        <description>&lt;p&gt;There’s an XKCD comic that gets passed around in engineering circles.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/xkcd-dependency.png&quot; alt=&quot;XKCD 2347 — Dependency&quot; /&gt;
&lt;em&gt;&lt;a href=&quot;https://xkcd.com/2347/&quot;&gt;xkcd.com/2347&lt;/a&gt; — CC BY-NC 2.5&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In March 2016, a developer named Azer Koçulu — working out of Oakland, California — unpublished 250 npm packages after a dispute with npm Inc. over a package name. One of those packages was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;left-pad&lt;/code&gt;: eleven lines of JavaScript that padded strings on the left. Within hours, React wouldn’t build. Babel wouldn’t build. Thousands of projects that had never heard of Azer Koçulu, that had never made a conscious decision to depend on him, were broken.&lt;/p&gt;

&lt;p&gt;Nobody designed this. Nobody governed it. The dependency crept in, package by package, until a Turkish developer in California with a legitimate grievance &lt;strong&gt;had more impact on the global software supply chain than any single engineering organization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s the open-source internet, and it operates under its own rules.&lt;/p&gt;

&lt;p&gt;But the same thing happens inside large enterprises very often. Just slower, less dramatic, and without the tweets.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;how-enterprises-are-organized&quot;&gt;How enterprises are organized&lt;/h2&gt;

&lt;p&gt;Medium and large enterprises divide by business domain. Production. Retail. Digital. B2B. HR. Each domain has its own budget, its own leadership, its own roadmap, its own engineers.&lt;/p&gt;

&lt;p&gt;This is correct. I am not saying politically — structurally correct. Conway’s Law is not a suggestion: the systems you build reflect the communication structure of the organization building them. Domain-oriented organizations produce domain-coherent systems. That’s what you want.&lt;/p&gt;

&lt;p&gt;Domain architecture operates across four layers within each domain:&lt;/p&gt;

&lt;svg viewBox=&quot;0 0 480 200&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; style=&quot;max-width:480px;display:block;margin:1.75rem 0;font-family:inherit&quot;&gt;
  &lt;rect x=&quot;80&quot; y=&quot;10&quot; width=&quot;320&quot; height=&quot;40&quot; rx=&quot;3&quot; fill=&quot;#f6f6f6&quot; stroke=&quot;#e2e2e2&quot; /&gt;
  &lt;rect x=&quot;60&quot; y=&quot;58&quot; width=&quot;360&quot; height=&quot;40&quot; rx=&quot;3&quot; fill=&quot;#f6f6f6&quot; stroke=&quot;#e2e2e2&quot; /&gt;
  &lt;rect x=&quot;40&quot; y=&quot;106&quot; width=&quot;400&quot; height=&quot;40&quot; rx=&quot;3&quot; fill=&quot;#f6f6f6&quot; stroke=&quot;#e2e2e2&quot; /&gt;
  &lt;rect x=&quot;20&quot; y=&quot;154&quot; width=&quot;440&quot; height=&quot;40&quot; rx=&quot;3&quot; fill=&quot;#f6f6f6&quot; stroke=&quot;#e2e2e2&quot; /&gt;
  &lt;text x=&quot;240&quot; y=&quot;35&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; fill=&quot;#f8ffb6&quot;&gt;Business&lt;/text&gt;
  &lt;text x=&quot;240&quot; y=&quot;83&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; fill=&quot;#e2bbbb&quot;&gt;Data&lt;/text&gt;
  &lt;text x=&quot;240&quot; y=&quot;131&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; fill=&quot;#95cfff&quot;&gt;Application&lt;/text&gt;
  &lt;text x=&quot;240&quot; y=&quot;179&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; fill=&quot;#ffc3f5&quot;&gt;Technology&lt;/text&gt;
&lt;/svg&gt;

&lt;p&gt;Technology enables applications, applications produce and consume data, data enables business capability. This is well understood, which is a problem since the edges are not smooth.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-no-mans-land&quot;&gt;The no man’s land&lt;/h2&gt;

&lt;p&gt;When you divide into domains, you create boundaries. And boundaries, left unmanaged, become no man’s land.&lt;/p&gt;

&lt;p&gt;No man’s land is what happens when something important doesn’t clearly belong to any single domain — and so nobody owns it.&lt;/p&gt;

&lt;p&gt;In practice it looks like this:&lt;/p&gt;

&lt;p&gt;Too many business domains, and some units fall outside any of them — nobody claimed them, nobody maintains them, and they persist in a state of benign neglect until something breaks.&lt;/p&gt;

&lt;p&gt;A unit gets assigned to the closest domain even though the fit is wrong. It gets the attention of a domain that doesn’t understand it and doesn’t have the right incentives to invest in it.&lt;/p&gt;

&lt;p&gt;Analytical data that crosses domain boundaries has no clear owner. Multiple domains use it; none of them maintains it. Everyone assumes someone else is responsible.&lt;/p&gt;

&lt;p&gt;Tooling that enables a transformation programme lives in one domain, but the programme spans three. When the original sponsor moves on, the tool becomes an orphan — technically alive, practically unsupported.&lt;/p&gt;

&lt;p&gt;Systems get upgraded and modernised within their domains; the integration interfaces between them don’t. No single domain has the mandate or the budget to own the crossing. The interfaces hang in maintenance mode, a thread holding up a wall.&lt;/p&gt;

&lt;p&gt;There’s a version of this I’ve used in presentations: imagine Mufasa showing Simba the kingdom from Pride Rock, the savanna stretching out in every direction. Simba points to a dark patch on the horizon. “Dad, what is that area?” Mufasa doesn’t look. “Son, we don’t go there. That part was created by Steve from accounting.”&lt;/p&gt;

&lt;p&gt;Everyone laughs. Everyone in the room has a Steve from accounting.&lt;/p&gt;

&lt;p&gt;The grey zone problem is organizational, not technical. The thing in the dark patch isn’t broken — it just has no owner, no mandate, no one who sees it as their job to understand it. Domain teams can’t fix this. Each domain is optimizing for its own area by design. Nobody in Production has the incentive, the mandate, or the full picture to govern something that touches Production, Retail, and Finance simultaneously.&lt;/p&gt;

&lt;p&gt;Steve sometimes does, and generally people do not mind, because they dont know what steve does, they jsut knwo thsi is not presenting the problem.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;at-least-one-function-needs-to-transcend-the-boundaries&quot;&gt;At least one function needs to transcend the boundaries&lt;/h2&gt;

&lt;p&gt;This is where architecture comes in — specifically because it is a multidisciplinary function. The BDAT stack is a map of everything a domain team manages internally and everything that falls apart at the seams between them. An architecture function that operates across all four layers — business, data, application, technology — and across all domains is structurally positioned to see what no single domain team can see.&lt;/p&gt;

&lt;p&gt;That’s the job - ensure nothing stays in the grey zone urecognized, and unmanaged. To say: this crosses boundaries, which means it belongs to architecture until it belongs somewhere else. To make the invisible visible, assign ownership, and then get out of the way.&lt;/p&gt;

&lt;p&gt;Domain teams will optimize for their domains. That’s what they’re designed to do, and it’s right that they do it. You can’t ask a Production domain team to take ownership of the integration layer between Production and Retail — that’s not their scope, not their mandate, and not their incentive.&lt;/p&gt;

&lt;p&gt;Someone else has to hold the picture that no single domain can hold. That function is enterprise architecture.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-challenges-of-governance&quot;&gt;The challenges of governance&lt;/h2&gt;

&lt;p&gt;This is where most architecture functions fail.&lt;/p&gt;

&lt;p&gt;Standards that are agreed but not enforced don’t hold. Decision-making authority that isn’t clear doesn’t hold. Architecture reviews that can be bypassed at will don’t hold.&lt;/p&gt;

&lt;p&gt;The challenge: the things you’re governing are moving. Teams ship. Domains grow. New capabilities appear. The governance model has to be firm enough to provide consistency and fast enough not to become a bottleneck.&lt;/p&gt;

&lt;p&gt;Most organizations fail in one of two directions. Governance is so light it doesn’t actually constrain anything — you have principles, not decisions, and everyone nods at them and does what they were going to do anyway. Or it’s so heavy that teams route around it — the process costs more than violating it costs, so violation becomes standard practice.&lt;/p&gt;

&lt;p&gt;Governance needs to be affordable and firm. Can you achieve that?&lt;/p&gt;

&lt;p&gt;The test is simple: can someone get a clear answer to a significant technical proposal from your architecture function before the window for that decision has closed? If the answer is usually no — either because the function doesn’t engage or because it engages too slowly to matter — governance is broken. The direction of the failure tells you how to fix it.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;three-questions&quot;&gt;Three questions&lt;/h2&gt;

&lt;p&gt;Any significant technical initiative eventually needs three questions answered:&lt;/p&gt;

&lt;svg viewBox=&quot;0 0 480 80&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; style=&quot;max-width:480px;display:block;margin:1.75rem 0;font-family:inherit&quot;&gt;
  &lt;rect x=&quot;10&quot; y=&quot;20&quot; width=&quot;130&quot; height=&quot;40&quot; rx=&quot;3&quot; fill=&quot;#f6f6f6&quot; stroke=&quot;#e2e2e2&quot; /&gt;
  &lt;rect x=&quot;175&quot; y=&quot;20&quot; width=&quot;130&quot; height=&quot;40&quot; rx=&quot;3&quot; fill=&quot;#f6f6f6&quot; stroke=&quot;#e2e2e2&quot; /&gt;
  &lt;rect x=&quot;340&quot; y=&quot;20&quot; width=&quot;130&quot; height=&quot;40&quot; rx=&quot;3&quot; fill=&quot;#f6f6f6&quot; stroke=&quot;#e2e2e2&quot; /&gt;
  &lt;text x=&quot;75&quot; y=&quot;45&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; fill=&quot;#1a1a1a&quot;&gt;Can it be done?&lt;/text&gt;
  &lt;text x=&quot;240&quot; y=&quot;45&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; fill=&quot;#1a1a1a&quot;&gt;How will it be done?&lt;/text&gt;
  &lt;text x=&quot;405&quot; y=&quot;45&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; fill=&quot;#1a1a1a&quot;&gt;When will it be done?&lt;/text&gt;
  &lt;line x1=&quot;140&quot; y1=&quot;40&quot; x2=&quot;175&quot; y2=&quot;40&quot; stroke=&quot;#e2e2e2&quot; stroke-width=&quot;1.5&quot; marker-end=&quot;url(#arr)&quot; /&gt;
  &lt;line x1=&quot;305&quot; y1=&quot;40&quot; x2=&quot;340&quot; y2=&quot;40&quot; stroke=&quot;#e2e2e2&quot; stroke-width=&quot;1.5&quot; marker-end=&quot;url(#arr)&quot; /&gt;
  &lt;defs&gt;
    &lt;marker id=&quot;arr&quot; markerWidth=&quot;6&quot; markerHeight=&quot;6&quot; refX=&quot;6&quot; refY=&quot;3&quot; orient=&quot;auto&quot;&gt;
      &lt;path d=&quot;M0,0 L6,3 L0,6 Z&quot; fill=&quot;#767676&quot; /&gt;
    &lt;/marker&gt;
  &lt;/defs&gt;
&lt;/svg&gt;

&lt;p&gt;You can’t design how until you know whether. You can’t commit to when until you know how.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The architecture function’s job is to own the first question and structure the path to the second.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first phase — &lt;strong&gt;business modeling and assessment&lt;/strong&gt; — establishes the what and why, then produces a technical verdict: feasible or not, on what terms, with what constraints. This is where architecture earns its place at the business table. Not by showing up to validate decisions that have already been made, but by engaging early enough to shape them.&lt;/p&gt;

&lt;p&gt;The second phase — the &lt;strong&gt;architecture creation&lt;/strong&gt; — works from data architecture through application architecture to technology architecture, in that order:&lt;/p&gt;

&lt;svg viewBox=&quot;0 0 480 160&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; style=&quot;max-width:480px;display:block;margin:1.75rem 0;font-family:inherit&quot;&gt;
  &lt;rect x=&quot;10&quot; y=&quot;10&quot; width=&quot;140&quot; height=&quot;44&quot; rx=&quot;3&quot; fill=&quot;#f6f6f6&quot; stroke=&quot;#e2e2e2&quot; /&gt;
  &lt;rect x=&quot;170&quot; y=&quot;10&quot; width=&quot;140&quot; height=&quot;44&quot; rx=&quot;3&quot; fill=&quot;#f6f6f6&quot; stroke=&quot;#e2e2e2&quot; /&gt;
  &lt;rect x=&quot;330&quot; y=&quot;10&quot; width=&quot;140&quot; height=&quot;44&quot; rx=&quot;3&quot; fill=&quot;#f6f6f6&quot; stroke=&quot;#e2e2e2&quot; /&gt;
  &lt;text x=&quot;80&quot; y=&quot;30&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#1a1a1a&quot;&gt;Data architecture&lt;/text&gt;
  &lt;text x=&quot;80&quot; y=&quot;46&quot; text-anchor=&quot;middle&quot; font-size=&quot;11&quot; fill=&quot;#767676&quot;&gt;what needs to flow&lt;/text&gt;
  &lt;text x=&quot;240&quot; y=&quot;30&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#1a1a1a&quot;&gt;Application architecture&lt;/text&gt;
  &lt;text x=&quot;240&quot; y=&quot;46&quot; text-anchor=&quot;middle&quot; font-size=&quot;11&quot; fill=&quot;#767676&quot;&gt;what systems carry it&lt;/text&gt;
  &lt;text x=&quot;400&quot; y=&quot;30&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#1a1a1a&quot;&gt;Technology architecture&lt;/text&gt;
  &lt;text x=&quot;400&quot; y=&quot;46&quot; text-anchor=&quot;middle&quot; font-size=&quot;11&quot; fill=&quot;#767676&quot;&gt;what platforms support it&lt;/text&gt;
  &lt;line x1=&quot;150&quot; y1=&quot;32&quot; x2=&quot;170&quot; y2=&quot;32&quot; stroke=&quot;#e2e2e2&quot; stroke-width=&quot;1.5&quot; marker-end=&quot;url(#arr2)&quot; /&gt;
  &lt;line x1=&quot;310&quot; y1=&quot;32&quot; x2=&quot;330&quot; y2=&quot;32&quot; stroke=&quot;#e2e2e2&quot; stroke-width=&quot;1.5&quot; marker-end=&quot;url(#arr2)&quot; /&gt;
  &lt;defs&gt;
    &lt;marker id=&quot;arr2&quot; markerWidth=&quot;6&quot; markerHeight=&quot;6&quot; refX=&quot;6&quot; refY=&quot;3&quot; orient=&quot;auto&quot;&gt;
      &lt;path d=&quot;M0,0 L6,3 L0,6 Z&quot; fill=&quot;#767676&quot; /&gt;
    &lt;/marker&gt;
  &lt;/defs&gt;
  &lt;rect x=&quot;100&quot; y=&quot;100&quot; width=&quot;280&quot; height=&quot;44&quot; rx=&quot;3&quot; fill=&quot;#f6f6f6&quot; stroke=&quot;#e2e2e2&quot; /&gt;
  &lt;text x=&quot;240&quot; y=&quot;120&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#1a1a1a&quot;&gt;Planning → When&lt;/text&gt;
  &lt;text x=&quot;240&quot; y=&quot;136&quot; text-anchor=&quot;middle&quot; font-size=&quot;11&quot; fill=&quot;#767676&quot;&gt;falls out of the architecture, not the other way round&lt;/text&gt;
  &lt;line x1=&quot;240&quot; y1=&quot;54&quot; x2=&quot;240&quot; y2=&quot;100&quot; stroke=&quot;#e2e2e2&quot; stroke-width=&quot;1.5&quot; stroke-dasharray=&quot;4,3&quot; marker-end=&quot;url(#arr2)&quot; /&gt;
&lt;/svg&gt;

&lt;p&gt;The “when” falls out of planning once the architecture decisions exist — not before, and not by someone guessing.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-this-means-for-how-you-set-up-the-function&quot;&gt;What this means for how you set up the function&lt;/h2&gt;

&lt;p&gt;A few things that distinguish architecture functions that have real impact from:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The no man’s land inventory.&lt;/strong&gt; Someone in the architecture function should be able to answer, at any given time: what exists in this organization that isn’t clearly owned by any domain? If nobody has that list, nobody is governing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Upstream, not downstream.&lt;/strong&gt; Architecture that arrives at the end of a project to validate decisions is audit, not governance. The function needs to be in the room when the “can it be done” question is first asked — not when the answer has already been baked into a budget commitment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cross-boundary ownership is explicit.&lt;/strong&gt; Every integration interface, every shared data asset, every cross-domain capability needs a named owner with a named mandate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The three-question model is a forcing function.&lt;/strong&gt; When a business stakeholder asks “when will this be done?” before anyone has established “can it be done?”, the architecture function needs to redirect, not answer the wrong question faster. &lt;strong&gt;Part of the job is training the organization to sequence correctly.&lt;/strong&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Left-pad broke the internet in an afternoon. That was a governance failure at ecosystem scale — nobody owned the dependency graph, so nobody could protect it.&lt;/p&gt;

&lt;p&gt;Enterprise architecture exists to solve the same problem at organizational scale. Not to prevent domains from making their own decisions — that would break the thing that makes domain teams work.&lt;/p&gt;

&lt;p&gt;Job is to ensure that what lives between the domains, at the crossings, in the integration layer, in the shared capabilities that everyone uses and nobody maintains — that those things have owners, have governance, and don’t become your organization’s left-pad moment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The function is not glamorous. The decisions it makes are often invisible even if they prevent a problem that nobody ever knew was coming. That invisibility is the point. The architecture function is working when nothing breaks unexpectedly at the boundaries.&lt;/strong&gt;&lt;/p&gt;
</description>
        <pubDate>Sat, 27 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/architecture/2026/06/27/optimizing-architects.html</link>
        <guid isPermaLink="true">https://rastko.tech/architecture/2026/06/27/optimizing-architects.html</guid>
      </item>
    
      <item>
        <title>The Role of the Architect</title>
        <description>&lt;p&gt;The word “architect” is overloaded to the point of near-meaninglessness.&lt;/p&gt;

&lt;p&gt;In ancient Rome, Vitruvius defined architecture through three principles: &lt;em&gt;firmitas&lt;/em&gt; (strength), &lt;em&gt;utilitas&lt;/em&gt; (usefulness), and &lt;em&gt;venustas&lt;/em&gt; (beauty). A building must be structurally sound, serve its purpose, and be aesthetically pleasing. All three, not any one.&lt;/p&gt;

&lt;p&gt;Software architects, in theory, apply the same thinking: systems must be technically sound, serve business needs, and be elegant (or at least maintainable). The role requires deep technical knowledge combined with broad contextual awareness — business, organisational, operational.&lt;/p&gt;

&lt;p&gt;In practice, the role has been stretched into shapes that bear little resemblance to this.&lt;/p&gt;

&lt;h2 id=&quot;part-1-where-the-term-comes-from&quot;&gt;Part 1: Where the Term Comes From&lt;/h2&gt;

&lt;p&gt;The “software architect” title emerged in the 1990s as software systems grew complex enough to require dedicated people thinking about structure, interfaces, and technical direction beyond what individual teams could do.&lt;/p&gt;

&lt;p&gt;The classic architect role:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Sets technical direction and architectural standards&lt;/li&gt;
  &lt;li&gt;Makes key design decisions with long-term implications&lt;/li&gt;
  &lt;li&gt;Identifies and manages technical risk&lt;/li&gt;
  &lt;li&gt;Connects technical decisions to business outcomes&lt;/li&gt;
  &lt;li&gt;Enables other teams to build well&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This requires a specific and rare combination: deep technical ability, systems thinking, communication skills, and enough organisational awareness to understand what tradeoffs actually matter.&lt;/p&gt;

&lt;p&gt;The problem is that this rare combination is being applied to many roles that don’t actually fit it.&lt;/p&gt;

&lt;h2 id=&quot;part-2-three-case-studies-in-architect-role-misuse&quot;&gt;Part 2: Three Case Studies in Architect Role Misuse&lt;/h2&gt;

&lt;h3 id=&quot;case-study-1-partnering-with-customers&quot;&gt;Case Study 1: “Partnering with Customers”&lt;/h3&gt;

&lt;p&gt;At several large technology vendors (cloud providers, platform companies), the “Solutions Architect” role carries a quota.&lt;/p&gt;

&lt;p&gt;The job is not to design solutions. The job is to convince potential customers to buy the platform. The architect does technical demos, answers RFPs, writes proof-of-concept code, and serves as a trusted technical voice in the sales process.&lt;/p&gt;

&lt;p&gt;This is a sales engineering role. It requires different skills, different incentives, and a different performance model than an architecture role. The person in this role is optimised for closing deals, not for sound technical decision-making.&lt;/p&gt;

&lt;p&gt;Calling it “Solutions Architect” serves the vendor because it sounds technical and trustworthy. But the customer should understand what incentives are driving the advice they receive.&lt;/p&gt;

&lt;p&gt;This isn’t a criticism of the people in these roles — it’s a valuable function. But it’s not architecture. The mislabelling creates confusion.&lt;/p&gt;

&lt;h3 id=&quot;case-study-2-product-owner--business-analyst-creep&quot;&gt;Case Study 2: Product Owner / Business Analyst Creep&lt;/h3&gt;

&lt;p&gt;In many product organisations, the most technically literate Product Owners and Business Analysts get promoted or rebranded into “Solution Architect” roles.&lt;/p&gt;

&lt;p&gt;The pattern goes like this: a PO who can read API docs, attend technical refinement sessions, and write semi-coherent Jira acceptance criteria gets recognised as “technical”. At some point, they’re re-titled.&lt;/p&gt;

&lt;p&gt;The resulting role is essentially a technical PO or senior BA — someone who bridges business requirements and technical implementation. This is genuinely valuable, but it is not architecture.&lt;/p&gt;

&lt;p&gt;Architects in this mould often lack:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Hands-on experience designing systems under real constraints&lt;/li&gt;
  &lt;li&gt;Deep understanding of failure modes and non-functional concerns&lt;/li&gt;
  &lt;li&gt;The authority to say “no, this design is wrong” when the product owner wants something&lt;/li&gt;
  &lt;li&gt;Any experience operating what they design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The resulting “architecture” is often product requirements dressed up in technical language — a Confluence diagram that says “the system will do X” without any serious engagement with how.&lt;/p&gt;

&lt;h3 id=&quot;case-study-3-architect-per-feature-team&quot;&gt;Case Study 3: Architect Per Feature Team&lt;/h3&gt;

&lt;p&gt;In a scaling engineering organisation, there’s pressure to embed architects everywhere. Every feature team gets an architect. Every domain gets a domain architect.&lt;/p&gt;

&lt;p&gt;The problem: the work available to an architect embedded in a feature team is, by definition, feature-team-level work. The team’s architectural concerns are scoped to their service, their API, their database schema.&lt;/p&gt;

&lt;p&gt;This work may be important, but it’s not architecture in the sense of setting direction, managing cross-cutting concerns, or making decisions with long-term systemic implications. It’s detailed technical design — which engineers on the team can and should do.&lt;/p&gt;

&lt;p&gt;Architects embedded in feature teams tend to drift into:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Being a senior engineer who does more design and less coding&lt;/li&gt;
  &lt;li&gt;Being a bottleneck for technical decisions that the team should own&lt;/li&gt;
  &lt;li&gt;Losing visibility of the broader architectural concerns that only they can see&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meanwhile, the org has consumed its architecture capacity on feature-level concerns and has no bandwidth for real architectural work.&lt;/p&gt;

&lt;h2 id=&quot;part-3-why-this-happens&quot;&gt;Part 3: Why This Happens&lt;/h2&gt;

&lt;p&gt;These patterns aren’t random. They emerge from specific pressures:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hypergrowth scaling:&lt;/strong&gt; When a company doubles headcount in 18 months, processes and role definitions can’t keep up. Titles get applied loosely. People get promoted faster than their scope can grow. Architecture is a function that scales poorly — you can’t just double the architect headcount and get double the architectural output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Title inflation:&lt;/strong&gt; “Engineer” sounds less impressive than “Architect” to clients, to candidates, to organisational charts. There’s pressure to upgrade titles even when the scope doesn’t change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Filling gaps:&lt;/strong&gt; When a team lacks a strong technical senior engineer, attaching an “architect” to the team feels like a fix. Often it is — but it’s treating a symptom (weak team capability) rather than the cause.&lt;/p&gt;

&lt;h2 id=&quot;what-actually-scales&quot;&gt;What Actually Scales&lt;/h2&gt;

&lt;p&gt;Architecture capacity doesn’t scale linearly with headcount. You probably need fewer architects than you think.&lt;/p&gt;

&lt;p&gt;What you do need:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Architects with genuine scope — cross-cutting concerns, platform decisions, long-horizon thinking&lt;/li&gt;
  &lt;li&gt;Engineers who can do local technical design well (don’t call them architects, train them as engineers)&lt;/li&gt;
  &lt;li&gt;Clear interfaces between architectural decisions (set by architects) and implementation decisions (owned by teams)&lt;/li&gt;
  &lt;li&gt;An architecture function that’s connected to both technical reality and business strategy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The firms that do this well tend to have senior architects operating across multiple teams, setting direction, and deliberately transferring knowledge and decision-making authority to engineering teams as they mature. The architect’s job is to work themselves out of the loop on decisions that teams can handle — and to focus on the decisions that genuinely require their scope.&lt;/p&gt;

&lt;p&gt;That’s a harder job than being embedded in a feature team. It’s less visible on a short timescale. But it’s the job.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;Written from experience as an Engineering and Architecture leadership consultant. The patterns described are composites of situations I’ve observed across multiple large organisations; no single organisation is described here.&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 18 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/software/architecture/organisation/role/enterprise/tech/2022/10/18/architect-role-overloaded.html</link>
        <guid isPermaLink="true">https://rastko.tech/software/architecture/organisation/role/enterprise/tech/2022/10/18/architect-role-overloaded.html</guid>
      </item>
    
      <item>
        <title>Dynamic configuration management and circuit breakers in Kubernetes</title>
        <description>&lt;p&gt;Feature flags and circuit breakers sound straightforward. In a single-server application, they are. In a distributed system running across multiple Kubernetes clusters in multiple regions, the problem of &lt;em&gt;how do you get a configuration change to all pods simultaneously&lt;/em&gt; becomes non-trivial.&lt;/p&gt;

&lt;p&gt;This post presents an architecture for dynamic configuration management and circuit breakers in Kubernetes that has run in production on business-critical, high-scale systems.&lt;/p&gt;

&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;

&lt;p&gt;You have microservices deployed across multiple Kubernetes clusters — say, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eu-west&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-east&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-southeast&lt;/code&gt;. Each cluster has multiple pods of each service.&lt;/p&gt;

&lt;p&gt;You need to:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Flip a feature flag for all pods in all clusters simultaneously&lt;/li&gt;
  &lt;li&gt;Trip a circuit breaker when a downstream integration starts failing&lt;/li&gt;
  &lt;li&gt;Restore the circuit breaker when the integration recovers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can’t just update a database record and have all pods pick it up — there’s no shared state between clusters. You can’t use Kubernetes ConfigMaps as the source of truth — they’re per-cluster, and there’s no built-in sync mechanism.&lt;/p&gt;

&lt;p&gt;You need a proper distributed configuration architecture.&lt;/p&gt;

&lt;h2 id=&quot;the-architecture&quot;&gt;The Architecture&lt;/h2&gt;

&lt;p&gt;The solution has three layers:&lt;/p&gt;

&lt;h3 id=&quot;layer-1-central-config-api--storage&quot;&gt;Layer 1: Central Config API + Storage&lt;/h3&gt;

&lt;p&gt;A single, globally accessible Config API (REST) backed by persistent storage (PostgreSQL or similar). This is the &lt;strong&gt;single source of truth&lt;/strong&gt; for all configuration.&lt;/p&gt;

&lt;p&gt;Key operations:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET /config/{service}/{environment}&lt;/code&gt; — read current config&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUT /config/{service}/{environment}&lt;/code&gt; — update config&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET /config/history/{service}/{environment}&lt;/code&gt; — audit log&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Config API is your control plane. Operators interact with it (directly or via a UI) to change flags and configuration.&lt;/p&gt;

&lt;h3 id=&quot;layer-2-consul-kv-store-per-cluster&quot;&gt;Layer 2: Consul KV Store Per Cluster&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://www.consul.io/&quot;&gt;Consul&lt;/a&gt; provides a distributed key-value store with watch/notify capabilities. Deploy a Consul cluster per Kubernetes namespace (or per cluster).&lt;/p&gt;

&lt;p&gt;Consul is the &lt;strong&gt;local config cache&lt;/strong&gt; for each cluster. Pods watch Consul for changes rather than polling the central API. This gives:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Low latency config propagation (sub-second when a key changes)&lt;/li&gt;
  &lt;li&gt;Resilience — if the central API is unavailable, pods continue with last-known config&lt;/li&gt;
  &lt;li&gt;No direct coupling between pods and the central API&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;layer-3-config-service-reconciler&quot;&gt;Layer 3: Config Service (Reconciler)&lt;/h3&gt;

&lt;p&gt;A Config Service (a microservice or CronJob) runs in each cluster and reconciles config from the central storage into the local Consul:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Central Config API → Config Service → Consul KV Store → Pods
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The Config Service:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Polls the central Config API on a regular interval (e.g., every 30 seconds)&lt;/li&gt;
  &lt;li&gt;Compares the remote config with what’s currently in Consul&lt;/li&gt;
  &lt;li&gt;Pushes changes to Consul&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For time-sensitive changes (circuit breaker trips), the interval can be reduced or the Config API can push to the Config Service via webhook.&lt;/p&gt;

&lt;h2 id=&quot;how-pods-consume-config&quot;&gt;How Pods Consume Config&lt;/h2&gt;

&lt;p&gt;Pods watch the Consul KV Store for changes to their config key. When the key changes, they update their in-memory config without restarting.&lt;/p&gt;

&lt;p&gt;Most languages have Consul client libraries that support this pattern:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;consul&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;consul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Consul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;consul.production.svc.cluster.local&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Watch for changes
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;config/sensor-api/production&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;5m&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Value&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When Consul notifies the pod of a change, the pod reloads config immediately.&lt;/p&gt;

&lt;h2 id=&quot;circuit-breaker-integration&quot;&gt;Circuit Breaker Integration&lt;/h2&gt;

&lt;p&gt;Here’s where it gets interesting. The circuit breaker is driven by &lt;strong&gt;Prometheus alerts&lt;/strong&gt; rather than in-service logic.&lt;/p&gt;

&lt;p&gt;The flow:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Prometheus detects that a downstream integration is degraded (error rate &amp;gt; threshold, latency &amp;gt; threshold)&lt;/li&gt;
  &lt;li&gt;Prometheus fires an alert to Alertmanager&lt;/li&gt;
  &lt;li&gt;Alertmanager routes the alert to a webhook endpoint on the Config API&lt;/li&gt;
  &lt;li&gt;The Config API automatically flips the circuit breaker flag for the affected service&lt;/li&gt;
  &lt;li&gt;The Config Service propagates the change to all clusters’ Consul stores&lt;/li&gt;
  &lt;li&gt;All pods pick up the change within seconds&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Prometheus alert rule&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;groups&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;circuit-breakers&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;PaymentServiceDegraded&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;rate(http_requests_total{service=&quot;payment-service&quot;,status=~&quot;5..&quot;}[5m])&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;/ rate(http_requests_total{service=&quot;payment-service&quot;}[5m]) &amp;gt; 0.1&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;2m&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;annotations&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;circuit_breaker_target&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;payment-service-integration&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;circuit_breaker_action&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;open&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The alertmanager webhook configuration:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;receivers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;circuit-breaker-webhook&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;webhook_configs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://config-api.internal/circuit-breaker/trigger&apos;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;send_resolved&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When the alert resolves (the integration recovers), Alertmanager fires the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;send_resolved&lt;/code&gt; webhook, which closes the circuit breaker automatically.&lt;/p&gt;

&lt;p&gt;This is a &lt;strong&gt;metrics-driven, automated circuit breaker&lt;/strong&gt; — the system heals itself without human intervention.&lt;/p&gt;

&lt;h2 id=&quot;resilience-design&quot;&gt;Resilience Design&lt;/h2&gt;

&lt;p&gt;A few important resilience decisions in this architecture:&lt;/p&gt;

&lt;h3 id=&quot;full-config-objects-not-patches&quot;&gt;Full Config Objects, Not Patches&lt;/h3&gt;

&lt;p&gt;When the Config Service pushes to Consul, it always pushes the &lt;strong&gt;full config object&lt;/strong&gt; for a service, not a partial update or patch.&lt;/p&gt;

&lt;p&gt;Why: partial updates can leave a service in an inconsistent state if there’s a failure mid-update. Full object pushes are idempotent — if the same object is pushed twice, the result is the same.&lt;/p&gt;

&lt;h3 id=&quot;sensible-defaults&quot;&gt;Sensible Defaults&lt;/h3&gt;

&lt;p&gt;Every service must define sensible defaults for all config values. If Consul is unavailable at startup, the service starts with defaults. If a config value is missing from Consul, the service uses the default.&lt;/p&gt;

&lt;p&gt;Never let a missing config cause a startup failure.&lt;/p&gt;

&lt;h3 id=&quot;defaults-as-deployed-config&quot;&gt;Defaults as Deployed Config&lt;/h3&gt;

&lt;p&gt;The Consul config for a service in a fresh cluster starts as the deployed defaults (the same values the service uses if Consul is unavailable). This ensures a new cluster is immediately operational without a config sync cycle.&lt;/p&gt;

&lt;h3 id=&quot;no-partial-config-updates&quot;&gt;No Partial Config Updates&lt;/h3&gt;

&lt;p&gt;The Config API validates the full config object before accepting a write. You can’t write half a config. The schema is versioned, and the API rejects configs that don’t match the current schema.&lt;/p&gt;

&lt;h2 id=&quot;when-to-use-this-architecture&quot;&gt;When to Use This Architecture&lt;/h2&gt;

&lt;p&gt;This is a relatively complex system. It’s appropriate when you have:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Multiple Kubernetes clusters (multi-region or multi-environment)&lt;/li&gt;
  &lt;li&gt;Services that need sub-second config propagation&lt;/li&gt;
  &lt;li&gt;Circuit breakers that need to trip automatically based on metrics&lt;/li&gt;
  &lt;li&gt;Strict audit requirements for config changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For single-cluster deployments or simpler requirements, Kubernetes ConfigMaps with a restart-or-reload mechanism may be sufficient.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Operator / Prometheus Alert
          ↓
    Config API (REST) + Storage
          ↓ (via Config Service / reconciler)
    Consul KV Store (per cluster)
          ↓ (watch/notify)
    Pod in-memory config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The key properties:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Single source of truth (central Config API)&lt;/li&gt;
  &lt;li&gt;Low-latency propagation (Consul watches)&lt;/li&gt;
  &lt;li&gt;Resilience (Consul as local cache; sensible defaults)&lt;/li&gt;
  &lt;li&gt;Automated circuit breaking (Prometheus → Alertmanager → Config API → Consul)&lt;/li&gt;
  &lt;li&gt;Auditability (all changes logged in Config API)&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 27 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/devops/sre/circuit-breaker/automation/blueprints/cloud/kubernetes/architecture/2021/04/27/kubernetes-cloud-native-circuit-breaker.html</link>
        <guid isPermaLink="true">https://rastko.tech/devops/sre/circuit-breaker/automation/blueprints/cloud/kubernetes/architecture/2021/04/27/kubernetes-cloud-native-circuit-breaker.html</guid>
      </item>
    
      <item>
        <title>The 7 (and a half) tools to assist you on your DevOps journey</title>
        <description>&lt;p&gt;This post is a catalog. Not a deep dive into any single tool, but a map of the tools and concepts that meaningfully increase DevOps maturity. Think of it as a checklist you can work through incrementally.&lt;/p&gt;

&lt;p&gt;Seven tools, one half-tool. Let’s go.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;1-chatops&quot;&gt;1. ChatOps&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; Bringing CI/CD control into your team’s chat platform (Slack, Teams, etc.).&lt;/p&gt;

&lt;p&gt;Instead of logging into dashboards, you interact with your deployment pipeline via chat commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/deploy sensor-api v1.4.2 to production
&amp;gt; Deploying sensor-api v1.4.2 to production...
&amp;gt; ✅ Deployment complete. sensor-api v1.4.2 running in production.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Full team visibility into deployments without context-switching to dashboards&lt;/li&gt;
  &lt;li&gt;Chat serves as audit log (who deployed what, when)&lt;/li&gt;
  &lt;li&gt;Low-friction operations reduce deployment anxiety and encourage more frequent deploys&lt;/li&gt;
  &lt;li&gt;Incident response is faster when everyone can see what’s happening&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How to implement:&lt;/strong&gt; Hubot (GitHub), Lita, or custom Slack bots integrated with your CI/CD platform (Jenkins, CircleCI, GitHub Actions, etc.).&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-feature-flags&quot;&gt;2. Feature Flags&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; Conditional code paths controlled by runtime configuration, not deployments.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;feature_flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;new-sensor-processing-algo&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new_algorithm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;legacy_algorithm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt;
Feature flags decouple &lt;strong&gt;code deployment&lt;/strong&gt; from &lt;strong&gt;feature release&lt;/strong&gt;. You can:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Deploy code to production before turning the feature on&lt;/li&gt;
  &lt;li&gt;Release to a subset of users first (percentage rollout, specific regions, specific users)&lt;/li&gt;
  &lt;li&gt;Turn off a feature instantly if it causes problems — no rollback needed&lt;/li&gt;
  &lt;li&gt;Run A/B tests without redeploying&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Dimensions to flag on:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Environment (dev / staging / production)&lt;/li&gt;
  &lt;li&gt;User cohort (beta users, internal users, paying users)&lt;/li&gt;
  &lt;li&gt;Region or data center&lt;/li&gt;
  &lt;li&gt;Percentage of traffic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tools:&lt;/strong&gt; LaunchDarkly, Unleash (open source), Flagsmith, or a simple database-backed config service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall:&lt;/strong&gt; Feature flags accumulate technical debt. Have a process for cleaning up flags after features are fully released.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;3-circuit-breaker&quot;&gt;3. Circuit Breaker&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; An automatic switch that disconnects a failing integration to prevent cascading failures.&lt;/p&gt;

&lt;p&gt;Inspired by electrical circuit breakers. Three states:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Closed&lt;/strong&gt; — normal operation, requests flow through&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Open&lt;/strong&gt; — integration is failing, requests are blocked immediately (fail fast, no waiting for timeout)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Half-open&lt;/strong&gt; — probe state, allow some requests through to check if the integration recovered&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt;
In distributed systems, slow or failing dependencies can exhaust your thread pools and connection pools, causing your service to fail even for unrelated requests. Circuit breakers contain the blast radius.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt;
The circuit breaker watches metrics (error rate, latency) and trips when thresholds are exceeded. In our Kubernetes system, we can drive this via Prometheus alerts → webhook → config service (covered in the next post).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Libraries:&lt;/strong&gt; Resilience4j (Java), Polly (.NET), Hystrix (Netflix, now maintenance mode).&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;4-canary-and-shadow-prod-releases&quot;&gt;4. Canary and Shadow-Prod Releases&lt;/h2&gt;

&lt;h3 id=&quot;canary-releases&quot;&gt;Canary Releases&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; Route a small percentage of production traffic to a new version before rolling it out fully.&lt;/p&gt;

&lt;p&gt;With Kubernetes and nginx ingress:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;annotations&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;nginx.ingress.kubernetes.io/canary&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;nginx.ingress.kubernetes.io/canary-weight&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;10&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This routes 10% of traffic to the canary version, 90% to stable. Monitor the canary for errors, latency, and business metrics. If it looks good, increase the weight gradually. If it looks bad, remove the canary with zero user impact.&lt;/p&gt;

&lt;h3 id=&quot;shadow-production-testing&quot;&gt;Shadow Production Testing&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; Mirror production traffic to a new version without affecting the response the user receives.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;User request → stable version → user response
             ↓ (mirrored)
           new version → response discarded
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The new version processes the same real traffic but its responses are thrown away. You can compare responses to check for regressions.&lt;/p&gt;

&lt;p&gt;This is powerful for validating algorithm changes or significant refactors before they see production traffic.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;5-rollback&quot;&gt;5. Rollback&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; The ability to revert to the previous version of a service instantly.&lt;/p&gt;

&lt;p&gt;In Kubernetes, a rollback is as simple as:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl rollout undo deployment/sensor-api
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or more precisely, deploy the previous known-good image:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;image deployment/sensor-api sensor-api&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;sensor-api:git-sha-of-previous-version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt;
Rollback is your last line of defence. When everything else fails — canary didn’t catch it, feature flag can’t fix it — you need to be able to revert to the previous version in under 2 minutes.&lt;/p&gt;

&lt;p&gt;Make sure rollback is:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Practiced regularly (add it to your runbooks and fire drills)&lt;/li&gt;
  &lt;li&gt;Automated where possible (GitOps systems like ArgoCD make this trivial)&lt;/li&gt;
  &lt;li&gt;Not blocked by database migrations (design migrations to be backward-compatible)&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;6-seeds-project-bootstrap-templates&quot;&gt;6. Seeds (Project Bootstrap Templates)&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; Opinionated project templates that come pre-wired with all the standard tooling.&lt;/p&gt;

&lt;p&gt;Starting a new microservice from scratch takes days of setup: CI/CD configuration, Dockerfile, Kubernetes manifests, observability libraries, code structure, testing setup. Seeds compress this to minutes.&lt;/p&gt;

&lt;p&gt;Three types of seeds:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Microservice seed:&lt;/strong&gt; A template repository for each language/framework you use. Contains:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Dockerfile and .dockerignore&lt;/li&gt;
  &lt;li&gt;Kubernetes manifests (Deployment, Service, HPA, NetworkPolicy)&lt;/li&gt;
  &lt;li&gt;CI/CD pipeline configuration&lt;/li&gt;
  &lt;li&gt;Health check endpoint&lt;/li&gt;
  &lt;li&gt;Observability hooks (metrics, structured logging, tracing)&lt;/li&gt;
  &lt;li&gt;Testing scaffolding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;CICD seed:&lt;/strong&gt; A template for the CI/CD pipeline itself. Standardises pipeline stages across all services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloud bootstrap seed:&lt;/strong&gt; Terraform modules for spinning up standard infrastructure components (VPC, EKS cluster, RDS, S3, etc.) with sensible defaults and security baseline.&lt;/p&gt;

&lt;p&gt;New projects instantiate from these seeds. The result: every service starts life with good practices already in place, rather than accumulating them (or not) over time.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;65-shared-libraries-the-half-tool&quot;&gt;6.5. Shared Libraries (the half tool)&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; Internal libraries that encapsulate cross-cutting concerns — HTTP clients, logging, instrumentation, feature flag clients, etc.&lt;/p&gt;

&lt;p&gt;This is the half-tool because it’s not a standalone thing — it’s the companion to seeds. Seeds include these libraries by default.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to put in shared libraries:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;HTTP client with retry logic, circuit breaker, tracing headers&lt;/li&gt;
  &lt;li&gt;Structured logging (JSON, with standard fields)&lt;/li&gt;
  &lt;li&gt;Metrics instrumentation (counter, histogram, gauge)&lt;/li&gt;
  &lt;li&gt;Feature flag client&lt;/li&gt;
  &lt;li&gt;Health check endpoint implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt;
Without shared libraries, each team implements these things differently (or not at all). With shared libraries, the standard becomes the path of least resistance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall:&lt;/strong&gt; Shared libraries can become a bottleneck. Keep them small and well-maintained. Versioning is critical — don’t break all services by pushing a breaking change to a library they all depend on.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;7-devops-checklist&quot;&gt;7. DevOps Checklist&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; A crystallised list of the essential DevOps capabilities — a tool for assessing maturity and driving improvement.&lt;/p&gt;

&lt;p&gt;The adidas engineering organisation open-sourced their &lt;a href=&quot;https://github.com/adidas/adidas-devops-maturity-framework&quot;&gt;DevOps maturity framework&lt;/a&gt;. It covers:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Source control&lt;/strong&gt; — branching strategy, commit hygiene&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;CI/CD&lt;/strong&gt; — pipeline automation, quality gates, deployment frequency&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Testing&lt;/strong&gt; — coverage, test pyramid, integration testing&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Observability&lt;/strong&gt; — metrics, logging, alerting, SLOs&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt; — SAST, image scanning, RBAC, secrets management&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Reliability&lt;/strong&gt; — SLOs, incident response, runbooks, chaos engineering&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt; — architecture docs, runbooks, onboarding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use a checklist like this in two ways:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Assessment&lt;/strong&gt; — where is your team on each dimension today?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Roadmap&lt;/strong&gt; — which gaps are most important to close first?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The checklist doesn’t tell you &lt;em&gt;how&lt;/em&gt; to improve — that’s what the blueprints are for. But it tells you &lt;em&gt;where&lt;/em&gt; to look.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;These seven-and-a-half tools don’t need to be implemented all at once. Pick the ones with the highest leverage for your current situation, implement them well, then move to the next.&lt;/p&gt;

&lt;p&gt;The compound effect over 12-18 months is significant.&lt;/p&gt;
</description>
        <pubDate>Sat, 10 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/devops/automation/cicd/blueprints/cloud/kubernetes/architecture/sre/2021/04/10/tools-concepts-that-make-devops-flow.html</link>
        <guid isPermaLink="true">https://rastko.tech/devops/automation/cicd/blueprints/cloud/kubernetes/architecture/sre/2021/04/10/tools-concepts-that-make-devops-flow.html</guid>
      </item>
    
      <item>
        <title>Cloud Native CICD</title>
        <description>&lt;p&gt;If there’s one capability that separates high-performing engineering organisations from struggling ones, it’s software delivery. Not talent, not tooling, not architecture — delivery.&lt;/p&gt;

&lt;p&gt;Continuous integration and continuous delivery (CI/CD) is the engineering practice that makes frequent, safe delivery possible. This post builds the CI/CD blueprint for cloud-native systems.&lt;/p&gt;

&lt;h2 id=&quot;why-frequent-small-releases-win&quot;&gt;Why Frequent Small Releases Win&lt;/h2&gt;

&lt;p&gt;The research in &lt;em&gt;Accelerate&lt;/em&gt; (Forsgren, Humble, Kim) is unambiguous: high-performing teams deploy more frequently and have lower change failure rates than low-performing teams. These aren’t trade-offs — more frequent deployment is correlated with &lt;em&gt;better&lt;/em&gt; stability.&lt;/p&gt;

&lt;p&gt;The intuition: a deployment of 10 small changes is less risky than a deployment of 100 changes. Each small change is easier to understand, easier to review, easier to roll back if something goes wrong.&lt;/p&gt;

&lt;p&gt;Big bang releases are a risk accumulation strategy. Avoid them.&lt;/p&gt;

&lt;h2 id=&quot;cloud-native-in-eight-elements&quot;&gt;Cloud-Native in Eight Elements&lt;/h2&gt;

&lt;p&gt;Before getting into the pipeline, it’s worth stating what “cloud-native” means from a delivery perspective. Four central ideas:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Containerisation&lt;/strong&gt; — every workload is a container&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Orchestration&lt;/strong&gt; — Kubernetes manages the containers&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DevOps&lt;/strong&gt; — shared ownership of the full SDLC&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Continuous delivery&lt;/strong&gt; — software is always in a deployable state&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And eight elements that make it real:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Immutable infrastructure&lt;/li&gt;
  &lt;li&gt;Declarative configuration&lt;/li&gt;
  &lt;li&gt;Microservices&lt;/li&gt;
  &lt;li&gt;Dynamic scheduling&lt;/li&gt;
  &lt;li&gt;Automated delivery pipelines&lt;/li&gt;
  &lt;li&gt;Observability&lt;/li&gt;
  &lt;li&gt;Self-healing&lt;/li&gt;
  &lt;li&gt;Policy-as-code&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;scm-as-sdlc-tempo-driver&quot;&gt;SCM as SDLC Tempo Driver&lt;/h2&gt;

&lt;p&gt;Source control management (Git) is the heartbeat of the SDLC. Every significant step — feature start, code review, quality gate, deployment — should be triggered by a Git event.&lt;/p&gt;

&lt;p&gt;We use &lt;strong&gt;GitHub Flow&lt;/strong&gt; as the branching strategy:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; is always deployable&lt;/li&gt;
  &lt;li&gt;Feature work happens on short-lived branches (hours to days, not weeks)&lt;/li&gt;
  &lt;li&gt;PRs are the unit of review and the trigger for quality gates&lt;/li&gt;
  &lt;li&gt;Merge to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; triggers deployment to dev; tagged releases trigger staging/production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub Flow is simple and it forces small, frequent merges. Long-lived feature branches are a smell — they mean large, risky merges.&lt;/p&gt;

&lt;h2 id=&quot;the-containerisation-pipeline&quot;&gt;The Containerisation Pipeline&lt;/h2&gt;

&lt;p&gt;Every service gets built into a container image in CI:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git push → CI trigger → build container image → tag with git SHA → push to registry
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Key principles:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Build once&lt;/strong&gt; — the same image that passes tests gets deployed to every environment&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tag with git SHA&lt;/strong&gt; — gives you exact traceability from production back to the commit&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Never use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latest&lt;/code&gt;&lt;/strong&gt; — in production, always pin to a specific image SHA or version tag&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;dev-environment-per-branch&quot;&gt;Dev Environment Per Branch&lt;/h2&gt;

&lt;p&gt;One of the most powerful patterns in cloud-native CI/CD: &lt;strong&gt;a full development environment per branch&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With Kubernetes, it’s feasible to spin up a complete stack for every feature branch:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;feature-branch → CI → build image → deploy to dev/feature-xyz namespace → accessible at feature-xyz.dev.yourdomain.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This gives developers and reviewers a live, isolated environment to test against before merging. It eliminates the “works on my machine” problem and makes PR review much more effective.&lt;/p&gt;

&lt;p&gt;The namespace is torn down when the branch is deleted.&lt;/p&gt;

&lt;h2 id=&quot;quality-gates-on-prs&quot;&gt;Quality Gates on PRs&lt;/h2&gt;

&lt;p&gt;Before any code can merge to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;, it must pass a set of automated quality gates:&lt;/p&gt;

&lt;h3 id=&quot;1-unit-tests&quot;&gt;1. Unit Tests&lt;/h3&gt;

&lt;p&gt;Fast, isolated tests of individual components. Must pass with high coverage. Target: under 5 minutes.&lt;/p&gt;

&lt;h3 id=&quot;2-integration-tests&quot;&gt;2. Integration Tests&lt;/h3&gt;

&lt;p&gt;Tests that exercise the service against real (or realistic) dependencies. Slower, but catch integration bugs that unit tests can’t.&lt;/p&gt;

&lt;h3 id=&quot;3-static-security-scan-sast&quot;&gt;3. Static Security Scan (SAST)&lt;/h3&gt;

&lt;p&gt;Automated scanning for security vulnerabilities in code and dependencies. Fail the build on critical findings.&lt;/p&gt;

&lt;h3 id=&quot;4-code-quality-scan&quot;&gt;4. Code Quality Scan&lt;/h3&gt;

&lt;p&gt;Linting, static analysis, code smell detection. Sonarqube, CodeClimate, or similar.&lt;/p&gt;

&lt;h3 id=&quot;5-peer-review&quot;&gt;5. Peer Review&lt;/h3&gt;

&lt;p&gt;At minimum one human review of every change. Security-sensitive changes require a security-aware reviewer.&lt;/p&gt;

&lt;p&gt;All five gates are required. A merge that skips any of them is a risk that will eventually manifest as a production incident.&lt;/p&gt;

&lt;h2 id=&quot;build-once-promote-everywhere&quot;&gt;Build Once, Promote Everywhere&lt;/h2&gt;

&lt;p&gt;The golden rule of CI/CD: &lt;strong&gt;the same artifact that was tested is the artifact that runs in production&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Do not rebuild images between environments. Rebuilding introduces the possibility of differences — different dependency versions, different build environment state, different code if something was wrong with the first build.&lt;/p&gt;

&lt;p&gt;The promotion pipeline looks like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;commit → build image (tag: git SHA) → push to registry
                                              ↓
                                    deploy to dev (automatic on merge)
                                              ↓
                                    automated test suite in dev
                                              ↓
                                    promote same image to staging (manual or automatic)
                                              ↓
                                    acceptance tests in staging
                                              ↓
                                    promote same image to production (manual approval)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The image SHA is what gets promoted. The environments are different; the artifact is not.&lt;/p&gt;

&lt;h2 id=&quot;chatops&quot;&gt;ChatOps&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ChatOps&lt;/strong&gt; brings your deployment pipeline into your team’s communication tool (Slack, Teams, etc.).&lt;/p&gt;

&lt;p&gt;Instead of logging into a CI dashboard to trigger or check deployments, you interact via chat commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/deploy sensor-api v1.4.2 to staging
/rollback sensor-api in production
/status sensor-api
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The bot executes the commands, reports back, and logs everything in the channel. This gives the whole team visibility into what’s being deployed and when, without anyone needing to context-switch to a separate tool.&lt;/p&gt;

&lt;p&gt;ChatOps also serves as an audit log: every deployment, every rollback, is recorded in the chat channel with a timestamp and the person who triggered it.&lt;/p&gt;

&lt;h2 id=&quot;infrastructure-as-code&quot;&gt;Infrastructure as Code&lt;/h2&gt;

&lt;p&gt;The Kubernetes manifests, Helm charts, Terraform configurations — all of this is code, and it lives in Git.&lt;/p&gt;

&lt;p&gt;Changes to infrastructure go through the same review and quality gate process as application code. Separate repositories for app code and infrastructure config (GitOps pattern) is common and works well.&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;ArgoCD&lt;/strong&gt; or &lt;strong&gt;Flux&lt;/strong&gt; to apply infrastructure changes from Git automatically (GitOps). The cluster state is always reconciled with what’s in Git.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;A complete cloud-native CI/CD pipeline:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Developer pushes to feature branch&lt;/li&gt;
  &lt;li&gt;CI builds image, runs unit tests&lt;/li&gt;
  &lt;li&gt;Dev environment deployed from branch&lt;/li&gt;
  &lt;li&gt;PR raised → quality gates run (unit, integration, security scan, code quality)&lt;/li&gt;
  &lt;li&gt;PR reviewed and approved&lt;/li&gt;
  &lt;li&gt;Merge to main → automatic deploy to dev&lt;/li&gt;
  &lt;li&gt;Automated tests run in dev&lt;/li&gt;
  &lt;li&gt;Manual promotion to staging → acceptance tests&lt;/li&gt;
  &lt;li&gt;Manual approval → promote to production&lt;/li&gt;
  &lt;li&gt;ChatOps notification to team&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal is a pipeline where deploying to production is boring. Boring is good.&lt;/p&gt;
</description>
        <pubDate>Mon, 05 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/cicd/blueprints/cloud/kubernetes/architecture/2021/04/05/cicd-cloud-native-software-delivery.html</link>
        <guid isPermaLink="true">https://rastko.tech/cicd/blueprints/cloud/kubernetes/architecture/2021/04/05/cicd-cloud-native-software-delivery.html</guid>
      </item>
    
      <item>
        <title>The Kubernetes and cloud software security blueprint</title>
        <description>&lt;p&gt;Security is rarely the most exciting topic in software engineering, but it’s one of the most consequential. This post builds the security blueprint for our IoT case study — covering network security, secrets management, RBAC, and secure container configuration.&lt;/p&gt;

&lt;p&gt;The core principle throughout: &lt;strong&gt;security should be a first-class architectural concern, not a retrofit&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;network-segmentation-protect-your-databases&quot;&gt;Network Segmentation: Protect Your Databases&lt;/h2&gt;

&lt;p&gt;The first and most important network security decision: &lt;strong&gt;your databases should never be directly reachable from the internet&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In cloud infrastructure, this means:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Databases deployed in private subnets (no public IP, no internet gateway route)&lt;/li&gt;
  &lt;li&gt;Only the application layer (in the private subnet or VPC) can reach the database&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;VPC peering&lt;/strong&gt; used to connect application VPC to data VPC when they’re separate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Kubernetes specifically, this means pods that need to talk to a database get that access via a Service (or ExternalName/Endpoints), but the database itself is isolated at the network level.&lt;/p&gt;

&lt;h2 id=&quot;kubernetes-network-policies&quot;&gt;Kubernetes Network Policies&lt;/h2&gt;

&lt;p&gt;By default, all pods in a Kubernetes cluster can talk to all other pods. This is not what you want in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NetworkPolicies&lt;/strong&gt; let you define ingress and egress rules at the pod level:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;NetworkPolicy&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api-netpol&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;production&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;podSelector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;matchLabels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;policyTypes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Ingress&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Egress&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;ingress&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;podSelector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;matchLabels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ingress-controller&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TCP&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8080&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;egress&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;podSelector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;matchLabels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;kafka&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TCP&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;9092&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;namespaceSelector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;matchLabels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;kube-system&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;UDP&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;53&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# DNS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Start with a &lt;strong&gt;deny-all&lt;/strong&gt; base policy per namespace, then add explicit allow rules. This way, any new service that gets deployed is isolated by default until you explicitly open what it needs.&lt;/p&gt;

&lt;p&gt;Note: NetworkPolicies require a CNI plugin that supports them (Calico, Cilium, Weave Net). The default Kubernetes networking doesn’t enforce them.&lt;/p&gt;

&lt;h2 id=&quot;ddos-protection&quot;&gt;DDoS Protection&lt;/h2&gt;

&lt;p&gt;For a public-facing system, you need DDoS protection at multiple layers:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Cloud-level DDoS protection&lt;/strong&gt; — AWS Shield, GCP Cloud Armor, Azure DDoS Protection. These handle volumetric attacks at the network edge before traffic reaches your infrastructure.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;CDN-based protection&lt;/strong&gt; — Cloudflare, Fastly, or your cloud CDN. The CDN absorbs traffic spikes and can block malicious traffic patterns.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Ingress rate limiting&lt;/strong&gt; — Nginx Ingress supports rate limiting annotations:&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;nginx.ingress.kubernetes.io/limit-rps&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;100&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;nginx.ingress.kubernetes.io/limit-connections&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;10&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;API Gateway throttling&lt;/strong&gt; — for your web/mobile APIs, configure per-client rate limits at the API Gateway level.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Layer these protections. No single layer is sufficient.&lt;/p&gt;

&lt;h2 id=&quot;waf-web-application-firewall&quot;&gt;WAF (Web Application Firewall)&lt;/h2&gt;

&lt;p&gt;For the frontend APIs, a WAF provides protection against:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;SQL injection&lt;/li&gt;
  &lt;li&gt;XSS attacks&lt;/li&gt;
  &lt;li&gt;OWASP Top 10 vulnerabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AWS WAF, Cloudflare WAF, or ModSecurity integrated into your Ingress controller are common options. Configure rules appropriate for your API payload shapes.&lt;/p&gt;

&lt;h2 id=&quot;secrets-management&quot;&gt;Secrets Management&lt;/h2&gt;

&lt;p&gt;As mentioned in the infrastructure blueprint, Kubernetes Secrets are base64-encoded, not encrypted by default. In production, you need a proper secrets management approach.&lt;/p&gt;

&lt;h3 id=&quot;option-1-encrypted-etcd--kms&quot;&gt;Option 1: Encrypted etcd + KMS&lt;/h3&gt;

&lt;p&gt;Enable &lt;a href=&quot;https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/&quot;&gt;encryption at rest&lt;/a&gt; for Kubernetes etcd, backed by a cloud KMS:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# encryption config&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;apiserver.config.k8s.io/v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;EncryptionConfiguration&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;secrets&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;providers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;kms&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;aws-kms&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;endpoint&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unix:///tmp/socketfile.sock&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;cachesize&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1000&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This encrypts secrets at rest in etcd using your KMS key. The secrets still live in Kubernetes but are protected.&lt;/p&gt;

&lt;h3 id=&quot;option-2-hashicorp-vault&quot;&gt;Option 2: Hashicorp Vault&lt;/h3&gt;

&lt;p&gt;Vault is the most fully-featured secrets management solution. It provides:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Dynamic secrets (short-lived credentials generated on demand)&lt;/li&gt;
  &lt;li&gt;Secret leasing and renewal&lt;/li&gt;
  &lt;li&gt;Audit log of all secret access&lt;/li&gt;
  &lt;li&gt;Fine-grained access policies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Vault Agent Sidecar Injector can inject secrets into pods without the application needing to talk to Vault directly:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;annotations&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;vault.hashicorp.com/agent-inject&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;vault.hashicorp.com/role&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;sensor-api&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;vault.hashicorp.com/agent-inject-secret-config&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;secret/data/sensor-api/config&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Vault is more operationally complex than KMS-encrypted Secrets, but the dynamic secrets capability (especially for database credentials) is worth it for security-sensitive environments.&lt;/p&gt;

&lt;h2 id=&quot;rbac-principle-of-least-privilege&quot;&gt;RBAC: Principle of Least Privilege&lt;/h2&gt;

&lt;h3 id=&quot;kubernetes-rbac&quot;&gt;Kubernetes RBAC&lt;/h3&gt;

&lt;p&gt;Every service account should have only the permissions it actually needs. No service account should have cluster-admin unless it genuinely needs it.&lt;/p&gt;

&lt;p&gt;Define &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Role&lt;/code&gt; (namespace-scoped) or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClusterRole&lt;/code&gt; (cluster-scoped) with minimal permissions:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Role&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api-role&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;production&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;apiGroups&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;configmaps&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;verbs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;get&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;watch&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;list&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;resourceNames&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;sensor-api-config&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;apiGroups&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;secrets&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;verbs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;get&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;resourceNames&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;sensor-api-secrets&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Bind it to a dedicated ServiceAccount:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;RoleBinding&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api-binding&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;production&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;subjects&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ServiceAccount&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api-sa&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;production&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;roleRef&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Role&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api-role&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;apiGroup&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;rbac.authorization.k8s.io&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;cloud-iam&quot;&gt;Cloud IAM&lt;/h3&gt;

&lt;p&gt;The same principle applies to cloud IAM. Each service’s cloud IAM role should have only the permissions it needs:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The sensor API needs to publish to Kafka and write to S3 → those permissions only&lt;/li&gt;
  &lt;li&gt;The analytics job needs to read from S3 → read-only permissions only&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use cloud provider-specific mechanisms to bind Kubernetes ServiceAccounts to cloud IAM roles (AWS IRSA, GCP Workload Identity).&lt;/p&gt;

&lt;h2 id=&quot;secure-container-configuration&quot;&gt;Secure Container Configuration&lt;/h2&gt;

&lt;p&gt;Pod security context controls how containers run at the OS level:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;apps/v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Deployment&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;securityContext&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;runAsNonRoot&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;runAsUser&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1000&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;fsGroup&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2000&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;containers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api:1.0.0&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;securityContext&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;allowPrivilegeEscalation&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;readOnlyRootFilesystem&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;capabilities&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ALL&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;cpu&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;100m&quot;&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;128Mi&quot;&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;limits&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;cpu&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;500m&quot;&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;256Mi&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Key settings:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runAsNonRoot: true&lt;/code&gt; — container must not run as root&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readOnlyRootFilesystem: true&lt;/code&gt; — container can’t write to the filesystem (forces explicit volume mounts for any needed writes)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowPrivilegeEscalation: false&lt;/code&gt; — prevents privilege escalation attacks&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;capabilities: drop: ALL&lt;/code&gt; — drops all Linux capabilities (add back only what’s actually needed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These settings won’t stop every attack, but they significantly limit the blast radius of a container compromise.&lt;/p&gt;

&lt;h2 id=&quot;static-code-scanning&quot;&gt;Static Code Scanning&lt;/h2&gt;

&lt;p&gt;Shift security left by scanning code in CI:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;SAST&lt;/strong&gt; (Static Application Security Testing) — find vulnerabilities in your code before it ships (Snyk, Semgrep, SonarQube)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Container image scanning&lt;/strong&gt; — scan images for known CVEs (Trivy, Clair, AWS ECR scanning)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Kubernetes manifest scanning&lt;/strong&gt; — validate manifests against security policies (kube-score, Checkov, OPA/Gatekeeper)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add these as required quality gates in your CI pipeline. A build that introduces a critical CVE should fail.&lt;/p&gt;

&lt;h2 id=&quot;peer-review-for-security-changes&quot;&gt;Peer Review for Security Changes&lt;/h2&gt;

&lt;p&gt;Security-sensitive changes (RBAC changes, network policy changes, secrets handling) should require mandatory peer review. Ideally, with at least one reviewer who has security expertise.&lt;/p&gt;

&lt;p&gt;No automated tool catches everything. Human review catches what tools miss.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Concern&lt;/th&gt;
      &lt;th&gt;Solution&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Database isolation&lt;/td&gt;
      &lt;td&gt;Private subnets + VPC peering&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Pod-level network isolation&lt;/td&gt;
      &lt;td&gt;NetworkPolicies (deny-all default)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;DDoS protection&lt;/td&gt;
      &lt;td&gt;Cloud Shield + CDN + Ingress rate limiting&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Web attacks&lt;/td&gt;
      &lt;td&gt;WAF (AWS WAF / Cloudflare)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Secrets at rest&lt;/td&gt;
      &lt;td&gt;Encrypted etcd + KMS, or Vault&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Kubernetes permissions&lt;/td&gt;
      &lt;td&gt;RBAC with least privilege + dedicated ServiceAccounts&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Cloud permissions&lt;/td&gt;
      &lt;td&gt;Cloud IAM with least privilege + Workload Identity&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Container hardening&lt;/td&gt;
      &lt;td&gt;securityContext (nonRoot, readOnly, drop capabilities)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Code vulnerabilities&lt;/td&gt;
      &lt;td&gt;SAST + image scanning in CI&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</description>
        <pubDate>Thu, 04 Feb 2021 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/security/blueprints/cloud/kubernetes/architecture/2021/02/04/kubernetes-cloud-security-recommendations.html</link>
        <guid isPermaLink="true">https://rastko.tech/security/blueprints/cloud/kubernetes/architecture/2021/02/04/kubernetes-cloud-security-recommendations.html</guid>
      </item>
    
      <item>
        <title>The infrastructure blueprint of the microservice project - Kubernetes centric</title>
        <description>&lt;p&gt;In the &lt;a href=&quot;/blueprints/kubernetes/architecture/microservices/solutions/2020/11/12/case-study-blueprint-intro.html&quot;&gt;previous post&lt;/a&gt; we introduced the IoT case study. Now let’s build the infrastructure blueprint.&lt;/p&gt;

&lt;p&gt;The goal here is to map each component of the system to the right Kubernetes (or cloud-native) construct, and to explain the reasoning behind each decision.&lt;/p&gt;

&lt;h2 id=&quot;first-question-what-lives-in-kubernetes&quot;&gt;First Question: What Lives in Kubernetes?&lt;/h2&gt;

&lt;p&gt;Not everything needs to be in Kubernetes. A useful first pass is to categorise components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kubernetes-hosted:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Stateless API services&lt;/li&gt;
  &lt;li&gt;Stream processing consumers&lt;/li&gt;
  &lt;li&gt;Scheduled batch jobs&lt;/li&gt;
  &lt;li&gt;Internal tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cloud-hosted (managed services):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Kafka (MSK on AWS, Confluent Cloud, etc.) — operational complexity is high; managed is usually right&lt;/li&gt;
  &lt;li&gt;Relational database (RDS, CloudSQL, etc.) — same reasoning&lt;/li&gt;
  &lt;li&gt;Object storage for data lake (S3, GCS)&lt;/li&gt;
  &lt;li&gt;CDN for frontend asset delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keeping managed services outside Kubernetes simplifies operations significantly. You give up some control, but for infrastructure that isn’t your core competency, that’s a good trade.&lt;/p&gt;

&lt;h2 id=&quot;ingress-getting-traffic-in&quot;&gt;Ingress: Getting Traffic In&lt;/h2&gt;

&lt;p&gt;For external traffic, we use the standard three-layer Kubernetes ingress pattern:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Internet → Cloud LoadBalancer → Kubernetes NodePort → Ingress Controller → Services
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Cloud LoadBalancer&lt;/strong&gt; — provisioned by the cloud provider, gives us an external IP, handles TLS termination at the edge&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;NodePort&lt;/strong&gt; — exposes the Ingress Controller on a port on each node&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Ingress Controller&lt;/strong&gt; (nginx or similar) — routes HTTP/S traffic to Services based on host/path rules&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;ClusterIP Services&lt;/strong&gt; — the internal service discovery layer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the standard pattern and works well for HTTP/S traffic. For the sensor ingest path, we may want a separate TCP/UDP path if sensors use non-HTTP protocols — handled via a separate LoadBalancer Service.&lt;/p&gt;

&lt;h2 id=&quot;scaling-the-sensor-api&quot;&gt;Scaling the Sensor API&lt;/h2&gt;

&lt;p&gt;The sensor ingest API will receive high and variable traffic. We use &lt;strong&gt;HorizontalPodAutoscaler (HPA)&lt;/strong&gt; to scale the Deployment automatically:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;autoscaling/v2&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;HorizontalPodAutoscaler&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api-hpa&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;scaleTargetRef&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;apps/v1&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Deployment&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;minReplicas&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;maxReplicas&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;20&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Resource&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;cpu&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Utilization&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;averageUtilization&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;60&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Key points:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minReplicas: 3&lt;/code&gt; — we never want fewer than 3 for availability (across zones)&lt;/li&gt;
  &lt;li&gt;CPU at 60% target gives headroom before performance degrades&lt;/li&gt;
  &lt;li&gt;For real systems, consider custom metrics (requests per second) rather than CPU&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;kafka-consumers-statefulset-vs-deployment&quot;&gt;Kafka Consumers: StatefulSet vs Deployment&lt;/h2&gt;

&lt;p&gt;The Kafka consumer services (stream processors) require careful thought. Should they be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Deployment&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StatefulSet&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;It depends on whether the consumers maintain local state:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stateless consumers → Deployment&lt;/strong&gt;
If the consumer processes each message independently and writes output elsewhere (DB, another Kafka topic), use a Deployment. Pods are interchangeable, scaling is simple.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stateful consumers → StatefulSet&lt;/strong&gt;
If the consumer maintains local state (e.g., Kafka Streams with a local RocksDB store), use a StatefulSet. Pods have stable identities and stable storage. Kafka partition assignment can be pinned to specific pods.&lt;/p&gt;

&lt;p&gt;For most consumers in this system, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Deployment&lt;/code&gt; with external state is the right default. Reach for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StatefulSet&lt;/code&gt; only when you genuinely need stable identity.&lt;/p&gt;

&lt;h2 id=&quot;batch-analytics-cronjob&quot;&gt;Batch Analytics: CronJob&lt;/h2&gt;

&lt;p&gt;The analytics batch job (periodic aggregations, reports) maps cleanly to a Kubernetes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CronJob&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;batch/v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;CronJob&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;analytics-aggregator&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;*&quot;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# hourly&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;jobTemplate&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;containers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;aggregator&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;analytics-aggregator:latest&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;restartPolicy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;OnFailure&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;CronJobs are simple and reliable for periodic work. Just be careful with:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;concurrencyPolicy: Forbid&lt;/code&gt; if jobs must not overlap&lt;/li&gt;
  &lt;li&gt;Monitoring for missed/failed runs (Kubernetes doesn’t alert on this by default)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;configuration-configmaps-and-secrets&quot;&gt;Configuration: ConfigMaps and Secrets&lt;/h2&gt;

&lt;p&gt;Non-sensitive configuration goes into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConfigMap&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ConfigMap&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api-config&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;kafka_bootstrap_servers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;kafka.internal:9092&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;kafka_topic&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;sensor-events&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;max_batch_size&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;100&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sensitive values (credentials, API keys) go into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Secret&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Secret&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sensor-api-secrets&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Opaque&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;db_password&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;base64-encoded&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;api_key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;base64-encoded&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important caveat on Secrets:&lt;/strong&gt; Kubernetes Secrets are base64-encoded, not encrypted by default. They’re protected by RBAC, not encryption. For production, you need either:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Encrypted etcd (enable at the cluster level)&lt;/li&gt;
  &lt;li&gt;A KMS solution (AWS KMS, GCP KMS, Hashicorp Vault)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ll cover this in the security blueprint.&lt;/p&gt;

&lt;h2 id=&quot;external-service-abstraction&quot;&gt;External Service Abstraction&lt;/h2&gt;

&lt;p&gt;When your pods need to reach external services (the managed Kafka, the RDS database), use Kubernetes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service&lt;/code&gt; with a custom &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Endpoints&lt;/code&gt; object. This lets you treat external services as if they were internal Kubernetes services:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Service&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;kafka-external&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;9092&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Endpoints&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;kafka-external&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;subsets&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;addresses&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;10.0.1.50&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# MSK broker IP&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;9092&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This decouples your application code from knowing it’s talking to an external service. You can swap the external service for an in-cluster one (e.g., during development) without changing application config.&lt;/p&gt;

&lt;h2 id=&quot;frontend-apis-api-gateway&quot;&gt;Frontend APIs: API Gateway&lt;/h2&gt;

&lt;p&gt;The web and mobile frontend APIs get an additional layer: an &lt;strong&gt;API Gateway&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The API Gateway handles:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Authentication / JWT validation&lt;/li&gt;
  &lt;li&gt;Rate limiting per client&lt;/li&gt;
  &lt;li&gt;Request routing to downstream services&lt;/li&gt;
  &lt;li&gt;Response caching where appropriate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Options: AWS API Gateway, Kong, Ambassador/Emissary, or nginx with lua. The choice depends on your cloud provider and team familiarity.&lt;/p&gt;

&lt;h2 id=&quot;cdn-for-static-assets&quot;&gt;CDN for Static Assets&lt;/h2&gt;

&lt;p&gt;Frontend static assets (JS bundles, CSS, images) are served via CDN. This is a no-brainer:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Reduces latency for end users&lt;/li&gt;
  &lt;li&gt;Reduces load on origin servers&lt;/li&gt;
  &lt;li&gt;Free DDoS mitigation (to a degree)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CDN configuration is outside Kubernetes. The CDN origin points at your Ingress or a separate object storage bucket.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Component&lt;/th&gt;
      &lt;th&gt;Kubernetes Object&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Sensor ingest API&lt;/td&gt;
      &lt;td&gt;Deployment + HPA&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Stateless Kafka consumers&lt;/td&gt;
      &lt;td&gt;Deployment&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Stateful Kafka consumers&lt;/td&gt;
      &lt;td&gt;StatefulSet&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Analytics batch job&lt;/td&gt;
      &lt;td&gt;CronJob&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Internal services&lt;/td&gt;
      &lt;td&gt;Deployment + ClusterIP Service&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;External traffic entry&lt;/td&gt;
      &lt;td&gt;LoadBalancer + Ingress&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Configuration&lt;/td&gt;
      &lt;td&gt;ConfigMap&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Credentials&lt;/td&gt;
      &lt;td&gt;Secret + KMS&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;External service refs&lt;/td&gt;
      &lt;td&gt;Service + Endpoints&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Frontend APIs&lt;/td&gt;
      &lt;td&gt;Deployment + API Gateway&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;Next: &lt;a href=&quot;/security/blueprints/cloud/kubernetes/architecture/2021/02/04/kubernetes-cloud-security-recommendations.html&quot;&gt;The Kubernetes and cloud software security blueprint&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 19 Nov 2020 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/blueprints/infrastructure/kubernetes/architecture/microservices/solutions/2020/11/19/infrastructure-blueprint-kubernetes-microservices.html</link>
        <guid isPermaLink="true">https://rastko.tech/blueprints/infrastructure/kubernetes/architecture/microservices/solutions/2020/11/19/infrastructure-blueprint-kubernetes-microservices.html</guid>
      </item>
    
      <item>
        <title>The blueprints - case study, specification and architecture review (intro)</title>
        <description>&lt;p&gt;Before diving into individual blueprints, we need a concrete system to reason about. Abstract discussions of architecture are useful up to a point — but the real complexity emerges when you apply principles to a specific problem.&lt;/p&gt;

&lt;p&gt;This post introduces the &lt;strong&gt;IoT data ingestion platform&lt;/strong&gt; that will serve as the case study throughout this series.&lt;/p&gt;

&lt;h2 id=&quot;the-system&quot;&gt;The System&lt;/h2&gt;

&lt;p&gt;The system receives data from a large number of distributed sensors and devices:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Raspberry Pi arrays&lt;/li&gt;
  &lt;li&gt;IoT sensor networks&lt;/li&gt;
  &lt;li&gt;Mobile phones and tablets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This data flows through the system, gets processed and stored in two ways:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;A &lt;strong&gt;data lake&lt;/strong&gt; for raw and transformed event data (analytics, ML)&lt;/li&gt;
  &lt;li&gt;A &lt;strong&gt;relational database&lt;/strong&gt; for structured, queryable data (operational)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On the output side, the system exposes APIs consumed by:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Web frontends&lt;/li&gt;
  &lt;li&gt;Mobile applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a fairly typical modern data-intensive system, but with enough moving parts to make the blueprints meaningful.&lt;/p&gt;

&lt;h2 id=&quot;why-this-system&quot;&gt;Why This System?&lt;/h2&gt;

&lt;p&gt;It represents a common class of problem:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;High ingest volume&lt;/strong&gt; — thousands of sensors sending data continuously&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Mixed workloads&lt;/strong&gt; — stream processing, batch processing, request-response APIs&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Multiple consumers&lt;/strong&gt; — different clients with different latency and reliability requirements&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Greenfield&lt;/strong&gt; — we’re designing it from scratch, which means we choose the constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;technology-decisions&quot;&gt;Technology Decisions&lt;/h2&gt;

&lt;p&gt;Only one technology is strictly decided at this point: &lt;strong&gt;Apache Kafka&lt;/strong&gt; as the streaming platform.&lt;/p&gt;

&lt;p&gt;Kafka is the right choice here because:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;It decouples producers from consumers&lt;/li&gt;
  &lt;li&gt;It provides durable, replayable message storage&lt;/li&gt;
  &lt;li&gt;It handles high-throughput ingest gracefully&lt;/li&gt;
  &lt;li&gt;It’s a proven choice for this class of problem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything else — databases, languages, frameworks, cloud provider — is left open deliberately. The blueprints should be applicable regardless of those choices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kubernetes&lt;/strong&gt; is assumed as the infrastructure foundation throughout.&lt;/p&gt;

&lt;h2 id=&quot;nfr-analysis-pass&quot;&gt;NFR Analysis Pass&lt;/h2&gt;

&lt;p&gt;Before building anything, it’s worth doing an explicit pass on non-functional requirements. For this system, key NFRs include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Availability&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The sensor ingest path needs to be highly available — sensors can’t buffer indefinitely&lt;/li&gt;
  &lt;li&gt;Web/mobile APIs need standard SLA (99.9%+)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Ingest must scale horizontally as sensor count grows&lt;/li&gt;
  &lt;li&gt;Data storage must handle growing data volumes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Sensor data may be sensitive; transit encryption required&lt;/li&gt;
  &lt;li&gt;Backend APIs must authenticate and authorise properly&lt;/li&gt;
  &lt;li&gt;Infrastructure must follow least-privilege principles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;High-volume distributed systems are hard to debug without good telemetry&lt;/li&gt;
  &lt;li&gt;Need metrics, logs, and traces across all components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Deployability&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Frequent releases without downtime&lt;/li&gt;
  &lt;li&gt;Safe rollback capability&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;upcoming-blueprints&quot;&gt;Upcoming Blueprints&lt;/h2&gt;

&lt;p&gt;Based on this system, here are the blueprints we’ll build out:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Infrastructure blueprint&lt;/strong&gt; — how to structure the Kubernetes workloads&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Security blueprint&lt;/strong&gt; — Kubernetes and cloud security posture&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;CI/CD blueprint&lt;/strong&gt; — cloud-native software delivery pipeline&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Observability blueprint&lt;/strong&gt; — metrics, logging, tracing&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Configuration management&lt;/strong&gt; — dynamic config and circuit breakers&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DevOps tooling&lt;/strong&gt; — the practices and tools&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each blueprint will reference back to this case study and show how the principles apply concretely.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;Next: &lt;a href=&quot;/blueprints/infrastructure/kubernetes/architecture/microservices/solutions/2020/11/19/infrastructure-blueprint-kubernetes-microservices.html&quot;&gt;The infrastructure blueprint of the microservice project&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 12 Nov 2020 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/blueprints/kubernetes/architecture/microservices/solutions/2020/11/12/case-study-blueprint-intro.html</link>
        <guid isPermaLink="true">https://rastko.tech/blueprints/kubernetes/architecture/microservices/solutions/2020/11/12/case-study-blueprint-intro.html</guid>
      </item>
    
      <item>
        <title>The two scales of DevOps</title>
        <description>&lt;p&gt;DevOps is one of the most misused and misunderstood terms in software engineering. Ask ten engineers what DevOps means and you’ll get ten different answers. Some will say CI/CD. Some will say shared responsibility. Some will say it’s just a job title for ops people who can code.&lt;/p&gt;

&lt;p&gt;I want to introduce a mental model that I find useful: &lt;strong&gt;the two scales of DevOps&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;scale-1-the-scale-of-development&quot;&gt;Scale 1: The Scale of Development&lt;/h2&gt;

&lt;p&gt;The first scale is about &lt;strong&gt;developer flow&lt;/strong&gt; — how fast and how safely can your engineering organisation ship software?&lt;/p&gt;

&lt;p&gt;Key metrics (from the DORA research):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Lead Time for Change&lt;/strong&gt; — from commit to production&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Deployment Frequency&lt;/strong&gt; — how often you deploy&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Change Failure Rate&lt;/strong&gt; — how often deployments cause incidents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Scale of Development encompasses everything that affects these metrics:&lt;/p&gt;

&lt;h3 id=&quot;cicd&quot;&gt;CI/CD&lt;/h3&gt;

&lt;p&gt;The pipeline that takes code from commit to production. Build, test, scan, deploy. The goal is to make this fast, reliable, and automated. A slow CI/CD pipeline kills flow.&lt;/p&gt;

&lt;h3 id=&quot;developer-experience-dx&quot;&gt;Developer Experience (DX)&lt;/h3&gt;

&lt;p&gt;Everything that affects a developer’s ability to work effectively: local development environments, tooling, documentation, onboarding, cognitive load of the codebase.&lt;/p&gt;

&lt;p&gt;A team with poor DX will move slowly regardless of how good the pipeline is.&lt;/p&gt;

&lt;h3 id=&quot;flow-efficiency&quot;&gt;Flow Efficiency&lt;/h3&gt;

&lt;p&gt;Derived from Lean manufacturing. Of the total time from “idea” to “shipped”, what fraction is actual work vs waiting? In most organisations, the ratio is terrible — 10-20% active work, 80-90% wait time (in queues, review, etc.).&lt;/p&gt;

&lt;p&gt;Improving flow efficiency often has more impact than improving individual speed.&lt;/p&gt;

&lt;h3 id=&quot;emergent-design&quot;&gt;Emergent Design&lt;/h3&gt;

&lt;p&gt;In fast-moving systems, big-upfront design doesn’t work. You need the capacity for continuous, incremental design improvement — refactoring, abstraction, simplification — as a first-class engineering activity.&lt;/p&gt;

&lt;h2 id=&quot;scale-2-the-scale-of-life&quot;&gt;Scale 2: The Scale of Life&lt;/h2&gt;

&lt;p&gt;The second scale is about &lt;strong&gt;production reliability&lt;/strong&gt; — when things are running in production, how do you keep them running?&lt;/p&gt;

&lt;p&gt;This is the domain of &lt;strong&gt;Site Reliability Engineering (SRE)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Key metrics:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;MTTD&lt;/strong&gt; — Mean Time to Detect (how fast do you know something is wrong?)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;MTTR&lt;/strong&gt; — Mean Time to Resolve (how fast can you fix it?)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SLO/SLI/SLA&lt;/strong&gt; — Service Level Objectives, Indicators, Agreements&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;the-four-golden-signals&quot;&gt;The Four Golden Signals&lt;/h3&gt;

&lt;p&gt;Google’s SRE book defines four signals that, if monitored, give you a complete picture of production health:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Latency&lt;/strong&gt; — how long requests take&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Traffic&lt;/strong&gt; — how much demand is hitting the system&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Errors&lt;/strong&gt; — rate of failed requests&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Saturation&lt;/strong&gt; — how “full” the system is (CPU, memory, connections)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;slos-and-error-budgets&quot;&gt;SLOs and Error Budgets&lt;/h3&gt;

&lt;p&gt;SLOs (Service Level Objectives) define the target reliability of a service — e.g., “99.9% of requests succeed in under 200ms”. The gap between 100% and the SLO is the &lt;strong&gt;error budget&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Error budgets align incentives: development teams want to ship features fast; SRE teams want stability. The error budget is the negotiated zone where both can happen. If the budget is being consumed too fast, you slow down releases. If there’s plenty of budget, you can move faster.&lt;/p&gt;

&lt;h2 id=&quot;devops-vs-sre&quot;&gt;DevOps vs SRE&lt;/h2&gt;

&lt;p&gt;DevOps and SRE are often treated as competing philosophies. They’re not — they’re complementary.&lt;/p&gt;

&lt;p&gt;DevOps is a cultural movement: shared ownership, collaboration between dev and ops, automation of toil. SRE is Google’s implementation of that culture, with specific practices and metrics.&lt;/p&gt;

&lt;p&gt;You can think of it this way:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;DevOps defines the &lt;strong&gt;what&lt;/strong&gt; (goals, culture, principles)&lt;/li&gt;
  &lt;li&gt;SRE provides the &lt;strong&gt;how&lt;/strong&gt; (practices, metrics, tooling)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;cognitive-load&quot;&gt;Cognitive Load&lt;/h2&gt;

&lt;p&gt;One concept that cuts across both scales is &lt;strong&gt;cognitive load&lt;/strong&gt; — the mental burden placed on engineers.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Team Topologies&lt;/em&gt; (Skelton &amp;amp; Pais) makes this the central constraint of team design. Teams that own too much, or work with systems too complex to reason about, move slowly and make more mistakes.&lt;/p&gt;

&lt;p&gt;Architectural decisions — how services are split, how teams are structured, what shared platforms exist — should be evaluated in terms of their cognitive load impact as much as their technical properties.&lt;/p&gt;

&lt;h2 id=&quot;books-worth-reading&quot;&gt;Books worth reading&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Accelerate&lt;/em&gt; — Forsgren, Humble, Kim — the research behind DORA metrics&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;The SRE Book&lt;/em&gt; — Google — the canonical SRE reference&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Team Topologies&lt;/em&gt; — Skelton &amp;amp; Pais — team structure and cognitive load&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;Next: &lt;a href=&quot;/blueprints/kubernetes/architecture/microservices/solutions/2020/11/12/case-study-blueprint-intro.html&quot;&gt;The blueprints - case study, specification and architecture review&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 02 Nov 2020 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/blueprints/cloud/cloud-native/devops/sre/kubernetes/infrastructure/architecture/solutions/2020/11/02/two-scales-of-devops.html</link>
        <guid isPermaLink="true">https://rastko.tech/blueprints/cloud/cloud-native/devops/sre/kubernetes/infrastructure/architecture/solutions/2020/11/02/two-scales-of-devops.html</guid>
      </item>
    
      <item>
        <title>Native to the cloud</title>
        <description>&lt;p&gt;This is the first post in the &lt;strong&gt;Cloud-Native Blueprints&lt;/strong&gt; series — a set of deep dives into the non-functional aspects of cloud-native projects. The series is Kubernetes-centric, but the concepts apply broadly.&lt;/p&gt;

&lt;h2 id=&quot;how-we-got-here&quot;&gt;How we got here&lt;/h2&gt;

&lt;p&gt;Cloud computing didn’t just give us cheaper servers. It gave us a fundamentally different way to think about software architecture. Before cloud, infrastructure was slow to provision, expensive to scale, and painful to manage. Architectural decisions were made with those constraints baked in.&lt;/p&gt;

&lt;p&gt;Cloud changed the constraints. Suddenly you could provision resources in minutes, scale horizontally on demand, and pay only for what you used. Architectural thinking had to catch up.&lt;/p&gt;

&lt;p&gt;Out of this shift emerged &lt;strong&gt;cloud-native&lt;/strong&gt; — a design philosophy and set of practices built to fully exploit what cloud infrastructure makes possible. Not “lift and shift” of old workloads, but systems designed from the ground up for elastic, distributed, automated environments.&lt;/p&gt;

&lt;h2 id=&quot;kubernetes-as-the-foundation&quot;&gt;Kubernetes as the foundation&lt;/h2&gt;

&lt;p&gt;Of all the technologies that emerged from the cloud-native movement, &lt;strong&gt;Kubernetes&lt;/strong&gt; has become the de facto standard for cloud-native infrastructure. It provides:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Container orchestration at scale&lt;/li&gt;
  &lt;li&gt;Declarative configuration of the desired state&lt;/li&gt;
  &lt;li&gt;Self-healing and automated rollouts&lt;/li&gt;
  &lt;li&gt;A common abstraction layer across cloud providers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kubernetes doesn’t solve everything — it introduces its own complexity — but it epitomises cloud-native infrastructure. This series will use Kubernetes as the primary lens.&lt;/p&gt;

&lt;h2 id=&quot;what-this-series-is-about&quot;&gt;What this series is about&lt;/h2&gt;

&lt;p&gt;Running software on Kubernetes is one thing. Running it &lt;em&gt;well&lt;/em&gt; — at scale, reliably, securely, and efficiently — is another.&lt;/p&gt;

&lt;p&gt;Most engineering attention goes to functional requirements: the features, the business logic, the data. Non-functional requirements (NFRs) — reliability, security, performance, observability, deployability — often get treated as afterthoughts.&lt;/p&gt;

&lt;p&gt;They shouldn’t be. In distributed systems, the NFRs are frequently &lt;em&gt;harder&lt;/em&gt; than the functional requirements, and failures in them tend to be catastrophic rather than graceful.&lt;/p&gt;

&lt;p&gt;This series will systematically cover the non-functional blueprints for cloud-native systems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Infrastructure&lt;/strong&gt; — how to structure Kubernetes workloads&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt; — Kubernetes and cloud security posture&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;CI/CD&lt;/strong&gt; — cloud-native software delivery&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Observability&lt;/strong&gt; — monitoring, logging, tracing&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Configuration management&lt;/strong&gt; — dynamic config and circuit breakers&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DevOps tooling&lt;/strong&gt; — the practices and tools that make it work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each blueprint will be grounded in a concrete case study: an IoT data ingestion platform. This gives us a realistic, complex system to reason about.&lt;/p&gt;

&lt;h2 id=&quot;a-word-of-caution&quot;&gt;A word of caution&lt;/h2&gt;

&lt;p&gt;Cloud-native comes with real complexity costs. Not every system needs Kubernetes. Not every team has the capability to own the full SDLC end-to-end.&lt;/p&gt;

&lt;p&gt;The right question isn’t “should we use cloud-native?” but “which parts of cloud-native make sense for our context, our team, and our problem?”&lt;/p&gt;

&lt;p&gt;Throughout this series, I’ll try to be honest about that. The goal isn’t to sell you on a stack. It’s to give you the blueprints to make good decisions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don’t break stuff whatever others say.&lt;/strong&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;Next: &lt;a href=&quot;/blueprints/cloud/cloud-native/devops/sre/kubernetes/infrastructure/architecture/solutions/2020/11/02/two-scales-of-devops.html&quot;&gt;The two scales of DevOps&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 22 Oct 2020 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/blueprints/cloud/cloud-native/kubernetes/infrastructure/architecture/solutions/2020/10/22/native-to-cloud.html</link>
        <guid isPermaLink="true">https://rastko.tech/blueprints/cloud/cloud-native/kubernetes/infrastructure/architecture/solutions/2020/10/22/native-to-cloud.html</guid>
      </item>
    
      <item>
        <title>Monitoring Data Flows in a Microservice System</title>
        <description>&lt;p&gt;To deliver high-quality service, organizations must carefully track data flows within applications. This typically requires establishing well-designed code metrics and implementing robust monitoring systems around those metrics.&lt;/p&gt;

&lt;p&gt;Metrics represent “the fastest observability data. They have the quickest output, can be consumed directly… require the smallest throughput, and have the smallest retention footprint.”&lt;/p&gt;

&lt;p&gt;In service-oriented architectures, understanding how to leverage metrics at distributed integration points enables early problem detection—a critical capability explored throughout this piece.&lt;/p&gt;

&lt;h2 id=&quot;the-system-architecture&quot;&gt;The System Architecture&lt;/h2&gt;

&lt;p&gt;The article examines a microservice-based system featuring:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A Frontend API microservice (functioning partially as an API gateway)&lt;/li&gt;
  &lt;li&gt;Integration Aggregator (A.I.) microservices&lt;/li&gt;
  &lt;li&gt;Subsystem microservices specialized for domain aggregates&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;understanding-the-data-flow&quot;&gt;Understanding the Data Flow&lt;/h2&gt;

&lt;p&gt;The discussion focuses on synchronous data flows involving multiple sequential service calls. The presented sequence diagram shows a typical backend flow where:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Frontend API initiates requests&lt;/li&gt;
  &lt;li&gt;Multiple services process data sequentially&lt;/li&gt;
  &lt;li&gt;Responses aggregate and return to users&lt;/li&gt;
  &lt;li&gt;Two subflows represent error responses and timeout scenarios&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;observability-perspective&quot;&gt;Observability Perspective&lt;/h2&gt;

&lt;p&gt;Applying observability principles to the flow architecture reveals measurement opportunities. The system should expose metrics for two primary purposes:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Performance measurement&lt;/li&gt;
  &lt;li&gt;Flow correctness verification&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two metric types serve these purposes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Counters&lt;/strong&gt; (displayed as squares/rhomboids): Track initiated calls, completed calls, and caught errors&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Timers&lt;/strong&gt; (displayed as arrow bands): Measure call duration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-to-measure&quot;&gt;What to Measure&lt;/h2&gt;

&lt;p&gt;Effective flow observability requires exposing:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Counters for every initiated and completed call with descriptive labels&lt;/li&gt;
  &lt;li&gt;Counters for caught errors, distinguishing between 5xx and 4xx responses&lt;/li&gt;
  &lt;li&gt;Timers for successful calls (error response timing is typically less relevant)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Importantly, status codes should be tracked with granular labeling, allowing later aggregation while preserving detailed data capture.&lt;/p&gt;

&lt;h2 id=&quot;where-to-measure&quot;&gt;Where to Measure&lt;/h2&gt;

&lt;p&gt;Measurements should focus on:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Incrementing counters and starting timers when calls initiate&lt;/li&gt;
  &lt;li&gt;Incrementing success counters and stopping timers upon response receipt&lt;/li&gt;
  &lt;li&gt;Incrementing error counters when catching erroneous responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A critical insight: “measuring the performance of every service by measuring its responses on the side of the consumer service” provides intuitive, logical system performance understanding. This approach accounts for networking, security measures, and integration overhead—factors internal service measurements miss.&lt;/p&gt;

&lt;h2 id=&quot;why-measure-quality-of-service&quot;&gt;Why Measure: Quality of Service&lt;/h2&gt;

&lt;p&gt;The overarching motivation centers on &lt;strong&gt;Quality of Service (QoS)&lt;/strong&gt;. Providing reliable service demands understanding system performance, which requires observing exposed data.&lt;/p&gt;

&lt;h3 id=&quot;performance-monitoring&quot;&gt;Performance Monitoring&lt;/h3&gt;

&lt;p&gt;API endpoint performance represents the most critical metric—the total duration of the complete flow. Plotting performance over time reveals degradation patterns.&lt;/p&gt;

&lt;p&gt;Effective dashboards combine:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Total flow performance graphs&lt;/li&gt;
  &lt;li&gt;Individual segment performance graphs&lt;/li&gt;
  &lt;li&gt;Request volume counters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When performance degrades, these visualizations identify whether particular segments disproportionately impact response times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alerting approaches include:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Performance budget-based alerts (e.g., responses exceeding 300ms)&lt;/li&gt;
  &lt;li&gt;Historical comparison alerts (e.g., 20% slower than yesterday’s baseline)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;“The same way service#1 that is calling service#2 needs to qualify the performance of service#2, your users are qualifying your application’s performance, and you are there to make sure that it is the best performance you can achieve.”&lt;/p&gt;

&lt;h3 id=&quot;error-rate-monitoring&quot;&gt;Error Rate Monitoring&lt;/h3&gt;

&lt;p&gt;All error response counters contribute to error rate tracking, supporting both quality assurance and technical flaw identification.&lt;/p&gt;

&lt;p&gt;Error characterization distinguishes between status code ranges:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;4xx vs 5xx separation&lt;/strong&gt; applies when subsystems exhibit distinct 400-range behaviors (authentication, authorization)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Combined tracking&lt;/strong&gt; suits systems without special 4xx handling&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;404 exclusion&lt;/strong&gt; often makes sense for public-facing systems where page misses are common&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The article illustrates that error impacts vary contextually:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Private applications with authentication: 4xx errors signal security concerns&lt;/li&gt;
  &lt;li&gt;Integration systems: 404s indicate upstream changes requiring immediate attention&lt;/li&gt;
  &lt;li&gt;Public search functionality: 404s are expected from crawlers&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;5xx errors are always problematic&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Error rate alerting should be stringent, typically based on SLOs triggering when endpoints breach service-level objectives for extended periods.&lt;/p&gt;

&lt;p&gt;“Make sure not to waste time on staring at monitoring dashboards - set up alerts and go do something fun” — emphasizing automation over manual observation.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Key takeaways include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Code instrumentation constitutes a core software development responsibility&lt;/li&gt;
  &lt;li&gt;System observability requires architectural consideration matching the attention devoted to system design itself&lt;/li&gt;
  &lt;li&gt;Consumer-side performance measurement provides the proper perspective, accounting for integration and networking factors&lt;/li&gt;
  &lt;li&gt;Error management remains paramount&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 12 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/microservices/sre/monitoring/alerting/observability/programming/architecture/solutions/2020/09/12/monitoring-microservice-data-flows.html</link>
        <guid isPermaLink="true">https://rastko.tech/microservices/sre/monitoring/alerting/observability/programming/architecture/solutions/2020/09/12/monitoring-microservice-data-flows.html</guid>
      </item>
    
      <item>
        <title>Planning Observability of Your System</title>
        <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Observability is the ability of your system to expose data about its performance and behavior so we can further monitor, analyze, and alert on certain trends or changes. Making your system observable requires certain effort in your project.&lt;/p&gt;

&lt;h2 id=&quot;why-should-you-care&quot;&gt;Why Should You Care&lt;/h2&gt;

&lt;p&gt;Observability of your system is the &lt;strong&gt;top non-functional requirement&lt;/strong&gt;. In the author’s opinion, not even application performance tops observability. It is absolutely necessary that you know what is happening in your system at any given time and in level of detail necessary to be able to keep everything running smoothly by adequately reacting to change in the system.&lt;/p&gt;

&lt;p&gt;Of course, there is a possibility that you do not share this opinion, in which case you would probably rather develop your product, do a bit of testing, UAT, and push it out. Probably because it requires a certain amount of work and is considered non-essential as you start. If Google Analytics is all you need, refer back here when you change your mind. If, however, you want to dive into this topic and start planning, the author wants to share some insights that should help you pin down stuff that is most important for you and prioritize.&lt;/p&gt;

&lt;p&gt;There are quite a few aspects of observability in service-oriented architecture, and this article focuses on discussing every aspect with a little bit of depth in order to help you better understand, focus and plan developing your observability. To help you plan and have a broader conversation with all the people involved in planning your project, the author will provide some insight into the most popular stacks as well and give insights into the most important defining factors.&lt;/p&gt;

&lt;p&gt;Your system being observable can mean multiple things on as many levels, but generally, it means that system exposes data that we can consume to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Monitor system in real-time.&lt;/li&gt;
  &lt;li&gt;Alert or perform some automated task based on defined data state, or rather a change of state.&lt;/li&gt;
  &lt;li&gt;Analyze and predict behaviors, requirements etc…&lt;/li&gt;
  &lt;li&gt;Do a detailed analysis of the incident or any distinct event in the system.&lt;/li&gt;
  &lt;li&gt;Any combination of the above.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since it is all about using proper tools, let’s spend some time on quick discussion about what we need and what tool/type of observability we choose.&lt;/p&gt;

&lt;h2 id=&quot;characterizing-capabilities&quot;&gt;Characterizing Capabilities&lt;/h2&gt;

&lt;p&gt;When we talk observability of the system, the way we are planning it really depends on what we want to achieve. Ultimately, we would love to achieve everything, but some ability to focus and plan would be nice. Let us take a look at some factors to take into account when prioritizing observability.&lt;/p&gt;

&lt;h3 id=&quot;main-types-of-data&quot;&gt;Main Types of Data&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Logs&lt;/strong&gt; — Old, but gold. The first that ever existed has all the data about what is going on, but slow, hard to process, and needs huge system throughput to bring usage close to real-time. You can still go to the file that was generated last and grep it for a particular phrase or just look for the time when the error happened, which will forever be a favorite thing learned (apart from making pizza from scratch).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Metrics&lt;/strong&gt; — Quick, flexible, made for quick availability and low throughput requirement, easy and long retention. Not too much data per unit of information, real-time trend analysis and reaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traces&lt;/strong&gt; — Everything you would like to know about the call you made, seems like magic especially in a well-instrumented distributed system. Sometimes slower than logs, but allows for deeper analytics.&lt;/p&gt;

&lt;h3 id=&quot;performance-qualities&quot;&gt;Performance Qualities&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Usability&lt;/strong&gt; — Do metrics allow a good way to monitor and analyze them, with flexibility in data architecture to give enough versatility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Speed/throughput requirements&lt;/strong&gt; — how much metrics system can take before receiving some performance penalty. Also, how fast are the metrics available for consumption/use (both manual and automated).&lt;/p&gt;

&lt;h3 id=&quot;way-we-plan-to-consume-data&quot;&gt;Way We Plan to Consume Data&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Monitoring&lt;/strong&gt; — real-time plotting and observation of system state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alerting and automatic triggers&lt;/strong&gt; — reacting to events by broadcasting notification or triggering events.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analytics&lt;/strong&gt; — analyzing collected data to gather useful learnings about the system and/or perform root cause analysis (RCA) of the problem in the past (usual case) or ongoing problem (rarer since Analytics is mostly about applying complex algorithms to big data sets to draw conclusions, and that takes time).&lt;/p&gt;

&lt;h3 id=&quot;quick-comparison-table&quot;&gt;Quick Comparison Table&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Performance / Throughput needs&lt;/th&gt;
      &lt;th&gt;Recommended for&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Logs&lt;/td&gt;
      &lt;td&gt;Medium / Medium - still lots of text&lt;/td&gt;
      &lt;td&gt;RCA/Monitoring/Alerting&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Metrics&lt;/td&gt;
      &lt;td&gt;Fast / Low - smallest unit of data&lt;/td&gt;
      &lt;td&gt;Monitoring/Alerting/Analytics&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Traces&lt;/td&gt;
      &lt;td&gt;Slow / High - contains lots of data&lt;/td&gt;
      &lt;td&gt;RCA, Alerting in some setups&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;creating-observability&quot;&gt;Creating Observability&lt;/h2&gt;

&lt;p&gt;As you are building a system, no matter if it is a huge monolithic application, or a multiservice-something, planning observability you want to achieve will get you places. For that, you’ll have to know what kind of tools you need and what additional infrastructure will it take… of course, but there is also a choice of where to start. It is less obvious, but deciding to do everything might be a costly decision depending on how much time you got to deliver the first version of your system.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;For most of the stuff that is written, the assumption is your goal is full DevOps, and that your team is building everything and running it in all the environments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you are getting something pre-built, you have an army of engineers or reasonably long timelines there might be a way to get it all in time.&lt;/p&gt;

&lt;h3 id=&quot;logging&quot;&gt;Logging&lt;/h3&gt;

&lt;p&gt;Generally, you do not need to do anything in order for your system to start gathering logs, logs will be available to you anywhere from the default log directory for the OS of choice to Kubernetes logs. What you will need is everything else - literally.&lt;/p&gt;

&lt;p&gt;Going from just a stack of call logs inside a gazillion line file on the disc to a searchable log database that can also be used for a certain level of alerting and many different applications is the matter of planning. The author usually recommends two well-known stacks, that differ in the log collection segment:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;ELK&lt;/strong&gt; — Elastic, Logstash, Kibana which is more standard one&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;EFK&lt;/strong&gt; — Elastic, Fluentd, Kibana which is a more flexible one in terms of data flow management and further design scalability. It is also recommended for Kubernetes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everyone loves 3-letter abbreviations so nobody bothered to add F at the start of both since it became a standard. F for Filebeat.&lt;/p&gt;

&lt;p&gt;Basically, you need to setup EXK and Filebeat, Filebeat will pick up the logs as they arrive to any of the mentioned standard log outputs and send them to a log collector, that gets stored into the Elastic database so logs will be indexed and made searchable and visualizable through Kibana.&lt;/p&gt;

&lt;p&gt;Obviously, the more activity you got in your system, the more logs there is, more data throughput becomes crucial for your logs to get to you — Filebeat needs to send logs to Elastic that then needs to index them (on the way there is a throughput of whatever you use). There have been cases of hundreds of terabytes of logs a day with need of month to 3 months retention… It becomes a whole separate system to maintain.&lt;/p&gt;

&lt;p&gt;The good thing is that, when overwhelmed, these setups are quite good in the degrading performance but keeping data, so if you do not run out of physical hardware and everything just halts, your logs may be late to Kibana because elastic can’t index, or they might be stuck in some queue, but they will not be lost. That is, at least, something.&lt;/p&gt;

&lt;h4 id=&quot;in-the-wild&quot;&gt;In the Wild&lt;/h4&gt;

&lt;p&gt;Stack itself is relatively easy to deploy with lots of resources available online, from tutorials to docker-composed sets, Terraform submodules and the Helm charts to do it for you. The first hard thing to do is set everything right the first time from the delivery of logs perspective. The second hard thing to do is not to kill your logging stack with too much or too big logs.&lt;/p&gt;

&lt;p&gt;Good luck.&lt;/p&gt;

&lt;h3 id=&quot;metrics&quot;&gt;Metrics&lt;/h3&gt;

&lt;p&gt;On the metrics side of things are a lot different than on the logs side of things — although there is a general majority choice of a tool, and thus an approach to it, there are actually two different approaches based on a way metrics are exposed/collected:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Pull&lt;/strong&gt; — used by wider accepted and CNCF adopted Prometheus&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Push&lt;/strong&gt; — used by StatsD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Based on two stand out representatives of two groups, a quick comparison is provided.&lt;/p&gt;

&lt;h4 id=&quot;pull--prometheus&quot;&gt;Pull — Prometheus&lt;/h4&gt;

&lt;p&gt;Prometheus is a current metrics collection stack of choice, developed by SoundCloud and fully promoted to open source in 2015, although it was available for longer.&lt;/p&gt;

&lt;p&gt;Pull means that the metrics collector is scraping services that are being monitored by it. In turn, the system requires that any service that needs to be monitored by Prometheus exposes metrics. Data exposition format allows “condensation” of the metrics that are exposed, so they basically can accumulate until scraped for both variable scraping intervals, but also the longer periods in case of incidents with collector.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Metrics are kept in the service’s memory until the collector pulls (scrapes) the metrics.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The architecture of the metrics collection and way Prometheus is built gives us two important architectural advantages:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Resilience&lt;/strong&gt; — If Prometheus collector dies for some time, metrics are not lost because they are kept in the service’s memory until scraped&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Federation&lt;/strong&gt; — the same way the service exposes metrics to be collected by Prometheus, Prometheus itself can expose aggregated metrics to be collected by other Prometheus system, allowing for metrics collection scaling by creating a tree hierarchy collection structure known as Federation in the Prometheus ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prometheus has a full set of needed components within its ecosystem — it collects metrics in form of time-series and stores them, it also has a alert manager to handle alerts and push gateway to support sort lived services (jobs, container orchestration, serverless…).&lt;/p&gt;

&lt;p&gt;There is a certain complexity to using pull metrics that you have to take into consideration — since it scrapes services for metrics you would need service discovery to always know what to scrape, especially in container orchestration space.&lt;/p&gt;

&lt;h5 id=&quot;in-the-wild-1&quot;&gt;In the Wild&lt;/h5&gt;

&lt;p&gt;Prometheus is a multi-component system that is relatively easy to deploy thanks to the community, but it has lots of quirks for you to handle. It will be super useful, and is recommended wholeheartedly, but be ready to do some maintenance on it as it is a fast data collection and parsing system having many resilience points which often cause stuff like memory leaks and hard drive space overload.&lt;/p&gt;

&lt;p&gt;Every time you want to plot any real-life scenario data, you are making mid to high complexity query to Prometheus, which can overload it, especially in high-resolution intensive plots we can make Prometheus less efficient for its main purpose. Luckily, you can record (sort of index/cache) certain queries (rules) and make the whole thing more performant.&lt;/p&gt;

&lt;p&gt;Prometheus can be used as a source directly in Grafana, which is the best open source monitoring+analytics frontend dashboard tool out there.&lt;/p&gt;

&lt;h4 id=&quot;push--statsd&quot;&gt;Push — StatsD&lt;/h4&gt;

&lt;p&gt;The first monitoring stack that could seriously be called that was StatsD, developed by Etsy.&lt;/p&gt;

&lt;p&gt;Push means that your system is pushing the signals to StatsD all the time.&lt;/p&gt;

&lt;p&gt;This simplifies lots of architectural requirements since service discovery is not needed, the service itself needs to know where the StatsD server (also called daemon) is, and that is that it can receive signals from many sources.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The author personally thinks that price in a bit of complexity on the Prometheus side is worth it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Looking at the stack itself, where Prometheus has everything in one place, StatsD has its daemon and clients (for every language), but everything else needs a custom thing to plug in:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;To read and transform data you need something like Graphite, that you can later also use as a source for Grafana.&lt;/li&gt;
  &lt;li&gt;For alerting you need another module.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;in-the-wild-2&quot;&gt;In the Wild&lt;/h5&gt;

&lt;p&gt;Fact that the daemon gets hit for every event in your service and that your service needs to make a request every time the event you are measuring is done leads to new requirements on the software engineering side if the number of request to your app grows. You need to sample every metric if you do not want most of your resource consumption to go into metrics. There is this really good anecdote from Etsy that they actually had alerts on metrics sampling, so Ops guys would come for you if you did not sample or you did not sample enough.&lt;/p&gt;

&lt;p&gt;The best way to visualize in this case is also Grafana, but in this case you can not use StatsD as a data source directly, you need Graphite.&lt;/p&gt;

&lt;h5 id=&quot;sampling&quot;&gt;Sampling&lt;/h5&gt;

&lt;p&gt;The technique of reducing number of metrics in a way that you are only sending samples of data (that is why it is also known as downsampling). What you do is send one in 100 metrics generated (one in every 100 requests gets measured).&lt;/p&gt;

&lt;p&gt;Sampling helps in both push and pull case, but it is more useful in push case since it reduces resource consumption in the collection and storage space needed for retention. In Pull case, it just saves you disk space and some resources for more complex queries.&lt;/p&gt;

&lt;h3 id=&quot;tracing&quot;&gt;Tracing&lt;/h3&gt;

&lt;p&gt;As the data boom hit the industry it did not miss the observability of stuff we are building. Now we can expose every small detail about the long term behavior of our app in the form of a huge amount of data that tracks any request end to end, even in distributed systems.&lt;/p&gt;

&lt;p&gt;The main difference between the two large-volume observabilities is that logs in their essence represent a collection of individual events and traces are designed to represent set of connected events and their holistic picture for further analysis. The base of tracing observability is code instrumentation and there are many ways it is done (including connecting log events using request ids), but the currently accepted global standard is OpenTracing API (now part of OpenTelemetry).&lt;/p&gt;

&lt;p&gt;Two tools to mention are Zipkin and Jaeger, developed by Twitter and Uber respectively, both using OpenTracing API and both supporting every programming language in almost every form (framework) out there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zipkin&lt;/strong&gt; is simpler to deploy a more conventional client-server collection system that is oriented towards less complex, non-container-orchestrated systems. &lt;strong&gt;Jaeger&lt;/strong&gt; is more complex, distributed tracing oriented, and preferably deployed to Kubernetes.&lt;/p&gt;

&lt;h4 id=&quot;in-the-wild-3&quot;&gt;In the Wild&lt;/h4&gt;

&lt;p&gt;Tracing tools logically need more complex setups in their backends with fast databases, map/reduce systems, and special scaling needs in order to provide us with the best trace grouping and analysis capability. These are always complex systems of many small and big components to deploy and maintain across the space.&lt;/p&gt;

&lt;p&gt;In return, we get the ability to see requests travel through our system, and the capability to identify the exact place where any of the erroneous ones failed and which logs the failure produced etc…&lt;/p&gt;

&lt;p&gt;Data inflation!&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Logs have all the data, but you need a delivery system, database, indexing, and search/dashboard tool in order to be able to use them beyond merely skimming the text in a file on a disk somewhere&lt;/li&gt;
  &lt;li&gt;Metrics do not have too much data but they provide an essential way of measuring your system’s performance and reacting to it in real-time&lt;/li&gt;
  &lt;li&gt;Tracing is giving us deep insight into the system’s behavior, and holistic analysis of every request. Price is a complex system to gather, store, analyze, and store to be searched and visualized.&lt;/li&gt;
  &lt;li&gt;Prometheus is the best&lt;/li&gt;
  &lt;li&gt;Use Grafana.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;ps&quot;&gt;P.S.&lt;/h2&gt;

&lt;p&gt;This was written as a separate article since the author realized that intro to another observability article that had been written can actually be planning and tools insight guide for a broader audience — aiming for all specialties like engineers, architects, tech POs, QA engineers… Hopefully it worked :D&lt;/p&gt;
</description>
        <pubDate>Sat, 29 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/sre/observability/monitoring/logging/analytics/microservices/kubernetes/basics/2020/08/29/planning-observability-monitoring-analytics.html</link>
        <guid isPermaLink="true">https://rastko.tech/sre/observability/monitoring/logging/analytics/microservices/kubernetes/basics/2020/08/29/planning-observability-monitoring-analytics.html</guid>
      </item>
    
      <item>
        <title>Software in Time of Apocalypse</title>
        <description>&lt;p&gt;In the current moment, amid the COVID-19 crisis, isolation and heavy reliance on software for work, communication, entertainment, wellbeing, and information have made it increasingly difficult to comprehend the evolution of software perception over the last 10-15 years.&lt;/p&gt;

&lt;p&gt;Only nine years before this essay, Marc Andreessen published his influential piece on why software was consuming the world. At that time, Netflix, Uber, and Airbnb were already transforming commerce, though the full scope of digital disruption was still unfolding. Software rapidly altered the commercial landscape, bringing businesses online and enabling new service-based models.&lt;/p&gt;

&lt;h2 id=&quot;nowhere-to-run&quot;&gt;Nowhere to Run&lt;/h2&gt;

&lt;p&gt;Now facing global pandemic and physical isolation, society is confronting an unfamiliar need: to persist, sustain life in its best form, and prioritize wellness above all else. The author describes this moment as “the great pause”—a time when people cannot escape into constant activity.&lt;/p&gt;

&lt;p&gt;The pause has shifted purchasing patterns away from experiences like concerts and rideshare services toward goods like furniture, flowers, food, and record players. More significantly, it has encouraged genuine human connection, both with ourselves and others.&lt;/p&gt;

&lt;h2 id=&quot;new-digital-wave&quot;&gt;New Digital Wave&lt;/h2&gt;

&lt;p&gt;A profound wave of digital transformation is occurring. Small businesses are rapidly establishing web shops. Museums and galleries are launching virtual tours. Painting lessons, film festivals, and theater productions are being streamed online. Musicians perform free shows to global audiences from their homes.&lt;/p&gt;

&lt;p&gt;Education has transformed through cloud-based systems, videos, games, and video calls. Children adapted immediately to Zoom classrooms and Google Meet gatherings, maintaining social interaction despite physical distance.&lt;/p&gt;

&lt;h2 id=&quot;a-proper-wellness&quot;&gt;A Proper Wellness&lt;/h2&gt;

&lt;p&gt;Remote yoga sessions, Instagram live streams of meaningful content, guided meditations, and online therapy services have proliferated. Cooking tutorials, fitness challenges, and wellness content that previously remained niche now serve genuine needs rather than marketing-driven desires.&lt;/p&gt;

&lt;p&gt;The author observes that people are learning what they need to be well through digital means—ancient meditation practices alongside modern fitness programs, dancing therapies, and virtual fitness challenges.&lt;/p&gt;

&lt;h2 id=&quot;after-the-great-pause&quot;&gt;After the Great Pause&lt;/h2&gt;

&lt;p&gt;This pandemic represents a learning experience about our greatest modern invention: software and digital transformation. Society is realizing that the same tools used to accelerate consumption and sensory overload can facilitate healing and connection.&lt;/p&gt;

&lt;p&gt;The crucial insight: “Screens we are looking at are not the problem — we are the problem. Screens were not alienating us, it was us who were alienating us.” Now, stuck to screens more than ever, people use them for connection rather than isolation. Society has finally recognized that software serves human flourishing.&lt;/p&gt;
</description>
        <pubDate>Mon, 20 Apr 2020 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/essay/2020/04/20/software-in-time-of-apocalypse.html</link>
        <guid isPermaLink="true">https://rastko.tech/essay/2020/04/20/software-in-time-of-apocalypse.html</guid>
      </item>
    
      <item>
        <title>Un-busy Your Team</title>
        <description>&lt;h2 id=&quot;the-rituals&quot;&gt;The rituals&lt;/h2&gt;

&lt;p&gt;How many companies you know are doing “the agile”?&lt;/p&gt;

&lt;p&gt;How many are going through some kind of agile transformation at the moment?&lt;/p&gt;

&lt;p&gt;What are the rituals of your agile team? Do you have any?&lt;/p&gt;

&lt;p&gt;Did those rituals get added on top of your regular agenda or did they streamline it and “merge” it (in a sense)?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I know most of you are cringing by now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;the-sync&quot;&gt;The sync&lt;/h2&gt;

&lt;p&gt;Being in the tech industry for a while now, I got a pretty good understanding of how easy all the good process management and organizational ideas descend into the spiral of never ending syncs, reports, daily meetings… It all seems logical - to gain visibility of every small process, you have to have many meetings to align with everyone or read same amount of reports. Small price to pay to gain transparency and agility.&lt;/p&gt;

&lt;p&gt;And when we achieve nothing, which is logical result of not doing anything, we conclude that we need the retrospective. Or even better — &lt;strong&gt;a few retrospectives&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But, is not doing anything actually the worst thing about it? What does it mean “to do” in this case?&lt;/p&gt;

&lt;h2 id=&quot;the-team&quot;&gt;The team&lt;/h2&gt;

&lt;p&gt;In our industry (any engineering and science, really, but let’s stick to what we know) your team is your “think tank”, it is carefully chosen group of talented people who have tools to do &lt;em&gt;the job&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And the job is … problem solving, creating, hacking… It is fight for that new idea, for knowledge and inspiration.&lt;/p&gt;

&lt;h2 id=&quot;irq&quot;&gt;IRQ&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;In a computer, an interrupt request is a hardware signal sent to the processor that temporarily stops a running program and allows a special program, an interrupt handler, to run instead. Hardware interrupts are used to handle events such as receiving data from a modem or network card, key presses, or mouse movements.&lt;/p&gt;

  &lt;p&gt;&lt;em&gt;Wikipedia (and any microprocessor architecture 101 course)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Interruption works more or less the same with people — you send a request for new piece of work, if it is perceived as more important current work will pause and new work will begin.&lt;/p&gt;

&lt;p&gt;However, no real life work is as simple and as straight forward to jump on as pre-processed, compiled and linked code sent straight to microprocessor that then does what it is best in. Microprocessor has queue for this stuff as well…&lt;/p&gt;

&lt;h2 id=&quot;the-busy&quot;&gt;The busy&lt;/h2&gt;

&lt;p&gt;When person is interrupted while working, by new piece of work or just new piece of information, many things happen cognitively and emotionally before we even get to doing some of it. When new communication comes in, especially if it is relate to other similar, but not the same piece of work, context change hits and, for some period of time, takes over significant part of our cognitive capacity. If this is, as it is usually the case, followed by emotional reaction due to being interrupted, we have significant negative impact on both cognitive capacity and spirit. People tend to be stressed out if ability to focus is taken away from them, or when priorities keep changing.&lt;/p&gt;

&lt;p&gt;This is where real problem is shaped — today, people are often busy even before they start doing something, and they sometimes stay so busy that they do not actually do anything… And in many cases it is our failure as leaders — we did not protect our teams from this.&lt;/p&gt;

&lt;h2 id=&quot;focus-at-work&quot;&gt;Focus at work&lt;/h2&gt;

&lt;p&gt;Focus is a lot about strategic choice, about systematically avoiding context switches. Shifting your mind from one thing to another cost us lowered productivity time — very often low productivity and high frustration periods.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;More precisely&lt;/strong&gt; — in most of the cases &lt;strong&gt;it costs us days of significantly lowered productivity every week&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;some-idle-time&quot;&gt;Some idle time&lt;/h2&gt;

&lt;p&gt;Make sure to know that having idle time is essential for creative work. Stopping your mind from racing, blurring the focus and just hanging around yields lots of beautiful thought processes. Idleness is in the root of EUREKA! moment.&lt;/p&gt;

&lt;p&gt;Your team needs focus and idleness, you need focus and idleness, your company’s mission and vision depends on your focus and idleness.&lt;/p&gt;

&lt;h2 id=&quot;the-busy-busy&quot;&gt;The busy busy&lt;/h2&gt;

&lt;p&gt;What, unfortunately, happens is that we are busy, which turns out to be quite the opposite to actually doing work.&lt;/p&gt;

&lt;p&gt;This phenomena is semi-recognized through quite proverbially paraphrasing “Busy is a new stupid” everywhere and trying to make some sense out of our schedules and how to effectively manage our time.&lt;/p&gt;

&lt;h2 id=&quot;what-is-there-to-do-anyways&quot;&gt;What is there to do, anyways?&lt;/h2&gt;

&lt;p&gt;It is time to recognize the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Not all interruptions are work requests but all the interruptions are making your mind busy.&lt;/li&gt;
  &lt;li&gt;Not all time consuming tasks are work, but they are making you busy&lt;/li&gt;
  &lt;li&gt;You can not hack and create while you are busy, unless you are busy hacking and creating.&lt;/li&gt;
  &lt;li&gt;You can not learn new thing while you are busy, unless you are busy learning.&lt;/li&gt;
  &lt;li&gt;When you stop being busy, your mind needs time to settle before becoming creative (not to mention sugar).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;leaders&quot;&gt;Leaders&lt;/h2&gt;

&lt;p&gt;It is job of a leader to make sure things are moving forward, motivating team and finding that spark that puts everyone where they want to be. You got to know where everyone wants to be and what everyone wants to do.&lt;/p&gt;

&lt;p&gt;Additionally, leader needs to get team’s work where it needs to be according to general vision. Vision, marching orders — tomayto, tomahto… Your only job is to enable everyone in the team to be their best selves, to focus, move forward and thrive. Leader should protect the team from distractions in order to let them do what they do best.&lt;/p&gt;

&lt;p&gt;All in all it is rather &lt;em&gt;conundrum-a-day&lt;/em&gt; then &lt;em&gt;I-got-this situation&lt;/em&gt;, but one thing is certain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In order to be able to do everything that needs to be done, we have to help team be less busy.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our teams of engineers and creatives need to not be busy. We need to commit our time to protect the precious minds that create our worlds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We need to unbusy our teams.&lt;/strong&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 27 Oct 2019 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/essay/agile/2019/10/27/unbusy-your-team.html</link>
        <guid isPermaLink="true">https://rastko.tech/essay/agile/2019/10/27/unbusy-your-team.html</guid>
      </item>
    
      <item>
        <title>Internal and External Connectivity in Kubernetes Space</title>
        <description>&lt;p&gt;As you navigate through your application’s development stages and consider Kubernetes deployment, understanding how components connect internally and externally becomes essential.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Knowledge you will get from this article also covers ‘services &amp;amp; networking’ part of CKAD exam, which currently takes 13% of the certification exam curriculum.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;services&quot;&gt;Services&lt;/h2&gt;

&lt;p&gt;Kubernetes services enable networking between cluster components and external systems. The article covers three main types:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NodePort&lt;/strong&gt; — Exposes pods through a node’s port, involving three port layers:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;targetPort (application listening port)&lt;/li&gt;
  &lt;li&gt;Port (service port)&lt;/li&gt;
  &lt;li&gt;NodePort (external access port, range 30000-32767)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example NodePort service:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Service&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;k8s-nodeport-service&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;NodePort&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;targetPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;6379&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;6379&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;NodePort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;30666&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Services use &lt;strong&gt;selectors&lt;/strong&gt; to link to pod sets, functioning as load balancers distributing traffic randomly across matching pods.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ClusterIP&lt;/strong&gt; — Provides internal cluster communication through unified IP/name for pod groups, preventing instability from pod recreation and eliminating manual load-balancing complexity.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Service&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;api-1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ClusterIP&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;targetPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;9090&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;9090&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;api-1&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;backend&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;ClusterIP serves as the default service type when unspecified.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LoadBalancer&lt;/strong&gt; — Provisions external cloud load balancers with advanced features and standard port mapping. Each exposed service requires its own load balancer, potentially increasing complexity and costs.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Service&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;lb1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;externalTrafficPolicy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Local&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;LoadBalancer&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;80&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;targetPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;80&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TCP&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http&lt;/span&gt;
 &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;443&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;targetPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;443&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TCP&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;lb1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;“The external traffic will not be equally load balanced across pods, but rather equally balanced at the node level.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;ingress&quot;&gt;Ingress&lt;/h2&gt;

&lt;p&gt;Managing multiple web servers with different pod sets using traditional services becomes complex in real-world scenarios. This complexity motivated Kubernetes to introduce &lt;strong&gt;Ingress&lt;/strong&gt; as a Layer 7 load balancer solution.&lt;/p&gt;

&lt;p&gt;Ingress provides load balancing, SSL termination, and name-based virtual hosting for HTTP/HTTPS traffic.&lt;/p&gt;

&lt;h3 id=&quot;ingress-controller-setup&quot;&gt;Ingress Controller Setup&lt;/h3&gt;

&lt;p&gt;Two components are necessary:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Ingress Controller&lt;/strong&gt; — Manages ingress rules (nginx, GCE officially supported)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Ingress Resources&lt;/strong&gt; — Defines HTTP routing rules&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example nginx ingress controller deployment:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;extensions/v1beta1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Deployment&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx-ingress-controller&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;replicas&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;matchLabels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx-ingress&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx-ingress&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;containers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx-ingress-controller&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;quay.io/kubernetes-ingress-controller/nginx-ingress-controller&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/nginx-ingress-controller&lt;/span&gt;
     &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;configMap=$(POD_NAMESPACE)/ingress-config&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;POD_NAME&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;valueFrom&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;fieldRef&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;fieldPath&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;metadata.name&lt;/span&gt;
     &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;POD_NAMESPACE&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;valueFrom&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;fieldRef&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;fieldPath&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;metadata.namespace&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;containerPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;80&lt;/span&gt;
     &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;containerPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;443&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;ConfigMap deployment:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ConfigMap&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx-configuration&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A NodePort service exposes the ingress controller:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Service&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx-ingress&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;NodePort&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;-targetPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;80&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;80&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TCP&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;-targetPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;433&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;433&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TCP&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx-ingress&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Service accounts require specific permissions:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ServiceAccount&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;matadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx-ingress-serviceaccount&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;ingress-resources&quot;&gt;Ingress Resources&lt;/h3&gt;

&lt;p&gt;Simple ingress routing all traffic to one service:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;extensions/v1beta1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Ingress&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;simple-api-ingress&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;serviceName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;simple-api-service&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;servicePort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Path-based routing example:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;extensions/v1beta1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Ingress&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;proper-api-ingress&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;-http&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;-path&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/api/search&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;serviceName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;search-api-service&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;servicePort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8081&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;-path&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/api&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;serviceName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;api-service&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;servicePort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8080&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;-path&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;serviceName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;frontend-service&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;servicePort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8082&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Host-based routing with subdomains:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;extensions/v1beta1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Ingress&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;proper-api-ingress&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;-host&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;api.example.com&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;-path&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/search&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;serviceName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;search-api-service&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;servicePort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8081&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;-path&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;serviceName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;api-service&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;servicePort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8080&lt;/span&gt;
 &lt;span class=&quot;na&quot;&gt;-host&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;app.example.com&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;-path&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;serviceName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;frontend-service&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;servicePort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8082&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The article emphasizes maintaining all configurations as code in version control repositories, following infrastructure-as-code principles for application reliability.&lt;/p&gt;
</description>
        <pubDate>Sat, 13 Jul 2019 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/kubernetes/2019/07/13/services-and-networking.html</link>
        <guid isPermaLink="true">https://rastko.tech/kubernetes/2019/07/13/services-and-networking.html</guid>
      </item>
    
      <item>
        <title>Local Kubernetes Setup with Minikube on Mac OS X</title>
        <description>&lt;p&gt;Minikube serves as an excellent tool for establishing a local Kubernetes environment to test and experiment with deployments. This guide walks through installation, configuration, and integration with essential tools.&lt;/p&gt;

&lt;h2 id=&quot;minikube-installation&quot;&gt;Minikube Installation&lt;/h2&gt;

&lt;p&gt;Minikube operates through a virtual machine and supports various hypervisor options. VirtualBox is the recommended choice for macOS.&lt;/p&gt;

&lt;p&gt;Installation via Homebrew:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew cask &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;virtualbox minikube
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;macOS security features may block VirtualBox installation on Mojave and later versions. Access &lt;strong&gt;System Preferences &amp;gt; Security &amp;amp; Privacy&lt;/strong&gt; and approve Oracle software installation on the General tab before rerunning the installation command.&lt;/p&gt;

&lt;h2 id=&quot;running-and-accessing-the-cluster&quot;&gt;Running and Accessing the Cluster&lt;/h2&gt;

&lt;p&gt;Start the minikube cluster with:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;minikube start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Stop the cluster when not in use to conserve battery life:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;minikube stop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Access the Kubernetes dashboard:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;minikube dashboard
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For users managing multiple cluster contexts, list and switch to minikube:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kubectl config get-contexts
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kubectl config use-context minikube
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;ingress-controller&quot;&gt;Ingress Controller&lt;/h2&gt;

&lt;p&gt;Enable the ingress add-on for deployments requiring ingress resources:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;minikube addons &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;ingress
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Configure local hostnames in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/hosts&lt;/code&gt; to match ingress rules:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;minikube ip&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; local.host&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; /etc/hosts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;container-registry&quot;&gt;Container Registry&lt;/h2&gt;

&lt;h3 id=&quot;local-docker-registry&quot;&gt;Local Docker Registry&lt;/h3&gt;

&lt;p&gt;Point your Docker context to minikube:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;minikube docker-env&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To revert: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ eval $(docker-machine env -u)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Start a local registry container:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 5000:5000 &lt;span class=&quot;nt&quot;&gt;--restart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;always &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; registry registry:2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Build and tag images for local registry:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker build &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; &amp;lt;your_tag&amp;gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker tag &amp;lt;your_tag&amp;gt; localhost:5000/&amp;lt;your_tag&amp;gt;:&amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost:5000/&amp;lt;your_tag&amp;gt;:&amp;lt;version&amp;gt;&lt;/code&gt; as the image reference in deployments.&lt;/p&gt;

&lt;h3 id=&quot;remote-container-repository&quot;&gt;Remote Container Repository&lt;/h3&gt;

&lt;p&gt;For remote repositories (ECR, GCR, Docker Registry), use the registry-creds addon for authentication:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;minikube addons configure registry-creds
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;minikube addons &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;registry-creds
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note on ECR:&lt;/strong&gt; If using AWS ECR without a role ARN, provide a placeholder value like “changeme” rather than leaving it blank to prevent deployment failures.&lt;/p&gt;

&lt;p&gt;Reference the pull secret in deployments:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;imagePullSecrets&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;awsecr-cred&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;helm&quot;&gt;Helm&lt;/h2&gt;

&lt;p&gt;Helm functions as a package manager and configuration tool for Kubernetes. Installation and initialization:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;kubernetes-helm
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;helm init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Helm currently uses Tiller as its backend, deployed during initialization. Verify deployment with:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kubectl describe deploy tiller-deploy &lt;span class=&quot;nt&quot;&gt;--namespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kube-system
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This setup provides a complete local Kubernetes environment for testing deployments before production deployment.&lt;/p&gt;
</description>
        <pubDate>Tue, 01 Jan 2019 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/kubernetes/2019/01/01/minikube-on-mac.html</link>
        <guid isPermaLink="true">https://rastko.tech/kubernetes/2019/01/01/minikube-on-mac.html</guid>
      </item>
    
      <item>
        <title>Building General Purpose Blockchain</title>
        <description>&lt;blockquote&gt;
  &lt;p&gt;towards blockchain solution for any micro service ecosystems&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The author describes an academic experiment to develop a general-purpose blockchain system that goes beyond introductory tutorials. The goal is creating a blockchain that functions as a supplementary backend component within multi/microservice architectures, removing single points of failure while strengthening data security through decentralization and replication.&lt;/p&gt;

&lt;h2 id=&quot;what-is-general-purpose-blockchain&quot;&gt;What is General Purpose Blockchain&lt;/h2&gt;

&lt;p&gt;The author references extensive documentation resources and notes the industry is still defining blockchain’s actual use cases beyond financial applications. They propose that blockchain functions as specialized storage for sensitive data and transactions, integrated with existing microservice ecosystems through command and event buses.&lt;/p&gt;

&lt;h2 id=&quot;base-set-of-features&quot;&gt;Base Set of Features&lt;/h2&gt;

&lt;h3 id=&quot;tool-not-star&quot;&gt;Tool, Not Star&lt;/h3&gt;

&lt;p&gt;The solution should be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Easy to deploy&lt;/li&gt;
  &lt;li&gt;Highly configurable to adapt to system needs&lt;/li&gt;
  &lt;li&gt;Simple to integrate via RESTful API&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;multiple-consensus-algorithms&quot;&gt;Multiple Consensus Algorithms&lt;/h3&gt;

&lt;p&gt;The author recommends supporting several approaches:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;PoW&lt;/strong&gt; (Proof-of-work): Computationally challenging to create but easy to verify&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DPoS&lt;/strong&gt; (Delegated proof-of-stake): Representative nodes chosen by network clusters&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DBC&lt;/strong&gt; (Delegated block creation): Scheduled resource consumption for private networks&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;multi-chain-capability&quot;&gt;Multi-chain Capability&lt;/h3&gt;

&lt;p&gt;Support for multiple, differently-structured chains within a single application.&lt;/p&gt;

&lt;h3 id=&quot;denormalization&quot;&gt;Denormalization&lt;/h3&gt;

&lt;p&gt;Convert blockchain data into conventional databases or reporting systems.&lt;/p&gt;

&lt;h3 id=&quot;built-in-encryption&quot;&gt;Built-in Encryption&lt;/h3&gt;

&lt;p&gt;Default encryption with configurable field-level protection.&lt;/p&gt;

&lt;h3 id=&quot;devops-integration&quot;&gt;DevOps Integration&lt;/h3&gt;

&lt;p&gt;Docker support, manifests, and versioned API contracts.&lt;/p&gt;

&lt;h3 id=&quot;administrative-features&quot;&gt;Administrative Features&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Thin UI for user management, chain forking, encryption control&lt;/li&gt;
  &lt;li&gt;Analytics dashboard tracking usage, chain sizes, and performance metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;nice-to-have-features&quot;&gt;Nice-to-Have Features&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Custom code execution (“contracts”)&lt;/li&gt;
  &lt;li&gt;Socket integration&lt;/li&gt;
  &lt;li&gt;CLI client&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;implementation-approach&quot;&gt;Implementation Approach&lt;/h2&gt;

&lt;p&gt;The author notes the project exists at https://github.com/metaphorical/quantum-blockchain with documentation, Trello board, and contribution guidelines. Development continues part-time toward an MVP version 1.0, welcoming community contributors.&lt;/p&gt;
</description>
        <pubDate>Sun, 08 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/blockchain/opensource/project/python/programming/2018/07/08/building-general-purpose-blockchain.html</link>
        <guid isPermaLink="true">https://rastko.tech/blockchain/opensource/project/python/programming/2018/07/08/building-general-purpose-blockchain.html</guid>
      </item>
    
      <item>
        <title>Blockchain as a Solution — Not the Blockchain Guide You Want, But the One You Deserve</title>
        <description>&lt;p&gt;This is part two of a short blockchain series. The first article explored foundational concepts in cryptocurrency.&lt;/p&gt;

&lt;h2 id=&quot;blockchain-as-a-niche-of-safety&quot;&gt;Blockchain as a Niche of Safety&lt;/h2&gt;

&lt;p&gt;The author emphasizes timing’s importance in technology adoption. Artificial neural networks, though 75 years old as a computational model, only became practically viable when supporting infrastructure matured sufficiently. This same perspective applies to blockchain’s future applications—some are currently feasible while others await further technological development.&lt;/p&gt;

&lt;h2 id=&quot;death-taxes-and-real-estate--break-free-from-bureaucracy&quot;&gt;Death, Taxes and Real Estate — Break Free From Bureaucracy&lt;/h2&gt;

&lt;p&gt;Public records worldwide suffer from inconsistencies: missing ownership documentation, vague tax recordings, and tampered birth/death records. Access control remains problematic—who can view public real estate data, who grants access, and how is it managed?&lt;/p&gt;

&lt;p&gt;Blockchain addresses these concerns through its original design. The technology emerged as a solution for notary databases and has since evolved into its current form.&lt;/p&gt;

&lt;h2 id=&quot;keeping-track-of-changes--untouchable-data&quot;&gt;Keeping Track of Changes — Untouchable Data&lt;/h2&gt;

&lt;p&gt;Real estate functions primarily as an investment, making ownership history critical. This information requires privacy protection despite regulatory oversight. Public notification should only occur when properties are in transition or dispute.&lt;/p&gt;

&lt;p&gt;In a typical transaction, data keys exchange between parties to verify property value and ownership details. Once confirmed, a validation process checks for irregularities, disputes, or conditions affecting the transaction. Upon clearing all checks, new ownership records on the blockchain while other transaction elements (money transfer, etc.) occur outside it.&lt;/p&gt;

&lt;p&gt;For birth, marriage, and death certificates, blockchain provides clean, immutable records without requiring extensive node networks—though crucially, different stakeholders must operate separate nodes.&lt;/p&gt;

&lt;h2 id=&quot;tax-collection-and-insurance-claims--triggering-the-actions&quot;&gt;Tax Collection and Insurance Claims — Triggering the Actions&lt;/h2&gt;

&lt;p&gt;Taxation and insurance present greater complexity. Beyond storing untouchable data, meaningful system improvements require substantial development. Major insurance companies and governments are researching this space through initiatives like the b3i blockchain initiative and China’s blockchain tax research.&lt;/p&gt;

&lt;p&gt;Current research centers on Ethereum’s “smart contracts”—the blockchain’s capacity to execute preprogrammed actions when specific conditions materialize.&lt;/p&gt;

&lt;h2 id=&quot;global-distribution-of-local-controls&quot;&gt;Global Distribution of Local Controls&lt;/h2&gt;

&lt;p&gt;Implementation requires interconnected blockchain networks operating at global scale, performing varied validations and inter-network exchanges to determine conditions for executing complex financial contracts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consider this scenario:&lt;/strong&gt; A person relocates mid-year, changing employment and residence while tax obligations span two countries with different regulations. Birth records transfer to residence-processing blockchains, connecting visa dates to contract dates. Taxation blockchains exchange data applying new rules. Identity data links to newly formed files in global private record systems. The complete system recalculates, validates, stores, and executes tax returns accounting for work in multiple jurisdictions, potentially including property ownership and recent mortgages.&lt;/p&gt;

&lt;p&gt;“It would just require you to request this change with your private encryption key (which can be retinal scan).” This thought experiment, while technologically feasible, requires unrealistic expectations regarding coordination.&lt;/p&gt;

&lt;p&gt;The future likely involves either distributed global networks providing granular role-based access to private and governmental data ledgers, or centralized global governance. Neither scenario appears imminent.&lt;/p&gt;

&lt;p&gt;“Bare in mind that it took several months (maybe even years?) for people to adopt P2P networks as a way to safely download entertainment content.” Implementing more complex, less essential systems will require decades (assuming humanity avoids self-destruction).&lt;/p&gt;

&lt;h2 id=&quot;every-day-blockchain-application--importance-of-truth&quot;&gt;Every Day Blockchain Application — Importance of Truth&lt;/h2&gt;

&lt;p&gt;Modern commerce and other sectors require enhanced auditing, verification, and event tracking reliability. Current experiments aim to integrate blockchain into these areas, providing greater trustworthiness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Humanitarian Aid:&lt;/strong&gt; This sector desperately needs spending controls, transport verification, and origin-to-destination tracking. Blockchain could provide secure, distributed identity solutions benefiting UN bodies, NGOs, and international organizations. Progress appears slow, though UNICEF members have discussed blockchain with experts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fair Trade and Direct Trade:&lt;/strong&gt; These initiatives’ core purpose involves maintaining records proving products benefit their producers directly. Distributed data systems can verify complete product paths from production through distribution. However, “Educating people to reward fair and direct trade products can’t be handled through blockchain.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Organic Food:&lt;/strong&gt; Similar tracking applies here, emphasizing locations, seeds, fertilizers, and distribution networks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Freshness:&lt;/strong&gt; Shelf time significantly affects fruit, vegetable, and flower pricing. This domain sees substantial data forgery due to financial incentives. Major US food retailers support blockchain initiatives for tracking and automatic expiration recall.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vehicle History:&lt;/strong&gt; Mileage, maintenance records, and tune-ups present persistent tracking challenges, particularly regarding odometer fraud during vehicle sales.&lt;/p&gt;

&lt;p&gt;Virtually any sector requiring reliable, immutable, distributed databases could benefit from blockchain implementation.&lt;/p&gt;

&lt;h2 id=&quot;blockchain-beyond-database--remember-seti&quot;&gt;Blockchain Beyond Database — Remember SETI&lt;/h2&gt;

&lt;p&gt;Code execution during block creation enables distributed computing. Ethereum and similar implementations allow blockchain node operators to opt into code execution participation.&lt;/p&gt;

&lt;p&gt;Current applications primarily involve contracts—checking network condition satisfaction before executing inter-party transactions. However, blockchain-based code execution could revive projects like SETI@home. Many SETI@home volunteers redirected computing power toward Bitcoin and cryptocurrency mining, but distributed systems could theoretically provide supercomputer-scale processing for scientific endeavors globally.&lt;/p&gt;

&lt;p&gt;Technical maturity obstacles remain significant.&lt;/p&gt;

&lt;h2 id=&quot;cryptocurrencies-are-the-solution-and-a-problem&quot;&gt;Cryptocurrencies Are the Solution and a Problem&lt;/h2&gt;

&lt;p&gt;Cryptocurrencies enable important technological concepts addressing major gaps, but progress carries costs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Direct Cost:&lt;/strong&gt; Freedom and anonymity generate illegal marketplaces for drug trafficking, weapons, hired violence, human trafficking, and worse. The Silk Road marketplace exemplified this problem. The FBI seized over 200,000 Bitcoin from it—representing one direct cost of progress.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hidden Cost:&lt;/strong&gt; The cryptocurrency community should consolidate technologies and resources. Thousands of currencies cannot address Bitcoin mining’s energy inefficiency. Mining remains computationally intensive, with processors consuming maximum power.&lt;/p&gt;

&lt;p&gt;“Bitcoin mining in the world is consuming almost as much power as Switzerland.” This year’s consumption likely exceeds Switzerland’s total energy use. Since mining concentrates in low-electricity-cost regions burning coal for power generation, Bitcoin carries a substantially larger carbon footprint than Switzerland.&lt;/p&gt;

&lt;p&gt;“Our children do not need Bitcoin (crypto currencies in general) if mining does not get lot more energy optimized, but I think they can find pretty good use for a blockchain based solutions.” Blockchain research and adoption remain essential, necessitating continued field exploration.&lt;/p&gt;
</description>
        <pubDate>Wed, 28 Feb 2018 00:00:00 +0000</pubDate>
        <link>https://rastko.tech/blockchain/2018/02/28/the-blockchain-guide-you-want.html</link>
        <guid isPermaLink="true">https://rastko.tech/blockchain/2018/02/28/the-blockchain-guide-you-want.html</guid>
      </item>
    
  </channel>
</rss>
