<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>kube-proxy on Digi Hunch</title><link>https://static.digihunch.com/tag/kube-proxy/</link><description>Recent content in kube-proxy on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Sat, 11 Jan 2025 21:16:19 -0500</lastBuildDate><atom:link href="https://static.digihunch.com/tag/kube-proxy/index.xml" rel="self" type="application/rss+xml"/><item><title>Certified Kubernetes Administrator (CKA) Exam</title><link>https://static.digihunch.com/2021/04/preparing-certified-kubernetes-administrator-exam/</link><pubDate>Fri, 30 Apr 2021 09:50:00 -0400</pubDate><guid>https://static.digihunch.com/2021/04/preparing-certified-kubernetes-administrator-exam/</guid><description>&lt;p class="wp-block-paragraph"&gt;The Certified Kubernetes Administrator (CKA) exam is a hands-on session where you need to follow the instructions to configure the system in a bash terminal on the web browser. In my experience, some shortcut keys (such as Alt+F) do not work, which slows me down a little bit. For each question, you need to switch kubectl context as instructed in the question. Some questions share the same context so it is very easy to omit this step. You can verify response with your own command but will not be told whether you scored in each question. During the CKA exam I tried to spin up a terminal session from within &lt;a href="https://static.digihunch.com/2019/10/personal-vim-cheatsheet/"&gt;Vim&lt;/a&gt; editor and the terminal ran out of buffer. I had to reboot the machine with the help of proctor, and my completed work are saved.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="1405" height="121" src="https://static.digihunch.com/wp-content/uploads/2021/05/image.png" alt="" class="wp-image-2266"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In general this is an exam I enjoy preparing and writing because it is very hands on. Result is out a day after, and I passed at 96%. I heard about tight timelines but I managed to finish 15 minutes before the end, most likely owing to my dexterity with Linux commands. With that I&amp;#8217;m happy to share my notes in preparation for the CKA exam.&lt;/p&gt;&#10;&lt;p class="has-white-background-color has-background wp-block-paragraph"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="590px" viewBox="-0.5 -0.5 590 638" style="max-width:100%;max-height:638px;"&gt;&lt;defs&gt;&lt;/defs&gt;&lt;g&gt;&lt;rect x="0" y="347" width="170" height="290" rx="25.5" ry="25.5" fill="#fff2cc" stroke="#d6b656" stroke-dasharray="3 3" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 168px; height: 1px; padding-top: 344px; margin-left: 1px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; font-weight: bold; background-color: #ffffff; white-space: normal; word-wrap: normal; "&gt;Worker Node&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="85" y="344" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle" font-weight="bold"&gt;Worker Node&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="10" y="377" width="150" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 148px; height: 1px; padding-top: 392px; margin-left: 11px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kube-proxy&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="85" y="396" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kube-proxy&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="10" y="427" width="150" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 148px; height: 1px; padding-top: 442px; margin-left: 11px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kubelet&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="85" y="446" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kubelet&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="10" y="477" width="150" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 148px; height: 1px; padding-top: 492px; margin-left: 11px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container runtime&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="85" y="496" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container runtime&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 85 457 L 85 477 L 85 457 L 85 470.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 85 475.88 L 81.5 468.88 L 85 470.63 L 88.5 468.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;rect x="10" y="527" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 537px; margin-left: 11px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="45" y="541" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="90" y="527" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 537px; margin-left: 91px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="125" y="541" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="10" y="557" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 567px; margin-left: 11px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="45" y="571" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="90" y="557" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 567px; margin-left: 91px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="125" y="571" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="10" y="587" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 597px; margin-left: 11px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="45" y="601" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="90" y="587" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 597px; margin-left: 91px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="125" y="601" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="190" y="347" width="170" height="290" rx="25.5" ry="25.5" fill="#fff2cc" stroke="#d6b656" stroke-dasharray="3 3" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 168px; height: 1px; padding-top: 344px; margin-left: 191px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; font-weight: bold; background-color: #ffffff; white-space: normal; word-wrap: normal; "&gt;Worker Node&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="275" y="344" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle" font-weight="bold"&gt;Worker Node&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="200" y="377" width="150" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 148px; height: 1px; padding-top: 392px; margin-left: 201px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kube-proxy&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="275" y="396" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kube-proxy&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="200" y="427" width="150" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 148px; height: 1px; padding-top: 442px; margin-left: 201px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kubelet&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="275" y="446" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kubelet&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="200" y="477" width="150" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 148px; height: 1px; padding-top: 492px; margin-left: 201px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container runtime&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="275" y="496" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container runtime&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 275 457 L 275 477 L 275 457 L 275 470.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 275 475.88 L 271.5 468.88 L 275 470.63 L 278.5 468.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;rect x="200" y="527" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 537px; margin-left: 201px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="235" y="541" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="280" y="527" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 537px; margin-left: 281px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="315" y="541" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="200" y="557" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 567px; margin-left: 201px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="235" y="571" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="280" y="557" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 567px; margin-left: 281px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="315" y="571" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="200" y="587" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 597px; margin-left: 201px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="235" y="601" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="280" y="587" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 597px; margin-left: 281px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="315" y="601" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="380" y="347" width="170" height="290" rx="25.5" ry="25.5" fill="#fff2cc" stroke="#d6b656" stroke-dasharray="3 3" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 168px; height: 1px; padding-top: 344px; margin-left: 381px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; font-weight: bold; background-color: #ffffff; white-space: normal; word-wrap: normal; "&gt;Worker Node&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="465" y="344" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle" font-weight="bold"&gt;Worker Node&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="390" y="377" width="150" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 148px; height: 1px; padding-top: 392px; margin-left: 391px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kube-proxy&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="465" y="396" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kube-proxy&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="390" y="427" width="150" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 148px; height: 1px; padding-top: 442px; margin-left: 391px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kubelet&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="465" y="446" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kubelet&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="390" y="477" width="150" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 148px; height: 1px; padding-top: 492px; margin-left: 391px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container runtime&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="465" y="496" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container runtime&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 465 457 L 465 477 L 465 457 L 465 470.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 465 475.88 L 461.5 468.88 L 465 470.63 L 468.5 468.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;rect x="390" y="527" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 537px; margin-left: 391px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="425" y="541" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="470" y="527" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 537px; margin-left: 471px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="505" y="541" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="390" y="557" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 567px; margin-left: 391px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="425" y="571" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="470" y="557" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 567px; margin-left: 471px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="505" y="571" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="390" y="587" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 597px; margin-left: 391px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="425" y="601" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="470" y="587" width="70" height="20" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 597px; margin-left: 471px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="505" y="601" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 546.37 392 L 570 392 Q 580 392 580 382 L 580 197 Q 580 187 570 187 L 431.37 187" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 541.12 392 L 548.12 388.5 L 546.37 392 L 548.12 395.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 426.12 187 L 433.12 183.5 L 431.37 187 L 433.12 190.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;rect x="10" y="17" width="460" height="250" rx="37.5" ry="37.5" fill="#dae8fc" stroke="#6c8ebf" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 458px; height: 1px; padding-top: 14px; margin-left: 11px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; font-weight: bold; white-space: normal; word-wrap: normal; "&gt;Control&amp;nbsp; Plane&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="240" y="14" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle" font-weight="bold"&gt;Control&amp;nbsp; Plane&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="30" y="37" width="200" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 44px; margin-left: 31px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kube-controller-manager&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="130" y="56" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kube-controller-manager&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="30" y="107" width="200" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 114px; margin-left: 31px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kube-scheduler&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="130" y="126" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kube-scheduler&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="40" y="47" width="200" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 54px; margin-left: 41px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kube-controller-manager&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="140" y="66" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kube-controller-manager&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="50" y="57" width="200" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 64px; margin-left: 51px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kube-controller-manager&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="150" y="76" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kube-controller-manager&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="40" y="117" width="200" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 124px; margin-left: 41px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kube-scheduler&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="140" y="136" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kube-scheduler&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="50" y="127" width="200" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 134px; margin-left: 51px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kube-scheduler&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="150" y="146" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kube-scheduler&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="30" y="187" width="200" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 194px; margin-left: 31px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;cloud-controller-manager&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="130" y="206" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;cloud-controller-manager&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="40" y="197" width="200" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 204px; margin-left: 41px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;cloud-controller-manager&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="140" y="216" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;cloud-controller-manager&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="50" y="207" width="200" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 214px; margin-left: 51px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;cloud-controller-manager&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="150" y="226" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;cloud-controller-manager&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="305" y="167" width="120" height="40" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 174px; margin-left: 306px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;kube-api-server&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="365" y="186" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;kube-api-server&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 335 55 C 335 44.33 395 44.33 395 55 L 395 99 C 395 109.67 335 109.67 335 99 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 335 55 C 335 63 395 63 395 55 M 335 59 C 335 67 395 67 395 59 M 335 63 C 335 71 395 71 395 63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 74px; margin-left: 336px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;etcd&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="365" y="86" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;etcd&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 254.25 76.75 L 330.75 162.25" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 250.75 72.83 L 258.02 75.72 L 254.25 76.75 L 252.8 80.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 334.25 166.17 L 326.98 163.28 L 330.75 162.25 L 332.2 158.62 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 255.8 219.36 L 299.2 199.64" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 251.02 221.54 L 255.94 215.45 L 255.8 219.36 L 258.84 221.83 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 303.98 197.46 L 299.06 203.55 L 299.2 199.64 L 296.16 197.17 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 255.37 145.42 L 299.63 173.58" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 250.94 142.6 L 258.73 143.41 L 255.37 145.42 L 254.97 149.31 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 304.06 176.4 L 296.27 175.59 L 299.63 173.58 L 300.03 169.69 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 365 113.37 L 365 160.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 365 108.12 L 368.5 115.12 L 365 113.37 L 361.5 115.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 365 165.88 L 361.5 158.88 L 365 160.63 L 368.5 158.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 546.37 442 L 570 442 Q 580 442 580 432 L 580 197 Q 580 187 570 187 L 431.37 187" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 541.12 442 L 548.12 438.5 L 546.37 442 L 548.12 445.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 426.12 187 L 433.12 183.5 L 431.37 187 L 433.12 190.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;/g&gt;&lt;switch&gt;&lt;g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;/g&gt;&lt;a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank" rel="noopener"&gt;&lt;text text-anchor="middle" font-size="10px" x="50%" y="100%"&gt;Viewer does not support full SVG 1.1&lt;/text&gt;&lt;/a&gt;&lt;/switch&gt;&lt;/svg&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For taking CKA exam, we should be familiar with the diagram above.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-tips-for-troubleshooting"&gt;Tips for Troubleshooting&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The CKA exam is hands-on and therefore requires quite a bit of troubleshooting. Here are my notes.&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Check Node status to start with&lt;/li&gt;&#10;&lt;li&gt;Check core services on each node:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;sudo systemctl status kubelet&lt;/li&gt;&#10;&lt;li&gt;sudo systemctl status docker&lt;/li&gt;&#10;&lt;li&gt;sudo journalctl -u kubelet&lt;/li&gt;&#10;&lt;li&gt;sudo journalctl -u docker&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Check component logs (on hosting VM)&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;/var/log/kube-apiserver.log&lt;/li&gt;&#10;&lt;li&gt;/var/log/kube-scheduler.log&lt;/li&gt;&#10;&lt;li&gt;/var/log/kube-controller-manager.log&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;If cluster is built by kubeadm, then some of those services are running in Pods within kube-system namespace. Check those pods:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;run interactive shell: &amp;gt; kubectl exec podname &amp;#8211;stdin &amp;#8211;tty &amp;#8212; /bin/sh&lt;/li&gt;&#10;&lt;li&gt;there is an image for lots of useful network tool called nicolaka/netshoot&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Store pod names to variable. e.g. &amp;gt; POD_NAME=$(kubectl get pods -l run=nginx -o jsonpath=&amp;#8221;{.items[0].metadata.name}&amp;#8221;)&lt;/li&gt;&#10;&lt;li&gt;With kubectl, you may&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;alias it to k for faster typing&lt;/li&gt;&#10;&lt;li&gt;&amp;#8211;dry-run: to run imperative command without creating object&lt;/li&gt;&#10;&lt;li&gt;&amp;#8211;record: record the command that was used to make a change&lt;/li&gt;&#10;&lt;li&gt;-o: set output format, wide, yaml, or jsonpath=&amp;#8221;expression&amp;#8221;. For example, to get pod name: &amp;gt; kubectl get pods -l run=nginx -o jsonpath=&amp;#8221;{.items[0].metadata.name}&amp;#8221;&lt;/li&gt;&#10;&lt;li&gt;&amp;#8211;sort-by: use JSONPath expression&lt;/li&gt;&#10;&lt;li&gt;&amp;#8211;selector: filter results &lt;strong&gt;by label&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 class="wp-block-heading" id="h-build-k8s-cluster-using-kubeadm"&gt;Build K8s cluster using kubeadm&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The CKA exam requires you to know how to build cluster with kubeadm. This involves installing four components (docker-ce, kubeadm, kubectl and kubelet), as outlined below:&lt;/p&gt;&#10;&lt;table id="tablepress-12" class="tablepress tablepress-id-12 tbody-has-connected-cells"&gt;&#10;&lt;thead&gt;&#10;&lt;tr class="row-1"&gt;&#10;&#9;&lt;th class="column-1"&gt;step&lt;/th&gt;&lt;th colspan="2" class="column-2"&gt;command&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody class="row-striping row-hover"&gt;&#10;&lt;tr class="row-2"&gt;&#10;&#9;&lt;td class="column-1"&gt;1. Install docker-ce&lt;/td&gt;&lt;td colspan="2" class="column-2"&gt;&gt; curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -&lt;br /&gt;&#10;&gt; sudo add-apt-repository \&lt;br /&gt;&#10; "deb [arch=amd64] https://download.docker.com/linux/ubuntu \&lt;br /&gt;&#10; $(lsb_release -cs) \&lt;br /&gt;&#10; stable"&lt;br /&gt;&#10;&gt; sudo apt-get update&lt;br /&gt;&#10;&gt; sudo apt-get install -y docker-ce=18.06.1~ce~3-0~ubuntu&lt;br /&gt;&#10;&gt; sudo apt-mark hold docker-ce&lt;br /&gt;&#10;&gt; sudo systemctl status docker&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-3"&gt;&#10;&#9;&lt;td class="column-1"&gt;2. Install kubeadm, kubelet and kubectl&lt;/td&gt;&lt;td colspan="2" class="column-2"&gt;&gt; curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -&lt;br /&gt;&#10;cat &lt;&lt; EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list&lt;br /&gt;&#10;deb https://apt.kubernetes.io/ kubernetes-xenial main&lt;br /&gt;&#10;EOF&lt;br /&gt;&#10;&gt; sudo apt-get update&lt;br /&gt;&#10;&gt; sudo apt-get install -y kubelet kubeadm kubectl&lt;br /&gt;&#10;&gt; sudo apt-mark hold kubelet kubeadm kubectl&lt;br /&gt;&#10;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-4"&gt;&#10;&#9;&lt;td class="column-1"&gt;3. Form a K8s cluster&lt;/td&gt;&lt;td class="column-2"&gt;On master node:&lt;br /&gt;&#10;&gt; sudo kubeadm init --pod-network-cidr=10.244.0.0/16&lt;br /&gt;&#10;This command prints out a command for worker nodes to join.&lt;br /&gt;&#10;&lt;/td&gt;&lt;td class="column-3"&gt;On worker node:&lt;br /&gt;&#10;sudo the command generated on master&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-5"&gt;&#10;&#9;&lt;td class="column-1"&gt;4. Configure kubectl&lt;/td&gt;&lt;td class="column-2"&gt;On master node:&lt;br /&gt;&#10;&gt; mkdir -p $HOME/.kube&lt;br /&gt;&#10;&gt; sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config&lt;br /&gt;&#10;&gt; sudo chown $(id -u):$(id -g) $HOME/.kube/config&lt;br /&gt;&#10;&lt;/td&gt;&lt;td class="column-3"&gt;Optionally on worker node:&lt;br /&gt;&#10;&gt; mkdir -p $HOME/.kube&lt;br /&gt;&#10;then scp $HOME/.kube/config from control plane node&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-6"&gt;&#10;&#9;&lt;td class="column-1"&gt;5. Set up cluster networking&lt;/td&gt;&lt;td colspan="2" class="column-2"&gt;&gt; echo "net.bridge.bridge-nf-call-iptables=1" | sudo tee -a /etc/sysctl.conf&lt;br /&gt;&#10;&gt; sudo sysctl -p&lt;br /&gt;&#10;Then from any environment with kubectl, bring up the system pods for cluster networking&lt;br /&gt;&#10;&gt; kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml&lt;br /&gt;&#10;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;!-- #tablepress-12 from cache --&gt;&#10;&lt;h3 class="wp-block-heading" id="h-add-new-node-to-kubeadm-cluster"&gt;Add new node to KubeAdm cluster&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This is fairly simple with the help of kubeadm. The node to join cluster must be able to communicate with master node. Create a token and print join command from master node:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; kubeadm token create --print-join-command&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then from the node to join, run this command &lt;strong&gt;as sudo&lt;/strong&gt;. You will see that it performs the TLS bootstrap for you. Once completed, the standard output will say this node has joined the cluster. You can confirm with command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; kubectl get nodes&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Sometimes one needs to migrate pods to the newly joined node. This can be done by draining the existing nodes.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note you can also use &lt;a href="https://github.com/kubernetes-sigs/kubespray" class="rank-math-link"&gt;kubespray &lt;/a&gt;to build K8s cluster as &lt;a href="https://static.digihunch.com/2020/12/instance-initialization-with-aws-cdk-in-python/" class="rank-math-link"&gt;previously &lt;/a&gt;discussed, and &lt;a href="https://github.com/digihunch/kubelab" class="rank-math-link"&gt;here &lt;/a&gt;is a my IaC project to launch AWS instances and build a K8s cluster with kubespray on top of it. For my learning, I often create a GKE (Google Kubernetes Engine) cluster from GCP&amp;#8217;s cloudshell. There is a &lt;a href="https://cloud.google.com/kubernetes-engine/docs/quickstart" class="rank-math-link"&gt;guide&lt;/a&gt; on how to start a cluster but it comes down to three commands:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ gcloud config set compute/zone us-east1-b&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ gcloud container clusters create tcluster --num-nodes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ gcloud container clusters get-credentials tcluster&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The third command above is to configure kubectl on the cloudshell. Follow &lt;a href="https://cloud.google.com/anthos/clusters/docs/on-prem/1.5/how-to/ssh-cluster-node" class="rank-math-link"&gt;this&lt;/a&gt; guide if you need to SSH to node.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-upgrade-kubeadm-cluster"&gt;Upgrade KubeAdm cluster&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/"&gt;This&lt;/a&gt; involves upgrade three components (kubeadm, kubectl and kubelet) on two types of node: master node and worker node. They steps vary slightly for two nodes. But drain and uncordon is needed for both types of nodes. Pick a node and follow the steps below:&lt;/p&gt;&#10;&lt;table id="tablepress-13" class="tablepress tablepress-id-13 tbody-has-connected-cells"&gt;&#10;&lt;thead&gt;&#10;&lt;tr class="row-1"&gt;&#10;&#9;&lt;th class="column-1"&gt;Step&lt;/th&gt;&lt;th colspan="2" class="column-2"&gt;Command&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody class="row-striping row-hover"&gt;&#10;&lt;tr class="row-2"&gt;&#10;&#9;&lt;td class="column-1"&gt;1. drain the node from kubectl client (e.g. master node)&lt;/td&gt;&lt;td colspan="2" class="column-2"&gt;&gt; sudo kubectl drain nodename --ignore-daemonsets&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-3"&gt;&#10;&#9;&lt;td class="column-1"&gt;2. Determine kubeadm target version&lt;/td&gt;&lt;td colspan="2" class="column-2"&gt;&gt; apt-mark showhold&lt;br /&gt;&#10;&gt; sudo apt-mark unhold kubeadm kubectl kubelet&lt;br /&gt;&#10;&gt; apt list --installed | grep kube&lt;br /&gt;&#10;&gt; apt-cache show kubeadm | less&lt;br /&gt;&#10;&gt; sudo apt-get install -y kubeadm=1.20.2-00&lt;br /&gt;&#10;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-4"&gt;&#10;&#9;&lt;td class="column-1"&gt;3. update kubeadm&lt;/td&gt;&lt;td class="column-2"&gt;On master node:&lt;br /&gt;&#10;&gt; sudo kubeadm upgrade plan v1.20.2&lt;br /&gt;&#10;&gt; sudo kubeadm upgrade apply v1.20.2&lt;br /&gt;&#10;&lt;/td&gt;&lt;td class="column-3"&gt;On worker node:&lt;br /&gt;&#10;&gt; sudo kubeadm upgrade node&lt;br /&gt;&#10;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-5"&gt;&#10;&#9;&lt;td class="column-1"&gt;4. On the node to update, determine target version for kubectl and kubelet, then install&lt;/td&gt;&lt;td colspan="2" class="column-2"&gt;&gt; apt-cache show kubectl | less&lt;br /&gt;&#10;&gt; apt-cache show kubelet | less&lt;br /&gt;&#10;&gt; sudo apt-get install -y kubectl=1.20.2-00 kubelet=1.20.2-00&lt;br /&gt;&#10;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-6"&gt;&#10;&#9;&lt;td class="column-1"&gt;5. Restart kubelet&lt;/td&gt;&lt;td colspan="2" class="column-2"&gt;&gt; sudo systemctl daemon-reload&lt;br /&gt;&#10;&gt; sudo systemctl restart kubelet&lt;br /&gt;&#10;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-7"&gt;&#10;&#9;&lt;td class="column-1"&gt;6. Uncordon&lt;/td&gt;&lt;td colspan="2" class="column-2"&gt;&gt; kubectl uncordon nodename&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;!-- #tablepress-13 from cache --&gt;&#10;&lt;h3 class="wp-block-heading" id="h-backup-and-restore-etcd"&gt;Backup and restore Etcd&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://etcd.io/"&gt;Etcd&lt;/a&gt; is a distributed key-value store. It uses Raft protocol for distributed consensus. Etcd is the third distributed system I touch on. The previous two are: Cassandra (using Paxos protocol for distributed consensus) and ZooKeeper (using ZAB protocol). &lt;a href="https://www.alibabacloud.com/blog/a-brief-analysis-of-consensus-protocol-from-logical-clock-to-raft_594675"&gt;Here&lt;/a&gt; is a good article that summarizes the protocols. As for the exam we only need to use etcd with the client tool.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The etcd itself can run on a cluster of servers, each running etcd as a systemd service as etcd/etcd (user/group). It can be deployed in two ways: &lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;stacked etcd: an instance of etcd lives with kube-api-server on the same control plane node&lt;/li&gt;&#10;&lt;li&gt;external etcd: in a dedicated cluster of etcd&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Alternatively, etcd can run as a pod, most likely in kube-system namespace. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The etcd service listens on port 2379 for client communication and on port 2380 for server (peer-to-peer) communication. When the systemd service was initialized there are a few key environment variables (e.g. cert locations, ETCD_DATA_DIR) privoded as configuration. To see them, run:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; cat /etc/systemd/system/etcd.service | grep Env&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;These environment variables (prefixed with ETCD_) are for the service only. They can provide current configuration information for us to use later. &amp;nbsp;When it’s running as a pod, check out the directory for static pod for the yaml declaration (e.g. /etc/Kubernetes/manifests/etcd.yaml), where these parameters are passed in as environment variable.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The &lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/"&gt;etcdctl&lt;/a&gt; utility is a command line client for etcd. The default API version is 3 so no need any more to set ETCDCTL_API=3 before each command. The utility needs three arguments three arguments (&amp;#8211;cacert, &amp;#8211;cert, and &amp;#8211;key) but we can pass the information via environment variables:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; export ETCDCTL_CACERT&lt;span style="color:#f92672"&gt;=&lt;/span&gt; /home/cloud_user/etcd-certs/etcd-ca.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; export ETCDCTL_CERT&lt;span style="color:#f92672"&gt;=&lt;/span&gt; /home/cloud_user/etcd-certs/etcd-server.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; export ETCDCTL_KEY&lt;span style="color:#f92672"&gt;=&lt;/span&gt; /home/cloud_user/etcd-certs/etcd-server.key&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; export ETCDCTL_ENDPOINTS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;https://etcd1:2379&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The environment variable names are uppercase of the argument name with prefix ETCDCTL_. Only global options of arguments can be supplied via environment variables. They remain effective throughout the rest of activities. Also note that the CACERT is needed only when client-cert-auth is true. Now to backup, we can simply run:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; etcdctl snapshot save /home/cloud_user/etcd_backup.db&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;To restore from a file, you want to remove existing etcd data directory first. The directory can be found in ETCD_DATA_DIR variable. Suppose it is /var/lib/etcd, you need root permission to write to it, then correct ownership before starting the service:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; sudo systemctl stop etcd &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo mv /var/lib/etcd/ /tmp/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; sudo etcdctl snapshot restore /home/cloud_user/etcd_backup.db --data-dir /var/lib/etcd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; sudo chown -R etcd:etcd /var/lib/etcd &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo systemctl start etcd&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;To verify the restore result, simply run:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; etcdctl get cluster.name&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 class="wp-block-heading" id="h-object-management"&gt;Object Management&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the CKA exam, we need to interact with many types of built-in Kubernetes objects.&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;RBAC objects:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;A Role defines permissions &lt;strong&gt;within namespace&lt;/strong&gt;.&lt;/li&gt;&#10;&lt;li&gt;A ClusterRole defines &lt;strong&gt;cluster-wide&lt;/strong&gt; permissions.&lt;/li&gt;&#10;&lt;li&gt;Both Roles and ClusterRoles are K8s objects that defines a set of permissions&lt;/li&gt;&#10;&lt;li&gt;RoleBinding and ClusterRoleBinding are objects that connect Roles and ClusterRoles to users.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Service Account: an account &lt;strong&gt;used by container processes&lt;/strong&gt; within Pods to authenticate the K8s API. If your Pods need to communicate with the K8s API, you can use service accounts to control their access.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="has-white-background-color has-background wp-block-paragraph"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="271px" viewBox="-0.5 -0.5 271 261" style="max-width:100%;max-height:261px;"&gt;&lt;defs&gt;&lt;/defs&gt;&lt;g&gt;&lt;rect x="150" y="70" width="120" height="50" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 118px; height: 1px; padding-top: 95px; margin-left: 152px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: left; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;RoleBinding&lt;br&gt;* roleRef&lt;br&gt;* subjects&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="152" y="99" fill="#000000" font-family="Helvetica" font-size="12px"&gt;RoleBinding&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="0" y="70" width="120" height="50" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 118px; height: 1px; padding-top: 95px; margin-left: 2px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: left; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;ClusterRoleBinding&lt;br&gt;* roleRef&lt;br&gt;* subjects&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="2" y="99" fill="#000000" font-family="Helvetica" font-size="12px"&gt;ClusterRoleBinding&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="90" y="0" width="100" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#d6b656" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 15px; margin-left: 91px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;ServiceAccount&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="140" y="19" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;ServiceAccount&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="0" y="170" width="120" height="90" fill="#f5f5f5" stroke="#666666" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 118px; height: 1px; padding-top: 215px; margin-left: 2px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: left; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;&lt;div&gt;&lt;span&gt;ClusterRole:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;* rules&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;#8211; apiGroups&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;#8211; resources&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;#8211; resourceNames&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;#8211; verbs&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="2" y="219" fill="#333333" font-family="Helvetica" font-size="12px"&gt;ClusterRole:&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="150" y="170" width="120" height="90" fill="#f5f5f5" stroke="#666666" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 118px; height: 1px; padding-top: 215px; margin-left: 152px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: left; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;&lt;div&gt;&lt;span&gt;Role:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;* rules&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;#8211; apiGroups&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;#8211; resources&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;#8211; resourceNames&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;#8211; verbs&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="152" y="219" fill="#333333" font-family="Helvetica" font-size="12px"&gt;Role:&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 196.37 15 L 203.18 15 Q 210 15 210 25 L 210 70" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 191.12 15 L 198.12 11.5 L 196.37 15 L 198.12 18.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 83.63 15 L 70 15 Q 60 15 60 25 L 60 70" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 88.88 15 L 81.88 18.5 L 83.63 15 L 81.88 11.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 60 120 L 60 163.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 60 168.88 L 56.5 161.88 L 60 163.63 L 63.5 161.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 210 120 L 210 163.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 210 168.88 L 206.5 161.88 L 210 163.63 L 213.5 161.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;switch&gt;&lt;g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;/g&gt;&lt;a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank" rel="noopener"&gt;&lt;text text-anchor="middle" font-size="10px" x="50%" y="100%"&gt;Viewer does not support full SVG 1.1&lt;/text&gt;&lt;/a&gt;&lt;/switch&gt;&lt;/svg&gt;&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Inspect resource usage either with a K8s Metrics Server, or by command:&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; kubectl top pod --sort-by &amp;lt;JSONPATH&amp;gt; --selector &amp;lt;selector&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;a href="https://andrewlock.net/running-kubernetes-and-the-dashboard-with-docker-desktop/"&gt;Here&lt;/a&gt; is a good guide to install metrics server and dashboard (e.g. on docker-desktop).&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-pods-and-containers"&gt;Pods and Containers&lt;/h3&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;ConfigMaps: store data in key-value map.&lt;/li&gt;&#10;&lt;li&gt;Secrets: same as ConfigMaps but for sensitive data only&lt;/li&gt;&#10;&lt;li&gt;Two ways to pass ConfigMap and Secret data to your container:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;As environment variables in container operating system&lt;/li&gt;&#10;&lt;li&gt;As files presented on mounted volumes in container file system.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Container Resource management:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Resource requests: K8s scheduler will use resource requests to avoid scheduling pods on nodes that do not have enough available resources. 1 CPU unit = 1/1000 of one core&lt;/li&gt;&#10;&lt;li&gt;Resource limits: allow you to limit the amount of resources your containers can use. The container runtime is responsible for enforcement. The enforcement behaviour is different. For example, some terminates container that attempts to use more resource than the limit.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Probes&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Liveness Probe: automatically determine whether or not a container application is in a healthy state. By default K8s does not consider a container to be down until the container process stops. Liveness Probe allow you to customize this detection mechanism and make it more sophisticated.&lt;/li&gt;&#10;&lt;li&gt;Startup Probes: similar to liveness probes. However, while liveness probes run constantly on a schedule, startup probes run at container startup and stop running once they succeed. Startup probes are used to determine when the application has successfully started up. It is especially useful for legacy applications that can have long startup times.&lt;/li&gt;&#10;&lt;li&gt;Readiness Probes: determine when a container is ready to accept requests. When you have a service backed by multiple container endpoints, user traffic will not be sent to a particular pod until its containers have all passed the readiness checks defined by their readinesse probes. Use readiness probes to prevent user traffic from being sent to pods that are still in the process of starting up.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Restart policy for self-healing pods&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;(default) Always: container will always be restarted if they stop, even if they completed successfully (returned 0).&lt;/li&gt;&#10;&lt;li&gt;OnFailure: container will be restarted if the container process exists with an error code, or the container is determined to be unhealthy by a liveness probe.&lt;/li&gt;&#10;&lt;li&gt;Never: let it be&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Multi-container pods:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;containers share the same networking namespace and can communicate with one another on any port, even if the port is not exposed to the cluster&lt;/li&gt;&#10;&lt;li&gt;Container can use volumes to share data in a Pod. Example: a legacy application is hard-coded to write log output to a file on disk. You use a sidecar container to read the log file from shared volume and prints it to the console so the log output will appear in the container log.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Init containers: containers that run once during the startup process of a pod. A pod can have any number of init containers, and they will each run once into completion, before the next init container starts. You may use init containers to perform a variety of startup tasks, they can contain and use software and setup scripts that are not needed by your main containers. They are often useful in keeping your main containers lighter and more secure by offloading startup tasks to a separate container. Use case include:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;cause a pod to wait for another K8s resource to be created before finishing startup&lt;/li&gt;&#10;&lt;li&gt;perform sensitive startup steps securely outside of app containers&lt;/li&gt;&#10;&lt;li&gt;populate data into a shared volume at startup&lt;/li&gt;&#10;&lt;li&gt;communicate with another service at startup&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Scheduling: Scheduler (a component in control plane) assigns Pods to a suitable Node so kubelets can run them. The factor taken into account:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;resource request vs available node resources&lt;/li&gt;&#10;&lt;li&gt;various configurations that affect scheduling using node labels&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Pod allocation&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;nodeSelector is an attribute of Pod to allow you to limit which Node(s) the Pod can be scheduled on. The selector is based on label.&lt;/li&gt;&#10;&lt;li&gt;nodeName is an attribute of Pod that allows you to bypass scheduling and assign Pod to a specific Node by name.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;DaemonSet: automatically runs a copy of a Pod on each node. When a new node is added to the clsuter, DaemonSet will run a new copy of the Pod on it. DaemonSets also respect normal scheduling rules around node labels, taints and tolerations. If a pod would not normally be scheduled on a node, a DaemonSet will not create a copy of the Pod on that node.&lt;/li&gt;&#10;&lt;li&gt;Static Pod: A Pod that is managed directly by the kubelet on a node, not by the K8s API server. They can run even if there is not K8s API server present. Kubelet automatically creates static Pods from YAML manifest files located in the manifest path on the node.&lt;/li&gt;&#10;&lt;li&gt;Mirror Pod: Kubelet will create a mirror Pod for each static Pod. Mirror Pods allow you to see the status of the static Pod via the K8s API, but you cannot change or manage them via the API.&lt;/li&gt;&#10;&lt;li&gt;Taints: applied to nodes to repel a set of pods. A taint specifies key-value and effect. Effect can be &lt;code&gt;NoSchedule&lt;/code&gt; or &lt;code&gt;NoEffect&lt;/code&gt;. The former prevents pods without matching tolerations to schedule to the tainted node. The latter also evicts pre-existing pods with no matching toleration. &lt;/li&gt;&#10;&lt;li&gt;Tolerations: applied to pods so they can be scheduled to nodes with matching taints. A toleration consists of key-value pair, effect and operation. The operation can be &lt;code&gt;Equal&lt;/code&gt; or &lt;code&gt;Exists&lt;/code&gt;. To determine whether a toleration matches a taint. The keys and the effects must be the same. In addition:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;the operator is Exists (and thus no value should be specified in the toleration); or&lt;/li&gt;&#10;&lt;li&gt;the operator is Equal, and all the values match those of the taints;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Now we have three ways to influence the scheduling behaviour. The first, is simply by specifying &lt;code&gt;nodeSelector&lt;/code&gt; on the Pod, with the required the node label. The second, as just discussed, is to use &lt;code&gt;Taints&lt;/code&gt; and &lt;code&gt;Tolerations&lt;/code&gt;. The third way, is similar to the first, using &lt;code&gt;nodeAffinity&lt;/code&gt; attributes on Pods. nodeAffinity is more powerful and flexible than nodeSelector by supporting more complex scheduling rules (e.g. matching rules).&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Use Node Affinity when your scheduling rule is based on &lt;span style="text-decoration: underline" class="underline"&gt;direct condition&lt;/span&gt;, i.e. &lt;span style="text-decoration: underline" class="underline"&gt;schedule a Pod to this Node when XXX&lt;/span&gt;. In this case, you have &lt;a href="https://kubernetes.io/docs/reference/labels-annotations-taints"&gt;well-known labels&lt;/a&gt; on nodes, and specify &lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/#schedule-a-pod-using-required-node-affinity"&gt;nodeAffinity&lt;/a&gt; on Pods. &lt;/li&gt;&#10;&lt;li&gt;Use Taints and Tolerations when your scheduling rule is based on &lt;span style="text-decoration: underline" class="underline"&gt;inverse statement, i.e. do not schedule a Pod to this Node unless XXX&lt;/span&gt;. In this case, you put a taint &amp;#8220;MyCondition:NoSchedule&amp;#8221; on a Node, so that no Pod will ever get scheduled to this Node. The only exception is when a Pod has the Toleration &amp;#8220;MyCondition:NoSchedule&amp;#8221;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 class="wp-block-heading" id="h-deployments"&gt;Deployments&lt;/h3&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Deployment is an object that defines a desired state for a ReplicaSet (a set of replica Pods). The Deployment Controller seeks to maintain the desired state by creating, deleting, and replacing Pods with new configurations.&lt;/li&gt;&#10;&lt;li&gt;With Deployments, you can horizontally scale an application up and down by changing the number of replicas. You can perform rolling updates and rollback.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 class="wp-block-heading" id="h-networking"&gt;Networking&lt;/h3&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;The K8s network model defines how Pods communicate with each other, regardless of which Node they are running on.&lt;/li&gt;&#10;&lt;li&gt;Each Pod has its own unique IP address within the cluster. Any Pod can reach any other Pod using that Pod&amp;#8217;s IP address. This creates a virtual network that allows Pods to easily communicate with each other.&lt;/li&gt;&#10;&lt;li&gt;One type of K8s network plugin is CNI plugin. It has many flavours such as Calico. Each plugin has its own unique installation process. Kubenetes nodes will remain &lt;strong&gt;NotReady&lt;/strong&gt; until a network plugin is installed.&lt;/li&gt;&#10;&lt;li&gt;The K8s virtual network uses a DNS (e.g. a Kubeadm cluster uses CoreDNS pod in kube-system namespace) to allow Pods to locate other Pods and Services using domain names. The Pod DNS name follows this format: pod-ip-address.namespace.pod.cluster.local&lt;/li&gt;&#10;&lt;li&gt;A K8s NetworkPolicy is an object that allows you to control the flow of network communication to and from Pods so you can isolate traffic. NetworkPolicy can apply to Ingress (using from selector), Egress (using to selector) or both.&lt;/li&gt;&#10;&lt;li&gt;NetworkPolicy has an attribute podSelector to determine to which Pods in the namespace the NetworkPolicy applies, by selecting Pods by with Pod labels.&lt;/li&gt;&#10;&lt;li&gt;By default, Pods are considered non-isolated and completed open to all communication. If any NetworkPolidy selects a Pod, the Pod is considered isolated and will only be open to traffic allowed by NetworkPolicies.&lt;/li&gt;&#10;&lt;li&gt;A variety of selector can be used: podSelector, namespaceSelector, ipBlockSelector and port.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 class="wp-block-heading" id="h-services"&gt;Services&lt;/h3&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Services provide a way to expose an application running as a set of pods, so clients can access applications in an abstract way without needing to be aware of the application pods. In this model, client make requests to a Service, which routes traffic to its pods in a load-balanced fashion&lt;/li&gt;&#10;&lt;li&gt;Endpoints are the backend entities to which Services route traffic. If there are multiple Pods behind a service, each Pod will have an endpoint associated with the service.&lt;/li&gt;&#10;&lt;li&gt;Each service has a type that determines how and where service will expose your application.&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;ClusterIP: expose application inside the cluster network&lt;/li&gt;&#10;&lt;li&gt;NodePort: expose application outside the cluster network&lt;/li&gt;&#10;&lt;li&gt;LoadBalancer: expose application outside thecluster network, but use an extermal cloud load balancer from cloud platform.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Services are assigned with DNS names. The FQDN follows this format: service.namespace.svc.cluster-domain.example, which is used by pods across namespaces&lt;/li&gt;&#10;&lt;li&gt;Pods within the same namespace can reference service simply by service name.&lt;/li&gt;&#10;&lt;li&gt;To manage external access to service, you can also use Ingress object. Ingress object is capable of providing more functionality than a simple NodePort Service, such as SSL termination, advanced load balancing, or name-based virtual hosting. You must install one or more Ingerss controller (many different implementations) to back up the ingress objects.&lt;/li&gt;&#10;&lt;li&gt;Ingress defines a set of routing rules. Each rule has a set of paths, each with a backend. Requests matching a path will be routed to its associated backend.&lt;/li&gt;&#10;&lt;li&gt;If a Service uses a named port, an ingress can also use the port&amp;#8217;s name (instead of port number) to choose to which port of a service it will route.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 class="wp-block-heading" id="h-storage"&gt;Storage&lt;/h3&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Volumes allow you to store data outside the container file system, while allowing the container to access the data at runtime. When Pod is gone, volumes do not persist.&lt;/li&gt;&#10;&lt;li&gt;Persistent Volumes are a slightly more advanced form of Volume. They allow you to treat storage as an abstract resource and consume it in Pods. PV can be provisioned separately by storage administrator, and they persist regardless of pod lifecycle. PV needs to be claimed by pods. PV uses a set of attributes to describe the underlying storage resource.&lt;/li&gt;&#10;&lt;li&gt;Both volumes and PVs each have a volume type: NFS, Cloud (AWS, Azure, GCP), ConfigMaps and Secrets, Simple Directory on node&lt;/li&gt;&#10;&lt;li&gt;Two volume types to distinguish:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;hostPath: store data in a specified directory on K8s node&lt;/li&gt;&#10;&lt;li&gt;emptyDir: store data in dynamically created location on the node. The directory exists only as long as the Pod exists on the node. The directory and the data are deleted as Pod is removed. This type is useful for simply sharing data between containers in the same pod.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Both volumes and PVs are specified under Pod, and individual containers must include volumeMounts object to map volume name to local mountPath&lt;/li&gt;&#10;&lt;li&gt;Storage Class object allow K8s admins to specify the types of storage services they offer on their platform. A key property is allowVolumeExpansion. This allows PVC to resize. At storage class level, there are two reclaim policies: Retain and Delete. The default is Delete.&lt;/li&gt;&#10;&lt;li&gt;PV has an attribute named persistentVolumeReclaimPolicy. This is reclaim policy at PV level. If the attribute is not defined, it is inherited from storage class. The persistentVolumeReclaimPolicy has three options. When PVC is deleted:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Retain: keeps all data but requires admin to manually reclaim the volume (i.e. delete PV, clean up data, delete storage asset)&lt;/li&gt;&#10;&lt;li&gt;Delete (cloud storage only): deletes both PV and the underlying storage resource automatically&lt;/li&gt;&#10;&lt;li&gt;Recycle: scrub (rm -rf /vol/) all data in the underlying storage resource, and allow the volume to be reused.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;PVC represents a user&amp;#8217;s request for storage resources. It defines a set of attributes similiar to those of a PV. When a PVC is created, it will look for a PV that is able to meet the requested criteria. If it finds one, it will automatically be bound to the PV. PVC can be mounted to a Pod&amp;#8217;s containers just like any other volume&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In general the CKA exam experience is quite positive and rewarding. In future posts I will shift focus on Kubernetes not only for the CKA exam, but also for keeping track of my learning.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Good luck with your CKA exam.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/04/public-key-infrastructure-pki/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Public Key Infrastructure (PKI) – Introduction&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/05/secure-web-application-deployment/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Secure web application deployment&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Basic Resource Object in Kubernetes 1 of 2</title><link>https://static.digihunch.com/2021/01/basic-kubernetes-resource-object-1-of-2/</link><pubDate>Sat, 16 Jan 2021 22:13:00 -0400</pubDate><guid>https://static.digihunch.com/2021/01/basic-kubernetes-resource-object-1-of-2/</guid><description>&lt;p class="wp-block-paragraph"&gt;For someone from a system administration background, it would be amazing to discover that Kubernetes provides a solution to every pain point in the traditional software deployment landscape. On the contrary, it also brings about a lot of complexity due to the types of resource objects introduced. &lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/pod-128.png" alt=""/&gt;&lt;figcaption&gt;Pod&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A Pod is a shared execution environment for one or more containers. The containers running in a Pod share resources such as memory, volumes, network namespace (e.g. IP address, port range, hostname, routing table), UTS namespace (e.g. hostname) and IPC namespace (Unix domain sockets). Every Pod has its own IP address that is routable on the Pod network. All Pods connect to the same flat network called the Pod network.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A pod most commonly only contains a single container, which is considered a good practice, unless there is good reasons to put two containers in a single pod (sharing resource). One such good reason is to co-schedule tightly-coupled workloads (such as logging, sharing volume, etc). Within the Pod, the containers communicate with each other via localhost interface of the Pod. In service mesh model, there is also a proxy container in each application Pod. The proxy container handles all network traffic entering and leaving the Pod. Also, within the Pod, to avoid competing for resources, individual containers can have their own cgroup limits, which actively police resource usage.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Pods are mortal (composable). They come and go (with dynamic IPs), so application should not store state in Pods. Deploying a Pod is an atomic (all or nothing) operation. When a Pod is scheduled to a node, it enters the pending state while the container runtime on the node downloads images and starts any containers. Once&amp;#8217;s everything is ready, the Pod enters the running state.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We typically deploy Pods via higher-level controllers such as Deployments (to offer scalability and rolling updates), DaemonSets (to run one instance of a service on every node in the cluster), StatefulSets (for stateful application components), and CronJobs (for short-lived tasks that need to run at set times just like a Linux &lt;a href="https://static.digihunch.com/2018/05/cron-and-logrotate-in-centos/"&gt;cronjob&lt;/a&gt;).&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/deploy-128.png" alt=""/&gt;&lt;figcaption&gt;Deployments&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Deployment manages multiple replicas of the same Pod (via ReplicaSets). To follow best practice, you interact with Deployments instead of ReplicaSets, and use YAML file (declarative model). You can perform rolling update or rollback.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/rs-128.png" alt=""/&gt;&lt;figcaption&gt;ReplicaSets&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;ReplicaSets provide self-healing and scaling capabilities to Pods. If a Pod fails, it will be replaced. If load increases, then the ReplicaSets creates new Pod. This is all implemented with a background reconciliation loop that is constantly checking whether the right number of Pod replicas are present on the cluster. If not, Kubernetes declares a red-alert condition, orders the control plan to bring up more replicas. The best practice however, is that you should not manage ReplicaSets directly. Instead, you should perform all actions against the Deployment object and leave the Deployment to manage ReplicaSets.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://storage.googleapis.com/cdn.thenewstack.io/media/2017/11/07751442-deployment.png" alt=""/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/svc-128.png" alt=""/&gt;&lt;figcaption&gt;Service&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Pods themselves are mortal (IP churn) so it&amp;#8217;s a bad idea to talk directly to individual Pods. Service object provides stable and reliable networking for a set of dynamic Pods. Service gets its own stable IP address, stable port and stable DNS name. It can also load-balance request across the Pods.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Services are loosely coupled with Pods via labels and label selectors. You specify label selector for Service and labels on Pods when creating them. All the labels in label selector are used to select target Pods. Service acts as front-end, consisting of stable IP, DNS name and port, with Pods acting as backend, consisting of constantly changing Pods. Labels are simple yet extremely powerful. During blue-green update, you may use version label as a technique to control what backend pool is used behind Service object. For example, start with version=1, deploy version 2, remove version from label selector, and eventually add version=2 back to label selector, before phasing out the old Deployment.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Services learn Pod status via Endpoint object, more details to follow.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are several types of Service, the default being &lt;strong&gt;ClusterIP&lt;/strong&gt;. A ClusterIP Service has a stable IP address and port that is only accessible from inside the cluster. The ClusterIP gets registered against the name of the Service on the cluster&amp;#8217;s internal DNS service (implemented via coreDNS with Control plane Pods). This means that the ClusterIP only works within the cluster, not outside. The other type of Service is called a &lt;strong&gt;NodePort&lt;/strong&gt;, which is built on top of ClusterIP, but also enables access from outside of the cluster. The Service object has a reliable NodePort mapped to every node in the cluster. The NodePort value is the same on every cluster. Traffic from outside of the cluster can hit any node in the cluster on the NodePort and get through the the Pods.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Other types of Services include LoadBalancer and ExternalName. LoadBalancer Services integrate with load-balancers from cloud provider. They build on top of NodePort Services and allow clients on the internet to reach your Pods via the load balancer of cloud vendor. ExternalName Services route traffic to systems outside of your K8s cluster.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For service discovery within the cluster, Kubelet program every container with the knowledge of the internal DNS (/etc/resolv.conf). The internal DNS service watches constantly the API server for new Services and automatically register them in the DNS. The other means of service discovery is through environment variables. However, in this method the Pods have no way of learning about new Services added to the cluster after the Pod itself is created.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/ep-128.png" alt=""/&gt;&lt;figcaption&gt;Endpoints&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Endpoints object is a dynamic list of all the healthy Pods on the cluster that match the Service&amp;#8217;s label selector. Each Service gets its own Endpoints objects for an up-to-date list of matching Pods. Kubernetes is constantly evaluating the Service&amp;#8217;s label selector against the currently list of healthy Pods on the cluster. Any new Pods that match the selector get added to the Endpoints object, and any Pods that disappear get removed.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When sending traffic to Pods, via a Service, an application will query the cluster&amp;#8217;s internal DNS for the IP address of a Service, then sends the traffic to this stable IP address. Service then forwards it on to a Pod. Kubernetes-native application however, has the ability to query the Endpoints API directly, bypassing the DNS lookup and use of the Service&amp;#8217;s IP.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;It requires a thorough understanding of Services, Endpoints and the service discovery mechanism to perform effective troubleshooting in Kubernetes.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The aforementioned internal DNS service (we usually call it the &amp;#8220;cluster DNS&amp;#8221;) is implemented in the kube-system Namespace as a set of Pods managed by a Deployment called coredns. These Pods are fronted by a Service called kube-dns. The cluster DNS is constantly looking for new Services and automatically register their details (metadata.name). We might need to check the logs for each of the coredns Pods during troubleshooting. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The kubelet process on every node is watching the API Server for new Endpoints objects, when it sees them, it creates local networking rules that redirect ClusterIP traffic to Pod IPs, using &lt;a href="https://static.digihunch.com/2020/11/ipvs-iptables-and-kube-proxy/" class="rank-math-link"&gt;IPVS technology&lt;/a&gt; on Linux to manage these rules.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/ds-128.png" alt=""/&gt;&lt;figcaption&gt;DaemonSet&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A DaemonSet ensures that all (or some) Nodes run a copy of a Pod. As nodes are added to the cluster, Pods are added to them. As nodes are removed from the cluster, those Pods are garbage collected. Deleting a DaemonSet will clean up the Pods it created.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Some typical uses of a DaemonSet are: cluster storage daemon on every node, logs collection daemon on every node, a node monitoring daemon on every node.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/hpa-128.png" alt=""/&gt;&lt;figcaption&gt;Horizontal Pod Autoscaler&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The Horizontal Pod Autoscaler automatically scales the number of Pods in a replication controller, deployment, replica set or stateful set based on observed CPU utilization (or, with custom metrics support, on some other application-provided metrics). Note that Horizontal Pod Autoscaling does not apply to objects that can&amp;#8217;t be scaled, for example, DaemonSets.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The Horizontal Pod Autoscaler is implemented as a Kubernetes API resource and a controller. The resource determines the behaviour of the controller. The controller periodically adjusts the number of replicas in a replication controller or deployment to match the observed average CPU utilization to the target specified by user.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are more details about HPA &lt;a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/" class="rank-math-link"&gt;here&lt;/a&gt; and &lt;a href="https://cloud.google.com/kubernetes-engine/docs/concepts/horizontalpodautoscaler" class="rank-math-link"&gt;here&lt;/a&gt;.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/blob/master/icons/png/resources/labeled/sts-128.png?raw=true" alt="sts-128.png"/&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;StatefulSets are designed for stateful application, which creates and saves valuable data. The three properties that form the state of a Pod are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Pod names (&amp;lt;StatefulSetName&amp;gt;-&amp;lt;Integer&amp;gt;)&lt;/li&gt;&lt;li&gt;DNS hostnames&lt;/li&gt;&lt;li&gt;volume bindings&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;They are sometimes referred to as the Pods &lt;em&gt;sticky ID&lt;/em&gt;. StatefulSets ensures that these are all predictable and persistent. For example, failed Pods managed by a StatefulSet will be replaced by new Pods with the exact same Pod name, the exact same DNS hostname, and the exact same volumes, even if the replacement Pod is started on a different cluster Node.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note that StatefulSets create one Pod at a time, and always wait for previous Pods to be &lt;em&gt;running and ready&lt;/em&gt; before creating the next. Scaling operations are also governed by the same ordered startup rules. This is different from Deployments that use a ReplicaSet controller to start all Pods at the same time, causing potential race conditions. The way StatefulSet controllers do their own self-healing and scaling is architecturally different to Deployments which use a separate ReplicaSet controller for these operations. The reason it is a game changer to know the order in which Pods will be scaled down, as well as that Pods will not be terminated in parallel, is because clustered apps that store data are usually at high risk of losing data if multiple replicas go down at the same time.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Deleting a StatefulSet does not terminate Pods in order. So you may want to scale a StatefulSet to 0 replicas before deleting it. You might also set 10 seconds grace period before terminating to allow applications a chance to flush local buffers and safely commit any writes still in flight.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In Kubernetes, Volumes are decoupled from Pods via PersistentVolumes and PersistentVolumeClaims. So volumes have separate lifecycles to Pods and can survive Pod failures and termination operations. When a StatefulSet Pod is created, any volumes it needs are created at the same time and named in a way to connect them to the right Pod. Any time a StatefulSet Pod fails or is terminated, the associated volumes are unaffected. This allows replacement Pods to attach to the same storage as the Pods they&amp;#8217;re replacing, even if the replacement Pod is scheduled to a different cluster Node. Similarly, if a StatefulSet Pod is detected as part of a scale-down operation, subsequent scale-up operations will attach new Pods to the existing volumes that match their names.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Since each StatefulSet Pod needs its own unique storage, hence its own PVC, this can be done by volumeClaimTemplate, which dynamically creates a PVC each time a new Pod replica is dynamically created. This eliminates the hassle to have to pre-create a unique PVC for every potential StatefulSet Pod.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/ns-128.png" alt=""/&gt;&lt;figcaption&gt;Namespaces&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Namespaces allows you to partition resource objects. For example, you may create a Namespace called prod and dev. Object names must be unique within Namespaces but not across Namespaces.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/12/ansible-tower-lab-environment-on-aws/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;AWS CDK example in Typescript – provision an AWX server&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/01/blockchain-and-di-fi/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Blockchain and DeFi&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>IPVS, iptables and kube-proxy</title><link>https://static.digihunch.com/2020/11/ipvs-iptables-and-kube-proxy/</link><pubDate>Tue, 24 Nov 2020 13:17:00 -0400</pubDate><guid>https://static.digihunch.com/2020/11/ipvs-iptables-and-kube-proxy/</guid><description>&lt;p class="wp-block-paragraph"&gt;This is an overview of the underlying technologies that drives load balancing. It covers LVS, Netfilter, iptables, IPVS and eventually kube-proxy.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-lvs-linux-virtual-server"&gt;LVS (Linux Virtual Server)&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;One of the ways to implement software load balancing is via LVS (Linux Virtual Server), as &lt;a href="https://static.digihunch.com/2020/01/several-ways-to-ensure-high-availability/" class="rank-math-link"&gt;previously discussed&lt;/a&gt;. The diagram below shows the LVS &lt;a href="http://www.linuxvirtualserver.org/about.html" class="rank-math-link"&gt;framework&lt;/a&gt;, with IPVS as the fundamental technology:&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-large"&gt;&lt;img loading="lazy" decoding="async" width="304" height="340" src="https://static.digihunch.com/wp-content/uploads/2021/05/lvs.jpeg" alt="" class="wp-image-2262"/&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The major work of the LVS project is to develop advanced IP load balancing software (IPVS), application-level load balancing software (KTCPVS), cluster management components. &lt;a href="http://www.linuxvirtualserver.org/software/ktcpvs/ktcpvs.html" class="rank-math-link"&gt;KTCPVS &lt;/a&gt;implements application-level load balancing inside the Linux kernel (still under development). &lt;a href="http://www.linuxvirtualserver.org/software/ipvs.html" class="rank-math-link"&gt;IPVS &lt;/a&gt;is an advanced IP load balancing software implemented inside the Linux kernel. The IPVS code was already included into the standard Linux kernel 2.4 and 2.6.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-netfilter"&gt;Netfilter&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Both IPVS and iptables (the technology behind Linux firewall, discussed &lt;a href="https://static.digihunch.com/2018/10/redhat-firewall-configuration-firewalld-vs-iptables/" class="rank-math-link"&gt;here&lt;/a&gt;) are based on &lt;strong&gt;netfilter&lt;/strong&gt;, a &lt;span style="text-decoration: underline;"&gt;packet-filtering framework&lt;/span&gt; provided by the Linux kernel. In this section, we will discuss them all together, starting with Netfilter and then discuss how iptables and IPVS uses netfilter. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Netfilter allows various networking-related operations to be implemented in the form of customized handlers, by offers various functions and operations for &lt;span style="text-decoration: underline;"&gt;packet filtering&lt;/span&gt;, &lt;span style="text-decoration: underline;"&gt;network address translation&lt;/span&gt;, and &lt;span style="text-decoration: underline;"&gt;port translation&lt;/span&gt;, which provide the functionality required for directing packets through a network and prohibiting packets from reaching sensitive locations within a network. Netfilter represents a set of &lt;strong&gt;hooks&lt;/strong&gt; inside the Linux kernel, allowing specific kernel modules to register &lt;strong&gt;callback&lt;/strong&gt; functions with the kernel&amp;#8217;s networking stack. Those functions, usually applied to the traffic in the form of filtering and modification rules, are called for every packet that traverses the respective hook within the networking stack.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-iptables"&gt;Iptables&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The kernel modules named &lt;strong&gt;ip_tables&lt;/strong&gt;, &lt;strong&gt;ip6_tables&lt;/strong&gt;, &lt;strong&gt;arp_tables &lt;/strong&gt;(the underscore is part of the name), and &lt;strong&gt;ebtables &lt;/strong&gt;comprise the &lt;span style="text-decoration: underline;"&gt;legacy packet filtering portion of the Netfilter hook system&lt;/span&gt;. They provide a table-based system for defining firewall rules that can filter or transform packets. The tables can be administered through the &lt;span style="text-decoration: underline;"&gt;user-space tools&lt;/span&gt; &lt;strong&gt;iptables&lt;/strong&gt;, &lt;strong&gt;ip6tables&lt;/strong&gt;, &lt;strong&gt;arptables&lt;/strong&gt;, and &lt;strong&gt;ebtables&lt;/strong&gt;. &lt;strong&gt;Notice&lt;/strong&gt; that although both the &lt;span style="text-decoration: underline;"&gt;kernel modules&lt;/span&gt; and &lt;span style="text-decoration: underline;"&gt;userspace utilities&lt;/span&gt; have similar names, each of them is a different entity with different functionality.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="306" src="https://static.digihunch.com/wp-content/uploads/2023/01/iptables.jpeg" alt="" class="wp-image-7749" srcset="https://static.digihunch.com/wp-content/uploads/2023/01/iptables.jpeg 1024w, https://static.digihunch.com/wp-content/uploads/2023/01/iptables-300x90.jpeg 300w, https://static.digihunch.com/wp-content/uploads/2023/01/iptables-768x230.jpeg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When a network packet is received on a network device, it first passes through the &lt;strong&gt;&lt;em&gt;Prerouting &lt;/em&gt;&lt;/strong&gt;hook. This is where the routing decision takes place. The kernel decides whether the packet is destined for a local process (e.g., a listening socket on a server in this system) or whether to forward it (system operates as a router). In the first case, the packet passes the &lt;strong&gt;&lt;em&gt;Input &lt;/em&gt;&lt;/strong&gt;hook and is then handed over to the local process.  If the packet is destined to be forwarded, it traverses the &lt;strong&gt;&lt;em&gt;Forward &lt;/em&gt;&lt;/strong&gt;hook and then a final &lt;strong&gt;&lt;em&gt;Postrouting &lt;/em&gt;&lt;/strong&gt;hook before being sent out on a network device. For packets that are generated locally (e.g., by a client or server process that likes sending things out), they must first pass the &lt;strong&gt;&lt;em&gt;Output &lt;/em&gt;&lt;/strong&gt;hook and then the  &lt;strong&gt;&lt;em&gt;Postrouting &lt;/em&gt;&lt;/strong&gt;hook before being sent out on a network device.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The aforementioned hooks &amp;nbsp;exist independently for the IPv4 and IPv6 protocols. Thus, IPv4 and IPv6 packets each traverse their own hooks. There are also other hooks for ARP packets and for Bridging. And all the &amp;nbsp;hooks exist independently within each network namespace. Additionally, there is an&amp;nbsp;&lt;strong&gt;&lt;em&gt;ingress&amp;nbsp;&lt;/em&gt;&lt;/strong&gt;hook for each network device. The list goes on… More explanations are from &lt;a href="https://www.teldat.com/blog/en/nftables-and-netfilter-hooks-via-linux-kernel/" class="rank-math-link"&gt;here&lt;/a&gt; and &lt;a href="https://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and-netfilter-architecture#iptables-rules" class="rank-math-link"&gt;here&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-ipvs"&gt;IPVS&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In LVS, IPVS is also based on netfilter framework, but works only on INPUT chain, by registering ip_vs_in hook function, to process request. IPVS (aka layer-4 switching) runs on a host at the front of a cluster of real servers. It directs requests for TCP/UDP based servers to the real server, while ensuring the resonse from (one or several) real server appears to the client as if they were all from a virtual service on a sigle IP address. It is based on in-kernel hash tables. The userspace utility is ipvsadm.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://i.imgur.com/i60QKw4.png" alt=""/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When the client request reaches the kernel space of load balancer, it arrives at PREROUTING chain. Route will determine whether the request packet is for the local host or not, based on the destination address of the packet. The packet is sent to INPUT chain if it is. The ip_vs_in function is hooked to LOCAL_IN and will examine the packet. If it finds a matching IPVS rule, it will (bypass INPUT chain) directly trigger POSTROUTING chain, &lt;strong&gt;skipping &lt;/strong&gt;iptables rules.vThis is discussed in detail &lt;a href="http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/LVS-HOWTO.filter_rules.html" class="rank-math-link"&gt;here&lt;/a&gt;. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;IPVS supports 8 load balancing algorithms (round robin, weighted round robin, least-connection, weighted least connection, locality-based least-connection, locality-based least-connection with replication, destination-hashing, and source-hashing) and 3 packet-forwarding methods (NAT, tunneling and direct routing).&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The main difference between iptables and IPVS, is &lt;a href="https://www.thegeekstuff.com/2011/01/iptables-fundamentals/"&gt;iptables&lt;/a&gt; includes a number of tables, each with a number of chains, each further involves a number of rules. The total number of rules is large. The packet is assessed against many of such rules. For the same reason, the order of the rule matters. IPVS on the other hand, leverages hash table, with a complexity of O(1), or O(n) in the worst case scenarios. They vary significantly in the efficiency of packet filtering and forwarding, especially when the rules gets complicated. Iptable also presents more latency when adding or removing rules as more rules are involved. This &lt;a href="https://www.slideshare.net/LCChina/scale-kubernetes-to-support-50000-services" class="rank-math-link"&gt;presentation &lt;/a&gt;includes some quantitative comparison.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-kubeproxy"&gt;KubeProxy&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In Kubernetes architecture, &lt;a class="rank-math-link" href="https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/"&gt;KubeProxy &lt;/a&gt;takes care of load balancing. Kube-proxy can run in three modes: userspace, iptables and IPVS. &lt;/p&gt;&#10;&lt;figure class="wp-block-image is-resized"&gt;&lt;img loading="lazy" decoding="async" src="https://d33wubrfki0l68.cloudfront.net/e351b830334b8622a700a8da6568cb081c464a9b/13020/images/docs/services-userspace-overview.svg" alt="Services overview diagram for userspace proxy" width="826" height="464"/&gt;&lt;figcaption class="wp-element-caption"&gt;userspace proxy mode&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The userspace mode is old and inefficient. The packet is compared against iptables rule and then forwarded to a pod named kube-Proxy, which operates as an application to forward packet to backend pods.&lt;/p&gt;&#10;&lt;figure class="wp-block-image is-resized"&gt;&lt;img loading="lazy" decoding="async" src="https://d33wubrfki0l68.cloudfront.net/27b2978647a8d7bdc2a96b213f0c0d3242ef9ce0/e8c9b/images/docs/services-iptables-overview.svg" alt="Services overview diagram for iptables proxy" width="810" height="601"/&gt;&lt;figcaption class="wp-element-caption"&gt;iptables proxy mode&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The iptables mode is better since it uses the kernel feature of iptables, which is fairly mature. kube-proxy manages iptables rule based on the service yaml of Kubernetes.&lt;/p&gt;&#10;&lt;figure class="wp-block-image is-resized"&gt;&lt;img loading="lazy" decoding="async" src="https://d33wubrfki0l68.cloudfront.net/2d3d2b521cf7f9ff83238218dac1c019c270b1ed/9ac5c/images/docs/services-ipvs-overview.svg" alt="Services overview diagram for IPVS proxy" width="810" height="601"/&gt;&lt;figcaption class="wp-element-caption"&gt;IPVS proxy mode&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With the comparison between iptables and IPVS earlier, we can expect that iptables operations slow down dramatically in large scale cluster. Therefore IPVS based kubeproxy was &lt;a class="rank-math-link" href="https://github.com/kubernetes/kubernetes/issues/17470"&gt;brought up&lt;/a&gt;. This &lt;a class="rank-math-link" href="https://speakerdeck.com/sufuf3/ipvs-based-kube-proxy-for-scaled-kubernetes-load-balancing"&gt;presentation &lt;/a&gt;illustrated the differences.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In this post we discussed load balancing technologies from ipvs to iptables and then to kube-proxy, which is used in Kubernetes nodes.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/11/how-imaging-devices-talk-to-each-other-tip-in-dicom/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;How imaging devices talk to each other (in DICOM)&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/12/instance-initialization-with-aws-cdk-in-python/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;AWS CDK example in Python – provision Kubernetes Nodes&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>High Availability and Load Balancer</title><link>https://static.digihunch.com/2020/01/several-ways-to-ensure-high-availability/</link><pubDate>Wed, 22 Jan 2020 20:49:00 -0400</pubDate><guid>https://static.digihunch.com/2020/01/several-ways-to-ensure-high-availability/</guid><description>&lt;h3 class="wp-block-heading" id="h-overview"&gt;Overview&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Fault tolerance and high availability are two architectural characteristics that people often confuse with each other. High availability focuses on minimizing downtime. It guarantees uptime, but not performance in the event of component failures. Fault tolerance, on the other hand, focuses on stable capacity even in the event of component failures. Fault tolerance has higher bar, and therefore is more expensive. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Suppose an application requires four servers to meet performance goal. Placing two servers in each of the two AZs will meet HA criteria but not FT requirement. In the event of an AZ failure, application can operate at degraded performance yet still be highly available. However, FT requires stable capacity and to meet FT requirement, we&amp;#8217;d have to place four servers in each AZ. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;High availability can be achieved either by clustering, or load balancing. A cluster involves several nodes, all able to perform the same function, but may take different roles at different times (e.g. primary, standby) in order for the cluster to perform its function as a single system. In Linux, clustering is implemented by pacemaker or corosync. With a high load system, it is common to set up load balancing system to achieve high availability (and fault tolerance).&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-load-balancing"&gt;Load balancing&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The idea of load balancing is simple: load goes high and we want to scale horizontally instead of simply upgrading server hardware. At a high level, there has been three approaches to load balancing:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;DNS rotating:&lt;/strong&gt; (aka. DNS round robin) DNS record resolves to multiple IPs, very simple and cheap to implement. Since DNS is cached, the load distribution will come imbalanced and it&amp;#8217;s hard to re-balance, making this a very limited approach;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Hardware Load Balancer&lt;/strong&gt;: using dedicated hardware device to configure load balancing. This option is expensive and only enterprises can afford it (&lt;a class="rank-math-link" href="https://kemptechnologies.com/compare-kemp-to-f5-big-ip-ltm-citrix-netscaler-mpx-load-balancers/"&gt;here&lt;/a&gt;&amp;#8216;s some pricing information). A classic load balancer operates at layer 3 and 4, which is also known as POLB (plain old load balancer). It is the core functionality of hardware load balancer. The hardware load balancer on the market today usually come with a variety of add-on features, such as advanced load balancing (L4, L7 path-based, script driven), compression, caching, SSL offloading, and even DDoS mitigation, etc. The whole suite of features makes it an Application Delivery Controller (ADC). Therefore many refer to hardware load balancer as &lt;a href="https://www.f5.com/company/blog/go-beyond-polb-plain-old-load-balancing"&gt;hardware-based ADC&lt;/a&gt; to highlight the features in addition to POLB. Hardware-based ADCs ship with manufactures hardware, with specialized processors, advanced network hardware, and often &lt;a href="https://www.f5.com/services/resources/white-papers/software-defined-hardware-enabling-performance-and-agility-with-the-big-ip-iseries-architecture"&gt;ASIC&lt;/a&gt; (application specific integrated circuit). At a higher expense, they have better reliability and capacity. Some major market players are:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;F5 &amp;#8211; &lt;a class="rank-math-link" href="https://www.f5.com/services/resources/white-papers"&gt;Big IP&lt;/a&gt;, F5 also has a &lt;a href="https://devcentral.f5.com/s/articles/what-is-load-balancing-24740"&gt;good article &lt;/a&gt;about history of load balancer.&lt;/li&gt;&#10;&lt;li&gt;Cisco &amp;#8211; Citrix A&lt;a href="https://www.citrix.com/products/citrix-adc/"&gt;https://www.citrix.com/products/citrix-adc/&lt;/a&gt;DC (formerly NetScaler ADC)&lt;/li&gt;&#10;&lt;li&gt;A10 Networks &amp;#8211; &lt;a class="rank-math-link" href="https://www.a10networks.com/products/thunder-adc/"&gt;Thunder&lt;/a&gt; (general) and &lt;a class="rank-math-link" href="http://docs.hc.a10networks.com/2.2.4/ads-intro.html"&gt;Lightning&lt;/a&gt; (cloud)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Software Load Balancer:&lt;/strong&gt; using software to achieve load balancing. These solutions are affordable, and usually open-source. They can be loaded on commodity hardware (including NIC). Some (e.g. &lt;a class="rank-math-link" href="https://www.nginx.com/resources/glossary/application-delivery-controller/"&gt;Nginx&lt;/a&gt;) refers to themselves as software-based ADC. Major players are:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;HA Proxy&lt;/li&gt;&#10;&lt;li&gt;Nginx&lt;/li&gt;&#10;&lt;li&gt;Linux Virtual Server (LVS, L4 only)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The hardware ADCs are usually supported commercially and there are plenty of resources from their white papers. There is an ongoing debate about whether one is better than the other. However, there is no doubt that a software-based load balancer is more approachable as open-source tools. The line between software and hardware load balancers becomes blurred today as hardware vendors try to adapt their software appliance to commodity hardware. Check out &lt;a href="https://www.nginx.com/blog/not-all-software-load-balancers-are-created-equal/"&gt;this&lt;/a&gt; article. The rest of this post, will focus on software-based load balancer. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-software-based-load-balancer"&gt;Software-based load balancer&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We explained that ADC (application delivery controller) is an expanded set of features from load balancer, and will only cover the load balancer part of the feature set in this article.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://www.haproxy.org/" class="rank-math-link"&gt;HAProxy&lt;/a&gt; supports both layer 4 and layer 7 load balancing. It supports load balancing based on cookie and session, as well as health check. Since it is layer 4 load balancing, it supports any TCP protocol such as read traffic for MySQL. &amp;nbsp;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://www.nginx.com/" class="rank-math-link"&gt;Nginx&lt;/a&gt; is a high-performance, event-driven, cross-platform layer 7 load balancing application. It works as a reverse proxy where it receives request for the Internet and forwards it to (upstream) internal servers. It consumes less memory than many of its alternatives for layer 7 load balancing. There are many strategies for load balancing such as round robin, by weight, by hash of requesting IP, by upstream response time, or by URL hash. It supports 20-30 k concurrent connections, and support compression and health check. It is known to be very stable and common for small and medium volume. Nginx has a commercial counterpart Nginx Plus with advanced features.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Nginx and HA proxy are commonly used in front end load balancing. For backend traffic such as database (e.g. separating read write traffic), LVS can be used.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-linux-virtual-server"&gt;Linux Virtual Server&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/4/html/virtual_server_administration/ch-lvs-overview-vsa" class="rank-math-link"&gt;LVS&lt;/a&gt; (Linux Virtual Server) is part of standard Linux kernel. It performs layer 4 load balancing based on TCP or UDP and therefore consumes less memory and CPU. Compared to layer 7 load balancing, the performance is generally higher, and the configuration is less complex (with simpler routing rules). &lt;a href="http://www.linuxvirtualserver.org/" class="rank-math-link"&gt;LVS&lt;/a&gt; is usually configured in a &lt;a href="http://www.linuxvirtualserver.org/architecture.html" class="rank-math-link"&gt;common cluster architecture&lt;/a&gt; involving these components:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Load balancer: the front-end machine of the whole cluster systems, and balances requests from clients among a set of servers, so that the clients consider that all the services is from a single IP address.&lt;/li&gt;&#10;&lt;li&gt;Server cluster: set of servers running actual business workload&lt;/li&gt;&#10;&lt;li&gt;Shared storage: a shared storage space for the servers, such as NFS&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://i.imgur.com/EU0gAUv.png" alt=""/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Load balancer is the single entry-point of server cluster systems, it can run&amp;nbsp;IPVS&amp;nbsp;that implements IP load balancing techniques inside the Linux kernel, or&amp;nbsp;KTCPVS&amp;nbsp;that implements application-level load balancing inside the Linux kernel. When IPVS is used, all the servers are required to provide the same services and contents, the load balancer forward a new client request to a server according to the specified scheduling algorithms and the load of each server. No matter which server is selected, the client should get the same result. When KTCPVS is used, servers can have different contents, the load balancer can forward a request to a different server according to the content of request. Since KTCPVS is implemented inside the Linux kernel, the overhead of relaying data is minimal, so that it can still have high throughput.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;IPVS is also called layer-4 switching, it directs TCP/UDP requests to the real servers behind load balancer. It works in three modes:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Network Address Translation (NAT)&lt;/li&gt;&#10;&lt;li&gt;Direct Routing (DR)&lt;/li&gt;&#10;&lt;li&gt;Tunnel mode (TUN)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;These are three packet-forwarding methods in IPVS. The IPVS is implemented as a module over the netfilter framework, similar to &lt;a href="https://static.digihunch.com/2018/10/redhat-firewall-configuration-firewalld-vs-iptables/" class="rank-math-link"&gt;iptables&lt;/a&gt;, which is also built on top of netfilter, based on chain and rules.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-summary"&gt;Summary &lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We had an overview of high availability, and then expanded on load balancing, an important mechanism to implement high availability. We touched on both hardware-based and software-based load balancing technologies, and dived a little more into Linux Virtual Server. It is worth-noting that LVS is also the foundation of kube-proxy, the load balancing mechanism used in Kubernetes.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/01/nginx-as-a-reverse-proxy-for-nifi/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Nginx as a reverse proxy for Nifi web UI and Kibana&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/02/everything-about-the-domain/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Introduction to Active Directory (AD)&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>