ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

UOS服务器版部署Rancher避坑指南:Kubernetes管理平台搭建

UOS服务器版部署Rancher避坑指南:Kubernetes管理平台搭建

上个月接了个活儿,某单位一台基于UOS服务器版的机器,要求把Rancher部署上去,用来接管后面新建的Kubernetes集群。一开始我觉得这不算难——Rancher官方文档写得很清楚,Docker跑一个容器就完事。但实际动手后发现,UOS这套系统和普通的Ubuntu、CentOS还是有些不一样的地方,从软件源到内核参数,再到内网证书,处处有坑。这篇文章就把我踩过的坑和最终跑通的完整路径整理出来,给要在国产操作系统上部署Rancher的朋友做个参考。

先说明一下适合谁看:如果你需要在UOS上搭一个Kubernetes管理平台、要给业务方提供可视化的集群管理界面,或者正在做内网离线交付,这篇文章基本可以照着操作。文中涉及的命令我都尽量给出完整版和逐参数解释,不只会告诉你“怎么跑通”,还会说清楚“为什么这么配”。

1. 为什么有人要在UOS上装Rancher:先看清这个组合的价值

1.1 UOS和Rancher各自解决什么问题

UOS是国产Linux操作系统,服务器版主要跑在政务、金融、教育这些对自主可控有要求的场景里。它底层基于Debian体系,用apt管理软件包,所以很多Debian系的经验可以直接迁移过来,但又不完全一样:软件源是自有的,内核版本相对保守,默认启用的安全模块也和社区版有差异。

Rancher则是Kubernetes的图形化管理平台。裸K8s最大的问题就是管理门槛高,装好了还要面对一堆YAML、证书、Node节点状态,业务方一看就头大。Rancher把这些东西封装成了网页操作:创建集群、导入集群、部署应用、看监控日志、做权限隔离,都能点鼠标完成。把Rancher部署在UOS上,等于在国产化的基础上补齐了容器编排的运维能力,这在很多信创项目里是刚需。

1.2 我在实际中遇到的三种部署诉求

接需求的时候,对方并没有说得很细,我在现场梳理下来大致是三类:第一类,先在一台UOS上把Rancher Server跑起来,后面再慢慢纳管其他集群;第二类,整机离线,机器不能上外网,所有镜像都得拷进去;第三类,要求提供可重复执行的部署文档,方便以后换机器重新部署。

这三种诉求对应的路径不太一样。第一种最简单,在线拉镜像就行;第二种要花大力气解决镜像搬运和私有仓库的问题;第三种则要求整个流程脚本化、参数化。下面我会按线上环境为主线来讲,离线部分单独开一节,因为那是踩坑最多的环节。

2. 环境准备:版本核对、内核参数与容器运行时选型

2.1 先跑三个命令确认机器底子

部署前千万别急着装Docker,先确认三件事:系统版本、内核版本、架构。UOS服务器版常见的是v20系列,内核一般在4.19左右,架构通常是x86_64,也有不少ARM机器。用下面三条命令看:

cat /etc/os-release uname -r uname -m

我遇到的那台机器是x86_64,内核4.19,跑Rancher 2.7系列完全没问题。需要注意一点:如果你的Rancher版本很新(比如2.9、2.10开始的部分特性),对内核和容器运行时版本有更高要求,建议先去官方release note里核对一下最低内核版本。4.19跑老一点但还在维护期的2.7.x是最稳妥的搭配。

另外,磁盘规划是个容易被忽略的环节。Rancher的数据全部写在/var/lib/rancher目录下,包括配置、证书、etcd快照等。我习惯把数据目录单独挂一块盘,或者至少确保这个分区剩余空间在20GB以上。容器日志、镜像、下游集群的kubeconfig都会堆在上面,真到磁盘写满的时候,Rancher的表现是各种莫名其妙的报错,排查起来非常被动。

2.2 Docker还是containerd:单节点场景的选择逻辑

