公司要求把CentOS全换成国产系统,迁移了20台服务器,我踩了6个坑……
创始人
2026-08-06 05:54:19

两个月前,领导甩过来一份文件:信创改造时间表,要求Q3结束前把所有 CentOS 服务器迁移到国产操作系统。我数了一下,生产环境加测试环境,一共 20 台。

CentOS 7 早就停服了,安全补丁断供,这个道理我都懂。但"懂"和"干"之间,隔着一个运维人的血泪。下面把这两个月的迁移经历原原本本写出来,包括我踩的 6 个坑,希望能让后面要迁的同行少走弯路。

一、选型:openEuler、麒麟、统信UOS,到底选谁

市面上主流的国产服务器操作系统就三个方向:openEuler(华为系)、银河麒麟(中国电子系)和统信UOS(统信软件)。我花了一周做对比,结论是没有最好的,只有最合适的。

# 三大国产服务器OS对比(运维视角)

openEuler 22.03 LTS

- 内核: 5.10(可选6.6)

- 包管理: dnf/yum(RPM系,CentOS运维最熟悉)

- 社区活跃度最高,文档全,踩坑有人陪

- 适合: 云原生、容器、Web服务器

银河麒麟 V10 SP3

- 内核: 4.19(稳定优先)

- 包管理: dnf/yum(RPM系)

- 等保资质齐全,政企项目必备

- 适合: 政务、金融、等保要求高的场景

统信UOS Server V20

- 内核: 5.10

- 包管理: apt/dpkg(Debian系)

- 桌面端体验最好,服务器端偏少

- 适合: 需要桌面端的办公场景

我们公司的业务是 Web 应用 + Java 后端 + MySQL 数据库,没有等保强制要求,所以选了 openEuler 22.03 LTS SP3。理由很简单:RPM 系包管理,运维团队不用重新学;社区活跃,有问题搜得到;LTS 版本支持到 2027 年,够用了。

选型建议:如果你的环境以容器和云原生为主,openEuler 是首选;如果有等保合规要求,直接上麒麟 V10;如果团队更熟悉 Debian/Ubuntu 系,统信UOS 也能用。千万别哪个流行选哪个,要跟着你的业务场景走。

二、迁移前评估:这步比迁移本身重要十倍

很多人拿到迁移任务第一反应就是找台机器开始装系统,这是最危险的。迁移出问题,八成是评估没做好。

我在正式迁移前做了三件事:

第一件:盘点所有软件依赖。SSH 到每台机器,把已安装的 RPM 包列表导出来,重点标注非标准仓库安装的包、源码编译安装的软件、以及依赖特定 glibc 版本的应用。

# 导出已安装包列表

rpm -qa --queryformat '%{NAME} %{VERSION} %{ARCH}\n' | sort > installed_pkgs.txt

# 找出非标准仓库安装的包

rpm -qa --qf '%{NAME} %{VENDOR}\n' | grep -v "CentOS" | grep -v "Red Hat"

# 检查源码编译安装的软件(通常在/usr/local下)

ls /usr/local/ | grep -v bin | grep -v lib | grep -v share

# 检查glibc版本(很多老应用卡在这里)

ldd --version | head -1

第二件:梳理定时任务和系统服务。crontab 里的任务、systemd 自定义服务、rc.local 里的启动脚本,这些迁移后最容易遗漏。我建了个表格,每台机器列出所有非默认启用的服务和定时任务。

第三件:跑兼容性评估工具。openEuler 官方提供了 x2openEuler 工具,可以自动扫描 CentOS 系统的软件兼容性,生成评估报告。

# 安装并运行 x2openEuler 评估工具

yum install -y x2openEuler

x2openEuler assess --target centos7 --output ./assess_report

这步帮我提前发现了 3 个问题:一个用了 CentOS 7 特有老版本 glibc 的 Java 应用、一个依赖 Python 2.7 的运维脚本、一个编译时硬编码了路径的 C 程序。如果直接迁,这三个坑够我 debug 一星期。

三、第一台迁移:从测试环境开始试水

评估做完,正式开干。第一台我选了测试环境的一台 Web 服务器,跑的是 Nginx + 一个 Python Flask 应用,业务影响最小,适合当小白鼠。

