0% found this document useful (0 votes)
44 views239 pages

Kuber Net Es

Uploaded by

Lawrence Owusu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
44 views239 pages

Kuber Net Es

Uploaded by

Lawrence Owusu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 239

Index

Kubernetes is a Container Orchestration Platform


Pods as the Smallest Deployable Units in Kubernetes
Pods Can Contain Multiple Containers Sharing a Network
Namespace
Kubernetes Services Provide Stable Network Endpoints
Kubernetes Configuration Files Use YAML
Understanding Kubernetes Deployments
Understanding ReplicaSets in Kubernetes
Utilizing Namespaces for Organization in Kubernetes
Understanding Labels and Selectors for Kubernetes
Resource Management
Managing Configuration with ConfigMaps
Managing Sensitive Information with Kubernetes Secrets
Persistent Storage in Kubernetes with Volumes
Understanding Kubernetes Volume Types
Exploring DaemonSets in Kubernetes
Understanding Kubernetes Jobs for Batch Processing
Scheduled Tasks with Kubernetes CronJobs
Horizontal Pod Autoscaling in Kubernetes
Understanding Network Policies in Kubernetes
Managing External Access with Ingress
Central Management with the API Server
Understanding etcd: The Data Store for Kubernetes
The Role of the Controller Manager in Kubernetes
Understanding Kubernetes Scheduler and Pod Placement
Introduction to Kubernetes Nodes
Understanding Kubelet: The Node Agent in Kubernetes
Understanding Container Runtime in Kubernetes
Understanding Kube-proxy: Managing Network Rules for
Pods
ServiceAccounts: Identity for Pods in Kubernetes
Understanding RBAC in Kubernetes
Resource Quotas in Kubernetes
Setting Resource Limits with LimitRanges
Controlling Pod Placement with Affinity and Anti-Affinity
Rules
Controlling Pod Scheduling with Taints and Tolerations
Understanding Kubernetes Declarative API
Understanding Reconciliation Loops in Kubernetes
Imperative vs. Declarative Configuration in Kubernetes
Understanding kubectl: The Command-Line Tool for
Kubernetes
Declarative Configuration with kubectl apply
Understanding 'kubectl create' for Imperative Configuration
Retrieving Kubernetes Resources with 'kubectl get'
Detailed Resource Information with kubectl describe
Fetching Logs from Pods with kubectl logs
Executing Commands Inside a Kubernetes Pod
Forwarding Local Ports to a Kubernetes Pod
Scaling Deployments with kubectl scale
Removing Resources with kubectl delete
Helm: Kubernetes Package Management with Charts
Kustomize: Customizing Kubernetes YAML Without
Templates
Running Kubernetes Locally with Minikube
Lightweight Kubernetes with k3s
Running Kubernetes Clusters with Kind
Applying Kubernetes Configurations with kubectl
Deleting Kubernetes Resources Defined in a YAML File
Listing Pods in a Specific Namespace
Understanding Resource Usage with kubectl top
Editing Resources Directly with kubectl edit
Managing Rollouts and Rollbacks with kubectl rollout
Debugging with kubectl get events
Viewing Current Kubeconfig Settings with kubectl config
view
Switching Between Contexts with kubectl config set-context
Preparing a Node for Maintenance with kubectl drain
Marking a Node Unschedulable with kubectl cordon
Understanding kubectl taint: Controlling Pod Scheduling on
Nodes
Using kubectl label: Organizing Resources with Labels
Adding Annotations to Kubernetes Resources with kubectl
annotate
Starting a Local Proxy to the Kubernetes API Server with
kubectl proxy
Copying Files Between a Pod and the Local Filesystem Using
kubectl cp
Understanding Kubernetes Flat Networking Model
Understanding Pod Lifecycle Events in Kubernetes
Ensuring Pod Health with Liveness and Readiness Probes
Initialization Tasks with Init Containers in Kubernetes
Networking and Storage in Multi-container Pods
Kubernetes Supports OCI-Compliant Container Images
New Features in the Latest Kubernetes Stable Version
Difference Between StatefulSets and Deployments in
Kubernetes
Introduction to Network Plugins (CNI) in Kubernetes
Cluster Autoscaler: Dynamically Managing Node Count
Ingress Controllers: Essential for Managing Ingress
Resources
Understanding PodDisruptionBudgets in Kubernetes
The "API First" Approach in Kubernetes
Extending Kubernetes with CustomResourceDefinitions
(CRDs)
Managing Stateful Workloads with Kubernetes Operators
Bootstrapping Kubernetes Clusters with kubeadm
Understanding Resource Requests and Limits in Kubernetes
Kubernetes: Multi-Cloud and On-Premises Support
Managed Kubernetes Services: Simplifying Cluster
Management
Introduction to Istio: Managing Service-to-Service
Communication in Kubernetes
Understanding Metrics Server in Kubernetes for Resource
Monitoring
Monitoring Kubernetes Clusters with Prometheus
Visualizing Metrics with Grafana
Backing Up and Restoring Kubernetes Clusters with Velero
Running Security Checks on Kubernetes with Kube-bench
Understanding Kubernetes RBAC: Roles and Bindings
Kubernetes Auditing: Tracking Resource Access and
Modifications
Kubernetes Secrets Are Base64-Encoded, Not Encrypted
Dynamic Storage Provisioning in Kubernetes with
StorageClasses
Understanding ClusterIP, NodePort, and LoadBalancer in
Kubernetes
Advanced Networking with Service Mesh: Using Linkerd
Understanding Kubernetes Versioning and Upgrade
Importance
Kubernetes Controllers: The Heart of Cluster Management
Kubernetes Multi-Tenancy: Securely Sharing Clusters
Transition from Pod Security Policies to Pod Security
Admission
Introduction

Kubernetes has rapidly become an essential tool in modern


cloud-native application development and operations.
This book is designed for those who already have a solid
understanding of basic programming concepts but are new
to Kubernetes.
Here, you will find the critical knowledge you need to get
started with Kubernetes, focusing exclusively on the
essentials.Whether you're a beginner eager to learn
Kubernetes or a seasoned professional looking to refresh
your knowledge with the latest updates, this book provides
you with the concise information you need to efficiently
master Kubernetes.We encourage you to leave a review or
comment after reading.
Your feedback is invaluable in helping others on their
Kubernetes journey.Thank you for choosing this guide.
We hope it serves you well.
1
Kubernetes is a Container
Orchestration Platform
Kubernetes is not a programming language but a container
orchestration platform. It automates the deployment,
scaling, and management of containerized applications,
making it essential for handling complex applications in
production environments.

To understand Kubernetes better, let's start with a basic


command that helps you interact with a Kubernetes cluster.
This example demonstrates how to list all running Pods
within a specific namespace.
[Code]

kubectl get pods --namespace=default


[Result]

NAME READY STATUS RESTARTS AGE


example-pod-1 1/1 Running 0 5m
example-pod-2 1/1 Running 0 3m

Kubernetes manages applications by organizing them into


containers, which are grouped into Pods. A Pod typically
contains one or more containers that are logically related
and share the same network namespace, storage volumes,
and configurations. Kubernetes automates the process of
deploying these Pods across a cluster of machines, ensuring
high availability, scalability, and efficient resource
utilization.Understanding Kubernetes as an orchestration
tool is crucial because it handles the complexities of
managing containerized applications, including load
balancing, automatic scaling, and self-healing. Developers
don't need to manually manage the lifecycle of each
container; Kubernetes automates it based on the desired
state defined in configurations.

[Trivia]
Kubernetes was originally developed by Google, based on
their internal project called Borg. The name "Kubernetes"
comes from the Greek word for "helmsman" or "pilot,"
reflecting its role in guiding and managing containers.
2
Pods as the Smallest Deployable
Units in Kubernetes
In Kubernetes, Pods are the smallest deployable units. A Pod
encapsulates one or more containers, along with their
storage resources, a unique network IP, and options that
govern how the containers should run.

This example shows how to create a simple Pod


configuration using a YAML file. We'll then deploy this Pod to
a Kubernetes cluster and observe its status.
[Code]

apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: example-container
image: nginx:latest
ports:
- containerPort: 80
bash
kubectl apply -f example-pod.

[Result]

pod/example-pod created
A Pod in Kubernetes represents a single instance of a
running process in your cluster. It can run multiple
containers, but in most cases, a Pod runs a single container.
Pods are ephemeral; they can be deleted and recreated as
needed, often by Kubernetes controllers that manage the
desired state of your applications.When you deploy a Pod,
Kubernetes assigns it an IP address, which allows it to
communicate with other Pods in the cluster. Pods also have
associated storage volumes that persist data even when the
containers are restarted. The YAML configuration file defines
the Pod's specifications, including the container image to
use, ports to expose, and other settings.Understanding Pods
is foundational to working with Kubernetes, as they are the
basic units that Kubernetes manages. Higher-level objects
like Deployments, Services, and StatefulSets are built
around Pods to manage their lifecycle, scaling, and
networking.

[Trivia]
Pods in Kubernetes are designed to support a pattern called
"sidecar," where a secondary container runs alongside the
main application container to enhance its functionality. This
can include logging, monitoring, or proxy services.
3
Pods Can Contain Multiple
Containers Sharing a Network
Namespace
In Kubernetes, a Pod is the smallest deployable unit and can
contain one or more containers. These containers share the
same network namespace, which means they can
communicate with each other using localhost and share the
same IP address and port space.

The following example demonstrates how two containers


within the same Pod can communicate with each other
through localhost. We'll create a simple Pod definition with
two containers: one running an Nginx server and another
running a busybox container that will curl the Nginx server.
[Code]

apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod
spec:
containers:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
- name: busybox-container
image: busybox
command: ['sh', '-c', 'while true; do sleep 3600; done']

[Result]

Pod "multi-container-pod" created.To verify communication,


you can exec into the busybox container and curl the Nginx
server:kubectl exec -it multi-container-pod -c busybox-
container -- curl http://localhost
This command will return the default Nginx welcome page,
confirming that the containers share the same network
namespace.

In a Pod, all containers share the same network namespace,


which includes the same IP address and port space. This
allows containers in the same Pod to communicate with
each other directly via localhost without any additional
configuration. The implication is that these containers are
tightly coupled and are designed to work together, often
forming parts of a single application or service.The
containers in a Pod can also share storage volumes, which
allows them to share data easily. However, despite sharing
the network and storage, each container runs in its own
isolated environment and can have its own unique runtime
configuration.

[Trivia]
Pods are ephemeral, meaning they are not meant to be
durable entities. If a Pod dies, it won't be resurrected;
instead, a new Pod with a new network identity will be
created. This is why relying on Pod IPs for communication is
not recommended; instead, Kubernetes Services should be
used to provide stable network endpoints.
4
Kubernetes Services Provide
Stable Network Endpoints
A Kubernetes Service is an abstraction that defines a logical
set of Pods and a policy by which to access them. Services
provide a stable IP address and DNS name to connect to
Pods, ensuring that even if Pods are recreated or
rescheduled, the service's IP remains constant.

The following example shows how to create a Kubernetes


Service that exposes a Deployment of Nginx Pods. The
Service will provide a stable endpoint for accessing the
Nginx Pods, even if individual Pods are terminated and new
ones are created.
[Code]

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP

[Result]

Deployment "nginx-deployment" created.Service "nginx-


service" created.You can access the Nginx service using the
following command to get the Service’s Cluster IP:kubectl
get svc nginx-service
This command will return the service's IP address, which you
can use to access the Nginx Pods from within the cluster.

Kubernetes Services decouple the lifecycle of Pods from


their network endpoints. When a Service is created, it
assigns a stable IP address and DNS name that can be used
to access the Pods associated with the service. This ensures
that even if the Pods behind the service change, the
service's IP address and DNS name remain constant,
providing a reliable method for accessing applications.There
are different types of services in Kubernetes, such as
ClusterIP (the default), NodePort, and LoadBalancer. Each
type serves a different purpose, depending on the specific
networking needs of your application. In this example, we
used ClusterIP, which is only accessible from within the
cluster.

