DEV Community

janak0ff
janak0ff

Posted on

Set Resource Limits in Kubernetes Pods

The Nautilus DevOps team has noticed performance issues in some Kubernetes-hosted applications due to resource constraints. To address this, they plan to set limits on resource utilization. Here are the details:

Create a pod named httpd-pod with a container named httpd-container. Use the httpd image with the latest tag (specify as httpd:latest). Configure the following container-level resource requests and limits for the container:

Requests: Memory: 15Mi, CPU: 100m
Limits: Memory: 20Mi, CPU: 100m

Note: The kubectl utility on the jump-host has been configured to work with the Kubernetes cluster.


Mastering Kubernetes Resource Management: A Complete Guide to Setting Pod Limits

Introduction

Resource management is one of the most critical aspects of running applications in Kubernetes. Without proper resource limits, a single misbehaving application can consume all available cluster resources, causing performance degradation or complete failure of other applications. This is exactly the challenge the Nautilus DevOps team faced, and in this comprehensive guide, we'll explore how to solve it.

In this blog post, we'll walk through a real-world scenario of setting resource limits in Kubernetes pods, understanding the theory behind resource requests and limits, and learning best practices for production environments.


The Problem: Why Resource Limits Matter

Imagine this scenario: You're running multiple microservices in your Kubernetes cluster. One of them, let's say a logging agent, has a memory leak. Without resource limits, it will continue consuming memory until the node runs out of RAM, causing the entire node to fail and taking down all other applications running on it.

This is exactly the kind of problem the Nautilus DevOps team was facing. Their applications were experiencing performance issues due to resource constraints, and they needed a solution to prevent any single application from overwhelming the cluster.

Real-World Impact

Issue Without Limits With Limits
Memory Leak Node crashes, all pods affected Only the leaking pod is OOM-killed
CPU Spike Other applications starve Pod is throttled, others remain unaffected
Resource Exhaustion Cluster becomes unresponsive Resources are fairly distributed
Cost Over-provisioning leads to waste Efficient resource utilization

Understanding Resource Requests and Limits

Before diving into the implementation, let's understand the core concepts:

What are Resource Requests?

Requests are the minimum amount of resources a container needs to run. Kubernetes uses these for scheduling decisions.

resources:
  requests:
    memory: "15Mi"    # Minimum memory guaranteed
    cpu: "100m"       # Minimum CPU guaranteed (0.1 CPU core)
Enter fullscreen mode Exit fullscreen mode

What are Resource Limits?

Limits are the maximum amount of resources a container can use. If a container exceeds these limits:

  • Memory: The container will be terminated (OOMKilled)
  • CPU: The container will be throttled (slowed down)
resources:
  limits:
    memory: "20Mi"    # Maximum memory allowed
    cpu: "100m"       # Maximum CPU allowed (0.1 CPU core)
Enter fullscreen mode Exit fullscreen mode

Resource Units Explained

CPU Units:

  • 1 = 1 CPU core
  • 100m = 100 millicores (0.1 CPU core)
  • 500m = 500 millicores (0.5 CPU core)
  • 1000m = 1 CPU core

Memory Units:

  • Ki = Kibibyte (1024 bytes)
  • Mi = Mebibyte (1024 KiB)
  • Gi = Gibibyte (1024 Mi)
  • Ti = Tebibyte (1024 Gi)

Why Both Requests and Limits?

┌─────────────────────────────────────────┐
│          Node Resources                  │
│  ┌─────────────────────────────────────┐ │
│  │      Total Available                │ │
│  │  ┌───────┐  ┌───────┐  ┌───────┐  │ │
│  │  │ App 1 │  │ App 2 │  │ App 3 │  │ │
│  │  │ R:15Mi│  │ R:10Mi│  │ R:20Mi│  │ │
│  │  │ L:20Mi│  │ L:15Mi│  │ L:25Mi│  │ │
│  │  └───────┘  └───────┘  └───────┘  │ │
│  └─────────────────────────────────────┘ │
└─────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode
  • Requests guarantee resources for scheduling
  • Limits prevent resource abuse
  • Together they ensure fair resource distribution

