Microk8s 搭建环境上手
在日常开发中,我们会用到非常多的在环境安装很多非应用的软件。如果每个软件我都自己安装一遍就会显得繁琐。这时候我们会考虑使用 docker 来部署镜像来获得这些环境软件,在这个意义上的确可以达到目的。不过,笔者这里就直接使用 Microk8s,主要是为了后面 k8s 和分布式的学习,因此有了这篇文章,仅作为个人记录。
前置准备
若只需一个节点,只需要一个树莓派就可以了(一个节点很弱的,其实这时候不如买几台小 PC,x86性能更好),笔者这里准备了 3 个树莓派4B(8G RAM)作为集群使用。每个树莓派需要一个TF卡和电源,笔者使用 64GB SandDisk TF卡和树莓派官方电源。大部分安装过程可以使用以下几个链接完成:
树莓派镜像烧录
在Raspberry Pi Imager(下称 Imager)页面中,直接下载即可得到该简单易用的烧录软件。
烧录方式:下载好镜像后烧录
若你去 Ubuntu 官网下载镜像,并需要直接烧录,也可以使用该工具来烧录到TF卡,另一个选择是使用 Rufus 工具来烧录,若在 Linux 你当然也可以使用传统的 dd 工具来烧录,但是需要扩展另外一个分区不然不会占满整张内存卡,不管怎样这些都可以达到目的。
烧录方式:下载并烧录
使用管理员权限打开 Imager 后,按照以下操作步骤找到对应的操作系统:
笔者这里使用的是 Ubuntu 20.04.4 LTS 版本的 Linux 发行版。然后选择 存储 盘来烧录树莓派系统。
选择好后点击 “WRITE” 即可,
烧录完成后我们的TF卡会有两个盘 system-boot, writable。在插电启动树莓派之前,我们需要设定一下这个树莓派的网络配置(笔者使用 WIFI),进入到 system 盘,找到 network-config 文件其内容如下所示:
version: 2
ethernets:
eth0:
dhcp4: true
optional: true
wifis:
wlan0:
dhcp4: true
optional: true
access-points:
"<wifi 名称>":
password: "<wifi 密码>"
这里只需要吧 <wifi 名称>,<wifi 密码> 修改成对应的内容即可。注意,尽量使用2.4G的网络热点,5G 似乎要在进入系统后才能连接上。
此时,我们需要先知道局域网目前有的 IP 方便找到树莓派的 IP,笔者使用 Advanced IP Scanner,若你自行编写软件来扫描,直接模拟 Ping 来检测即可,好的万事俱全,插电开机。
找到IP后使用 ssh ubuntu@<ip>
连接上树莓派,默认密码为 ubuntu
Microk8s 的安装
由于这里笔者用于开发环境,所以使用了 snap,使用该连接 How to build a Raspberry Pi Kubernetes cluster using MicroK8s 从第 4 步开始,就可以了无非是执行一些命令。
这个过程更加详细的说明在 Alternative installs 页面。这个连接中说明了 ZFS 需要额外的处理。
要点一
注意需要找到 cmdline.txt 修改增加 cgroup_enable=memory cgroup_memory=1
参数。不要手抖,每个树莓派都要加,不然会导致节点的 Allocatable 一节的 Ephemeral Storage 为空导致节点一直不可用(我查了几个小时)如命令输出。
$ sudo microk8s.kubectl describe node
Name: ubuntu
Roles: <none>
Labels: beta.kubernetes.io/arch=arm64
...
Capacity:
cpu: 4
memory: 3884328Ki
pods: 110
Allocatable:
cpu: 4
memory: 3781928Ki
pods: 110
<这里没有 ephemeral storage>
System Info:
Machine ID: 2b8d67c7a06d4728b72b84a1ae2712a1
System UUID: 2b8d67c7a06d4728b72b84a1ae2712a1
Boot ID: a866e687-b92c-4b9a-af59-1f9e04bb101b
Kernel Version: 5.4.0-1052-raspi
OS Image: Ubuntu 20.04.4 LTS
Operating System: linux
Architecture: arm64
Container Runtime Version: containerd://1.2.5
Kubelet Version: v1.18.20
Kube-Proxy Version: v1.18.20
Non-terminated Pods: (0 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 0 (0%) 0 (0%)
memory 0 (0%) 0 (0%)
ephemeral-storage 0 (0%) 0 (0%)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Starting 27m kubelet Starting kubelet.
Warning InvalidDiskCapacity 27m kubelet invalid capacity 0 on image filesystem
Normal NodeHasSufficientMemory 27m kubelet Node ubuntu status is now: NodeHasSufficientMemory
Normal NodeHasNoDiskPressure 27m kubelet Node ubuntu status is now: NodeHasNoDiskPressure
Normal NodeHasSufficientPID 27m kubelet Node ubuntu status is now: NodeHasSufficientPID
此时 pod 启动遇到 taint 问题:
$ sudo microk8s.kubectl describe pod kubernetes-dashboard-67765b55f5-nxr8f -n kube-system
Name: kubernetes-dashboard-67765b55f5-nxr8f
Namespace: kube-system
Priority: 0
Node: <none>
Labels: k8s-app=kubernetes-dashboard
....
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 56s (x7 over 2m35s) default-scheduler 0/1 nodes are available: 1 node(s) had taint {node.kubernetes.io/not-ready: }, that the pod didn't tolerate.
要点二
在这里需要说明一下,笔者安装的 Microk8s 的版本为 1.18 版本。
sudo snap install microk8s --classic --channel=1.18/stable
要点三
安装完成后需要启用一些插件。
要点四
运行 microk8s 命令时可能会遇到权限不足的问题,此时可以加 sudo 或者将当前用户加入到 microk8s 用户组中。
$ microk8s.kubectl describe pod kubernetes-dashboard-67765b55f5-nxr8f -n kube-system
Insufficient permissions to access MicroK8s.
You can either try again with sudo or add the user ubuntu to the 'microk8s' group:
sudo usermod -a -G microk8s ubuntu
sudo chown -f -R ubuntu ~/.kube
The new group will be available on the user's next login.
k8s.gcr.io 镜像问题
在 Microk8s 安装后,执行 sudo microk8s dashboard-proxy
会一直等待 dashboard 启动起来,使用 sudo mirok8s.status
使用 microk8s.kubectl get pods -n kube-system
发现所有节点都没有启动起来。
$ sudo microk8s.kubectl get nodes
NAME STATUS ROLES AGE VERSION
ubuntu Ready <none> 52m v1.18.20
$ sudo microk8s.kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-588fd544bf-p2kn8 0/1 Pending 0 60s
dashboard-metrics-scraper-db65b9c6f-4hh4q 0/1 Pending 0 67s
heapster-v1.5.2-5bc67ff868-wq58w 0/4 Pending 0 66s
hostpath-provisioner-9b7695c6b-44plx 0/1 Pending 0 40s
kubernetes-dashboard-67765b55f5-nxr8f 0/1 Pending 0 67s
monitoring-influxdb-grafana-v4-6cc44d985f-rh9wg 0/2 Pending 0 66s
使用 sudo microk8s.kubectl describe pod kubernetes-dashboard-67765b55f5-nxr8f -n kube-system
调查后发现这其实是镜像(k8s.gcr.io/pause 等一系列镜像)没有下载好的问题。
$ sudo microk8s.kubectl describe pod kubernetes-dashboard-67765b55f5-nxr8f -n kube-system
Name: kubernetes-dashboard-67765b55f5-nxr8f
Namespace: kube-system
Priority: 0
Node: ubuntu/192.168.31.67
Start Time: Sun, 13 Mar 2022 12:51:47 +0000
Labels: k8s-app=kubernetes-dashboard
....
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m15s default-scheduler Successfully assigned kube-system/kubernetes-dashboard-67765b55f5-nxr8f to ubuntu
Warning FailedCreatePodSandBox 38s (x4 over 2m45s) kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to get sandbox image "k8s.gcr.io/pause:3.1": failed to pull image "k8s.gcr.io/pause:3.1": failed to resolve image "k8s.gcr.io/pause:3.1": no available registry endpoint: failed to do request: Head "https://k8s.gcr.io/v2/pause/manifests/3.1": dial tcp 108.177.125.82:443: i/o timeout
提示拉取镜像失败:failed to pull image "k8s.gcr.io/pause:3.1"
笔者经过查找和对比,得到以下做法
- 使用 Docker 构建镜像(github 上有仓库),并导入为对应的 k8s.gcr.io/xxxx 镜像。
- 在其他 Mirror 中下载镜像,并导入为对应的 k8s.gcr.io/xxxx 镜像
这里笔者在 docker.io 发现 gcrxio 这位大哥似乎已经构建了一大堆对应的 k8s.gcr.io 的镜像,因此直接使用这位大哥的镜像,按照镜像导入的处理归纳为这些命令的执行,以 k8s.gcr.io/heapster-grafana-arm64:v4.4.3
镜像的拉取为例。
$ microk8s.ctr images pull docker.io/gcrxio/k8s.gcr.io_heapster-grafana-arm64:v4.4.3 --all-platforms
$ microk8s.ctr images export temp.tar docker.io/gcrxio/k8s.gcr.io_heapster-grafana-arm64:v4.4.3
$ microk8s.ctr images import --base-name k8s.gcr.io/heapster-grafana-arm64 temp.tar
$ microk8s.ctr images rm docker.io/gcrxio/k8s.gcr.io_heapster-grafana-arm64:v4.4.3
上面需要注意的是 microk8s.ctr images import --base-name k8s.gcr.io/heapster-grafana-arm64 temp.tar
该命令中 --base-name 部分为所需的 k8s.gcr.io 的镜像和名称,不用带版本。
以上这样的命令分别需要给 k8s.gcr.io/pause:3.1、k8s.gcr.io/heapster-influxdb-arm64:v1.3.3,k8s.gcr.io/heapster-arm64:v1.5.2 都进行一次。 这里有运行所需的镜像拉取命令,全部执行后,microk8s 节点就会转变为 ready 状态。
sudo microk8s.ctr images pull docker.io/gcrxio/k8s.gcr.io_pause:3.1 --all-platforms
sudo microk8s.ctr images export temp.tar docker.io/gcrxio/k8s.gcr.io_pause:3.1
sudo microk8s.ctr images import --base-name k8s.gcr.io/pause temp.tar
sudo microk8s.ctr images rm docker.io/gcrxio/k8s.gcr.io_pause:3.1
sudo microk8s.ctr images pull docker.io/gcrxio/k8s.gcr.io_heapster-grafana-arm64:v4.4.3 --all-platforms
sudo microk8s.ctr images export temp.tar docker.io/gcrxio/k8s.gcr.io_heapster-grafana-arm64:v4.4.3
sudo microk8s.ctr images import --base-name k8s.gcr.io/heapster-grafana-arm64 temp.tar
sudo microk8s.ctr images rm docker.io/gcrxio/k8s.gcr.io_heapster-grafana-arm64:v4.4.3
sudo microk8s.ctr images pull docker.io/gcrxio/k8s.gcr.io_heapster-influxdb-arm64:v1.3.3 --all-platforms
sudo microk8s.ctr images export temp.tar docker.io/gcrxio/k8s.gcr.io_heapster-influxdb-arm64:v1.3.3
sudo microk8s.ctr images import --base-name k8s.gcr.io/heapster-influxdb-arm64 temp.tar
sudo microk8s.ctr images rm docker.io/gcrxio/k8s.gcr.io_heapster-influxdb-arm64:v1.3.3
sudo microk8s.ctr images pull docker.io/gcrxio/k8s.gcr.io_heapster-arm64:v1.5.2 --all-platforms
sudo microk8s.ctr images export temp.tar docker.io/gcrxio/k8s.gcr.io_heapster-arm64:v1.5.2
sudo microk8s.ctr images import --base-name k8s.gcr.io/heapster-arm64 temp.tar
sudo microk8s.ctr images rm docker.io/gcrxio/k8s.gcr.io_heapster-arm64:v1.5.2
rm -f temp.tar
执行完成后,等待吃一碗泡面的时间查看节点和 pod 的状态:
$ sudo microk8s.kubectl get nodes
NAME STATUS ROLES AGE VERSION
ubuntu Ready <none> 61m v1.18.20
$ sudo microk8s.kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-588fd544bf-p2kn8 1/1 Running 0 38m
dashboard-metrics-scraper-db65b9c6f-4hh4q 1/1 Running 0 38m
heapster-v1.5.2-5bc67ff868-wq58w 4/4 Running 0 38m
hostpath-provisioner-9b7695c6b-44plx 1/1 Running 0 38m
kubernetes-dashboard-67765b55f5-nxr8f 1/1 Running 0 38m
monitoring-influxdb-grafana-v4-6cc44d985f-rh9wg 2/2 Running 0 38m
处理好镜像问题后,再次执行 microk8s.dashboard-proxy
,这次变可以进入到 dashboard 页面了:
$ sudo microk8s.dashboard-proxy
Checking if Dashboard is running.
Waiting for Dashboard to come up.
Dashboard will be available at https://127.0.0.1:10443
Use the following token to login:
eyJhbGciOiJSUzI1NiIsImtpZCI6ImVLdVY0QTZRY3FkVi01S3Q0ekI2ZGRBMEVsZEFHN2Z5SUEzcHUyVUhxNGMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLTRqcTl2Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI1ZmFlNzM2MS04YmUzLTQyODAtOTk3NS05MzdhOGVkMzQ5YWEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.TbRZB7qci21fXK9zBK-B8slfh7pcTIrCx8FTI5iqLW7WHYoW0WYCq6BwHO9GtvNDeJvliQHNirDCAgZ9GScSGaVnxMKYtdN_ns0om-MV7Q85ZA4sBdgyaizCN4ZHzLpiCpBODKDvPQN6HMDY8KBhjIztOpOC5FIQaDTlAASp4xIdR57SHwvPaoZ1uCUKG7DUe7pDPIui8V7zY2LiqLY1QCdo3JUHmhVNfOAWhWi8kQ3jfXUuBPLXSybYnrcELok5t5pnVueNjhrfh4_GheC9JGBh9TRYK-3gT5r87Ab7FiJ6ZSkJo-YwaRWm87Ld8FE_TT3_Y04QRlkUGEpGFhjLWQ
使用前面找到的树莓派IP进入该页面,使用类似上面命令输出的最后一行的 Token 登录进控制台,笔者树莓派IP为192.168.31.67,故链接为:https://192.168.31.67:10443
登录后可以看到这个界面,接下来就可以查阅 Kubernetes Tutorials 创建 echoserver 验证k8s 环境运行状况了。
每个镜像使用 docker.io 仓库的需要在前面加 “docker.io” 如在该 Tutorials 中部署 echoserver 时的镜像为 k8s.gcr.io/echoserver:1.4
实际中需要换成 docker.io/gcrxio/k8s.gcr.io_echoserver-arm:1.8
(感谢 gcrxio 大哥),这是因为我们使用的是 arm 架构。另外,kubectl 命令整合在 microk8s 子命令中,所以命令需要更换成下面的形式:
sudo microk8s.kubectl create deployment hello-node --image=docker.io/gcrxio/k8s.gcr.io_echoserver-arm:1.8
sudo microk8s.kubectl expose deployment hello-node --type=LoadBalancer --port=8080
创建 Deployment 一小节:
创建 Service 一小节:
成功后在 dashboard 中可以看到这样的界面:
访问 http://<树莓派IP>:<hello-node 端口>
即可访问到 echoserver,这里的 <hello-node 端口>
为 32445,笔者这里 <树莓派IP>
为 192.168.31.67。
所以地址为 http://192.168.31.67:32445,如结果下图所示
重新安装的问题
在 microk8s 运行后,重新安装并作为工作节点(运行 microk8s join ...命令)在部署镜像时,可能会遇到 "cni0" already has an IP address different from 10.1.71.1/24
的问题。这是因为上一次的安装并运行后,没有删除 网卡 cni0 和网卡 finnel.1 直接改成和 different from 后面一致的网段便可以解决该问题:
$ ip address
.....
$ sudo ip address change 10.1.71.1/24 dev cni0
$ sudo ip address delete 10.1.71.0/32 dev cni0
$ sudo ip address change 10.1.71.1/24 dev flannel.1
$ sudo ip address delete 10.1.71.0/32 dev flannel.1
结语
在这篇文章中,我简略地介绍了 microk8s 的安装和部分问题,并给出了在安装 microk8s 在树莓派中会使用到的连接。并给出了笔者搭建问题的解决办法,但每个人实践时遇到的问题是不一样的,若读者有必要使用 k8s 环境学习时,可参考本文章搭建 microk8s 环境来学习。在这里感谢各位读者,我们下次见。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。