How to Setup Kubernetes 1.4 with kubeadm on Ubuntu

If you read our article about running Kubernetes locally, you are probably familiar with Kubernetes and eager to try it on real cluster as opposed to running it on one node with Minikube. Well, since then Kubernetes 1.4 came out, and it makes it very easy to setup clusters of arbitrary size using new kubeadm command. We will now install kubernetes 1.4 on two Ubuntu 16.04 nodes.

Preparing the machines

Machines can be VM instances or physical servers. To prepare the machines, on all machines run:

curl | apt-key add -

This is key for new repository, and repository we add here

cat <<EOF > /etc/apt/sources.list.d/kubernetes.list
deb kubernetes-xenial main

And then we load the new repository list

apt-get update

To actually install, run following command:

apt-get install -y kubelet kubeadm kubectl kubernetes-cni

After running this on all nodes, we can proceed to making a cluster.

Initializing the cluster

After we installed everything needed, we need to pick one of the nodes to be a master.

On master run:

kubeadm init

The command will work for several minutes and in the end will give you command you need to run on your node to connect it to this master. For example like this

root@ubuntu-linoxide01:~# kubeadm init
<master/tokens> generated token: "7fa96f.ddb39492a1894689"
<master/pki> created keys and certificates in "/etc/kubernetes/pki"
<util/kubeconfig> created "/etc/kubernetes/admin.conf"
<util/kubeconfig> created "/etc/kubernetes/kubelet.conf"
<master/apiclient> created API client configuration
<master/apiclient> created API client, waiting for the control plane to become ready
<master/apiclient> all control plane components are healthy after 23.051433 seconds
<master/apiclient> waiting for at least one node to register and become ready
<master/apiclient> first node is ready after 5.012029 seconds
<master/discovery> created essential addon: kube-discovery, waiting for it to become ready
<master/discovery> kube-discovery is ready after 13.005947 seconds
<master/addons> created essential addon: kube-proxy
<master/addons> created essential addon: kube-dns

Kubernetes master initialised successfully!

You can now join any number of machines by running the following on each node:

kubeadm join --token 7fa96f.ddb39352a1894689

I have highlighted the kubeadm init command that is ran on master, and the kubeadm join command that it produces. Keep this later command secret, anyone having it could use it to connect his own nodes to your cluster.

After your run the command kubeadm join to join the node to your master, you can run the following command on master to verify that all went well:

kubectl get nodes

But this doesn't yet mean you can already put the application to your cluster. There is couple more things you need to do. First is installing pod network on your master so that pods can communicate with each other:

kubectl apply -f

And second, to be able to have pods run on master as well as on nodes, use this command:

kubectl taint nodes --all dedicated-

That is useful if you have small number of machines running kubernetes, on this tutorial we have two, one master and one node. On bigger clusters, you might leave out that command as it is better security choice to have your master not run any pods.

Deploying a test application

First application we are going to try is micro-services example from kubectl manual. Lets start by cloning the application with git

git clone

Next we use kubectl command to deploy the application:

kubectl apply -f microservices-demo/deploy/kubernetes/manifests

This will take some time as there are quite a few containers to be created. You see the progress by typing

kubectl get pods

If there are pods which say ContainterCreating or anything other that Running, it means you need to wait some more, maybe get a sandwich or coffee. When all containers say Running, we can move to next command. Which is:

kubectl describe svc front-end

This will give you data about front end service (svc or service), and we need that data to be to acess the site from outside world.

root@ubuntu-linoxide01:~# kubectl describe svc front-end
Name: front-end
Namespace: default
Labels: name=front-end
Selector: name=front-end
Type: NodePort
Port: <unset> 80/TCP
NodePort: <unset> 31939/TCP
Session Affinity: None

Or better with image:


Most important here are Type:NodePort line and NodePort: <unset> 31939/TCP. LoadBalancer is not yet supported with kubeadm, so we use NodePort and it exposes the service to ouside world on some port on the ip of the master. So you take your master ip and add it port number from NodPort: line of above command, which is in this case 31939. So when you type that in your browser, you get our sample site with socks


