使用DockerFile构建Bare Metal镜像

2023年 8月 29日 108.0k 0

Mutable和Immutable介绍

云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。容器技术的最大创造就是通过Dockerfile将应用打包为容器镜像,实现了不可变基础设施,标准化了应用模板。
在容器之前叫Mutable(可变的基础设施)在OS上部署应用,重启生效,可以随时进行修改。
使用DockerFile构建Bare Metal镜像-1
容器技术就是Immutable的代表,引入容器镜像,通过Dockerfile将应用标准化打包为容器镜像,通过容器镜像启动容器,无法在容器中进行永久性修改,需要修改只能通过更新Dockerfile方式进行。
使用DockerFile构建Bare Metal镜像-1 现如今Immutable理念也开始逐步从容器下沉到Bare Metal OS,通过Dockerfile构建Bare Metal镜像,实现Bare Metal OS Immutable。典型的开源项目技术Elemental项目

Elemental概述

Elemental 是一系列工具集合,主要是想通过 Kubernetes 实现集中式、完整的云原生操作系统构建和管理。集群节点操作系统是通过Elemental CLI通过容器映像构建和维护的,并使用Elemental CLI安装在新主机上。
Elemental Operator和Rancher System Agent使Rancher Manager 能够完全控制 Elemental 集群,从在节点上安装和管理操作系统到以集中方式配置新的 K3s 或 RKE2 集群。 使用DockerFile构建Bare Metal镜像-1 Elemental项目组成

  • elemental-toolkit - 包括一组操作系统实用程序,可通过容器启用操作系统管理。包括 dracut 模块、引导加载程序配置、cloud-init 自定义配置服务等。
  • elemental-operator - 这连接到 Rancher Manager 并处理 machineRegistration 和 machineInventory CRD
  • elemental-register - 这通过 machineRegistrations 注册机器并通过 elemental-cli 安装
  • elemental-cli - 这会安装任何基于 elemental-toolkit 的衍生工具。实现OCI容器镜像构建为可在虚拟机、物理机、嵌入式设备运行的ISO镜像。
  • rancher-system-agent - 在已安装的系统上运行并从 Rancher Manager 获取命令在系统上安装和运行rancher-agent,注册到Rancher中。

项目地址:https://github.com/rancher/elemental-toolkit

配置使用

在一台装有Docker的主机上进行提前准备项:

  • 一台安装了Docker的主机
  • Harbor镜像仓库
  • EXSI或物理pc、服务器用于build后的ISO测试

使用Elemental-toolkit构建ISO流程

  • 基础base镜像发行版:
    teal: SLE Micro for Rancher based one, shipping packages from Sle Micro 5.3.
    green: openSUSE based one, shipping packages from OpenSUSE Leap 15.4 repositories.
    blue: Fedora based one, shipping packages from Fedora 33 repositories
    orange: Ubuntu based one, shipping packages form Ubuntu 20.10 repositories
  • 自定义镜像并制作OCI Image
  • 在装有Docker的机器启动Elemental Build
    UEFI Boot,选择合适的实例类型
    Clout-init userdata 初始化
    Default user/pass: root/cos
  • 升级自定义镜像
    elemental upgrade –no-verify –reboot -d niusmallnan/containeros\:dev

在安装了Docker的主机上创建/root/derivative目录。整体目录结构

/root/derivative/
├── Dockerfile
├── cloud-init.yaml
├── install.sh
├── installer.sh
├── k3s
├── k3s-airgap-images-amd64.tar.gz
├── manifest.yaml
├── nginx.yaml
├── overlay
│   └── iso
│       └── boot
│           └── grub2
│               └── grub.cfg
└── repositories.yaml

Demo架构 使用DockerFile构建Bare Metal镜像-1

  • 通过Elemental构建的OS中包含K3S
  • 将需要部署的应用yaml放置到 /var/lib/rancher/k3s/server/manifests目录,K3S启动成功后会自动部署yaml启动应用。

下载K3S离线镜像包和CLI文件
https://github.com/k3s-io/k3s/releasesnginx.yaml文件用于k3s启动后加载此yaml文件,模拟演示是个应用