容器运行时选哪个,很多人会纠结。Rancher Server本身是作为一个容器跑起来的,官方最推荐的单节点部署方式就是用Docker启动Rancher容器;如果你走K3s或者RKE2的路子,那用的是containerd。

单节点部署Rancher Server,我建议直接用Docker,理由很实际:排障简单,docker logs、docker inspect这些命令大家都熟;升级就是换个镜像重新起容器,逻辑直白;Docker的生态和文档也最全。containerd不是不能用,只是当你只想快速把Rancher跑起来时,没必要多绕一层。

UOS上装Docker有两条路:一是直接apt装软件源里的版本,优点是命令简单,缺点是版本经常偏旧,可能低于Rancher要求的最低版本;二是下载官方静态包手动安装,优点是最新、可控,缺点是要自己处理systemd服务文件。我实际用的是离线deb包方式,具体操作在下一节展开。

2.3 初始化系统参数:swap、时间同步、文件句柄

装完Docker先别急着拉镜像,有几个系统参数先改了,不然后面K8s集群初始化的时候会翻车。

第一,swap建议关掉。Kubernetes默认要求节点上的swap是关闭状态,虽然这个要求主要针对下游集群的节点,但Rancher Server所在的机器顺手也关了,省得后面出幺蛾子:

swapoff -a sed -i 's/.*swap.*/#&/' /etc/fstab

第二,开启IPv4转发。容器和Pod之间的流量依赖这个参数,默认可能是0:

echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf sysctl -p

第三,时间同步必须做。Rancher和K8s之间的通信很依赖时间一致性,证书校验、token校验全都建立在时间正确的前提上。UOS服务器版一般自带chrony,但很多内网机器没配好NTP源,我见过因为时间差了五分钟导致Rancher页面能开、下游集群怎么都注册不上的情况。建议尽早确认:

chronyc sources -v date

如果时间不对,配好NTP源然后用systemctl restart chronyd重启服务。这一步成本最低,却是最容易埋雷的。

3. Docker单节点部署Rancher Server:命令级拆解

3.1 安装Docker的两种路径与源的选择

在线环境下,UOS的默认软件源如果已经收录了docker.io(有些版本确实有),直接:

apt-get update apt-get install -y docker.io systemctl enable --now docker

这个方式适合快速验证,但版本可能只有20.10左右,跑Rancher 2.6及以上够用。如果你对版本有要求,也可以添加Docker官方的apt源来装docker-ce,不过这要求机器能访问外网,内网环境就得走离线包了。

离线装Docker的办法是:在一台能联网的同架构机器上下载docker-ce的deb包(包括containerd.io、docker-ce-cli、docker-ce这几个依赖),然后拷贝到UOS上执行:

dpkg -i containerd.io_*.deb docker-ce-cli_*.deb docker-ce_*.deb

依赖不全会报错,缺什么就用apt-get install -f补齐。装完验证一下:

docker version systemctl status docker

这里有个实操细节:UOS默认可能启用了AppArmor,如果后面容器启动行为异常,先看一眼dmesg | grep -i apparmor,有时候需要给Docker的systemd服务额外加上容器的profile配置。不过多数情况下Rancher容器不会撞上这个,先有个印象就行。

3.2 启动Rancher的标准命令逐参数说明

Docker就绪后,核心就是这一条命令:

docker run -d \ --name rancher \ --restart=unless-stopped \ -p 80:80 \ -p 443:443 \ -v /data/rancher:/var/lib/rancher \ rancher/rancher:v2.7.9