Step-by-Step Implementation

Prerequisites

  • Kubernetes cluster
  • kubectl configured on your jump-host
  • Basic understanding of Kubernetes concepts

Step 1: Generate the Pod YAML

First, let's generate a base YAML manifest:

kubectl run httpd-pod \
  --image=httpd:latest \
  --restart=Never \
  --dry-run=client -o yaml > httpd-pod.yaml
Enter fullscreen mode Exit fullscreen mode

Step 2: Edit the YAML to Add Resource Limits

Open the file and add the resource specifications:

nano httpd-pod.yaml
Enter fullscreen mode Exit fullscreen mode

Before:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: httpd-pod
  name: httpd-pod
spec:
  containers:
  - image: httpd:latest
    name: httpd-pod
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Never
status: {}
Enter fullscreen mode Exit fullscreen mode

After:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: httpd-pod
  name: httpd-pod
spec:
  containers:
  - image: httpd:latest
    name: httpd-container
    resources:
      requests:
        memory: "15Mi"
        cpu: "100m"
      limits:
        memory: "20Mi"
        cpu: "100m"
  dnsPolicy: ClusterFirst
  restartPolicy: Never
status: {}
Enter fullscreen mode Exit fullscreen mode

Step 3: Apply the Configuration

Create the pod with resource limits:

kubectl apply -f httpd-pod.yaml
Enter fullscreen mode Exit fullscreen mode

Expected output:

pod/httpd-pod created
Enter fullscreen mode Exit fullscreen mode

Step 4: Quick Verification

Check if the pod is running:

kubectl get pods
Enter fullscreen mode Exit fullscreen mode

Output:

NAME         READY   STATUS    RESTARTS   AGE
httpd-pod   1/1     Running   0          10s
Enter fullscreen mode Exit fullscreen mode

Verification and Validation

1. Using kubectl describe

Get detailed information about the pod:

kubectl describe pod httpd-pod
Enter fullscreen mode Exit fullscreen mode

Look for the resources section:

Containers:
  httpd-container:
    Container ID:   containerd://...
    Image:          httpd:latest
    State:          Running
    Limits:
      cpu:     100m
      memory:  20Mi
    Requests:
      cpu:     100m
      memory:  15Mi
Enter fullscreen mode Exit fullscreen mode

2. Using JSONPath

Extract specific resource values:

# CPU Request
kubectl get pod httpd-pod -o jsonpath='{.spec.containers[0].resources.requests.cpu}'
# Output: 100m

# Memory Request
kubectl get pod httpd-pod -o jsonpath='{.spec.containers[0].resources.requests.memory}'
# Output: 15Mi

# CPU Limit
kubectl get pod httpd-pod -o jsonpath='{.spec.containers[0].resources.limits.cpu}'
# Output: 100m

# Memory Limit
kubectl get pod httpd-pod -o jsonpath='{.spec.containers[0].resources.limits.memory}'
# Output: 20Mi
Enter fullscreen mode Exit fullscreen mode

3. Using YAML Output

View the full pod specification:

kubectl get pod httpd-pod -o yaml | grep -A 6 resources
Enter fullscreen mode Exit fullscreen mode

Expected output:

resources:
  limits:
    cpu: 100m
    memory: 20Mi
  requests:
    cpu: 100m
    memory: 15Mi
Enter fullscreen mode Exit fullscreen mode

4. Check Pod Events

Verify no resource-related errors:

kubectl get events --field-selector involvedObject.name=httpd-pod
Enter fullscreen mode Exit fullscreen mode

5. Comprehensive Verification Script

Here's a complete verification script:

#!/bin/bash
echo "=== Pod Resource Verification ==="
echo "Pod Status: $(kubectl get pod httpd-pod -o jsonpath='{.status.phase}')"
echo "CPU Request: $(kubectl get pod httpd-pod -o jsonpath='{.spec.containers[0].resources.requests.cpu}')"
echo "Memory Request: $(kubectl get pod httpd-pod -o jsonpath='{.spec.containers[0].resources.requests.memory}')"
echo "CPU Limit: $(kubectl get pod httpd-pod -o jsonpath='{.spec.containers[0].resources.limits.cpu}')"
echo "Memory Limit: $(kubectl get pod httpd-pod -o jsonpath='{.spec.containers[0].resources.limits.memory}')"
echo "QoS Class: $(kubectl get pod httpd-pod -o jsonpath='{.status.qosClass}')"
Enter fullscreen mode Exit fullscreen mode

Quality of Service (QoS) Classes Explained

Based on the resource requests and limits you set, Kubernetes assigns a QoS class to each pod. This determines the pod's priority when resources are scarce.

1. Guaranteed QoS (Highest Priority)

Conditions: Requests = Limits for ALL resources

resources:
  requests:
    cpu: "100m"
    memory: "15Mi"
  limits:
    cpu: "100m"
    memory: "15Mi"
Enter fullscreen mode Exit fullscreen mode

Characteristics:

  • Highest priority in the cluster
  • Least likely to be evicted
  • Best for critical applications

2. Burstable QoS (Medium Priority)

Conditions: Requests < Limits for at least one resource

resources:
  requests:
    cpu: "50m"
    memory: "10Mi"
  limits:
    cpu: "100m"
    memory: "20Mi"
Enter fullscreen mode Exit fullscreen mode

Characteristics:

  • Can use more resources when available
  • Moderate priority
  • Most common for production applications

3. BestEffort QoS (Lowest Priority)

Conditions: No requests or limits specified

resources: {}
Enter fullscreen mode Exit fullscreen mode

Characteristics:

  • Lowest priority
  • Most likely to be evicted
  • Only use for non-critical workloads

QoS Class Comparison

QoS Class CPU Memory Priority Use Case
Guaranteed Requests = Limits Requests = Limits Highest Critical apps (control plane, databases)
Burstable Requests < Limits Requests = Limits Medium Most production workloads
Burstable Requests = Limits Requests < Limits Medium Most production workloads
Burstable Requests < Limits Requests < Limits Medium Most production workloads
BestEffort No limits No limits Lowest Batch jobs, testing

Advanced Resource Management

1. Namespace-Level Resource Quotas

Limit total resources in a namespace:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: development
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "10"
Enter fullscreen mode Exit fullscreen mode

Apply the quota:

kubectl apply -f resource-quota.yaml
Enter fullscreen mode Exit fullscreen mode

View quota usage:

kubectl describe quota -n development
Enter fullscreen mode Exit fullscreen mode

2. Default Resource Limits with LimitRange

Set default resource limits for all pods in a namespace:

apiVersion: v1
kind: LimitRange
metadata:
  name: resource-limits
  namespace: development
spec:
  limits:
  - max:
      cpu: "500m"
      memory: "256Mi"
    min:
      cpu: "50m"
      memory: "64Mi"
    default:
      cpu: "200m"
      memory: "128Mi"
    defaultRequest:
      cpu: "100m"
      memory: "64Mi"
    type: Container
Enter fullscreen mode Exit fullscreen mode

Apply the limit range:

kubectl apply -f limit-range.yaml
Enter fullscreen mode Exit fullscreen mode

3. Pod with Multiple Containers

Different containers can have different resource limits:

apiVersion: v1
kind: Pod
metadata:
  name: multi-container-pod
spec:
  containers:
  - name: web-server
    image: httpd:latest
    resources:
      requests:
        cpu: "100m"
        memory: "64Mi"
      limits:
        cpu: "200m"
        memory: "128Mi"
  - name: logger
    image: busybox
    command: ["sh", "-c", "tail -f /dev/null"]
    resources:
      requests:
        cpu: "50m"
        memory: "32Mi"
      limits:
        cpu: "100m"
        memory: "64Mi"
