13 Kubernetes Tricks You Didn’t Know

DavidW (skyDragon)
overcast blog
Published in
10 min readFeb 26, 2024

--

Kubernetes, with its comprehensive ecosystem, offers numerous functionalities that can significantly enhance the management, scalability, and security of containerized applications. Below are 13 tricks, each detailed with a trick explanation, a usage example, contextual applications, and precautions to observe.

1. Graceful Pod Shutdown with PreStop Hooks

Trick: PreStop hooks allow for the execution of specific commands or scripts inside a pod just before it gets terminated. This capability is crucial for ensuring that applications shut down gracefully, saving state where necessary, or performing clean-up tasks to avoid data corruption and ensure a smooth restart.

Usage Example:

apiVersion: v1
kind: Pod
metadata:
name: graceful-shutdown-example
spec:
containers:
- name: sample-container
image: nginx
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 30 && nginx -s quit"]

This configuration ensures that the nginx server has 30 seconds to finish serving current requests before shutting down.

When to Use: Implement PreStop hooks in environments where service continuity is critical, and you need to ensure zero or minimal downtime during deployments, scaling, or pod recycling.

Be Careful Of: The termination grace period Kubernetes allows for a pod. If the PreStop hook script takes longer than this grace period, Kubernetes will forcibly terminate the pod, potentially leading to the very issues you’re trying to avoid.

2. Automated Secret Rotation with Kubelet

Trick: Kubernetes supports the automatic rotation of secrets without restarting the pods consuming these secrets. This feature is particularly useful for maintaining security standards by regularly changing sensitive information without impacting the application’s availability.

Usage Example: Assume you’ve updated a secret in Kubernetes. Kubernetes will update the mounted secrets in the pods without any intervention needed, ensuring that applications always have the latest credentials without manual updates or restarts.

When to Use: This feature is indispensable for applications that require high levels of security compliance, necessitating frequent secret rotations, such as database passwords, API keys, or TLS certificates.

Be Careful Of: Applications must be designed to dynamically read the updated secrets. Some applications cache secrets at startup, which means they won’t recognize updated secrets without a restart. Ensure your applications check for secret updates periodically or react to changes appropriately.

3. Debugging Pods with Ephemeral Containers

Trick: Ephemeral containers provide a way to temporarily attach a debug container to a running pod without changing its original specification. This is immensely helpful for debugging live issues in a production environment where you cannot afford to disrupt service.

Usage Example:

kubectl alpha debug -it podname --image=busybox --target=containername

This command adds a busybox container to your existing pod, allowing you to execute commands and inspect the pod's environment without altering its running state.

When to Use: Utilize ephemeral containers when diagnosing issues in a live environment, especially when standard logs and metrics do not provide enough information. It’s a powerful tool for real-time, in-depth analysis of production issues.

Be Careful Of: Since ephemeral containers can access the pod’s resources and sensitive data, use them judiciously, especially in production environments. Ensure only authorized personnel can deploy ephemeral containers to avoid potential security risks.

4. Horizontal Pod Autoscaling Based on Custom Metrics

Trick: Horizontal Pod Autoscaler (HPA) can scale your deployments based on custom metrics, not just standard CPU and memory usage. This is particularly useful for applications with scaling needs tied to specific business metrics or performance indicators, such as queue length, request latency, or custom application metrics.

Usage Example:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: custom-metric-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: your-application
minReplicas: 1
maxReplicas: 10
metrics:
- type: Pods
pods:
metric:
name: your_custom_metric
target:
type: AverageValue
averageValue: 10

This HPA configuration scales your application based on the average value of a custom metric your_custom_metric.

When to Use: Employ custom metric scaling for applications where traditional resource-based metrics do not accurately represent load or for fine-tuned scaling behavior based on business needs.

Be Careful Of: Setting up custom metrics involves integrating with a metrics server that supports custom metrics, such as Prometheus. Ensure your metrics are reliable indicators of load to prevent over or under-scaling.

5. Using Init Containers for Setup Scripts

Trick: Init containers run before the app containers in a pod and are perfect for setup scripts that need to run to completion before the app starts. This could include tasks like database migrations, configuration file creation, or waiting for an external service to become available. Init containers can run a sequence of setup tasks, ensuring that each step is successfully completed before the main application container starts.

Usage Example:

apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: myapp-container
image: myapp
initContainers:
- name: init-myservice
image: busybox
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']