我逐个拆一下参数,你就不用来回翻文档了:

  • --name rancher:容器名字,后面查看日志、停止、删除都用它。
  • --restart=unless-stopped:机器重启后容器自动拉起,除非手动stop,这是生产环境必须加的。
  • -p 80:80 -p 443:443:把宿主机的80和443映射到容器内。Rancher的UI默认走443,80端口的用途是做HTTP到HTTPS的跳转。如果你的UOS机器上已经装了Nginx或其他Web服务占了80/443,这里要改端口,比如-p 8080:80 -p 8443:443,但后面访问地址也要跟着变。
  • -v /data/rancher:/var/lib/rancher:数据持久化。宿主机目录建议用绝对路径,我习惯单独建/data/rancher而不是默认的/var/lib/rancher,因为系统盘空间往往紧张,单独挂数据盘更灵活。
  • rancher/rancher:v2.7.9:镜像名加版本标签。最好不要直接用latest,版本固定下来,升级和回滚都清楚。

有些教程会加--privileged,我个人不建议单节点Rancher Server这么干,权限给太宽了,出安全问题难交代。Rancher容器本身不需要特权模式就能正常工作。

3.3 初始化流程与Server URL的意义

容器起来之后,先看日志确认启动进度:

docker logs -f rancher

看到类似“Rancher has been provisioned”之类字样,说明初始化得差不多了,然后浏览器访问https://<UOS服务器IP>/。第一次打开会要求设置admin密码,还会弹一个Rancher Server URL的配置项。

这个Server URL非常关键。它会被写进kubeconfig和集群agent的连接信息里,下游集群全靠这个地址回调Rancher Server。内网环境就填https://<IP>:443或者你规划的域名,别填localhost,也别填一个别人访问不到的内网地址。我见过一个人填了公网域名结果内网解析不到,整整排查了一下午。

初始化完成后,主界面能看到“Add Cluster”、“Import Existing”等入口。到这里,单节点的Rancher Server就算立起来了。但如果你后续要纳管集群,建议先做一件事:把Rancher的system default registry设置好,否则后面导入新集群时,每个节点还要单独配镜像加速,非常痛苦。

4. 内网离线部署才是重头戏:镜像搬运与私有仓库配置

4.1 离线镜像包的导出与导入

很多UOS部署环境是彻底离线的,服务器不能访问Docker Hub,这时候在线拉镜像这条路直接堵死。我的做法分两步:找一台能联网的机器做中转,把需要的镜像打成tar包,再拷进UOS用docker load导入。

最简单的单镜像搬运:

# 有网机器上 docker pull rancher/rancher:v2.7.9 docker save -o rancher-v2.7.9.tar rancher/rancher:v2.7.9 # UOS机器上 docker load -i rancher-v2.7.9.tar

但生产环境远不止一个镜像。当你用Rancher建集群时,它要拉一堆系统组件镜像,比如rancher/mirrored-pause、rancher/mirrored-coredns-coredns、各种kube-proxy、etcd的镜像。一个个手动pull/save不现实。

正确做法是使用Rancher官方维护的离线镜像清单和脚本。具体思路是:在有网机器上拉取Rancher代码库里的rancher-images.txt,配合官方提供的save/load脚本,把所有需要的镜像都导出来。大致流程是:

# 有网机器上执行 ./rancher-save-images.sh --image-list ./rancher-images.txt # 会生成 rancher-images.tar.gz 和 rancher-images.txt

然后把这两个文件拷贝到UOS上,执行:

./rancher-load-images.sh --image-list ./rancher-images.txt --images rancher-images.tar.gz

load脚本会自动逐个docker load,你只需要等它跑完。这个方式我实测过,虽然耗时久(几十个镜像,每个都要解压),但比手动一个个拉靠谱太多。

4.2 配置私有镜像仓库与registry地址

离线环境只把镜像load到本地Docker是不够的,因为Rancher创建下游集群时,每个K8s节点默认还是会去拉公共仓库的镜像,离线节点根本拉不到。正解是搭一个私有镜像仓库(Harbor或者简单的registry容器都行),把所有镜像推上去,然后让Rancher的默认拉取地址指向它。

在UOS上快速起一个registry容器:

docker run -d --name registry \ -p 5000:5000 \ -v /data/registry:/var/lib/registry \ registry:2

然后把tar包里的镜像重新打标签并推送:

