Resource management is a crucial aspect of running applications in Kubernetes. In this hands-on guide, we’ll explore how to set up and use resource requests and limits in a Kubernetes cluster. Let’s dive in!
Prerequisites
- A running Kubernetes cluster
kubectlcommand-line tool configured to communicate with your cluster
Step 1: Create a New Namespace
First, let’s create a new namespace for our experiments:
kubectl create namespace mem-exampleStep 2: Install Metrics Server
The Metrics Server collects resource metrics from Kubelets and exposes them in Kubernetes apiserver through Metrics API. Let’s install it using the provided YAML:
kubectl apply -f metrics-server.yamlVerify that the Metrics Server is running:
kubectl get pods -n kube-system | grep metrics-serverYou should see a pod running with the name metrics-server-*.
Step 3: Specify Memory Request and Limit
Now, let’s create a Pod with specific memory requests and limits:
apiVersion: v1kind: Podmetadata: name: memory-demo namespace: mem-examplespec: containers: - name: memory-demo-ctr image: polinux/stress resources: requests: memory: "100Mi" limits: memory: "200Mi" command: ["stress"] args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]Save this as memory-demo.yaml and apply it:
kubectl apply -f memory-demo.yamlStep 4: Verify Pod Status
Check the status of the pod:
kubectl get pod memory-demo -n mem-exampleYou should see the pod in a Running state.
Step 5: View Detailed Pod Information
Let’s look at the detailed information about the pod:
kubectl get pod memory-demo -n mem-example --output=yamlIn the output, you should see the memory request and limit specified in the resources section.
Step 6: View Pod Metrics
Now, let’s check the actual memory usage of our pod:
kubectl top pod memory-demo -n mem-exampleThis command will show you the current CPU and memory usage of the pod.
Step 7: Exceed Memory Limits
Let’s create another pod that tries to use more memory than its limit:
apiVersion: v1kind: Podmetadata: name: memory-demo-2 namespace: mem-examplespec: containers: - name: memory-demo-2-ctr image: polinux/stress resources: requests: memory: "50Mi" limits: memory: "100Mi" command: ["stress"] args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]Save this as memory-demo-2.yaml and apply it:
kubectl apply -f memory-demo-2.yamlStep 8: Observe OOM Kill
Check the status of the new pod:
kubectl get pod memory-demo-2 -n mem-exampleYou might see that the pod is in a CrashLoopBackOff state. Let’s check the logs:
kubectl logs memory-demo-2 -n mem-exampleYou should see an error message indicating that the pod was killed due to an Out of Memory (OOM) condition.
apiVersion: v1kind: ServiceAccountmetadata: labels: k8s-app: metrics-server name: metrics-server namespace: kube-system---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: labels: k8s-app: metrics-server rbac.authorization.k8s.io/aggregate-to-admin: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-view: "true" name: system:aggregated-metrics-readerrules: - apiGroups: - metrics.k8s.io resources: - pods - nodes verbs: - get - list - watch---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: labels: k8s-app: metrics-server name: system:metrics-serverrules: - apiGroups: - "" resources: - nodes/metrics verbs: - get - apiGroups: - "" resources: - pods - nodes verbs: - get - list - watch---apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: labels: k8s-app: metrics-server name: metrics-server-auth-reader namespace: kube-systemroleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: extension-apiserver-authentication-readersubjects: - kind: ServiceAccount name: metrics-server namespace: kube-system---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: labels: k8s-app: metrics-server name: metrics-server:system:auth-delegatorroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:auth-delegatorsubjects: - kind: ServiceAccount name: metrics-server namespace: kube-system---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: labels: k8s-app: metrics-server name: system:metrics-serverroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:metrics-serversubjects: - kind: ServiceAccount name: metrics-server namespace: kube-system---apiVersion: v1kind: Servicemetadata: labels: k8s-app: metrics-server name: metrics-server namespace: kube-systemspec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: k8s-app: metrics-server---apiVersion: apps/v1kind: Deploymentmetadata: labels: k8s-app: metrics-server name: metrics-server namespace: kube-systemspec: selector: matchLabels: k8s-app: metrics-server strategy: rollingUpdate: maxUnavailable: 0 template: metadata: labels: k8s-app: metrics-server spec: containers: - args: - --cert-dir=/tmp - --secure-port=10250 - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname - --kubelet-use-node-status-port - --kubelet-insecure-tls - --metric-resolution=15s image: registry.k8s.io/metrics-server/metrics-server:v0.7.1 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: https scheme: HTTPS periodSeconds: 10 name: metrics-server ports: - containerPort: 10250 name: https protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /readyz port: https scheme: HTTPS initialDelaySeconds: 20 periodSeconds: 10 resources: requests: cpu: 100m memory: 200Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 1000 seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /tmp name: tmp-dir nodeSelector: kubernetes.io/os: linux priorityClassName: system-cluster-critical serviceAccountName: metrics-server volumes: - emptyDir: {} name: tmp-dir---apiVersion: apiregistration.k8s.io/v1kind: APIServicemetadata: labels: k8s-app: metrics-server name: v1beta1.metrics.k8s.iospec: group: metrics.k8s.io groupPriorityMinimum: 100 insecureSkipTLSVerify: true service: name: metrics-server namespace: kube-system version: v1beta1 versionPriority: 100Conclusion
In this practical guide, we’ve explored how to set and use resource requests and limits in Kubernetes. We’ve seen how Kubernetes schedules pods based on their resource requests and how it enforces resource limits to prevent pods from consuming more resources than allocated.
Key takeaways:
- Resource requests help Kubernetes schedule pods efficiently.
- Resource limits prevent pods from consuming excessive resources.
- Pods that exceed their memory limits are terminated with an OOM kill.
- The Metrics Server is crucial for monitoring actual resource usage in your cluster.
Remember, setting appropriate resource requests and limits is crucial for maintaining a stable and efficient Kubernetes cluster. Always monitor your applications’ actual resource usage and adjust these values as needed.
Happy Kuberneting!