- Solution Objective
- Features
- Architecture - Overview - Infrastructure - Workflow - Network - Security - High-Availability - Monitoring
- Installation and Configuration
- On ALL Nodes, if within GFW
- Master
- Worker
- Add New Worker
- Bash Auto Completion
- Install
helm
(tiller) - Check Tiller's status and find the following error due to GFW - Installfluxcd
- Install and Configurefluxctl
- Why K3S
- IoT, lightweight and isolate application from infrastructure
- You declaratively describe the entire desired state of your system in git
- Automate everything and you manage code rather than container
- Less maintenance with high tolerance
- Native CI/ CD
- K3S + GitOps
- Raspberry-Pi software stack
- The flow of code: change then update
- GitOps' fluxcd = automated git -> cluster synchronisation
Reference > https://docs.fluxcd.io/en/latest/introduction.html
Image source > https://github.com/fluxcd/flux
- SSL, managed by k3s
- Software-firewall being used
- Extra VPN might be required, software or hardware ones
I'm considering to replace openvpn
with wireguard
to establish and maintain the encryption tunnel between k3s master and raspberrypi end-point as k3s worker.
- Isolated namespace:
flux
anddemo
(deployment target sample) - Cluster access control:
sudo chmod 644 /etc/rancher/k3s/k3s.yaml
- Access toke to Git =
kubectl secret
Reference > https://www.danielstechblog.io/running-a-kubernetes-cluster-with-k3s-on-raspbian/
Currently k3s does not support HA masters, we can have only one master right now. Really?
https://github.com/billimek/k8s-gitops/tree/master/monitoring
helm
andtiller
- simplify and standardize install and deploymentfluxctl
- change code, instead of containergit
- centralized repo
Reference > https://rancher.com/docs/k3s/latest/en/running/
-
A pre-requisite step on ALL nodes, if within GFW or air-gap env, before install starts and if adding new node, this is a must as well
# Download the appropriate release wget https://github.com/rancher/k3s/releases/download/v0.9.0/k3s-airgap-images-amd64.tar sudo mkdir -p /var/lib/rancher/k3s/agent/images/ sudo cp pause-3.1.tar /var/lib/rancher/k3s/agent/images/ sudo cp k3s-airgap-images-amd64.tar /var/lib/rancher/k3s/agent/images/
-
Make
kubeconfig
readable to non-root user,curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644
or
curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" sh -s -
or if you want to use
docker
instead ofcontainerd
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--docker" sh -
On master node
sudo cat /var/lib/rancher/k3s/server/node-token
K104dcf919a073e2335312f1bee5e41a024d76c19d86d91190661069cd8df80ee6f::node:7353837f5b3029369df7c7a7ad27d280
On worker node(s)
export K3S_URL="https://192.168.100.31:6443"
export K3S_TOKEN="K104dcf919a073e2335312f1bee5e41a024d76c19d86d91190661069cd8df80ee6f::node:7353837f5b3029369df7c7a7ad27d280"
curl -sfL https://get.k3s.io | K3S_URL=${K3S_URL} K3S_TOKEN=${K3S_TOKEN} sh -
Check on master
kubectl get nodes
Check journal
journalctl -u k3s-agent
In case you want to uninstall
/usr/local/bin/k3s-uninstall.sh
Attention: if k3s-agent gets uninstalled, /var/lib/rancher/k3s/agent/images/
will be erased as well. You would have to recreate it and copy the necessary image.tar files into it. Then systemctl restart k3s-agent.service
# Download the appropriate release. You need arm64 binary for Raspberry-Pi device
wget https://github.com/rancher/k3s/releases/download/v0.9.0/k3s-airgap-images-amd64.tar
sudo mkdir -p /var/lib/rancher/k3s/agent/images/
sudo cp pause-3.1.tar /var/lib/rancher/k3s/agent/images/
sudo cp k3s-airgap-images-amd64.tar /var/lib/rancher/k3s/agent/images/
-
Setup env
source <(kubectl completion bash) echo "source <(kubectl completion bash)" >> ~/.bashrc alias k=kubectl complete -F __start_kubectl k
cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
$ curl -LO https://git.io/get_helm.sh
$ chmod 700 get_helm.sh
$ ./get_helm.sh
# Create a service account for tiller
kubectl -n kube-system create sa tiller
# Create a cluster role binding for tiller
kubectl create clusterrolebinding tiller-cluster-rule \
--clusterrole=cluster-admin \
--serviceaccount=kube-system:tiller
# Deploy tiller to kube-system
helm init --skip-refresh --upgrade --service-account tiller --history-max 20
Reference > https://rancher.com/docs/rancher/v2.x/en/installation/ha/helm-init/
kubectl -n kube-system describe pod tiller-deploy-75f6c87b87-4f8zc
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 57s default-scheduler Successfully assigned kube-system/tiller-deploy-75f6c87b87-4f8zc to node05
Warning Failed 26s kubelet, node05 Failed to pull image "gcr.io/kubernetes-helm/tiller:v2.14.3": rpc error: code = Unknown desc = failed to resolve image "gcr.io/kubernetes-helm/tiller:v2.14.3": no available registry endpoint: failed to do request: Head https://gcr.io/v2/kubernetes-helm/tiller/manifests/v2.14.3: dial tcp 74.125.23.82:443: i/o timeout
Warning Failed 26s kubelet, node05 Error: ErrImagePull
Normal BackOff 25s kubelet, node05 Back-off pulling image "gcr.io/kubernetes-helm/tiller:v2.14.3"
Warning Failed 25s kubelet, node05 Error: ImagePullBackOff
Normal Pulling 13s (x2 over 56s) kubelet, node05 Pulling image "gcr.io/kubernetes-helm/tiller:v2.14.3"
The workaround is to place tiller.tar
into specific k3s' images path /var/lib/rancher/k3s/agent/images/
on each agent/ worker
docker pull sapcc/tiller:v2.14.3
docker tag sapcc/tiller:v2.14.3 gcr.io/kubernetes-helm/tiller:v2.14.3
docker save gcr.io/kubernetes-helm/tiller:v2.14.3 > ./tiller.tar
sudo cp tiller.tar /var/lib/rancher/k3s/agent/images/
sudo systemctl restart k3s-agent.service
Reference > https://docs.fluxcd.io/en/latest/tutorials/get-started-helm.html
kubectl -n kube-system create sa tiller
kubectl create clusterrolebinding tiller-cluster-rule \
--clusterrole=cluster-admin \
--serviceaccount=kube-system:tiller
# Deploy tiller in cluster
helm init --skip-refresh --upgrade --service-account tiller --history-max 10
# Add repo
helm repo add fluxcd https://charts.fluxcd.io
# Apply the Helm Release CRD
kubectl apply -f https://raw.githubusercontent.com/fluxcd/flux/helm-0.10.1/deploy-helm/flux-helm-release-crd.yaml
Fork fluxcd/flux-get-started
on GitHub and replace the fluxcd
with your GitHub username
Reference > https://docs.fluxcd.io/en/latest/tutorials/get-started-helm.html#install-flux
helm upgrade -i flux \
--set helmOperator.create=true \
--set helmOperator.createCRD=false \
--set [email protected]:j3ffyang/flux-get-started \
--namespace flux fluxcd/flux
You would have
kubectl -n flux get all
NAME READY STATUS RESTARTS AGE
pod/flux-memcached-b8f88949-zsnhm 1/1 Running 0 4m47s
pod/flux-helm-operator-6bcb497545-dkpcm 1/1 Running 0 4m47s
pod/flux-7c4c75f86-kt68f 1/1 Running 0 4m47s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/flux-memcached ClusterIP 10.43.240.190 <none> 11211/TCP 4m47s
service/flux ClusterIP 10.43.136.163 <none> 3030/TCP 4m47s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/flux-memcached 1/1 1 1 4m47s
deployment.apps/flux-helm-operator 1/1 1 1 4m47s
deployment.apps/flux 1/1 1 1 4m47s
NAME DESIRED CURRENT READY AGE
replicaset.apps/flux-memcached-b8f88949 1 1 1 4m47s
replicaset.apps/flux-helm-operator-6bcb497545 1 1 1 4m47s
replicaset.apps/flux-7c4c75f86 1 1 1 4m47s
https://github.com/fluxcd/flux/releases/download/1.14.2/fluxctl_linux_amd64
sudo cp fluxctl_linux_amd64 /usr/local/bin/fluxctl
sudo chmod 755 /usr/local/bin/fluxctl
fluxctl --k8s-fwd-ns=flux list-workloads
Get the access key
fluxctl identity --k8s-fwd-ns flux
In order to sync your cluster state with git you need to copy the public key and create a deploy key with write access on your GitHub repository.
Open GitHub, navigate to your fork, go to Settings
> Deploy keys
, click on Add deploy key
, give it a Title
, check Allow write access
, paste the Flux public key and click Add key
.
(Or replace YOURUSER with your GitHub ID in this url: https://github.com/YOURUSER/flux-get-started/settings/keys/new and paste the key there.)
helm list --namespace demo
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
mongodb 1 Wed Sep 25 18:31:56 2019 DEPLOYED mongodb-4.9.0 4.0.3 demo
git clone [email protected]:j3ffyang/flux-get-started.git
cd flux-get-started
vi releases/mongodb.yaml
values:
image:
repository: bitnami/mongodb
tag: 4.0.6
Then commit
git add --all; git commit --message "upgrade mongo tag from 403 to 406"; git push
Check the Change
kubectl -n flux logs deployment/flux -f
kubectl describe -n demo deployment/mongodb | grep Image
kubectl -n demo get all
You would see
kubectl describe -n demo deployment/mongodb | grep Image
Image: docker.io/bitnami/mongodb:4.0.6
Check Status
fluxctl list-controllers -a --k8s-fwd-ns flux
This is the screenshot of that I switched MongoDB's tag from 4.0.6
back to 4.0.3
. The change took ~2 minutes to complete.
On my Debian laptop, burn an OS image on /dev/sda
Warning: double check USB device path, before burning
jeff@debian:~/Downloads$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 1 14.9G 0 disk
├─sda1 8:1 1 256M 0 part
└─sda2 8:2 1 5.8G 0 part
nvme0n1 259:0 0 477G 0 disk
├─nvme0n1p1 259:1 0 243M 0 part /boot
├─nvme0n1p2 259:2 0 1K 0 part
└─nvme0n1p5 259:3 0 476.7G 0 part
└─nvme0n1p5_crypt 254:0 0 476.7G 0 crypt
├─debian--vg-root 254:1 0 28G 0 lvm /
├─debian--vg-swap_1 254:2 0 15.6G 0 lvm [SWAP]
└─debian--vg-home 254:3 0 433.1G 0 lvm /home
Download and load the image (be careful and you understand what you're doing when using dd
)
sudo dd bs=4M if=2019-09-26-raspbian-buster-lite.img of=/dev/sda conv=fsync status=progress
Download 64bit image for Raspberry Pi 4 from https://github.com/sakaki-/raspbian-nspawn-64
wget -c https://github.com/sakaki-/raspbian-nspawn-64/releases/download/v1.3.0/raspbian-nspawn-64.img.xz
sudo bash -c "xzcat raspbian-nspawn-64.img.xz > /dev/sdX && sync"
# replace X with the correct device and make sure you know what you're doing
Or Ubuntu 18.04 ARM64 RPI 3 official image published > https://www.raspberrypi.org/forums/viewtopic.php?t=230742, https://blog.cloudkernels.net/posts/rpi4-64bit-image/ (find the packaged image at the bottom) and https://github.com/TheRemote/Ubuntu-Server-raspi4-unofficial/releases
Power up Raspberry-Pi
Install ssh-server
and systemctl enable ssh.service
then systemctl start ssh.service
pi@raspberrypi:~ $ uname -a
Linux raspberrypi 4.19.69-v8+ #1261 SMP PREEMPT Tue Sep 3 20:27:16 BST 2019 aarch64 GNU/Linux
curl -fsSL get.docker.com -o get-docker.sh && sh get-docker.sh
sudo gpasswd -a $USER docker
Download airgap binary for arm64 (from https://github.com/rancher/k3s/releases/) and place it into /var/lib/rancher/k3s/agent/images
if the device doesn't have access to gcr.io
and/ or googleapis.com
pi@raspberrypi:~ $ pwd
/home/pi
pi@raspberrypi:~ $ ls
Downloads k3s-airgap-images-arm64.tar
pi@raspberrypi:~ $ sudo mkdir -p /var/lib/rancher/k3s/agent/images
pi@raspberrypi:~ $ sudo cp k3s-airgap-images-arm64.tar /var/lib/rancher/k3s/agent/images
Configure K3S on Raspberry
# on K3S master
sudo cat /var/lib/rancher/k3s/server/node-token
K104dcf919a073e2335312f1bee5e41a024d76c19d86d91190661069cd8df80ee6f::node:7353837f5b3029369df7c7a7ad27d280
# on Raspberry
export K3S_URL="https://192.168.100.31:6443"
export K3S_TOKEN="K104dcf919a073e2335312f1bee5e41a024d76c19d86d91190661069cd8df80ee6f::node:7353837f5b3029369df7c7a7ad27d280"
curl -sfL https://get.k3s.io | K3S_URL=${K3S_URL} K3S_TOKEN=${K3S_TOKEN} sh -
If you want to specify a version of k3s
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v0.9.1 K3S_URL=${K3S_URL} K3S_TOKEN=${K3S_TOKEN} sh -
-
If you need to uninstall
/usr/local/bin/k3s-agent-uninstall.sh
, all/var/lib/rancher/
will be removed. You would have to recreatepi@raspberrypi:~ $ sudo mkdir -p /var/lib/rancher/k3s/agent/images pi@raspberrypi:~ $ sudo cp k3s-airgap-images-arm64.tar /var/lib/rancher/k3s/agent/images
-
If
journalctl -u k3s-agent.service
complains
level=error msg="Node password rejected, contents of '/var/lib/rancher/k3s/agent/node-password.txt' may not match server passwd entry"
You can find the correct key on master
sudo cat /var/lib/rancher/k3s/server/cred/node-passwd
35f386b0221c7c6e6f024d73fdcc089f,node06
02e6618e937ae3a925d8f8d04072f368,node05
08e44c44157f1dfaa302cecc6268350d,node04
8d2859b7c9a3a7d95155ba0343c5d1ce,node03
5f52b394dcc6afe1cc8a1afac33ba4d6,raspberrypi
The last one is what you're looking for, then on worker edit /var/lib/rancher/k3s/agent/node-password.txt
/usr/local/bin/k3s-uninstall.sh
Uninstall will erase /var/lib/rancher/k3s/agent/images
or k3s-agent-uninstall.sh
Reference > https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md https://kubernetes.io/docs/tasks/debug-application-cluster/crictl/ https://raesene.github.io/blog/2018/08/05/Docker-Containers-Without-Docker/
- Import an image
pi@raspberrypi:~ $ sudo ctr images import vantiq-edge_1.26.15.tar # the image needs built on ARM64 architecture
unpacking docker.io/vantiq/vantiq-edge:1.26.15 (sha256:21998d513b3c0d1e90e3a255a5dffbea69090e58185f0b74a42a7026771c124e)...done
pi@raspberrypi:~ $ sudo crictl images
IMAGE TAG IMAGE ID SIZE
docker.io/coredns/coredns 1.6.3 8ae59e1bfb260 42.5MB
docker.io/library/traefik 1.7.14 f521d51518617 81.5MB
docker.io/rancher/klipper-helm v0.1.5 b4c152c2279ca 80.4MB
k8s.gcr.io/pause 3.1 6cf7c80fe4444 529kB
docker.io/rancher/klipper-lb v0.1.1 f4fe2ba53ca6a 6.22MB
docker.io/vantiq/vantiq-edge 1.26.15 6c34e50d96de0 339MB
- Label the node on which the private image is going to get launched
kubectl label nodes raspberrypi device=raspberrypi
- Edit
deployment.yaml
withnodeAffinity
specification
apiVersion: apps/v1
kind: Deployment
metadata:
name: vantiq-edge-deployment
spec:
selector:
matchLabels:
app: vantiq-edge
template:
metadata:
labels:
app: vantiq-edge
spec:
containers:
- name: vantiq-edge
image: docker.io/vantiq/vantiq-edge:1.26.15
imagePullPolicy: IfNotPresent
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "device"
operator: In
values: ["raspberrypi"]
- Launch
kubectl apply -f deployment.yaml
sudo crictl images # list images
sudo crictl rmi c1e4f72eb6760 # remove an image
sudo ctr images import edge-arm.tar # import an image
Reference > https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md
- Kubernetes orchestration
- Managing compute resource, network, volume and security
- Built-in high-availability, fault-tolerance and load-balancing, sort of self-healing feature
- Rich plugins like dark-launching/ A/B-testing
- Natural integration with CI/ CD
- Workload manageability
- The network performance over public network in between K3S master and Raspberry-Pi as end-point device remotely