Enter fullscreen mode Exit fullscreen mode

4. Horizontal Pod Autoscaler (HPA)

Automatically scale pods based on resource usage:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: httpd-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: httpd-deployment
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
Enter fullscreen mode Exit fullscreen mode

Monitoring Resource Usage

1. Using kubectl top

Monitor real-time resource usage:

# View pod resource usage
kubectl top pod httpd-pod

# View all pods resource usage
kubectl top pods

# View node resource usage
kubectl top nodes

# View with specific namespace
kubectl top pods -n production
Enter fullscreen mode Exit fullscreen mode

2. Setting Up Metrics Server

If kubectl top is not available:

# Install metrics server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# Verify installation
kubectl get deployment metrics-server -n kube-system
Enter fullscreen mode Exit fullscreen mode

3. Continuous Monitoring

# Monitor pod usage every 5 seconds
watch -n 5 'kubectl top pod httpd-pod'

# Monitor all pods in namespace
watch -n 5 'kubectl top pods -n production'

# Monitor node usage
watch -n 5 'kubectl top nodes'
Enter fullscreen mode Exit fullscreen mode

4. Using Prometheus and Grafana

For enterprise monitoring, set up Prometheus:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: httpd-monitor
spec:
  selector:
    matchLabels:
      app: httpd
  endpoints:
  - port: metrics
    interval: 30s
Enter fullscreen mode Exit fullscreen mode

Common Issues and Troubleshooting

Issue 1: Pod Stuck in Pending State

Error:

0/1 nodes are available: 1 Insufficient cpu
Enter fullscreen mode Exit fullscreen mode

Solution:

# Check node resources
kubectl describe nodes

# Check pod events
kubectl describe pod httpd-pod | grep -A 10 Events

# Reduce resource requests
kubectl patch pod httpd-pod -p '{"spec":{"containers":[{"name":"httpd-container","resources":{"requests":{"cpu":"50m","memory":"10Mi"}}}]}}'
Enter fullscreen mode Exit fullscreen mode

Issue 2: Container Terminated with OOMKilled

Error:

State: Terminated
Reason: OOMKilled
Enter fullscreen mode Exit fullscreen mode

Solution:

# Check pod status
kubectl get pod httpd-pod

# View termination reason
kubectl describe pod httpd-pod | grep -A 5 "State"

# Increase memory limit
kubectl patch pod httpd-pod -p '{"spec":{"containers":[{"name":"httpd-container","resources":{"limits":{"memory":"256Mi"}}}]}}'

# Or check for memory leaks in the application
kubectl logs httpd-pod --previous
Enter fullscreen mode Exit fullscreen mode

Issue 3: CPU Throttling

Symptoms:

  • Application performance degradation
  • Increased response times

Diagnosis:

# Check CPU usage
kubectl top pod httpd-pod

# Check CPU throttling from inside container
kubectl exec httpd-pod -- cat /sys/fs/cgroup/cpu/cpu.stat
Enter fullscreen mode Exit fullscreen mode

Solution:

# Increase CPU limit
kubectl patch pod httpd-pod -p '{"spec":{"containers":[{"name":"httpd-container","resources":{"limits":{"cpu":"200m"}}}]}}'
Enter fullscreen mode Exit fullscreen mode

Issue 4: Resource Quota Exceeded

Error:

error: failed to create: pods "httpd-pod" is forbidden: exceeded quota: compute-quota
Enter fullscreen mode Exit fullscreen mode

Solution:

# Check current quota usage
kubectl describe resourcequota compute-quota -n development

# Either reduce resource requests or increase quota
kubectl patch resourcequota compute-quota -n development -p '{"spec":{"hard":{"requests.cpu":"8"}}}'
Enter fullscreen mode Exit fullscreen mode