123456789101112131415161718192021222324252627282930313233 apiVersion: apps/v1kind: Deploymentmetadata:name: nginx-deploymentspec:selector:matchLabels:app: nginxreplicas: 1template:metadata:labels:app: nginxspec:containers:- name: nginximage: wanshaoyuan/nginx:v1.0ports:- containerPort: 80
---apiVersion: v1kind: Servicemetadata:name: my-servicespec:type: NodePortselector:app: nginxports:- port: 80targetPort: 80nodePort: 30007

Dockerfile文件创建

ARG LUET_VERSION=0.32.0
FROM quay.io/luet/base:$LUET_VERSION AS luet
FROM registry.suse.com/suse/sle-micro-rancher/5.2
ARG ARCH=amd64
ENV ARCH=${ARCH}
# Copy the luet config file pointing to the upgrade repository
COPY repositories.yaml /etc/luet/luet.yaml
# Copy luet from the official images
COPY --from=luet /usr/bin/luet /usr/bin/luet
ENV LUET_NOLOCK=true
RUN luet install -y \
toolchain/yip \
toolchain/luet \
utils/installer \
system/cos-setup \
system/immutable-rootfs \
system/grub2-config \
system/base-dracut-modules
RUN  mkdir /var/lib/rancher/k3s/agent/images/ -p &&  mkdir /var/lib/rancher/k3s/server/manifests -p
COPY install.sh /system/oem/
COPY k3s /usr/local/bin
COPY nginx.yaml /system/oem/
COPY k3s-airgap-images-amd64.tar.gz /system/oem/
RUN  chmod a+x /usr/local/bin/k3s && chmod a+x /system/oem/install.sh
WORKDIR /system/oem
RUN  INSTALL_K3S_SKIP_START="true" INSTALL_K3S_SKIP_ENABLE="true" INSTALL_K3S_SKIP_DOWNLOAD="true" sh install.sh
## System layout
# Required by k3s etc.
RUN mkdir /usr/libexec && mkdir /usr/local/bin -p && touch /usr/libexec/.keep
# Copy custom files
# COPY files/ /
# Copy cloud-init default configuration
COPY cloud-init.yaml /system/oem/
# Generate initrd
RUN mkinitrd
# OS level configuration
RUN echo "VERSION=999" > /etc/os-release
RUN echo "GRUB_ENTRY_NAME=derivative" >> /etc/os-release
RUN echo "welcome to our derivative" >> /etc/issue.d/01-derivative

cloud-init文件创建,主要用于磁盘分区配置和登录用户名和密码配置
cloud-init.yaml

name: "Default settings"
stages:
initramfs:
# Setup default hostname
- name: "Branding"
hostname: "derivative"
# Setup an admin group with sudo access
- name: "Setup groups"
ensure_entities:
- entity: |
kind: "group"
group_name: "admin"
password: "x"
gid: 900            
# Setup network - openSUSE specific
- name: "Network setup"
files:
- path: /etc/sysconfig/network/ifcfg-eth0
content: |
BOOTPROTO='dhcp'
STARTMODE='onboot'                  
permissions: 0600
owner: 0
group: 0
# Setup a custom user
- name: "Setup users"
users:
# Replace the default user name here and settings
joe:
# Comment passwd for no password
passwd: "joe"
shell: /bin/bash
homedir: "/home/joe"
groups:
- "admin"
#authorized_keys:
# Replace here with your ssh keys
# joe: 
# - ssh-rsa ....
# Setup sudo
- name: "Setup sudo"
files:
- path: "/etc/sudoers"
owner: 0
group: 0
permsisions: 0600
content: |
Defaults always_set_home
Defaults secure_path="/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/bin:/usr/local/sbin"
Defaults env_reset
Defaults env_keep = "LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_ATIME LC_ALL LANGUAGE LINGUAS XDG_SESSION_COOKIE"
Defaults !insults
root ALL=(ALL) ALL
%admin ALL=(ALL) NOPASSWD: ALL
@includedir /etc/sudoers.d            
commands:
- passwd -l root
# Setup persistency so k3s works properly
# See also: https://rancher.github.io/elemental-toolkit/docs/reference/immutable_rootfs/#configuration-with-an-environment-file
rootfs.after:
- name: "Immutable Layout configuration"
environment_file: /run/cos/cos-layout.env
environment:
VOLUMES: "LABEL=COS_OEM:/oem LABEL=COS_PERSISTENT:/var"
OVERLAY: "tmpfs:25%"
RW_PATHS: "/usr/local /etc /srv"
PERSISTENT_STATE_PATHS: >-
/etc/systemd
/etc/rancher
/etc/ssh
/etc/iscsi 
/etc/cni
/home
/opt
/root
/usr/libexec
/var/log
/var/lib/wicked
/var/lib/longhorn
/var/lib/cni
/usr/local/bin
PERSISTENT_STATE_TARGET: >-
/etc/systemd
/etc/rancher
/etc/ssh
/etc/iscsi
/etc/cni
/home
/opt
/root
/usr/libexec
/var/log
/var/lib/kubelet
/var/lib/wicked
/var/lib/longhorn
/var/lib/cni
/usr/local/bin
PERSISTENT_STATE_BIND: "true"
# Finally, let's start k3s when network is available, and download the SSH key from github for the joe user
network:
- name: "Deploy cos-system"
commands:
- elemental install /dev/sda 
- systemctl enable k3s && systemctl start  k3s
after-install:
- name: "install k3s"
commands:
- mount /dev/sda5 /var
- mkdir -p  /var/lib/rancher/k3s/agent/images/  && mkdir /var/lib/rancher/k3s/server/manifests -p
- cp /system/oem/k3s-airgap-images-amd64.tar.gz  /var/lib/rancher/k3s/agent/images/
- cp /system/oem/nginx.yaml /var/lib/rancher/k3s/server/manifests
- reboot

