Kubernetes on a single machine

by Camille Rodriguez on 17 October 2019

As developers, we do not always have access to a production-like environment to test new features and run proof-of-concepts. This is why it can be very interesting to deploy Kubernetes on a single machine. Of course, there is the new microk8s snap that allows a super fast deployment of a k8s cluster on a laptop (and it is definitely worth a try, look here to see how I deployed and tested it in just a few minutes), but if you’re looking for the full experience, here’s how I deployed the Charmed Distribution of Kubernetes on LXD containers in a single bare-metal machine.

Note: This is an adaptation of Michael Iatrou’s post with the newer LXD version 3.18 and Ubuntu 18.04 Bionic Beaver.

You will need a machine equipped with at least 4 CPU cores, 16GB RAM,100GB free disk space, preferably SSD and one NIC. I am using MAAS to deploy Ubuntu 18.04.3 LTS on a machine. I configured a Linux bridge (br0) and attached one NIC (eno1) to it. Here is the /etc/netplan/config.yaml configuration of my machine.

$ cat /etc/netplan/config.yaml
network:
    bridges:
        br0:
            addresses:
            - 172.16.7.50/24
            gateway4: 172.16.7.1
            interfaces:
            - eno1
            macaddress: 2c:60:0c:f9:3c:23
            mtu: 1500
            nameservers:
                addresses:
                - 10.246.96.1
                search:
                - maas
            parameters:
                forward-delay: 15
                stp: false
    ethernets:
        eno1:
            match:
                macaddress: 2c:60:0c:f9:3c:23
            mtu: 1500
            set-name: eno1

First step is to SSH into our machine and download the various components needed for this task. Juju and LXD are now available with snaps, which is the recommended way to deploy these tools.

$ sudo apt update
$ sudo apt dist-upgrade -y
$ sudo snap install juju --classic
$ sudo snap install lxd

We get the Juju version 2.6.9-bionic-amd64 and the LXD version 3.18. The next step is to launch the LXD init to set it up.

$ /snap/bin/lxd init
Would you like to use LXD clustering? (yes/no) [default=no]:
Do you want ot configure a new storage pool? (yes/no) [default=yes]:
Name of the new storage pool [default=default]:
Name of the storage backend to use (btrfs, ceph, dir, lvm, zfs) [default=zfs]: dir
Would you like to connect to a MAAS server? (yes/no) [default=no]:
Would you like to create a new local network bridge? (yes/no) [default=yes]: no
Would you like to configure LXD to use an existing bridge or host interface? (yes/no) [default=no]: yes
Name of the existing bridge or host interface: br0
Would you like LXD to be available over the network? (yes/no) [default=no]:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]:
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:

We can now bootstrap our local Juju controller with LXD. Juju is the tool with which we will deploy a Kubernetes environment.

$ juju bootstrap lxd lxd-local

If this command ran successfully, you should get a message saying that a controller was launched on localhost/localhost, and that an initial model “default” has been added. You can double check by looking at the output of these two following commands.

$ juju controllers
Use --refresh option with this command to see the latest information.

Controller  Model    User   Access     Cloud/Region         Models  Nodes    HA  Version
lxd-local*  default  admin  superuser  localhost/localhost       3      1  none  2.6.9 

$ juju models
Controller: lxd-local

Model       Cloud/Region         Type  Status     Machines  Cores  Units  Access  Last connection
controller  localhost/localhost  lxd   available         1      -  -      admin   just now
default*    localhost/localhost  lxd   available         0      -  -      admin   20 hours ago

And you can see that the controller that was spawned is listed in the lxc container list.

$ lxc list

Great! Now, we need to create a new model for our Kubernetes deployment:

$ juju add-model kubernetes
$ juju models
Controller: lxd-local

Model       Cloud/Region         Type  Status     Machines  Cores  Units  Access  Last connection
controller  localhost/localhost  lxd   available         1      -  -      admin   just now
default    localhost/localhost  lxd   available          0      -  -      admin   20 hours ago
kubernetes*  localhost/localhost  lxd   available        0      -  -   admin   59 minutes ago

For our Kubernetes machines, we need to create a LXD profile that enables privilege machine containers and add an SSH key to it. Create a new YAML file juju-lxd-profile.yaml with the following configuration:

name: juju-kubernetes
config:
  user.user-data: |
    #cloud-config
    ssh_authorized_keys:
      - @@SSHPUB@@
  boot.autostart: "true"
  linux.kernel_modules: ip_tables,ip6_tables,netlink_diag,nf_nat,overlay
  raw.lxc: |
    lxc.apparmor.profile=unconfined
    lxc.mount.auto=proc:rw sys:rw
    lxc.cap.drop=
  security.nesting: "true"
  security.privileged: "true"
description: ""
devices:
  aadisable:
    path: /sys/module/nf_conntrack/parameters/hashsize
    source: /dev/null
    type: disk
  aadisable1:
    path: /sys/module/apparmor/parameters/enabled
    source: /dev/null
    type: disk

Make sure that you have generated an SSH key pair for user “ubuntu”, before you execute the following one-liner:

$ sed -ri "s'@@SSHPUB@@'$(cat ~/.ssh/id_rsa.pub)'" juju-lxd-profile.yaml

Then update the juju-kubernetes LXD profile:

$ lxc profile edit "juju-kubernetes" < juju-lxd-profile.yaml

Finally, deploy Kubernetes!

$ juju deploy charmed-kubernetes

At the time of writing this post, it is the version charmed-kubernetes-798 that was fetched and deployed. You can watch the status of each component as they get installed via the following:

When everything is green, active and idle, your deployment is ready to be used!


Note: if you are deploying on a machine behind a proxy, check this out! You will need to set the proxy in the Juju model and for some specific components.

Related posts

What is a Kubernetes operator?

Kubernetes is the open source, industry-standard platform for deploying, managing and scaling containerized applications – and applications on Kubernetes are easier with operators. […]

Operate popular open source on Kubernetes – Attend Operator Day at KubeCon EU 2024

Operate popular open source on Kubernetes – Attend Operator Day at KubeCon EU 2024 […]

Understanding roles in software operators

In today’s blog we take a closer look at roles – the key elements that make up the design pattern – and how they work together to simplify maintaining application infrastructure. […]