It is our example microservices application.

If you want to delete sock application, run following command

kubectl delete -f microservices-demo/deploy/kubernetes/manifests

From here you can try some more examples for kubernetes

Trying new commands in Kubernetes 1.4

The kubeadm was not only change in Kubernetes 1.4. Far from it. The kubectl also got an update. For example the kubectl hel command got more clear, and well... more helpful. Lets see what is says:

root@ubuntu-linoxide02:~# kubectl help
kubectl controls the Kubernetes cluster manager.

Find more information at

Basic Commands (Beginner):
create Create a resource by filename or stdin
expose Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service
run Run a particular image on the cluster
set Set specific features on objects

Basic Commands (Intermediate):
get Display one or many resources
explain Documentation of resources
edit Edit a resource on the server
delete Delete resources by filenames, stdin, resources and names, or by resources and label selector

Deploy Commands:
rollout Manage a deployment rollout
rolling-update Perform a rolling update of the given ReplicationController
scale Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job
autoscale Auto-scale a Deployment, ReplicaSet, or ReplicationController

Cluster Management Commands:
cluster-info Display cluster info
top Display Resource (CPU/Memory/Storage) usage
cordon Mark node as unschedulable
uncordon Mark node as schedulable
drain Drain node in preparation for maintenance
taint Update the taints on one or more nodes

Troubleshooting and Debugging Commands:
describe Show details of a specific resource or group of resources
logs Print the logs for a container in a pod
attach Attach to a running container
exec Execute a command in a container
port-forward Forward one or more local ports to a pod
proxy Run a proxy to the Kubernetes API server

Advanced Commands:
apply Apply a configuration to a resource by filename or stdin
patch Update field(s) of a resource using strategic merge patch
replace Replace a resource by filename or stdin
convert Convert config files between different API versions

Settings Commands:
label Update the labels on a resource
annotate Update the annotations on a resource
completion Output shell completion code for the given shell (bash or zsh)

Other Commands:
api-versions Print the supported API versions on the server, in the form of "group/version"
config Modify kubeconfig files
help Help about any command
version Print the client and server version information

Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).

Thre is new -n flag which enables you to issue commands to only one virtual cluster, or so called namespace. So this command:

kubectl get nodes -n kube-system

Will get you the pods belonging to kube-system namespace.

kubectl get pods -n kube-system
etcd-ubuntu-linoxide02 1/1 Running 0 4h
kube-apiserver-ubuntu-linoxide02 1/1 Running 0 4h
kube-controller-manager-ubuntu-linoxide02 1/1 Running 0 4h
kube-discovery-982812725-dxj6r 1/1 Running 0 4h
kube-dns-2247936740-n44pu 3/3 Running 0 4h
kube-proxy-amd64-oe87p 1/1 Running 0 4h
kube-proxy-amd64-tuzwv 1/1 Running 0 4h
kube-scheduler-ubuntu-linoxide02 1/1 Running 0 4h
weave-net-as39l 2/2 Running 0 4h
weave-net-fc0v5 2/2 Running 0 4h

There is also new kubectl top command which enables you to get cpu and memory usage in pods, but for that command you need to install heapster.


We ran trough basic scenario of installing Kubernetes with the new kubeadm utility. The kubeadm is still new and it is not feature complete, but it shows lots of promise. It greatly simplifies the creation of clusters and adding nodes on the fly. The Kubernetes developers have committed to make kubeadm feature complete, which means adding LoadBalancer support as well as other missing features. Until then, we can either use kubeadm without load balancer or if we need load balancer, we would have to do manual cluster configuration without kubeadm. This was all for this article, thank you for reading.

About Mihajlo Milenovic

Miki is a long time GNU/Linux user, Free Software advocate and a freelance system administrator from Serbia. Got introduced to GNU/Linux in year 2003 on old AMD Duron computer, and since than always eager to learn new stuff about this system. From 2016 writes for Linoxide to share his experiences with wider audience

Author Archive Page

Have anything to say?

Your email address will not be published. Required fields are marked *

All comments are subject to moderation.