docker tag rancher/rancher:v2.7.9 <内网IP>:5000/rancher/rancher:v2.7.9 docker push <内网IP>:5000/rancher/rancher:v2.7.9

配置Rancher默认registry,我习惯在启动容器时直接注入环境变量:

docker run -d --name rancher \ --restart=unless-stopped \ -p 80:80 -p 443:443 \ -e CATTLE_SYSTEM_DEFAULT_REGISTRY=<内网IP>:5000 \ -v /data/rancher:/var/lib/rancher \ rancher/rancher:v2.7.9

每个人的镜像命名规范不同,这个环境变量主要影响Rancher系统组件镜像的拉取地址前缀。如果你的私有仓库上镜像路径不是标准的rancher/mirrored-xxx结构,就需要在创建集群的高级设置里单独配置。实测下来,最省心的还是保持私有仓库路径和官方一致,只改成带IP的完整前缀。

4.3 证书处理:内网HTTPS信任链怎么搭

在线部署Rancher默认会给自己签一个自签证书,浏览器第一次访问会跳警告,这个还能接受。但内网场景通常有企业CA或者客户强制要求用正式证书,这时候必须在启动时挂载证书。

方法是在启动Rancher容器时,把证书和私钥放到宿主机的/data/rancher-certs目录下,命名为tls.crt和tls.key,然后挂载进去:

docker run -d --name rancher \ --restart=unless-stopped \ -p 80:80 -p 443:443 \ -v /data/rancher-certs:/etc/rancher/ssl \ -v /data/rancher:/var/lib/rancher \ rancher/rancher:v2.7.9

Rancher会优先读取/etc/rancher/ssl下的证书,不再使用自签证书。这里有个坑:证书的Common Name一定要和访问的地址匹配,包括IP SAN或者域名SAN,否则浏览器照样报错,下游集群的agent连接也会因为证书校验失败而注册不上。

另一个容易被忽略的是:如果用的是企业内网CA签发的证书,客户端机器上要信任这个CA。UOS上操作很简单:

cp your-ca.crt /usr/local/share/ca-certificates/ update-ca-certificates

这样本机的curl、容器、以及其他工具访问Rancher时,就不会因为“certificate signed by unknown authority”而中断。这个步骤在部署文档里经常被漏掉,但线上环境几乎必然遇到。

5. UOS特有的坑:一套完整排查链路

5.1 现象一:页面能开,下游集群连不上

症状很明确:Rancher页面正常打开,但导入一个新集群到一半就失败,agent Pod一直Pending或者CrashLoopBackOff。

先别查Node,从网络链路看起。第一步确认UOS的防火墙状态:

systemctl status firewalld ufw status

UOS服务器版可能默认启用了ufw,也可能没有防火墙,但有些定制镜像会在iptables层面加了限制。最直接的办法是看443端口是否确实在监听:

ss -tlnp | grep -E '443|80' iptables -L -n | grep 443

我遇到的情况是:443端口监听正常,但iptables FORWARD链默认DROP,导致Rancher访问下游集群的Pod网络时被丢包。这个坑在Debian系上很典型,因为Docker会往iptables里加规则,但FORWARD链的默认策略可能还是DROP。临时改法:

iptables -P FORWARD ACCEPT

永久生效还是在/etc/sysctl.conf里确认net.ipv4.ip_forward=1,并检查ufw如果开着,得放行ufw allow 443/tcp。

5.2 现象二:Rancher容器反复重启

这个问题我是在离线导入镜像时踩到的。表现为:docker ps看到容器状态一直在restarting,页面打不开,docker logs报错信息又不明显。

从经验看,优先查三件事:一是数据卷权限,/data/rancher目录的所有者必须是root,如果之前用别的用户拷过数据,目录权限不对容器起来就会崩,用chown -R root:root /data/rancher修正;二是磁盘空间,df -h看看是不是分区满了,etcd写入失败时容器会不停重启;三是内存是否够用,UOS上如果内存小于4GB,同时跑Rancher和其他服务很容易触发OOM,dmesg | tail或者journalctl -k | grep -i oom能看出来。

