Ubuntu Multipass: Part Deux (k3s and PVC)

Published: Oct 22, 2019 by Isaac Johnson

K3s on Multipass is pretty nice, but we have to add storage to make it useful.  Let’s add StorageOS to provide a Persistant Volume system.

We can follow this guide (https://docs.storageos.com/docs/platforms/kubernetes/install/1.15)

$ kubectl create -f https://github.com/storageos/cluster-operator/releases/download/1.4.0/storageos-operator.yaml

$ kubectl create -f https://github.com/storageos/cluster-operator/releases/download/1.4.0/storageos-operator.yaml
customresourcedefinition.apiextensions.k8s.io/storageosclusters.storageos.com created
customresourcedefinition.apiextensions.k8s.io/storageosupgrades.storageos.com created
customresourcedefinition.apiextensions.k8s.io/jobs.storageos.com created
customresourcedefinition.apiextensions.k8s.io/nfsservers.storageos.com created
namespace/storageos-operator created
clusterrole.rbac.authorization.k8s.io/storageos-operator created
serviceaccount/storageoscluster-operator-sa created
clusterrolebinding.rbac.authorization.k8s.io/storageoscluster-operator-rolebinding created
deployment.apps/storageos-cluster-operator created
$ kubectl -n storageos-operator get pod
NAME READY STATUS RESTARTS AGE
storageos-cluster-operator-57fc9c468f-f69xf 0/1 ContainerCreating 0 9s

Next we need to create and expose a secret for storage OS to use.

$ echo mySecret | base64
bXlTZWNyZXQK
$ vi myStorageSecret.yaml
$ cat myStorageSecret.yaml 
apiVersion: v1
kind: Secret
metadata:
  name: "storageos-api"
  namespace: "storageos-operator"
  labels:
    app: "storageos"
type: "kubernetes.io/storageos"
data:
  apiUsername: bXlTZWNyZXQK
  apiPassword: bXlTZWNyZXQK

$ kubectl create -f myStorageSecret.yaml 
secret/storageos-api created

Now, let’s create a 512mb cluster:

$ kubectl apply -f myClusterDefn.yaml 
storageoscluster.storageos.com/example-storageos created
$ cat myClusterDefn.yaml 
apiVersion: "storageos.com/v1"
kind: StorageOSCluster
metadata:
  name: "example-storageos"
  namespace: "storageos-operator"
spec:
  secretRefName: "storageos-api" # Reference the Secret created in the previous step
  secretRefNamespace: "storageos-operator" # Namespace of the Secret
  k8sDistro: "kubernetes"
  images:
    nodeContainer: "storageos/node:1.4.0" # StorageOS version
  resources:
    requests:
    memory: "512Mi"

The “memory” setting at the bottom sets the size.

Once we’ve applied the definition we can check that the pods came up.  They will be responsible for distributing the storage across the nodes.

$ kubectl -n storageos get pods -w
NAME READY STATUS RESTARTS AGE
storageos-daemonset-hgv9v 0/1 Init:0/1 0 41s
storageos-daemonset-qg4vz 0/1 Init:0/1 0 41s
storageos-daemonset-qhhkx 0/1 Init:0/1 0 41s
storageos-scheduler-67d54d4f45-cl4kv 0/1 ContainerCreating 0 41s

One problem we have is our cluster just doesn’t have a node that can satisfy these requirements …

NAME READY STATUS RESTARTS AGE
storageos-daemonset-hgv9v 0/1 PodInitializing 0 2m36s
storageos-daemonset-qg4vz 0/1 PodInitializing 0 2m36s
storageos-daemonset-qhhkx 0/1 PodInitializing 0 2m36s
storageos-scheduler-67d54d4f45-5nwlh 0/1 Evicted 0 33s
storageos-scheduler-67d54d4f45-8x62v 0/1 Evicted 0 25s
storageos-scheduler-67d54d4f45-97ngn 0/1 Evicted 0 28s
storageos-scheduler-67d54d4f45-bmqhl 0/1 Evicted 0 31s
storageos-scheduler-67d54d4f45-cl4kv 0/1 Evicted 0 2m36s
storageos-scheduler-67d54d4f45-d2dcq 0/1 Evicted 0 31s
storageos-scheduler-67d54d4f45-ds5mf 0/1 Evicted 0 33s
storageos-scheduler-67d54d4f45-gjjqt 0/1 Evicted 0 24s
storageos-scheduler-67d54d4f45-hgxkk 0/1 Evicted 0 29s
storageos-scheduler-67d54d4f45-hvgb9 0/1 Evicted 0 26s
storageos-scheduler-67d54d4f45-kcbmc 0/1 Evicted 0 32s
storageos-scheduler-67d54d4f45-ps2rw 0/1 Evicted 0 27s
storageos-scheduler-67d54d4f45-sq8fx 0/1 Evicted 0 30s
storageos-scheduler-67d54d4f45-vf4hp 0/1 ContainerCreating 0 22s
storageos-scheduler-67d54d4f45-xh7dc 0/1 Evicted 0 33s

In fact, im certain our little 3 node cluster from the first guide is having a hard time keeping up…

$ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-586d5d67cb-26dxm 0/1 Evicted 0 3m15s
kube-system calico-kube-controllers-586d5d67cb-gvvnd 0/1 Evicted 0 18h
kube-system calico-kube-controllers-586d5d67cb-hfpx2 0/1 Pending 0 11s
kube-system calico-kube-controllers-586d5d67cb-rtl8g 0/1 Evicted 0 3m54s
kube-system calico-node-hwwdx 1/1 Running 0 91s
kube-system calico-node-ndqsh 1/1 Running 0 18h
kube-system calico-node-zhl8g 1/1 Running 0 18h
kube-system coredns-58687784f9-6lns4 0/1 Pending 0 3m20s
kube-system coredns-58687784f9-7dw4l 0/1 Evicted 0 18h
kube-system coredns-58687784f9-d4vvx 0/1 Evicted 0 4m29s
kube-system coredns-58687784f9-jfvsp 0/1 Evicted 0 18h
kube-system coredns-58687784f9-kggg5 0/1 Evicted 0 5m10s
kube-system coredns-58687784f9-ks2pv 0/1 Pending 0 45s
kube-system dns-autoscaler-79599df498-76rd6 0/1 Evicted 0 18h
kube-system dns-autoscaler-79599df498-fgtcw 0/1 Pending 0 8s
kube-system dns-autoscaler-79599df498-w2hsl 0/1 Evicted 0 3m52s
kube-system kube-apiserver-node1 1/1 Running 0 18h
kube-system kube-controller-manager-node1 1/1 Running 1 18h
kube-system kube-proxy-sfg6t 1/1 Running 0 59s
kube-system kube-proxy-tcdpj 1/1 Running 0 18h
kube-system kube-proxy-tmdvf 1/1 Running 0 18h
kube-system kube-scheduler-node1 1/1 Running 1 18h
kube-system kubernetes-dashboard-556b9ff8f8-nxvpf 0/1 Evicted 0 18h
kube-system kubernetes-dashboard-556b9ff8f8-pqlc9 0/1 Pending 0 81s
kube-system nginx-proxy-node2 1/1 Running 0 18h
kube-system nginx-proxy-node3 1/1 Running 0 18h
kube-system nodelocaldns-7fl6d 0/1 ContainerCreating 0 77s
kube-system nodelocaldns-87rbr 1/1 Running 0 17s
kube-system nodelocaldns-vmw8w 0/1 Running 0 5s
storageos-operator storageos-cluster-operator-57fc9c468f-46hfv 0/1 Evicted 0 2m43s
storageos-operator storageos-cluster-operator-57fc9c468f-4z9kx 0/1 Evicted 0 2m39s
storageos-operator storageos-cluster-operator-57fc9c468f-5zqpm 0/1 Evicted 0 2m45s
storageos-operator storageos-cluster-operator-57fc9c468f-65jnb 0/1 Evicted 0 2m40s
storageos-operator storageos-cluster-operator-57fc9c468f-8qz62 0/1 Evicted 0 2m41s
storageos-operator storageos-cluster-operator-57fc9c468f-b49d6 0/1 Evicted 0 2m44s
storageos-operator storageos-cluster-operator-57fc9c468f-bf8cv 0/1 Evicted 0 2m38s
storageos-operator storageos-cluster-operator-57fc9c468f-c5lmn 0/1 Evicted 0 2m41s
storageos-operator storageos-cluster-operator-57fc9c468f-dgrg2 0/1 Evicted 0 2m45s
storageos-operator storageos-cluster-operator-57fc9c468f-f69xf 0/1 Evicted 0 10m
storageos-operator storageos-cluster-operator-57fc9c468f-jpmqg 0/1 Evicted 0 2m39s
storageos-operator storageos-cluster-operator-57fc9c468f-jrvx5 0/1 Evicted 0 2m45s
storageos-operator storageos-cluster-operator-57fc9c468f-ltvtm 0/1 Evicted 0 2m44s
storageos-operator storageos-cluster-operator-57fc9c468f-n5fkc 0/1 Evicted 0 2m45s
storageos-operator storageos-cluster-operator-57fc9c468f-nn5bn 0/1 Evicted 0 2m43s
storageos-operator storageos-cluster-operator-57fc9c468f-q6gjj 0/1 Evicted 0 2m42s
storageos-operator storageos-cluster-operator-57fc9c468f-txf54 0/1 Pending 0 2m37s
storageos storageos-daemonset-7rlv5 0/1 Evicted 0 48s
storageos storageos-daemonset-hgv9v 0/1 ImagePullBackOff 0 6m3s
storageos storageos-daemonset-qg4vz 0/1 ImagePullBackOff 0 6m3s
storageos storageos-scheduler-67d54d4f45-5nwlh 0/1 Evicted 0 4m
storageos storageos-scheduler-67d54d4f45-8x62v 0/1 Evicted 0 3m52s
storageos storageos-scheduler-67d54d4f45-97ngn 0/1 Evicted 0 3m55s
storageos storageos-scheduler-67d54d4f45-bmqhl 0/1 Evicted 0 3m58s
storageos storageos-scheduler-67d54d4f45-cl4kv 0/1 Evicted 0 6m3s
storageos storageos-scheduler-67d54d4f45-d2dcq 0/1 Evicted 0 3m58s
storageos storageos-scheduler-67d54d4f45-ds5mf 0/1 Evicted 0 4m
storageos storageos-scheduler-67d54d4f45-gjjqt 0/1 Evicted 0 3m51s
storageos storageos-scheduler-67d54d4f45-hgxkk 0/1 Evicted 0 3m56s
storageos storageos-scheduler-67d54d4f45-hvgb9 0/1 Evicted 0 3m53s
storageos storageos-scheduler-67d54d4f45-kcbmc 0/1 Evicted 0 3m59s
storageos storageos-scheduler-67d54d4f45-ps2rw 0/1 Evicted 0 3m54s
storageos storageos-scheduler-67d54d4f45-sq8fx 0/1 Evicted 0 3m57s
storageos storageos-scheduler-67d54d4f45-ssg2m 0/1 Pending 0 114s
storageos storageos-scheduler-67d54d4f45-vf4hp 0/1 Evicted 0 3m49s
storageos storageos-scheduler-67d54d4f45-xh7dc 0/1 Evicted 0 4m

Using K3s with larger Nodes

Let’s launch a few larger xenial instances.

$ multipass launch -c 2 -d 15G -m 2G -n k3s01 xenial
Retrieving image: 9% 

After the first one, the rest launch fast (after an image is cached):

$ multipass launch -c 2 -d 15G -m 2G -n k3s01 xenial
Launched: k3s01                                                                 
$ multipass launch -c 2 -d 15G -m 2G -n k3s02 xenial
Launched: k3s02                                                                 
$ multipass launch -c 2 -d 15G -m 2G -n k3s03 xenial
Launched: k3s03      

Let’s now hop into the first node and launch k3s under root:

$ multipass shell k3s01
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-165-generic x86_64)

 * Documentation: https://help.ubuntu.com
 * Management: https://landscape.canonical.com
 * Support: https://ubuntu.com/advantage

