Working with Pods
Estimated time to read: 11 minutes
Introduction
Pods are the Smallest Deployable Units of computing that can be created and managed in Kubernetes. Pods with super-powers such as self-healing, scaling, updates and rollbacks. Some quick examples If we want to deploy an app, you deploy it in a Pod. If you terminate an app, you terminate its Pod. If you scale an app up or down, you add or remove Pods.
Why Pods ?
- Write your app/code
- Package it as a container image
- Wrap the container image in a Pod
- Run it on Kubernetes
Note: Kubernetes doesn’t allow containers to run directly on a cluster, they always have to be wrapped in a Pod.
- Pods augment containers
- Pods assist in scheduling
- Pods enable resource sharing
Pods augment containers
- Labels and annotations
- Restart policies
- Probes (startup probes, readiness probes, liveness probes, and potentially more)
- Affinity and anti-affinity rules
- Termination control
- Security policies
- Resource requests and limits
Deploy Pod using Imperative method Deploy a Pod using Declarative method Generate the pod manifest in the YAML and JSON format Reading the Pod's information and metadata Listing the objects output in JSON or YAML format Entering into a container in a Pod Static Pod Multi-Container Pod Sidecar Container Deleting a Pod
Imperative Method
-
Create a pod with Imperative Method
Introspecting running Pods
-
List the pod status
-
List Pods with wide option -o wide gives a couple more columns but is still a single line of output
-
Get complete pod in details
-
Deleting a Pod
Declarative Method
For the declarative method, we use YAML (Yet Another Markup Language) files to present the configuration of what we desire to be the end product.
Run a kubectl explain pods command to list all possible Pod attributes.
Beware, the command returns over 1,000 lines and the following output has been trimmed.
Pod manifest files
In order to create a pod using a declarative method, we need to create a yaml file and prepare a template. Example Configuration
---
apiVersion: v1
kind: Pod
metadata:
name: firstpod
spec:
containers:
- name: nginx
image: nginx:latest
-
The .apiVersion defines the schema version to use when creating the object. This file is defining a Pod object and telling Kubernetes to build it using the v1 Pod schema.
-
The normal format for apiVersion is api-group/version
-
However, Pods are defined in a special API group called the core group which omits the api-group part.
-
For example, StorageClass objects are defined in the v1 schema of the storage.k8s.io API group and are described in YAML files as storage.k8s.io/v1.
-
-
The .kind field tells Kubernetes the type of object being defined. This file is defining a Pod object.
- The .metadata section is where you attach things such as names, labels, annotations, and a Namespace.
- The .spec section is where you define the containers the Pod will run. This is called the Pod template, and this example is defining a single-container Pod based on the nginx:latest image.
Dry Run
A dry run is a way to simulate the execution of a command without actually applying any changes.
You can use the --dry-run
flag with various kubectl
commands to perform a dry run. As of Kubernetes 1.18 and later, the --dry-run
flag has been updated to take two options: client
and server
.
-
--dry-run=client
: This performs the dry run on the client side without sending the request to the API server. This was the default behavior in Kubernetes 1.17 and earlier. -
--dry-run=server
: This performs the dry run on the server side, meaning it sends the request to the API server, which then validates the request and simulates the changes without persisting them. This is the preferred option in newer versions, as it provides more accurate validation.
Dry Run Benefits
- Validation: Ensure your manifests are correct and will be accepted by the API server.
- Safety: Avoid unintended changes to the live environment.
- Automation: Use dry runs as part of CI/CD pipelines to validate configurations before deploying them.
Auto Generate Pod manifest files
we can generate the pod manifest in two different formats
- YML
- Json
Pod manifest in yml
-
Create a pod containing a nginx server using webserver1.yml file
Pod manifest in Json
-
Create a pod containing a httpd server using webserver2.json file
Labels
labels are key-value pairs that are attached to objects, such as Pods, Services, and Nodes. Labels are used to organize and select subsets of objects. They are a powerful way to manage and query resources in your Kubernetes cluster.
-
Key: A string that identifies the label. Keys can be up to 63 characters long, must begin and end with an alphanumeric character, and can include dashes (
-
), underscores (_
), and dots (.
). Optionally, keys can be prefixed with a domain name followed by a slash, allowing for more organizational control (e.g.,app.kubernetes.io/name
). -
Value: A string that is associated with the key. Values can be up to 63 characters long and must adhere to the same character rules as keys.
-
Selectors: Labels are often used in conjunction with selectors to query or filter resources. For example, you can create a Service that selects all Pods with a specific label.
Example Configuration
apiVersion: v1
kind: Pod
metadata:
name: podwithlabel
labels:
name: PodwithLabel
environment: production
tier: front-end
spec:
containers:
- name: nginx
image: nginx:latest
-
Create Pod without label:
-
Create pod with labels
-
list pods with labels
-
Add or override the labels to the existing pods
-
Listing Pods with a Specific Label
-
Delete pod with label
Note: Spin up
01-pod.yml
and02-PodwithLabel.yml
Common Uses of Labels to Organizing resources, Targeting resources, Filtering and Monitoring and Logging
Pod With Port Number
In Kubernetes, we can specify the port numbers to containers use within a Pod by defining them in the Pod's YAML manifest. This allows you to expose specific ports for your application to handle traffic.
apiVersion: v1
kind: Pod
metadata:
name: podwithport
labels:
name: PodwithPort
environment: production
tier: front-end
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Ports: A list of ports that the container will expose. ContainerPort: The port that the container will expose (80
for HTTP traffic in this example).
-
Create pod with container Single port number
-
Describe the pod
-
Create pod with container Multiple port number
-
Describe the pod
-
Get the Pod IP
-
Assign POD IP to Variable
Resource requests
- Resource Requests define the minimum amount of CPU or Memory that a container is guaranteed to have.
-
Kubernetes uses the request value to determine how to schedule the container onto a node. The scheduler ensures that the node has at least the requested amount of resources available.
Resource Limits
-
Resource Limits define the maximum amount of CPU or memory that a container is allowed to use.
-
If a container tries to use more than the limit, Kubernetes may throttle the CPU or, in the case of memory, terminate the container.
Example Configuration
apiVersion: v1
kind: Pod
metadata:
name: podwithresourcesrequest
labels:
name: podwithresourcesrequest
environment: production
tier: front-end
spec:
containers:
- name: podwithresourcesrequest
image: nginx
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- Requests:
memory: "64Mi"
means the container is guaranteed 64 MiB of memory.cpu: "250m"
means the container is guaranteed 250 millicores (0.25 of a CPU core).
- Limits:
memory: "128Mi"
means the container can use up to 128 MiB of memory.cpu: "500m"
means the container can use up to 500 millicores (0.5 of a CPU core).
Best Practices
-
Set Requests Based on Baseline Usage: Set resource requests based on the average resource usage of your application. This ensures that the application always gets the resources it needs to function properly.
-
Set Limits Based on Peak Usage: Set resource limits slightly above the expected peak usage to allow for short bursts of resource consumption without risking throttling or OOM kills.
-
Monitor and Adjust: Regularly monitor the resource usage of your applications and adjust the requests and limits as necessary to optimize performance and resource utilization.
Using resource requests and limits effectively ensures that your applications run smoothly, that resources are used efficiently, and that the cluster remains stable and performant.
Multi-Container Pod
Multi-container Pod in Kubernetes is a Pod that runs more than one container. These containers share the same network namespace, storage volumes, and can communicate with each other directly using localhost
. Multi-container Pods are typically used when you have tightly coupled processes that need to work together within the same Pod.
Why Use Multi-Container Pods?
Multi-container Pods are useful in scenarios where:
-
Sidecar Containers: A container that provides supporting functionality for the main application, such as logging, monitoring, or data synchronization.
-
Ambassador Containers: A container that acts as a proxy or helper for external communication, simplifying interactions with external services.
-
Adapter Containers: A container that modifies or adapts the output of another container, such as transforming logs or data.
Example Configuration
apiVersion: v1
kind: Pod
metadata:
name: multicontainerpod
spec:
containers:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
- name: sidecar-logger
image: busybox
command: ["sh", "-c", "while true; do echo $(date) - Log from sidecar; sleep 100; done"]
-
Create Multi-Container pod
-
Describe the multi container pod
-
Check the container logs
Use Cases
- Microservices: When you have two tightly coupled microservices that need to share resources or communicate frequently.
- Service Mesh: Sidecar containers are often used in service mesh architectures to handle networking tasks such as load balancing, traffic management, and security.
- Data Processing Pipelines: Where one container handles data ingestion, another processes the data, and yet another exports the processed data.
Connect to Container in a POD
To connect to a container within a Kubernetes Pod, you typically use the kubectl exec
command. This command allows you to run commands inside a container, effectively giving you access to the container's shell or to execute a specific command inside it.
-i
: Stands for "interactive." It keeps the session open, allowing you to interact with the container.-t
: Stands for "TTY." It allocates a terminal for the session, which is useful for running interactive commands like a shell.<pod-name>
: The name of the Pod you want to connect to.<command>
: The command you want to run inside the container, such assh
orbash
for a shell.
-
Execute some commands in Nginx container
-
Running individual commands in a Container
-
Specifying a Container in a Multi-Container Pod
If your Pod has multiple containers, you need to specify which container you want to connect to using the
-c
flag:
Clean up
-
[x] Remove the all pods at a time