迁移方式有两种:原地升级和全新部署。我选了全新部署——新装一台 openEuler,把应用搬过去,旧机器保留一周作为回退后路。原地升级虽然省事,但残留的旧包和配置容易埋雷,生产环境不推荐。

# 1. 新装 openEuler 22.03 LTS SP3(最小化安装)

# 安装后先更新系统

dnf update -y

# 2. 安装基础运维工具

dnf install -y vim net-tools bind-utils tar wget curl tree htop

dnf install -y policycoreutils-python-utils # SELinux 管理工具

# 3. 从旧机器同步应用配置

# Nginx 配置

scp root@old-server:/etc/nginx/nginx.conf /etc/nginx/

scp -r root@old-server:/etc/nginx/conf.d/ /etc/nginx/

# 4. 安装应用运行环境

dnf install -y nginx

dnf install -y python3 python3-pip

pip3 install flask gunicorn

# 5. 同步应用代码和数据

rsync -avz root@old-server:/opt/app/ /opt/app/

# 6. 启动服务并验证

systemctl enable --now nginx

systemctl enable --now gunicorn

看起来很顺利对吧?实际上从第 3 步开始就出事了。下面是让我加班到深夜的 6 个坑。

坑一:包名一样,版本不一样

旧机器上 Nginx 是 CentOS 7 用 EPEL 源装的 1.20 版本,openEuler 官方源里的 Nginx 是 1.24。版本号差了不说,配置文件的默认参数也不一样。

最隐蔽的一个差异:openEuler 的 Nginx 默认关掉了 gzip_types 里的 text/css 和 application/javascript。旧的 nginx.conf 直接拷过来没问题,但如果你像我们一样用 conf.d 里的独立配置文件管理 gzip,新版本默认行为变了,前端资源加载速度直接慢了一倍。

教训:迁移后别只验证"服务能不能起来",要逐项验证配置参数是否生效。我用 nginx -T 把完整生效配置打印出来,和旧机器 diff 了一遍,才发现这个差异。

坑二:Python 版本地狱

CentOS 7 默认 Python 是 2.7,openEuler 默认 Python 是 3.9(没有 Python 2)。我们有一套老的运维监控脚本是用 Python 2 写的,直接搬过来全报错。

报错集中在几个地方:print 语句变 print 函数、urllib2 模块拆分成了 urllib.request 和 urllib.error、ConfigParser 变成了 configparser。这些都是 Python 2 到 3 的经典迁移问题,但当你一次面对几十个脚本的时候,改起来还是头大。

# 方案一:装 Python 2(不推荐,但能救急)

# openEuler 官方源没有 python2,需要编译安装

dnf install -y gcc openssl-devel bzip2-devel libffi-devel

wget https://www.python.org/ftp/python/2.7.18/Python-2.7.18.tgz

tar xzf Python-2.7.18.tgz && cd Python-2.7.18

./configure --enable-optimizations && make altinstall

# 方案二:用 2to3 工具批量转换(推荐)

python3 -m lib2to3 -w -n /opt/scripts/monitor.py

# -w 直接修改文件,-n 不创建备份(建议先备份再跑)

我选了方案二,用 2to3 批量转换后人工检查。大部分脚本能自动转,但有几个用了 commands.getoutput()(Python 3 里没有这个模块)的,得手动改成 subprocess.getoutput()。一共 23 个脚本,改了半天。

教训:迁移前先跑一遍 grep -rn "python2\|#!/usr/bin/python" /opt/ /usr/local/",把所有 Python 2 脚本找出来,提前改。别等迁移完了才发现脚本跑不了,业务等着你修,压力完全不一样。

坑三:内核参数不兼容,性能掉了一截

openEuler 22.03 默认内核是 5.10,CentOS 7 是 3.10。内核大版本跳了两个,有些 sysctl 参数要么改名了,要么默认值变了。

我把旧的 sysctl 配置直接拷过来,sysctl -p 的时候报了三个错。

# CentOS 7 能用但 openEuler 报错的参数

net.bridge.bridge-nf-call-ip6tables = 1 # 模块名变了

net.bridge.bridge-nf-call-iptables = 1 # 同上