0 packages can be updated.
0 updates are security updates.

New release '18.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.


To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

multipass@k3s01:~$ sudo su - 
root@k3s01:~# curl -sfL https://get.k3s.io | sh -
[INFO] Finding latest release
[INFO] Using v0.9.1 as release
[INFO] Downloading hash https://github.com/rancher/k3s/releases/download/v0.9.1/sha256sum-amd64.txt
[INFO] Downloading binary https://github.com/rancher/k3s/releases/download/v0.9.1/k3s
[INFO] Verifying binary download
[INFO] Installing k3s to /usr/local/bin/k3s
[INFO] Creating /usr/local/bin/kubectl symlink to k3s
[INFO] Creating /usr/local/bin/crictl symlink to k3s
[INFO] Creating /usr/local/bin/ctr symlink to k3s
[INFO] Creating killall script /usr/local/bin/k3s-killall.sh
[INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO] env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO] systemd: Creating service file /etc/systemd/system/k3s.service
[INFO] systemd: Enabling k3s unit
Created symlink from /etc/systemd/system/multi-user.target.wants/k3s.service to /etc/systemd/system/k3s.service.
[INFO] systemd: Starting k3s

then get the k8s config

root@k3s01:~# cat /etc/rancher/k3s/k3s.yaml
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJWakNCL3FBREFnRUNBZ0VBTUFvR0NDcUdTTTQ5QkFNQ01DTXhJVEFmQmdOVkJBTU1HR3N6Y3kxelpYSjIKWlhJdFkyRkFNVFUzTURRd09UYzJNREFlRncweE9URXdNRGN3TURVMk1EQmFGdzB5T1RFd01EUXdNRFUyTURCYQpNQ014SVRBZkJnTlZCQU1NR0dzemN5MXpaWEoyWlhJdFkyRkFNVFUzTURRd09UYzJNREJaTUJNR0J5cUdTTTQ5CkFnRUdDQ3FHU000OUF3RUhBMElBQk9YaEhkVCtaMzNSYUVwU2MxUmdRTkhRTHVrTG5ycjJVMmlZZGZqN1djL08KNkhhb09zYWhQQkNkN0E1TEplZ25Pd3M4RkNYbUpjeG1yRWM1NEk4MXRTcWpJekFoTUE0R0ExVWREd0VCL3dRRQpBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUZNaGVYYTE3M285CnlwQ3JiSStOQlhTZTUyUGRDeUZvdndVTktaOFJMdDFmQWlBY241OFM1YktIQzJnYWtaeTdTcFZWbG9Hek1CQTAKYVVZS1VrUHpwc3plQ2c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://127.0.0.1:6443
  name: default