Issue 5: Pod Not Respecting Limits

Verification:

# Check if limits are properly applied
kubectl exec httpd-pod -- cat /sys/fs/cgroup/memory/memory.limit_in_bytes
kubectl exec httpd-pod -- cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us
Enter fullscreen mode Exit fullscreen mode

Best Practices for Production

✅ DO's

1. Always Set Both Requests and Limits

# GOOD - Both set
resources:
  requests:
    cpu: "100m"
    memory: "64Mi"
  limits:
    cpu: "200m"
    memory: "128Mi"

# BAD - No resources set
resources: {}
Enter fullscreen mode Exit fullscreen mode

2. Use Appropriate Resource Values

Application Type CPU Request CPU Limit Memory Request Memory Limit
Static Web 50m 100m 10Mi 20Mi
API Service 100m 200m 64Mi 128Mi
Database 500m 1000m 1Gi 2Gi
Data Processing 500m 2000m 2Gi 4Gi

3. Implement Liveness and Readiness Probes

livenessProbe:
  httpGet:
    path: /health
    port: 80
  initialDelaySeconds: 30
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /ready
    port: 80
  initialDelaySeconds: 15
  periodSeconds: 5
Enter fullscreen mode Exit fullscreen mode

4. Use Namespace Defaults

Create LimitRange and ResourceQuota at the namespace level:

apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
spec:
  limits:
  - default:
      cpu: 200m
      memory: 128Mi
    defaultRequest:
      cpu: 100m
      memory: 64Mi
    type: Container
Enter fullscreen mode Exit fullscreen mode

5. Monitor Resource Usage Regularly

# Regular monitoring
kubectl top pods

# Setup alerts for resource thresholds
# Use monitoring tools like Prometheus, Grafana, or Datadog
Enter fullscreen mode Exit fullscreen mode

6. Test Resource Limits in Staging

Always test resource limits in a staging environment before production:

# Test memory limit
kubectl exec httpd-pod -- /bin/bash -c "dd if=/dev/zero of=/dev/null bs=1M count=100"

# Test CPU limit
kubectl exec httpd-pod -- /bin/bash -c "while true; do :; done"
Enter fullscreen mode Exit fullscreen mode

7. Document Resource Requirements

Create a document specifying resource requirements for each microservice:

Microservice: httpd-web
CPU Request: 100m
CPU Limit: 200m
Memory Request: 64Mi
Memory Limit: 128Mi
Reason: Average load is 50m CPU and 32Mi memory
Enter fullscreen mode Exit fullscreen mode

❌ DON'Ts

1. Don't Use :latest Tag in Production

# BAD - Unpredictable versions
image: httpd:latest

# GOOD - Specific version
image: httpd:2.4.54
Enter fullscreen mode Exit fullscreen mode

2. Don't Overcommit Resources

# BAD - Limits exceed node capacity
resources:
  limits:
    cpu: "4"
    memory: "16Gi"

# GOOD - Appropriate limits
resources:
  limits:
    cpu: "1"
    memory: "2Gi"
Enter fullscreen mode Exit fullscreen mode

3. Don't Set Requests Too High

# BAD - Wastes resources
requests:
  cpu: "2"
  memory: "4Gi"
# Actual usage: 50m CPU, 128Mi memory

# GOOD - Realistic requests
requests:
  cpu: "100m"
  memory: "256Mi"
Enter fullscreen mode Exit fullscreen mode

4. Don't Ignore Memory Limits

Memory is a more critical resource than CPU:

  • CPU overuse → throttling
  • Memory overuse → OOM kill
# GOOD - Memory limits set
resources:
  limits:
    memory: "128Mi"

# BAD - Missing memory limits
resources:
  limits:
    cpu: "100m"
Enter fullscreen mode Exit fullscreen mode

5. Don't Use Burstable for Critical Apps

For critical applications, use Guaranteed QoS:

# GOOD - Guaranteed QoS (for critical apps)
requests:
  cpu: "100m"
  memory: "128Mi"
limits:
  cpu: "100m"
  memory: "128Mi"

# BAD - Burstable (for critical apps)
requests:
  cpu: "50m"
  memory: "64Mi"
limits:
  cpu: "100m"
  memory: "128Mi"
Enter fullscreen mode Exit fullscreen mode

Real-World Examples

Example 1: E-commerce Application

apiVersion: v1
kind: Pod
metadata:
  name: web-frontend
  namespace: production
  labels:
    app: ecommerce
    tier: frontend
spec:
  containers:
  - name: nginx
    image: nginx:1.21.6
    ports:
    - containerPort: 80
    resources:
      requests:
        cpu: "100m"
        memory: "128Mi"
      limits:
        cpu: "200m"
        memory: "256Mi"
    livenessProbe:
      httpGet:
        path: /health
        port: 80
      initialDelaySeconds: 20
      periodSeconds: 10
    readinessProbe:
      httpGet:
        path: /ready
        port: 80
      initialDelaySeconds: 10
      periodSeconds: 5
Enter fullscreen mode Exit fullscreen mode

Example 2: Data Processing Application

apiVersion: v1
kind: Pod
metadata:
  name: data-processor
  namespace: production
  labels:
    app: data-pipeline
    tier: backend
spec:
  containers:
  - name: processor
    image: data-processor:2.1.0
    resources:
      requests:
        cpu: "500m"
        memory: "2Gi"
      limits:
        cpu: "1000m"
        memory: "4Gi"
    env:
    - name: JVM_OPTS
      value: "-Xmx3g -Xms1g"
    volumeMounts:
    - name: data
      mountPath: /data
  restartPolicy: Always
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: data-pvc
Enter fullscreen mode Exit fullscreen mode

Example 3: Microservices with Different Requirements

apiVersion: apps/v1
kind: Deployment
metadata:
  name: microservice-app
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: microservice
  template:
    metadata:
      labels:
        app: microservice
    spec:
      containers:
      # API Gateway (lightweight)
      - name: api-gateway
        image: api-gateway:1.0.0
        resources:
          requests:
            cpu: "50m"
            memory: "64Mi"
          limits:
            cpu: "100m"
            memory: "128Mi"

      # User Service (medium)
      - name: user-service
        image: user-service:1.0.0
        resources:
          requests:
            cpu: "100m"
            memory: "256Mi"
          limits:
            cpu: "200m"
            memory: "512Mi"

      # Search Service (heavy)
      - name: search-service
        image: search-service:1.0.0
        resources:
          requests:
            cpu: "500m"
            memory: "1Gi"
          limits:
            cpu: "1000m"
            memory: "2Gi"
Enter fullscreen mode Exit fullscreen mode

Capacity Planning and Right-Sizing

Step 1: Monitor Current Usage

# Monitor for a week to understand patterns
kubectl top pod --all-namespaces --no-headers > resource-usage.log
Enter fullscreen mode Exit fullscreen mode

Step 2: Analyze Usage Patterns

#!/usr/bin/env python3
import json
import subprocess

# Get pod resource usage
def get_pod_usage():
    cmd = "kubectl top pods --all-namespaces -o json"
    output = subprocess.check_output(cmd, shell=True)
    data = json.loads(output)

    for item in data['items']:
        name = item['metadata']['name']
        namespace = item['metadata']['namespace']
        cpu = item['containers'][0]['usage']['cpu']
        memory = item['containers'][0]['usage']['memory']
        print(f"{namespace}/{name}: CPU={cpu}, Memory={memory}")
Enter fullscreen mode Exit fullscreen mode

Step 3: Set Appropriate Requests and Limits

Based on usage patterns:

Metric Request Limit
CPU Average + 10% Peak + 20%
Memory Average + 20% Peak + 30%

