Resources and Limits
Make sure you are in the correct namespace:
You will need to create the
If the response is:
Then you can create the namespace with:
|
kubectl config set-context --current --namespace=myspace
Make sure nothing is running in your namespace:
kubectl get all
No resources found in myspace namespace.
First deploy an application without any Requests or Limits:
kubectl apply -f apps/kubefiles/myboot-deployment.yml
Describe the pod:
PODNAME=$(kubectl get pod -l app=myboot --field-selector 'status.phase!=Terminating' -o name)
kubectl describe $PODNAME
There are not resource limits configured for the pod.
Name: myboot-66d7d57687-jzbzj
Namespace: myspace
Priority: 0
Node: gcp-5xldg-w-b-rlp45.us-central1-b.c.ocp42project.internal/10.0.32.5
Start Time: Sun, 29 Mar 2020 14:24:24 -0400
Labels: app=myboot
pod-template-hash=66d7d57687
Annotations: k8s.v1.cni.cncf.io/networks-status:
[{
"name": "openshift-sdn",
"interface": "eth0",
"ips": [
"10.130.2.23"
],
"dns": {},
"default-route": [
"10.130.2.1"
]
}]
openshift.io/scc: restricted
Status: Running
IP: 10.130.2.23
IPs:
IP: 10.130.2.23
Controlled By: ReplicaSet/myboot-66d7d57687
Containers:
myboot:
Container ID: cri-o://2edfb0a5a93f375516ee49d33df20bee40c14792b37ec1648dc5205244095a53
Image: quay.io/burrsutter/myboot:v1
Image ID: quay.io/burrsutter/myboot@sha256:cdf39f191f5d322ebe6c04cae218b0ad8f6dbbb8a81e81a88c0fbc6e3c05f860
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Started: Sun, 29 Mar 2020 14:24:32 -0400
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-vlzsl (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-vlzsl:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-vlzsl
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned myspace/myboot-66d7d57687-jzbzj to gcp-5xldg-w-b-rlp45.us-central1-b.c.ocp42project.internal
Normal Pulled 12m kubelet, gcp-5xldg-w-b-rlp45.us-central1-b.c.ocp42project.internal Container image "quay.io/burrsutter/myboot:v1" already present on machine
Normal Created 12m kubelet, gcp-5xldg-w-b-rlp45.us-central1-b.c.ocp42project.internal Created container myboot
Normal Started 12m kubelet, gcp-5xldg-w-b-rlp45.us-central1-b.c.ocp42project.internal Started container myboot
Delete that deployment:
kubectl delete deployment myboot
Create a new deployment with resource requests:
kubectl apply -f apps/kubefiles/myboot-deployment-resources.yml
And check the status of the Pod:
kubectl get pods
NAME READY STATUS RESTARTS AGE
myboot-7b7d754c86-kjwlr 0/1 Pending 0 19s
If you want to get more information about the error:
kubectl get events --sort-by=.metadata.creationTimestamp
<unknown> Warning FailedScheduling pod/myboot-7b7d754c86-kjwlr 0/6 nodes are available: 6 Insufficient cpu.
<unknown> Warning FailedScheduling pod/myboot-7b7d754c86-kjwlr 0/6 nodes are available: 6 Insufficient cpu.
The "resource requests" of the pod specification require that at least one worker node has N cores and X memory available. If there is no worker node that meets the requirements, you receive "PENDING" and the appropriate notations in the events listing.
You can also use kubectl describe
on the pod to find more information about the failure.
PODNAME=$(kubectl get pod -l app=myboot --field-selector 'status.phase!=Terminating' -o name)
kubectl describe $PODNAME
We should fix the deployment while keeping a history of changes done by replace
:
kubectl replace -f apps/kubefiles/myboot-deployment-resources-limits.yml
The above command will replace the Deployment template and instruct the Pod to have container limits. Describe the Pod:
PODNAME=$(kubectl get pod -l app=myboot --field-selector 'status.phase!=Terminating' -o name)
kubectl describe $PODNAME
Deploy the service:
kubectl apply -f apps/kubefiles/myboot-service.yml
And watch your Pods:
watch -n 1 -- kubectl get pods
In another Terminal, loop and curl that service:
IP=$(minikube ip -p devnation)
PORT=$(kubectl get service/myboot -o jsonpath="{.spec.ports[*].nodePort}")
If using a hosted Kubernetes cluster like OpenShift then use curl and the EXTERNAL-IP address with port 8080
or get it using kubectl
:
IP=$(kubectl get service myboot -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
PORT=$(kubectl get service myboot -o jsonpath="{.spec.ports[*].port}")
If you are in AWS, you need to get the hostname instead of ip.
|
IP=$(kubectl get service myboot -o jsonpath="{.status.loadBalancer.ingress[0].hostname}")
Curl the Service:
curl $IP:$PORT
Execute in loop:
while true
do curl $IP:$PORT
sleep 0.8
done
In yet another terminal window, curl the /sysresources endpoint:
curl $IP:$PORT/sysresources
The reported memory vs what was set in the resource limits |
PODNAME=$(kubectl get pod -l app=myboot -o name)
kubectl get $PODNAME -o jsonpath='{.spec.containers[*].resources}'
{
"limits": {
"cpu": "1",
"memory": "400Mi"
},
"requests": {
"cpu": "250m",
"memory": "300Mi"
}
}
Then curl
the /consume
endpoint:
curl $IP:$PORT/consume
curl: (52) Empty reply from server
And you should notice that your loop also fails:
Aloha from Spring Boot! 1120 on myboot-d78fb6d58-69kl7
curl: (56) Recv failure: Connection reset by peer
Describe the Pod to see the error:
PODNAME=$(kubectl get pod -l app=myboot --field-selector 'status.phase!=Terminating' -o name)
kubectl describe $PODNAME
And look for the following part:
Last State: Terminated
Reason: OOMKilled
Exit Code: 137
kubectl get $PODNAME -o jsonpath='{.status.containerStatuses[0].lastState.terminated'}
{
"containerID": "cri-o://7b9be70ce4b616d6083d528dee708cea879da967373dad0d396fb999bd3898d3",
"exitCode": 137,
"finishedAt": "2020-03-29T19:14:56Z",
"reason": "OOMKilled",
"startedAt": "2020-03-29T18:50:15Z"
}
You might even see the STATUS column of the watch kubectl get pods
reflect the OOMKilled:
NAME READY STATUS RESTARTS AGE
myboot-d78fb6d58-69kl7 0/1 OOMKilled 1 30m
And you will notice that the RESTARTS column increments with each crash of the Spring Boot Pod.