net.ipv4.neigh.default.gc_thresh3 = 8192 # 默认值已调大,不需要手动设

# openEuler 正确写法

net.bridge.bridge-nf-call-ip6tables = 1 # 需先 modprobe br_netfilter

net.bridge.bridge-nf-call-iptables = 1

# gc_thresh3 默认已经是 8192,删掉即可

更隐蔽的问题是性能。我们的 Java 应用迁移后吞吐量掉了大约 15%,排查了两天才发现是 内核的透明大页(THP)策略变了。CentOS 7 默认是 always,openEuler 默认是 madvise。对于 Java 这种内存密集型应用,改成 always 之后性能立刻恢复。

# 检查当前 THP 策略

cat /sys/kernel/mm/transparent_hugepage/enabled

# 输出: [madvise] always never <- 中括号表示当前值

# 改成 always(Java 应用推荐)

echo always > /sys/kernel/mm/transparent_hugepage/enabled

# 永久生效

echo "echo always > /sys/kernel/mm/transparent_hugepage/enabled" >> /etc/rc.local

chmod +x /etc/rc.local

坑四:SELinux 策略比 CentOS 严格一截

openEuler 的 SELinux 默认是 enforcing 模式,而且策略比 CentOS 7 更严格。我们的 Nginx 要反向代理到一个非标准端口(8080),CentOS 上跑得好好的,openEuler 上直接 502。

查了半天日志,发现是 SELinux 阻止了 Nginx 连接 8080 端口。

# 查看 SELinux 拦截日志

grep denied /var/log/audit/audit.log | tail -20

# 查看 Nginx 允许连接的端口

semanage port -l | grep http_port_t

# 输出里没有 8080

# 添加 8080 到允许列表

semanage port -a -t http_port_t -p tcp 8080

# 或者临时关闭 SELinux 排查(不推荐生产长期关闭)

setenforce 0

教训:很多人遇到 SELinux 问题第一反应是 setenforce 0,这不叫解决问题,这叫掩耳盗铃。正确做法是逐条排查 audit 日志,用 audit2allow 生成自定义策略。多花半小时,但安全底线保住了。

坑五:systemd 服务脚本行为变了

我们有个 Java 应用用 systemd 管理启动,service 文件里写了 LimitNOFILE=65536。CentOS 上一直正常,openEuler 上应用启动后文件句柄上限还是 1024。

查了半天才知道,openEuler 的 systemd 版本更新了,LimitNOFILE 的生效逻辑变了。新版本要求同时设置 LimitNOFILE=65536 和 LimitNOFILESoft=65536,否则 soft limit 不生效。

# /etc/systemd/system/myapp.service

[Service]

ExecStart=/opt/app/bin/startup.sh

LimitNOFILE=65536

LimitNOFILESoft=65536 # openEuler 必须加这行

LimitNPROC=65536

LimitNPROCSoft=65536 # 同理

# 改完后重载

systemctl daemon-reload

systemctl restart myapp

# 验证进程的实际 limit

cat /proc/$(pidof java)/limits | grep "Max open files"

类似的问题还有 TimeoutStartSec,CentOS 默认 90 秒,openEuler 默认 120 秒。如果你的服务文件里没显式设置,行为就不一样。Java 应用启动慢的,这个差异可能导致你以为启动成功了其实超时了。

坑六:编译环境变了,老C程序编不过

我们有个用 C 写的流量采集程序,源码编译安装。CentOS 7 上 gcc 4.8,openEuler 上 gcc 10。版本跳了这么多,编译直接报错:一堆 implicit function declaration 的 warning 变成了 error。

原因是 gcc 10 开始默认开启 -Werror=implicit-function-declaration,老代码里没 include 头文件就调用函数的习惯,在新编译器下直接过不了。

# 方案一:Makefile 里加编译选项(快速救急)

CFLAGS += -Wno-error=implicit-function-declaration

CFLAGS += -Wno-error=int-conversion

CFLAGS += -fcommon # gcc 10 默认 -fno-common,老代码可能需要改回

# 方案二:补全缺失的 #include(治本)

# 逐个修复编译错误,加上正确的头文件引用

