<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Labs on Eriks training corner</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/index.html</link><description>Recent content in Labs on Eriks training corner</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="https://training.caha.cloud/en/kubernetes-gt/labs/index.xml" rel="self" type="application/rss+xml"/><item><title>Lab 01 - Workstation setup</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-01-workstation-setup/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-01-workstation-setup/index.html</guid><description>&lt;h1 id="lab-01---workstation-setup"&gt;Lab 01 - Workstation setup&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; turn support01 into your kubectl workstation.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-01/02-architecture/"&gt;Architecture&lt;/a&gt; ·
&lt;strong&gt;Cheat sheet:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/cheatsheets/kubectl/"&gt;kubectl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;support01 has Docker and the NFS exports, but deliberately &lt;strong&gt;no kubectl and no
kubeconfig&lt;/strong&gt;. Building your own client is the first thing you do at any
customer, so you may as well do it here.&lt;/p&gt;
&lt;h2 id="before-you-start-network-on-support01"&gt;Before you start: network on support01&lt;/h2&gt;
&lt;p&gt;support01 does not have its addresses yet, so SSH will not work. Fix it once
from the &lt;strong&gt;Oracle VirtualBox console&lt;/strong&gt; (double-click the support01 VM, log in as
&lt;code&gt;student&lt;/code&gt; / &lt;code&gt;linux&lt;/code&gt;).&lt;/p&gt;</description></item><item><title>Lab 02 - First look at the cluster</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-02-first-look-at-the-cluster/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-02-first-look-at-the-cluster/index.html</guid><description>&lt;h1 id="lab-02---first-look-at-the-cluster"&gt;Lab 02 - First look at the cluster&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; map every box of the architecture diagram to something running.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-01/02-architecture/"&gt;Architecture&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - where am I connected, and as whom?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl cluster-info
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl config get-contexts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl config view --minify &lt;span class="p"&gt;|&lt;/span&gt; grep server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Check &lt;code&gt;config get-contexts&lt;/code&gt; before anything destructive. Most production
accidents are the right command in the wrong cluster.&lt;/p&gt;
&lt;h2 id="the-pod-network"&gt;The Pod network&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - which CNI runs here, and which address range do Pods get?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -n calico-system -o wide &lt;span class="c1"&gt;# one calico-node per node&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get cm -n kube-system kubeadm-config -o yaml &lt;span class="p"&gt;|&lt;/span&gt; grep -E &lt;span class="s1"&gt;&amp;#39;podSubnet|serviceSubnet&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -A -o wide &lt;span class="p"&gt;|&lt;/span&gt; grep 10.244 &lt;span class="p"&gt;|&lt;/span&gt; head -5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Calico was installed with the cluster. Every Pod gets an address from
&lt;code&gt;10.244.0.0/16&lt;/code&gt;, Services from &lt;code&gt;10.96.0.0/12&lt;/code&gt;. You work with Calico itself on
Day 4.&lt;/p&gt;</description></item><item><title>Lab 03 - The Kubernetes API and kubectl</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-03-kubernetes-api/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-03-kubernetes-api/index.html</guid><description>&lt;h1 id="lab-03---the-kubernetes-api-and-kubectl"&gt;Lab 03 - The Kubernetes API and kubectl&lt;/h1&gt;
&lt;span class="badge cstyle info badge-with-title"&gt;&lt;span class="badge-title"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; Info&lt;/span&gt;&lt;span class="badge-content"&gt;discover&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; answer any Kubernetes question from the terminal - and see the HTTP
behind kubectl.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-01/03-kubernetes-api/"&gt;The Kubernetes API and kubectl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Try each task first; the box holds one working answer.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Task 1.&lt;/strong&gt; List every kind the cluster knows. Find the short name and API
group of &lt;code&gt;deployments&lt;/code&gt;, and whether it is namespaced.&lt;/p&gt;
&lt;div class="expand"&gt;
&lt;input type="checkbox" id="expand-2" aria-controls="expandcontent-2" &gt;
&lt;label class="expand-label" for="expand-2" &gt;
&lt;i class="fas fa-chevron-down"&gt;&lt;/i&gt;
&lt;i class="fas fa-chevron-right"&gt;&lt;/i&gt;
Show the command
&lt;/label&gt;
&lt;div id="expandcontent-2" class="expand-content"&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl api-resources &lt;span class="p"&gt;|&lt;/span&gt; grep -i deploy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;deployments deploy apps/v1 true Deployment&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>Lab 04 - Imperative vs. declarative objects</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-04-declarative-imperative/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-04-declarative-imperative/index.html</guid><description>&lt;h1 id="lab-04---imperative-vs-declarative-objects"&gt;Lab 04 - Imperative vs. declarative objects&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; feel why &lt;code&gt;apply&lt;/code&gt; is the only thing you put in a pipeline.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-01/04-declarative-imperative/"&gt;Declarative vs. imperative&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="imperative"&gt;Imperative&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - an action, executed once&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy web --image nginx:1.27
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy web --image nginx:1.27 &lt;span class="c1"&gt;# AlreadyExists - not idempotent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl scale deploy web --replicas &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl delete deploy web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="declarative"&gt;Declarative&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - generate the manifest instead of writing it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy web --image nginx:1.27 --replicas &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --dry-run&lt;span class="o"&gt;=&lt;/span&gt;client -o yaml &amp;gt; web.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat web.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3 - validate against the API without storing anything&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f web.yaml --dry-run&lt;span class="o"&gt;=&lt;/span&gt;server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;client&lt;/code&gt; only builds the object locally; &lt;code&gt;server&lt;/code&gt; runs full validation and
admission, then throws the result away.&lt;/p&gt;</description></item><item><title>Lab 05 - Namespaces</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-05-namespaces/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-05-namespaces/index.html</guid><description>&lt;h1 id="lab-05---namespaces"&gt;Lab 05 - Namespaces&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; scope your work and stop typing &lt;code&gt;-n&lt;/code&gt;.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-01/05-namespaces/"&gt;Namespaces&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - what exists now&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get ns
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Four namespaces come with every cluster. &lt;code&gt;kube-system&lt;/code&gt; holds the control plane
Pods - look but do not deploy there.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - declarative (recommended)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; ns-dev.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Namespace
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: dev
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f ns-dev.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3 - imperative, for the throwaway one&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create ns &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4 - the same name in both, with no conflict&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl run web --image nginx:1.27 -n dev
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl run web --image nginx:1.27 -n &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -n dev
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -A &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s1"&gt;&amp;#39; web &amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Names are unique &lt;strong&gt;per namespace per kind&lt;/strong&gt;. That is the whole point: dev and
prod can both have a &lt;code&gt;web&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Lab 06 - Labels, selectors and annotations</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-06-labels-annotations/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-06-labels-annotations/index.html</guid><description>&lt;h1 id="lab-06---labels-selectors-and-annotations"&gt;Lab 06 - Labels, selectors and annotations&lt;/h1&gt;
&lt;span class="badge cstyle info badge-with-title"&gt;&lt;span class="badge-title"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; Info&lt;/span&gt;&lt;span class="badge-content"&gt;discover&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; slice a pile of Pods any way you need.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-01/06-labels-annotations/"&gt;Labels, selectors and annotations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Set-up - six Pods with different labels:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create ns shop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; p in &lt;span class="s2"&gt;&amp;#34;web-1 app=web,env=prod,tier=frontend&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;web-2 app=web,env=dev,tier=frontend&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;api-1 app=api,env=prod,tier=backend&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;api-2 app=api,env=test,tier=backend&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;db-1 app=db,env=prod&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;cache-1 app=cache,env=dev&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;set&lt;/span&gt; -- &lt;span class="nv"&gt;$p&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kubectl run &lt;span class="nv"&gt;$1&lt;/span&gt; -n shop --image nginx:1.27 --labels &lt;span class="nv"&gt;$2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl config set-context --current --namespace&lt;span class="o"&gt;=&lt;/span&gt;shop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Task 1.&lt;/strong&gt; List all Pods with their labels. Then show only &lt;code&gt;app&lt;/code&gt; and &lt;code&gt;env&lt;/code&gt; as
columns.&lt;/p&gt;</description></item><item><title>Lab 07 - Pods</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-07-pods/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-07-pods/index.html</guid><description>&lt;h1 id="lab-07---pods"&gt;Lab 07 - Pods&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; generate a Pod manifest, add resources, and see what a Pod really is.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-01/08-pods/"&gt;Pods&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - imperative: create and throw away&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl run bbox --image busybox --restart&lt;span class="o"&gt;=&lt;/span&gt;Never -- sleep &lt;span class="m"&gt;3600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl delete pod bbox
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;--restart=Never&lt;/code&gt; is what makes &lt;code&gt;kubectl run&lt;/code&gt; produce a bare Pod instead of
something managed. &lt;code&gt;-- sleep 3600&lt;/code&gt; overrides the image&amp;rsquo;s command, because
busybox would otherwise exit immediately.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - generate the manifest instead&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl run bbox --image busybox --restart&lt;span class="o"&gt;=&lt;/span&gt;Never --dry-run&lt;span class="o"&gt;=&lt;/span&gt;client -o yaml &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -- sleep &lt;span class="m"&gt;3600&lt;/span&gt; &amp;gt; bbox.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat bbox.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Edit &lt;code&gt;bbox.yaml&lt;/code&gt; and add resources to the container:&lt;/p&gt;</description></item><item><title>Lab 08 - ReplicaSets and Deployments</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-08-replicasets-deployments/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-08-replicasets-deployments/index.html</guid><description>&lt;h1 id="lab-08---replicasets-and-deployments"&gt;Lab 08 - ReplicaSets and Deployments&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; watch the reconciliation loop, see the selector do the binding, and
run your first Deployment.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-01/09-replicasets-deployments/"&gt;ReplicaSets and Deployments&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="replicaset"&gt;ReplicaSet&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - a ReplicaSet by hand (the only time you will write one)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; web-rs.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: ReplicaSet
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: web-rs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; replicas: 3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; matchLabels:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; app: web
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; labels:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; app: web
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: web
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; image: nginx:1.27
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f web-rs.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get rs,pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web -o wide
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - self-healing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl delete pod &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web -o name &lt;span class="p"&gt;|&lt;/span&gt; head -1&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The same loop that created the Pods counted two, wanted three, created one.&lt;/p&gt;</description></item><item><title>Lab 09 - DaemonSets</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-09-daemonsets/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-09-daemonsets/index.html</guid><description>&lt;h1 id="lab-09---daemonsets"&gt;Lab 09 - DaemonSets&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; one Pod per node, and the two surprises that come with it.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-02/01-daemonsets/"&gt;DaemonSets&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - the cluster already runs several&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get ds -A
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -A -o wide &lt;span class="p"&gt;|&lt;/span&gt; grep -E &lt;span class="s1"&gt;&amp;#39;kube-proxy|calico-node&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;kube-proxy and the CNI agent are DaemonSets: they must exist on every node,
including nodes that join tomorrow. There is no &lt;code&gt;replicas&lt;/code&gt; field anywhere - the
node list is the count.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - your own&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; logger-ds.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: DaemonSet
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: node-logger
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; matchLabels:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; app: node-logger
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; labels:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; app: node-logger
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: logger
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; image: busybox:1.36
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; command: [&amp;#34;sh&amp;#34;, &amp;#34;-c&amp;#34;, &amp;#34;while true; do echo \&amp;#34;$(date) $(hostname)\&amp;#34;; sleep 30; done&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; resources:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; requests: { cpu: &amp;#34;10m&amp;#34;, memory: &amp;#34;16Mi&amp;#34; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f logger-ds.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get ds node-logger
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;node-logger -o wide
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Three Pods, one per worker - and &lt;strong&gt;none on control01&lt;/strong&gt;.&lt;/p&gt;</description></item><item><title>Lab 10 - StatefulSets</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-10-statefulsets/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-10-statefulsets/index.html</guid><description>&lt;h1 id="lab-10---statefulsets"&gt;Lab 10 - StatefulSets&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; stable names, per-Pod storage, ordered start - and the clean-up
surprise.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-02/02-statefulsets/"&gt;StatefulSets&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="storage-first"&gt;Storage first&lt;/h2&gt;
&lt;p&gt;Each replica needs its own volume. This cluster has no StorageClass yet
(Day 5), so create three PersistentVolumes on the NFS exports of support01:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 0 -&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; i in &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 3&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; cat &lt;span class="s"&gt;&amp;lt;&amp;lt;YAML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: PersistentVolume
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: pv-storage$i
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; capacity:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; storage: 1Gi
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; accessModes: [&amp;#34;ReadWriteMany&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; persistentVolumeReclaimPolicy: Retain
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; storageClassName: &amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; nfs:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; server: support01
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; path: /storage$i
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt; &amp;gt; pvs.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f pvs.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pv &lt;span class="c1"&gt;# three, STATUS Available&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="headless-service-first"&gt;Headless Service first&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 -&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; web-headless.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: web-headless
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; clusterIP: None # headless - no virtual IP
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; app: web-sts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; ports:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - port: 80
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f web-headless.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get svc web-headless &lt;span class="c1"&gt;# CLUSTER-IP is &amp;#34;None&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A normal Service hides the Pods behind one IP. A headless Service does the
opposite: DNS returns the individual Pod addresses, so each replica is
addressable by name. A StatefulSet requires one.&lt;/p&gt;</description></item><item><title>Lab 11 - Jobs and CronJobs</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-11-jobs-cronjobs/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-11-jobs-cronjobs/index.html</guid><description>&lt;h1 id="lab-11---jobs-and-cronjobs"&gt;Lab 11 - Jobs and CronJobs&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; run work that finishes, in parallel, on a schedule - and see how a
failing Job gives up.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-02/03-jobs-cronjobs/"&gt;Jobs and CronJobs&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - a one-off Job&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create job hello --image busybox:1.36 -- sh -c &lt;span class="s1"&gt;&amp;#39;echo &amp;#34;hello from $(hostname)&amp;#34;; sleep 5&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get job,pods -l job-name&lt;span class="o"&gt;=&lt;/span&gt;hello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; --for&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;complete&lt;/span&gt; job/hello --timeout&lt;span class="o"&gt;=&lt;/span&gt;60s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl logs job/hello
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;COMPLETIONS 1/1&lt;/code&gt; and the Pod in &lt;code&gt;Completed&lt;/code&gt;. The Pod is kept so you can read
its log.&lt;/p&gt;</description></item><item><title>Lab 12 - ConfigMaps and Secrets</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-12-configmaps-secrets/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-12-configmaps-secrets/index.html</guid><description>&lt;h1 id="lab-12---configmaps-and-secrets"&gt;Lab 12 - ConfigMaps and Secrets&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; same image, different configuration - and learn which changes need a
restart.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-02/04-configmaps-secrets/"&gt;ConfigMaps and Secrets&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - from literals and from a file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;color=blue\nretries=3\n&amp;#39;&lt;/span&gt; &amp;gt; app.properties
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create cm app-cfg &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;DATACENTER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dc01 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --from-file&lt;span class="o"&gt;=&lt;/span&gt;app.properties
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get cm app-cfg -o yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;--from-literal&lt;/code&gt; makes one key; &lt;code&gt;--from-file&lt;/code&gt; makes a key named after the file
whose value is the whole file. Both live in the same &lt;code&gt;data&lt;/code&gt; map.&lt;/p&gt;</description></item><item><title>Lab 13 - Services and DNS</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-13-services-dns/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-13-services-dns/index.html</guid><description>&lt;h1 id="lab-13---services-and-dns"&gt;Lab 13 - Services and DNS&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; reach Pods by a stable name, from inside and from outside.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-02/05-networking-services/"&gt;Networking, CNI, Services and DNS&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - something to expose&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy web --image nginx:1.27 --replicas &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web -o wide &lt;span class="c1"&gt;# note the Pod IPs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - ClusterIP, the default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl expose deploy web --port &lt;span class="m"&gt;80&lt;/span&gt; --name web-svc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get svc web-svc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get endpointslices -l kubernetes.io/service-name&lt;span class="o"&gt;=&lt;/span&gt;web-svc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The EndpointSlice is the interesting object: it holds the three Pod IPs. The
Service is just a stable front; the EndpointSlice is the live membership list,
maintained by a controller as Pods become ready.&lt;/p&gt;</description></item><item><title>Lab 14 - Helm: install Traefik, releases and charts</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-14-helm/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-14-helm/index.html</guid><description>&lt;h1 id="lab-14---helm-install-traefik-releases-and-charts"&gt;Lab 14 - Helm: install Traefik, releases and charts&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; install Helm, then use it on a real chart: Traefik, the entry point
for Labs 15 and 16. Inspect, install, upgrade, roll back.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-02/06-helm/"&gt;Helm&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="install-helm"&gt;Install Helm&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 -&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;700&lt;/span&gt; get_helm.sh &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./get_helm.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="look-before-you-install"&gt;Look before you install&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - the repository&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm repo add traefik https://traefik.github.io/charts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm repo update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm search repo traefik/traefik
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm search repo traefik/traefik --versions &lt;span class="p"&gt;|&lt;/span&gt; head -5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3 - the chart&amp;#39;s interface&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm show chart traefik/traefik &lt;span class="p"&gt;|&lt;/span&gt; head -12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm show values traefik/traefik &lt;span class="p"&gt;|&lt;/span&gt; grep -n -A6 -E &lt;span class="s1"&gt;&amp;#39;^(service|gateway|providers):&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;show values&lt;/code&gt; is the public interface of a chart. A setting that is not there
does not exist - &lt;code&gt;--set&lt;/code&gt; on an unknown key is silently ignored.&lt;/p&gt;</description></item><item><title>Lab 15 - Ingress with Traefik (legacy)</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-15-ingress/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-15-ingress/index.html</guid><description>&lt;h1 id="lab-15---ingress-with-traefik-legacy"&gt;Lab 15 - Ingress with Traefik (legacy)&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; publish two applications by host name with the old API - enough to
read the Ingress objects you will meet in existing clusters.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-02/07-ingress/"&gt;Ingress (legacy)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Requires Traefik from &lt;a href="https://training.caha.cloud/en/kubernetes-gt/labs/lab-14-helm/"&gt;Lab 14&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - two applications, ClusterIP only&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create ns web
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy shop --image nginx:1.27 -n web
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy wiki --image httpd:2.4 -n web
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl expose deploy shop --port &lt;span class="m"&gt;80&lt;/span&gt; -n web
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl expose deploy wiki --port &lt;span class="m"&gt;80&lt;/span&gt; -n web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - one Ingress, two hosts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create ingress web -n web --class traefik &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --rule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;shop.k8s.lab/*=shop:80&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --rule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;wiki.k8s.lab/*=wiki:80&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --dry-run&lt;span class="o"&gt;=&lt;/span&gt;client -o yaml &amp;gt; ingress.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat ingress.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f ingress.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get ingress -n web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3 - test through Traefik&amp;#39;s NodePort&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -s -H &lt;span class="s1"&gt;&amp;#39;Host: shop.k8s.lab&amp;#39;&lt;/span&gt; http://worker01:30080 &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s1"&gt;&amp;#39;&amp;lt;title&amp;gt;.*&amp;lt;/title&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -s -H &lt;span class="s1"&gt;&amp;#39;Host: wiki.k8s.lab&amp;#39;&lt;/span&gt; http://worker01:30080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -s -o /dev/null -w &lt;span class="s1"&gt;&amp;#39;%{http_code}\n&amp;#39;&lt;/span&gt; -H &lt;span class="s1"&gt;&amp;#39;Host: other.k8s.lab&amp;#39;&lt;/span&gt; http://worker01:30080
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One port, two applications, and a 404 from Traefik for an unknown host.&lt;/p&gt;</description></item><item><title>Lab 16 - Gateway API with Traefik</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-16-gateway-api/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-16-gateway-api/index.html</guid><description>&lt;h1 id="lab-16---gateway-api-with-traefik"&gt;Lab 16 - Gateway API with Traefik&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; route by host, path and header through one entry point, split
traffic for a canary - as the application team, on a Gateway owned by the
platform team.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-02/08-gateway-api/"&gt;Gateway API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Requires Traefik and the Gateway API CRDs from
&lt;a href="https://training.caha.cloud/en/kubernetes-gt/labs/lab-14-helm/"&gt;Lab 14&lt;/a&gt; and the &lt;code&gt;shop&lt;/code&gt; / &lt;code&gt;wiki&lt;/code&gt;
apps in namespace &lt;code&gt;web&lt;/code&gt; from Lab 15.&lt;/p&gt;
&lt;h2 id="the-platform-side"&gt;The platform side&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - what the platform team gives you&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get gatewayclass
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get gateway -n traefik
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get gateway traefik-gateway -n traefik -o yaml &lt;span class="p"&gt;|&lt;/span&gt; grep -A12 &lt;span class="s1"&gt;&amp;#39;listeners:&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;GatewayClass &lt;code&gt;traefik&lt;/code&gt; - the implementation.&lt;/li&gt;
&lt;li&gt;Gateway &lt;code&gt;traefik-gateway&lt;/code&gt; in namespace &lt;code&gt;traefik&lt;/code&gt;, listener &lt;code&gt;web&lt;/code&gt; on port
&lt;strong&gt;8000&lt;/strong&gt; - Traefik&amp;rsquo;s entry point, exposed on NodePort 30080.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;allowedRoutes.namespaces.from: All&lt;/code&gt; - routes from any namespace may attach.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - PROGRAMMED must be True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get gateway traefik-gateway -n traefik
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="the-application-side"&gt;The application side&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3 - one HTTPRoute per application, in the application&amp;#39;s namespace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; routes.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: gateway.networking.k8s.io/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: HTTPRoute
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: shop
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; namespace: web
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; parentRefs:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: traefik-gateway
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; namespace: traefik
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; hostnames: [&amp;#34;shop.k8s.lab&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; rules:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - backendRefs:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: shop
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; port: 80
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: gateway.networking.k8s.io/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: HTTPRoute
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: wiki
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; namespace: web
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; parentRefs:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: traefik-gateway
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; namespace: traefik
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; hostnames: [&amp;#34;wiki.k8s.lab&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; rules:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - backendRefs:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: wiki
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; port: 80
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f routes.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get httproute -n web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4 - did the Gateway accept them?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl describe httproute shop -n web &lt;span class="p"&gt;|&lt;/span&gt; grep -A20 &lt;span class="s1"&gt;&amp;#39;Status:&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Look for &lt;code&gt;Accepted: True&lt;/code&gt; and &lt;code&gt;ResolvedRefs: True&lt;/code&gt; under the parent
&lt;code&gt;traefik-gateway&lt;/code&gt;. The route tells you if something is wrong - Ingress never
did.&lt;/p&gt;</description></item><item><title>Lab 17 - Kustomize overlays</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-17-kustomize/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-17-kustomize/index.html</guid><description>&lt;h1 id="lab-17---kustomize-overlays"&gt;Lab 17 - Kustomize overlays&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; one base, two environments, no copy-paste.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-02/09-kustomize/"&gt;Kustomize&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="the-base"&gt;The base&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 -&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p ~/kust/base ~/kust/overlays/dev ~/kust/overlays/prod
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/kust
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy web --image nginx:1.27 --dry-run&lt;span class="o"&gt;=&lt;/span&gt;client -o yaml &amp;gt; base/deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create svc clusterip web --tcp 80:80 --dry-run&lt;span class="o"&gt;=&lt;/span&gt;client -o yaml &amp;gt; base/service.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; base/kustomization.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: kustomize.config.k8s.io/v1beta1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Kustomization
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;resources:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - service.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl kustomize base
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;kubectl kustomize&lt;/code&gt; only renders - nothing is sent to the cluster.&lt;/p&gt;</description></item><item><title>Lab Extra - 01 - External access from your PC</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-extra-01-external-access/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-extra-01-external-access/index.html</guid><description>&lt;h1 id="lab-extra---01---external-access-from-your-pc"&gt;Lab Extra - 01 - External access from your PC&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; open &lt;code&gt;http://red.app.internal&lt;/code&gt;, &lt;code&gt;http://blue.app.internal&lt;/code&gt; and
&lt;code&gt;http://green.app.internal&lt;/code&gt; in the browser on your Windows PC and land on
three different applications in the cluster - through an edge proxy on
support01, a MetalLB load-balancer address and the Gateway API.
&lt;strong&gt;Chapters:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-02/05-networking-services/"&gt;Services&lt;/a&gt; ·
&lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-02/06-helm/"&gt;Helm&lt;/a&gt; ·
&lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-02/08-gateway-api/"&gt;Gateway API&lt;/a&gt;&lt;/p&gt;
&lt;div class="box notices cstyle info"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; Info&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;&lt;strong&gt;Homework.&lt;/strong&gt; This lab does not fit into the course day - plan 2-3 hours.
It needs Traefik, the Gateway API CRDs and the Gateway &lt;code&gt;traefik-gateway&lt;/code&gt; from
&lt;a href="https://training.caha.cloud/en/kubernetes-gt/labs/lab-14-helm/"&gt;Lab 14&lt;/a&gt; and
&lt;a href="https://training.caha.cloud/en/kubernetes-gt/labs/lab-16-gateway-api/"&gt;Lab 16&lt;/a&gt;, and nothing
from later days. Later labs do not depend on it: NodePort 30080 keeps working
whatever you do here.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>Lab 18 - Rolling updates and rollbacks</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-18-rollouts/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-18-rollouts/index.html</guid><description>&lt;h1 id="lab-18---rolling-updates-and-rollbacks"&gt;Lab 18 - Rolling updates and rollbacks&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; roll forward, break it, roll back - and choose a strategy.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-03/01-rollouts/"&gt;Rolling updates and rollbacks&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - a Deployment with 4 replicas&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy web --image nginx:1.27 --replicas &lt;span class="m"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl annotate deploy web kubernetes.io/change-cause&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;initial 1.27&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl rollout status deploy/web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - roll forward, watch it happen (second terminal: kubectl get pods -l app=web -w)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl &lt;span class="nb"&gt;set&lt;/span&gt; image deploy/web &lt;span class="nv"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx:1.28
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl annotate deploy web kubernetes.io/change-cause&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;upgrade to 1.28&amp;#34;&lt;/span&gt; --overwrite
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl rollout status deploy/web
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get rs -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl rollout &lt;span class="nb"&gt;history&lt;/span&gt; deploy/web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Two ReplicaSets: old at 0, new at 4. &lt;code&gt;CHANGE-CAUSE&lt;/code&gt; makes the history
readable.&lt;/p&gt;</description></item><item><title>Lab 19 - Requests, limits and quotas</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-19-resources-quotas/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-19-resources-quotas/index.html</guid><description>&lt;h1 id="lab-19---requests-limits-and-quotas"&gt;Lab 19 - Requests, limits and quotas&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; install metrics-server, see throttling and OOM kills, and put guard
rails on a namespace.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-03/02-resources/"&gt;Requests, limits and quotas&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="install-metrics-server"&gt;Install metrics-server&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 -&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl top nodes &lt;span class="c1"&gt;# error: Metrics API not available&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.9.0/components.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl patch deploy metrics-server -n kube-system --type&lt;span class="o"&gt;=&lt;/span&gt;json &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p &lt;span class="s1"&gt;&amp;#39;[{&amp;#34;op&amp;#34;:&amp;#34;add&amp;#34;,&amp;#34;path&amp;#34;:&amp;#34;/spec/template/spec/containers/0/args/-&amp;#34;,&amp;#34;value&amp;#34;:&amp;#34;--kubelet-insecure-tls&amp;#34;}]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl rollout status deploy/metrics-server -n kube-system
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep 30&lt;span class="p"&gt;;&lt;/span&gt; kubectl top nodes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;--kubelet-insecure-tls&lt;/code&gt;: kubeadm kubelets use self-signed serving
certificates. Fine in a lab; in production sign them (&lt;code&gt;serverTLSBootstrap&lt;/code&gt;).&lt;/p&gt;</description></item><item><title>Lab 20 - Autoscaling with HPA</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-20-hpa/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-20-hpa/index.html</guid><description>&lt;h1 id="lab-20---autoscaling-with-hpa"&gt;Lab 20 - Autoscaling with HPA&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; put load on an application and watch it scale out - and back in.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-03/03-autoscaling/"&gt;Autoscaling with HPA&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Requires metrics-server from
&lt;a href="https://training.caha.cloud/en/kubernetes-gt/labs/lab-19-resources-quotas/"&gt;Lab 19&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - a CPU-hungry app WITH a CPU request&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy php-apache --image registry.k8s.io/hpa-example
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl &lt;span class="nb"&gt;set&lt;/span&gt; resources deploy php-apache --requests&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;cpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;200m --limits&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;cpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;500m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl expose deploy php-apache --port &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl rollout status deploy/php-apache
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - the HPA: target 50 % of the request, 1-6 replicas, fast scale-down for the lab&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; hpa.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: autoscaling/v2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: HorizontalPodAutoscaler
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: php-apache
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; scaleTargetRef:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; apiVersion: apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; kind: Deployment
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: php-apache
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; minReplicas: 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; maxReplicas: 6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; metrics:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - type: Resource
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; resource:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: cpu
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; target:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; type: Utilization
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; averageUtilization: 50
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; behavior:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; scaleDown:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; stabilizationWindowSeconds: 30
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f hpa.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get hpa php-apache &lt;span class="c1"&gt;# TARGETS cpu: 0%/50% (may show &amp;lt;unknown&amp;gt; for ~30 s)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3 - load (in a second terminal, leave it running)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl run load --image busybox:1.36 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never -- &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sh -c &lt;span class="s1"&gt;&amp;#39;while true; do wget -q -O- http://php-apache; done&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4 - watch it scale out&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get hpa php-apache -w &lt;span class="c1"&gt;# Ctrl-C after a few minutes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get deploy php-apache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl describe hpa php-apache &lt;span class="p"&gt;|&lt;/span&gt; tail -8
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;TARGETS&lt;/code&gt; jumps to 200-300 %, &lt;code&gt;REPLICAS&lt;/code&gt; climbs until the average is back
near 50 %. The events show each decision: &lt;code&gt;New size: 4; reason: cpu resource utilization (percentage of request) above target&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Lab 21 - Scheduling and node maintenance</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-21-scheduling-node-ops/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-21-scheduling-node-ops/index.html</guid><description>&lt;h1 id="lab-21---scheduling-and-node-maintenance"&gt;Lab 21 - Scheduling and node maintenance&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; reserve a node for a workload, require specific hardware, and take a
node out for maintenance without downtime.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-03/04-scheduling-nodes/"&gt;Scheduling and node operations&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="tolerations-permit"&gt;Tolerations permit&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - reserve worker03 for &amp;#34;database&amp;#34; workloads&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl taint node worker03 &lt;span class="nv"&gt;workload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;db:NoSchedule
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; tolerant.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Pod
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: tolerant
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; tolerations:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - key: workload
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; operator: Equal
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; value: db
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; effect: NoSchedule
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: box
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; image: busybox:1.36
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; command: [&amp;#34;sleep&amp;#34;, &amp;#34;3600&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f tolerant.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pod tolerant -o wide
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Look at which node it picked.&lt;/strong&gt; It probably is &lt;em&gt;not&lt;/em&gt; worker03. The toleration
said &amp;ldquo;I can live with that taint&amp;rdquo;, not &amp;ldquo;put me there&amp;rdquo; - the scheduler was free
to choose any node and the empty one was not necessarily the best fit.&lt;/p&gt;</description></item><item><title>Lab 22 - Health checks</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-22-probes/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-22-probes/index.html</guid><description>&lt;h1 id="lab-22---health-checks"&gt;Lab 22 - Health checks&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; see what each probe does when it fails - and how readiness protects a
rollout.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-03/05-probes/"&gt;Startup, readiness and liveness probes&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="readiness-no-traffic-no-restart"&gt;Readiness: no traffic, no restart&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - three replicas behind a Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy web --image nginx:1.27 --replicas &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl expose deploy web --port &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl rollout status deploy/web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - add a readiness probe on a file we control&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl patch deploy web -p &lt;span class="s1"&gt;&amp;#39;{&amp;#34;spec&amp;#34;:{&amp;#34;template&amp;#34;:{&amp;#34;spec&amp;#34;:{&amp;#34;containers&amp;#34;:[{&amp;#34;name&amp;#34;:&amp;#34;nginx&amp;#34;,&amp;#34;readinessProbe&amp;#34;:{&amp;#34;httpGet&amp;#34;:{&amp;#34;path&amp;#34;:&amp;#34;/ready.html&amp;#34;,&amp;#34;port&amp;#34;:80},&amp;#34;periodSeconds&amp;#34;:3}}]}}}}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web -w &lt;span class="c1"&gt;# Ctrl-C: new Pods Running but 0/1 READY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The rollout is &lt;strong&gt;stuck, safely&lt;/strong&gt;: new Pods never become ready, so the old ones
keep serving.&lt;/p&gt;</description></item><item><title>Lab 23 - Logs, events and troubleshooting</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-23-troubleshooting/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-23-troubleshooting/index.html</guid><description>&lt;h1 id="lab-23---logs-events-and-troubleshooting"&gt;Lab 23 - Logs, events and troubleshooting&lt;/h1&gt;
&lt;span class="badge cstyle info badge-with-title"&gt;&lt;span class="badge-title"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; Info&lt;/span&gt;&lt;span class="badge-content"&gt;discovery&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; read logs and events fluently, then diagnose five broken Pods from
cluster output alone.
&lt;strong&gt;Chapters:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-03/06-logs-events/"&gt;Logs and events&lt;/a&gt; ·
&lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-03/07-debugging/"&gt;Troubleshooting&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="warm-up-logs-and-events"&gt;Warm-up: logs and events&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# setup - a chatty Deployment with two containers per Pod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; chatty.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Deployment
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: chatty
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; replicas: 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; matchLabels: { app: chatty }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; labels: { app: chatty }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: app
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; image: busybox:1.36
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; command: [&amp;#34;sh&amp;#34;, &amp;#34;-c&amp;#34;, &amp;#34;i=0; while true; do i=$((i+1)); echo \&amp;#34;app line $i\&amp;#34;; sleep 2; done&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: sidecar
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; image: busybox:1.36
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; command: [&amp;#34;sh&amp;#34;, &amp;#34;-c&amp;#34;, &amp;#34;while true; do echo sidecar alive; sleep 5; done&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f chatty.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Task L1.&lt;/strong&gt; Show the last 5 lines of the &lt;code&gt;app&lt;/code&gt; container of &lt;strong&gt;all&lt;/strong&gt; chatty
Pods, with the Pod name in front of each line.&lt;/p&gt;</description></item><item><title>Lab 24 - Ephemeral containers and kubectl debug</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-24-kubectl-debug/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-24-kubectl-debug/index.html</guid><description>&lt;h1 id="lab-24---ephemeral-containers-and-kubectl-debug"&gt;Lab 24 - Ephemeral containers and kubectl debug&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; debug a Pod that has no shell, a Pod that crashes at start, and a
node.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-03/07-debugging/"&gt;Troubleshooting and kubectl debug&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="a-pod-without-tools"&gt;A Pod without tools&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - a minimal image: no shell, nothing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl run minimal --image registry.k8s.io/pause:3.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -it minimal -- sh &lt;span class="c1"&gt;# fails: no sh in the image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - bring your own tools as an ephemeral container&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl debug -it minimal --image busybox:1.36 --target minimal
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Inside the debug container:&lt;/p&gt;</description></item><item><title>Lab 25 - Troubleshooting challenge</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-25-troubleshooting-challenge/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-25-troubleshooting-challenge/index.html</guid><description>&lt;h1 id="lab-25---troubleshooting-challenge"&gt;Lab 25 - Troubleshooting challenge&lt;/h1&gt;
&lt;span class="badge cstyle info badge-with-title"&gt;&lt;span class="badge-title"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; Info&lt;/span&gt;&lt;span class="badge-content"&gt;discover&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; a &amp;ldquo;production&amp;rdquo; namespace with several faults. Make it work using
only what you learned in Days 1-3.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-03/07-debugging/"&gt;Troubleshooting and kubectl debug&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="the-scenario"&gt;The scenario&lt;/h2&gt;
&lt;p&gt;The shop team deployed to namespace &lt;code&gt;challenge&lt;/code&gt; and went home. Nothing works.
Your definition of done:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;frontend&lt;/code&gt; Deployment: &lt;strong&gt;3/3 ready&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;worker&lt;/code&gt; Deployment: &lt;strong&gt;1/1 ready&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;curl -H 'Host: shop.k8s.lab' http://worker01:30080&lt;/code&gt; returns the nginx page
(Traefik + Gateway from Day 2).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kubectl get events -n challenge --types=Warning&lt;/code&gt; shows nothing new.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Set it up - &lt;strong&gt;do not read the manifest&lt;/strong&gt;, that is cheating:&lt;/p&gt;</description></item><item><title>Lab 26 - Users, certificates and kubeconfig</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-26-users-kubeconfig/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-26-users-kubeconfig/index.html</guid><description>&lt;h1 id="lab-26---users-certificates-and-kubeconfig"&gt;Lab 26 - Users, certificates and kubeconfig&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; create user &lt;code&gt;jane&lt;/code&gt; (group &lt;code&gt;dev-team&lt;/code&gt;) with a certificate signed by
the cluster, and log in as her.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-04/01-authn-authz/"&gt;Authentication and authorization&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - who am I now?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl auth whoami
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;kubernetes-admin&lt;/code&gt;, group &lt;code&gt;kubeadm:cluster-admins&lt;/code&gt; - the certificate in your
kubeconfig.&lt;/p&gt;
&lt;h2 id="jane-asks-for-a-certificate"&gt;Jane asks for a certificate&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - private key and CSR: CN = user name, O = group&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p ~/jane &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~/jane
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl genrsa -out jane.key &lt;span class="m"&gt;2048&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl req -new -key jane.key -out jane.csr -subj &lt;span class="s2"&gt;&amp;#34;/CN=jane/O=dev-team&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3 - send it to the cluster&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; csr.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;YAML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: certificates.k8s.io/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: CertificateSigningRequest
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: jane
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; request: $(base64 -w0 jane.csr)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; signerName: kubernetes.io/kube-apiserver-client
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; expirationSeconds: 86400
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; usages: [&amp;#34;client auth&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f csr.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get csr jane &lt;span class="c1"&gt;# Pending&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="the-admin-approves"&gt;The admin approves&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4 -&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl certificate approve jane
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get csr jane &lt;span class="c1"&gt;# Approved,Issued&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get csr jane -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.status.certificate}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; base64 -d &amp;gt; jane.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl x509 -in jane.crt -noout -subject -issuer -enddate
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Issuer = the cluster CA, valid 24 h - because we asked for
&lt;code&gt;expirationSeconds: 86400&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Lab 27 - RBAC</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-27-rbac/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-27-rbac/index.html</guid><description>&lt;h1 id="lab-27---rbac"&gt;Lab 27 - RBAC&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; give Jane exactly what she needs in &lt;code&gt;dev&lt;/code&gt; - and nothing else.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-04/02-rbac/"&gt;RBAC and least privilege&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Requires user &lt;code&gt;jane&lt;/code&gt; from &lt;a href="https://training.caha.cloud/en/kubernetes-gt/labs/lab-26-users-kubeconfig/"&gt;Lab 26&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - something to look at&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy web --image nginx:1.27 --replicas &lt;span class="m"&gt;2&lt;/span&gt; -n dev
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl --context jane get pods &lt;span class="c1"&gt;# Forbidden&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - a Role: read Pods and their logs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create role pod-reader -n dev &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --verb&lt;span class="o"&gt;=&lt;/span&gt;get,list,watch --resource&lt;span class="o"&gt;=&lt;/span&gt;pods,pods/log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create rolebinding jane-pod-reader -n dev &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --role&lt;span class="o"&gt;=&lt;/span&gt;pod-reader --user&lt;span class="o"&gt;=&lt;/span&gt;jane
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl --context jane get pods &lt;span class="c1"&gt;# works&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl --context jane logs deploy/web --tail&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl --context jane delete pod --all &lt;span class="c1"&gt;# Forbidden&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl --context jane get deploy &lt;span class="c1"&gt;# Forbidden - only pods&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3 - the whole list, from the admin side&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl auth can-i --list -n dev --as jane
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="groups-and-built-in-roles"&gt;Groups and built-in roles&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4 - dev-team may edit in dev (built-in ClusterRole &amp;#34;edit&amp;#34;, scoped by RoleBinding)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create rolebinding dev-team-edit -n dev --clusterrole&lt;span class="o"&gt;=&lt;/span&gt;edit --group&lt;span class="o"&gt;=&lt;/span&gt;dev-team
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl --context jane get deploy &lt;span class="c1"&gt;# works now - via her group&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl --context jane scale deploy web --replicas &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl --context jane get secrets &lt;span class="c1"&gt;# works - edit includes secrets!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl --context jane get pods -n default &lt;span class="c1"&gt;# Forbidden - other namespace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;edit&lt;/code&gt; includes reading Secrets and &lt;code&gt;pods/exec&lt;/code&gt;. Convenient - and a lot of
power. Is that what the team needs?&lt;/p&gt;</description></item><item><title>Lab 28 - Service accounts</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-28-service-accounts/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-28-service-accounts/index.html</guid><description>&lt;h1 id="lab-28---service-accounts"&gt;Lab 28 - Service accounts&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; see the token every Pod carries, call the API with it, and give an
application exactly the rights it needs.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-04/03-service-accounts/"&gt;Service accounts&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - a Pod with curl, running as the default ServiceAccount&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl run api-client -n dev --image curlimages/curl:8.10.1 --command -- sleep &lt;span class="m"&gt;3600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pod api-client -n dev -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.spec.serviceAccountName}{&amp;#34;\n&amp;#34;}&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;# default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -n dev api-client -- ls /var/run/secrets/kubernetes.io/serviceaccount
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - what is in the token? (a JWT: header.payload.signature)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -n dev api-client -- cat /var/run/secrets/kubernetes.io/serviceaccount/token &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;|&lt;/span&gt; cut -d. -f2 &lt;span class="p"&gt;|&lt;/span&gt; base64 -d 2&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Find &lt;code&gt;sub&lt;/code&gt; (&lt;code&gt;system:serviceaccount:dev:default&lt;/code&gt;), &lt;code&gt;aud&lt;/code&gt;, &lt;code&gt;exp&lt;/code&gt; (about 1 hour)
and the Pod name - the token is &lt;strong&gt;bound&lt;/strong&gt; to this Pod.&lt;/p&gt;</description></item><item><title>Lab 29 - Workload hardening</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-29-security-context/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-29-security-context/index.html</guid><description>&lt;h1 id="lab-29---workload-hardening"&gt;Lab 29 - Workload hardening&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; take a default container apart, then run the same web server
hardened: non-root, read-only, no capabilities.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-04/04-security-context/"&gt;Security context and container hardening&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="what-a-default-container-can-do"&gt;What a default container can do&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 -&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create ns hard
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl run plain -n hard --image nginx:1.27
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -n hard plain -- id &lt;span class="c1"&gt;# uid=0(root)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -n hard plain -- sh -c &lt;span class="s1"&gt;&amp;#39;echo hacked &amp;gt; /usr/share/nginx/html/index.html; echo written&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; -n hard plain -- grep Cap /proc/1/status
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Root, writable filesystem, a set of capabilities (&lt;code&gt;CapEff&lt;/code&gt; not zero). If an
attacker gets code execution, they can rewrite your website.&lt;/p&gt;</description></item><item><title>Lab 30 - Pod Security Admission</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-30-pod-security-admission/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-30-pod-security-admission/index.html</guid><description>&lt;h1 id="lab-30---pod-security-admission"&gt;Lab 30 - Pod Security Admission&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; roll out Pod Security Standards on a namespace the safe way: warn
first, enforce later.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-04/05-pod-security/"&gt;Pod Security Standards and Admission&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Uses namespace &lt;code&gt;hard&lt;/code&gt; and &lt;code&gt;hardened.yaml&lt;/code&gt; from
&lt;a href="https://training.caha.cloud/en/kubernetes-gt/labs/lab-29-security-context/"&gt;Lab 29&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - which namespaces have a level today?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get ns -L pod-security.kubernetes.io/enforce,pod-security.kubernetes.io/warn
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nothing - every namespace allows privileged Pods.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - a privileged Pod, allowed today&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl run root-shell -n dev --image busybox:1.36 --restart&lt;span class="o"&gt;=&lt;/span&gt;Never &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --overrides&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{&amp;#34;spec&amp;#34;:{&amp;#34;hostPID&amp;#34;:true,&amp;#34;containers&amp;#34;:[{&amp;#34;name&amp;#34;:&amp;#34;root-shell&amp;#34;,&amp;#34;image&amp;#34;:&amp;#34;busybox:1.36&amp;#34;,&amp;#34;command&amp;#34;:[&amp;#34;sleep&amp;#34;,&amp;#34;3600&amp;#34;],&amp;#34;securityContext&amp;#34;:{&amp;#34;privileged&amp;#34;:true}}]}}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pod root-shell -n dev
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl delete pod root-shell -n dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;hostPID&lt;/code&gt; + &lt;code&gt;privileged&lt;/code&gt; = full control over the node. Nothing stopped it.&lt;/p&gt;</description></item><item><title>Lab 31 - Admission policies</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-31-admission-policies/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-31-admission-policies/index.html</guid><description>&lt;h1 id="lab-31---admission-policies"&gt;Lab 31 - Admission policies&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; enforce your own rules with a built-in ValidatingAdmissionPolicy -
no extra software.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-04/06-admission-policies/"&gt;Admission policies&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="rule-1-no-latest"&gt;Rule 1: no &lt;code&gt;latest&lt;/code&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 -&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; vap-latest.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: admissionregistration.k8s.io/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: ValidatingAdmissionPolicy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: no-latest-tag
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; failurePolicy: Fail
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; matchConstraints:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; resourceRules:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - apiGroups: [&amp;#34;apps&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; apiVersions: [&amp;#34;v1&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; operations: [&amp;#34;CREATE&amp;#34;, &amp;#34;UPDATE&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; resources: [&amp;#34;deployments&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; validations:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - expression: &amp;gt;-
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; object.spec.template.spec.containers.all(c,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; c.image.contains(&amp;#39;:&amp;#39;) &amp;amp;&amp;amp; !c.image.endsWith(&amp;#39;:latest&amp;#39;))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; message: &amp;#34;images must have an explicit tag other than latest&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: admissionregistration.k8s.io/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: ValidatingAdmissionPolicyBinding
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: no-latest-tag
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; policyName: no-latest-tag
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; validationActions: [&amp;#34;Warn&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; matchResources:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; namespaceSelector:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; matchLabels:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; policy: enforced
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f vap-latest.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create ns policy-demo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl label ns policy-demo &lt;span class="nv"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;enforced
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - Warn mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy a -n policy-demo --image nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy b -n policy-demo --image nginx:1.27
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;a&lt;/code&gt; is created &lt;strong&gt;with a warning&lt;/strong&gt;; &lt;code&gt;b&lt;/code&gt; without. Warn first - see who would be
hit.&lt;/p&gt;</description></item><item><title>Lab 32 - Network policies with Calico</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-32-network-policies/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-32-network-policies/index.html</guid><description>&lt;h1 id="lab-32---network-policies-with-calico"&gt;Lab 32 - Network policies with Calico&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; get to know the cluster&amp;rsquo;s CNI, then segment a three-tier app: only
frontend -&amp;gt; backend -&amp;gt; db, nothing else.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-04/07-network-policies/"&gt;Network policies and segmentation&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="calico-up-close"&gt;Calico, up close&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - the operator&amp;#39;s view&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get tigerastatus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get installation default -o yaml &lt;span class="p"&gt;|&lt;/span&gt; grep -A8 calicoNetwork
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -n calico-system -o wide
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - Calico resources, through the Calico API server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl api-resources --api-group&lt;span class="o"&gt;=&lt;/span&gt;projectcalico.org
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get ippools -o wide
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One IP pool &lt;code&gt;10.244.0.0/16&lt;/code&gt;, VXLAN encapsulation - the overlay you saw on
Day 2.&lt;/p&gt;</description></item><item><title>Lab 33 - Image scanning, encryption at rest, audit log</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-33-supply-chain/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-33-supply-chain/index.html</guid><description>&lt;h1 id="lab-33---image-scanning-encryption-at-rest-audit-log"&gt;Lab 33 - Image scanning, encryption at rest, audit log&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; find vulnerabilities before they run, make Secrets unreadable in
etcd, and record who does what.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-04/08-supply-chain/"&gt;Images, secrets and audit&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="part-1---trivy-support01"&gt;Part 1 - Trivy (support01)&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - install from the vendor&amp;#39;s apt repository&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get install -y wget gnupg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;|&lt;/span&gt; gpg --dearmor &lt;span class="p"&gt;|&lt;/span&gt; sudo tee /usr/share/keyrings/trivy.gpg &amp;gt;/dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee /etc/apt/sources.list.d/trivy.list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apt-cache policy trivy &lt;span class="p"&gt;|&lt;/span&gt; head -5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get install -y trivy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;trivy --version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="box notices cstyle warning"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-exclamation-triangle"&gt;&lt;/i&gt; Warning&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;Check the version: &lt;strong&gt;v0.69.4 was a malicious release&lt;/strong&gt; (March 2026 supply-chain
attack). Your trainer tells you the version to pin
(&lt;code&gt;sudo apt-get install trivy=&amp;lt;version&amp;gt;&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>Lab 34 - Security review challenge</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-34-security-challenge/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-34-security-challenge/index.html</guid><description>&lt;h1 id="lab-34---security-review-challenge"&gt;Lab 34 - Security review challenge&lt;/h1&gt;
&lt;span class="badge cstyle info badge-with-title"&gt;&lt;span class="badge-title"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; Info&lt;/span&gt;&lt;span class="badge-content"&gt;discover&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; a team asks for a security review before go-live. Find the problems,
fix them, and prove each fix.
&lt;strong&gt;Chapters:&lt;/strong&gt; Day 4 - all of them.&lt;/p&gt;
&lt;h2 id="the-application"&gt;The application&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; payments.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Namespace
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: payments }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: ServiceAccount
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: payments-app, namespace: payments }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: rbac.authorization.k8s.io/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: ClusterRoleBinding
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: payments-app-admin }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;subjects: [{ kind: ServiceAccount, name: payments-app, namespace: payments }]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;roleRef: { kind: ClusterRole, name: cluster-admin, apiGroup: rbac.authorization.k8s.io }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: ConfigMap
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: payments-cfg, namespace: payments }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;data:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; DB_HOST: db
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; DB_PASSWORD: &amp;#34;Summer2026!&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Deployment
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: api, namespace: payments }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; replicas: 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector: { matchLabels: { app: api } }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; metadata: { labels: { app: api } }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; serviceAccountName: payments-app
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: api
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; image: nginx:latest
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; envFrom: [{ configMapRef: { name: payments-cfg } }]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; securityContext: { privileged: true }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Deployment
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: db, namespace: payments }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; replicas: 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector: { matchLabels: { app: db } }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; metadata: { labels: { app: db } }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: db
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; image: nginx:1.27
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: db, namespace: payments }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector: { app: db }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; ports: [{ port: 80 }]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f payments.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(&lt;code&gt;db&lt;/code&gt; is a stand-in - nginx on port 80 plays the database.)&lt;/p&gt;</description></item><item><title>Lab 35 - Static and dynamic storage</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-35-storage/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-35-storage/index.html</guid><description>&lt;h1 id="lab-35---static-and-dynamic-storage"&gt;Lab 35 - Static and dynamic storage&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; replace hand-written PersistentVolumes with self-service: a CSI
driver and a StorageClass.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-05/01-storage/"&gt;PV, PVC and StorageClasses&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On Day 2 (&lt;a href="https://training.caha.cloud/en/kubernetes-gt/labs/lab-10-statefulsets/"&gt;Lab 10&lt;/a&gt;)
you wrote three static NFS PVs by hand. Check they are still there:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pv &lt;span class="c1"&gt;# pv-storage1..3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="dynamic-provisioning-with-the-nfs-csi-driver"&gt;Dynamic provisioning with the NFS CSI driver&lt;/h2&gt;
&lt;p&gt;Everything so far was &lt;strong&gt;static&lt;/strong&gt;: you wrote a PV for every share, by hand. That
does not scale - ten teams asking for volumes means ten PVs and a ticket each.
A &lt;strong&gt;CSI driver&lt;/strong&gt; plus a &lt;strong&gt;StorageClass&lt;/strong&gt; turns that into self-service: the PVC
asks, the driver creates.&lt;/p&gt;</description></item><item><title>Lab 36 - Running a stateful application</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-36-stateful-app/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-36-stateful-app/index.html</guid><description>&lt;h1 id="lab-36---running-a-stateful-application"&gt;Lab 36 - Running a stateful application&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; run Redis with persistent storage the production way - dynamic
volumes, spread replicas, a disruption budget - then grow its disk and survive
a node drain.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-05/02-stateful-workloads/"&gt;Stateful workloads&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Requires the &lt;code&gt;nfs-csi&lt;/code&gt; StorageClass from
&lt;a href="https://training.caha.cloud/en/kubernetes-gt/labs/lab-35-storage/"&gt;Lab 35&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 -&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create ns state
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl config set-context --current --namespace&lt;span class="o"&gt;=&lt;/span&gt;state
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; redis.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: redis
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; clusterIP: None
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector: { app: redis }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; ports: [{ port: 6379 }]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: StatefulSet
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: redis
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; serviceName: redis
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; replicas: 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; matchLabels: { app: redis }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; labels: { app: redis }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; topologySpreadConstraints:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - maxSkew: 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; topologyKey: kubernetes.io/hostname
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; whenUnsatisfiable: DoNotSchedule
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; labelSelector:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; matchLabels: { app: redis }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: redis
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; image: redis:7.4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; args: [&amp;#34;--appendonly&amp;#34;, &amp;#34;yes&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; ports: [{ containerPort: 6379 }]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; readinessProbe:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; exec: { command: [&amp;#34;redis-cli&amp;#34;, &amp;#34;ping&amp;#34;] }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; resources:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; requests: { cpu: &amp;#34;50m&amp;#34;, memory: &amp;#34;64Mi&amp;#34; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; limits: { memory: &amp;#34;256Mi&amp;#34; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; volumeMounts:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - { name: data, mountPath: /data }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; volumeClaimTemplates:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: data
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; accessModes: [&amp;#34;ReadWriteOnce&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; storageClassName: nfs-csi
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; resources:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; requests:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; storage: 200Mi
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: policy/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: PodDisruptionBudget
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; name: redis
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; maxUnavailable: 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; matchLabels: { app: redis }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f redis.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl rollout status sts/redis
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods,pvc -o wide
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Two Pods on two different nodes, two PVCs created by the driver - nobody
wrote a PV.&lt;/p&gt;</description></item><item><title>Lab 37 - Prometheus and Grafana</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-37-prometheus-grafana/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-37-prometheus-grafana/index.html</guid><description>&lt;h1 id="lab-37---prometheus-and-grafana"&gt;Lab 37 - Prometheus and Grafana&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; install the monitoring stack, read the cluster in Grafana, scrape
your own application and write an alert.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-05/03-observability/"&gt;Monitoring with Prometheus and Grafana&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="install-kube-prometheus-stack"&gt;Install kube-prometheus-stack&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 -&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm repo update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; kps-values.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;prometheus:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; prometheusSpec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; retention: 2d
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; serviceMonitorSelectorNilUsesHelmValues: false # watch ALL ServiceMonitors
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; ruleSelectorNilUsesHelmValues: false # and ALL PrometheusRules
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# kubeadm binds these to localhost - skip them in the lab
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kubeEtcd: { enabled: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kubeScheduler: { enabled: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kubeControllerManager: { enabled: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm install kps prometheus-community/kube-prometheus-stack -n monitoring &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --create-namespace -f kps-values.yaml --wait --timeout 10m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -n monitoring
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - what arrived?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get crd &lt;span class="p"&gt;|&lt;/span&gt; grep monitoring.coreos.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get ds,deploy,sts -n monitoring
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get servicemonitors -n monitoring
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Prometheus and Alertmanager (StatefulSets, run by the Prometheus Operator),
Grafana, kube-state-metrics, node-exporter (DaemonSet) - and a dozen
ServiceMonitors describing what to scrape.&lt;/p&gt;</description></item><item><title>Lab 38 - Production incident analysis</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-38-incident-analysis/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-38-incident-analysis/index.html</guid><description>&lt;h1 id="lab-38---production-incident-analysis"&gt;Lab 38 - Production incident analysis&lt;/h1&gt;
&lt;span class="badge cstyle info badge-with-title"&gt;&lt;span class="badge-title"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; Info&lt;/span&gt;&lt;span class="badge-content"&gt;discover&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; three tickets from users. Find the root cause with metrics, events
and logs, mitigate, and write a short postmortem.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-05/03-observability/"&gt;Monitoring with Prometheus and Grafana&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Requires the monitoring stack from
&lt;a href="https://training.caha.cloud/en/kubernetes-gt/labs/lab-37-prometheus-grafana/"&gt;Lab 37&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="set-the-scene"&gt;Set the scene&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; incidents.yaml &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;YAML&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Namespace
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: prod }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Deployment
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: checkout, namespace: prod }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; replicas: 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector: { matchLabels: { app: checkout } }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; metadata: { labels: { app: checkout } }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: checkout
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; image: registry.k8s.io/hpa-example
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; resources:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; requests: { cpu: &amp;#34;50m&amp;#34; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; limits: { cpu: &amp;#34;50m&amp;#34; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: checkout, namespace: prod }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector: { app: checkout }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; ports: [{ port: 80 }]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Deployment
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: reports, namespace: prod }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; replicas: 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector: { matchLabels: { app: reports } }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; metadata: { labels: { app: reports } }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: reports
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; image: busybox:1.36
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; command: [&amp;#34;sh&amp;#34;, &amp;#34;-c&amp;#34;, &amp;#34;x=; while true; do x=\&amp;#34;$x$(head -c 1000000 /dev/zero | tr &amp;#39;\\0&amp;#39; a)\&amp;#34;; sleep 2; done&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; resources:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; limits: { memory: &amp;#34;64Mi&amp;#34; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Deployment
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: catalog, namespace: prod }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; replicas: 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector: { matchLabels: { app: catalog, track: stable } }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; metadata: { labels: { app: catalog, track: stable } }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; containers: [{ name: web, image: &amp;#34;nginx:1.27&amp;#34; }]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Deployment
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: catalog-test, namespace: prod }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; replicas: 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector: { matchLabels: { app: catalog, track: test } }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; template:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; metadata: { labels: { app: catalog, track: test } }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: web
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; image: nginx:1.27
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; command: [&amp;#34;sh&amp;#34;, &amp;#34;-c&amp;#34;, &amp;#34;rm /usr/share/nginx/html/index.html; nginx -g &amp;#39;daemon off;&amp;#39;&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: catalog, namespace: prod }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; selector: { app: catalog }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; ports: [{ port: 80 }]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kind: Pod
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata: { name: traffic, namespace: prod }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; containers:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; - name: traffic
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; image: busybox:1.36
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; command: [&amp;#34;sh&amp;#34;, &amp;#34;-c&amp;#34;, &amp;#34;while true; do wget -qO- http://checkout &amp;gt;/dev/null; wget -qO- http://catalog &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; done&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;YAML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f incidents.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wait 5 minutes for the metrics to build up. &lt;strong&gt;Do not read the manifest&lt;/strong&gt; -
work from the symptoms.&lt;/p&gt;</description></item><item><title>Lab 39 - Backup and restore with Velero</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-39-velero/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-39-velero/index.html</guid><description>&lt;h1 id="lab-39---backup-and-restore-with-velero"&gt;Lab 39 - Backup and restore with Velero&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; back up a namespace with its volume data to S3 object storage,
destroy it, and restore it.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-05/04-backup-dr/"&gt;Backup and disaster recovery&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="object-storage-garage-on-support01"&gt;Object storage: Garage on support01&lt;/h2&gt;
&lt;p&gt;MinIO&amp;rsquo;s free edition stopped shipping images in 2025, so we use
&lt;a href="https://garagehq.deuxfleurs.fr/" target="_blank"&gt;Garage&lt;/a&gt; - a small S3-compatible server,
one container.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - config and credentials&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p ~/garage/meta ~/garage/data &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~/garage
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; garage.toml &lt;span class="s"&gt;&amp;lt;&amp;lt;TOML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;metadata_dir = &amp;#34;/var/lib/garage/meta&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;data_dir = &amp;#34;/var/lib/garage/data&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;db_engine = &amp;#34;sqlite&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;replication_factor = 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;rpc_bind_addr = &amp;#34;[::]:3901&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;rpc_public_addr = &amp;#34;127.0.0.1:3901&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;rpc_secret = &amp;#34;$(openssl rand -hex 32)&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;[s3_api]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;s3_region = &amp;#34;garage&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;api_bind_addr = &amp;#34;[::]:3900&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;TOML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;GARAGE_DEFAULT_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;GK&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;openssl rand -hex 16&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;GARAGE_DEFAULT_SECRET_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;openssl rand -hex 32&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;GARAGE_DEFAULT_BUCKET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;velero
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;[default]\naws_access_key_id=%s\naws_secret_access_key=%s\n&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$GARAGE_DEFAULT_ACCESS_KEY&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$GARAGE_DEFAULT_SECRET_KEY&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &amp;gt; ~/credentials-velero
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - run it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -d --name garage --restart unless-stopped &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p 3900:3900 -p 3901:3901 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v ~/garage/garage.toml:/etc/garage.toml &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v ~/garage/meta:/var/lib/garage/meta -v ~/garage/data:/var/lib/garage/data &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e GARAGE_DEFAULT_ACCESS_KEY -e GARAGE_DEFAULT_SECRET_KEY -e GARAGE_DEFAULT_BUCKET &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; dxflrs/garage:v2.3.0 /garage server --single-node --default-bucket
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; garage /garage status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; garage /garage bucket list &lt;span class="c1"&gt;# velero&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="install-velero"&gt;Install Velero&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3 - the CLI (pin the version your trainer gives you; plugin 1.14.x = Velero 1.18.x)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;VELERO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v1.18.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -fsSL https://github.com/vmware-tanzu/velero/releases/download/&lt;span class="nv"&gt;$VELERO&lt;/span&gt;/velero-&lt;span class="nv"&gt;$VELERO&lt;/span&gt;-linux-amd64.tar.gz &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;|&lt;/span&gt; tar xz -C /tmp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mv /tmp/velero-&lt;span class="nv"&gt;$VELERO&lt;/span&gt;-linux-amd64/velero /usr/local/bin/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;velero version --client-only
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4 - the server side (Pods reach Garage by IP - support01 is not in cluster DNS)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;S3_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;hostname -I &lt;span class="p"&gt;|&lt;/span&gt; tr &lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s1"&gt;&amp;#39;^192.168.128.&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$S3_IP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;velero install &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --provider aws &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --plugins velero/velero-plugin-for-aws:v1.14.0 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --bucket velero &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --secret-file ~/credentials-velero &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --backup-location-config &lt;span class="nv"&gt;region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;garage,s3ForcePathStyle&lt;span class="o"&gt;=&lt;/span&gt;true,s3Url&lt;span class="o"&gt;=&lt;/span&gt;http://&lt;span class="nv"&gt;$S3_IP&lt;/span&gt;:3900 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --use-volume-snapshots&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --use-node-agent &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --default-volumes-to-fs-backup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -n velero -w &lt;span class="c1"&gt;# velero + one node-agent per node; Ctrl-C&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;velero backup-location get &lt;span class="c1"&gt;# PHASE Available&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;--use-node-agent&lt;/code&gt; + &lt;code&gt;--default-volumes-to-fs-backup&lt;/code&gt;: volume data is copied
file by file (Kopia) - works with any storage, including NFS.&lt;/p&gt;</description></item><item><title>Lab 40 - etcd snapshot and restore</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-40-etcd-backup/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-40-etcd-backup/index.html</guid><description>&lt;h1 id="lab-40---etcd-snapshot-and-restore"&gt;Lab 40 - etcd snapshot and restore&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; save the complete cluster state, make a &amp;ldquo;fatal mistake&amp;rdquo;, and roll
the whole cluster back to the snapshot.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-05/04-backup-dr/"&gt;Backup and disaster recovery&lt;/a&gt;&lt;/p&gt;
&lt;div class="box notices cstyle warning"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-exclamation-triangle"&gt;&lt;/i&gt; Warning&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;This lab rewinds the &lt;strong&gt;entire cluster&lt;/strong&gt;. Everything created after the snapshot
disappears. Trainer: take a VM snapshot of control01 before the lab.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="tools-on-control01"&gt;Tools on control01&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1 - which etcd version runs? (on support01)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pod -n kube-system etcd-control01 -o &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{.spec.containers[0].image}{&amp;#34;\n&amp;#34;}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2 - matching etcdctl / etcdutl on control01&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh student@control01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ETCD_VER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v3.6.5 &lt;span class="c1"&gt;# &amp;lt;- the version from step 1, with &amp;#34;v&amp;#34;, without &amp;#34;-0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -fsSL https://github.com/etcd-io/etcd/releases/download/&lt;span class="nv"&gt;$ETCD_VER&lt;/span&gt;/etcd-&lt;span class="nv"&gt;$ETCD_VER&lt;/span&gt;-linux-amd64.tar.gz &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;|&lt;/span&gt; tar xz -C /tmp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mv /tmp/etcd-&lt;span class="nv"&gt;$ETCD_VER&lt;/span&gt;-linux-amd64/etcdctl /tmp/etcd-&lt;span class="nv"&gt;$ETCD_VER&lt;/span&gt;-linux-amd64/etcdutl /usr/local/bin/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;etcdctl version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;ectl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;sudo etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ectl endpoint health
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ectl member list -w table
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="state-worth-saving"&gt;State worth saving&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3 - on support01&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create ns precious
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create deploy vault -n precious --image nginx:1.27 --replicas &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create cm before-snapshot --from-literal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;old
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="snapshot"&gt;Snapshot&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4 - on control01&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh student@control01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;ectl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;sudo etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ectl snapshot save /root/etcd-snap.db
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo etcdutl snapshot status /root/etcd-snap.db -w table
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo cp /root/etcd-snap.db /tmp/ &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo chmod &lt;span class="m"&gt;644&lt;/span&gt; /tmp/etcd-snap.db
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;scp student@control01:/tmp/etcd-snap.db ~/etcd-snap-&lt;span class="k"&gt;$(&lt;/span&gt;date +%F&lt;span class="k"&gt;)&lt;/span&gt;.db &lt;span class="c1"&gt;# off the node!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The file holds &lt;strong&gt;every object&lt;/strong&gt; of the cluster, including all Secrets - store
it like a password.&lt;/p&gt;</description></item><item><title>Lab 41 - An operator: PostgreSQL</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-41-operators/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-41-operators/index.html</guid><description>&lt;h1 id="lab-41---an-operator-postgresql"&gt;Lab 41 - An operator: PostgreSQL&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; install a real operator, create a database cluster with one small
manifest, and watch the operator repair it.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-05/05-crds-operators/"&gt;CRDs and operators&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You will use &lt;a href="https://cloudnative-pg.io/" target="_blank"&gt;CloudNativePG&lt;/a&gt;, a PostgreSQL operator.
Everything you have learned so far applies: what the operator creates is
StatefulSet-like Pods, Services, Secrets and PVCs - objects you can already read.&lt;/p&gt;
&lt;h2 id="storage-first---and-it-must-be-dynamic"&gt;Storage first - and it must be dynamic&lt;/h2&gt;
&lt;p&gt;PostgreSQL is the first workload in this course that will &lt;strong&gt;not&lt;/strong&gt; run on the
static NFS PVs you wrote by hand. nginx ran as root and wrote to the export
root quite happily; the CloudNativePG image runs as the unprivileged &lt;code&gt;postgres&lt;/code&gt;
user (UID 26), and it cannot write into a root-owned NFS directory. The Pod
starts, &lt;code&gt;initdb&lt;/code&gt; fails on permissions, and the Pod crash-loops.&lt;/p&gt;</description></item><item><title>Lab 42 - End-to-end production scenario</title><link>https://training.caha.cloud/en/kubernetes-gt/labs/lab-42-production-scenario/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/labs/lab-42-production-scenario/index.html</guid><description>&lt;h1 id="lab-42---end-to-end-production-scenario"&gt;Lab 42 - End-to-end production scenario&lt;/h1&gt;
&lt;span class="badge cstyle info badge-with-title"&gt;&lt;span class="badge-title"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; Info&lt;/span&gt;&lt;span class="badge-content"&gt;discover&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; take an application to production with everything from the five
days - then survive a game day.
&lt;strong&gt;Chapter:&lt;/strong&gt; &lt;a href="https://training.caha.cloud/en/kubernetes-gt/day-05/06-production/"&gt;Production operations and best practices&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Work in pairs. Build everything in &lt;strong&gt;one file&lt;/strong&gt; &lt;code&gt;~/prod-shop.yaml&lt;/code&gt; (plus the
Velero commands) so it can go to git.&lt;/p&gt;
&lt;h2 id="the-application"&gt;The application&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/stefanprodan/podinfo" target="_blank"&gt;podinfo&lt;/a&gt;
&lt;code&gt;ghcr.io/stefanprodan/podinfo:6.7.0&lt;/code&gt; - port &lt;strong&gt;9898&lt;/strong&gt;, health &lt;code&gt;/healthz&lt;/code&gt;,
readiness &lt;code&gt;/readyz&lt;/code&gt;, metrics &lt;code&gt;/metrics&lt;/code&gt;, message from env &lt;code&gt;PODINFO_UI_MESSAGE&lt;/code&gt;.&lt;/p&gt;</description></item></channel></rss>