---
@@ -62,7 +62,7 @@ Roberto Bochet <avrdudo@poul.org>
-## Minikube[^1]
+## [Minikube](https://minikube.sigs.k8s.io/docs/)
...sets up a **development** cluster directly on your machine using **containers**, or **VMs**
@@ -78,11 +78,107 @@ It will deploy a kubernetes cluster composed of 3 nodes
-
+---
+layout: two-cols-header
+---
-[^1]: https://minikube
+
-
+## Imperative vs Declarative
+
+
+
+
+
+::left::
+
+
I specify a task to be executed
+
+e.g., "Clean the room!"
+
+
You have to perform the required task,
+and once completed,
+it's no longer your responsibility
+
+
+
+
+
Ansible
+
+
+
+
Podman
+
+
+
+::right::
+
+
I declare a desired state
+
+e.g., "The room must be clean"
+
+
You have to maintain the desired state until a new state is declared
+
+
+
+
+
OpenTofu (Terraform)
+
+
+
+
Kubernetes
+
+
+
+---
+layout: center
+class: text-center
+---
+
+## Administrator requests cluster change
+
+
+
+```mermaid {scale: 0.8}
+sequenceDiagram
+ actor Admin as Administrator
+ participant API as Kubernetes API
+ participant Database@{ "type" : "database" }
+
+Admin->>+API: kubectl apply -f resource.yaml
+API->>API: Schema validation
+API->>+Database: UPDATE
+Database--)-API: Done
+API--)-Admin: Done
+```
+
+---
+layout: center
+class: text-center
+---
+
+## Operator updates cluster status according to desired one
+
+
+
+```mermaid {scale: 0.65}
+sequenceDiagram
+ participant Controller as Controller
+ participant API as Kubernetes API
+ participant Database@{ "type" : "database" }
+participant Node as Kubernetes Node
+
+Controller->>+API: Requests desired status
+API->>+Database: GET
+Database--)-API: Response
+API--)-Controller: Desired status
+Controller<<->>Node: Verifies real status
+Controller->>Node: Makes changes
+Controller->>+API: Update real cluster status
+API->>+Database: UPDATE
+Database--)-API: Done
+API--)-Controller: Done
+```
---
layout: center
From ea4a11ec711bc2ca99604eeb90531c697a1bdd6b Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Fri, 24 Oct 2025 16:11:14 +0200
Subject: [PATCH 11/67] Introduce debug code in workflow
---
.github/workflows/publish.yml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index d4957db..fd36cb1 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -2,7 +2,9 @@ name: Deploy slides to Pages
on:
push:
- branches: ["main"]
+ branches:
+ - main
+ - initial
workflow_dispatch:
From 2a90e11cff3e540f667a8b5010dedbfb8046337b Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Fri, 24 Oct 2025 18:10:15 +0200
Subject: [PATCH 12/67] Fix workflow pdf generator
---
.github/workflows/publish.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index fd36cb1..794db08 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -33,7 +33,7 @@ jobs:
id: pages
uses: actions/configure-pages@v5
- name: Build slides
- run: bun run build --out _site --base "${{ steps.pages.outputs.base_path }}"
+ run: bun run build --out _site --base "${{ steps.pages.outputs.base_path }}/"
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
From 0d12df6f9a2b109d8beed1a747a283b7f8b85c73 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Fri, 24 Oct 2025 22:50:18 +0200
Subject: [PATCH 13/67] Add intro layout
---
layouts/intro.vue | 79 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
create mode 100644 layouts/intro.vue
diff --git a/layouts/intro.vue b/layouts/intro.vue
new file mode 100644
index 0000000..c82d2c0
--- /dev/null
+++ b/layouts/intro.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
---
# What is Kubernetes?
----
+
-# Why should you use Kubernetes?
+Kubernetes is an open-source container orchestration system for automating software deployment, scaling, and management.
+
+
---
@@ -78,6 +67,48 @@ It will deploy a kubernetes cluster composed of 3 nodes
+---
+
+## Let's use the glorified podman
+
+
+
+```shell
+kubectl run -it --image=alpine iwannabeubuntu sh
+```
+
+
+Create and run a particular image in a pod.
+
+
+
+
+
+
+```shell
+kubectl get pods
+```
+
+
+Display one or many resources.
+
+
+
+
+---
+
+# Why should I use Kubernetes?
+
+
+
---
layout: two-cols-header
---
@@ -130,6 +161,38 @@ it's no longer your responsibility
+---
+
+# Kubernetes resources
+
+These are defined by `yaml` manifests
+
+```yaml {none|1|2|3-5|6|all}{lines: true}
+apiVersion:
+kind:
+metadata:
+ name:
+ # other metadata
+# resource specification
+```
+
+<<< @/snippets/pod-echo-server.yaml yaml[resource.yaml]{hide|all}{lines:true}
+
+---
+
+## Create a resource
+
+```shell
+kubectl apply -f resource.yaml
+```
+
+
+Apply a configuration to a resource by file name or stdin.
+The resource name must be specified.
+This resource will be created if it doesn't exist yet.
+JSON and YAML formats are accepted.
+
+
---
layout: center
class: text-center
@@ -139,18 +202,7 @@ class: text-center
-```mermaid {scale: 0.8}
-sequenceDiagram
- actor Admin as Administrator
- participant API as Kubernetes API
- participant Database@{ "type" : "database" }
-
-Admin->>+API: kubectl apply -f resource.yaml
-API->>API: Schema validation
-API->>+Database: UPDATE
-Database--)-API: Done
-API--)-Admin: Done
-```
+<<< @/snippets/diagrams/kubeapi.mermaid mermaid
---
layout: center
@@ -161,32 +213,22 @@ class: text-center
-```mermaid {scale: 0.65}
-sequenceDiagram
- participant Controller as Controller
- participant API as Kubernetes API
- participant Database@{ "type" : "database" }
-participant Node as Kubernetes Node
-
-Controller->>+API: Requests desired status
-API->>+Database: GET
-Database--)-API: Response
-API--)-Controller: Desired status
-Controller<<->>Node: Verifies real status
-Controller->>Node: Makes changes
-Controller->>+API: Update real cluster status
-API->>+Database: UPDATE
-Database--)-API: Done
-API--)-Controller: Done
-```
+<<< @/snippets/diagrams/controller.mermaid mermaid {scale: 0.65}
---
-layout: center
-class: text-center
+
+# Pods
+
+<<< @/snippets/pod-echo-server.yaml yaml {\*}{lines:true}
+
+---
+hideInToc: true
---
-# Learn More
+## Table of contents
-[Documentation](https://sli.dev) · [GitHub](https://github.com/slidevjs/slidev) · [Showcases](https://sli.dev/resources/showcases)
+
-
+---
+layout: outro
+---
From b7d85e83a62f81855f515d459af39279ee33d551 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Sat, 25 Oct 2025 00:00:11 +0200
Subject: [PATCH 22/67] Add coming soon layout
---
layouts/coming-soon.vue | 10 ++++++++++
1 file changed, 10 insertions(+)
create mode 100644 layouts/coming-soon.vue
diff --git a/layouts/coming-soon.vue b/layouts/coming-soon.vue
new file mode 100644
index 0000000..a99523d
--- /dev/null
+++ b/layouts/coming-soon.vue
@@ -0,0 +1,10 @@
+
+
+
+
---
@@ -53,7 +53,7 @@ Kubernetes is an open-source container orchestration system for automating softw
## [Minikube](https://minikube.sigs.k8s.io/docs/)
-...sets up a **development** cluster directly on your machine using **containers**, or **VMs**
+...creates a test cluster right on your computer using either **containers** or **VMs**
@@ -63,14 +63,32 @@ Kubernetes is an open-source container orchestration system for automating softw
minikube start --nodes 3
```
-It will deploy a kubernetes cluster composed of 3 nodes
+This deploys a development Kubernetes cluster composed of 3 nodes
+
+
+
+
+```shell
+kubectl get nodes
+```
+
+To check if the 3 nodes are correctly set up
+
+
+
+
+kubectl controls the Kubernetes cluster manager.
+
+
---
## Let's use the glorified podman
+
+
```shell
@@ -83,6 +101,8 @@ Create and run a particular image in a pod.
+
+
```shell
@@ -95,27 +115,18 @@ Display one or many resources.
----
-
-# Why should I use Kubernetes?
-
-
-## Imperative vs Declarative
+# Imperative vs Declarative
@@ -125,7 +136,7 @@ layout: two-cols-header
I specify a task to be executed
-e.g., "Clean the room!"
+e.g., "Clean the room"
You have to perform the required task,
and once completed,
@@ -198,25 +209,55 @@ layout: center
class: text-center
---
-## Administrator requests cluster change
+## You require a resource...
-
+
-<<< @/snippets/diagrams/kubeapi.mermaid mermaid
+<<< @/snippets/diagrams/kubeapi.mermaid mermaid {scale: 0.95}
---
layout: center
class: text-center
---
-## Operator updates cluster status according to desired one
+## ...a controller provisions it
-
+
<<< @/snippets/diagrams/controller.mermaid mermaid {scale: 0.65}
---
+## Operator pattern
+
+
+
+This is what makes Kubernetes really powerful
+
+You require a resource... ...a controller provisions it
+
+
A little spoiler:
+
Relying on this mechanism, you can extend the Kubernetes functionality, creating custom resource schemas and controllers.
+
+
We'll come back to it later
+
+---
+
+# So, why should I use Kubernetes?
+
+
+
+
+- It's the industry standard
+- Everyone's using it
+- Tell it what you want, not how to do it
+- You can extend it however you need (through the Operator pattern)
+
+
+
diff --git a/layouts/coming-soon.vue b/layouts/coming-soon.vue
index a99523d..981b2d7 100644
--- a/layouts/coming-soon.vue
+++ b/layouts/coming-soon.vue
@@ -1,5 +1,5 @@
diff --git a/layouts/intro.vue b/layouts/intro.vue
index c82d2c0..e41f3a1 100644
--- a/layouts/intro.vue
+++ b/layouts/intro.vue
@@ -1,38 +1,38 @@
diff --git a/layouts/outro.vue b/layouts/outro.vue
index 20566ed..2088bd1 100644
--- a/layouts/outro.vue
+++ b/layouts/outro.vue
@@ -1,38 +1,38 @@
From aef93b96270041a1d88010ec4f4b2feca0d56757 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 27 Oct 2025 01:18:33 +0100
Subject: [PATCH 27/67] Add pods and services sections
---
slides.md | 161 +++++++++++++++++-
.../manifests/pod-echo-server-labels.yaml | 14 ++
snippets/{ => manifests}/pod-echo-server.yaml | 0
snippets/manifests/service-echo-server.yaml | 12 ++
.../service-node-port-echo-server.yaml | 13 ++
5 files changed, 194 insertions(+), 6 deletions(-)
create mode 100644 snippets/manifests/pod-echo-server-labels.yaml
rename snippets/{ => manifests}/pod-echo-server.yaml (100%)
create mode 100644 snippets/manifests/service-echo-server.yaml
create mode 100644 snippets/manifests/service-node-port-echo-server.yaml
diff --git a/slides.md b/slides.md
index 8695d6c..c624adb 100644
--- a/slides.md
+++ b/slides.md
@@ -187,7 +187,7 @@ metadata:
# resource specification
```
-<<< @/snippets/pod-echo-server.yaml yaml[resource.yaml]{hide|all}{lines:true}
+<<< @/snippets/manifests/pod-echo-server.yaml yaml[resource.yaml]{hide|all}{lines:true}
---
@@ -251,22 +251,171 @@ This is what makes Kubernetes really powerful
- It's the industry standard
- Everyone's using it
- Tell it what you want, not how to do it
-- You can extend it however you need (through the Operator pattern)
+- You can extend it however you need (through the operator pattern)
---
-# Pods
+# [Pods](https://kubernetes.io/docs/concepts/workloads/pods/)
-<<< @/snippets/pod-echo-server.yaml yaml {\*}{lines:true}
+They are the smallest deployable units of computing that you can create and manage in Kubernetes
+
+<<< @/snippets/manifests/pod-echo-server.yaml yaml[pod-echo-server.yaml]{hide|all|1-2|3-4|6-11|7|8|9-11|12|all}{lines:true}
+
+
---
-layout: coming-soon
+transition: fade
+---
+
+# [Services](https://kubernetes.io/docs/concepts/services-networking/service/)
+
+They act as an abstraction layer that exposes the applications in the running pods to other services or external clients.
+They provide a stable endpoint and load balancing features for accessing pods within the cluster
+
+<<< @/snippets/manifests/service-echo-server.yaml yaml[service-echo-server.yaml]{hide|all|1-2|3-4|6|9-12|7-8|all}{lines:true}
+
+
+
+---
+transition: fade
+---
+
+## [Labels and Selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)
+
+
+
+**Labels** are key/value pairs that are attached to objects such as Pods.
+
+
+
+```yaml{hide|all}{lines: true}
+labels:
+ app: echo-server
+ tier: frontend
+ environment: production
+```
+
+
+
+**Selectors** are used to target a group of objects that match a specified set of labels
+
+
+
+```yaml{hide|all}{lines: true}
+selector:
+ matchLabels:
+ app: echo-server
+ environment: production
+```
+
+
+
+`matchLabels` targets resources that match all specified labels;
+`matchExpressions` lets you use more complex logic based on labels
+
+
+
+---
+transition: fade
+hideInToc: true
---
-# Services
+# [Services](https://kubernetes.io/docs/concepts/services-networking/service/)
+
+So, the pod we want to expose needs labels that match the service selector
+
+````md magic-move[pod-echo-server.yaml]{lines:true}
+<<< @/snippets/manifests/pod-echo-server.yaml yaml{all}
+
+<<< @/snippets/manifests/pod-echo-server-labels.yaml yaml{5-6|all}
+````
+
+
+
+---
+hideInToc: true
+---
+
+# [Services](https://kubernetes.io/docs/concepts/services-networking/service/)
+
+A `ClusterIP` service can't be reached from outside the cluster.
+To expose it externally, use a `NodePort` service.
+
+
+
+````md magic-move[service-node-port-echo-server.yaml]{lines:true}
+<<< @/snippets/manifests/service-echo-server.yaml yaml{all}
+
+<<< @/snippets/manifests/service-node-port-echo-server.yaml yaml{all|6|6|13|13|all}
+````
+
+
+
+Available service types in addition to the default [ClusterIP](https://kubernetes.io/docs/concepts/services-networking/service/#type-clusterip) are [NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport), [LoadBalancer](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer), and [ExternalName](https://kubernetes.io/docs/concepts/services-networking/service/#externalname)
+
+Note: Kubernetes only allows node ports in the range 30000–32767 by default
+
+
---
layout: coming-soon
diff --git a/snippets/manifests/pod-echo-server-labels.yaml b/snippets/manifests/pod-echo-server-labels.yaml
new file mode 100644
index 0000000..c79a06d
--- /dev/null
+++ b/snippets/manifests/pod-echo-server-labels.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: echo-server
+ labels:
+ app: echo-server
+spec:
+ containers:
+ - name: echo-server
+ image: ealen/echo-server
+ ports:
+ - name: http
+ containerPort: 80
+ restartPolicy: Always
diff --git a/snippets/pod-echo-server.yaml b/snippets/manifests/pod-echo-server.yaml
similarity index 100%
rename from snippets/pod-echo-server.yaml
rename to snippets/manifests/pod-echo-server.yaml
diff --git a/snippets/manifests/service-echo-server.yaml b/snippets/manifests/service-echo-server.yaml
new file mode 100644
index 0000000..613fd76
--- /dev/null
+++ b/snippets/manifests/service-echo-server.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: echo-server
+spec:
+ type: ClusterIP
+ selector:
+ app: echo-server
+ ports:
+ - name: http-service
+ targetPort: http
+ port: 8080
diff --git a/snippets/manifests/service-node-port-echo-server.yaml b/snippets/manifests/service-node-port-echo-server.yaml
new file mode 100644
index 0000000..9c35695
--- /dev/null
+++ b/snippets/manifests/service-node-port-echo-server.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: echo-server-node
+spec:
+ type: NodePort
+ selector:
+ app: echo-server
+ ports:
+ - name: http-service
+ targetPort: http
+ port: 8080
+ nodePort: 30808
From 6568b2e5e005456101c60601fcc4c979e210d006 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 27 Oct 2025 01:59:08 +0100
Subject: [PATCH 28/67] Improve prettier config
---
.prettierrc.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.prettierrc.yaml b/.prettierrc.yaml
index ce455a8..5e9906e 100644
--- a/.prettierrc.yaml
+++ b/.prettierrc.yaml
@@ -6,6 +6,7 @@ overrides:
- slides.md
- pages/*.md
options:
+ embeddedLanguageFormatting: off
parser: slidev
plugins:
- prettier-plugin-slidev
From 221878dbb48c0d917bbfcd5e042408aa438b7c4d Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 27 Oct 2025 02:32:40 +0100
Subject: [PATCH 29/67] Add deployments
---
slides.md | 95 +++++++++++++++++--
.../manifests/deployment-echo-server.yaml | 22 +++++
2 files changed, 110 insertions(+), 7 deletions(-)
create mode 100644 snippets/manifests/deployment-echo-server.yaml
diff --git a/slides.md b/slides.md
index c624adb..21881e7 100644
--- a/slides.md
+++ b/slides.md
@@ -256,12 +256,16 @@ This is what makes Kubernetes really powerful
+---
+layout: two-cols
---
# [Pods](https://kubernetes.io/docs/concepts/workloads/pods/)
They are the smallest deployable units of computing that you can create and manage in Kubernetes
+::right::
+
<<< @/snippets/manifests/pod-echo-server.yaml yaml[pod-echo-server.yaml]{hide|all|1-2|3-4|6-11|7|8|9-11|12|all}{lines:true}
---
+layout: two-cols
transition: fade
---
# [Services](https://kubernetes.io/docs/concepts/services-networking/service/)
-They act as an abstraction layer that exposes the applications in the running pods to other services or external clients.
+They act as an abstraction layer that exposes the applications in the running pods to other services or external clients.
They provide a stable endpoint and load balancing features for accessing pods within the cluster
+::right::
+
<<< @/snippets/manifests/service-echo-server.yaml yaml[service-echo-server.yaml]{hide|all|1-2|3-4|6|9-12|7-8|all}{lines:true}
---
+layout: two-cols
hideInToc: true
---
@@ -387,6 +398,12 @@ hideInToc: true
A `ClusterIP` service can't be reached from outside the cluster.
To expose it externally, use a `NodePort` service.
+Available service types in addition to the default [ClusterIP](https://kubernetes.io/docs/concepts/services-networking/service/#type-clusterip) are [NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport), [LoadBalancer](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer), and [ExternalName](https://kubernetes.io/docs/concepts/services-networking/service/#externalname)
+
+Note: Kubernetes only allows node ports in the range 30000-32767 by default
+
+::right::
+
````md magic-move[service-node-port-echo-server.yaml]{lines:true}
@@ -397,10 +414,6 @@ To expose it externally, use a `NodePort` service.
-Available service types in addition to the default [ClusterIP](https://kubernetes.io/docs/concepts/services-networking/service/#type-clusterip) are [NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport), [LoadBalancer](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer), and [ExternalName](https://kubernetes.io/docs/concepts/services-networking/service/#externalname)
-
-Note: Kubernetes only allows node ports in the range 30000–32767 by default
-
---
-layout: coming-soon
+layout: two-cols
+transition: fade
---
-# Deployments
+# [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
+
+These manages a set of Pods to run an application workload, usually one that doesn't maintain state.
+
+Deployments and pods are bound by the Labels/Selectors system
+
+Note: deployments do not directly create pods; they use an intermediate resource called [ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/)
+
+::right::
+
+<<< @/snippets/manifests/deployment-echo-server.yaml yaml[deployment-echo-server.yaml]{hide|all|1-2|3-4|10-22|7-9,13-14|6|all}{lines: true}
+
+
+
+---
+hideInToc: true
+---
+
+# [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
+
+Deployments are one of the Kubernetes resources that help ensure Highly Availability(HA) of services
+
+
+
+```shell
+kubectl scale --replicas 1 deployment echo-server
+```
+
+
+Set a new size for a deployment, replica set, replication controller, or stateful set.
+
+
+
+
+
---
hideInToc: true
diff --git a/snippets/manifests/deployment-echo-server.yaml b/snippets/manifests/deployment-echo-server.yaml
new file mode 100644
index 0000000..3501b6a
--- /dev/null
+++ b/snippets/manifests/deployment-echo-server.yaml
@@ -0,0 +1,22 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: echo-server
+spec:
+ replicas: 3
+ selector:
+ matchLabels:
+ app: echo-server
+ template:
+ metadata:
+ name: echo-server
+ labels:
+ app: echo-server
+ spec:
+ containers:
+ - name: echo-server
+ image: ealen/echo-server
+ ports:
+ - name: http
+ containerPort: 80
+ restartPolicy: Always
From a81580c33659a40308dde514932e7f5e425e6f8d Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Wed, 29 Oct 2025 15:41:55 +0100
Subject: [PATCH 30/67] Split slides in multiple files
---
pages/00-overview.md | 218 +++++++++++++++++++
pages/10-pods.md | 33 +++
pages/11-services.md | 139 ++++++++++++
pages/12-deployments.md | 73 +++++++
slides.md | 461 +---------------------------------------
5 files changed, 467 insertions(+), 457 deletions(-)
create mode 100644 pages/00-overview.md
create mode 100644 pages/10-pods.md
create mode 100644 pages/11-services.md
create mode 100644 pages/12-deployments.md
diff --git a/pages/00-overview.md b/pages/00-overview.md
new file mode 100644
index 0000000..59e8219
--- /dev/null
+++ b/pages/00-overview.md
@@ -0,0 +1,218 @@
+# What is Kubernetes?
+
+
+
+Kubernetes is an open-source container orchestration system for automating software deployment, scaling, and management.
+
+
+
+---
+
+# How can I **safely** test Kubernetes?
+
+
+
+## [Minikube](https://minikube.sigs.k8s.io/docs/)
+
+...creates a test cluster right on your computer using either **containers** or **VMs**
+
+
+
+
+
+```shell
+minikube start --nodes 3
+```
+
+This deploys a development Kubernetes cluster composed of 3 nodes
+
+
+
+
+
+
+
+```shell
+kubectl get nodes
+```
+
+To check if the 3 nodes are correctly set up
+
+
+
+
+kubectl controls the Kubernetes cluster manager.
+
+
+---
+
+## Let's use the glorified podman
+
+
+
+
+
+```shell
+kubectl run -it --image=alpine iwannabeubuntu sh
+```
+
+
+Create and run a particular image in a pod.
+
+
+
+
+
+
+
+
+```shell
+kubectl get pods
+```
+
+
+Display one or many resources.
+
+
+
+
+
+
You have to perform the required task,
+and once completed,
+it's no longer your responsibility
+
+
+
+
+
Ansible
+
+
+
+
Podman
+
+
+
+::right::
+
+
I declare a desired state
+
+e.g., "The room must be clean"
+
+
You have to maintain the desired state until a new state is declared
+
+
+
+
+
OpenTofu (Terraform)
+
+
+
+
Kubernetes
+
+
+
+---
+
+# Kubernetes resources
+
+These are defined by `yaml` manifests
+
+```yaml {none|1|2|3-5|6|all}{lines: true}
+apiVersion:
+kind:
+metadata:
+ name:
+ # other metadata
+# resource specification
+```
+
+<<< @/snippets/manifests/pod-echo-server.yaml yaml[resource.yaml]{hide|all}{lines:true}
+
+---
+
+## Create a resource
+
+```shell
+kubectl apply -f resource.yaml
+```
+
+
+Apply a configuration to a resource by file name or stdin.
+The resource name must be specified.
+This resource will be created if it doesn't exist yet.
+JSON and YAML formats are accepted.
+
+
+---
+layout: center
+class: text-center
+---
+
+## You require a resource...
+
+
+
+<<< @/snippets/diagrams/kubeapi.mermaid mermaid {scale: 0.95}
+
+---
+layout: center
+class: text-center
+---
+
+## ...a controller provisions it
+
+
+
+<<< @/snippets/diagrams/controller.mermaid mermaid {scale: 0.65}
+
+---
+
+## Operator pattern
+
+
+
+This is what makes Kubernetes really powerful
+
+You require a resource... ...a controller provisions it
+
+
A little spoiler:
+
Relying on this mechanism, you can extend the Kubernetes functionality, creating custom resource schemas and controllers.
+
+
We'll come back to it later
+
+---
+
+# So, why should I use Kubernetes?
+
+
+
+
+- It's the industry standard
+- Everyone's using it
+- Tell it what you want, not how to do it
+- You can extend it however you need (through the operator pattern)
+
+
+
diff --git a/pages/10-pods.md b/pages/10-pods.md
new file mode 100644
index 0000000..8d265dc
--- /dev/null
+++ b/pages/10-pods.md
@@ -0,0 +1,33 @@
+---
+layout: two-cols
+---
+
+# [Pods](https://kubernetes.io/docs/concepts/workloads/pods/)
+
+They are the smallest deployable units of computing that you can create and manage in Kubernetes
+
+::right::
+
+<<< @/snippets/manifests/pod-echo-server.yaml yaml[pod-echo-server.yaml]{hide|all|1-2|3-4|6-11|7|8|9-11|12|all}{lines:true}
+
+
diff --git a/pages/11-services.md b/pages/11-services.md
new file mode 100644
index 0000000..ac49aa9
--- /dev/null
+++ b/pages/11-services.md
@@ -0,0 +1,139 @@
+---
+layout: two-cols
+transition: fade
+---
+
+# [Services](https://kubernetes.io/docs/concepts/services-networking/service/)
+
+They act as an abstraction layer that exposes the applications in the running pods to other services or external clients.
+They provide a stable endpoint and load balancing features for accessing pods within the cluster
+
+::right::
+
+<<< @/snippets/manifests/service-echo-server.yaml yaml[service-echo-server.yaml]{hide|all|1-2|3-4|6|9-12|7-8|all}{lines:true}
+
+
+
+---
+transition: fade
+---
+
+## [Labels and Selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)
+
+
+
+**Labels** are key/value pairs that are attached to objects such as Pods.
+
+
+
+```yaml{hide|all}{lines: true}
+labels:
+ app: echo-server
+ tier: frontend
+ environment: production
+```
+
+
+
+**Selectors** are used to target a group of objects that match a specified set of labels
+
+
+
+```yaml{hide|all}{lines: true}
+selector:
+ matchLabels:
+ app: echo-server
+ environment: production
+```
+
+
+
+`matchLabels` targets resources that match all specified labels;
+`matchExpressions` lets you use more complex logic based on labels
+
+
+
+---
+layout: two-cols
+transition: fade
+hideInToc: true
+---
+
+# [Services](https://kubernetes.io/docs/concepts/services-networking/service/)
+
+So, the pod we want to expose needs labels that match the service selector
+
+::right::
+
+````md magic-move[pod-echo-server.yaml]{lines:true}
+<<< @/snippets/manifests/pod-echo-server.yaml yaml{all}
+
+<<< @/snippets/manifests/pod-echo-server-labels.yaml yaml{5-6|all}
+````
+
+
+
+---
+layout: two-cols
+hideInToc: true
+---
+
+# [Services](https://kubernetes.io/docs/concepts/services-networking/service/)
+
+A `ClusterIP` service can't be reached from outside the cluster.
+To expose it externally, use a `NodePort` service.
+
+Available service types in addition to the default [ClusterIP](https://kubernetes.io/docs/concepts/services-networking/service/#type-clusterip) are [NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport), [LoadBalancer](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer), and [ExternalName](https://kubernetes.io/docs/concepts/services-networking/service/#externalname)
+
+Note: Kubernetes only allows node ports in the range 30000-32767 by default
+
+::right::
+
+
+
+````md magic-move[service-node-port-echo-server.yaml]{lines:true}
+<<< @/snippets/manifests/service-echo-server.yaml yaml{all}
+
+<<< @/snippets/manifests/service-node-port-echo-server.yaml yaml{all|6|6|13|13|all}
+````
+
+
+
+
diff --git a/pages/12-deployments.md b/pages/12-deployments.md
new file mode 100644
index 0000000..1e33d28
--- /dev/null
+++ b/pages/12-deployments.md
@@ -0,0 +1,73 @@
+---
+layout: two-cols
+transition: fade
+---
+
+# [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
+
+These manages a set of Pods to run an application workload, usually one that doesn't maintain state.
+
+Deployments and pods are bound by the Labels/Selectors system
+
+Note: deployments do not directly create pods; they use an intermediate resource called [ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/)
+
+::right::
+
+<<< @/snippets/manifests/deployment-echo-server.yaml yaml[deployment-echo-server.yaml]{hide|all|1-2|3-4|10-22|7-9,13-14|6|all}{lines: true}
+
+
+
+---
+hideInToc: true
+---
+
+# [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
+
+Deployments are one of the Kubernetes resources that help ensure Highly Availability(HA) of services
+
+
+
+```shell
+kubectl scale --replicas 1 deployment echo-server
+```
+
+
+Set a new size for a deployment, replica set, replication controller, or stateful set.
+
+
+
+
+
diff --git a/slides.md b/slides.md
index 21881e7..ae57ff1 100644
--- a/slides.md
+++ b/slides.md
@@ -36,474 +36,21 @@ hideInToc: true
All you need to start with Kubernetes
---
-
-# What is Kubernetes?
-
-
-
-Kubernetes is an open-source container orchestration system for automating software deployment, scaling, and management.
-
-
-
+src: ./pages/00-overview.md
---
-# How can I **safely** test Kubernetes?
-
-
-
-## [Minikube](https://minikube.sigs.k8s.io/docs/)
-
-...creates a test cluster right on your computer using either **containers** or **VMs**
-
-
-
-
-
-```shell
-minikube start --nodes 3
-```
-
-This deploys a development Kubernetes cluster composed of 3 nodes
-
-
-
-
-
-
-
-```shell
-kubectl get nodes
-```
-
-To check if the 3 nodes are correctly set up
-
-
-
-
-kubectl controls the Kubernetes cluster manager.
-
-
---
-
-## Let's use the glorified podman
-
-
-
-
-
-```shell
-kubectl run -it --image=alpine iwannabeubuntu sh
-```
-
-
-Create and run a particular image in a pod.
-
-
-
-
-
-
-
-
-```shell
-kubectl get pods
-```
-
-
-Display one or many resources.
-
-
-
-
-
-
You have to perform the required task,
-and once completed,
-it's no longer your responsibility
-
-
-
-
-
Ansible
-
-
-
-
Podman
-
-
-
-::right::
-
-
I declare a desired state
-
-e.g., "The room must be clean"
-
-
You have to maintain the desired state until a new state is declared
-
-
-
-
-
OpenTofu (Terraform)
-
-
-
-
Kubernetes
-
-
-
----
-
-# Kubernetes resources
-
-These are defined by `yaml` manifests
-
-```yaml {none|1|2|3-5|6|all}{lines: true}
-apiVersion:
-kind:
-metadata:
- name:
- # other metadata
-# resource specification
-```
-
-<<< @/snippets/manifests/pod-echo-server.yaml yaml[resource.yaml]{hide|all}{lines:true}
-
----
-
-## Create a resource
-
-```shell
-kubectl apply -f resource.yaml
-```
-
-
-Apply a configuration to a resource by file name or stdin.
-The resource name must be specified.
-This resource will be created if it doesn't exist yet.
-JSON and YAML formats are accepted.
-
-
----
-layout: center
-class: text-center
----
-
-## You require a resource...
-
-
-
-<<< @/snippets/diagrams/kubeapi.mermaid mermaid {scale: 0.95}
-
----
-layout: center
-class: text-center
----
-
-## ...a controller provisions it
-
-
-
-<<< @/snippets/diagrams/controller.mermaid mermaid {scale: 0.65}
-
---
-
-## Operator pattern
-
-
-
-This is what makes Kubernetes really powerful
-
-You require a resource... ...a controller provisions it
-
-
A little spoiler:
-
Relying on this mechanism, you can extend the Kubernetes functionality, creating custom resource schemas and controllers.
-
-
We'll come back to it later
-
+src: ./pages/11-services.md
---
-# So, why should I use Kubernetes?
-
-
-
-
-- It's the industry standard
-- Everyone's using it
-- Tell it what you want, not how to do it
-- You can extend it however you need (through the operator pattern)
-
-
-
-
---
-layout: two-cols
+src: ./pages/12-deployments.md
---
-# [Pods](https://kubernetes.io/docs/concepts/workloads/pods/)
-
-They are the smallest deployable units of computing that you can create and manage in Kubernetes
-
-::right::
-
-<<< @/snippets/manifests/pod-echo-server.yaml yaml[pod-echo-server.yaml]{hide|all|1-2|3-4|6-11|7|8|9-11|12|all}{lines:true}
-
-
-
----
-layout: two-cols
-transition: fade
----
-
-# [Services](https://kubernetes.io/docs/concepts/services-networking/service/)
-
-They act as an abstraction layer that exposes the applications in the running pods to other services or external clients.
-They provide a stable endpoint and load balancing features for accessing pods within the cluster
-
-::right::
-
-<<< @/snippets/manifests/service-echo-server.yaml yaml[service-echo-server.yaml]{hide|all|1-2|3-4|6|9-12|7-8|all}{lines:true}
-
-
-
----
-transition: fade
----
-
-## [Labels and Selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)
-
-
-
-**Labels** are key/value pairs that are attached to objects such as Pods.
-
-
-
-```yaml{hide|all}{lines: true}
-labels:
- app: echo-server
- tier: frontend
- environment: production
-```
-
-
-
-**Selectors** are used to target a group of objects that match a specified set of labels
-
-
-
-```yaml{hide|all}{lines: true}
-selector:
- matchLabels:
- app: echo-server
- environment: production
-```
-
-
-
-`matchLabels` targets resources that match all specified labels;
-`matchExpressions` lets you use more complex logic based on labels
-
-
-
----
-layout: two-cols
-transition: fade
-hideInToc: true
----
-
-# [Services](https://kubernetes.io/docs/concepts/services-networking/service/)
-
-So, the pod we want to expose needs labels that match the service selector
-
-::right::
-
-````md magic-move[pod-echo-server.yaml]{lines:true}
-<<< @/snippets/manifests/pod-echo-server.yaml yaml{all}
-
-<<< @/snippets/manifests/pod-echo-server-labels.yaml yaml{5-6|all}
-````
-
-
-
----
-layout: two-cols
-hideInToc: true
----
-
-# [Services](https://kubernetes.io/docs/concepts/services-networking/service/)
-
-A `ClusterIP` service can't be reached from outside the cluster.
-To expose it externally, use a `NodePort` service.
-
-Available service types in addition to the default [ClusterIP](https://kubernetes.io/docs/concepts/services-networking/service/#type-clusterip) are [NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport), [LoadBalancer](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer), and [ExternalName](https://kubernetes.io/docs/concepts/services-networking/service/#externalname)
-
-Note: Kubernetes only allows node ports in the range 30000-32767 by default
-
-::right::
-
-
-
-````md magic-move[service-node-port-echo-server.yaml]{lines:true}
-<<< @/snippets/manifests/service-echo-server.yaml yaml{all}
-
-<<< @/snippets/manifests/service-node-port-echo-server.yaml yaml{all|6|6|13|13|all}
-````
-
-
-
-
-
----
-layout: two-cols
-transition: fade
----
-
-# [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
-
-These manages a set of Pods to run an application workload, usually one that doesn't maintain state.
-
-Deployments and pods are bound by the Labels/Selectors system
-
-Note: deployments do not directly create pods; they use an intermediate resource called [ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/)
-
-::right::
-
-<<< @/snippets/manifests/deployment-echo-server.yaml yaml[deployment-echo-server.yaml]{hide|all|1-2|3-4|10-22|7-9,13-14|6|all}{lines: true}
-
-
-
----
-hideInToc: true
----
-
-# [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
-
-Deployments are one of the Kubernetes resources that help ensure Highly Availability(HA) of services
-
-
-
-```shell
-kubectl scale --replicas 1 deployment echo-server
-```
-
-
-Set a new size for a deployment, replica set, replication controller, or stateful set.
-
-
-
-
-
-
---
hideInToc: true
---
From c5abb2e5a211cc1e2de4c8cf49181a2f839eda45 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Wed, 29 Oct 2025 17:10:27 +0100
Subject: [PATCH 31/67] Add license badge
---
components/assets/CC-BY-4.0.svg | 1 +
components/assets/CC-BY-SA-4.0.svg | 1 +
components/assets/CC0-1.0.svg | 1 +
components/license-badge.vue | 37 ++++++++++++++++++++
components/utilities/source_code.ts | 52 +++++++++++++++++++++++++++++
5 files changed, 92 insertions(+)
create mode 100644 components/assets/CC-BY-4.0.svg
create mode 100644 components/assets/CC-BY-SA-4.0.svg
create mode 100644 components/assets/CC0-1.0.svg
create mode 100644 components/license-badge.vue
create mode 100644 components/utilities/source_code.ts
diff --git a/components/assets/CC-BY-4.0.svg b/components/assets/CC-BY-4.0.svg
new file mode 100644
index 0000000..093be5a
--- /dev/null
+++ b/components/assets/CC-BY-4.0.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/components/assets/CC-BY-SA-4.0.svg b/components/assets/CC-BY-SA-4.0.svg
new file mode 100644
index 0000000..57cbde1
--- /dev/null
+++ b/components/assets/CC-BY-SA-4.0.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/components/assets/CC0-1.0.svg b/components/assets/CC0-1.0.svg
new file mode 100644
index 0000000..6212d5e
--- /dev/null
+++ b/components/assets/CC0-1.0.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/components/license-badge.vue b/components/license-badge.vue
new file mode 100644
index 0000000..0054d71
--- /dev/null
+++ b/components/license-badge.vue
@@ -0,0 +1,37 @@
+
+
+
+
---
src: ./pages/00-overview.md
From 0d796c381abe2b7c32b9a2edfe01b9553e908eb6 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Wed, 29 Oct 2025 17:21:20 +0100
Subject: [PATCH 36/67] Add missing link
---
pages/00-overview.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pages/00-overview.md b/pages/00-overview.md
index 59e8219..4a6a975 100644
--- a/pages/00-overview.md
+++ b/pages/00-overview.md
@@ -189,7 +189,7 @@ class: text-center
---
-## Operator pattern
+## [Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)
From d28418cabe762573b81a0e2cf88542106f1b1e15 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Wed, 29 Oct 2025 17:43:30 +0100
Subject: [PATCH 37/67] Minor changes
---
pages/10-pods.md | 1 +
pages/11-services.md | 2 ++
pages/12-deployments.md | 1 +
slides.md | 6 +++---
4 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/pages/10-pods.md b/pages/10-pods.md
index 8d265dc..53e817c 100644
--- a/pages/10-pods.md
+++ b/pages/10-pods.md
@@ -1,5 +1,6 @@
---
layout: two-cols
+title: Pods
---
# [Pods](https://kubernetes.io/docs/concepts/workloads/pods/)
diff --git a/pages/11-services.md b/pages/11-services.md
index ac49aa9..0c71851 100644
--- a/pages/11-services.md
+++ b/pages/11-services.md
@@ -1,6 +1,7 @@
---
layout: two-cols
transition: fade
+title: Services
---
# [Services](https://kubernetes.io/docs/concepts/services-networking/service/)
@@ -32,6 +33,7 @@ kubectl run -it --image=alpine/curl --rm --restart=Never ottenitore -- http://ec
---
transition: fade
+hideInToc: true
---
## [Labels and Selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)
diff --git a/pages/12-deployments.md b/pages/12-deployments.md
index 1e33d28..2258979 100644
--- a/pages/12-deployments.md
+++ b/pages/12-deployments.md
@@ -1,6 +1,7 @@
---
layout: two-cols
transition: fade
+title: Deployments
---
# [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
diff --git a/slides.md b/slides.md
index e55b20d..6b02668 100644
--- a/slides.md
+++ b/slides.md
@@ -22,11 +22,11 @@ export:
timeout: 30000
dark: true
withClicks: false
- withToc: false
+ withToc: true
remoteAssets: build
-colorSchema: dark
+colorSchema: auto
###############################
layout: intro
@@ -56,7 +56,7 @@ src: ./pages/12-deployments.md
hideInToc: true
---
-## Table of contents
+# Table of contents
From 03c14f213f4c39daf3fdd799341362490737f154 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Wed, 29 Oct 2025 17:53:09 +0100
Subject: [PATCH 38/67] Add source code url generator in ci
---
.github/workflows/publish.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 794db08..3b12022 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -29,6 +29,8 @@ jobs:
bun-version: latest
- name: Pull dependencies
run: bun install --frozen-lockfile
+ - name: Set source code url
+ run: sed -i "s|^sourceCode:.*|sourceCode:\ ${{github.server_url}}/${{github.repository}}|" ./slides.md
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
From 6565ce984c64fd55f3fc924d7c818877f917536b Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Thu, 30 Oct 2025 16:59:48 +0100
Subject: [PATCH 39/67] Add snippets for secrets and configmaps
---
.../configmap-echo-server-config.yaml | 7 ++++++
.../configmap-echo-server-scripts.yaml | 11 +++++++++
snippets/manifests/pod-echo-server-env.yaml | 22 +++++++++++++++++
.../manifests/pod-echo-server-secrets.yaml | 22 +++++++++++++++++
.../manifests/pod-echo-server-volumes.yaml | 24 +++++++++++++++++++
.../manifests/secret-echo-server-base64.yaml | 7 ++++++
snippets/manifests/secret-echo-server.yaml | 7 ++++++
7 files changed, 100 insertions(+)
create mode 100644 snippets/manifests/configmap-echo-server-config.yaml
create mode 100644 snippets/manifests/configmap-echo-server-scripts.yaml
create mode 100644 snippets/manifests/pod-echo-server-env.yaml
create mode 100644 snippets/manifests/pod-echo-server-secrets.yaml
create mode 100644 snippets/manifests/pod-echo-server-volumes.yaml
create mode 100644 snippets/manifests/secret-echo-server-base64.yaml
create mode 100644 snippets/manifests/secret-echo-server.yaml
diff --git a/snippets/manifests/configmap-echo-server-config.yaml b/snippets/manifests/configmap-echo-server-config.yaml
new file mode 100644
index 0000000..91725e0
--- /dev/null
+++ b/snippets/manifests/configmap-echo-server-config.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: echo-server-config
+data:
+ LOG_LEVEL: "warning"
+ DEBUG: "true"
diff --git a/snippets/manifests/configmap-echo-server-scripts.yaml b/snippets/manifests/configmap-echo-server-scripts.yaml
new file mode 100644
index 0000000..46342c8
--- /dev/null
+++ b/snippets/manifests/configmap-echo-server-scripts.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: echo-server-scripts
+data:
+ init.sh: |
+ #!/usr/bin/env sh
+ apk add --no-cache git
+ purge.sh: |
+ #!/usr/bin/env sh
+ rm -r /var/cache/*
diff --git a/snippets/manifests/pod-echo-server-env.yaml b/snippets/manifests/pod-echo-server-env.yaml
new file mode 100644
index 0000000..75a738a
--- /dev/null
+++ b/snippets/manifests/pod-echo-server-env.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: echo-server
+ labels:
+ app: echo-server
+spec:
+ containers:
+ - name: echo-server
+ image: ealen/echo-server
+ envFrom:
+ - configMapRef:
+ name: echo-server-config
+ env:
+ - name: VERBOSITY
+ valueFrom:
+ configMapKeyRef:
+ name: echo-server-config
+ key: LOG_LEVEL
+ ports:
+ - name: http
+ containerPort: 80
diff --git a/snippets/manifests/pod-echo-server-secrets.yaml b/snippets/manifests/pod-echo-server-secrets.yaml
new file mode 100644
index 0000000..fe3034b
--- /dev/null
+++ b/snippets/manifests/pod-echo-server-secrets.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: echo-server
+ labels:
+ app: echo-server
+spec:
+ containers:
+ - name: echo-server
+ image: ealen/echo-server
+ envFrom:
+ - secretRef:
+ name: echo-server-secrets
+ env:
+ - name: AUTH_KEY
+ valueFrom:
+ secretKeyRef:
+ name: echo-server-secrets
+ key: api-secret
+ ports:
+ - name: http
+ containerPort: 80
diff --git a/snippets/manifests/pod-echo-server-volumes.yaml b/snippets/manifests/pod-echo-server-volumes.yaml
new file mode 100644
index 0000000..6d8cb51
--- /dev/null
+++ b/snippets/manifests/pod-echo-server-volumes.yaml
@@ -0,0 +1,24 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: echo-server
+ labels:
+ app: echo-server
+spec:
+ containers:
+ - name: echo-server
+ image: ealen/echo-server
+ ports:
+ - name: http
+ containerPort: 80
+ volumeMounts:
+ - name: scripts
+ mountPath: /scripts
+ - name: scripts
+ mountPath: /init.d/init.sh
+ subPath: init.sh
+ volumes:
+ - name: scripts
+ configMap:
+ name: echo-server-scripts
+ defaultMode: 0544
diff --git a/snippets/manifests/secret-echo-server-base64.yaml b/snippets/manifests/secret-echo-server-base64.yaml
new file mode 100644
index 0000000..77fe439
--- /dev/null
+++ b/snippets/manifests/secret-echo-server-base64.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: echo-server-secrets
+data:
+ api-secret: c2VjcmV0Cg==
+ DB_PASSWORD: Y2hhbmdlbWUK
diff --git a/snippets/manifests/secret-echo-server.yaml b/snippets/manifests/secret-echo-server.yaml
new file mode 100644
index 0000000..04450d9
--- /dev/null
+++ b/snippets/manifests/secret-echo-server.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: echo-server-secrets
+stringData:
+ api-secret: "secret"
+ DB_PASSWORD: "changeme"
From 12ea4b71cf71dce02229c5da34c02848a4c18569 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Thu, 30 Oct 2025 17:03:38 +0100
Subject: [PATCH 40/67] Add configmaps and secrets section
---
pages/13-configmaps-secrets.md | 184 +++++++++++++++++++++++++++++++++
slides.md | 4 +
2 files changed, 188 insertions(+)
create mode 100644 pages/13-configmaps-secrets.md
diff --git a/pages/13-configmaps-secrets.md b/pages/13-configmaps-secrets.md
new file mode 100644
index 0000000..ac16c86
--- /dev/null
+++ b/pages/13-configmaps-secrets.md
@@ -0,0 +1,184 @@
+---
+layout: two-cols
+title: ConfigMaps and Secrets
+transition: fade
+---
+
+# [ConfigMaps](https://kubernetes.io/docs/concepts/configuration/configmap/) and [Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)
+
+Kubernetes provides two main resources to store and use application configurations
+
+
+
+Both contain a list of key/value elements, and they can be passed to pods as environment variables or mounted as files
+
+
+
+::right::
+
+
+
+```yaml {*}{lines:true}
+LISTEN_HOST: 0.0.0.0
+LISTEN_PORT: 8080
+
+DB_HOST: postgres-db
+DB_PORT: 5432
+DB_USER: postgres
+DB_PASSWORD: changeme
+
+LOG_LEVEL: warning
+DEBUG: "true"
+```
+
+
+
+```yaml {*}{lines:true}
+init.sh: |
+ #!/usr/bin/env sh
+ apk add --no-cache git
+purge.sh: |
+ #!/usr/bin/env sh
+ rm -r /var/cache/*
+```
+
+
+
+---
+layout: two-cols
+transition: fade
+hideInToc: true
+---
+
+# [ConfigMaps](https://kubernetes.io/docs/concepts/configuration/configmap/)
+
+They can be used to store non-confidential configurations, like scripts
+
+::right::
+
+<<<@/snippets/manifests/configmap-echo-server-config.yaml yaml[configmap-echo-server-config.yaml]{all|5-7|all}{lines:true}
+
+
+
+<<<@/snippets/manifests/configmap-echo-server-scripts.yaml yaml[configmap-echo-server-scripts.yaml]{all|5-13|all}{lines:true, at: 1}
+
+---
+layout: two-cols
+transition: fade
+hideInToc: true
+---
+
+# [ConfigMaps](https://kubernetes.io/docs/concepts/configuration/configmap/)
+
+The content of a `ConfigMap` can be passed to a pod as environment variables
+
+
+
+With the keyword `envFrom`, all the key/value pairs defined in the `ConfigMap` will be passed to the `Pod` as environment variables
+
+`env` allows for more granular configuration, enabling you to define individual environment variables and bind them to a custom name
+
+
+
+::right::
+
+<<<@/snippets/manifests/pod-echo-server-env.yaml yaml[pod-echo-server-env.yaml]{all|11-13|14-19|all}{lines:true,at:1}
+
+
+
+---
+layout: two-cols
+transition: fade
+hideInToc: true
+---
+
+# [ConfigMaps](https://kubernetes.io/docs/concepts/configuration/configmap/)
+
+The content of a `ConfigMap` can also be mounted in the `Pod` as a volume
+
+
+
+At the pod level the `ConfigMap` has to be referred as a volume definition
+
+The whole content of the `configMap` can be mounted to a directory, or alternatively, specific elements can be mounted to specific paths
+
+
+
+::right::
+
+<<<@/snippets/manifests/pod-echo-server-volumes.yaml yaml[pod-echo-server-volumes.yaml]{all|20-24|14-19|all}{lines:true,at:1}
+
+
+
+---
+layout: two-cols
+transition: fade
+hideInToc: true
+---
+
+# [Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)
+
+Putting sensitive information in `ConfigMaps` is not recommended. For this type of configuration, you should use `Secrets`
+
+
+
+The secret data can be specified in the `data` field encoded in `base64`
+
+Or alternatively, as plain text using the `stringData` field
+
+The two secrets shown on the right are equivalent
+
+
+
+::right::
+
+<<<@/snippets/manifests/secret-echo-server-base64.yaml yaml[secret-echo-server.yaml]{hide|all}{lines:true, at:1}
+
+
+
+<<<@/snippets/manifests/secret-echo-server.yaml yaml[secret-echo-server.yaml]{hide|all}{lines:true, at:2}
+
+---
+layout: two-cols
+hideInToc: true
+---
+
+# [Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)
+
+The use is similar to the `ConfigMaps`
+
+
+
+As with `ConfigMaps`, `Secrets` can be used both in the `envFrom` section...
+
+... and in the `env` one
+
+
+
+::right::
+
+<<<@/snippets/manifests/pod-echo-server-secrets.yaml yaml[pod-echo-server-secrets.yaml]{all|11-13|14-19|all}{lines:true,at:1}
+
+
diff --git a/slides.md b/slides.md
index 6b02668..c84ec7a 100644
--- a/slides.md
+++ b/slides.md
@@ -52,6 +52,10 @@ src: ./pages/11-services.md
src: ./pages/12-deployments.md
---
+---
+src: ./pages/13-configmaps-secrets.md
+---
+
---
hideInToc: true
---
From 576427b7c84876bfa2cc2960409f7a2f10a964d5 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Thu, 30 Oct 2025 17:04:14 +0100
Subject: [PATCH 41/67] Minor improvements
---
pages/10-pods.md | 2 +-
pages/11-services.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/pages/10-pods.md b/pages/10-pods.md
index 53e817c..bd12eab 100644
--- a/pages/10-pods.md
+++ b/pages/10-pods.md
@@ -29,6 +29,6 @@ They are the smallest deployable units of computing that you can create and mana
```shell
kubectl apply -f pod-echo-server.yaml
kubectl get pods -o wide
-kubectl run -it --image=alpine/curl --rm --restart=Never ottenitore -- http:// | jq
+kubectl run -it --image=alpine/curl --rm --restart=Never --quiet ottenitore -- http:// | jq
```
-->
diff --git a/pages/11-services.md b/pages/11-services.md
index 0c71851..e2c4248 100644
--- a/pages/11-services.md
+++ b/pages/11-services.md
@@ -94,7 +94,7 @@ So, the pod we want to expose needs labels that match the service selector
```shell
kubectl apply -f pod-echo-server-labels.yaml
-kubectl run -it --image=alpine/curl --rm --restart=Never ottenitore -- http://echo-server:8080 | jq
+kubectl run -it --image=alpine/curl --rm --restart=Never --quiet ottenitore -- http://echo-server:8080 | jq
```
-->
From 42b4c31036dbab288c47ac6bef3394fe95ddac2d Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Thu, 30 Oct 2025 17:06:21 +0100
Subject: [PATCH 42/67] Add gap in between two cols in layout
---
styles/index.css | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 styles/index.css
diff --git a/styles/index.css b/styles/index.css
new file mode 100644
index 0000000..3cc09e0
--- /dev/null
+++ b/styles/index.css
@@ -0,0 +1,3 @@
+.two-columns {
+ gap: 10px;
+}
From 59bd34469e884fe68404f399d644cf6f0da4eeff Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Sat, 1 Nov 2025 21:43:55 +0100
Subject: [PATCH 43/67] Add namespace snippets
---
snippets/manifests/namespace-echo-server.yaml | 4 ++++
.../manifests/pod-echo-server-namespace-secret.yaml | 12 ++++++++++++
snippets/manifests/pod-echo-server-namespace.yaml | 13 +++++++++++++
.../manifests/secret-echo-server-namespace.yaml | 7 +++++++
4 files changed, 36 insertions(+)
create mode 100644 snippets/manifests/namespace-echo-server.yaml
create mode 100644 snippets/manifests/pod-echo-server-namespace-secret.yaml
create mode 100644 snippets/manifests/pod-echo-server-namespace.yaml
create mode 100644 snippets/manifests/secret-echo-server-namespace.yaml
diff --git a/snippets/manifests/namespace-echo-server.yaml b/snippets/manifests/namespace-echo-server.yaml
new file mode 100644
index 0000000..ded7498
--- /dev/null
+++ b/snippets/manifests/namespace-echo-server.yaml
@@ -0,0 +1,4 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: echo-server
diff --git a/snippets/manifests/pod-echo-server-namespace-secret.yaml b/snippets/manifests/pod-echo-server-namespace-secret.yaml
new file mode 100644
index 0000000..c193acd
--- /dev/null
+++ b/snippets/manifests/pod-echo-server-namespace-secret.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: echo-server
+ namespace: echo-server-two
+spec:
+ containers:
+ - name: echo-server
+ image: ealen/echo-server
+ envFrom:
+ - secretRef:
+ name: echo-server-secrets
diff --git a/snippets/manifests/pod-echo-server-namespace.yaml b/snippets/manifests/pod-echo-server-namespace.yaml
new file mode 100644
index 0000000..ede43b0
--- /dev/null
+++ b/snippets/manifests/pod-echo-server-namespace.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: echo-server
+ namespace: echo-server
+spec:
+ containers:
+ - name: echo-server
+ image: ealen/echo-server
+ ports:
+ - name: http
+ containerPort: 80
+ restartPolicy: Always
diff --git a/snippets/manifests/secret-echo-server-namespace.yaml b/snippets/manifests/secret-echo-server-namespace.yaml
new file mode 100644
index 0000000..1fa3140
--- /dev/null
+++ b/snippets/manifests/secret-echo-server-namespace.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: echo-server-secrets
+ namespace: echo-server-one
+stringData:
+ api-secret: "secret"
From c5483209544279f4ed529176e1e017f1d4d895c4 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Sat, 1 Nov 2025 21:44:18 +0100
Subject: [PATCH 44/67] Add namespaces slides
---
pages/14-namespaces.md | 102 +++++++++++++++++++++++++++++++++++++++++
slides.md | 4 ++
2 files changed, 106 insertions(+)
create mode 100644 pages/14-namespaces.md
diff --git a/pages/14-namespaces.md b/pages/14-namespaces.md
new file mode 100644
index 0000000..e86c222
--- /dev/null
+++ b/pages/14-namespaces.md
@@ -0,0 +1,102 @@
+---
+layout: two-cols
+title: Namespaces
+transition: fade
+---
+
+# [Namespaces](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)
+
+They provide a logical separation between applications
+
+
+
+**Most** resources are `Namespace`-specific
+
+
+
+
+
+
+
+`kubectl` accepts the argument `-n [namespace]` to refer to the resources in a specific `Namespace`
+
+```shell
+kubectl get -n echo-server pods
+```
+
+
+
+
+
+
+
+Some of its subcommands (e.g., `get`, `describe`) also support the argument `--all-namespaces` to refer to the resources in all `Namespaces`
+
+```shell
+kubectl get --all-namespaces echo-server pods
+```
+
+
+
+::right::
+
+<<<@/snippets/manifests/namespace-echo-server.yaml yaml[namespace-echo-server.yaml]{*}{lines:true}
+
+
+
+<<<@/snippets/manifests/pod-echo-server-namespace.yaml yaml[pod-echo-server.yaml]{hide|5}{lines:true,at:1}
+
+---
+layout: two-cols
+hideInToc: true
+transition: fade
+---
+
+# [Namespaces](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)
+
+In general, resources in one `Namespace` cannot directly access resources in another `Namespace`
+
+
+
+This example results in a `Pod` with the status `CreateContainerConfigError` and the error message `Error: secret "echo-server-secrets" not found`
+
+
+
+::right::
+
+<<<@/snippets/manifests/secret-echo-server-namespace.yaml yaml[secret-echo-server.yaml]{hide|5}{lines:true,at:1}
+
+
+
+<<<@/snippets/manifests/pod-echo-server-namespace-secret.yaml yaml[pod-echo-server.yaml]{hide|5,10-12}{lines:true,at:1}
+
+---
+hideInToc: true
+---
+
+# [Namespaces](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)
+
+By default, `Namespace` networks are not isolated
+
+
+
+To access a `Service` in another `Namespace` you can use the domain in the form
+`{service_name}.{namespace_name}`
+
+This mechanism relies on the "search domains" system
+
+```shell
+kubectl -n tests exec pods/echo-server -- cat /etc/resolv.conf
+```
+
+```text
+search tests.svc.cluster.local svc.cluster.local cluster.local
+nameserver 10.96.0.10
+options ndots:5
+```
+
+`webapp -> webapp.tests.svc.cluster.local`
+
+`postgresql.databases -> postgresql.databases.svc.cluster.local`
+
+
diff --git a/slides.md b/slides.md
index c84ec7a..799b0d3 100644
--- a/slides.md
+++ b/slides.md
@@ -56,6 +56,10 @@ src: ./pages/12-deployments.md
src: ./pages/13-configmaps-secrets.md
---
+---
+src: ./pages/14-namespaces.md
+---
+
---
hideInToc: true
---
From 2ea123bfb62607d89a712e50e72f176f15536ef1 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Sun, 2 Nov 2025 20:25:53 +0100
Subject: [PATCH 45/67] Add helm snippets
---
snippets/manifests/helm/rendered.yaml | 13 +++++++++++++
snippets/manifests/helm/templates.yaml | 13 +++++++++++++
snippets/manifests/helm/values.yaml | 2 ++
3 files changed, 28 insertions(+)
create mode 100644 snippets/manifests/helm/rendered.yaml
create mode 100644 snippets/manifests/helm/templates.yaml
create mode 100644 snippets/manifests/helm/values.yaml
diff --git a/snippets/manifests/helm/rendered.yaml b/snippets/manifests/helm/rendered.yaml
new file mode 100644
index 0000000..86b5feb
--- /dev/null
+++ b/snippets/manifests/helm/rendered.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: "example-config"
+data:
+ apiBaseUrl: "http://localhost:8090/api"
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: "example-secret"
+data:
+ apiKey: "c2VjcmV0"
diff --git a/snippets/manifests/helm/templates.yaml b/snippets/manifests/helm/templates.yaml
new file mode 100644
index 0000000..3ac624a
--- /dev/null
+++ b/snippets/manifests/helm/templates.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ .Release.Name }}-config
+data:
+ apiBaseUrl: {{ .Values.apiBaseUrl | quote }}
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Release.Name }}-secret
+data:
+ apiKey: {{ .Values.apiKey | b64enc }}
diff --git a/snippets/manifests/helm/values.yaml b/snippets/manifests/helm/values.yaml
new file mode 100644
index 0000000..b2fb126
--- /dev/null
+++ b/snippets/manifests/helm/values.yaml
@@ -0,0 +1,2 @@
+apiBaseUrl: "http://localhost:8090/api"
+apiKey: "secret"
From dd6f28da47ac5e4e509b2d82bdd34ebfad34f2f4 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Sun, 2 Nov 2025 20:26:37 +0100
Subject: [PATCH 46/67] Add logos icons package
---
bun.lock | 3 +++
package.json | 1 +
2 files changed, 4 insertions(+)
diff --git a/bun.lock b/bun.lock
index 1484173..1883a16 100644
--- a/bun.lock
+++ b/bun.lock
@@ -4,6 +4,7 @@
"": {
"name": "kubernetes",
"dependencies": {
+ "@iconify-json/logos": "^1.2.10",
"@iconify-json/vscode-icons": "^1.2.33",
"@iconify/vue": "^5.0.0",
"@slidev/cli": "^52.6.0",
@@ -152,6 +153,8 @@
"@iconify-json/carbon": ["@iconify-json/carbon@1.2.14", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-33u6uGiYJ79Dfp72peT+PBMcjxzi+NyJLpqYRX8pnw0zchsUW7Us2xecgvkWgD83KYcbe6hufyWlHFU9y7fb/Q=="],
+ "@iconify-json/logos": ["@iconify-json/logos@1.2.10", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-qxaXKJ6fu8jzTMPQdHtNxlfx6tBQ0jXRbHZIYy5Ilh8Lx9US9FsAdzZWUR8MXV8PnWTKGDFO4ZZee9VwerCyMA=="],
+
"@iconify-json/ph": ["@iconify-json/ph@1.2.2", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-PgkEZNtqa8hBGjHXQa4pMwZa93hmfu8FUSjs/nv4oUU6yLsgv+gh9nu28Kqi8Fz9CCVu4hj1MZs9/60J57IzFw=="],
"@iconify-json/svg-spinners": ["@iconify-json/svg-spinners@1.2.4", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-ayn0pogFPwJA1WFZpDnoq9/hjDxN+keeCMyThaX4d3gSJ3y0mdKUxIA/b1YXWGtY9wVtZmxwcvOIeEieG4+JNg=="],
diff --git a/package.json b/package.json
index 1469c67..58edf25 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
"lint:fix": "prettier . --write"
},
"dependencies": {
+ "@iconify-json/logos": "^1.2.10",
"@iconify-json/vscode-icons": "^1.2.33",
"@iconify/vue": "^5.0.0",
"@slidev/cli": "^52.6.0",
From a55bdcc1bfb782ea2f7f63c88dececc7dc2f92c8 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Sun, 2 Nov 2025 20:26:49 +0100
Subject: [PATCH 47/67] Add some ignore in prettier
---
.prettierignore | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.prettierignore b/.prettierignore
index a67cee8..137d2d9 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,2 +1,4 @@
.prettierignore
+*.lock
*.svg
+**/helm/templates.yaml
From dae40a9d0f85e22fb4e07faa706eebc98f20595b Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Sun, 2 Nov 2025 20:27:02 +0100
Subject: [PATCH 48/67] Add gap between two cols with header layout
---
styles/index.css | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/styles/index.css b/styles/index.css
index 3cc09e0..b91c357 100644
--- a/styles/index.css
+++ b/styles/index.css
@@ -1,3 +1,7 @@
.two-columns {
gap: 10px;
}
+
+.two-cols-header {
+ gap: 10px;
+}
From 95fbd9b0f210bb7f6a629c465e3208c86d04503b Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Sun, 2 Nov 2025 20:27:26 +0100
Subject: [PATCH 49/67] Add helm slides
---
pages/20-helm.md | 149 +++++++++++++++++++++++++++++++++++++++++++++++
slides.md | 4 ++
2 files changed, 153 insertions(+)
create mode 100644 pages/20-helm.md
diff --git a/pages/20-helm.md b/pages/20-helm.md
new file mode 100644
index 0000000..1528cea
--- /dev/null
+++ b/pages/20-helm.md
@@ -0,0 +1,149 @@
+---
+layout: two-cols
+transition: fade
+title: Helm
+---
+
+# [Helm](https://helm.sh/docs)
+
+A [CNCF graduated project](https://www.cncf.io/projects/), it is the main package manager for Kubernetes
+
+
+
+Helm charts (packages) are released as `tgz` archives, containing all the manifests needed to deploy a whole service
+
+To customize the installation of the service, a helm chart exposes a list of overridable variables: the `values.yaml`
+
+
+
+::right::
+
+
+
+
+
+---
+layout: two-cols-header
+transition: fade
+hideInToc: true
+---
+
+# [Helm](https://helm.sh/docs)
+
+It uses a templating system based on [Go template language](https://pkg.go.dev/text/template)
+
+::left::
+
+<<<@/snippets/manifests/helm/templates.yaml yaml[templates.yaml]{hide|all}{lines:true}
+<<<@/snippets/manifests/helm/values.yaml yaml[values.yaml]{hide|all}{lines:true}
+
+::right::
+
+
+
+With the release name "example" these produce
+
+
+
+<<<@/snippets/manifests/helm/rendered.yaml yaml{hide|all}{lines:true,at:3}
+
+---
+transition: fade
+hideInToc: true
+---
+
+# [Helm](https://helm.sh/docs)
+
+It has not an official repository, instead it allows developers to create one's own
+
+
+
+Anyway, an indexer for Helm charts is available: [Artifact Hub](https://artifacthub.io/), a [CNCF incubating project](https://www.cncf.io/projects/)
+
+You can find charts directly on the web search or from cli using the command `helm search hub [keywords]`
+
+For each result, you can find: the repository, the chart name, the version history and the default `values.yaml`
+
+
+
+---
+transition: fade
+hideInToc: true
+---
+
+# [Helm](https://helm.sh/docs)
+The procedure to install a Helm chart is straightforward
+
+1. Fetch the helm chart repository
+
+
+
+```shell
+helm repo add ealenn https://ealenn.github.io/charts
+```
+
+
+Adds a chart repository to your local Helm configuration
+
+
+
+
+
+
+
+
+```shell
+helm repo update
+```
+
+
+Gets the latest information about charts from the respective chart repositories
+
+
+
+
+---
+transition: fade
+hideInToc: true
+---
+
+# [Helm](https://helm.sh/docs)
+The procedure to install a Helm chart is straightforward
+
+1. Fetch the helm chart repository
+2. Define the custom `values.yaml`
+
+
+
+```shell
+helm show values ealenn/echo-server
+```
+
+
+Inspects a chart (directory, file, or URL) and displays the contents of the values.yaml file
+
+
+
+
+---
+hideInToc: true
+---
+
+# [Helm](https://helm.sh/docs)
+The procedure to install a Helm chart is straightforward
+
+1. Fetch the helm chart repository
+2. Define the custom `values.yaml`
+3. Install the chart
+
+
+
+```shell
+helm install -n echo-server --create-namespace --values ./values.yaml ealenn/echo-server
+```
+
+
+Installs a chart archive
+
+
+
diff --git a/slides.md b/slides.md
index 799b0d3..057a956 100644
--- a/slides.md
+++ b/slides.md
@@ -60,6 +60,10 @@ src: ./pages/13-configmaps-secrets.md
src: ./pages/14-namespaces.md
---
+---
+src: ./pages/20-helm.md
+---
+
---
hideInToc: true
---
From 61c29f023504bf3904d2fd4cd02a977d45ff6460 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 3 Nov 2025 03:34:04 +0100
Subject: [PATCH 50/67] Add ingresses snippets
---
.../ingresses/ingress-echo-server-class.yaml | 17 +++++++++++++++++
.../ingresses/ingress-echo-server.yaml | 16 ++++++++++++++++
.../ingresses/ingress-nginx-class.yaml | 6 ++++++
.../ingresses/ingress-nginx-values.yaml | 9 +++++++++
4 files changed, 48 insertions(+)
create mode 100644 snippets/manifests/ingresses/ingress-echo-server-class.yaml
create mode 100644 snippets/manifests/ingresses/ingress-echo-server.yaml
create mode 100644 snippets/manifests/ingresses/ingress-nginx-class.yaml
create mode 100644 snippets/manifests/ingresses/ingress-nginx-values.yaml
diff --git a/snippets/manifests/ingresses/ingress-echo-server-class.yaml b/snippets/manifests/ingresses/ingress-echo-server-class.yaml
new file mode 100644
index 0000000..f9412d3
--- /dev/null
+++ b/snippets/manifests/ingresses/ingress-echo-server-class.yaml
@@ -0,0 +1,17 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: echo-server
+spec:
+ ingressClassName: nginx
+ rules:
+ - host: echo.example.org
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: echo-server
+ port:
+ name: http
diff --git a/snippets/manifests/ingresses/ingress-echo-server.yaml b/snippets/manifests/ingresses/ingress-echo-server.yaml
new file mode 100644
index 0000000..d2c7153
--- /dev/null
+++ b/snippets/manifests/ingresses/ingress-echo-server.yaml
@@ -0,0 +1,16 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: echo-server
+spec:
+ rules:
+ - host: echo.example.org
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: echo-server
+ port:
+ name: http
diff --git a/snippets/manifests/ingresses/ingress-nginx-class.yaml b/snippets/manifests/ingresses/ingress-nginx-class.yaml
new file mode 100644
index 0000000..2a68f08
--- /dev/null
+++ b/snippets/manifests/ingresses/ingress-nginx-class.yaml
@@ -0,0 +1,6 @@
+apiVersion: networking.k8s.io/v1
+kind: IngressClass
+metadata:
+ name: nginx
+spec:
+ controller: k8s.io/ingress-nginx
diff --git a/snippets/manifests/ingresses/ingress-nginx-values.yaml b/snippets/manifests/ingresses/ingress-nginx-values.yaml
new file mode 100644
index 0000000..a3af2b7
--- /dev/null
+++ b/snippets/manifests/ingresses/ingress-nginx-values.yaml
@@ -0,0 +1,9 @@
+controller:
+ ingressClassResource:
+ default: true
+
+ service:
+ type: NodePort
+ nodePorts:
+ http: 30080
+ https: 30443
From 3d46fe9936116f46025ef33d19a841155042a91d Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 3 Nov 2025 03:34:31 +0100
Subject: [PATCH 51/67] Add ingresses
---
pages/21-ingresses.md | 123 ++++++++++++++++++++++++++++++++++++++++++
slides.md | 4 ++
2 files changed, 127 insertions(+)
create mode 100644 pages/21-ingresses.md
diff --git a/pages/21-ingresses.md b/pages/21-ingresses.md
new file mode 100644
index 0000000..8081130
--- /dev/null
+++ b/pages/21-ingresses.md
@@ -0,0 +1,123 @@
+---
+layout: two-cols
+transition: fade
+title: Ingresses
+---
+
+# [Ingresses](https://kubernetes.io/docs/concepts/services-networking/ingress/)
+
+They allow the exposure of multiple HTTP services through the same endpoint, acting as a reverse proxy
+
+
+
+`Ingresses` also rely on the operator pattern, but no default controller is provided out of the box
+
+N.B. `Ingresses` are now in the EoL, superseded by [Gateway API](https://kubernetes.io/docs/concepts/services-networking/gateway/). However, they are still widely used
+
+
+
+::right::
+
+<<<@/snippets/manifests/ingresses/ingress-echo-server.yaml yaml[ingress-echo-server.yaml]{hide|all|1-2|7|10-11|12-16|all}{lines:true,at:1}
+
+
+
+---
+layout: two-cols-header
+transition: fade
+hideInToc: true
+---
+
+# [Ingresses](https://kubernetes.io/docs/concepts/services-networking/ingress/)
+
+To use `Ingresses`, a specific controller has to provision it
+
+::left::
+
+
+
+There are various controllers based on applications like `nginx`, `traefik`, etc.
+
+One of the most popular is the [Ingress-Nginx Controller](https://kubernetes.github.io/ingress-nginx/)
+
+It can be easily installed exploiting the official [helm chart](https://kubernetes.github.io/ingress-nginx/deploy/#quick-start)
+
+
+
+::right::
+
+```shell{hide|all}
+helm repo add ingress-nginx \
+ https://kubernetes.github.io/ingress-nginx
+```
+
+
+
+<<<@/snippets/manifests/ingresses/ingress-nginx-values.yaml yaml[values.yaml]{hide|all}{lines:true}
+
+
+
+```shell{hide|all}
+helm install -n ingress-nginx --create-namespace \
+ --values ./values.yaml \
+ ingress-nginx ingress-nginx/ingress-nginx
+```
+
+---
+layout: two-cols
+transition: fade
+hideInToc: true
+---
+
+# [Ingresses](https://kubernetes.io/docs/concepts/services-networking/ingress/)
+
+Ingress can be now provisioned by the nginx controller
+
+
+
+When the controller receives an HTTP request matching the `Host` header and the path prefix, it will be redirected to the backend service
+
+
+
+::right::
+
+````md magic-move[ingress-echo-server.yaml]{lines:true}
+<<<@/snippets/manifests/ingresses/ingress-echo-server.yaml yaml
+````
+
+
+
+---
+layout: two-cols
+transition: fade
+hideInToc: true
+---
+
+# [IngressClasses](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class)
+
+They allow specifying which controller should provision an `Ingress`
+
+<<< @/snippets/manifests/ingresses/ingress-nginx-class.yaml yaml{hide|all}{lines:true}
+
+::right::
+
+````md magic-move[ingress-echo-server.yaml]{lines:true}
+<<< @/snippets/manifests/ingresses/ingress-echo-server.yaml yaml{all}
+
+<<< @/snippets/manifests/ingresses/ingress-echo-server-class.yaml yaml{6}
+````
diff --git a/slides.md b/slides.md
index 057a956..4050cdd 100644
--- a/slides.md
+++ b/slides.md
@@ -64,6 +64,10 @@ src: ./pages/14-namespaces.md
src: ./pages/20-helm.md
---
+---
+src: ./pages/21-ingresses.md
+---
+
---
hideInToc: true
---
From dcb0a0cc46a296600c56c9766d0cd521daadff23 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 3 Nov 2025 03:34:50 +0100
Subject: [PATCH 52/67] Add anchor in opertator slide
---
pages/00-overview.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/pages/00-overview.md b/pages/00-overview.md
index 4a6a975..0317412 100644
--- a/pages/00-overview.md
+++ b/pages/00-overview.md
@@ -187,6 +187,9 @@ class: text-center
<<< @/snippets/diagrams/controller.mermaid mermaid {scale: 0.65}
+---
+title: Operator pattern
+routeAlias: operator-pattern
---
## [Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)
From 1d43c011d84f0394710dc9faa22911bf4c769167 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 3 Nov 2025 03:40:48 +0100
Subject: [PATCH 53/67] Refactor namespaces snippets
---
pages/14-namespaces.md | 8 ++++----
.../manifests/{ => namespaces}/namespace-echo-server.yaml | 0
.../pod-echo-server-secret.yaml} | 0
.../pod-echo-server.yaml} | 0
.../secret-echo-server.yaml} | 0
5 files changed, 4 insertions(+), 4 deletions(-)
rename snippets/manifests/{ => namespaces}/namespace-echo-server.yaml (100%)
rename snippets/manifests/{pod-echo-server-namespace-secret.yaml => namespaces/pod-echo-server-secret.yaml} (100%)
rename snippets/manifests/{pod-echo-server-namespace.yaml => namespaces/pod-echo-server.yaml} (100%)
rename snippets/manifests/{secret-echo-server-namespace.yaml => namespaces/secret-echo-server.yaml} (100%)
diff --git a/pages/14-namespaces.md b/pages/14-namespaces.md
index e86c222..e2b3e41 100644
--- a/pages/14-namespaces.md
+++ b/pages/14-namespaces.md
@@ -40,11 +40,11 @@ kubectl get --all-namespaces echo-server pods
::right::
-<<<@/snippets/manifests/namespace-echo-server.yaml yaml[namespace-echo-server.yaml]{*}{lines:true}
+<<<@/snippets/manifests/namespaces/namespace-echo-server.yaml yaml[namespace-echo-server.yaml]{*}{lines:true}
-<<<@/snippets/manifests/pod-echo-server-namespace.yaml yaml[pod-echo-server.yaml]{hide|5}{lines:true,at:1}
+<<<@/snippets/manifests/namespaces/pod-echo-server.yaml yaml[pod-echo-server.yaml]{hide|5}{lines:true,at:1}
---
layout: two-cols
@@ -64,11 +64,11 @@ This example results in a `Pod` with the status `CreateContainerConfigError` and
::right::
-<<<@/snippets/manifests/secret-echo-server-namespace.yaml yaml[secret-echo-server.yaml]{hide|5}{lines:true,at:1}
+<<<@/snippets/manifests/namespaces/secret-echo-server.yaml yaml[secret-echo-server.yaml]{hide|5}{lines:true,at:1}
-<<<@/snippets/manifests/pod-echo-server-namespace-secret.yaml yaml[pod-echo-server.yaml]{hide|5,10-12}{lines:true,at:1}
+<<<@/snippets/manifests/namespaces/pod-echo-server-secret.yaml yaml[pod-echo-server.yaml]{hide|5,10-12}{lines:true,at:1}
---
hideInToc: true
diff --git a/snippets/manifests/namespace-echo-server.yaml b/snippets/manifests/namespaces/namespace-echo-server.yaml
similarity index 100%
rename from snippets/manifests/namespace-echo-server.yaml
rename to snippets/manifests/namespaces/namespace-echo-server.yaml
diff --git a/snippets/manifests/pod-echo-server-namespace-secret.yaml b/snippets/manifests/namespaces/pod-echo-server-secret.yaml
similarity index 100%
rename from snippets/manifests/pod-echo-server-namespace-secret.yaml
rename to snippets/manifests/namespaces/pod-echo-server-secret.yaml
diff --git a/snippets/manifests/pod-echo-server-namespace.yaml b/snippets/manifests/namespaces/pod-echo-server.yaml
similarity index 100%
rename from snippets/manifests/pod-echo-server-namespace.yaml
rename to snippets/manifests/namespaces/pod-echo-server.yaml
diff --git a/snippets/manifests/secret-echo-server-namespace.yaml b/snippets/manifests/namespaces/secret-echo-server.yaml
similarity index 100%
rename from snippets/manifests/secret-echo-server-namespace.yaml
rename to snippets/manifests/namespaces/secret-echo-server.yaml
From a699d1b3c221244f2beafd675d5a1a0121b6db5b Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 3 Nov 2025 03:47:39 +0100
Subject: [PATCH 54/67] Refactor configmaps and secrets snippets
---
pages/13-configmaps-secrets.md | 14 +++++++-------
.../configmap-echo-server-config.yaml | 0
.../configmap-echo-server-scripts.yaml | 0
.../pod-echo-server-env.yaml | 0
.../pod-echo-server-secrets.yaml | 0
.../pod-echo-server-volumes.yaml | 0
.../secret-echo-server-base64.yaml | 4 ++--
.../secret-echo-server.yaml | 0
8 files changed, 9 insertions(+), 9 deletions(-)
rename snippets/manifests/{ => configmaps-secrets}/configmap-echo-server-config.yaml (100%)
rename snippets/manifests/{ => configmaps-secrets}/configmap-echo-server-scripts.yaml (100%)
rename snippets/manifests/{ => configmaps-secrets}/pod-echo-server-env.yaml (100%)
rename snippets/manifests/{ => configmaps-secrets}/pod-echo-server-secrets.yaml (100%)
rename snippets/manifests/{ => configmaps-secrets}/pod-echo-server-volumes.yaml (100%)
rename snippets/manifests/{ => configmaps-secrets}/secret-echo-server-base64.yaml (56%)
rename snippets/manifests/{ => configmaps-secrets}/secret-echo-server.yaml (100%)
diff --git a/pages/13-configmaps-secrets.md b/pages/13-configmaps-secrets.md
index ac16c86..1fbaf25 100644
--- a/pages/13-configmaps-secrets.md
+++ b/pages/13-configmaps-secrets.md
@@ -56,11 +56,11 @@ They can be used to store non-confidential configurations, like scripts
::right::
-<<<@/snippets/manifests/configmap-echo-server-config.yaml yaml[configmap-echo-server-config.yaml]{all|5-7|all}{lines:true}
+<<<@/snippets/manifests/configmaps-secrets/configmap-echo-server-config.yaml yaml[configmap-echo-server-config.yaml]{all|5-7|all}{lines:true}
-<<<@/snippets/manifests/configmap-echo-server-scripts.yaml yaml[configmap-echo-server-scripts.yaml]{all|5-13|all}{lines:true, at: 1}
+<<<@/snippets/manifests/configmaps-secrets/configmap-echo-server-scripts.yaml yaml[configmap-echo-server-scripts.yaml]{all|5-13|all}{lines:true, at: 1}
---
layout: two-cols
@@ -82,7 +82,7 @@ With the keyword `envFrom`, all the key/value pairs defined in the `ConfigMap` w
::right::
-<<<@/snippets/manifests/pod-echo-server-env.yaml yaml[pod-echo-server-env.yaml]{all|11-13|14-19|all}{lines:true,at:1}
+<<<@/snippets/manifests/configmaps-secrets/pod-echo-server-env.yaml yaml[pod-echo-server-env.yaml]{all|11-13|14-19|all}{lines:true,at:1}
@@ -116,10 +116,10 @@ To expose it externally, use a `NodePort` service.
-````md magic-move[service-node-port-echo-server.yaml]{lines:true}
-<<< @/snippets/manifests/service-echo-server.yaml yaml{all}
+````md magic-move[service-echo-server-node-port.yaml]{lines:true}
+<<< @/snippets/manifests/services/service-echo-server.yaml yaml{all}
-<<< @/snippets/manifests/service-node-port-echo-server.yaml yaml{all|6|6|13|13|all}
+<<< @/snippets/manifests/services/service-echo-server-node-port.yaml yaml{all|6|6|13|13|all}
````
@@ -134,7 +134,7 @@ To expose it externally, use a `NodePort` service.
[click:2] `nodePort`
```shell
-kubectl apply -f service-node-port-echo-server.yaml
+kubectl apply -f ./snippets/manifests/services/service-echo-server-node-port.yaml
kubectl get nodes -o wide
curl http://:30808 | jq
```
diff --git a/pages/12-deployments.md b/pages/12-deployments.md
index 2258979..561c922 100644
--- a/pages/12-deployments.md
+++ b/pages/12-deployments.md
@@ -6,7 +6,7 @@ title: Deployments
# [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
-These manages a set of Pods to run an application workload, usually one that doesn't maintain state.
+These manage a set of Pods to run an application workload, usually one that doesn't maintain state.
Deployments and pods are bound by the Labels/Selectors system
@@ -14,7 +14,7 @@ These manages a set of Pods to run an application workload, usually one that doe
::right::
-<<< @/snippets/manifests/deployment-echo-server.yaml yaml[deployment-echo-server.yaml]{hide|all|1-2|3-4|10-22|7-9,13-14|6|all}{lines: true}
+<<< @/snippets/manifests/deployments/deployment-echo-server.yaml yaml[deployment-echo-server.yaml]{hide|all|1-2|3-4|10-22|7-9,13-14|6|all}{lines: true}
+
+---
+layout: two-cols
+hideInToc: true
+---
+
+# [Custom Resource Definitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions)
+Once the `CRDs` are defined, the relative resources are managed as the native ones
+
+::right::
+
+<<<@/snippets/manifests/custom-resource-definitions/distro-fedora.yaml yaml[distro-fedora.yaml]{all|1-2|5-8|all}{lines:true}
+
+<<<@/snippets/manifests/custom-resource-definitions/distro-ubuntu.yaml yaml[distro-ubuntu.yaml]{all|1-2|5-8|all}{lines:true,at:1}
+
+
diff --git a/slides.md b/slides.md
index 4050cdd..e9d24b2 100644
--- a/slides.md
+++ b/slides.md
@@ -68,13 +68,17 @@ src: ./pages/20-helm.md
src: ./pages/21-ingresses.md
---
+---
+src: ./pages/22-custom-resource-definitions.md
+---
+
---
hideInToc: true
---
# Table of contents
-
+
---
layout: outro
From a63b140823a0e1cc2a2ebf9eaa690e0ea61a5d12 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Fri, 7 Nov 2025 16:25:36 +0100
Subject: [PATCH 61/67] Add LICENSE file
---
.prettierignore | 1 +
LICENSE | 427 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 428 insertions(+)
create mode 100644 LICENSE
diff --git a/.prettierignore b/.prettierignore
index 137d2d9..ced3696 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -2,3 +2,4 @@
*.lock
*.svg
**/helm/templates.yaml
+LICENSE
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7d4f96c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,427 @@
+Attribution-ShareAlike 4.0 International
+
+=======================================================================
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and
+does not provide legal services or legal advice. Distribution of
+Creative Commons public licenses does not create a lawyer-client or
+other relationship. Creative Commons makes its licenses and related
+information available on an "as-is" basis. Creative Commons gives no
+warranties regarding its licenses, any material licensed under their
+terms and conditions, or any related information. Creative Commons
+disclaims all liability for damages resulting from their use to the
+fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share
+original works of authorship and other material subject to copyright
+and certain other rights specified in the public license below. The
+following considerations are for informational purposes only, are not
+exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+
+=======================================================================
+
+Creative Commons Attribution-ShareAlike 4.0 International Public
+License
+
+By exercising the Licensed Rights (defined below), You accept and agree
+to be bound by the terms and conditions of this Creative Commons
+Attribution-ShareAlike 4.0 International Public License ("Public
+License"). To the extent this Public License may be interpreted as a
+contract, You are granted the Licensed Rights in consideration of Your
+acceptance of these terms and conditions, and the Licensor grants You
+such rights in consideration of benefits the Licensor receives from
+making the Licensed Material available under these terms and
+conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+
+ c. BY-SA Compatible License means a license listed at
+ creativecommons.org/compatiblelicenses, approved by Creative
+ Commons as essentially the equivalent of this Public License.
+
+ d. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+
+ e. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+
+ f. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+
+ g. License Elements means the license attributes listed in the name
+ of a Creative Commons Public License. The License Elements of this
+ Public License are Attribution and ShareAlike.
+
+ h. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+
+ i. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+
+ j. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+
+ k. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+
+ l. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+
+ m. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+
+Section 2 -- Scope.
+
+ a. License grant.
+
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+
+ a. reproduce and Share the Licensed Material, in whole or
+ in part; and
+
+ b. produce, reproduce, and Share Adapted Material.
+
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+
+ 5. Downstream recipients.
+
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+
+ b. Additional offer from the Licensor -- Adapted Material.
+ Every recipient of Adapted Material from You
+ automatically receives an offer from the Licensor to
+ exercise the Licensed Rights in the Adapted Material
+ under the conditions of the Adapter's License You apply.
+
+ c. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+
+ b. Other rights.
+
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties.
+
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+ a. Attribution.
+
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+
+ ii. a copyright notice;
+
+ iii. a notice that refers to this Public License;
+
+ iv. a notice that refers to the disclaimer of
+ warranties;
+
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+
+ b. ShareAlike.
+
+ In addition to the conditions in Section 3(a), if You Share
+ Adapted Material You produce, the following conditions also apply.
+
+ 1. The Adapter's License You apply must be a Creative Commons
+ license with the same License Elements, this version or
+ later, or a BY-SA Compatible License.
+
+ 2. You must include the text of, or the URI or hyperlink to, the
+ Adapter's License You apply. You may satisfy this condition
+ in any reasonable manner based on the medium, means, and
+ context in which You Share Adapted Material.
+
+ 3. You may not offer or impose any additional or different terms
+ or conditions on, or apply any Effective Technological
+ Measures to, Adapted Material that restrict exercise of the
+ rights granted under the Adapter's License You apply.
+
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that
+apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database;
+
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material,
+ including for purposes of Section 3(b); and
+
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not
+replace Your obligations under this Public License where the Licensed
+Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+
+ 2. upon express reinstatement by the Licensor.
+
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+
+
+=======================================================================
+
+Creative Commons is not a party to its public
+licenses. Notwithstanding, Creative Commons may elect to apply one of
+its public licenses to material it publishes and in those instances
+will be considered the “Licensor.” The text of the Creative Commons
+public licenses is dedicated to the public domain under the CC0 Public
+Domain Dedication. Except for the limited purpose of indicating that
+material is shared under a Creative Commons public license or as
+otherwise permitted by the Creative Commons policies published at
+creativecommons.org/policies, Creative Commons does not authorize the
+use of the trademark "Creative Commons" or any other trademark or logo
+of Creative Commons without its prior written consent including,
+without limitation, in connection with any unauthorized modifications
+to any of its public licenses or any other arrangements,
+understandings, or agreements concerning use of licensed material. For
+the avoidance of doubt, this paragraph does not form part of the
+public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
From 3faebb05f058bbb4f8ce2aa8cf306c55c870c1c2 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 10 Nov 2025 02:58:36 +0100
Subject: [PATCH 62/67] Add annotations slides
---
pages/23-annotations.md | 20 +++++++++++++++++++
slides.md | 4 ++++
.../configmap-echo-server-annotated.yaml | 17 ++++++++++++++++
3 files changed, 41 insertions(+)
create mode 100644 pages/23-annotations.md
create mode 100644 snippets/manifests/annotations/configmap-echo-server-annotated.yaml
diff --git a/pages/23-annotations.md b/pages/23-annotations.md
new file mode 100644
index 0000000..8c312c9
--- /dev/null
+++ b/pages/23-annotations.md
@@ -0,0 +1,20 @@
+---
+layout: two-cols
+title: Annotations
+---
+
+# [Annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)
+
+They introduce the flexibility of `CRDs` to the built-in `RDs`
+
+
+
+`Annotations` are a set of key/value pairs that can be defined for any resource in the `metadata` field
+
+They can be read and processed by tools and controllers, enabling them to modify their behavior based on these values
+
+
+
+::right::
+
+<<<@/snippets/manifests/annotations/configmap-echo-server-annotated.yaml yaml[configmap-echo-server-annotated.yaml]{5-7}{lines:true}
diff --git a/slides.md b/slides.md
index e9d24b2..fb27685 100644
--- a/slides.md
+++ b/slides.md
@@ -72,6 +72,10 @@ src: ./pages/21-ingresses.md
src: ./pages/22-custom-resource-definitions.md
---
+---
+src: ./pages/23-annotations.md
+---
+
---
hideInToc: true
---
diff --git a/snippets/manifests/annotations/configmap-echo-server-annotated.yaml b/snippets/manifests/annotations/configmap-echo-server-annotated.yaml
new file mode 100644
index 0000000..638b707
--- /dev/null
+++ b/snippets/manifests/annotations/configmap-echo-server-annotated.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: echo-server
+ annotations:
+ meta.helm.sh/release-name: echo-server
+ meta.helm.sh/release-namespace: echo-server
+data:
+ ENABLE__COOKIES: "true"
+ ENABLE__ENVIRONMENT: "true"
+ ENABLE__FILE: "true"
+ ENABLE__HEADER: "true"
+ ENABLE__HOST: "true"
+ ENABLE__HTTP: "true"
+ ENABLE__REQUEST: "true"
+ LOGS__IGNORE__PING: "false"
+ PORT: "80"
From c5bbc1b7fde003c0bc03e62eecbbd9c9134b8804 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 10 Nov 2025 03:00:21 +0100
Subject: [PATCH 63/67] Minor change in ingress
---
pages/21-ingresses.md | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/pages/21-ingresses.md b/pages/21-ingresses.md
index 289b243..979b68c 100644
--- a/pages/21-ingresses.md
+++ b/pages/21-ingresses.md
@@ -35,10 +35,12 @@ They allow the exposure of multiple HTTP services through the same endpoint, act
---
layout: two-cols-header
transition: fade
-hideInToc: true
+title: Ingress Controllers
+level: 2
+routeAlias: ingress-controllers
---
-# [Ingresses](https://kubernetes.io/docs/concepts/services-networking/ingress/)
+# [Ingress Controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/)
To use `Ingresses`, a specific controller has to provision it
From 50beff714031685ddd992030f24d3825350ccf4f Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 10 Nov 2025 03:00:32 +0100
Subject: [PATCH 64/67] Add component v-space
---
components/v-space.vue | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
create mode 100644 components/v-space.vue
diff --git a/components/v-space.vue b/components/v-space.vue
new file mode 100644
index 0000000..db2bd3a
--- /dev/null
+++ b/components/v-space.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
From 3143267b871ea890fc74a6af16601a8ae572c0bb Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 10 Nov 2025 03:08:41 +0100
Subject: [PATCH 65/67] Add cert manager snippets
---
.../cert-manager/certificate-selfsigned.yaml | 13 +++++++++++
...usterissuer-letsencrypt-staging-dns01.yaml | 16 ++++++++++++++
...sterissuer-letsencrypt-staging-http01.yaml | 14 ++++++++++++
.../clusterissuer-selfsigned.yaml | 6 +++++
.../ingress-echo-server-tls-annotated.yaml | 22 +++++++++++++++++++
.../cert-manager/ingress-echo-server-tls.yaml | 20 +++++++++++++++++
.../cert-manager/issuer-selfsigned.yaml | 7 ++++++
7 files changed, 98 insertions(+)
create mode 100644 snippets/manifests/cert-manager/certificate-selfsigned.yaml
create mode 100644 snippets/manifests/cert-manager/clusterissuer-letsencrypt-staging-dns01.yaml
create mode 100644 snippets/manifests/cert-manager/clusterissuer-letsencrypt-staging-http01.yaml
create mode 100644 snippets/manifests/cert-manager/clusterissuer-selfsigned.yaml
create mode 100644 snippets/manifests/cert-manager/ingress-echo-server-tls-annotated.yaml
create mode 100644 snippets/manifests/cert-manager/ingress-echo-server-tls.yaml
create mode 100644 snippets/manifests/cert-manager/issuer-selfsigned.yaml
diff --git a/snippets/manifests/cert-manager/certificate-selfsigned.yaml b/snippets/manifests/cert-manager/certificate-selfsigned.yaml
new file mode 100644
index 0000000..513e582
--- /dev/null
+++ b/snippets/manifests/cert-manager/certificate-selfsigned.yaml
@@ -0,0 +1,13 @@
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: selfsigned-example
+spec:
+ issuerRef:
+ group: cert-manager.io
+ kind: ClusterIssuer
+ name: selfsigned
+ dnsNames:
+ - example.com
+ - www.example.com
+ secretName: selfsigned-example-tls
diff --git a/snippets/manifests/cert-manager/clusterissuer-letsencrypt-staging-dns01.yaml b/snippets/manifests/cert-manager/clusterissuer-letsencrypt-staging-dns01.yaml
new file mode 100644
index 0000000..eb82f83
--- /dev/null
+++ b/snippets/manifests/cert-manager/clusterissuer-letsencrypt-staging-dns01.yaml
@@ -0,0 +1,16 @@
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ email: "admin@example.org"
+ privateKeySecretRef:
+ name: letsencrypt-staging
+ solvers:
+ - dns01:
+ cloudflare:
+ apiTokenSecretRef:
+ name: cloudflare-api-token-secret
+ key: api-token
diff --git a/snippets/manifests/cert-manager/clusterissuer-letsencrypt-staging-http01.yaml b/snippets/manifests/cert-manager/clusterissuer-letsencrypt-staging-http01.yaml
new file mode 100644
index 0000000..3fe22ad
--- /dev/null
+++ b/snippets/manifests/cert-manager/clusterissuer-letsencrypt-staging-http01.yaml
@@ -0,0 +1,14 @@
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ email: "admin@example.org"
+ privateKeySecretRef:
+ name: letsencrypt-staging
+ solvers:
+ - http01:
+ ingress:
+ ingressClassName: nginx
diff --git a/snippets/manifests/cert-manager/clusterissuer-selfsigned.yaml b/snippets/manifests/cert-manager/clusterissuer-selfsigned.yaml
new file mode 100644
index 0000000..8120e82
--- /dev/null
+++ b/snippets/manifests/cert-manager/clusterissuer-selfsigned.yaml
@@ -0,0 +1,6 @@
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: selfsigned
+spec:
+ selfSigned: {}
diff --git a/snippets/manifests/cert-manager/ingress-echo-server-tls-annotated.yaml b/snippets/manifests/cert-manager/ingress-echo-server-tls-annotated.yaml
new file mode 100644
index 0000000..c55411d
--- /dev/null
+++ b/snippets/manifests/cert-manager/ingress-echo-server-tls-annotated.yaml
@@ -0,0 +1,22 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: echo-server
+ annotations:
+ cert-manager.io/cluster-issuer: letsencrypt-staging
+spec:
+ rules:
+ - host: echo.example.org
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: echo-server
+ port:
+ name: http
+ tls:
+ - hosts:
+ - echo.example.org
+ secretName: echo-server-tls
diff --git a/snippets/manifests/cert-manager/ingress-echo-server-tls.yaml b/snippets/manifests/cert-manager/ingress-echo-server-tls.yaml
new file mode 100644
index 0000000..d11bb23
--- /dev/null
+++ b/snippets/manifests/cert-manager/ingress-echo-server-tls.yaml
@@ -0,0 +1,20 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: echo-server
+spec:
+ rules:
+ - host: echo.example.org
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: echo-server
+ port:
+ name: http
+ tls:
+ - hosts:
+ - echo.example.org
+ secretName: echo-server-tls
diff --git a/snippets/manifests/cert-manager/issuer-selfsigned.yaml b/snippets/manifests/cert-manager/issuer-selfsigned.yaml
new file mode 100644
index 0000000..54bfd58
--- /dev/null
+++ b/snippets/manifests/cert-manager/issuer-selfsigned.yaml
@@ -0,0 +1,7 @@
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: selfsigned
+ namespace: cert-manager
+spec:
+ selfSigned: {}
From cc209b85cdd8eba58ee43e37957a208e1f5e3a60 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 10 Nov 2025 03:09:04 +0100
Subject: [PATCH 66/67] Add cert manager slides
---
pages/23-annotations.md | 1 +
pages/24-cert-manager.md | 325 +++++++++++++++++++++++++++++++++++++++
slides.md | 4 +
3 files changed, 330 insertions(+)
create mode 100644 pages/24-cert-manager.md
diff --git a/pages/23-annotations.md b/pages/23-annotations.md
index 8c312c9..e486ebc 100644
--- a/pages/23-annotations.md
+++ b/pages/23-annotations.md
@@ -1,6 +1,7 @@
---
layout: two-cols
title: Annotations
+routeAlias: annotations
---
# [Annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)
diff --git a/pages/24-cert-manager.md b/pages/24-cert-manager.md
new file mode 100644
index 0000000..dcb1822
--- /dev/null
+++ b/pages/24-cert-manager.md
@@ -0,0 +1,325 @@
+---
+#layout: two-cols
+transition: fade
+title: cert-manager
+---
+
+# [cert-manager](https://cert-manager.io/docs/)
+
+It's an operator designed to provision X.509 certificates
+
+
+
+
+
+It can be installed with `helm`
+
+```shell
+helm install cert-manager oci://quay.io/jetstack/charts/cert-manager \
+ --namespace cert-manager --create-namespace \
+ --set crds.enabled=true
+```
+
+
+
+
+
+
+
+N.B. `cert-manager` helm chart is distributed via OCI registry. In this case `helm repo add` is not required
+
+
+
+
+
+---
+transition: fade
+level: 2
+---
+
+# [X.509 Certificate](https://en.wikipedia.org/wiki/X.509)
+
+An X.509 certificate binds an identity to a public key using a digital signature.
+
+
+
+The concept of "identity" is purposefully kept generic,
+enabling certificates to be used across a wide range of use cases and applications.
+
+- DNS names
+- IP addresses
+- email
+
+The certificate, which includes the "identity" and the public key (owned by the applicant),
+is signed and released by a [Certificate Authority (CA)](https://en.wikipedia.org/wiki/Certificate_authority)
+
+The validity of the certificate is proved through the [chain of trust](https://en.wikipedia.org/wiki/Chain_of_trust):
+The verifier of the certificate needs to trust only the [Root CA](https://en.wikipedia.org/wiki/Root_certificate)
+
+
+
+---
+layout: two-cols
+transition: fade
+level: 2
+---
+
+# [cert-manager Issuers](https://cert-manager.io/docs/concepts/issuer/)
+
+They represent certificate authorities (CAs) that are able to release X.509 certificates
+
+
+
+
+
+`cert-manager` offer two types of issuer resources: `Issuer` which is `Namespace` specific and `ClusterIssuer` which is usable cluster wide
+
+
+
+::right::
+
+<<<@/snippets/manifests/cert-manager/issuer-selfsigned.yaml yaml[issuer-selfsigned.yaml]{all}{lines:true}
+
+
+
+<<<@/snippets/manifests/cert-manager/clusterissuer-selfsigned.yaml yaml[clusterissuer-selfsigned.yaml]{hide|all}{lines:true,at:1}
+
+---
+layout: two-cols
+transition: fade
+level: 2
+---
+
+# [cert-manager Certificates](https://cert-manager.io/docs/usage/certificate/)
+
+They represent a human-readable definition of a certificate request
+
+
+
+
+
+Each `Certificate` is managed by a specific `Issuer`
+
+`cert-manager` provides support for specifying different "identities" to be included in the certificates
+(e.g. `dnsName`, `uris`, `ipAddresses`, etc.)
+
+The certificate (and the associated private key) will be stored in a secret once it is generated
+
+N.B. the operator will take care of renewing the certificate when it is about to expire
+
+
+
+::right::
+
+<<<@/snippets/manifests/cert-manager/certificate-selfsigned.yaml yaml[certificate-selfsigned.yaml]{all|6-9|10-12|13|all}{lines:true,at:1}
+
+
+
+---
+layout: two-cols-header
+transition: fade
+level: 2
+---
+
+# [ACME](https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment)
+
+(Automatic Certificate Management Environment)
+is a protocol for automating interactions between [Certificate Authorities](https://en.wikipedia.org/wiki/Certificate_authority) and servers
+
+
+
+::left::
+
+
+
+
+
+
+
+[certbot](https://certbot.eff.org/) is the reference implementation of server certificate management software using the ACME protocol
+
+
+
+::right::
+
+
+
+
+
+
+
+[Let's Encrypt](https://certbot.eff.org/) is a non-profit certificate authority run by Internet Security Research Group (ISRG) that provides X.509 certificates for Transport Layer Security (TLS) encryption at no charge
+
+
+
+---
+layout: two-cols-header
+transition: fade
+level: 2
+---
+
+# [ACME Challenges](https://acmeprotocol.dev/acme/challenges/)
+
+Challenges provide the CA with assurance that certificate requesters control the identifiers (domain names or IP addresses) requested to be included in the certificates
+
+
+
+
+
+In a TLS scenario, the CA certifies ownership of domain names (or less commonly IP addresses)
+
+So, the `cert-manager` operator needs to prove to the CA that it has control over the domains specified in the certificate request
+
+
+
+---
+layout: two-cols-header
+transition: fade
+level: 2
+---
+
+# [ACME HTTP-01 Challenge](https://acmeprotocol.dev/acme/challenges/#http-01)
+
+It requires proving that the operator can expose an HTTP server on the domains
+
+
+
+
+
+The CA provides a token for the challenge to the operator, who has to expose a plain text file at
+```text
+http:///.well-known/acme-challenge/
+```
+containing the token plus a thumbprint of the ACME account key
+
+
+
+
+
+The CA can verify the domain ownership by pulling the file and checking the content
+
+
+
+
+
+N.B. the HTTP server must be exposed on the internet to allow the CA to complete the check
+
+
+
+---
+layout: two-cols-header
+transition: fade
+level: 2
+---
+
+# [ACME DNS-01 Challenge](https://acmeprotocol.dev/acme/challenges/#dns-01)
+
+It requires proving that the operator can modify DNS records in the DNS zone
+
+
+
+
+
+The CA provides a token for the challenge to the operator,
+who has to create a TXT record `_acme-challenge.` containing it
+
+
+
+
+
+The CA can verify the domain ownership by making a DNS query to a trusted DNS
+
+
+
+
+
+N.B. this kind of challenge can be used also for wildcard domains and domains without record A/AAAA on the internet (e.g., inside a VPN)
+
+
+
+---
+transition: fade
+level: 2
+---
+
+# [cert-manager Issuers HTTP-01](https://cert-manager.io/docs/configuration/acme/http01/)
+
+`cert-manager` can perform an HTTP-01 challenge exploiting an Ingress Controller
+
+<<<@/snippets/manifests/cert-manager/clusterissuer-letsencrypt-staging-http01.yaml yaml[clusterissuer-letsencrypt-staging-http01.yaml]{all|7|8|9-10|11-14|all}{lines:true}
+
+---
+transition: fade
+level: 2
+---
+
+# [cert-manager Issuers DNS-01](https://cert-manager.io/docs/configuration/acme/dns01/)
+
+`cert-manager` also supports the DNS-01 challenge
+
+<<<@/snippets/manifests/cert-manager/clusterissuer-letsencrypt-staging-dns01.yaml yaml[clusterissuer-letsencrypt-staging-dns01.yaml]{all|11-16|all}{lines:true}
+
+
+
+N.B. for this challenge, `cert-manager` has to support your DNS provider (e.g., Cloudflare)
+
+
+
+---
+layout: two-cols
+transition: fade
+level: 2
+---
+
+# [Ingresses over TLS](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls)
+
+`Ingresses` can also expose a service over HTTPS
+
+
+
+If the `Ingress controller` supports HTTPS, settings the `.spec.tls` field makes the `Ingress` served also on HTTPS
+
+It is enough to provide the `Secret` containing the certificate
+
+
+
+::right::
+
+````md magic-move[ingress-echo-server-tls.yaml] {lines:true,at:0}
+<<<@/snippets/manifests/cert-manager/ingress-echo-server-tls.yaml yaml{17-20|17-20|20|17-20}
+````
+
+---
+layout: two-cols
+level: 2
+---
+
+# [Ingresses over TLS](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls)
+
+`cert-manager` can also directly provide the `Certificate` resource for an `Ingress`
+
+
+
+This behavior can be achieved by setting the `"cert-manager.io/cluster-issuer"` annotation to reference a `ClusterIssuer`
+
+
+
+::right::
+
+````md magic-move[ingress-echo-server-tls.yaml]{lines:true,at:0}
+<<<@/snippets/manifests/cert-manager/ingress-echo-server-tls.yaml yaml{17-20}
+<<<@/snippets/manifests/cert-manager/ingress-echo-server-tls-annotated.yaml yaml{5-6}
+````
diff --git a/slides.md b/slides.md
index fb27685..bf1f6fe 100644
--- a/slides.md
+++ b/slides.md
@@ -76,6 +76,10 @@ src: ./pages/22-custom-resource-definitions.md
src: ./pages/23-annotations.md
---
+---
+src: ./pages/24-cert-manager.md
+---
+
---
hideInToc: true
---
From 32c5aa5f31b324a9c80f599c49ae340cae055842 Mon Sep 17 00:00:00 2001
From: Roberto Bochet
Date: Mon, 10 Nov 2025 03:38:06 +0100
Subject: [PATCH 67/67] Add cert manager resources flowchart
---
.prettierignore | 1 +
pages/24-cert-manager.md | 15 ++++++++++++++-
snippets/diagrams/cert-manager-resources.mermaid | 16 ++++++++++++++++
3 files changed, 31 insertions(+), 1 deletion(-)
create mode 100644 snippets/diagrams/cert-manager-resources.mermaid
diff --git a/.prettierignore b/.prettierignore
index ced3696..f18ccd7 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,5 +1,6 @@
.prettierignore
*.lock
*.svg
+*.mermaid
**/helm/templates.yaml
LICENSE
diff --git a/pages/24-cert-manager.md b/pages/24-cert-manager.md
index dcb1822..3fc2686 100644
--- a/pages/24-cert-manager.md
+++ b/pages/24-cert-manager.md
@@ -304,7 +304,8 @@ It is enough to provide the `Secret` containing the certificate
---
layout: two-cols
-level: 2
+transition: fade
+level: 3
---
# [Ingresses over TLS](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls)
@@ -323,3 +324,15 @@ This behavior can be achieved by setting the `"cert-manager.io/cluster-issuer"`
<<<@/snippets/manifests/cert-manager/ingress-echo-server-tls.yaml yaml{17-20}
<<<@/snippets/manifests/cert-manager/ingress-echo-server-tls-annotated.yaml yaml{5-6}
````
+
+---
+level: 2
+---
+
+# cert-manager resources workflow
+
+For debugging purposes, it is useful to understand the role of the `cert-manager` resources
+
+
+
+<<<@/snippets/diagrams/cert-manager-resources.mermaid
diff --git a/snippets/diagrams/cert-manager-resources.mermaid b/snippets/diagrams/cert-manager-resources.mermaid
new file mode 100644
index 0000000..a00730e
--- /dev/null
+++ b/snippets/diagrams/cert-manager-resources.mermaid
@@ -0,0 +1,16 @@
+flowchart LR
+ U([User])
+ C[Certificate]
+ A[\Annotated Ingress\]
+ CR[CertificateRequest]
+ O[Order]
+ CH@{shape: procs, label: "Challenges"}
+ S[Secret]
+
+ U -.-> C
+ U -.-> A
+ A --> C
+ C --> CR
+ CR --> O
+ O --> CH
+ CR --> S