contexts:
- context:
    cluster: default
    user: default
  name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
  user:
    password: 13ce1f2b78925ec83bf707d1827067fc
    username: admin
root@k3s01:~# cat /var/lib/rancher/k3s/server/node-token
K10c5795c31973084adf816154d5ac70d85b83c6336c9f76d6accbf5b8df590e6ab::node:eb0b4dcfe8dad3df47361ce12d0988ed

Make sure to get the IP and change the server line server: https://127.0.0.1:6443 above before using locally;

$ multipass list
Name State IPv4 Image
k3s03 Running 192.168.64.14 Ubuntu 16.04 LTS
k3s01 Running 192.168.64.12 Ubuntu 16.04 LTS
k3s02 Running 192.168.64.13 Ubuntu 16.04 LTS

Now let’s add other nodes

$ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-66f496764-2cz8f 1/1 Running 0 2m32s
kube-system helm-install-traefik-5hn5g 0/1 Completed 0 2m32s
kube-system svclb-traefik-4r6tr 3/3 Running 0 2m18s
kube-system traefik-d869575c8-58nrn 1/1 Running 0 2m18s

Now let’s add our other nodes

$ multipass shell k3s02
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-165-generic x86_64)

 * Documentation: https://help.ubuntu.com
 * Management: https://landscape.canonical.com
 * Support: https://ubuntu.com/advantage