创建manifest.yaml文件定义OS启动引导所需要文件

iso:
rootfs:
- channel:system/cos
uefi:
- channel:live/grub2-efi-image
image:
- channel:live/grub2
- channel:live/grub2-efi-image
label: "COS_LIVE"
name: "cOS-0"
# Raw disk creation values start
raw_disk:
x86_64:
# which packages to install and the target to install them at
packages:
- name: channel:system/grub2-efi-image
target: efi
- name: channel:system/grub2-config
target: root
- name: channel:system/grub2-artifacts
target: root/grub2
- name: channel:recovery/cos-img
target: root/cOS
repositories:
- uri: quay.io/costoolkit/releases-teal
arch: "x86_64"

创建repositories.yaml文件

logging:
color: false
enable_emoji: false
general:
debug: false
spinner_charset: 9
repositories:
- name: "cos"
description: "cOS official"
type: "docker"
enable: true
cached: true
priority: 1
verify: false
urls:
- "quay.io/costoolkit/releases-green"

创建grub文件配置内核引导
在/root/derivative/overlay/iso/boot/目录创建grub2grub.cfg文件

search --no-floppy --file --set=root /boot/kernel
set default=0
set timeout=10
set timeout_style=menu
set linux=linux
set initrd=initrd
if [ "${grub_cpu}" = "x86_64" -o "${grub_cpu}" = "i386" -o "${grub_cpu}" = "arm64" ];then
if [ "${grub_platform}" = "efi" ]; then
if [ "${grub_cpu}" != "arm64" ]; then
set linux=linuxefi
set initrd=initrdefi
fi
fi
fi
if [ "${grub_platform}" = "efi" ]; then
echo "Please press 't' to show the boot menu on this console"
fi
set font=($root)/boot/${grub_cpu}/loader/grub2/fonts/unicode.pf2
if [ -f ${font} ];then
loadfont ${font}
fi
menuentry "cOS" --class os --unrestricted {
echo Loading kernel...
$linux ($root)/boot/kernel.xz cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs console=tty1 console=ttyS0 rd.cos.disable
echo Loading initrd...
$initrd ($root)/boot/rootfs.xz
}
if [ "${grub_platform}" = "efi" ]; then
hiddenentry "Text mode" --hotkey "t" {
set textmode=true
terminal_output console
}
fi

先构建镜像

docker build -t 172.16.1.208/library/example:v4.0 .

镜像要上传到镜像仓库才能build iso

docker push 172.16.1.208/library/example:v4.0

构建ISO

1 docker run --rm -ti -v $(pwd):/build quay.io/costoolkit/elemental-cli:v0.0.15-ae4f000 --config-dir /build --overlay-iso /build/overlay/iso --debug build-iso -o /build 172.16.1.208/library/example:v4.0

注:目前只支持公开的镜像仓库,不支持私有的镜像仓库
https://github.com/rancher/elemental-cli/issues/389构建完成,生成此cOS-0.iso镜像文件

