写在最前

有时候,我们确实会遇到官方 Docker 镜像只提供 x86_64(amd64)版本,而没有原生 ARM64 支持的情况。即使拿到源码,也可能因依赖或构建脚本限制无法自行编译。

这时,可以借助 QEMU user-mode emulation(通过 tonistiigi/binfmt 等工具注册)来实现:在 ARM64 主机上透明运行 amd64 镜像。

优点

  • 无需修改镜像或源码,一键启用异构架构支持。

  • 适用于那些“必须用官方镜像”但对性能要求不高的场景(如监控代理、配置同步、日志转发、GTID 追踪等辅助服务)。

代价

  • CPU 密集型任务性能损失明显(通常只有原生 30%-60%)。

  • IO/网络型任务影响较小(一般 10%-30%,低负载下几乎无感)。

核心技术背景是它基于 Linux 内核的 binfmt_misc 机制 + QEMU 用户态模拟(user-mode emulation)。

  • binfmt_misc:Linux 内核的一个模块,允许注册“二进制格式处理器”。当内核尝试执行一个非本机架构的可执行文件时(比如在 ARM64 主机上运行 x86_64 二进制),它会自动调用注册的模拟器(QEMU)来“翻译”执行,而不需要手动干预。

  • QEMU:开源模拟器,这里用的是静态编译的 QEMU user-mode 版本,支持多种架构(amd64、arm64、riscv64、ppc64le 等)。

总之,这是一种实用且低成本的“救急”方案,在多架构环境中广泛使用,权衡好性能与便利性即可。

1. docker 部署

docker run --privileged --rm tonistiigi/binfmt --install x86_64

2. kubernetes 部署

通过 tonistiigi/binfmt 一次性初始化节点的 QEMU 多架构支持,即可在集群层面实现 arm64 运行 x86 镜像的能力。该过程仅需短暂运行 DaemonSet,启动完成后无需保留任何组件可以删除掉这个DaemonSet,后续对 Kubernetes 和业务配置均无侵入。

2.1 daemonset

kind: DaemonSet
apiVersion: apps/v1
metadata:
  name: binfmt-register
  namespace: kube-system
  labels:
    app: binfmt-register
  annotations:
    deprecated.daemonset.template.generation: '2'
    kubesphere.io/creator: admin
spec:
  selector:
    matchLabels:
      app: binfmt-register
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: binfmt-register
      annotations:
        kubesphere.io/creator: admin
        kubesphere.io/restartedAt: '2025-12-26T04:26:22.011Z'
    spec:
      initContainers:
        - name: register-binfmt
          image: 'tonistiigi/binfmt:latest'
          args:
            - '--install'
            - x86_64
          resources: {}
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: Always
          securityContext:
            privileged: true
      containers:
        - name: pause
          image: 'pause:3.9'
          resources: {}
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      dnsPolicy: ClusterFirst
      hostPID: true
      securityContext: {}
      schedulerName: default-scheduler
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 0
  revisionHistoryLimit: 10

写在最后