Kairos:Kubernetes原生不可变基础设施构建实践

发布时间:2026/5/17 1:09:25

Kairos:Kubernetes原生不可变基础设施构建实践 1. 项目概述当Kubernetes遇见不可变基础设施如果你和我一样常年泡在云原生和基础设施自动化的圈子里那你一定对“不可变基础设施”这个概念不陌生。简单来说它就像我们小时候玩的乐高积木——每一块积木都是预先封装好的、标准化的模块要搭建新东西或者修复损坏的部分我们不是去修改现有的积木块而是直接替换掉整个模块。在服务器运维领域这意味着我们不再登录到一台运行中的服务器里去修修补补打补丁、改配置而是直接构建一个包含了所有更新和配置的、全新的、完整的服务器镜像然后用这个新镜像去替换掉旧的实例。听起来很美好对吧但实际操作起来尤其是在Kubernetes这个已经成为事实标准的容器编排平台上你会发现这条路有点“水土不服”。传统的云厂商提供了成熟的镜像构建服务比如AWS的EC2 Image Builder, GCP的Packer with Compute Engine但这些方案往往和特定的云平台深度绑定流程复杂而且很难与Kubernetes集群的声明式配置和GitOps工作流无缝集成。我们想要的是像管理Kubernetes应用一样用YAML文件去声明我的操作系统镜像应该长什么样然后有一个工具能自动地、可靠地、可重复地把它构建出来。这就是GeraldYa/kairos项目试图解决的问题。Kairos不是一个全新的操作系统发行版而是一个构建框架和一套工具集它的核心目标是让你能够用声明式的方式为Kubernetes环境构建完全定制化的、不可变的Linux操作系统镜像。你可以把它想象成一个“Kubernetes原生的镜像构建器”。它基于成熟的开源项目如Elemental源自SUSE Linux Enterprise的衍生项目和systemd提供了一个从镜像配方定义、自动化构建、到最终镜像分发的完整工作流。对于运维工程师、SRE和平台团队而言这意味着你可以将底层基础设施的版本控制和生命周期管理提升到和应用部署同等的自动化与可靠性水平。2. 核心设计理念与架构拆解2.1 为什么是“Kubernetes原生”要理解Kairos的价值首先要明白传统镜像构建流程在云原生环境下的痛点。通常构建一个用于Kubernetes节点的镜像无论是Worker节点还是专用的边缘设备你需要选择一个基础镜像如Ubuntu, Fedora, Flatcar Container Linux。编写一个脚本可能是Shell、Ansible或Packer配置在其中安装kubelet、容器运行时containerd/docker、CNI插件、监控代理等一堆软件包。在某个CI/CD流水线或本地虚拟机中执行这个脚本生成一个RAW或QCOW2格式的镜像文件。将镜像上传到云存储或镜像仓库。在目标平台如OpenStack、vSphere、裸金属上用这个镜像创建新机器。这个过程充满了手动干预、环境依赖和“雪花服务器”的风险。每个镜像的构建环境细微差异都可能导致不可预知的问题。Kairos提出的“Kubernetes原生”方案旨在用Kubernetes的哲学来解决这个问题声明式配置你的镜像配方不再是一堆命令脚本而是一个或多个Kubernetes自定义资源CRD比如MachineRegistration或ClusterConfig。你通过YAML文件描述最终镜像的状态“我需要一个基于openSUSE MicroOS的镜像预装k3s v1.27并包含我的自定义证书和SSH密钥”。可重复性与幂等性构建过程在一个受控的、容器化的环境中进行通常本身就在一个Kubernetes Pod里。相同的配方输入无论在哪里执行理论上都会产出完全一致的输出。与现有工具链集成你的镜像配方YAML可以和你的应用部署清单Deployment, Service存放在同一个Git仓库中。你的CI/CD系统如Argo CD, Flux在同步应用配置的同时也可以触发镜像的构建和更新真正实现从基础设施到应用的端到端GitOps。2.2 Kairos架构的核心组件Kairos的架构可以粗略分为三个层次构建时Build-time、运行时Runtime和生命周期管理Lifecycle Management。构建时层这是Kairos最核心的部分。它提供了一个名为kairos的CLI工具以及一系列构建容器镜像。你通过一个配置文件例如cloud-config.yaml或自定义的CRD定义你的需求。kairosCLI会读取这个配置并启动一个构建容器。这个容器内部从一个你指定的、不可变的、精简的基础操作系统“种子”镜像开始Kairos官方提供基于openSUSE MicroOS、Ubuntu Core等的变体。这些种子镜像本身非常小只包含启动系统和Kairos框架。根据你的配置动态地安装软件包、写入文件、配置用户和网络。这个过程大量使用了systemd单元和cloud-init的标准语法因此兼容性很好。最终输出一个包含了所有定制内容的、全新的、不可变的系统镜像文件格式可以是ISO、RAW、QCOW2等。这个镜像文件就是你的“黄金镜像”。运行时层你使用构建好的镜像去启动一台物理机、虚拟机或云实例。首次启动时镜像内的Kairos框架会执行首次启动配置这可能包括连接到你的Kubernetes集群如果是边缘场景可能是自动组建一个K3s集群。应用在构建时可能尚未完全确定的配置例如从密钥管理服务获取密钥。将自身注册到中央管理平台如果配置了的话。 运行时系统本身仍然是不可变的。所有的用户数据、容器工作负载、Kubernetes的/var目录下的数据都被引导到另一个独立的、可写的持久化分区或卷上。系统分区是只读的确保了基础环境的一致性。生命周期管理层这是Kairos面向生产环境的关键。它提供了原子化的、安全的系统升级机制。当有新的安全补丁或功能更新时你不是在运行的系统上执行apt-get upgrade而是构建一个包含了所有更新的新版本“黄金镜像”。通过管理通道可以是Kubernetes Operator也可以是简单的HTTP服务器将新镜像分发给所有节点。节点在后台下载新镜像并在下次重启时从新的、只读的系统镜像启动。如果启动失败它可以自动回滚到上一个已知良好的版本。这个机制与容器滚动更新类似但作用于整个操作系统层面。注意Kairos的“不可变”主要体现在系统分区。它采用了A/B分区更新或类似ostree的原子更新模型。这意味着更新过程要么完全成功要么完全回滚避免了传统升级过程中因断电或网络问题导致的系统半残状态极大地提升了大规模集群更新的可靠性。3. 从零开始构建你的第一个定制化Kairos镜像理论说了这么多我们来点实际的。假设我们需要为一个内部开发测试的Kubernetes集群构建一批Worker节点镜像要求基于Ubuntu预装containerd和Kubernetes 1.28的kubelet、kubeadm、kubectl并设置好内网仓库的证书。3.1 环境准备与工具安装首先你需要一个能够运行容器和构建镜像的环境。最方便的是直接使用一台Linux开发机或者一个拥有特权容器权限的Kubernetes Pod。# 1. 安装Kairos CLI # 前往项目的GitHub Release页面https://github.com/geraldya/kairos/releases下载最新版的 kairos 二进制文件。 # 这里以Linux amd64为例 wget https://github.com/geraldya/kairos/releases/download/v2.0.0/kairos-2.0.0-linux-amd64 sudo install -m 755 kairos-2.0.0-linux-amd64 /usr/local/bin/kairos # 验证安装 kairos version # 2. 准备一个工作目录 mkdir -p ~/kairos-build cd ~/kairos-build3.2 编写镜像构建配方Cloud Config这是整个流程的核心。我们将创建一个cloud-config.yaml文件。这个文件遵循cloud-init的语法但会被Kairos在构建阶段解析和执行。# ~/kairos-build/cloud-config.yaml name: my-k8s-worker-image stages: initramfs: - name: Install base packages commands: - | # 更新包缓存并安装必要工具 apt-get update apt-get install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates - name: Install containerd commands: - | # 安装containerd curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpt-key add - add-apt-repository deb [archamd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable apt-get update apt-get install -y containerd.io # 配置containerd使用systemd作为cgroup driverKubernetes推荐 containerd config default /etc/containerd/config.toml sed -i s/SystemdCgroup false/SystemdCgroup true/ /etc/containerd/config.toml systemctl enable containerd - name: Install Kubernetes components commands: - | # 添加Kubernetes仓库 curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - echo deb https://apt.kubernetes.io/ kubernetes-xenial main /etc/apt/sources.list.d/kubernetes.list apt-get update # 安装指定版本的kubelet, kubeadm, kubectl apt-get install -y kubelet1.28.0-00 kubeadm1.28.0-00 kubectl1.28.0-00 apt-mark hold kubelet kubeadm kubectl # 防止被自动升级 - name: Configure internal registry certificate files: - path: /usr/local/share/ca-certificates/internal-ca.crt content: | -----BEGIN CERTIFICATE----- (这里粘贴你的内部CA证书内容) -----END CERTIFICATE----- commands: - update-ca-certificates # 系统启动后的阶段配置 boot: - name: Final system configuration commands: - echo My custom Kubernetes worker image is ready! /etc/motd这个配置文件定义了在构建镜像的initramfs阶段即系统初始化早期需要执行的一系列命令安装基础工具、containerd、Kubernetes三件套并部署内部CA证书。在boot阶段我们添加了一个简单的登录提示信息。3.3 执行镜像构建命令现在我们可以使用kairosCLI来构建镜像了。我们需要指定一个基础“种子”镜像。这里我们使用Kairos官方提供的kairos-ubuntu-22.04镜像。cd ~/kairos-build # 使用docker作为构建后端需要本地有docker daemon kairos build \ --cloud-config cloud-config.yaml \ --image docker://ghcr.io/kairos-io/kairos-ubuntu-22.04:latest \ --output-dir ./output让我们拆解这个命令--cloud-config: 指定我们刚写的配方文件。--image: 指定基础种子镜像。这里从GitHub Container Registry拉取。--output-dir: 构建产出的目录。执行这个命令后kairos会拉取基础镜像。启动一个特权构建容器将我们的配方注入。在容器内按阶段执行配方中的命令层层叠加变更。将最终的系统状态打包成一个可启动的磁盘镜像文件通常是build/*.img或build/*.iso存放在./output目录下。构建过程可能需要10-30分钟取决于网络速度和配方的复杂程度。完成后你会在./output目录下找到类似kairos-timestamp-amd64.img的文件。这个.img文件就是你的定制化不可变镜像可以直接用于创建虚拟机或刷写到物理硬盘。实操心得第一次构建时很容易在cloud-config.yaml的命令里犯错。建议先在本地启动一个基于相同种子镜像的临时容器进行调试。可以使用docker run -it --privileged ghcr.io/kairos-io/kairos-ubuntu-22.04:latest bash进入容器手动执行你配方中的命令确保所有包名正确、网络可达、命令无误。这能节省大量因构建失败而等待的时间。4. 高级场景集成K3s与GitOps工作流仅仅构建一个静态镜像还不够酷。Kairos真正的威力在于与轻量级Kubernetes发行版如K3s和GitOps工具的集成实现边缘集群的“一键部署”和“自动管理”。4.1 构建一个自带K3s的集群节点镜像Kairos内置了对K3s的良好支持。我们可以构建一个镜像让它启动后自动成为一个K3s集群的节点Server或Agent。# k3s-node-config.yaml name: edge-k3s-agent # 使用专门针对k3s优化的基础镜像变体 kairos: version: v2.0.0 # 网络配置确保主机名和网络在启动时设置好 stages: network: - commands: - hostnamectl set-hostname edge-node-{{ trunc 4 .MachineID }} initramfs: - name: Provision K3s environment: K3S_URL: https://my-k3s-server:6443 # 你的K3s Server API地址 K3S_TOKEN: my-secret-node-token # 从K3s Server获取的token K3S_ARGS: --node-ip {{.Address }} --snapshotterzfs # 额外参数 commands: - | # Kairos提供了内置的kairos-agent工具来安装k3s kairos-agent install --device auto --k3s-agent这个配置更简洁。它利用了Kairos提供的kairos-agent工具该工具知道如何与K3s集成。在initramfs阶段它通过环境变量接收K3s集群的接入信息Server URL和Token并在首次启动时自动将自己注册为集群的一个Agent节点。构建命令类似kairos build --cloud-config k3s-node-config.yaml --image docker://ghcr.io/kairos-io/kairos-opensuse-leap:latest --output-dir ./k3s-output用这个镜像批量启动设备比如十台树莓派它们会在启动后自动连接到指定的K3s Server形成一个即插即用的边缘Kubernetes集群。这对于IoT和边缘计算场景极具吸引力。4.2 实现基础设施即代码与GitOps将镜像构建配方纳入Git版本控制是走向生产级不可变基础设施的关键一步。我们可以这样组织代码仓库my-infra-code/ ├── clusters/ │ ├── prod/ │ │ ├── cloud-config.yaml # 生产环境镜像配方 │ │ └── kustomization.yaml │ └── staging/ │ └── cloud-config.yaml # staging环境镜像配方 ├── apps/ # 普通的Kubernetes应用清单 │ └── my-app/ └── .github/workflows/ # 或 gitlab-ci.yml, Jenkinsfile等 └── build-images.yaml在CI/CD流水线如GitHub Actions中你可以配置这样的任务# .github/workflows/build-images.yaml name: Build Kairos Images on: push: paths: - clusters/** workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Build Image run: | docker run --privileged \ -v $(pwd)/clusters/prod/cloud-config.yaml:/config.yaml \ -v $(pwd)/artifacts:/output \ ghcr.io/kairos-io/kairos-cli:latest build \ --cloud-config /config.yaml \ --image docker://ghcr.io/kairos-io/kairos-ubuntu-22.04:latest \ --output-dir /output - name: Upload Artifact uses: actions/upload-artifactv3 with: name: kairos-image path: artifacts/这样每当你的cloud-config.yaml发生变更比如需要更新Kubernetes版本或添加新的安全代理推送到Git仓库后CI流水线就会自动触发一个新的、经过验证的“黄金镜像”的构建。然后你可以通过另一个GitOps工具如Flux的镜像更新自动化策略将新镜像滚动部署到你的节点集群中。注意事项在CI/CD中运行特权容器构建镜像存在安全风险。务必确保你的构建Runner环境是隔离和受信的。更好的实践是使用Kubernetes集群中的Kaniko、Buildah等无需特权模式的镜像构建工具或者使用Kairos提供的专门构建器镜像它们可能已经做了相应的安全强化。5. 生产环境部署的挑战与解决方案实录将Kairos用于开发测试环境很顺畅但上生产总会遇到一些“坑”。以下是我在实际部署中总结的几个关键问题和应对策略。5.1 镜像构建速度与缓存优化问题每次构建都从零开始安装所有包耗时极长超过30分钟CI/CD流水线反馈缓慢。排查与解决分析瓶颈使用time命令分段测量发现90%的时间花在apt-get update和下载安装包上。引入本地包缓存代理在内网搭建一个APT缓存代理如apt-cacher-ng。修改cloud-config.yaml中的APT源地址指向内网代理。stages: initramfs: - name: Configure apt proxy files: - path: /etc/apt/apt.conf.d/02proxy content: | Acquire::http::Proxy http://your-apt-cacher:3142; Acquire::https::Proxy false; commands: - apt-get update # 这次update会利用缓存快很多使用Kairos的构建缓存机制Kairos的构建过程是分层的。如果你的配方中前期步骤很少变动可以利用Docker层缓存原理。但Kairos CLI本身不直接管理缓存我们可以通过将构建环境容器化并持久化缓存目录来模拟。# 在CI脚本中将构建容器的 /var/cache/kairos 目录挂载到宿主机持久化卷 docker run --privileged \ -v /persistent/cache:/var/cache/kairos \ -v $(pwd)/config.yaml:/config.yaml \ ... kairos-cli build ...精简配方审查安装的软件包移除非必要的依赖。优先使用基础镜像中已存在的包。效果优化后常规构建时间从30分钟以上缩短到8-10分钟。5.2 大规模节点的镜像分发与升级问题有上百个边缘节点如何安全、高效地分发新版镜像并触发升级解决方案实录 Kairos提供了kairos-agent命令行工具来管理节点升级但需要一种方式将升级命令推送到所有节点。使用Kubernetes DaemonSet进行推送推荐如果节点已经是Kubernetes集群的一部分这是最云原生的方式。# upgrade-ds.yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: kairos-upgrader spec: selector: matchLabels: app: kairos-upgrader template: metadata: labels: app: kairos-upgrader spec: hostPID: true # 需要主机PID命名空间以重启系统 containers: - name: upgrader image: alpine:latest command: [/bin/sh] args: - -c - | # 1. 从配置中心或环境变量获取新镜像URL NEW_IMAGE_URL$(cat /etc/upgrade/image_url) # 2. 在节点上执行升级命令 nsenter -t 1 -m -u -n -i -- kairos-agent upgrade --image $NEW_IMAGE_URL # 3. (可选) 安排重启 echo Upgrade staged. Reboot manually or via another mechanism. securityContext: privileged: true # 需要特权执行升级命令 volumeMounts: - name: upgrade-config mountPath: /etc/upgrade volumes: - name: upgrade-config configMap: name: kairos-upgrade-config通过更新ConfigMapkairos-upgrade-config中的image_urlDaemonSet会滚动更新在每个节点上执行升级命令。使用边缘管理平台如果节点网络受限或非K8s管理可以考虑与Kairos生态集成的项目如kairos-provider或通过WebSocket/TLS隧道建立反向连接由中心服务器统一发起升级指令。分批次升级与健康检查无论采用哪种推送方式都必须分批次Canary发布进行。先升级少量如5%节点观察监控指标节点状态、Pod运行情况、系统负载一段时间确认无误后再扩大升级范围。Kairos的原子升级特性确保了单节点可以快速回滚但集群级别的分批升级策略需要你自己制定。5.3 调试与故障排查当节点启动失败或行为异常时如何排查常见问题速查表现象可能原因排查步骤镜像构建失败报错Failed to execute stagecloud-config.yaml语法错误或命令执行失败。1. 运行kairos validate cloud-config.yaml检查语法。2. 在构建命令中添加--debug标志获取更详细日志。3. 手动在基础镜像容器中运行失败的命令段。节点启动后无法加入K3s集群网络不通、Token错误、Server证书问题。1. 通过Kairos提供的救援模式或控制台登录节点。2. 检查journalctl -u kairos-agent查看代理日志。3. 手动执行curl -k https://k3s-server:6443测试网络和证书。4. 验证K3S_TOKEN是否正确是否有节点数限制。系统启动卡在某个服务自定义的systemd服务单元有误或依赖不满足。1. 在GRUB启动菜单如果有选择“救援模式”或“单用户模式”启动。2. 使用systemctl status service-name和journalctl -xe -u service-name查看具体错误。3. 检查服务单元文件的语法和依赖关系After,Requires。升级后节点失联新镜像存在致命bug或升级过程被中断。1. Kairos支持回滚。如果节点有带外管理IPMI/iDRAC强制重启它应自动从上一个活动分区启动。2. 检查升级日志通常位于/run/kairos/upgrade.log或通过journalctl过滤kairos相关单元。独家避坑技巧启用持久化日志在cloud-config.yaml中配置将日志持久化到数据分区避免重启后丢失关键故障信息。stages: boot: - name: Persist journals commands: - mkdir -p /persist/var/log/journal - systemctl enable systemd-journald.service - sed -i s/#Storageauto/Storagepersistent/ /etc/systemd/journald.conf - sed -i s|#ForwardToSyslogyes|ForwardToSyslogno| /etc/systemd/journald.conf预留一个“安全网”SSH密钥在构建镜像时注入一个你控制的SSH公钥到root或某个救援用户。这样即使网络配置错误导致无法通过常规方式登录你仍然可以通过带外网络或直接连接的方式进入系统修复。先测试后部署务必在虚拟化环境如QEMU/KVM或一两台物理测试机上完整走通“构建-部署-升级-回滚”的整个流程确认所有环节符合预期后再推广到生产环境。可以使用qemu-system-x86_64命令直接启动构建出的.img文件进行测试。6. 与其他方案的对比与选型思考在考虑采用Kairos之前了解它在技术光谱中的位置至关重要。这里将其与几个常见方案进行对比。方案核心思想优点缺点适用场景Kairos声明式、不可变、Kubernetes原生的镜像构建与管理。1.与K8s/GitOps理念无缝集成用YAML管理一切。2.原子化升级与回滚系统可靠性高。3.脱离云厂商锁定可在任何地方运行。4. 社区活跃专注于边缘/K8s生态。1.学习曲线较陡需要理解其构建阶段和配置模型。2.生态相对年轻企业级支持和商业工具较少。3. 对传统应用强依赖可写系统目录改造难度大。1. 大规模、地理分散的Kubernetes边缘集群。2. 追求完全不可变基础设施和GitOps的团队。3. 需要统一管理混合云/裸金属K8s节点。Packer通用、可插拔的镜像构建工具通过Provisioner配置系统。1.极其成熟和稳定社区庞大文档丰富。2.支持几乎所有云平台和虚拟化后端AWS, GCP, Azure, VMware等。3. 丰富的ProvisionerShell, Ansible, Chef可选。1.配置偏向过程式脚本而非声明式。2.镜像生命周期管理较弱需要额外工具实现滚动更新。3. 与K8s生态集成不深需要自己拼接CI/CD。1. 需要为多个云平台构建相同镜像。2. 团队已熟悉Ansible等配置管理工具。3. 构建传统虚拟机镜像为主。OS镜像厂商标配(如RHEL Image Builder, Ubuntu Autoinstall)操作系统厂商提供的官方定制工具。1.官方支持与发行版结合最紧密稳定性最佳。2. 通常提供GUI工具上手简单。3. 对该发行版的特有功能支持最好。1.严重厂商锁定工具链无法用于其他发行版。2.输出格式和部署目标可能受限。3.云原生集成能力普遍偏弱。1. 深度绑定特定Linux发行版如RHEL, Ubuntu的企业环境。2. 对官方支持有强依赖的合规场景。手动制作Golden Image手动安装配置后使用工具如dd,virt-sysprep克隆镜像。1.绝对控制每一步都清晰可见。2.零工具依赖在简单场景下最快。1.完全不可重复是“雪花服务器”的根源。2.毫无版本控制无法追溯变更。3.效率极低无法规模化。仅适用于一次性、临时的测试环境绝对不应用于生产。选型思考 如果你的世界是围绕Kubernetes展开的尤其是涉及边缘计算、需要管理成百上千个异构节点、并且团队已经接受了声明式和GitOps文化那么Kairos带来的标准化、自动化和可靠性提升是巨大的值得投入学习成本。如果你的需求主要是为公有云制作通用的虚拟机镜像或者团队技能树更偏向传统的配置管理Ansible, SaltStack那么Packer可能是更稳妥、社区资源更丰富的选择。对于大型企业如果已经标准化了某个企业级Linux发行版优先考虑其官方镜像构建工具在合规和支持上会更省心。我个人在实际操作中的体会是Kairos这类工具代表了一种趋势基础设施的抽象层正在从“可变的服务器”上移到“不可变的、由代码定义的镜像”和“声明式的编排平台”。它可能不是最简单的起点但它引导你走向的是一个更健壮、更自动化、也更符合云原生哲学的未来。刚开始接触时确实需要花时间理解它的“阶段”stages模型和配置语法但一旦跑通第一个Pipeline看到代码变更自动触发集群底层镜像的滚动更新那种“一切皆代码一切皆自动”的顺畅感会让你觉得之前的投入都是值得的。最后再分享一个小技巧多看看项目examples/目录下的配置以及社区在GitHub Discussions里的分享这是快速掌握最佳实践的最短路径。

相关新闻