I have configured a secret on Kubernetes and inside the node, I am able to pull an image with docker pull perfectly. But when kubectl tries to schedule a pod on the node it shows image pull backoff error. Is there any setting needs to be done while bootstrapping. I am using community AMI on AWS for Kubernetes node.
Try this:
kubectl describe pod-name - see event log at the end. it should show series of events starting from initial image pull to subsequent attempts and may continue to restart in order to achieve desired state as per deployment record
In most scenarios something within container erroring out resulting restart expected behavior by k8s. to check logs - kubectl logs pod-name
Try to keep container running so you can peek inside running container for more troubleshooting using kubectl exec -it pod-name (if single container) or kubectl exec -it pod-name -c container-name.
Related
A word of warning, this is my first posting, and I am new to docker and Kubernetes with enough knowledge to get me into trouble.
I am confused about where docker container images are being stored and listing images.
To illustrate my confusion I start with the confirmation that "docker images" indicates no image for nginx is present.
Next I create a pod running nginx.
kubectl run nginx --image=nginx is succesful in pulling image "nginx" from github (or that's my assumption):
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 8s default-scheduler Successfully assigned default/nginx to minikube
Normal Pulling 8s kubelet Pulling image "nginx"
Normal Pulled 7s kubelet Successfully pulled image "nginx" in 833.30993ms
Normal Created 7s kubelet Created container nginx
Normal Started 7s kubelet Started container nginx
Even though the above output indicates the image is pulled, issuing "docker images" does not include nginx the output.
If I understand correctly, when an image is pulled, it is being stored on my local disk. In my case (Linux) in /var/lib/docker.
So my first question is, why doesn't docker images list it in the output, or is the better question where does docker images look for images?
Next if I issue a docker pull for nginx it is pulled from what I assume to be Github. docker images now includes it in it's output.
Just for my clarification, nothing up to this point involves a private local registry, correct?
I purposefully create a basic local Docker Registry using the docker registry container thinking it would be clearer since that will allow me to explicitly specify a registry but this only results in another issue:
docker run -d \
-p 5000:5000 \
--restart=always \
--name registry \
-v /registry:/var/lib/registry \
registry
I tag and push the nginx image to my newly created local registry:
docker tag nginx localhost:5000/nginx:latest
docker push localhost:5000/nginx:latest
The push refers to repository [localhost:5000/nginx]
2bed47a66c07: Pushed
82caad489ad7: Pushed
d3e1dca44e82: Pushed
c9fcd9c6ced8: Pushed
0664b7821b60: Pushed
9321ff862abb: Pushed
latest: digest: sha256:4424e31f2c366108433ecca7890ad527b243361577180dfd9a5bb36e828abf47 size: 1570
I now delete the original nginx image:
docker rmi nginx
Untagged: nginx:latest
Untagged: nginx#sha256:9522864dd661dcadfd9958f9e0de192a1fdda2c162a35668ab6ac42b465f0603
... and the newely tagged one:
docker rmi localhost:5000/nginx
Untagged: localhost:5000/nginx:latest
Untagged: localhost:5000/nginx#sha256:4424e31f2c366108433ecca7890ad527b243361577180dfd9a5bb36e828abf47
Deleted: sha256:f652ca386ed135a4cbe356333e08ef0816f81b2ac8d0619af01e2b256837ed3e
... but from where are they being deleted?
Now the image nginx should only be present in localhost:5000/? But docker images doesn't show it in it's output.
Moving on, I try to create the nginx pod once more using the image pushed to localhost:5000/nginx:latest.
kubectl run nginx --image=localhost:5000/nginx:latest --image-pull-policy=IfNotPresent
This is the new issue. The connection to localhost:5000 is refused.
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Pulling 1s kubelet Pulling image "localhost:5000/nginx:latest"
Warning Failed 1s kubelet Failed to pull image "localhost:5000/nginx:latest": rpc error: code = Unknown desc = Error response from daemon: Get "http://localhost:5000/v2/": dial tcp 127.0.0.1:5000: connect: connection refused
Warning Failed 1s kubelet Error: ErrImagePull
Normal BackOff 0s kubelet Back-off pulling image "localhost:5000/nginx:latest"
Why is it I can pull and push to localhost:5000, but pod creation fails with what appears to be an authorization issue? I try logging into the registry but no matter what I use for the username and user password, login is successful. This confuses me more.
I would try creating/specifying imagePullSecret, but based on docker login outcome, it doesn't make sense.
Clearly I not getting it.
Someone please have pity on me and show where I have lost my way.
I will try to bring some clarity to you despite the fact your question already contains about 1000 questions (and you'll probably have 1000 more after my answer :D)
Before you can begin to understand any of this, you need to learn a few basic things:
Docker produces images which are used by containers - it similar to Virtual Machine, but more lightweight (I'm oversimplifying, but the TL;DR is pretty much that).
Kubernetes is an orchestration tool - it is responsible for starting containers (by using already built images) and tracking their state (i.e. if this container has crashed it should be restarted, or if it's not started it should be started, etc)
Docker can run on any machine. To be able to start a container you need to build an image first. The image is essentially a lightweight mini OS (i.e. alpine, ubuntu, windows, etc) which is configured with only those dependencies you need to run your application. This image is then pushed to a public repository/registry (hub.docker.com) or to a private one. And afterwards it's used for starting containers.
Kubernetes builds on top of this and adds the "automation" layer which is responsible for scheduling and monitoring the containers. For example, you have a group of 10 servers all running nginx. One of those servers restarts - the nginx container will be automatically started by k8s.
A kubernetes cluster is the group of physical machines that are dedicated to the mentioned logical cluster. These machines have labels or tags which define the purpose of physical node and work as a constraint for where a container will be scheduled.
Now that I have explained the minimum basics in an oversimplified way I can move with answering your questions.
When you do docker run nginx - you are instructing docker to pull the nginx image from https://hub.docker.com/_/nginx and then start it on the machine you executed the command on (usually your local machine).
When you do kubectl run nginx --image=nginx - you are instructing Kubernetes to do something similar to 1. but in a cluster. The container will be deployed to a random machine somewhere in the cluster unless you put a nodeSelector or configure affinity. If you put a nodeSelector this container (called Pod in K8S) will be placed on that specific node.
You have started a private registry server on your local machine. It is crucial to know that localhost inside a container will point to the container itself.
It is worth mentioning that some of the kubernetes commands will create their own container for the execution phase of the command. (remember this!)
When you run kubectl run nginx --image=nginx everything works fine, because it is downloading the image from https://hub.docker.com/_/nginx.
When you run kubectl run nginx --image=localhost:5000/nginx you are telling kubernetes to instruct docker to look for the image at localhost which is ambiguous because you have multiple layers of containers running (check 4.). This means the command that will do docker pull localhost:5000/nginx also runs in a docker container -- so there is no service running at port :5000 (the registry is running in a completely different isolated container!) :D
And this is why you are getting Error: ErrImagePull - it can't resolve localhost as it points to itslef.
As for the docker rmi nginx and docker rmi localhost:5000/nginx commands - by running them you removed your local copy of the nginx images.
If you run docker run localhost:5000/nginx on the machine where you started docker run registry you should get a running nginx container.
You should definitely read the Docker Guide BEFORE you try to dig into Kubernetes or nothing will ever make sense.
Your head will stop hurting after that I promise... :D
TL;DR
docker images lists images stored in the docker daemon's data root, by default /var/lib/docker.
You're deploying images to Kubernetes, the images are pulled onto the node on which the pod is scheduled. For example, using Kubernetes in Docker:
kind create cluster
kubectl run nginx --image=nginx
docker exec -it $(kubectl get pod nginx -o jsonpath={.spec.nodeName}) crictl images
crictl is a command-line interface for CRI-compatible container runtimes.
Docker images are pulled from Docker Hub by default, not Github. When using a local docker registry, images are stored in the registry's data volume. The docker registry storage may be customized, by default data is stored in (storage.filesystem.rootdirectory) /var/lib/registry.
You can use tools like skopeo to list images stored in a docker registry, for example:
skopeo list-tags docker://localhost:5000/nginx --tls-verify=false
I'm using the latest version of microk8s and docker on the same VM. microk8s registry is enabled.
I restaged my image argus
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
argus 0.1 6d72b6be9981 3 hours ago 164MB
localhost:32000/argus registry 6d72b6be9981 3 hours ago 164MB
then I pushed it
$ docker push localhost:32000/argus:registry
The push refers to repository [localhost:32000/argus]
c8a05c6fda3e: Pushed
5836f564d6a0: Pushed
9e3dd069b4a1: Pushed
6935b1ceeced: Pushed
d02e8e9f8523: Pushed
c5129c726314: Pushed
0f299cdf8fbc: Pushed
edaf6f6a5ef5: Pushed
9eb034f85642: Pushed
043895432150: Pushed
a26398ad6d10: Pushed
0dee9b20d8f0: Pushed
f68ef921efae: Pushed
registry: digest: sha256:0a0ac9e076e3249b8e144943026bc7c24ec47ce6559a4e087546e3ff3fef5c14 size: 3052
all working seemingly fine but when I try to deploy a pod with:
$ microk8s kubectl create deployment argus --image=argus
deployment.apps/argus created
$ microk8s kubectl get pods
NAME READY STATUS RESTARTS AGE
argus-84c8dcc968-27nlz 0/1 ErrImagePull 0 9s
$ microk8s kubectl logs argus-84c8dcc968-27nlz
Error from server (BadRequest): container "argus" in pod "argus-84c8dcc968-27nlz" is waiting to start: trying and failing to pull image
The image can not be pulled, I tried the $ microk8s ctr images ls but this does not tell me anything.
So what is it that I'm doing wrong here?
update:
A bit of an update here when I try:
$ microk8s ctr image pull localhost:32000/argus:registry
ctr: failed to resolve reference "localhost:32000/argus:registry": failed to do request: Head "https://localhost:32000/v2/argus/manifests/registry": http: server gave HTTP response to HTTPS client
So it seems that it does not like that it gets and http response from my local repository. I looked into the config at /var/snap/microk8s/current/args/containerd-template.toml and there the localhost repository is correctly configured:
[plugins."io.containerd.grpc.v1.cri".registry]
# 'plugins."io.containerd.grpc.v1.cri".registry.mirrors' are namespace to mirror mapping for all namespaces.
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://registry-1.docker.io", ]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:32000"]
endpoint = ["http://localhost:32000"]
I'm running all of this on a centos8 VM. When I installed docker
I needed to do it with sudo dnf install docker-ce --nobest because otherwise there was some kind of conflict with containerd maybe it has todo something with this?
Okay, there were multiple issues at play here, and I think I solved them all. First of, I made a mistake with the Docker Image. It was a test image, but it should have had something that continuously runs because after PID 1 ends the container gets restarted, the reasons is that microk8s/kubernetes assumes a there is a problem. That's why there was the crash loop.
Second, to check which repositories are present in the local registry, it's easiest to curl the rest API of the registry with:
$curl http://host:32000/v2/_catalog
to get a list of all images, and:
$curl http://host:32000/v2/{repositoryName}/tags/list
to get all tags for a given repo.
Lastly, to pull from the registry to the cluster manually without getting the https error, it's necessary to add the --plain-http option like this:
$microk8s ctr image pull --plain-http localhost:32000/repo:tag
you can use kubectl describe to check the pod
i guess it try to pull the "argus" from docker.io
have you try add localhost:32000 to the image parameter?
microk8s kubectl create deployment argus --image=localhost:32000/argus:registry
I am following a tutorial, where a pod is created using the below command:
kubectl run firstPod --image={image from dockerhub repository}
But I am getting the following error:
Error from server (Forbidden): pods "firstPod" is forbidden: error looking up service account default/default: serviceaccount "default" not found
The goal of command is to pull docker image from my own repository and use it to create pod. I saw already some solutions that use .yaml file (but I didn't like the answer). All I want is to run this command. I am using windows 10 and docker desktop for a kubernetes cluster (minikube etc.).
You can test it with network-multitool. It will keep on running a webserver and have a lot of great tools.
kubectl run multitool --image=praqma/network-multitool --replicas=1
If that works, find the podname
kubectl get pods
Then you can exec into it with the name you found above
kubectl exec -it multitool-3822887632-pwlr1 bash
From inside the container/pod you can tjek that the webserver is running by
curl localhost
If the first command doesnt work, then something is wrong.
Check if the service account exists
kubectl get sa
Thanks for answers. Now I realize, that I forget to start my local cluster minikube.
minikube start
Now it is ok to create a pod.
I have a docker image I have created that works on docker like this (local docker)n...
docker run -p 4000:8080 jrg/hello-kerb
Now I am trying to run it as a Kubernetes pod. To do this I create the deployment...
kubectl create deployment hello-kerb --image=jrg/hello-kerb
Then I run kubectl get deployments but the new deployment comes as unavailable...
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-kerb 1 1 1 0 17s
I was using this site as the instructions. It shows that the status should be available...
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-node 1 1 1 1 1m
What am I missing? Why is the deployment unavailable?
UPDATE
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-kerb-6f8f84b7d6-r7wk7 0/1 ImagePullBackOff 0 12s
If you are running a local image (from docker build) it is directly available to the docker daemon and can be executed. If you are using a remote daemon, f.e. in a kubernetes cluster, it will try to get the image from the default registry, since the image is not available locally. This is usually dockerhub. I checked https://hub.docker.com/u/jrg/ and there seems to be no repository and therefore no jrg/hello-kerb
So how can you solve this? When using minikube, you can build (and provide) the image using the docker daemon that is provided by minikube.
eval $(minikube docker-env)
docker build -t jrg/hello-kerb .
You could also provide the image at a registry that is reachable from your container runtime in the kubernetes cluster, f.e. dockerhub.
I solved this by using kubectl edit deployment hello-kerb then finding "imagePullPolicy" (:/PullPolicy). Finally I changed the value from "Always" to "Never". After saving this when I run kubectl get pod it shows...
NAME READY STATUS RESTARTS AGE
hello-kerb-6f744b6cc5-x6dw6 1/1 Running 0 6m
And I can access it.
I have been trying to run tomcat container on port 5000 on cluster using kubernetes. But when i am using kubectl create -f tmocat_pod.yaml , it creates pod but docker ps does not give any output. Why is it so?
Ideally, when it is running a pod, it means it is running a container inside that pod and that container is defined in yaml file.
Why is that docker ps does not show any containers running?
I am following the below URLs:
http://containertutorials.com/get_started_kubernetes/k8s_example.html
https://blog.jetstack.io/blog/k8s-getting-started-part2/
How can I get it running and see tomcat running on browser on port 5000.
The docker containers should be running on the virtual machine. Since I only installed minikube on my local machine, I confirmed the following will bring what you want:
minikub ssh
...
docker ps
Just try the kubernetes equivalent of minikube ssh.
In Kubernetes, Docker contaienrs are run on Pods, and Pods are run on Nodes, and Nodes are run on your machine (minikube/GKE)
When you run kubectl create -f tmocat_pod.yaml you basically create a pod and it runs the docker container on that pod.
The node that holds this pod, is basically a virtual instance, if you could 'SSH' into that node, docker ps would work.
What you need is:
kubectl get pods <-- It is like docker ps, it shows you all the pods (think of it as docker containers) running
kubectl get nodes <-- view the host machines for your pods.
kubectl describe pods <pod-name> <-- view system logs for your pods.
kubectl logs <pod-name> <-- Will give you logs for the specific pod.
You can connect your Terminal with the docker server what is running inside your Node/VM.
With this command in your terminal: eval $(minikube docker-env)
This only configures your current terminal window.
illustration
may be you are not using docker as container runtime.
I faced the same issue, and i forgot that i switched to gVisor with runsc as handler.
cat /etc/default/kubelet
KUBELET_EXTRA_ARGS="--container-runtime remote --container-runtime-endpoint unix:///run/containerd/containerd.sock"
If so, you need to use runsc command instead of docker.
I'm not sure where you are running the docker ps command, but if you are trying to do that from your host machine and the k8s cluster is located elsewhere, i.e. your machine is not a node in the cluster, docker ps will not return anything since the containers are not tied to your docker host.
Assuming your pod is running, kubectl get pods will display all of your running pods. To check further details, you can use kubectl describe pod <yourpodname> to check the status of each container (in great detail). To get the pod names, you should be able to use tab-complete with the kubernetes cli. Also, if your pod contains multiple containers, you will need to give the container name as well, which you can use tab-complete for after you've selected your pod.
The output will look similar to:
kubectl describe pod comparison-api-dply-reborn-6ffb88b46b-s2mtx
Name: comparison-api-dply-reborn-6ffb88b46b-s2mtx
Namespace: default
Node: aks-nodepool1-99697518-0/10.240.0.5
Start Time: Fri, 20 Apr 2018 14:08:21 -0400
Labels: app=comparison-pod-reborn
pod-template-hash=2996446026
...
Status: Running
IP: *.*.*.*
Controlled By: ReplicaSet/comparison-api-dply-reborn-6ffb88b46b
Containers:
rabbit-mq:
...
Port: 5672/TCP
State: Running
...
If your containers and pods are already running, then you shouldn't need to troubleshoot them too much. To make them accessible from the Public Internet, take a look at Services (https://kubernetes.io/docs/concepts/services-networking/service/) to make your API's IP address fixed and easily reachable.
Have you tried a "docker ps -a" to see if the container is dead? If it is there you can see its logs with "docker logs " and maybe this gives you a hint.
If your pod is running successfully and if you are looking for the container on the node where the pod is scheduled the issue could be kubernetes is using a different container runtime.
Example
root#renjith-laptop:/home/renjith/raspbery-k8s# kubectl exec -it nginx-8586cf59-h92ct bash
root#nginx-8586cf59-h92ct:/# exit
exit
root#renjith-laptop:/home/renjith/raspbery-k8s# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-8586cf59-h92ct 1/1 Running 0 47s 10.20.0.3 renjith-laptop
root#renjith-laptop:/home/renjith/raspbery-k8s# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root#renjith-laptop:/home/renjith/raspbery-k8s#
Here I am able exec to the pod, and I am in the same node where pod is scheduled, but docker ps doesn't show the container. In my case kubelet is using different container runtime, one of the argument to kubelet service is --container-runtime-endpoint=unix:///var/run/cri-containerd.sock
From Kubernetes documentation to get container images running on your system:
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" |\
tr -s '[[:space:]]' '\n' |\
sort |\
uniq -c
Then you get back something like:
2 registry.k8s.io/coredns/coredns:v1.9.3
1 registry.k8s.io/etcd:3.5.4-0
1 registry.k8s.io/kube-apiserver:v1.25.1
1 registry.k8s.io/kube-controller-manager:v1.25.1
3 registry.k8s.io/kube-proxy:v1.25.1
1 registry.k8s.io/kube-scheduler:v1.25.1