本文由 Anthropic Claude Opus 4.6 模型自动生成。Claude Code 是 Anthropic 官方推出的 AI 编程助手命令行工具（CLI），可在终端中以自然语言驱动代码编写、调试与重构。本文将详细介绍如何在 Windows 系统上完成安装与配置，并涵盖 VS Code 集成使用。1. 环境要求项目最低要求操作系统Windows 10 / 11GitGit for Windows（详见第 2 节）Node.js（仅 npm 方式需要）≥ 18.0VS Code（如需扩展）≥ 1.98.0内存≥ 4 GB（推荐 8 GB）订阅计划Claude Pro / Max / Teams / Enterprise，或 API Key（按量付费）网络需要稳定的互联网连接2. 前置准备：安装 GitClaude Code 依赖 Git，所有安装方式均需要预先安装 Git for Windows。访问 Git 官网：https://git-scm.com/downloads/win下载并安装 Git for Windows，安装过程中建议勾选 "Git Bash Here" 上下文菜单选项。验证安装：git --version3. 安装 Claude Code CLI提供三种安装方式，推荐程度由高到低排列。方式一：PowerShell 一键安装（推荐）这是官方推荐的 Windows 原生安装方式，无需预装 Node.js，且支持后台自动更新。安装脚本会将 Claude Code 独立二进制文件下载至 C:\Users\<用户名>\.local\bin 目录，并自动将其添加到用户 PATH。打开 PowerShell（无需管理员权限）。执行以下命令：irm https://claude.ai/install.ps1 | iex安装完成后，关闭并重新打开终端（PATH 更新需要新会话生效），然后验证安装：claude --version方式二：WinGet 安装如果你的系统已内置 WinGet（Windows 10 1709+ / Windows 11 默认包含），可执行：winget install Anthropic.ClaudeCode与 PowerShell 一键安装类似，此方式同样无需 Node.js，支持自动更新。方式三：npm 全局安装适合已有 Node.js 开发环境、或需要精确锁定特定版本的用户。前置步骤：安装 Node.js访问 Node.js 官网：https://nodejs.org/下载 LTS（长期支持版） 安装包（≥ 18.0）。运行安装程序，保持默认选项即可（建议勾选 "Add to PATH"）。验证安装：node -v # 应输出 v18.x.x 或更高版本 npm -v # 应输出 npm 版本号安装 Claude Code打开 Git Bash 或 PowerShell，执行：npm install -g @anthropic-ai/claude-code注意：请勿使用 sudo。如遇权限错误（EACCES），应修复 npm 全局目录权限，而非提权安装。npm 方式不支持自动更新，需手动执行 npm update -g @anthropic-ai/claude-code 升级。验证安装成功：claude --version三种安装方式对比对比项PowerShell 一键安装WinGetnpm 全局安装是否需要 Node.js否否是（≥ 18）自动更新支持支持不支持（需手动）安装位置~\.local\bin系统管理npm 全局目录版本锁定支持支持支持需要管理员权限否否否4. 身份认证安装完成后，需要进行身份认证才能使用。方式一：OAuth 浏览器登录（推荐）适用于 Claude Pro / Max / Teams / Enterprise 订阅用户。在终端中启动 Claude Code：claude首次运行时会自动打开默认浏览器，跳转至 Anthropic 授权页面。使用你的 Claude 账号登录并授权即可。方式二：API Key 认证适用于按量付费用户。前往 Anthropic Console 获取 API Key：https://console.anthropic.com/在「API Keys」页面创建新的密钥并妥善保存。设置环境变量（PowerShell）：# 临时设置（仅当前会话有效） $env:ANTHROPIC_API_KEY = "sk-ant-xxxxx" # 永久设置（写入用户环境变量） [System.Environment]::SetEnvironmentVariable("ANTHROPIC_API_KEY", "sk-ant-xxxxx", "User")启动 Claude Code：claude安全提示： 建议通过系统环境变量或密钥管理器存储 API Key，避免将其明文写入脚本或配置文件中。方式三：通过 settings.json 配置文件适用于使用第三方 API 中转服务或需要持久化配置的用户。找到用户级全局配置文件，路径为：%USERPROFILE%\.claude\settings.json即 C:\Users\<你的用户名>\.claude\settings.json。如果文件不存在，手动创建即可。在文件中通过 env 字段设置认证信息：{ "env": { "ANTHROPIC_API_KEY": "sk-ant-xxxxx" } }如需指向自定义 API 端点（例如第三方中转服务），可同时配置 ANTHROPIC_BASE_URL：{ "env": { "ANTHROPIC_AUTH_TOKEN": "sk-xxxxx", "ANTHROPIC_BASE_URL": "https://your-proxy-endpoint.example.com" } }说明：settings.json 中的 env 字段会在 Claude Code 启动时自动注入为环境变量，无需手动执行 export 或 $env: 设置。该文件为用户级全局配置，对所有项目生效。如需项目级配置，可在项目根目录下创建 .claude/settings.local.json，结构相同。此方式的优先级高于系统环境变量。5. 在 VS Code 中使用 Claude CodeClaude Code 提供了官方 VS Code 扩展，可在编辑器内直接与 Claude 交互。5.1 安装扩展打开 VS Code（要求版本 ≥ 1.98.0）。按 Ctrl + Shift + X 打开 扩展（Extensions） 面板。在搜索框中输入 "Claude Code"。找到由 Anthropic 发布的官方扩展，点击 Install 安装。也可通过 VS Code Marketplace 页面直接安装：https://marketplace.visualstudio.com/items?itemName=anthropic.claude-code5.2 登录认证安装完成后：VS Code 侧边栏（Activity Bar）会出现 Claude Code 图标。点击图标打开 Claude Code 面板。首次使用时，按提示完成 OAuth 登录或输入 API Key。5.3 基本使用操作说明打开 Claude 面板点击侧边栏 Claude 图标，或使用快捷键 Ctrl + L提问 / 下达指令在输入框中用自然语言描述需求，如 "重构这个函数"引用选中代码在编辑器中选中代码后打开 Claude 面板，选中内容会自动作为上下文传入应用代码建议Claude 生成的代码修改可直接 Diff 预览并一键应用到文件终端集成Claude 可直接在 VS Code 集成终端中执行命令5.4 常用工作流示例用户：解释一下这段代码的作用 用户：给 calculateTotal 函数添加单元测试 用户：把这个组件从 Class 组件重构为函数组件 用户：查找项目中所有未处理的 Promise 异常6. 卸载 Claude Code CLI根据你使用的安装方式，选择对应的卸载方法。6.1 PowerShell 一键安装的卸载删除安装目录中的 Claude Code 二进制文件：Remove-Item "$env:USERPROFILE\.local\bin\claude.exe" -Force（可选）清理用户配置数据：Remove-Item "$env:USERPROFILE\.claude" -Recurse -Force（可选）从用户 PATH 中移除 %USERPROFILE%\.local\bin（如该目录下已无其他工具）：# 查看当前用户 PATH [System.Environment]::GetEnvironmentVariable("PATH", "User") # 手动编辑移除对应路径，或通过"系统属性 → 环境变量"界面操作6.2 WinGet 安装的卸载winget uninstall Anthropic.ClaudeCode如需同时清理配置数据：Remove-Item "$env:USERPROFILE\.claude" -Recurse -Force6.3 npm 全局安装的卸载npm uninstall -g @anthropic-ai/claude-code如需同时清理配置数据：Remove-Item "$env:USERPROFILE\.claude" -Recurse -Force提示： ~\.claude 目录中包含认证信息、用户配置及对话历史。如果你打算重新安装，可以保留该目录以免重新配置。7. Windows 常见问题与注意事项Q1：出现 "MSVCP140.dll was not found" 错误原因： 缺少 Microsoft Visual C++ 运行时库。解决方案： 下载并安装最新的 Visual C++ Redistributable：https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redistQ2：MCP Server 在 Windows 上配置异常在 Windows 下配置 MCP（Model Context Protocol）服务器时，需使用 cmd /c 包裹 npx 命令。在项目根目录的 .mcp.json 中：{ "mcpServers": { "example": { "command": "cmd", "args": ["/c", "npx", "your-mcp-server"] } } }Q3：npm 安装后 claude 命令无法识别排查步骤：确认 npm 全局目录在系统 PATH 中：npm config get prefix将输出路径添加到系统环境变量 PATH。重新打开终端后重试。Q4：代理/网络问题导致安装失败如在公司网络或代理环境下安装失败，尝试配置 npm 代理：npm config set proxy http://your-proxy:port npm config set https-proxy http://your-proxy:port8. 相关资源资源链接Claude Code 官方文档https://docs.anthropic.com/en/docs/claude-codeClaude Code GitHub 仓库https://github.com/anthropics/claude-codenpm 包页面https://www.npmjs.com/package/@anthropic-ai/claude-codeVS Code 扩展页面https://marketplace.visualstudio.com/items?itemName=anthropic.claude-codeNode.js 下载https://nodejs.org/Git for Windows 下载https://git-scm.com/downloads/winAnthropic Console（API Key 管理）https://console.anthropic.com/本文档最后更新时间：2026 年 3 月
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
1 环境准备本文所有环境基于 openEuler 22.03 LTS SP4 操作系统1.1 网络环境# 配置代理 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}1.2 安装 cuda# 安装基础工具及内核开发包 $ yum install -y gcc-c++ make dkms kernel-source-$(uname -r) kernel-devel-$(uname -r) # 下载 cuda 包 $ wget https://repo.oepkgs.net/openEuler/rpm/openEuler-22.03-LTS-SP4/contrib/drivers/x86_64/Packages/cuda_12.4.0_550.54.14_linux.run -P /root # 安装 cuda 包 $ sh /root/cuda_12.4.0_550.54.14_linux.run ...... =========== = Summary = =========== Driver: Installed Toolkit: Installed in /usr/local/cuda-12.4/ Please make sure that - PATH includes /usr/local/cuda-12.4/bin - LD_LIBRARY_PATH includes /usr/local/cuda-12.4/lib64, or, add /usr/local/cuda-12.4/lib64 to /etc/ld.so.conf and run ldconfig as root To uninstall the CUDA Toolkit, run cuda-uninstaller in /usr/local/cuda-12.4/bin To uninstall the NVIDIA Driver, run nvidia-uninstall Logfile is /var/log/cuda-installer.log # 配置 PATH 变量 $ sed -i \ -e '$a \ ' \ -e "\$a export PATH=$PATH" \ -e '$a export PATH=$PATH:/usr/local/cuda-12.4/bin' \ /etc/profile # 刷新 /etc/profile 文件 $ source /etc/profile # 配置库文件 $ sed -i '$a /usr/local/cuda-12.4/lib64' /etc/ld.so.conf # 刷新动态链接库 $ ldconfig # 查看 Nvidia 驱动版本 $ nvidia-smi # 查看 cuda 版本 $ nvcc --version nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2024 NVIDIA Corporation Built on Tue_Feb_27_16:19:38_PST_2024 Cuda compilation tools, release 12.4, V12.4.99 Build cuda_12.4.r12.4/compiler.33961263_01.3 安装 docker1.3.1 安装 docker# 定义要安装的 docker 版本及架构（x86_64、aarch64） $ DOCKER_VERSION=26.0.0; DOCKER_ARCH=x86_64 # 从官方仓库下载二进制 docker 压缩包 $ wget https://download.docker.com/linux/static/stable/"${DOCKER_ARCH}"/docker-"${DOCKER_VERSION}".tgz -P /root # 解压下载的压缩包 $ tar -xvf /root/docker-"${DOCKER_VERSION}".tgz -C /root # 复制解压的命令到 /usr/bin 目录 $ cp /root/docker/* /usr/bin # 创建 docker 组，否则会有 could not change group /var/run/docker.sock to docker: group docker not found 的警告信息，并且 cir-docker 会启动失败 $ groupadd docker # 编写启动文件 $ cat > /etc/systemd/system/docker.service <<"EOF" [Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target firewalld.service Wants=network-online.target [Service] Type=notify ExecStart=/usr/bin/dockerd ExecReload=/bin/kill -s HUP $MAINPID LimitNOFILE=infinity LimitNPROC=infinity TimeoutStartSec=0 Delegate=yes KillMode=process Restart=on-failure StartLimitBurst=3 StartLimitInterval=60s [Install] WantedBy=multi-user.target EOF # 配置代理 $ 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 # 修改 cgroup 为 systemd，修改日志驱动 $ [ ! -d "/etc/docker" ] && mkdir /etc/docker cat > /etc/docker/daemon.json <<EOF { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" } } EOF # 重新加载配置 $ systemctl daemon-reload # 启动（重启） docker $ systemctl restart docker && systemctl enable docker # 查看代理、Cgroup 驱动、日志驱动配置 $ docker info | grep -E "Proxy|Cgroup Driver|Logging Driver" Logging Driver: json-file Cgroup Driver: systemd HTTP Proxy: http://192.168.230.1:10809 HTTPS Proxy: http://192.168.230.1:10809 No Proxy: localhost,127.0.0.11.3.2 安装 docker-compose# 创建插件目录 $ mkdir -p /usr/libexec/docker/cli-plugins # 定义要安装的 docker-compose 版本及架构（x86_64、aarch64） $ COMPOSE_VERSION=2.33.0; COMPOSE_ARCH=x86_64 # 从官方仓库下载二进制 docker-compose 命令 $ wget https://github.com/docker/compose/releases/download/v"${COMPOSE_VERSION}"/docker-compose-linux-"${COMPOSE_ARCH}" -P /root # 安装 docker-compose $ install -m 755 /root/docker-compose-linux-"${COMPOSE_ARCH}" /usr/libexec/docker/cli-plugins/docker-compose # 验证 docker-compose 是否安装成功 $ docker compose version Docker Compose version v2.33.02 安装（卸载）ollama2.1 安装 ollama2.1.1 在线安装参考文档：ollama/docs/linux.md at main · ollama/ollama · GitHub# 安装 ollama（若不指定版本则安装最新版本） $ curl -fsSL https://ollama.com/install.sh | OLLAMA_VERSION=0.5.11 sh # 修改 ollama 监听地址，默认监听在回环网卡 $ sed -i '/^Environment=.*/i Environment="OLLAMA_HOST=0.0.0.0:11434"' /etc/systemd/system/ollama.service # 重新加载配置 $ systemctl daemon-reload # 重新启动 ollama $ systemctl restart ollama # 查看监听的地址 $ netstat -anpt | grep ollama tcp6 0 0 :::11434 :::* LISTEN 110562/ollama2.1.2 本地安装参考文档：ollama/docs/linux.md at main · ollama/ollama · GitHub# 指定要安装的 ollama 版本及架构（amd64、arm64） $ OLLAMA_VERSION=0.5.11; OLLAMA_ARCH=amd64 # 下载安装包 $ wget https://github.com/ollama/ollama/releases/download/v"${OLLAMA_VERSION}"/ollama-linux-"${OLLAMA_ARCH}".tgz -P /root # 解压并安装 $ tar -xvf /root/ollama-linux-"${OLLAMA_ARCH}".tgz -C /usr # 创建 ollama 用户、组 $ useradd -r -s /bin/false -U -m -d /usr/share/ollama ollama usermod -a -G ollama $(whoami) # 编写 service 文件 $ cat > /etc/systemd/system/ollama.service <<EOF [Unit] Description=Ollama Service After=network-online.target [Service] ExecStart=/usr/bin/ollama serve User=ollama Group=ollama Restart=always RestartSec=3 Environment="OLLAMA_HOST=0.0.0.0:11434" Environment="PATH=$PATH" [Install] WantedBy=default.target EOF # 重载配置文件 $ systemctl daemon-reload # 启动 ollama 并设置开机自启 $ systemctl start ollama && systemctl enable ollama # 查看监听的地址 $ netstat -anpt | grep ollama tcp6 0 0 :::11434 :::* LISTEN 2650/ollama2.2 卸载 ollama# 停止 ollama 服务 $ systemctl stop ollama && systemctl disable ollama # 删除 service 文件 $ rm -rf /etc/systemd/system/ollama.service # 删除 ollama 二进制文件 $ rm -rf $(which ollama) # 删除 ollama 库文件 $ rm -rf /usr/local/lib/ollama # 删除 ollama 用户、组 $ groupdel ollama userdel ollama # 删除家目录（同时会删除家目录下的大模型文件） $ rm -rf /usr/share/ollama2.3 ollama 使用指南2.3.1 命令使用指南$ ollama Usage: ollama [flags] ollama [command] Available Commands: serve Start ollama # 启动 ollama 服务 create Create a model from a Modelfile # 从 Modelfile 文件创建模型 show Show information for a model # 显示模型信息 run Run a model # 运行模型，若不存在则先下载 stop Stop a running model # 停止正在运行的模型 pull Pull a model from a registry # 从仓库拉取模型 push Push a model to a registry # 推送模型到仓库 list List models # 列出所有模型 ps List running models # 列出正在运行的模型并查看资源消耗 cp Copy a model # 复制模型 rm Remove a model # 删除模型 help Help about any command # 查看命令帮助 Flags: -h, --help help for ollama # 查看命令帮助 -v, --version Show version information # 查看版本2.3.2 相关环境变量（1）OLLAMA_HOST：指定 ollama 服务的监听地址及端口参考文档：ollama/api/client.go at main · ollama/ollama · GitHub使用场景：ollama 服务默认监听地址为 127.0.0.1，需要从外部访问或调用 ollama 服务使用方法：指定监听的地址和端口 OLLAMA_HOST=0.0.0.0:11434（2）OLLAMA_NUM_PARALLEL：每个模型同时处理的并行请求的最大数量参考文档：ollama/docs/faq.md at main · ollama/ollama · GitHub使用场景：每个模型需要处理多个并发使用方法：默认值将根据可用内存自动选择 4 或 1，若有需要可以手动调整 OLLAMA_NUM_PARALLEL=10（3）OLLAMA_MAX_QUEUE：当 ollama 忙碌时，它在拒绝额外请求之前将排队的最大请求数量参考文档：ollama/docs/faq.md at main · ollama/ollama · GitHub使用场景：调整 ollama 忙碌时可以排队的最大请求数量使用方法： 默认值是 512，若有需要可以手动调整 OLLAMA_MAX_QUEUE=256（4）OLLAMA_MAX_LOADED_MODELS：可同时加载的最大模型数量参考文档：ollama/docs/faq.md at main · ollama/ollama · GitHub使用场景：同时需要加载多个模型（如果已加载一个或多个模型时，没有足够的可用内存来加载新的模型请求，所有新的请求将被排队，直到新模型能够被加载。当先前的模型变为闲置时，将卸载一个或多个模型以腾出空间给新模型。排队的请求将按顺序处理。在使用 GPU 推理时，新模型必须能够完全适应 VRAM，以允许并发加载模型。）使用方法：默认值为 CPU 或 GPU 的 3 倍，若有需要可以手动调整 OLLAMA_MAX_LOADED_MODELS=6（5）CUDA_VISIBLE_DEVICES：限制 ollama 可使用的 NVIDIA 显卡参考文档：ollama/docs/gpu.md at main · ollama/ollama · GitHub使用场景：系统中有多块 NVIDIA 显卡，需要限制 ollama 只使用其中一部分或完全不使用显卡使用方法：使用数字 ID：执行 nvidia-smi 命令获取显卡的序号，然后定义环境变量 CUDA_VISIBLE_DEVICES=0,1使用 UUID：执行 nvidia-smi -L 命令获取显卡 UUID，然后定义环境变量 CUDA_VISIBLE_DEVICES=GPU-1831a5ee-622a-7e65-06cc-d57de8902585,GPU-d21e966e-7a89-884f-d0b2-444d371bb8f9不使用显卡：若想忽略显卡并强制使用 CPU，可以使用一个无效的 GPU ID，例如 CUDA_VISIBLE_DEVICES=-13 安装（使用）Dify3.1 安装 Dify参考文档：Docker Compose 部署 | Dify# 克隆 Dify 源代码至本地环境 $ git clone https://github.com/langgenius/dify.git # 进入 Dify 源代码目录 $ cd dify # 切换到需要的版本 $ git checkout 0.15.3 # 进入 Dify 源代码的 Docker 目录 $ cd docker # 复制环境配置文件 $ cp .env.example .env # 启动 Docker 容器 $ docker compose up -d [+] Running 74/74 ✔ api Pulled 211.9s ✔ sandbox Pulled 213.7s ✔ redis Pulled 161.0s ✔ weaviate Pulled 8.8s ✔ worker Pulled 211.9s ✔ db Pulled 157.2s ✔ web Pulled 133.0s ✔ ssrf_proxy Pulled 83.6s ✔ nginx Pulled 19.2s [+] Running 11/11 ✔ Network docker_default Created 0.0s ✔ Network docker_ssrf_proxy_network Created 0.0s ✔ Container docker-web-1 Started 0.4s ✔ Container docker-sandbox-1 Started 0.3s ✔ Container docker-ssrf_proxy-1 Started 0.5s ✔ Container docker-redis-1 Started 0.3s ✔ Container docker-weaviate-1 Started 0.4s ✔ Container docker-db-1 Started 0.4s ✔ Container docker-api-1 Started 0.5s ✔ Container docker-worker-1 Started 0.6s ✔ Container docker-nginx-1 Started 0.7s # 查看 3 个业务服务 api/worker/web，以及 6 个基础组件 weaviate/db/redis/nginx/ssrf_proxy/sandbox 是否运行 $ docker compose ps在 Windows 浏览器中访问 http://${your_server_ip}/install 进入管理员初始化页面，设置管理员账户在 Windows 浏览器中访问 http://${your_server_ip} 进入主页面
基于 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
北京到了深秋时节，最美的莫过于映衬在黄瓦红墙下金色的银杏与夹杂在绿树青山中火红的枫叶 对于有北京最美赏秋地之称的故宫、中山公园、地坛公园等白天的照片已经看的够多了 公历2024年11月16日，正好是农历的十月十六，俗话说十五的月亮十六圆，此次也毫不例外，更是本年最后的最大满月 既已月色入户，何不欣然起行？遂至景山公园 ，记录下晚上美好的瞬间 拍摄设备：佳能 EOS R6 Mark2 + RF24-105 F4 + RF16 F2.8 {dotted startColor="#1989fa" endColor="#1989fa"/}故宫西北角楼 {lamp/}从角楼远眺神武门（一） {lamp/}银杏与神武门交相辉映 {lamp/}从角楼远眺神武门（二）{lamp/}从角楼远眺神武门（三）{lamp/}故宫神武门广场 {lamp/}从景山俯瞰故宫 {lamp/}景山万春亭 {lamp/}仙人望月 {lamp/}景山富览亭 {lamp/}从景山远望中央广播电视总台大楼和中信大厦 {lamp/}华表与国徽 {lamp/}
基于 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