0 packages can be updated.
0 updates are security updates.

New release '18.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.


To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

multipass@k3s02:~$ sudo su -
root@k3s02:~# curl -sfL https://get.k3s.io | K3S_URL=https://192.168.64.12:6443 K3S_TOKEN=K10c5795c31973084adf816154d5ac70d85b83c6336c9f76d6accbf5b8df590e6ab::node:eb0b4dcfe8dad3df47361ce12d0988ed sh -
[INFO] Finding latest release
[INFO] Using v0.9.1 as release
[INFO] Downloading hash https://github.com/rancher/k3s/releases/download/v0.9.1/sha256sum-amd64.txt
[INFO] Downloading binary https://github.com/rancher/k3s/releases/download/v0.9.1/k3s
[INFO] Verifying binary download
[INFO] Installing k3s to /usr/local/bin/k3s
[INFO] Creating /usr/local/bin/kubectl symlink to k3s
[INFO] Creating /usr/local/bin/crictl symlink to k3s
[INFO] Creating /usr/local/bin/ctr symlink to k3s
[INFO] Creating killall script /usr/local/bin/k3s-killall.sh
[INFO] Creating uninstall script /usr/local/bin/k3s-agent-uninstall.sh
[INFO] env: Creating environment file /etc/systemd/system/k3s-agent.service.env
[INFO] systemd: Creating service file /etc/systemd/system/k3s-agent.service
[INFO] systemd: Enabling k3s-agent unit
Created symlink from /etc/systemd/system/multi-user.target.wants/k3s-agent.service to /etc/systemd/system/k3s-agent.service.
[INFO] systemd: Starting k3s-agent

