<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Vim on 小盒子的技术分享</title><link>https://xiaobox.github.io/tags/vim/</link><description>Recent content in Vim on 小盒子的技术分享</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Mon, 13 Apr 2026 03:56:46 +0000</lastBuildDate><atom:link href="https://xiaobox.github.io/tags/vim/index.xml" rel="self" type="application/rss+xml"/><item><title>Postman 越来越臃肿了，我换了个开源的，还能让 AI 帮我写测试</title><link>https://xiaobox.github.io/p/2026-04-13-postman-yue-lai-yue-yong-zhong-le-wo-huan-le-ge-kai-yuan-de/</link><pubDate>Mon, 13 Apr 2026 03:56:46 +0000</pubDate><guid>https://xiaobox.github.io/p/2026-04-13-postman-yue-lai-yue-yong-zhong-le-wo-huan-le-ge-kai-yuan-de/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-postman-yue-lai-yue-yong-zhong-le-wo-huan-le-ge-kai-yuan-de-/cover.jpg" alt="Featured image of post Postman 越来越臃肿了，我换了个开源的，还能让 AI 帮我写测试" /&gt;&lt;p&gt;Postman 我用了好几年了。&lt;/p&gt;
&lt;p&gt;从最早的 Chrome 插件时代开始用的，那时候它还是个轻量小工具，打开就能测接口，干干净净。但最近这两年，怎么说呢，它开始「端着」了。&lt;/p&gt;
&lt;p&gt;打开就让我登录。不登录不让用。&lt;/p&gt;
&lt;p&gt;好不容易登录了，又弹窗让我升级 Team 版。&lt;/p&gt;
&lt;p&gt;集合还给我存到云端去了。我就测个本地接口，你把我的请求数据往你服务器上传干嘛？&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-postman-yue-lai-yue-yong-zhong-le-wo-huan-le-ge-kai-yuan-de-/001-293772cd.png"&gt;&lt;/p&gt;
&lt;p&gt;我一直忍着，直到有一天，团队里两个人同时改了同一个集合，Postman 云同步直接给合并冲突了，还没法像 Git 那样 diff 看变更。那天我就想，不行了，得换。&lt;/p&gt;
&lt;p&gt;然后我遇到了 Bruno。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-postman-yue-lai-yue-yong-zhong-le-wo-huan-le-ge-kai-yuan-de-/002-67da7d91.png"&gt;&lt;/p&gt;
&lt;p&gt;怎么形容呢，就像你一直在用一个越来越臃肿的 IDE，突然有人递给你一个 Vim，告诉你「够用了，而且是你的」。&lt;/p&gt;
&lt;p&gt;Bruno 干了一件特别简单但特别对的事情，它把你的 API 请求存成 .bru 文件，放在你本地文件夹里。&lt;/p&gt;
&lt;p&gt;就是普通的文本文件，打开长这样。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;meta { name: 用户登录 type: http seq: 1}post { url: {{baseUrl}}/auth/login body: json auth: none}headers { Content-Type: application/json}body:json { { &amp;#34;username&amp;#34;: &amp;#34;{{username}}&amp;#34;, &amp;#34;password&amp;#34;: &amp;#34;{{password}}&amp;#34;, &amp;#34;expiresInMins&amp;#34;: 30 }}script:post-response { if (res.status === 200) { bru.setVar(&amp;#34;authToken&amp;#34;, res.body.accessToken); bru.setVar(&amp;#34;userId&amp;#34;, res.body.id); }}tests { test(&amp;#34;登录应该返回 200&amp;#34;, function() { expect(res.status).to.equal(200); }); test(&amp;#34;响应中应该包含 accessToken&amp;#34;, function() { expect(res.body.accessToken).to.be.a(&amp;#34;string&amp;#34;); expect(res.body.accessToken.length).to.be.greaterThan(0); }); test(&amp;#34;响应中应该包含用户基本信息&amp;#34;, function() { expect(res.body.id).to.be.a(&amp;#34;number&amp;#34;); expect(res.body.username).to.equal(&amp;#34;emilys&amp;#34;); expect(res.body.email).to.be.a(&amp;#34;string&amp;#34;); }); test(&amp;#34;响应时间应该小于 3 秒&amp;#34;, function() { expect(res.responseTime).to.be.lessThan(3000); });}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;你看，GET 请求、Header、Body、断言，全都是纯文本。你用任何编辑器都能打开它，改完保存就行。&lt;/p&gt;
&lt;p&gt;这玩意最不同的地方在哪？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;它可以用 Git 管理。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;以前团队共享 Postman 集合，那叫一个痛苦。谁改了什么不知道，版本对不对不确定，冲突了还没法 resolve。&lt;/p&gt;
&lt;p&gt;现在用 Bruno，接口定义就是文件，扔进 Git 仓库，该 PR 就 PR，该 Code Review 就 Code Review。有人改了某个接口的 Header，diff 里看得一清二楚。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-postman-yue-lai-yue-yong-zhong-le-wo-huan-le-ge-kai-yuan-de-/003-c38b66fd.png"&gt;&lt;/p&gt;
&lt;p&gt;用程序员已经会的工具，解决程序员的问题。不用学新的协作方式，不用付费，不用担心数据被传到哪个云上。&lt;/p&gt;
&lt;p&gt;Bruno 官网上有一句话我印象特别深，大意是**「我们不会同步你的任何数据到云端，甚至连登录的概念都没有。我们看不到你在 Bruno 里输入了什么，也不会用你的数据训练任何 AI 模型」。**&lt;/p&gt;
&lt;p&gt;在这个年代，一个工具敢这么说，我觉得还是挺硬气的。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-postman-yue-lai-yue-yong-zhong-le-wo-huan-le-ge-kai-yuan-de-/004-2762e255.png"&gt;&lt;/p&gt;
&lt;p&gt;回到工具本身。说到这里，可能有朋友会想，开源 API 客户端一抓一大把，Insomnia、Hoppscotch、Thunder Client，凭什么是 Bruno？&lt;/p&gt;
&lt;p&gt;我自己用下来，让我有「这玩意不一样」的瞬间，是发现它有 CLI。&lt;/p&gt;
&lt;p&gt;但我说的不是「能在终端里跑测试」这种废话。Newman 也能跑，Postman 自己也有命令行。我说的是另一件事。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bruno 的 CLI，让 Claude Code 和 Cursor 这种 AI 编程工具，第一次能真正帮你写和跑接口测试。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这话有点大，我用两件刚发生的真事讲一下。&lt;/p&gt;
&lt;p&gt;回到 Bruno 的 CLI 本身。装它就一行，&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;npm i -g @usebruno/cli
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;装完之后命令叫 &lt;code&gt;bru&lt;/code&gt;，跑整个集合的测试是这样，&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;bru run --env production
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;输出长这样。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-postman-yue-lai-yue-yong-zhong-le-wo-huan-le-ge-kai-yuan-de-/005-95a75ce3.png"&gt;&lt;/p&gt;
&lt;p&gt;干净、彩色、有 ✓ 和 ✗、有总耗时、有失败原因。最重要的是，&lt;strong&gt;这是一段普通的终端命令，输出是普通的文本&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;为什么这件事重要？因为这两个特征，正好是 AI 编程 agent 工作的边界。&lt;/p&gt;
&lt;p&gt;Claude Code、Cursor、Codex 这些工具，它们能干什么？它们能读你的代码文件，能写新的文件，能在终端里跑命令，能读命令的输出。它们不能干什么？它们不能点击 Postman 的按钮，不能在你 GUI 里输入 token，不能登录任何账号。(&lt;strong&gt;或者说不方便，成本高，效率低&lt;/strong&gt;)&lt;/p&gt;
&lt;p&gt;Postman 的核心数据存在云端、操作靠 GUI、协作靠登录，这三件事每一件都把 AI agent 挡在外面。&lt;/p&gt;
&lt;p&gt;而 Bruno 的核心数据是 .bru 文本文件、操作靠 CLI、协作靠 Git。每一件都正好是 AI 最擅长的那种事。&lt;/p&gt;
&lt;p&gt;抽象的说完了，说点具体的。&lt;/p&gt;
&lt;p&gt;我前两天就让 Claude Code 帮我加了一个测试，过程是这样的。&lt;/p&gt;
&lt;p&gt;我跟它说，「我刚加了一个搜索商品的接口，帮我在 bruno 集合里加个测试用例」。&lt;/p&gt;
&lt;p&gt;它干了三件事，全程没问我任何问题。&lt;/p&gt;
&lt;p&gt;第一步，读了我现有的一个 .bru 文件，就是为了搞清楚我用的格式。比如我习惯加哪些 test，断言风格是什么样的。&lt;/p&gt;
&lt;p&gt;第二步，照着这个格式写了一个新的 06-搜索商品.bru 文件，放在我集合的根目录里。请求方法、URL、query 参数、4 条断言，全都给我加上了。&lt;/p&gt;
&lt;p&gt;第三步，它直接执行 &lt;code&gt;bru run 06-搜索商品.bru --env production&lt;/code&gt;，亲眼看着 4 个测试全绿，然后才回我一句「写完了，4/4 通过」。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-postman-yue-lai-yue-yong-zhong-le-wo-huan-le-ge-kai-yuan-de-/006-f94498cf.png"&gt;&lt;/p&gt;
&lt;p&gt;整个过程我没碰 Bruno 的 GUI，没敲一个字符的代码，没解释什么是 .bru 格式。AI 自己读自己写自己跑自己验证。&lt;/p&gt;
&lt;p&gt;你可能会问，这个事换成 Postman 不行吗？&lt;/p&gt;
&lt;p&gt;我得先把话说清楚，Postman 不是没有 CLI。Newman 一直都在，Postman Collection 也是 JSON 文件，AI 理论上能读能写。这条路是通的。&lt;/p&gt;
&lt;p&gt;但你真去试一下就会发现，那条路上全是石头。&lt;/p&gt;
&lt;p&gt;Postman 的 Collection JSON 格式不是给人手写的。我做了个最朴素的对比，同一个 GET 请求加一条「状态码等于 200」的断言，写成 .bru 是 15 行，导出成 Postman Collection JSON 是 44 行。区别在哪？.bru 里 URL 就是一个字符串 &lt;code&gt;https://api.example.com/users&lt;/code&gt;，Postman JSON 里 URL 被拆成 &lt;code&gt;protocol&lt;/code&gt;、&lt;code&gt;host&lt;/code&gt; 数组、&lt;code&gt;path&lt;/code&gt; 数组三个字段。.bru 里测试代码就是普通 JS，Postman JSON 里测试代码以字符串数组的形式塞在 event 里，每一行 JS 都得加引号、转义、再 JSON 序列化一次。还有一堆 &lt;code&gt;_postman_id&lt;/code&gt;、&lt;code&gt;_exporter_id&lt;/code&gt;、&lt;code&gt;schema&lt;/code&gt; 这种内部元数据，跟你的业务接口毫无关系，但你不写就报错。&lt;/p&gt;
&lt;p&gt;让 AI 写 .bru，它跟写 markdown 一样轻松。让 AI 写 Postman JSON，它更像在翻译一份配置文件，token 烧得多，出错概率高，写完你自己 review 都费劲，git diff 出来三行业务变更夹在二十行格式噪音里。&lt;/p&gt;
&lt;p&gt;所以不是 AI 不能写 Postman 的测试，是 Postman 的格式从一开始就没打算让人手写，更没打算让 AI 直接读写。它假设你有一个 GUI 在中间帮你管理这些内部细节。AI 进来之后，那个假设就有点尴尬了。&lt;/p&gt;
&lt;p&gt;我说的还不是最炸的场景。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;真正让我觉得 Bruno + AI 是 1 + 1 大于 10 的，是调试场景。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我又试了一次，让 Claude Code 帮我加一个购物车接口的测试。它写完跑了一遍，挂了。&lt;/p&gt;
&lt;p&gt;错误信息是这样的。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;✕ 购物车应该有 totalPrice 字段 expected undefined to be a number✕ 购物车应该有 products 数组 expected undefined to be an array
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;```bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;它猜错了字段名。这种事很正常，毕竟它没真的去看接口返回。但接下来才有意思。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;它没有问我、没有让我提供文档、也没有放弃。它自己执行了一条 curl 命令，把购物车接口的真实响应拉了下来。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;```bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;curl -s https://dummyjson.com/carts/1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;看到响应里字段是 &lt;code&gt;total&lt;/code&gt; 和 &lt;code&gt;products&lt;/code&gt;，不是 &lt;code&gt;totalPrice&lt;/code&gt; 和 &lt;code&gt;items&lt;/code&gt;。它马上把测试里的字段名改了，再跑一遍，全绿。&lt;/p&gt;
&lt;p&gt;整个调试过程，我做了什么？我什么也没做。我只是看着它一步一步跑完。&lt;/p&gt;
&lt;p&gt;这就是 Bruno + CLI + AI 的真正价值。你的 API 测试不再是一个孤立的、需要你手动维护的负担，而是变成了 AI 可以读、可以写、可以跑、可以调试的一种代码。&lt;/p&gt;
&lt;p&gt;它和你的源码、你的 Git 历史、你的 CI/CD、你的 AI agent，全都是一体的。&lt;/p&gt;
&lt;p&gt;写到这里我猜有人要拍桌子了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;「等等，国内程序员谁还用 Postman 啊？Apifox 它不香吗？」&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;发，我们专门聊聊 Apifox。&lt;/p&gt;
&lt;p&gt;我必须先承认它真的很强。一体化平台，API 文档、调试、Mock、自动化测试、团队协作全在一个工具里搞定，相当于 Postman + Swagger + JMeter 三合一。界面是中文，文档是中文，国内团队几乎零学习成本。如果你的团队 20 人以上，需要权限管理、需要实时协作、需要统一的 API 文档管理，Apifox 是比 Bruno 更合适的选择。这点我不否认。&lt;/p&gt;
&lt;p&gt;而且 Apifox 不傻，它也在跟上 AI 浪潮。它有 apifox-cli，能在终端里跑测试场景。它甚至专门做了 Apifox MCP Server，可以让 Cursor 和 Claude Desktop 读取 Apifox 项目里的 API 文档，帮你写代码。&lt;/p&gt;
&lt;p&gt;那问题来了，Bruno 和 Apifox 在 AI 这件事上到底有啥不一样？&lt;/p&gt;
&lt;p&gt;我读了一圈 Apifox 的官方文档，发现一个挺有意思的差别。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Apifox 接 AI 的方式，是让 AI 来连接 Apifox。Bruno 接 AI 的方式，是 Bruno 根本就是 AI 已经会读的格式。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;具体说，Apifox 的 AI 工作流是这样的，你的测试数据躺在 Apifox 云端项目里，你装一个 Apifox MCP Server，配置 Cursor 去连这个 MCP，AI 通过 MCP 协议向 Apifox 服务发请求，把 API 文档拿下来，再帮你生成代码。&lt;/p&gt;
&lt;p&gt;Bruno 的 AI 工作流是这样的，你的测试就是项目目录里的 .bru 文件，AI 直接 cat、edit、bru run。完了。&lt;/p&gt;
&lt;p&gt;你看出区别了吗？Apifox 把 AI 当成一个外部工具来对接，所以需要 MCP 这一层中转。而 Bruno 根本不需要 MCP，因为它跟 AI 用的是同一种原生语言：&lt;strong&gt;文本文件加终端命令。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;还有一个更现实的差别。Apifox 的 MCP Server 现在的能力，是让 AI 读取 API 文档来生成代码，它并不能让 AI 直接去编辑你的测试用例。AI 在 Apifox 这边的角色基本上是只读的。&lt;/p&gt;
&lt;p&gt;而我前面演示的那两个场景，Claude Code 帮我写新测试、自动调试、修字段名，那是完整的读写跑改循环。AI 不光在读，还在写，还在跑，还在调试。这是因为 .bru 是普通文件，Edit 工具就能改，Bash 工具就能跑。它中间没有任何一层，所以也没有任何一层会卡住。&lt;/p&gt;
&lt;p&gt;这不是说 Apifox 不好，是两条不同的路。Apifox 选的是「我是平台，AI 来连我」，Bruno 选的是「我什么都不是，我就是文件」。前者适合企业级场景，后者适合代码即测试的开发者工作流。&lt;/p&gt;
&lt;p&gt;我自己是后者。我喜欢我所有的东西都能塞进 Git 仓库，喜欢 AI 直接读我硬盘上的文件，不喜欢任何账号、登录、云端中转。所以我选 Bruno。&lt;/p&gt;
&lt;p&gt;如果你的工作场景更接近企业级 SaaS 那一套，那 Apifox 完全没问题，甚至更合适。但如果你跟我一样，希望让 AI 一句话把接口测试搞定，那 Bruno 这条路确实更顺。&lt;/p&gt;
&lt;p&gt;聊完 Apifox 我们继续。顺便提一下 CI 集成，因为这块也很丝滑。Bruno CLI 支持输出 JUnit XML，GitHub Actions、GitLab CI、Jenkins 直接吃这个格式。我的工作流文件大概长这样。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;- name: 安装 Bruno CLI run: npm install -g @usebruno/cli- name: 跑接口测试 run: bru run --env production --reporter-junit junit.xml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;两步。你的 PR 一提交，所有接口测试自动跑一遍，挂了直接拒绝合并。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-postman-yue-lai-yue-yong-zhong-le-wo-huan-le-ge-kai-yuan-de-/007-56b53ed9.png"&gt;&lt;/p&gt;
&lt;p&gt;生成的测试执行也挺好看的&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-postman-yue-lai-yue-yong-zhong-le-wo-huan-le-ge-kai-yuan-de-/008-cc895180.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-04-13-postman-yue-lai-yue-yong-zhong-le-wo-huan-le-ge-kai-yuan-de-/009-90333e8c.png"&gt;&lt;/p&gt;
&lt;p&gt;整套东西免费、开源、本地、Git 友好、AI 友好，不用登录、不用付钱、不用担心数据上云。&lt;/p&gt;
&lt;p&gt;安装很简单。桌面版，&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;brew install bruno
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="sb"&gt;```&lt;/span&gt;bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;CLI，
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="sb"&gt;```&lt;/span&gt;bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;npm i -g @usebruno/cli
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;用了一周之后我把 Postman 卸了。&lt;/p&gt;
&lt;p&gt;不是它不好，是我不再需要一个登录才能用、集合存在别人云上、免费版各种限制、AI 完全帮不上忙的接口测试工具了。&lt;/p&gt;
&lt;p&gt;我只需要一个文件夹、几个 .bru 文件、一条终端命令，和一个能读懂这一切的 AI。&lt;/p&gt;
&lt;p&gt;有时候工具的进步不是功能越加越多，而是把不该有的东西去掉。Bruno 去掉了登录、去掉了云端、去掉了 GUI 锁定，剩下的全是程序员真正需要的东西。&lt;/p&gt;
&lt;p&gt;而当你把这些不需要的东西去掉之后，你会发现一个意外的副作用，AI 进来了。&lt;/p&gt;
&lt;p&gt;好了就说这么多。&lt;/p&gt;
&lt;p&gt;如果你也受够了 Postman，试试 Bruno。说不定你也会像我一样，用完就回不去了。&lt;/p&gt;
&lt;p&gt;ps:我写的 demo 在这里，你可以拉下来试一下，可以 run 的 ：https://github.com/xiaobox/bruno-demo&lt;/p&gt;</description></item><item><title>Vim 从何而来</title><link>https://xiaobox.github.io/p/2023-11-04-vim-cong-he-er-lai/</link><pubDate>Sat, 04 Nov 2023 06:38:45 +0000</pubDate><guid>https://xiaobox.github.io/p/2023-11-04-vim-cong-he-er-lai/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-04-vim-cong-he-er-lai/cover.jpg" alt="Featured image of post Vim 从何而来" /&gt;&lt;p&gt;Vim 编辑器的创造者、维护者和终身领导者 Bram Moolenaar 于 2023 年 8 月 3 日因病去世，享年 62 岁&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-04-vim-cong-he-er-lai/001-f4d5def9.png"&gt;为了纪念这位杰出的荷兰程序员，我们今天来聊一聊 Vim 的历史。&lt;/p&gt;
&lt;p&gt;Vim 无处不在。它被很多人使用。同时 Vim 可能是世界上 “最难用的软件之一” ，但是又多次被程序员们评价为 最受欢迎的 代码编辑器。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-04-vim-cong-he-er-lai/002-74d85dda.png"&gt;&lt;/p&gt;
&lt;p&gt;Vim 预装在 Mac OS 上，并且在 Linux 领域拥有大量支持者。即使对于那些讨厌它的人来说，它也很熟悉，因为足够流行的命令行工具会默认将用户带入 Vim。&lt;/p&gt;
&lt;p&gt;有一些主要网站，包括 Facebook，当你按 &lt;code&gt;j&lt;/code&gt; 键时会向下滚动，当你按 &lt;code&gt;k&lt;/code&gt; 键时会向上滚动 — 这就是通过 Vim 的广泛传播而形成的文化。&lt;/p&gt;
&lt;p&gt;然而 Vim 也是一个谜。&lt;/p&gt;
&lt;p&gt;例如，与众所周知的由 Facebook 开发和维护的 &lt;code&gt;React&lt;/code&gt; 不同，Vim 没有明显的赞助商。&lt;/p&gt;
&lt;p&gt;尽管它无处不在且很重要，但似乎没有任何类型的委员会或组织对 Vim 做出决策。&lt;/p&gt;
&lt;p&gt;你可能会花几分钟浏览 Vim 网站（https://www.vim.org），但无法更好地了解谁创建了 Vim 或为什么创建。&lt;/p&gt;
&lt;p&gt;如果你启动 Vim 时没有给它提供文件参数，那么你将看到 Vim 的启动消息，其中显示 Vim 是由“Bram Moolenaar 等人”开发的。但这并不能告诉你太多。布拉姆·穆勒纳尔 (Bram Moolenaar) 是谁？他的合作者又是谁？&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-04-vim-cong-he-er-lai/003-4ef42ca2.png"&gt;&lt;/p&gt;
&lt;p&gt;也许更重要的是，为什么退出 Vim 需要输入 &lt;code&gt;:wq&lt;/code&gt; ？&lt;/p&gt;
&lt;p&gt;当然，这是一个“写入”操作，然后是一个“退出”操作，但这并不是一个特别直观的约定。谁决定复制文本应该被称为“yanking”？为什么 &lt;code&gt;:%s/foo/bar/gc&lt;/code&gt; 是“查找和替换”的缩写？Vim 的特性似乎太随意了，不可能是虚构的，但它们是从哪里来的呢？&lt;/p&gt;
&lt;p&gt;正如通常的情况一样，答案始于古老——贝尔实验室。从某种意义上说，Vim 只是一个软件的最新版本——称之为“wq 文本编辑器”——自 Unix 时代开始以来一直在不断开发和改进。&lt;/p&gt;
&lt;h2 id="ken-thompson-编写了一个行编辑器"&gt;&lt;a href="#ken-thompson-%e7%bc%96%e5%86%99%e4%ba%86%e4%b8%80%e4%b8%aa%e8%a1%8c%e7%bc%96%e8%be%91%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;Ken Thompson 编写了一个行编辑器
&lt;/h2&gt;&lt;p&gt;1966 年，贝尔实验室聘请了 Ken Thompson。汤普森刚刚在加州大学伯克利分校获得了电气工程和计算机科学硕士学位。在那里，他使用了一个名为 QED 的文本编辑器，该编辑器是在 1965 年至 1966 年间为伯克利分时系统编写的。&lt;/p&gt;
&lt;p&gt;汤普森到达贝尔实验室后做的第一件事就是为麻省理工学院兼容时间重写 QED - 共享系统。后来他为 Multics 项目编写了 QED 的另一个版本。在此过程中，他扩展了该程序，以便用户可以搜索文件中的行并使用正则表达式进行替换。&lt;/p&gt;
&lt;p&gt;Multics 项目与伯克利分时系统一样，旨在创建一个商业上可行的分时操作系统，该项目是麻省理工学院、通用电气和贝尔实验室之间的合作项目。AT&amp;amp;T 最终认为该项目毫无进展并退出。&lt;/p&gt;
&lt;p&gt;汤普森和贝尔实验室研究员丹尼斯·里奇现在无法访问分时系统，他们开始创建自己的版本，最终被称为 Unix。1969 年 8 月，当他的妻子和年幼的儿子去加利福尼亚度假时，Thompson 组装了新系统的基本组件，“为操作系统、shell、编辑器各分配了一周的时间”。&lt;/p&gt;
&lt;p&gt;编辑器将被称为 &lt;code&gt;ed&lt;/code&gt; 。它基于 QED，但并不是精确的重新实现。Thompson 决定放弃某些 QED 功能。正则表达式支持被削减，以便只能理解相对简单的正则表达式。QED 允许用户通过打开多个缓冲区来一次编辑多个文件，但 &lt;code&gt;ed&lt;/code&gt; 一次只能使用一个缓冲区。尽管 QED 可以执行包含命令的缓冲区，但 &lt;code&gt;ed&lt;/code&gt; 不会执行此类操作。可能需要进行这些简化。Dennis Ritchie 表示，没有 QED 的高级正则表达式“并没有多大损失”&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ed&lt;/code&gt; 现在是 POSIX 规范的一部分，因此如果你有兼容 POSIX 的系统，则可以将其安装在你的计算机上。它值得一试，因为许多 &lt;code&gt;ed&lt;/code&gt; 命令如今已成为 Vim 的一部分。例如，为了将缓冲区写入磁盘，你必须使用 &lt;code&gt;w&lt;/code&gt; 命令。为了退出编辑器，你必须使用 &lt;code&gt;q&lt;/code&gt; 命令。这两个命令可以同时在同一行指定 - &lt;code&gt;wq&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;与 Vim 一样， &lt;code&gt;ed&lt;/code&gt; 是一个模式编辑器；要从命令模式进入输入模式，你可以使用插入命令（ &lt;code&gt;i&lt;/code&gt; ）、附加命令（ &lt;code&gt;a&lt;/code&gt; ）或更改命令（ &lt;code&gt;c&lt;/code&gt; ），取决于你如何转换文本。&lt;code&gt;ed&lt;/code&gt; 还引入了用于查找和替换（或“替换”）文本的 &lt;code&gt;s/foo/bar/g&lt;/code&gt; 语法。&lt;/p&gt;
&lt;p&gt;鉴于所有这些相似之处，你可能认为普通 Vim 用户使用 &lt;code&gt;ed&lt;/code&gt; 不会遇到任何问题。但 &lt;code&gt;ed&lt;/code&gt; 在另一个重要方面与 Vim 完全不同。&lt;code&gt;ed&lt;/code&gt; 是一个真正的行编辑器。它是在电传打字机时代编写并广泛使用的。当 Ken Thompson 和 Dennis Ritchie 攻克 Unix 时，他们看起来像这样：&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-04-vim-cong-he-er-lai/004-b07e8a57.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ed&lt;/code&gt; 不允许你在打开缓冲区的其他行之间编辑行，或移动光标，因为 &lt;code&gt;ed&lt;/code&gt; 每次都必须重新打印整个文件对其进行了更改。1969 年的时候， &lt;code&gt;ed&lt;/code&gt; 还没有“清除”屏幕内容的机制，因为屏幕只是一张纸，已经输出的所有内容都是用墨水输出的。必要时，你可以要求 &lt;code&gt;ed&lt;/code&gt; 使用列表命令 ( &lt;code&gt;l&lt;/code&gt; ) 为您打印出一系列行。因此，使用 &lt;code&gt;ed&lt;/code&gt; 有点像试图用功率不足的手电筒在黑暗的房子里寻找出路。你一次只能看到这么多，所以你必须尽力记住所有东西在哪里。&lt;/p&gt;
&lt;p&gt;这是 &lt;code&gt;ed&lt;/code&gt; 会话的示例。我添加了注释（在 # 字符之后）来解释每行的用途&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;tt 09:49 ~&lt;span class="o"&gt;]&lt;/span&gt;$ ed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;i &lt;span class="c1"&gt;# Enter input mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;Hello world!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;Isn&lt;span class="s1"&gt;&amp;#39;t it a nice day?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;. # Finish input
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;1,2l # List lines 1 to 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Hello world!$
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;$
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;2d # Delete line 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;,l # List entire buffer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Hello world!$
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Isn&amp;#39;&lt;/span&gt;t it a nice day?$
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;s/nice/terrible/g &lt;span class="c1"&gt;# Substitute globally&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;,l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;Hello world!$
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;Isn&lt;span class="s1"&gt;&amp;#39;t it a terrible day?$
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;w foo.txt # Write to foo.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;38 # (bytes written)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;q # Quit
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;[sinclairtarget 10:50 ~]$ cat foo.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Hello world!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Isn&amp;#39;&lt;/span&gt;t it a terrible day?
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="bill-joy-编写了一个文本编辑器"&gt;&lt;a href="#bill-joy-%e7%bc%96%e5%86%99%e4%ba%86%e4%b8%80%e4%b8%aa%e6%96%87%e6%9c%ac%e7%bc%96%e8%be%91%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;Bill Joy 编写了一个文本编辑器
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;ed&lt;/code&gt; 对于 Thompson 和 Ritchie 来说工作得足够好。但其他人发现它很难使用，并且它被认为是 Unix 对新手特别不友好的一个例子。&lt;/p&gt;
&lt;p&gt;1975 年，一位名叫 George Coulouris 的人在伦敦玛丽女王学院安装的 Unix 系统上开发了 ed 的改进版本。&lt;/p&gt;
&lt;p&gt;与 &lt;code&gt;ed&lt;/code&gt; 不同，Coulouris 的程序允许用户在屏幕上编辑一行，逐个按键地浏览该行。Coulouris 称他的程序为 em ，或“凡人的编辑器”&lt;/p&gt;
&lt;p&gt;1976 年，Coulouris 带着 &lt;code&gt;em&lt;/code&gt; 来到加州大学伯克利分校，并以客座教授的身份在加州大学伯克利分校度过了一个夏天。此时距离肯·汤普森离开伯克利去贝尔实验室工作整整十年了。在伯克利，Coulouris 遇到了 Bill Joy，他是一名从事 Berkeley Software Distribution (BSD) 工作的研究生。Coulouris 向 Joy 展示了 &lt;code&gt;em&lt;/code&gt; ，Joy 从 Coulouris 的源代码开始构建了 &lt;code&gt;ed&lt;/code&gt; 的改进版本，称为 &lt;code&gt;ex&lt;/code&gt; ，用于“扩展 &lt;code&gt;ed&lt;/code&gt; 的 1.1 版本与 1978 年 BSD Unix 的第一个版本捆绑在一起。&lt;code&gt;ex&lt;/code&gt; 很大程度上与 &lt;code&gt;ed&lt;/code&gt; 兼容，但它增加了两种模式：“open”模式，它启用了单行编辑，就像 &lt;code&gt;em&lt;/code&gt; 一样，以及“视觉”模式，它接管整个屏幕并启用整个文件的实时编辑，就像我们今天习惯的那样。&lt;/p&gt;
&lt;p&gt;1979 年的第二个 BSD 版本，引入了一个名为 &lt;code&gt;vi&lt;/code&gt; 的可执行文件，它的作用只不过是在可视模式下打开 &lt;code&gt;ex&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ex / vi&lt;/code&gt; （此后称为 &lt;code&gt;vi&lt;/code&gt; ）建立了我们现在与 Vim 关联的大部分约定，这些约定尚未成为 &lt;code&gt;ed&lt;/code&gt; 的一部分。Joy 使用的视频终端是 Lear Siegler ADM-3A，其键盘没有光标键。相反，箭头被绘制在 &lt;code&gt;h&lt;/code&gt; 、 &lt;code&gt;j&lt;/code&gt; 、 &lt;code&gt;k&lt;/code&gt; 和 &lt;code&gt;l&lt;/code&gt; 键上，这就是 Joy 使用这些键作为光标的原因 vi 中的移动。ADM-3A 键盘上的退出键也是今天我们可以找到 Tab 键的地方。&lt;/p&gt;
&lt;p&gt;命令前缀的&lt;code&gt;:&lt;/code&gt;字符也来自 &lt;code&gt;vi&lt;/code&gt; ，在常规模式下（即通过运行 &lt;code&gt;ex&lt;/code&gt; 输入的模式）使用 &lt;code&gt;:&lt;/code&gt; 作为提示。这解决了长期以来对 &lt;code&gt;ed&lt;/code&gt; 的抱怨。在可视模式下，保存和退出现在需要输入经典的 &lt;code&gt;:wq&lt;/code&gt; 。“Yanking”和“putting”、标记以及用于设置选项的 &lt;code&gt;set&lt;/code&gt; 命令都是原始 &lt;code&gt;vi&lt;/code&gt; 的一部分。我们今天在 Vim 中进行基本文本编辑过程中使用的功能主要是 &lt;code&gt;vi&lt;/code&gt; 功能。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-04-vim-cong-he-er-lai/005-73369976.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;vi&lt;/code&gt; 是除 &lt;code&gt;ed&lt;/code&gt; 之外唯一与 BSD Unix 捆绑在一起的文本编辑器。当时，Emacs 可能要花费数百美元（这是在 GNU Emacs 之前），因此 &lt;code&gt;vi&lt;/code&gt; 变得非常流行。但 &lt;code&gt;vi&lt;/code&gt; 是 &lt;code&gt;ed&lt;/code&gt; 的直接后代，这意味着如果没有 AT&amp;amp;T 源许可证，则无法修改源代码。这促使一些人创建 &lt;code&gt;vi&lt;/code&gt; 的开源版本。STEVIE（VI 爱好者的 ST 编辑器）出现于 1987 年，Elvis 出现于 1990 年， nvi 出现于 1994 年。其中一些克隆添加了额外的功能，如语法突出显示和分割窗口。尤其是 Elvis，它的许多功能都被纳入了 Vim，因为许多 Elvis 用户都在推动将其纳入其中。&lt;/p&gt;
&lt;h2 id="bram-moolenaar-撰写-vim"&gt;&lt;a href="#bram-moolenaar-%e6%92%b0%e5%86%99-vim" class="header-anchor"&gt;&lt;/a&gt;Bram Moolenaar 撰写 Vim
&lt;/h2&gt;&lt;p&gt;“Vim” 现在缩写为“Vi Improve”，最初代表“Vi Imitation”。与许多其他 &lt;code&gt;vi&lt;/code&gt; 克隆一样，Vim 最初是尝试在不可用的平台上复制 &lt;code&gt;vi&lt;/code&gt; 。Bram Moolenaar 是一位荷兰软件工程师，在荷兰 Venlo 的一家复印机公司工作，他想要为他全新的 Amiga 2000 使用类似 &lt;code&gt;vi&lt;/code&gt; 的东西。在 1988 年，Moolenaar 以现有的 STEVIE vi 克隆为起点，开始研究 Vim。&lt;/p&gt;
&lt;p&gt;Moolenaar 可以访问 STEVIE，因为 STEVIE 之前曾出现在名为 Fred Fish 磁盘的东西上。Fred Fish 是一位美国程序员，他每个月都会寄出一张软盘，其中包含精选的适用于 Amiga 平台的最佳开源软件。任何人都可以索取磁盘，只需支付邮费即可。Fred Fish 磁盘上发布了 STEVIE 的多个版本。Moolenaar 使用的版本已在 Fred Fish 磁盘 256 上发布。&lt;/p&gt;
&lt;p&gt;Moolenaar 喜欢 STEVIE，但很快注意到缺少许多 &lt;code&gt;vi&lt;/code&gt; 命令。因此，对于 Vim 的第一个版本，Moolenaar 将 &lt;code&gt;vi&lt;/code&gt; 兼容性作为他的首要任务。其他人编写了一系列 &lt;code&gt;vi&lt;/code&gt; 宏，Moolenaar 能够让这些宏在 Vim 中运行。1991 年，Vim 首次在 Fred Fish 磁盘 591 上发布，名称为“Vi Imitation”。Moolenaar 添加了一些功能（包括多级撤消和针对编译器错误的“快速修复”模式），这意味着 Vim 已经超越了 &lt;code&gt;vi&lt;/code&gt; 。但 Vim 一直是“Vi Imitation（模仿）”，直到 1993 年通过 FTP 发布 Vim 2.0。&lt;/p&gt;
&lt;p&gt;Moolenaar 在各种互联网合作者的偶尔帮助下，稳定地为 Vim 添加了功能。Vim 2.0 引入了对 &lt;code&gt;wrap&lt;/code&gt; 选项和水平滚动长行文本的支持。Vim 3.0 添加了对分割窗口和缓冲区的支持，该功能受到 &lt;code&gt;vi&lt;/code&gt; 克隆 &lt;code&gt;nvi&lt;/code&gt; 的启发。Vim 现在还将每个缓冲区保存到交换文件中，以便编辑后的文本可以在崩溃时幸存下来。Vimscript 首次出现在 Vim 5.0 中，并支持语法突出显示。与此同时，Vim 的受欢迎程度与日俱增。它被移植到 MS-DOS、Windows、Mac，甚至 Unix，与原始的 &lt;code&gt;vi&lt;/code&gt; 竞争。&lt;/p&gt;
&lt;p&gt;2006 年，Vim 被评选为最受 Linux Journal 读者欢迎的编辑器。如今，根据 Stack Overflow 的 2018 年开发者调查，Vim 是最流行的文本模式（即终端仿真器）编辑器，25.8% 的软件开发人员（以及 40% 的系统管理员/DevOps 人员）使用它。有一段时间，在 20 世纪 80 年代末和整个 90 年代，程序员发动了“编辑器战争”，使 Emacs 用户与 &lt;code&gt;vi&lt;/code&gt; （最终是 Vim）用户对立。虽然 Emacs 当然仍然有一些追随者，但有些人认为编辑器之战已经结束，Vim 获胜了。2018 年 Stack Overflow 开发者调查表明这是事实；只有 4.1% 的受访者使用 Emacs。&lt;/p&gt;
&lt;p&gt;Vim 是如何变得如此成功的？显然人们喜欢 Vim 提供的功能。但我认为，Vim 背后的悠久历史表明，它拥有的优势不仅仅是其功能集。Vim 的代码库可以追溯到 1988 年，当时 Moolenaar 开始研究它。“wq 文本编辑器”有几种不同的具体表达方式，但部分归功于 Bill Joy 和 Bram Moolenaar 对向后兼容性的不同寻常的关注，随着时间的推移，好的想法逐渐积累起来。从这个意义上说，“wq 文本编辑器”是运行时间最长、最成功的开源项目之一，得到了计算世界中一些最伟大思想家的贡献。我不认为“初创公司抛弃所有先例并创造颠覆性新软件”的开发方法一定是坏事，但 Vim 提醒我们，协作和增量方法也可以产生奇迹。&lt;/p&gt;</description></item><item><title>vim 配置 nginx 语法高亮</title><link>https://xiaobox.github.io/p/2021-09-06-vim-pei-zhi-nginx-yu-fa-gao-liang/</link><pubDate>Mon, 06 Sep 2021 07:33:47 +0000</pubDate><guid>https://xiaobox.github.io/p/2021-09-06-vim-pei-zhi-nginx-yu-fa-gao-liang/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-09-06-vim-pei-zhi-nginx-yu-fa-gao-liang/cover.jpg" alt="Featured image of post vim 配置 nginx 语法高亮" /&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;当你使用 vim 编辑器编辑 nginx 的配置文件时，vim 编辑器是无法自动识别出 nginx 的相关语法的。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;所以，使用 vim 编辑器编辑 nginx 配置文件时，无法实现”语法高亮”功能，也就是说，默认情况下，使用 vim 编辑 nginx 配置文件时，没有彩色的语法着色。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于使用者来说，这样体验不好，nginx 官方很贴心，在源码包中为我们提供了 vim 针对 nginx 的语法高亮配置文件，我们只要把这些文件拷贝到 vim 的对应目录中即可直接使用，方法很简单&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# wget http://nginx.org/download/nginx-1.14.2.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# tar -xf nginx-1.14.2.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;进入到源码包解压目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cd nginx-1.14.2/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;将相应的语法文件拷贝到对应的目录中，即可完成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cp -r contrib/vim/* /usr/share/vim/vimfiles/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-09-06-vim-pei-zhi-nginx-yu-fa-gao-liang/001-b77bd5fb.jpg"&gt;&lt;/p&gt;
&lt;p&gt;参考：https://www.zsythink.net/archives/3091&lt;/p&gt;</description></item><item><title>centos7 使用kubeadm 安装 k8s集群</title><link>https://xiaobox.github.io/p/2021-03-21-centos7-shi-yong-kubeadm-an-zhuang-k8s-ji-qun/</link><pubDate>Sun, 21 Mar 2021 10:56:34 +0000</pubDate><guid>https://xiaobox.github.io/p/2021-03-21-centos7-shi-yong-kubeadm-an-zhuang-k8s-ji-qun/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-03-21-centos7-shi-yong-kubeadm-an-zhuang-k8s-ji-qun/cover.jpg" alt="Featured image of post centos7 使用kubeadm 安装 k8s集群" /&gt;&lt;h2 id="环境"&gt;&lt;a href="#%e7%8e%af%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;环境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;centos 7.6&lt;/li&gt;
&lt;li&gt;k8s 1.13.4&lt;/li&gt;
&lt;li&gt;3台机器 1台master 2台worker&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="准备工作"&gt;&lt;a href="#%e5%87%86%e5%a4%87%e5%b7%a5%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;准备工作
&lt;/h2&gt;&lt;h3 id="关闭swap"&gt;&lt;a href="#%e5%85%b3%e9%97%adswap" class="header-anchor"&gt;&lt;/a&gt;关闭swap
&lt;/h3&gt;&lt;p&gt;执行swapoff临时关闭swap。重启后会失效，若要永久关闭，可以编辑/etc/fstab文件，将其中swap分区一行注释掉&lt;/p&gt;
&lt;p&gt;至于为什么关闭这里有个说明：&lt;code&gt;https://github.com/kubernetes/kubernetes/issues/53533&lt;/code&gt;，亦有说影响性能的 &lt;code&gt;https://www.zhihu.com/question/374752553&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="关闭防火墙和selinux"&gt;&lt;a href="#%e5%85%b3%e9%97%ad%e9%98%b2%e7%81%ab%e5%a2%99%e5%92%8cselinux" class="header-anchor"&gt;&lt;/a&gt;关闭防火墙和selinux
&lt;/h3&gt;&lt;p&gt;根据文档来的:&lt;code&gt;https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;# 将 SELinux 设置为 permissive 模式（相当于将其禁用）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;setenforce 0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;sed -i &amp;#39;s/^SELINUX=enforcing$/SELINUX=permissive/&amp;#39; /etc/selinux/config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="开放端口"&gt;&lt;a href="#%e5%bc%80%e6%94%be%e7%ab%af%e5%8f%a3" class="header-anchor"&gt;&lt;/a&gt;开放端口
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-03-21-centos7-shi-yong-kubeadm-an-zhuang-k8s-ji-qun/001-dfefcdc1.jpg"&gt;&lt;/p&gt;
&lt;h3 id="允许-iptables-检查桥接流量"&gt;&lt;a href="#%e5%85%81%e8%ae%b8-iptables-%e6%a3%80%e6%9f%a5%e6%a1%a5%e6%8e%a5%e6%b5%81%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;允许 iptables 检查桥接流量
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt;EOF | sudo tee /etc/modules-load.d/k8s.conf
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;br_netfilter
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt;EOF | sudo tee /etc/sysctl.d/k8s.conf
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;net.bridge.bridge-nf-call-ip6tables = 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;net.bridge.bridge-nf-call-iptables = 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;9&lt;/span&gt;&lt;span class="cl"&gt;sudo sysctl --system
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="安装docker全部节点"&gt;&lt;a href="#%e5%ae%89%e8%a3%85docker%e5%85%a8%e9%83%a8%e8%8a%82%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;安装docker（全部节点）
&lt;/h2&gt;&lt;h3 id="安装"&gt;&lt;a href="#%e5%ae%89%e8%a3%85" class="header-anchor"&gt;&lt;/a&gt;安装
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#安装需要的工具&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;yum&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;yum&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;utils&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;persistent&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;lvm2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#设置源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;yum&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;mirrors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;aliyun&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ce&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;centos&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ce&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#查看有哪些docker版本&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;yum&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ce&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;showduplicates&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;sort&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#安装特定的版本&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;yum&lt;/span&gt; &lt;span class="n"&gt;makecache&lt;/span&gt; &lt;span class="n"&gt;fast&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;yum&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ce&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;18.09&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="n"&gt;el7&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ce&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;18.09&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="n"&gt;el7&lt;/span&gt; &lt;span class="n"&gt;containerd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="n"&gt;el7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#启动docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;systemctl&lt;/span&gt; &lt;span class="n"&gt;daemon&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;reload&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;systemctl&lt;/span&gt; &lt;span class="n"&gt;restart&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#设置为开机启动&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;systemctl&lt;/span&gt; &lt;span class="n"&gt;enable&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="修改docker默认存储位置"&gt;&lt;a href="#%e4%bf%ae%e6%94%b9docker%e9%bb%98%e8%ae%a4%e5%ad%98%e5%82%a8%e4%bd%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;修改Docker默认存储位置
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;systemctl&lt;/span&gt; &lt;span class="err"&gt;stop&lt;/span&gt; &lt;span class="err"&gt;docker&lt;/span&gt; &lt;span class="err"&gt;或者&lt;/span&gt; &lt;span class="err"&gt;service&lt;/span&gt; &lt;span class="err"&gt;docker&lt;/span&gt; &lt;span class="err"&gt;stop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;#然后移动整个/var/lib/docker目录到目的路径：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;mv&lt;/span&gt; &lt;span class="err"&gt;/var/lib/docker&lt;/span&gt; &lt;span class="err"&gt;/home/data/docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;ln&lt;/span&gt; &lt;span class="err"&gt;-s&lt;/span&gt; &lt;span class="err"&gt;/home/data/docker&lt;/span&gt; &lt;span class="err"&gt;/var/lib/docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;#reload配置文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;systemctl&lt;/span&gt; &lt;span class="err"&gt;daemon-reload&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;#重启docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;systemctl&lt;/span&gt; &lt;span class="err"&gt;restart&lt;/span&gt; &lt;span class="err"&gt;docker.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;#设置docker&lt;/span&gt; &lt;span class="err"&gt;开机启动&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;systemctl&lt;/span&gt; &lt;span class="err"&gt;enable&lt;/span&gt; &lt;span class="err"&gt;docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//当然你也可以通过修改配置文件的方式
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;vim&lt;/span&gt; &lt;span class="err"&gt;/etc/docker/daemon.json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;registry-mirrors&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://7e61f7f9.m.daocloud.io&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;graph&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/new-path/docker&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="阿里云镜像加速"&gt;&lt;a href="#%e9%98%bf%e9%87%8c%e4%ba%91%e9%95%9c%e5%83%8f%e5%8a%a0%e9%80%9f" class="header-anchor"&gt;&lt;/a&gt;阿里云镜像加速
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#访问：https://cr.console.aliyun.com/cn-beijing/instances/mirrors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#找到加速方法，如：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;sudo mkdir -p /etc/docker
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;sudo tee /etc/docker/daemon.json &lt;span class="s"&gt;&amp;lt;&amp;lt;-&amp;#39;EOF&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;registry-mirrors&amp;#34;: [&amp;#34;https://se35r65b.mirror.aliyuncs.com&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;sudo systemctl daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;sudo systemctl restart docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="安装kubeadm-kubelet和kubectlmaster和worker都装"&gt;&lt;a href="#%e5%ae%89%e8%a3%85kubeadm-kubelet%e5%92%8ckubectlmaster%e5%92%8cworker%e9%83%bd%e8%a3%85" class="header-anchor"&gt;&lt;/a&gt;安装kubeadm, kubelet和kubectl(master和worker都装)
&lt;/h2&gt;&lt;h3 id="添加-yum-仓库-创建etcyumreposdkubernetesrepo文件如下内容"&gt;&lt;a href="#%e6%b7%bb%e5%8a%a0-yum-%e4%bb%93%e5%ba%93-%e5%88%9b%e5%bb%baetcyumreposdkubernetesrepo%e6%96%87%e4%bb%b6%e5%a6%82%e4%b8%8b%e5%86%85%e5%ae%b9" class="header-anchor"&gt;&lt;/a&gt;添加 yum 仓库 创建/etc/yum.repos.d/kubernetes.repo，文件如下内容
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;[kubernetes]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;name=Kubernetes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;enabled=1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;gpgcheck=1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;repo_gpgcheck=1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="安装--kubelet-kubectl-和-kubeadm"&gt;&lt;a href="#%e5%ae%89%e8%a3%85--kubelet-kubectl-%e5%92%8c-kubeadm" class="header-anchor"&gt;&lt;/a&gt;安装 kubelet kubectl 和 kubeadm
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;yum install -y kubelet-1.13.4 kubeadm-1.13.4 kubectl-1.13.4 kubernetes-cni-0.6.0 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;systemctl enable --now kubelet
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="从阿里云手动摘取镜像"&gt;&lt;a href="#%e4%bb%8e%e9%98%bf%e9%87%8c%e4%ba%91%e6%89%8b%e5%8a%a8%e6%91%98%e5%8f%96%e9%95%9c%e5%83%8f" class="header-anchor"&gt;&lt;/a&gt;从阿里云手动摘取镜像
&lt;/h3&gt;&lt;p&gt;执行kubeadm config images pull查 看到 gcr.io 的连接，如果拉取成功可以进入下一步。如果失败，说明无法访问 grc.io。这时需要手动拉取镜像，可以执行下面的脚本，从阿里云拉取相应镜像&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;images&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; kube-apiserver:v1.13.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; kube-controller-manager:v1.13.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; kube-scheduler:v1.13.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; kube-proxy:v1.13.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; pause:3.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; etcd:3.2.24
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; coredns:1.2.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; imageName in &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/&lt;span class="nv"&gt;$imageName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/&lt;span class="nv"&gt;$imageName&lt;/span&gt; k8s.gcr.io/&lt;span class="nv"&gt;$imageName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="初始化master"&gt;&lt;a href="#%e5%88%9d%e5%a7%8b%e5%8c%96master" class="header-anchor"&gt;&lt;/a&gt;初始化（master）
&lt;/h2&gt;&lt;h3 id="记得加入-pod-network-cidr-因为后面的网络组件用的是flannel"&gt;&lt;a href="#%e8%ae%b0%e5%be%97%e5%8a%a0%e5%85%a5-pod-network-cidr-%e5%9b%a0%e4%b8%ba%e5%90%8e%e9%9d%a2%e7%9a%84%e7%bd%91%e7%bb%9c%e7%bb%84%e4%bb%b6%e7%94%a8%e7%9a%84%e6%98%afflannel" class="header-anchor"&gt;&lt;/a&gt;记得加入 pod-network-cidr 因为后面的网络组件用的是flannel
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;kubeadm init --pod-network-cidr=10.244.0.0/16 --image-repository registry.aliyuncs.com/google_containers
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="安装成功提示"&gt;&lt;a href="#%e5%ae%89%e8%a3%85%e6%88%90%e5%8a%9f%e6%8f%90%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;安装成功提示
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;Your Kubernetes master has initialized successfully!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;To start using your cluster, you need to run the following as a regular user:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; mkdir -p &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.kube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; sudo cp -i /etc/kubernetes/admin.conf &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.kube/config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; sudo chown &lt;span class="k"&gt;$(&lt;/span&gt;id -u&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="k"&gt;$(&lt;/span&gt;id -g&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.kube/config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;You should now deploy a pod network to the cluster.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;Run &lt;span class="s2"&gt;&amp;#34;kubectl apply -f [podnetwork].yaml&amp;#34;&lt;/span&gt; with one of the options listed at:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; https://kubernetes.io/docs/concepts/cluster-administration/addons/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;You can now join any number of machines by running the following on each node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;as root:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; kubeadm join 10.22.9.162:6443 --token e225cp.14g848dy4vpoas75 --discovery-token-ca-cert-hash sha256:aaf9910fb2b94e8c2bc2aea0b2a08538796d8322331561ef1094bebe8a7a790f
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="第一次使用-kubernetes-集群所需要的配置命令"&gt;&lt;a href="#%e7%ac%ac%e4%b8%80%e6%ac%a1%e4%bd%bf%e7%94%a8-kubernetes-%e9%9b%86%e7%be%a4%e6%89%80%e9%9c%80%e8%a6%81%e7%9a%84%e9%85%8d%e7%bd%ae%e5%91%bd%e4%bb%a4" class="header-anchor"&gt;&lt;/a&gt;第一次使用 Kubernetes 集群所需要的配置命令
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;mkdir -p &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.kube
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;sudo cp -i /etc/kubernetes/admin.conf &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.kube/config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;sudo chown &lt;span class="k"&gt;$(&lt;/span&gt;id -u&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="k"&gt;$(&lt;/span&gt;id -g&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.kube/config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这些配置命令的原因是：Kubernetes 集群默认需要加密方式访问。所以，这几条命令，就是将刚刚部署生成的 Kubernetes 集群的安全配置文件，保存到当前用户的.kube 目录下，kubectl 默认会使用这个目录下的授权信息访问 Kubernetes 集群。如果不这么做的话，我们每次都需要通过 &lt;code&gt;export KUBECONFIG&lt;/code&gt; 环境变量告诉 kubectl 这个安全配置文件的位置。&lt;/p&gt;
&lt;h3 id="master节点生成其他节点加入的方式"&gt;&lt;a href="#master%e8%8a%82%e7%82%b9%e7%94%9f%e6%88%90%e5%85%b6%e4%bb%96%e8%8a%82%e7%82%b9%e5%8a%a0%e5%85%a5%e7%9a%84%e6%96%b9%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;master节点生成其他节点加入的方式
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;kubeadm token create --print-join-command
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="部署-flannel-网络组件"&gt;&lt;a href="#%e9%83%a8%e7%bd%b2-flannel-%e7%bd%91%e7%bb%9c%e7%bb%84%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;部署 flannel 网络组件
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="查看状态"&gt;&lt;a href="#%e6%9f%a5%e7%9c%8b%e7%8a%b6%e6%80%81" class="header-anchor"&gt;&lt;/a&gt;查看状态
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 用 kubectl get 命令来查看当前唯一一个节点的状态了&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;kubectl get nodes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 用 kubectl describe 来查看这个节点（Node）对象的详细信息、状态和事件（Event）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;kubectl describe node master
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 通过 kubectl get 重新检查 Pod 的状态：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;kubectl get pods -n kube-system
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 部署过程中任何环节有问题都可以查看日志 &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;journalctl -l -u kubelet
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="master-节点配置"&gt;&lt;a href="#master-%e8%8a%82%e7%82%b9%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;master 节点配置
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;删除master节点默认污点 taint：污点的意思。如果一个节点被打上了污点，那么pod是不允许运行在这个节点上面的 默认情况下集群不会在master上调度pod，如果偏想在master上调度Pod，可以执行如下操作：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#查看污点&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;kubectl describe node master&lt;span class="p"&gt;|&lt;/span&gt;grep -i taints
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#删除污点&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;kubectl taint nodes master node-role.kubernetes.io/master-
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="加入集群worker"&gt;&lt;a href="#%e5%8a%a0%e5%85%a5%e9%9b%86%e7%be%a4worker" class="header-anchor"&gt;&lt;/a&gt;加入集群（worker）
&lt;/h2&gt;&lt;p&gt;利用之前master 初始化的信息加入集群&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;kubeadm join 10.22.9.162:6443 --token 43t2na.80oiehldy76rw6lz --discovery-token-ca-cert-hash sha256:67fd28cb6fd03242eda63c7a395096aba1a6784f7234a9b6269ff0941e9070e3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;加入成功后在master查看集群状态&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;kubectl get nodes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="安装dashboard-uimaster"&gt;&lt;a href="#%e5%ae%89%e8%a3%85dashboard-uimaster" class="header-anchor"&gt;&lt;/a&gt;安装Dashboard UI（master）
&lt;/h2&gt;&lt;h3 id="获得配置文件"&gt;&lt;a href="#%e8%8e%b7%e5%be%97%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;获得配置文件
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="手动获取镜像"&gt;&lt;a href="#%e6%89%8b%e5%8a%a8%e8%8e%b7%e5%8f%96%e9%95%9c%e5%83%8f" class="header-anchor"&gt;&lt;/a&gt;手动获取镜像
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;docker pull anjia0532/google-containers.kubernetes-dashboard-amd64:v1.10.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;docker tag anjia0532/google-containers.kubernetes-dashboard-amd64:v1.10.0 k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;docker rmi anjia0532/google-containers.kubernetes-dashboard-amd64:v1.10.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="修改配置文件ports部分"&gt;&lt;a href="#%e4%bf%ae%e6%94%b9%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6ports%e9%83%a8%e5%88%86" class="header-anchor"&gt;&lt;/a&gt;修改配置文件（ports部分）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ------------------- Dashboard Service ------------------- #&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;k8s-app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kubernetes-dashboard&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kubernetes-dashboard&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kube-system&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;NodePort&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;443&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8443&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodePort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30001&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;k8s-app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kubernetes-dashboard&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="运行并查看状态"&gt;&lt;a href="#%e8%bf%90%e8%a1%8c%e5%b9%b6%e6%9f%a5%e7%9c%8b%e7%8a%b6%e6%80%81" class="header-anchor"&gt;&lt;/a&gt;运行并查看状态
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;kubectl apply -f kubernetes-dashboard.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#通过以下命令查看 pod 状态&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;kubectl get pods -n kubernetes-dashboard
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;kubectl get pods,svc -n kubernetes-dashboard
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="登录"&gt;&lt;a href="#%e7%99%bb%e5%bd%95" class="header-anchor"&gt;&lt;/a&gt;登录
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;##创建管理员&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;kubectl create serviceaccount dashboard-admin -n kube-system
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;kubectl create clusterrolebinding dashboard-admin --clusterrole&lt;span class="o"&gt;=&lt;/span&gt;cluster-admin --serviceaccount&lt;span class="o"&gt;=&lt;/span&gt;kube-system:dashboard-admin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;##获取token &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;kubectl describe secrets -n kube-system &lt;span class="k"&gt;$(&lt;/span&gt;kubectl -n kube-system get secret &lt;span class="p"&gt;|&lt;/span&gt; grep dashboard-admin &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $1}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-03-21-centos7-shi-yong-kubeadm-an-zhuang-k8s-ji-qun/002-bf47af4b.jpg"&gt;&lt;/p&gt;
&lt;h2 id="完全清除或卸载k8s"&gt;&lt;a href="#%e5%ae%8c%e5%85%a8%e6%b8%85%e9%99%a4%e6%88%96%e5%8d%b8%e8%bd%bdk8s" class="header-anchor"&gt;&lt;/a&gt;完全清除或卸载K8s
&lt;/h2&gt;&lt;p&gt;This a gist for quick uninstall kubernetes If the cluster is node, First delete it from master&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;kubectl drain &amp;lt;node name&amp;gt; — delete-local-data — force — ignore-daemonsets
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;kubectl delete node &amp;lt;node name&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then remove kubeadm completely&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;kubeadm reset 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# on debian base &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;sudo apt-get purge kubeadm kubectl kubelet kubernetes-cni kube* 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#on centos base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;sudo yum remove kubeadm kubectl kubelet kubernetes-cni kube*
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# on debian base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;sudo apt-get autoremove
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#on centos base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;sudo yum autoremove
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;sudo rm -rf ~/.kube
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;参考：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;a class="link" href="https://www.yinxiang.com/everhub/note/f420816c-2019-47a1-8dcd-7b3ade25ac1f" target="_blank" rel="noopener"
 &gt;https://www.yinxiang.com/everhub/note/f420816c-2019-47a1-8dcd-7b3ade25ac1f&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;a class="link" href="https://blog.51cto.com/3241766/2405624" target="_blank" rel="noopener"
 &gt;https://blog.51cto.com/3241766/2405624&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;a class="link" href="https://juejin.cn/post/6844904161759199240#heading-25" target="_blank" rel="noopener"
 &gt;https://juejin.cn/post/6844904161759199240#heading-25&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-03-21-centos7-shi-yong-kubeadm-an-zhuang-k8s-ji-qun/003-06dd59d5.gif"&gt;&lt;/p&gt;
&lt;p&gt;关注公众号 获取更多精彩内容&lt;/p&gt;</description></item></channel></rss>