我之前一次部署,问题就出在离线导入镜像时磁盘被解压后的镜像塞满,Rancher容器写到一半磁盘满,直接OOM。清了/var/lib/docker下没用的镜像和Build缓存,重启Docker再起容器就好了。

5.3 现象三:时间不同步导致的证书报错

症状是页面偶尔能打开,但登录后操作很容易报401、403,或者下游集群的Pod报x509: certificate has expired or is not yet valid。很多人的第一反应是证书过期了,翻来覆去找原因,结果发现系统时间慢了十分钟。

这在物理机和内网虚拟机上特别常见,CMOS电池没电、NTP没配通,都可能导致时间漂移。我用一条命令确认:

timedatectl status

如果显示NTP service: inactive,或者时间跟实际差得远,立刻配chrony:

apt-get install -y chrony systemctl enable --now chronyd chronyc makestep

等时间校准后再访问Rancher,证书问题通常就消失了。Rancher对时间异常其实挺敏感的,因为整个认证体系都是基于时间戳签发的token,时间一歪,页面和你以为的都正常,但后端校验就是不通过。

6. 部署完怎么验收:验证清单与日常运维要点

6.1 我的验收清单(可直接抄)

每次部署完,我都会按下面这张清单过一遍,免得交付了才发现漏配置:

检查项操作方式预期结果
页面可访问浏览器打开 https://UOS_IP/出现登录页,无证书告警(或已信任)
容器稳定docker psrancher容器运行中,无restarting
日志无异常docker logs rancher --since 10m无ERROR级别刷屏
数据持久化ls /data/rancher能看到配置、证书、audit日志等目录
时间同步chronyc tracking显示已同步,时间偏差小于1秒
转发已开启sysctl net.ipv4.ip_forward输出1
Server URL可回访在下游节点curl https://UOS_IP/healthz返回200或类似健康响应
创建测试集群页面上新建一个自定义集群集群节点状态Active

重点说一下/healthz这个健康检查路径,Rancher会返回200,在下游节点上先curl通,再去做集群导入,能提前拦截百分之八十的网络问题。

6.2 备份与升级的几个实用经验

Rancher的备份我推荐在页面上装rancher-backup这个应用,它能把Rancher的CRD配置、RBAC、证书这些打包成压缩文件,支持上传到S3兼容存储,恢复的时候也方便。但UOS离线环境要先把这个应用的镜像搬到私有仓库,不然装不上。

如果不想装应用,最低成本的备份方式是直接打包数据目录:

systemctl stop docker # 或者 docker stop rancher tar -czf rancher-backup-$(date +%F).tar.gz /data/rancher systemctl start docker

注意备份前要么停容器,要么确保数据目录没有并发写入,否则etcd相关的文件可能备份出一个半成品,恢复时怎么都起不来。

升级Rancher就三步:pull新镜像、删掉旧容器(保留数据卷)、用同一套挂载参数起新容器。官方文档有明确的升级路径,切记不要跨大版本跳级升级。我上次从2.7升到2.8是直接换镜像起的,数据完全保留,页面提示迁移完成,整个过程半小时内搞定。当然前提是数据目录挂载没变、证书没动、端口没改。

还有一个日常运维细节:Rancher容器所在的主机名不要随便改,它的kubeconfig和生成的证书可能包含主机名信息,改完hostname可能导致集群状态异常。我在UOS上就遇到过,改了/etc/hostname重启后,Rancher页面虽然能开,但内部有些校验开始报不匹配。所以主机名这种东西,部署前定好,部署后别动。

最后分享一个我自己的习惯:每次部署UOS上的Rancher,我都会先在虚拟机里完整跑一遍流程,把每一步命令的输出记录下来,包括docker run的参数、证书的路径、私有仓库的地址。等上了生产环境,基本就是照着记录复现一遍,很少出意外。这个习惯帮我省了不少半夜值班的麻烦,建议你也试试。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进