And do the same for k3s03

$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k3s02 Ready worker 34m v1.15.4-k3s.1
k3s01 Ready master 40m v1.15.4-k3s.1
k3s03c Ready worker 10s v1.15.4-k3s.1

Setting up storageOS

$ kubectl create -f https://github.com/storageos/cluster-operator/releases/download/1.4.0/storageos-operator.yaml
customresourcedefinition.apiextensions.k8s.io/storageosclusters.storageos.com created
customresourcedefinition.apiextensions.k8s.io/storageosupgrades.storageos.com created
customresourcedefinition.apiextensions.k8s.io/jobs.storageos.com created
customresourcedefinition.apiextensions.k8s.io/nfsservers.storageos.com created
namespace/storageos-operator created
clusterrole.rbac.authorization.k8s.io/storageos-operator created
serviceaccount/storageoscluster-operator-sa created
clusterrolebinding.rbac.authorization.k8s.io/storageoscluster-operator-rolebinding created
deployment.apps/storageos-cluster-operator created

Now check the pod

$ kubectl -n storageos-operator get pod
NAME READY STATUS RESTARTS AGE
storageos-cluster-operator-6bb7ccc597-5fzgm 1/1 Running 0 112s

And then we can test it

$ kubectl -n storageos get pods
NAME READY STATUS RESTARTS AGE
storageos-scheduler-78b68c74cb-fx5lk 1/1 Running 0 21m
storageos-daemonset-d997r 1/1 Running 0 21m
storageos-daemonset-vz5sv 0/1 Init:CrashLoopBackOff 6 10m
storageos-daemonset-bmsm6 0/1 Init:CrashLoopBackOff 8 21m
storageos-daemonset-ll7ml 0/1 Init:CrashLoopBackOff 8 21m
storageos-daemonset-mlvbk 1/1 Running 0 4m47s

I discovered that storageos fails on xenial (16.04) and does better with the standard 18.04 ( bionic ) image.

I recreated the cluster using standard images and tried again…

$ multipass list --format table
Name State IPv4 Image
k3s003 Running 192.168.64.21 Ubuntu 18.04 LTS
k3s002 Running 192.168.64.20 Ubuntu 18.04 LTS
k3s001 Running 192.168.64.19 Ubuntu 18.04 LTS
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k3s002 Ready worker 24h v1.15.4-k3s.1
k3s003 Ready worker 24h v1.15.4-k3s.1
k3s001 Ready master 24h v1.15.4-k3s.1

the k3s install (again)

