最近给家里几台闲置机器拆开重新整理了一下,然后统统装上了 Proxmox 做虚拟化,然后开出小鸡来想着搞点没玩过的东西玩玩,四下看了看于是决定用 openSUSE Kubic 来装个 Kubernetes 集群来图一乐。
本文假设读者有在一台没有安装任何操作系统的计算机上安装 openSUSE 或其它主流 Linux 发行版的能力,并且假设读者具备一定的 Linux 使用经验,以及对 Kubernetes 有基本的了解。阅读本文还可能会需要一些计算机网络的基础知识。
本文同时发表在 我自己的博客。
openSUSE Kubic
这是一个 openSUSE 社区提供的衍生发行版,基于 openSUSE MicroOS 并预装了 Kubic 环境,可以较为方便地部署 Kubernetes 环境。和 openSUSE 本体的主要区别大概有两点,一是使用 openSUSE MicroOS 作为基础所以整个系统是 “事务式更新” 的,另一个就是预装了 Kubic 环境,不需要自己安装 Kubernetes 相关的各种工具。
openSUSE MicroOS 与 “事务式更新”
大体说来,openSUSE MicroOS 是一个针对专用场景(也就是说不是一般性的个人桌面应用)设计的偏轻量化和可靠性的基底系统,在 Wiki 页面上可以看到比较详细的介绍,不过就我个人的感受来看,最主要的区别和特色在于它的 “事务式更新” 机制。
“事务式更新” 是一个利用文件系统 “写入时复制” (Copy-on-write, CoW) 功能来隔离单次运行中对系统做出的修改的机制,从效果上有点类似于高级版的 “还原卡”。即每次系统更新都写到一个新的文件系统快照 (Snapshot) 中,当前运行中的系统对该新快照中的内容并不感知,而是直到下次重启系统时,从新的快照启动更新后的系统;如果新的系统存在异常,可以再次重启并在启动菜单选择上一个快照启动,实现回滚。这个行为和数据库中 “事务” 的概念如出一辙,将系统更新的若干过程包装成原子操作,可以避免系统进入到 “更新到一半某个地方坏掉了但一下子修不好又回不去” 的尴尬状况,所以名字也算是比较贴切了。
目前 openSUSE MicroOS 自己的实现 是基于 Btrfs 来做的,理论上这套工具也可以移植到其他支持 CoW 的文件系统上,并且实际上利用文件系统快照功能来实现备份和回滚都不是什么新鲜点子,也有不少人自己写脚本实现了类似的功能,但 MicroOS 这套工具胜在将其标准化和集成到了发行版中,目前也没看到有别的发行版在搞类似的东西,所以可以算是一大特色。
从用户角度看,这玩意带来的主要区别在于:
- 更新系统不能直接
zypper dup
, 而是要先执行transactional-update shell
再在新打开的 shell 中执行更新命令。(当然实际上transactional-update
本身就是执行zypper ref && zypper dup
, 但如果要单独安装某个包就只能先进 shell 了) - 更新、安装、卸载,以及修改重要的配置等操作后退出该 shell, 会发现系统还是进入 transactional update shell 之前的样子,所有修改仿佛不存在,要到下一次系统启动才会生效
- 如果希望在重启系统之前继续修改某个快照的内容,可以用
transactional-update -c xx shell
来进行,其中 xx 是快照编号,可以在每次进入和退出 transactional update shell 的时候看到 - 使用
transactional-update cleanup
可以清理所有未使用(非当前启动的)快照、释放磁盘空间
还有不少参数和子命令可以用 transactional-update -h
查看,不过我自己是觉得有了 shell 就什么都能做了(
Kubic
一句话说来就是一个在 openSUSE MicroOS 上预装了 kubeadm
和一些其他周边工具,针对容器平台宿主机这个特定场景的衍生发行版。整个衍生关系大概是这样的:openSUSE Tumbleweed → openSUSE MicroOS → openSUSE Kubic.
openSUSE Kubic 使用了一个叫 Salt 的运维工具来实现多节点间的控制,并且在上面包了一个叫 kubic-control 的工具提供 kubicctl
以及其它一些相关的命令。默认使用 cri-o 代替知名度更大一些(但逐渐商业化)的 Docker 作为容器运行时。
整个集群的架构是一个 Kubic Admin 节点和若干个普通 Kubic 节点,通过 Salt 实现了鉴权打通后可以直接在 Kubic Admin 上通过 kubicctl
等命令来自动配置所有需要的节点,具体步骤之后会有例子。
安装系统
接下来实际部署一个 Kubic 集群看看。首先安装的是 Kubic Admin, 这个节点也会被作为 Kubernetes master.
需要注意所有节点的主机名一定要是在当前网络内可解析的 FQDN, 安装完成后不要随意修改,否则可能会造成一些奇怪的问题。
以下部分步骤有截图,来自我在虚拟机里面安装系统的过程,和最新的安装向导不一定完全一致,参考进行即可。整个安装过程都是图形化向导,步骤也并不多。
首先是选择安装角色,不同选项代表了不同的预装软件和配置集合。
第一个节点选 Kubic Admin Node, 之后安装的其它节点选 Addional Kubic Node.
如果需要部署多 master 集群,还需要安装一台 Kubic Loadbalancer Node 配置 haproxy, 这个 haproxy 也可以部署在其他任意地方,也不限于 haproxy
本身,任意可以反向代理 HTTPS 请求的负载均衡软件或设备均可。其反代的目标是所有 Kubernetes Master 节点的 6443 端口,即 Kubernetes Control Plane. 之后整个集群和所有的客户端都会通过这个负载均衡器来访问 Control Plane, 它的域名也需要在当前网络中可以解析,且不能随意更改。
之后在配置界面修改时区为需要的时区,并且修改网络配置为静态 IP 地址。修改网络配置时最好在 IP 地址设置和 DNS 设置中将主机名都填写成机器的 FQDN, 并且可能需要添加一条默认路由。
然后就可以点击 Install 进行安装了。完成后会自动重启。
进入系统后先 transactional-update shell
然后 zypper ref && zypper dup
更新系统,并且安装需要的软件包以及按需调整系统配置,比如我会安装 fail2ban
并设置其开机启动,以及由于家里网络环境的需要会修改 /etc/sysctl.conf
禁用掉 IPv6. 完成系统更新和配置后退出 transactional update shell, 重启系统。
再次进入系统后检查各项配置是否正确,然后可以用 transactional-update cleanup
清除之前的旧快照。之后的每一个节点安装后都推荐进行系统更新与配置的操作,不再重复说明。
如果安装后无法 SSH 登录机器,可以修改/新建 /etc/ssh/sshd_config.d/rootlogin.conf
文件添加一行 PermitRootLogin yes
再重启 sshd.service
后使用。
初始化 Kubernetes 集群
在安装好 Kubic Admin 和配置好负载均衡(如果部署单 master 的 Kubernetes 集群则不需要负载均衡器)后即可初始化 Kubernetes 集群。
初始化 Kubernetes 集群的操作通过 kubicctl init
命令完成,如果需要设置集群的一些属性(比如 Kubernetes 版本,默认是装当前的最新版)可以通过参数指定,具体看 kubicctl -h
的帮助即可。由于这里我要部署一个多 master 的高可用 Kubernetes 集群,所以还需要加上 --multi-master
参数,其值为负载均衡器的域名。
kubic-master-fenrir:~ # kubicctl init --multi-master kubic-lb-m31.home.atr.moe
Initializing kubernetes master can take several minutes, please be patient.
Setting up multi-master kubernetes node (reacheable as 'kubic-lb-m31.home.atr.moe') with weave
Initialize Kubernetes control-plane
Deploy weave
Deploy Kubernetes Reboot Daemon (kured)
First Kubernetes master succesfully setup.
Please add at minimum two further master nodes!
如果 kubicctl init
的过程卡住,或者干脆超时报错,则需要对 registry.opensuse.org
施放魔法。具体操作不赘述,但推荐将魔法阵部署在网关上以向节点提供透明的冲浪体验。
在集群初始化完成后,即可通过以下操作获取 kubeconfig 文件,并且可以用 kubectl
查看当前的集群状态了:
kubic-master-fenrir:~ # mkdir .kube
kubic-master-fenrir:~ # kubicctl kubeconfig > .kube/config
kubic-master-fenrir:~ # kubectl get no
NAME STATUS ROLES AGE VERSION
kubic-master-fenrir NotReady control-plane,master 47s v1.20.2
向 Kubernetes 集群添加更多节点
如果之前还没有给 Kubic Admin 以外的节点装机,那现在就是时候动手了。按照我的预期拓扑,至少还需要两台 Kubernetes Master 节点,和若干 Kubernetes Worker 节点。所有这些节点的装机方法是一样的。
进入到安装向导,安装类型选择 Addional Kubic Node, 并在下一个界面填写 Kubic Admin 节点的域名(注意不是负载均衡器的域名)。
之后同样是配置时区、网络等操作,和安装 Kubic Admin 节点时雷同。
在完成所有剩余节点的系统安装和配置之后,回到第一台,也就是 Kubic Admin 节点,开始向集群中添加节点。
首先是执行 salt-key -L
查看当前的所有节点列表,检查是否正确,如果有误则到对应机器上修改 /etc/salt
下的配置文件并重启 salt-minion
服务。如果是修改节点名称,可以在确认新节点已经出现在 salt-key -L
的 Unaccepted Keys 列表之后用 salt-key -d xxx
命令来删除旧的记录。
确认列表无误后执行 salt-key -A
接受所有 key, 也可以用 -a xxx
参数来一个一个接受。
然后使用 kubicctl node add
命令来添加剩余的两台 Kubernetes Master 节点:
kubic-master-fenrir:~ # kubicctl node add --type master kubic-master-janus.home.atr.moe
Upload certificates ...
kubic-master-janus.home.atr.moe: adding node...
kubic-master-janus.home.atr.moe: joining cluster...
kubic-master-janus.home.atr.moe: node successful added
Node(s) successfully added
添加 Kubernetes Master 节点需要一台一台操作,添加的对象是 salt-key -L
中看到的节点名称,正常情况下它应该和该节点的 FQDN 是一样的。
完成后即可看到相应节点的状态:
kubic-master-fenrir:~ # kubectl get no
NAME STATUS ROLES AGE VERSION
kubic-master-fenrir Ready control-plane,master 15m v1.20.2
kubic-master-janus Ready control-plane,master 7m42s v1.20.2
kubic-master-narvi Ready control-plane,master 4m20s v1.20.2
此时应当检查负载均衡器的设置,将三台 master 都添加到反代后端中。(之前的操作只需要有第一台节点在反代后端中即可完成)
添加多台 worker 节点可以在一条命令中完成(当然分开也没关系),多个节点间使用逗号分割即可:
kubic-master-fenrir:~ # kubicctl node add kubic-worker-fenrir.home.atr.moe,kubic-worker.janus.home.atr.moe
kubic-worker.janus.home.atr.moe: adding node...
kubic-worker-fenrir.home.atr.moe: adding node...
kubic-worker.janus.home.atr.moe: joining cluster...
kubic-worker-fenrir.home.atr.moe: joining cluster...
kubic-worker.janus.home.atr.moe: node successful added
kubic-worker-fenrir.home.atr.moe: node successful added
Node(s) successfully added
如果添加 node 失败或者其他原因玩脱了,可以 kubectl delete node xxx
删除该 node, 再登录到对应机器上 kubeadmin reset
清空配置,然后就可以回到 Kubic Admin 上重新使用 kubicctl
添加了。
一切完成后通过 kubectl
即可正常操作 Kubernetes 集群:
kubic-master-fenrir:~ # kubectl get no
NAME STATUS ROLES AGE VERSION
kubic-master-fenrir Ready control-plane,master 59m v1.20.2
kubic-master-janus Ready control-plane,master 55m v1.20.2
kubic-master-narvi Ready control-plane,master 52m v1.20.2
kubic-worker-fenrir Ready <none> 9m36s v1.20.2
kubic-worker-janus Ready <none> 25s v1.20.2
kubic-worker-narvi Ready <none> 8m42s v1.20.2
Have a lot of fun~