I want to show how you can enable Kubernetes in your day to day development workflow. So that you get the feel of production deployment locally from day 1.
I have a flask application which I am working on. The basic directory structure looks like this:
$ ll total 24 -rw-rw-r--. 1 foo foo 427 Apr 23 16:23 app.py -rw-rw-r--. 1 foo foo 201 Apr 23 16:55 docker-compose.yml -rw-rw-r--. 1 foo foo 363 Apr 23 16:21 Dockerfile -rwxrwxr-x. 1 foo foo 82 Dec 5 19:41 entrypoint.sh -rw-rw-r--. 1 foo foo 3010 Dec 5 19:41 README.adoc -rw-rw-r--. 1 foo foo 11 Dec 5 19:41 requirements.txt
You can find all of these files in this github repo.
For having a local cluster I am using minikube. So follow instructions to
setup minikube. Once you follow the instructions
you will have a vm running a single node kubernetes cluster and a locally available
Before running this application on the minikube cluster we need configurations that kubernetes understands. Since we already have docker-compose file we will generate configs from this file with the help from tool called kompose. Install kompose as per instructions as given on docs.
$ mkdir configs $ kompose convert -o configs/ WARN Kubernetes provider doesnt support build key - ignoring INFO file "configs/hitcounter-service.yaml" created INFO file "configs/redis-service.yaml" created INFO file "configs/hitcounter-deployment.yaml" created INFO file "configs/redis-deployment.yaml" created
Before we deploy the app we need to make some changes in the deployment files, that were converted from docker-compose service
build construct in them. In our case only python app
hitcounter is built is being built from
We will edit file
configs directory, to not pull image but read image from the local docker
storage. Add a field after
imagePullPolicy: IfNotPresent. Make changes as shown in following diff:
$ git diff diff --git a/configs/hitcounter-deployment.yaml b/configs/hitcounter-deployment.yaml index 7b1116d..0ef35b3 100644 --- a/configs/hitcounter-deployment.yaml +++ b/configs/hitcounter-deployment.yaml @@ -17,6 +17,7 @@ spec: - name: REDIS_HOST value: redis image: hitcounter + imagePullPolicy: IfNotPresent name: hitcounter ports: - containerPort: 5000
Now we are ready with the configs, but we need to build container image for our app. So here you will need to have
docker-compose installed on your machine. For that follow docs here.
Build image in the minikube
eval $(minikube docker-env) docker-compose build
Once the build is complete, we are good to the deployment in kubernetes.
$ kubectl create -f configs/ deployment "hitcounter" created service "hitcounter" created deployment "redis" created service "redis" created
To verify that the app is running, find out the exposed IP Address as follows:
$ kubectl get svc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE hitcounter 10.0.0.244 <pending> 5000:30476/TCP 6s kubernetes 10.0.0.1 <none> 443/TCP 3d redis 10.0.0.21 <none> 6379/TCP 6s
Now hit the externally exposed port
30476 of service
$ curl $(minikube ip):30476
Now everytime you make changes to code do the following:
docker-compose build kubectl scale deployment hitcounter --replicas=0 kubectl scale deployment hitcounter --replicas=1
Above we are removing all containers with old image and asking it to use the new image. For OpenShift we can do
oc deploy hitcounter --latest and it will trigger the deployment but I could not find anything similar with
- Why do I need to make changes in the kompose generated configs?
Because by the default the config that kompose generates will not set
imagePullPolicyand hence Kubernetes assumes its value to be
Always. So if you don’t make changes and try to deploy then Kubernetes will try to find the image from docker hub. Which it won’t find and then that deployment will fail. So we need to tell Kubernetes to look for the image in local docker storage.
- Can I use the same configs in the production servers as well?
Yes you can use it just remove the change we did in the
imagePullPolicy: IfNotPresent. The change is done to enable you to use the locally built images without having to push the image to any container registry.
- How do I get images when I am deploying in production level cluster?
Make sure your cluster can pull images from some private container registry. And then set up a build pipeline from your code repo to build container on every change of it’s stable branch.
- I have
builddefined in my
docker-composeservice why do I need to mention image name?
With docker-compose this is okay. But kompose cannot make up a name on it’s own and create deployment. The issue is tracked in kompose. But for now with
buildalso provide the
imagename you would expect.
- I get error running docker commands with minikube?
If you face problem accessing the docker daemon running inside the minikube VM like one of this
$ eval $(minikube docker-env) $ docker ps could not read CA certificate "/etc/docker/ca.pem": open /etc/docker/ca.pem: no such file or directory
This could be because there is a mismatch in docker client and docker daemon version, so to solve this issue just copy the docker client from the minikube VM to the local machine.
Enter in the VM
Copy the binary to host machine
scp $(which docker) email@example.com:/home/foo/
Now put the binary in
If you have any other questions please ask it, I would like to add those here in FAQ section.