This example uses an init container to wait until a service named myservice is available before starting the main application container.

When to Use: Init containers are invaluable when your application containers depend on external services or configurations being available before they start. They ensure your application starts with the environment already prepared.

Be Careful Of: The entire pod’s startup is blocked until all init containers complete successfully. Ensure that init containers are efficient and fail gracefully to prevent them from becoming a bottleneck or causing pod startup failures.

6. Node Affinity for Workload-Specific Scheduling

Trick: Node affinity allows you to specify rules that limit which nodes your pod can be scheduled on, based on labels on nodes. This is useful for directing workloads to nodes with specific hardware (like GPUs), ensuring data locality, or adhering to compliance and data sovereignty requirements.

Usage Example:

apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
containers:
- name: with-node-affinity
image: nginx
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd

This pod will only be scheduled on nodes with the label disktype=ssd.

When to Use: Use node affinity when your applications require specific node capabilities or when you need to control the distribution of workloads for performance optimization, legal, or regulatory reasons.

Be Careful Of: Overuse of node affinity can lead to poor cluster utilization and scheduling complexities. Ensure your cluster has a balanced distribution of labels and affinities to maintain efficient resource utilization.

7. Taints and Tolerations for Pod Isolation

Trick: Taints and tolerations work together to ensure pods are not scheduled onto inappropriate nodes. A taint on a node repels pods that do not tolerate that taint. Tolerations are applied to pods, allowing them to schedule on tainted nodes. This mechanism is essential for dedicating nodes to specific workloads, such as GPU-intensive applications or ensuring that only certain pods run on nodes with sensitive data.

Usage Example:

# Applying a taint to a node
kubectl taint nodes node1 key=value:NoSchedule
# Pod specification with toleration
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: nginx
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"

This setup ensures that mypod can be scheduled on node1, which has a specific taint that other pods cannot tolerate.

When to Use: Taints and tolerations are particularly useful in multi-tenant clusters, where isolating workloads is crucial for security or performance reasons. They are also beneficial for running specialized workloads that require dedicated resources.

Be Careful Of: Misconfiguring taints and tolerations can lead to scheduling issues, where pods are not scheduled as expected or some nodes are left underutilized. Regularly review your taints and tolerations setup to ensure it aligns with your scheduling requirements.

8. Pod Priority and Preemption for Critical Workloads

Trick: Kubernetes allows you to assign priorities to pods, and higher priority pods can preempt (evict) lower priority pods if necessary. This ensures that critical workloads have the resources they need, even in a highly congested cluster.

Usage Example:

# PriorityClass definition
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for XYZ service pods only."
# Pod specification with priorityClassName
apiVersion: v1
kind: Pod
metadata:
name: high-priority-pod
spec:
containers:
- name: high-priority
image: nginx
priorityClassName: high-priority

This configuration defines a high-priority class and assigns it to a pod, ensuring it can preempt other lower-priority pods.

When to Use: Use pod priority and preemption for applications that are critical to your business operations, especially when running in clusters where resource contention is common.

Be Careful Of: Improper use can lead to resource starvation of less critical applications. It’s essential to balance the needs of different workloads and consider the overall impact on cluster health and application performance.

9. ConfigMaps and Secrets for Dynamic Configuration

Trick: ConfigMaps and Secrets provide mechanisms to inject configuration data into pods. This allows for the externalization of configuration, making applications easier to configure without the need for hard-coding configuration data. ConfigMaps are ideal for non-sensitive data, while Secrets are intended for sensitive data.

Usage Example:

# ConfigMap Example
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
config.json: |
{
"key": "value",
"databaseURL": "http://mydatabase.example.com"
}
# Pod Spec using ConfigMap
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: myapp-container
image: myapp
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config

This configuration injects the contents of app-config into the pod, allowing the application to read its configuration from /etc/config/config.json.

When to Use: Whenever you need to externalize your application’s configuration or secret data, making it easier to manage, update, and maintain without rebuilding your container images.

Be Careful Of: While ConfigMaps are excellent for storing non-sensitive data, avoid using them for any data that should be kept secure. Always use Secrets for passwords, tokens, keys, and other sensitive data, and be aware of best practices for securing Secrets, such as encrypting them at rest.

10. Kubectl Debug for Direct Container Debugging

Trick: kubectl debug provides a way to create a temporary duplicate of a pod and replace its containers with debug versions or add new troubleshooting tools without affecting the original pod. This is incredibly useful for debugging issues in a live environment without impacting the running state of your application.