multipass@k3s001:~$ sudo su -
root@k3s001:~# curl -sfL https://get.k3s.io | sh -
[INFO] Finding latest release
[INFO] Using v0.9.1 as release
[INFO] Downloading hash https://github.com/rancher/k3s/releases/download/v0.9.1/sha256sum-amd64.txt
[INFO] Downloading binary https://github.com/rancher/k3s/releases/download/v0.9.1/k3s
root@k3s001:~# curl -sfL https://get.k3s.io | sh -
[INFO] Finding latest release
[INFO] Using v0.9.1 as release
[INFO] Downloading hash https://github.com/rancher/k3s/releases/download/v0.9.1/sha256sum-amd64.txt
[INFO] Downloading binary https://github.com/rancher/k3s/releases/download/v0.9.1/k3s
root@k3s001:~# curl -sfL https://get.k3s.io | sh -
[INFO] Finding latest release
[INFO] Using v0.9.1 as release
[INFO] Downloading hash https://github.com/rancher/k3s/releases/download/v0.9.1/sha256sum-amd64.txt
[INFO] Downloading binary https://github.com/rancher/k3s/releases/download/v0.9.1/k3s
[INFO] Verifying binary download
[INFO] Installing k3s to /usr/local/bin/k3s
[INFO] Creating /usr/local/bin/kubectl symlink to k3s
[INFO] Creating /usr/local/bin/crictl symlink to k3s
[INFO] Creating /usr/local/bin/ctr symlink to k3s
[INFO] Creating killall script /usr/local/bin/k3s-killall.sh
[INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO] env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO] systemd: Creating service file /etc/systemd/system/k3s.service
[INFO] systemd: Enabling k3s unit
Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service.
[INFO] systemd: Starting k3s
root@k3s001:~# cat /etc/rancher/k3s/k3s.yaml
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJWekNCL3FBREFnRUNBZ0VBTUFvR0NDcUdTTTQ5QkFNQ01DTXhJVEFmQmdOVkJBTU1HR3N6Y3kxelpYSjIKWlhJdFkyRkFNVFUzTURReE5Ea3hNREFlRncweE9URXdNRGN3TWpJeE5UQmFGdzB5T1RFd01EUXdNakl4TlRCYQpNQ014SVRBZkJnTlZCQU1NR0dzemN5MXpaWEoyWlhJdFkyRkFNVFUzTURReE5Ea3hNREJaTUJNR0J5cUdTTTQ5CkFnRUdDQ3FHU000OUF3RUhBMElBQkxmQ2FPREVyQVlYMGdkSXNZVlNuYXFCSDloTGdHL0svVXpiNEN2c0p1YnMKQ0dXYXkyOUNJQlB3TmhucVVxYjlCbGZORXpJZzBTYjNpTWEvbmVVU0NoaWpJekFoTUE0R0ExVWREd0VCL3dRRQpBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSUdYMDR6RlIvcXVwCmJtMnBjYVArQ1k2RFBwNHRUaEowQ3o3SS94RVIvK3NnQWlFQS9rSm1wNHE1STM1RnBObmtXM1FzNVdLa1o3SFoKOHZKbmFzeGV5MU5nT1hVPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://127.0.0.1:6443
  name: default
contexts:
- context:
    cluster: default
    user: default
  name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
  user:
    password: 2b3bb9fdc218d5b6d0d0f4d68039764b
    username: admin
root@k3s001:~# cat /var/lib/rancher/k3s/server/node-token
K10ccd856eec2f143409ec885b18d5a8f5a91d13ed645d5d16e49fe1c8e64095891::node:1e58d200c6c2107c43cf1dbd27142e7d
root@k3s001:~# 

Set server in config : 192.168.64.19

Now let’s check our storage class then make it default:

$ kubectl get sc
NAME PROVISIONER AGE
fast kubernetes.io/storageos 6h8m
$ kubectl patch storageclass fast -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
storageclass.storage.k8s.io/fast patched
$ kubectl get sc
NAME PROVISIONER AGE
fast (default) kubernetes.io/storageos 6h12m

Setting it as default is an important step. If you don’t, you’ll have to be explicit in any deploys, be them yaml or helm based.

Installing Helm/Tiller

