<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Day 3 on Eriks training corner</title><link>https://training.caha.cloud/en/kubernetes-gt/day-03/index.html</link><description>Recent content in Day 3 on Eriks training corner</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="https://training.caha.cloud/en/kubernetes-gt/day-03/index.xml" rel="self" type="application/rss+xml"/><item><title>Rolling updates and rollbacks</title><link>https://training.caha.cloud/en/kubernetes-gt/day-03/01-rollouts/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-03/01-rollouts/index.html</guid><description>&lt;h1 id="rolling-updates-and-rollbacks"&gt;Rolling updates and rollbacks&lt;/h1&gt;
&lt;h2 id="deployment-lifecycle"&gt;Deployment lifecycle&lt;/h2&gt;
&lt;div class="mermaid align-center"&gt;stateDiagram-v2
[*] --&amp;gt; Progressing: new template (image, env, ...)
Progressing --&amp;gt; Complete: all new Pods available
Progressing --&amp;gt; Failed: progressDeadlineSeconds exceeded
Complete --&amp;gt; Progressing: next change
Failed --&amp;gt; Progressing: fix or rollout undo&lt;/div&gt;&lt;p&gt;Only a change of the &lt;strong&gt;Pod template&lt;/strong&gt; starts a rollout. &lt;code&gt;replicas&lt;/code&gt; does not.&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 rollout status deploy/web &lt;span class="c1"&gt;# waits; exit code != 0 on failure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get deploy web -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.conditions[*].type}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Condition&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Progressing=True&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;rollout running or finished&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Progressing=False&lt;/code&gt; reason &lt;code&gt;ProgressDeadlineExceeded&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;stuck longer than &lt;code&gt;progressDeadlineSeconds&lt;/code&gt; (600 s)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Available=True&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;at least &lt;code&gt;replicas - maxUnavailable&lt;/code&gt; Pods ready&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="strategies"&gt;Strategies&lt;/h2&gt;
&lt;div class="mermaid align-center"&gt;graph LR
subgraph RollingUpdate
A1[v1 v1 v1] --&amp;gt; A2[v1 v1 v2] --&amp;gt; A3[v1 v2 v2] --&amp;gt; A4[v2 v2 v2]
end
subgraph Recreate
B1[v1 v1 v1] --&amp;gt; B2[- - -] --&amp;gt; B3[v2 v2 v2]
end&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minReadySeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Pod must stay ready this long to count&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;revisionHistoryLimit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# old ReplicaSets kept for rollback&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;RollingUpdate &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# or Recreate (downtime, never two versions)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;rollingUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;maxSurge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# extra Pods allowed during the rollout&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;maxUnavailable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Pods allowed to be missing&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxUnavailable: 0, maxSurge: 1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;zero downtime, needs room for one more Pod&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxUnavailable: 1, maxSurge: 0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;no extra capacity, one Pod less during rollout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Recreate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;all old Pods go first - for apps that cannot run two versions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A broken image &lt;strong&gt;stalls&lt;/strong&gt; a rolling update - the old Pods keep serving.&lt;/p&gt;</description></item><item><title>Requests, limits and quotas</title><link>https://training.caha.cloud/en/kubernetes-gt/day-03/02-resources/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-03/02-resources/index.html</guid><description>&lt;h1 id="requests-limits-and-quotas"&gt;Requests, limits and quotas&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;250m&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;, memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;128Mi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;}&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# guaranteed, used for scheduling&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;500m&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;, memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;256Mi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;}&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# hard ceiling, enforced by cgroups&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Units: &lt;code&gt;1&lt;/code&gt; CPU = 1 core = &lt;code&gt;1000m&lt;/code&gt;. Memory &lt;code&gt;Mi&lt;/code&gt;/&lt;code&gt;Gi&lt;/code&gt; (binary), &lt;code&gt;M&lt;/code&gt;/&lt;code&gt;G&lt;/code&gt; (decimal).&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Request&lt;/th&gt;
&lt;th&gt;Limit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Used by&lt;/td&gt;
&lt;td&gt;scheduler (node must have it free)&lt;/td&gt;
&lt;td&gt;kubelet / kernel at runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU over it&lt;/td&gt;
&lt;td&gt;fine, if the node has spare&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;throttled&lt;/strong&gt; - slower, not killed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory over it&lt;/td&gt;
&lt;td&gt;fine, until the node is short&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;OOMKilled&lt;/strong&gt; - container restarts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="mermaid align-center"&gt;graph LR
N[&amp;#34;Node allocatable 4 CPU&amp;#34;] --&amp;gt; A[&amp;#34;Pod A request 1&amp;#34;]
N --&amp;gt; B[&amp;#34;Pod B request 2&amp;#34;]
N --&amp;gt; F[&amp;#34;free for scheduling: 1&amp;#34;]&lt;/div&gt;&lt;p&gt;The scheduler counts &lt;strong&gt;requests&lt;/strong&gt;, not real usage.&lt;/p&gt;</description></item><item><title>Autoscaling with HPA</title><link>https://training.caha.cloud/en/kubernetes-gt/day-03/03-autoscaling/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-03/03-autoscaling/index.html</guid><description>&lt;h1 id="autoscaling-with-hpa"&gt;Autoscaling with HPA&lt;/h1&gt;
&lt;p&gt;The &lt;strong&gt;HorizontalPodAutoscaler&lt;/strong&gt; changes &lt;code&gt;replicas&lt;/code&gt; of a Deployment (or
StatefulSet) based on metrics.&lt;/p&gt;
&lt;div class="mermaid align-center"&gt;graph LR
K[kubelets] --&amp;gt; MS[metrics-server]
MS --&amp;gt;|metrics.k8s.io| HPA[HPA controller&amp;lt;br/&amp;gt;every 15 s]
HPA --&amp;gt;|scale| D[Deployment]
D --&amp;gt; P[Pods]&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;autoscaling/v2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;HorizontalPodAutoscaler&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scaleTargetRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;apps/v1, kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;Deployment, name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web }&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minReplicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;maxReplicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Resource&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;cpu&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;Utilization, averageUtilization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;}&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# % of the REQUEST&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scaleDown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stabilizationWindowSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;300&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# default: wait 5 min before shrinking&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;desired = ceil(current replicas x current usage / target)&lt;/strong&gt;
Example: 2 Pods at 150 % CPU, target 50 % -&amp;gt; &lt;code&gt;ceil(2 x 150 / 50) = 6&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Scheduling and node operations</title><link>https://training.caha.cloud/en/kubernetes-gt/day-03/04-scheduling-nodes/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-03/04-scheduling-nodes/index.html</guid><description>&lt;h1 id="scheduling-and-node-operations"&gt;Scheduling and node operations&lt;/h1&gt;
&lt;h2 id="how-the-scheduler-decides"&gt;How the scheduler decides&lt;/h2&gt;
&lt;div class="mermaid align-center"&gt;graph LR
P[new Pod] --&amp;gt; F[&amp;#34;Filter&amp;lt;br/&amp;gt;requests fit? taints tolerated?&amp;lt;br/&amp;gt;selector / affinity match?&amp;#34;]
F --&amp;gt; S[&amp;#34;Score&amp;lt;br/&amp;gt;spread, preferred affinity,&amp;lt;br/&amp;gt;least allocated&amp;#34;]
S --&amp;gt; B[bind to best node]
F --&amp;gt;|no node left| PE[Pending &amp;#43; FailedScheduling event]&lt;/div&gt;&lt;h2 id="the-tools"&gt;The tools&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;On&lt;/th&gt;
&lt;th&gt;Says&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nodeSelector&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pod&lt;/td&gt;
&lt;td&gt;run only on nodes with these labels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;node affinity &lt;code&gt;required...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pod&lt;/td&gt;
&lt;td&gt;same, with operators (&lt;code&gt;In&lt;/code&gt;, &lt;code&gt;NotIn&lt;/code&gt;, &lt;code&gt;Exists&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;node affinity &lt;code&gt;preferred...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pod&lt;/td&gt;
&lt;td&gt;try these nodes, else anywhere&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pod anti-affinity&lt;/td&gt;
&lt;td&gt;Pod&lt;/td&gt;
&lt;td&gt;not next to Pods like these&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;topologySpreadConstraints&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pod&lt;/td&gt;
&lt;td&gt;spread evenly over nodes / zones&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;taint&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Node&lt;/td&gt;
&lt;td&gt;keep Pods away&amp;hellip;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;toleration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pod&lt;/td&gt;
&lt;td&gt;&amp;hellip;unless they tolerate it&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A toleration &lt;strong&gt;permits&lt;/strong&gt;, it does not &lt;strong&gt;attract&lt;/strong&gt;. To reserve nodes for a
workload: taint the nodes + toleration + selector on the Pod.&lt;/p&gt;</description></item><item><title>Startup, readiness and liveness probes</title><link>https://training.caha.cloud/en/kubernetes-gt/day-03/05-probes/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-03/05-probes/index.html</guid><description>&lt;h1 id="startup-readiness-and-liveness-probes"&gt;Startup, readiness and liveness probes&lt;/h1&gt;
&lt;p&gt;Without probes Kubernetes knows only &amp;ldquo;the process runs&amp;rdquo;. Probes tell it whether
the application &lt;strong&gt;works&lt;/strong&gt;.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Probe&lt;/th&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;On failure&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;startupProbe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;has it finished booting?&lt;/td&gt;
&lt;td&gt;the other probes wait; after &lt;code&gt;failureThreshold&lt;/code&gt; -&amp;gt; restart&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;readinessProbe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;can it take traffic now?&lt;/td&gt;
&lt;td&gt;removed from Service endpoints - &lt;strong&gt;no restart&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;livenessProbe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;is it hung?&lt;/td&gt;
&lt;td&gt;container &lt;strong&gt;restarted&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="mermaid align-center"&gt;graph LR
S[container starts] --&amp;gt; SP{startup OK?}
SP --&amp;gt;|no, too long| R[restart]
SP --&amp;gt;|yes| L[liveness &amp;#43; readiness run]
L --&amp;gt;|readiness fails| NR[not Ready - no traffic]
L --&amp;gt;|liveness fails| R&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;app&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nginx:1.27&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;startupProbe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;httpGet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;/, port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;}&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;failureThreshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 30 x 2 s = up to 60 s to start&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;periodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;readinessProbe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;httpGet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;/ready, port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;}&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;periodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;livenessProbe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;httpGet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;/healthz, port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;}&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;periodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;failureThreshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Handlers: &lt;code&gt;httpGet&lt;/code&gt; (2xx/3xx = OK), &lt;code&gt;tcpSocket&lt;/code&gt;, &lt;code&gt;exec&lt;/code&gt; (exit 0 = OK), &lt;code&gt;grpc&lt;/code&gt;.
Tuning: &lt;code&gt;initialDelaySeconds&lt;/code&gt;, &lt;code&gt;periodSeconds&lt;/code&gt;, &lt;code&gt;timeoutSeconds&lt;/code&gt; (1 s!),
&lt;code&gt;failureThreshold&lt;/code&gt;, &lt;code&gt;successThreshold&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Logs and events</title><link>https://training.caha.cloud/en/kubernetes-gt/day-03/06-logs-events/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-03/06-logs-events/index.html</guid><description>&lt;h1 id="logs-and-events"&gt;Logs and events&lt;/h1&gt;
&lt;h2 id="container-logs"&gt;Container logs&lt;/h2&gt;
&lt;p&gt;Applications write to &lt;strong&gt;stdout/stderr&lt;/strong&gt;. The runtime stores it on the node in
&lt;code&gt;/var/log/pods/&amp;lt;ns&amp;gt;_&amp;lt;pod&amp;gt;_&amp;lt;uid&amp;gt;/&amp;lt;container&amp;gt;/&lt;/code&gt;, the kubelet rotates it
(default 10 MiB x 5 files).&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 logs web &lt;span class="c1"&gt;# one Pod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl logs web -c sidecar &lt;span class="c1"&gt;# one container&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl logs web --previous &lt;span class="c1"&gt;# the crashed instance before this one&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl logs -f deploy/web &lt;span class="c1"&gt;# follow, via the controller&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl logs -l &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web --prefix --tail&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt; &lt;span class="c1"&gt;# many Pods, name in front&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl logs web --since&lt;span class="o"&gt;=&lt;/span&gt;10m --timestamps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl logs web --all-containers
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Logs disappear with the Pod. For history you need a &lt;strong&gt;logging stack&lt;/strong&gt;:&lt;/p&gt;</description></item><item><title>Troubleshooting and kubectl debug</title><link>https://training.caha.cloud/en/kubernetes-gt/day-03/07-debugging/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://training.caha.cloud/en/kubernetes-gt/day-03/07-debugging/index.html</guid><description>&lt;h1 id="troubleshooting-and-kubectl-debug"&gt;Troubleshooting and kubectl debug&lt;/h1&gt;
&lt;h2 id="the-routine"&gt;The routine&lt;/h2&gt;
&lt;div class="mermaid align-center"&gt;graph TB
A[&amp;#34;kubectl get pod -o wide&amp;lt;br/&amp;gt;state? node?&amp;#34;] --&amp;gt; B[&amp;#34;kubectl describe pod&amp;lt;br/&amp;gt;Events at the bottom&amp;#34;]
B --&amp;gt; C{&amp;#34;container started?&amp;#34;}
C --&amp;gt;|no| D[&amp;#34;fix from the event:&amp;lt;br/&amp;gt;image, scheduling, config, volume&amp;#34;]
C --&amp;gt;|yes| E[&amp;#34;kubectl logs [--previous]&amp;#34;]
E --&amp;gt; F[&amp;#34;exec / debug&amp;lt;br/&amp;gt;look inside&amp;#34;]&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;Look at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Pending&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;events: &lt;code&gt;FailedScheduling&lt;/code&gt; - capacity, taint, affinity, PVC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ImagePullBackOff&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;events: image name, tag, registry credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CreateContainerConfigError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;events: missing ConfigMap / Secret / key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CrashLoopBackOff&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;logs --previous&lt;/code&gt;, &lt;code&gt;describe&lt;/code&gt; -&amp;gt; Last State, exit code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;OOMKilled&lt;/code&gt; (exit 137)&lt;/td&gt;
&lt;td&gt;memory limit too low, or a leak&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Running&lt;/code&gt;, not Ready&lt;/td&gt;
&lt;td&gt;readiness probe - no traffic from Services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;no response via Service&lt;/td&gt;
&lt;td&gt;EndpointSlice empty -&amp;gt; selector or readiness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Terminating&lt;/code&gt; forever&lt;/td&gt;
&lt;td&gt;finalizer, or a node that is gone&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Work &lt;strong&gt;outwards&lt;/strong&gt;: Pod ready? -&amp;gt; Service has endpoints? -&amp;gt; DNS resolves? -&amp;gt;
Gateway route accepted?&lt;/p&gt;</description></item></channel></rss>