一、混合架构是什么,为什么要聊这个
先说清楚一个概念,混合架构说白了就是在一套系统里同时跑着不同类型的计算资源。比如你手上有ARM架构的服务器,也有x86架构的服务器,你可能还想加上一些国产芯片的机器,这些机器加在一起形成一个统一的资源池。为什么要这么做?因为现实场景里,大家手里的硬件五花八门,不可能全部统一。有的机构是老系统要维护,有的是新采购的国产设备,硬要一刀切反而不现实。
openEuler作为国产操作系统的代表之一,它在处理这种混合场景时提供了不少便利。但怎么设计一个合理的部署架构,让不同架构的机器都能协同工作,同时又不会引入额外的管理复杂度,这确实是很多人头疼的事。这篇文章就把这个事从头到尾捋一遍,从整体思路到具体落地,尽量说得直白。
二、openEuler在国内部署中的位置
openEuler是开源开放、安全稳定的操作系统内核,最早由华为发起,现在已经成为国内操作系统生态的重要组成部分。在国内的信息基础设施建设里,它经常承担关键角色,特别是政府、金融、电信这些行业,对操作系统有自主可控的要求,openEuler就是首选之一。
它的优势在于对多种架构的支持。无论是x86、ARM还是RISC-V,openEuler都有对应的版本。这对于混合架构场景来说非常关键,因为你不需要为每一种芯片单独部署一套操作系统。同一个基础镜像,可以在不同的硬件上跑起来。
不过这里有个坑需要注意。虽然openEuler本身支持多架构,但你在上面跑的应用不一定都支持。一个应用如果在x86上编译好了,你直接放到ARM机器上就跑不了。所以整个架构设计里,怎么解决应用的跨架构适配问题,是一个核心课题。
三、混合架构部署的整体设计思路
整体思路可以概括成一句话:统一管控,分区运行。
意思是说,不管你底下有多少种硬件,上层的管理面要统一起来。运维人员只需要面对一套管理工具,不需要分别去连每台机器。但在实际运行层面,不同的任务要根据硬件能力分配到合适的节点上。
这个思路具体怎么落地呢?我的建议是用容器化的方式来组织。把应用打包成镜像,镜像可以针对不同的架构分别构建,然后用容器编排工具来管理这些容器。编排工具负责调度,根据节点的架构类型把对应架构的镜像调度上去。
整个架构大致分三层:
最底层是基础设施层,就是各种架构的物理服务器和虚拟机。这一层你不需要关心它有多少种架构,只要它们都跑着openEuler就行。
中间是平台层,负责资源的调度和管理。这里推荐用Kubernetes来做,它对多架构的支持比较成熟,而且插件生态丰富。
最上层是业务层,就是你的应用。应用需要做到架构无关,或者至少针对每种架构都有对应的版本。
四、具体部署方案与配置示例
4.1 节点规划
节点规划是第一步。你得先搞清楚自己手里有哪些机器,每种机器什么架构,适合跑什么任务。
下面是一个节点规划的示例。技术栈统一使用Kubernetes和Bash,所有配置和脚本都围绕这个技术栈展开。
# ============================================
# 节点规划脚本示例
# 技术栈:Kubernetes + Bash + openEuler
# 用途:统计集群中各架构节点的数量
# ============================================
# 获取集群中所有节点的架构信息
echo "=== 集群节点架构分布 ==="
# 按架构分组统计
for arch in x86_64 aarch64 riscv64; do
count=$(kubectl get nodes -o json | \
jq ".items[] | select(.status.nodeInfo.architecture == \"$arch\") | .metadata.name" | \
wc -l)
echo "架构 $arch: $count 个节点"
done
# 查看每个节点的详细架构信息
echo ""
echo "=== 节点详细信息 ==="
kubectl get nodes -o wide | \
while read line; do
echo "$line"
done
这个脚本会帮你快速了解集群里的硬件构成。有了这个基础信息,你才能决定后面的资源分配策略。
4.2 集群初始化配置
集群初始化是混合架构部署的关键环节。在openEuler上部署Kubernetes集群时,需要注意内核参数的调整和存储后端的兼容性。
# ============================================
# openEuler上的Kubernetes集群初始化
# 技术栈:Kubernetes + openEuler
# 用途:在openEuler系统上初始化Kubernetes控制节点
# ============================================
# 第一步:配置openEuler内核参数
# 混合架构下需要确保网络转发和网桥过滤被启用
cat > /etc/sysctl.d/99-kubernetes.conf << 'EOF'
# 启用IP转发
net.ipv4.ip_forward = 1
# 关闭IPVS相关的限制(如果需要)
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
# 应用内核参数
sysctl --system
# 第二步:安装容器运行时
# openEuler使用dnf作为包管理器
dnf install -y containerd
# 第三步:配置containerd(多架构支持)
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
# 在config.toml中确保以下配置存在
# 添加插件配置到containerd配置
cat >> /etc/containerd/config.toml << 'EOF'
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.k8s.io/pause:3.9"
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
EOF
# 第四步:启动并设置开机自启
systemctl enable --now containerd
# 第五步:安装kubeadm、kubelet和kubectl
dnf install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
systemctl enable --now kubelet
# 第六步:初始化控制节点
kubeadm init \
--apiserver-advertise-address=<你的内网IP> \
--pod-network-cidr=10.244.0.0/16 \
--ignore-preflight-errors=MemSwapInUse
这段配置里有个重点:containerd的配置。在混合架构环境下,containerd需要正确配置运行时,确保它能识别和处理不同架构的容器镜像。sandbox_image这一行要特别留意,它决定了Pod的沙箱环境,不同架构下可能需要指定不同的pause镜像。
4.3 容器镜像的多架构构建
这是混合架构部署中最容易踩坑的地方。你的应用需要能同时跑在x86和ARM上,那就必须构建多架构的镜像。
# ============================================
# 多架构容器镜像构建示例
# 技术栈:Docker Buildx + openEuler
# 用途:构建同时支持x86_64和aarch64的容器镜像
# ============================================
# 第一步:安装并初始化Docker Buildx
# Buildx是Docker的多平台构建工具
docker run --privileged --rm tonistiigi/binfmt --install all
# 验证支持的架构
docker buildx inspect --bootstrap
# 第二步:编写多架构的Dockerfile
# 这个Dockerfile会根据目标架构选择对应的包
cat > Dockerfile << 'DOCKERFILE'
# 基础镜像选择:根据构建架构动态选择
ARG TARGETARCH
# 如果是ARM架构,使用aarch64的基础镜像
# 如果是x86架构,使用x86_64的基础镜像
FROM openeuler/openeuler:22.03 AS builder-${TARGETARCH}
# 安装依赖(openEuler使用dnf)
RUN dnf install -y \
gcc \
make \
python3 \
&& dnf clean all
# 拷贝源代码
COPY . /workspace
WORKDIR /workspace
# 编译应用(编译过程会根据架构自动适配)
RUN make build ARCH=${TARGETARCH}
# 最终运行镜像
FROM openeuler/openeuler:22.03 AS runtime-${TARGETARCH}
RUN dnf install -y \
ca-certificates \
&& dnf clean all
COPY --from=builder-${TARGETARCH} /workspace/build /opt/app
EXPOSE 8080
# 启动命令
CMD ["/opt/app/start.sh"]
DOCKERFILE
# 第三步:使用Buildx构建多架构镜像
# 注意:需要使用buildx而不是普通的docker build
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t registry.example.com/myapp:v1.0.0 \
--push \
.
# 第四步:推送后在Kubernetes中使用
# 多架构镜像需要配置imagePullPolicy
cat > deployment.yaml << 'YAML'
apiVersion: apps/v1
kind: Deployment
metadata:
name: multi-arch-app
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: multi-arch-app
template:
metadata:
labels:
app: multi-arch-app
spec:
# 关键:配置节点选择器,确保调度到正确的架构节点
nodeSelector:
kubernetes.io/arch: amd64
containers:
- name: app
image: registry.example.com/myapp:v1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 500m
memory: 1Gi
YAML
这个示例里用到了Docker Buildx,它是构建多架构镜像的标准工具。原理很简单:它在一次构建过程中,同时针对多个架构编译你的应用,然后打包成一个包含多架构层的镜像。Kubernetes在拉取这个镜像时,会自动根据当前节点的架构选择对应的层来运行。
五、容器编排与资源调度
多架构环境下,资源调度的策略需要特别设计。你不能随便把一个x86的应用调度到ARM节点上,反之亦然。
# ============================================
# 多架构资源调度配置
# 技术栈:Kubernetes
# 用途:通过NodeSelector和Affinity实现架构感知调度
# ============================================
# 方法一:使用NodeSelector(简单直接)
cat > node-selector-deployment.yaml << 'YAML'
apiVersion: apps/v1
kind: Deployment
metadata:
name: x86-app
spec:
replicas: 2
selector:
matchLabels:
app: x86-app
template:
metadata:
labels:
app: x86-app
spec:
nodeSelector:
# 只调度到x86架构的节点
kubernetes.io/arch: amd64
containers:
- name: x86-workload
image: registry.example.com/x86-app:v1.0
YAML
# 方法二:使用Affinity(更灵活,推荐)
cat > affinity-deployment.yaml << 'YAML'
apiVersion: apps/v1
kind: Deployment
metadata:
name: flexible-app
spec:
replicas: 4
selector:
matchLabels:
app: flexible-app
template:
metadata:
labels:
app: flexible-app
spec:
affinity:
# 节点亲和性:优先调度到ARM节点
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- arm64
# 备选:如果ARM节点不够,也可以调度到x86节点
- weight: 50
preference:
matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- amd64
containers:
- name: flexible-workload
image: registry.example.com/multi-arch-app:v1.0
YAML
# 方法三:使用Taints和Tolerations(强制隔离)
# 先给ARM节点打上污点
kubectl taint nodes arm-node-01 kubernetes.io/arch=arm64:NoSchedule
# 然后在工作负载中配置容忍
cat > taint-tolerance-deployment.yaml << 'YAML'
apiVersion: apps/v1
kind: Deployment
metadata:
name: arm-only-app
spec:
replicas: 2
selector:
matchLabels:
app: arm-only-app
template:
metadata:
labels:
app: arm-only-app
spec:
tolerations:
# 容忍ARM节点的污点
- key: "kubernetes.io/arch"
operator: "Equal"
value: "arm64"
effect: "NoSchedule"
nodeSelector:
kubernetes.io/arch: arm64
containers:
- name: arm-workload
image: registry.example.com/arm-app:v1.0
YAML
三种方法各有特点。NodeSelector最简单,但它只是个基础过滤,不能表达复杂条件。Affinity最灵活,可以设置优先和备选策略,适合弹性调度的场景。Taints和Tolerations适合强制隔离的场景,比如你有一批ARM节点专门跑AI推理任务,不想让它们被其他工作负载占用。
六、网络与安全策略
混合架构下的网络策略需要特别考虑,因为不同架构节点之间的网络通信可能会有差异。
# ============================================
# 混合架构网络策略配置
# 技术栈:Kubernetes NetworkPolicy + openEuler
# 用途:配置跨架构节点的网络访问控制
# ============================================
# 为多架构应用配置网络策略
cat > network-policy.yaml << 'YAML'
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: multi-arch-network-policy
namespace: production
spec:
podSelector:
matchLabels:
app: multi-arch-app
policyTypes:
- Ingress
- Egress
# 入站规则:只允许来自同命名空间的请求
ingress:
- from:
- namespaceSelector:
matchLabels:
name: production
ports:
- protocol: TCP
port: 8080
# 出站规则:允许访问外部依赖
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.244.0.0/16
- 10.96.0.0/16
ports:
- protocol: TCP
port: 443
- protocol: UDP
port: 53
网络策略在混合架构下的重要性比单架构场景更高。因为不同架构的节点可能分布在不同物理位置,网络延迟和带宽限制可能不同。通过NetworkPolicy,你可以精确控制哪些架构节点之间可以通信,哪些不能。
另外,openEuler的网络栈有一些特色配置需要注意。比如openEuler在容器场景下默认使用Cilium作为CNI插件,它支持eBPF加速网络转发,这对性能有不错的提升。
# ============================================
# Cilium CNI在openEuler上的配置
# 技术栈:Cilium + openEuler + Kubernetes
# 用途:配置Cilium实现高性能容器网络
# ============================================
# Cilium的全局配置
cat > cilium-config.yaml << 'YAML'
apiVersion: cilium.io/v2
kind: CiliumConfig
metadata:
name: cilium-config
namespace: kube-system
spec:
# 启用BPF加速
bpf:
masquerade: true
# 多架构下确保BPF程序正确加载
ct:
timeout:
tcp: 300
tcp-fin: 120
# 跨架构节点的网络策略强制执行
policy:
enabled: true
lb:
proxyMode: "snat"
# 对于多架构场景,建议使用snat模式
# 这样跨架构的通信会先经过网关节点做源地址转换
Cilium的snat模式在混合架构场景下特别有用。当一个x86节点上的Pod要和ARM节点上的Pod通信时,snat模式会确保流量经过统一的入口点,避免直接跨架构节点通信可能带来的兼容性问题。
七、应用场景分析
混合架构加openEuler的组合,有几个典型的应用场景值得展开说说。
第一个场景是政务系统的国产化替代。很多政府机构正在把老旧的x86服务器逐步替换为国产芯片设备,但这个过程不是一夜之间完成的。在过渡期内,新买的国产服务器和旧的x86服务器要同时在线运行。这时候混合架构部署方案就能派上用场。你可以用openEuler统一操作系统层,用Kubernetes统一管控面,然后在应用层做架构适配。旧的业务跑在x86节点上,新的业务优先部署到ARM或国产芯片节点上。
第二个场景是AI推理服务的多架构部署。AI推理任务对算力的需求很高,不同架构的GPU和AI加速卡性能差异很大。有的AI芯片是ARM架构的,有的是x86架构的。用混合架构部署方案,你可以根据不同模型的推理需求,把任务分配到最合适的硬件上。比如一个轻量级模型跑在ARM节点上,一个需要大量浮点运算的模型跑在x86节点上,通过Kubernetes的调度策略自动分配。
第三个场景是边缘计算和中心云的协同。边缘节点可能用的是ARM架构的低功耗设备,中心云用的是x86架构的高性能服务器。混合架构方案可以让两边的资源统一管理,数据可以在中心和边缘之间灵活调度。openEuler在边缘场景下的资源占用比较轻,很适合这种场景。
八、技术优缺点
优点方面:
第一,资源利用率高。混合架构让你不再需要为每种硬件单独维护一套集群,统一管理降低了运维成本。
第二,平滑过渡。从x86迁移到国产架构不需要一次性完成,可以逐步推进,降低业务风险。
第三,架构灵活性。不同架构的硬件可以各司其职,把计算密集型任务放到高性能节点,把轻量任务放到低功耗节点。
第四,生态支持好。openEuler本身对多架构的支持比较完善,Kubernetes生态对多架构的调度也有成熟的方案。
缺点方面:
第一,镜像构建成本增加。你需要为每个应用维护多架构的镜像,构建和测试的工作量会翻倍。
第二,调试复杂度提升。同一个应用在x86上正常,在ARM上出错,排查起来需要同时熟悉两种架构的特性和差异。
第三,性能调优困难。不同架构的硬件性能模型不同,统一的性能基线不好建立。比如一个应用在x86上跑得好好的,换到ARM上可能需要重新调整并发数、内存分配策略等参数。
第四,工具链兼容性。不是所有开发工具都支持多架构。有些编译工具链可能只针对x86做了优化,在ARM上的性能可能打折扣。
九、注意事项
第一,镜像仓库要支持多架构。不是所有容器镜像仓库都支持multi-arch manifest。你在选择镜像仓库的时候,要确认它是否支持OCI的多架构规范。Docker Hub、Harbor(新版本)都支持,但一些自建仓库可能版本太老不支持。
第二,应用层的架构适配不能偷懒。有些应用开发者为了省事,直接把x86编译好的二进制文件放到镜像里,然后在ARM节点上就报错。正确的做法是用Dockerfile的TARGETARCH参数,让应用根据目标架构重新编译。
第三,存储后端要统一。混合架构节点上如果用的是不同的存储后端,可能会导致I/O性能差异很大。建议在openEuler上统一使用支持多架构的存储插件,比如Rook或者OpenEBS。
第四,监控和日志要覆盖架构维度。监控面板里要能看到不同架构节点的资源使用情况。否则出了问题很难定位是哪个架构节点的故障。Prometheus和Grafana的组合可以很好地支持这一点,只需要在指标里加上architecture标签。
第五,安全策略要关注架构差异。不同架构的安全特性可能不同。比如某些安全沙箱技术在x86上支持得很好,在ARM上可能没有。在配置Pod安全策略或者准入控制器时,要注意这些差异。
第六,CI/CD流水线要支持多架构构建。你的代码提交后,CI流水线需要自动触发多架构的构建和测试。GitHub Actions、GitLab CI等都支持matrix构建,可以在一个流水线里同时构建多个架构。
十、总结
混合架构下的部署架构设计,核心是在"统一管理"和"差异化运行"之间找到平衡。openEuler作为国产操作系统,在多架构支持方面已经做得比较成熟,配合Kubernetes的容器编排能力,可以构建出一套既高效又可扩展的混合架构部署方案。
实际操作中的关键点是:用容器化来隔离架构差异,用Kubernetes来统一调度,用Buildx来构建多架构镜像,用NetworkPolicy来管理跨架构通信。这四个要素配合好,混合架构部署就不会变成一团乱麻。
对于正在推进国产化替代的团队来说,混合架构不是一个临时方案,而是一个长期的过渡策略。在完全切换到国产架构之前,混合架构方案可以保证业务连续性,同时让你逐步验证国产硬件的可靠性。等到一切就绪,再平滑地关掉x86节点,整个过程可以做得非常顺滑。
最后想说的是,技术选型没有银弹。混合架构有它明显的优势,但也有额外的复杂度。如果你团队目前只有一种架构的硬件,那没有必要提前引入混合架构的复杂度。但如果你已经有多种架构的设备,或者计划在不久的将来引入新架构的硬件,那这套方案值得认真考虑。
评论
围绕“基于openEuler的国产操作系统在混合架构下的部署架构设计”参与讨论