<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>DevNull</title><description>No description</description><link>https://blog.devnu11.cn/</link><templateTheme>Firefly</templateTheme><templateThemeVersion>6.11.0</templateThemeVersion><templateThemeUrl>https://github.com/CuteLeaf/Firefly</templateThemeUrl><lastBuildDate>2026年7月10日 17:07:53</lastBuildDate><item><title>我是如何给「残疾」国产模型接上眼睛和联网的</title><link>https://blog.devnu11.cn/posts/%E6%88%91%E6%98%AF%E5%A6%82%E4%BD%95%E7%BB%99-%E6%AE%8B%E7%96%BE-%E5%9B%BD%E4%BA%A7%E6%A8%A1%E5%9E%8B%E6%8E%A5%E4%B8%8A%E7%9C%BC%E7%9D%9B%E5%92%8C%E8%81%94%E7%BD%91%E7%9A%84/</link><guid isPermaLink="true">https://blog.devnu11.cn/posts/%E6%88%91%E6%98%AF%E5%A6%82%E4%BD%95%E7%BB%99-%E6%AE%8B%E7%96%BE-%E5%9B%BD%E4%BA%A7%E6%A8%A1%E5%9E%8B%E6%8E%A5%E4%B8%8A%E7%9C%BC%E7%9D%9B%E5%92%8C%E8%81%94%E7%BD%91%E7%9A%84/</guid><description>众所周知，大部分国产主流模型都是没有多模态识图能力的，甚至接入 Claude Code 之后连网络搜索都无法调用。本文分享我如何通过自研 skill 和 MCP 工具，为国产模型补齐视觉与联网短板。</description><pubDate>Tue, 30 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;前两天我在折腾 Claude Code 的模型配置，想着把智谱的 GLM-5.2 接进去试试效果。代码补全倒是挺流畅的，上下文理解也还行，正当我美滋滋地觉得「国产模型真香」的时候，随手往对话框里丢了一张截图。&lt;/p&gt;
&lt;p&gt;结果是一行报错,错误码400。&lt;/p&gt;
&lt;p&gt;我盯着那个错误提示愣了一下,反应过来之后才想到，对哦，GLM-5.2 没有多模态识图能力。不光是智谱，你去看看 DeepSeek、Qwen 这些国产主流模型，在 Claude Code 的接口兼容层里，代码生成和工具调用都能跑通，唯独图片输入这块，全军覆没。&lt;/p&gt;
&lt;p&gt;这还不是最离谱的。&lt;/p&gt;
&lt;p&gt;更离谱的是，因为国产模型不支持 Anthropic 原生的服务端工具，连 &lt;code&gt;web_fetch&lt;/code&gt; 这个用来抓取网页内容的工具都调用不了。你让它去查个最新版本的 React 文档，它直接开始给你背训练数据里的过时内容，信誓旦旦地给你推荐已经废弃的 API。&lt;/p&gt;
&lt;p&gt;就很崩溃。&lt;/p&gt;
&lt;p&gt;想象一下，一个 AI 助手，看不见你屏幕上的报错截图，也上不了网查资料，只能靠着脑子里那堆不知道啥时候的数据瞎猜。这哪是人工智能啊，这分明是人工智障。&lt;/p&gt;
&lt;p&gt;我当时就在想，不行，得给它装上义体。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;我先把问题拆成两块。&lt;/p&gt;
&lt;p&gt;第一块是眼睛。模型看不见图片，那我们就给它配个眼镜。&lt;/p&gt;
&lt;p&gt;我自己写了一个 skill，叫 &lt;code&gt;/recognize-image&lt;/code&gt;。原理其实挺朴素的，既然大模型本身没有视觉能力，那就让它当一个指挥官，遇到图片的时候，自己构造一段详细的提示词，然后把图片丢给能识图的小模型去处理。小模型看完图之后，把看到的内容用文字描述返回给大模型。大模型拿到这个描述，就相当于「看」到了图片。&lt;/p&gt;
&lt;p&gt;整个过程对用户来说是无感的。你照常把图片发过去，后台会自动走这套流程。&lt;/p&gt;
&lt;p&gt;但这里又冒出来一个坑。&lt;/p&gt;
&lt;p&gt;Claude Code 的 VSCode 插件，默认行为是直接把粘贴的图片塞进消息里发给模型。这对于 Claude 原生的多模态模型没问题，但换成国产模型之后，因为不支持图片工具，直接就会报错。所以我改了一下插件的逻辑，让粘贴的图片先保存到本地临时目录，然后把图片路径以文本形式插入到对话里。这样 skill 就能读取到这个路径，再去调用识图流程。&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;/images/posts/b78d42d4-0854-499f-bdf3-ef1af54845c0.png&quot; alt=&quot;改造后的粘贴效果&quot; /&gt;&lt;figcaption&gt;改造后的粘贴效果&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;坦率的讲，这个改造挺粗暴的，就是在插件的粘贴事件里加了一层拦截。但效果出奇地好。现在我可以直接截图、粘贴，国产模型也能「看」图说话了。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;第二块是搜索。模型上不了网，那我们就给它配个浏览器。&lt;/p&gt;
&lt;p&gt;Claude Code 自带的 &lt;code&gt;web_fetch&lt;/code&gt; 工具，本质上依赖的是 Anthropic 的服务端能力。你把 &lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt; 指向国产模型的兼容接口之后，这个工具就直接废掉了。我试过几次，模型要么假装自己调了工具然后胡编内容，要么直接报错说工具不可用。&lt;/p&gt;
&lt;p&gt;那怎么办呢？&lt;/p&gt;
&lt;p&gt;我的方案是，在 Claude Code 的通用规则提示词里，明确告诉 AI 禁用 &lt;code&gt;web_fetch&lt;/code&gt; 工具。然后给它配两个 MCP 服务，一个叫 &lt;code&gt;tavily&lt;/code&gt;，一个叫 &lt;code&gt;cc-web&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;Tavily 是一个专门给 AI 用的搜索引擎 API，返回的结果已经是清洗过的、适合大模型直接阅读的格式。你先去 tavily.ai 注册个账号，拿到 API key，然后在 Claude Code 的 MCP 配置里加上这么一段：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;mcpServers&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;tavily&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;npx&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;args&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;span&gt;&quot;-y&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;@tavily/mcp&quot;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;env&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;TAVILY_API_KEY&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;你的key&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;配置完之后，你问 AI 「React 19 有什么新特性」，它就不会再去翻自己脑子里的陈年老黄历了，而是直接走 Tavily 去搜最新的文档和博客，然后把结果整理成回答给你。&lt;/p&gt;
&lt;p&gt;但是有个现实问题。Tavily 的免费额度是每月 1000 次调用，对个人轻度使用来说够用了，但如果你跟我一样，动不动就让 AI 去查一堆资料，很快就会把额度烧光。&lt;/p&gt;
&lt;p&gt;怎么办呢？&lt;/p&gt;
&lt;p&gt;有个比较骚的操作。Tavily 支持一个账号注册多个 API key，而且免费额度是按 key 算的。所以你可以注册好几个账号，搞一堆 key，然后在配置里做一个轮询逻辑。我在本机就是这么配的，写了个简单的代理层，每次请求自动换 key，相当于白嫖了 N 倍的免费额度。&lt;/p&gt;
&lt;p&gt;当然如果你嫌麻烦，直接充钱也行，Tavily 的付费版也不贵。&lt;/p&gt;
&lt;p&gt;那 &lt;code&gt;cc-web&lt;/code&gt; 是干嘛的呢？它是兜底方案。当 Tavily 因为某些原因搜不到结果，或者返回的内容不够完整的时候，&lt;code&gt;cc-web&lt;/code&gt; 就会顶上，直接去抓取指定的网页内容。这两个工具一主一备，基本上就能覆盖所有的搜索需求了。&lt;/p&gt;
&lt;p&gt;我在提示词里给 AI 定的优先级很明确，先走 Tavily，Tavily 搞不定的再丢给 cc-web，web_fetch 直接禁用。这样一套组合拳下来，国产模型在 Claude Code 里也能实时联网了。&lt;/p&gt;
&lt;p&gt;为了验证这套方案到底能不能用，我特意设计了一个复合任务，同时测识图和联网两个能力。&lt;/p&gt;
&lt;p&gt;我给 AI 丢了一张 SQL 注入靶场的截图，让它识图，同时让它去调研 GPT 和 Claude 的最新模型信息。&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;/images/posts/b836d04b-e5f4-41b4-91d9-defd3429c3ca.png&quot; alt=&quot;同时发起识图和联网请求&quot; /&gt;&lt;figcaption&gt;同时发起识图和联网请求&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;AI 收到之后，一边调用 recognize-image 去识别那张截图，一边通过 Tavily 搜索最新模型资讯。两个操作并行执行，互不干扰。&lt;/p&gt;
&lt;p&gt;最后它给我的汇报是这样的。&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;/images/posts/a4a1c6eb-5fbe-4fb4-8f86-53445d875c79.png&quot; alt=&quot;识图和联网的汇报结果&quot; /&gt;&lt;figcaption&gt;识图和联网的汇报结果&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;截图里的 SQL 注入 payload 被完整识别出来了，数据库列表也读得准。GPT 和 Claude 的最新动态也都搜到了，没有给我编造假消息。&lt;/p&gt;
&lt;p&gt;到这一步我才真的松了一口气。国产模型不是不能用，它只是缺了几块拼图。你把眼睛和浏览器给它配齐，它照样能干活。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;说实话，折腾完这一套之后，我的感受挺复杂的。&lt;/p&gt;
&lt;p&gt;一方面，确实爽。现在我的 Claude Code 配置里默认就是 GLM-5.2，代码写得又快又准，还能看图、能上网，使用体验跟 Claude 原生模型已经差不了太多了。成本还低了一大截。&lt;/p&gt;
&lt;p&gt;但另一方面，又有点心酸。&lt;/p&gt;
&lt;p&gt;为什么用户要自己写 skill、改插件、配 MCP、搞多 key 轮询，才能让一个国产模型正常地「看见」和「搜索」？这些能力在 Claude、GPT 那边都是开箱即用的。国产模型在基础能力上追得很快，但在生态兼容和工具链的完整性上，差距还是挺明显的。&lt;/p&gt;
&lt;p&gt;我不是说国产模型不行。GLM-5.2 的代码能力真的挺强的，DeepSeek V4 的逻辑推理也很惊艳。但就像一个视力正常的人和一个戴眼镜的人，虽然最终都能看清世界，但那个戴眼镜的人永远要多一道工序。&lt;/p&gt;
&lt;p&gt;我写 recognize-image 这个 skill，改 VSCode 插件的配置，配 Tavily 的 MCP，做 key 的轮询。这些操作对于普通用户来说，门槛其实挺高的。你需要懂一点代码，需要知道什么是 MCP，需要能看懂报错信息，需要愿意花时间去折腾。&lt;/p&gt;
&lt;p&gt;那那些不懂代码的普通用户呢？他们就活该用着一个看不见、搜不了的「残疾人」模型吗？&lt;/p&gt;
&lt;p&gt;我觉得不是。&lt;/p&gt;
&lt;p&gt;所以我把这些经验写下来，把配置方法分享出来。不是说这些东西有多牛逼，而是希望能帮更多人少走点弯路。技术进步的最终目的，应该是让所有人都能平等地享受它带来的便利，而不是制造新的信息鸿沟。&lt;/p&gt;
&lt;p&gt;说到底，给模型装上眼睛和浏览器，其实也是在给我们自己争取更多的选择权。&lt;/p&gt;
&lt;p&gt;不用被某一家厂商绑架，不用因为某个功能缺失就被迫放弃一个性价比很高的模型。你想用 GLM 就用 GLM，想用 DeepSeek 就用 DeepSeek，我来帮你把缺失的拼图补上。&lt;/p&gt;
&lt;p&gt;这可能也是独立开发者在这个时代的某种价值吧。&lt;/p&gt;</content:encoded></item><item><title>我为自己造了个治理 AI 写代码的小工具，后来发现别人早就做了</title><link>https://blog.devnu11.cn/posts/%E6%88%91%E4%B8%BA%E8%87%AA%E5%B7%B1%E9%80%A0%E4%BA%86%E4%B8%AA%E6%B2%BB%E7%90%86ai%E5%86%99%E4%BB%A3%E7%A0%81%E7%9A%84%E5%B0%8F%E5%B7%A5%E5%85%B7/</link><guid isPermaLink="true">https://blog.devnu11.cn/posts/%E6%88%91%E4%B8%BA%E8%87%AA%E5%B7%B1%E9%80%A0%E4%BA%86%E4%B8%AA%E6%B2%BB%E7%90%86ai%E5%86%99%E4%BB%A3%E7%A0%81%E7%9A%84%E5%B0%8F%E5%B7%A5%E5%85%B7/</guid><description>AI 写代码很容易乱，所以我弄了个小工具管一下。写到一半发现 GSD 也在做同样的事，但我最后选择了继续用自己的。</description><pubDate>Mon, 15 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;我有一个自己的个人工具箱项目，放在本地，叫「项目管理工具」。不大，就是一些我自己常用的脚本和小功能，平时维护着玩。前段时间我想给它加几个新模块，就让 AI 帮忙写。&lt;/p&gt;
&lt;p&gt;一开始还挺顺的。我跟 AI 说了项目结构，哪些文件能动，哪些不能动，用什么技术栈，代码风格是什么样的。它听懂了，写得也还行。&lt;/p&gt;
&lt;p&gt;但聊着聊着，事情开始变得诡异。&lt;/p&gt;
&lt;p&gt;大概聊到第三四十轮的时候，我发现 AI 开始「失忆」了。前面明明说过「这个文件是核心配置，别动」，它突然又开始改。我提醒它一次，它道歉，改回去。再过几轮，它又忘了。&lt;/p&gt;
&lt;p&gt;我一开始以为是提示词没写好。后来才明白，不是它不想记住，是它的上下文窗口就那么大。几十轮对话之后，最早说的那些约束已经被压缩得稀碎，它根本读不到了。那些我反复强调的「不要改这里」「用这个风格」「注意兼容老版本」，对它来说就像从来没说过一样。&lt;/p&gt;
&lt;p&gt;更崩溃的是换 agent 的时候。&lt;/p&gt;
&lt;p&gt;有时候一个任务跑太久，或者我想换个思路，就会新开一个 agent 来接手。然后我发现，之前跟上一个 agent 交代了半天的项目背景、约束条件、当前目标，全都得重新说一遍。不然新 agent 一上来就按自己的理解乱写，完全不知道前面的规矩。&lt;/p&gt;
&lt;p&gt;就这样来来回回折腾了很久。&lt;/p&gt;
&lt;p&gt;项目越来越重。代码里到处都是「临时加的」「先这样用着」「以后再重构」的东西。有些文件我已经不敢动了，因为一动就会连锁崩。有些逻辑连 AI 自己都解释不清，「为什么这里要这样写？」「我也不太确定，可能是之前某次修改留下的」。&lt;/p&gt;
&lt;p&gt;到最后，这个项目变成了一座石山。&lt;/p&gt;
&lt;p&gt;不是不能用，是没人敢动。包括我自己。每次想加一个功能，AI 写完之后要么破坏老逻辑，要么引入一堆看不懂的补丁。我 review diff 的时候，已经分不清哪些改动是必要的，哪些是 AI 自己发挥的了。&lt;/p&gt;
&lt;p&gt;某个深夜，我突然产生了一个念头。&lt;/p&gt;
&lt;p&gt;要不，推倒重来吧。&lt;/p&gt;
&lt;p&gt;这个念头冒出来的一瞬间，我感受到了一种荒诞的疲惫。我明明一直在「高效开发」，一直在让 AI 帮我写代码，怎么最后走到了要重写整个项目的地步？&lt;/p&gt;
&lt;p&gt;那天晚上我一直在思考，问题到底出在哪。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;我一开始想得很简单，先把需求都写下来。&lt;/p&gt;
&lt;p&gt;不要全靠聊天记录，因为聊天记录真的太不靠谱了。一个项目做几天以后，AI 早期答应过什么、现在到底在改哪个范围、这个任务怎么验收，全部散在对话里。上下文一压缩，很多东西就没了。&lt;/p&gt;
&lt;p&gt;最先想到的是 markdown。这个想法很正常，因为 markdown 好写，也能给人看。比如我可以写一个需求列表，写一下当前在做什么，再写一下哪些文件能改，哪些文件不能乱动。公司里做需求也会有单子、有范围、有验收，那 AI 写代码应该也差不多需要这些东西。&lt;/p&gt;
&lt;p&gt;试了一段时间后，问题主要有三个。&lt;/p&gt;
&lt;p&gt;一个问题是格式会乱。AI 往 markdown 里加东西的时候，每次写法都不一样。今天写成表格，明天写成列表，后天又多加几个标题。刚开始还能看，后面就像几版需求说明拼在一起，想找个准信都费劲。&lt;/p&gt;
&lt;p&gt;还有一个问题是读取不稳定。文档一大，AI 不是每次都能把所有内容看完。它有时候只读一部分，然后按那一部分继续写。&lt;/p&gt;
&lt;p&gt;最麻烦的是，markdown 只能写规矩，不能让 AI 一定按规矩办。你在文档里写「动手之前先看任务」，但它有时候还是直接开写。流程只写在文档里，约束力不够。&lt;/p&gt;
&lt;p&gt;所以我就想，那不如做一个小工具。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;这个工具后来叫 ai-board。&lt;/p&gt;
&lt;p&gt;我的想法就是，把要做的事都放到一个看板里。一个需求从开始到结束，都要有状态。现在做哪个，改哪些文件，最后怎么验收，都尽量记下来。&lt;/p&gt;
&lt;p&gt;这样至少有一个好处，就是你问 AI 「现在在做什么」，它不用去猜聊天记录，而是去看当前任务。它要改文件，也应该先看这个任务说了哪些范围。&lt;/p&gt;
&lt;p&gt;数据没有继续用纯 markdown 存，因为前面已经被 markdown 折腾过了。我用了 JSON 存状态，然后再生成 markdown 给人看。人看的是文档，机器读的是固定结构。&lt;/p&gt;
&lt;p&gt;写这个的时候我还加了一些基础保护。写状态文件先写临时文件，再替换正式文件，避免写一半坏掉。多进程同时操作时加锁。事件日志写失败时留兜底文件。&lt;/p&gt;
&lt;p&gt;一个管任务的小工具，至少不能把自己的任务状态弄丢。这个要求应该不算高。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;但 ai-board 管不住 AI 的所有行为。&lt;/p&gt;
&lt;p&gt;它有用的地方，是让每次修改都挂在一个任务下面。你能看到这次为什么改，改了哪些范围，最后有没有验收。这个比只靠聊天记录要强一点。&lt;/p&gt;
&lt;p&gt;但它也有很多管不到的地方。&lt;/p&gt;
&lt;p&gt;比如它可以在提交代码的时候检查一下，看看这次改的文件有没有跑出任务范围。但它拦的是提交，不是 AI 写文件的那个瞬间。AI 写错文件以后，最后提交时才会被发现。&lt;/p&gt;
&lt;p&gt;还有，git 本来就可以跳过检查。你真要绕过去，它也拦不住。这个我觉得没必要装作自己能拦住。&lt;/p&gt;
&lt;p&gt;再比如 scope 现在主要看路径。路径上没冲突，不代表业务上没冲突。两个文件可能一个改了接口，一个改了调用，工具看不出来里面的关系。&lt;/p&gt;
&lt;p&gt;所以它解决的是任务留痕和范围提醒，不是强制权限控制。你绕过流程，它不会替你兜底。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;我写到一半的时候，看到别人推荐了一个叫 GSD 的项目。说它是给 Claude Code 做治理的工具。&lt;/p&gt;
&lt;p&gt;我点进去看了一下，它做的事情和我想的方向很像。也是把任务拆开，也是管理 scope，也是希望 AI 不要想到哪里写到哪里。&lt;/p&gt;
&lt;p&gt;而且它已经做得很大了。很多贡献者，好几万 star，还有一堆测试和设计文档。&lt;/p&gt;
&lt;p&gt;我忙活半天，最后发现别人已经在同一个方向上做了很久。&lt;/p&gt;
&lt;p&gt;那一瞬间的感受挺复杂的。有点挫败，「早知道直接用这个算了」。又有点好奇，「那我来看看它做得怎么样」。&lt;/p&gt;
&lt;p&gt;我还是装了一下试了试。GSD 确实很完整。它会把事情分成讨论、计划、执行、验证这些阶段，每个阶段都有自己的提示词和 agent。它不是随便写写的项目。&lt;/p&gt;
&lt;p&gt;但我用下来觉得它太大了。&lt;/p&gt;
&lt;p&gt;命令很多，概念也多，每次带进去的上下文也不少。它能做更多事，但我的需求是让自己的小项目别乱成一团，不一定需要这么大一套东西。&lt;/p&gt;
&lt;p&gt;我还拿相近的任务跑过一次。GSD 用的 token 更多，ai-board 少一些。这个数字不能说明 ai-board 更厉害，因为两边干的活不同。一个是工作流系统，一个是本地任务本，直接比不太合适。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;如果单纯说成熟度，ai-board 肯定比不过 GSD。&lt;/p&gt;
&lt;p&gt;这个没什么好装的。&lt;/p&gt;
&lt;p&gt;ai-board 现在就是一个单人写的小工具。测试也主要集中在 CLI 那边。多 agent 的事情基本没怎么管，scope 也只是路径级别。跨机器协作这些更是没有。它现在的问题我自己也都知道。&lt;/p&gt;
&lt;p&gt;但是我还是会继续用它，因为它刚好够我用。&lt;/p&gt;
&lt;p&gt;我现在不需要特别完整的治理框架。我的需求是每次让 AI 改代码之前，先有个任务，能知道改哪里，能留下记录。工具本身不要太复杂，不要让我为了用工具又学一堆工具本身的东西。&lt;/p&gt;
&lt;p&gt;GSD 很强，但我怕的是工具太强以后，我自己反而更容易偷懒。AI 改完代码，我还是要看 diff，还是要知道它到底干了什么。如果最后我还是要认真看，那我就更喜欢一个轻一点的东西。&lt;/p&gt;
&lt;p&gt;这可能也是我现在对 AI 写代码的态度。工具可以帮忙，但不能替我负责。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;这次造轮子之后，我至少确认了自己的需求。轻量、能留痕、能约束当前任务范围。&lt;/p&gt;
&lt;p&gt;我想要的不是一个很大的系统，而是一个能让我别忘事、别乱改、能回头查的小东西。&lt;/p&gt;
&lt;p&gt;如果你现在让 AI 写代码也经常写乱，而且连任务状态都没地方放，那 ai-board 可能能帮你先把记录这件事做起来。&lt;/p&gt;
&lt;p&gt;如果你要的是很完整的多 agent 流程，那就应该去看 GSD。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;pipx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ai-board&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ai-board&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;onboard&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--init-if-missing&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded></item><item><title>AI 写代码这半年，我从兴奋到冷静，再到整了一堆 skill</title><link>https://blog.devnu11.cn/posts/ai%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8%E5%BF%83%E5%BE%97%E4%B8%8Eskill%E6%8E%A8%E8%8D%90/</link><guid isPermaLink="true">https://blog.devnu11.cn/posts/ai%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8%E5%BF%83%E5%BE%97%E4%B8%8Eskill%E6%8E%A8%E8%8D%90/</guid><description>用 AI agent 写代码，从「啥都能写」到「得管着它写」，中间踩的坑和沉淀下来的几个 skill。</description><pubDate>Mon, 15 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;大概半年前我第一次用 Codex。我说了一句「帮我写一个 todo list 的页面」，它就开始哗哗地创建文件、装依赖、写组件。五分钟后，一个能跑的前端页面出现在浏览器里。&lt;/p&gt;
&lt;p&gt;这种感觉太爽了。好像突然拥有了一个不用吃饭、不用睡觉、不会抱怨的实习生。而且它比实习生强多了，你让它改什么它立刻改，不会跟你顶嘴，也不会甩锅。&lt;/p&gt;
&lt;p&gt;然后我就上头了。&lt;/p&gt;
&lt;p&gt;那段时间我几乎所有代码都交给 AI 写。需求一说，它就开始改。我也懒得看过程，反正最后能跑就行。&lt;/p&gt;
&lt;p&gt;但大概过了一个月，问题开始冒出来了。&lt;/p&gt;
&lt;p&gt;有一天我让 AI 帮我加一个用户登录功能。它写完之后我 review diff，发现它把之前好不容易调好的路由结构全改了，还顺手把我没让动的数据库模型也动了。登录功能是有了，但整个项目的逻辑变得特别拧巴。&lt;/p&gt;
&lt;p&gt;我问它为啥要改这些。它说，「为了让登录功能更好地集成进系统」。&lt;/p&gt;
&lt;p&gt;它不是不会写。它是太会写了。只要你说得不绝对清楚，它就会按自己的理解去补全，去「优化」，去「让系统更完整」。最后补出来的东西不一定是你要的，但 diff 一定很大，大到你看不完。&lt;/p&gt;
&lt;p&gt;从那以后，我对 AI 开发工具就没一开始那么兴奋了。&lt;/p&gt;
&lt;p&gt;它还是有用，但前提是任务、范围、验收标准，得先说清楚。不说清楚，它就会自己往下补，补到你都不认识这个项目为止。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;我日常主要用两个工具，Codex 和 Claude Code。&lt;/p&gt;
&lt;p&gt;Codex 用得更多，因为我主力模型还是 GPT。日常改项目、跑本地工作流，Codex 成本低，工具调用和文件修改的流程也已经被 OpenAI 打磨得差不多了。&lt;/p&gt;
&lt;p&gt;但 Codex 接别的模型会麻烦一些。2026 年那次接口调整以后，其他模型想接进来经常要走中转，或者本地再套一层代理。能跑是能跑，但工具调用会变得很不稳定。有时候你明明没给它那个工具，它还是像真的有一样去调用。排查这种 bug 真的很搞心态。&lt;/p&gt;
&lt;p&gt;Claude Code 在这方面更开放。接其他 AI API 更方便，agent 相关的能力也更完整，上下文管理、子代理这些都有。我如果要试国产模型，或者想折腾多模型，一般会先想到 Claude Code。&lt;/p&gt;
&lt;p&gt;不过日常开发我还是 Codex 为主。毕竟现在这套习惯是围着 GPT 和 Codex 搭起来的，要换的话迁移成本不低。而且 Codex 的响应速度确实快，写那种需要反复试错的代码时，快几秒的体验差距还挺明显的。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;说到 skill，这玩意是我最近半年觉得最值的东西。&lt;/p&gt;
&lt;p&gt;你可以把它理解成一种「可复用的 prompt 模板」。有些工作流程或者约束标准，你每次跟 AI 对话都要重复说一遍，很烦。把它写成一个 skill，需要的时候直接调用，AI 就会按那套规则来执行。&lt;/p&gt;
&lt;p&gt;我自己现在沉淀了几个常用的，挑几个有意思的聊聊。&lt;/p&gt;
&lt;p&gt;agent-browser 是用来做前端页面检查的。以前让 AI 测前端，我经常用 Playwright 那一套。能用，但 AI 有时候找不到元素，有时候页面还没加载完就开始点，还有时候明明点错了还继续往下跑。测试日志显示流程跑完了，页面实际状态不一定对。&lt;/p&gt;
&lt;p&gt;agent-browser 能打开页面、看页面状态、点按钮、填表单、截图。做前端改动以后，让它跑一遍页面流程，比只看代码更容易发现问题。复杂交互还是要自己看，但日常页面检查，它已经够用了。&lt;/p&gt;
&lt;p&gt;darwin-skill 是我用来检查和优化其他 skill 的。它能帮你发现 skill 里有没有边界不清、说明不够具体之类的问题。补几条规则之后，AI 的行为确实会好一点。&lt;/p&gt;
&lt;p&gt;但这里有个坑。skill 特别容易越写越长。今天发现一个问题，加一条规则。明天又发现一个偏差，再加一条。加到后面，文件里全是限制，AI 读起来累，你自己维护也累。&lt;/p&gt;
&lt;p&gt;我现在更倾向于够用就停。skill 不是越厚越好。它应该让 AI 更清楚，不是把所有可能出错的地方都堵一遍。堵不完的。你自己写代码还会出 bug 呢，凭什么要求 AI 看了几十条规则就绝不犯错？&lt;/p&gt;
&lt;p&gt;ai-board 是我自己写的小工具，主要用来管 vibe coding 里的任务状态。这个我后面专门写了一篇文章讲，这里就不展开了。&lt;/p&gt;
&lt;p&gt;better-icons 是我最近才开始用的，但用了一次就离不开了。它的作用很简单，就是让 AI 在写前端的时候，别随便找个图标就往上堆。你告诉它你要什么风格、什么场景的图标，它会去搜一套统一的、质量在线的图标资源，而不是让页面上出现三四种不同风格的图标混在一起的惨剧。&lt;/p&gt;
&lt;p&gt;GPT 写前端有个毛病，遇到图标就随手扔一个 &lt;code&gt;LuIcon&lt;/code&gt; 或者 &lt;code&gt;FaIcon&lt;/code&gt;，有时候同一个页面里线性和面性图标混用，粗细还不一致。你肉眼一看就觉得哪里怪怪的，但 AI 自己完全意识不到。better-icons 就是专门治这个的。它会让 AI 先想明白这套 UI 适合什么风格的图标，再找一套统一的来用。&lt;/p&gt;
&lt;p&gt;前端方面我开了几个 skill。frontend-design 和 ui-ux-pro-max 主要是让 AI 别写得太随便。它们会提醒一些布局、颜色、组件状态之类的问题。效果有，但也不能指望开了 skill 就直接出很好看的页面。&lt;/p&gt;
&lt;p&gt;还有一个叫 uncodixfy，是专门用来压 GPT 前端味的。GPT 写前端经常会堆大圆角、玻璃拟态、卡片套卡片，页面上还喜欢写一堆解释文字，好像怕用户不知道这个按钮是干嘛的。uncodixfy 能压一点，但模型本身审美不行的话，它也救不了太多。&lt;/p&gt;
&lt;p&gt;前端 skill 能把下限拉高一点，但上限还是看模型和参考模板。你给它一张设计稿，它至少能抄个大概。你让它从零开始自由发挥，那画面通常不太能看。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;做项目的时候，我现在养成了一个习惯，让 AI 先 plan，再写代码。&lt;/p&gt;
&lt;p&gt;这个习惯是踩坑踩出来的。以前我经常直接说「帮我做一个 xxx」，AI 很快就开始写。做到一半才发现，它理解的功能和我想的不一样。有时候页面路由不对，有时候数据结构不对，有时候它多做了一堆我根本没要的东西。&lt;/p&gt;
&lt;p&gt;空项目还好，大不了删掉重来。麻烦的是项目已经有一部分代码了，它再按自己的理解改一大片。你 review 的时候会很痛苦，因为你不只是看代码质量，还要重新判断它有没有偏离需求。&lt;/p&gt;
&lt;p&gt;所以现在我会先让它把需求拆出来，确认功能列表、数据模型、页面、文件范围。确认差不多了再动手。前面多花一点时间，后面少返工。&lt;/p&gt;
&lt;p&gt;我后来也把这个流程放进了 ai-board 的 onboard 里。接手一个项目时，先把方向问清楚，再排任务。不然 AI 开始写得太快，反而容易把自己带偏。&lt;/p&gt;
&lt;p&gt;说到前端，我现在基本不让 GPT 裸写了。&lt;/p&gt;
&lt;p&gt;它能写，代码也能跑。但它写出来的页面经常有一种很重的 AI 味。组件很大，圆角很多，到处都是半透明和渐变。还有一个毛病是喜欢在界面里写很多说明，好像怕用户不知道这个按钮是干嘛的。&lt;/p&gt;
&lt;p&gt;prompt 能修一部分问题，但模型自己的审美底子影响很大。同一个需求，Claude 和 Gemini 做出来的东西通常更能看。国产模型里 DeepSeek 我也试过，价格便宜，前端效果也不差。&lt;/p&gt;
&lt;p&gt;换模型也不能完全靠它自由发挥。更稳的办法是先给一个还不错的模板，让 AI 对着改。这样它至少有参考，不会从零开始乱画。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;折腾了这么久，我现在对 AI 写代码的态度挺明确的。&lt;/p&gt;
&lt;p&gt;它是个很强的工具，但工具不能替你思考。需求是你自己的，验收标准也是你自己的。AI 可以帮你快速实现，但方向对不对，最终还是要人来判断。&lt;/p&gt;
&lt;p&gt;那些觉得「有了 AI 以后我不用学代码了」的人，可能还没被 diff 炸过。&lt;/p&gt;
&lt;p&gt;等你经历过一次 AI 把项目改得面目全非、你花了整整一个下午才理清楚它到底动了什么之后，你就会明白。AI 不是来替代你的，它是来加速你的。但加速的前提是，你自己得知道路在哪。&lt;/p&gt;
&lt;p&gt;不然它加速的方向，可能是悬崖。&lt;/p&gt;</content:encoded></item><item><title>搭建 Kubernetes 集群</title><link>https://blog.devnu11.cn/posts/%E6%90%AD%E5%BB%BAk8s%E9%9B%86%E7%BE%A4/</link><guid isPermaLink="true">https://blog.devnu11.cn/posts/%E6%90%AD%E5%BB%BAk8s%E9%9B%86%E7%BE%A4/</guid><description>记录用 kubeadm 搭建 k8s 集群的过程，使用 containerd 运行时和 Calico 网络</description><pubDate>Mon, 11 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;最近需要搭个 k8s 集群做测试，用的是 kubeadm 部署方式。集群镜像从私有 Harbor 仓库拉取，Harbor 的搭建可以参考&lt;a href=&quot;../%E6%90%AD%E5%BB%BAharbor%E7%A7%81%E6%9C%89%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93/&quot;&gt;上一篇文章&lt;/a&gt;。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;环境规划&lt;a href=&quot;#环境规划&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;主机&lt;/th&gt;&lt;th&gt;IP&lt;/th&gt;&lt;th&gt;用途&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;k8s-master&lt;/td&gt;&lt;td&gt;192.168.100.20&lt;/td&gt;&lt;td&gt;控制平面节点&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;k8s-node1&lt;/td&gt;&lt;td&gt;192.168.100.21&lt;/td&gt;&lt;td&gt;工作节点&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;k8s-node2&lt;/td&gt;&lt;td&gt;192.168.100.22&lt;/td&gt;&lt;td&gt;工作节点&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;harbor&lt;/td&gt;&lt;td&gt;192.168.100.14&lt;/td&gt;&lt;td&gt;私有镜像仓库&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;k8s 版本：v1.33.5&lt;br /&gt;
网络插件：Calico v3.31.0&lt;br /&gt;
容器运行时：containerd&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;系统初始化&lt;a href=&quot;#系统初始化&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;所有节点都需要执行以下操作。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;关闭 swap&lt;a href=&quot;#关闭-swap&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;swapoff&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-a&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;/swap/s/^/#/&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/fstab&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;调整内核参数&lt;a href=&quot;#调整内核参数&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;span&gt; &amp;gt; &lt;/span&gt;&lt;span&gt;/etc/sysctl.d/k8s.conf&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;net.ipv4.ip_forward = 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;net.bridge.bridge-nf-call-iptables = 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;net.bridge.bridge-nf-call-ip6tables = 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sysctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--system&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;配置主机名和解析&lt;a href=&quot;#配置主机名和解析&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 在 master 节点&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;hostnamectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;set-hostname&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;k8s-master&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 在 node1 节点&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;hostnamectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;set-hostname&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;k8s-node1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 在 node2 节点&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;hostnamectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;set-hostname&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;k8s-node2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 所有节点添加 hosts 解析&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &amp;gt;&amp;gt; &lt;/span&gt;&lt;span&gt;/etc/hosts&lt;/span&gt;&lt;span&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;192.168.100.20 k8s-master&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;192.168.100.21 k8s-node1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;192.168.100.22 k8s-node2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;192.168.100.14 reg.westos.org&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;配置 k8s yum 源&lt;a href=&quot;#配置-k8s-yum-源&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;span&gt; &amp;gt; &lt;/span&gt;&lt;span&gt;/etc/yum.repos.d/kubernetes.repo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[kubernetes]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;name=Kubernetes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.33/rpm/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;enabled=1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;gpgcheck=0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;配置 SSH 免密（可选）&lt;a href=&quot;#配置-ssh-免密可选&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;方便后续操作，写个脚本批量配置：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#!/bin/bash&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;USER&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;root&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;PASSWORD&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;123&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;PORT&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;HOSTS&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;192.168.100.20&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;192.168.100.21&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;192.168.100.22&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;[ &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;span&gt; ~/.ssh/id_rsa.pub ] &amp;amp;&amp;amp; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ssh-keygen&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rsa&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-N&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/.ssh/id_rsa&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entry&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;HOSTS&lt;/span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;do&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;host&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$entry&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$PORT&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[[ &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$entry&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; *:* ]] &amp;amp;&amp;amp; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;host&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;entry&lt;/span&gt;&lt;/span&gt;&lt;span&gt;%%:*&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &amp;amp;&amp;amp; &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;entry&lt;/span&gt;&lt;/span&gt;&lt;span&gt;##*:&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;sshpass&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$PASSWORD&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ssh-copy-id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StrictHostKeyChecking=no&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$port&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$USER&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;$host&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;done&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;配置 IPVS&lt;a href=&quot;#配置-ipvs&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;k8s 用 IPVS 做负载均衡，需要加载相关内核模块：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &amp;gt; &lt;/span&gt;&lt;span&gt;/etc/modules-load.d/ipvs.conf&lt;/span&gt;&lt;span&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ip_vs&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ip_vs_rr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ip_vs_wrr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ip_vs_sh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;nf_conntrack&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;overlay&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;br_netfilter&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 立即加载&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;modprobe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ip_vs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ip_vs_rr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ip_vs_wrr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ip_vs_sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nf_conntrack&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;overlay&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;br_netfilter&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 安装管理工具&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;dnf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ipvsadm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ipset&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;安装 containerd&lt;a href=&quot;#安装-containerd&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;所有节点安装：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;yum&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;containerd.io&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cri-tools&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;containerd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; &amp;gt; &lt;/span&gt;&lt;span&gt;/etc/containerd/config.toml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 启用 systemd cgroup 驱动&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;s#SystemdCgroup = false#SystemdCgroup = true#g&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/containerd/config.toml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--now&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;containerd&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 配置 crictl&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;span&gt; &amp;gt; &lt;/span&gt;&lt;span&gt;/etc/crictl.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;runtime-endpoint: unix:///run/containerd/containerd.sock&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;image-endpoint: unix:///run/containerd/containerd.sock&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;section&gt;&lt;h3&gt;配置 Harbor 证书&lt;a href=&quot;#配置-harbor-证书&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;让 containerd 信任 Harbor 的证书：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 所有节点创建目录&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/containerd/certs.d/reg.westos.org&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 在 harbor 节点上，将证书复制到各节点&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;scp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/docker/certs.d/reg.westos.org/ca.crt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;192.168.100.20:/etc/containerd/certs.d/reg.westos.org/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;scp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/docker/certs.d/reg.westos.org/ca.crt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;192.168.100.21:/etc/containerd/certs.d/reg.westos.org/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;scp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/docker/certs.d/reg.westos.org/ca.crt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;192.168.100.22:/etc/containerd/certs.d/reg.westos.org/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 在所有 k8s 节点上，修改 containerd 配置&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;s#config_path = &quot;&quot;#config_path = &quot;/etc/containerd/certs.d&quot;#g&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/containerd/config.toml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;s#registry.k8s.io/pause:3.8#reg.westos.org/k8s/pause:3.10#g&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/containerd/config.toml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;containerd&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;准备镜像&lt;a href=&quot;#准备镜像&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;安装 k8s 组件&lt;a href=&quot;#安装-k8s-组件&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;所有节点安装：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;yum&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kubelet&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kubeadm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--now&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kubelet&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;查看需要的镜像&lt;a href=&quot;#查看需要的镜像&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubeadm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;images&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--image-repository&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;registry.aliyuncs.com/google_containers&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--kubernetes-version&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v1.33.5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;会列出这些镜像：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;kube-apiserver.33.5&lt;/li&gt;
&lt;li&gt;kube-controller-manager.33.5&lt;/li&gt;
&lt;li&gt;kube-scheduler.33.5&lt;/li&gt;
&lt;li&gt;kube-proxy.33.5&lt;/li&gt;
&lt;li&gt;coredns.12.0&lt;/li&gt;
&lt;li&gt;pause:3.10&lt;/li&gt;
&lt;li&gt;etcd:3.5.21-0&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;推送镜像到 Harbor&lt;a href=&quot;#推送镜像到-harbor&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在 harbor 节点上拉取镜像并推送：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 从阿里云拉取&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;registry.aliyuncs.com/google_containers/pause:3.10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;registry.aliyuncs.com/google_containers/kube-apiserver:v1.33.5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;registry.aliyuncs.com/google_containers/kube-controller-manager:v1.33.5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;registry.aliyuncs.com/google_containers/kube-scheduler:v1.33.5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;registry.aliyuncs.com/google_containers/kube-proxy:v1.33.5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;registry.aliyuncs.com/google_containers/coredns:v1.12.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;registry.aliyuncs.com/google_containers/etcd:3.5.21-0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 在 Harbor Web 界面创建 k8s 项目（设为公开）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 批量打标签&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;images&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;span&gt;grep&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;google_containers&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;awk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;{print $1&quot;:&quot;$2}&apos;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;awk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-F/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;{system(&quot;docker tag &quot;$0&quot; reg.westos.org/k8s/&quot;$3&quot;&quot;)}&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 批量推送&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;images&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;span&gt;grep&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reg.westos.org/k8s&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;awk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;{system(&quot;docker push &quot;$1&quot;:&quot;$2&quot;&quot;)}&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;初始化 Master 节点&lt;a href=&quot;#初始化-master-节点&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在 k8s-master 上执行：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubeadm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--pod-network-cidr=10.244.0.0/16&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--image-repository&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reg.westos.org/k8s&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--kubernetes-version&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v1.33.5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;初始化成功后会输出 join 命令，记下来给 node 节点用：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubeadm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;join&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;192.168.100.20:6443&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--token&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;afmhpb.r5vcfet4ro49kg5i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--discovery-token-ca-cert-hash&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sha256:69a36f40befb0f36e29c1afae2291be7ff652672ec730728aebb90b73f436192&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;section&gt;&lt;h3&gt;配置 kubectl&lt;a href=&quot;#配置-kubectl&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$HOME&lt;/span&gt;&lt;span&gt;/.kube&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/kubernetes/admin.conf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$HOME&lt;/span&gt;&lt;span&gt;/.kube/config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;chown&lt;/span&gt;&lt;span&gt; $(&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-u&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-g&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;$HOME&lt;/span&gt;&lt;span&gt;/.kube/config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 命令补全&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;echo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;source &amp;lt;(kubectl completion bash)&quot;&lt;/span&gt;&lt;span&gt; &amp;gt;&amp;gt; &lt;/span&gt;&lt;span&gt;~/.bashrc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;source&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/.bashrc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;验证一下：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nodes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;此时 master 节点状态是 &lt;code&gt;NotReady&lt;/code&gt;，因为还没装网络插件。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;安装 Calico 网络插件&lt;a href=&quot;#安装-calico-网络插件&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;准备 Calico 镜像&lt;a href=&quot;#准备-calico-镜像&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在 harbor 节点上：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;quay.io/calico/cni:v3.31.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;quay.io/calico/node:v3.31.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;quay.io/calico/kube-controllers:v3.31.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 在 Harbor Web 界面创建 calico 项目&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 打标签并推送&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;images&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;span&gt;grep&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;calico&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;awk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;{print $1&quot;:&quot;$2}&apos;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;awk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-F/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;{system(&quot;docker tag &quot;$0&quot; reg.westos.org/calico/&quot;$3&quot;&quot;)}&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;images&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;span&gt;grep&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reg.westos.org/calico&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;awk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;{system(&quot;docker push &quot;$1&quot;:&quot;$2&quot;&quot;)}&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;部署 Calico&lt;a href=&quot;#部署-calico&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在 master 节点上：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;wget&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://raw.githubusercontent.com/projectcalico/calico/v3.31.0/manifests/calico.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;s#quay.io/#reg.westos.org/#g&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;calico.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;calico.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;等待 calico pods 启动：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-A&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;span&gt;grep&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;calico&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;全部 Running 后，再查看节点状态：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;node&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;master 节点应该变成 &lt;code&gt;Ready&lt;/code&gt; 状态了。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;加入 Worker 节点&lt;a href=&quot;#加入-worker-节点&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在 node1 和 node2 上执行之前保存的 join 命令：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubeadm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;join&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;192.168.100.20:6443&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--token&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;afmhpb.r5vcfet4ro49kg5i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--discovery-token-ca-cert-hash&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sha256:69a36f40befb0f36e29c1afae2291be7ff652672ec730728aebb90b73f436192&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;回到 master 节点查看：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;node&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;输出：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;NAME         STATUS   ROLES           AGE     VERSION&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;k8s-master   Ready    control-plane   35m     v1.33.5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;k8s-node1    Ready    &amp;lt;none&amp;gt;          2m      v1.33.5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;k8s-node2    Ready    &amp;lt;none&amp;gt;          6m22s   v1.33.5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;常见问题&lt;a href=&quot;#常见问题&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;containerd 没配置 Harbor 证书路径&lt;/li&gt;
&lt;li&gt;Harbor 项目权限设为私有了（改成公开或配置 imagePullSecrets）&lt;/li&gt;
&lt;li&gt;节点 &lt;code&gt;/etc/hosts&lt;/code&gt; 没有 Harbor 域名解析&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;另外如果 token 过期了，可以在 master 上重新生成：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubeadm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--print-join-command&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;</content:encoded></item><item><title>搭建 Harbor 私有镜像仓库</title><link>https://blog.devnu11.cn/posts/%E6%90%AD%E5%BB%BAharbor%E7%A7%81%E6%9C%89%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93/</link><guid isPermaLink="true">https://blog.devnu11.cn/posts/%E6%90%AD%E5%BB%BAharbor%E7%A7%81%E6%9C%89%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93/</guid><description>记录一下在内网环境搭建 Harbor 私有镜像仓库的过程，包括 HTTPS 配置和 Trivy 扫描</description><pubDate>Thu, 07 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h2&gt;环境&lt;a href=&quot;#环境&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;服务器：&lt;code&gt;192.168.100.14&lt;/code&gt;，已装好 Docker&lt;/li&gt;
&lt;li&gt;域名：&lt;code&gt;reg.westos.org&lt;/code&gt;（内网域名）&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;生成证书&lt;a href=&quot;#生成证书&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Harbor 需要 HTTPS，先生成自签名证书。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certs&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-newkey&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rsa:4096&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-nodes&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-sha256&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-keyout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certs/westos.org.key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-addext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;subjectAltName = DNS:reg.westos.org&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-x509&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-days&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;365&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-out&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certs/westos.org.crt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;然后把证书复制到 &lt;code&gt;/data&lt;/code&gt; 目录，Harbor 会从这里读取：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/data&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/data&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;安装 Harbor&lt;a href=&quot;#安装-harbor&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;去 &lt;a href=&quot;https://github.com/goharbor/harbor/releases&quot; target=&quot;_blank&quot;&gt;Harbor Release&lt;/a&gt; 下载离线安装包：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;wget&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://github.com/goharbor/harbor/releases/download/v2.14.0/harbor-offline-installer-v2.14.0.tgz&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;tar&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;zxf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;harbor-offline-installer-v2.14.0.tgz&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;harbor/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;复制配置模板并修改：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;harbor.yml.tmpl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;harbor.yml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vim&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;harbor.yml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;主要改这几个地方：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;hostname&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;reg.westos.org&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;80&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;https&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;443&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;certificate&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/data/certs/westos.org.crt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;private_key&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/data/certs/westos.org.key&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;harbor_admin_password&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;12345&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# 改成你的密码&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;执行安装，带上 &lt;code&gt;--with-trivy&lt;/code&gt; 参数会一起安装漏洞扫描工具：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;./install.sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--with-trivy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;等一会儿，看到 &lt;code&gt;Harbor has been installed and started successfully&lt;/code&gt; 就好了。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Docker 客户端配置&lt;a href=&quot;#docker-客户端配置&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;直接 &lt;code&gt;docker login&lt;/code&gt; 会报证书错误，因为是自签名的。需要让 Docker 信任这个证书：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/docker/certs.d/reg.westos.org&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/data/certs/westos.org.crt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/docker/certs.d/reg.westos.org/ca.crt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;docker&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 重启后 Harbor 也要重新启动&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/harbor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compose&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;现在可以登录了：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;login&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reg.westos.org&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Username: admin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Password: 12345&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;使用&lt;a href=&quot;#使用&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;浏览器访问 &lt;code&gt;https://reg.westos.org&lt;/code&gt;，用 admin 账户登录。&lt;/p&gt;&lt;p&gt;先创建一个项目，比如叫 &lt;code&gt;myproject&lt;/code&gt;，选私有。&lt;/p&gt;&lt;p&gt;然后试着推送一个镜像：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nginx:latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tag&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nginx:latest&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reg.westos.org/myproject/nginx:v1.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reg.westos.org/myproject/nginx:v1.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;在 Web 界面里就能看到推送的镜像了。&lt;/p&gt;&lt;p&gt;拉取也很简单：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reg.westos.org/myproject/nginx:v1.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Trivy 扫描问题&lt;a href=&quot;#trivy-扫描问题&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在 Web 界面点”扫描”按钮的时候，Trivy 会报错说下载不了漏洞库。因为它要从 GitHub 拉数据，国内网络不太行。&lt;/p&gt;&lt;p&gt;解决办法是给它配个代理：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/harbor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vim&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;./common/config/trivy-adapter/env&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;加上代理配置（换成你自己的代理地址）：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;HTTP_PROXY&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;http://192.168.10.141:7897&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;HTTPS_PROXY&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;http://192.168.10.141:7897&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;然后重启：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compose&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;down&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compose&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;现在扫描应该能正常工作了。扫描结果会显示镜像里有哪些漏洞，方便评估风险。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;其他机器使用&lt;a href=&quot;#其他机器使用&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;如果其他机器要用这个仓库，需要：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;配置域名解析（&lt;code&gt;/etc/hosts&lt;/code&gt; 或 DNS）&lt;/li&gt;
&lt;li&gt;复制证书到客户端：
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;scp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;root@192.168.100.14:/data/certs/westos.org.crt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/docker/certs.d/reg.westos.org/ca.crt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;登录即可&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;就这样，基本的 Harbor 仓库就搭好了。&lt;/p&gt;&lt;/section&gt;</content:encoded></item></channel></rss>