wheelnext 包的构建原理、结构分析与安装流程
简介随着异构算力与多样化运行环境的普及，同一 Python 发行包在不同硬件、驱动与系统组合上的适配差异日益显著。传统“单一 wheel 适配全部环境”的分发模型通常面临两类问题：一是依赖运行时探测与兼容分支，导致部署链路复杂、行为不确定性上升；二是通过拆分多发行包实现适配，带来命名体系扩张、发布流程冗余与运维成本增加。wheelnext 引入的 Variant 机制，目标是在不破坏既有包名与版本语义的前提下，为同一版本提供可按平台能力精确匹配的 wheel 变体在该体系中，variantlib 与 uv-wheelnext 分别承担构建侧与安装侧职责。variantlib 负责对基础 wheel 注入变体元数据、生成带变体标识的产物，并输出用于分发侧索引的 variants.json；uv-wheelnext 负责在安装阶段解析变体索引、加载 provider 插件获取环境能力、执行候选变体过滤与排序，并确定最终安装目标。两者协同后，可形成“发布阶段声明差异、安装阶段自动匹配”的闭环流程本文以 vllm_ascend 为案例，围绕变体包生命周期展开分析：首先说明如何使用 variantlib 构建变体包；其次通过拆包比对定位原始包与变体包的结构差异及其来源；最后结合实际安装日志，复盘 uv-wheelnext 的识别、匹配与选择过程，建立从构建到安装的端到端技术认知1 使用 variantlib 生成变体包本章以原始包 vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64.whl 为例，详述如何通过注入变体信息 ascend :: npu_type :: a2 生成变体包 vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64-a2.whl，以便更好理解变体包内部结构的变化及产生变化的内容来源1.1 安装 uv-wheelnext参考文档：An experimental, variant-enabled build of uv# 执行以下命令安装 $ curl -LsSf https://astral.sh/uv/install.sh | INSTALLER_DOWNLOAD_URL=https://wheelnext.astral.sh sh # 执行以下命令刷新 PATH 环境变量 $ source $HOME/.local/bin/env # 查看版本号，可以发现命令仍为 uv，但版本已经带有 uv-wheelnext $ uv --version uv-wheelnext 0.8.41.2 安装 variantlib 工具# 克隆 variantlib 源代码 $ git clone https://github.com/wheelnext/variantlib.git # 进入克隆的 variantlib 源代码目录 $ cd variantlib # 创建虚拟环境 $ uv venv # 安装 variantlib $ uv pip install --system . # 查看版本号，确认安装是否成功 $ variantlib --version variantlib version: 0.0.31.3 生成变体包1.3.1 准备 pyproject.toml 文件编写 pyproject.toml 文件（必须）：[variant.default-priorities] namespace = ["ascend"] [variant.providers.ascend] enable-if = "platform_system == 'Linux'" plugin-api = "huawei_ascend_variant_provider.plugin:AscendVariantPlugin" requires = ["huawei-ascend-variant-provider>=0.0.1,<1.0.0"]关于 pyproject.toml 文件，有以下几点注意：文件名称可以随意命名，不必须为 pyproject.tomlvariantlib 在注入变体信息过程中，只是读取 pyproject.toml，并不会对其修改该 pyproject.toml 文件与 vllm_ascend 项目本身的 pyproject.toml 并无关联，因此有两种用法：新建 pyproject.toml（可任意命名），只需写入以上的 variant 信息即可在 vllm_ascend 项目原有的 pyproject.toml 中追加 variant 信息1.3.2 生成变体包执行以下命令，注入变体信息，生成变体包：$ variantlib make-variant \ -f vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64.whl \ -o ./ \ --pyproject-toml pyproject.toml \ --property "ascend :: npu_type :: a2" \ --variant-label a2 \ --skip-plugin-validationvariantlib make-variant 命令相关选项及作用如下：命令选项作用-f指定基础 wheel 包-o指定输出变体包的位置--pyproject-toml指定包含 variant 信息的 pyproject.toml--property指定变体特征--variant-label指定变体包的变体后缀，如 -a2、-a3--skip-plugin-validation跳过使用 provider 校验执行以下命令，校验变体包属性：$ variantlib analyze-wheel \ -i vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64-a2.whl variantlib.commands.analyze_wheel - INFO - Filepath: `vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64-a2.whl` ... is a Wheel Variant - Label: `a2` ############################## Variant: `38edb458` ############################# ascend :: npu_type :: a2 ################################################################################执行以下命令，为指定目录下的所有变体包生成索引文件：$ variantlib generate-index-json -d ./2 原始包与变体包的结构分析根据第 1 章的操作，成功构建出变体包 vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64-a2.whl，以下将通过拆包对比的方法，分析注入变体信息过程中，产生了哪些变化以及变化的来源2.1 原始包与变体包名称差异原始包名称：vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64.whl变体包名称：vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64-a2.whl对比这两个包的名称可以发现，变体包多了一个变体后缀 -a2。关于变体后缀，参考以下说明：来源： 有以下两种来源（参考代码：variantlib/api.py:347-364）由 variantlib make-variant 命令的 --variant-label 选项指定若没有指定，则根据变体属性计算 SHA256 取前 8 位作为 label作用： 用于判断指定的包是否为变体包（参考代码：variantlib/commands/analyze_wheel.py:54-64）若变体后缀存在，则认为该包为变体包若变体后缀不存在，则认为该包为普通包2.2 原始包与变体包结构差异使用 unzip 命令分别解压原始包与变体包，查看其结构差异原始包的结构如下：. ├── vllm_ascend │ ├── ascend_config.py │ ├── ...... │ └── xlite └── vllm_ascend-0.13.0rc1.dist-info ├── entry_points.txt ├── LICENSE ├── METADATA ├── RECORD ├── top_level.txt └── WHEEL 20 directories, 20 files变体包的结构如下：. ├── vllm_ascend │ ├── ascend_config.py │ ├── ...... │ └── xlite └── vllm_ascend-0.13.0rc1.dist-info ├── entry_points.txt ├── LICENSE ├── METADATA ├── RECORD ├── top_level.txt ├── variant.json └── WHEEL 20 directories, 21 files对比原始包与变体包结构发现，在变体包的 .dist-info 目录下多出一个 variant.json 文件。关于该文件，有以下信息（参考代码：variantlib/commands/make_variant.py:241-287）：该文件在注入变体信息，构建变体包时产生与其他文件相同，该文件的 SHA256 值同样会被记录到 .dist-info/RECORD 文件中：vllm_ascend-0.13.0rc1.dist-info/variant.json,sha256=3LE9xShDUHoYkI1LktyD3Dq4n0JJLM5U_DSM_DQajrg,624除该文件及 .dist-info/RECORD 文件之外，其他文件完全不变该文件的内容来源参考以下 2.3 节2.3 variant.json 文件内容的来源查看 variant.json 文件内容：{ "$schema": "https://variants-schema.wheelnext.dev/v0.0.3.json", "default-priorities": { "namespace": [ "ascend" ] }, "providers": { "ascend": { "enable-if": "platform_system == 'Linux'", "plugin-api": "huawei_ascend_variant_provider.plugin:AscendVariantPlugin", "requires": [ "huawei-ascend-variant-provider>=0.0.1,<1.0.0" ] } }, "variants": { "a2": { "ascend": { "npu_type": [ "a2" ] } } } }该文件的内容来源及作用如下（参考代码：variantlib/api.py:173-272）：$schema：来源：硬编码常量 VARIANTS_JSON_SCHEMA_URL作用：标明该 variant.json 文件遵循的是 wheelnext 变体规范的 v0.0.3 版本，便于工具（如 uv-wheelnext）根据版本号正确解析支持 JSON Schema 的编辑器或工具可以据此自动校验 variant.json 的结构是否合法default-priorities：来源：variantlib make-variant 命令 --pyproject-toml 选项指定的 pyproject.toml 文件。若该文件没有包含 [variant.*] 配置信息，则字段值为空作用（参考代码：variantlib/resolver/sorting.py）：控制变体候选的排序优先级，列表中靠前的 namespace 优先级更高安装时，包管理器通过 provider 插件获取当前平台支持的属性后，用此优先级对可用变体排序，选出最佳匹配providers：来源：与 default-priorities 相同作用： 定义如何加载和调用 provider 插件来获取当前平台的变体属性（参考代码：variantlib/plugins/loader.py）enable-if：环境标记表达式，安装时评估此条件决定是否加载该插件plugin-api：插件的导入路径（如 module:ClassName），用于动态加载插件实例requires：该插件的依赖包列表，安装时需要先确保这些依赖可用variants：来源：key： 与变体包的变体后缀一致，参考 2.1 原始包与变体包名称差异value： 按 namespace → feature → [values] 嵌套的属性字典，由 variantlib make-variant 命令的 --property 选项指定作用：声明该包所有已构建的变体组合及其属性值（参考代码：variantlib/resolver/filtering.py）安装时，将每个变体的属性与当前平台（通过 provider 插件查询到的）支持的属性做匹配过滤多个属性间是 AND 关系（必须全部满足），单个属性的多个 value 间是 OR 关系（满足任一即可）过滤后的变体再按 default-priorities 排序，选出最优变体安装3 uv-wheelnext 如何识别安装变体包在 a3 服务器上执行以下命令安装变体包 vllm-ascend，查看其输出日志，以分析安装流程：$ uv pip install -v --prerelease=allow \ --extra-index-url https://mirrors.huaweicloud.com/ascend/repos/pypi/variant \ vllm-ascend安装过程打印如下：# ==================== 阶段一：环境探测 ==================== DEBUG uv 0.8.4 DEBUG Searching for default Python interpreter in virtual environments DEBUG Found `cpython-3.11.14-linux-aarch64-gnu` at `/root/yzc/wheel/bin/python3` (active virtual environment) Using Python 3.11.14 environment at: wheel DEBUG Acquired lock for `wheel` DEBUG At least one requirement is not satisfied: vllm-ascend DEBUG Using request timeout of 30s DEBUG Solving with installed Python version: 3.11.14 DEBUG Solving with target Python version: >=3.11.14 DEBUG Adding direct dependency: vllm-ascend* # ==================== 阶段二：索引发现 ==================== DEBUG No cache entry for: https://mirrors.huaweicloud.com/ascend/repos/pypi/variant/vllm-ascend/ WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: register.html DEBUG Searching for a compatible version of vllm-ascend (*) # ==================== 阶段三：变体索引获取 ==================== DEBUG No cache entry for: https://mirrors.huaweicloud.com/ascend/repos/pypi/variant/vllm-ascend/vllm_ascend-0.17.0rc1-cp311-cp311-manylinux_2_24_aarch64.whl DEBUG No cache entry for: https://mirrors.huaweicloud.com/ascend/repos/pypi/variant/vllm-ascend/vllm_ascend-0.17.0rc1-variants.json # ==================== 阶段四：Provider 插件查询 ==================== DEBUG Querying provider `ascend` for variants DEBUG Using base executable for virtual environment: /usr/local/python3.11.14/bin/python3.11 DEBUG Solving with installed Python version: 3.11.14 DEBUG Solving with target Python version: >=3.11.14 DEBUG Adding direct dependency: huawei-ascend-variant-provider>=0.0.2, <1.0.0 DEBUG No cache entry for: https://mirrors.huaweicloud.com/ascend/repos/pypi/variant/huawei-ascend-variant-provider/ DEBUG Searching for a compatible version of huawei-ascend-variant-provider (>=0.0.2, <1.0.0) DEBUG Selecting: huawei-ascend-variant-provider==0.0.2 [compatible] (huawei_ascend_variant_provider-0.0.2-py3-none-any.whl) DEBUG No cache entry for: https://mirrors.huaweicloud.com/ascend/repos/pypi/variant/huawei-ascend-variant-provider/huawei_ascend_variant_provider-0.0.2-py3-none-any.whl DEBUG Tried 1 versions: huawei-ascend-variant-provider 1 DEBUG marker environment resolution took 0.193s DEBUG Installing in huawei-ascend-variant-provider==0.0.2 in /root/.cache/uv/wheelnext-builds-v0/.tmpuuXXg1 DEBUG Identified uncached distribution: huawei-ascend-variant-provider==0.0.2 (huawei_ascend_variant_provider-0.0.2-py3-none-any.whl) DEBUG Downloading and building requirement for build: huawei-ascend-variant-provider==0.0.2 DEBUG No cache entry for: https://mirrors.huaweicloud.com/ascend/repos/pypi/variant/huawei-ascend-variant-provider/huawei_ascend_variant_provider-0.0.2-py3-none-any.whl DEBUG Installing build requirement: huawei-ascend-variant-provider==0.0.2 # ==================== 阶段五：变体选择与安装 ==================== DEBUG Using variant wheel vllm_ascend-0.17.0rc1-cp311-cp311-manylinux_2_24_aarch64-a3.whl DEBUG Selecting: vllm-ascend==0.17.0rc1 [compatible] (vllm_ascend-0.17.0rc1-cp311-cp311-manylinux_2_24_aarch64-a3.whl) DEBUG Adding transitive dependency for vllm-ascend==0.17.0rc1: cmake>=3.26 DEBUG Adding transitive dependency for vllm-ascend==0.17.0rc1: decorator* ......根据以上安装日志，uv-wheelnext 识别并安装变体包的完整流程可分为五个阶段3.1 环境探测DEBUG Searching for default Python interpreter in virtual environments DEBUG Found `cpython-3.11.14-linux-aarch64-gnu` at `/root/yzc/wheel/bin/python3` DEBUG Solving with installed Python version: 3.11.14uv-wheelnext 首先探测当前 Python 环境：确定解释器版本（3.11.14）确定平台架构（linux-aarch64）确定 ABI 标签（cp311）这些信息将作为后续 wheel 兼容性过滤的基础条件3.2 索引发现DEBUG No cache entry for: .../vllm-ascend/ DEBUG Searching for a compatible version of vllm-ascend (*)uv-wheelnext 向 --extra-index-url 指定的变体索引源发起请求，获取 vllm-ascend 的可用版本列表此阶段与标准 pip 安装一致，遍历索引页面中的所有文件链接，跳过不兼容的文件（如 HTML 页面、不匹配的平台标签等）3.3 变体索引获取DEBUG No cache entry for: .../vllm_ascend-0.17.0rc1-cp311-cp311-manylinux_2_24_aarch64.whl DEBUG No cache entry for: .../vllm_ascend-0.17.0rc1-variants.json这是 uv-wheelnext 区别于标准 uv 的核心步骤。在找到兼容的 wheel 文件后，uv-wheelnext 会额外请求同目录下的 {name}-{version}-variants.json 文件。该文件由 variantlib generate-index-json 命令预先生成，其内容与结构如见 2.3 variant.json 文件内容的来源variants.json 是变体包的索引文件，它声明了该版本所有可用的变体标签及其属性，以及对应的 provider 插件信息。uv-wheelnext 正是通过该文件发现"此包存在变体"，从而进入变体解析流程。3.4 Provider 插件查询DEBUG Querying provider `ascend` for variants DEBUG Adding direct dependency: huawei-ascend-variant-provider>=0.0.2, <1.0.0 DEBUG Installing build requirement: huawei-ascend-variant-provider==0.0.2uv-wheelnext 从 variants.json 的 providers 字段中读取 provider 插件信息，执行以下操作：解析 requires 字段，将 huawei-ascend-variant-provider>=0.0.2,<1.0.0 作为临时依赖进行解析和安装将 provider 插件安装到隔离的临时环境 /root/.cache/uv/wheelnext-builds-v0/.tmpuuXXg1，避免污染用户环境通过 plugin-api 字段指定的入口点（huawei_ascend_variant_provider.plugin:AscendVariantPlugin）加载插件实例调用插件的 get_supported_configs() 方法，查询当前平台支持的变体属性（参考代码：variantlib/api.py:68-78）例如在昇腾 a3 设备上，provider 插件会返回 ascend :: npu_type :: a3，表示当前平台支持该变体属性3.5 变体匹配、排序与选择DEBUG Using variant wheel vllm_ascend-0.17.0rc1-cp311-cp311-manylinux_2_24_aarch64-a3.whl DEBUG Selecting: vllm-ascend==0.17.0rc1 [compatible]获取到平台支持的变体属性后，uv-wheelnext 将完成最终选择，具体步骤如下：过滤（filter_variants）：遍历 variants.json 中声明的所有变体，将每个变体的属性与平台支持的属性进行匹配。多个属性间为 AND 关系（必须全部满足），单个属性的多个 value 间为 OR 关系（满足任一即可）。不兼容的变体被淘汰注入 Null Variant：始终将空属性的 null variant 加入候选列表作为兜底，确保即使没有匹配的变体，也能回退到基础包排序（sort_variants_descriptions）：根据 default-priorities 中定义的 namespace、feature、property 优先级，对通过过滤的变体进行排序，优先级高的排在前面选择：取排序后的第一个变体作为最优匹配。本例中，变体 a3（属性 ascend :: npu_type :: a3）与当前平台完全匹配，因此 uv-wheelnext 最终选择安装 vllm_ascend-0.17.0rc1-cp311-cp311-manylinux_2_24_aarch64-a3.whl
1 问题现状在讨论问题之前，先假设这样的场景：某服务器管理员忘记了 root 用户的密码，不能登录服务器，此时需要进行怎样的操作来重置 root 用户的密码呢？一般的操作流程如下：重启服务器进入 grub2 界面（选择内核的界面）按 “e” 进入 grub2 配置界面，找到 linux 开头的行，将该行中的 ro 修改为 rw，并在该行的末尾加上 init=/bin/sh使用组合键 “ctrl+x” 进入单用户模式，获得 shell 操作界面，执行 passwd root 命令为 root 用户设置密码若 SELinux 为 Enforcing 状态，则还需要执行 touch /.autorelabel 命令以使系统重新打标签退出单用户，重启服务器，使用新的 root 用户密码登录系统从以上处理流程可以看到，即使在不知道服务器 root 用户密码的情况下，只要能接触到物理服务器，也能通过一系列操作进入系统。因此，出于安全考虑，对 grub2 加密是有必要的。以下内容摘自官方文档：GRUB (GRand UnifiedBootloader) 是操作系统启动管理器，用来引导不同系统（如Windows、Linux）。GRUB2 是 GRUB 的升级版。系统启动时，可以通过 GRUB2 界面修改启动参数。为了确保系统的启动参数不被任意修改，需要对 GRUB2 界面进行加密，仅在输入正确的 GRUB2 口令时才能修改openEuler 操作系统默认为 grub2 进行了加密并设置了密码，登录 grub2 的用户名为 root，登陆密码为 openEuler#12。官方文档也进行了说明，详见：帐号清单虽然对 grub2 设置密码比较安全，但是机房重地，并非人人都能接触到物理服务器。因此在某些场景下为 grub2 加密反而使操作变得繁琐，在实际生产中，也遇到很多想要取消 grub2 加密的需求，以下就该问题提出完整的解决方案2 如何取消 grub2 加密2.1 临时方案直接修改 /boot/efi/EFI/openEuler/grub.cfg 或 /boot/grub2/grub.cfg 文件，当然也可以修改 /etc/grub2-efi.cfg 文件（与前述文件是软链接关系），将如下代码删除：set superusers=root password_pbkdf2 root grub.pbkdf2.sha512.10000.5A45748D892672FDA02DD3B6F7AE390AC6E6D532A600D4AC477D25C7D087644697D8A0894DFED9D86DC2A27F4E01D925C46417A225FC099C12DBD3D7D49A7425.2BD2F5BF4907DCC389CC5D165DB85CC3E2C94C8F9A30B01DACAA9CD552B731BA1DD3B7CC2C765704D55B8CD962D2AEF19A753CBE9B8464E2B1EB39A3BB4EAB08删除上述代码后，再次重启系统进入 grub2 就不再需要输入密码。然而作为临时方案，这种操作是不能永久生效的当执行了 grub2-mkconfig -o /path/to/grub.cfg 命令或执行了能触发该命令的操作时，都会重新生成 grub.cfg 文件，使得被删除的代码又重新写入2.2 永久方案只要删除 /etc/grub.d/00_header 文件末尾 cat <<EOF ... EOF 部分的代码，即可实现永久取消 grub2 加密在临时方案中修改 grub.cfg 文件时，注意到删除的代码位于以下两行注释中：### BEGIN /etc/grub.d/00_header ### ...... set superusers=root password_pbkdf2 root grub.pbkdf2.sha512.10000.5A45748D892672FDA02DD3B6F7AE390AC6E6D532A600D4AC477D25C7D087644697D8A0894DFED9D86DC2A27F4E01D925C46417A225FC099C12DBD3D7D49A7425.2BD2F5BF4907DCC389CC5D165DB85CC3E2C94C8F9A30B01DACAA9CD552B731BA1DD3B7CC2C765704D55B8CD962D2AEF19A753CBE9B8464E2B1EB39A3BB4EAB08 ### END /etc/grub.d/00_header ###可见这两行用于加密的代码来自于 /etc/grub.d/00_header 文件，那么接下来修改这个文件。该文件末尾有以下代码，表示在生成 grub.cfg 文件时，通过 cat <<EOF ... EOF 命令将加密的代码写入 grub.cfg 文件：cat <<EOF set superusers=root password_pbkdf2 root grub.pbkdf2.sha512.10000.5A45748D892672FDA02DD3B6F7AE390AC6E6D532A600D4AC477D25C7D087644697D8A0894DFED9D86DC2A27F4E01D925C46417A225FC099C12DBD3D7D49A7425.2BD2F5BF4907DCC389CC5D165DB85CC3E2C94C8F9A30B01DACAA9CD552B731BA1DD3B7CC2C765704D55B8CD962D2AEF19A753CBE9B8464E2B1EB39A3BB4EAB08 EOF因此只要删除 /etc/grub.d/00_header 文件末尾 cat <<EOF ... EOF 部分的代码，即可实现永久取消 grub2 加密2.3 彻底解决方案删除 /usr/sbin/security-tool.sh 文件第 948 行的代码删除的代码内容如下：echo -e "cat <<EOF\nset superusers="root"\npassword_pbkdf2 root grub.pbkdf2.sha512.10000.5A45748D892672FDA02DD3B6F7AE390AC6E6D532A600D4AC477D25C7D087644697D8A0894DFED9D86DC2A27F4E01D925C46417A225FC099C12DBD3D7D49A7425.2BD2F5BF4907DCC389CC5D165DB85CC3E2C94C8F9A30B01DACAA9CD552B731BA1DD3B7CC2C765704D55B8CD962D2AEF19A753CBE9B8464E2B1EB39A3BB4EAB08\nEOF\n" >> /etc/grub.d/00_header在永久解决方案中，/etc/grub.d/00_header 文件末尾 cat <<EOF ... EOF 部分的代码也不是凭空产生的，而是由 /usr/sbin/security-tool.sh 这个文件的第 948 行代码写入的，因此只要将其删除，即可从源头上取消 grub2 加密3 总结grub2 加密的流程为：先通过 /usr/sbin/security-tool.sh 文件第 948 行的代码将加密指令写入 /etc/grub.d/00_header 文件末尾再通过/etc/grub.d/00_header 文件末尾的加密指令，将加密内容写入 grub.cfg 文件系统启动时读取 grub.cfg 文件的加密内容从而对 grub2 加密在了解 grub2 加密的流程后，就可以在每个阶段进行操作，从而达到彻底取消、永久取消、临时取消 grub2 加密的目的
openEuler-20.03-LTSx86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS/EPOL/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/EPOL/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS/EPOL/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/EPOL/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/update/aarch64/ enabled=1 gpgcheck=0openEuler-20.03-LTS-SP1x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP1/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP1/EPOL/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP1/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP1/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP1/EPOL/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP1/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP1/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP1/EPOL/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP1/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP1/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP1/EPOL/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP1/update/aarch64/ enabled=1 gpgcheck=0openEuler-20.03-LTS-SP2x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP2/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP2/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP2/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP2/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP2/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP2/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP2/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP2/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP2/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP2/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP2/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP2/update/aarch64/ enabled=1 gpgcheck=0openEuler-20.03-LTS-SP3x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP3/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP3/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP3/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP3/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP3/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP3/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP3/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP3/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP3/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP3/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP3/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP3/update/aarch64/ enabled=1 gpgcheck=0openEuler-20.03-LTS-SP4x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP4/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP4/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP4/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP4/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP4/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP4/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP4/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP4/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP4/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP4/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP4/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP4/update/aarch64/ enabled=1 gpgcheck=0openEuler-22.03-LTSx86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/update/aarch64/ enabled=1 gpgcheck=0openEuler-22.03-LTS-SP1x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP1/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP1/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP1/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP1/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP1/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP1/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP1/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP1/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP1/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP1/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP1/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP1/update/aarch64/ enabled=1 gpgcheck=0openEuler-22.03-LTS-SP2x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP2/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP2/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP2/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP2/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP2/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP2/update/aarch64/ enabled=1 gpgcheck=0openEuler-22.03-LTS-SP3x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP3/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP3/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP3/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP3/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP3/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP3/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP3/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP3/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP3/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP3/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP3/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP3/update/aarch64/ enabled=1 gpgcheck=0openEuler-22.03-LTS-SP4x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP4/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP4/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP4/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP4/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP4/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP4/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/update/aarch64/ enabled=1 gpgcheck=0openEuler-24.03-LTSx86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS/update/aarch64/ enabled=1 gpgcheck=0openEuler-24.03-LTS-SP1x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP1/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP1/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP1/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP1/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP1/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP1/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP1/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP1/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP1/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP1/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP1/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP1/update/aarch64/ enabled=1 gpgcheck=0openEuler-24.03-LTS-SP2x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP2/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP2/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP2/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP2/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP2/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP2/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP2/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP2/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP2/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP2/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP2/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP2/update/aarch64/ enabled=1 gpgcheck=0openEuler-24.03-LTS-SP3x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP3/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP3/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP3/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP3/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP3/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP3/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP3/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP3/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP3/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP3/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP3/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP3/update/aarch64/ enabled=1 gpgcheck=0
1 配置全局代理1.1 Shell配置代理PROXY_IP=192.168.230.1 PROXY_PORT=10808 export http_proxy=http://${PROXY_IP}:${PROXY_PORT} export https_proxy=http://${PROXY_IP}:${PROXY_PORT} export ALL_PROXY=http://${PROXY_IP}:${PROXY_PORT} export all_proxy=http://${PROXY_IP}:${PROXY_PORT}取消代理unset http_proxy https_proxy ALL_PROXY all_proxy1.2 PowerShell配置代理$env:HTTP_PROXY = "http://127.0.0.1:10808" $env:HTTPS_PROXY = "http://127.0.0.1:10808"取消代理$env:HTTP_PROXY = $null $env:HTTPS_PROXY = $null2 系统环境配置2.1 修改 repo 源2.1 将官方源修改为华为源\cp -a /etc/yum.repos.d/openEuler.repo /etc/yum.repos.d/openEuler.repo.origin sed -i \ -e '/^metalink/ s/^\(.*\)$/#\1/g' \ -e 's/repo.openeuler.org/repo.huaweicloud.com\/openeuler/g' \ /etc/yum.repos.d/openEuler.repo dnf clean all && dnf makecache2.2 将华为源修改为官方源\cp -a /etc/yum.repos.d/openEuler.repo /etc/yum.repos.d/openEuler.repo.hauwei sed -i \ -e '/^meta/ s/^\(.*\)$/#\1/g' \ -e 's/repo.huaweicloud.com\/openeuler/repo.openeuler.org/g' \ /etc/yum.repos.d/openEuler.repo dnf clean all && dnf makecache2.3 修改源中的系统版本curr_version=$(grep -o 'openEuler-[^/]*' openEuler.repo | sort -u) && echo ${curr_version} dest_version=openEuler-24.03-LTS-SP2 sed -i \ -e '/^meta/ s/^\(.*\)$/#\1/g' \ -e "s/${curr_version}/${dest_version}/g" \ /etc/yum.repos.d/openEuler.repo dnf clean all && dnf makecache2.2 开启系统 debug 日志# 开启 systemd 的 debug 日志 $ sed -i '/LogLevel=.*/c LogLevel=debug' /etc/systemd/system.conf # 开启 journal 的 debug 日志 $ sed -i -e '/^\[Journal\]/a LogLevel=debug' \ -e '/^\[Journal\]/a LogTarget=journald' \ /etc/systemd/journald.conf # 开启内核 debug 日志 $ sed -i '/^GRUB_CMDLINE_LINUX=.*/ s/\"$/ rd.debug\"/' /etc/default/grub $ [ -d "/sys/firmware/efi" ] && grub2-mkconfig -o /boot/efi/EFI/$(cat /etc/os-release | grep -w ID | awk -F '"' '{print$2}')/grub.cfg || grub2-mkconfig -o /boot/grub2/grub.cfg2.3 修改 cgroup v1 为 cgroup v2sed -i \ -e '/^GRUB_CMDLINE_LINUX=/ s/cgroup_disable=files //' \ -e '/^GRUB_CMDLINE_LINUX=/ s/"$/ systemd.unified_cgroup_hierarchy=1"/ \ /etc/default/grub if [ -d /sys/firmware/efi ]; then grub2-mkconfig -o /boot/efi/EFI/openEuler/grub.cfg else grub2-mkconfig -o /boot/grub2/grub.cfg fi3 开发环境配置3.1 配置 go 开发环境# 定义要安装的 go 版本及架构（amd64、arm64） $ GO_VERSION=1.22.11; GO_ARCH=amd64 # 下载 go 二进制包 $ wget https://golang.google.cn/dl/go"${GO_VERSION}".linux-"${GO_ARCH}".tar.gz -P /root # 解压 go 二进制包到指定目录 $ rm -rf /usr/local/go && tar -xvf go"${GO_VERSION}".linux-"${GO_ARCH}".tar.gz -C /usr/local # 配置 go 开发需要的环境变量 $ cat >> /etc/profile <<"EOF" export GOPATH=/root/go export GOBIN=${GOPATH}/bin export GOROOT=/usr/local/go export PATH=${PATH}:${GOROOT}/bin EOF # 重载环境变量 $ source /etc/profile # 查看 go 版本 $ go version3.2 配置 jdk 环境JDK 下载地址：Java Downloads | Oracle# 解压下载的 jdk $ tar -xvf jdk-11.0.27_linux-x64_bin.tar.gz -C /usr/local # 创建软链接，方便版本管理 $ ln -s /usr/local/jdk-11.0.27 /usr/local/java # 配置环境变量 $ sed -i \ -e '$a \ ' \ -e '$a export JAVA_HOME=/usr/local/java' \ -e '$a export JAVA_BIN=${JAVA_HOME}/bin' \ -e '$a export PATH=${JAVA_BIN}:${PATH}' \ /etc/profile # 刷新环境变量 $ source /etc/profile # 查看 java 版本 $ java -version java version "11.0.27" 2025-04-15 LTS Java(TM) SE Runtime Environment 18.9 (build 11.0.27+8-LTS-232) Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.27+8-LTS-232, mixed mode)3.3 配置 nodejs 环境（使用 nvm ）nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions# 安装 nvm $ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash # 刷新环境变量 $ source .bashrc # 安装最新 LTS 版 nodejs $ nvm install --lts # 切换到最新 LTS 版 nodejs $ nvm use --lts # 使用 corepack 安装 pnpm $ corepack enable $ corepack prepare pnpm@10.22.0 --activate3.4 配置 uv 环境https://docs.astral.sh/uv/getting-started/installation/# 使用脚本一键安装 $ curl -LsSf https://astral.sh/uv/install.sh | sh # （可选）为 uv 命令启用 shell 自动补全 $ echo 'eval "$(uv generate-shell-completion bash)"' >> ~/.bashrc # 刷新环境变量 $ source ~/.bashrc # 验证是否安装成功 $ uv --version # 创建虚拟环境 $ uv venv --python 3.11.6 myvenv4 下载工具相关配置4.1 wget（1）配置全局禁用证书验证echo -e "\ncheck_certificate = off" >> /etc/wgetrc4.2 git（1）配置全局禁用证书验证git config --global http.sslVerify false（2）配置国内代理$4.3 go（1）配置国内代理export GOPROXY=https://goproxy.io,direct4.4 pip（1）配置站点可信mkdir ~/.pip cat > ~/.pip/pip.conf <<EOF [global] index-url = https://mirrors.huaweicloud.com/repository/pypi/simple trusted-host = mirrors.huaweicloud.com timeout = 120 EOF4.5 gem（1）配置全局禁用证书验证echo ":ssl_verify_mode: 0" >> ~/.gemrc（2）配置国内代理cat >> ~/.gemrc <<-EOF :sources: - https://gems.ruby-china.com/ EOF
基于 openEuler 24.03 LTS 操作系统源码部署 Kubernetes 开发版本
1 安装目标使用源码编译安装 Kubernetes，可以方便的切换版本，方便开发测试工作。本文以 openEuler 24.03 LTS 系统作为基础环境，演示如何操作2 环境准备2.1 网络环境由于编译 docker 所需的源代码资源都在外网，因此需要提前配置代理# 配置代理 PROXY_IP=192.168.230.1 PROXY_PORT=10809 export http_proxy=http://${PROXY_IP}:${PROXY_PORT} export https_proxy=http://${PROXY_IP}:${PROXY_PORT} export ALL_PROXY=http://${PROXY_IP}:${PROXY_PORT} export all_proxy=socks://${PROXY_IP}:${PROXY_PORT} # 测试代理 $ curl www.google.com2.2 系统环境（1）设置主机名及域名解析# 设置主机名 $ hostnamectl set-hostname k8s-master # 配置域名解析 $ cat >>/etc/hosts <<EOF 192.168.230.240 k8s-master EOF（2）关闭防火墙及 SELinux# 关闭防火墙 $ systemctl stop firewalld && systemctl disable firewalld # 关闭 SELinux $ setenforce 0 && sed -i 's/\(SELINUX=\).*/\1disabled/' /etc/selinux/config（3）关闭 Swap 分区# 关闭 Swap 分区 $ swapoff -a # 禁止开机自动挂载 Swap 分区 $ sed -i '/swap/ s/^\(.*\)$/#\1/g' /etc/fstab（4）加载 netfilter 模块# 加载 netfilter 模块 $ modprobe br_netfilter && lsmod | grep br_netfilter br_netfilter 36864 0 bridge 397312 1 br_netfilter # 设置开机自动加载 netfilter 模块 $ cat >/etc/modules-load.d/br_netfilter.conf <<EOF br_netfilter EOF（5）调整内核参数# 编写配置文件 $ cat > /etc/sysctl.d/kubernetes.conf <<EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 vm.max_map_count = 262144 EOF # 加载配置文件 $ sysctl -p /etc/sysctl.d/kubernetes.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 vm.max_map_count = 2621442.3 工具环境（1）安装编译及其他工具# 安装编译工具 $ yum install -y gcc-c++ make rsync lxcfs # 启动 lxcfs $ systemctl start lxcfs && systemctl enable lxcfs（2）安装 cfssl 工具# 下载 cfssl 工具 $ wget https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssl_1.6.5_linux_amd64 -P /root # 安装 cfssl 工具 $ mv /root/cfssl_1.6.5_linux_amd64 /usr/local/bin/cfssl && chmod +x /usr/local/bin/cfssl # 测试 cfssl 工具 $ cfssl version Version: 1.6.5 Runtime: go1.22.0 # 下载 cfssljson 工具 $ wget https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssljson_1.6.5_linux_amd64 -P /root # 安装 cfssljson 工具 $ mv /root/cfssljson_1.6.5_linux_amd64 /usr/local/bin/cfssljson && chmod +x /usr/local/bin/cfssljson # 测试 cfssl 工具 $ cfssljson -version Version: 1.6.5 Runtime: go1.22.02.4 go 环境（1）配置环境变量# 配置环境变量 $ cat >> /etc/profile <<"EOF" export GOPATH=/root/go export GOBIN=${GOPATH}/bin export GOROOT=/usr/local/go export PATH=${PATH}:${GOROOT}/bin EOF # 重载环境变量 $ source /etc/profile（2）安装 go 二进制包# 下载 go 二进制包 $ wget https://golang.google.cn/dl/go1.20.8.linux-amd64.tar.gz -P /root --2024-12-01 12:47:12-- https://golang.google.cn/dl/go1.20.8.linux-amd64.tar.gz Connecting to 192.168.230.1:10809... connected. Proxy request sent, awaiting response... 302 Found Location: https://dl.google.com/go/go1.20.8.linux-amd64.tar.gz [following] --2024-12-01 12:47:12-- https://dl.google.com/go/go1.20.8.linux-amd64.tar.gz Connecting to 192.168.230.1:10809... connected. Proxy request sent, awaiting response... 200 OK Length: 100431921 (96M) [application/x-gzip] Saving to: ‘/root/go1.20.8.linux-amd64.tar.gz’ go1.20.8.linux-amd64.tar. 100%[=============>] 95.78M 11.2MB/s in 8.8s 2024-12-01 12:47:21 (10.9 MB/s) - ‘/root/go1.20.8.linux-amd64.tar.gz’ saved [100431921/100431921] # 解压二进制包 $ rm -rf /usr/local/go && tar -zxvf go1.20.8.linux-amd64.tar.gz -C /usr/local # 查看 go 版本 $ go version go version go1.20.8 linux/amd642.5 容器环境（1）安装配置 Docker# 安装 docker $ yum install -y docker # 启动 docker $ systemctl start docker && systemctl enable docker # 创建服务配置目录 $ mkdir -p /etc/systemd/system/docker.service.d # 配置代理 $ cat > /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF [Service] Environment="HTTP_PROXY=http://${PROXY_IP}:${PROXY_PORT}" Environment="HTTPS_PROXY=http://${PROXY_IP}:${PROXY_PORT}" Environment="NO_PROXY=localhost,127.0.0.1" EOF # 重新加载配置 $ systemctl daemon-reload # 重启 docker $ systemctl restart docker # 查看代理是否配置成功 $ docker info | grep Proxy HTTP Proxy: http://192.168.230.1:10809 HTTPS Proxy: http://192.168.230.1:10809 No Proxy: localhost,127.0.0.1 # 测试拉取镜像 $ docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world c1ec31eb5944: Pull complete Digest: sha256:305243c734571da2d100c8c8b3c3167a098cab6049c9a5b066b6021a60fcb966 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. ......（2）安装配置 CRI-Dockerd2022 年 5 月 3 日，Kubernetes 1.24 版本正式发布，该版本 Kubernetes 正式移除对 Dockershim 的支持（参考文档：Kubernetes容器运行时弃用Docker转型Containerd | i4T）。因此，若还使用 Docker 作为容器运行时，则需要手动安装 CRI-Dockerd，或者使用 Containerd 作为容器运行时（安装方法见附录）# 下载 cri-dockerd $ wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.15/cri-dockerd-0.3.15.amd64.tgz -P /root # 解压下载的压缩包 $ tar -xvf /root/cri-dockerd-0.3.15.amd64.tgz cri-dockerd/ cri-dockerd/cri-dockerd # 复制命令到 /usr/bin/ 目录，并添加可执行权限 $ cp /root/cri-dockerd/cri-dockerd /usr/bin/ && chmod +x /usr/bin/cri-dockerd # 编写 cri-docker.service 文件 $ cat > /etc/systemd/system/cri-dockerd.service <<"EOF" [Unit] Description=CRI Interface for Docker Application Container Engine Documentation=https://docs.mirantis.com After=network-online.target firewalld.service docker.service Wants=network-online.target Requires=cri-dockerd.socket [Service] Type=notify ExecStart=/usr/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.k8s.io/pause:3.8 ExecReload=/bin/kill -s HUP $MAINPID TimeoutSec=0 RestartSec=2 Restart=always StartLimitBurst=3 StartLimitInterval=60s LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity TasksMax=infinity Delegate=yes KillMode=process [Install] WantedBy=multi-user.target EOF # 编写 cri-docker.socket 文件 $ cat > /usr/lib/systemd/system/cri-dockerd.socket <<"EOF" [Unit] Description=CRI Docker Socket for the API PartOf=cri-dockerd.service [Socket] ListenStream=%t/cri-dockerd.sock SocketMode=0660 SocketUser=root SocketGroup=docker [Install] WantedBy=sockets.target EOF # 重载配置文件 $ systemctl daemon-reload # 启动 cri-docker 并设置开机自启 $ systemctl start cri-dockerd && systemctl enable cri-dockerd Created symlink /etc/systemd/system/multi-user.target.wants/cri-dockerd.service → /etc/systemd/system/cri-dockerd.service. # 查看 cri-docker 状态 $ systemctl status cri-dockerd ● cri-dockerd.service - CRI Interface for Docker Application Container Engine Loaded: loaded (/etc/systemd/system/cri-dockerd.service; enabled; preset: disabled) Active: active (running) since Mon 2024-12-02 08:40:30 CST; 6s ago TriggeredBy: ● cri-dockerd.socket Docs: https://docs.mirantis.com Main PID: 2655 (cri-dockerd) Tasks: 10 Memory: 10.6M () CGroup: /system.slice/cri-dockerd.service └─2655 /usr/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.k8s.io/pause:3.8 ..... # 查看套接字文件，调用方法：unix:///run/cri-dockerd.sock $ ls -l /run/cri-dockerd.sock srwxr-xr-x 1 root root 0 Dec 2 08:40 /run/cri-dockerd.sock3 编译安装 Kubernetes3.1 编译 Kubernetes# 创建存放源代码的目录 $ mkdir -p ${GOPATH}/src/kubernetes # 进入源代码目录 $ cd ${GOPATH}/src/kubernetes # 克隆 Kubernetes 源代码 $ git clone https://github.com/kubernetes/kubernetes Cloning into 'kubernetes'... remote: Enumerating objects: 1593137, done. remote: Counting objects: 100% (47/47), done. remote: Compressing objects: 100% (38/38), done. remote: Total 1593137 (delta 12), reused 33 (delta 8), pack-reused 1593090 (from 1) Receiving objects: 100% (1593137/1593137), 1.05 GiB | 16.23 MiB/s, done. Resolving deltas: 100% (1166449/1166449), done. Updating files: 100% (26242/26242), done. # 进入克隆的 Kubernetes 源代码目录 $ cd ${GOPATH}/src/kubernetes/kubernetes # 查看所有版本分支 $ git ls-remote --tags origin # 将 Kubernetes 切换到需要的版本 $ git checkout v1.29.11 Updating files: 100% (15331/15331), done. Note: switching to 'v1.29.11'. ...... # 执行编译命令，编译所有工具 $ KUBE_BUILD_PLATFORMS="$(go env GOHOSTOS)/$(go env GOHOSTARCH)" make all GOFLAGS=-v GOGCFLAGS="-N -l" # 查看编译生成的命令 $ ls -l ./_output/local/bin/linux/amd64 total 1152540 -rwxr-xr-x 1 root root 61943960 Dec 2 08:55 apiextensions-apiserver -rwxr-xr-x 1 root root 147363496 Dec 2 08:55 e2e_node.test -rwxr-xr-x 1 root root 169920112 Dec 2 08:55 e2e.test -rwxr-xr-x 1 root root 9294084 Dec 2 08:55 ginkgo -rwxr-xr-x 1 root root 1908996 Dec 2 08:55 go-runner -rwxr-xr-x 1 root root 48709784 Dec 2 08:55 kubeadm -rwxr-xr-x 1 root root 59478168 Dec 2 08:55 kube-aggregator -rwxr-xr-x 1 root root 124129432 Dec 2 08:55 kube-apiserver -rwxr-xr-x 1 root root 119271576 Dec 2 08:55 kube-controller-manager -rwxr-xr-x 1 root root 50225304 Dec 2 08:55 kubectl -rwxr-xr-x 1 root root 48554136 Dec 2 08:55 kubectl-convert -rwxr-xr-x 1 root root 112603396 Dec 2 08:55 kubelet -rwxr-xr-x 1 root root 1687704 Dec 2 08:55 kube-log-runner -rwxr-xr-x 1 root root 110997656 Dec 2 08:55 kubemark -rwxr-xr-x 1 root root 55877784 Dec 2 08:55 kube-proxy -rwxr-xr-x 1 root root 56565912 Dec 2 08:55 kube-scheduler -rwxr-xr-x 1 root root 1605784 Dec 2 08:55 mounter # 配置环境变量 $ sed -i '$a export PATH=${PATH}:${GOPATH}/src/kubernetes/kubernetes/_output/local/bin/linux/amd64' /etc/profile # 重载环境变量 $ source /etc/profile # 测试环境变量是否生效 $ kubeadm version kubeadm version: &version.Info{Major:"1", Minor:"29", GitVersion:"v1.29.11", GitCommit:"960a2f019319ab5f7ac1c256efcc180a4113343a", GitTreeState:"clean", BuildDate:"2024-12-02T00:49:59Z", GoVersion:"go1.22.8", Compiler:"gc", Platform:"linux/amd64"}说明：如果只想编译其中一个组件，例如只编译 kubelet，可以使用该命令：KUBE_BUILD_PLATFORMS="$(go env GOHOSTOS)/$(go env GOHOSTARCH)" make all WHAT=cmd/kubelet GOFLAGS=-v GOGCFLAGS="-N -l"3.2 安装 etcd# 进入克隆的 Kubernetes 源代码目录 $ cd ${GOPATH}/src/kubernetes/kubernetes # 执行安装脚本 $ ./hack/install-etcd.sh Downloading https://github.com/coreos/etcd/releases/download/v3.5.16/etcd-v3.5.16-linux-amd64.tar.gz succeed etcd v3.5.16 installed. To use: export PATH="/root/go/src/kubernetes/kubernetes/third_party/etcd:${PATH}" # 查看编译生成的命令 $ ls -l third_party/etcd/ total 55180 drwxr-xr-x 3 1000 1000 4096 Sep 11 02:22 Documentation -rwxr-xr-x 1 1000 1000 23621784 Sep 11 02:22 etcd -rwxr-xr-x 1 1000 1000 17899672 Sep 11 02:22 etcdctl -rwxr-xr-x 1 1000 1000 14893208 Sep 11 02:22 etcdutl -rw-r--r-- 1 1000 1000 42066 Sep 11 02:22 README-etcdctl.md -rw-r--r-- 1 1000 1000 7359 Sep 11 02:22 README-etcdutl.md -rw-r--r-- 1 1000 1000 9210 Sep 11 02:22 README.md -rw-r--r-- 1 1000 1000 7896 Sep 11 02:22 READMEv2-etcdctl.md # 配置环境变量 $ sed -i '$a export PATH=${PATH}:${GOPATH}/src/kubernetes/kubernetes/third_party/etcd' /etc/profile # 重载环境变量 $ source /etc/profile # 测试环境变量是否生效 $ etcd --version etcd Version: 3.5.16 Git SHA: f20bbad Go Version: go1.22.7 Go OS/Arch: linux/amd644 使用 Kubernetes4.1 启动 Kubernetes# 进入克隆的 Kubernetes 源代码目录 $ cd ${GOPATH}/src/kubernetes/kubernetes # 修改启动脚本中：允许特权容器运行、API 节点名称 $ sed -i \ -e '/^ALLOW_PRIVILEGED=/c ALLOW_PRIVILEGED=${ALLOW_PRIVILEGED:-"true"}' \ -e '/^HOSTNAME_OVERRIDE=/c HOSTNAME_OVERRIDE=${HOSTNAME_OVERRIDE:-"$(hostname)"}' \ ./hack/local-up-cluster.sh # 若 Kubernetes 版本大于等于 1.24，且使用 Docker 作为容器运行时，则还需要修改容器运行时的套接字 $ sed -i '/^CONTAINER_RUNTIME_ENDPOINT/c CONTAINER_RUNTIME_ENDPOINT=${CONTAINER_RUNTIME_ENDPOINT:-"unix:///run/cri-dockerd.sock"}' ./hack/local-up-cluster.sh # 执行启动脚本 $ ./hack/local-up-cluster.sh -O ...... To start using your cluster, you can open up another terminal/tab and run: export KUBECONFIG=/var/run/kubernetes/admin.kubeconfig cluster/kubectl.sh Alternatively, you can write to the default kubeconfig: export KUBERNETES_PROVIDER=local cluster/kubectl.sh config set-cluster local --server=https://localhost:6443 --certificate-authority=/var/run/kubernetes/server-ca.crt cluster/kubectl.sh config set-credentials myself --client-key=/var/run/kubernetes/client-admin.key --client-certificate=/var/run/kubernetes/client-admin.crt cluster/kubectl.sh config set-context local --cluster=local --user=myself cluster/kubectl.sh config use-context local cluster/kubectl.sh ------------------------------以下步骤重新打开一个终端执行------------------------------ # 刷新环境变量 $ source /etc/profile # 声明连接 Kubernetes API 服务器信息的配置文件 $ export KUBECONFIG=/var/run/kubernetes/admin.kubeconfig # 查看集群节点状态 $ kubectl get node NAME STATUS ROLES AGE VERSION k8s-master Ready <none> 10m v1.29.11-dirty4.2 安装 CalicoCalico 下载地址：https://github.com/projectcalico/calicoCalico 版本与 Kubernete 版本需要有对应关系，可参考文档：Documentation archive | Calico Documentation# 下载 calico $ wget https://github.com/projectcalico/calico/releases/download/v3.28.2/release-v3.28.2.tgz -P /root # 解压 calico $ tar -xvf /root/release-v3.28.2.tgz -C /root # 加载 calico 镜像 $ for img in $(ls /root/release-v3.28.2/images/*); do docker load -i "${img}"; done fc72e302317a: Loading layer [==========================>] 3.692MB/3.692MB 17f473a5550b: Loading layer [==========================>] 205.5MB/205.5MB 5f70bf18a086: Loading layer [==========================>] 1.024kB/1.024kB Loaded image: calico/cni:v3.28.2 4e9f7ac9fb07: Loading layer [==========================>] 38.33MB/38.33MB Loaded image: calico/dikastes:v3.28.2 3bdcbcc4896a: Loading layer [==========================>] 124.9MB/124.9MB Loaded image: calico/flannel-migration-controller:v3.28.2 b99a8e25f25e: Loading layer [==========================>] 75.3MB/75.3MB Loaded image: calico/kube-controllers:v3.28.2 31f1fc200f28: Loading layer [==========================>] 374.2MB/374.2MB Loaded image: calico/node:v3.28.2 03b5f1752b13: Loading layer [==========================>] 9.832MB/9.832MB Loaded image: calico/pod2daemon-flexvol:v3.28.2 67c02963f81a: Loading layer [==========================>] 67.58MB/67.58MB Loaded image: calico/typha:v3.28.2 # 获取 Pod 网络 $ grep "^CLUSTER_CIDR" ${GOPATH}/src/kubernetes/kubernetes/hack/local-up-cluster.sh | awk -F'[-}]' '{print $2}' 10.1.0.0/16 # 修改 yaml 文件，将 CALICO_IPV4POOL_CIDR 修改为获取的 Pod 网络 $ sed -i \ -e '/CALICO_IPV4POOL_CIDR/ s/#\ //' \ -e '/192.168.0.0\/16/ s/#\ //' \ -e "/192.168.0.0\/16/ s/192.168.0.0\/16/10.1.0.0\/16/" \ /root/release-v3.28.2/manifests/calico.yaml # 启动 calico $ kubectl apply -f /root/release-v3.28.2/manifests/calico.yaml # 查看 pod 是否正常运行 $ kubectl get pod -A NAMESPACE NAME READY STATUS RESTARTS AGE kube-system calico-kube-controllers-658958974b-m6jn2 1/1 Running 0 29s kube-system calico-node-4c84x 1/1 Running 0 29s kube-system coredns-69cbfb9798-hlqvv 1/1 Running 0 5m5s5 如何切换版本# 进入克隆的 Kubernetes 源代码目录 $ cd ${GOPATH}/src/kubernetes/kubernetes # 查看所有版本分支 $ git ls-remote --tags origin # 将 Kubernetes 强制切换到需要的版本 $ git checkout -f v1.31.3 Previous HEAD position was 960a2f01931 Release commit for Kubernetes v1.29.11 HEAD is now at c83cbee114d Release commit for Kubernetes v1.31.3 # 执行编译命令，编译所有工具 $ KUBE_BUILD_PLATFORMS="$(go env GOHOSTOS)/$(go env GOHOSTARCH)" make all GOFLAGS=-v GOGCFLAGS="-N -l" # 测试新版本命令 $ kubeadm version kubeadm version: &version.Info{Major:"1", Minor:"31", GitVersion:"v1.31.3", GitCommit:"c83cbee114ddb732cdc06d3d1b62c9eb9220726f", GitTreeState:"clean", BuildDate:"2024-12-02T06:04:02Z", GoVersion:"go1.22.8", Compiler:"gc", Platform:"linux/amd64"} # 执行 etcd 安装脚本 $ ./hack/install-etcd.sh Downloading https://github.com/etcd-io/etcd/releases/download/v3.5.15/etcd-v3.5.15-linux-amd64.tar.gz succeed # 测试新版本命令 $ etcd --version etcd Version: 3.5.15 Git SHA: 9a5533382 Go Version: go1.21.12 Go OS/Arch: linux/amd64 # 必须删除 cni 插件，否则会导致 coredns 启动失败。详见 6（2） $ rm -rf /opt/cni # 后续按照第 4 章中的方法启动即可6 FAQ（1）/root/go/src/kubernetes/kubernetes/_output/local/.gimme/versions/go1.22.8.linux.amd64/pkg/tool/linux_amd64/link: mapping output file failed: no space left on device问题现象：问题原因：编译过程中需要向 /tmp 目录写入临时文件，但该目录空间不足解决方案：若 /tmp 为单独挂载的 tmpfs 文件系统。则将其卸载：# 查看 /tmp 是否挂载 $ df -Th /tmp Filesystem Type Size Used Avail Use% Mounted on tmpfs tmpfs 2.7G 66M 2.6G 3% /tmp # 卸载 /tmp $ umount -fl /tmp（2）切换分支后，coredns 启动失败问题现象：执行 kubectl describe pod -n kube-system coredns-*-* 命令，看到包含类似如下报错：问题原因：切换版本后，cni 插件不兼容，导致网络有问题解决方案：每次切换版本，都要及时删除 cni 插件：$ rm -rf /opt/cni附录 部署 Containerd# 下载 containerd 包 $ wget https://github.com/containerd/containerd/releases/download/v1.7.15/cri-containerd-cni-1.7.15-linux-amd64.tar.gz -P /root # 将下载的包解压到根目录中，压缩包自带目录结构 $ tar -xvf /root/cri-containerd-cni-1.7.15-linux-amd64.tar.gz -C / # 创建配置文件目录 $ mkdir /etc/containerd # 生成配置文件 $ containerd config default > /etc/containerd/config.toml # 配置 systemdcgroup 驱动程序 $ sed -i '/SystemdCgroup/ s/false/true/' /etc/containerd/config.toml # 更新runc，因为cri-containerd-cni-1.6.6-linux-amd64.tar.gz的runc二进制文件有问题，最后说明。这一步很重要 ✰ ✰ ✰ # wget https://github.com/opencontainers/runc/releases/download/v1.1.3/runc.amd64 # mv runc.amd64 /usr/local/sbin/runc # mv：是否覆盖"/usr/local/sbin/runc"？ y # chmod +x /usr/local/sbin/runc # 创建服务配置目录 $ mkdir -p /etc/systemd/system/containerd.service.d # 配置代理 $ cat > /etc/systemd/system/containerd.service.d/http-proxy.conf <<EOF [Service] Environment="HTTP_PROXY=http://${PROXY_IP}:${PROXY_PORT}" Environment="HTTPS_PROXY=http://${PROXY_IP}:${PROXY_PORT}" Environment="NO_PROXY=localhost,127.0.0.1" EOF # 重新加载配置 $ systemctl daemon-reload # 启动 containerd 服务并设置开机自启 $ systemctl start containerd && systemctl enable containerd Created symlink /etc/systemd/system/multi-user.target.wants/containerd.service → /etc/systemd/system/containerd.service. # 查看 containerd 服务状态 $ systemctl status containerd ● containerd.service - containerd container runtime Loaded: loaded (/etc/systemd/system/containerd.service; enabled; preset: disabled) Active: active (running) since Mon 2024-12-02 08:54:44 CST; 19s ago Docs: https://containerd.io Main PID: 3129 (containerd) Tasks: 12 Memory: 10.6M () CGroup: /system.slice/containerd.service └─3129 /usr/local/bin/containerd ...... # 测试拉取镜像 $ ctr image pull docker.io/library/hello-world:latest docker.io/library/hello-world:latest: resolved |++++++++++++++++++++++++++++++++++++++| index-sha256:305243c734571da2d100c8c8b3c3167a098cab6049c9a5b066b6021a60fcb966: done |++++++++++++++++++++++++++++++++++++++| manifest-sha256:e2fc4e5012d16e7fe466f5291c476431beaa1f9b90a5c2125b493ed28e2aba57: done |++++++++++++++++++++++++++++++++++++++| config-sha256:d2c94e258dcb3c5ac2798d32e1249e42ef01cba4841c2234249495f87264ac5a: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:c1ec31eb59444d78df06a974d155e597c894ab4cda84f08294145e845394988e: done |++++++++++++++++++++++++++++++++++++++| elapsed: 5.1 s total: 14.4 K (2.8 KiB/s) unpacking linux/amd64 sha256:305243c734571da2d100c8c8b3c3167a098cab6049c9a5b066b6021a60fcb966... done: 29.001739ms # 查看套接字文件，调用方法：unix:///run/containerd/containerd.sock $ ls -l /run/containerd/containerd.sock srw-rw---- 1 root root 0 Dec 2 09:15 /run/containerd/containerd.sock
基于 openEuler 22.03 LTS SP4 编译 docker 20.10.13
1 编译目标由于 openEuler 所有版本适配的 docker 版本为 18.09，版本比较低不能满足大部分使用场景。因此本文以基于openEuler 22.03 LTS SP4 操作系统编译 docker-ce-20.10.13 为例，演示在 openEuler 操作系统上编译高版本 docker 的操作流程2 环境准备2.1 网络环境由于编译 docker 所需的源代码资源都在外网，因此需要提前配置代理# 配置代理 PROXY_IP=192.168.230.1 PROXY_PORT=1080 export http_proxy=http://${PROXY_IP}:${PROXY_PORT} export https_proxy=http://${PROXY_IP}:${PROXY_PORT} export ALL_PROXY=http://${PROXY_IP}:${PROXY_PORT} export all_proxy=socks://${PROXY_IP}:${PROXY_PORT} # 测试代理 $ curl www.google.com2.2 编译工具安装必要的编译工具$ yum install -y rpm-build rpmdevtools gcc gcc-c++ make golang2.3 编译资源软件包名下载地址docker-ce-20.10.10-3.el8.src.rpmhttps://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-20.10.10-3.el8.src.rpmdocker-ce-cli-20.10.13-3.el8.src.rpmhttps://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-cli-20.10.13-3.el8.src.rpmdocker-ce-rootless-extras-20.10.13-3.el8.src.rpmhttps://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-rootless-extras-20.10.13-3.el8.src.rpmcontainerd.io-1.4.3-3.2.src.rpmhttps://repo.openeuler.openatom.cn/openEuler-preview/sw_arch/openEuler-22.03-LTS/sources/Packages/containerd.io-1.4.3-3.2.src.rpmdocker-scan-plugin-0.12.0-3.el8.src.rpmhttps://download.docker.com/linux/centos/8/source/stable/Packages/docker-scan-plugin-0.12.0-3.el8.src.rpm3 编译流程3.1 编译 docker-ce3.1.1 编译# 定义 GOPATH 路径 $ export GOPATH=/go # 设置不使用 Go Modules 功能 $ export GO111MODULE=off # 从 docker 官方仓库下载 docker-ce-20.10.10-3.el8.src.rpm 源码包 $ wget https://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-20.10.10-3.el8.src.rpm -P /root -2024-11-09 12:39:03-- https://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-20.10.10-3.el8.src.rpm Connecting to 192.168.230.1:1080... connected. Proxy request sent, awaiting response... 200 OK Length: 11328477 (11M) [binary/octet-stream] Saving to: ‘/root/docker-ce-20.10.10-3.el8.src.rpm’ docker-ce-20.10.10-3.el8. 100%[==================>] 10.80M 1.67MB/s in 7.5s 2024-11-09 12:39:12 (1.44 MB/s) - ‘/root/docker-ce-20.10.10-3.el8.src.rpm’ saved [11328477/11328477] # 安装 docker-ce-20.10.10-3.el8.src.rpm源码包 $ rpm -ivh /root/docker-ce-20.10.10-3.el8.src.rpm warning: /root/docker-ce-20.10.10-3.el8.src.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY Updating / installing... 1:docker-ce-3:20.10.10-3.el8 ################################# [100%] # 进入 spec 文件目录 $ cd /root/rpmbuild/SPECS # 修改 spec 文件 $ sed -i \ -e '1i %define _version 20.10.13' \ -e '1i %define _release 3' \ -e '1i %define _origversion %{_version}' \ -e '1i \ ' \ docker-ce.spec # 安装编译包依赖 $ yum builddep -y docker-ce.spec # 开始编译 $ rpmbuild -ba docker-ce.spec3.1.2 FAQ（1）no required module provides package github.com/docker/libnetwork/cmd/proxy: go.mod file not found in current directory or any parent directory; see 'go help modules' 报错信息：报错原因：参考文献：报错no required module provides package github.comxx的解决方案-CSDN博客Go Modules 是在 Go 1.11 版本中引入的。此时从 git 上下载的依赖库不再保存在 GOPATH 中，而是存到当前项目中，并使用 go.mod 文件跟踪依赖库和其版本。GO111MODULE 这个环境变量也是此时引入的，作为控制是否开启 Go Modules 的开关，Go Modules 和 GOPATH 是两个对立的依赖存储和搜索方式解决方案：从 Go 1.16 开始，默认行为是 GO111MODULE=on，这意味着如果您想继续使用旧 GOPATH 方式，则必须强制 Go 不使用 Go Modules 功能：$ export GO111MODULE=off（2）error: missing GOPATH; please see https://golang.org/doc/code.html#GOPATH alternatively, set AUTO_GOPATH=1 报错信息：报错原因：GOPATH 变量未定义$ echo $GOPATH 解决方案：指定 GOPATH 变量$ export GOPATH=/go3.2 编译 docker-ce-cli3.2.1 编译# 定义 GOPATH 路径 $ export GOPATH=/go # 添加 PATH 变量 $ export PATH=${PATH}:${GOPATH}/bin # 设置不使用 Go Modules 功能 $ export GO111MODULE=off # 从 docker 官方仓库下载 docker-ce-cli-20.10.13-3.el8.src.rpm 源码包 $ wget https://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-cli-20.10.13-3.el8.src.rpm -P /root --2024-11-09 17:26:50-- https://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-cli-20.10.13-3.el8.src.rpm Connecting to 192.168.230.1:1080... connected. Proxy request sent, awaiting response... 200 OK Length: 7688788 (7.3M) [binary/octet-stream] Saving to: ‘/root/docker-ce-cli-20.10.13-3.el8.src.rpm’ docker-ce-cli-20.10.13-3. 100%[==================>] 7.33M 1.64MB/s in 4.5s 2024-11-09 17:26:56 (1.64 MB/s) - ‘/root/docker-ce-cli-20.10.13-3.el8.src.rpm’ saved [7688788/7688788] # 安装 docker-ce-cli-20.10.13-3.el8.src.rpm 源码包 $ rpm -ivh /root/docker-ce-cli-20.10.13-3.el8.src.rpm warning: /root/docker-ce-cli-20.10.13-3.el8.src.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY Updating / installing... 1:docker-ce-cli-1:20.10.13-3.el8 ################################# [100%] # 进入 spec 文件目录 $ cd /root/rpmbuild/SPECS # 修改 spec 文件 $ sed -i \ -e '1i %define _version 20.10.13' \ -e '1i %define _release 3' \ -e '1i %define _origversion %{_version}' \ -e '1i \ ' \ docker-ce-cli.spec # 安装编译包依赖 $ yum builddep -y docker-ce-cli.spec # 开始编译 $ rpmbuild -ba docker-ce-cli.spec3.2.2 FAQ（1）cannot find package "github.com/docker/cli/cmd/docker" in any of报错信息：报错原因：GOPATH 变量未定义$ echo $GOPATH 解决方案：指定 GOPATH 变量$ export GOPATH=/go（2）go: cannot find main module, but found vendor.conf in /go/src/github.com/docker/cli报错信息：报错原因：参考文献：报错no required module provides package github.comxx的解决方案-CSDN博客Go Modules 是在 Go 1.11 版本中引入的。此时从 git 上下载的依赖库不再保存在 GOPATH 中，而是存到当前项目中，并使用 go.mod 文件跟踪依赖库和其版本。GO111MODULE 这个环境变量也是此时引入的，作为控制是否开启 Go Modules 的开关，Go Modules 和 GOPATH 是两个对立的依赖存储和搜索方式解决方案：从 Go 1.16 开始，默认行为是 GO111MODULE=on，这意味着如果您想继续使用旧 GOPATH 方式，则必须强制 Go 不使用 Go Modules 功能：$ export GO111MODULE=off（3）./man/md2man-all.sh: line 21: go-md2man: command not found报错信息：报错原因：未找到 go-md2man 命令，实际此时该命令已经编译成功，位于 /go/bin 目录中$ ls -l /go/bin/ total 2604 -rwxr-xr-x 1 root root 2666053 Nov 9 17:39 go-md2man解决方案：将 /go/bin 添加 PATH 变量# 将 /go/bin 添加 PATH 变量 $ export PATH=${PATH}:${GOPATH}/bin # 查询是否能找到 go-md2man 命令 $ which go-md2man /go/bin/go-md2man3.3 编译 docker-ce-rootless-extras# 从 docker 官方仓库下载 docker-ce-rootless-extras-20.10.13-3.el8.src.rpm 源码包 $ wget https://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-rootless-extras-20.10.13-3.el8.src.rpm -P /root --2024-11-09 17:52:50-- https://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-rootless-extras-20.10.13-3.el8.src.rpm Connecting to 192.168.230.1:1080... connected. Proxy request sent, awaiting response... 200 OK Length: 11211542 (11M) [binary/octet-stream] Saving to: ‘/root/docker-ce-rootless-extras-20.10.13-3.el8.src.rpm’ docker-ce-rootless-extras 100%[==================>] 10.69M 2.57MB/s in 4.2s 2024-11-09 17:52:55 (2.57 MB/s) - ‘/root/docker-ce-rootless-extras-20.10.13-3.el8.src.rpm’ saved [11211542/11211542] # 安装 docker-ce-rootless-extras-20.10.13-3.el8.src.rpm 源码包 $ rpm -ivh /root/docker-ce-rootless-extras-20.10.13-3.el8.src.rpm warning: /root/docker-ce-rootless-extras-20.10.13-3.el8.src.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY Updating / installing... 1:docker-ce-rootless-extras-0:20.10################################# [100%] # 进入 spec 文件目录 $ cd /root/rpmbuild/SPECS # 修改 spec 文件 $ sed -i \ -e '1i %define _version 20.10.13' \ -e '1i %define _release 3' \ -e '1i \ ' \ docker-ce-rootless-extras.spec # 安装编译包依赖 $ yum builddep -y docker-ce-rootless-extras.spec # 开始编译 $ rpmbuild -ba docker-ce-rootless-extras.spec3.4 编译 containerd.io3.4.1 编译（1）环境准备# 定义 GOPATH 路径 $ export GOPATH=/root/go（2）部署 containerd 源码# 创建存放 containerd 的源码目录 $ mkdir -p $GOPATH/src/github.com/containerd # 进入存放 containerd 的源码目录 $ cd $GOPATH/src/github.com/containerd # 克隆 containerd 源码 $ git clone https://github.com/containerd/containerd.git Cloning into 'containerd'... remote: Enumerating objects: 148247, done. remote: Counting objects: 100% (19157/19157), done. remote: Compressing objects: 100% (1209/1209), done. remote: Total 148247 (delta 18390), reused 18188 (delta 17926), pack-reused 129090 (from 1) Receiving objects: 100% (148247/148247), 113.09 MiB | 2.27 MiB/s, done. Resolving deltas: 100% (96229/96229), done. # 进入克隆的 containerd 源码目录 $ cd $GOPATH/src/github.com/containerd/containerd # 切换分支，因为高版本分支需要较高的 go 版本支持 $ git checkout v1.5.18 # 确认分支是否正确 $ git branch * (HEAD detached at v1.5.18) main（3）部署 runc 源码# 创建存放 runc 的源码目录 $ mkdir -p $GOPATH/src/github.com/opencontainers # 进入存放 runc 的源码目录 $ cd $GOPATH/src/github.com/opencontainers # 克隆 runc 源码 $ git clone https://github.com/opencontainers/runc.git Cloning into 'runc'... remote: Enumerating objects: 44540, done. remote: Counting objects: 100% (194/194), done. remote: Compressing objects: 100% (138/138), done. remote: Total 44540 (delta 80), reused 126 (delta 49), pack-reused 44346 (from 1) Receiving objects: 100% (44540/44540), 22.01 MiB | 1.52 MiB/s, done. Resolving deltas: 100% (29266/29266), done. # 进入克隆的 runc 源码目录 $ cd $GOPATH/src/github.com/opencontainers/runc # 切换分支，因为高版本分支需要较高的 go 版本支持 $ git checkout v1.1.12 # 确认分支是否正确 $ git branch * (HEAD detached at v1.1.12) main（4）部署 go-md2man 工具命令# 安装 go-md2man 工具命令 $ go install github.com/cpuguy83/go-md2man/v2@latest # 查看命令是否安装成功 $ ls -l ${GOPATH}/bin total 2624 -rwxr-xr-x 1 root root 2685640 Nov 9 19:59 go-md2man # 将命令路径添加到 PATH $ export PATH=${PATH}:${GOPATH}/bin # 查询是否能找到 go-md2man 命令 $ which go-md2man /root/go/bin/go-md2man（5）编译 containerd.io# 从 OEPKGS 仓库下载 containerd.io-1.4.3-3.2.src.rpm 源码包 $ wget https://repo.openeuler.openatom.cn/openEuler-preview/sw_arch/openEuler-22.03-LTS/sources/Packages/containerd.io-1.4.3-3.2.src.rpm -P /root --2024-11-09 19:32:48-- https://repo.openeuler.openatom.cn/openEuler-preview/sw_arch/openEuler-22.03-LTS/sources/Packages/containerd.io-1.4.3-3.2.src.rpm Resolving repo.openeuler.openatom.cn (repo.openeuler.openatom.cn)... 124.70.105.51 Connecting to repo.openeuler.openatom.cn (repo.openeuler.openatom.cn)|124.70.105.51|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 15017 (15K) [application/x-redhat-package-manager] Saving to: ‘/root/containerd.io-1.4.3-3.2.src.rpm’ containerd.io-1.4.3-3.2.s 100%[==================>] 14.67K 45.6KB/s in 0.3s 2024-11-09 19:32:48 (45.6 KB/s) - ‘/root/containerd.io-1.4.3-3.2.src.rpm’ saved [15017/15017] # 安装 containerd.io-1.4.3-3.2.src.rpm 源码包 $ rpm -ivh /root/containerd.io-1.4.3-3.2.src.rpm Updating / installing... 1:containerd.io-1.4.3-3.2 ################################# [100%] # 进入 spec 文件目录 $ cd /root/rpmbuild/SPECS # 修改 spec 文件 $ sed -i '/^rm -rf %{_topdir}\/BUILD\// s/\/$//' containerd.spec # 定义 spec 文件中需要的环境变量 $ export RPM_VERSION=1.4.3 $ export RPM_RELEASE_VERSION=3.2 # 安装编译包依赖 $ yum builddep -y containerd.spec # 开始编译 $ rpmbuild -ba containerd.spec3.4.2 FAQ（1）RPM: error: line 46: Empty tag: Version报错信息：报错原因：containerd.spec 文件中第 46 行和第 47 行为定义 rpm 包的版本信息，其变量的值来自于环境变量 RPM_VERSION 和 RPM_RELEASE_VERSION，但是这两个环境变量未定义Version: %{getenv:RPM_VERSION} Release: %{getenv:RPM_RELEASE_VERSION}解决方案：在命令行中定义环境变量：RPM_VERSION 和 RPM_RELEASE_VERSION$ export RPM_VERSION=1.4.3 $ export RPM_RELEASE_VERSION=3.2（2）is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt报错信息：报错原因：go.mod 文件和 vendor/modules.txt 文件之间存在不一致解决方案：重新拉取源代码，确认go.mod 文件和 vendor/modules.txt 文件是否一致3.5 编译 docker-scan-plugin# 从 docker 官方仓库下载 docker-scan-plugin-0.12.0-3.el8.src.rpm 源码包 $ wget https://download.docker.com/linux/centos/8/source/stable/Packages/docker-scan-plugin-0.12.0-3.el8.src.rpm -P /root --2024-11-09 20:38:29-- https://download.docker.com/linux/centos/8/source/stable/Packages/docker-scan-plugin-0.12.0-3.el8.src.rpm Connecting to 192.168.230.1:1080... connected. Proxy request sent, awaiting response... 200 OK Length: 104035 (102K) [binary/octet-stream] Saving to: ‘/root/docker-scan-plugin-0.12.0-3.el8.src.rpm’ docker-scan-plugin-0.12.0 100%[==================>] 101.60K 278KB/s in 0.4s 2024-11-09 20:38:33 (278 KB/s) - ‘/root/docker-scan-plugin-0.12.0-3.el8.src.rpm’ saved [104035/104035] # 安装 docker-scan-plugin-0.12.0-3.el8.src.rpm 源码包 $ rpm -ivh /root/docker-scan-plugin-0.12.0-3.el8.src.rpm warning: /root/docker-scan-plugin-0.12.0-3.el8.src.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY Updating / installing... 1:docker-scan-plugin-0:0.12.0-3.el8################################# [100%] # 进入 spec 文件目录 $ cd /root/rpmbuild/SPECS # 修改 spec 文件 $ sed -i \ -e '1i %define _scan_rpm_version 0.12.0' \ -e '1i %define _release 3' \ -e '1i %define _scan_version v%{_scan_rpm_version}' \ -e '1i \ ' \ docker-scan-plugin.spec # 安装编译包依赖 $ yum builddep -y docker-scan-plugin.spec # 开始编译 $ rpmbuild -ba docker-scan-plugin.spec4 安装测试（1）安装# 进入存放构建完成的 rpm 包目录 $ cd /root/rpmbuild/RPMS/x86_64/ # 查看编译完成的 rpm 包 $ ls -l total 91636 -rw-r--r-- 1 root root 31520637 Nov 9 20:32 containerd.io-1.4.3-3.2.x86_64.rpm -rw-r--r-- 1 root root 22738649 Nov 9 17:10 docker-ce-20.10.13-3.x86_64.rpm -rw-r--r-- 1 root root 30831385 Nov 9 17:46 docker-ce-cli-20.10.13-3.x86_64.rpm -rw-r--r-- 1 root root 4890517 Nov 9 19:20 docker-ce-rootless-extras-20.10.13-3.x86_64.rpm -rw-r--r-- 1 root root 3842797 Nov 9 20:44 docker-scan-plugin-0.12.0-3.x86_64.rpm # 执行本地安装 $ yum localinstall *.rpm（2）测试# 配置加速地址 $ cat >> /etc/docker/daemon.json <<EOF { "registry-mirrors": [ "https://367e3d3a84aa407eb200df7aab688eaf.mirror.swr.myhuaweicloud.com" ] } EOF # 启动 docker 并设置开机自启 $ systemctl start docker && systemctl enable docker Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service. # 查看 docker 基本信息 $ docker info Client: Context: default Debug Mode: false Plugins: app: Docker App (Docker Inc., v0.9.1-beta3) buildx: Docker Buildx (Docker Inc., v0.8.0-docker) scan: Docker Scan (Docker Inc., v0.12.0) Server: Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 0 Server Version: 20.10.13 Storage Driver: overlay2 Backing Filesystem: extfs Supports d_type: true Native Overlay Diff: true userxattr: false Logging Driver: json-file Cgroup Driver: cgroupfs Cgroup Version: 1 Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc Default Runtime: runc Init Binary: docker-init containerd version: runc version: v1.1.12-0-g51d5e946 init version: de40ad0 Kernel Version: 5.10.0-216.0.0.115.oe2203sp4.x86_64 Operating System: openEuler 22.03 (LTS-SP4) OSType: linux Architecture: x86_64 CPUs: 8 Total Memory: 7.228GiB Name: localhost.localdomain ID: S6QG:FGLU:ZJC2:2N2Q:6SZS:HDTN:MDBY:CACI:DQ7Q:SX3B:XJ34:MFNO Docker Root Dir: /var/lib/docker Debug Mode: false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false # 拉取镜像 $ docker pull openeuler/openeuler:22.03-lts-sp4 22.03-lts-sp4: Pulling from openeuler/openeuler 6550e36f5825: Pull complete 12f045674288: Pull complete Digest: sha256:7b3947d10e1f9459ffae6303349f9f7dba79a1eb992adaa10172df6cbdac2b4e Status: Downloaded newer image for openeuler/openeuler:22.03-lts-sp4 docker.io/openeuler/openeuler:22.03-lts-sp4 # 创建容器 $ docker run -d --name test01 openeuler/openeuler:22.03-lts-sp4 /bin/bash -c "sleep 3600" cca749590ba66bdd6812bba5e83c17d5be217772933cb3c725aa831883c93b9a
使用 x2openEuler 工具升级 SUSE12 过程中升级前检查中断的可能原因及解决方案
一、问题现象近期，遇到多起 SUSE12 升级过程中升级前检查中断的事件，具体报错现象如下图所示：经查看日志，发现是在收集硬件信息时报错，即 x2openEuler-client hardware-collect 命令执行失败：进一步查看升级日志，并且在待升级节点手动执行 x2openEuler-client hardware-collect 命令，均发现以下报错信息：报错显示：操作系统上没有发现 /usr/sbin/lspci 命令二、原因分析以上报错由一系列原因导致：① SUSE12 实际存在且可以执行 lspci 命令② 通过执行 which lspci 命令发现其位于 /sbin/ 目录中③ SUSE12 系统中 /usr/sbin/ 目录和 /sbin/ 目录并不是软链接关系④ x2openEuler 工具收集硬件信息时执行的 lspci 命令是带绝对路径的 /usr/sbin/lspci 最终导致硬件信息收集失败，检查中断三、解决方案此问题并非必现，具体出现原因可能与用户环境配置相关。若遇到此问题可以创建一个软连接 /usr/sbin/lspci 到 /sbin/lspci 最终还是建议工具能够注意并修复一下这个问题，避免不必要的麻烦
本文基于 openEuler 22.03 LTS SP1 操作系统进行操作1 VNC 部署流程1.1 安装 VNC# 安装 VNC 服务端 $ yum install -y tigervnc-server # 安装 VNC 客户端（可选） $ yum install -y tigervnc # 查看安装情况 $ rpm -qa | grep tigervnc tigervnc-selinux-1.12.0-9.oe2203sp1.noarch tigervnc-license-1.12.0-9.oe2203sp1.noarch tigervnc-server-minimal-1.12.0-9.oe2203sp1.x86_64 tigervnc-server-1.12.0-9.oe2203sp1.x86_64 tigervnc-1.12.0-9.oe2203sp1.x86_64 # 查看服务管理文件，用于使用 systemd 管理 VNC 服务 $ ll /usr/lib/systemd/system/vncserver\@.service -rw-r--r-- 1 root root 1558 5月 24 2023 /usr/lib/systemd/system/vncserver@.service # 查看相关配置文件 $ tree /etc/tigervnc/ /etc/tigervnc/ ├── vncserver-config-defaults # 默认配置文件，可被 ~/.vnc/config 和 vncserver-config-mandatory 覆盖 ├── vncserver-config-mandatory # 强制配置文件，可以覆盖 ~/.vnc/config 和 vncserver-config-defaults └── vncserver.users # 配置 VNC 用户以及访问端口号 0 directories, 3 files1.2 配置 tigervnc-server1.2.1 修改默认配置文件tigervnc-server 默认配置文件位于 /etc/tigervnc/vncserver-config-defaults 修改前的配置文件内容为：$ cat /etc/tigervnc/vncserver-config-defaults ## Default settings for VNC servers started by the vncserver service # # Any settings given here will override the builtin defaults, but can # also be overriden by ~/.vnc/config and vncserver-config-mandatory. # # See HOWTO.md and the following manpages for more details: # vncsession(8) Xvnc(1) # # Several common settings are shown below. Uncomment and modify to your # liking. # session=gnome # securitytypes=vncauth,tlsvnc # geometry=2000x1200 # localhost # alwaysshared修改后的配置文件内容为：$ cat /etc/tigervnc/vncserver-config-defaults session=gnome # 会话类型：gnome、dde、kiran securitytypes=vncauth,tlsvnc # 安全类型 geometry=1918x888 # VNC 界面分辨率，根据实际情况调整 # localhost # 若取消注释，表示只能在本地连接 VNC alwaysshared # 表示同一个显示端口允许多用户同时登录1.2.2 配置 VNC 用户及访问端口VNC 用户以及访问端口号配置文件为 /etc/tigervnc/vncserver.users# 修改配置文件，添加端口号及对应的用户名 $ sed -i '$a :1=root' /etc/tigervnc/vncserver.users说明：:1=root ：表示可以通过 :1 或 5901 端口，使用 root 用户登录 VNC，其他用户类似1.2.3 修改 VNC 用户密码（1）若 VNC 用户为 root 用户，则按照以下步骤设置 root 用户密码# 确认当前登录用户为 root 用户 $ whoami root # 设置 root 用户密码 $ vncpasswd Password: Verify: Would you like to enter a view-only password (y/n)? A view-only password is not used # 查看生成的密码文件 $ ls -l ~/.vnc/passwd -rw------- 1 root root 8 3月 4 14:18 /root/.vnc/passwd（2）若 VNC 用户为普通用户（假如普通用户为 ep），则按照以下步骤设置普通用户密码# 切换到 ep 用户 $ su - ep # 确认当前用户为 ep 用户 $ whoami ep # 设置 ep 用户密码 $ vncpasswd Password: Verify: Would you like to enter a view-only password (y/n)? A view-only password is not used # 查看生成的密码文件 $ ls -l ~/.vnc/passwd -rw------- 1 ep ep 8 3月 4 14:22 /home/ep/.vnc/passwd1.2.4 配置启动参数（可选，一般不需要）启动参数文件位于 ~/.vnc/xstartup ，若此文件不存在，则手动创建即可注意：若 VNC 用户为 root 用户，则此文件位于 /root/.vnc/ 目录，若 VNC 用户为普通用户，则此文件位于 /home/USER/.vnc/ 目录其中，DISPLAY 变量的值应该为：从 /etc/tigervnc/vncserver.users 文件查找当前用户对应端口号（1）gnome 桌面使用如下配置$ cat > ~/.vnc/xstartup <<EOF #!/bin/bash unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS #exec /etc/X11/xinit/xinitrc (sleep 5 && export DISPLAY=:1 && xfce4-session) & EOF（2）DDE 桌面使用如下配置$ cat > ~/.vnc/xstartup <<EOF #!/bin/bash unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS exec /usr/bin/startdde EOF（3）Kiran 桌面使用如下配置$ cat > ~/.vnc/xstartup <<EOF #!/bin/bash unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS exec /usr/bin/kiran-session-manager --session-type=kiran EOF1.2.5 创建服务管理脚本# 复制服务管理脚本，vncserver@:1.service，其中 @ 后面的数字与 /etc/tigervnc/vncserver.users 文件中的端口对应 $ cp -a /usr/lib/systemd/system/vncserver@.service /etc/systemd/system/vncserver@:1.service # 重新加载服务管理脚本 $ systemctl daemon-reload # 启动 VNC 服务并设置开机自启 $ systemctl enable --now vncserver@:1.service # 查看服务状态 $ systemctl status vncserver@:1.service ● vncserver@:1.service - Remote desktop service (VNC) Loaded: loaded (/etc/systemd/system/vncserver@:1.service; enabled; vendor preset: disabled) Active: active (running) since Fri 2024-03-01 15:22:13 CST; 1h 31min ago Process: 1195 ExecStart=/usr/libexec/vncsession-start :1 (code=exited, status=0/SUCCESS) Main PID: 1219 (vncsession) Tasks: 0 (limit: 98697) Memory: 1.8M CGroup: /system.slice/system-vncserver.slice/vncserver@:1.service ‣ 1219 /usr/sbin/vncsession root :1 3月 01 15:22:13 localhost systemd[1]: Starting Remote desktop service (VNC)... 3月 01 15:22:13 localhost systemd[1]: Started Remote desktop service (VNC). # 查看端口号 $ netstat -anpt | grep Xvnc tcp 0 0 0.0.0.0:5901 0.0.0.0:* LISTEN 1446/Xvnc tcp6 0 0 :::5901 :::* LISTEN 1446/Xvnc1.3 使用 noVNC 转发# 安装 noVNC 服务 $ yum install -y novnc # 连接 VNC，执行该命令后将持续占用终端 $ novnc_server --listen 44944 --vnc localhost:5901 # 可以执行以下命令，将其放入后台运行 $ nohup novnc_server --listen 44944 --vnc localhost:5901 & # 查看端口号 $ netstat -anpt | grep python3 tcp 0 0 0.0.0.0:44944 0.0.0.0:* LISTEN 9690/python3当然也可以编写 service 文件，使用 systemd 管理：# 编写 service 文件 $ cat > /etc/systemd/system/noVNC.service <<EOF [Unit] Description=noVNC Web VNC Proxy After=network.target [Service] Type=simple User=nobody ExecStart=/usr/bin/novnc_server --listen 44944 --vnc localhost:5901 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF # 重新加载配置 $ systemctl daemon-raload # 启动 noVNC 服务并设置开机自启 $ systemctl enable --now noVNC现在可以在 Windows 浏览器中通过 http://SERVER-IP:noVNC-PORT 来访问 VNC 服务了，例如：http://192.168.230.250:44944/
1 前言everything 镜像中包含了许多 rpm 包，可以提供基本的安装使用，然而还有一部分软件包需要连网到公网 repo 源中下载。但是在生产环境中，服务器大多数是不能连接公网的，因此需要搭建一个局域网 repo 源，即让一台能够连接公网的服务器从公网 repo 源中同步 rpm 包到本地，然后局域网的其他服务器再从这台能连接公网的服务器中下载 rpm 包2 所需的服务或命令2.1 Web 服务用于局域网中其他服务器访问，可以使用 httpd 服务或 nginx 服务2.2 dnf reposync 命令$ dnf reposync [OPTIONS] -c [CONFIG FILE] 指定配置文件运行（默认配置文件是 /etc/yum.conf） -q 安静操作 -v 显示详细信息 -b 尝试使用最佳的软件包版本 -C 完全从系统缓存运行，不更新缓存 -R [minutes] 最大命令等待时间 -y 所有问题自动回答 yes --assumeno 所有问题自动回答 no --enablerepo [repo] 启用其他存储库，可以指定多次 --disablerepo [repo] 禁用仓库，可以指定多次 --repo [repo], --repoid [repo] 仅使用指定的存储库 --exclude [package] 排除软件包 --forcearch ARCH 强制使用指定的架构 --arch [arch] 仅下载指定架构的软件包 --delete 删除存储库中不再存在的本地软件包 -n 仅下载最新的软件包 -p DOWNLOAD_PATH 指定软件包下载的位置 --norepopath 在下载目录中不重新生成以 `repo name` 命名的目录2.3 createrepo 命令$ createrepo [OPTION?] <directory_to_index> -q 以安静模式运行 -v 显示详细信息 -o 指定生成的元数据存放的位置 --excludes=PACKAGE_NAME_GLOB 指定生成元数据时排除的包 --update 在原有元数据上升级，只更新有变化的软件 --workers 读取 rpm 包的数量，默认为 53 同步官方源服务器名称用途操作系统版本IP 地址Server搭建局域网 repo 源openEuler 22.03 LTS SP1192.168.255.221Client模拟局域网内主机openEuler 22.03 LTS192.168.255.2203.1 Server 端配置3.1.1 系统基本设置# 关闭防火墙，并停止开机自启 $ systemctl stop firewalld $ systemctl disable firewalld # 关闭 SELinux $ setenforce 0 # 安装用于提供 reposync 命令的工具包 $ yum install -y dnf-plugins-core # 安装用于提供 createrepo 命令的工具包 $ yum install -y createrepo # 创建专用目录，保存同步的 RPM 包 $ mkdir /openEuler-22.03-LTS-REPO另外注意要留有足够的分区空间去保存 RPM 包3.1.2 配置 Web 服务此处使用 nginx 服务# 安装 nginx $ yum install -y nginx # 启动服务，并设置开机自启 $ systemctl start nginx $ systemctl enable nginx # 在默认网页根目录下创建 openEuler-22.03-LTS 目录及以下子目录，用来存放 RPM 包 $ mkdir -p /usr/share/nginx/html/openEuler-22.03-LTS/{everything,update,EPOL} $ mkdir -p /usr/share/nginx/html/openEuler-22.03-LTS/EPOL/main # 编写配置文件，允许显示目录索引 $ cat > /etc/nginx/conf.d/openEuler-22.03-LTS.conf <<EOF server { listen 8001; root /usr/share/nginx/html/openEuler-22.03-LTS; location / { autoindex on; autoindex_exact_size off; autoindex_format html; autoindex_localtime on; } } EOF # 重启 nginx 服务 $ systemctl restart nginx使用 Windows 浏览器访问 http://192.168.255.221:8001，查看访问是否正常3.1.3 配置 repo 源Server 端需要配置局域网内客户端主机操作系统的 repo 源。例如本实验中作为局域网 repo 源服务器的 Server 端的操作系统版本为 openEuler 22.03 LTS SP1，而客户端主机操作系统为 openEuler 22.03 LTS，那么需要在 Server 端配置 openEuler 22.03 LTS 操作系统的 repo 源openEuler 各版本的 repo 源可以在论坛中找到：【汇总贴】openEuler常用repo源 - 迁移 - openEuler 论坛注意：一定要修改新添加的 repo 源的 repo id 和 repo name，即修改 [ REPO ID ] 和 naem=REPO NAME 的内容，否则可能会和现有的 repo 源名字冲突# 在 Server 端配置客户端主机操作系统的 reop 源 $ cat > /etc/yum.repos.d/openEuler-22.03-LTS.repo <<EOF [openEuler-22.03-everything] name=openEuler-22.03-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 gpgkey=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/everything/x86_64/RPM-GPG-KEY-openEuler [openEuler-22.03-EPOL] name=openEuler-22.03-EPOL baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-22.03-update] name=openEuler-22.03-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/update/x86_64/ enabled=1 gpgcheck=0 EOF # 清空 yum 缓存 $ yum clean all # 重建 yum 缓存 $ yum makecache # 查看当前的 repo 源 $ yum repolist repo id repo name openEuler-22.03-EPOL openEuler-22.03-EPOL openEuler-22.03-everything openEuler-22.03-everything openEuler-22.03-update openEuler-22.03-update从命令返回结果看到，openEuler 22.03 LTS 版本的 repo 源已经成功添加，另外需要记住此处的 repo id ，在同步时会指定 --repoid=REPO_ID 选项3.1.4 同步 everything 源（1）同步 everything 源的 RPM 包到本地# 同步 everything 源的 RPM 包到本地 $ dnf reposync -v --repoid=openEuler-22.03-everything -p /openEuler-22.03-LTS-REPO # 同步完成后会在 /openEuler-22.03-LTS-REPO 目录创建一个名称同 repo name 的目录 $ ls /openEuler-22.03-LTS-REPO/ openEuler-22.03-everything # 查看目录结构 $ tree -L 1 /openEuler-22.03-LTS-REPO/openEuler-22.03-everything/ /openEuler-22.03-LTS-REPO/openEuler-22.03-everything/ └── Packages（2）生成 everything 源的 RPM 包元数据# 执行以下命令生成元数据 $ createrepo -v --workers 10 /openEuler-22.03-LTS-REPO/openEuler-22.03-everything # 查看生成元数据后的目录结构 $ tree -L 1 /openEuler-22.03-LTS-REPO/openEuler-22.03-everything/ /openEuler-22.03-LTS-REPO/openEuler-22.03-everything/ ├── Packages └── repodata # 查看生成的元数据文件 $ ls /openEuler-22.03-LTS-REPO/openEuler-22.03-everything/repodata 0079e1d3bd752a19486cb91269c98c8b5a6254d3ca13e5c0326e085561f1ed2a-other.sqlite.bz2 355628d38b0cd6163757264bc7971f3d86ff1d530a44c034786f3116b167f490-filelists.xml.gz 73565b368f50f6d2bb92543e2f7bcef4a9bc159ccdfbc728fc22e9b2ed5bb528-primary.xml.gz 7c20d73494e2525944a113b55983be13ba437e354da3e45f19f456b8f39457b4-other.xml.gz 9b353c421ef03be739e96d529e92393dfc4864205d974309a6af813e47893fff-filelists.sqlite.bz2 bd6c1976aae37a44ef7c7f9390c0321b4f7a27c4991e318f57b9c37016cb32fa-primary.sqlite.bz2 repomd.xml（3）创建软链接到 nginx 网页根目录# 创建 everything 源软链接到 nginx 网页根目录 $ ln -s /openEuler-22.03-LTS-REPO/openEuler-22.03-everything/ /usr/share/nginx/html/openEuler-22.03-LTS/everything/x86_643.1.5 同步 update 源（1）同步 update 源的 RPM 包到本地# 同步 update 源的 RPM 包到本地 $ dnf reposync -v --repoid=openEuler-22.03-update -p /openEuler-22.03-LTS-REPO # 同步完成后会在 /openEuler-22.03-LTS-REPO 目录创建一个名称同 repo name 的目录 $ ls /openEuler-22.03-LTS-REPO/ openEuler-22.03-update # 查看目录结构 $ tree -L 1 /openEuler-22.03-LTS-REPO/openEuler-22.03-update/ /openEuler-22.03-LTS-REPO/openEuler-22.03-update/ └── Packages（2）生成 update 源的 RPM 包元数据# 执行以下命令生成元数据 $ createrepo -v --workers 10 /openEuler-22.03-LTS-REPO/openEuler-22.03-update # 查看生成元数据后的目录结构 $ tree -L 1 /openEuler-22.03-LTS-REPO/openEuler-22.03-update /openEuler-22.03-LTS-REPO/openEuler-22.03-update ├── Packages └── repodata # 查看生成的元数据文件 $ ls /openEuler-22.03-LTS-REPO/openEuler-22.03-update/repodata 8943580f5aefe7f532fbbd9f19d771aaf9407a855b0acad33723007d8dde4199-primary.xml.gz ad1a113f7358bfebf9d13783d8fa8ce0a9b151725ecfc2da059226280422c30a-other.xml.gz bf573c34d9f77a76757a2a496b2c9ee671dddc81d660a95b063f8b81b8d7a4f9-filelists.sqlite.bz2 c6b747c4c6ee6cb6a44683b4a3636066cba5c9e573ea19ad95a5e315a9af1836-primary.sqlite.bz2 e152e3b11a7fcf011e16a27f7e6ba855ac12025b114ec5916e09d4edb0fa61e9-other.sqlite.bz2 f88eb68a9e41086c6b2de992367613c9b1e530bea82a73aa82e6faad6e5ed53d-filelists.xml.gz repomd.xml（3）创建软链接到 nginx 网页根目录# 创建 update 源软链接到 nginx 网页根目录 $ ln -s /openEuler-22.03-LTS-REPO/openEuler-22.03-update/ /usr/share/nginx/html/openEuler-22.03-LTS/update/x86_643.1.6 同步 EPOL 源（1）同步 EPOL 源的 RPM 包到本地# 同步 update 源的 RPM 包到本地 $ dnf reposync -v --repoid=openEuler-22.03-EPOL -p /openEuler-22.03-LTS-REPO # 同步完成后会在 /openEuler-22.03-LTS-REPO 目录创建一个名称同 repo name 的目录 $ ls /openEuler-22.03-LTS-REPO/ openEuler-22.03-EPOL # 查看目录结构 $ tree -L 1 /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL/ └── Packages（2）生成 EPOL 源的 RPM 包元数据# 执行以下命令生成元数据 $ createrepo -v --workers 10 /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL # 查看生成元数据后的目录结构 $ tree -L 1 /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL ├── Packages └── repodata # 查看生成的元数据文件 $ ls /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL/repodata 2d41ed62331b529104c7b04fd34680e8eeb8783e212e910e5230daaa66a900a4-filelists.sqlite.bz2 3445b86e5fd0157d0fd08aaf06cde6f1feca76517b574d8fdd3b40abe827b71e-other.xml.gz 709755e7d41e355645979f47b78155234bae9d50b2422105a4b03fca6ea93c83-filelists.xml.gz 70e673639de7efb802e65a54ce80e99c49ea93b1a8a4b4a676a47a91cadc99fa-primary.xml.gz 8c1cb6add3f18391a70436bed3bca18b9e0eac6861d8c5e2266c9952be3ea9f0-other.sqlite.bz2 bae172c52a64e4637d189780ff27d983e3c97bcbc17278f74afe0a23ab6e9ecd-primary.sqlite.bz2 repomd.xml（3）创建软链接到 nginx 网页根目录# 创建 EPOL 源软链接到 nginx 网页根目录 $ ln -s /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL/ /usr/share/nginx/html/openEuler-22.03-LTS/EPOL/main/x86_643.1.7 在前端界面查看 RPM 包使用 Windows 浏览器访问： http://192.168.255.221:8001，查看 RPM 包3.2 Client 端配置3.2.1 系统基本设置# 关闭防火墙，并停止开机自启 $ systemctl stop firewalld $ systemctl disable firewalld # 关闭 SELinux $ setenforce 03.2.2 配置 repo 源# 创建备份目录，将现有的 repo 源都移动到备份目录中 $ cd /etc/yum.repos.d/ $ mkdir bak $ mv ./* bak/ # 编写新的 repo 源，URL 地址指向局域网 repo 源服务器 cat > /etc/yum.repos.d/lan.repo <<EOF [openEuler-22.03-everything] name=openEuler-22.03-everything baseurl=http://192.168.255.221:8001/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-22.03-EPOL] name=openEuler-22.03-epol baseurl=http://192.168.255.221:8001/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-22.03-update] name=openEuler-22.03-update baseurl=http://192.168.255.221:8001/update/x86_64/ enabled=1 gpgcheck=0 EOF # 清空 yum 缓存 $ yum clean all # 重建 yum 缓存 $ yum makecache # 查看当前的 repo 源 $ yum repolist repo id repo name openEuler-22.03-EPOL openEuler-22.03-epol openEuler-22.03-everything openEuler-22.03-everything openEuler-22.03-update openEuler-22.03-update3.2.3 测试 repo 源# 随便搜索一个软件包 $ yum provides tree Last metadata expiration check: 0:08:11 ago on Wed 13 Dec 2023 04:36:36 PM CST. tree-1.8.0-2.oe2203.x86_64 : Tree file viewer tool Repo : openEuler-22.03-everything Matched from: Provide : tree = 1.8.0-2.oe2203 # 安装搜索的软件包 $ yum install -y tree4 使用 .iso 镜像搭建本地 repo 源4.1 基于 HTTP 协议搭建# 安装 httpd 服务及其他工具 $ yum install -y httpd createrepo # 修改配置文件，不显示默认网页 $ mv /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.bak $ sed -i '/^\s*DirectoryIndex/ s/index.html//' /etc/httpd/conf/httpd.conf # 挂载 everything 镜像 $ mount /dev/sr0 /mnt/ # 创建 repo 目录 $ mkdir -p /var/www/html/openEuler-LTS-SP1/Package # 从镜像中复制软件包到 repo 目录 $ cp /mnt/Packages/* /var/www/html/openEuler-LTS-SP1/Package/ # 生成元数据信息 $ createrepo -v --workers 20 /var/www/html/openEuler-LTS-SP1/ # 修改目录及文件权限 $ chmod 755 /var/www/html/openEuler-LTS-SP1/Package/ $ chmod 755 /var/www/html/openEuler-LTS-SP1/repodata/ $ chmod 644 /var/www/html/openEuler-LTS-SP1/Package/* $ chmod 644 /var/www/html/openEuler-LTS-SP1/repodata/* # 启动 httpd 服务 $ systemctl start httpd客户端编写 repo 文件：# 编写 repo 文件 $ cat > /etc/yum.repos.d/local.repo <<EOF [local-repo] name=local-repo baseurl=http://192.168.230.201/openEuler-LTS-SP1/ enabled=1 gpgcheck=0 EOF4.2 基于 FTP 协议搭建# 安装 vsftpd 服务及其他工具 $ yum install -y vsftpd createrepo # 配置 vsftpd 服务，允许匿名用户登录 $ sed -i '/^anonymous_enable/c anonymous_enable=YES' /etc/vsftpd/vsftpd.conf # 挂载 everything 镜像 $ mount /dev/sr0 /mnt/ # 创建 repo 目录 $ mkdir -p /var/ftp/pub/openEuler-22.03-LTS-SP1/Packages # 从镜像中复制软件包到 repo 目录 $ cp /mnt/Packages/* /var/ftp/pub/openEuler-22.03-LTS-SP1/Packages/ # 生成元数据信息 $ createrepo -v --workers 20 /var/ftp/pub/openEuler-22.03-LTS-SP1/ # 启动 vsftpd 服务 $ systemctl start vsftpd客户端编写 repo 文件：# 编写 repo 文件 $ cat > /etc/yum.repos.d/local.repo <<EOF [local-repo] name=local-repo baseurl=ftp://192.168.230.201/pub/openEuler-22.03-LTS-SP1/ enabled=1 gpgcheck=0 EOF