123456789101112131415 o250800372/iso / -chmod 0755 -- -boot_image grub bin_path=/boot/x86_64/loader/eltorito.img -boot_image grub grub2_mbr=/tmp/elemental-iso250800372/iso//boot/x86_64/loader/boot_hybrid.img -boot_image grub grub2_boot_info=on -boot_image any partition_offset=16 -boot_image any cat_path=/boot/x86_64/boot.catalog -boot_image any cat_hidden=on -boot_image any boot_info_table=on -boot_image any platform_id=0x00 -boot_image any emul_type=no_emulation -boot_image any load_size=2048 -append_partition 2 0xef /tmp/elemental-iso250800372/iso/boot/uefi.img -boot_image any next -boot_image any efi_path=--interval:appended_partition_2:all:: -boot_image any platform_id=0xef -boot_image any emul_type=no_emulation'DEBU[2023-03-12T11:54:38Z] Xorriso: xorriso 1.4.6 : RockRidge filesystem manipulator, libburnia project.
Drive current: -outdev '/build/cOS-0.iso'Media current: stdio file, overwriteableMedia status : is blankMedia summary: 0 sessions, 0 data blocks, 0 data, 5851m freexorriso : UPDATE : 623 files added in 1 secondsAdded to ISO image: directory '/'='/tmp/elemental-iso250800372/iso'xorriso : NOTE : Copying to System Area: 512 bytes from file '/tmp/elemental-iso250800372/iso/boot/x86_64/loader/boot_hybrid.img'xorriso : UPDATE : Writing: 24576s 6.5% fifo 100% buf 50%xorriso : UPDATE : Writing: 221184s 58.1% fifo 100% buf 50% 415.0xDISO image produced: 380645 sectorsWritten to medium : 380656 sectors at LBA 48Writing to '/build/cOS-0.iso' completed successfully.

将cOS-0.iso下载到ESXI或其他虚拟化平台也可以刻录U盘直接安装物理机。配置选4c4G 60G磁盘 使用DockerFile构建Bare Metal镜像-1
加载ISO后自动分区,自动进行初始化,安装系统,完成后自动重启进入系统。密码ssh账号密码joe/joe 使用DockerFile构建Bare Metal镜像-1
在安装后的系统查看已经部署好的K3S。 使用DockerFile构建Bare Metal镜像-1 查看自动部署的应用 使用DockerFile构建Bare Metal镜像-1
访问应用因为整个系统都限制了修改,所以在操作系统任何目录执行修改命令都无法修改。如

123456789 rm -rf *
evice or resource busyrm: cannot remove 'var/lib/kubelet/pods/cbf59b3a-d29a-4129-a3c9-8b79b1235104/volumes/kubernetes.io~projected/kube-api-access-zf8c5': Device or resource busyrm: cannot remove 'var/lib/kubelet/pods/ea697a4c-8cb8-425f-8e50-6396f5669167/volumes/kubernetes.io~projected/kube-api-access-bq66h': Device or resource busyrm: cannot remove 'var/lib/kubelet/pods/f18cd482-4c6f-4dd0-80fa-5fc314d3cc5b/volumes/kubernetes.io~projected/kube-api-access-8fdq7': Device or resource busyrm: cannot remove 'var/lib/longhorn': Device or resource busyrm: cannot remove 'var/lib/wicked': Device or resource busyrm: cannot remove 'var/log': Device or resource busy
12 touch 1touch: cannot touch '1': Read-only file system

总结

通过Elemental实现了操作系统为不变基础设施,同时也可以将我们传统的OS带入云原生,通过Dockerfile去构建,通过CICD去统一发版维护,目前能想到的一个比较大的应用场景在于,一个是边缘场景,边缘设备操作系统批量部署安装。另外就是一些to b的客户将自己业务+容器编排和OS通过Elemental构建打包,直接到客户现场加载ISO就部署完了,开箱即用。另外OS也可以标准化,统一化管理。

相关文章

KubeSphere 部署向量数据库 Milvus 实战指南
探索 Kubernetes 持久化存储之 Longhorn 初窥门径
征服 Docker 镜像访问限制!KubeSphere v3.4.1 成功部署全攻略
那些年在 Terraform 上吃到的糖和踩过的坑
无需 Kubernetes 测试 Kubernetes 网络实现
Kubernetes v1.31 中的移除和主要变更

发布评论