<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>MIutopia&#39;s Blog</title>
  
  
  <link href="https://www.cloudetopia.top/atom.xml" rel="self"/>
  
  <link href="https://www.cloudetopia.top/"/>
  <updated>2026-07-08T08:02:15.040Z</updated>
  <id>https://www.cloudetopia.top/</id>
  
  <author>
    <name>MIutopia</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>别学 Git 命令了——直接用自然语言让 Claude Code 帮你回滚</title>
    <link href="https://www.cloudetopia.top/2026/07/01/2026-07-01-%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%9B%9E%E6%BB%9A/"/>
    <id>https://www.cloudetopia.top/2026/07/01/2026-07-01-%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%9B%9E%E6%BB%9A/</id>
    <published>2026-07-01T08:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>上一篇我们讲了 Git 回滚的五种方法——<code>checkout</code>、<code>reset</code>、<code>revert</code>、<code>stash</code>、重新克隆。如果你认真学了，应该能应对大部分翻车场景。</p><p>但说实话，对很多新手来说，记住这些命令的区别还是挺头疼的。什么时候用 <code>--soft</code>，什么时候用 <code>--hard</code>？<code>revert</code> 和 <code>reset</code> 到底该选哪个？</p><p><strong>如果不用记这些命令呢？</strong></p><p>如果你能直接用中文告诉 Claude Code：”把刚才那次改动撤掉”、”回到十分钟前的状态”、”先存个档再继续改”——它自己去执行对应的 Git 命令，你只需要看结果对不对。</p><p>这篇文章就讲怎么做到这件事。</p><h2 id="核心思路：让-Claude-当你的-Git-翻译官"><a href="#核心思路：让-Claude-当你的-Git-翻译官" class="headerlink" title="核心思路：让 Claude 当你的 Git 翻译官"></a>核心思路：让 Claude 当你的 Git 翻译官</h2><p>Git 命令是给人看的操作界面，但本质上它做的事情很简单：保存快照、对比差异、恢复状态。这些逻辑 Claude Code 完全理解。</p><p>你要做的只有两件事：</p><ol><li><strong>在 CLAUDE.md 里定好规则</strong>，让 Claude 在干活时自动做好安全防护</li><li><strong>用自然语言指挥回滚</strong>，不需要记任何 Git 命令</li></ol><h2 id="第一步：在-CLAUDE-md-里写好”安全规范”"><a href="#第一步：在-CLAUDE-md-里写好”安全规范”" class="headerlink" title="第一步：在 CLAUDE.md 里写好”安全规范”"></a>第一步：在 CLAUDE.md 里写好”安全规范”</h2><p>打开你项目根目录的 <code>CLAUDE.md</code>，加上这样一段规则：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs markdown"><span class="hljs-section">## 安全规范</span><br><br><span class="hljs-section">### 操作前自动存档</span><br><span class="hljs-bullet">-</span> 每次修改文件前，先 git add + git commit 当前状态，提交信息格式：<br>  &quot;checkpoint: 操作前的安全存档 - [简要描述即将执行的操作]&quot;<br><span class="hljs-bullet">-</span> 这样每次改动都有一个可以回退的节点<br><br><span class="hljs-section">### 批量操作前额外保护</span><br><span class="hljs-bullet">-</span> 批量修改超过 3 个文件前，先创建一个新的 Git 分支<br><span class="hljs-bullet">-</span> 在分支上完成操作，确认无误后再合并回 main<br><br><span class="hljs-section">### 回滚响应</span><br><span class="hljs-bullet">-</span> 当我说&quot;撤回&quot;、&quot;回滚&quot;、&quot;撤销&quot;、&quot;回到之前&quot;时，<br>  自动执行 git revert 或 git reset（根据是否已推送判断）<br><span class="hljs-bullet">-</span> 当我说&quot;存档&quot;时，执行 git stash<br><span class="hljs-bullet">-</span> 当我说&quot;恢复存档&quot;时，执行 git stash pop<br></code></pre></td></tr></table></figure><p>有了这段规则，Claude Code 每次启动都会读到它，然后按照这个规范来工作。</p><h2 id="实际效果：用自然语言完成整个流程"><a href="#实际效果：用自然语言完成整个流程" class="headerlink" title="实际效果：用自然语言完成整个流程"></a>实际效果：用自然语言完成整个流程</h2><p>下面模拟一个完整的工作场景，看看实际用起来是什么样的。</p><h3 id="场景：批量改写博客文章格式"><a href="#场景：批量改写博客文章格式" class="headerlink" title="场景：批量改写博客文章格式"></a>场景：批量改写博客文章格式</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">你：帮我把 <span class="hljs-built_in">source</span>/_posts/ 下所有旧文章统一改写成最新那篇的风格。<br><br>Claude：好的，我先存档当前状态，然后开始逐篇改写。<br>       [自动执行 git commit -m <span class="hljs-string">&quot;checkpoint: 操作前的安全存档 - 批量改写文章格式&quot;</span>]<br>       开始改写第 1 篇...<br></code></pre></td></tr></table></figure><p>注意这里 Claude <strong>自动先做了存档</strong>，不需要你提醒。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">你：等一下，第 2 篇改得不对，把第 2 篇恢复成原来的。<br><br>Claude：好的，我把 article2.md 恢复到上次存档的状态。<br>       [自动执行 git checkout HEAD~1 -- <span class="hljs-built_in">source</span>/_posts/article2.md]<br>       已恢复，你看一下对不对。<br></code></pre></td></tr></table></figure><p>你不需要知道 <code>git checkout HEAD~1 --</code> 这个命令，只需要说”恢复成原来的”。</p><figure class="highlight prolog"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs prolog">你：其他文章改得没问题，继续改剩下的。<br><br><span class="hljs-symbol">Claude</span>：好的，继续改写第 <span class="hljs-number">3</span> 篇到第 <span class="hljs-number">15</span> 篇...<br>       [改完后自动 commit]<br>       全部改完了，要我直接推送到 <span class="hljs-symbol">GitHub</span> 吗？<br></code></pre></td></tr></table></figure><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs">你：先别推，我本地看看效果。<br><br>Claude：好的，暂不推送。你可以在本地预览，有问题随时告诉我。<br></code></pre></td></tr></table></figure><figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs pgsql">你：看了下效果不太好，把刚才的批量改动全部撤掉。<br><br>Claude：好的，我撤销最近那次批量改写的 <span class="hljs-keyword">commit</span>。<br>       [自动执行 git revert HEAD 或 git <span class="hljs-keyword">reset</span> <span class="hljs-comment">--soft HEAD~1]</span><br>       已撤销，所有文章恢复到改写前的状态。<br></code></pre></td></tr></table></figure><p>整个过程你没有输入过一条 Git 命令。</p><h2 id="常用的自然语言回滚指令"><a href="#常用的自然语言回滚指令" class="headerlink" title="常用的自然语言回滚指令"></a>常用的自然语言回滚指令</h2><p>整理一些你在实际工作中会用到的自然语言指令，直接对 Claude Code 说就行：</p><table><thead><tr><th>你说的话</th><th>Claude 会做的事</th></tr></thead><tbody><tr><td>“撤回上一步”</td><td><code>git reset --soft HEAD~1</code>（还没 push）或 <code>git revert HEAD</code>（已 push）</td></tr><tr><td>“把刚才改的 XX 文件恢复原样”</td><td><code>git checkout HEAD~1 -- 文件名</code></td></tr><tr><td>“全部撤掉，回到改之前”</td><td><code>git reset --hard HEAD~N</code>（会先跟你确认）</td></tr><tr><td>“先存个档”</td><td><code>git stash</code></td></tr><tr><td>“恢复存档”</td><td><code>git stash pop</code></td></tr><tr><td>“看看之前改了什么”</td><td><code>git diff</code> 或 <code>git log --oneline</code></td></tr><tr><td>“回到昨天下午的状态”</td><td>根据 <code>git log</code> 的时间戳找到对应 commit，执行 reset 或 revert</td></tr><tr><td>“这个改动太危险，开个新分支做”</td><td><code>git checkout -b 新分支名</code></td></tr></tbody></table><p>你不需要记住这些命令，<strong>只需要用你习惯的方式描述你想做什么</strong>。</p><h2 id="进阶：让-Claude-自己判断风险"><a href="#进阶：让-Claude-自己判断风险" class="headerlink" title="进阶：让 Claude 自己判断风险"></a>进阶：让 Claude 自己判断风险</h2><p>在 CLAUDE.md 里可以加更智能的规则，让 Claude 自己判断哪些操作需要额外保护：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs markdown"><span class="hljs-section">## 风险判断规则</span><br><br><span class="hljs-section">### 高风险操作（必须自动存档 + 通知用户）</span><br><span class="hljs-bullet">-</span> 删除文件<br><span class="hljs-bullet">-</span> 批量修改超过 5 个文件<br><span class="hljs-bullet">-</span> 修改配置文件（<span class="hljs-emphasis">_config.yml、vercel.json 等）</span><br><span class="hljs-emphasis">- 修改主题文件</span><br><span class="hljs-emphasis"></span><br><span class="hljs-emphasis">### 中风险操作（自动存档，静默执行）</span><br><span class="hljs-emphasis">- 修改单篇文章内容</span><br><span class="hljs-emphasis">- 添加新文件</span><br><span class="hljs-emphasis">- 修改 frontmatter</span><br><span class="hljs-emphasis"></span><br><span class="hljs-emphasis">### 低风险操作（直接执行）</span><br><span class="hljs-emphasis">- 读取文件</span><br><span class="hljs-emphasis">- 查看 git 状态</span><br><span class="hljs-emphasis">- 查看部署日志</span><br></code></pre></td></tr></table></figure><p>这样 Claude 在删除文件之前会自动先 commit 存档，你不用担心它”静默删库”。</p><h2 id="一个完整的实战演示"><a href="#一个完整的实战演示" class="headerlink" title="一个完整的实战演示"></a>一个完整的实战演示</h2><p>用我的博客项目做个真实演示。</p><h3 id="任务：给所有文章加-SEO-描述"><a href="#任务：给所有文章加-SEO-描述" class="headerlink" title="任务：给所有文章加 SEO 描述"></a>任务：给所有文章加 SEO 描述</h3><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs gradle">你：给 <span class="hljs-keyword">source</span><span class="hljs-regexp">/_posts/</span> 下每篇文章的 frontmatter 加一个 <span class="hljs-keyword">description</span> 字段，<br>    用一句话概括文章内容。<br><br>Claude：收到。我先存档当前状态。<br>       [git commit -m <span class="hljs-string">&quot;checkpoint: 操作前的安全存档 - 批量添加 SEO 描述&quot;</span>]<br>       <br>       开始处理第 <span class="hljs-number">1</span> 篇：<span class="hljs-number">2023</span>-<span class="hljs-number">10</span>-<span class="hljs-number">17</span>-Docker.md<br>       <span class="hljs-keyword">description</span>: <span class="hljs-string">&quot;Docker 入门教程，涵盖核心概念、安装配置和常用命令&quot;</span><br>       <br>       第 <span class="hljs-number">2</span> 篇：<span class="hljs-number">2023</span>-<span class="hljs-number">10</span>-<span class="hljs-number">20</span>-Dockerfile.md<br>       <span class="hljs-keyword">description</span>: <span class="hljs-string">&quot;Dockerfile 编写指南，从基础语法到最佳实践&quot;</span><br>       ...<br>       <br>       全部处理完毕，共修改 <span class="hljs-number">15</span> 个文件。要我提交吗？<br><br>你：提交吧。<br><br>Claude：[git add . &amp;&amp; git commit -m <span class="hljs-string">&quot;feat: 为所有文章添加 SEO description&quot;</span>]<br>       已提交。需要推送到 GitHub 吗？<br><br>你：推吧。<br><br>Claude：[git <span class="hljs-keyword">push</span> origin main]<br>       已推送，Vercel 会自动部署。<br></code></pre></td></tr></table></figure><h3 id="发现问题，需要回滚"><a href="#发现问题，需要回滚" class="headerlink" title="发现问题，需要回滚"></a>发现问题，需要回滚</h3><figure class="highlight maxima"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs maxima">你：等下，我看到有篇文章的 description 写得不准确，<br>    把所有改动都撤掉，我重新给你更准确的概括。<br><br>Claude：好的，已经推送到远程了，我用 git <span class="hljs-built_in">revert</span> 来撤销。<br>       [git <span class="hljs-built_in">revert</span> HEAD --no-edit]<br>       [git <span class="hljs-built_in">push</span> <span class="hljs-built_in">origin</span> main]<br>       已撤销并推送，所有文章的 description 字段已移除，<br>       恢复到添加前的状态。你可以重新给我更准确的概括。<br></code></pre></td></tr></table></figure><p>看，从发现问题到完成回滚，你只说了一句话。</p><h2 id="对比：传统方式-vs-自然语言方式"><a href="#对比：传统方式-vs-自然语言方式" class="headerlink" title="对比：传统方式 vs 自然语言方式"></a>对比：传统方式 vs 自然语言方式</h2><table><thead><tr><th>操作</th><th>传统方式（你需要记的命令）</th><th>自然语言方式</th></tr></thead><tbody><tr><td>撤销未提交的改动</td><td><code>git checkout -- 文件名</code></td><td>“把 XX 恢复原样”</td></tr><tr><td>撤回一次 commit</td><td><code>git reset --soft HEAD~1</code></td><td>“撤回上一步”</td></tr><tr><td>撤销已推送的改动</td><td><code>git revert HEAD</code> + <code>git push</code></td><td>“把刚才推送的撤掉”</td></tr><tr><td>临时保存现场</td><td><code>git stash</code></td><td>“先存个档”</td></tr><tr><td>查看改了什么</td><td><code>git diff</code> &#x2F; <code>git log</code></td><td>“看看之前改了什么”</td></tr><tr><td>回到某个时间点</td><td><code>git log</code> → 找 hash → <code>git reset</code></td><td>“回到昨天下午的状态”</td></tr></tbody></table><p>传统方式你需要记住命令、理解参数、判断用哪个。自然语言方式你只需要<strong>描述你想达到的效果</strong>。</p><h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><p>虽然自然语言回滚很方便，但有几点还是要了解：</p><p><strong>Claude 会先确认再执行危险操作。</strong> 如果你在 CLAUDE.md 里写了”高风险操作前通知用户”，Claude 在执行 <code>git reset --hard</code> 这种不可逆操作前会先问你确认。这是好事——给 AI 加一道人工审核。</p><p><strong>推送后的回滚比推送前复杂。</strong> 没推送的改动，Claude 可以直接 reset；已经推送的，需要用 revert 生成新 commit。你不需要理解这个区别，但知道”推出去的东西撤回来会多一步”有助于你养成”改完先看再推”的习惯。</p><p><strong>频繁存档会产生很多 commit。</strong> 如果你介意 git 历史太乱，可以让 Claude 在任务完成后把多个 checkpoint commit 合并成一个（用 <code>git rebase -i</code>，但这个操作比较复杂，建议让 Claude 自己处理）。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>回到这篇文章的核心观点：<strong>你不需要成为 Git 专家，也能安全地使用 AI 写代码。</strong></p><p>通过在 CLAUDE.md 里设定好安全规范，Claude Code 会在每次操作前自动存档，在你需要回滚时理解你的自然语言指令，然后替你执行正确的 Git 命令。</p><p>你要做的只是：</p><ol><li>写清楚 CLAUDE.md 里的安全规则</li><li>用中文告诉 Claude 你想做什么</li><li>在 Claude 执行后检查结果</li></ol><p>剩下的，交给 AI。</p><hr><p><em>这是 Claude Code + GitHub + Vercel 系列文章的第四篇。从环境搭建到项目管理，从故障恢复到自然语言回滚，你已经掌握了一套完整的 AI 协作开发工作流。现在，去实践吧。</em></p>]]></content>
    
    
    <summary type="html">用自然语言指令让 AI 执行 Git 回滚操作，无需记住任何 Git 命令。</summary>
    
    
    
    <category term="教程" scheme="https://www.cloudetopia.top/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="AI Agent" scheme="https://www.cloudetopia.top/tags/AI-Agent/"/>
    
    <category term="Claude Code" scheme="https://www.cloudetopia.top/tags/Claude-Code/"/>
    
    <category term="Git" scheme="https://www.cloudetopia.top/tags/Git/"/>
    
  </entry>
  
  <entry>
    <title>Claude Code 写代码翻车了？Git 回滚与故障恢复实战</title>
    <link href="https://www.cloudetopia.top/2026/07/01/2026-07-01-Git%E5%9B%9E%E6%BB%9A%E4%B8%8E%E6%95%85%E9%9A%9C%E6%81%A2%E5%A4%8D/"/>
    <id>https://www.cloudetopia.top/2026/07/01/2026-07-01-Git%E5%9B%9E%E6%BB%9A%E4%B8%8E%E6%95%85%E9%9A%9C%E6%81%A2%E5%A4%8D/</id>
    <published>2026-07-01T06:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>前两篇文章里，我们搭好了 Claude Code + GitHub + Vercel 的协作环境，也学会了用 Claude Code 自动化管理项目。但你迟早会遇到一个问题——<strong>AI 翻车了</strong>。</p><p>可能是 Claude Code 批量改文件时误删了几篇博客，可能是改错了配置文件导致 Vercel 部署失败，也可能是推送了一段有 bug 的代码把线上页面搞崩了。</p><p>别慌。这就是 Git 存在的意义——<strong>它是你的时间机器，让你随时可以回到”还没出问题”的那个时刻</strong>。</p><p>这篇文章专门讲：当 Claude Code 搞砸事情的时候，怎么用 Git 把局面救回来。</p><h2 id="AI-翻车的常见场景"><a href="#AI-翻车的常见场景" class="headerlink" title="AI 翻车的常见场景"></a>AI 翻车的常见场景</h2><p>先看看 Claude Code 可能怎么”翻车”，心里有个数：</p><table><thead><tr><th>翻车类型</th><th>具体表现</th><th>严重程度</th></tr></thead><tbody><tr><td>误删文件</td><td>批量操作时删掉了不该删的文件</td><td>🔴 高</td></tr><tr><td>改错配置</td><td>修改了 <code>_config.yml</code> 导致构建失败</td><td>🟡 中</td></tr><tr><td>推送 bug</td><td>推送了有语法错误的代码，Vercel 部署失败</td><td>🟡 中</td></tr><tr><td>覆盖内容</td><td>用错误内容覆盖了重要文件</td><td>🔴 高</td></tr><tr><td>批量改坏</td><td>批量替换时正则写错，所有文件都被改错</td><td>🔴 高</td></tr></tbody></table><p>好消息是：<strong>只要这些改动已经提交到了 Git，就都能救回来</strong>。哪怕文件被删了、内容被覆盖了，Git 都有办法恢复。</p><h2 id="Git-核心概念速补"><a href="#Git-核心概念速补" class="headerlink" title="Git 核心概念速补"></a>Git 核心概念速补</h2><p>在学回滚之前，需要先理解 Git 的几个关键区域。不用背，理解意思就行：</p><figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs armasm">工作区（Working Directory）  →  你电脑上看到的文件<br>       ↓  git <span class="hljs-keyword">add</span><br>暂存区（Staging <span class="hljs-meta">Area</span>）      →  准备好要提交的改动<br>       ↓  git commit<br>本地仓库（Repository）      →  提交历史，每个 commit 是一个快照<br>       ↓  git <span class="hljs-keyword">push</span><br>远程仓库（Remote）          →  GitHub 上的备份<br></code></pre></td></tr></table></figure><p><strong>关键认知：每次 <code>git commit</code> 都是给项目拍了一张”快照”。</strong> 回滚的本质就是”把文件恢复到之前某张快照的状态”。</p><p>记住这个概念，后面的操作就很好理解了。</p><h2 id="回滚实战：五招救命"><a href="#回滚实战：五招救命" class="headerlink" title="回滚实战：五招救命"></a>回滚实战：五招救命</h2><h3 id="第一招：git-checkout-—-撤销工作区的修改"><a href="#第一招：git-checkout-—-撤销工作区的修改" class="headerlink" title="第一招：git checkout — 撤销工作区的修改"></a>第一招：git checkout — 撤销工作区的修改</h3><p><strong>场景</strong>：Claude Code 刚改了几个文件，你还没 <code>git add</code>，一看改得不对，想撤回。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看当前状态，看哪些文件被改了</span><br>git status<br><br><span class="hljs-comment"># 撤销某个文件的修改（还没 add 的）</span><br>git checkout -- <span class="hljs-built_in">source</span>/_posts/某篇文章.md<br><br><span class="hljs-comment"># 撤销所有文件的修改（还没 add 的）</span><br>git checkout -- .<br></code></pre></td></tr></table></figure><p>这是最轻量的一招，相当于告诉 Git：”工作区里这些改动我不要了，恢复到上次 commit 的状态。”</p><blockquote><p>⚠️ 注意：这个操作<strong>不可逆</strong>。撤销后，未暂存的改动就彻底丢了。如果不确定，可以先用 <code>git stash</code> 暂存（后面会讲）。</p></blockquote><h3 id="第二招：git-reset-—-撤回暂存区或提交"><a href="#第二招：git-reset-—-撤回暂存区或提交" class="headerlink" title="第二招：git reset — 撤回暂存区或提交"></a>第二招：git reset — 撤回暂存区或提交</h3><p><strong>场景一</strong>：Claude Code 已经 <code>git add</code> 了，但还没 <code>git commit</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 把暂存区的改动撤回到工作区（不会丢代码）</span><br>git reset HEAD<br><br><span class="hljs-comment"># 或者只撤回某个文件</span><br>git reset HEAD <span class="hljs-built_in">source</span>/_posts/某篇文章.md<br></code></pre></td></tr></table></figure><p><strong>场景二</strong>：Claude Code 已经 <code>git commit</code> 了，但还没 <code>git push</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 撤回最近一次 commit，改动回到暂存区</span><br>git reset --soft HEAD~1<br><br><span class="hljs-comment"># 撤回最近一次 commit，改动回到工作区</span><br>git reset HEAD~1<br></code></pre></td></tr></table></figure><p><code>HEAD~1</code> 表示”往回退一个 commit”。如果是退两个就是 <code>HEAD~2</code>，以此类推。</p><p><code>--soft</code> 和默认的区别：</p><table><thead><tr><th>参数</th><th>commit 撤回后，改动在哪</th></tr></thead><tbody><tr><td><code>--soft</code></td><td>留在暂存区（相当于还没 commit）</td></tr><tr><td>默认（<code>--mixed</code>）</td><td>回到工作区（相当于还没 add）</td></tr><tr><td><code>--hard</code></td><td><strong>直接丢弃，什么都不剩</strong></td></tr></tbody></table><blockquote><p>⚠️ <code>--hard</code> 是最危险的选项，它会<strong>彻底丢弃</strong>所有改动。除非你确定那些改动完全不需要，否则不要用。</p></blockquote><h3 id="第三招：git-revert-—-安全地撤销已推送的提交"><a href="#第三招：git-revert-—-安全地撤销已推送的提交" class="headerlink" title="第三招：git revert — 安全地撤销已推送的提交"></a>第三招：git revert — 安全地撤销已推送的提交</h3><p><strong>场景</strong>：Claude Code 改完代码已经 <code>git push</code> 到 GitHub 了，Vercel 也部署了，结果发现问题。</p><p>这时候不能直接 <code>reset</code>——因为远程仓库已经有了那个 commit，你本地 reset 后 push 会冲突。</p><p>正确做法是用 <code>git revert</code>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看最近的 commit 记录</span><br>git <span class="hljs-built_in">log</span> --oneline<br><br><span class="hljs-comment"># 撤销最近一次 commit（生成一个新的&quot;反向 commit&quot;）</span><br>git revert HEAD<br><br><span class="hljs-comment"># 撤销指定的某次 commit</span><br>git revert abc1234<br></code></pre></td></tr></table></figure><p><code>git revert</code> 的原理是：生成一个新的 commit，内容恰好是目标 commit 的”反面”——它加了什么就删什么，它删了什么就加什么。</p><p>这样做的好处是<strong>不会改写历史</strong>，其他协作者不会受到影响。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># revert 完成后推送到远程</span><br>git push origin main<br></code></pre></td></tr></table></figure><h3 id="第四招：git-stash-—-临时保存现场"><a href="#第四招：git-stash-—-临时保存现场" class="headerlink" title="第四招：git stash — 临时保存现场"></a>第四招：git stash — 临时保存现场</h3><p><strong>场景</strong>：你正在让 Claude Code 改一篇文章，改到一半发现另一个文件有更紧急的问题要处理。但当前改动还没完成，不想提交也不想丢掉。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 把当前改动暂存起来</span><br>git stash<br><br><span class="hljs-comment"># 现在工作区是干净的，可以去处理紧急问题了</span><br><span class="hljs-comment"># ...处理完毕...</span><br><br><span class="hljs-comment"># 恢复之前暂存的改动</span><br>git stash pop<br></code></pre></td></tr></table></figure><p><code>git stash</code> 就像一个临时抽屉——把改动先放进去，等你忙完了再拿出来继续。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看暂存了几个抽屉</span><br>git stash list<br><br><span class="hljs-comment"># 恢复指定的暂存</span><br>git stash pop stash@&#123;1&#125;<br></code></pre></td></tr></table></figure><h3 id="第五招：重新克隆-—-终极方案"><a href="#第五招：重新克隆-—-终极方案" class="headerlink" title="第五招：重新克隆 — 终极方案"></a>第五招：重新克隆 — 终极方案</h3><p><strong>场景</strong>：本地仓库搞得一团乱，reset 来 reset 去已经分不清状态了。</p><p>最简单粗暴的办法——删掉本地仓库，重新从 GitHub 克隆一份干净的：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 回到上级目录</span><br><span class="hljs-built_in">cd</span> ..<br><br><span class="hljs-comment"># 删掉搞乱的本地仓库</span><br><span class="hljs-built_in">rm</span> -rf hexo-blog-source<br><br><span class="hljs-comment"># 重新克隆</span><br>git <span class="hljs-built_in">clone</span> https://github.com/MIutopia/hexo-blog-source.git<br></code></pre></td></tr></table></figure><p>只要 GitHub 上的代码是对的，重新克隆就能拿到一份完全干净的环境。之前的所有本地操作（stash、reset、checkout 搞乱的）统统不存在了。</p><blockquote><p>💡 这不是”认输”，这是<strong>务实</strong>。当 Git 状态复杂到理不清的时候，花 5 分钟重新克隆比花 2 小时排查状态高效得多。</p></blockquote><h2 id="真实案例复盘"><a href="#真实案例复盘" class="headerlink" title="真实案例复盘"></a>真实案例复盘</h2><p>讲一个我实际遇到的情况，完整演示一遍恢复流程。</p><h3 id="事故经过"><a href="#事故经过" class="headerlink" title="事故经过"></a>事故经过</h3><p>我让 Claude Code 批量改写博客文章的格式。它读了几篇参考文章后，开始逐篇修改。改到一半时，我发现它<strong>把几篇文章的 frontmatter 删掉了</strong>，而且还 <code>git add</code> 了。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">git status 输出：<br>modified:   <span class="hljs-built_in">source</span>/_posts/article1.md    ← frontmatter 被删了<br>modified:   <span class="hljs-built_in">source</span>/_posts/article2.md    ← 内容被覆盖了<br>modified:   <span class="hljs-built_in">source</span>/_posts/article3.md    ← 正常<br></code></pre></td></tr></table></figure><h3 id="第一步：冷静，先别提交"><a href="#第一步：冷静，先别提交" class="headerlink" title="第一步：冷静，先别提交"></a>第一步：冷静，先别提交</h3><p>看到问题后最重要的是——<strong>不要慌，不要急着 commit 或 push</strong>。只要还没 commit，一切都好办。</p><h3 id="第二步：查看具体改了什么"><a href="#第二步：查看具体改了什么" class="headerlink" title="第二步：查看具体改了什么"></a>第二步：查看具体改了什么</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">git diff <span class="hljs-built_in">source</span>/_posts/article1.md<br></code></pre></td></tr></table></figure><p><code>git diff</code> 会显示详细的改动对比，帮你判断哪些改动是好的、哪些是坏的。</p><h3 id="第三步：选择性恢复"><a href="#第三步：选择性恢复" class="headerlink" title="第三步：选择性恢复"></a>第三步：选择性恢复</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># article1 和 article2 改坏了，恢复到上次 commit 的状态</span><br>git checkout -- <span class="hljs-built_in">source</span>/_posts/article1.md<br>git checkout -- <span class="hljs-built_in">source</span>/_posts/article2.md<br><br><span class="hljs-comment"># article3 改得没问题，保留改动</span><br></code></pre></td></tr></table></figure><h3 id="第四步：确认状态"><a href="#第四步：确认状态" class="headerlink" title="第四步：确认状态"></a>第四步：确认状态</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">git status<br><span class="hljs-comment"># 现在只有 article3 是 modified 状态，其他都恢复了</span><br></code></pre></td></tr></table></figure><h3 id="第五步：重新让-Claude-Code-修复"><a href="#第五步：重新让-Claude-Code-修复" class="headerlink" title="第五步：重新让 Claude Code 修复"></a>第五步：重新让 Claude Code 修复</h3><figure class="highlight dos"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs dos">你：article1.<span class="hljs-built_in">md</span> 和 article2.<span class="hljs-built_in">md</span> 的 frontmatter 被你删掉了，<br>    请重新加上，格式参考 article3.<span class="hljs-built_in">md</span>。注意不要动正文内容。<br></code></pre></td></tr></table></figure><p>这次加了更明确的指令，Claude Code 正确修复了两篇文章。</p><h3 id="第六步：检查后提交"><a href="#第六步：检查后提交" class="headerlink" title="第六步：检查后提交"></a>第六步：检查后提交</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 再 diff 一次确认改动正确</span><br>git diff <span class="hljs-built_in">source</span>/_posts/article1.md<br>git diff <span class="hljs-built_in">source</span>/_posts/article2.md<br><br><span class="hljs-comment"># 确认没问题后提交</span><br>git add .<br>git commit -m <span class="hljs-string">&quot;fix: 修复批量改写导致的 frontmatter 丢失&quot;</span><br>git push origin main<br></code></pre></td></tr></table></figure><p>整个过程大约 5 分钟。如果没有 Git，这两篇文章就彻底丢了。</p><h2 id="防御性习惯：让翻车代价降到最低"><a href="#防御性习惯：让翻车代价降到最低" class="headerlink" title="防御性习惯：让翻车代价降到最低"></a>防御性习惯：让翻车代价降到最低</h2><p>与其事后救火，不如事前预防。以下是几个实用的防御策略：</p><h3 id="1-频繁提交，小步快跑"><a href="#1-频繁提交，小步快跑" class="headerlink" title="1. 频繁提交，小步快跑"></a>1. 频繁提交，小步快跑</h3><p>不要攒了一大堆改动才 commit。每完成一个小任务就提交一次，这样回滚的粒度更细，不会”一滚滚一大片”。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 好的习惯</span><br>git commit -m <span class="hljs-string">&quot;feat: 更新 article1 的 frontmatter&quot;</span><br>git commit -m <span class="hljs-string">&quot;feat: 更新 article2 的 frontmatter&quot;</span><br>git commit -m <span class="hljs-string">&quot;feat: 更新 article3 的 frontmatter&quot;</span><br><br><span class="hljs-comment"># 坏的习惯</span><br><span class="hljs-comment"># 改了 15 个文件后才 commit 一次</span><br></code></pre></td></tr></table></figure><h3 id="2-让-Claude-Code-在提交前先确认"><a href="#2-让-Claude-Code-在提交前先确认" class="headerlink" title="2. 让 Claude Code 在提交前先确认"></a>2. 让 Claude Code 在提交前先确认</h3><p>在 CLAUDE.md 里加一条规则：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs markdown"><span class="hljs-section">## 注意事项</span><br><span class="hljs-bullet">-</span> 批量修改文件前，先改一个文件让我确认<br><span class="hljs-bullet">-</span> 确认通过后再批量执行<br><span class="hljs-bullet">-</span> 每次 commit 前，先 git diff 让我检查<br></code></pre></td></tr></table></figure><p>这样 Claude Code 就不会”闷头大干”了。</p><h3 id="3-善用分支"><a href="#3-善用分支" class="headerlink" title="3. 善用分支"></a>3. 善用分支</h3><p>对于不确定的大改动，先在新分支上操作：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 创建并切换到新分支</span><br>git checkout -b refactor/article-format<br><br><span class="hljs-comment"># 在这个分支上随便改，改坏了也不影响 main</span><br><span class="hljs-comment"># ...Claude Code 在这里操作...</span><br><br><span class="hljs-comment"># 确认没问题后合并回 main</span><br>git checkout main<br>git merge refactor/article-format<br></code></pre></td></tr></table></figure><p>如果分支上的改动彻底搞砸了？直接切回 main 分支，那个分支不要就行了。</p><h3 id="4-利用-Vercel-Preview-部署"><a href="#4-利用-Vercel-Preview-部署" class="headerlink" title="4. 利用 Vercel Preview 部署"></a>4. 利用 Vercel Preview 部署</h3><p>Vercel 对每个 Git 分支都会生成一个 Preview URL。你可以在推送前先在 Preview 环境验证效果，确认没问题了再合并到 main 分支触发正式部署。</p><figure class="highlight arcade"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs arcade">main 分支 → 正式部署（production）<br><span class="hljs-built_in">feature</span> 分支 → Preview 部署（预览环境）<br></code></pre></td></tr></table></figure><h3 id="5-定期备份关键配置"><a href="#5-定期备份关键配置" class="headerlink" title="5. 定期备份关键配置"></a>5. 定期备份关键配置</h3><p>把 <code>_config.yml</code>、<code>vercel.json</code> 这类关键配置文件单独备份一份。即使 Git 出了问题，至少还有本地备份可以恢复。</p><h2 id="常见问题与踩坑记录"><a href="#常见问题与踩坑记录" class="headerlink" title="常见问题与踩坑记录"></a>常见问题与踩坑记录</h2><p>❌ <strong>git reset –hard 后文件丢了，能恢复吗？</strong></p><p>能，但稍微麻烦。<code>git reflog</code> 可以看到所有 HEAD 移动的记录，包括 reset 操作：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">git reflog<br><span class="hljs-comment"># 找到 reset 之前的 commit hash</span><br>git reset --hard HEAD@&#123;3&#125;  <span class="hljs-comment"># 回到那个状态</span><br></code></pre></td></tr></table></figure><p>只要还没有被 Git 的垃圾回收清理掉（默认 30 天），就能找回来。</p><p>❌ <strong>已经 push 到 GitHub 的错误 commit，revert 后需要 force push 吗？</strong></p><p>不需要。<code>git revert</code> 生成的是新 commit，正常 <code>git push</code> 就行。只有 <code>git reset</code> 改写了历史才需要 force push（而且不推荐在公共分支上 force push）。</p><p>❌ <strong>Claude Code 执行 git push 后 Vercel 部署失败了，怎么办？</strong></p><p>先查看 Vercel 的构建日志定位错误。如果是代码问题，修复后重新 push 即可——Vercel 会自动重新部署。如果急需回滚到上一个正常版本，可以用 <code>git revert</code> 撤销那次有问题的 commit 再 push。</p><p>❌ <strong>多人协作时回滚会不会影响其他人？</strong></p><p>会。如果你在公共分支上用了 <code>git reset --hard</code> 然后 force push，其他人的本地仓库会和远程不一致。所以公共分支上优先用 <code>git revert</code>，它不改写历史，对所有人都安全。</p><p>❌ <strong>git stash pop 后出现冲突怎么办？</strong></p><p> stash 的内容和当前文件有冲突时，Git 会标记冲突区域。手动解决冲突后，运行 <code>git add</code> 和 <code>git commit</code> 完成合并。如果冲突太多不想处理，可以 <code>git checkout -- .</code> 放弃 stash 的改动。</p><h2 id="总结：回滚速查表"><a href="#总结：回滚速查表" class="headerlink" title="总结：回滚速查表"></a>总结：回滚速查表</h2><p>最后整理一张速查表，遇到问题直接对照操作：</p><table><thead><tr><th>情况</th><th>命令</th><th>说明</th></tr></thead><tbody><tr><td>改了文件，还没 add</td><td><code>git checkout -- 文件名</code></td><td>撤销工作区改动</td></tr><tr><td>已经 add，还没 commit</td><td><code>git reset HEAD 文件名</code></td><td>撤回到工作区</td></tr><tr><td>已经 commit，还没 push</td><td><code>git reset --soft HEAD~1</code></td><td>撤回 commit，保留改动</td></tr><tr><td>已经 push 到远程</td><td><code>git revert HEAD</code></td><td>生成反向 commit</td></tr><tr><td>想临时保存现场</td><td><code>git stash</code> → <code>git stash pop</code></td><td>暂存 → 恢复</td></tr><tr><td>彻底搞乱了</td><td>重新 <code>git clone</code></td><td>从头来过</td></tr></tbody></table><p>记住一个核心原则：<strong>只要代码在 Git 里，就丢不了</strong>。每次 commit 都是一个存档点，随时可以读档重来。</p><hr><p><em>四篇文章到这里就结束了。从环境搭建到自动化管理，再到故障恢复，你已经有了一套完整的 AI 协作开发工作流。剩下的就是动手实践——打开终端，输入 <code>claude</code>，开始你的第一次 AI 协作吧。</em></p>]]></content>
    
    
    <summary type="html">AI 写代码翻车怎么办？Git 回滚与故障恢复实战指南，附带速查表。</summary>
    
    
    
    <category term="教程" scheme="https://www.cloudetopia.top/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="AI Agent" scheme="https://www.cloudetopia.top/tags/AI-Agent/"/>
    
    <category term="Claude Code" scheme="https://www.cloudetopia.top/tags/Claude-Code/"/>
    
    <category term="Git" scheme="https://www.cloudetopia.top/tags/Git/"/>
    
    <category term="故障恢复" scheme="https://www.cloudetopia.top/tags/%E6%95%85%E9%9A%9C%E6%81%A2%E5%A4%8D/"/>
    
  </entry>
  
  <entry>
    <title>用 Claude Code 实现项目自动化与管理</title>
    <link href="https://www.cloudetopia.top/2026/07/01/2026-07-01-ClaudeCode%E8%87%AA%E5%8A%A8%E5%8C%96%E7%AE%A1%E7%90%86/"/>
    <id>https://www.cloudetopia.top/2026/07/01/2026-07-01-ClaudeCode%E8%87%AA%E5%8A%A8%E5%8C%96%E7%AE%A1%E7%90%86/</id>
    <published>2026-07-01T04:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>搭好 Claude Code + GitHub + Vercel 的环境后，你可能已经体验过”说句话就能写代码”的快感了。但这只是冰山一角。</p><p>Claude Code 真正的威力在于<strong>自动化</strong>——它不只是帮你写一段代码，而是能理解整个项目、批量执行操作、按你的规范自动管理文件。这篇文章会带你从”让 AI 写代码”进阶到”让 AI 管理项目”。</p><h2 id="Claude-Code-能做什么，不能做什么"><a href="#Claude-Code-能做什么，不能做什么" class="headerlink" title="Claude Code 能做什么，不能做什么"></a>Claude Code 能做什么，不能做什么</h2><p>先搞清楚能力边界，避免期望过高或过低。</p><table><thead><tr><th>擅长</th><th>不擅长</th></tr></thead><tbody><tr><td>读写项目文件、修改配置</td><td>需要图形界面操作的任务（如拖拽 UI）</td></tr><tr><td>执行命令行操作（git、npm、docker 等）</td><td>实时交互类操作（如调试断点）</td></tr><tr><td>理解项目上下文，按规范生成代码</td><td>超出训练数据范围的极新框架</td></tr><tr><td>批量处理重复性任务</td><td>需要人类审美判断的设计工作</td></tr><tr><td>多步骤复杂流程的编排</td><td>需要实时网络浏览的场景（部分受限）</td></tr></tbody></table><p>简单说：<strong>凡是能在终端里完成的事，Claude Code 基本都能帮你做</strong>。</p><h2 id="项目指令文件：给-AI-队友写”入职手册”"><a href="#项目指令文件：给-AI-队友写”入职手册”" class="headerlink" title="项目指令文件：给 AI 队友写”入职手册”"></a>项目指令文件：给 AI 队友写”入职手册”</h2><p>Claude Code 有一个核心特性——它会自动读取项目根目录的 <code>CLAUDE.md</code> 文件。这个文件就是你的项目规范，告诉 Claude Code 你的项目是什么、该怎么干活。</p><h3 id="一个完整的-CLAUDE-md-示例"><a href="#一个完整的-CLAUDE-md-示例" class="headerlink" title="一个完整的 CLAUDE.md 示例"></a>一个完整的 CLAUDE.md 示例</h3><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs markdown"><span class="hljs-section"># CLAUDE.md</span><br><br><span class="hljs-section">## 项目信息</span><br>Hexo 个人博客项目，部署在 Vercel 上。<br>源码仓库：MIutopia/hexo-blog-source<br><br><span class="hljs-section">## 目录结构</span><br><span class="hljs-bullet">-</span> source/<span class="hljs-emphasis">_posts/    文章目录（Markdown 格式）</span><br><span class="hljs-emphasis">- source/images/    图片资源</span><br><span class="hljs-emphasis">- themes/fluid/     主题文件</span><br><span class="hljs-emphasis"></span><br><span class="hljs-emphasis">## 文章规范</span><br><span class="hljs-emphasis">- 每篇文章必须包含 YAML frontmatter：title、date、categories、tags</span><br><span class="hljs-emphasis">- 日期格式：YYYY-MM-DD HH:MM:SS</span><br><span class="hljs-emphasis">- 代码块必须标注语言类型（如 ```bash）</span><br><span class="hljs-emphasis">- 使用中文写作，技术术语保留英文原文</span><br><span class="hljs-emphasis"></span><br><span class="hljs-emphasis">## 工作流</span><br><span class="hljs-emphasis">- 修改完成后用 git add . &amp;&amp; git commit &amp;&amp; git push 推送</span><br><span class="hljs-emphasis">- 提交信息格式：type: description</span><br><span class="hljs-emphasis">  - feat: 新功能/新文章</span><br><span class="hljs-emphasis">  - fix: 修复问题</span><br><span class="hljs-emphasis">  - docs: 文档更新</span><br><span class="hljs-emphasis">  - refactor: 重构</span><br><span class="hljs-emphasis"></span><br><span class="hljs-emphasis">## 注意事项</span><br><span class="hljs-emphasis">- 不要修改 _</span>config.yml 除非明确要求<br><span class="hljs-bullet">-</span> 不要删除任何已有文件<br><span class="hljs-bullet">-</span> 图片文件不要通过 Git 管理（太大）<br></code></pre></td></tr></table></figure><p>有了这份”入职手册”，Claude Code 就知道：</p><ul><li>文章该写在哪里、什么格式</li><li>改完代码该怎么提交</li><li>哪些文件不能碰</li></ul><h3 id="让指令文件生效"><a href="#让指令文件生效" class="headerlink" title="让指令文件生效"></a>让指令文件生效</h3><p>不需要任何额外配置，只要文件放在项目根目录，Claude Code 每次启动时会自动读取。你可以随时修改它，下次对话就会生效。</p><blockquote><p>⚠️ 如果你的项目比较复杂，还可以创建 <code>AGENTS.md</code>（多 Agent 协作规范）或 <code>SOUL.md</code>（语气和风格定义），Claude Code 同样会自动识别。</p></blockquote><h2 id="实战：用-Claude-Code-管理-Hexo-博客"><a href="#实战：用-Claude-Code-管理-Hexo-博客" class="headerlink" title="实战：用 Claude Code 管理 Hexo 博客"></a>实战：用 Claude Code 管理 Hexo 博客</h2><p>下面用我的博客项目做例子，展示 Claude Code 在实际项目管理中的几种用法。</p><h3 id="场景一：批量改写文章风格"><a href="#场景一：批量改写文章风格" class="headerlink" title="场景一：批量改写文章风格"></a>场景一：批量改写文章风格</h3><p>博客里有十几篇从旧网站迁移过来的文章，格式混乱、代码块没有语言标记、还混着 HTML 实体。手动改太痛苦了。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">你：<span class="hljs-built_in">source</span>/_posts/ 目录下除了 2026-06-30 那篇，其他文章都是从旧网站<br>    迁移过来的，格式有问题。请帮我逐篇改写，统一成最新那篇的风格：<br>    YAML frontmatter → 前言 → 正文分节 → 常见问题 → 结尾。<br>    代码块加上语言标记，HTML 实体转回正常字符。<br></code></pre></td></tr></table></figure><p>Claude Code 会：</p><ol><li>先读取参考文章（2026-06-30 那篇）学习风格</li><li>逐篇读取旧文章</li><li>按新风格重写</li><li>保存回原文件</li></ol><p>十几篇文章，几分钟就改完了。</p><h3 id="场景二：批量分类和打标签"><a href="#场景二：批量分类和打标签" class="headerlink" title="场景二：批量分类和打标签"></a>场景二：批量分类和打标签</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">你：帮我看一下 <span class="hljs-built_in">source</span>/_posts/ 下所有文章的 categories 和 tags，<br>    如果分类不合理就调整一下。Docker 相关的文章 categories 改成<span class="hljs-string">&quot;容器&quot;</span>，<br>    Kubernetes 和 OpenStack 的改成<span class="hljs-string">&quot;云原生&quot;</span>。<br></code></pre></td></tr></table></figure><p>Claude Code 会读取每篇文章的 frontmatter，判断内容主题，然后批量修改。</p><h3 id="场景三：生成文章摘要和-SEO-优化"><a href="#场景三：生成文章摘要和-SEO-优化" class="headerlink" title="场景三：生成文章摘要和 SEO 优化"></a>场景三：生成文章摘要和 SEO 优化</h3><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs gradle">你：给每篇文章在 frontmatter 里加一个 <span class="hljs-keyword">description</span> 字段，<br>    用一句话概括文章内容，控制在 <span class="hljs-number">150</span> 字以内，用于 SEO。<br></code></pre></td></tr></table></figure><h3 id="场景四：检查部署状态"><a href="#场景四：检查部署状态" class="headerlink" title="场景四：检查部署状态"></a>场景四：检查部署状态</h3><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">你：帮我检查一下 Vercel 上最新的部署状态，有没有报错。<br></code></pre></td></tr></table></figure><p>Claude Code 可以调用 Vercel 的 API 或 CLI 来检查部署日志。</p><h2 id="自动化工作流设计"><a href="#自动化工作流设计" class="headerlink" title="自动化工作流设计"></a>自动化工作流设计</h2><p>把上面的场景串起来，就是一个完整的自动化工作流：</p><figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs armasm">你描述需求（自然语言）<br>       ↓<br><span class="hljs-symbol">Claude</span> <span class="hljs-meta">Code</span> 读取 CLAUDE.md 了解项目规范<br>       ↓<br><span class="hljs-symbol">Claude</span> <span class="hljs-meta">Code</span> 执行操作（写代码/改文件/跑命令）<br>       ↓<br><span class="hljs-symbol">Claude</span> <span class="hljs-meta">Code</span> 本地验证（检查语法、运行测试）<br>       ↓<br><span class="hljs-symbol">git</span> <span class="hljs-keyword">add</span> → git commit → git <span class="hljs-keyword">push</span><br>       ↓<br><span class="hljs-symbol">Vercel</span> 检测到推送，自动构建部署<br>       ↓<br>部署完成，你收到通知<br></code></pre></td></tr></table></figure><p>整个过程你只需要做第一步和最后一步的确认，中间全是自动的。</p><h3 id="关键：让-Claude-Code-自己决定提交时机"><a href="#关键：让-Claude-Code-自己决定提交时机" class="headerlink" title="关键：让 Claude Code 自己决定提交时机"></a>关键：让 Claude Code 自己决定提交时机</h3><p>在 CLAUDE.md 里写清楚规则后，你可以直接说：</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">你：改完这篇文章后直接推送到 GitHub。<br></code></pre></td></tr></table></figure><p>Claude Code 会自己执行 <code>git add</code>、<code>git commit</code>、<code>git push</code>，不需要你一步步教。</p><h2 id="进阶玩法"><a href="#进阶玩法" class="headerlink" title="进阶玩法"></a>进阶玩法</h2><h3 id="定时任务自动巡检"><a href="#定时任务自动巡检" class="headerlink" title="定时任务自动巡检"></a>定时任务自动巡检</h3><p>Claude Code 支持定时任务功能。比如你可以设置每天早上自动检查：</p><figure class="highlight tap"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs tap">每天早上<span class="hljs-number"> 9 </span>点，检查 Vercel 部署状态，如果有失败的就通知我。<br></code></pre></td></tr></table></figure><h3 id="多项目并行管理"><a href="#多项目并行管理" class="headerlink" title="多项目并行管理"></a>多项目并行管理</h3><p>如果你同时维护多个项目，每个项目根目录放一份 CLAUDE.md，Claude Code 切换到不同目录时会自动加载对应的规范。</p><figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs applescript">你：切到 <span class="hljs-keyword">my</span>-blog 项目，帮我检查一下有没有待推送的改动。<br>你：切到 portfolio 项目，把首页的联系方式更新一下。<br></code></pre></td></tr></table></figure><h3 id="用-Memory-保持上下文连贯"><a href="#用-Memory-保持上下文连贯" class="headerlink" title="用 Memory 保持上下文连贯"></a>用 Memory 保持上下文连贯</h3><p>Claude Code 的 Memory 功能可以记住跨会话的信息。比如你告诉它：</p><figure class="highlight coq"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs coq">你：记住一下，我的博客域名是 cloudetopia.<span class="hljs-built_in">top</span>，部署在 Vercel 上。<br></code></pre></td></tr></table></figure><p>以后每次对话它都知道这个信息，不需要你重复说明。</p><h2 id="效率对比"><a href="#效率对比" class="headerlink" title="效率对比"></a>效率对比</h2><p>同样一批任务，手动操作和 Claude Code 操作的对比：</p><table><thead><tr><th>任务</th><th>手动操作</th><th>Claude Code</th></tr></thead><tbody><tr><td>改写 14 篇文章格式</td><td>2-3 小时</td><td>10 分钟</td></tr><tr><td>批量调整分类标签</td><td>30 分钟</td><td>2 分钟</td></tr><tr><td>检查部署状态</td><td>打开网页 → 登录 → 查看</td><td>一句话</td></tr><tr><td>新增一篇博客文章</td><td>写内容 + 手动加 frontmatter + git 操作</td><td>描述需求，全自动</td></tr><tr><td>修复一个配置错误</td><td>查文档 + 改文件 + 测试 + 提交</td><td>描述问题，自动完成</td></tr></tbody></table><p>效率提升不是线性的——<strong>越重复、越机械的任务，AI 的优势越明显</strong>。</p><h2 id="常见问题与踩坑记录"><a href="#常见问题与踩坑记录" class="headerlink" title="常见问题与踩坑记录"></a>常见问题与踩坑记录</h2><p>❌ <strong>Claude Code 不遵守 CLAUDE.md 里的规范</strong></p><p>检查文件是否在<strong>项目根目录</strong>（和 <code>.git</code> 同级），文件名必须是大写的 <code>CLAUDE.md</code>。如果项目结构复杂，可以在子目录也放一份。</p><p>❌ <strong>批量操作时 Claude Code 改错了文件</strong></p><p>这是 AI 的常见问题。建议先让它在<strong>一个文件上试改</strong>，确认效果满意后再说”其他文件也按这个方式改”。Git 的存在就是为了防止这种意外——改错了可以回滚（下一篇详细讲）。</p><p>❌ <strong>Claude Code 执行 git push 失败</strong></p><p>通常是认证问题。确认 Git 的 remote URL 正确（<code>git remote -v</code> 检查），以及你已经配置了 Personal Access Token 或 SSH Key。</p><p>❌ <strong>Vercel 部署成功但页面没更新</strong></p><p>可能是浏览器缓存。尝试强制刷新（Ctrl+Shift+R），或者在 Vercel 控制台手动触发一次 Redeploy。</p><p>❌ <strong>Claude Code 响应变慢或卡住</strong></p><p>可能是上下文太长了。试试开启新会话，或者把复杂任务拆成几个小任务分步执行。</p><h2 id="下一步"><a href="#下一步" class="headerlink" title="下一步"></a>下一步</h2><p>现在你已经能用 Claude Code 高效管理项目了。但 AI 写代码难免会出错——删错文件、改坏配置、推送了有 bug 的版本。下一篇我们会讲：<strong>当 Claude Code 翻车时，如何用 Git 快速回滚，把损失降到最低</strong>。</p><hr><p><em>下一篇：Claude Code 写代码翻车了？Git 回滚与故障恢复实战</em></p>]]></content>
    
    
    <summary type="html">用 Claude Code 实现项目管理自动化，涵盖批量操作、配置管理、部署检查等场景。</summary>
    
    
    
    <category term="教程" scheme="https://www.cloudetopia.top/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="AI Agent" scheme="https://www.cloudetopia.top/tags/AI-Agent/"/>
    
    <category term="Claude Code" scheme="https://www.cloudetopia.top/tags/Claude-Code/"/>
    
    <category term="自动化" scheme="https://www.cloudetopia.top/tags/%E8%87%AA%E5%8A%A8%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>从零搭建 AI 协作开发环境：Claude Code + GitHub + Vercel</title>
    <link href="https://www.cloudetopia.top/2026/07/01/2026-07-01-AI%E5%8D%8F%E4%BD%9C%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/"/>
    <id>https://www.cloudetopia.top/2026/07/01/2026-07-01-AI%E5%8D%8F%E4%BD%9C%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/</id>
    <published>2026-07-01T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>2025 年，AI 编程工具迎来了一次爆发。从 GitHub Copilot 到 Cursor，再到 Anthropic 推出的 Claude Code，开发者第一次可以真正意义上”让 AI 帮你写代码、跑命令、管项目”。</p><p>但这套工具链搭起来并不容易——尤其是对于零基础的新手来说，Claude Code 是什么、GitHub 怎么用、Vercel 怎么连，每一个概念都是新的。</p><p>这篇文章的目标很简单：<strong>带你从零开始，把 Claude Code + GitHub + Vercel 这套 AI 协作开发环境跑通</strong>。搭好之后，你只需要用自然语言告诉 Claude Code 你想做什么，它就能帮你写代码、提交到 GitHub、自动部署到 Vercel。</p><h2 id="先搞清楚四个概念"><a href="#先搞清楚四个概念" class="headerlink" title="先搞清楚四个概念"></a>先搞清楚四个概念</h2><p>在动手之前，先用最直白的话解释一下这四个工具各自是干什么的。</p><table><thead><tr><th>工具</th><th>一句话解释</th><th>生活类比</th></tr></thead><tbody><tr><td>Git</td><td>代码的版本管理工具，每次修改都有记录</td><td>游戏的存档系统</td></tr><tr><td>GitHub</td><td>云端的代码仓库，存代码的地方</td><td>云盘，但专门存代码</td></tr><tr><td>Vercel</td><td>自动部署平台，代码推上去就能变成网站</td><td>自动售货机，投币（推代码）就出货（网站）</td></tr><tr><td>Claude Code</td><td>AI 编程助手，用命令行跟你协作写代码</td><td>一个坐在你旁边的程序员队友</td></tr></tbody></table><p>它们之间的关系是这样的：</p><figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs armasm">你用自然语言描述需求<br>       ↓<br><span class="hljs-symbol">Claude</span> <span class="hljs-meta">Code</span> 帮你写代码、改文件<br>       ↓<br><span class="hljs-symbol">git</span> <span class="hljs-keyword">push</span> 推送到 GitHub<br>       ↓<br><span class="hljs-symbol">Vercel</span> 检测到更新，自动构建部署<br>       ↓<br>你的网站上线了<br></code></pre></td></tr></table></figure><p>整个过程你只需要做两件事：<strong>描述需求</strong> 和 <strong>确认结果</strong>。中间的脏活累活全是 Claude Code 和自动化流程帮你干。</p><h2 id="环境搭建"><a href="#环境搭建" class="headerlink" title="环境搭建"></a>环境搭建</h2><h3 id="第一步：注册-GitHub-并创建仓库"><a href="#第一步：注册-GitHub-并创建仓库" class="headerlink" title="第一步：注册 GitHub 并创建仓库"></a>第一步：注册 GitHub 并创建仓库</h3><p>去 <a href="https://github.com/">github.com</a> 注册一个账号（免费），然后创建一个新仓库。</p><p>比如我们要做一个博客项目，就叫 <code>my-blog</code>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 在 GitHub 网页上点 &quot;New Repository&quot;</span><br><span class="hljs-comment"># 仓库名：my-blog</span><br><span class="hljs-comment"># 勾选 &quot;Add a README file&quot;</span><br><span class="hljs-comment"># 点 &quot;Create repository&quot;</span><br></code></pre></td></tr></table></figure><blockquote><p>⚠️ 仓库名建议用英文小写 + 短横线，比如 <code>my-blog</code>、<code>portfolio-site</code>，不要用中文或空格。</p></blockquote><h3 id="第二步：安装-Git-并配置身份"><a href="#第二步：安装-Git-并配置身份" class="headerlink" title="第二步：安装 Git 并配置身份"></a>第二步：安装 Git 并配置身份</h3><p><strong>Windows 用户</strong>：去 <a href="https://git-scm.com/download/win">git-scm.com</a> 下载安装，一路默认即可。</p><p><strong>macOS 用户</strong>：打开终端输入：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">xcode-select --install<br></code></pre></td></tr></table></figure><p>安装完成后，配置你的身份信息：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">git config --global user.name <span class="hljs-string">&quot;你的名字&quot;</span><br>git config --global user.email <span class="hljs-string">&quot;你的邮箱&quot;</span><br></code></pre></td></tr></table></figure><p>这里的邮箱建议和 GitHub 注册邮箱保持一致，后面推送代码时会用到。</p><p>验证安装是否成功：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">git --version<br><span class="hljs-comment"># 输出类似：git version 2.43.0</span><br></code></pre></td></tr></table></figure><h3 id="第三步：把-GitHub-仓库克隆到本地"><a href="#第三步：把-GitHub-仓库克隆到本地" class="headerlink" title="第三步：把 GitHub 仓库克隆到本地"></a>第三步：把 GitHub 仓库克隆到本地</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 克隆仓库到你电脑上</span><br>git <span class="hljs-built_in">clone</span> https://github.com/你的用户名/my-blog.git<br><span class="hljs-built_in">cd</span> my-blog<br></code></pre></td></tr></table></figure><p>现在你的电脑上就有了一个和 GitHub 同步的文件夹，后面所有的代码改动都会在这里进行。</p><h3 id="第四步：安装-Node-js"><a href="#第四步：安装-Node-js" class="headerlink" title="第四步：安装 Node.js"></a>第四步：安装 Node.js</h3><p>Claude Code 和 Vercel 都依赖 Node.js 环境。去 <a href="https://nodejs.org/">nodejs.org</a> 下载 LTS 版本安装。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">node --version<br><span class="hljs-comment"># 输出类似：v20.11.0</span><br><br>npm --version<br><span class="hljs-comment"># 输出类似：10.2.0</span><br></code></pre></td></tr></table></figure><h3 id="第五步：安装-Claude-Code"><a href="#第五步：安装-Claude-Code" class="headerlink" title="第五步：安装 Claude Code"></a>第五步：安装 Claude Code</h3><p>Claude Code 是 Anthropic 推出的命令行 AI 编程工具，通过 npm 安装：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install -g @anthropic-ai/claude-code<br></code></pre></td></tr></table></figure><p>安装完成后，首次运行需要登录认证：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">claude<br><span class="hljs-comment"># 首次启动会引导你登录 Anthropic 账号</span><br><span class="hljs-comment"># 按提示在浏览器中完成授权即可</span><br></code></pre></td></tr></table></figure><blockquote><p>⚠️ Claude Code 需要 Anthropic API 账号或订阅（Claude Pro&#x2F;Max）。如果还没有，先去 <a href="https://console.anthropic.com/">console.anthropic.com</a> 注册。</p></blockquote><h3 id="国内用户：使用-cc-switch-接入国产大模型"><a href="#国内用户：使用-cc-switch-接入国产大模型" class="headerlink" title="国内用户：使用 cc-switch 接入国产大模型"></a>国内用户：使用 cc-switch 接入国产大模型</h3><p>由于网络环境限制，国内用户直接访问 Anthropic API 可能会遇到连接超时或认证失败的问题。社区开发了一个实用工具 <strong>cc-switch</strong>，可以帮你快速切换 Claude Code 的配置，接入国内的大模型服务（如通义千问、DeepSeek、Moonshot 等），无需科学上网即可使用。</p><p><strong>安装 cc-switch：</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install -g cc-switch<br></code></pre></td></tr></table></figure><p><strong>基本用法：</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看当前配置</span><br>cc-switch list<br><br><span class="hljs-comment"># 切换到国内模型（以 DeepSeek 为例）</span><br>cc-switch use deepseek<br><br><span class="hljs-comment"># 手动配置自定义 API 端点</span><br>cc-switch config --api-url https://api.deepseek.com/v1 --api-key sk-你的密钥<br></code></pre></td></tr></table></figure><p>cc-switch 本质上是一个配置管理工具，它帮你修改 Claude Code 的环境变量（<code>ANTHROPIC_BASE_URL</code>、<code>ANTHROPIC_API_KEY</code> 等），让请求指向你指定的 API 地址。这样即使无法直连 Anthropic，也能用国产大模型获得类似的 Agent 体验。</p><table><thead><tr><th>模型</th><th>API 地址</th><th>特点</th></tr></thead><tbody><tr><td>DeepSeek</td><td><code>https://api.deepseek.com/v1</code></td><td>性价比高，代码能力强</td></tr><tr><td>通义千问</td><td><code>https://dashscope.aliyuncs.com/compatible-mode/v1</code></td><td>阿里出品，中文理解好</td></tr><tr><td>Moonshot (Kimi)</td><td><code>https://api.moonshot.cn/v1</code></td><td>长上下文支持好</td></tr></tbody></table><blockquote><p>⚠️ 使用国产大模型时，Claude Code 的部分高级特性（如某些工具调用格式）可能不完全兼容。建议先用 DeepSeek 或通义千问测试基础功能，确认稳定后再用于正式项目。</p></blockquote><h3 id="第六步：连接-Vercel"><a href="#第六步：连接-Vercel" class="headerlink" title="第六步：连接 Vercel"></a>第六步：连接 Vercel</h3><p>去 <a href="https://vercel.com/">vercel.com</a> 注册账号，建议直接用 GitHub 账号登录，省去绑定步骤。</p><p>然后在项目根目录安装 Vercel CLI：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install -g vercel<br></code></pre></td></tr></table></figure><p>登录 Vercel：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">vercel login<br><span class="hljs-comment"># 选择通过 GitHub 登录，浏览器会弹出授权页面</span><br></code></pre></td></tr></table></figure><h2 id="第一次协作实战"><a href="#第一次协作实战" class="headerlink" title="第一次协作实战"></a>第一次协作实战</h2><p>环境搭好了，现在来走一遍完整流程。我们用 Claude Code 创建一个简单的网页项目，然后推送到 GitHub，让 Vercel 自动部署。</p><h3 id="1-让-Claude-Code-帮你写代码"><a href="#1-让-Claude-Code-帮你写代码" class="headerlink" title="1. 让 Claude Code 帮你写代码"></a>1. 让 Claude Code 帮你写代码</h3><p>在项目目录下启动 Claude Code：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">cd</span> my-blog<br>claude<br></code></pre></td></tr></table></figure><p>进入对话界面后，直接用自然语言描述你的需求：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs css">你：帮我创建一个简单的个人主页，包含一个标题、一段自我介绍、<br>    和一个项目展示区域。用 <span class="hljs-selector-tag">HTML</span> + CSS，风格简洁现代。<br></code></pre></td></tr></table></figure><p>Claude Code 会帮你生成文件、写入代码。你可以继续对话调整：</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">你：标题改成深蓝色，卡片加个圆角和阴影效果。<br></code></pre></td></tr></table></figure><figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs 1c">你：再加一个底部 footer，显示 <span class="hljs-string">&quot;© 2026 My Blog&quot;</span>。<br></code></pre></td></tr></table></figure><p>这就是 Claude Code 的核心用法——<strong>你描述需求，它写代码</strong>。不需要你手动编辑任何文件。</p><h3 id="2-推送到-GitHub"><a href="#2-推送到-GitHub" class="headerlink" title="2. 推送到 GitHub"></a>2. 推送到 GitHub</h3><p>代码写好后，让 Claude Code 帮你提交：</p><figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs 1c">你：把所有改动提交到 Git，提交信息写 <span class="hljs-string">&quot;feat: 初始化个人主页&quot;</span>。<br></code></pre></td></tr></table></figure><p>Claude Code 会执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">git add .<br>git commit -m <span class="hljs-string">&quot;feat: 初始化个人主页&quot;</span><br></code></pre></td></tr></table></figure><p>然后推送到 GitHub：</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">你：推送到 GitHub。<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">git push origin main<br></code></pre></td></tr></table></figure><h3 id="3-Vercel-自动部署"><a href="#3-Vercel-自动部署" class="headerlink" title="3. Vercel 自动部署"></a>3. Vercel 自动部署</h3><p>去 Vercel 控制台，点 **”Add New” → “Project”**，导入你刚才创建的 <code>my-blog</code> 仓库。</p><p>Vercel 会自动识别项目类型，大部分情况下默认配置就能用。对于纯 HTML 项目，几乎不需要额外配置，直接点 <strong>Deploy</strong>。</p><p>几秒后，Vercel 会给你一个在线访问地址：</p><figure class="highlight dts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs dts">✅ Congratulations! Your project has been deployed.<br><span class="hljs-symbol">https:</span><span class="hljs-comment">//my-blog.vercel.app</span><br></code></pre></td></tr></table></figure><p>从此以后，每次你让 Claude Code 改完代码并 <code>git push</code>，Vercel 就会自动重新部署。<strong>你甚至不需要打开 Vercel 的网页。</strong></p><h2 id="项目指令文件：让-Claude-Code-更懂你的项目"><a href="#项目指令文件：让-Claude-Code-更懂你的项目" class="headerlink" title="项目指令文件：让 Claude Code 更懂你的项目"></a>项目指令文件：让 Claude Code 更懂你的项目</h2><p>Claude Code 有一个很强大的特性——<strong>项目指令文件</strong>。在项目根目录创建一个 <code>CLAUDE.md</code>，写入项目的背景信息和规范，Claude Code 每次启动时都会读取它。</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs markdown"><span class="hljs-section"># CLAUDE.md</span><br><br><span class="hljs-section">## 项目信息</span><br>这是一个基于 Hexo 的个人博客项目，部署在 Vercel 上。<br><br><span class="hljs-section">## 代码规范</span><br><span class="hljs-bullet">-</span> 文章使用 Markdown 格式，存放在 source/<span class="hljs-emphasis">_posts/ 目录</span><br><span class="hljs-emphasis">- 每篇文章必须包含 YAML frontmatter（title、date、categories、tags）</span><br><span class="hljs-emphasis">- 代码块必须标注语言类型</span><br><span class="hljs-emphasis"></span><br><span class="hljs-emphasis">## 工作流</span><br><span class="hljs-emphasis">- 修改完成后用 git push 推送到 main 分支</span><br><span class="hljs-emphasis">- Vercel 会自动构建部署</span><br><span class="hljs-emphasis">- 提交信息格式：type: description（如 feat: 新文章、fix: 修复排版）</span><br></code></pre></td></tr></table></figure><p>有了这个文件，Claude Code 就知道你的项目是什么、该怎么写代码、该怎么提交。相当于给 AI 队友写了一份”入职手册”。</p><h2 id="工具对比：Claude-Code-vs-其他-AI-编程工具"><a href="#工具对比：Claude-Code-vs-其他-AI-编程工具" class="headerlink" title="工具对比：Claude Code vs 其他 AI 编程工具"></a>工具对比：Claude Code vs 其他 AI 编程工具</h2><p>市面上有不少 AI 编程工具，简单对比一下各自的定位：</p><table><thead><tr><th>工具</th><th>形态</th><th>擅长场景</th><th>价格</th></tr></thead><tbody><tr><td>Claude Code</td><td>命令行 Agent</td><td>全栈开发、项目管理、自动化操作</td><td>Claude Pro $20&#x2F;月 或 API 按量</td></tr><tr><td>Cursor</td><td>代码编辑器</td><td>日常写代码、补全、重构</td><td>Pro $20&#x2F;月</td></tr><tr><td>GitHub Copilot</td><td>IDE 插件</td><td>代码补全、行级建议</td><td>$10&#x2F;月</td></tr><tr><td>QoderWork</td><td>桌面助手</td><td>文件处理、多工具协作、日常办公</td><td>积分制</td></tr></tbody></table><p>Claude Code 最大的优势在于它是一个 <strong>Agent</strong>——不只是补全代码，而是能理解整个项目上下文、执行命令、操作 Git、管理文件。你可以把它理解为一个”能动手干活的 AI 程序员”，而不只是一个”打字快的代码助手”。</p><p>当然，这些工具并不冲突。很多人会同时用 Cursor 写日常代码、用 Claude Code 做复杂任务和项目管理。</p><h2 id="常见问题与踩坑记录"><a href="#常见问题与踩坑记录" class="headerlink" title="常见问题与踩坑记录"></a>常见问题与踩坑记录</h2><p>❌ <strong>Claude Code 安装报错 <code>EACCES permission denied</code></strong></p><p>Windows 用户需要用管理员权限运行终端，macOS&#x2F;Linux 用户不要加 <code>sudo</code>，改用修复 npm 全局目录权限的方式：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">mkdir</span> ~/.npm-global<br>npm config <span class="hljs-built_in">set</span> prefix <span class="hljs-string">&#x27;~/.npm-global&#x27;</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&#x27;export PATH=~/.npm-global/bin:$PATH&#x27;</span> &gt;&gt; ~/.bashrc<br><span class="hljs-built_in">source</span> ~/.bashrc<br>npm install -g @anthropic-ai/claude-code<br></code></pre></td></tr></table></figure><p>❌ <strong>cc-switch 切换后 Claude Code 无响应或报错</strong></p><p>通常是 API Key 无效或端点地址不对。用 <code>cc-switch list</code> 检查当前配置，确认 API Key 没有过期、端点地址拼写正确。部分国产模型的 API 路径需要带 <code>/v1</code> 后缀。</p><p>❌ <strong>git push 要求输入密码，但输入 GitHub 密码不对</strong></p><p>GitHub 已经不支持密码认证了，需要用 Personal Access Token：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 去 GitHub → Settings → Developer settings → Personal access tokens → Generate new token</span><br><span class="hljs-comment"># 勾选 repo 权限，生成后复制 token</span><br><span class="hljs-comment"># push 时密码栏粘贴这个 token</span><br></code></pre></td></tr></table></figure><p>❌ <strong>Vercel 部署后页面空白</strong></p><p>通常是构建命令或输出目录配置不对。检查 <code>vercel.json</code> 中的 <code>buildCommand</code> 和 <code>outputDirectory</code> 是否和你的项目匹配。</p><p>❌ <strong>Claude Code 不认识我的项目结构</strong></p><p>第一次使用时，建议先让它”读一下项目”：</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">你：帮我分析一下这个项目的目录结构和主要技术栈。<br></code></pre></td></tr></table></figure><p>或者确保项目根目录有 <code>CLAUDE.md</code> 指令文件，Claude Code 会自动读取。</p><p>❌ <strong>Vercel 没有自动触发部署</strong></p><p>检查 Vercel 项目 Settings → Git，确认仓库已正确连接，Production Branch 设为 <code>main</code>。</p><h2 id="这套工作流的核心思路"><a href="#这套工作流的核心思路" class="headerlink" title="这套工作流的核心思路"></a>这套工作流的核心思路</h2><p>回顾一下，整套环境的核心逻辑其实就三句话：</p><p><strong>GitHub 存代码，Vercel 跑网站，Claude Code 帮你干活。</strong></p><p>你不需要记住复杂的命令，不需要手动构建部署，甚至不需要精通编程。你只需要清楚地描述”我想要什么”，剩下的交给 AI 和自动化。</p><p>这也是 2026 年开发方式的一个趋势——**从”人写代码”到”人描述需求，AI 写代码，自动化流程上线”**。</p><hr><p><em>下一篇我们会深入讲解如何用 Claude Code 实现项目的自动化管理，包括批量操作、定时任务、多项目协作等进阶玩法。</em></p>]]></content>
    
    
    <summary type="html">从零搭建 Claude Code + GitHub + Vercel AI 协作开发环境，适合零基础入门。</summary>
    
    
    
    <category term="教程" scheme="https://www.cloudetopia.top/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="Vercel" scheme="https://www.cloudetopia.top/tags/Vercel/"/>
    
    <category term="AI Agent" scheme="https://www.cloudetopia.top/tags/AI-Agent/"/>
    
    <category term="Claude Code" scheme="https://www.cloudetopia.top/tags/Claude-Code/"/>
    
    <category term="GitHub" scheme="https://www.cloudetopia.top/tags/GitHub/"/>
    
  </entry>
  
  <entry>
    <title>Hexo 博客迁移全记录：从 GitHub Pages 到 Vercel</title>
    <link href="https://www.cloudetopia.top/2026/06/30/2026-06-30-Hexo-to-Vercel/"/>
    <id>https://www.cloudetopia.top/2026/06/30/2026-06-30-Hexo-to-Vercel/</id>
    <published>2026-06-30T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>我的个人博客（cloudetopia.top）原本部署在 GitHub Pages 上，一直存在几个痛点：部署流程繁琐、国内访问慢、图片缓存难控制等。最近趁着本地源文件丢失的机会，干脆做了一次彻底的技术栈升级——<strong>从 GitHub Pages 迁移到 Vercel</strong>。</p><p>这篇文章完整记录了迁移过程、踩坑和解决方案，供有同样需求的朋友参考。</p><h2 id="旧架构的问题"><a href="#旧架构的问题" class="headerlink" title="旧架构的问题"></a>旧架构的问题</h2><p>迁移前的架构：</p><figure class="highlight verilog"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs verilog">本地写 Markdown → hexo <span class="hljs-keyword">generate</span> → hexo deploy → GitHub Pages<br></code></pre></td></tr></table></figure><p>这个流程有几个明显的问题：</p><ul><li><strong>部署依赖本地环境</strong>：换台电脑就得重新装 Node.js、Hexo CLI</li><li><strong>国内访问慢</strong>：GitHub Pages 服务器在海外</li><li><strong>主题文件丢失</strong>：本地源文件丢了，LiveForCode 主题只剩残片</li><li><strong>无 CI&#x2F;CD</strong>：每次更新都要手动构建、推送</li></ul><h2 id="新架构：Vercel-方案"><a href="#新架构：Vercel-方案" class="headerlink" title="新架构：Vercel 方案"></a>新架构：Vercel 方案</h2><p>迁移后的架构：</p><figure class="highlight arcade"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs arcade">本地写 Markdown → git <span class="hljs-built_in">push</span> → Vercel 自动构建 → 全球 CDN 分发<br></code></pre></td></tr></table></figure><p>一步到位，自动部署。</p><h3 id="对比优势"><a href="#对比优势" class="headerlink" title="对比优势"></a>对比优势</h3><table><thead><tr><th>维度</th><th>GitHub Pages</th><th>Vercel</th></tr></thead><tbody><tr><td>部署方式</td><td>本地手动</td><td>git push 自动</td></tr><tr><td>国内访问</td><td>慢</td><td>Edge Network</td></tr><tr><td>CI&#x2F;CD</td><td>无</td><td>内置</td></tr><tr><td>Serverless</td><td>不支持</td><td>支持</td></tr><tr><td>成本</td><td>免费</td><td>免费</td></tr></tbody></table><h2 id="迁移过程"><a href="#迁移过程" class="headerlink" title="迁移过程"></a>迁移过程</h2><p>花了几个小时完成了整个迁移，核心步骤如下：</p><h3 id="1-配置-Vercel-部署"><a href="#1-配置-Vercel-部署" class="headerlink" title="1. 配置 Vercel 部署"></a>1. 配置 Vercel 部署</h3><p>在项目根目录创建 <code>vercel.json</code>：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">&#123;</span><br>  <span class="hljs-attr">&quot;buildCommand&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;npx hexo generate&quot;</span><span class="hljs-punctuation">,</span><br>  <span class="hljs-attr">&quot;outputDirectory&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;public&quot;</span><span class="hljs-punctuation">,</span><br>  <span class="hljs-attr">&quot;installCommand&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;npm install&quot;</span><span class="hljs-punctuation">,</span><br>  <span class="hljs-attr">&quot;framework&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">null</span></span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure><p>然后去 Vercel 导入 GitHub 仓库，绑定域名就好了。</p><h3 id="2-替换主题"><a href="#2-替换主题" class="headerlink" title="2. 替换主题"></a>2. 替换主题</h3><p>原 LiveForCode 主题的模板文件已丢失，选了 <strong>Hexo Fluid</strong> 主题替代。安装很简单：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install --save hexo-theme-fluid hexo-renderer-ejs hexo-renderer-stylus<br></code></pre></td></tr></table></figure><blockquote><p>⚠️ 一定要装 <code>hexo-renderer-ejs</code> 和 <code>hexo-renderer-stylus</code>，否则 Fluid 主题会生成空白页面。</p></blockquote><p>然后在 <code>_config.yml</code> 里设置 <code>theme: fluid</code>，再写一份 <code>_config.fluid.yml</code> 自定义配置。</p><h3 id="3-迁移图片"><a href="#3-迁移图片" class="headerlink" title="3. 迁移图片"></a>3. 迁移图片</h3><p>旧博客的头图存在 hexo-blog 仓库里，选了几张迁移过来：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">mkdir</span> -p <span class="hljs-built_in">source</span>/images/hero<br><span class="hljs-comment"># 下载 01~09.jpg</span><br></code></pre></td></tr></table></figure><p>在主题配置里指向新路径即可。</p><h2 id="踩坑记录"><a href="#踩坑记录" class="headerlink" title="踩坑记录"></a>踩坑记录</h2><h3 id="❌-部署后空白页面"><a href="#❌-部署后空白页面" class="headerlink" title="❌ 部署后空白页面"></a>❌ 部署后空白页面</h3><p>Vercel 返回 HTTP 200 但 HTML 是空的——<strong>缺少 EJS 渲染器</strong>。</p><p><strong>解决</strong>：安装 <code>hexo-renderer-ejs</code> 和 <code>hexo-renderer-stylus</code>。</p><h3 id="❌-hexo-command-not-found-exit-127"><a href="#❌-hexo-command-not-found-exit-127" class="headerlink" title="❌ hexo: command not found (exit 127)"></a>❌ hexo: command not found (exit 127)</h3><p>Vercel 默认把框架识别为 “Hexo”，内置构建命令不兼容。</p><p><strong>解决</strong>：在 Vercel 项目 Settings → Build &amp; Development Settings 里把 Framework Preset 改成 <strong>Other</strong>。</p><h3 id="❌-提交邮箱不匹配被阻止"><a href="#❌-提交邮箱不匹配被阻止" class="headerlink" title="❌ 提交邮箱不匹配被阻止"></a>❌ 提交邮箱不匹配被阻止</h3><p>Vercel 校验提交邮箱，<code>noreply</code> 邮箱被阻止。</p><p><strong>解决</strong>：改成 GitHub 绑定的真实邮箱，关掉 Require Verified Commits。</p><h3 id="❌-自动部署没触发"><a href="#❌-自动部署没触发" class="headerlink" title="❌ 自动部署没触发"></a>❌ 自动部署没触发</h3><p>Git 集成没正确配置。</p><p><strong>解决</strong>：Vercel 项目 Settings → Git 确认仓库已连接，Production Branch 设为 <code>main</code>。</p><h2 id="最终工作流"><a href="#最终工作流" class="headerlink" title="最终工作流"></a>最终工作流</h2><p>现在发布一篇文章只需要：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">git add .<br>git commit -m <span class="hljs-string">&quot;新文章&quot;</span><br>git push origin main<br><span class="hljs-comment"># ✅ Vercel 自动构建部署</span><br></code></pre></td></tr></table></figure><p>整个过程完全自动化，再也不需要本地 <code>hexo generate</code> 和 <code>hexo deploy</code> 了。</p><h2 id="关于-Fluid-主题"><a href="#关于-Fluid-主题" class="headerlink" title="关于 Fluid 主题"></a>关于 Fluid 主题</h2><p>Fluid 是一个非常成熟的中文 Hexo 主题，支持：</p><ul><li>全屏 Banner 头图</li><li>Material Design 卡片布局</li><li>代码高亮 + 复制按钮</li><li>中文搜索</li><li>文章目录导航</li><li>自动摘要</li></ul><p>配置也很灵活，通过 <code>_config.fluid.yml</code> 可以定制导航、首页样式、文章元信息等。</p><h2 id="后续计划"><a href="#后续计划" class="headerlink" title="后续计划"></a>后续计划</h2><ul><li><input checked="" disabled="" type="checkbox"> 上传自定义头像</li><li><input disabled="" type="checkbox"> 用 Vercel KV 实现阅读计数器</li><li><input disabled="" type="checkbox"> 换一个更流畅的评论系统</li><li><input disabled="" type="checkbox"> 集成站点统计</li></ul><hr><p><em>以上就是这次迁移的完整记录。源码在 <a href="https://github.com/MIutopia/hexo-blog-source">MIutopia&#x2F;hexo-blog-source</a>，欢迎参考。</em></p>]]></content>
    
    
    <summary type="html">Hexo 博客从 GitHub Pages 迁移到 Vercel 的完整记录，含踩坑与解决方案。</summary>
    
    
    
    <category term="教程" scheme="https://www.cloudetopia.top/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="DevOps" scheme="https://www.cloudetopia.top/tags/DevOps/"/>
    
    <category term="Hexo" scheme="https://www.cloudetopia.top/tags/Hexo/"/>
    
    <category term="Vercel" scheme="https://www.cloudetopia.top/tags/Vercel/"/>
    
  </entry>
  
  <entry>
    <title>Keepalived 部署实战</title>
    <link href="https://www.cloudetopia.top/2024/06/18/2024-06-18-%E9%83%A8%E7%BD%B2KeepAlived/"/>
    <id>https://www.cloudetopia.top/2024/06/18/2024-06-18-%E9%83%A8%E7%BD%B2KeepAlived/</id>
    <published>2024-06-18T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Keepalived 是一个用于 Linux 服务器的轻量级高可用解决方案。这篇文章记录了在 CentOS 上从源码编译安装 Keepalived 的完整过程，为后续搭建 Nginx + Keepalived 高可用集群做准备。</p><h2 id="安装依赖"><a href="#安装依赖" class="headerlink" title="安装依赖"></a>安装依赖</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 安装 libnl-3 开发库</span><br><span class="hljs-built_in">sudo</span> yum install libnl3-devel libnl3-cli-devel<br></code></pre></td></tr></table></figure><blockquote><p>注：本次部署专注于构建基于 Nginx 和 Keepalived 的高可用集群，已安装的 Nginx 相关工具将不再重复安装。</p></blockquote><h2 id="下载并解压-Keepalived"><a href="#下载并解压-Keepalived" class="headerlink" title="下载并解压 Keepalived"></a>下载并解压 Keepalived</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 进入目录</span><br><span class="hljs-built_in">cd</span> /opt/nginx<br><br><span class="hljs-comment"># 解压 Keepalived</span><br>tar -xvzf keepalived-2.3.1.tar.gz<br></code></pre></td></tr></table></figure><blockquote><p>官网下载地址：<a href="https://keepalived.org/download.html">Keepalived for Linux</a></p></blockquote><h2 id="编译安装"><a href="#编译安装" class="headerlink" title="编译安装"></a>编译安装</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 创建安装目录</span><br><span class="hljs-built_in">mkdir</span> /opt/nginx/keepalived<br><br><span class="hljs-comment"># 进入源码目录</span><br><span class="hljs-built_in">cd</span> /opt/nginx/keepalived-2.3.1<br><br><span class="hljs-comment"># 配置</span><br>./configure --prefix=/opt/nginx/keepalived<br><br><span class="hljs-comment"># 编译安装</span><br>make &amp;&amp; make install<br></code></pre></td></tr></table></figure><h2 id="验证安装"><a href="#验证安装" class="headerlink" title="验证安装"></a>验证安装</h2><p>编译安装完成后，如果显示以下内容，则表示安装成功：</p><figure class="highlight ada"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs ada"><span class="hljs-keyword">Use</span> IPVS Framework       : <span class="hljs-type">Yes</span><br>IPVS <span class="hljs-keyword">use</span> libnl           : <span class="hljs-type">Yes</span><br><span class="hljs-keyword">Use</span> VRRP Framework       : <span class="hljs-type">Yes</span><br><span class="hljs-keyword">Use</span> VRRP VMAC            : <span class="hljs-type">Yes</span><br><span class="hljs-keyword">Use</span> VRRP authentication  : <span class="hljs-type">Yes</span><br><span class="hljs-keyword">With</span> track_process       : <span class="hljs-type">Yes</span><br><span class="hljs-keyword">With</span> linkbeat            : <span class="hljs-type">Yes</span><br></code></pre></td></tr></table></figure><blockquote><p><strong>WARNING</strong>：如果出现警告，可能缺少 Keepalived 所需的第三方库&#x2F;工具。</p></blockquote><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="❌-编译报错：缺少依赖"><a href="#❌-编译报错：缺少依赖" class="headerlink" title="❌ 编译报错：缺少依赖"></a>❌ 编译报错：缺少依赖</h3><p><strong>原因</strong>：缺少 libnl 或 openssl 开发库。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install -y libnl3-devel openssl-devel<br></code></pre></td></tr></table></figure><h3 id="❌-启动失败"><a href="#❌-启动失败" class="headerlink" title="❌ 启动失败"></a>❌ 启动失败</h3><p><strong>原因</strong>：配置文件错误或权限不足。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 检查配置文件</span><br><span class="hljs-built_in">cat</span> /opt/nginx/keepalived/etc/keepalived/keepalived.conf<br><br><span class="hljs-comment"># 使用 root 用户启动</span><br>/opt/nginx/keepalived/sbin/keepalived<br></code></pre></td></tr></table></figure><hr><p><em>以上就是 Keepalived 安装的全部内容。后续文章将介绍如何搭建 Nginx + Keepalived 高可用集群。</em></p>]]></content>
    
    
    <summary type="html">Keepalived 高可用解决方案部署实战，为 Nginx 集群搭建提供基础环境。</summary>
    
    
    
    <category term="负载均衡" scheme="https://www.cloudetopia.top/categories/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/"/>
    
    
    <category term="Keepalived" scheme="https://www.cloudetopia.top/tags/Keepalived/"/>
    
    <category term="高可用" scheme="https://www.cloudetopia.top/tags/%E9%AB%98%E5%8F%AF%E7%94%A8/"/>
    
  </entry>
  
  <entry>
    <title>部署 Nginx + Keepalived 高可用集群</title>
    <link href="https://www.cloudetopia.top/2024/06/18/2024-06-18-%E9%83%A8%E7%BD%B2Nginx-KeepAlived%E9%AB%98%E5%8F%AF%E7%94%A8%E9%9B%86%E7%BE%A4/"/>
    <id>https://www.cloudetopia.top/2024/06/18/2024-06-18-%E9%83%A8%E7%BD%B2Nginx-KeepAlived%E9%AB%98%E5%8F%AF%E7%94%A8%E9%9B%86%E7%BE%A4/</id>
    <published>2024-06-18T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>使用 Nginx 与 Keepalived 构建高可用集群，是提升系统稳定性和可靠性的常见方案。这篇文章从概念讲起，逐步搭建完整的高可用环境。</p><h2 id="核心概念"><a href="#核心概念" class="headerlink" title="核心概念"></a>核心概念</h2><h3 id="Nginx"><a href="#Nginx" class="headerlink" title="Nginx"></a>Nginx</h3><p>Nginx 是一款高性能的 HTTP 和反向代理服务器，主要应用于负载均衡和静态内容服务，同时也提供了 IMAP&#x2F;SMTP&#x2F;POP3 服务。</p><h3 id="Keepalived"><a href="#Keepalived" class="headerlink" title="Keepalived"></a>Keepalived</h3><p>Keepalived 是一个用于监听和故障转移的工具，基于 VRRP 协议（虚拟路由冗余协议）实现。它可以监控服务器状态，并在主服务器故障时自动切换到备份服务器。</p><p>Keepalived 提供了几种冗余方式：</p><ul><li>主备模式（Master-Backup）</li><li>负载均衡模式（Load Balancing）</li><li>主备负载均衡模式</li></ul><h3 id="双机高可用方案"><a href="#双机高可用方案" class="headerlink" title="双机高可用方案"></a>双机高可用方案</h3><ul><li>Keepalived + Nginx 双机主从模式</li><li>Keepalived + Nginx 双机主主模式</li></ul><h2 id="Nginx-核心功能"><a href="#Nginx-核心功能" class="headerlink" title="Nginx 核心功能"></a>Nginx 核心功能</h2><h3 id="正向代理"><a href="#正向代理" class="headerlink" title="正向代理"></a>正向代理</h3><p>帮助内网客户端访问外网服务器的代理方式。客户端无法直接访问目标服务器，但可以通过代理服务器进行访问。</p><p><strong>主要目的</strong>：解决访问限制问题，如绕过地区限制或组织内部的访问限制。</p><h3 id="反向代理"><a href="#反向代理" class="headerlink" title="反向代理"></a>反向代理</h3><p>把外网客户端的请求转发给内网服务器的代理方式。客户端并不知道实际提供服务的服务器地址，只与代理服务器进行交互。</p><p><strong>作用</strong>：</p><ul><li>作为负载均衡器，将客户端请求分发到多个后端服务器</li><li>安全防护，过滤恶意请求和响应</li></ul><h3 id="负载均衡"><a href="#负载均衡" class="headerlink" title="负载均衡"></a>负载均衡</h3><p>将工作负载均匀地分配到多个服务器上，防止任何单一节点过载。</p><p><strong>度量标准</strong>：CPU 使用率、内存使用率、磁盘 I&#x2F;O、网络带宽、并发用户数量等。</p><p><strong>分类</strong>：</p><ul><li><strong>客户端负载均衡</strong>：发生在客户端，由自己决定访问哪台服务器</li><li><strong>服务端负载均衡</strong>：通过专门的负载均衡器（如 Nginx、HAProxy）分发请求</li></ul><h2 id="环境搭建"><a href="#环境搭建" class="headerlink" title="环境搭建"></a>环境搭建</h2><h3 id="1-安装依赖"><a href="#1-安装依赖" class="headerlink" title="1. 安装依赖"></a>1. 安装依赖</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum -y install gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel<br></code></pre></td></tr></table></figure><h3 id="2-下载并解压-Nginx"><a href="#2-下载并解压-Nginx" class="headerlink" title="2. 下载并解压 Nginx"></a>2. 下载并解压 Nginx</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 创建目录</span><br><span class="hljs-built_in">mkdir</span> /opt/nginx<br><span class="hljs-built_in">cd</span> /opt/nginx<br><br><span class="hljs-comment"># 下载并解压</span><br>wget http://nginx.org/download/nginx-1.26.1.tar.gz<br>tar -xzvf nginx-1.26.1.tar.gz<br></code></pre></td></tr></table></figure><h3 id="3-编译安装"><a href="#3-编译安装" class="headerlink" title="3. 编译安装"></a>3. 编译安装</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 创建安装目录</span><br><span class="hljs-built_in">mkdir</span> nginx-1.26.1_install<br><br><span class="hljs-comment"># 进入源码目录</span><br><span class="hljs-built_in">cd</span> nginx-1.26.1<br><br><span class="hljs-comment"># 配置</span><br>./configure --prefix=/opt/nginx/nginx-1.26.1_install<br><br><span class="hljs-comment"># 编译安装</span><br>make &amp;&amp; make install<br></code></pre></td></tr></table></figure><h3 id="4-启动-Nginx"><a href="#4-启动-Nginx" class="headerlink" title="4. 启动 Nginx"></a>4. 启动 Nginx</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 检查配置</span><br>/opt/nginx/nginx-1.26.1_install/sbin/nginx -t<br><br><span class="hljs-comment"># 启动</span><br>/opt/nginx/nginx-1.26.1_install/sbin/nginx<br><br><span class="hljs-comment"># 验证</span><br>curl http://192.168.10.100:80<br></code></pre></td></tr></table></figure><h2 id="Keepalived-配置"><a href="#Keepalived-配置" class="headerlink" title="Keepalived 配置"></a>Keepalived 配置</h2><h3 id="主节点配置"><a href="#主节点配置" class="headerlink" title="主节点配置"></a>主节点配置</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">vi /opt/nginx/keepalived/etc/keepalived/keepalived.conf<br></code></pre></td></tr></table></figure><figure class="highlight angelscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><code class="hljs angelscript">! Configuration File <span class="hljs-keyword">for</span> keepalived<br><br>global_defs &#123;<br>   notification_email &#123;<br>     <span class="hljs-symbol">acassen@</span>firewall.loc<br>   &#125;<br>   router_id LVS_DEVEL<br>&#125;<br><br>vrrp_script chk_nginx &#123;<br>    script <span class="hljs-string">&quot;/opt/nginx/keepalived/check_nginx.sh&quot;</span><br>    <span class="hljs-built_in">int</span>erval <span class="hljs-number">2</span><br>    weight <span class="hljs-number">2</span><br>&#125;<br><br>vrrp_instance VI_1 &#123;<br>    state MASTER<br>    <span class="hljs-keyword">interface</span> <span class="hljs-symbol">eth0</span><br>    <span class="hljs-symbol">virtual_router_id</span> <span class="hljs-symbol">51</span><br>    <span class="hljs-symbol">priority</span> <span class="hljs-symbol">100</span><br>    <span class="hljs-symbol">advert_int</span> <span class="hljs-symbol">1</span><br>    <span class="hljs-symbol">authentication</span> &#123;<br>        auth_type PASS<br>        auth_pass <span class="hljs-number">1111</span><br>    &#125;<br>    virtual_ipaddress &#123;<br>        <span class="hljs-number">192.168</span><span class="hljs-number">.10</span><span class="hljs-number">.100</span><br>    &#125;<br>    track_script &#123;<br>        chk_nginx<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><h3 id="检查脚本"><a href="#检查脚本" class="headerlink" title="检查脚本"></a>检查脚本</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">vi /opt/nginx/keepalived/check_nginx.sh<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-meta">#!/bin/bash</span><br><span class="hljs-keyword">if</span> ! pgrep -x nginx &gt; /dev/null; <span class="hljs-keyword">then</span><br>    systemctl start nginx<br>    <span class="hljs-keyword">if</span> ! pgrep -x nginx &gt; /dev/null; <span class="hljs-keyword">then</span><br>        systemctl stop keepalived<br>    <span class="hljs-keyword">fi</span><br><span class="hljs-keyword">fi</span><br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">chmod</span> +x /opt/nginx/keepalived/check_nginx.sh<br></code></pre></td></tr></table></figure><h3 id="备节点配置"><a href="#备节点配置" class="headerlink" title="备节点配置"></a>备节点配置</h3><p>与主节点类似，修改以下参数：</p><figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs pf"><span class="hljs-keyword">state</span> BACKUP<br>priority <span class="hljs-number">90</span><br></code></pre></td></tr></table></figure><h2 id="启动服务"><a href="#启动服务" class="headerlink" title="启动服务"></a>启动服务</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 主节点</span><br>/opt/nginx/keepalived/sbin/keepalived<br><br><span class="hljs-comment"># 备节点</span><br>/opt/nginx/keepalived/sbin/keepalived<br><br><span class="hljs-comment"># 验证 VIP</span><br>ip addr show eth0<br></code></pre></td></tr></table></figure><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="❌-VIP-无法访问"><a href="#❌-VIP-无法访问" class="headerlink" title="❌ VIP 无法访问"></a>❌ VIP 无法访问</h3><p><strong>原因</strong>：Keepalived 未正确启动或配置错误。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 检查 Keepalived 状态</span><br>ps -ef | grep keepalived<br><br><span class="hljs-comment"># 检查日志</span><br><span class="hljs-built_in">tail</span> -f /var/log/messages<br></code></pre></td></tr></table></figure><h3 id="❌-Nginx-故障未切换"><a href="#❌-Nginx-故障未切换" class="headerlink" title="❌ Nginx 故障未切换"></a>❌ Nginx 故障未切换</h3><p><strong>原因</strong>：检查脚本未正确执行。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 手动测试脚本</span><br>/opt/nginx/keepalived/check_nginx.sh<br><br><span class="hljs-comment"># 检查脚本权限</span><br><span class="hljs-built_in">chmod</span> +x /opt/nginx/keepalived/check_nginx.sh<br></code></pre></td></tr></table></figure><hr><p><em>以上就是 Nginx + Keepalived 高可用集群的完整搭建过程。</em></p>]]></content>
    
    
    <summary type="html">使用 Nginx 与 Keepalived 构建高可用集群，提升系统稳定性和可靠性的完整方案。</summary>
    
    
    
    <category term="负载均衡" scheme="https://www.cloudetopia.top/categories/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/"/>
    
    
    <category term="Nginx" scheme="https://www.cloudetopia.top/tags/Nginx/"/>
    
    <category term="Keepalived" scheme="https://www.cloudetopia.top/tags/Keepalived/"/>
    
    <category term="高可用" scheme="https://www.cloudetopia.top/tags/%E9%AB%98%E5%8F%AF%E7%94%A8/"/>
    
  </entry>
  
  <entry>
    <title>Tomcat 部署实战</title>
    <link href="https://www.cloudetopia.top/2024/06/15/2024-06-15-%E9%83%A8%E7%BD%B2Tomcat/"/>
    <id>https://www.cloudetopia.top/2024/06/15/2024-06-15-%E9%83%A8%E7%BD%B2Tomcat/</id>
    <published>2024-06-15T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Tomcat 是 Apache 软件基金会的一个开源项目，实现了 Java Servlet 和 JavaServer Pages 规范。这篇文章记录了在 CentOS 上部署 Tomcat 的完整过程。</p><h2 id="部署准备"><a href="#部署准备" class="headerlink" title="部署准备"></a>部署准备</h2><h3 id="安装-Java"><a href="#安装-Java" class="headerlink" title="安装 Java"></a>安装 Java</h3><p>Tomcat 是基于 Java 的应用服务器，需要先安装 Java 环境。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 检查 Java 是否已安装</span><br>java -version<br><br><span class="hljs-comment"># 如果没有安装，使用 yum 安装</span><br>yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel<br><br><span class="hljs-comment"># 验证安装</span><br>java -version<br></code></pre></td></tr></table></figure><h3 id="下载-Tomcat"><a href="#下载-Tomcat" class="headerlink" title="下载 Tomcat"></a>下载 Tomcat</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 下载 Tomcat 9</span><br>wget https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.65/bin/apache-tomcat-9.0.65.tar.gz<br><br><span class="hljs-comment"># 解压</span><br>tar -zxvf apache-tomcat-9.0.65.tar.gz<br><br><span class="hljs-comment"># 移动到指定目录</span><br><span class="hljs-built_in">mv</span> apache-tomcat-9.0.65 /usr/local/tomcat<br></code></pre></td></tr></table></figure><h2 id="启动-Tomcat"><a href="#启动-Tomcat" class="headerlink" title="启动 Tomcat"></a>启动 Tomcat</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 启动 Tomcat</span><br>/usr/local/tomcat/bin/startup.sh<br><br><span class="hljs-comment"># 查看日志</span><br><span class="hljs-built_in">tail</span> -f /usr/local/tomcat/logs/catalina.out<br></code></pre></td></tr></table></figure><h2 id="配置防火墙"><a href="#配置防火墙" class="headerlink" title="配置防火墙"></a>配置防火墙</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 开放 8080 端口</span><br>firewall-cmd --add-port=8080/tcp --permanent<br>firewall-cmd --reload<br></code></pre></td></tr></table></figure><p>访问 <code>http://服务器IP:8080</code> 即可看到 Tomcat 默认页面。</p><h2 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 停止 Tomcat</span><br>/usr/local/tomcat/bin/shutdown.sh<br><br><span class="hljs-comment"># 查看 Tomcat 进程</span><br>ps -ef | grep tomcat<br><br><span class="hljs-comment"># 查看日志</span><br><span class="hljs-built_in">tail</span> -f /usr/local/tomcat/logs/catalina.out<br></code></pre></td></tr></table></figure><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="❌-启动失败：JAVA-HOME-未设置"><a href="#❌-启动失败：JAVA-HOME-未设置" class="headerlink" title="❌ 启动失败：JAVA_HOME 未设置"></a>❌ 启动失败：JAVA_HOME 未设置</h3><p><strong>原因</strong>：环境变量未正确配置。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 设置 JAVA_HOME</span><br><span class="hljs-built_in">export</span> JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk<br><br><span class="hljs-comment"># 或添加到 /etc/profile</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&#x27;export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk&#x27;</span> &gt;&gt; /etc/profile<br><span class="hljs-built_in">source</span> /etc/profile<br></code></pre></td></tr></table></figure><h3 id="❌-端口被占用"><a href="#❌-端口被占用" class="headerlink" title="❌ 端口被占用"></a>❌ 端口被占用</h3><p><strong>原因</strong>：8080 端口已被其他服务占用。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 修改 Tomcat 端口</span><br>vi /usr/local/tomcat/conf/server.xml<br><span class="hljs-comment"># 找到 &lt;Connector port=&quot;8080&quot; ...&gt; 修改端口</span><br></code></pre></td></tr></table></figure><hr><p><em>以上就是 Tomcat 部署的全部内容。</em></p>]]></content>
    
    
    <summary type="html">Tomcat 部署实战教程，记录 CentOS 上 Java 环境安装与 Tomcat 服务配置全过程。</summary>
    
    
    
    <category term="教程" scheme="https://www.cloudetopia.top/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="Tomcat" scheme="https://www.cloudetopia.top/tags/Tomcat/"/>
    
    <category term="Java" scheme="https://www.cloudetopia.top/tags/Java/"/>
    
  </entry>
  
  <entry>
    <title>Nginx 虚拟主机配置实战</title>
    <link href="https://www.cloudetopia.top/2024/06/14/2024-06-14-Nginx%E8%99%9A%E6%8B%9F%E4%B8%BB%E6%9C%BA%E7%9A%84%E9%85%8D%E7%BD%AE/"/>
    <id>https://www.cloudetopia.top/2024/06/14/2024-06-14-Nginx%E8%99%9A%E6%8B%9F%E4%B8%BB%E6%9C%BA%E7%9A%84%E9%85%8D%E7%BD%AE/</id>
    <published>2024-06-14T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Nginx 的虚拟主机功能允许单个 Nginx 服务器为多个域名或 IP 地址提供服务，无需为每个域名运行单独的 Nginx 实例。这篇文章介绍如何配置基于域名和基于 IP 的虚拟主机。</p><h2 id="创建项目路径"><a href="#创建项目路径" class="headerlink" title="创建项目路径"></a>创建项目路径</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 创建项目目录</span><br><span class="hljs-built_in">mkdir</span> -p /var/www/site1<br><span class="hljs-built_in">mkdir</span> -p /var/www/site2<br><br><span class="hljs-comment"># 创建测试页面</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;&lt;h1&gt;Welcome to Site1&lt;/h1&gt;&quot;</span> &gt; /var/www/site1/index.html<br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;&lt;h1&gt;Welcome to Site2&lt;/h1&gt;&quot;</span> &gt; /var/www/site2/index.html<br></code></pre></td></tr></table></figure><h2 id="配置虚拟主机"><a href="#配置虚拟主机" class="headerlink" title="配置虚拟主机"></a>配置虚拟主机</h2><h3 id="基于域名的虚拟主机"><a href="#基于域名的虚拟主机" class="headerlink" title="基于域名的虚拟主机"></a>基于域名的虚拟主机</h3><p>编辑 Nginx 配置文件 <code>/etc/nginx/nginx.conf</code> 或创建单独的配置文件：</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">server</span> &#123;<br>    <span class="hljs-attribute">listen</span> <span class="hljs-number">80</span>;<br>    <span class="hljs-attribute">server_name</span> site1.example.com;<br>    <span class="hljs-attribute">root</span> /var/www/site1;<br>    <span class="hljs-attribute">index</span> index.html;<br>&#125;<br><br><span class="hljs-section">server</span> &#123;<br>    <span class="hljs-attribute">listen</span> <span class="hljs-number">80</span>;<br>    <span class="hljs-attribute">server_name</span> site2.example.com;<br>    <span class="hljs-attribute">root</span> /var/www/site2;<br>    <span class="hljs-attribute">index</span> index.html;<br>&#125;<br></code></pre></td></tr></table></figure><h3 id="基于端口的虚拟主机"><a href="#基于端口的虚拟主机" class="headerlink" title="基于端口的虚拟主机"></a>基于端口的虚拟主机</h3><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">server</span> &#123;<br>    <span class="hljs-attribute">listen</span> <span class="hljs-number">8080</span>;<br>    <span class="hljs-attribute">server_name</span> localhost;<br>    <span class="hljs-attribute">root</span> /var/www/site1;<br>    <span class="hljs-attribute">index</span> index.html;<br>&#125;<br><br><span class="hljs-section">server</span> &#123;<br>    <span class="hljs-attribute">listen</span> <span class="hljs-number">8081</span>;<br>    <span class="hljs-attribute">server_name</span> localhost;<br>    <span class="hljs-attribute">root</span> /var/www/site2;<br>    <span class="hljs-attribute">index</span> index.html;<br>&#125;<br></code></pre></td></tr></table></figure><h2 id="重启-Nginx"><a href="#重启-Nginx" class="headerlink" title="重启 Nginx"></a>重启 Nginx</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 测试配置</span><br>nginx -t<br><br><span class="hljs-comment"># 重启 Nginx</span><br>systemctl restart nginx<br></code></pre></td></tr></table></figure><h2 id="本地测试"><a href="#本地测试" class="headerlink" title="本地测试"></a>本地测试</h2><p>在本地 <code>/etc/hosts</code> 文件中添加域名映射：</p><figure class="highlight accesslog"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs accesslog"><span class="hljs-number">127.0.0.1</span> site1.example.com<br><span class="hljs-number">127.0.0.1</span> site2.example.com<br></code></pre></td></tr></table></figure><p>然后访问 <code>http://site1.example.com</code> 和 <code>http://site2.example.com</code> 即可看到不同的页面。</p><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="❌-403-Forbidden"><a href="#❌-403-Forbidden" class="headerlink" title="❌ 403 Forbidden"></a>❌ 403 Forbidden</h3><p><strong>原因</strong>：Nginx 没有权限访问目录。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">chmod</span> -R 755 /var/www/site1<br><span class="hljs-built_in">chown</span> -R nginx:nginx /var/www/site1<br></code></pre></td></tr></table></figure><h3 id="❌-502-Bad-Gateway"><a href="#❌-502-Bad-Gateway" class="headerlink" title="❌ 502 Bad Gateway"></a>❌ 502 Bad Gateway</h3><p><strong>原因</strong>：后端服务未启动或配置错误。</p><p><strong>解决</strong>：检查 <code>proxy_pass</code> 或 <code>fastcgi_pass</code> 配置是否正确。</p><hr><p><em>以上就是 Nginx 虚拟主机配置的全部内容。</em></p>]]></content>
    
    
    <summary type="html">Nginx 虚拟主机配置实战，详解基于域名和基于 IP 的虚拟主机搭建方法。</summary>
    
    
    
    <category term="负载均衡" scheme="https://www.cloudetopia.top/categories/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/"/>
    
    
    <category term="Nginx" scheme="https://www.cloudetopia.top/tags/Nginx/"/>
    
    <category term="负载均衡" scheme="https://www.cloudetopia.top/tags/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/"/>
    
  </entry>
  
  <entry>
    <title>Nginx 部署实战</title>
    <link href="https://www.cloudetopia.top/2024/06/14/2024-06-14-Nginx%E9%83%A8%E7%BD%B2/"/>
    <id>https://www.cloudetopia.top/2024/06/14/2024-06-14-Nginx%E9%83%A8%E7%BD%B2/</id>
    <published>2024-06-14T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Nginx 是一款高性能的 HTTP 和反向代理服务器，广泛应用于 Web 服务、负载均衡和反向代理。这篇文章记录了在 CentOS 上从源码编译安装 Nginx 的完整过程。</p><h2 id="安装依赖"><a href="#安装依赖" class="headerlink" title="安装依赖"></a>安装依赖</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum -y install gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel<br></code></pre></td></tr></table></figure><h2 id="下载并解压-Nginx"><a href="#下载并解压-Nginx" class="headerlink" title="下载并解压 Nginx"></a>下载并解压 Nginx</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 创建目录</span><br><span class="hljs-built_in">mkdir</span> /opt/nginx<br><span class="hljs-built_in">cd</span> /opt/nginx<br><br><span class="hljs-comment"># 下载 Nginx</span><br>wget http://nginx.org/download/nginx-1.26.1.tar.gz<br><br><span class="hljs-comment"># 解压</span><br>tar -xvf nginx-1.26.1.tar.gz<br></code></pre></td></tr></table></figure><blockquote><p>官网下载地址：<a href="http://nginx.org/en/download.html">http://nginx.org/en/download.html</a></p></blockquote><h2 id="编译安装"><a href="#编译安装" class="headerlink" title="编译安装"></a>编译安装</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 创建安装目录</span><br><span class="hljs-built_in">cd</span> /opt/nginx<br><span class="hljs-built_in">mkdir</span> nginx-1.26.1_install<br><br><span class="hljs-comment"># 进入源码目录</span><br><span class="hljs-built_in">cd</span> nginx-1.26.1<br><br><span class="hljs-comment"># 配置（指定安装目录）</span><br>./configure --prefix=/opt/nginx/nginx-1.26.1_install<br><br><span class="hljs-comment"># 编译</span><br>make<br><br><span class="hljs-comment"># 安装</span><br>make install<br></code></pre></td></tr></table></figure><h3 id="安装后的目录结构"><a href="#安装后的目录结构" class="headerlink" title="安装后的目录结构"></a>安装后的目录结构</h3><table><thead><tr><th>目录</th><th>说明</th></tr></thead><tbody><tr><td><code>conf/</code></td><td>Nginx 配置文件（nginx.conf）</td></tr><tr><td><code>html/</code></td><td>默认网页文件</td></tr><tr><td><code>logs/</code></td><td>日志文件</td></tr><tr><td><code>sbin/</code></td><td>Nginx 主程序</td></tr></tbody></table><h2 id="启动-Nginx"><a href="#启动-Nginx" class="headerlink" title="启动 Nginx"></a>启动 Nginx</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 检查配置语法</span><br>/opt/nginx/nginx-1.26.1_install/sbin/nginx -t<br><br><span class="hljs-comment"># 启动 Nginx</span><br>/opt/nginx/nginx-1.26.1_install/sbin/nginx<br><br><span class="hljs-comment"># 查看版本</span><br>./sbin/nginx -v<br><br><span class="hljs-comment"># 查看进程</span><br>ps -ef | grep nginx<br></code></pre></td></tr></table></figure><h2 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 停止 Nginx</span><br>/opt/nginx/nginx-1.26.1_install/sbin/nginx -s stop<br><br><span class="hljs-comment"># 重启 Nginx</span><br>/opt/nginx/nginx-1.26.1_install/sbin/nginx -s reopen<br><br><span class="hljs-comment"># 重新加载配置</span><br>/opt/nginx/nginx-1.26.1_install/sbin/nginx -s reload<br></code></pre></td></tr></table></figure><h2 id="验证"><a href="#验证" class="headerlink" title="验证"></a>验证</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 关闭防火墙（测试用）</span><br>systemctl stop firewalld<br>systemctl <span class="hljs-built_in">disable</span> firewalld<br></code></pre></td></tr></table></figure><p>访问 <code>http://192.168.10.100:80</code> 即可看到 Nginx 默认欢迎页面。</p><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="❌-端口被占用"><a href="#❌-端口被占用" class="headerlink" title="❌ 端口被占用"></a>❌ 端口被占用</h3><p><strong>原因</strong>：80 端口已被其他服务占用。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看占用端口的进程</span><br>netstat -tlnp | grep 80<br><br><span class="hljs-comment"># 或修改 Nginx 监听端口</span><br>vi /opt/nginx/nginx-1.26.1_install/conf/nginx.conf<br><span class="hljs-comment"># 修改 listen 80; 为其他端口</span><br></code></pre></td></tr></table></figure><h3 id="❌-权限不足"><a href="#❌-权限不足" class="headerlink" title="❌ 权限不足"></a>❌ 权限不足</h3><p><strong>原因</strong>：非 root 用户启动 Nginx。</p><p><strong>解决</strong>：使用 <code>sudo</code> 或切换到 root 用户。</p><hr><p><em>以上就是 Nginx 编译安装的全部内容。</em></p>]]></content>
    
    
    <summary type="html">Nginx 部署实战，从源码编译安装到基础配置，记录 CentOS 上完整部署流程。</summary>
    
    
    
    <category term="负载均衡" scheme="https://www.cloudetopia.top/categories/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/"/>
    
    
    <category term="Nginx" scheme="https://www.cloudetopia.top/tags/Nginx/"/>
    
    <category term="负载均衡" scheme="https://www.cloudetopia.top/tags/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/"/>
    
  </entry>
  
  <entry>
    <title>架构基础理论</title>
    <link href="https://www.cloudetopia.top/2024/06/14/2024-06-14-%E6%9E%B6%E6%9E%84%E5%9F%BA%E7%A1%80%E7%90%86%E8%AE%BA/"/>
    <id>https://www.cloudetopia.top/2024/06/14/2024-06-14-%E6%9E%B6%E6%9E%84%E5%9F%BA%E7%A1%80%E7%90%86%E8%AE%BA/</id>
    <published>2024-06-14T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在软件开发和系统设计中，”架构”是一个核心概念。这篇文章简要介绍前端、后端、接口等基础概念。</p><h2 id="架构概述"><a href="#架构概述" class="headerlink" title="架构概述"></a>架构概述</h2><h3 id="前端"><a href="#前端" class="headerlink" title="前端"></a>前端</h3><p>前端是用户看得见的页面（小程序、Web 网页、App），负责将后端处理好的数据进行处理和展示。</p><ul><li><strong>静态页面</strong>：页面内容被写死，不会动态变化</li><li><strong>开发语言</strong>：Java、HTML、CSS、JavaScript 等</li></ul><p>前端代码可以存放于任何有网且能够连接到后端数据库的地方，运行于客户端（如浏览器、App）。</p><h3 id="后端"><a href="#后端" class="headerlink" title="后端"></a>后端</h3><p>后端负责处理业务逻辑、数据存储和计算。它接收前端的请求，进行处理后返回结果。</p><ul><li><strong>开发语言</strong>：Java、Python、Go、Node.js 等</li><li><strong>数据库</strong>：MySQL、PostgreSQL、MongoDB 等</li></ul><h3 id="接口"><a href="#接口" class="headerlink" title="接口"></a>接口</h3><p>接口是前后端通信的桥梁，定义数据交换的格式和规范。</p><p>常见的接口规范：</p><table><thead><tr><th>规范</th><th>说明</th></tr></thead><tbody><tr><td>RESTful</td><td>基于 HTTP 方法的接口风格</td></tr><tr><td>GraphQL</td><td>灵活的数据查询语言</td></tr><tr><td>gRPC</td><td>高性能远程过程调用框架</td></tr></tbody></table><h2 id="典型架构"><a href="#典型架构" class="headerlink" title="典型架构"></a>典型架构</h2><figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs scss">┌─────────────┐     ┌─────────────┐     ┌─────────────┐<br>│   前端      │────→│   接口      │────→│   后端      │<br>│  (浏览器)   │←────│  (API)      │←────│  (服务器)   │<br>└─────────────┘     └─────────────┘     └─────────────┘<br>                                              │<br>                                              ↓<br>                                        ┌─────────────┐<br>                                        │   数据库    │<br>                                        └─────────────┘<br></code></pre></td></tr></table></figure><h2 id="高可用架构"><a href="#高可用架构" class="headerlink" title="高可用架构"></a>高可用架构</h2><p>为了保证服务的可用性，通常会采用集群部署：</p><ul><li><strong>Nginx + Keepalived</strong>：实现 Web 服务的高可用</li><li><strong>数据库主从复制</strong>：实现数据的高可用</li><li><strong>Redis 集群</strong>：实现缓存的高可用</li></ul><hr><p><em>以上就是架构基础理论的全部内容。后续文章会继续深入讲解各个组件。</em></p>]]></content>
    
    
    <summary type="html">软件架构基础概念入门，介绍前端、后端、接口等核心概念及其关系。</summary>
    
    
    
    <category term="架构" scheme="https://www.cloudetopia.top/categories/%E6%9E%B6%E6%9E%84/"/>
    
    
    <category term="架构" scheme="https://www.cloudetopia.top/tags/%E6%9E%B6%E6%9E%84/"/>
    
    <category term="入门" scheme="https://www.cloudetopia.top/tags/%E5%85%A5%E9%97%A8/"/>
    
  </entry>
  
  <entry>
    <title>Ceph 分布式存储详解</title>
    <link href="https://www.cloudetopia.top/2024/03/11/2024-03-11-ceph/"/>
    <id>https://www.cloudetopia.top/2024/03/11/2024-03-11-ceph/</id>
    <published>2024-03-11T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Ceph 是一个统一的分布式存储系统，可以提供对象存储、块存储和文件系统存储。这篇文章从版本介绍开始，逐步讲解 Ceph 的安装和部署过程。</p><h2 id="Ceph-版本历史"><a href="#Ceph-版本历史" class="headerlink" title="Ceph 版本历史"></a>Ceph 版本历史</h2><p>第一个 Ceph 版本是 0.1，要回溯到 2008 年 1 月。多年来，版本号方案一直没变，直到 2015 年 4 月 0.94.1（Hammer 的第一个修正版）发布后，为了避免 0.99（以及 0.100 或 1.00？），制定了新策略：</p><ul><li><code>x.0.z</code> - 开发版（给早期测试者）</li><li><code>x.1.z</code> - 候选版（用于测试集群）</li><li><code>x.2.z</code> - 稳定版（给用户）</li></ul><table><thead><tr><th>版本名称</th><th>版本号</th><th>发布时间</th></tr></thead><tbody><tr><td>Argonaut</td><td>0.48 (LTS)</td><td>2012-06-03</td></tr><tr><td>Bobtail</td><td>0.56 (LTS)</td><td>2013-05-07</td></tr><tr><td>Cuttlefish</td><td>0.61</td><td>2013-01-01</td></tr><tr><td>Dumpling</td><td>0.67 (LTS)</td><td>2013-08-14</td></tr><tr><td>Emperor</td><td>0.72</td><td>2013-11-09</td></tr><tr><td>Firefly</td><td>0.80 (LTS)</td><td>2014-05</td></tr><tr><td>Giant</td><td>0.87</td><td>2014-10</td></tr><tr><td>Hammer</td><td>0.94 (LTS)</td><td>2015-04</td></tr><tr><td>Infernalis</td><td>9.2.0</td><td>2015-11</td></tr><tr><td>Jewel</td><td>10.2.9</td><td>2016-04</td></tr><tr><td>Kraken</td><td>11.2.1</td><td>2017-10</td></tr><tr><td>Luminous</td><td>12.2.12</td><td>2017-10</td></tr><tr><td>Mimic</td><td>13.2.7</td><td>2018-05</td></tr><tr><td>Nautilus</td><td>14.2.5</td><td>2019-02</td></tr><tr><td>Octopus</td><td>15.2.17</td><td>2020-03-23</td></tr><tr><td>Pacific</td><td>16.2.15</td><td>2021-03-31</td></tr><tr><td>Quincy</td><td>17.2.7</td><td>2022-04-19</td></tr><tr><td>Reef</td><td>18.2.1</td><td>2023-08-07</td></tr></tbody></table><blockquote><p>根据 <a href="https://docs.ceph.com/en/latest/releases/">官网</a> 给出的消息，从 O 版（Octopus）开始（包括 O 版）之前的版本都不会再进行维护更新。</p></blockquote><h2 id="安装方式介绍"><a href="#安装方式介绍" class="headerlink" title="安装方式介绍"></a>安装方式介绍</h2><table><thead><tr><th>工具</th><th>说明</th></tr></thead><tbody><tr><td><a href="https://docs.ceph.com/ceph-ansible/">ceph-ansible</a></td><td>使用 Ansible 部署和管理 Ceph 集群</td></tr><tr><td><a href="https://docs.ceph.com/projects/ceph-deploy/en/latest/">ceph-deploy</a></td><td>快速部署集群的工具</td></tr><tr><td><a href="https://docs.ceph.com/en/latest/cephadm/install/">Cephadm</a></td><td>安装和管理 Ceph 集群（推荐）</td></tr></tbody></table><p><strong>Cephadm 特点：</strong></p><ul><li>只支持 Octopus 及更新版本</li><li>与编排 API 完全集成</li><li>需要容器支持（Podman 或 Docker）和 Python 3</li><li>需要 systemd</li></ul><h2 id="环境准备"><a href="#环境准备" class="headerlink" title="环境准备"></a>环境准备</h2><h3 id="主机规划"><a href="#主机规划" class="headerlink" title="主机规划"></a>主机规划</h3><table><thead><tr><th>主机名</th><th>IP 地址</th><th>配置</th></tr></thead><tbody><tr><td>center</td><td>192.168.10.100</td><td>2核2G +20G</td></tr><tr><td>ceph-node1</td><td>192.168.10.11</td><td>2核2G +20G+30G×3</td></tr><tr><td>ceph-node2</td><td>192.168.10.12</td><td>2核2G +20G+30G×3</td></tr><tr><td>ceph-node3</td><td>192.168.10.13</td><td>2核2G +20G+30G×3</td></tr></tbody></table><h3 id="关闭防火墙和-SELinux"><a href="#关闭防火墙和-SELinux" class="headerlink" title="关闭防火墙和 SELinux"></a>关闭防火墙和 SELinux</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 所有节点执行</span><br>systemctl stop firewalld &amp;&amp; systemctl <span class="hljs-built_in">disable</span> firewalld &amp;&amp; setenforce 0<br>sed -i <span class="hljs-string">&#x27;s/enforcing/disabled/&#x27;</span> /etc/selinux/config<br></code></pre></td></tr></table></figure><h3 id="配置主机名和-hosts"><a href="#配置主机名和-hosts" class="headerlink" title="配置主机名和 hosts"></a>配置主机名和 hosts</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 各节点分别执行</span><br>hostnamectl set-hostname center<br>hostnamectl set-hostname ceph-1<br>hostnamectl set-hostname ceph-2<br>hostnamectl set-hostname ceph-3<br><br><span class="hljs-comment"># 所有节点添加 hosts 映射</span><br><span class="hljs-built_in">cat</span> &gt;&gt;/etc/hosts &lt;&lt;<span class="hljs-string">EOF</span><br><span class="hljs-string">192.168.10.100 center</span><br><span class="hljs-string">192.168.10.11 ceph-1</span><br><span class="hljs-string">192.168.10.12 ceph-2</span><br><span class="hljs-string">192.168.10.13 ceph-3</span><br><span class="hljs-string">EOF</span><br></code></pre></td></tr></table></figure><h3 id="配置时间同步"><a href="#配置时间同步" class="headerlink" title="配置时间同步"></a>配置时间同步</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 安装 NTP</span><br>yum -y install ntp<br><br><span class="hljs-comment"># 编辑配置文件（ceph-1/2/3 节点）</span><br>vi /etc/ntp.conf<br>server center iburst     <span class="hljs-comment"># 添加的内容（将原来的注释掉）</span><br><br><span class="hljs-comment"># 启动服务</span><br>systemctl restart ntpd<br>systemctl <span class="hljs-built_in">enable</span> ntpd<br><br><span class="hljs-comment"># 验证时间同步</span><br>ntpdate -q &lt;主机IP&gt;<br></code></pre></td></tr></table></figure><h3 id="配置免密登录"><a href="#配置免密登录" class="headerlink" title="配置免密登录"></a>配置免密登录</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 在 center 节点执行</span><br>ssh-keygen -t rsa<br>ssh-copy-id ceph-1<br>ssh-copy-id ceph-2<br>ssh-copy-id ceph-3<br></code></pre></td></tr></table></figure><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="❌-OSD-启动失败"><a href="#❌-OSD-启动失败" class="headerlink" title="❌ OSD 启动失败"></a>❌ OSD 启动失败</h3><p><strong>原因</strong>：磁盘未正确格式化或权限问题。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 检查磁盘状态</span><br>ceph disk list<br><span class="hljs-comment"># 格式化磁盘</span><br>ceph-volume lvm create --data /dev/sdb<br></code></pre></td></tr></table></figure><h3 id="❌-集群健康状态异常"><a href="#❌-集群健康状态异常" class="headerlink" title="❌ 集群健康状态异常"></a>❌ 集群健康状态异常</h3><p><strong>原因</strong>：OSD 数量不足或网络问题。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看集群状态</span><br>ceph -s<br>ceph health detail<br></code></pre></td></tr></table></figure><hr><p><em>以上就是 Ceph 分布式存储的基础介绍。后续文章会继续深入讲解 Ceph 的高级配置。</em></p>]]></content>
    
    
    <summary type="html">Ceph 分布式存储系统详解，从版本演进到安装部署，覆盖对象、块和文件存储。</summary>
    
    
    
    <category term="存储" scheme="https://www.cloudetopia.top/categories/%E5%AD%98%E5%82%A8/"/>
    
    
    <category term="Ceph" scheme="https://www.cloudetopia.top/tags/Ceph/"/>
    
    <category term="分布式存储" scheme="https://www.cloudetopia.top/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E5%AD%98%E5%82%A8/"/>
    
  </entry>
  
  <entry>
    <title>OpenStack Train 搭建实战（2024版）</title>
    <link href="https://www.cloudetopia.top/2023/12/12/2023-12-13-OpenStack%E6%90%AD%E5%BB%BA/"/>
    <id>https://www.cloudetopia.top/2023/12/12/2023-12-13-OpenStack%E6%90%AD%E5%BB%BA/</id>
    <published>2023-12-12T16:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h1 id="OpenStack-Train-搭建实战（2024版）"><a href="#OpenStack-Train-搭建实战（2024版）" class="headerlink" title="OpenStack Train 搭建实战（2024版）"></a>OpenStack Train 搭建实战（2024版）</h1><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>OpenStack 是一个开源的云计算管理平台项目，由 NASA 和 Rackspace 于 2010 年联合发起。它可以帮助企业搭建私有云或公有云环境，管理计算、存储、网络等基础资源。本文基于 CentOS 7 + Train 版本，手把手带你搭建一个双节点的 OpenStack 环境。</p><blockquote><p>⚠️ OpenStack 配置文件中<strong>不能有中文</strong>（包括注释），否则会导致服务启动失败。</p></blockquote><h2 id="环境规划"><a href="#环境规划" class="headerlink" title="环境规划"></a>环境规划</h2><table><thead><tr><th>节点</th><th>IP 地址（内&#x2F;外）</th><th>规格</th></tr></thead><tbody><tr><td>controller</td><td>192.168.10.10 &#x2F; 192.168.11.10</td><td>4核4G，硬盘100G</td></tr><tr><td>compute</td><td>192.168.10.20 &#x2F; 192.168.11.20</td><td>4核4G，硬盘100G+100G</td></tr></tbody></table><p>双网卡配置：NAT（内网通信）+ 仅主机（外部访问）。两台主机默认密码 <code>000000</code>。</p><h2 id="基础环境配置"><a href="#基础环境配置" class="headerlink" title="基础环境配置"></a>基础环境配置</h2><h3 id="修改主机名"><a href="#修改主机名" class="headerlink" title="修改主机名"></a>修改主机名</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># controller 节点</span><br>hostnamectl set-hostname controller &amp;&amp; bash<br><br><span class="hljs-comment"># compute 节点</span><br>hostnamectl set-hostname compute &amp;&amp; bash<br></code></pre></td></tr></table></figure><h3 id="主机映射（双节点）"><a href="#主机映射（双节点）" class="headerlink" title="主机映射（双节点）"></a>主机映射（双节点）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">cat</span> &gt;&gt;/etc/hosts &lt;&lt;<span class="hljs-string">EOF</span><br><span class="hljs-string">192.168.10.10 controller</span><br><span class="hljs-string">192.168.10.20 compute</span><br><span class="hljs-string">EOF</span><br></code></pre></td></tr></table></figure><h3 id="关闭防火墙与-SELinux（双节点）"><a href="#关闭防火墙与-SELinux（双节点）" class="headerlink" title="关闭防火墙与 SELinux（双节点）"></a>关闭防火墙与 SELinux（双节点）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">systemctl stop firewalld &amp;&amp; setenforce 0<br>systemctl <span class="hljs-built_in">disable</span> firewalld<br>sed -i <span class="hljs-string">&#x27;s/enforcing/disabled/&#x27;</span> /etc/selinux/config<br></code></pre></td></tr></table></figure><h3 id="配置免密登录（双节点）"><a href="#配置免密登录（双节点）" class="headerlink" title="配置免密登录（双节点）"></a>配置免密登录（双节点）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">ssh-keygen -t rsa          <span class="hljs-comment"># 连按三次回车</span><br>ssh-copy-id controller     <span class="hljs-comment"># 第一次输入 yes，第二次输入密码</span><br>ssh-copy-id compute        <span class="hljs-comment"># 同上</span><br></code></pre></td></tr></table></figure><h3 id="配置阿里云镜像仓库（双节点）"><a href="#配置阿里云镜像仓库（双节点）" class="headerlink" title="配置阿里云镜像仓库（双节点）"></a>配置阿里云镜像仓库（双节点）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">rm</span> -rf /etc/yum.repos.d/*<br>curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo<br>yum makecache<br>yum -y upgrade<br>yum -y install epel-release<br></code></pre></td></tr></table></figure><h3 id="时间同步（Chrony）"><a href="#时间同步（Chrony）" class="headerlink" title="时间同步（Chrony）"></a>时间同步（Chrony）</h3><p>推荐安装 Chrony，比 NTP 更适合虚拟化环境。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum -y install chrony<br></code></pre></td></tr></table></figure><p><strong>controller 节点</strong> — 修改 <code>/etc/chrony.conf</code>：</p><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">server</span> ntp3.aliyun.com iburst<br><span class="hljs-attribute">allow</span> <span class="hljs-literal">all</span><br><span class="hljs-attribute">local</span> stratum <span class="hljs-number">10</span><br></code></pre></td></tr></table></figure><p><strong>compute 节点</strong> — 修改 <code>/etc/chrony.conf</code>：</p><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">server</span> controller iburst<br><span class="hljs-attribute">allow</span> <span class="hljs-literal">all</span><br><span class="hljs-attribute">local</span> stratum <span class="hljs-number">10</span><br></code></pre></td></tr></table></figure><p><strong>双节点启动服务：</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">systemctl restart chronyd<br>systemctl <span class="hljs-built_in">enable</span> chronyd<br>chronyc sources    <span class="hljs-comment"># 左侧显示 * 号表示同步成功</span><br></code></pre></td></tr></table></figure><h2 id="安装基础组件"><a href="#安装基础组件" class="headerlink" title="安装基础组件"></a>安装基础组件</h2><h3 id="部署-OpenStack-Train-仓库（双节点）"><a href="#部署-OpenStack-Train-仓库（双节点）" class="headerlink" title="部署 OpenStack Train 仓库（双节点）"></a>部署 OpenStack Train 仓库（双节点）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum -y install centos-release-openstack-train<br></code></pre></td></tr></table></figure><blockquote><p>❌ CentOS 7 已停止维护，部署后需要手动换源为阿里云镜像。</p></blockquote><p>修改以下四个 repo 文件，将 <code>baseurl</code> 改为 <code>mirrors.aliyun.com</code>，注释掉 <code>mirrorlist</code>：</p><table><thead><tr><th>文件</th><th>说明</th></tr></thead><tbody><tr><td><code>/etc/yum.repos.d/CentOS-OpenStack-train.repo</code></td><td>OpenStack 主仓库</td></tr><tr><td><code>/etc/yum.repos.d/CentOS-Ceph-Nautilus.repo</code></td><td>Ceph 存储仓库</td></tr><tr><td><code>/etc/yum.repos.d/CentOS-QEMU-EV.repo</code></td><td>QEMU 虚拟化仓库</td></tr><tr><td><code>/etc/yum.repos.d/CentOS-NFS-Ganesha-28.repo</code></td><td>NFS Ganesha 仓库</td></tr></tbody></table><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum clean all &amp;&amp; yum repolist<br></code></pre></td></tr></table></figure><h3 id="安装-OpenStack-客户端（双节点）"><a href="#安装-OpenStack-客户端（双节点）" class="headerlink" title="安装 OpenStack 客户端（双节点）"></a>安装 OpenStack 客户端（双节点）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum -y install python-openstackclient<br>yum -y install openstack-selinux<br></code></pre></td></tr></table></figure><h3 id="安装-MariaDB-数据库（controller）"><a href="#安装-MariaDB-数据库（controller）" class="headerlink" title="安装 MariaDB 数据库（controller）"></a>安装 MariaDB 数据库（controller）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum -y install mariadb mariadb-server python2-PyMySQL<br></code></pre></td></tr></table></figure><p>编辑 <code>/etc/my.cnf.d/openstack.cnf</code>：</p><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs ini"><span class="hljs-section">[mysqld]</span><br><span class="hljs-attr">bind-address</span> = <span class="hljs-number">192.168</span>.<span class="hljs-number">10.10</span><br><span class="hljs-attr">default-storage-engine</span> = innodb<br><span class="hljs-attr">innodb_file_per_table</span> = <span class="hljs-literal">on</span><br><span class="hljs-attr">max_connections</span> = <span class="hljs-number">4096</span><br><span class="hljs-attr">collation-server</span> = utf8_general_ci<br><span class="hljs-attr">character-set-server</span> = utf8<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">systemctl start mariadb.service<br>systemctl <span class="hljs-built_in">enable</span> mariadb.service<br>mysql_secure_installation    <span class="hljs-comment"># 设置 root 密码为 000000</span><br></code></pre></td></tr></table></figure><h3 id="安装-RabbitMQ-消息队列（controller）"><a href="#安装-RabbitMQ-消息队列（controller）" class="headerlink" title="安装 RabbitMQ 消息队列（controller）"></a>安装 RabbitMQ 消息队列（controller）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum -y install rabbitmq-server<br>systemctl start rabbitmq-server.service<br>systemctl <span class="hljs-built_in">enable</span> rabbitmq-server.service<br><br><span class="hljs-comment"># 创建 OpenStack 用户</span><br>rabbitmqctl -n rabbit@controller add_user openstack openstack123<br>rabbitmqctl -n rabbit@controller set_permissions openstack <span class="hljs-string">&quot;.*&quot;</span> <span class="hljs-string">&quot;.*&quot;</span> <span class="hljs-string">&quot;.*&quot;</span><br></code></pre></td></tr></table></figure><h3 id="安装-Memcached-缓存（controller）"><a href="#安装-Memcached-缓存（controller）" class="headerlink" title="安装 Memcached 缓存（controller）"></a>安装 Memcached 缓存（controller）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install memcached python-memcached -y<br></code></pre></td></tr></table></figure><p>修改 <code>/etc/sysconfig/memcached</code>，将 <code>OPTIONS</code> 改为：</p><figure class="highlight abnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs abnf"><span class="hljs-attribute">OPTIONS</span><span class="hljs-operator">=</span><span class="hljs-string">&quot;-l 127.0.0.1,::1,controller&quot;</span><br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">systemctl start memcached.service<br>systemctl <span class="hljs-built_in">enable</span> memcached.service<br></code></pre></td></tr></table></figure><h3 id="安装-etcd（controller，可选）"><a href="#安装-etcd（controller，可选）" class="headerlink" title="安装 etcd（controller，可选）"></a>安装 etcd（controller，可选）</h3><p>从 Stein 版本开始引入，用于分布式键值存储。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum -y install etcd<br></code></pre></td></tr></table></figure><p>编辑 <code>/etc/etcd/etcd.conf</code>，根据 <code>[Member]</code> 和 <code>[Clustering]</code> 段修改对应 IP 地址，然后：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">systemctl start etcd<br>systemctl <span class="hljs-built_in">enable</span> etcd<br>etcdctl cluster-health    <span class="hljs-comment"># 输出 healthy 即成功</span><br></code></pre></td></tr></table></figure><h2 id="Keystone-身份认证服务"><a href="#Keystone-身份认证服务" class="headerlink" title="Keystone 身份认证服务"></a>Keystone 身份认证服务</h2><h3 id="创建数据库"><a href="#创建数据库" class="headerlink" title="创建数据库"></a>创建数据库</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">mysql -uroot -p000000<br></code></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">CREATE</span> DATABASE keystone;<br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> keystone.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;keystone&#x27;</span>@<span class="hljs-string">&#x27;localhost&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;keystone123&#x27;</span>;<br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> keystone.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;keystone&#x27;</span>@<span class="hljs-string">&#x27;%&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;keystone123&#x27;</span>;<br></code></pre></td></tr></table></figure><h3 id="安装配置"><a href="#安装配置" class="headerlink" title="安装配置"></a>安装配置</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install openstack-keystone httpd mod_wsgi -y<br></code></pre></td></tr></table></figure><p>编辑 <code>/etc/keystone/keystone.conf</code>：</p><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs ini"><span class="hljs-section">[database]</span><br><span class="hljs-attr">connection</span> = mysql+pymysql://keystone:keystone123@controller/keystone<br><br><span class="hljs-section">[token]</span><br><span class="hljs-attr">provider</span> = fernet<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 同步数据库</span><br>su -s /bin/sh -c <span class="hljs-string">&quot;keystone-manage db_sync&quot;</span> keystone<br><br><span class="hljs-comment"># 初始化 Fernet 密钥</span><br>keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone<br>keystone-manage credential_setup --keystone-user keystone --keystone-group keystone<br><br><span class="hljs-comment"># 初始化管理员用户</span><br>keystone-manage bootstrap --bootstrap-password admin \<br>  --bootstrap-admin-url http://controller:5000/v3/ \<br>  --bootstrap-internal-url http://controller:5000/v3/ \<br>  --bootstrap-public-url http://controller:5000/v3/ \<br>  --bootstrap-region-id RegionOne<br></code></pre></td></tr></table></figure><h3 id="配置-HTTP-服务器"><a href="#配置-HTTP-服务器" class="headerlink" title="配置 HTTP 服务器"></a>配置 HTTP 服务器</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs bash">vi /etc/httpd/conf/httpd.conf<br><span class="hljs-comment"># 添加：ServerName controller</span><br><br><span class="hljs-built_in">ln</span> -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/<br>systemctl start httpd.service<br>systemctl <span class="hljs-built_in">enable</span> httpd.service<br></code></pre></td></tr></table></figure><h3 id="创建环境变量脚本"><a href="#创建环境变量脚本" class="headerlink" title="创建环境变量脚本"></a>创建环境变量脚本</h3><p>创建 <code>admin.sh</code>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-meta">#!/bin/bash</span><br><span class="hljs-built_in">export</span> OS_USERNAME=admin<br><span class="hljs-built_in">export</span> OS_PASSWORD=admin<br><span class="hljs-built_in">export</span> OS_PROJECT_NAME=admin<br><span class="hljs-built_in">export</span> OS_USER_DOMAIN_NAME=Default<br><span class="hljs-built_in">export</span> OS_PROJECT_DOMAIN_NAME=Default<br><span class="hljs-built_in">export</span> OS_AUTH_URL=http://controller:5000/v3<br><span class="hljs-built_in">export</span> OS_IDENTITY_API_VERSION=3<br><span class="hljs-built_in">export</span> OS_IMAGE_API_VERSION=2<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">source</span> admin.sh<br>openstack endpoint list    <span class="hljs-comment"># 验证</span><br></code></pre></td></tr></table></figure><h3 id="创建域、项目、用户和角色"><a href="#创建域、项目、用户和角色" class="headerlink" title="创建域、项目、用户和角色"></a>创建域、项目、用户和角色</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs bash">openstack domain create --description <span class="hljs-string">&quot;An Example Domain&quot;</span> example<br>openstack project create --domain default --description <span class="hljs-string">&quot;Service Project&quot;</span> service<br>openstack project create --domain default --description <span class="hljs-string">&quot;Demo Project&quot;</span> myproject<br>openstack user create --domain default --password-prompt myuser<br>openstack role create myrole<br>openstack role add --project myproject --user myuser myrole<br></code></pre></td></tr></table></figure><h2 id="Glance-镜像服务"><a href="#Glance-镜像服务" class="headerlink" title="Glance 镜像服务"></a>Glance 镜像服务</h2><h3 id="创建数据库和用户"><a href="#创建数据库和用户" class="headerlink" title="创建数据库和用户"></a>创建数据库和用户</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">CREATE</span> DATABASE glance;<br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> glance.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;glance&#x27;</span>@<span class="hljs-string">&#x27;localhost&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;glance123&#x27;</span>;<br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> glance.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;glance&#x27;</span>@<span class="hljs-string">&#x27;%&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;glance123&#x27;</span>;<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">source</span> /etc/openstack/keystone/admin-openrc.sh<br>openstack user create --domain default --password-prompt glance<br>openstack role add --project service --user glance admin<br>openstack service create --name glance --description <span class="hljs-string">&#x27;Openstack Image&#x27;</span> image<br><br><span class="hljs-comment"># 创建 API 端点</span><br>openstack endpoint create --region RegionOne image public http://controller:9292<br>openstack endpoint create --region RegionOne image internal http://controller:9292<br>openstack endpoint create --region RegionOne image admin http://controller:9292<br></code></pre></td></tr></table></figure><h3 id="安装配置-1"><a href="#安装配置-1" class="headerlink" title="安装配置"></a>安装配置</h3><p>编辑 <code>/etc/glance/glance-api.conf</code>，配置数据库连接、Keystone 认证和存储后端：</p><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs ini"><span class="hljs-section">[database]</span><br><span class="hljs-attr">connection</span> = mysql+pymysql://glance:glance123@controller/glance<br><br><span class="hljs-section">[keystone_authtoken]</span><br><span class="hljs-attr">www_authenticate_uri</span> = http://controller:<span class="hljs-number">5000</span><br><span class="hljs-attr">auth_url</span> = http://controller:<span class="hljs-number">5000</span><br><span class="hljs-attr">memcached_servers</span> = controller:<span class="hljs-number">11211</span><br><span class="hljs-attr">auth_type</span> = password<br><span class="hljs-attr">project_domain_name</span> = Default<br><span class="hljs-attr">user_domain_name</span> = Default<br><span class="hljs-attr">project_name</span> = service<br><span class="hljs-attr">username</span> = glance<br><span class="hljs-attr">password</span> = glance<br><br><span class="hljs-section">[glance_store]</span><br><span class="hljs-attr">stores</span> = file,http<br><span class="hljs-attr">default_store</span> = file<br><span class="hljs-attr">filesystem_store_datadir</span> = /var/lib/glance/images/<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">su -s /bin/sh -c <span class="hljs-string">&quot;glance-manage db_sync&quot;</span> glance<br>systemctl <span class="hljs-built_in">enable</span> openstack-glance-api.service<br>systemctl start openstack-glance-api.service<br></code></pre></td></tr></table></figure><h2 id="Placement-服务"><a href="#Placement-服务" class="headerlink" title="Placement 服务"></a>Placement 服务</h2><h3 id="创建数据库和用户-1"><a href="#创建数据库和用户-1" class="headerlink" title="创建数据库和用户"></a>创建数据库和用户</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">CREATE</span> DATABASE placement;<br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> placement.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;placement&#x27;</span>@<span class="hljs-string">&#x27;localhost&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;placement123&#x27;</span>;<br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> placement.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;placement&#x27;</span>@<span class="hljs-string">&#x27;%&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;placement123&#x27;</span>;<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash">openstack user create --domain default --password-prompt placement<br>openstack role add --project service --user placement admin<br>openstack service create --name placement --description <span class="hljs-string">&#x27;placement API&#x27;</span> placement<br><br>openstack endpoint create --region RegionOne placement public http://controller:8778<br>openstack endpoint create --region RegionOne placement internal http://controller:8778<br>openstack endpoint create --region RegionOne placement admin http://controller:8778<br></code></pre></td></tr></table></figure><h3 id="安装配置-2"><a href="#安装配置-2" class="headerlink" title="安装配置"></a>安装配置</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum -y install openstack-placement-api<br></code></pre></td></tr></table></figure><p>编辑 <code>/etc/placement/placement.conf</code>，配置数据库和 Keystone 认证后：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">su -s /bin/sh -c <span class="hljs-string">&quot;placement-manage db sync&quot;</span> placement<br>placement-status upgrade check    <span class="hljs-comment"># 验证</span><br></code></pre></td></tr></table></figure><h2 id="Nova-计算服务"><a href="#Nova-计算服务" class="headerlink" title="Nova 计算服务"></a>Nova 计算服务</h2><h3 id="创建数据库和用户-2"><a href="#创建数据库和用户-2" class="headerlink" title="创建数据库和用户"></a>创建数据库和用户</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">CREATE</span> DATABASE nova_api;<br><span class="hljs-keyword">CREATE</span> DATABASE nova;<br><span class="hljs-keyword">CREATE</span> DATABASE nova_cell0;<br><br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> nova_api.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;nova&#x27;</span>@<span class="hljs-string">&#x27;%&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;nova123&#x27;</span>;<br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> nova.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;nova&#x27;</span>@<span class="hljs-string">&#x27;%&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;nova123&#x27;</span>;<br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> nova_cell0.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;nova&#x27;</span>@<span class="hljs-string">&#x27;%&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;nova123&#x27;</span>;<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash">openstack user create --domain default --password-prompt nova<br>openstack role add --project service --user nova admin<br>openstack service create --name nova --description <span class="hljs-string">&quot;Openstack Compute&quot;</span> compute<br><br>openstack endpoint create --region RegionOne compute public http://controller:8774/v2.1<br>openstack endpoint create --region RegionOne compute internal http://controller:8774/v2.1<br>openstack endpoint create --region RegionOne compute admin http://controller:8774/v2.1<br></code></pre></td></tr></table></figure><h3 id="controller-节点配置"><a href="#controller-节点配置" class="headerlink" title="controller 节点配置"></a>controller 节点配置</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install openstack-nova-api openstack-nova-conductor openstack-nova-novncproxy openstack-nova-scheduler -y<br></code></pre></td></tr></table></figure><p>编辑 <code>/etc/nova/nova.conf</code> 关键配置：</p><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs ini"><span class="hljs-section">[DEFAULT]</span><br><span class="hljs-attr">enabled_apis</span> = osapi_compute,metadata<br><span class="hljs-attr">transport_url</span> = rabbit://openstack:openstack123@controller:<span class="hljs-number">5672</span>/<br><span class="hljs-attr">use_neutron</span> = <span class="hljs-literal">true</span><br><span class="hljs-attr">firewall_driver</span> = nova.virt.firewall.NoopFirewallDriver<br><span class="hljs-attr">my_ip</span> = <span class="hljs-number">192.168</span>.<span class="hljs-number">10.10</span><br><br><span class="hljs-section">[api]</span><br><span class="hljs-attr">auth_strategy</span> = keystone<br><br><span class="hljs-section">[vnc]</span><br><span class="hljs-attr">enabled</span> = <span class="hljs-literal">true</span><br><span class="hljs-attr">server_listen</span> = <span class="hljs-variable">$my_ip</span><br><span class="hljs-attr">server_proxyclient_address</span> = <span class="hljs-variable">$my_ip</span><br><br><span class="hljs-section">[glance]</span><br><span class="hljs-attr">api_servers</span> = http://controller:<span class="hljs-number">9292</span><br><br><span class="hljs-section">[placement]</span><br><span class="hljs-attr">auth_url</span> = http://controller:<span class="hljs-number">5000</span>/v3<br><span class="hljs-attr">username</span> = placement<br><span class="hljs-attr">password</span> = placement<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 同步数据库</span><br>su -s /bin/sh -c <span class="hljs-string">&quot;nova-manage api_db sync&quot;</span> nova<br>su -s /bin/sh -c <span class="hljs-string">&quot;nova-manage cell_v2 map_cell0&quot;</span> nova<br>su -s /bin/sh -c <span class="hljs-string">&quot;nova-manage cell_v2 create_cell --name=cell1 --verbose&quot;</span> nova<br>su -s /bin/sh -c <span class="hljs-string">&quot;nova-manage db sync&quot;</span> nova<br><br><span class="hljs-comment"># 启动服务</span><br>systemctl <span class="hljs-built_in">enable</span> openstack-nova-api --now<br>systemctl <span class="hljs-built_in">enable</span> openstack-nova-scheduler --now<br>systemctl <span class="hljs-built_in">enable</span> openstack-nova-conductor --now<br>systemctl <span class="hljs-built_in">enable</span> openstack-nova-novncproxy --now<br></code></pre></td></tr></table></figure><h3 id="compute-节点配置"><a href="#compute-节点配置" class="headerlink" title="compute 节点配置"></a>compute 节点配置</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum -y install openstack-nova-compute<br></code></pre></td></tr></table></figure><p>编辑 <code>/etc/nova/nova.conf</code>，主要修改 <code>my_ip = 192.168.10.20</code>，VNC 监听改为 <code>0.0.0.0</code>，并添加 <code>novncproxy_base_url</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 检查硬件加速支持</span><br>egrep -c <span class="hljs-string">&#x27;(vmx|svm)&#x27;</span> /proc/cpuinfo<br><span class="hljs-comment"># 返回 0 则需设置 virt_type = qemu</span><br><br>systemctl <span class="hljs-built_in">enable</span> libvirtd --now<br>systemctl <span class="hljs-built_in">enable</span> openstack-nova-compute --now<br></code></pre></td></tr></table></figure><p><strong>controller 节点验证：</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">openstack compute service list --service nova-compute<br>su -s /bin/sh -c <span class="hljs-string">&quot;nova-manage cell_v2 discover_hosts --verbose&quot;</span> nova<br></code></pre></td></tr></table></figure><h2 id="Neutron-网络服务"><a href="#Neutron-网络服务" class="headerlink" title="Neutron 网络服务"></a>Neutron 网络服务</h2><h3 id="创建数据库和用户-3"><a href="#创建数据库和用户-3" class="headerlink" title="创建数据库和用户"></a>创建数据库和用户</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">CREATE</span> DATABASE neutron;<br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> neutron.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;neutron&#x27;</span>@<span class="hljs-string">&#x27;localhost&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;neutron123&#x27;</span>;<br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> neutron.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;neutron&#x27;</span>@<span class="hljs-string">&#x27;%&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;neutron123&#x27;</span>;<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash">openstack user create --domain default --password-prompt neutron<br>openstack role add --project service --user neutron admin<br>openstack service create --name neutron --description <span class="hljs-string">&quot;Openstack Networking&quot;</span> network<br><br>openstack endpoint create --region RegionOne network public http://controller:9696<br>openstack endpoint create --region RegionOne network internal http://controller:9696<br>openstack endpoint create --region RegionOne network admin http://controller:9696<br></code></pre></td></tr></table></figure><h3 id="controller-节点配置-1"><a href="#controller-节点配置-1" class="headerlink" title="controller 节点配置"></a>controller 节点配置</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install openstack-neutron openstack-neutron-ml2 openstack-neutron-linuxbridge ebtables -y<br></code></pre></td></tr></table></figure><p>核心配置文件包括：</p><table><thead><tr><th>配置文件</th><th>关键配置</th></tr></thead><tbody><tr><td><code>/etc/neutron/neutron.conf</code></td><td>数据库、RabbitMQ、Keystone、Nova 联动</td></tr><tr><td><code>/etc/neutron/plugins/ml2/ml2_conf.ini</code></td><td>ML2 插件：flat&#x2F;vlan 网络类型</td></tr><tr><td><code>/etc/neutron/plugins/ml2/linuxbridge_agent.ini</code></td><td>Linux Bridge 映射物理网卡</td></tr><tr><td><code>/etc/neutron/dhcp_agent.ini</code></td><td>DHCP 驱动配置</td></tr><tr><td><code>/etc/neutron/metadata_agent.ini</code></td><td>元数据代理配置</td></tr></tbody></table><blockquote><p>⚠️ 需要配置内核参数 <code>net.bridge.bridge-nf-call-iptables = 1</code></p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 创建软连接并同步数据库</span><br><span class="hljs-built_in">ln</span> -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini<br>su -s /bin/sh -c <span class="hljs-string">&quot;neutron-db-manage --config-file /etc/neutron/neutron.conf \</span><br><span class="hljs-string">  --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head&quot;</span> neutron<br><br>systemctl restart neutron-server neutron-linuxbridge-agent neutron-dhcp-agent neutron-metadata-agent<br>systemctl <span class="hljs-built_in">enable</span> neutron-server neutron-linuxbridge-agent neutron-dhcp-agent neutron-metadata-agent<br></code></pre></td></tr></table></figure><h3 id="compute-节点配置-1"><a href="#compute-节点配置-1" class="headerlink" title="compute 节点配置"></a>compute 节点配置</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install openstack-neutron-linuxbridge ebtables ipset -y<br></code></pre></td></tr></table></figure><p>配置 <code>neutron.conf</code>、<code>linuxbridge_agent.ini</code> 和 <code>nova.conf</code> 中的 neutron 段后：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">systemctl restart openstack-nova-compute<br>systemctl <span class="hljs-built_in">enable</span> neutron-linuxbridge-agent --now<br></code></pre></td></tr></table></figure><h2 id="Dashboard-仪表盘"><a href="#Dashboard-仪表盘" class="headerlink" title="Dashboard 仪表盘"></a>Dashboard 仪表盘</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install openstack-dashboard -y<br></code></pre></td></tr></table></figure><p>编辑 <code>/etc/openstack-dashboard/local_settings</code>，关键配置：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs python">OPENSTACK_HOST = <span class="hljs-string">&quot;controller&quot;</span><br>ALLOWED_HOSTS = [<span class="hljs-string">&#x27;*&#x27;</span>]<br>OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = <span class="hljs-literal">True</span><br>OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = <span class="hljs-string">&#x27;Default&#x27;</span><br>OPENSTACK_KEYSTONE_DEFAULT_ROLE = <span class="hljs-string">&#x27;user&#x27;</span><br>TIME_ZONE = <span class="hljs-string">&quot;Asia/Shanghai&quot;</span><br>WEBROOT = <span class="hljs-string">&#x27;/dashboard&#x27;</span><br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">systemctl restart httpd memcached<br><span class="hljs-comment"># 访问 http://192.168.10.10/dashboard</span><br><span class="hljs-comment"># 域: default | 用户名: admin | 密码: admin</span><br></code></pre></td></tr></table></figure><h2 id="Cinder-块存储服务"><a href="#Cinder-块存储服务" class="headerlink" title="Cinder 块存储服务"></a>Cinder 块存储服务</h2><h3 id="controller-节点"><a href="#controller-节点" class="headerlink" title="controller 节点"></a>controller 节点</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">CREATE</span> DATABASE cinder;<br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> cinder.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;cinder&#x27;</span>@<span class="hljs-string">&#x27;%&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;cinder123&#x27;</span>;<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash">openstack user create --domain default --password-prompt cinder<br>openstack role add --project service --user cinder admin<br>openstack service create --name cinderv2 --description <span class="hljs-string">&quot;OpenStack Block Storage&quot;</span> volumev2<br>openstack service create --name cinderv3 --description <span class="hljs-string">&quot;OpenStack Block Storage&quot;</span> volumev3<br><br><span class="hljs-comment"># 创建 v2/v3 的 public/internal/admin 端点（端口 8776）</span><br>yum install openstack-cinder -y<br></code></pre></td></tr></table></figure><p>编辑 <code>/etc/cinder/cinder.conf</code> 配置数据库、RabbitMQ 和 Keystone 后：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> su -s /bin/sh -c <span class="hljs-string">&quot;cinder-manage db sync&quot;</span> cinder<br>systemctl restart openstack-nova-api<br>systemctl start openstack-cinder-api openstack-cinder-scheduler<br>systemctl <span class="hljs-built_in">enable</span> openstack-cinder-api openstack-cinder-scheduler<br></code></pre></td></tr></table></figure><h3 id="compute-节点"><a href="#compute-节点" class="headerlink" title="compute 节点"></a>compute 节点</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install lvm2 device-mapper-persistent-data -y<br>systemctl <span class="hljs-built_in">enable</span> lvm2-lvmetad.service &amp;&amp; systemctl start lvm2-lvmetad.service<br><br><span class="hljs-comment"># 创建物理卷和卷组</span><br>pvcreate /dev/sdb<br>vgcreate cinder-volumes /dev/sdb<br></code></pre></td></tr></table></figure><p>编辑 <code>/etc/lvm/lvm.conf</code> 添加过滤器：</p><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ini"><span class="hljs-attr">filter</span> = [ <span class="hljs-string">&quot;a/sda/&quot;</span>, <span class="hljs-string">&quot;a/sdb/&quot;</span>, <span class="hljs-string">&quot;r/.*/&quot;</span>]<br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install openstack-cinder targetcli python-keystone -y<br></code></pre></td></tr></table></figure><p>配置 <code>/etc/cinder/cinder.conf</code>，添加 <code>[lvm]</code> 段指定卷驱动后：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">systemctl start openstack-cinder-volume.service target.service<br>systemctl <span class="hljs-built_in">enable</span> openstack-cinder-volume.service target.service<br></code></pre></td></tr></table></figure><h2 id="Swift-对象存储服务"><a href="#Swift-对象存储服务" class="headerlink" title="Swift 对象存储服务"></a>Swift 对象存储服务</h2><h3 id="创建服务凭据"><a href="#创建服务凭据" class="headerlink" title="创建服务凭据"></a>创建服务凭据</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">openstack user create --domain default --password-prompt swift<br>openstack role add --project service --user swift admin<br>openstack service create --name swift --description <span class="hljs-string">&quot;OpenStack Object Storage&quot;</span> object-store<br><br><span class="hljs-comment"># 创建 public/internal/admin 端点（端口 8080）</span><br></code></pre></td></tr></table></figure><h3 id="controller-节点-1"><a href="#controller-节点-1" class="headerlink" title="controller 节点"></a>controller 节点</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install openstack-swift-proxy python-swiftclient python-keystoneclient \<br>  python-keystonemiddleware memcached -y<br><br>curl -o /etc/swift/proxy-server.conf \<br>  https://opendev.org/openstack/swift/raw/branch/master/etc/proxy-server.conf-sample<br></code></pre></td></tr></table></figure><p>编辑 <code>proxy-server.conf</code> 配置 Keystone 认证和缓存后：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">systemctl <span class="hljs-built_in">enable</span> openstack-swift-proxy.service memcached.service<br>systemctl start openstack-swift-proxy.service memcached.service<br></code></pre></td></tr></table></figure><h3 id="compute-节点-1"><a href="#compute-节点-1" class="headerlink" title="compute 节点"></a>compute 节点</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install xfsprogs rsync -y<br><br><span class="hljs-comment"># 格式化并挂载磁盘</span><br>mkfs.xfs /dev/sdb &amp;&amp; mkfs.xfs /dev/sdc<br><span class="hljs-built_in">mkdir</span> -p /srv/node/sdb /srv/node/sdc<br><span class="hljs-comment"># 编辑 /etc/fstab 添加挂载项后 mount</span><br><br><span class="hljs-comment"># 配置 rsync 并启动</span><br>systemctl <span class="hljs-built_in">enable</span> rsyncd.service &amp;&amp; systemctl start rsyncd.service<br><br><span class="hljs-comment"># 安装 Swift 存储组件</span><br>yum install openstack-swift-account openstack-swift-container openstack-swift-object -y<br></code></pre></td></tr></table></figure><h3 id="创建和分发-Ring（controller）"><a href="#创建和分发-Ring（controller）" class="headerlink" title="创建和分发 Ring（controller）"></a>创建和分发 Ring（controller）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">cd</span> /etc/swift/<br><br><span class="hljs-comment"># Account Ring</span><br>swift-ring-builder account.builder create 10 3 1<br>swift-ring-builder account.builder add --region 1 --zone 1 --ip 192.168.10.20 --port 6202 --device sdb --weight 100<br>swift-ring-builder account.builder add --region 1 --zone 1 --ip 192.168.10.20 --port 6202 --device sdc --weight 100<br>swift-ring-builder account.builder rebalance<br><br><span class="hljs-comment"># Container Ring</span><br>swift-ring-builder container.builder create 10 3 1<br>swift-ring-builder container.builder add --region 1 --zone 1 --ip 192.168.10.20 --port 6201 --device sdb --weight 100<br>swift-ring-builder container.builder add --region 1 --zone 1 --ip 192.168.10.20 --port 6201 --device sdc --weight 100<br>swift-ring-builder container.builder rebalance<br><br><span class="hljs-comment"># Object Ring</span><br>swift-ring-builder object.builder create 10 3 1<br>swift-ring-builder object.builder add --region 1 --zone 1 --ip 192.168.10.20 --port 6200 --device sdb --weight 100<br>swift-ring-builder object.builder add --region 1 --zone 1 --ip 192.168.10.20 --port 6200 --device sdc --weight 100<br>swift-ring-builder object.builder rebalance<br><br><span class="hljs-comment"># 分发到 compute 节点</span><br>scp swift.conf compute:/etc/swift/swift.conf<br><span class="hljs-built_in">chown</span> -R root:swift /etc/swift<br></code></pre></td></tr></table></figure><h2 id="常见问题与踩坑记录"><a href="#常见问题与踩坑记录" class="headerlink" title="常见问题与踩坑记录"></a>常见问题与踩坑记录</h2><p>❌ <strong>CentOS 7 源失效</strong>：部署 OpenStack 仓库后必须手动换源，否则 yum 安装会报 404。</p><p>❌ <strong>配置文件中混入中文</strong>：OpenStack 所有服务的配置文件（包括注释）都不能有中文，否则服务启动直接报错。</p><p>❌ <strong>Nova 计算节点无法发现</strong>：需要在 controller 节点执行 <code>nova-manage cell_v2 discover_hosts</code>，或在 <code>nova.conf</code> 中设置 <code>discover_hosts_in_cells_interval = 300</code> 自动发现。</p><p>❌ <strong>Neutron 网络不通</strong>：检查内核参数 <code>net.bridge.bridge-nf-call-iptables</code> 是否设置为 1，以及 Linux Bridge 的物理网卡映射是否正确。</p><p>❌ <strong>Swift Ring 不平衡</strong>：每次添加或删除存储节点后都需要执行 <code>rebalance</code>，否则数据分布不均匀。</p><p>❌ <strong>Dashboard 无法访问</strong>：确认 <code>WEBROOT = &#39;/dashboard&#39;</code>，访问地址为 <code>http://controller/dashboard</code>，而不是根路径。</p><h2 id="服务安装顺序总结"><a href="#服务安装顺序总结" class="headerlink" title="服务安装顺序总结"></a>服务安装顺序总结</h2><p>整个 OpenStack 的搭建按照以下顺序进行：基础环境 → Keystone（认证）→ Glance（镜像）→ Placement（资源调度）→ Nova（计算）→ Neutron（网络）→ Dashboard（仪表盘）→ Cinder（块存储）→ Swift（对象存储）。每一步都需要先创建数据库和用户，再安装配置组件，最后启动服务并验证。</p><p>搭建完成后，可以通过 Dashboard 或 CLI 命令创建实例、分配浮动 IP、挂载云硬盘等操作，真正体验 OpenStack 的云计算能力。</p>]]></content>
    
    
    <summary type="html">OpenStack Train 版本双节点搭建实战，基于 CentOS 7 手把手部署私有云环境。</summary>
    
    
    
    <category term="云计算" scheme="https://www.cloudetopia.top/categories/%E4%BA%91%E8%AE%A1%E7%AE%97/"/>
    
    
    <category term="OpenStack" scheme="https://www.cloudetopia.top/tags/OpenStack/"/>
    
    <category term="运维" scheme="https://www.cloudetopia.top/tags/%E8%BF%90%E7%BB%B4/"/>
    
  </entry>
  
  <entry>
    <title>Kubernetes 工作流程图解</title>
    <link href="https://www.cloudetopia.top/2023/12/12/2023-12-12-Kubernetes%E6%B5%81%E7%A8%8B%E5%9B%BE/"/>
    <id>https://www.cloudetopia.top/2023/12/12/2023-12-12-Kubernetes%E6%B5%81%E7%A8%8B%E5%9B%BE/</id>
    <published>2023-12-12T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>本文以流程图形式展示 Kubernetes 的核心工作流程，涵盖 Pod 调度、服务发现、网络通信等关键环节。</p><blockquote><p>注：原文中的图片已移除，后续将补充文字说明。</p></blockquote><h2 id="Pod-调度流程"><a href="#Pod-调度流程" class="headerlink" title="Pod 调度流程"></a>Pod 调度流程</h2><figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs arduino">用户提交 Pod 请求<br>       ↓<br>API <span class="hljs-built_in">Server</span> 接收请求<br>       ↓<br><span class="hljs-built_in">Scheduler</span> 根据策略选择节点<br>       ↓<br>Controller Manager 通知 Kubelet<br>       ↓<br>Kubelet 启动容器<br>       ↓<br>Pod 运行中<br></code></pre></td></tr></table></figure><h2 id="服务发现流程"><a href="#服务发现流程" class="headerlink" title="服务发现流程"></a>服务发现流程</h2><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs routeros">Pod 启动并注册到 Endpoints<br>       ↓<span class="hljs-built_in"></span><br><span class="hljs-built_in">Service </span>通过 Selector 匹配 Pod<br>       ↓<br>kube-proxy 配置 iptables/IPVS 规则<br>       ↓<br>客户端访问<span class="hljs-built_in"> Service </span>ClusterIP<br>       ↓<br>流量转发到后端 Pod<br></code></pre></td></tr></table></figure><h2 id="网络通信模型"><a href="#网络通信模型" class="headerlink" title="网络通信模型"></a>网络通信模型</h2><p>K8s 网络模型遵循以下原则：</p><ul><li>每个 Pod 都有独立的 IP 地址</li><li>Pod 之间可以直接通信</li><li>节点上的代理（kube-proxy）负责服务发现和负载均衡</li></ul><hr><p><em>后续将补充更详细的流程图和说明。</em></p>]]></content>
    
    
    <summary type="html">以流程图形式展示 Kubernetes 核心工作流程，涵盖 Pod 调度、服务发现与网络通信。</summary>
    
    
    
    <category term="云原生" scheme="https://www.cloudetopia.top/categories/%E4%BA%91%E5%8E%9F%E7%94%9F/"/>
    
    
    <category term="Kubernetes" scheme="https://www.cloudetopia.top/tags/Kubernetes/"/>
    
    <category term="架构" scheme="https://www.cloudetopia.top/tags/%E6%9E%B6%E6%9E%84/"/>
    
  </entry>
  
  <entry>
    <title>Kubernetes 核心概念详解</title>
    <link href="https://www.cloudetopia.top/2023/12/12/2023-12-12-Kubernetes%E8%AF%A6%E8%A7%A3/"/>
    <id>https://www.cloudetopia.top/2023/12/12/2023-12-12-Kubernetes%E8%AF%A6%E8%A7%A3/</id>
    <published>2023-12-12T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Kubernetes（K8s）是容器编排的事实标准。这篇文章从 Pod 开始，逐步讲解 K8s 的核心概念和资源对象。</p><h2 id="Pod"><a href="#Pod" class="headerlink" title="Pod"></a>Pod</h2><h3 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h3><p>Pod 是 K8s 中最小的部署单元，是一组（一个或多个）容器的集合。Pod 就像是豌豆荚，而容器就像是豌豆荚中的豌豆。这些容器共享存储、网络等资源。</p><h3 id="Pod-资源清单"><a href="#Pod-资源清单" class="headerlink" title="Pod 资源清单"></a>Pod 资源清单</h3><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>          <span class="hljs-comment"># API 版本</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Pod</span>               <span class="hljs-comment"># 资源对象类型</span><br><span class="hljs-attr">metadata:</span>               <span class="hljs-comment"># Pod 元数据</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-pod</span>       <span class="hljs-comment"># Pod 名称</span><br>  <span class="hljs-attr">labels:</span>               <span class="hljs-comment"># 定义标签</span><br>    <span class="hljs-attr">tybe:</span> <span class="hljs-string">app</span><br>    <span class="hljs-attr">test:</span> <span class="hljs-number">1.0</span><span class="hljs-number">.0</span><br>  <span class="hljs-attr">namespace:</span> <span class="hljs-string">&#x27;default&#x27;</span>  <span class="hljs-comment"># 命名空间</span><br><span class="hljs-attr">spec:</span>                   <span class="hljs-comment"># Pod 规格</span><br>  <span class="hljs-attr">containers:</span>           <span class="hljs-comment"># 容器列表</span><br>  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx</span><br>    <span class="hljs-attr">image:</span> <span class="hljs-string">&#x27;nginx:1.20.2&#x27;</span><br>    <span class="hljs-attr">imagePullPolicy:</span> <span class="hljs-string">IfNotPresent</span><br>    <span class="hljs-attr">startupProbe:</span>       <span class="hljs-comment"># 启动探针</span><br>      <span class="hljs-attr">exec:</span><br>        <span class="hljs-attr">command:</span><br>        <span class="hljs-bullet">-</span> <span class="hljs-string">/bin/sh</span><br>        <span class="hljs-bullet">-</span> <span class="hljs-string">-c</span><br>        <span class="hljs-bullet">-</span> <span class="hljs-string">&quot;sleep 3; echo success &gt; /inited&quot;</span><br>      <span class="hljs-attr">initialDelaySeconds:</span> <span class="hljs-number">1</span><br>      <span class="hljs-attr">periodSeconds:</span> <span class="hljs-number">5</span><br>      <span class="hljs-attr">failureThreshold:</span> <span class="hljs-number">3</span><br>      <span class="hljs-attr">successThreshold:</span> <span class="hljs-number">1</span><br>      <span class="hljs-attr">timeoutSeconds:</span> <span class="hljs-number">5</span><br>    <span class="hljs-attr">readinessProbe:</span>     <span class="hljs-comment"># 就绪探针</span><br>      <span class="hljs-attr">httpGet:</span><br>        <span class="hljs-attr">path:</span> <span class="hljs-string">/started.html</span><br>        <span class="hljs-attr">port:</span> <span class="hljs-number">80</span><br>      <span class="hljs-attr">initialDelaySeconds:</span> <span class="hljs-number">1</span><br>      <span class="hljs-attr">periodSeconds:</span> <span class="hljs-number">5</span><br>      <span class="hljs-attr">failureThreshold:</span> <span class="hljs-number">3</span><br>    <span class="hljs-attr">command:</span>            <span class="hljs-comment"># 启动命令</span><br>    <span class="hljs-bullet">-</span> <span class="hljs-string">nginx</span><br>    <span class="hljs-bullet">-</span> <span class="hljs-string">-g</span><br>    <span class="hljs-bullet">-</span> <span class="hljs-string">&#x27;daemon off;&#x27;</span><br>    <span class="hljs-attr">workingDir:</span> <span class="hljs-string">/usr/share/nginx/html</span><br>    <span class="hljs-attr">ports:</span><br>    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">http</span><br>      <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span><br>      <span class="hljs-attr">protocol:</span> <span class="hljs-string">TCP</span><br>    <span class="hljs-attr">env:</span>                <span class="hljs-comment"># 环境变量</span><br>    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">JVM_OPTS</span><br>      <span class="hljs-attr">value:</span> <span class="hljs-string">&#x27;-Xms128m -Xmx128m&#x27;</span><br>    <span class="hljs-attr">resources:</span>          <span class="hljs-comment"># 资源限制</span><br>      <span class="hljs-attr">requests:</span><br>        <span class="hljs-attr">cpu:</span> <span class="hljs-string">100m</span><br>        <span class="hljs-attr">memory:</span> <span class="hljs-string">128Mi</span><br>      <span class="hljs-attr">limits:</span><br>        <span class="hljs-attr">cpu:</span> <span class="hljs-string">200m</span><br>        <span class="hljs-attr">memory:</span> <span class="hljs-string">256Mi</span><br>  <span class="hljs-attr">restartPolicy:</span> <span class="hljs-string">OnFailure</span><br></code></pre></td></tr></table></figure><h2 id="Deployment-控制器"><a href="#Deployment-控制器" class="headerlink" title="Deployment 控制器"></a>Deployment 控制器</h2><h3 id="配置文件"><a href="#配置文件" class="headerlink" title="配置文件"></a>配置文件</h3><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-deploy</span><br>  <span class="hljs-attr">labels:</span><br>    <span class="hljs-attr">controller:</span> <span class="hljs-string">deploy</span><br><span class="hljs-attr">spec:</span><br>  <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>                    <span class="hljs-comment"># 副本数量</span><br>  <span class="hljs-attr">revisionHistoryLimit:</span> <span class="hljs-number">5</span>        <span class="hljs-comment"># 保留历史版本数</span><br>  <span class="hljs-attr">paused:</span> <span class="hljs-literal">false</span>                  <span class="hljs-comment"># 是否暂停部署</span><br>  <span class="hljs-attr">progressDeadlineSeconds:</span> <span class="hljs-number">600</span>   <span class="hljs-comment"># 部署超时时间</span><br>  <span class="hljs-attr">strategy:</span>                      <span class="hljs-comment"># 更新策略</span><br>    <span class="hljs-attr">type:</span> <span class="hljs-string">RollingUpdate</span><br>    <span class="hljs-attr">rollingUpdate:</span><br>      <span class="hljs-attr">maxSurge:</span> <span class="hljs-number">30</span><span class="hljs-string">%</span>              <span class="hljs-comment"># 最大额外副本数</span><br>  <span class="hljs-attr">selector:</span>                      <span class="hljs-comment"># 选择器</span><br>    <span class="hljs-attr">matchLabels:</span><br>      <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-pod</span><br>  <span class="hljs-attr">template:</span>                      <span class="hljs-comment"># Pod 模板</span><br>    <span class="hljs-attr">metadata:</span><br>      <span class="hljs-attr">labels:</span><br>        <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-pod</span><br>    <span class="hljs-attr">spec:</span><br>      <span class="hljs-attr">containers:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx</span><br>        <span class="hljs-attr">image:</span> <span class="hljs-string">nginx:1.20.2</span><br>        <span class="hljs-attr">ports:</span><br>        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span><br></code></pre></td></tr></table></figure><h3 id="版本管理"><a href="#版本管理" class="headerlink" title="版本管理"></a>版本管理</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看升级状态</span><br>kubectl rollout status deployment nginx-deploy<br><br><span class="hljs-comment"># 查看升级历史</span><br>kubectl rollout <span class="hljs-built_in">history</span> deployment nginx-deploy<br><br><span class="hljs-comment"># 暂停升级</span><br>kubectl rollout pause deployment nginx-deploy<br><br><span class="hljs-comment"># 继续升级</span><br>kubectl rollout resume deployment nginx-deploy<br><br><span class="hljs-comment"># 回滚到上一版本</span><br>kubectl rollout undo deployment nginx-deploy<br><br><span class="hljs-comment"># 回滚到指定版本</span><br>kubectl rollout undo deployment nginx-deploy --to-revision=2<br></code></pre></td></tr></table></figure><h3 id="滚动更新"><a href="#滚动更新" class="headerlink" title="滚动更新"></a>滚动更新</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 更新镜像</span><br>kubectl <span class="hljs-built_in">set</span> image deployment nginx-deploy nginx=nginx:1.21.0<br><br><span class="hljs-comment"># 或直接编辑</span><br>kubectl edit deployment nginx-deploy<br></code></pre></td></tr></table></figure><h3 id="金丝雀发布"><a href="#金丝雀发布" class="headerlink" title="金丝雀发布"></a>金丝雀发布</h3><p>金丝雀发布是一种灰度发布策略，先部署少量新版本实例，验证无误后再逐步扩大范围。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 创建金丝雀部署（1个副本）</span><br>kubectl <span class="hljs-built_in">set</span> image deployment nginx-deploy nginx=nginx:1.21.0<br>kubectl scale deployment nginx-deploy --replicas=1<br><br><span class="hljs-comment"># 验证通过后，全量更新</span><br>kubectl <span class="hljs-built_in">set</span> image deployment nginx-deploy nginx=nginx:1.21.0<br></code></pre></td></tr></table></figure><h2 id="Service"><a href="#Service" class="headerlink" title="Service"></a>Service</h2><p>Service 用于暴露 Pod 的访问入口，提供稳定的 IP 和 DNS 名称。</p><h3 id="Service-类型"><a href="#Service-类型" class="headerlink" title="Service 类型"></a>Service 类型</h3><table><thead><tr><th>类型</th><th>说明</th></tr></thead><tbody><tr><td>ClusterIP</td><td>默认类型，仅集群内部可访问</td></tr><tr><td>NodePort</td><td>通过节点端口暴露服务</td></tr><tr><td>LoadBalancer</td><td>使用云提供商的负载均衡器</td></tr><tr><td>ExternalName</td><td>映射到外部 DNS 名称</td></tr></tbody></table><h3 id="配置示例"><a href="#配置示例" class="headerlink" title="配置示例"></a>配置示例</h3><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span><br><span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span><br><span class="hljs-attr">metadata:</span><br>  <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-service</span><br><span class="hljs-attr">spec:</span><br>  <span class="hljs-attr">selector:</span><br>    <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-pod</span><br>  <span class="hljs-attr">ports:</span><br>  <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">80</span><br>    <span class="hljs-attr">targetPort:</span> <span class="hljs-number">80</span><br>    <span class="hljs-attr">nodePort:</span> <span class="hljs-number">30080</span><br>  <span class="hljs-attr">type:</span> <span class="hljs-string">NodePort</span><br></code></pre></td></tr></table></figure><h2 id="ConfigMap-和-Secret"><a href="#ConfigMap-和-Secret" class="headerlink" title="ConfigMap 和 Secret"></a>ConfigMap 和 Secret</h2><h3 id="ConfigMap"><a href="#ConfigMap" class="headerlink" title="ConfigMap"></a>ConfigMap</h3><p>用于存储非敏感配置数据。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 创建 ConfigMap</span><br>kubectl create configmap my-config --from-file=config.properties<br><br><span class="hljs-comment"># 或在 YAML 中定义</span><br>apiVersion: v1<br>kind: ConfigMap<br>metadata:<br>  name: my-config<br>data:<br>  config.properties: |<br>    key1=value1<br>    key2=value2<br></code></pre></td></tr></table></figure><h3 id="Secret"><a href="#Secret" class="headerlink" title="Secret"></a>Secret</h3><p>用于存储敏感数据（密码、密钥等）。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 创建 Secret</span><br>kubectl create secret generic my-secret --from-literal=password=my-password<br><br><span class="hljs-comment"># 在 Pod 中使用</span><br><span class="hljs-built_in">env</span>:<br>- name: DB_PASSWORD<br>  valueFrom:<br>    secretKeyRef:<br>      name: my-secret<br>      key: password<br></code></pre></td></tr></table></figure><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="❌-Pod-一直处于-Pending-状态"><a href="#❌-Pod-一直处于-Pending-状态" class="headerlink" title="❌ Pod 一直处于 Pending 状态"></a>❌ Pod 一直处于 Pending 状态</h3><p><strong>原因</strong>：节点资源不足或没有匹配的节点。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看 Pod 事件</span><br>kubectl describe pod &lt;pod-name&gt;<br><br><span class="hljs-comment"># 查看节点资源</span><br>kubectl top nodes<br></code></pre></td></tr></table></figure><h3 id="❌-镜像拉取失败"><a href="#❌-镜像拉取失败" class="headerlink" title="❌ 镜像拉取失败"></a>❌ 镜像拉取失败</h3><p><strong>原因</strong>：镜像地址错误或网络问题。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 检查镜像名称</span><br>kubectl get pod &lt;pod-name&gt; -o yaml | grep image<br><br><span class="hljs-comment"># 配置镜像仓库密钥</span><br>kubectl create secret docker-registry my-registry --docker-server=...<br></code></pre></td></tr></table></figure><hr><p><em>以上就是 Kubernetes 核心概念的详解。K8s 内容丰富，后续文章会继续深入讲解各个组件。</em></p>]]></content>
    
    
    <summary type="html">Kubernetes 核心概念详解，从 Pod 到 Service，逐步讲解 K8s 的关键资源对象。</summary>
    
    
    
    <category term="云原生" scheme="https://www.cloudetopia.top/categories/%E4%BA%91%E5%8E%9F%E7%94%9F/"/>
    
    
    <category term="DevOps" scheme="https://www.cloudetopia.top/tags/DevOps/"/>
    
    <category term="Kubernetes" scheme="https://www.cloudetopia.top/tags/Kubernetes/"/>
    
  </entry>
  
  <entry>
    <title>OpenStack 核心项目演变</title>
    <link href="https://www.cloudetopia.top/2023/12/12/2023-12-12-OpenStack%E6%A0%B8%E5%BF%83%E9%A1%B9%E7%9B%AE%E6%BC%94%E5%8F%98/"/>
    <id>https://www.cloudetopia.top/2023/12/12/2023-12-12-OpenStack%E6%A0%B8%E5%BF%83%E9%A1%B9%E7%9B%AE%E6%BC%94%E5%8F%98/</id>
    <published>2023-12-12T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>本文梳理 OpenStack 各个核心项目的演变历程，包括 Nova、Neutron、Cinder、Swift 等组件的发展脉络。</p><blockquote><p>注：原文中的图片已移除，后续将补充文字说明。</p></blockquote><h2 id="OpenStack-核心组件"><a href="#OpenStack-核心组件" class="headerlink" title="OpenStack 核心组件"></a>OpenStack 核心组件</h2><table><thead><tr><th>组件</th><th>功能</th><th>状态</th></tr></thead><tbody><tr><td>Nova</td><td>计算服务</td><td>活跃</td></tr><tr><td>Neutron</td><td>网络服务</td><td>活跃</td></tr><tr><td>Cinder</td><td>块存储</td><td>活跃</td></tr><tr><td>Swift</td><td>对象存储</td><td>活跃</td></tr><tr><td>Glance</td><td>镜像服务</td><td>活跃</td></tr><tr><td>Keystone</td><td>身份认证</td><td>活跃</td></tr><tr><td>Horizon</td><td>仪表盘</td><td>活跃</td></tr><tr><td>Heat</td><td>编排服务</td><td>活跃</td></tr></tbody></table><h2 id="项目演变时间线"><a href="#项目演变时间线" class="headerlink" title="项目演变时间线"></a>项目演变时间线</h2><figure class="highlight basic"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs basic"><span class="hljs-symbol">2010 </span>- OpenStack 项目启动（NASA + Rackspace）<br><span class="hljs-symbol">2011 </span>- Austin 版本发布<br><span class="hljs-symbol">2012 </span>- Essex/Folsom 版本<br><span class="hljs-symbol">2013 </span>- Grizzly/Havana 版本<br><span class="hljs-symbol">2014 </span>- Icehouse/Juno 版本<br><span class="hljs-symbol">2015 </span>- Kilo/Liberty/Mitaka 版本<br><span class="hljs-symbol">2016 </span>- Newton/Ocata 版本<br><span class="hljs-symbol">2017 </span>- Pike/Queens/Rocky 版本<br><span class="hljs-symbol">2018 </span>- Stein/Train 版本<br><span class="hljs-symbol">2019 </span>- Ussuri/Victoria 版本<br><span class="hljs-symbol">2020 </span>- Wallaby/Xena 版本<br><span class="hljs-symbol">2021 </span>- Yoga/Zed 版本<br><span class="hljs-symbol">2022 </span>- Antelope/Bobcat 版本<br><span class="hljs-symbol">2023 </span>- Caracal 版本<br></code></pre></td></tr></table></figure><h2 id="架构演变趋势"><a href="#架构演变趋势" class="headerlink" title="架构演变趋势"></a>架构演变趋势</h2><p>早期 OpenStack 采用单体架构，各组件之间耦合度较高。随着云原生技术的发展，OpenStack 逐渐向微服务架构演进，容器化部署成为趋势。</p><hr><p><em>后续将补充各组件的详细演变说明。</em></p>]]></content>
    
    
    <summary type="html">梳理 OpenStack 各核心项目的演变历程，包括 Nova、Neutron、Cinder 等组件的发展脉络。</summary>
    
    
    
    <category term="云计算" scheme="https://www.cloudetopia.top/categories/%E4%BA%91%E8%AE%A1%E7%AE%97/"/>
    
    
    <category term="架构" scheme="https://www.cloudetopia.top/tags/%E6%9E%B6%E6%9E%84/"/>
    
    <category term="OpenStack" scheme="https://www.cloudetopia.top/tags/OpenStack/"/>
    
  </entry>
  
  <entry>
    <title>MySQL 基础篇：安装与入门</title>
    <link href="https://www.cloudetopia.top/2023/10/25/2023-10-25-MySQL/"/>
    <id>https://www.cloudetopia.top/2023/10/25/2023-10-25-MySQL/</id>
    <published>2023-10-25T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>MySQL 是最流行的关系型数据库管理系统之一，广泛应用于 Web 应用开发。这篇文章记录了在 CentOS 上安装 MySQL 的完整过程，以及 MariaDB 作为替代方案的说明。</p><h2 id="安装前检查"><a href="#安装前检查" class="headerlink" title="安装前检查"></a>安装前检查</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 检查系统是否已安装 MySQL</span><br>rpm -qa | grep mysql<br><br><span class="hljs-comment"># 如果已安装，卸载旧版本</span><br>rpm -e mysql                    <span class="hljs-comment"># 普通删除</span><br>rpm -e --nodeps mysql           <span class="hljs-comment"># 强制删除（忽略依赖）</span><br></code></pre></td></tr></table></figure><h2 id="安装-MySQL"><a href="#安装-MySQL" class="headerlink" title="安装 MySQL"></a>安装 MySQL</h2><h3 id="方法一：使用-YUM-安装"><a href="#方法一：使用-YUM-安装" class="headerlink" title="方法一：使用 YUM 安装"></a>方法一：使用 YUM 安装</h3><p>参考 <a href="https://dev.mysql.com/downloads/repo/yum/">MySQL 官方文档</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 下载 MySQL 仓库</span><br>wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm<br><br><span class="hljs-comment"># 安装仓库</span><br>rpm -ivh mysql-community-release-el7-5.noarch.rpm<br><br><span class="hljs-comment"># 更新并安装</span><br>yum update<br>yum install mysql-server<br><br><span class="hljs-comment"># 设置权限</span><br><span class="hljs-built_in">chown</span> -R mysql:mysql /var/lib/mysql/<br><br><span class="hljs-comment"># 初始化</span><br>mysqld --initialize<br><br><span class="hljs-comment"># 启动 MySQL</span><br>systemctl start mysqld<br><br><span class="hljs-comment"># 检查状态</span><br>systemctl status mysqld<br></code></pre></td></tr></table></figure><blockquote><p><strong>注意</strong>：第一次启动 MySQL 服务时，服务器会自动进行初始化配置。</p></blockquote><h3 id="方法二：使用-MariaDB（MySQL-替代方案）"><a href="#方法二：使用-MariaDB（MySQL-替代方案）" class="headerlink" title="方法二：使用 MariaDB（MySQL 替代方案）"></a>方法二：使用 MariaDB（MySQL 替代方案）</h3><p>MariaDB 是 MySQL 的一个分支，主要由开源社区维护，采用 GPL 授权许可。开发这个分支的原因之一是：甲骨文公司收购了 MySQL 后，有将 MySQL 闭源的潜在风险。</p><p>MariaDB 的目的是完全兼容 MySQL，包括 API 和命令行，可以轻松成为 MySQL 的代替品。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 安装 MariaDB</span><br>yum install mariadb-server mariadb <br><br><span class="hljs-comment"># 启动/停止/重启</span><br>systemctl start mariadb<br>systemctl stop mariadb<br>systemctl restart mariadb<br><br><span class="hljs-comment"># 设置开机启动</span><br>systemctl <span class="hljs-built_in">enable</span> mariadb<br></code></pre></td></tr></table></figure><h2 id="验证安装"><a href="#验证安装" class="headerlink" title="验证安装"></a>验证安装</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看版本</span><br>mysqladmin --version<br><span class="hljs-comment"># 输出示例：mysqladmin  Ver 8.42 Distrib 5.6.51, for Linux on x86_64</span><br><br><span class="hljs-comment"># 如果以上命令未输出任何信息，说明 MySQL 未安装成功</span><br><br><span class="hljs-comment"># 进入 MySQL</span><br>mysql<br></code></pre></td></tr></table></figure><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="❌-忘记-root-密码"><a href="#❌-忘记-root-密码" class="headerlink" title="❌ 忘记 root 密码"></a>❌ 忘记 root 密码</h3><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 停止 MySQL 服务</span><br>systemctl stop mysqld<br><br><span class="hljs-comment"># 以安全模式启动</span><br>mysqld_safe --skip-grant-tables &amp;<br><br><span class="hljs-comment"># 进入 MySQL 修改密码</span><br>mysql<br>&gt; USE mysql;<br>&gt; UPDATE user SET password=PASSWORD(<span class="hljs-string">&#x27;新密码&#x27;</span>) WHERE user=<span class="hljs-string">&#x27;root&#x27;</span>;<br>&gt; FLUSH PRIVILEGES;<br>&gt; EXIT;<br><br><span class="hljs-comment"># 重启 MySQL</span><br>systemctl restart mysqld<br></code></pre></td></tr></table></figure><h3 id="❌-远程连接被拒绝"><a href="#❌-远程连接被拒绝" class="headerlink" title="❌ 远程连接被拒绝"></a>❌ 远程连接被拒绝</h3><p><strong>原因</strong>：MySQL 默认只允许本地连接。</p><p><strong>解决</strong>：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 授权远程访问</span><br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> PRIVILEGES <span class="hljs-keyword">ON</span> <span class="hljs-operator">*</span>.<span class="hljs-operator">*</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;root&#x27;</span>@<span class="hljs-string">&#x27;%&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;密码&#x27;</span> <span class="hljs-keyword">WITH</span> <span class="hljs-keyword">GRANT</span> OPTION;<br>FLUSH PRIVILEGES;<br></code></pre></td></tr></table></figure><hr><p><em>以上就是 MySQL 安装和入门的全部内容。后续文章会继续介绍 MySQL 的进阶用法。</em></p>]]></content>
    
    
    <summary type="html">MySQL 基础入门教程，记录 CentOS 上 MySQL 安装配置的完整过程及 MariaDB 替代方案。</summary>
    
    
    
    <category term="数据库" scheme="https://www.cloudetopia.top/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
    
    <category term="MySQL" scheme="https://www.cloudetopia.top/tags/MySQL/"/>
    
    <category term="数据库" scheme="https://www.cloudetopia.top/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
  </entry>
  
  <entry>
    <title>Dockerfile 详解：从基础到实战</title>
    <link href="https://www.cloudetopia.top/2023/10/20/2023-10-20-Dockerfile/"/>
    <id>https://www.cloudetopia.top/2023/10/20/2023-10-20-Dockerfile/</id>
    <published>2023-10-20T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Dockerfile 是用来构建 Docker 镜像的文本文件，包含了一条条指令，告诉 Docker 如何一步步构建镜像。掌握 Dockerfile 是 Docker 进阶的必经之路。</p><p>这篇文章从基础概念讲起，通过实例带你理解 Dockerfile 的常用指令和构建流程。</p><h2 id="Dockerfile-构建流程"><a href="#Dockerfile-构建流程" class="headerlink" title="Dockerfile 构建流程"></a>Dockerfile 构建流程</h2><p>一个完整的 Docker 镜像由以下几步构成：</p><ol><li>编写 Dockerfile 文件</li><li>使用 <code>docker build</code> 命令构建镜像</li><li>使用 <code>docker run</code> 命令运行镜像</li><li>使用 <code>docker push</code> 发布镜像（推荐 DockerHub、阿里云镜像仓库）</li></ol><blockquote><p>参考 <a href="https://docs.docker.com/engine/reference/builder/">Docker 官方文档</a></p></blockquote><h2 id="Dockerfile-指令"><a href="#Dockerfile-指令" class="headerlink" title="Dockerfile 指令"></a>Dockerfile 指令</h2><p>Dockerfile 中每个指令都会创建一个新的镜像层。</p><table><thead><tr><th>指令</th><th>说明</th></tr></thead><tbody><tr><td><code>FROM</code></td><td>基础镜像，一切从这里开始</td></tr><tr><td><code>MAINTAINER</code></td><td>镜像维护者（姓名+邮箱）</td></tr><tr><td><code>RUN</code></td><td>构建镜像时执行的命令</td></tr><tr><td><code>ADD</code></td><td>添加文件并自动解压压缩包</td></tr><tr><td><code>COPY</code></td><td>复制文件到镜像中（类似 ADD，但不解压）</td></tr><tr><td><code>WORKDIR</code></td><td>设置工作目录</td></tr><tr><td><code>VOLUME</code></td><td>挂载目录</td></tr><tr><td><code>EXPOSE</code></td><td>暴露端口号</td></tr><tr><td><code>CMD</code></td><td>容器启动时执行的命令（仅最后一个生效，可被替代）</td></tr><tr><td><code>ENTRYPOINT</code></td><td>容器启动时执行的命令（可追加参数）</td></tr><tr><td><code>ONBUILD</code></td><td>当镜像被继承时触发的指令</td></tr><tr><td><code>ENV</code></td><td>设置环境变量</td></tr></tbody></table><h3 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h3><ul><li>每个指令（关键字）必须<strong>大写</strong></li><li>文件从上到下顺序执行</li><li><code>#</code> 表示注释</li><li>每条指令都会创建并提交一个新的镜像层</li></ul><h2 id="实战：创建自定义-CentOS-镜像"><a href="#实战：创建自定义-CentOS-镜像" class="headerlink" title="实战：创建自定义 CentOS 镜像"></a>实战：创建自定义 CentOS 镜像</h2><h3 id="1-编写-Dockerfile"><a href="#1-编写-Dockerfile" class="headerlink" title="1. 编写 Dockerfile"></a>1. 编写 Dockerfile</h3><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs dockerfile"><span class="hljs-comment"># 创建文件：/home/dockerfile/dockerfile.centos</span><br><span class="hljs-keyword">FROM</span> centos:<span class="hljs-number">7</span><br><span class="hljs-keyword">MAINTAINER</span> cf&lt;kisssheep1557@<span class="hljs-number">163</span>.com&gt;<br><br><span class="hljs-keyword">ENV</span> MYPATH /usr/local/<br><span class="hljs-keyword">WORKDIR</span><span class="language-bash"> <span class="hljs-variable">$MYPATH</span></span><br><br><span class="hljs-keyword">RUN</span><span class="language-bash"> yum -y install vim</span><br><span class="hljs-keyword">RUN</span><span class="language-bash"> yum -y install net-tools</span><br><br><span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">80</span><br><br><span class="hljs-keyword">CMD</span><span class="language-bash"> <span class="hljs-built_in">echo</span> <span class="hljs-variable">$MYPATH</span></span><br><span class="hljs-keyword">CMD</span><span class="language-bash"> <span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;-----end-----&quot;</span></span><br><span class="hljs-keyword">CMD</span><span class="language-bash"> /bin/bash</span><br></code></pre></td></tr></table></figure><h3 id="2-构建镜像"><a href="#2-构建镜像" class="headerlink" title="2. 构建镜像"></a>2. 构建镜像</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 命令格式：docker build -f &lt;Dockerfile路径&gt; -t &lt;镜像名&gt;:&lt;tag&gt; .</span><br>docker build -f dockerfile.centos -t mycentos:0.1 .<br></code></pre></td></tr></table></figure><h3 id="3-对比测试"><a href="#3-对比测试" class="headerlink" title="3. 对比测试"></a>3. 对比测试</h3><p>官方基础镜像 <code>centos:7</code> 通常没有 vim 等常用命令，而通过 Dockerfile 构建的 <code>mycentos:0.1</code> 已经预装了这些工具。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看镜像构建历史</span><br>docker <span class="hljs-built_in">history</span> &lt;镜像ID&gt;<br></code></pre></td></tr></table></figure><h2 id="CMD-与-ENTRYPOINT-的区别"><a href="#CMD-与-ENTRYPOINT-的区别" class="headerlink" title="CMD 与 ENTRYPOINT 的区别"></a>CMD 与 ENTRYPOINT 的区别</h2><p>这两个指令都用于指定容器启动时执行的命令，但行为不同：</p><ul><li><strong>CMD</strong>：只有最后一个生效，可以被 <code>docker run</code> 的参数替代</li><li><strong>ENTRYPOINT</strong>：会追加参数，不会被替代</li></ul><h3 id="测试-CMD"><a href="#测试-CMD" class="headerlink" title="测试 CMD"></a>测试 CMD</h3><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs dockerfile"><span class="hljs-keyword">FROM</span> centos:<span class="hljs-number">7</span><br><span class="hljs-keyword">CMD</span><span class="language-bash"> [<span class="hljs-string">&quot;ls&quot;</span>,<span class="hljs-string">&quot;-a&quot;</span>]</span><br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 构建镜像</span><br>docker build -f mydockerfile-cmd-test -t myimage:tag .<br><br><span class="hljs-comment"># 运行 - 执行 ls -a</span><br>docker run 06f2cc65ea4a<br><br><span class="hljs-comment"># 尝试追加 -l 参数 - 报错！</span><br>docker run 06f2cc65ea4a -l<br><span class="hljs-comment"># 原因：-l 替换了 CMD [&quot;ls&quot;,&quot;-a&quot;]，而不是追加</span><br></code></pre></td></tr></table></figure><h3 id="测试-ENTRYPOINT"><a href="#测试-ENTRYPOINT" class="headerlink" title="测试 ENTRYPOINT"></a>测试 ENTRYPOINT</h3><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs dockerfile"><span class="hljs-keyword">FROM</span> centos:<span class="hljs-number">7</span><br><span class="hljs-keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="hljs-string">&quot;ls&quot;</span>,<span class="hljs-string">&quot;-a&quot;</span>]</span><br></code></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 构建镜像</span><br>docker build -f mydockerfile-entrypoint-test -t myimages:tag .<br><br><span class="hljs-comment"># 运行 - 执行 ls -a</span><br>docker run 5184c7d459a0<br><br><span class="hljs-comment"># 追加 -l 参数 - 成功执行 ls -al！</span><br>docker run 5184c7d459a0 -l<br><span class="hljs-comment"># 原因：-l 被追加到 ENTRYPOINT 后面</span><br></code></pre></td></tr></table></figure><h2 id="实战：制作-Tomcat-镜像"><a href="#实战：制作-Tomcat-镜像" class="headerlink" title="实战：制作 Tomcat 镜像"></a>实战：制作 Tomcat 镜像</h2><h3 id="1-准备材料"><a href="#1-准备材料" class="headerlink" title="1. 准备材料"></a>1. 准备材料</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 拉取基础镜像</span><br>docker pull centos:7<br><br><span class="hljs-comment"># 准备目录</span><br><span class="hljs-built_in">cd</span> /home/dockerfile<br><br><span class="hljs-comment"># 下载 Tomcat 和 JDK 压缩包</span><br><span class="hljs-comment"># Tomcat: https://tomcat.apache.org/download-80.cgi</span><br><span class="hljs-comment"># JDK: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html</span><br><span class="hljs-built_in">ls</span><br><span class="hljs-comment"># apache-tomcat-8.5.93.tar.gz  jdk-8u381-linux-x64.tar.gz</span><br></code></pre></td></tr></table></figure><h3 id="2-编写-Dockerfile"><a href="#2-编写-Dockerfile" class="headerlink" title="2. 编写 Dockerfile"></a>2. 编写 Dockerfile</h3><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs dockerfile"><span class="hljs-keyword">FROM</span> centos:<span class="hljs-number">7</span><br><span class="hljs-keyword">MAINTAINER</span> yqy&lt;kisssheep1557@<span class="hljs-number">163</span>.com&gt;<br><br><span class="hljs-comment"># 复制说明文件</span><br><span class="hljs-keyword">COPY</span><span class="language-bash"> readme.txt /usr/local/readme.txt</span><br><br><span class="hljs-comment"># 添加并解压压缩包</span><br><span class="hljs-keyword">ADD</span><span class="language-bash"> jdk-8u381-linux-x64.tar.gz /usr/local  </span><br><span class="hljs-keyword">ADD</span><span class="language-bash"> apache-tomcat-8.5.93.tar.gz /usr/local</span><br><br><span class="hljs-comment"># 安装 vim</span><br><span class="hljs-keyword">RUN</span><span class="language-bash"> yum install -y vim</span><br><br><span class="hljs-comment"># 设置工作目录</span><br><span class="hljs-keyword">ENV</span> MYPATH /usr/local<br><span class="hljs-keyword">WORKDIR</span><span class="language-bash"> <span class="hljs-variable">$MYPATH</span></span><br><br><span class="hljs-comment"># 配置环境变量</span><br><span class="hljs-keyword">ENV</span> JAVA_HOME /usr/local/jdk1.<span class="hljs-number">8.0</span>_381<br><span class="hljs-keyword">ENV</span> CLASS_PATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar<br><span class="hljs-keyword">ENV</span> CATALINA_HOME /usr/local/apache-tomcat-<span class="hljs-number">8.5</span>.<span class="hljs-number">93</span><br><span class="hljs-keyword">ENV</span> CATALINA_BASH /usr/local/apache-tomcat-<span class="hljs-number">8.5</span>.<span class="hljs-number">93</span><br><span class="hljs-keyword">ENV</span> PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin<br><br><span class="hljs-comment"># 暴露端口</span><br><span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">8080</span> <br><br><span class="hljs-comment"># 启动 Tomcat 并监控日志</span><br><span class="hljs-keyword">CMD</span><span class="language-bash"> /usr/local/apache-tomcat-8.5.93/bin/startup.sh &amp;&amp; <span class="hljs-built_in">tail</span> -F /usr/local/apache-tomcat-8.5.93/logs/catalina.out</span><br></code></pre></td></tr></table></figure><h3 id="3-构建并运行"><a href="#3-构建并运行" class="headerlink" title="3. 构建并运行"></a>3. 构建并运行</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 构建镜像</span><br>docker build -t diytomcat .<br><br><span class="hljs-comment"># 运行容器（简单版）</span><br>docker run -d -p 9090:8080 --name diytomcat01 diytomcat:latest<br><br><span class="hljs-comment"># 运行容器（带挂载）</span><br>docker run -d -p 3355:8080 --name yqytomcat \<br>  -v /home/yqy/build/tomcat/test:/usr/local/apache-tomcat-8.5.93/webapps/test \<br>  -v /home/yqy/build/tomcat/tomcatlog:/usr/local/apache-tomcat-8.5.93/logs \<br>  diytomcat<br></code></pre></td></tr></table></figure><p>访问 <code>http://服务器IP:9090</code> 即可看到 Tomcat 默认页面。</p><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="❌-构建时-yum-install-失败"><a href="#❌-构建时-yum-install-失败" class="headerlink" title="❌ 构建时 yum install 失败"></a>❌ 构建时 yum install 失败</h3><p><strong>原因</strong>：CentOS 7 官方源已停止维护。</p><p><strong>解决</strong>：更换为 vault 源或阿里云镜像源。</p><h3 id="❌-CMD-命令不生效"><a href="#❌-CMD-命令不生效" class="headerlink" title="❌ CMD 命令不生效"></a>❌ CMD 命令不生效</h3><p><strong>原因</strong>：多个 CMD 指令只有最后一个生效。</p><p><strong>解决</strong>：使用 <code>&amp;&amp;</code> 连接多个命令，或使用 ENTRYPOINT。</p><hr><p><em>以上就是 Dockerfile 的核心内容和实战示例。掌握这些指令，你就可以构建自己的 Docker 镜像了。</em></p>]]></content>
    
    
    <summary type="html">Dockerfile 编写指南，从基础指令到多阶段构建，带你掌握镜像构建的核心技能。</summary>
    
    
    
    <category term="教程" scheme="https://www.cloudetopia.top/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="Docker" scheme="https://www.cloudetopia.top/tags/Docker/"/>
    
    <category term="DevOps" scheme="https://www.cloudetopia.top/tags/DevOps/"/>
    
  </entry>
  
  <entry>
    <title>Docker 入门实战：从安装到镜像加速</title>
    <link href="https://www.cloudetopia.top/2023/10/17/2023-10-17-Docker/"/>
    <id>https://www.cloudetopia.top/2023/10/17/2023-10-17-Docker/</id>
    <published>2023-10-17T02:00:00.000Z</published>
    <updated>2026-07-08T08:02:15.040Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Docker 是一个开源的容器化平台，用于构建、部署和运行应用程序。它基于 Linux 容器（LXC）技术，提供了一种轻量级且可移植的虚拟化解决方案。</p><p>通过使用 Docker，开发人员可以将应用程序及其所有依赖项打包到一个称为容器的独立单元中。这些容器可以在任何支持 Docker 的操作系统上运行，无需额外配置。每个容器都是独立的、安全的，并且具有自己的文件系统、网络和进程空间。</p><p>这篇文章记录了在 CentOS 上安装 Docker 并配置国内镜像加速的完整过程。</p><h2 id="Docker-的主要优点"><a href="#Docker-的主要优点" class="headerlink" title="Docker 的主要优点"></a>Docker 的主要优点</h2><ul><li><strong>轻量级</strong>：相比传统的虚拟机，Docker 容器占用更少的系统资源，启动更快</li><li><strong>可移植性</strong>：容器可以在不同的环境中运行，无论是开发、测试还是生产环境</li><li><strong>简化部署</strong>：将应用程序及其依赖项作为一个整体打包，简化部署流程</li><li><strong>灵活性</strong>：提供灵活的管理和扩展功能，可以快速部署、停止、复制和迁移容器</li><li><strong>高效性</strong>：容器共享主机的操作系统内核，资源利用和性能非常高效</li></ul><h2 id="环境要求"><a href="#环境要求" class="headerlink" title="环境要求"></a>环境要求</h2><p>Docker 要求 CentOS 内核版本高于 3.10（CentOS 7 以上无需升级内核）。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看系统内核版本</span><br><span class="hljs-built_in">uname</span> -r<br><span class="hljs-comment"># 输出示例：3.10.0-1160.92.1.el7.x86_64</span><br></code></pre></td></tr></table></figure><blockquote><p>本文基于 CentOS 7.9 操作，如有其他问题请参考 <a href="https://docs.docker.com/get-docker/">Docker 官方文档</a>。</p></blockquote><h2 id="安装-Docker"><a href="#安装-Docker" class="headerlink" title="安装 Docker"></a>安装 Docker</h2><h3 id="1-卸载旧版本（如已安装）"><a href="#1-卸载旧版本（如已安装）" class="headerlink" title="1. 卸载旧版本（如已安装）"></a>1. 卸载旧版本（如已安装）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 检查是否已安装</span><br>docker --version<br><span class="hljs-comment"># 如果提示 command not found，说明未安装</span><br><br><span class="hljs-comment"># 卸载旧版本</span><br><span class="hljs-built_in">sudo</span> yum remove docker \<br>                docker-client \<br>                docker-client-latest \<br>                docker-common \<br>                docker-latest \<br>                docker-logrotate \<br>                docker-engine<br></code></pre></td></tr></table></figure><h3 id="2-安装依赖工具"><a href="#2-安装依赖工具" class="headerlink" title="2. 安装依赖工具"></a>2. 安装依赖工具</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> yum install -y yum-utils<br></code></pre></td></tr></table></figure><h3 id="3-配置-Docker-仓库"><a href="#3-配置-Docker-仓库" class="headerlink" title="3. 配置 Docker 仓库"></a>3. 配置 Docker 仓库</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> yum-config-manager \<br>    --add-repo \<br>    https://download.docker.com/linux/centos/docker-ce.repo<br></code></pre></td></tr></table></figure><h3 id="4-安装-Docker-引擎"><a href="#4-安装-Docker-引擎" class="headerlink" title="4. 安装 Docker 引擎"></a>4. 安装 Docker 引擎</h3><p><strong>安装最新版本：</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> yum -y install docker-ce docker-ce-cli containerd.io<br></code></pre></td></tr></table></figure><p><strong>或安装特定版本：</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看可用版本</span><br>yum list docker-ce --showduplicates | <span class="hljs-built_in">sort</span> -r<br><br><span class="hljs-comment"># 安装指定版本（示例）</span><br><span class="hljs-built_in">sudo</span> yum install docker-ce-24.0.0 docker-ce-cli-24.0.0 containerd.io docker-buildx-plugin docker-compose-plugin<br></code></pre></td></tr></table></figure><h3 id="5-启动-Docker"><a href="#5-启动-Docker" class="headerlink" title="5. 启动 Docker"></a>5. 启动 Docker</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 启动 Docker</span><br><span class="hljs-built_in">sudo</span> systemctl start docker<br><br><span class="hljs-comment"># 设置开机自启</span><br><span class="hljs-built_in">sudo</span> systemctl <span class="hljs-built_in">enable</span> docker<br><br><span class="hljs-comment"># 验证安装</span><br>docker --version<br><span class="hljs-comment"># 输出示例：Docker version 24.0.6, build ed223bc</span><br></code></pre></td></tr></table></figure><h3 id="6-验证安装"><a href="#6-验证安装" class="headerlink" title="6. 验证安装"></a>6. 验证安装</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker run hello-world<br></code></pre></td></tr></table></figure><p>如果看到 <code>Hello from Docker!</code> 的输出，说明安装成功。</p><h2 id="配置国内镜像加速"><a href="#配置国内镜像加速" class="headerlink" title="配置国内镜像加速"></a>配置国内镜像加速</h2><p>由于 Docker Hub 服务器在国外，拉取镜像时会很慢。可以使用国内的镜像加速服务，例如阿里云、清华、网易、中科大等。</p><p>这里以阿里云为例：</p><ol><li>打开 <a href="https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors">阿里云镜像加速地址</a> 并登录</li><li>在左侧菜单中选择「镜像加速器」</li><li>复制你的专属加速地址</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> <span class="hljs-built_in">mkdir</span> -p /etc/docker<br><span class="hljs-built_in">sudo</span> <span class="hljs-built_in">tee</span> /etc/docker/daemon.json &lt;&lt;-<span class="hljs-string">&#x27;EOF&#x27;</span><br>&#123;<br>  <span class="hljs-string">&quot;registry-mirrors&quot;</span>: [<span class="hljs-string">&quot;https://你的ID.mirror.aliyuncs.com&quot;</span>]<br>&#125;<br>EOF<br><span class="hljs-built_in">sudo</span> systemctl daemon-reload<br><span class="hljs-built_in">sudo</span> systemctl restart docker<br></code></pre></td></tr></table></figure><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="❌-拉取镜像超时"><a href="#❌-拉取镜像超时" class="headerlink" title="❌ 拉取镜像超时"></a>❌ 拉取镜像超时</h3><p><strong>原因</strong>：Docker Hub 在国内访问慢。</p><p><strong>解决</strong>：配置国内镜像加速器（见上文）。</p><h3 id="❌-权限不足"><a href="#❌-权限不足" class="headerlink" title="❌ 权限不足"></a>❌ 权限不足</h3><p><strong>原因</strong>：当前用户不在 docker 用户组。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> usermod -aG docker <span class="hljs-variable">$USER</span><br><span class="hljs-comment"># 重新登录后生效</span><br></code></pre></td></tr></table></figure><hr><p><em>以上就是 Docker 安装和配置的全部内容。后续文章会继续介绍 Docker 的进阶用法。</em></p>]]></content>
    
    
    <summary type="html">Docker 入门实战教程，涵盖容器核心概念、安装配置和镜像加速，助你快速上手容器化部署。</summary>
    
    
    
    <category term="教程" scheme="https://www.cloudetopia.top/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="Docker" scheme="https://www.cloudetopia.top/tags/Docker/"/>
    
    <category term="DevOps" scheme="https://www.cloudetopia.top/tags/DevOps/"/>
    
  </entry>
  
</feed>
