Pod Stuck on `CrashLoopBackOff` even though it should go into /bin/bash

8/9/2019

I'm running a Kubernetes cluster with minikube and my deployment (or individual Pods) won't stay running even though I specify in the Dockerfile that it should stay leave a terminal open (I've also tried it with sh). They keep getting restarted and sometimes they get stuck on a CrashLoopBackOff status before restarting again:

FROM ubuntu

EXPOSE 8080

CMD /bin/bash

My deployment file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sleeper-deploy
spec:
  replicas: 10
  selector:
    matchLabels:
      app: sleeper-world
  minReadySeconds: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: sleeper-world
    spec:
      containers:
      - name: sleeper-pod
        image: kubelab
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

All in all, my workflow follows (deploy.sh):

#!/bin/bash

# Cleaning

kubectl delete deployments --all
kubectl delete pods --all

# Building the Image

sudo docker build \
    -t kubelab \
    .

# Deploying

kubectl apply -f sleeper_deployment.yml

By the way, I've tested the Docker Container solo using sudo docker run -dt kubelab and it does stay up. Why doesn't it stay up within Kubernetes? Is there a parameter (in the YAML file) or a flag I should be using for this special case?

-- Philippe Fanaro
docker
dockerfile
kubernetes
minikube

1 Answer

8/9/2019

1. Original Answer (but edited...)

If you are familiar with Docker, check this.

If you are looking for an equivalent of docker run -dt kubelab, try kubectl run -it kubelab --restart=Never --image=ubuntu /bin/bash. In your case, with the Docker -t flag: Allocate a pseudo-tty. That's why your Docker Container stays up.

Try:

kubectl run kubelab \
    --image=ubuntu \
    --expose \
    --port 8080 \
    -- /bin/bash -c 'while true;do sleep 3600;done'

Or:

kubectl run kubelab \
    --image=ubuntu \
    --dry-run -oyaml \
    --expose \
    --port 8080 \
    -- /bin/bash -c 'while true;do sleep 3600;done'

2. Explaining what's going on (Added by Philippe Fanaro):

As stated by @David Maze, the bash process is going to exit immediately because the artificial terminal won't have anything going into it, a slightly different behavior from Docker.

If you change the restart Policy, it will still terminate, the difference is that the Pod won't regenerate or restart.

One way of doing it is (pay attention to the tabs of restartPolicy):

apiVersion: v1
kind: Pod
metadata:
  name: kubelab-pod
  labels:
    zone: prod
    version: v1
spec:
  containers:
  - name: kubelab-ctr
    image: kubelab
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
  restartPolicy: Never

However, this will not work if it is specified inside a deployment YAML. And that's because deployments force regeneration, trying to always get to the desired state. This can be confirmed in the Deployment Documentation Webpage:

Only a .spec.template.spec.restartPolicy equal to Always is allowed, which is the default if not specified.

3. If you really wish to force the Docker Container to Keep Running

In this case, you will need something that doesn't exit. A server-like process is one example. But you can also try something mentioned in this StackOverflow answer:

CMD exec /bin/bash -c "trap : TERM INT; sleep infinity & wait"

This will keep your container alive until it is told to stop. Using trap and wait will make your container react immediately to a stop request. Without trap/wait stopping will take a few seconds.

-- FL3SH
Source: StackOverflow