At the end of the previous lesson you had a cluster started and verified with a couple of borrowed commands. Now let us go for the tool itself. kubectl is the official client for the Kubernetes API and it is going to be, by a wide margin, the program you use most in this course and in your professional life with Kubernetes: creating, querying, inspecting, debugging and deleting all go through it. The good news is that kubectl is extraordinarily regular: once you understand its grammar, you know how to use it with any type of object, including the ones that do not exist yet. This lesson teaches you that grammar, the configuration file that decides which cluster you talk to, the verbs you will use daily on the Rutas Norte components, the output formats that turn kubectl into a serious query tool, and the productivity settings that separate whoever fights the cluster from whoever works with ease.
Contents
- What kubectl is, and installing it
- The kubeconfig file: clusters, users and contexts
- Anatomy of a kubectl command
- The day-to-day verbs
- Output formats and queries
- Label selection and live watching
- Imperative versus declarative
- Productivity: aliases, completion, explain and plugins
- What kubectl is, and installing it
kubectl has no intelligence of its own: it translates your commands into HTTPS requests against the kube-apiserver. Everything kubectl can do could be done by curl with the right certificate; what it adds is convenience, formatting and local validation.
Practical consequence: anything kubectl will not let you do is being forbidden by the server (RBAC), not by the tool.
Installation
Linux:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
rm kubectlmacOS:
Windows (PowerShell):
Verification:
Client Version: v1.30.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.30.0Compatibility rule (version skew): kubectl supports a difference of one minor version above or below the server. A 1.30 client works with 1.29, 1.30 and 1.31 servers. With bigger gaps, specific commands can fail in ways that are not obvious, so keep the client close to the server.
- The kubeconfig file: clusters, users and contexts
When minikube said "kubectl is now configured to use rutas-norte" in the previous lesson, what it did was write to ~/.kube/config. That file answers three questions: which server do I talk to?, with which credentials? and in which default namespace?
# ~/.kube/config (simplified)
apiVersion: v1
kind: Config
clusters: # WHICH server
- name: rutas-norte
cluster:
server: https://192.168.49.2:8443
certificate-authority: /home/user/.minikube/ca.crt
users: # WITH WHICH credentials
- name: rutas-norte
user:
client-certificate: /home/user/.minikube/profiles/rutas-norte/client.crt
client-key: /home/user/.minikube/profiles/rutas-norte/client.key
contexts: # THE COMBINATION of both + namespace
- name: rutas-norte
context:
cluster: rutas-norte
user: rutas-norte
namespace: default
current-context: rutas-norte # which one is active right nowThe key idea: a context is a triple (cluster, user, namespace). Switching context means switching cluster or identity with a single command. In a professional environment you will have contexts such as rutas-norte-dev, rutas-norte-pre and rutas-norte-pro, and getting the context wrong is the quickest way to cause an incident.
Context management commands
# See every available context; the active one carries an asterisk
kubectl config get-contexts
# Switch context
kubectl config use-context rutas-norte
# See only the name of the active context
kubectl config current-context
# Set the default namespace of the active context
kubectl config set-context --current --namespace=rutas-norte-devCURRENT NAME CLUSTER AUTHINFO NAMESPACE
* rutas-norte rutas-norte rutas-norte rutas-norte-dev
docker-desktop docker-desktop docker-desktopThat last command —setting the default namespace— will save you typing -n rutas-norte-dev hundreds of times during the course. Do it as soon as you create the namespace in lesson 01-07.
The KUBECONFIG variable: you can have several files and combine them. That is the usual arrangement when you work with several clients or environments:
Security tip: the kubeconfig contains credentials. Treat it like a private key:
600permissions, never in Git, never over chat.
- Anatomy of a kubectl command
The whole CLI follows this grammar:
kubectl [verb] [type] [name] [flags]
│ │ │ │
│ │ │ └── -n, -o, -l, --dry-run, --watch...
│ │ └───────── name of the object (optional: if absent, all of them)
│ └──────────────── pod, deployment, service, pvc, node...
└─────────────────────── get, describe, apply, delete, logs, exec...Examples read aloud:
kubectl get pods # give me every pod in the current namespace
kubectl get pod bookings-api -n rutas-norte-dev # give me that specific pod in that namespace
kubectl describe deployment web-store # explain that Deployment to me in detail
kubectl delete pod bookings-api # delete that podNames, plurals and short names
Kubernetes accepts singular, plural and short name interchangeably. kubectl get po, kubectl get pod and kubectl get pods are identical. The short names that save the most typing:
| Type | Short name | Type | Short name |
|---|---|---|---|
pods |
po |
services |
svc |
deployments |
deploy |
namespaces |
ns |
replicasets |
rs |
configmaps |
cm |
statefulsets |
sts |
persistentvolumeclaims |
pvc |
daemonsets |
ds |
persistentvolumes |
pv |
ingresses |
ing |
serviceaccounts |
sa |
The complete, authoritative list for your cluster, with short names, API group and whether the resource lives in a namespace:
NAME SHORTNAMES APIVERSION NAMESPACED KIND
configmaps cm v1 true ConfigMap
pods po v1 true Pod
services svc v1 true Service
nodes no v1 false Node
deployments deploy apps/v1 true Deployment
ingresses ing networking.k8s.io/v1 true IngressThe NAMESPACED column matters: it explains why kubectl get nodes -n rutas-norte-dev ignores the namespace (nodes are cluster-scoped).
The namespace, always present
kubectl get pods # the current context's namespace
kubectl get pods -n rutas-norte-pre # one specific namespace
kubectl get pods -A # every namespace (--all-namespaces)Forgetting the namespace is the number one cause of "my pod has vanished".
- The day-to-day verbs
We will work on a Rutas Norte scenario with the web store and the API already deployed in rutas-norte-dev.
4.1. get — a quick inventory
NAME READY STATUS RESTARTS AGE
bookings-api-6c8d7f9b45-2xk9p 1/1 Running 0 12m
bookings-api-6c8d7f9b45-hn4vq 1/1 Running 0 12m
web-store-7d4f8c6b9-lq2mn 1/1 Running 0 18m
notifications-worker-59c7d8f 0/1 CrashLoopBackOff 5 (48s ago) 9mHow to read each column:
- READY
1/1: containers ready / total containers in the pod.0/1means the container exists but has not passed its readiness probe. - STATUS:
Runningis normal;Pending(the scheduler finds no room),ContainerCreating,ImagePullBackOff(it cannot pull the image),CrashLoopBackOff(it starts and dies in a loop),Completed(finished tasks). - RESTARTS: restarts. A growing number is the clearest sign of a problem.
- AGE: since the object was created.
In that output, notifications-worker is clearly broken. The next three verbs are how you investigate it.
4.2. describe — the diagnosis
Name: notifications-worker-59c7d8f
Namespace: rutas-norte-dev
Node: rutas-norte/192.168.49.2
Labels: app=notifications-worker
app.kubernetes.io/part-of=rutas-norte
environment=dev
Status: Running
Containers:
worker:
Image: registry.rutasnorte.example/notifications-worker:1.2.0
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Error
Exit Code: 1
Restart Count: 5
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 9m default-scheduler Successfully assigned ...
Normal Pulled 8m (x4 over 9m) kubelet Container image already present
Warning BackOff 45s (x22 over 8m) kubelet Back-off restarting failed containerThe Events section is always the first thing to read. It is the diary of what the cluster has tried to do with that object and why it failed. Here it tells us that the container exits with code 1 and the kubelet retries with a growing back-off. We also see that the scheduler did assign it (so it is not a resource problem) and that the image pulled fine (so it is not a registry problem): the failure is inside the application.
describe works with any type: kubectl describe node rutas-norte, kubectl describe svc bookings-api, kubectl describe pvc postgres-data.
4.3. logs — the application's voice
# The pod's last lines
kubectl logs notifications-worker-59c7d8f -n rutas-norte-dev
# The logs of the PREVIOUS run: essential in a CrashLoopBackOff
kubectl logs notifications-worker-59c7d8f -n rutas-norte-dev --previous
# Follow live, last 50 lines, with timestamps
kubectl logs -f --tail=50 --timestamps bookings-api-6c8d7f9b45-2xk9p -n rutas-norte-dev
# Aggregated logs from ALL the replicas selected by label
kubectl logs -l app=bookings-api -n rutas-norte-dev --tail=20
# One specific container of a multi-container pod
kubectl logs my-pod -c metrics-sidecar[2026-08-05T02:14:07Z] notifications-worker v1.2.0 starting up
[2026-08-05T02:14:07Z] connecting to redis-cache:6379
[2026-08-05T02:14:12Z] ERROR: dial tcp: lookup redis-cache: no such host
[2026-08-05T02:14:12Z] process exited with code 1There is the cause: the worker cannot find redis-cache through DNS, probably because the Service does not exist yet. --previous is the most forgotten flag and the most useful: without it, in a CrashLoopBackOff you will see the logs of a container that has just started and has not failed yet.
4.4. exec — getting into the container
# A one-off command
kubectl exec bookings-api-6c8d7f9b45-2xk9p -n rutas-norte-dev -- env | grep DB_
# An interactive session
kubectl exec -it bookings-api-6c8d7f9b45-2xk9p -n rutas-norte-dev -- shThe -- separates kubectl's flags from the command to run inside; forgetting it is a classic mistake. -it means interactive with a terminal, just as in Docker.
A professional note: many well-built images are distroless and have neither sh nor networking tools. For those cases there is kubectl debug, which injects an ephemeral container with utilities; we will see it in module 7.
4.5. apply and delete — changing the desired state
kubectl apply -f k8s/base/bookings-api.yaml # one file
kubectl apply -f k8s/base/ # every file in the directory
kubectl apply -f k8s/base/ --recursive # including subdirectories
kubectl delete -f k8s/base/bookings-api.yaml # delete whatever the file declares
kubectl delete pod bookings-api-6c8d7f9b45-2xk9p # delete a specific object
kubectl delete pods -l app=bookings-api # delete by labelapply is the heart of the declarative model and we will study it thoroughly in the next lesson, Objects, YAML Manifests and the Declarative Model.
About delete: remember that deletion is asynchronous and that deleting a pod managed by a controller does not remove it, it only causes a new one to be created. To remove it for real you have to delete the controller.
4.6. edit — a one-off change in place
It opens the object in your editor ($EDITOR) and applies the changes when you save. It is convenient for experimenting and dangerous in production: the change does not end up in Git, so the next apply from the repository will silently revert it. Use it to explore; never as a way to deploy.
4.7. port-forward — local access without exposing anything
Now http://localhost:8080 reaches that pod. The format is local-port:container-port. It also works against a Service (svc/bookings-api 8081:80). It is the fastest way to check that something works before you have Ingress, and it is exactly what you will use in lesson 01-07 to see the Rutas Norte store in your browser. The process stays in the foreground: stop it with Ctrl+C.
4.8. explain — the offline documentation
KIND: Pod
VERSION: v1
FIELD: resources <ResourceRequirements>
DESCRIPTION:
Compute Resources required by this container. Cannot be updated.
FIELDS:
limits <map[string]Quantity>
Limits describes the maximum amount of compute resources allowed.
requests <map[string]Quantity>
Requests describes the minimum amount of compute resources required.This command deserves a paragraph of its own because it is the one that pays off most in the long run. It queries the schema of your own cluster, including the CRDs installed, so it never gives you stale information or information from another version. It works at any depth and, with --recursive, shows the complete tree of fields:
In the CKA/CKAD certification, where only the official documentation may be consulted, kubectl explain is the shortcut that saves minutes.
- Output formats and queries
The -o flag turns kubectl from a viewer into a query tool.
| Format | What it is for |
|---|---|
| (default) | A readable summary table |
-o wide |
Adds columns: pod IP, node, image |
-o yaml |
The complete object exactly as it is in the API, with its status |
-o json |
The same, in JSON, for processing with jq |
-o name |
Only type/name, ideal for chaining commands |
-o jsonpath='...' |
Extracts specific fields |
-o custom-columns=... |
A bespoke table |
NAME READY STATUS IP NODE NOMINATED NODE
bookings-api-6c8d7f9b45-2xk9p 1/1 Running 10.244.0.17 rutas-norte <none>
web-store-7d4f8c6b9-lq2mn 1/1 Running 10.244.0.14 rutas-norte <none># The complete object, including what the system has written
kubectl get pod bookings-api-6c8d7f9b45-2xk9p -n rutas-norte-dev -o yaml | head -25
# Extract specific fields with jsonpath
kubectl get pods -n rutas-norte-dev \
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}'
# A bespoke table: name, image and node
kubectl get pods -n rutas-norte-dev \
-o custom-columns='POD:.metadata.name,IMAGE:.spec.containers[0].image,NODE:.spec.nodeName'
# Sorting: the pods that have restarted most, first
kubectl get pods -A --sort-by=.status.containerStatuses[0].restartCount
# Sorting by age
kubectl get pods -n rutas-norte-dev --sort-by=.metadata.creationTimestampPOD IMAGE NODE
bookings-api-6c8d7f9b45-2xk9p registry.rutasnorte.example/bookings-api:2.4.0 rutas-norte
web-store-7d4f8c6b9-lq2mn registry.rutasnorte.example/web-store:1.8.0 rutas-nortecustom-columns and jsonpath are the two tools that make kubectl fit for quick audits: "give me every image in use in production", "tell me which pods have no memory limits".
- Label selection and live watching
Remember from the lesson Key Concepts and Terminology that labels are the system's coupling mechanism. The -l flag gives you access to that same mechanism from the CLI:
# Equality
kubectl get pods -l app=bookings-api -n rutas-norte-dev
# Several conditions (AND)
kubectl get pods -l app=bookings-api,environment=dev -n rutas-norte-dev
# Inequality
kubectl get pods -l 'environment!=pro' -A
# Sets
kubectl get pods -l 'app in (bookings-api,web-store)' -n rutas-norte-dev
kubectl get pods -l 'app notin (occupancy-reports)' -n rutas-norte-dev
# Existence of the key, with any value
kubectl get pods -l app.kubernetes.io/part-of -A
# The whole Rutas Norte platform, of any type, in one go
kubectl get all -l app.kubernetes.io/part-of=rutas-norte -AThat last query is the reason it is worth being disciplined about the project's labelling scheme: it lets you see, delete or inspect the entire platform with a single command.
Live watching with --watch (or -w): the command does not finish and prints changes as they happen. It is the best way to see the reconciliation loop in action:
NAME READY STATUS RESTARTS AGE
bookings-api-6c8d7f9b45-2xk9p 1/1 Running 0 12m
bookings-api-6c8d7f9b45-2xk9p 1/1 Terminating 0 14m
bookings-api-6c8d7f9b45-wq7rt 0/1 Pending 0 0s
bookings-api-6c8d7f9b45-wq7rt 0/1 ContainerCreating 0 1s
bookings-api-6c8d7f9b45-wq7rt 1/1 Running 0 4sYou recognise that sequence: it is exactly the walkthrough from the lesson Kubernetes Architecture —Pending while the scheduler decides, ContainerCreating while the kubelet works, Running when the container is alive— happening in front of your eyes because the ReplicaSet has replaced a deleted pod.
Sibling commands that also wait:
kubectl wait --for=condition=Ready pod -l app=bookings-api -n rutas-norte-dev --timeout=60s
kubectl get events -n rutas-norte-dev --watch
- Imperative versus declarative
kubectl supports both styles and it is worth having a view on when to use each.
| Aspect | Imperative | Declarative |
|---|---|---|
| Typical command | kubectl create deployment ..., kubectl scale, kubectl expose |
kubectl apply -f k8s/ |
| Source of truth | Your terminal history | The repository's files |
| Reproducible | No | Yes |
| Reviewable in a pull request | No | Yes |
| Speed for something one-off | Very high | Medium |
| Recommended use | Learning, quick tests, timed exams | Anything that reaches a real environment |
# Imperative: fast, but it leaves no trace in any file
kubectl create deployment bookings-api --image=registry.rutasnorte.example/bookings-api:2.4.0
kubectl scale deployment bookings-api --replicas=4
kubectl expose deployment bookings-api --port=80 --target-port=3000
# Declarative: the desired state lives in Git
kubectl apply -f k8s/base/bookings-api.yamlThe middle ground, and probably the most useful trick in the whole lesson: generate the manifest with an imperative command and save it, using --dry-run=client -o yaml.
kubectl create deployment bookings-api \
--image=registry.rutasnorte.example/bookings-api:2.4.0 \
--dry-run=client -o yaml > k8s/base/bookings-api.yamlThis creates nothing in the cluster: it only prints the YAML kubectl would have sent. You edit it, version it and apply it. It is the usual way to avoid writing manifests from scratch, and in the CKAD it is practically mandatory if you want to finish in time. The next lesson goes deeper into --dry-run, kubectl diff and the internal mechanics of apply.
- Productivity: aliases, completion, explain and plugins
Add this to your ~/.bashrc or ~/.zshrc. The difference in comfort is enormous:
# Completion (bash)
source <(kubectl completion bash)
# A short alias, with completion for the alias too
alias k=kubectl
complete -o default -F __start_kubectl k
# Common shortcuts
alias kgp='kubectl get pods'
alias kgpw='kubectl get pods -o wide'
alias kd='kubectl describe'
alias kl='kubectl logs'
alias kaf='kubectl apply -f'
alias kns='kubectl config set-context --current --namespace'For zsh, swap completion bash for completion zsh. With this, k get po -n <TAB> even completes the names of the existing namespaces for you, because completion queries the API.
Other tools worth knowing about, even though we are not using them yet:
| Tool | What it adds |
|---|---|
| krew | A plugin manager for kubectl (kubectl krew install ...) |
kubectl ctx / kubectl ns (the ctx and ns plugins) |
Switching context and namespace interactively |
kubectl tree |
Seeing the Deployment → ReplicaSet → Pod hierarchy |
kubectl neat |
Strips a -o yaml of system-generated fields |
stern |
Aggregated, colour-coded logs from many pods at once |
k9s |
A terminal interface for navigating the cluster |
Installing krew and a plugin, by way of example:
None of this is essential, but on a real working day it saves hours. What matters is the previous part: aliases, completion and kubectl explain.
Common Mistakes and Tips
- Working in the wrong context. The most expensive mistake of all. Before any destructive command,
kubectl config current-context. Configure your prompt to show context and namespace (kube-ps1, starship, oh-my-zsh) and treat it as non-negotiable as soon as you have access to a production environment. - Forgetting the namespace. If an object "does not exist", try it with
-Abefore concluding anything. Set the default namespace withkubectl config set-context --current --namespace=.... - Reading
logswithout--previousin aCrashLoopBackOff. You will see the current container starting up, not the error that killed the previous one. - Omitting the
--inkubectl exec. Without it, kubectl reads your command's flags as its own and fails confusingly. - Using
kubectl editas a deployment method. The change is not recorded anywhere and is lost on the nextapply. It is for investigating, not for operating. - Believing
kubectl delete podremoves the application. If there is a controller behind it, the pod comes back. You have to delete the Deployment, or better, the manifest withkubectl delete -f. - Ignoring
kubectl explain. It is exact documentation for your version, with no internet connection and without switching windows. Get into the habit of using it before searching the web. - Tip: memorise this diagnostic trio and always apply it in this order —
kubectl get(does it exist and in what state?),kubectl describe(what has the cluster tried and what do the events say?),kubectl logs(what does the application say?). It resolves the vast majority of incidents.
Exercises
Exercise 1: Context, namespace and exploration
On your rutas-norte cluster:
- Show the active context and check that it is the right one.
- Create the
rutas-norte-devnamespace and set it as the context's default namespace. - List every pod in the cluster, from every namespace, showing the node and the IP.
- Find out, without leaving the terminal and without searching the internet, what a pod's
spec.restartPolicyfield means and which values it accepts. - Show the
kube-systempods sorted by age, from oldest to most recent.
Exercise 2: Advanced audit queries
Rutas Norte's security team asks for an inventory. Write the commands that answer:
- Every image in use in the cluster, with the pod and the namespace it belongs to, in table format.
- The pods of the whole cluster sorted by restart count, to spot the unstable ones.
- Only the names of the pods carrying the label
app.kubernetes.io/part-of=rutas-norte, in a format suitable for chaining with another command. - Every resource in the cluster that does not live in a namespace.
Exercise 3: From imperative to declarative
Without creating anything in the cluster, generate the YAML manifest of a pod called web-store with the image registry.rutasnorte.example/web-store:1.8.0, save it to k8s/base/web-store-pod.yaml, and then explain what the difference is between running that command with --dry-run=client and without it. As an extra check, use kubectl to find out whether the Pod resource belongs to the core API group or to apps.
Solutions
Solution 1
# 1
kubectl config current-context # -> rutas-norte
# 2
kubectl create namespace rutas-norte-dev
kubectl config set-context --current --namespace=rutas-norte-dev
# 3
kubectl get pods -A -o wide
# 4
kubectl explain pod.spec.restartPolicyFIELD: restartPolicy <string>
DESCRIPTION:
Restart policy for all containers within the pod. One of Always, OnFailure,
Never. Default to Always.Solution 2
# 1
kubectl get pods -A -o custom-columns='NS:.metadata.namespace,POD:.metadata.name,IMAGE:.spec.containers[*].image'
# 2
kubectl get pods -A --sort-by=.status.containerStatuses[0].restartCount
# 3
kubectl get pods -A -l app.kubernetes.io/part-of=rutas-norte -o name
# 4
kubectl api-resources --namespaced=falsePoint 3 returns lines such as pod/bookings-api-6c8d7f9b45-2xk9p, which can be piped straight into kubectl delete or kubectl describe. Point 4 lists nodes, namespaces, persistentvolumes, storageclasses, clusterroles, among others: the cluster-scoped resources we saw in the concepts lesson.
Solution 3
kubectl run web-store \
--image=registry.rutasnorte.example/web-store:1.8.0 \
--dry-run=client -o yaml > k8s/base/web-store-pod.yamlThe difference: with --dry-run=client, kubectl builds the object locally and prints it, sending nothing to the server; no pod is created and the cluster does not even need to be running. Without that flag, the request is sent to the apiserver, goes through authentication, authorization and admission, is written to etcd and the pod is really created. There is also --dry-run=server, which does send the request but tells the server not to persist it: it validates against the real admission webhooks without creating anything. We will see it in the next lesson.
For the API group:
The APIVERSION column shows a plain v1, with no slash and no group prefix: that means Pod belongs to the core group (or "legacy"), unlike Deployment, which appears as apps/v1.
Conclusion
kubectl is an HTTP client with a very regular grammar: verb, type, name and flags. Mastering it comes down to internalising that grammar, always knowing which context and namespace you are working in, handling the get → describe → logs diagnostic trio fluently, and taking advantage of the output formats and label selection to turn the CLI into a genuine query tool. With kubectl explain you also have exact documentation for your own cluster without leaving the terminal, and with aliases and completion the daily work stops being typing.
In this lesson we have used apply without fully explaining what it does inside, and we have seen YAML manifests without breaking down their structure. The next lesson settles that debt, Objects, YAML Manifests and the Declarative Model: the field-by-field anatomy of an object, API groups and versions, the YAML you need to know, the real difference between apply, create and replace, the tools for validating beforehand and how to organise the Rutas Norte manifests in the k8s/ directory.
Kubernetes Course
Module 1: Introduction to Kubernetes
- What Is Kubernetes?
- Kubernetes Architecture
- Key Concepts and Terminology
- Setting Up a Kubernetes Cluster
- The Kubernetes CLI: kubectl
- Objects, YAML Manifests and the Declarative Model
- The Course Project: the Rutas Norte Platform
Module 2: Core Kubernetes Components
- Pods
- ReplicaSets
- Deployments
- Updates, Rollbacks and Deployment Strategies
- Services
- Namespaces
- Labels, Selectors and Annotations
Module 3: Configuration and Secret Management
- ConfigMaps
- Secrets
- Environment Variables
- Resource Quotas and Limits
- LimitRanges and Quality of Service (QoS) Classes
- ServiceAccounts and API Access from Pods
Module 4: Networking in Kubernetes
- Cluster Networking
- Service Types
- Internal DNS and Service Discovery
- Ingress Controllers
- TLS and Certificate Management with cert-manager
- Network Policies
Module 5: Storage in Kubernetes
- Volumes
- Persistent Volumes
- Persistent Volume Claims
- Storage Classes
- Dynamic Provisioning, Expansion and Snapshots
- Backup and Restore of Persistent Data
Module 6: Advanced Kubernetes Concepts
- StatefulSets
- DaemonSets
- Jobs and CronJobs
- Init Containers, Sidecars and Multi-Container Patterns
- Scheduling: Affinity, Taints and Tolerations
- Custom Resource Definitions (CRDs)
- Operators and the Controller Pattern
Module 7: Monitoring and Logging
- Health Checks and Probes
- Metrics Server and kubectl top
- Monitoring with Prometheus
- Visualization and Alerting with Grafana and Alertmanager
- Centralized Logging with Elasticsearch, Fluentd and Kibana (EFK)
- Application Debugging and Cluster Events
Module 8: Kubernetes Security
- Role-Based Access Control (RBAC)
- Security Contexts and Container Hardening
- Pod Security Policies and Pod Security Standards
- Network Security
- Image Security
- Auditing, Scanning and Vulnerability Management
Module 9: Scaling and Performance
- Horizontal Pod Autoscaling
- Vertical Pod Autoscaling
- Cluster Autoscaling
- Event-Driven and Custom-Metric Scaling with KEDA
- High Availability: PodDisruptionBudgets and Topology
- Performance Tuning
Module 10: Kubernetes Ecosystem and Tooling
- Minikube and Local Environments with kind
- Kubeadm
- Helm
- Kustomize
- GitOps with Argo CD and Flux
- Managed Kubernetes: EKS, AKS and GKE
Module 11: Case Studies and Real-World Applications
- Deploying a Web Application
- Running Stateful Applications
- CI/CD with Kubernetes
- Deployment Strategies: Blue-Green and Canary
- Multi-Cluster Management
- Production Operations: Incidents, Runbooks and Costs
