Kubernetes Objects - Probes, Resource Limits, Environment Variables
Overview
Kubernetes provides comprehensive mechanisms for monitoring application health, managing resource consumption, and configuring runtime environments. This document covers the essential components for ensuring application reliability and performance.
Liveness Probes
Purpose
Applications running inside containers may not function correctly despite appearing operational. If a running application hasn't crashed or shut down but isn't performing its intended function, kubelet cannot detect this issue automatically.
Liveness probes enable organizations to determine whether containers are functioning correctly by sending HTTP requests, establishing TCP connections, or executing commands within containers.
Implementation Methods
liveness_probe.yaml
# HTTP GET request example
# If it returns 200 or above, it's successful!
# If not, kubelet will restart the container
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness
args:
- /server
livenessProbe:
httpGet: # We're sending a GET request
path: /healthz # Path definition
port: 8080 # Port definition
httpHeaders: # Optional headers for the GET request
- name: Custom-Header
value: Awesome
initialDelaySeconds: 3 # The application may not start immediately,
# send the request after x seconds of running
periodSeconds: 3 # How frequently this request will be sent
# (health check is performed continuously)
---
# Command execution example
# If exit code -1 is received, the container is restarted
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: k8s.gcr.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec: # Command is executed
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
---
# TCP connection example
# If successful, it continues; otherwise, the container is restarted
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: k8s.gcr.io/goproxy:0.1
ports:
- containerPort: 8080
livenessProbe: # TCP connection is created
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
Readiness Probes
Deployment Update Process
When a deployment is updated (e.g., with a new image version), Kubernetes follows this sequence:
- Deployment Update: The deployment is updated with the new image (e.g., "v2")
- New Pod Creation: A new Pod with the updated image (v2) is created
- Pod Startup: The new Pod (v2) starts running
- Readiness Probe Activation: The readiness check mechanism begins after the
initialDelaySecondsperiod - First Health Check: The readiness probe performs its first check
- Service Integration: Once the check passes, the new Pod (v2) is added to the service
- Traffic Switch: At this point, the old Pod (v1) is removed from the service, but it's not terminated yet
- Graceful Shutdown: The old Pod (v1) continues processing any existing requests
- Termination Signal: Kubernetes sends a SIGTERM signal to allow the Pod to shut down gracefully
- Pod Termination: After completing its processes, the old Pod (v1) terminates itself
Use Case
Consider a system with 3 Pods and 1 LoadBalancer service. After making an update with a new image, old Pods are removed from service and new ones are added. From the moment new Pods are integrated, the LoadBalancer starts directing incoming traffic. However, applications may need to connect to external services, pull data, process it, and then become operational when they first start. During this initialization period, incoming requests won't be answered correctly. In essence, the application is running but not ready to provide service.
Solution: Kubelet uses Readiness Probes to determine when a container is ready to accept traffic (initial status). If all containers in a Pod pass the Readiness Probes check, the Service is added behind the Pod.
Operational Behavior
In the example above, when new images are created, old Pods are not immediately terminated. This is because there may be previously received requests and ongoing processes. For this reason, Kubernetes first severs the Pod's relationship with the service, preventing it from receiving new requests, and waits for existing internal requests to complete.
terminationGracePeriodSeconds: 30 → Existing processes complete, wait 30 seconds, then close. (30 seconds is the
default setting and is generally sufficient.)
Key Difference: Readiness probes focus on the initial operational moment, while Liveness probes continuously check whether the application is functioning properly.
Example: Consider a Backend application that needs time to connect to MongoDB when it first starts. It makes sense for the Service to be added behind the Pod only after the MongoDB connection is established. For this reason, readiness probes are used in this scenario.
Configuration
Readiness probes support three different methods, similar to Liveness probes:
- HTTP GET requests, TCP connections, and command execution
readiness_probe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
team: development
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: ozguryazilimci/k8s:blue
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /healthcheck
port: 80
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready # A request is sent to this endpoint; if it returns OK, the application is ready
port: 80
initialDelaySeconds: 20 # First check is made after 20 seconds delay from startup
periodSeconds: 3 # Continues trying every 3 seconds
terminationGracePeriodSeconds: 50 # Explanation provided above
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
app: frontend
ports:
- protocol: TCP
port: 80
targetPort: 80
Resource Limits
Purpose
Resource limits allow organizations to manage CPU and Memory restrictions for Pods. Unless specified otherwise, Pods can utilize 100% of the CPU and Memory of the machine they run on in Kubernetes. This situation can create resource contention issues. For this reason, organizations can specify how much CPU and Memory Pods will use.
CPU Configuration

Memory Configuration

YAML Configuration
apiVersion: v1
kind: Pod
metadata:
labels:
test: requestlimit
name: requestlimit
spec:
containers:
- name: requestlimit
image: ozguryazilimci/stress
resources:
requests: # Minimum requirements needed for the Pod to function
memory: "64M" # This Pod needs at least 64M memory
cpu: "250m" # = Quarter CPU core = "0.25"
limits: # Maximum limits for the Pod to function
memory: "256M"
cpu: "0.5" # = Half CPU Core = "500m"
Important Notes:
- If requirements cannot be met, the container cannot be created
- Memory behaves differently than CPU. Kubernetes doesn't block when memory requests exceed limits. If memory usage exceeds limits, the Pod enters "OOMKilled" state and is restarted
Environment Variables
Purpose
Consider a scenario where a Node.js server is created and database information is stored directly in server files. If the container image created from these server files falls into unauthorized hands, a major security vulnerability occurs. For this reason, Environment Variables must be used.
Configuration
apiVersion: v1
kind: Pod
metadata:
name: envpod
labels:
app: frontend
spec:
containers:
- name: envpod
image: ozguryazilimci/env:latest
ports:
- containerPort: 80
env:
- name: USER # First we specify the name
value: "TestName" # Then we specify the value
- name: database
value: "testdb.example.com"
Management Operations
Viewing Environment Variables:
kubectl exec <podName> -- printenv
Accessing Applications:
kubectl port-forward pod/envpod 8080:80
Then open localhost:8080 in your browser.