Usage Example:

kubectl debug pod/myapp-pod -it --copy-to=myapp-debug --container=myapp-container --image=busybox

This command creates a copy of myapp-pod, replacing myapp-container with a busybox image for debugging purposes.

When to Use: This trick is invaluable when you need to troubleshoot a pod that is crashing or not behaving as expected in production. It allows for real-time debugging with minimal impact on the service.

Be Careful Of: The debug pod can still affect the overall cluster resource allocation and potentially access sensitive data. Ensure that access to the debug command is tightly controlled and that debug pods are cleaned up after use.

11. Efficient Resource Management with Requests and Limits

Trick: Kubernetes allows you to specify CPU and memory (RAM) requests and limits for each container in a pod. Requests guarantee that a container gets the specified amount of resources, while limits ensure a container never uses more than the allotted amount. This helps in managing resource allocation efficiently and preventing any single application from monopolizing cluster resources.

Usage Example:

apiVersion: v1
kind: Pod
metadata:
name: resource-demo
spec:
containers:
- name: demo-container
image: nginx
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"

This pod specification requests certain amounts of CPU and memory for demo-container, ensuring it has the resources needed for optimal performance while preventing it from exceeding specified limits.

When to Use: Apply requests and limits to all containers to ensure predictable application performance and avoid resource contention among applications running in the cluster.

Be Careful Of: Setting limits too low can lead to pods being terminated or not scheduled if the cluster cannot provide the requested resources. Conversely, setting them too high can lead to inefficient utilization of cluster resources. Monitor application performance and adjust requests and limits as necessary.

12. Custom Resource Definitions (CRDs) for Extending Kubernetes

Trick: CRDs allow you to extend Kubernetes with your own API objects, enabling the creation of custom resources that operate like native Kubernetes objects. This is powerful for adding domain-specific functionality to your clusters, facilitating custom operations, and integrating with external systems.

Usage Example:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct

This CRD defines a new resource type CronTab in the cluster, which can be used to schedule tasks just like a traditional cron job, but with Kubernetes-native management.

When to Use: CRDs are ideal for extending Kubernetes functionality to meet the specific needs of your applications or services, such as introducing domain-specific resource types or integrating with external services and APIs.

Be Careful Of: Designing and managing CRDs requires a good understanding of Kubernetes internals and the API machinery. Poorly designed CRDs can lead to performance issues and complicate cluster management. Always ensure CRDs are thoroughly tested and consider the impact on cluster stability and performance.

13. Kubernetes API for Dynamic Interaction and Automation

Trick: The Kubernetes API enables dynamic interaction with your cluster, allowing you to automate scaling, deployment, and management tasks programmatically. By leveraging the API, you can create scripts or applications that interact with your cluster in real-time, enabling sophisticated automation and integration scenarios that go beyond what’s possible with static configuration files and manual commands.

Usage Example: Here’s a basic example using curl to interact with the Kubernetes API to get a list of pods in the default namespace. This assumes you have an access token and the Kubernetes API is reachable at https://<kubernetes-api-server>.

curl -X GET https://<kubernetes-api-server>/api/v1/namespaces/default/pods \
-H "Authorization: Bearer <your-access-token>" \
-H 'Accept: application/json'

For more complex interactions, consider using client libraries available in various programming languages like Go, Python, Java, which abstract away the HTTP requests and offer more convenient interfaces to work with the Kubernetes API.

When to Use: The Kubernetes API is incredibly powerful for developing custom automation, dynamic scaling policies, CI/CD integrations, or even custom controllers that extend Kubernetes functionalities. It’s especially useful when you need to integrate Kubernetes operations with external systems or create custom deployment workflows.

Be Careful Of: Direct interaction with the Kubernetes API requires careful handling of authentication and authorization. Ensure that your scripts and applications adhere to the principle of least privilege, requesting only the permissions they need to function. Additionally, be mindful of the potential load on the API server when making frequent or complex queries, as this can impact cluster performance. Always validate and sanitize input to your API clients to avoid security vulnerabilities, especially if they interact with external systems or user-generated content.

This trick empowers developers and operators to tailor Kubernetes to their unique operational contexts, enabling a level of automation and integration that can significantly enhance operational efficiency and agility.

Learn more

--

--

Into cloud-native architectures and tools like K8S, Docker, Microservices. I write code to help clouds stay afloat and guides that take people to the clouds.