[Trivia]
Kubernetes uses label selectors to associate Pods with
Services. The Service selects Pods based on their labels,
meaning it can automatically direct traffic to all Pods that
match the specified labels. This dynamic association allows
for easy scaling and updating of applications, as new Pods
matching the labels will automatically be included in the
Service's endpoints.
5
Kubernetes Configuration Files
Use YAML
Kubernetes utilizes YAML (YAML Ain't Markup Language) for
its configuration files, which makes it accessible and easy to
read. Unlike proprietary languages, YAML is a human-
readable data serialization format that is widely used for
configuration files.

The following code snippet demonstrates a basic Kubernetes


deployment configuration written in YAML. This example
creates a simple Nginx deployment.
[Code]

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80

[Result]

When you apply this configuration using kubectl apply -f


nginx-deployment.yaml, Kubernetes will create a
deployment named nginx-deployment with 3 replicas of the
Nginx container running on port 80.

YAML files are structured in a way that emphasizes


readability. Each level of indentation represents a hierarchy,
making it easy to understand the relationships between
different components. In this example:
apiVersion specifies the version of the Kubernetes API to
use.
kind indicates the type of resource being created (in this
case, a Deployment).
metadata contains data that helps uniquely identify the
resource.
spec defines the desired state of the deployment, including
the number of replicas and the template for the Pods.
YAML is sensitive to indentation, so ensure that your spacing
is consistent. Each level should be indented with spaces, not
tabs.

[Trivia]
YAML is not only used in Kubernetes but is also popular in
other configuration management tools like Ansible and
Docker Compose. Its simplicity and readability make it a
preferred choice for developers and system administrators
alike. Additionally, YAML supports comments, which can be
added using the # symbol, allowing for better
documentation within the configuration files.
6
Understanding Kubernetes
Deployments
In Kubernetes, a Deployment is a resource that manages the
desired state of Pods. It ensures that the specified number
of Pods are running at all times, allowing for easy scaling
and updates.

The following code snippet shows how to create a


Deployment that manages Pods for a simple web
application.
[Code]

apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-deployment
spec:
replicas: 2
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: my-webapp:1.0
ports:
- containerPort: 8080

[Result]

When you apply this configuration using kubectl apply -f


webapp-deployment.yaml, Kubernetes will create a
deployment named webapp-deployment with 2 replicas of
the my-webapp container running on port 8080.

The Deployment resource in Kubernetes provides several


key benefits:
Scaling: You can easily scale the number of replicas up or
down by modifying the replicas field in the Deployment
configuration.
Rolling Updates: Deployments support rolling updates,
allowing you to update the application without downtime.
You can change the image version, and Kubernetes will
gradually replace the old Pods with new ones.
Self-Healing: If a Pod fails, the Deployment controller
automatically replaces it to maintain the desired state.
In the example provided:
The selector field is crucial as it defines how the
Deployment finds which Pods to manage. It matches Pods
with the label app: webapp.
The template section describes the Pods that will be
created, including their specifications.

[Trivia]
Kubernetes Deployments are a fundamental concept in
Kubernetes and are often used in conjunction with other
resources like Services and ConfigMaps. Understanding how
Deployments work is essential for managing applications
effectively in a Kubernetes environment. Additionally, the
kubectl rollout command can be used to manage the rollout
of updates to your Deployments, providing further control
over application deployment processes.
7
Understanding ReplicaSets in
Kubernetes
A ReplicaSet is a Kubernetes resource that ensures a
specified number of pod replicas are running at any given
time. It helps maintain the desired state of your application
by automatically replacing any pods that fail or are deleted.

The following example demonstrates how to create a


ReplicaSet that maintains three replicas of a simple Nginx
pod.
[Code]

apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80

[Result]

When you apply this configuration with kubectl apply -f


<filename>.yaml, you will see the following output
confirming the creation of the ReplicaSet:
replicaset.apps/nginx-replicaset created

A ReplicaSet works by using a selector to identify the pods it


should manage. In this example, the selector specifies that
it should manage pods with the label app: nginx. The
template section defines the pod configuration, including
the container image and ports. If any of the three pods
crash or are deleted, the ReplicaSet will automatically
create new ones to ensure that three are always running.

[Trivia]
ReplicaSets are often used indirectly through Deployments,
which provide additional features like rolling updates and
easy rollback.
The kubectl get rs command can be used to check the
status of ReplicaSets in your cluster.
Understanding how ReplicaSets work is crucial for managing
application availability and scaling in Kubernetes.
8
Utilizing Namespaces for
Organization in Kubernetes
Namespaces in Kubernetes provide a mechanism for
isolating resources within a single cluster. They allow you to
organize and manage your applications and services
effectively, especially in environments where multiple teams
or projects coexist.

The following example illustrates how to create a


namespace and deploy a pod within that namespace.
[Code]

apiVersion: v1
kind: Namespace
metadata:
name: dev-environment
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: dev-environment
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
[Result]

When you apply this configuration with kubectl apply -f


<filename>.yaml, you will see the following output
confirming the creation of the namespace and the pod:
namespace/dev-environment created
pod/nginx-pod created

In this example, we first create a namespace called dev-


environment. The subsequent pod definition specifies that it
should be created within this namespace. Namespaces are
particularly useful in multi-tenant environments, as they
help prevent resource conflicts and provide a way to apply
resource quotas and policies at the namespace level.

[Trivia]
Kubernetes comes with several default namespaces,
including default, kube-system, and kube-public.
You can switch between namespaces using the kubectl
config set-context --current --namespace=<namespace-
name> command.
Namespaces can also be used to enforce security policies,
as Role-Based Access Control (RBAC) can be applied at the
namespace level.
9
Understanding Labels and
Selectors for Kubernetes
Resource Management
Labels and selectors are fundamental concepts in
Kubernetes that help you organize and manage your
resources effectively. Labels are key-value pairs attached to
objects, while selectors are queries used to filter those
objects based on their labels.

The following code snippet demonstrates how to create a


pod with labels and how to use a selector to query those
pods.
[Code]

apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: my-app
env: production
spec:
containers:
- name: my-container
image: nginx
To list pods with a specific label, you can use the following
command:
kubectl get pods -l app=my-app
[Result]

NAME READY STATUS RESTARTS AGE


my-pod 1/1 Running 0 1m

In this example, we created a pod named my-pod with two


labels: app set to my-app and env set to production. Labels
are useful for grouping resources and can be used in
selectors to filter resources. The command kubectl get pods
-l app=my-app retrieves all pods that have the label app set
to my-app. This allows you to easily manage and query
resources based on their characteristics.

[Trivia]
Labels can be used for various purposes, such as versioning,
environment identification, or grouping related components.
You can combine multiple selectors using logical operators.
For example, kubectl get pods -l app=my-
app,env=production will list pods that match both labels.
Labels are not unique; multiple resources can have the
same label.
10
Managing Configuration with
ConfigMaps
ConfigMaps are a Kubernetes resource that allows you to
manage configuration data separately from your application
code. This separation makes your applications more flexible
and easier to manage.

The following example shows how to create a ConfigMap


and use it in a pod definition.
[Code]

apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
database-url:
"mysql://user:password@hostname:3306/dbname"
log-level: "debug"
---
apiVersion: v1
kind: Pod
metadata:
name: my-app-pod
spec:
containers:
- name: my-app-container
image: my-app-image
env:
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: my-config
key: database-url

[Result]

pod/my-app-pod created

In this example, we first create a ConfigMap named my-


config that contains configuration data, including a
database URL and a log level. Then, we define a pod named
my-app-pod that uses this ConfigMap to set an environment
variable DATABASE_URL. The valueFrom field allows the pod
to access the value stored in the ConfigMap. This approach
keeps your application code clean and allows you to change
configurations without modifying the code.

[Trivia]
ConfigMaps can store data in key-value pairs, and the data
can be referenced in various ways, such as environment
variables or command-line arguments.
You can update a ConfigMap without restarting the pods
that use it, although the pods will need to be configured to
reload the configuration dynamically.
ConfigMaps are particularly useful for separating
configuration from code in microservices architectures,
enhancing the maintainability and scalability of applications.
11
Managing Sensitive Information
with Kubernetes Secrets
Kubernetes Secrets are a way to store and manage sensitive
information such as passwords, OAuth tokens, and SSH
keys. By using Secrets, you can keep sensitive data
separate from your application code, enhancing security
and simplifying configuration management.

The following code snippet demonstrates how to create a


Secret in Kubernetes and then access it from a pod.
[Code]

# Create a Secret named 'my-secret' containing a username


and password
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
username: dXNlcm5hbWU= # base64 encoded
'username'
password: cGFzc3dvcmQ= # base64 encoded 'password'
To create the Secret, save the above YAML to a file named
secret.yaml and run:
kubectl apply -f secret.
To access the Secret in a pod, you can use the following
YAML configuration:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: my-image
env:
- name: USERNAME
valueFrom:
secretKeyRef:
name: my-secret
key: username
- name: PASSWORD
valueFrom:
secretKeyRef:
name: my-secret
key: password

[Result]

The Secret my-secret will be created successfully, and the


pod will start with the environment variables USERNAME
and PASSWORD populated from the Secret.

Kubernetes Secrets store data in base64-encoded format to


ensure it is not easily readable in plain text. This encoding
does not provide encryption; thus, it is crucial to use
additional security measures, such as enabling encryption at
rest in your Kubernetes cluster. Secrets can be used in
various ways, including environment variables, command-
line arguments, or mounted as files in a pod.

[Trivia]
Secrets are namespace-scoped, meaning they are only
accessible within the namespace they are created in.
By default, Secrets are stored unencrypted in etcd,
Kubernetes' backing store, so it is important to secure etcd
and consider using encryption features.
You can create Secrets from literal values or files, making it
easy to manage sensitive data.
12
Persistent Storage in Kubernetes
with Volumes
In Kubernetes, Volumes provide a way to manage persistent
storage for containers. Unlike ephemeral storage, which is
lost when a pod is terminated, Volumes allow data to persist
beyond the lifecycle of individual containers, enabling
stateful applications to function correctly.

The following code snippet shows how to define a Persistent


Volume (PV) and a Persistent Volume Claim (PVC) in
Kubernetes, which can then be used by a pod.
[Code]

# Define a Persistent Volume


apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /mnt/data # Path on the host where data will be
stored
# Define a Persistent Volume Claim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
To create the PV and PVC, save the above YAML to a file
named storage.yaml and run:
kubectl apply -f storage.
To use the PVC in a pod, you can define it as follows:
apiVersion: v1
kind: Pod
metadata:
name: my-stateful-pod
spec:
containers:
- name: my-stateful-container
image: my-image
volumeMounts:
- mountPath: /data
name: my-storage
volumes:
- name: my-storage
persistentVolumeClaim:
claimName: my-pvc

[Result]

The Persistent Volume my-pv and the Persistent Volume


Claim my-pvc will be created successfully, and the pod will
start with the specified volume mounted at /data.
Persistent Volumes (PVs) are a cluster resource that
represents a piece of storage in the cluster, while Persistent
Volume Claims (PVCs) are requests for those resources.
When a PVC is bound to a PV, it allows the pod to use that
storage. Kubernetes supports various types of storage
backends, including cloud storage solutions and local disks.
Understanding how to manage storage is essential for
deploying stateful applications like databases.

[Trivia]
The hostPath volume type is primarily used for development
and testing, as it ties the pod to a specific node.
Other volume types include NFS, AWS EBS, and GCE
Persistent Disks, which provide more robust solutions for
production environments.
It is essential to consider the access modes of volumes,
such as ReadWriteOnce, ReadOnlyMany, and
ReadWriteMany, as they dictate how many pods can access
the volume simultaneously.
13
Understanding Kubernetes
Volume Types
Kubernetes supports various types of volumes that allow
containers to store data persistently or temporarily. Key
volume types include hostPath, emptyDir, and
persistentVolumeClaim, each serving different use cases.

The following code snippet demonstrates how to define


these volume types in a Kubernetes Pod specification.
[Code]

apiVersion: v1
kind: Pod
metadata:
name: volume-example
spec:
containers:
- name: my-container
image: nginx
volumeMounts:
- mountPath: /data
name: my-empty-dir
- mountPath: /host-data
name: my-host-path
volumes:
- name: my-empty-dir
emptyDir: {}
- name: my-host-path
hostPath:
path: /tmp/host-data

[Result]

This YAML file defines a Pod named volume-example with


two volumes: my-empty-dir (an empty directory that lasts
for the Pod's lifetime) and my-host-path (a volume that
maps to a directory on the host's filesystem).

In this example, emptyDir creates a temporary storage


space that is deleted when the Pod is removed. It is useful
for scratch data that does not need to persist beyond the
Pod's lifecycle. On the other hand, hostPath allows the Pod
to access a specific path on the host machine, which can be
useful for sharing data between the host and the container.
However, using hostPath can lead to portability issues, as it
ties the Pod to a specific node.

[Trivia]
Volume Lifecycle: Volumes in Kubernetes have a lifecycle
independent of the containers that use them. This means
that data can persist even if the Pod is restarted.
Persistent Volumes: For long-term data storage, consider
using PersistentVolume and PersistentVolumeClaim, which
allow you to manage storage resources more effectively
across different environments.
14
Exploring DaemonSets in
Kubernetes
DaemonSets are a powerful Kubernetes resource that
ensures a specific Pod runs on all (or a subset of) nodes in a
cluster. This is particularly useful for services like logging or
monitoring agents that need to operate on every node.

The following code snippet illustrates how to create a


DaemonSet that deploys a simple logging agent on each
node.
[Code]

apiVersion: apps/v1
kind: DaemonSet
metadata:
name: logging-agent
spec:
selector:
matchLabels:
app: logging-agent
template:
metadata:
labels:
app: logging-agent
spec:
containers:
- name: log-agent
image: fluentd:latest
[Result]

This YAML file defines a DaemonSet named logging-agent,


which deploys the Fluentd container on every node in the
cluster.

In this example, the DaemonSet ensures that the log-agent


container runs on every node, allowing it to collect logs from
all applications running on those nodes. If a new node is
added to the cluster, Kubernetes automatically schedules a
log-agent Pod on that node. Conversely, if a node is
removed, the corresponding log-agent Pod is also
terminated.

[Trivia]
Use Cases: Common use cases for DaemonSets include log
collection, monitoring, and network proxying.
Node Selector: You can use node selectors or affinity rules
within a DaemonSet to control on which nodes the Pods
should run, allowing for greater flexibility and resource
management.
15
Understanding Kubernetes Jobs
for Batch Processing
Kubernetes Jobs are designed to manage batch processes,
allowing you to run tasks that need to complete
successfully. They ensure that a specified number of pods
successfully terminate, making them ideal for tasks that
require completion, such as data processing or backups.

The following code snippet demonstrates how to create a


simple Kubernetes Job that runs a basic task.
[Code]

apiVersion: batch/v1
kind: Job
metadata:
name: example-job
spec:
template:
spec:
containers:
- name: job-container
image: busybox
command: ["echo", "Hello, Kubernetes Jobs!"]
restartPolicy: Never
backoffLimit: 4

[Result]
Hello, Kubernetes Jobs!

In this example, we define a Job named example-job. The


Job runs a single container based on the busybox image,
executing the command echo "Hello, Kubernetes Jobs!". The
restartPolicy: Never ensures that the pod will not restart
once it completes its task. The backoffLimit: 4 specifies that
if the Job fails, Kubernetes will retry up to four times before
considering it failed.

[Trivia]
Jobs are particularly useful for tasks that are not continuous
and need to run to completion.
You can specify parallelism in Jobs to run multiple pods
simultaneously, which can speed up the processing of large
datasets.
Jobs can be monitored using kubectl get jobs to check their
status and completion.
16
Scheduled Tasks with Kubernetes
CronJobs
Kubernetes CronJobs allow you to run jobs on a scheduled
basis, similar to how the cron utility works in Linux. This is
useful for automating repetitive tasks like backups, report
generation, or system maintenance.

The following code snippet illustrates how to create a


CronJob that runs a task every minute.
[Code]

apiVersion: batch/v1
kind: CronJob
metadata:
name: example-cronjob
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: cronjob-container
image: busybox
command: ["echo", "Hello from Kubernetes
CronJob!"]
restartPolicy: Never
[Result]

Hello from Kubernetes CronJob!

In this example, the example-cronjob is scheduled to run


every minute, as indicated by the schedule: "*/1 * * * *" line.
The CronJob creates a Job that runs the busybox container
executing the command echo "Hello from Kubernetes
CronJob!". Just like with Jobs, the restartPolicy: Never
ensures that the pod does not restart after completion.

[Trivia]
CronJobs can be scheduled using standard cron syntax,
allowing for complex timing configurations.
You can specify concurrency policies to control how jobs are
managed if previous jobs are still running when a new one is
scheduled.
Monitoring CronJobs is similar to monitoring Jobs, and you
can use kubectl get cronjobs to view their schedules and
statuses.
17
Horizontal Pod Autoscaling in
Kubernetes
Horizontal Pod Autoscaling (HPA) is a feature in Kubernetes
that automatically adjusts the number of Pods in a
deployment based on observed CPU and memory usage.
This ensures that your application can handle varying loads
efficiently without manual intervention.

The following code demonstrates how to create an HPA


resource that scales the number of Pods based on CPU
utilization.
[Code]

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50

[Result]

This YAML configuration does not produce a direct output


when applied, but it creates an HPA resource that will
monitor the CPU usage of the Pods in the my-app
deployment. If the average CPU usage exceeds 50%, the
HPA will increase the number of Pods, up to a maximum of
10.

The HPA resource is defined in YAML format, specifying the


target deployment and the desired CPU utilization
percentage. The minReplicas and maxReplicas fields
determine the scaling limits. When CPU usage goes beyond
the defined threshold, Kubernetes will automatically create
more Pods to balance the load, and conversely, it will reduce
the number of Pods if the load decreases.

[Trivia]
HPA can also scale based on custom metrics, not just CPU
and memory.
The HPA controller continuously monitors the metrics and
adjusts the number of Pods every 30 seconds by default.
To use HPA effectively, ensure that metrics-server is
installed in your cluster, as it collects resource usage data.
18
Understanding Network Policies
in Kubernetes
Network Policies in Kubernetes are used to control the
communication between Pods. They define rules that specify
which Pods can communicate with each other and under
what conditions, enhancing the security of your
applications.

The following code illustrates how to create a Network Policy


that allows traffic only from specific Pods.
[Code]

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-specific-pods
spec:
podSelector:
matchLabels:
role: my-app
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
[Result]

Applying this YAML configuration will not produce a direct


output, but it will create a Network Policy that allows only
Pods with the label role: frontend to send traffic to Pods with
the label role: my-app.

The Network Policy is defined to apply to Pods with the label


role: my-app. The ingress section specifies that only Pods
with the label role: frontend are allowed to communicate
with these Pods. By default, all traffic is denied unless
explicitly allowed by a Network Policy, making it a powerful
tool for securing Pod communication.

[Trivia]
Network Policies are implemented by the container network
interface (CNI) plugin, so ensure that your CNI supports
them.
You can define multiple policies for different types of traffic
(Ingress and Egress).
Network Policies can be combined to create complex
communication patterns between Pods, allowing for fine-
grained control over network traffic.
19
Managing External Access with
Ingress
Ingress is a powerful Kubernetes resource that manages
external access to services, primarily through HTTP. It allows
you to define rules for routing external traffic to your
internal services based on the request's hostname or path.

The following example demonstrates how to create an


Ingress resource that routes traffic to different services
based on the URL path.
[Code]

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- host: example.com
http:
paths:
- path: /service1
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
- path: /service2
pathType: Prefix
backend:
service:
name: service2
port:
number: 80

[Result]

This YAML configuration does not produce a direct output


when applied, but it creates an Ingress resource that routes
requests to http://example.com/service1 to the service1
service and http://example.com/service2 to the service2
service.

The Ingress resource defines rules for routing HTTP(S) traffic


to different services based on the request's URL. In this
example:
The host field specifies the domain name for which the rules
apply.
The paths section lists the URL paths and the corresponding
backend services.
The pathType can be Prefix (matches all paths that start
with the specified path) or Exact (matches the path exactly).
To use Ingress, you also need an Ingress controller, which is
responsible for fulfilling the Ingress rules. Popular options
include NGINX Ingress Controller and Traefik.

[Trivia]
Ingress can also handle SSL termination, allowing you to
manage HTTPS traffic easily.
You can use annotations in the Ingress resource to
customize the behavior of the Ingress controller, such as
enabling rate limiting or configuring authentication.
20
Central Management with the
API Server
The API server is the core component of the Kubernetes
control plane. It serves as the central management entity
that exposes the Kubernetes API and handles all
communication between the various components of the
system.

The following command demonstrates how to interact with


the Kubernetes API server using kubectl to retrieve
information about the nodes in the cluster.
[Code]

kubectl get nodes


[Result]

NAME STATUS ROLES AGE VERSION


node1 Ready <none> 10d v1.24.0
node2 Ready <none> 10d v1.24.0

The command kubectl get nodes queries the Kubernetes API


server to retrieve the current status of all nodes in the
cluster. The output shows:
NAME: The name of each node.
STATUS: Indicates whether the node is ready to accept pods.
ROLES: The role of the node (e.g., master, worker).
AGE: How long the node has been part of the cluster.
VERSION: The version of Kubernetes running on the node.
The API server acts as the gateway for all REST commands
used to manage the cluster. It processes requests, validates
them, and updates the corresponding objects in etcd, the
key-value store used by Kubernetes for persistent storage.

[Trivia]
The API server is stateless, meaning it does not store any
data itself; it relies on etcd for persistence.
All Kubernetes components communicate with the API
server, making it a crucial part of the architecture.
You can extend the API server with custom resources and
controllers to manage your specific workloads.
21
Understanding etcd: The Data
Store for Kubernetes
etcd is a distributed key-value store that is used by
Kubernetes to store all of its cluster data, including
configuration details and the current state of the cluster.

The following example demonstrates how to interact with


etcd using the etcdctl command-line tool to retrieve the
cluster's configuration data.
[Code]

# Retrieve the current cluster state from etcd


etcdctl get / --prefix

[Result]

/kubernetes.io/cluster/my-cluster
/kubernetes.io/cluster/my-cluster=true
/pods/...

etcd is crucial for Kubernetes because it provides a reliable


way to store and retrieve configuration data. It operates in a
distributed manner, meaning that data is replicated across
multiple nodes to ensure high availability and fault
tolerance. When you run the etcdctl get / --prefix command,
you are querying etcd for all keys that start with '/', which
typically includes all the configuration data stored in the
cluster. This command is essential for understanding the
current state of the cluster and diagnosing issues.

[Trivia]
etcd is built on the Raft consensus algorithm, which ensures
that the data is consistent across all nodes.
The default data storage for Kubernetes, etcd, is often run
as a separate component in a Kubernetes cluster, but it can
also be managed externally.
etcd supports watch functionality, allowing clients to receive
notifications on changes to keys, which is useful for dynamic
configurations.
22
The Role of the Controller
Manager in Kubernetes
The Controller Manager in Kubernetes is responsible for
ensuring that the desired state of the cluster matches its
actual state by monitoring and managing various resources.

The following code snippet illustrates how to check the


status of a deployment, which is one of the resources
managed by the Controller Manager.
[Code]

# Check the status of a deployment named 'my-


deployment'
kubectl get deployment my-deployment

[Result]

NAME READY UP-TO-DATE AVAILABLE AGE


my-deployment 3/3 3 3 10m

The Controller Manager runs multiple controllers, each


responsible for a specific resource type, such as
deployments, replicasets, and nodes. When you execute the
kubectl get deployment my-deployment command, you are
querying the Kubernetes API server, which in turn
communicates with the Controller Manager. The output
shows the number of replicas that are ready, up-to-date,
and available, which helps you understand if your
deployment is functioning as intended. If the actual state
does not match the desired state (for example, if some pods
are not running), the Controller Manager will take action to
correct this discrepancy, such as starting new pods or
scaling down existing ones.

[Trivia]
The Controller Manager can run multiple instances for high
availability, but only one instance of each controller should
be active at a time to avoid conflicts.
Controllers use a loop to continuously monitor the state of
the cluster and make adjustments as needed, which is a
core principle of Kubernetes' reconciliation loop.
Common controllers include the Replication Controller,
Deployment Controller, and Node Controller, each serving a
unique purpose in managing the cluster's resources.
23
Understanding Kubernetes
Scheduler and Pod Placement
The Kubernetes Scheduler is a critical component that
determines where Pods should run within a cluster based on
resource availability and defined policies.

The following code snippet demonstrates how to view the


scheduling events of Pods in a Kubernetes cluster.
[Code]

kubectl get events --field-selector involvedObject.kind=Pod -


-sort-by='.metadata.creationTimestamp'
[Result]

LAST
SEEN TYPE REASON OBJECT MESSAGE
1m Normal Scheduled pod/my-
pod Successfully assigned default/my-pod to node-1
1m Normal Pulling pod/my-pod Pulling
image "nginx:latest"
1m Normal Pulled pod/my-
pod Successfully pulled image "nginx:latest"
1m Normal Created pod/my-pod Created
container my-container
1m Normal Started pod/my-pod Started
container my-container
The command above retrieves events related to Pods in the
Kubernetes cluster, specifically focusing on their scheduling.
The --field-selector flag filters events to only show those
involving Pods, while --sort-by organizes them by creation
timestamp. The output shows the sequence of events,
including when a Pod was scheduled to a node, when the
image was pulled, and when the container was started. This
helps in understanding how the Scheduler operates in
placing Pods based on available resources and policies.

[Trivia]
The Scheduler uses various algorithms to make placement
decisions, considering factors such as resource requests
(CPU and memory), node affinity/anti-affinity rules, taints
and tolerations, and custom scheduling policies.
Understanding these concepts is crucial for optimizing
resource utilization and application performance in a
Kubernetes environment.
24
Introduction to Kubernetes
Nodes
Nodes are the worker machines in a Kubernetes cluster
where Pods are deployed and run. They can be either
physical or virtual machines.

The following command lists all nodes in the Kubernetes


cluster along with their status and resource availability.
[Code]

kubectl get nodes -o wide


[Result]

NAME STATUS ROLES AGE VERSION INTERNAL-


IP EXTERNAL-IP OS-IMAGE KERNEL-
VERSION CONTAINER-RUNTIME
node-
1 Ready <none> 5d v1.23.0 192.168.1.1 <none>
Ubuntu 20.04 LTS 5.4.0-1042-azure docker://20.10.7
node-
2 Ready <none> 5d v1.23.0 192.168.1.2 <none>
Ubuntu 20.04 LTS 5.4.0-1042-azure docker://20.10.7

The kubectl get nodes -o wide command provides an


overview of all nodes in the cluster, displaying their status,
roles, age, Kubernetes version, internal and external IP
addresses, operating system image, kernel version, and
container runtime. The "Ready" status indicates that the
node is available to accept Pods. Understanding the
characteristics of nodes is essential for managing workloads
effectively and ensuring that applications have the
necessary resources to run optimally.

[Trivia]
Nodes can be categorized into two types: master nodes,
which manage the Kubernetes control plane, and worker
nodes, where the actual application workloads run. Each
node in a Kubernetes cluster runs a container runtime (like
Docker), a kubelet (which communicates with the
Kubernetes API server), and a kube-proxy (which manages
network routing). Knowing how to manage nodes and their
resources is fundamental for maintaining a healthy
Kubernetes environment.
25
Understanding Kubelet: The
Node Agent in Kubernetes
Kubelet is a crucial agent that runs on every node within a
Kubernetes cluster. Its primary responsibility is to ensure
that the containers in the pods are running as expected by
continuously monitoring the state of the node and
interacting with the container runtime.

The Kubelet agent communicates with the Kubernetes API


server to get the necessary pod specifications. It then
ensures the containers described in the pod specifications
are running and healthy. Below is an example of how
Kubelet interacts with the API server and the container
runtime to manage a pod on a node.
[Code]

# Simulate a Kubelet's interaction with the API server


kubectl get pods --all-namespaces -o wide
# Example output shows the status of all pods in the
cluster, which is similar to what the Kubelet processes

[Result]

NAMESPACE NAME READY STATUS


RESTARTS AGE IP NODE NOMINATED
NODE READINESS GATES
default example-
pod 1/1 Running 0 3m 192.168.1.
12 worker-node-1 <none> <none>

Kubelet continuously polls the container runtime on the


node to ensure that the containers specified in the pod
definition are running. If a container fails or stops
unexpectedly, the Kubelet can restart it based on the pod’s
restart policy. Kubelet is also responsible for reporting the
node’s health status and resource usage back to the
Kubernetes control plane, allowing Kubernetes to make
scheduling and scaling decisions.When you deploy an
application in Kubernetes, the Kubelet on each node ensures
that the containers for your application are running. It does
so by monitoring the pod's status and interacting with the
container runtime, such as Docker or containerd. Kubelet
only cares about the containers that are part of a
Kubernetes pod, and it won't manage any containers that
are started outside of Kubernetes.

[Trivia]
Kubelet uses a process called "node heartbeat" to regularly
report to the Kubernetes API server that the node is healthy
and functioning correctly. This heartbeat is sent every few
seconds. If the Kubernetes control plane does not receive a
heartbeat from a node for a certain period (default is 40
seconds), it marks the node as "NotReady," and any pods on
that node may be rescheduled to other nodes.
26
Understanding Container
Runtime in Kubernetes
The container runtime in Kubernetes, such as Docker or
containerd, is responsible for running the containers on a
node. It works closely with the Kubelet to ensure containers
are launched and maintained according to the pod
specifications provided by Kubernetes.

The container runtime is the underlying software that


actually runs the containers on a node. It receives
commands from the Kubelet to start, stop, and manage
containers. Here is an example demonstrating how to
interact with Docker (a popular container runtime) to
manage containers on a Kubernetes node.
[Code]

# Check the status of containers managed by Docker on a


node
docker ps -a
# Example output shows all containers running on the node,
including those managed by Kubernetes

[Result]

CONTAINER
ID IMAGE COMMAND CREATED STATU
S PORTS NAMES
d9b100f2d815 nginx:latest "nginx -g 'daemon of…" 5
minutes ago Up 5
minutes 80/tcp k8s_nginx_default_example-pod-
12345_67890
f1234567890b pause:3.2 "/pause" 5 minutes
ago Up 5 minutes
(Paused) k8s_POD_default_example-pod-
12345_67890

The container runtime is a critical component of the


Kubernetes architecture. Docker was historically the default
container runtime, but Kubernetes has shifted to using
containerd as a more lightweight and Kubernetes-focused
solution. The container runtime handles the low-level work
of pulling container images, starting containers, and
managing the container's lifecycle.The interaction between
Kubelet and the container runtime is seamless. Kubelet
sends commands to the container runtime to create, stop,
and monitor containers as defined in the pod specifications.
The container runtime then executes these commands,
ensuring that the containers are running as intended. If a
container crashes or stops unexpectedly, the runtime will
attempt to restart it according to the policies defined in the
pod's configuration.

[Trivia]
Kubernetes introduced the Container Runtime Interface
(CRI) to allow different container runtimes to be plugged
into Kubernetes. This makes Kubernetes flexible and allows
it to support various runtimes beyond Docker and
containerd, such as CRI-O. This modularity ensures
Kubernetes can evolve with new container technologies as
they emerge.
27
Understanding Kube-proxy:
Managing Network Rules for
Pods
Kube-proxy is a crucial component in Kubernetes that
manages network rules on nodes, enabling communication
between services and Pods. It ensures that network traffic is
routed correctly to the appropriate Pod based on defined
services.

The following code snippet demonstrates how to check the


status of Kube-proxy and view its configuration.
[Code]

kubectl get pods -n kube-system -l k8s-app=kube-proxy


[Result]

NAME READY STATUS RESTARTS AGE


kube-proxy-abc123 1/1 Running 0 10d
kube-proxy-def456 1/1 Running 0 10d

Kube-proxy operates in three different modes: userspace,


iptables, and IPVS. In userspace mode, it listens for requests
and forwards them to the appropriate Pod. Iptables mode
uses Linux's built-in packet filtering to manage traffic
directly, which is more efficient. IPVS provides advanced
load balancing capabilities. Understanding these modes
helps in optimizing network performance in Kubernetes
clusters.

[Trivia]
Kube-proxy is essential for service discovery in Kubernetes,
allowing Pods to communicate without needing to know the
specific IP addresses of other Pods.
It can be configured to operate in different modes based on
performance needs and cluster architecture.
Kube-proxy is typically deployed as a DaemonSet, ensuring
that there is one instance running on each node in the
cluster.
28
ServiceAccounts: Identity for
Pods in Kubernetes
ServiceAccounts in Kubernetes provide a way for processes
running in Pods to authenticate and interact with the
Kubernetes API. They are essential for managing
permissions and security within the cluster.

The following code snippet shows how to create a


ServiceAccount and bind it to a role.
[Code]

# Create a ServiceAccount
kubectl create serviceaccount my-service-account
# Bind the ServiceAccount to a role (e.g., view role)
kubectl create clusterrolebinding my-service-account-
binding --clusterrole=view --serviceaccount=default:my-
service-account

[Result]

serviceaccount/my-service-account created
clusterrolebinding.rbac.authorization.k8s.io/my-service-
account-binding created

ServiceAccounts are automatically created in the "default"


namespace unless specified otherwise. When a Pod is
created, it can be associated with a ServiceAccount, which
provides it with a token for authenticating API requests. This
token is mounted into the Pod at a specific path, allowing
applications to use it seamlessly. Understanding how to
manage ServiceAccounts and their permissions is crucial for
maintaining security and access control in Kubernetes
environments.

[Trivia]
Each ServiceAccount is associated with a set of permissions
defined by Role-Based Access Control (RBAC), allowing for
fine-grained access to resources.
By default, Kubernetes creates a ServiceAccount named
"default" in each namespace, which can be used if no other
ServiceAccount is specified.
ServiceAccounts can be used in conjunction with Kubernetes
Secrets to manage sensitive information securely.
29
Understanding RBAC in
Kubernetes
RBAC (Role-Based Access Control) is a method used in
Kubernetes to manage permissions within a cluster. It allows
administrators to define roles and assign them to users or
groups, controlling what actions they can perform on
resources.

The following code snippet demonstrates how to create a


role and a role binding in Kubernetes, which are essential
components of RBAC.
[Code]

# Define a role that allows reading pods in a specific


namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
# Bind the role to a user
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods-binding
namespace: default
subjects:
- kind: User
name: example-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io

[Result]

No output is generated directly from the YAML file, but


applying it will create the Role and RoleBinding in the
specified namespace.

In this example, we first define a Role named pod-reader


that grants permissions to read pods within the default
namespace. The rules section specifies the resources (pods)
and the allowed actions (get, list, watch). Next, we create a
RoleBinding named read-pods-binding that associates the
pod-reader role with a user named example-user. This
means that example-user can now perform the specified
actions on pods in the default namespace.
Understanding RBAC is crucial for maintaining security and
ensuring that users have only the permissions they need to
perform their tasks.

[Trivia]
RBAC is one of the key security features in Kubernetes,
allowing for fine-grained access control.
It is essential to regularly review roles and bindings to
ensure they align with the principle of least privilege.
RBAC can be used in conjunction with other authentication
methods, such as OpenID Connect or LDAP, for enhanced
security.
30
Resource Quotas in Kubernetes
Resource quotas are a way to limit the resource usage of a
namespace in Kubernetes. They help prevent a single team
or application from consuming all the resources in a cluster,
ensuring fair distribution among multiple users or
applications.

The following code snippet illustrates how to create a


resource quota that limits CPU and memory usage in a
namespace.
[Code]

# Define a resource quota for a namespace


apiVersion: v1
kind: ResourceQuota
metadata:
name: cpu-memory-quota
namespace: default
spec:
hard:
requests.cpu: "2"
requests.memory: "4Gi"
limits.cpu: "4"
limits.memory: "8Gi"

[Result]

No output is generated directly from the YAML file, but


applying it will create the ResourceQuota in the specified
namespace.

In this example, we define a ResourceQuota named cpu-


memory-quota in the default namespace. The hard section
specifies the maximum resource limits for CPU and memory.
Here, the quota allows a total of 2 CPU requests and 4 GiB
of memory requests, while limiting the maximum to 4 CPU
limits and 8 GiB of memory limits. This means that all pods
in the default namespace must share these resources,
preventing any single pod from consuming all available
resources.
Implementing resource quotas is an effective way to
manage resources in a multi-tenant environment, ensuring
that all applications have the resources they need to
function properly.

[Trivia]
Resource quotas can be applied to various resources,
including CPU, memory, persistent volume claims, and
more.
They help maintain cluster stability and performance,
especially in environments with multiple teams or
applications.
Resource quotas can be monitored using Kubernetes
metrics, allowing administrators to track resource usage and
adjust quotas as necessary.
31
Setting Resource Limits with
LimitRanges
LimitRanges in Kubernetes allow you to define minimum and
maximum resource usage for Pods or containers. This helps
ensure that your applications do not consume more
resources than intended, which is crucial for maintaining
cluster stability and performance.

The following code snippet demonstrates how to create a


LimitRange that sets minimum and maximum CPU and
memory limits for Pods in a specific namespace.
[Code]

apiVersion: v1
kind: LimitRange
metadata:
name: example-limit-range
namespace: my-namespace
spec:
limits:
- default:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "250m"
memory: "256Mi"
type: Container
[Result]

The LimitRange is created successfully, and if you check the


resources for Pods in the my-namespace, they will reflect
the defined limits.

In this example, the default field specifies the maximum


resource limits for containers, meaning no container can use
more than 500 milliCPU and 512 MiB of memory. The
defaultRequest field indicates the minimum resources that
will be allocated to each container, which helps the
Kubernetes scheduler make better decisions about where to
place Pods based on available resources. If a Pod does not
specify its own resource requests or limits, the defaults will
be applied.

[Trivia]
Resource Requests and Limits: Requests are the minimum
resources required for a Pod to run, while limits are the
maximum resources it can consume. This distinction helps
Kubernetes manage resources efficiently.
Impact on Scheduling: If a Pod exceeds its limit, it may be
throttled or terminated, affecting application performance.
Conversely, if it does not meet its request, it may not be
scheduled if there are insufficient resources available.
Best Practices: Always define resource requests and limits to
avoid resource contention and ensure fair distribution of
resources among applications.
32
Controlling Pod Placement with
Affinity and Anti-Affinity Rules
Affinity and Anti-Affinity rules in Kubernetes are used to
control how Pods are placed on nodes within a cluster. These
rules help ensure that Pods are scheduled in a way that
meets specific requirements, such as co-locating related
services or spreading workloads across different nodes.

The following code snippet illustrates how to set up Affinity


rules to ensure that certain Pods are scheduled on the same
node, while Anti-Affinity rules prevent Pods from being
placed on the same node.
[Code]

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- my-app
topologyKey: "kubernetes.io/hostname"
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- my-app
topologyKey: "kubernetes.io/hostname"
containers:
- name: my-container
image: my-image

[Result]

The Deployment is created successfully, and Pods will be


scheduled according to the defined Affinity and Anti-Affinity
rules.

In this example, the podAffinity rule specifies that Pods with


the label app: my-app should be scheduled on the same
node (topologyKey: kubernetes.io/hostname). This is useful
for applications that require low latency communication.
Conversely, the podAntiAffinity rule ensures that Pods with
the same label are not placed on the same node, which can
enhance fault tolerance by spreading replicas across
different nodes.

[Trivia]
Topology Keys: The topologyKey defines how the rules are
applied based on the node labels. Common keys include
kubernetes.io/hostname for node-level rules and failure-
domain.beta.kubernetes.io/zone for zone-level rules.
Impact on Scheduling: Affinity and Anti-Affinity rules can
make scheduling more complex and may lead to
unschedulable Pods if the cluster does not have enough
resources or suitable nodes.
Best Practices: Use Affinity and Anti-Affinity rules judiciously
to avoid over-constraining the scheduler, which can lead to
resource wastage or scheduling failures.
33
Controlling Pod Scheduling with
Taints and Tolerations
In Kubernetes, taints and tolerations are mechanisms used
to control which nodes can or cannot accept specific Pods.
This ensures that Pods are only scheduled on nodes that
meet certain conditions.

To prevent certain Pods from being scheduled on specific


nodes, you can apply a taint to those nodes. Tolerations can
then be added to Pods to allow them to be scheduled on
nodes with matching taints.
[Code]

# Taint a node
kubectl taint nodes <node-name> key=value:NoSchedule
# Define a Pod with a toleration
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
[Result]

node/<node-name> tainted
pod/my-pod created

Taints and tolerations work together to influence scheduling


decisions in Kubernetes. When you taint a node with a key,
value, and effect (like NoSchedule), you are essentially
telling the Kubernetes scheduler that no Pod should be
placed on this node unless the Pod has a matching
toleration. The toleration in a Pod’s spec allows the Pod to
"tolerate" the node's taint and be scheduled on it.The key
components are:Key: Identifies the taint.Value: An optional
string associated with the key.Effect: Defines what happens
if a Pod does not tolerate the taint (e.g., NoSchedule,
PreferNoSchedule, NoExecute).Taints and tolerations are
essential for managing workloads in heterogeneous clusters,
ensuring that sensitive workloads are isolated or that
specific hardware resources are only used by particular
applications.

[Trivia]
Taints and tolerations do not guarantee exclusive access to
nodes. For stricter control, consider using Node Affinity or
Node Selectors in combination with taints and tolerations.
34
Understanding Kubernetes
Declarative API
The Kubernetes API is declarative, meaning that you define
the desired state of your resources, and Kubernetes works
to maintain that state.

When you create or modify a resource in Kubernetes, you do


not directly control what the system does at every step.
Instead, you declare what you want, and Kubernetes
ensures that the current state matches your desired state.
[Code]

# Define a Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80

[Result]

deployment.apps/nginx-deployment created

In the declarative model, you describe the desired state of


the system using YAML or JSON files. For example, when you
define a Deployment, you specify how many replicas of a
Pod should be running. Kubernetes continuously monitors
the cluster and adjusts resources to match the declared
state. If a Pod fails or a node becomes unreachable,
Kubernetes will automatically create new Pods to maintain
the desired replica count.The declarative nature of the API
allows for version control and easy rollback. It also simplifies
the management of complex systems by allowing users to
focus on "what" rather than "how." Kubernetes’ controllers
handle the "how," ensuring that the system's actual state
aligns with the desired state.

[Trivia]
The opposite of the declarative approach is the imperative
approach, where each action must be explicitly defined.
Kubernetes supports both methods, but the declarative
approach is preferred for its scalability, maintainability, and
ability to handle complex scenarios.
35
Understanding Reconciliation
Loops in Kubernetes
Kubernetes uses reconciliation loops to continuously ensure
that the current state of the system matches the desired
state defined by the user. This mechanism is fundamental to
Kubernetes' operation, allowing it to maintain the desired
configuration and automatically correct any discrepancies.

The following code demonstrates how a simple Deployment


is defined in Kubernetes, which Kubernetes will manage
through its reconciliation loops.
[Code]

apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deployment
spec:
replicas: 3
selector:
matchLabels:
app: example
template:
metadata:
labels:
app: example
spec:
containers:
- name: example-container
image: nginx:latest

[Result]

When you apply this Deployment configuration using the


command kubectl apply -f deployment.yaml, Kubernetes will
create and maintain 3 replicas of the nginx container as
specified.

In this example, the Deployment object defines the desired


state of the application. Kubernetes continuously monitors
the actual state of the application (the number of running
pods, for instance) and compares it to the desired state (3
replicas). If any pod fails or is deleted, Kubernetes will
automatically create a new pod to ensure that the desired
number of replicas is maintained. This process is known as
reconciliation.
The reconciliation loop runs continuously, checking the state
of the system against the desired state and making
adjustments as necessary. This is a powerful feature of
Kubernetes that helps ensure high availability and reliability
of applications.

[Trivia]
The reconciliation loop is a key concept in Kubernetes that is
not only limited to Deployments but is also used in other
resources like StatefulSets, DaemonSets, and more.
The controller manager in Kubernetes is responsible for
managing these reconciliation loops, ensuring that the
desired state is achieved and maintained.
Understanding reconciliation is crucial for troubleshooting
and optimizing Kubernetes applications, as it helps you
grasp how Kubernetes reacts to changes and failures.
36
Imperative vs. Declarative
Configuration in Kubernetes
Kubernetes supports two main styles of configuration:
imperative and declarative. Understanding the difference
between these two approaches is essential for effectively
managing Kubernetes resources.

The following example illustrates both imperative and


declarative methods for creating a Pod in Kubernetes.
[Code]

Imperative command to create a Pod


kubectl run example-pod --image=nginx:latest --
restart=Never
Declarative configuration using a YAML file
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: example-container
image: nginx:latest

[Result]

Imperative: Running the command kubectl run example-pod


--image=nginx:latest --restart=Never will create a Pod
named example-pod immediately.
Declarative: Applying the YAML file with kubectl apply -f
pod.yaml will also create the same Pod.

In the imperative approach, commands are executed


directly to create or modify resources. This method is
straightforward and can be useful for quick tasks or one-off
operations. However, it can become cumbersome for
managing complex applications or multiple resources.
On the other hand, the declarative approach involves
defining the desired state of the resources in configuration
files (like YAML). When this configuration is applied,
Kubernetes takes care of creating and maintaining the
resources to match the specified state. This method is more
manageable for larger applications and allows for version
control and easier collaboration.
The declarative style is generally preferred in production
environments, as it provides a clear and consistent way to
manage resources and track changes over time.

[Trivia]
The declarative approach aligns well with GitOps practices,
where configurations are stored in Git repositories, allowing
for easier rollbacks and audits.
While the imperative approach can be quicker for simple
tasks, it lacks the reproducibility and scalability benefits of
the declarative method.
Kubernetes' kubectl command-line tool supports both
approaches, giving users flexibility based on their needs and
workflows.
37
Understanding kubectl: The
Command-Line Tool for
Kubernetes
kubectl is the command-line tool used to interact with
Kubernetes clusters. It allows users to manage and control
Kubernetes resources, such as deploying applications,
inspecting cluster resources, and troubleshooting issues.
Mastering kubectl is essential for anyone working with
Kubernetes.

The following example demonstrates a basic use of kubectl


to list all pods running in the default namespace of a
Kubernetes cluster. This command is a fundamental
operation for managing resources in a Kubernetes cluster.
[Code]

kubectl get pods


[Result]

NAME READY STATUS RESTARTS AG


E
my-app-5d8bd7f74d-
abcde 1/1 Running 0 10m
another-app-5f7g8h9jkl-
xyz 1/1 Running 0 15m
kubectl get pods is a basic yet powerful command in
Kubernetes. It retrieves and displays information about all
pods in the specified namespace (default is the default
namespace). Each pod represents one or more containers
that are running in the cluster.NAME: The name of the
pod.READY: Shows the number of containers that are
running and ready in the pod.STATUS: Displays the current
status of the pod (e.g., Running, Pending, Failed).RESTARTS:
Indicates how many times the containers within the pod
have been restarted.AGE: The amount of time since the pod
was created.Understanding these fields is crucial for
troubleshooting and managing the state of your Kubernetes
cluster.

[Trivia]
kubectl is a versatile tool, with a wide range of commands
available. Some of the most commonly used commands
include kubectl describe (to get detailed information about a
resource), kubectl logs (to fetch logs from a pod), and
kubectl exec (to execute commands inside a container).It's
important to note that kubectl communicates with the
Kubernetes API server to perform these actions, making it a
direct interface to the cluster's state and configuration.
38
Declarative Configuration with
kubectl apply
kubectl apply is used to manage Kubernetes resources using
declarative configuration files. Instead of manually creating
and updating resources, you define the desired state in a
YAML file, and kubectl apply ensures that the cluster
matches this state.

Below is an example of a simple YAML configuration file for a


deployment, and how to use kubectl apply to create and
manage this deployment in the Kubernetes cluster.
[Code]

# deployment.apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: nginx:1.19.10
ports:
- containerPort: 80
bash
kubectl apply -f deployment.

[Result]

deployment.apps/my-deployment created

When you use kubectl apply, you are operating in a


declarative mode. This means you define the desired state
of your application in a YAML file, and Kubernetes
continuously works to ensure that the cluster reflects this
state.In the provided example:apiVersion: Specifies the API
version of the Kubernetes resource.kind: Indicates the type
of resource (in this case, a Deployment).metadata: Contains
the name of the deployment.spec: Defines the desired state
of the deployment, including the number of replicas (3), the
selector labels for identifying pods, and the pod template
that describes how the pod should be created (including the
container image and port).After applying the file with
kubectl apply -f deployment.yaml, Kubernetes creates a
Deployment with three replicas of the specified container,
ensuring that your application is running as intended.

[Trivia]
One key advantage of declarative configuration with kubectl
apply is its idempotency. This means you can apply the
same configuration file multiple times without changing the
result. Kubernetes will only make the necessary changes to
align the current state of the cluster with the desired state
defined in the YAML file.Moreover, kubectl apply allows for
easier version control and collaboration, as the configuration
files can be stored in a version control system like Git,
enabling teams to manage and review changes to the
cluster configuration systematically.
39
Understanding 'kubectl create'
for Imperative Configuration
The kubectl create command is used for creating
Kubernetes resources in an imperative manner. This means
that the command directly tells Kubernetes what to do,
without needing a predefined configuration file.

Below is an example of how to use kubectl create to create


a new deployment in Kubernetes. This approach is useful
when you want to quickly set up a resource without creating
a YAML file first.
[Code]

kubectl create deployment nginx-deployment --


image=nginx
[Result]

The command will return:deployment.apps/nginx-


deployment created

The kubectl create command is part of Kubernetes'


imperative approach, allowing you to interact directly with
the Kubernetes API server to create resources like pods,
deployments, services, etc. In this example, nginx-
deployment is the name of the deployment being created,
and --image=nginx specifies the container image to use for
the deployment. Imperative commands are quick and useful
for simple or ad-hoc tasks, but they can become
unmanageable for complex setups, where declarative
configurations (using YAML files) are preferred.Important
Note: Imperative commands are generally not saved as part
of your source code, meaning they aren't version-controlled
or easily reproducible like declarative YAML configurations.
This makes them ideal for temporary or non-critical tasks.

[Trivia]
The kubectl create command can create various resources,
including deployments, services, namespaces, and more.
Each resource has its own set of parameters and flags that
can be used to customize its creation. This is particularly
powerful for developers and operators who need to interact
with Kubernetes clusters in a fast and flexible way.
40
Retrieving Kubernetes Resources
with 'kubectl get'
The kubectl get command is used to retrieve information
about Kubernetes resources such as pods, services,
deployments, and more. It provides a quick overview of the
status and configuration of these resources.

Here’s an example of using kubectl get to list all the pods in


the default namespace. This command is essential for
monitoring and managing the resources within your
Kubernetes cluster.
[Code]

kubectl get pods


[Result]

The command will return something


like:NAME READY STATUS RESTARTS AGE
nginx-deployment-5c688d7b99-
7sl5g 1/1 Running 0 10m

The kubectl get command is a fundamental tool for


interacting with Kubernetes resources. It allows you to see
the current state of resources, their configurations, and their
status in real-time. The output can be customized with
various flags, such as -o wide for more detailed information
or -o yaml for the output in YAML format. Understanding the
kubectl get command is crucial for monitoring and
troubleshooting in Kubernetes.Key Options:-o yaml: Outputs
the resource information in YAML format.-o json: Outputs the
resource information in JSON format.-w or --watch:
Continuously watch the resource for changes.

[Trivia]
kubectl get can retrieve a wide range of resources beyond
just pods, including nodes, services, deployments,
namespaces, and more. The versatility of this command
makes it a cornerstone of Kubernetes management, often
used in scripts and automation tools to check the status of
resources before proceeding with further actions.
41
Detailed Resource Information
with kubectl describe
kubectl describe is a command used in Kubernetes to
provide detailed information about various resources in your
cluster, such as Pods, Services, Deployments, and more.
This command is essential for understanding the current
state of your resources and diagnosing issues.

The following code example demonstrates how to use


kubectl describe to get detailed information about a specific
Pod.
[Code]

kubectl describe pod my-pod


[Result]

Name: my-pod
Namespace: default
Priority: 0
Node: node-1/192.168.1.1
Start Time: Mon, 20 Aug 2024 10:00:00 +0900
Labels: app=my-app
Annotations: <none>
Status: Running
IP: 10.244.0.1
Containers:
my-container:
Container ID: docker://abcdef123456
Image: my-image:latest
Image ID: docker-pullable://my-
image@sha256:abcdef...
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Mon, 20 Aug 2024 10:01:00 +0900
Ready: True
Restart Count: 0
Environment:
MY_ENV_VAR: my-value
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from
default-token-abcde (ro)
Conditions:
Type Status
Initialized True
Ready True
PodScheduled True
Volumes:
default-token-abcde:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-abcde
Optional: false

The output from kubectl describe pod my-pod provides a


comprehensive overview of the Pod's status, including its
name, namespace, node assignment, container details, and
any conditions affecting its operation. Each section gives
insights into the Pod's environment, such as the container's
state (Running, Terminated, etc.), the number of restarts,
and the volumes it uses. This information is crucial for
troubleshooting and ensuring that your applications are
running as expected.
[Trivia]
kubectl describe can be used with various resource types,
including Pods, Services, Deployments, Nodes, and more.
The command outputs not only the current state but also
events related to the resource, which can help identify
issues like failed scheduling or unsuccessful container
starts.
You can filter the output further using flags like --namespace
to specify a different namespace or --show-events to include
events in the output.
42
Fetching Logs from Pods with
kubectl logs
kubectl logs is a command that retrieves logs from a specific
Pod's container, which is invaluable for debugging
applications running in Kubernetes. This command allows
developers to see the output of their applications and
diagnose issues based on log messages.

The following example demonstrates how to use kubectl


logs to fetch logs from a specific container within a Pod.
[Code]

kubectl logs my-pod -c my-container


[Result]

2024-08-20 10:01:00 INFO Starting application...


2024-08-20 10:01:05 INFO Application is running.
2024-08-20 10:01:10 ERROR Failed to connect to the
database.
2024-08-20 10:01:15 INFO Retrying connection...

The output from kubectl logs my-pod -c my-container


displays the log messages generated by the specified
container within the Pod. This includes timestamps, log
levels (INFO, ERROR, etc.), and the actual log messages.
Analyzing these logs helps developers identify errors or
unexpected behavior in their applications. The logs can be
filtered or tailored further using options like --previous to
view logs from a previous instance of a container that
crashed.

[Trivia]
The -c flag specifies the container name when a Pod has
multiple containers. If the Pod has only one container, this
flag can be omitted.
Logs are stored in the container's stdout and stderr streams,
making it easy to capture application output.
You can also use the --follow flag with kubectl logs to stream
logs in real-time, which is particularly useful for monitoring
live applications.
43
Executing Commands Inside a
Kubernetes Pod
kubectl exec allows you to run commands directly inside a
container that is part of a Kubernetes Pod. This is
particularly useful for debugging and managing applications
running in your Pods.

The following example demonstrates how to use kubectl


exec to execute a command inside a specific container of a
Pod.
[Code]

# Execute the 'ls' command inside the 'my-container' of


'my-pod'
kubectl exec my-pod -c my-container -- ls /app

[Result]

file1.txt
file2.txt
directory1

When you run the above command, kubectl connects to the


Kubernetes API server and sends a request to execute the ls
/app command in the specified container (my-container) of
the Pod (my-pod). The -- indicates the end of command
options, allowing you to pass the command you want to
execute. The output shows the contents of the /app
directory inside the container.
This command is especially useful for checking the state of
files, verifying configurations, or debugging issues within
the container. You can replace ls /app with any command
you wish to run, such as cat, curl, or any application-specific
command.

[Trivia]
kubectl exec can also be used to start an interactive shell
session inside the container. For example, using kubectl
exec -it my-pod -c my-container -- /bin/bash allows you to
interact with the container as if you were logged into it
directly.
You can execute commands in all containers of a Pod by
omitting the -c option, but specifying the container is a good
practice to avoid ambiguity.
44
Forwarding Local Ports to a
Kubernetes Pod
kubectl port-forward is a command that allows you to
forward one or more local ports to a Pod, making it easier to
test and debug applications that are running inside
Kubernetes.

The following example illustrates how to use kubectl port-


forward to forward a local port to a Pod.
[Code]

# Forward local port 8080 to port 80 of 'my-pod'


kubectl port-forward my-pod 8080:80

[Result]

Forwarding from 127.0.0.1:8080 -> 80

When you execute this command, kubectl sets up a tunnel


between your local machine and the specified Pod (my-pod).
The command forwards traffic from your local port 8080 to
port 80 of the Pod. This is useful for accessing web
applications running inside your Pods without exposing
them via a Service.
For instance, if you have a web server running in your Pod
that listens on port 80, you can access it in your web
browser by navigating to http://localhost:8080. This
command will keep running in the terminal, and you can
stop it by pressing Ctrl+C.
This method is particularly useful for development and
testing, as it allows you to interact with your applications in
a controlled manner without modifying the cluster's
networking configuration.

[Trivia]
kubectl port-forward can also be used with Services,
allowing you to forward traffic to a Service instead of a
specific Pod. For example, kubectl port-forward service/my-
service 8080:80 would forward local port 8080 to port 80 of
the service.
This command is great for debugging issues with services
that are not exposed externally, as it allows you to interact
with them directly from your local machine.
45
Scaling Deployments with
kubectl scale
The kubectl scale command is used to adjust the number of
replicas in a Kubernetes Deployment or ReplicaSet. This
allows you to easily manage the number of pod instances
running in your cluster.

Below is an example of how to use the kubectl scale


command to change the number of replicas in a
Deployment.
[Code]

# Scale the deployment named 'my-deployment' to 5


replicas
kubectl scale deployment my-deployment --replicas=5

[Result]

deployment.apps/my-deployment scaled

When you execute the kubectl scale command, Kubernetes


updates the desired state of the Deployment to match the
specified number of replicas. In this case, if there were
fewer than 5 pods running, Kubernetes will create new pods
to reach the desired count. Conversely, if there were more
than 5 pods, Kubernetes will terminate the excess pods. This
command is essential for managing load and ensuring your
application can handle varying amounts of traffic.
[Trivia]
Replicas: A replica is a copy of a pod. The main purpose of
replicas is to ensure that a specified number of identical
pods are running at any given time.
Deployment: A Deployment provides declarative updates to
applications. You can define the desired state in a
Deployment and Kubernetes will manage the actual state to
match your desired state.
Scaling: Scaling can be done manually using kubectl scale,
or automatically using Horizontal Pod Autoscaler (HPA),
which adjusts the number of replicas based on CPU
utilization or other select metrics.
46
Removing Resources with
kubectl delete
The kubectl delete command is used to remove resources
from your Kubernetes cluster, such as Deployments, Pods,
Services, and more. This command is crucial for managing
the lifecycle of your applications.

Here is an example of how to use the kubectl delete


command to remove a Deployment from your cluster.
[Code]

# Delete the deployment named 'my-deployment'


kubectl delete deployment my-deployment

[Result]

deployment.apps "my-deployment" deleted

When you run the kubectl delete command, Kubernetes will


remove the specified resource from the cluster. In this
example, the Deployment named my-deployment is
deleted, which in turn causes all associated pods to be
terminated. This is a critical operation, as it permanently
removes the resource and any associated state. Be cautious
when using this command, especially in production
environments, as it can lead to downtime for your
application.
[Trivia]
Resource Types: You can delete various types of resources,
including Pods, Services, ConfigMaps, and more, using the
kubectl delete command.
Graceful Deletion: By default, Kubernetes will attempt to
gracefully terminate the pods associated with the resource
before deletion. You can specify a --grace-period to control
how long Kubernetes waits before forcibly terminating the
pods.
Dry Run: You can use the --dry-run flag with kubectl delete
to simulate the deletion without actually removing the
resource, which is useful for testing commands before
executing them.
47
Helm: Kubernetes Package
Management with Charts
Helm is a package manager designed for Kubernetes,
enabling users to manage pre-configured Kubernetes
resources known as Charts. Charts are collections of YAML
files that describe a related set of Kubernetes resources.

Here’s an example of how Helm can be used to deploy a


simple NGINX server using a Helm Chart.
[Code]

# Add the official Helm stable repository


helm repo add stable https://charts.helm.sh/stable
# Update your Helm repositories
helm repo update
# Search for the nginx Chart in the stable repository
helm search repo nginx
# Install the nginx Chart
helm install my-nginx stable/nginx
# Check the deployment
kubectl get pods

[Result]

NAME: my-nginx
LAST DEPLOYED: Tue Aug 20 15:32:15 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NAME READY STATUS RESTARTS AGE
my-nginx-6dff6c64ff-8f7h7 1/1 Running 0 1m

Helm simplifies Kubernetes application deployment by


packaging multiple Kubernetes resources into a single unit,
known as a Chart. Each Chart is a collection of files that
describe a set of related Kubernetes resources. When you
deploy a Chart using the helm install command, Helm sends
all the Kubernetes resources described in the Chart to the
Kubernetes cluster in one go.Helm Charts are versioned,
making it easy to manage application versions and
rollbacks. This versioning also ensures that you can deploy
the same application configuration across different
environments without having to manage Kubernetes YAML
files manually.Helm also provides features like template
rendering, allowing dynamic configuration of Kubernetes
resources based on input values. This makes Helm a
powerful tool for managing complex Kubernetes applications
with many configurable parameters.

[Trivia]
Helm was originally developed by DeisLabs, which was later
acquired by Microsoft. It has since become one of the most
widely used tools in the Kubernetes ecosystem. Helm is
often referred to as the "apt" or "yum" of Kubernetes,
drawing an analogy to Linux package managers.
48
Kustomize: Customizing
Kubernetes YAML Without
Templates
Kustomize is a tool for customizing Kubernetes YAML files
without the need for templates. It allows you to create
overlays that modify the base Kubernetes configurations in
a declarative manner.

Here’s an example of using Kustomize to customize a


Kubernetes deployment.
[Code]

# Create a directory for your base YAML


mkdir -p my-app/base
# Create a simple deployment YAML file in the base
directory
cat <<EOF > my-app/base/deployment.apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: nginx:1.17.10
EOF
# Create a Kustomization file in the same base directory
cat <<EOF > my-app/base/kustomization.resources:
- deployment.EOF
# Now create an overlay to change the number of replicas
mkdir -p my-app/overlay
# Create a kustomization file in the overlay directory
cat <<EOF > my-app/overlay/kustomization.resources:
- ../base
patchesStrategicMerge:
- deployment-patch.EOF
# Create the patch file to increase replicas
cat <<EOF > my-app/overlay/deployment-patch.apiVersion:
apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 5
EOF
# Build the customized deployment using Kustomize
kustomize build my-app/overlay

[Result]

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 5
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: nginx:1.17.10

Kustomize allows you to maintain base Kubernetes


configurations separately from environment-specific
customizations. By using overlays, you can apply different
customizations to the base configurations without
duplicating YAML files. This approach keeps your Kubernetes
configurations DRY (Don't Repeat Yourself) and makes it
easier to manage different environments, such as
development, staging, and production.Kustomize is natively
integrated into kubectl, meaning you can use it without
installing any additional tools. When running kubectl apply -
k ./overlay, it automatically applies the customized
resources defined in your Kustomize setup.Kustomize uses a
concept called "patchesStrategicMerge" to modify existing
fields in a declarative way, ensuring that your
customizations can be easily applied and managed.

[Trivia]
Kustomize was the first Kubernetes-native configuration
tool, allowing for a more declarative management style
without using templates. It was integrated into kubectl in
version 1.14, making it accessible out of the box for
Kubernetes users.
49
Running Kubernetes Locally with
Minikube
Minikube is a tool that allows developers to run a local
Kubernetes cluster on their machine. This is extremely
useful for testing and development purposes without
needing a full-scale Kubernetes setup.

To get started with Minikube, you need to have it installed


on your system. Once installed, you can easily start a local
Kubernetes cluster using a single command.
[Code]

minikube start
[Result]

This command initializes a local Kubernetes cluster. You will


see output similar to:😄 minikube v1.25.2 on Darwin 12.0.1

🔥 Automatically selected the docker driver

🌟 Creating Kubernetes v1.22.2 cluster...


Enabled addons: default-storageclass, storage-

🏄
provisioner
Done! kubectl is now configured to use "minikube"
cluster and "default" namespace by default

Minikube simplifies the process of running Kubernetes


locally by creating a virtual machine (VM) or a container
(depending on the driver used) that hosts your Kubernetes
cluster. It supports multiple hypervisors and container
runtimes, such as Docker, VirtualBox, and KVM. Minikube is
great for beginners because it abstracts away the
complexity of setting up a Kubernetes cluster, allowing you
to focus on learning Kubernetes concepts.To interact with
your local cluster, you can use the kubectl command-line
tool, which Minikube configures for you. This lets you
manage resources, deploy applications, and more, just as
you would in a production Kubernetes environment.

[Trivia]
Minikube also comes with several built-in add-ons, such as
the Kubernetes Dashboard, which you can enable to
visualize your cluster's resources. This is particularly helpful
for those new to Kubernetes who prefer a graphical
interface.
50
Lightweight Kubernetes with k3s
k3s is a lightweight, easy-to-install Kubernetes distribution
designed for edge computing, IoT, and resource-constrained
environments. It's perfect for development and small-scale
production workloads.

k3s is designed to be simple and efficient. It's a single


binary that includes everything you need to run a
Kubernetes cluster with minimal resources.
[Code]

To install k3s on a Linux machine, run the following


command:curl -sfL https://get.k3s.io | sh -
[Result]

This command installs k3s on your system and starts a


lightweight Kubernetes cluster. You will see output similar
to:[INFO] Finding release for channel stable
[INFO] Using v1.21.4+k3s1 as release
[INFO] Downloading hash https://github.com/k3s-
io/k3s/releases/download/v1.21.4+k3s1/sha256sum-
amd64.txt
[INFO] Installing k3s to /usr/local/bin/k3s
[INFO] Starting k3s

k3s is designed to be compact, with a binary size of around


40 MB. It achieves this by removing non-essential features
found in the full Kubernetes distribution and replacing them
with lightweight alternatives. For example, k3s uses sqlite3
as the default datastore instead of etcd, which reduces its
memory footprint.k3s also supports ARM processors, making
it ideal for running on devices like Raspberry Pi. It's often
used in edge computing scenarios where resources are
limited, but you still need the orchestration capabilities of
Kubernetes.After installation, k3s automatically starts the
Kubernetes API server, and you can use the kubectl
command-line tool to interact with your cluster.

[Trivia]
k3s was originally developed by Rancher Labs and is now
part of the CNCF (Cloud Native Computing Foundation).
Despite being lightweight, k3s is fully compliant with the
Kubernetes API, so any Kubernetes tool or application should
work seamlessly with it.
51
Running Kubernetes Clusters
with Kind
Kind is a tool that allows you to run Kubernetes clusters
using Docker containers as nodes, making it easier to set up
and experiment with Kubernetes on your local machine.

The following example demonstrates how to create a


Kubernetes cluster using Kind and lists all the nodes in the
cluster.
[Code]

# Install Kind (if not already installed)


curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-
amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
# Create a new Kubernetes cluster with Kind
kind create cluster --name my-cluster
# Check the nodes in the cluster
kubectl get nodes

[Result]

NAME STATUS ROLES AGE VERSIO


N
my-cluster-control-plane Ready control-
plane 1m v1.25.0
Kind stands for "Kubernetes IN Docker." It is primarily used
for testing Kubernetes clusters locally and is highly useful
for CI/CD pipelines. When you run kind create cluster, Kind
sets up a Kubernetes cluster where each node is a Docker
container. The cluster's configuration can be customized
using a YAML file if needed. The cluster created by Kind is
ephemeral, meaning it is primarily used for testing and
development purposes. The command kubectl get nodes is
used to list all nodes within the Kubernetes cluster, and in
this case, it will show the control plane node that Kind
created.

[Trivia]
Kind is a great tool for learning Kubernetes because it
doesn't require a cloud provider or expensive hardware to
run clusters. It supports multi-node clusters, networking,
and most Kubernetes features, making it a practical option
for local development. Additionally, since Kind uses Docker,
it's possible to easily integrate with other tools and
workflows that are container-based.
52
Applying Kubernetes
Configurations with kubectl
The kubectl apply -f <file> command applies or updates the
configuration of Kubernetes resources based on the YAML
file provided, managing their desired state in the cluster.

Here’s an example of how to use kubectl apply to create a


deployment in a Kubernetes cluster using a YAML
configuration file.
[Code]

# deployment.apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21.0
ports:
- containerPort: 80
bash
# Apply the deployment using kubectl
kubectl apply -f deployment.

[Result]

deployment.apps/nginx-deployment created

The kubectl apply -f <file> command reads the YAML file


and ensures that the specified configuration is applied to
the cluster. In this example, the YAML file defines a
Deployment named nginx-deployment with two replicas of
the nginx container. When this command is run, Kubernetes
will either create or update the deployment to match the
desired state defined in the YAML. The deployment ensures
that two pods running the nginx container are up and
running. Kubernetes will automatically manage the pods,
restarting any that fail or scaling up/down as specified.

[Trivia]
The kubectl apply command is declarative, meaning that it
ensures the cluster's state matches the configuration
defined in the YAML file. This is different from imperative
commands, which directly instruct Kubernetes to perform
specific actions. The declarative approach is powerful
because it allows for versioning and continuous
management of infrastructure as code, making it easier to
track changes and maintain desired states over time.
53
Deleting Kubernetes Resources
Defined in a YAML File
In Kubernetes, you can delete resources defined in a YAML
file using the kubectl delete -f <file> command. This is
useful when you want to remove all the resources specified
in that file in one go.

The command kubectl delete -f <file> will delete the


resources (e.g., Pods, Services, Deployments) that are
defined in the specified YAML file.
[Code]

kubectl delete -f deployment.


[Result]

deployment.apps "my-deployment" deleted


service "my-service" deleted

The kubectl delete -f <file> command reads the YAML file


provided and deletes all the Kubernetes resources described
in it. For example, if your YAML file contains a Deployment
and a Service, running this command will delete both the
Deployment and the Service. The -f flag stands for "file,"
indicating that the input is a file. It's important to ensure
that the YAML file is correctly formatted, as Kubernetes will
attempt to delete all resources defined within it. If a
resource defined in the file does not exist, Kubernetes will
return an error message indicating that the resource was
not found.

[Trivia]
The kubectl delete -f <file> command is useful in
Continuous Deployment (CD) pipelines, where you may
need to clean up resources from previous deployments
before deploying new ones. It's also commonly used in
development environments to tear down resources after
testing.
54
Listing Pods in a Specific
Namespace
To list all Pods within a specific namespace in Kubernetes,
you can use the kubectl get pods --namespace=
<namespace> command. This allows you to focus on
resources within a particular context, such as a
development or production environment.

The kubectl get pods --namespace=<namespace>


command fetches and displays all Pods running in the
specified namespace.
[Code]

kubectl get pods --namespace=dev


[Result]

NAME READY STATUS RESTARTS AGE


my-app-67d8f8fcbb-qwert 1/1 Running 0 5m
another-app-5fcb9d6b6c-zxcv 1/1 Running 1 10m

Namespaces in Kubernetes provide a way to divide cluster


resources between multiple users (via resource quota). In a
multi-tenant environment, namespaces are used to create
logical partitions within the cluster. The kubectl get pods --
namespace=<namespace> command is essential when
working in environments with multiple namespaces, as it
allows you to focus on a particular subset of the cluster’s
resources. If you do not specify the --namespace flag, the
command will default to the default namespace. This
behavior helps prevent accidental operations on the wrong
namespace.

[Trivia]
You can view all available namespaces in a cluster by
running kubectl get namespaces. This command lists all the
namespaces, which can be particularly helpful when
managing large clusters with many projects or
environments.
55
Understanding Resource Usage
with kubectl top
kubectl top is a command used in Kubernetes to display
metrics about resource usage for nodes and pods in a
cluster. This command is crucial for monitoring the
performance and resource consumption of your
applications.

The following command will show you the current resource


usage of all pods in a specific namespace.
[Code]

kubectl top pods -n <namespace>


[Result]

NAME CPU(cores) MEMORY(bytes)


nginx-6c5d7c8d6d-2k5x7 50m 128Mi
mysql-5dbb8c7c8d-4j7q2 100m 256Mi

The kubectl top pods command provides a snapshot of the


CPU and memory usage of each pod in the specified
namespace. The output includes:
NAME: The name of the pod.
CPU(cores): The amount of CPU currently being used by the
pod, measured in cores (milli-cores).
MEMORY(bytes): The amount of memory currently being
used by the pod, measured in bytes.
This command is particularly useful for identifying resource
bottlenecks and ensuring that your applications are running
efficiently. By monitoring resource usage, you can make
informed decisions about scaling your applications or
optimizing resource allocation.

[Trivia]
The kubectl top command requires the Metrics Server to be
installed in your cluster. The Metrics Server collects resource
metrics from Kubelets and exposes them via the Kubernetes
API.
You can also use kubectl top nodes to view resource usage
for each node in the cluster, which is helpful for monitoring
overall cluster health.
56
Editing Resources Directly with
kubectl edit
kubectl edit is a command that allows you to modify
Kubernetes resources directly in your cluster using your
default text editor. This is a powerful feature for making
quick changes without needing to reapply a configuration
file.

The following command will open the specified resource in


your default text editor for editing.
[Code]

kubectl edit deployment <deployment-name> -n


<namespace>
[Result]

The command opens the deployment configuration in your


text editor. After making changes and saving, Kubernetes
automatically applies the updates to the deployment.

When you run kubectl edit, the following happens:


The resource (in this case, a deployment) is fetched from
the Kubernetes API.
It opens in your default text editor (configured via the
EDITOR environment variable).
You can make changes to the resource definition, such as
updating the image version, changing environment
variables, or modifying resource requests/limits.
After saving and closing the editor, Kubernetes applies the
changes immediately.
This command is particularly useful for quick fixes or
adjustments, but it is important to be cautious, as changes
made through kubectl edit are applied directly and can
affect running applications.

[Trivia]
You can specify a different editor by setting the EDITOR
environment variable. For example, export EDITOR=nano
will use Nano as the text editor.
The kubectl edit command works for various resource types,
including pods, services, deployments, and more, making it
a versatile tool for cluster management.
57
Managing Rollouts and Rollbacks
with kubectl rollout
The kubectl rollout command is essential for managing the
deployment of applications in Kubernetes. It allows you to
initiate, monitor, and revert deployments effectively.

The following example demonstrates how to use kubectl


rollout to manage a deployment, including how to roll back
to a previous version if needed.
[Code]

# Create a simple deployment


kubectl create deployment my-app --image=nginx:1.14
# Check the rollout status
kubectl rollout status deployment/my-app
# Update the deployment to a new image
kubectl set image deployment/my-app nginx=nginx:1.16
# Check the rollout status again
kubectl rollout status deployment/my-app
# Rollback to the previous version
kubectl rollout undo deployment/my-app

[Result]

deployment.apps/my-app created
Waiting for rollout to finish: 0 out of 1 new replicas have
been updated...
deployment "my-app" successfully rolled out
Waiting for rollout to finish: 1 out of 1 new replicas have
been updated...
deployment "my-app" successfully rolled out
Rollback to deployment "my-app" completed

The kubectl create deployment command initializes a new


deployment with the specified image. The kubectl rollout
status command checks the status of the deployment,
ensuring that it has been successfully rolled out. When you
update the deployment with kubectl set image, you can
specify a new image version. If the update does not work as
expected, you can revert to the prior version using kubectl
rollout undo.

[Trivia]
Rollout History: Kubernetes maintains a history of your
deployments, allowing you to see previous versions and roll
back as needed.
Deployment Strategy: By default, Kubernetes uses a rolling
update strategy, which gradually replaces old pods with new
ones to minimize downtime.
Monitoring Rollouts: You can monitor the rollout process
through the Kubernetes dashboard or by using kubectl get
pods to see the status of individual pods.
58
Debugging with kubectl get
events
The kubectl get events command provides insights into the
events occurring in your Kubernetes cluster. This
information is crucial for troubleshooting issues within your
applications and infrastructure.

The following example shows how to retrieve events from


the cluster, which can help identify problems such as failed
deployments or pod scheduling issues.
[Code]

# Get all events in the cluster


kubectl get events --sort-by='.metadata.creationTimestamp'
# Get events for a specific namespace
kubectl get events -n my-namespace
# Get events for a specific resource, e.g., a pod
kubectl get events --field-selector
involvedObject.name=my-pod

[Result]

LAST
SEEN TYPE REASON OBJECT MESSAGE
1m Normal Scheduled pod/my-
pod Successfully assigned default/my-pod to node-1
1m Normal Pulling pod/my-pod Pulling
image "nginx:latest"
1m Normal Pulled pod/my-
pod Successfully pulled image "nginx:latest"
1m Normal Created pod/my-
pod Created container my-container
1m Normal Started pod/my-pod Started
container my-container

The kubectl get events command lists events in the cluster,


sorted by their creation timestamp. This command displays
various types of events, such as normal operations (e.g.,
pod scheduling, image pulling) and warnings (e.g., failed
health checks). By filtering events for specific resources,
you can focus on issues related to particular pods or
deployments, making it easier to diagnose problems.

[Trivia]
Event Types: Events can be categorized into Normal and
Warning, helping you quickly identify issues that may
require attention.
Event TTL: Events are stored in etcd with a default time-to-
live (TTL) of one hour, after which they are automatically
deleted.
Custom Events: You can create custom events in your
applications to log specific occurrences, which can be
helpful for monitoring and debugging.
59
Viewing Current Kubeconfig
Settings with kubectl config view
The kubectl config view command is used to display the
current configuration settings for Kubernetes clusters. This
includes information about clusters, contexts, and users
defined in the kubeconfig file.

The following command will show the current kubeconfig


settings, which are essential for understanding how your
Kubernetes client interacts with different clusters.
[Code]

kubectl config view


[Result]

apiVersion: v1
clusters:
- cluster:
server: https://example.com:6443
certificate-authority: /path/to/ca.crt
name: example-cluster
contexts:
- context:
cluster: example-cluster
user: example-user
name: example-context
current-context: example-context
kind: Config
preferences: {}
users:
- name: example-user
user:
client-certificate: /path/to/client.crt
client-key: /path/to/client.key

The output of kubectl config view provides a structured


YAML format that includes several key components:
Clusters: Lists all the clusters defined in your kubeconfig file,
along with their connection details like the API server URL
and the certificate authority file.
Contexts: Shows the contexts that link a cluster with a user.
Each context specifies which cluster and user to use when
executing commands.
Current Context: Indicates which context is currently active.
This is crucial for determining which cluster commands will
be executed against.
Users: Lists the users defined in the kubeconfig, including
their authentication details, such as client certificates and
keys.
Understanding this output is vital for managing multiple
Kubernetes environments effectively.

[Trivia]
The kubeconfig file is typically located at ~/.kube/config on
Unix-based systems.
You can specify a different kubeconfig file using the
KUBECONFIG environment variable or the --kubeconfig flag
with kubectl commands.
The kubectl config view --minify command can be used to
show only the details of the current context, which is useful
for quick checks.
60
Switching Between Contexts
with kubectl config set-context
The kubectl config set-context command allows users to
switch between different contexts defined in the kubeconfig
file. This is essential for managing multiple Kubernetes
clusters or environments.

The following command demonstrates how to switch to a


different context, enabling you to interact with a different
Kubernetes cluster.
[Code]

kubectl config set-context example-context


[Result]

Context "example-context" modified.

When you run kubectl config set-context example-context,


you are instructing kubectl to switch to the specified
context. The command modifies the current context to the
one named example-context.
Here’s a breakdown of the process:
Context: A context in Kubernetes is a combination of a
cluster, a user, and a namespace. By switching contexts,
you can quickly change the environment in which you are
working.
Modification Confirmation: The output confirms that the
context has been modified. You can verify the change by
running kubectl config current-context, which will show the
currently active context.
Switching contexts is particularly useful when working with
multiple clusters, such as development, staging, and
production environments.

[Trivia]
You can view all available contexts with the command
kubectl config get-contexts.
To set a context with specific cluster and user settings, you
can use the command kubectl config set-context <context-
name> --cluster=<cluster-name> --user=<user-name>.
Remember to ensure that your kubeconfig file is properly
configured with the necessary clusters and users before
switching contexts.
61
Preparing a Node for
Maintenance with kubectl drain
The kubectl drain command is used to safely prepare a
Kubernetes node for maintenance. This is done by evicting
all running Pods from the node, ensuring that no new Pods
are scheduled until maintenance is completed.

Before performing maintenance on a node, such as


upgrading the OS or hardware, it's crucial to drain the node.
Draining means evicting all Pods safely, allowing them to be
rescheduled on other nodes.
[Code]

kubectl drain <node-name> --ignore-daemonsets --delete-


local-data
[Result]

node/<node-name> cordoned
evicting pod default/nginx-deployment-6f77f7f8d9-w9j6q
evicting pod default/nginx-deployment-6f77f7f8d9-4x9kl
pod/nginx-deployment-6f77f7f8d9-w9j6q evicted
pod/nginx-deployment-6f77f7f8d9-4x9kl evicted

The kubectl drain command is vital in a Kubernetes


environment because it ensures a node can undergo
maintenance without causing disruption to the applications
running on it. The command typically involves three
steps:Cordoning: This marks the node as unschedulable,
preventing new Pods from being scheduled on it.Evicting
Pods: This forcefully evicts the Pods, except for DaemonSets
and mirror Pods. The --ignore-daemonsets flag ensures that
DaemonSets are not disrupted.Deleting Local Data: The --
delete-local-data flag ensures that any Pods using local
storage are also safely evicted. Without this, Pods that use
local storage might not be evicted, potentially leading to
issues during node maintenance.It’s important to note that
kubectl drain is meant for planned maintenance. For
unplanned or emergency node shutdowns, other strategies
might be required to avoid service disruption.

[Trivia]
DaemonSets: These are special Pods that run on every node
and are not automatically evicted by kubectl drain.
Examples include logging and monitoring agents.Cordoning:
This process marks the node as unschedulable, meaning no
new Pods can be scheduled on it, but it doesn't affect
already running Pods. This is automatically done when you
run kubectl drain.
62
Marking a Node Unschedulable
with kubectl cordon
The kubectl cordon command is used to mark a node as
unschedulable, preventing new Pods from being scheduled
on it. However, it does not affect Pods that are already
running on the node.

When you want to prevent new workloads from being


scheduled on a specific node, but don't want to disturb the
existing ones, you can use the kubectl cordon command.
This is particularly useful before draining a node for
maintenance.
[Code]

kubectl cordon <node-name>


[Result]

node/<node-name> cordoned

kubectl cordon is a simpler and less disruptive command


than kubectl drain. It only marks the node as unschedulable,
meaning no new Pods will be scheduled on it. This is often
the first step before performing more complex operations
like draining or upgrading the node.If you want to allow
scheduling on the node again, you can use the kubectl
uncordon <node-name> command. This reverts the node to
a schedulable state, allowing the Kubernetes scheduler to
place new Pods on it.This command is crucial in scenarios
where you need to slowly take a node out of service without
causing immediate disruption. By first cordoning and then
slowly draining the node, you ensure minimal impact on
running services.

[Trivia]
Difference between Cordoning and Draining: Cordoning
simply prevents new Pods from being scheduled on the
node. Draining goes further by also evicting existing
Pods.Maintenance Planning: Cordoning is often the first step
in maintenance planning, giving administrators the
flexibility to manage when and how Pods are relocated
without immediate pressure.
63
Understanding kubectl taint:
Controlling Pod Scheduling on
Nodes
kubectl taint is a command used in Kubernetes to add taints
to nodes. Taints allow you to control which Pods can be
scheduled on a particular node, ensuring that only specific
Pods can run on nodes that have certain conditions.

The following code snippet demonstrates how to add a taint


to a node. This taint will prevent Pods from being scheduled
on that node unless they tolerate the taint.
[Code]

kubectl taint nodes node-name key=value:NoSchedule


[Result]

node/node-name tainted

In this command, replace node-name with the actual name


of your node. The key=value:NoSchedule part specifies the
taint. Here’s what each component means:
key: A string that acts as the identifier for the taint.
value: A string that provides additional information about
the taint.
NoSchedule: This effect means that no Pods will be
scheduled on this node unless they have a matching
toleration.
For example, if you want to prevent any Pods from being
scheduled on a node unless they can tolerate a specific
condition, you would apply a taint like the one shown above.
Pods that do not have a corresponding toleration will not be
able to run on this node.

[Trivia]
Taints are used in conjunction with tolerations. A toleration
is a way for a Pod to indicate that it can tolerate a specific
taint. If a Pod does not have a toleration for a taint on a
node, it will not be scheduled on that node. This mechanism
is essential for managing resources effectively in a
Kubernetes cluster, especially in environments where
certain nodes may be reserved for specific workloads.
64
Using kubectl label: Organizing
Resources with Labels
kubectl label is a command that allows you to add labels to
Kubernetes resources. Labels are key-value pairs that help
you organize and select resources based on specific criteria.

The following code snippet shows how to add a label to a


Pod. This label can later be used by selectors to filter and
manage resources.
[Code]

kubectl label pods pod-name environment=production


[Result]

pod/pod-name labeled

In this command, replace pod-name with the name of your


Pod. The environment=production part specifies the label
being added. Here’s a breakdown:
environment: This is the key of the label.
production: This is the value associated with the key.
Labels are incredibly useful for grouping and selecting
resources. For instance, you might want to select all Pods
that are part of a production environment or filter them
based on their version. You can use selectors in various
Kubernetes commands to manage your resources more
effectively.
For example, to list all Pods with the label
environment=production, you would use:
kubectl get pods -l environment=production

[Trivia]
Labels are fundamental in Kubernetes for managing and
organizing resources. They can be used for various
purposes, such as deployment strategies, monitoring, and
scaling. It’s essential to plan your labeling strategy carefully,
as it can significantly simplify the management of your
Kubernetes resources. Additionally, labels can be updated or
removed, allowing for flexibility as your application evolves.
65
Adding Annotations to
Kubernetes Resources with
kubectl annotate
Annotations in Kubernetes are key-value pairs that store
metadata about resources. They are useful for attaching
non-identifying information to objects, which can be used by
external tooling and libraries.

The following command demonstrates how to add an


annotation to a Kubernetes resource, such as a pod.
[Code]

kubectl annotate pod my-pod description="This is my first


pod annotation"
[Result]

pod/my-pod annotated

In this example, the command kubectl annotate is used to


add an annotation to a pod named my-pod. The annotation
key is description, and its value is "This is my first pod
annotation". Annotations are not used to identify resources;
instead, they provide additional context that can be
leveraged by tools and scripts.
Annotations can be updated or removed using the same
command. For instance, to update the annotation, you can
run the same command with a new value, and to remove it,
you can use the --remove flag:
kubectl annotate pod my-pod description-
This command will remove the description annotation from
my-pod.

[Trivia]
Annotations differ from labels. While labels are used for
selecting and grouping objects, annotations are intended for
storing arbitrary metadata. This distinction is crucial for
organizing and managing Kubernetes resources effectively.
Annotations can also be used by controllers or operators to
manage resources dynamically.
66
Starting a Local Proxy to the
Kubernetes API Server with
kubectl proxy
The kubectl proxy command creates a local proxy that
allows you to interact with the Kubernetes API server. This is
useful for accessing the API without needing to authenticate
directly.

The following command starts a local proxy to the


Kubernetes API server, enabling you to access the API
through a local endpoint.
[Code]

kubectl proxy
[Result]

Starting to serve on 127.0.0.1:8001

When you run kubectl proxy, it starts a local server on your


machine (by default, on port 8001). This proxy forwards
requests to the Kubernetes API server. For example, you can
access the API by navigating to
http://localhost:8001/api/v1/pods in your web browser. This
will return a list of all pods in the current namespace,
formatted in JSON.
The proxy is particularly useful for development and
debugging, as it simplifies API access without the need for
complex authentication setups. You can also specify a
different port by using the --port option, like so:
kubectl proxy --port=8080
This command will start the proxy on port 8080 instead of
the default port 8001.

[Trivia]
Using kubectl proxy is a common practice for developers
who want to interact with the Kubernetes API without
dealing with authentication tokens or certificates. The proxy
handles these complexities, allowing for a more
straightforward approach to testing and debugging API calls.
Additionally, the proxy can be configured to limit access to
specific namespaces or resources, enhancing security
during development.
67
Copying Files Between a Pod and
the Local Filesystem Using
kubectl cp
The kubectl cp command allows you to copy files or
directories between a Kubernetes Pod and your local
machine’s filesystem, enabling file transfer operations
without needing direct access to the Pod’s container.

This example demonstrates how to copy a file from your


local system to a Pod, and vice versa, using the kubectl cp
command.
[Code]

# Copy a file from local machine to a Pod


kubectl cp /path/to/local/file
<pod_name>:/path/to/destination/
# Example:
kubectl cp ./localfile.txt my-pod:/tmp/localfile.txt
# Copy a file from a Pod to the local machine
kubectl cp <pod_name>:/path/to/file
/path/to/local/destination/
# Example:
kubectl cp my-pod:/tmp/remotefile.txt ./remotefile.txt

[Result]
If successful, the command will complete without errors,
and the file will appear at the specified destination on the
Pod or your local machine.

The kubectl cp command is a convenient way to manage


files within Pods, especially for debugging purposes,
transferring configuration files, or collecting logs. The
command essentially uses tar under the hood to archive the
files during transfer, which means both the source and
destination paths must exist and be accessible. Keep in
mind that the copied files inherit the permissions of the
source system, so you might need to adjust them afterward.

[Trivia]
If the file copy operation fails, it could be due to incorrect
file paths, insufficient permissions, or the Pod not being in a
Running state. Always ensure the Pod is running and paths
are correctly specified. Additionally, kubectl cp can only
copy files between a local system and a Pod, not between
Pods.
68
Understanding Kubernetes Flat
Networking Model
Kubernetes employs a flat networking model, meaning
every Pod within a cluster can communicate with every
other Pod by default, regardless of the node on which they
reside.

The following explanation provides an overview of


Kubernetes’ networking model, demonstrating how Pods can
communicate with each other using their assigned IP
addresses.
[Code]

# Example Deployment YAML


apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 2
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-container
image: k8s.gcr.io/echoserver:1.4
ports:
- containerPort: 8080
bash
# Get the Pod IPs
kubectl get pods -o wide
# Curl one Pod from another using the Pod IP
kubectl exec -it <pod_name> -- curl <target_pod_ip>:8080

[Result]

The kubectl exec command will return the HTML response


from the echoserver running in the target Pod,
demonstrating that the Pods can communicate directly
using their IPs.

In Kubernetes, each Pod is assigned a unique IP address


within the cluster’s internal network. This flat networking
model ensures that all Pods can communicate with each
other without NAT (Network Address Translation). The
Kubernetes network model abstracts the underlying physical
network, ensuring consistency across different network
implementations, whether you’re using a cloud provider’s
CNI (Container Network Interface) plugin or an on-premise
solution.

[Trivia]
While the flat networking model is powerful, it’s essential to
secure inter-Pod communication using Network Policies,
especially in multi-tenant environments or when dealing
with sensitive data. Network Policies allow you to restrict
traffic between Pods, controlling which Pods can
communicate with others based on labels, namespaces, and
other criteria.
69
Understanding Pod Lifecycle
Events in Kubernetes
Pod lifecycle events in Kubernetes refer to the different
phases that a Pod goes through from its creation to its
termination. The key phases include Pending, Running,
Succeeded, Failed, and Unknown.

The lifecycle of a Pod is crucial to understand because it


helps in managing and troubleshooting Kubernetes
applications. Here’s how you can observe these lifecycle
events using kubectl commands.
[Code]

# Create a Pod with a simple configuration


kubectl run nginx --image=nginx
# Check the status of the Pod
kubectl get pod nginx -o jsonpath='{.status.phase}'

[Result]

Pending
(Or)Running
(Or)
Succeeded
(Or)
Failed
(Or)Unknown
Pending: The Pod has been accepted by the Kubernetes
system, but one or more of the containers inside the Pod
has not been created. This phase could involve image
pulling, container creation, or network setup.Running: The
Pod has been bound to a node, and all of the containers
have been created. At least one container is still running, or
is in the process of starting or restarting.Succeeded: All
containers in the Pod have terminated successfully, and will
not be restarted.Failed: All containers in the Pod have
terminated, and at least one container has terminated in a
failure (exited with a non-zero status).Unknown: The state of
the Pod cannot be determined, usually because the
communication between the Pod and the node has failed.

[Trivia]
Kubernetes uses a controller to ensure that the desired
number of Pods are running at any given time. For example,
a Deployment controller ensures that a specific number of
Pods are up and running, and if a Pod fails, it is
automatically replaced.
70
Ensuring Pod Health with
Liveness and Readiness Probes
Liveness and Readiness Probes in Kubernetes are
mechanisms to ensure that a Pod is healthy and ready to
receive traffic. Liveness Probes detect if a container is still
alive, while Readiness Probes determine if the container is
ready to start accepting traffic.

Implementing Liveness and Readiness Probes in a Pod


specification is essential for maintaining the robustness of
your application. Below is an example of how to configure
these probes in a Pod definition file.
[Code]

apiVersion: v1
kind: Pod
metadata:
name: liveness-readiness-pod
spec:
containers:
- name: myapp-container
image: myapp:latest
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 3
periodSeconds: 3
readinessProbe:
httpGet:
path: /readiness
port: 8080
initialDelaySeconds: 5
periodSeconds: 3

[Result]

The result of applying this configuration would be a Pod that


Kubernetes continuously monitors for health and readiness.
If the Liveness Probe fails, Kubernetes will restart the
container. If the Readiness Probe fails, the Pod will be
removed from the service load balancer until it is ready
again.

Liveness Probe: Used to detect whether your application is


running. If the liveness probe fails, Kubernetes will kill the
container, and the container will be subjected to its restart
policy.Readiness Probe: Ensures that the container is ready
to start accepting traffic. If this probe fails, the Pod will not
be included in the list of endpoints for a service, meaning it
won’t receive traffic until it passes the
probe.initialDelaySeconds: Specifies the number of seconds
after the container has started before the probe is
initiated.periodSeconds: How often (in seconds) to perform
the probe.

[Trivia]
Liveness Probes can be implemented using different
methods such as HTTP GET requests, TCP sockets, or
executing a command inside the container. Readiness
Probes can also be customized similarly, making them
versatile for different use cases.
71
Initialization Tasks with Init
Containers in Kubernetes
Init containers in Kubernetes are special containers that run
before the main application containers in a Pod. They are
used for setup tasks that must complete before the main
application containers can start.

Let's look at an example where an init container is used to


ensure a database is ready before the application container
starts. This init container will check for the database's
availability before the main container attempts to connect.
[Code]

apiVersion: v1
kind: Pod
metadata:
name: init-container-example
spec:
initContainers:
- name: init-db-check
image: busybox
command: ['sh', '-c', 'until nslookup my-database; do echo
waiting for database; sleep 2; done;']
containers:
- name: app-container
image: my-app-image
ports:
- containerPort: 80
[Result]

If the database is not ready, the init container


outputs:waiting for database
waiting for database
...
Once the database becomes available, the init container
exits successfully, allowing the main application container to
start.

Init containers are ideal for handling tasks that must


complete before the main application starts. These could
include waiting for a service to be ready, setting up
environment configurations, or running a script to provision
necessary data. If the init container fails, the Pod will not
proceed to start the main containers, which helps in
ensuring that the necessary prerequisites are met before
the application runs.Each init container runs sequentially,
completing its task before the next one starts. Once all init
containers have successfully executed, Kubernetes starts
the main application containers in the Pod. Init containers
also use separate Docker images, which can be different
from the main application containers, allowing for flexibility
in the tools and environments needed for initialization tasks.

[Trivia]
Init containers can access the same volumes as regular
containers, which is useful for setting up files or
configuration data needed by the main application.If an init
container fails to start due to an error, Kubernetes will
restart it according to the Pod’s restart policy until it
succeeds or the Pod is deleted.
72
Networking and Storage in Multi-
container Pods
In Kubernetes, when multiple containers are defined within a
single Pod, they share the same network namespace. This
means they can communicate with each other using
localhost as if they were running within the same
environment. However, they can have separate storage
volumes, allowing for more flexible data management.

Consider a scenario where two containers within a Pod need


to communicate with each other, but one container needs
access to a specific volume for data storage, while the other
does not. We will configure this in the Pod's specification.
[Code]

apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod-example
spec:
volumes:
- name: shared-storage
emptyDir: {}
containers:
- name: app-container
image: nginx
volumeMounts:
- name: shared-storage
mountPath: /usr/share/nginx/ - name: sidecar-container
image: busybox
command: ['sh', '-c', 'echo "Hello from sidecar" >
/usr/share/nginx/html/index.html']

[Result]

After deploying the Pod, accessing the nginx service will


display the message "Hello from sidecar" in the browser,
which is written by the sidecar container to the shared
volume.

In a multi-container Pod, containers can share storage


volumes to exchange data or manage shared states. The
network namespace sharing means that all containers in the
Pod can communicate over localhost on different ports. For
example, one container could run an application server,
while another handles logging or monitoring, directly
communicating without exposing ports outside the
Pod.However, even though they share the same network
namespace, containers in a Pod can mount different
volumes. This allows for distinct storage strategies within
the same Pod, where one container might store persistent
data, and another might generate temporary files. This
design offers flexibility in configuring Pods to meet specific
application requirements.

[Trivia]
Kubernetes uses the concept of "sidecar" containers in
multi-container Pods, where an auxiliary container supports
the main application container by handling tasks such as
logging, monitoring, or data synchronization.Pods, being the
smallest deployable unit in Kubernetes, ensure that all
containers within them are tightly coupled and meant to
work together, sharing resources like CPU, memory, and
storage.
73
Kubernetes Supports OCI-
Compliant Container Images
Kubernetes allows you to pull and run container images
from any Open Container Initiative (OCI)-compliant registry.

In this example, we'll demonstrate how to deploy a simple


Nginx application using an image from an OCI-compliant
registry. We'll use a public image available from Docker Hub,
which is an OCI-compliant registry.
[Code]

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21.6
ports:
- containerPort: 80
To deploy this configuration, save it to a file named nginx-
deployment.yaml and run the following command:kubectl
apply -f nginx-deployment.

[Result]

deployment.apps/nginx-deployment created

The image field in the YAML configuration specifies the


container image to be used for the deployment. In this case,
we're pulling the nginx:1.21.6 image from Docker Hub.
Docker Hub is an OCI-compliant registry, meaning it follows
the standards defined by the Open Container Initiative.
Kubernetes is compatible with any registry that adheres to
these standards, ensuring flexibility in where you source
your container images.Kubernetes uses the container
runtime, typically containerd or CRI-O, to pull the image
from the registry and run it in a container. This process is
transparent to the user, but it's crucial to ensure that the
registry you use is OCI-compliant to avoid compatibility
issues.

[Trivia]
OCI, or Open Container Initiative, was established in 2015 to
create open standards for container formats and runtimes.
This initiative ensures that container technologies from
different vendors can interoperate, fostering a more flexible
and versatile ecosystem for containerized applications.
74
New Features in the Latest
Kubernetes Stable Version
The latest stable version of Kubernetes includes various new
features and improvements that enhance the platform's
functionality and user experience.

We'll explore some new features in Kubernetes by enabling


a specific alpha feature gate in a cluster and observing its
effect. This example demonstrates how to work with feature
gates, which control the activation of experimental or alpha
features in Kubernetes.
[Code]

To enable a feature gate, add the following flag to your


Kubernetes API server startup configuration:--feature-
gates=ExampleFeatureGate=true
You can check if the feature gate is enabled using:kubectl
describe node <node-name> | grep 'ExampleFeatureGate'

[Result]

If the feature gate is enabled, the result will show the


feature as active:ExampleFeatureGate=true
If the feature is not available or not enabled, the grep
command will return no output.
Kubernetes periodically introduces new features, which are
often first released as alpha or beta features controlled by
feature gates. These gates allow users to test and
experiment with new functionality before it becomes stable
and is enabled by default. The --feature-gates flag is added
to the configuration of Kubernetes components like the API
server, kubelet, or controller-manager to toggle these
features on or off.It's important to note that alpha features
are generally not recommended for production use as they
may not be fully stable. Beta features are more stable but
still subject to changes. Understanding how to manage
these feature gates is crucial for administrators who want to
test new Kubernetes capabilities in a safe and controlled
manner.

[Trivia]
Kubernetes follows a regular release cycle, typically every
three to four months. Each new release brings updates, new
features, performance improvements, and security patches.
It's essential for Kubernetes administrators to stay informed
about these updates to take full advantage of the platform's
evolving capabilities.
75
Difference Between StatefulSets
and Deployments in Kubernetes
StatefulSets and Deployments are two core Kubernetes
resources used to manage applications. Deployments are
ideal for stateless applications, ensuring that any pod can
be replaced by another without affecting the application. On
the other hand, StatefulSets are specifically designed for
stateful applications where the order and identity of pods
are crucial.

The following example demonstrates how to create both a


Deployment and a StatefulSet in Kubernetes. This will help
illustrate the differences in managing stateless versus
stateful applications.
[Code]

# Deployment Example
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.17.4
ports:
- containerPort: 80
---
# StatefulSet Example
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.17.4
ports:
- containerPort: 80
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi

[Result]

Deployment: When you apply the Deployment manifest,


Kubernetes will create 3 replicas of the nginx pod, all of
which are identical and can be replaced interchangeably
without any particular order or identity.StatefulSet: When
you apply the StatefulSet manifest, Kubernetes will create 3
replicas of the nginx pod, but each will have a unique
identity (e.g., web-0, web-1, web-2). These pods are created
in order, and if one pod is deleted, it will be recreated with
the same identity.

StatefulSets manage the deployment and scaling of a set of


pods and provide guarantees about the ordering and
uniqueness of these pods. This is crucial for applications like
databases where the state is maintained on disk, and pods
need to have stable, persistent storage, provided by
PersistentVolumeClaims.Deployments, in contrast, are used
for stateless applications. In a Deployment, all pods are
interchangeable, which is ideal for scaling applications
horizontally without worrying about the specific identity of
each pod.Key Points:StatefulSets: Pod identity (persistent),
order-specific, stable network identifiers.Deployments:
Stateless, interchangeable pods, ideal for load-balanced
services.

[Trivia]
StatefulSets are often used in scenarios where applications
require stable storage or are highly sensitive to the order of
operations, such as in databases (e.g., MySQL, Cassandra)
or other distributed systems requiring consistent network
identities.In a StatefulSet, the pod's hostname is derived
from the StatefulSet name and the ordinal index of the pod
(e.g., web-0), allowing the pod to be consistently
addressable by other resources.
76
Introduction to Network Plugins
(CNI) in Kubernetes
Kubernetes uses the Container Network Interface (CNI) to
extend and manage network capabilities for pods. CNIs are
responsible for establishing network connectivity, assigning
IP addresses to pods, and ensuring consistent
communication between them.

This example shows how to deploy a basic CNI plugin in


Kubernetes to enable networking capabilities.
Understanding how CNIs work is essential for configuring
and troubleshooting network connectivity in a Kubernetes
cluster.
[Code]

# Example CNI Plugin (Weave Net) Installation Command


kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-
version=$(kubectl version | base64 | tr -d '\n')"

[Result]

Executing this command will install the Weave Net CNI


plugin on your Kubernetes cluster, enabling networking
capabilities for your pods. The pods will be able to
communicate with each other across nodes in the cluster.

CNI Plugins are critical in Kubernetes clusters as they


manage how pods communicate across different nodes.
Each pod in a Kubernetes cluster typically gets an IP address
from the CNI, and the plugin ensures that this IP is unique
and routable across the cluster.Common CNI Plugins:Calico:
Offers networking and network policy features.Weave Net:
Simple networking with encryption and multicast
support.Flannel: Basic networking plugin for overlay
networks.Cilium: Provides advanced networking, including
L7 load balancing and security.Network Policies: CNIs often
support Kubernetes Network Policies, allowing you to define
rules about how pods can communicate with each other and
with external resources. These policies can control traffic
flow, improving the security and performance of your
applications.

[Trivia]
The CNI specification was originally developed by CoreOS
and is now a CNCF project. The goal is to create a common
interface that different networking solutions can implement,
allowing Kubernetes to be flexible with various network
environments.Some advanced CNIs like Cilium use eBPF
(extended Berkeley Packet Filter) for efficient networking
and security features directly within the Linux kernel,
providing enhanced performance and observability in large-
scale environments.
77
Cluster Autoscaler: Dynamically
Managing Node Count
The Cluster Autoscaler is a powerful Kubernetes component
that automatically adjusts the number of nodes in your
cluster based on the resource usage of your applications. It
ensures that your cluster has enough resources to run your
workloads efficiently while minimizing costs by scaling down
when resources are underutilized.

The following code snippet demonstrates how to deploy the


Cluster Autoscaler in a Kubernetes cluster. It includes the
necessary configuration and deployment commands.
[Code]

apiVersion: apps/v1
kind: Deployment
metadata:
name: cluster-autoscaler
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: cluster-autoscaler
template:
metadata:
labels:
app: cluster-autoscaler
spec:
containers:
- name: cluster-autoscaler
image: k8s.gcr.io/cluster-autoscaler:v1.21.0
command:
- ./cluster-autoscaler
- --cloud-provider=gce
- --nodes=1:10:YOUR_NODE_POOL_NAME
- --v=4
env:
- name: GOOGLE_APPLICATION_CREDENTIALS
value: /etc/gce-service-
account/key. volumeMounts:
- name: gce-service-account
mountPath: /etc/gce-service-account
volumes:
- name: gce-service-account
secret:
secretName: gce-service-account

[Result]

No output is displayed directly from the deployment


command, but you can check the status of the Cluster
Autoscaler by running:
kubectl get pods -n kube-system
You should see the cluster-autoscaler pod running.

The Cluster Autoscaler works by monitoring the resource


requests of your pods. If it detects that pods are pending
due to insufficient resources, it will add nodes to the cluster.
Conversely, if it finds nodes that are underutilized and their
workloads can be moved to other nodes, it will scale down
the number of nodes. This dynamic adjustment helps
maintain performance while controlling costs.
To use the Cluster Autoscaler, you need to specify the cloud
provider and the node pool configuration. The example
above uses Google Cloud as the provider, but similar
configurations exist for AWS, Azure, and others.

[Trivia]
The Cluster Autoscaler can only scale up if the underlying
infrastructure supports it (e.g., if you're using a cloud
provider).
It requires specific IAM permissions to manage resources in
the cloud environment.
The Cluster Autoscaler operates independently of the
Horizontal Pod Autoscaler, which scales the number of pod
replicas based on CPU or memory usage.
78
Ingress Controllers: Essential for
Managing Ingress Resources
Ingress Controllers are crucial components in Kubernetes
that manage Ingress resources, allowing you to define how
external HTTP/S traffic should be routed to your services.
They act as a bridge between the external world and your
internal Kubernetes services.

The following example demonstrates how to deploy an


NGINX Ingress Controller, which is one of the most
commonly used Ingress Controllers in Kubernetes.
[Code]

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ingress-controller
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: nginx-ingress
template:
metadata:
labels:
app: nginx-ingress
spec:
containers:
- name: nginx-ingress-controller
image: quay.io/kubernetes-ingress-controller/nginx-
ingress-controller:0.30.0
args:
- /nginx-ingress-controller
- --configmap=$(POD_NAMESPACE)/nginx-configuration
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-
services
- --udp-services-configmap=$(POD_NAMESPACE)/udp-
services
- --default-backend-
service=$(POD_NAMESPACE)/default-backend
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace

[Result]

No output is displayed directly from the deployment


command, but you can check the status of the NGINX
Ingress Controller by running:
kubectl get pods -n kube-system
You should see the nginx-ingress-controller pod running.

The NGINX Ingress Controller processes Ingress resources


defined in your cluster. An Ingress resource specifies rules
for routing HTTP/S traffic to different services based on the
request's host and path. For example, you can route traffic
for example.com/api to one service and example.com/app to
another.
To use Ingress effectively, you must define Ingress resources
in YAML format and then apply them to your cluster. The
Ingress Controller will watch for these resources and
configure the underlying NGINX server accordingly.
Here’s a simple example of an Ingress resource:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- host: example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /app
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80

[Trivia]
Ingress Controllers can handle SSL termination, allowing you
to secure your applications with HTTPS.
There are various Ingress Controllers available, including
NGINX, Traefik, and HAProxy, each with unique features and
configurations.
Ingress resources can also be used to set up load balancing
and path-based routing, enhancing the flexibility of your
Kubernetes applications.
79
Understanding
PodDisruptionBudgets in
Kubernetes
PodDisruptionBudgets (PDBs) are a critical feature in
Kubernetes that help maintain application availability during
maintenance events by limiting the number of Pods that can
be disrupted simultaneously.

The following code example demonstrates how to create a


PodDisruptionBudget for a deployment, ensuring that not
too many Pods are taken down at once during maintenance.
[Code]

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: my-app

[Result]

When you apply this configuration using kubectl apply -f


pdb.yaml, you will see a confirmation message indicating
that the PodDisruptionBudget has been created:
poddisruptionbudget.policy/my-app-pdb created

In this example, we define a PodDisruptionBudget named


my-app-pdb. The minAvailable: 2 setting means that at least
two Pods must remain available at all times. The selector
specifies which Pods this budget applies to, in this case,
those labeled with app: my-app. This ensures that during
maintenance, Kubernetes will not allow more than the
specified number of Pods to be disrupted, thus maintaining
the application's availability.

[Trivia]
PodDisruptionBudgets are particularly useful in scenarios
where applications require high availability, such as in
production environments. They work in conjunction with
other Kubernetes features like Eviction and Drain, which are
used during node maintenance. It's important to note that
PDBs only apply to voluntary disruptions, such as node
maintenance or scaling down, and do not prevent
involuntary disruptions like crashes or node failures.
80
The "API First" Approach in
Kubernetes
Kubernetes employs an "API first" approach, meaning that
all interactions with the system are performed through API
calls, making it highly extensible and adaptable.

The following example illustrates how to interact with the


Kubernetes API using kubectl to create a deployment,
showcasing the API-centric nature of Kubernetes.
[Code]

kubectl create deployment my-deployment --image=nginx


[Result]

Executing the command above will create a deployment and


return a message like:
deployment.apps/my-deployment created

In this command, we use kubectl, which is the command-


line tool for interacting with the Kubernetes API. The create
deployment command is an API call that instructs
Kubernetes to create a new deployment named my-
deployment using the nginx image. This command
exemplifies the API first approach, as kubectl translates user
commands into API requests to the Kubernetes server,
which then processes the request and updates the cluster
state accordingly.
[Trivia]
The API first design of Kubernetes allows for various client
libraries in different programming languages, enabling
developers to interact with Kubernetes programmatically.
This design also supports a wide range of tools and
integrations, enhancing the ecosystem around Kubernetes.
Understanding how to make API calls and interact with the
Kubernetes API is fundamental for anyone looking to
develop or manage applications in a Kubernetes
environment.
81
Extending Kubernetes with
CustomResourceDefinitions
(CRDs)
CustomResourceDefinitions (CRDs) allow you to extend
Kubernetes by defining your own custom resources, which
behave similarly to native Kubernetes resources like Pods or
Services. By using CRDs, you can introduce new resource
types into your Kubernetes cluster, enabling more tailored
and specific management of your applications.

Let's create a simple CRD for a "MyApp" resource. This


example will show how to define a custom resource and how
it can be applied and managed within a Kubernetes cluster.
[Code]

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: myapps.example.com
spec:
group: example.com
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: myapps
singular: myapp
kind: MyApp
shortNames:
- ma
---
apiVersion: example.com/v1
kind: MyApp
metadata:
name: my-first-app
spec:
config: "example configuration"
Apply this CRD:kubectl apply -f myapp-crd.

[Result]

customresourcedefinition.apiextensions.k8s.io/myapps.exa
mple.com created
myapp.example.com/my-first-app created
You can check the custom resource by running:kubectl get
myapps
Expected output:NAME AGE
my-first-app 10s

CRDs are essential for Kubernetes extensibility, as they


allow developers to introduce new resource types without
modifying the Kubernetes source code. When a CRD is
applied, Kubernetes automatically makes the API server
aware of the new resource type, which can then be
managed like any other native Kubernetes object.CRDs
consist of two main parts: the CustomResourceDefinition
itself and the custom resource that is defined by it. The
CustomResourceDefinition describes the new type, while
instances of the custom resource represent the actual
objects that can be created, managed, and deleted in the
cluster.In our example, MyApp is a custom resource defined
by the CRD. By applying the CRD, the Kubernetes API
becomes aware of MyApp and allows you to create
resources of this type within your namespaces.

[Trivia]
CRDs are part of Kubernetes’ API extension mechanism,
introduced in Kubernetes 1.7.Over 70% of Kubernetes
operators use CRDs to define the state of custom
resources.With CRDs, you can implement advanced features
like versioning, validation, and subresources (e.g., status
and scale).
82
Managing Stateful Workloads
with Kubernetes Operators
Operators are a method of packaging, deploying, and
managing a Kubernetes application. Operators extend
Kubernetes’ capabilities to manage complex, stateful
workloads, providing operational knowledge that is encoded
into a custom controller.

Let's create a basic Operator that watches over a custom


resource (MyApp) and automatically performs an action
when the resource is created or updated. This example
demonstrates the concept of an Operator and its interaction
with CRDs.
[Code]

package main
import (
"context"
"fmt"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
)
type MyApp struct {
Spec struct {
Config string `json:"config"`
} `json:"spec"`
}
func main() {
mgr, err := manager.New(manager.GetConfigOrDie(),
manager.Options{})
if err != nil {
fmt.Println("Error creating manager:", err)
return
}
c := mgr.GetClient()
myApp := &MyApp{}
key := client.ObjectKey{Name: "my-first-app",
Namespace: "default"}
err = c.Get(context.Background(), key, myApp)
if err != nil {
fmt.Println("Error getting MyApp resource:", err)
return
}
fmt.Printf("Found MyApp with config: %s\n",
myApp.Spec.Config)
stop := signals.SetupSignalHandler()
if err := mgr.Start(stop); err != nil {
fmt.Println("Error starting manager:", err)
}
}
Build and deploy this operator within your Kubernetes
cluster.

[Result]

Found MyApp with config: example configuration

Kubernetes Operators are a pattern for managing stateful


applications. An Operator extends the Kubernetes API by
encapsulating the operational knowledge needed to deploy
and manage complex applications. This includes tasks like
backup, upgrade, scaling, and self-healing of the
application.In the code example, we have a simple Go-
based Operator that interacts with the MyApp custom
resource. The Operator uses the Kubernetes controller-
runtime library to manage the lifecycle of MyApp resources.
When a MyApp resource is created, the Operator fetches its
configuration and performs an action—here, it simply prints
the configuration.This is a very simplified version of what
real-world Operators do. In production, an Operator might
automatically configure databases, manage clusters of
applications, or handle other complex tasks that would
otherwise require manual intervention.

[Trivia]
The Operator pattern was introduced by CoreOS in
2016.Operators can be written in several languages, with
Go being the most common due to its tight integration with
Kubernetes.Advanced Operators often include features like
leader election, Prometheus metrics, and reconcilers that
continually monitor the desired state of resources.
83
Bootstrapping Kubernetes
Clusters with kubeadm
kubeadm is a powerful tool designed to simplify the process
of setting up and bootstrapping Kubernetes clusters. It
provides a straightforward way to initialize a master node,
join worker nodes, and manage the overall cluster setup
with minimal configuration.

In this example, we will demonstrate how to initialize a


Kubernetes master node using kubeadm, and then join a
worker node to the cluster. This will set up a basic cluster
with one control plane (master) and one worker node.
[Code]

# Initialize the master node


sudo kubeadm init --pod-network-cidr=192.168.0.0/16
# To start using your cluster, you need to run the following
as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# Deploy a pod network add-on (we'll use Calico as an
example)
kubectl apply -f
https://docs.projectcalico.org/manifests/calico.
# Join a worker node to the cluster
# Run the following command on the worker node (this is an
example, the actual command will be output by kubeadm
init):
sudo kubeadm join <master-ip>:<master-port> --token
<token> --discovery-token-ca-cert-hash sha256:<hash>

[Result]

Upon running the above commands, the master node will be


initialized, and the worker node will join the cluster
successfully. You can verify this by running:kubectl get
nodes
This command will show both the master and worker nodes
listed as part of the cluster, each with a status of Ready.

kubeadm abstracts much of the complexity involved in


setting up a Kubernetes cluster. When you run kubeadm init,
it sets up the necessary control plane components, including
etcd, the API server, the controller manager, and the
scheduler. The --pod-network-cidr flag is used to specify the
CIDR block for the pod network. After initialization,
deploying a network plugin like Calico is crucial because it
allows the pods within the cluster to communicate with each
other across nodes.When joining a worker node using
kubeadm join, kubeadm requires a token and a hash to
securely connect to the master node. These are provided
during the master node initialization. The kubeadm tool also
configures the kubelet service on the nodes, which is
responsible for running containers and managing them at
the node level.

[Trivia]
kubeadm was introduced as a part of the Kubernetes 1.4
release to simplify cluster setup and has since become the
de facto tool for bootstrapping clusters.The use of kubeadm
is not limited to single master setups; it can also be used to
set up high-availability (HA) clusters with multiple control
plane nodes.The networking model in Kubernetes is unique
because it requires all pods in the cluster to be able to
communicate with each other without NAT, which is why
deploying a network plugin like Calico or Flannel is
mandatory after initialization.
84
Understanding Resource
Requests and Limits in
Kubernetes
Resource requests and limits in Kubernetes are mechanisms
that allow you to control how much CPU and memory a
container can use. Properly configuring these values
ensures efficient resource utilization and helps prevent any
single container from monopolizing resources, which could
degrade the performance of other containers in the same
node.

In this example, we will demonstrate how to set resource


requests and limits for a container in a Kubernetes pod
specification. This will help ensure that the container gets a
guaranteed amount of resources while preventing it from
using more than a specified limit.
[Code]

apiVersion: v1
kind: Pod
metadata:
name: resource-demo
spec:
containers:
- name: busybox
image: busybox
command: ["sh", "-c", "sleep 3600"]
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"

[Result]

When you apply this pod configuration to your Kubernetes


cluster:kubectl apply -f resource-demo.You will see the pod
created with the specified resource requests and limits. You
can check the assigned resources using:kubectl describe
pod resource-demo
This will display the pod’s resource requests and limits,
confirming they are set as specified.

Resource requests and limits are vital for ensuring that your
Kubernetes cluster runs efficiently. The requests field
specifies the minimum amount of CPU and memory that the
container will get, while the limits field specifies the
maximum resources the container can use. If a node doesn’t
have enough resources to meet the request, the pod won’t
be scheduled on that node.The CPU request is measured in
CPU units, where 1 CPU equals one physical core or one
virtual core in the cloud. Memory is measured in bytes, with
common values being Mi for mebibytes and Gi for gibibytes.
If a container exceeds its memory limit, it might be
terminated by the kubelet, and if it exceeds its CPU limit, it
will be throttled. Ensuring proper requests and limits can
prevent resource contention and ensure that critical
applications have the necessary resources to function
correctly.
[Trivia]
CPU in Kubernetes is measured in millicores (m). For
example, 500m equals 0.5 CPU, meaning half a CPU
core.Pods without specified resource requests are
considered to have zero requests, meaning they can be
starved of resources if other pods have defined
requests.Kubernetes scheduler uses these requests to make
decisions about which nodes to place pods on, so defining
them correctly is crucial for ensuring pods are placed on
nodes with sufficient resources.
85
Kubernetes: Multi-Cloud and On-
Premises Support
Kubernetes is a powerful container orchestration platform
that supports deployment across multiple cloud providers
and can also be run on-premises. This flexibility allows
organizations to choose the best environment for their
applications based on their specific needs.

The following code demonstrates how to deploy a simple


application on a Kubernetes cluster that can run on any
cloud provider or on-premises setup.
[Code]

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: nginx:latest
ports:
- containerPort: 80

[Result]

The deployment will create three replicas of an Nginx


container, accessible on port 80.

This YAML configuration file defines a Deployment in


Kubernetes. The key components are:
apiVersion: Specifies the version of the Kubernetes API to
use.
kind: Indicates that this resource is a Deployment.
metadata: Contains information about the Deployment,
such as its name.
spec: Defines the desired state of the Deployment, including
the number of replicas and the container specifications.
containers: Lists the containers that should be created,
including their images and ports.
Kubernetes abstracts the underlying infrastructure, allowing
you to run this configuration on any cloud provider (like
AWS, Google Cloud, or Azure) or on your own servers.

[Trivia]
Kubernetes was originally developed by Google and is now
maintained by the Cloud Native Computing Foundation
(CNCF).
It uses a declarative configuration model, meaning you
describe the desired state of your application, and
Kubernetes works to maintain that state.
Kubernetes supports various networking models, enabling
communication between containers across different
environments.
86
Managed Kubernetes Services:
Simplifying Cluster Management
Kubernetes clusters can be easily managed through
managed services such as Google Kubernetes Engine (GKE),
Amazon Elastic Kubernetes Service (EKS), and Azure
Kubernetes Service (AKS). These services simplify the
deployment, management, and scaling of Kubernetes
clusters, allowing developers to focus on building
applications rather than managing infrastructure.

The following command demonstrates how to create a


Kubernetes cluster using Google Kubernetes Engine (GKE)
via the gcloud command-line tool.
[Code]

gcloud container clusters create my-cluster --num-nodes=3


--zone=us-central1-a
[Result]

Creating a cluster named "my-cluster" with 3 nodes in the


specified zone will be initiated. The output will include
details about the cluster creation process and the resources
allocated.

This command uses the Google Cloud SDK to create a


Kubernetes cluster in GKE. Key components of the command
include:
gcloud container clusters create: The command to create a
new Kubernetes cluster.
my-cluster: The name of the cluster being created.
--num-nodes=3: Specifies that the cluster should have three
nodes.
--zone=us-central1-a: Indicates the geographical zone
where the cluster will be deployed.
Managed services like GKE, EKS, and AKS handle many
operational tasks, such as upgrades, monitoring, and
scaling, which can significantly reduce the operational
burden on teams.

[Trivia]
Managed Kubernetes services often include built-in
integrations with other cloud services, such as storage and
networking, making it easier to build complex applications.
They typically provide automatic scaling features, allowing
clusters to adjust resources based on workload demands.
These services also enhance security by providing features
like automatic updates and built-in monitoring tools.
87
Introduction to Istio: Managing
Service-to-Service
Communication in Kubernetes
Istio is a service mesh that integrates with Kubernetes to
manage and control the communication between
microservices. It offers advanced traffic management,
security features, and observability for services running
within a Kubernetes cluster.

The following code demonstrates how to deploy Istio on a


Kubernetes cluster. It will guide you through the process of
installing Istio using the Istioctl command-line tool, which
helps in managing the Istio components.
[Code]

# Step 1: Download the Istio installation package


curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.18.0
sh -
# Step 2: Change to the Istio package directory
cd istio-1.18.0
# Step 3: Add the istioctl client to your path
export PATH=$PWD/bin:$PATH
# Step 4: Install Istio on your Kubernetes cluster
istioctl install --set profile=demo -y
# Step 5: Label the namespace where you want to deploy
your application
kubectl label namespace default istio-injection=enabled
# Step 6: Deploy a sample application
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.

[Result]

✔ Istio core installed


✔ Istiod installed
✔ Ingress gateways installed
✔ Installation complete

Istio adds an abstraction layer called a service mesh that


allows you to manage traffic between microservices. By
default, Kubernetes handles basic networking, but Istio
extends this with capabilities such as load balancing, fine-
grained routing, circuit breaking, and secure service-to-
service communication using mutual TLS (mTLS). When you
deploy Istio, it injects an Envoy proxy as a sidecar container
next to each microservice. These proxies intercept and
manage all network traffic entering and leaving the
service.Labeling a namespace with istio-injection=enabled
enables automatic sidecar injection for any pods created
within that namespace. This makes it easier to manage
complex microservice environments by providing
centralized control over network policies, security, and
observability without modifying the services themselves.

[Trivia]
Istio’s observability tools allow you to monitor and trace
service behavior across your entire application stack. This
includes automatic collection of metrics, logs, and traces.
The system integrates with popular tools like Prometheus,
Grafana, and Jaeger to provide deep insights into service
performance and issues.
88
Understanding Metrics Server in
Kubernetes for Resource
Monitoring
Metrics Server is a cluster-wide aggregator of resource
usage data in Kubernetes. It collects metrics like CPU and
memory usage from nodes and pods, providing the data
necessary for scaling operations and resource monitoring.

The following code demonstrates how to deploy Metrics


Server on a Kubernetes cluster. Metrics Server is essential
for enabling Horizontal Pod Autoscaler (HPA) and monitoring
the resource consumption of your workloads.
[Code]

# Step 1: Download the Metrics Server manifest


kubectl apply -f https://github.com/kubernetes-sigs/metrics-
server/releases/latest/download/components.
# Step 2: Verify that Metrics Server is running
kubectl get deployment metrics-server -n kube-system
# Step 3: View node metrics (optional)
kubectl top nodes
# Step 4: View pod metrics (optional)
kubectl top pods --all-namespaces

[Result]
NAME DESIRED CURRENT UP-TO-
DATE AVAILABLE AGE
metrics-
server 1 1 1 1 30s
If you run the optional
commands:NAME CPU(cores) CPU% MEMORY(bytes
) MEMORY%
node-1 250m 12% 500Mi 25%
node-2 300m 15% 550Mi 27%

Metrics Server is a lightweight, scalable metrics solution


used by Kubernetes to collect resource metrics, such as CPU
and memory usage, from the nodes and pods in the cluster.
Unlike more comprehensive monitoring solutions, Metrics
Server is designed to be a fast and simple way to provide
resource metrics for autoscaling and basic monitoring
purposes. It serves as the backend for the Kubernetes
Horizontal Pod Autoscaler (HPA), allowing the cluster to
automatically adjust the number of pods in a deployment
based on current resource utilization.Metrics Server does
not store historical data and is not intended to be used as a
full monitoring solution. For more detailed and historical
monitoring, tools like Prometheus are recommended.
However, Metrics Server is sufficient for real-time resource
management within Kubernetes.

[Trivia]
Metrics Server is not deployed by default in Kubernetes
clusters. It is also different from Heapster, an older tool that
was deprecated in favor of Metrics Server. Metrics Server
can be paired with Prometheus for more advanced
monitoring setups, where Prometheus can handle long-term
storage and complex querying of metrics data.
89
Monitoring Kubernetes Clusters
with Prometheus
Prometheus is a powerful open-source monitoring system
widely used to collect and store metrics from Kubernetes
clusters. It enables developers and operators to gain
insights into the performance and health of their
applications and infrastructure.

The following code demonstrates how to deploy Prometheus


in a Kubernetes cluster using a simple configuration file.
[Code]

apiVersion: v1
kind: Service
metadata:
name: prometheus
spec:
ports:
- port: 9090
targetPort: 9090
selector:
app: prometheus
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
containers:
- name: prometheus
image: prom/prometheus
ports:
- containerPort: 9090
args:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
- "--web.listen-address=:9090"
volumeMounts:
- name: config-volume
mountPath: /etc/prometheus
- name: data-volume
mountPath: /prometheus
volumes:
- name: config-volume
configMap:
name: prometheus-config
- name: data-volume
emptyDir: {}

[Result]

The deployment will create a Prometheus server accessible


at http://<your-kubernetes-node-ip>:9090.
This YAML configuration defines a Kubernetes Service and
Deployment for Prometheus. The Service exposes
Prometheus on port 9090, while the Deployment manages
the Prometheus container. The prometheus.yml file (not
shown here) should be configured to specify which metrics
to scrape. The emptyDir volume is used to store Prometheus
data temporarily.

[Trivia]
Prometheus uses a pull model to collect metrics, meaning it
scrapes data from targets at specified intervals. It supports
multi-dimensional data collection and querying, allowing
users to slice and dice metrics in various ways. Additionally,
Prometheus is designed to work seamlessly with
Kubernetes, automatically discovering services and
endpoints.
90
Visualizing Metrics with Grafana
Grafana is an open-source analytics and monitoring platform
that integrates well with Prometheus, allowing users to
create visually appealing dashboards to display metrics
collected from Kubernetes clusters.

The following code snippet illustrates how to deploy Grafana


in a Kubernetes environment, configured to use Prometheus
as its data source.
[Code]

apiVersion: v1
kind: Service
metadata:
name: grafana
spec:
ports:
- port: 3000
targetPort: 3000
selector:
app: grafana
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
spec:
replicas: 1
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana
image: grafana/grafana
ports:
- containerPort: 3000
env:
- name: GF_SECURITY_ADMIN_PASSWORD
value: "admin" # Default admin password

[Result]

The deployment will create a Grafana server accessible at


http://<your-kubernetes-node-ip>:3000, with the default
admin username as admin and the password as admin.

This YAML configuration sets up a Service and Deployment


for Grafana. The Service exposes Grafana on port 3000,
while the Deployment handles the Grafana container. The
environment variable GF_SECURITY_ADMIN_PASSWORD sets
the default admin password for Grafana. After deployment,
you can log in to Grafana and add Prometheus as a data
source to start visualizing metrics.

[Trivia]
Grafana supports a wide range of data sources beyond
Prometheus, including InfluxDB, Elasticsearch, and MySQL. It
provides powerful visualization capabilities, allowing users
to create graphs, heatmaps, and alerts. Grafana dashboards
can be shared and customized, making it a popular choice
for teams monitoring their applications and infrastructure.
91
Backing Up and Restoring
Kubernetes Clusters with Velero
Velero is a powerful open-source tool used for backing up,
restoring, and migrating Kubernetes clusters and persistent
volumes. It provides a reliable way to protect your
Kubernetes environment from accidental data loss or
disaster.

In the following example, we will walk through the basic


steps to install Velero and perform a backup and restore
operation on a Kubernetes cluster.
[Code]

# Install Velero on your local machine


velero install --provider aws --bucket <YOUR-BUCKET-
NAME> --secret-file ./credentials-velero --use-restic --
backup-location-config region=<YOUR-REGION>
# Create a backup of your Kubernetes cluster
velero backup create my-cluster-backup --include-
namespaces default
# Check the status of the backup
velero backup describe my-cluster-backup --details
# Restore the backup
velero restore create --from-backup my-cluster-backup

[Result]
The result will display the progress and completion status of
the backup and restore operations. For example, you may
see output like:Backup request "my-cluster-backup"
submitted successfully.
Run `velero backup describe my-cluster-backup` or `velero
backup logs my-cluster-backup` for details.
Restore request "restore-1" submitted successfully.
Run `velero restore describe restore-1` or `velero restore
logs restore-1` for details.

Velero supports multiple cloud providers, such as AWS,


Google Cloud, and Azure. The --provider option specifies
which cloud provider to use. You need to configure cloud-
specific credentials beforehand, typically by creating a
credentials file.The --use-restic flag is optional but
recommended if you want to back up persistent volumes.
Restic is an open-source backup tool that Velero uses for
volume backups.After submitting a backup request, Velero
will snapshot the specified namespaces or resources. The
snapshots are stored in the cloud storage bucket you
specified during installation. You can monitor the backup
and restore processes using velero backup describe and
velero restore describe.Restoring a backup replaces the
current state of the specified resources in your cluster with
the state from the backup, making it an essential tool for
disaster recovery.

[Trivia]
Velero was originally called "Heptio Ark" before being
renamed. It was created by Heptio, a company founded by
Kubernetes co-creators Joe Beda and Craig McLuckie, which
was later acquired by VMware. Velero is now maintained by
VMware and is one of the most widely used backup tools for
Kubernetes environments.
92
Running Security Checks on
Kubernetes with Kube-bench
Kube-bench is a tool that checks whether Kubernetes is
deployed securely by running checks defined in the CIS
(Center for Internet Security) Kubernetes Benchmark.

The following example demonstrates how to install and run


Kube-bench to perform security checks on your Kubernetes
cluster.
[Code]

# Install Kube-bench
curl -L https://github.com/aquasecurity/kube-
bench/releases/download/v0.6.5/kube-
bench_0.6.5_linux_amd64.tar.gz | tar -xz
chmod +x kube-bench
sudo mv kube-bench /usr/local/bin/
# Run Kube-bench to check your Kubernetes cluster security
kube-bench --config-dir cfg --config cfg/config.
# View the detailed report
cat kube-bench-results.json | jq .

[Result]

The result of running Kube-bench will be a detailed report


that lists each check, its status (pass/fail), and
recommendations for remediation. The output may look
something like this:[
{
"test_number": "1.1.1",
"test_desc": "Ensure that the API server pod specification
file permissions are set to 644 or more restrictive",
"audit": "stat -c %a /etc/kubernetes/manifests/kube-
apiserver.yaml",
"type": "file",
"result": "PASS"
},
{
"test_number": "1.1.2",
"test_desc": "Ensure that the API server pod specification
file ownership is set to root:root",
"audit": "stat -c %U:%G /etc/kubernetes/manifests/kube-
apiserver.yaml",
"type": "file",
"result": "FAIL",
"remediation": "chown root:root
/etc/kubernetes/manifests/kube-apiserver.yaml"
}
]

Kube-bench automates the security assessment process by


executing predefined checks based on the CIS Kubernetes
Benchmark. This benchmark is a set of best practices for
securing Kubernetes clusters, developed by experts from
the Center for Internet Security.Kube-bench checks various
aspects of a Kubernetes cluster, such as API server
configurations, etcd security, and worker node security.
Each check comes with a pass or fail status and remediation
steps if necessary.It is crucial to regularly run security
checks with Kube-bench, especially in production
environments, to ensure that your cluster remains secure
and compliant with best practices.Kube-bench is maintained
by Aqua Security, a company specializing in container
security. The tool is open-source and widely used in the
Kubernetes community for hardening cluster security.

[Trivia]
The CIS Kubernetes Benchmark is a comprehensive guide
with over 200 recommendations for securing Kubernetes. It
covers everything from API server configurations to network
policies. Adhering to these guidelines is essential for
maintaining a secure Kubernetes environment, particularly
in regulated industries where compliance is mandatory.
93
Understanding Kubernetes
RBAC: Roles and Bindings
Kubernetes Role-Based Access Control (RBAC) is a method
for regulating access to resources based on the roles of
individual users within an organization. It uses roles, role
bindings, cluster roles, and cluster role bindings to define
permissions.

The following code demonstrates how to create a role and a


role binding in Kubernetes, allowing specific users to access
certain resources within a namespace.
[Code]

# Define a role that allows reading pods in the 'default'


namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
# Define a role binding that assigns the role to a user
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: alice # The user who will be granted access
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io

[Result]

No output is generated directly from the creation of the role


and role binding. However, you can verify the creation by
running:
kubectl get roles -n default
kubectl get rolebindings -n default

In this example, we defined a Role named pod-reader that


allows the user to perform get and list operations on pods in
the default namespace. The RoleBinding named read-pods
associates this role with a user named alice. This means
that alice can now read the pods in the default namespace.
RBAC is crucial for maintaining security and ensuring that
users have only the permissions they need to perform their
tasks, minimizing the risk of unauthorized access.

[Trivia]
RBAC is a powerful feature in Kubernetes that helps manage
permissions effectively, especially in large teams or
organizations.
Cluster roles and cluster role bindings function similarly to
roles and role bindings but are applicable across all
namespaces, making them suitable for cluster-wide
permissions.
To check the permissions granted to a user, you can use the
command kubectl auth can-i get pods --as alice -n default.
94
Kubernetes Auditing: Tracking
Resource Access and
Modifications
Auditing in Kubernetes is a feature that logs requests made
to the API server, providing a way to track who accessed
what resources and when. This is essential for security and
compliance.

The following example shows how to enable auditing in


Kubernetes by configuring the audit policy and starting the
API server with the appropriate flags.
[Code]

# Define an audit policy file (audit-policy.yaml)


apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata # Log metadata for all requests
resources:
- group: ""
resources: ["pods"]
To start the API server with auditing enabled, you would add
the following flags:
--audit-policy-file=/etc/kubernetes/audit-policy.--audit-log-
path=/var/log/audit.log

[Result]
No direct output is generated from the audit policy
configuration. However, once the API server is running with
auditing enabled, you can check the audit log by viewing
the specified log file:
cat /var/log/audit.log

In this example, we created an audit policy that logs


metadata for all requests related to pods. The API server is
configured to use this policy and write logs to
/var/log/audit.log.
Auditing is crucial for understanding the actions taken
within your Kubernetes cluster, helping to identify potential
security issues or unauthorized access. The audit logs can
be analyzed to ensure compliance with organizational
policies and regulatory requirements.

[Trivia]
Kubernetes auditing can be configured to log different levels
of detail, including metadata, request bodies, and response
bodies, depending on the sensitivity of the data and the
needs of the organization.
You can analyze audit logs using various tools, including ELK
stack (Elasticsearch, Logstash, Kibana) for better
visualization and monitoring.
Auditing is a key component of security best practices in
Kubernetes, especially in production environments.
95
Kubernetes Secrets Are Base64-
Encoded, Not Encrypted
Kubernetes Secrets are a way to store sensitive information,
such as passwords, OAuth tokens, and SSH keys, in your
cluster. However, by default, these secrets are only base64-
encoded, which is not the same as encryption.

Below is an example that demonstrates how to create a


Kubernetes Secret and shows that the data is stored in
base64 format.
[Code]

# Create a secret
kubectl create secret generic my-secret --from-
literal=username=admin --from-
literal=password=secret123
# Retrieve the secret
kubectl get secret my-secret -o yaml

[Result]

apiVersion: v1
data:
password: c2VjcmV0MTIz
username: YWRtaW4=
kind: Secret
metadata:
name: my-secret
namespace: default
type: Opaque

The values in the data section (e.g., YWRtaW4= for


username) are base64-encoded strings. Although base64
encoding makes the data less readable, it is not secure
against attackers with access to the cluster. Base64
encoding is simply a way of representing binary data as
ASCII characters, and it can easily be decoded back into its
original form. This means that sensitive information stored
in Secrets is at risk if additional encryption methods are not
used.To secure secrets, Kubernetes supports using external
tools such as HashiCorp Vault, or encrypting secrets at rest
using Kubernetes' built-in encryption providers.
Implementing these measures ensures that your secrets are
actually encrypted, rather than just base64-encoded.

[Trivia]
Base64 encoding is often confused with encryption, but they
serve different purposes. Base64 is used for encoding binary
data into text, while encryption is a method of securing data
by converting it into a format that cannot be easily
understood without the proper decryption key.
96
Dynamic Storage Provisioning in
Kubernetes with StorageClasses
Kubernetes supports dynamic provisioning of storage,
allowing persistent volumes to be created automatically
when needed using StorageClasses. This feature simplifies
the management of storage resources by removing the
need for administrators to manually provision storage.

Below is an example of how to create a StorageClass and


dynamically provision a PersistentVolumeClaim (PVC) using
it.
[Code]

# Define a StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-storage
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
replication-type: none
---
# Create a PersistentVolumeClaim using the StorageClass
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: fast-storage

[Result]

If you apply these YAML files, Kubernetes will automatically


create a PersistentVolume that matches the specifications in
the PVC using the defined StorageClass.

The StorageClass defines the type of storage and other


parameters needed to provision the storage dynamically.
The provisioner field specifies the type of storage backend,
such as kubernetes.io/gce-pd for Google Compute Engine
Persistent Disks. When a PersistentVolumeClaim requests
storage with a specific StorageClass, Kubernetes
dynamically provisions a PersistentVolume that satisfies the
claim, making it available to the application.This approach
eliminates the need for pre-provisioning storage resources,
enabling a more flexible and automated way of managing
storage in a Kubernetes cluster.

[Trivia]
Dynamic provisioning allows for more efficient resource
utilization, as storage is allocated only when needed.
Additionally, by using different StorageClasses,
administrators can offer varying levels of performance and
redundancy, tailored to the specific needs of different
applications.
97
Understanding ClusterIP,
NodePort, and LoadBalancer in
Kubernetes
ClusterIP, NodePort, and LoadBalancer are service types in
Kubernetes that define how a service is exposed to the
network. They determine whether the service is accessible
only within the cluster, from outside, or through an external
load balancer.

This example will demonstrate how to create each type of


service and the behavior associated with each. We will use a
simple Nginx pod as the application.
[Code]

# nginx-deployment.apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
# clusterip-service.apiVersion: v1
kind: Service
metadata:
name: nginx-clusterip
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
---
# nodeport-service.apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30001
type: NodePort
---
# loadbalancer-service.apiVersion: v1
kind: Service
metadata:
name: nginx-loadbalancer
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer

[Result]

When you apply these configurations:The ClusterIP service


(nginx-clusterip) will only be accessible within the
Kubernetes cluster.The NodePort service (nginx-nodeport)
will be accessible via <NodeIP>:30001, allowing external
access using the node’s IP address.The LoadBalancer
service (nginx-loadbalancer) will provision an external IP
address (depending on your cloud provider), which can be
used to access the service.To check the services:kubectl get
services
This command will show the IP addresses and ports
assigned to each service.

ClusterIP is the default service type and is used for internal


communication within the cluster. It is not accessible from
outside the cluster.NodePort opens a specific port on all
nodes in the cluster and forwards traffic from that port to
the service. This type of service allows external traffic to
access a service by using the IP address of any node along
with the NodePort.LoadBalancer integrates with external
load balancers provided by cloud providers like AWS or GCP.
This service type automatically creates an external IP
address and sets up the necessary routing to forward traffic
to the service.It's essential to understand that using
NodePort or LoadBalancer might expose your application to
the internet, potentially introducing security risks if not
properly secured.Note: When using a LoadBalancer, the
actual external IP might take some time to provision, and it
can differ depending on the cloud provider.

[Trivia]
The ClusterIP service type is often used in conjunction with
an Ingress resource to manage external access to services
without exposing each one individually. An Ingress controller
can route traffic to different services based on the
requested hostnames or paths, offering more flexibility than
NodePort or LoadBalancer alone.
98
Advanced Networking with
Service Mesh: Using Linkerd
Service mesh tools like Linkerd enhance the networking
capabilities of Kubernetes by providing features such as
automatic retries, load balancing, and secure
communication between services. They operate at a layer
above the basic Kubernetes services.

In this example, we'll set up Linkerd on a Kubernetes cluster


and use it to manage traffic between two microservices: a
hello service and a world service.
[Code]

# Step 1: Install Linkerd CLI


curl -sL https://run.linkerd.io/install | sh
# Step 2: Validate your Kubernetes cluster
linkerd check --pre
# Step 3: Install Linkerd on the cluster
linkerd install | kubectl apply -f -
# Step 4: Validate the installation
linkerd check
# Step 5: Deploy sample services
kubectl create deployment hello --image=crccheck/hello-
world
kubectl create deployment world --image=crccheck/hello-
world
# Step 6: Inject Linkerd into the deployments
kubectl get deploy hello -o yaml | linkerd inject - | kubectl
apply -f -
kubectl get deploy world -o yaml | linkerd inject - | kubectl
apply -f -
# Step 7: Create services for both deployments
kubectl expose deployment hello --port=8080 --target-
port=8000
kubectl expose deployment world --port=8080 --target-
port=8000
# Step 8: View the Linkerd dashboard
linkerd viz dashboard &

[Result]

After running these commands:Linkerd will be installed and


running on your cluster.The hello and world services will be
deployed with Linkerd sidecars, enabling advanced
networking features.You can access the Linkerd dashboard
at http://localhost:50750 to observe the traffic between your
services, visualize latency, and identify any issues.Linkerd
will automatically manage traffic between these services,
applying retries and load balancing as needed.

A service mesh is a dedicated infrastructure layer for


managing service-to-service communication. It provides
advanced features like:Automatic retries: If a service fails,
the mesh can automatically retry the request.Load
balancing: Evenly distributes traffic across multiple service
instances.TLS encryption: Securely encrypts communication
between services.Observability: Provides detailed metrics
and traces for traffic between services.Linkerd works by
injecting a lightweight proxy (sidecar) into each service pod.
These proxies intercept and manage all network
communication, providing the features mentioned above
without requiring any changes to the application
code.Service meshes like Linkerd are particularly beneficial
in microservices architectures, where managing
communication between numerous services can become
complex and error-prone.

[Trivia]
Linkerd, originally developed by Buoyant, was the first
service mesh project to join the Cloud Native Computing
Foundation (CNCF). Unlike some other service meshes,
Linkerd focuses on simplicity, security, and speed, making it
a popular choice for those new to service meshes or running
smaller clusters.
99
Understanding Kubernetes
Versioning and Upgrade
Importance
Kubernetes uses a semantic versioning scheme (e.g., 1.x.y)
to manage its releases. Understanding this versioning
system is crucial for maintaining cluster stability and
ensuring compatibility with applications. Regular upgrades
are essential to benefit from new features, security patches,
and performance improvements.

The following code demonstrates how to check the current


version of your Kubernetes cluster and how to upgrade it.
[Code]

# Check the current version of Kubernetes


kubectl version --short
# Upgrade Kubernetes using kubeadm (example command)
sudo kubeadm upgrade plan

[Result]

Client Version: v1.24.0


Server Version: v1.23.5
Output of sudo kubeadm upgrade plan will vary based on
your cluster configuration and available upgrades.
Kubernetes versioning consists of three parts: major (1),
minor (x), and patch (y). For example, in version 1.24.0, "1"
is the major version, "24" is the minor version, and "0" is the
patch version. Major versions introduce breaking changes,
while minor versions add features and patches fix bugs.
Regular upgrades help ensure that your cluster remains
secure and efficient, as older versions may no longer
receive support or updates.

[Trivia]
Kubernetes follows a quarterly release cycle for minor
versions, and it is recommended to upgrade your cluster at
least once a year to stay current with the latest features and
security fixes. You can also use tools like kubeadm for
managing cluster upgrades, which provides a safe and
controlled upgrade path.
100
Kubernetes Controllers: The
Heart of Cluster Management
Kubernetes controllers are control loops that monitor the
state of your cluster and make necessary adjustments to
achieve the desired state defined by the user. They play a
vital role in maintaining the health and performance of
applications running in Kubernetes.

The following code illustrates how to create a simple


deployment, which is managed by a controller to ensure
that the specified number of replicas is running.
[Code]

# Create a deployment with 3 replicas


kubectl create deployment my-app --image=nginx --
replicas=3
# Check the status of the deployment
kubectl get deployments

[Result]

NAME READY UP-TO-DATE AVAILABLE AGE


my-app 3/3 3 3 1m

In this example, a deployment named "my-app" is created


with three replicas of the Nginx container. The deployment
controller continuously monitors the state of the application,
ensuring that three replicas are always running. If one of the
pods fails, the controller automatically creates a new pod to
replace it, thus maintaining the desired state. This self-
healing capability is a key feature of Kubernetes.

[Trivia]
There are various types of controllers in Kubernetes,
including ReplicaSets, Deployments, StatefulSets, and
DaemonSets. Each type serves a specific purpose, such as
managing stateless applications, stateful applications, or
ensuring that a pod runs on every node in the cluster.
Understanding how these controllers work is essential for
effectively managing applications in Kubernetes.
101
Kubernetes Multi-Tenancy:
Securely Sharing Clusters
Kubernetes supports multi-tenancy, allowing multiple users
or teams to share the same cluster while maintaining
security and resource isolation. This is essential for
organizations that want to maximize resource utilization
without compromising security.

The following example demonstrates how to create


namespaces in Kubernetes, which are a key component of
multi-tenancy. Namespaces allow you to isolate resources
and manage access controls effectively.
[Code]

# Create two namespaces for different teams


kubectl create namespace team-a
kubectl create namespace team-b
# Verify the namespaces have been created
kubectl get namespaces

[Result]

NAME STATUS AGE


default Active 10d
kube-system Active 10d
team-a Active 1s
team-b Active 1s
Namespaces in Kubernetes act like virtual clusters within a
physical cluster. Each namespace can have its own set of
resources, such as pods, services, and deployments. This
isolation helps prevent conflicts between teams and allows
for different resource quotas and policies to be applied. For
example, you can limit the amount of CPU and memory
each namespace can use, ensuring that one team's
workload does not starve another.

[Trivia]
Multi-tenancy is crucial for cloud environments where
multiple customers share the same infrastructure.
Kubernetes uses Role-Based Access Control (RBAC) to
manage permissions for users and groups within
namespaces, enhancing security.
You can also use Network Policies to control traffic between
pods in different namespaces.
102
Transition from Pod Security
Policies to Pod Security
Admission
Pod Security Policies (PSPs) were used to control the
security settings of pods in Kubernetes, but they have been
deprecated in favor of the Pod Security Admission (PSA)
mechanism. PSA provides a simpler and more effective way
to enforce security standards for pods.

The following example illustrates how to use Pod Security


Admission to enforce security contexts for pods. This
example will show how to apply a security level to a
namespace.
[Code]

# Define a namespace with a Pod Security Admission level


apiVersion: v1
kind: Namespace
metadata:
name: secure-namespace
annotations:
pod-security.kubernetes.io/enforce: privileged
# Apply the namespace configuration
kubectl apply -f namespace.
# Verify the applied annotations
kubectl get namespace secure-namespace -o
jsonpath='{.metadata.annotations}'
[Result]

map[pod-security.kubernetes.io/enforce:privileged]

Pod Security Admission allows you to enforce security


policies at the namespace level using annotations. In this
example, we set the pod-security.kubernetes.io/enforce
annotation to privileged, which means that only pods with
privileged security contexts can run in this namespace. This
is a shift from the more complex PSP system, making it
easier for cluster administrators to manage security without
needing to define detailed policies for every aspect of pod
security.

[Trivia]
The PSA mechanism provides three levels of security:
Privileged, Baseline, and Restricted, allowing for flexible
security implementations.
The transition from PSP to PSA was made to simplify
security management and reduce the overhead associated
with defining complex policies.
It is recommended to adopt the Restricted level for most
workloads to minimize security risks.
Afterword

As you reach the end of this journey, I want to take a


moment to express my gratitude for your time and
attention.
This book has been crafted specifically for those who
already possess a foundational understanding of
programming and are eager to delve into the essential
knowledge of Kubernetes.
By focusing solely on the fundamental aspects, I hope to
provide you with a streamlined learning experience that
allows you to grasp the core concepts without unnecessary
distractions.
Whether you are a newcomer to Kubernetes or a seasoned
professional looking to refresh your knowledge, this book
aims to serve your needs effectively.
Your feedback is incredibly important to me.
I would be grateful if you could take a moment to share your
thoughts.
If you're pressed for time, a simple star rating would mean
the world to me.
I read every review personally, and your insights have a
direct impact on my future work.
Have you found the information helpful? Did it spark your
interest? Or perhaps you felt it fell short of your
expectations? Whatever your experience, I welcome your
comments.
If there are topics you wish to see explored in future
publications, please don't hesitate to let me know.
I am committed to continually providing valuable content
that meets your needs, and your voice plays a crucial role in
that process.
Thank you for being a part of this journey, and I look forward
to connecting with you again in the future.
Your support is invaluable, and I am eager to hear what you
think!
Thank you once again for your engagement and
encouragement.

You might also like