Step 4: Validate with Load Testing

# Test with increased load
kubectl run load-test --image=busybox --rm -it -- /bin/sh

# Inside the container:
wget -O /dev/null http://httpd-pod:80/index.html
# Or use tools like Apache Bench
ab -n 10000 -c 100 http://httpd-pod:80/
Enter fullscreen mode Exit fullscreen mode

Advanced: Resource Quotas and Limit Ranges

Complete Namespace Configuration

---
# Namespace
apiVersion: v1
kind: Namespace
metadata:
  name: development
  labels:
    environment: dev
    owner: engineering
---
# Resource Quota
apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: development
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "20"
    persistentvolumeclaims: "5"
---
# Limit Range
apiVersion: v1
kind: LimitRange
metadata:
  name: dev-limits
  namespace: development
spec:
  limits:
  - max:
      cpu: "500m"
      memory: "256Mi"
    min:
      cpu: "50m"
      memory: "64Mi"
    default:
      cpu: "200m"
      memory: "128Mi"
    defaultRequest:
      cpu: "100m"
      memory: "64Mi"
    type: Container
---
# Network Policy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: dev-network-policy
  namespace: development
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          environment: dev
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          environment: dev
Enter fullscreen mode Exit fullscreen mode

Security Implications of Resource Limits

Preventing Resource Exhaustion Attacks

apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  containers:
  - name: app
    image: app:1.0
    resources:
      requests:
        cpu: "100m"
        memory: "128Mi"
      limits:
        cpu: "200m"
        memory: "256Mi"
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop:
        - ALL
        add:
        - NET_BIND_SERVICE
      runAsNonRoot: true
      runAsUser: 1000
Enter fullscreen mode Exit fullscreen mode

Best Practices for Security

  1. Set CPU limits to prevent CPU starvation attacks
  2. Set memory limits to prevent memory exhaustion attacks
  3. Use LimitRanges to enforce limits at the namespace level
  4. Implement ResourceQuotas to limit total consumption
  5. Use PodSecurityPolicies to restrict privileged containers
  6. Monitor resource usage for unusual patterns
  7. Set appropriate requests to prevent scheduling on nodes with insufficient resources

Troubleshooting Resource Issues

Common Error Messages

Error Cause Solution
0/1 nodes are available: 1 Insufficient cpu Not enough CPU Reduce CPU requests or add nodes
0/1 nodes are available: 1 Insufficient memory Not enough memory Reduce memory requests or add nodes
The pod was OOMKilled Exceeded memory limit Increase memory limit or optimize app
Container is being throttled CPU limit too low Increase CPU limit
exceeded quota Resource quota exceeded Reduce resource requests or increase quota
pod stuck in Pending Various scheduling issues Check node resources and events

Debugging Commands

# Check node capacity
kubectl describe nodes

# Check node resource usage
kubectl top nodes

# Check pod events
kubectl describe pod httpd-pod

# Check all events
kubectl get events --sort-by='.lastTimestamp'

# Check resource usage
kubectl top pod httpd-pod

# Check container logs
kubectl logs httpd-pod --previous
Enter fullscreen mode Exit fullscreen mode

Clean Up

# Delete the pod
kubectl delete pod httpd-pod

# Delete using YAML
kubectl delete -f httpd-pod.yaml

# Delete namespace and all resources
kubectl delete namespace development

# Verify cleanup
kubectl get pods --all-namespaces
Enter fullscreen mode Exit fullscreen mode

Conclusion

Resource management is a fundamental skill for any Kubernetes administrator or DevOps engineer. By properly setting resource requests and limits, you can:

Prevent resource starvation - Ensure fair distribution of cluster resources
Improve cluster stability - Prevent a single application from impacting others
Optimize costs - Right-size your applications for efficient resource utilization
Ensure predictable performance - Guarantee resources for critical applications
Implement proper scheduling - Help Kubernetes make better placement decisions

Top comments (0)