Kubernetes Manifests
Introduction
Kubernetes manifests are YAML or JSON files that describe the desired state of resources in a Kubernetes cluster. They are the backbone of Kubernetes configuration, allowing you to define, create, and manage Kubernetes objects declaratively. In this guide, we'll explore what manifests are, their structure, and how to use them effectively.
Think of manifests as blueprints for your Kubernetes resources - they tell Kubernetes what you want to build and how you want it to look.
What Are Kubernetes Manifests?
Kubernetes manifests are declarative configuration files that define:
- What resources you want to create (Pods, Services, Deployments, etc.)
- What properties and configurations these resources should have
- How these resources should behave
Instead of telling Kubernetes how to create resources through a series of commands, manifests tell Kubernetes what resources should exist and their desired state. Kubernetes then works to ensure the actual state matches this desired state.
Manifest Structure
Most Kubernetes manifests are written in YAML format (though JSON is also supported). A basic manifest contains four required top-level fields:
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: nginx
image: nginx:1.17.3
Let's break down these core fields:
- apiVersion: Specifies which version of the Kubernetes API to use
- kind: Defines what type of resource you're creating
- metadata: Contains data that identifies the resource (name, labels, etc.)
- spec: Contains the desired state for the resource
Common Kubernetes Resource Types
Here are some of the most common resource types you'll define in manifests:
Resource | Description |
---|---|
Pod | The smallest deployable unit in Kubernetes |
Deployment | Manages a set of replicated Pods |
Service | Exposes Pods to network traffic |
ConfigMap | Stores configuration data |
Secret | Stores sensitive data (encrypted) |
PersistentVolumeClaim | Requests storage resources |
Namespace | Virtual cluster within a physical cluster |
Creating Your First Manifest
Let's create a simple manifest for a Deployment that runs an NGINX web server:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.17.3
ports:
- containerPort: 80
This manifest:
- Creates a Deployment resource named "nginx-deployment"
- Tells Kubernetes to create and maintain 3 replicas of the Pod
- Labels the Pods with
app: nginx
- Defines that each Pod should run the NGINX 1.17.3 container
- Specifies that the container listens on port 80
Applying Manifests
Once you've created a manifest file (e.g., deployment.yaml
), you can apply it to your cluster using the kubectl apply
command:
kubectl apply -f deployment.yaml
The output will look something like:
deployment.apps/nginx-deployment created
You can verify the deployment was created:
kubectl get deployments
Output:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 45s
Understanding More Complex Manifests
In real-world scenarios, you'll often create more complex manifests. Let's look at a more comprehensive example that includes a Deployment and a Service to expose it:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
labels:
app: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web-container
image: nginx:latest
ports:
- containerPort: 80
resources:
limits:
cpu: "0.5"
memory: "256Mi"
requests:
cpu: "0.2"
memory: "128Mi"
---
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80
type: ClusterIP
Key points about this example:
- The
---
separates different resources in the same file - We've added resource constraints for the container
- We've created a Service to expose the Deployment internally
- The Service targets Pods with the label
app: web
Manifest Validation
Before applying manifests, it's a good practice to validate them. You can use:
kubectl apply --dry-run=client -f your-manifest.yaml
This checks for syntax errors without actually creating resources.
For more detailed validation, you can use:
kubectl apply --server-side --dry-run=server -f your-manifest.yaml
This sends the manifest to the API server for validation without creating resources.
Working with Multiple Manifests
As your application grows, you'll have multiple manifests. There are several ways to organize them:
-
Multiple files: Create separate files for each resource type
bashkubectl apply -f deployment.yaml -f service.yaml
-
Directory: Organize manifests in a directory structure
bashkubectl apply -f ./my-app/
-
Kustomize: Use Kubernetes' built-in configuration customization tool
bashkubectl apply -k ./overlay/development/
Common Manifest Patterns
Environment Variables
apiVersion: v1
kind: Pod
metadata:
name: env-example
spec:
containers:
- name: nginx
image: nginx
env:
- name: DATABASE_URL
value: "postgres://user:password@localhost:5432/db"
- name: LOG_LEVEL
value: "info"
Using ConfigMaps
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database.url: "postgres://localhost:5432/db"
log.level: "debug"
---
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: app
image: myapp:1.0
envFrom:
- configMapRef:
name: app-config
Secret References
apiVersion: v1
kind: Pod
metadata:
name: secret-pod
spec:
containers:
- name: app
image: myapp:1.0
env:
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: db-secrets
key: password
Best Practices for Manifests
- Use version control: Store manifests in Git or another version control system
- Use namespaces: Organize resources into namespaces for better isolation
- Add labels and annotations: These help with resource organization and selection
- Keep manifests modular: Separate concerns into different files
- Use resource limits: Always specify CPU and memory limits
- Follow naming conventions: Use consistent naming for resources
- Document your manifests: Add comments to explain complex configurations
Visualizing Manifest Relationships
Troubleshooting Manifests
When applying manifests, you might encounter errors. Here are some common issues and solutions:
- YAML formatting: Ensure indentation is correct (YAML is whitespace-sensitive)
- API version mismatch: Verify the apiVersion is correct for your Kubernetes version
- Missing required fields: Check that all required fields are included
- Resource not found: Ensure the specified resource exists (for references)
- Permission issues: Verify you have the necessary permissions
Using Helm for Template-Based Manifests
While basic manifests are powerful, as applications grow more complex, consider using Helm, a package manager for Kubernetes that allows you to create reusable manifest templates.
# Install a Helm chart (template-based manifests)
helm install myapp ./mychart
Summary
Kubernetes manifests are the declarative way to define and manage Kubernetes resources. They allow you to:
- Define resources in a human-readable format (YAML or JSON)
- Describe the desired state rather than imperative commands
- Version control your infrastructure configuration
- Apply consistent configurations across environments
As you continue your Kubernetes journey, you'll create increasingly sophisticated manifests that define complex applications. The declarative approach used in manifests represents the true power of Kubernetes - letting you define what you want, not how to get there.
Exercises
- Create a manifest for a Pod running the
busybox
image that executes a command to print "Hello, Kubernetes!" - Build a manifest file that contains both a Deployment and a Service for a simple web application
- Create a ConfigMap with several key-value pairs and reference it in a Pod manifest
- Modify an existing manifest to add resource limits and requests
- Create a manifest that deploys an application with two different container images in the same Pod
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)