$ cat /Users/johnsi10/Documents/rbac-config.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system
$ kubectl create -f /Users/johnsi10/Documents/rbac-config.yaml
serviceaccount/tiller created
clusterrolebinding.rbac.authorization.k8s.io/tiller created
$ helm init --service-account tiller --history-max 200
$HELM_HOME has been configured at /Users/johnsi10/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation

Now that we have Tiller and a default storage class…

Adding a dashboard:

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
secret/kubernetes-dashboard-certs created
serviceaccount/kubernetes-dashboard created
role.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created
deployment.apps/kubernetes-dashboard created
service/kubernetes-dashboard created

And we need a dashboard admin user to use it:

$ cat dashboard-user.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kube-system
$ kubectl apply -f dashboard-user.yaml 
serviceaccount/admin-user created
$ cat dashboard-binding.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kube-system
$ kubectl apply -f dashboard-binding.yaml 
clusterrolebinding.rbac.authorization.k8s.io/admin-user created

Next we’ll need the token for the dashboard

$ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')
Name: admin-user-token-xrlcg
Namespace: kube-system
Labels: <none>
Annotations: kubernetes.io/service-account.name: admin-user
              kubernetes.io/service-account.uid: e8da6cd7-bd58-4b8d-9cd4-98fabbd0e15b

Type: kubernetes.io/service-account-token

Data
====
ca.crt: 526 bytes
namespace: 11 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLXhybGNnIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJlOGRhNmNkNy1iZDU4LTRiOGQtOWNkNC05OGZhYmJkMGUxNWIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06YWRtaW4tdXNlciJ9.s8sJf_6Uy1VvuMo_9n0fAv9K8o8U-Nm9RMohaK-agjMYvB_GG32SKFBnRcdPyqGdZu9Wt0huHI_rssw6Dy5v-jONPlZMMM_HInEqQU4O9f7FN4EMF5oX5CtqVhp-iwpES55RyyxPy_vlwMDUFbJK3GEggzEdk9l3sXtg95Kl6-e_VTrCOKbLkh4s6krw106aik4y8SJVNZsBDHtaDDOsVqQB59eLnLVY73JEcTc-RZ-3HtrPbmtnI-Z2PEHG8sD45QGuKK6m4mugGQxZeQ9-i-bYhuOsPiTGPM_L7TSK1GlEHIA9tLVPtMwsny47ORDC7QYEuK2ldlFatfXVbIDMGA

and use port-forward for the dashboard

$ kubectl port-forward kubernetes-dashboard-7d75c474bb-rb2tr -n kube-system 8443:8443
Forwarding from 127.0.0.1:8443 -> 8443
Forwarding from [::1]:8443 -> 8443
Handling connection for 8443

And we can see our storageos there as well

Networking.

The part that I’m working on next (and had been holding this blog entry on, but can’t delay further), is loadbalancing and networking.

I tried just installing MetalLB (https://metallb.universe.tf/installation/)

$ kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.8.1/manifests/metallb.yaml
namespace/metallb-system created
podsecuritypolicy.policy/speaker created
serviceaccount/controller created
serviceaccount/speaker created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
role.rbac.authorization.k8s.io/config-watcher created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/config-watcher created
daemonset.apps/speaker created
deployment.apps/controller created


$ kubectl apply -f layer2-config.yaml 
configmap/config created
$ cat layer2-config.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 10.42.5.240-10.42.5.250

And we could see that indeed LB requests were satisified by MetalLB

However, they were completely unroutable.  So yes, Metal LB handed out IPs, but they were as useful as a poopy flavoured lolly pop.  I’ve found a guide with Vagrant and Flannel and Metal LB that launches a cluster in VBox.  I’m working on figuring out this networking area and would welcome insights (isaac.johnson@gmail.com).

Summary:

After a bit of trial and error, we used Multipass and Bionic (18.04) images to make a great k3s cluster with valid persistent storage.  However, we stopped short of solving our networking and routing.

k3s multipass tutorial

Isaac Johnson

Isaac Johnson

Cloud Solutions Architect

Isaac is a CSA and DevOps engineer who focuses on cloud migrations and devops processes. He also is a dad to three wonderful daughters (hence the references to Princess King sprinkled throughout the blog).

Theme built by C.S. Rhymes