<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Labs :: Kubernetes training</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/index.html</link><description>Welcome to the labs for the “Kubernetes and Openshift advanced” training.</description><generator>Hugo</generator><language>en</language><copyright>Copyright (c) 2025 Fabrice Jammes - Licensed under CC BY-SA 4.0</copyright><lastBuildDate>Mon, 15 Jun 2026 14:15:26 +1000</lastBuildDate><atom:link href="https://k8s-school.fr/labs/k8s/en/1_labs/index.xml" rel="self" type="application/rss+xml"/><item><title>Kubernetes Controllers</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/controller/index.html</link><pubDate>Sun, 23 Mar 2025 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/controller/index.html</guid><description>Objective This lab will help you understand the role of Kubernetes controllers in managing the desired/actual state of cluster resources.
Prerequisites A Kubernetes cluster (Minikube, Kind, or a cloud-based Kubernetes cluster) kubectl installed and configured Step 1: Understand Controllers Kubernetes controllers are control loops that monitor the state of the cluster and make or request changes where needed. The key controllers include:</description></item><item><title>Multi-Container Pod Design Patterns</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/multi-container-patterns/index.html</link><pubDate>Mon, 24 Nov 2025 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/multi-container-patterns/index.html</guid><description>Auteur: Fabrice JAMMES (LinkedIn). Date: Nov 24, 2025 · 10 min read
Quick Exercise: Fix the Bugs! 🐛 Objective Create a pod with an init container and a sidecar - There are 2 bugs to fix!
Scenario Init container: generates an index.html with system info Main container: nginx 1.25.3 web server Sidecar: counts requests in access logs every 10 seconds Task Deploy the following pod and fix the errors:</description></item><item><title>Pod Anti Affinity</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/antiaffinity/index.html</link><pubDate>Thu, 06 Jun 2024 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/antiaffinity/index.html</guid><description>Create a nginx deployment with 3 pods Solution apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: gcr.io/google_containers/nginx-slim:0.9 ports: - containerPort: 8080 Add a ‘podAntiAffinity’ section to the deployment The goal is to distribute all pod for this deployment across different nodes.</description></item><item><title>Infrastructure pod</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/infrastructure-pod/index.html</link><pubDate>Thu, 20 Feb 2025 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/infrastructure-pod/index.html</guid><description>Author: Fabrice JAMMES (LinkedIn)
Task Follow the steps below to investigate the relationship between Kubernetes pods and containers:
Connect to a Kind node Answer Run docker ps to find the Kind node name. Use docker exec -it &lt;kind-node-name&gt; bash to enter the container. docker exec -it &lt;kind-node-name&gt; bash Use crictl to list pods and containers: Answer crictl ps -a lists all containers. crictl pods shows running pods. crictl ps -a crictl pods Investigate the relationship between a pod and its container(s): Answer crictl inspect &lt;container-id&gt; provides container details. ps auxf shows process hierarchy. crictl inspect &lt;container-id&gt; crictl inspectp &lt;pod-id&gt; ps auxf What is the role of the “pause” process? Answer The “pause” container acts as the parent container for all other containers in a pod. It holds the network namespace and ensures pod lifecycle consistency. Explore the directories /var/log and /var/lib/kubelet. Answer /var/log: Contains logs from Kubernetes components and container runtime. /var/lib/kubelet/pods: Stores pod data, volume mounts, and container runtime state Conclusion This lab guides you through a better understanding of pod technical architecture.</description></item><item><title>Trivy: Container Vulnerability Scanning</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/trivy/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/trivy/index.html</guid><description>Learn to scan container images for vulnerabilities and generate Software Bills of Materials (SBOM) using Trivy</description></item><item><title>Cosign: Container Image Signing &amp; Verification</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/cosign/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/cosign/index.html</guid><description>Learn to sign and verify container images using Cosign for supply chain security</description></item><item><title>Kubernetes easy install with Kubeadm</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/kubeadm/index.html</link><pubDate>Mon, 27 Jan 2020 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/kubeadm/index.html</guid><description>Auteur: Fabrice JAMMES (LinkedIn). Date: Jan 27, 2020 · 10 min read
This article explains how to install Kubernetes with kubeadm, the official Kubernetes installer. It is inspired by the official documentation, while declining it for Ubuntu and simplifying it.
It has been successfully tested with Kubernetes 1.31.0
Pre-requisites: Infrastructure One or more machines running Ubuntu LTS, with administrator access ( sudo) 2 GB or more of RAM per machine 2 or more processors on the master node Full network connectivity between all machines in the cluster The ‘size-of-master-and-master-components’ documentation define some guidelines on how to size your masters nodes depending on the total number of your Kubernetes nodes.</description></item><item><title>Kubernetes Service Account Token Lab</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/service-account/index.html</link><pubDate>Tue, 18 Nov 2025 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/service-account/index.html</guid><description>Auteur: Fabrice JAMMES (LinkedIn). Date: Nov 18, 2025 · 10 min read
A simple lab to explore Service Accounts and their tokens in Kubernetes.
Prerequisites A Kubernetes cluster (kind, minikube, or any cluster) kubectl configured jq installed (for JSON parsing) Lab Overview Understanding default Service Accounts Creating custom Service Accounts Exploring Service Account tokens (JWT) Using tokens to authenticate Token mounting behavior Part 1: Default Service Account Every namespace automatically gets a default service account.</description></item><item><title>RBAC</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/rbac/index.html</link><pubDate>Wed, 26 Feb 2025 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/rbac/index.html</guid><description>Author: Fabrice JAMMES (LinkedIn).
1. Create Namespaces Create two namespaces:
foo-&lt;ID&gt; bar-&lt;ID&gt; Answer kubectl create namespace foo-&lt;ID&gt; kubectl create namespace bar-&lt;ID&gt; 2. Deploy curl-custom-sa Pod Create a curl-custom-sa pod inside the foo-&lt;ID&gt; namespace, using the service account foo-&lt;ID&gt;:default (the default service account of foo-&lt;ID&gt;).</description></item><item><title>RBAC monitoring</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/rbac-secissue/index.html</link><pubDate>Thu, 06 Jun 2024 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/rbac-secissue/index.html</guid><description>Exercice: find RBAC security issue Connect to Kubernetes:
ktbx desk kubectx kind-kind Then use: https://github.com/alcideio/rbac-tool https://github.com/kubescape/kubescape https://github.com/corneliusweig/rakkess
To find the RBAC security issue in the cluster.</description></item><item><title>NetworkPolicy</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/networkpolicy/index.html</link><pubDate>Thu, 06 Jun 2024 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/networkpolicy/index.html</guid><description>Prerequisites # Launch the toolbox ktbx desk # Check your use kind-kind context kubectx #Launch initialization script /home/k8s0/openshift-advanced/labs/3_policies/ex4-network.sh # go to correct namespace kubens network-k8s&lt;ID&gt; Check that 3 pods have been created.
Solution kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS external 1/1 Running 0 2m app=external pgsql-postgresql-0 1/1 Running 0 2m ...,tier=database webserver 1/1 Running 0 2m tier=webserver Play with network policy Look at the official documentation and at the examples</description></item><item><title>Seccomp Security Profiles</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/seccomp/index.html</link><pubDate>Thu, 06 Jun 2024 19:00:00 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/seccomp/index.html</guid><description>Objectives Learn how to use seccomp (secure computing mode) to restrict system calls in Kubernetes pods. Seccomp is a Linux kernel feature that limits which system calls a process can make, providing an additional security layer.
Prerequisites Understanding Seccomp Seccomp is a security mechanism that filters system calls:</description></item><item><title>Audit Logs &amp; API Server</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/audit-logs/index.html</link><pubDate>Thu, 06 Jun 2024 15:00:00 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/audit-logs/index.html</guid><description>Objectives Configure audit policies to trace modifications on critical resources and secure the API Server in a Kubernetes cluster.
Prerequisites Define your cluster name:
$CLUSTER_NAME="my-cluster" Q1: How to modify the API Server configuration? Answer The API Server in Kubernetes runs as a static pod managed by the kubelet. Static pods are defined by YAML manifests in the /etc/kubernetes/manifests/ directory. When you modify a static pod manifest:</description></item><item><title>Runtime Security with Falco</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/falco/index.html</link><pubDate>Thu, 06 Jun 2024 16:00:00 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/falco/index.html</guid><description>Objectives Use Falco to detect suspicious behaviors inside containers in real-time and learn to configure custom security rules for Kubernetes environments.
Prerequisites Understanding Falco Falco is a cloud-native runtime security project that detects unexpected behavior, intrusions, and data theft in real-time. It works by monitoring system calls and Kubernetes events.</description></item><item><title>Hardening with CIS Benchmarks - Running kube-bench Jobs</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/kubebench-10-jobs/index.html</link><pubDate>Fri, 09 Jan 2026 10:00:00 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/kubebench-10-jobs/index.html</guid><description>Introduction to CIS Benchmarks The Center for Internet Security (CIS) provides best practices for securing Kubernetes. In this lab, we will use kube-bench, an open-source tool from Aqua Security, to check whether our cluster meets these security recommendations.
Running kube-bench as a Job In a CKS exam or production environment, you often run kube-bench as a Kubernetes Job to scan nodes without SSH access.</description></item><item><title>AppArmor Security Profiles</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/apparmor/index.html</link><pubDate>Thu, 06 Jun 2024 16:00:00 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/apparmor/index.html</guid><description>Objectives Learn how to use AppArmor to implement mandatory access control in Kubernetes pods. AppArmor is a Linux kernel security module that confines programs to a limited set of resources through security profiles.
Prerequisites Understanding AppArmor AppArmor is a security mechanism that provides path-based access control:</description></item><item><title>Hardening with CIS Benchmarks - Security Remediations</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/kubebench-20-remediations/index.html</link><pubDate>Fri, 09 Jan 2026 10:00:00 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/kubebench-20-remediations/index.html</guid><description>Practical CKS Exercise Workflow As a CKS candidate, you should practice the complete security hardening workflow manually. This section guides you through the key exercises step by step to remediate security issues found by kube-bench.
Remove the --profiling argument for the scheduler Look for the check 1.4.1: Ensure that the –profiling argument is set to false.</description></item><item><title>Hardening with CIS Benchmarks - Automation and Continuous Compliance</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/kubebench-30-automation/index.html</link><pubDate>Fri, 09 Jan 2026 10:00:00 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/kubebench-30-automation/index.html</guid><description>Automation and Continuous Compliance Why is running kube-bench manually not enough for a production environment?
Answers Configuration Drift: A manual change or update could revert security settings. New Benchmarks: CIS updates its recommendations regularly. Visibility: Security teams need centralized reporting, not just CLI logs. Suggested improvement Integrate kube-bench into a CronJob to run every week and send results to a security dashboard like Falco or a SIEM.</description></item><item><title>Helm chart - Quick Lab</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/helm/index.html</link><pubDate>Tue, 11 Nov 2025 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/helm/index.html</guid><description>Objective Create and deploy a Helm chart with nginx application using secure nginxinc image and resource configurations. Complete this lab in 10-15 minutes.
Prerequisites Kubernetes cluster running (minikube, kind, or cloud cluster) helm v3+ installed kubectl configured to access the cluster Setup: Create your namespace On a shared cluster, work in your own namespace to avoid colliding with other users. We name it after your numeric user id:</description></item><item><title>Helm on OpenShift: Migrating to Security Context Constraints</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/helm-openshift-migration/index.html</link><pubDate>Mon, 08 Jun 2026 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/helm-openshift-migration/index.html</guid><description>Objective A Helm chart that works perfectly on vanilla Kubernetes often fails on OpenShift. In this guided lab you’ll deploy a generic nginx Helm chart step by step — from its default values (which fail) to an OpenShift-compatible configuration (which succeeds) — diagnosing each failure along the way with oc/kubectl.
You’ll learn:
Why OpenShift’s Security Context Constraints (SCC) prevent containers from running as root How OpenShift assigns a non-root UID per namespace, and why that breaks images that assume root How to adapt a chart (here, the official nginx image) to run under restricted-v2 Complete this lab in 20-30 minutes.</description></item><item><title>OpenShift Airgapped: Mirroring Container Images</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/openshift-airgapped-image-mirroring/index.html</link><pubDate>Mon, 08 Jun 2026 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/openshift-airgapped-image-mirroring/index.html</guid><description>Author: Fabrice JAMMES (LinkedIn). Duration: 25-35 minutes
Objective Clusters running in restricted networks (“airgapped”) cannot pull images directly from the internet (i.e. docker.io). You must mirror the images you need into a registry the cluster can reach, and then make the cluster use that mirror.
There are two fundamentally different ways to achieve this:
A. Cluster-wide transparent redirection — configure OpenShift itself (ImageTagMirrorSet) to silently redirect every docker.io pull to your local mirror. Charts and Deployments stay untouched. B. Explicit reference — point each chart/Deployment directly at the mirror registry (image.registry=...). No cluster-level redirection is configured. In this guided lab you’ll deploy the same nginx chart both ways, observe how the resulting Pods differ, and weigh the trade-offs of each approach.</description></item><item><title>OpenShift Airgapped: Declarative Mirroring with oc-mirror v2</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/openshift-airgapped-oc-mirror/index.html</link><pubDate>Wed, 10 Jun 2026 18:00:00 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/openshift-airgapped-oc-mirror/index.html</guid><description>Author: Fabrice JAMMES (LinkedIn). Duration: 25-35 minutes
Objective In the previous lab you mirrored a single image with skopeo copy and hand-wrote an ImageTagMirrorSet to redirect docker.io pulls to it. That works, but it doesn’t scale: every image needs its own skopeo copy, and the mirror-set YAML must be kept perfectly in sync with whatever you copied — get the library/ namespace wrong and pulls 404.</description></item><item><title>Kustomize</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/kustomize/index.html</link><pubDate>Tue, 11 Nov 2025 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/kustomize/index.html</guid><description>Lab Overview In this quick lab, you will learn the essentials of Kustomize by creating a base configuration and two environment overlays (dev and production).
Duration: 10-15 minutes
Prerequisites:
kubectl installed (with Kustomize support) Basic understanding of Kubernetes resources Exercise 1: Setup Base Configuration Objective Create a base configuration for a simple nginx application.</description></item><item><title>OpenShift Networking: From Ingress to Route</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/openshift-ingress-route/index.html</link><pubDate>Mon, 15 Jun 2026 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/openshift-ingress-route/index.html</guid><description>Author: Fabrice JAMMES (LinkedIn). Duration: 20-30 minutes
Objective OpenShift predates the Kubernetes Ingress API by several years. Its native object for exposing HTTP(S) services is the Route (route.openshift.io/v1), handled by the HAProxy-based router. To stay compatible with portable Kubernetes manifests, OpenShift ships a controller — part of openshift-controller-manager / route-controller-manager — that watches every Ingress object cluster-wide and automatically creates a matching Route for it.</description></item><item><title>Monitoring with Prometheus</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/prometheus/index.html</link><pubDate>Thu, 20 Feb 2025 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/prometheus/index.html</guid><description>Author: Fabrice JAMMES (LinkedIn).
Prerequisites # Launch the toolbox ktbx desk # Check your use kind-kind context kubectx #Launch initialization script /home/k8s0/openshift-advanced/labs/3_policies/ex4-network.sh # go to correct namespace kubens network-k8s&lt;ID&gt; Kubernetes Monitoring Lab with Helm Objective The goal of this lab is to deploy the Prometheus Stack using Helm while following best practices in shell scripting.</description></item><item><title>Understanding StatefulSets</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/mongo/index.html</link><pubDate>Tue, 25 Feb 2025 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/mongo/index.html</guid><description>Semi-Manual Installation Create a MongoDB StatefulSet.
Apply the mongo-simple.yaml file to create the StatefulSet. Then apply the mongo-service.yaml file to create the headless service.
Check that the pods start in order.
Start a shell in an Ubuntu pod (kubectl run -i --rm --tty shell --image=ubuntu:24.04 -- bash), install nslookup or dig, and attempt a DNS resolution of:
mongo mongo-1.mongo What do you observe?</description></item><item><title>Kubectl proxy and curl</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/kubectl-proxy/index.html</link><pubDate>Wed, 26 Feb 2025 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/kubectl-proxy/index.html</guid><description>Author: Fabrice JAMMES (LinkedIn).
Objective Learn how to use kubectl proxy and curl to list services in a specified Kubernetes namespace.
Prerequisites A running Kubernetes cluster kubectl installed and configured curl installed Steps Step 1: Start kubectl proxy Run the following command to start the kubectl proxy:</description></item><item><title>Kubelet and static pods</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/openshift-staticpod/index.html</link><pubDate>Sun, 30 Jun 2024 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/openshift-staticpod/index.html</guid><description>Exercice 1: retrieve static pod specifications in Kubernetes (kind-based) Switch to Kubernetes cluster using kubectx kind-kind and then access the control plane Node using docker exec -t -- &lt;my-master-node&gt; sh and then access Kubelet configuration.
Answer MASTER_NODE=$(kubectl get nodes '--selector=node-role.kubernetes.io/control-plane' -o jsonpath='{.items[0].metadata.name}') # Exit the ktbx-toolbox to run docker docker exec -t -- kind-control-plane sh -c 'ps -ef | grep "/usr/bin/kubelet"' docker exec -t -- kind-control-plane sh -c 'cat /var/lib/kubelet/config.yaml | grep -i staticPodPath' docker exec -t -- kind-control-plane sh -c 'ls /etc/kubernetes/manifests' Exercice 1: retrieve static pod specifications in Openshift Switch to Kubernetes cluster using kubectx &lt;my-openshift-context&gt; and then access the control plane Node using oc debug node/&lt;my-master-node&gt; and then access Kubelet configuration.</description></item><item><title>etcd administration</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/openshift-etcd/index.html</link><pubDate>Sun, 30 Jun 2024 14:15:26 +1000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/openshift-etcd/index.html</guid><description>Auteur: Fabrice JAMMES (LinkedIn).
Exercice 1: display Kubernetes and Openshift resources Retrieve etcd pod name Answer # Wait for etcd pod to be u kubectl wait --timeout=240s --for=condition=Ready -n "openshift-etcd" pods -l "app=etcd,etcd=true,k8s-app=etcd" etcd_pod=$(kubectl get pods -n "openshift-etcd" -l "app=etcd,etcd=true,k8s-app=etcd" -o jsonpath='{.items[0].metadata.name}') Launch etcdctl --help inside etcd pod Answer # Display Kubernetes keys kubectl exec -t -n "openshift-etcd" "$etcd_pod" -- etcdctl --help</description></item><item><title>Horizontal Pod Autoscaling (HPA)</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/hpa/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/hpa/index.html</guid><description>Right-size cost by scaling the number of replicas automatically based on CPU load with the Horizontal Pod Autoscaler</description></item><item><title>Vertical Pod Autoscaling (VPA)</title><link>https://k8s-school.fr/labs/k8s/en/1_labs/vpa/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://k8s-school.fr/labs/k8s/en/1_labs/vpa/index.html</guid><description>Right-size CPU and memory requests automatically with the Vertical Pod Autoscaler to cut waste and avoid OOMKills</description></item></channel></rss>