我先用方案一让程序编过跑起来,然后安排开发逐步修方案二。这种技术债不能一直欠着,但迁移期间优先保证业务可用。

教训:所有源码编译安装的程序,迁移前一定要在新系统上试编译一次。编译问题比运行时问题好排查,至少报错信息明确。等上了生产才发现编不过,那就只能干瞪眼了。

四、迁移后验证:一张清单保平安

每台机器迁完,我都按这张清单逐项验证,确认全部通过才切流量。

1、基础验证

  • 系统版本确认:cat /etc/os-release
  • 内核版本确认:uname -r
  • 磁盘分区和挂载点正确:df -h && lsblk
  • 网络连通性:ping 网关、ping DNS、curl 业务地址
  • 主机名和 hosts 文件:hostname && cat /etc/hosts
  • 时区和时间同步:timedatectl && chronyc tracking

2、服务验证

  • 所有 systemd 服务状态正常:systemctl list-units --state=failed
  • 定时任务已迁移:crontab -l && ls /etc/cron.d/
  • 开机自启服务列表正确:systemctl list-unit-files --state=enabled
  • 防火墙规则已同步:firewall-cmd --list-all
  • SELinux 状态符合预期:getenforce && sestatus

3、应用验证

  • 应用端口监听正常:ss -tlnp
  • 应用日志无异常报错:tail -100 /var/log/messages
  • 进程资源限制符合预期:cat /proc/PID/limits
  • 文件句柄使用量正常:lsof | wc -l
  • 性能基准对比:同样的压测跑一遍,对比响应时间和吞吐量

五、速查清单:CentOS 迁移国产系统避坑指南

1、选型跟业务走,不跟热度走。容器云原生选 openEuler,等保合规选麒麟,桌面办公选统信UOS。

2、评估工具先跑一遍。x2openEuler 或类似的兼容性扫描工具能帮你提前发现 80% 的问题。

3、全新部署优于原地升级。留旧机器做回退后路,新机器验证通过后再切流量。

4、软件版本差异要逐项 diff。同名的包不同版本,默认参数可能变了,别只看"装上了没"。

5、Python 2 脚本提前迁移。用 2to3 批量转 + 人工检查,别等迁移当天才发现跑不了。

6、内核参数别无脑拷贝。大版本跳跃后参数名和默认值可能变了,sysctl -p 逐条验证。

7、SELinux 别直接关。用 audit2allow 生成策略,保住安全底线。

8、systemd 服务文件检查 limit 配置。新版本可能需要同时设置 hard 和 soft limit。

9、源码编译的程序提前试编。gcc 版本跨度大,编译报错比运行报错好排查。

10、验证清单逐项过。基础、服务、应用三层验证,全过了才切流量。

20 台服务器,前后花了 6 周,踩了 6 个坑。说实话,迁移本身不难,难的是那些藏在细节里的差异。包名一样版本不一样、参数一样默认值不一样、配置一样行为不一样——这些才是真正费时间的地方。

但换个角度想,CentOS 停服是不可逆的趋势,早迁早安心。趁着还有时间从容地迁,总比等出了安全漏洞被逼着临时迁要好。

作者丨Ваня

来源丨公众号:码农庄园的运维师(ID:gh_385167a730aa)

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn

上一篇:人工智能产业日报(08.04) : AI监管与增长

下一篇:没有了

相关内容

热门资讯

人工智能产业日报(08.04)... 行业动态 AI越狱、硅谷慌了,人类到底在害怕什么? 1346名来自OpenAI、Anthrop...
广西AI在印尼当“向导” “没有导航以前,送一趟货经常找不着地方或走错路。现在有了导航,跟着定位走就行。”近日,印度尼西亚北马...
京东:开源实时流式视频编辑模型... 钛媒体App 8月5日,据京东黑板报消息,8月5日,京东宣布开源自研的实时流式视频编辑模型JoyAI...
114B参数、6B激活,San... 鹭羽 发自 凹非寺 量子位 | 公众号 QbitAI 再牛的大模型,也要放到行业面前公开露个面,才算...
京东开源自研实时流式视频编辑模... 8月5日消息,京东黑板报今日发文宣布,京东开源自研实时流式视频编辑模型JoyAI-Video-Edi...