<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Kevin&#39;s Notes</title>
  
  <subtitle>Quick notes</subtitle>
  <link href="https://freemankevin.uk/atom.xml" rel="self"/>
  
  <link href="https://freemankevin.uk/"/>
  <updated>2026-04-17T10:30:31.801Z</updated>
  <id>https://freemankevin.uk/</id>
  
  <author>
    <name>Freeman Kevin</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Docker 微服务架构安全实践指南</title>
    <link href="https://freemankevin.uk/2026/04/17/docker-microservice-security/"/>
    <id>https://freemankevin.uk/2026/04/17/docker-microservice-security/</id>
    <published>2026-04-17T03:00:00.000Z</published>
    <updated>2026-04-17T10:30:31.801Z</updated>
    
    <content type="html"><![CDATA[<p>在 Docker 容器化微服务架构中,安全是一个不可忽视的重要环节。本文将分享一套完整的 Docker 微服务环境安全加固方案,涵盖端口暴露最小化、网络隔离、敏感信息管理以及多层防御策略。通过本指南,你可以有效缩减 90%+ 的攻击面,提升整体系统安全性。</p><span id="more"></span><p><strong>适用版本与环境说明：</strong></p><ul><li>Docker Engine: 20.10.x 及以上版本</li><li>Docker Compose: 2.x 及以上版本</li><li>操作系统: Ubuntu 20.04+&#x2F;Debian 11+&#x2F;CentOS 7.9+</li><li>内核版本: 建议 4.18+ 以支持完整的网络和安全特性</li><li>更新日期: 2026-04-17（建议每季度检查 Docker 安全公告）</li></ul><h2 id="核心安全原则"><a href="#核心安全原则" class="headerlink" title="核心安全原则"></a>核心安全原则</h2><h2 id="核心安全原则-1"><a href="#核心安全原则-1" class="headerlink" title="核心安全原则"></a>核心安全原则</h2><h3 id="端口最小化暴露原则"><a href="#端口最小化暴露原则" class="headerlink" title="端口最小化暴露原则"></a>端口最小化暴露原则</h3><p>在容器化环境中,端口暴露应遵循最小权限原则:</p><table><thead><tr><th>端口类型</th><th>是否映射到宿主机</th><th>说明</th></tr></thead><tbody><tr><td>22&#x2F;tcp (SSH)</td><td>✅ 是</td><td>系统管理必需</td></tr><tr><td>80&#x2F;tcp (HTTP)</td><td>✅ 是</td><td>Web 业务入口</td></tr><tr><td>443&#x2F;tcp (HTTPS)</td><td>✅ 是</td><td>安全 Web 入口(推荐)</td></tr><tr><td>数据库端口 (5432, 3306等)</td><td>❌ 否</td><td>仅容器内部访问</td></tr><tr><td>缓存端口 (6379, 11211等)</td><td>❌ 否</td><td>仅容器内部访问</td></tr><tr><td>注册中心端口 (8848, 8500等)</td><td>❌ 否</td><td>仅容器内部访问</td></tr><tr><td>后端服务端口</td><td>❌ 否</td><td>通过网关转发</td></tr><tr><td>管理后台端口</td><td>❌ 否</td><td>通过反向代理或VPN访问</td></tr></tbody></table><h3 id="网络分层架构"><a href="#网络分层架构" class="headerlink" title="网络分层架构"></a>网络分层架构</h3><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">                 [ 用户/外部网络 ]</span><br><span class="line">                        |</span><br><span class="line">                        | HTTP/HTTPS (80/443)</span><br><span class="line">                        v</span><br><span class="line">               [ Nginx 容器 (唯一入口) ]</span><br><span class="line">                        |</span><br><span class="line">           ---( Docker 内部网络: apps、middleware等 )---</span><br><span class="line">                        |</span><br><span class="line">                        v</span><br><span class="line">             [ gateway 容器 (网关) ]</span><br><span class="line">                    /   |   \</span><br><span class="line">                   /    |    \  (通过容器名称转发)</span><br><span class="line">                  v     v     v</span><br><span class="line">[ auth-service ]  [ user-service ]  [ business-service ]</span><br><span class="line">     |             |                |</span><br><span class="line">     |             |                |</span><br><span class="line">     +-------------+----------------+</span><br><span class="line">                   |</span><br><span class="line">                   v</span><br><span class="line">       [ 中间件层 ]</span><br><span class="line">     为了安全，以上所有容器均无端口映射到外部</span><br></pre></td></tr></table></figure><p><strong>网络分层说明</strong>:</p><ol><li><strong>外部入口层</strong>: 仅开放 HTTP(80) 和 HTTPS(443) 端口,所有流量必须通过 Nginx</li><li><strong>网关层</strong>: API Gateway 负责路由转发和权限验证</li><li><strong>应用服务层</strong>: 各业务微服务,通过容器名称互相调用</li><li><strong>中间件层</strong>: 数据库、缓存、注册中心等基础服务,严格内部访问</li></ol><div class="note warning"><p><strong>重要说明</strong>:<br>在 Docker Compose 环境中,服务间通信应使用<strong>容器名称</strong>(<code>container_name</code>)而非服务名称(<code>service name</code>)。容器名称是容器在网络中的唯一标识,确保服务间能够正确解析和访问。</p></div><p><strong>安全策略</strong>:</p><ul><li>所有内部服务容器均无端口映射到宿主机</li><li>外部请求只能到达 Nginx 容器</li><li>内部服务通过 Docker 网络隔离,无法直接从外部访问</li></ul><h2 id="宿主机防火墙配置"><a href="#宿主机防火墙配置" class="headerlink" title="宿主机防火墙配置"></a>宿主机防火墙配置</h2><h3 id="启用-UFW-防火墙"><a href="#启用-UFW-防火墙" class="headerlink" title="启用 UFW 防火墙"></a>启用 UFW 防火墙</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 启用 UFW 防火墙</span></span><br><span class="line"><span class="built_in">sudo</span> ufw <span class="built_in">enable</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置默认策略:拒绝所有入站,允许所有出站</span></span><br><span class="line"><span class="built_in">sudo</span> ufw default deny incoming</span><br><span class="line"><span class="built_in">sudo</span> ufw default allow outgoing</span><br><span class="line"></span><br><span class="line"><span class="comment"># 仅开放必要端口</span></span><br><span class="line"><span class="built_in">sudo</span> ufw allow 22/tcp comment <span class="string">&#x27;SSH Management&#x27;</span></span><br><span class="line"><span class="built_in">sudo</span> ufw allow 80/tcp comment <span class="string">&#x27;HTTP Web Entry&#x27;</span></span><br><span class="line"><span class="built_in">sudo</span> ufw allow 443/tcp comment <span class="string">&#x27;HTTPS Web Entry&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证配置</span></span><br><span class="line"><span class="built_in">sudo</span> ufw status verbose</span><br></pre></td></tr></table></figure><p>预期输出:</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Status: active</span><br><span class="line">Default: deny (incoming), allow (outgoing)</span><br><span class="line"></span><br><span class="line">To                         Action      From</span><br><span class="line">--                         ------      ----</span><br><span class="line">22/tcp                     ALLOW IN    Anywhere</span><br><span class="line">80/tcp                     ALLOW IN    Anywhere</span><br><span class="line">443/tcp                    ALLOW IN    Anywhere</span><br></pre></td></tr></table></figure><h2 id="Docker-网络架构配置"><a href="#Docker-网络架构配置" class="headerlink" title="Docker 网络架构配置"></a>Docker 网络架构配置</h2><h3 id="创建隔离网络"><a href="#创建隔离网络" class="headerlink" title="创建隔离网络"></a>创建隔离网络</h3><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># docker-compose.yml 顶层网络配置</span></span><br><span class="line"><span class="attr">networks:</span></span><br><span class="line">  <span class="comment"># 前端接入层网络</span></span><br><span class="line">  <span class="attr">frontend:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br><span class="line">    <span class="attr">internal:</span> <span class="literal">false</span>  <span class="comment"># 允许外部访问</span></span><br><span class="line">  </span><br><span class="line">  <span class="comment"># 应用服务层网络</span></span><br><span class="line">  <span class="attr">apps:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br><span class="line">    <span class="attr">internal:</span> <span class="literal">true</span>   <span class="comment"># 仅内部通信(可选,根据需求)</span></span><br><span class="line">  </span><br><span class="line">  <span class="comment"># 中间件层网络</span></span><br><span class="line">  <span class="attr">middleware:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br><span class="line">    <span class="attr">internal:</span> <span class="literal">true</span>   <span class="comment"># 严格内部访问</span></span><br><span class="line">  </span><br><span class="line">  <span class="comment"># 模型服务层网络</span></span><br><span class="line">  <span class="attr">ai-services:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br><span class="line">    <span class="attr">internal:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><h3 id="服务网络归属原则"><a href="#服务网络归属原则" class="headerlink" title="服务网络归属原则"></a>服务网络归属原则</h3><table><thead><tr><th>服务类型</th><th>网络归属</th><th>端口映射</th></tr></thead><tbody><tr><td>Nginx (反向代理)</td><td>frontend + apps</td><td>80:80, 443:443</td></tr><tr><td>API Gateway</td><td>apps + middleware</td><td>无</td></tr><tr><td>Java 微服务</td><td>apps + middleware</td><td>无</td></tr><tr><td>Python 后端</td><td>apps + ai-services</td><td>无</td></tr><tr><td>PostgreSQL</td><td>middleware + apps</td><td>无</td></tr><tr><td>Redis</td><td>middleware + apps</td><td>无</td></tr><tr><td>Nacos</td><td>middleware + apps</td><td>无</td></tr><tr><td>MinIO</td><td>middleware + apps</td><td>无</td></tr><tr><td>AI 模型服务</td><td>ai-services + apps</td><td>无</td></tr></tbody></table><h3 id="跨-Compose-文件的外部网络配置"><a href="#跨-Compose-文件的外部网络配置" class="headerlink" title="跨 Compose 文件的外部网络配置"></a>跨 Compose 文件的外部网络配置</h3><p>当服务分布在不同 Docker Compose 文件中时,需要使用外部网络实现互联互通。<strong>关键步骤</strong>:</p><ol><li><strong>查看现有 Docker 网络</strong>:</li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查看所有 Docker 网络</span></span><br><span class="line">docker network <span class="built_in">ls</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 输出示例:</span></span><br><span class="line"><span class="comment"># NETWORK ID     NAME                      DRIVER    SCOPE</span></span><br><span class="line"><span class="comment"># abc123def456   installapps_apps          bridge    local</span></span><br><span class="line"><span class="comment"># def789ghi012   middleware                bridge    local</span></span><br></pre></td></tr></table></figure><ol start="2"><li><strong>在 Compose 文件中引用外部网络</strong>:</li></ol><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">nginx:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">nginx:1.29.0-alpine</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">nginx</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;80:80&quot;</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;443:443&quot;</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">TZ=Asia/Shanghai</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">installapps_apps</span>  <span class="comment"># 引用外部网络(来自其他 compose 文件)</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD&quot;</span>, <span class="string">&quot;nginx&quot;</span>, <span class="string">&quot;-t&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">30s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">3</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./conf/mime.types:/etc/nginx/mime.types:ro</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./conf/nginx.conf:/etc/nginx/nginx.conf:ro</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./conf/web.conf:/etc/nginx/conf.d/default.conf:ro</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./data/nginx/html:/usr/share/nginx/html</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./data/nginx/logs:/var/log/nginx:rw</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line"></span><br><span class="line"><span class="attr">networks:</span></span><br><span class="line">  <span class="attr">installapps_apps:</span></span><br><span class="line">    <span class="attr">external:</span> <span class="literal">true</span>  <span class="comment"># 声明为外部网络</span></span><br><span class="line">  <span class="attr">middleware:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br></pre></td></tr></table></figure><div class="note danger"><p>外部网络的名称必须与 <code>docker network ls</code> 中显示的名称完全一致。</p></div><h2 id="端口映射配置规范"><a href="#端口映射配置规范" class="headerlink" title="端口映射配置规范"></a>端口映射配置规范</h2><h3 id="正确示例-仅映射必要端口"><a href="#正确示例-仅映射必要端口" class="headerlink" title="正确示例:仅映射必要端口"></a>正确示例:仅映射必要端口</h3><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="comment"># 唯一对外入口</span></span><br><span class="line">  <span class="attr">nginx:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">nginx:1.29-alpine</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">nginx</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;80:80&quot;</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;443:443&quot;</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">frontend</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">apps</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># 后端服务:不映射端口</span></span><br><span class="line">  <span class="attr">gateway:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/gateway:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">gateway</span></span><br><span class="line">    <span class="comment"># ports: 删除所有端口映射</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">apps</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># 数据库:不映射端口</span></span><br><span class="line">  <span class="attr">postgres:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/postgres:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">postgres</span></span><br><span class="line">    <span class="comment"># ports: 删除所有端口映射</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># 缓存:不映射端口</span></span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/redis:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">redis</span></span><br><span class="line">    <span class="comment"># ports: 删除所有端口映射</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br></pre></td></tr></table></figure><div class="note info"><p><strong>关键点</strong>:</p><ul><li><code>ports</code> 配置中的端口是<strong>容器自身服务端口</strong>,如 Nginx 默认 80、PostgreSQL 默认 5432</li><li>容器间通信使用 <code>container_name</code> 作为主机名,而非 <code>service name</code></li></ul></div><h3 id="错误示例-过度暴露端口"><a href="#错误示例-过度暴露端口" class="headerlink" title="错误示例:过度暴露端口"></a>错误示例:过度暴露端口</h3><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 危险!不要这样配置</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">postgres:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">postgres:17</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">postgres</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;5432:5432&quot;</span>  <span class="comment"># ⚠️ 数据库端口暴露在外</span></span><br><span class="line">  </span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">redis:8</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">redis</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;6379:6379&quot;</span>  <span class="comment"># ⚠️ 缓存端口暴露在外</span></span><br><span class="line">  </span><br><span class="line">  <span class="attr">backend:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">backend:latest</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">backend</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;8080:8080&quot;</span>  <span class="comment"># ⚠️ 后端端口暴露在外</span></span><br></pre></td></tr></table></figure><h2 id="敏感信息安全处理"><a href="#敏感信息安全处理" class="headerlink" title="敏感信息安全处理"></a>敏感信息安全处理</h2><h3 id="配置文件脱敏规范"><a href="#配置文件脱敏规范" class="headerlink" title="配置文件脱敏规范"></a>配置文件脱敏规范</h3><h4 id="镜像名称脱敏"><a href="#镜像名称脱敏" class="headerlink" title="镜像名称脱敏"></a>镜像名称脱敏</h4><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># ❌ 原始配置(含敏感信息)</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&quot;mycompany/app-server:v1.2.3&quot;</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&quot;registry.internal.com/project/backend:abc123&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ✅ 脱敏后配置</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&quot;&lt;your-registry&gt;/&lt;image-name&gt;:&lt;tag&gt;&quot;</span></span><br><span class="line">    <span class="comment"># 或使用环境变量</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&quot;$&#123;REGISTRY&#125;/$&#123;IMAGE_NAME&#125;:$&#123;IMAGE_TAG&#125;&quot;</span></span><br></pre></td></tr></table></figure><h4 id="密码凭证脱敏"><a href="#密码凭证脱敏" class="headerlink" title="密码凭证脱敏"></a>密码凭证脱敏</h4><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># ❌ 原始配置(硬编码密码)</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">postgres:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">postgres</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">POSTGRES_PASSWORD:</span> <span class="string">&quot;MyP@ssw0rd123&quot;</span></span><br><span class="line">  </span><br><span class="line">  <span class="attr">nacos:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">nacos</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">SPRING_CLOUD_NACOS_PASSWORD:</span> <span class="string">&quot;Nacos@123.com&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ✅ 方案一:使用环境变量文件</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">postgres:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">postgres</span></span><br><span class="line">    <span class="attr">env_file:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">.env.postgres</span>  <span class="comment"># 添加到 .gitignore</span></span><br><span class="line">  </span><br><span class="line">  <span class="attr">nacos:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">nacos</span></span><br><span class="line">    <span class="attr">env_file:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">.env.nacos</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ✅ 方案二:使用 Docker Secrets(Swarm模式)</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">postgres:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">postgres</span></span><br><span class="line">    <span class="attr">secrets:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">postgres_password</span></span><br><span class="line"><span class="attr">secrets:</span></span><br><span class="line">  <span class="attr">postgres_password:</span></span><br><span class="line">    <span class="attr">external:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ✅ 方案三:使用变量引用</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">postgres:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">postgres</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">POSTGRES_PASSWORD:</span> <span class="string">$&#123;POSTGRES_PASSWORD&#125;</span></span><br><span class="line"><span class="comment"># .env 文件(不提交到版本库)</span></span><br><span class="line"><span class="comment"># POSTGRES_PASSWORD=&lt;strong-password&gt;</span></span><br></pre></td></tr></table></figure><h4 id="IP-地址和域名脱敏"><a href="#IP-地址和域名脱敏" class="headerlink" title="IP 地址和域名脱敏"></a>IP 地址和域名脱敏</h4><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># ❌ 原始配置</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">app</span></span><br><span class="line">    <span class="attr">extra_hosts:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;server01.internal:192.168.1.100&quot;</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">SPRING_CLOUD_NACOS_DISCOVERY_IP:</span> <span class="string">&quot;192.168.1.100&quot;</span></span><br><span class="line">      <span class="attr">SERVER_URL:</span> <span class="string">&quot;https://api.example.com&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ✅ 脱敏后配置</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">app</span></span><br><span class="line">    <span class="attr">extra_hosts:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;&lt;hostname&gt;:&lt;ip-address&gt;&quot;</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">SPRING_CLOUD_NACOS_DISCOVERY_IP:</span> <span class="string">&quot;$&#123;SERVER_IP&#125;&quot;</span></span><br><span class="line">      <span class="attr">SERVER_URL:</span> <span class="string">&quot;$&#123;API_BASE_URL&#125;&quot;</span></span><br></pre></td></tr></table></figure><h3 id="gitignore-配置"><a href="#gitignore-配置" class="headerlink" title=".gitignore 配置"></a>.gitignore 配置</h3><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"># 敏感配置文件</span><br><span class="line">.env</span><br><span class="line">.env.*</span><br><span class="line">*.env</span><br><span class="line">secrets/</span><br><span class="line"></span><br><span class="line"># 包含敏感信息的配置</span><br><span class="line">docker-compose.override.yml</span><br><span class="line">docker-compose.prod.yml</span><br><span class="line"></span><br><span class="line"># 日志文件(可能含敏感信息)</span><br><span class="line">logs/</span><br><span class="line">*.log</span><br></pre></td></tr></table></figure><h3 id="环境变量模板文件"><a href="#环境变量模板文件" class="headerlink" title="环境变量模板文件"></a>环境变量模板文件</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># .env.template(提交到版本库)</span></span><br><span class="line"><span class="comment"># 复制此文件为 .env 并填写实际值</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 数据库配置</span></span><br><span class="line">POSTGRES_DB=&lt;database-name&gt;</span><br><span class="line">POSTGRES_USER=&lt;database-user&gt;</span><br><span class="line">POSTGRES_PASSWORD=&lt;strong-password&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># Nacos 配置</span></span><br><span class="line">NACOS_USERNAME=&lt;nacos-user&gt;</span><br><span class="line">NACOS_PASSWORD=&lt;nacos-password&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># MinIO 配置</span></span><br><span class="line">MINIO_ROOT_USER=&lt;minio-user&gt;</span><br><span class="line">MINIO_ROOT_PASSWORD=&lt;minio-password&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># Redis 配置</span></span><br><span class="line">REDIS_PASSWORD=&lt;redis-password&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 服务发现配置</span></span><br><span class="line">SERVER_IP=&lt;your-server-ip&gt;</span><br><span class="line">GATEWAY_PORT=&lt;gateway-port&gt;</span><br></pre></td></tr></table></figure><h2 id="Nginx-安全请求头配置"><a href="#Nginx-安全请求头配置" class="headerlink" title="Nginx 安全请求头配置"></a>Nginx 安全请求头配置</h2><h3 id="基础安全头配置"><a href="#基础安全头配置" class="headerlink" title="基础安全头配置"></a>基础安全头配置</h3><figure class="highlight nginx"><table><tr><td class="code"><pre><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">    <span class="attribute">listen</span> <span class="number">80</span>;</span><br><span class="line">    <span class="attribute">server_tokens</span> <span class="literal">off</span>;  <span class="comment"># 隐藏 Nginx 版本号</span></span><br><span class="line">    <span class="attribute">absolute_redirect</span> <span class="literal">off</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># 防止 MIME 类型嗅探</span></span><br><span class="line">    <span class="attribute">add_header</span> X-Content-Type-Options <span class="string">&quot;nosniff&quot;</span> always;</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># XSS 防护</span></span><br><span class="line">    <span class="attribute">add_header</span> X-XSS-Protection <span class="string">&quot;1; mode=block&quot;</span> always;</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># 防止点击劫持</span></span><br><span class="line">    <span class="attribute">add_header</span> X-Frame-Options <span class="string">&quot;DENY&quot;</span> always;</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># 引用策略</span></span><br><span class="line">    <span class="attribute">add_header</span> Referrer-Policy <span class="string">&quot;strict-origin-when-cross-origin&quot;</span> always;</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># 下载安全</span></span><br><span class="line">    <span class="attribute">add_header</span> X-Download-Options <span class="string">&quot;noopen&quot;</span> always;</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># 跨域策略</span></span><br><span class="line">    <span class="attribute">add_header</span> X-Permitted-Cross-Domain-Policies <span class="string">&quot;none&quot;</span> always;</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># 内容安全策略(根据实际需求调整)</span></span><br><span class="line">    <span class="attribute">add_header</span> Content-Security-Policy <span class="string">&quot;default-src &#x27;self&#x27;; script-src &#x27;self&#x27;; style-src &#x27;self&#x27; &#x27;unsafe-inline&#x27;; img-src &#x27;self&#x27; data: https:; font-src &#x27;self&#x27; data:; connect-src &#x27;self&#x27; http: https:; frame-ancestors &#x27;none&#x27;;&quot;</span> always;</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># HSTS(需配合 HTTPS 使用)</span></span><br><span class="line">    <span class="attribute">add_header</span> Strict-Transport-Security <span class="string">&quot;max-age=31536000; includeSubDomains&quot;</span> always;</span><br><span class="line">    </span><br><span class="line">    <span class="section">location</span> / &#123;</span><br><span class="line">        <span class="attribute">root</span> /usr/share/nginx/html;</span><br><span class="line">        <span class="attribute">index</span> index.html;</span><br><span class="line">        <span class="attribute">try_files</span> <span class="variable">$uri</span> <span class="variable">$uri</span>/ /index.html;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># 后端 API 代理(通过容器名称访问,不暴露端口)</span></span><br><span class="line">    <span class="section">location</span> /api/ &#123;</span><br><span class="line">        <span class="attribute">proxy_pass</span> http://gateway:8080/;  <span class="comment"># 使用容器名称</span></span><br><span class="line">        <span class="attribute">proxy_buffering</span> <span class="literal">off</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Host <span class="variable">$host</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Real-IP <span class="variable">$remote_addr</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Forwarded-For <span class="variable">$proxy_add_x_forwarded_for</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Forwarded-Proto <span class="variable">$scheme</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>说明</strong>: Nginx 反向代理配置中使用的是<strong>容器名称</strong>(<code>gateway</code>),这是容器在网络中的标识符,确保请求能正确路由到目标容器。</p><h3 id="安全请求头验证"><a href="#安全请求头验证" class="headerlink" title="安全请求头验证"></a>安全请求头验证</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 验证安全头是否生效</span></span><br><span class="line">curl -I http://&lt;your-server&gt;/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 预期输出应包含所有安全头</span></span><br><span class="line">HTTP/1.1 200 OK</span><br><span class="line">Server: nginx</span><br><span class="line">X-Content-Type-Options: nosniff</span><br><span class="line">X-XSS-Protection: 1; mode=block</span><br><span class="line">X-Frame-Options: DENY</span><br><span class="line">Referrer-Policy: strict-origin-when-cross-origin</span><br><span class="line">X-Download-Options: noopen</span><br><span class="line">X-Permitted-Cross-Domain-Policies: none</span><br><span class="line">Content-Security-Policy: default-src <span class="string">&#x27;self&#x27;</span>; ...</span><br><span class="line">Strict-Transport-Security: max-age=31536000; includeSubDomains</span><br></pre></td></tr></table></figure><h2 id="服务间通信配置"><a href="#服务间通信配置" class="headerlink" title="服务间通信配置"></a>服务间通信配置</h2><h3 id="连接地址标准化"><a href="#连接地址标准化" class="headerlink" title="连接地址标准化"></a>连接地址标准化</h3><table><thead><tr><th>连接场景</th><th>❌ 错误配置</th><th>✅ 正确配置</th></tr></thead><tbody><tr><td>Java 连接 Nacos</td><td><code>&lt;ip&gt;:38848</code></td><td><code>nacos:8848</code></td></tr><tr><td>Java 连接 PostgreSQL</td><td><code>&lt;ip&gt;:35433</code></td><td><code>postgres:5432</code></td></tr><tr><td>Java 连接 Redis</td><td><code>&lt;ip&gt;:36379</code></td><td><code>redis:6379</code></td></tr><tr><td>Nginx 转发请求</td><td><code>http://&lt;ip&gt;:8080</code></td><td><code>http://gateway:8080</code></td></tr><tr><td>服务注册地址</td><td>宿主机 IP</td><td>容器内部 IP(自动)</td></tr></tbody></table><p><strong>核心原则</strong>: 所有服务间通信使用<strong>容器名称</strong>作为主机名,Docker 内部 DNS 会自动解析为容器的内部 IP 地址。</p><h3 id="配置示例"><a href="#配置示例" class="headerlink" title="配置示例"></a>配置示例</h3><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="comment"># API 网关</span></span><br><span class="line">  <span class="attr">gateway:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/gateway:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">gateway</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">apps</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="comment"># 服务发现:使用容器名称</span></span><br><span class="line">      <span class="attr">SPRING_CLOUD_NACOS_CONFIG_SERVER_ADDR:</span> <span class="string">nacos:8848</span></span><br><span class="line">      <span class="attr">SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR:</span> <span class="string">nacos:8848</span></span><br><span class="line">      <span class="comment"># 数据库:使用容器名称</span></span><br><span class="line">      <span class="attr">SPRING_DATASOURCE_URL:</span> <span class="string">jdbc:postgresql://postgres:5432/&lt;db-name&gt;</span></span><br><span class="line">      <span class="comment"># 缓存:使用容器名称</span></span><br><span class="line">      <span class="attr">SPRING_REDIS_HOST:</span> <span class="string">redis</span></span><br><span class="line">      <span class="attr">SPRING_REDIS_PORT:</span> <span class="number">6379</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># 业务服务</span></span><br><span class="line">  <span class="attr">app-service:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/app-service:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">app-service</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">apps</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="comment"># 通过网关访问其他服务</span></span><br><span class="line">      <span class="attr">SERVICE_URL:</span> <span class="string">http://gateway:8080</span></span><br><span class="line">      <span class="comment"># 直接访问中间件</span></span><br><span class="line">      <span class="attr">DATABASE_URL:</span> <span class="string">postgres://postgres:5432/&lt;db-name&gt;</span></span><br><span class="line">      <span class="attr">CACHE_URL:</span> <span class="string">redis://redis:6379</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># 中间件</span></span><br><span class="line">  <span class="attr">postgres:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/postgres:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">postgres</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="comment"># 不映射端口,仅容器内访问</span></span><br><span class="line">    </span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/redis:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">redis</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="comment"># 不映射端口,仅容器内访问</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">nacos:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/nacos:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">nacos</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="comment"># 不映射端口,仅容器内访问</span></span><br></pre></td></tr></table></figure><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="code"><pre><span class="line"><span class="comment"># 检查 Docker 端口映射</span></span><br><span class="line">docker ps --format <span class="string">&quot;table &#123;&#123;.Names&#125;&#125;\t&#123;&#123;.Ports&#125;&#125;&quot;</span> | grep -v <span class="string">&quot;^NAMES&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 仅应看到:</span></span><br><span class="line"><span class="comment"># nginx    0.0.0.0:80-&gt;80/tcp, 0.0.0.0:443-&gt;443/tcp</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查宿主机监听端口</span></span><br><span class="line"><span class="built_in">sudo</span> netstat -tulnp | grep LISTEN</span><br><span class="line"></span><br><span class="line"><span class="comment"># 应仅看到: 22, 80, 443</span></span><br></pre></td></tr></table></figure><h3 id="网络隔离检查"><a href="#网络隔离检查" class="headerlink" title="网络隔离检查"></a>网络隔离检查</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查看容器网络</span></span><br><span class="line">docker network <span class="built_in">ls</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看网络详情</span></span><br><span class="line">docker network inspect apps</span><br><span class="line">docker network inspect middleware</span><br><span class="line"></span><br><span class="line"><span class="comment"># 确认容器间可通过容器名称访问</span></span><br><span class="line">docker <span class="built_in">exec</span> -it &lt;container-name&gt; ping postgres</span><br><span class="line">docker <span class="built_in">exec</span> -it &lt;container-name&gt; ping redis</span><br><span class="line">docker <span class="built_in">exec</span> -it &lt;container-name&gt; ping nacos</span><br></pre></td></tr></table></figure><h3 id="防火墙规则检查"><a href="#防火墙规则检查" class="headerlink" title="防火墙规则检查"></a>防火墙规则检查</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 检查 UFW 状态</span></span><br><span class="line"><span class="built_in">sudo</span> ufw status verbose</span><br><span class="line"></span><br><span class="line"><span class="comment"># 应显示:</span></span><br><span class="line"><span class="comment"># Default: deny (incoming), allow (outgoing)</span></span><br><span class="line"><span class="comment"># 22/tcp ALLOW IN Anywhere</span></span><br><span class="line"><span class="comment"># 80/tcp ALLOW IN Anywhere</span></span><br><span class="line"><span class="comment"># 443/tcp ALLOW IN Anywhere</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 从外部扫描端口(应在其他机器上执行)</span></span><br><span class="line">nmap -p 22,80,443,5432,6379,8848 &lt;your-server-ip&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 应仅看到 22, 80, 443 为 open</span></span><br></pre></td></tr></table></figure><h3 id="敏感信息检查"><a href="#敏感信息检查" class="headerlink" title="敏感信息检查"></a>敏感信息检查</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 检查配置文件中的敏感信息</span></span><br><span class="line">grep -r <span class="string">&quot;password\|Password\|PASSWORD&quot;</span> docker-compose*.yml</span><br><span class="line">grep -r <span class="string">&quot;secret\|Secret\|SECRET&quot;</span> docker-compose*.yml</span><br><span class="line">grep -r <span class="string">&quot;[0-9]\&#123;1,3\&#125;\.[0-9]\&#123;1,3\&#125;\.[0-9]\&#123;1,3\&#125;\.[0-9]\&#123;1,3\&#125;&quot;</span> docker-compose*.yml</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查 .env 文件是否被忽略</span></span><br><span class="line">git status | grep -i <span class="built_in">env</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 确认 .gitignore 包含敏感文件</span></span><br><span class="line"><span class="built_in">cat</span> .gitignore | grep -E <span class="string">&quot;\.env|secret&quot;</span></span><br></pre></td></tr></table></figure><h2 id="完整配置模板"><a href="#完整配置模板" class="headerlink" title="完整配置模板"></a>完整配置模板</h2><h3 id="docker-compose-yml-模板"><a href="#docker-compose-yml-模板" class="headerlink" title="docker-compose.yml 模板"></a>docker-compose.yml 模板</h3><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">&#x27;3.8&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 网络配置</span></span><br><span class="line"><span class="attr">networks:</span></span><br><span class="line">  <span class="attr">frontend:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br><span class="line">  <span class="attr">apps:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br><span class="line">  <span class="attr">middleware:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 通用配置</span></span><br><span class="line"><span class="attr">x-common-config:</span> <span class="string">&amp;common-config</span></span><br><span class="line">  <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">  <span class="attr">networks:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">apps</span></span><br><span class="line">  <span class="attr">logging:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">&quot;json-file&quot;</span></span><br><span class="line">    <span class="attr">options:</span></span><br><span class="line">      <span class="attr">max-size:</span> <span class="string">&quot;10m&quot;</span></span><br><span class="line">      <span class="attr">max-file:</span> <span class="string">&quot;3&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="comment"># ============ 前端层 ============</span></span><br><span class="line">  <span class="attr">nginx:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/nginx:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">nginx</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;80:80&quot;</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;443:443&quot;</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">frontend</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">apps</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./conf/nginx.conf:/etc/nginx/nginx.conf:ro</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./conf/web.conf:/etc/nginx/conf.d/default.conf:ro</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./data/certs:/etc/ssl/private:ro</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./data/html:/usr/share/nginx/html</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD&quot;</span>, <span class="string">&quot;nginx&quot;</span>, <span class="string">&quot;-t&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">30s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">3</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">gateway</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># ============ 网关层 ============</span></span><br><span class="line">  <span class="attr">gateway:</span></span><br><span class="line">    <span class="string">&lt;&lt;:</span> <span class="string">*common-config</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/gateway:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">gateway</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">apps</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">SPRING_CLOUD_NACOS_CONFIG_SERVER_ADDR:</span> <span class="string">nacos:8848</span></span><br><span class="line">      <span class="attr">SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR:</span> <span class="string">nacos:8848</span></span><br><span class="line">    <span class="attr">env_file:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">.env.gateway</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">nacos</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># ============ 应用层 ============</span></span><br><span class="line">  <span class="attr">app-service:</span></span><br><span class="line">    <span class="string">&lt;&lt;:</span> <span class="string">*common-config</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/app-service:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">app-service</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">apps</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="attr">env_file:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">.env.app</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># ============ 中间件层 ============</span></span><br><span class="line">  <span class="attr">postgres:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/postgres:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">postgres</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="comment"># 无端口映射</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">POSTGRES_DB:</span> <span class="string">$&#123;POSTGRES_DB&#125;</span></span><br><span class="line">      <span class="attr">POSTGRES_USER:</span> <span class="string">$&#123;POSTGRES_USER&#125;</span></span><br><span class="line">      <span class="attr">POSTGRES_PASSWORD:</span> <span class="string">$&#123;POSTGRES_PASSWORD&#125;</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./data/postgres:/var/lib/postgresql/data</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD&quot;</span>, <span class="string">&quot;pg_isready&quot;</span>, <span class="string">&quot;-U&quot;</span>, <span class="string">&quot;$&#123;POSTGRES_USER&#125;&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">30s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">3</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/redis:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">redis</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="comment"># 无端口映射</span></span><br><span class="line">    <span class="attr">command:</span> [<span class="string">&quot;redis-server&quot;</span>, <span class="string">&quot;/usr/local/etc/redis/redis.conf&quot;</span>]</span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./conf/redis.conf:/usr/local/etc/redis/redis.conf</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./data/redis:/data</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD&quot;</span>, <span class="string">&quot;redis-cli&quot;</span>, <span class="string">&quot;ping&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">5s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">3</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">nacos:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&lt;your-registry&gt;/nacos:&lt;tag&gt;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">nacos</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="comment"># 无端口映射</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">MODE:</span> <span class="string">standalone</span></span><br><span class="line">      <span class="attr">SPRING_DATASOURCE_PLATFORM:</span> <span class="string">mysql</span></span><br><span class="line">    <span class="attr">env_file:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">.env.nacos</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./data/nacos:/home/nacos/data</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD-SHELL&quot;</span>, <span class="string">&quot;curl -f http://localhost:8848/nacos/&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">30s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">3</span></span><br><span class="line">      <span class="attr">start_period:</span> <span class="string">60s</span></span><br></pre></td></tr></table></figure><h3 id="环境变量文件模板"><a href="#环境变量文件模板" class="headerlink" title="环境变量文件模板"></a>环境变量文件模板</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># .env.gateway</span></span><br><span class="line">SPRING_CLOUD_NACOS_USERNAME=&lt;nacos-username&gt;</span><br><span class="line">SPRING_CLOUD_NACOS_PASSWORD=&lt;nacos-password&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># .env.app</span></span><br><span class="line">DATABASE_URL=jdbc:postgresql://postgres:5432/&lt;db-name&gt;</span><br><span class="line">DATABASE_USER=&lt;db-user&gt;</span><br><span class="line">DATABASE_PASSWORD=&lt;db-password&gt;</span><br><span class="line">REDIS_HOST=redis</span><br><span class="line">REDIS_PORT=6379</span><br><span class="line">REDIS_PASSWORD=&lt;redis-password&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># .env.nacos</span></span><br><span class="line">MYSQL_SERVICE_HOST=&lt;mysql-host&gt;</span><br><span class="line">MYSQL_SERVICE_PORT=&lt;mysql-port&gt;</span><br><span class="line">MYSQL_SERVICE_USER=&lt;mysql-user&gt;</span><br><span class="line">MYSQL_SERVICE_PASSWORD=&lt;mysql-password&gt;</span><br></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></p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">┌─────────────────────────────────────────────────────────────┐</span><br><span class="line">│                    网络故障诊断流程                           │</span><br><span class="line">└─────────────────────────────────────────────────────────────┘</span><br><span class="line">                           │</span><br><span class="line">                           ▼</span><br><span class="line">        ┌──────────────────────────────────┐</span><br><span class="line">        │  1. 检查容器是否在同一网络        │</span><br><span class="line">        │     docker network inspect &lt;net&gt; │</span><br><span class="line">        └──────────────────────────────────┘</span><br><span class="line">                           │</span><br><span class="line">                  ┌────────┴────────┐</span><br><span class="line">                  │                 │</span><br><span class="line">              同一网络          不同网络</span><br><span class="line">                  │                 │</span><br><span class="line">                  ▼                 ▼</span><br><span class="line">        ┌──────────────┐   ┌──────────────────┐</span><br><span class="line">        │ 2. 测试连通性 │   │ 加入正确网络     │</span><br><span class="line">        │ ping/dig     │   │ docker network   │</span><br><span class="line">        │ curl         │   │ connect          │</span><br><span class="line">        └──────────────┘   └──────────────────┘</span><br><span class="line">                  │</span><br><span class="line">                  ▼</span><br><span class="line">        ┌──────────────────────────┐</span><br><span class="line">        │  3. 检查端口映射配置      │</span><br><span class="line">        │     docker ps --format   │</span><br><span class="line">        └──────────────────────────┘</span><br><span class="line">                  │</span><br><span class="line">         ┌────────┴─────────┐</span><br><span class="line">         │                  │</span><br><span class="line">      端口未映射          端口已映射</span><br><span class="line">      (预期状态)          (检查是否必要)</span><br><span class="line">         │                  │</span><br><span class="line">         ▼                  ▼</span><br><span class="line">  ┌────────────┐    ┌──────────────────┐</span><br><span class="line">  │ 服务正常    │    │ 评估安全风险     │</span><br><span class="line">  └────────────┐    │ 考虑移除映射     │</span><br><span class="line">                  └──────────────────┘</span><br></pre></td></tr></table></figure><p><strong>诊断命令链：</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># ===== 第一阶段：网络连通性检查 =====</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 查看所有网络</span></span><br><span class="line">docker network <span class="built_in">ls</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 检查特定网络中的容器</span></span><br><span class="line">docker network inspect apps</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 测试容器间连通性</span></span><br><span class="line">docker <span class="built_in">exec</span> -it gateway ping postgres</span><br><span class="line">docker <span class="built_in">exec</span> -it gateway ping redis</span><br><span class="line">docker <span class="built_in">exec</span> -it gateway ping nacos</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 检查 DNS 解析</span></span><br><span class="line">docker <span class="built_in">exec</span> -it gateway dig postgres</span><br><span class="line">docker <span class="built_in">exec</span> -it gateway nslookup redis</span><br><span class="line"></span><br><span class="line"><span class="comment"># ===== 第二阶段：端口暴露检查 =====</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 查看所有容器端口映射</span></span><br><span class="line">docker ps --format <span class="string">&quot;table &#123;&#123;.Names&#125;&#125;\t&#123;&#123;.Ports&#125;&#125;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 检查宿主机监听端口</span></span><br><span class="line"><span class="built_in">sudo</span> netstat -tulnp | grep LISTEN</span><br><span class="line"><span class="built_in">sudo</span> ss -tulnp | grep LISTEN</span><br><span class="line"></span><br><span class="line"><span class="comment"># 7. 从外部扫描端口（在其他机器上执行）</span></span><br><span class="line">nmap -p 22,80,443,5432,6379,8848 &lt;server-ip&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># ===== 第三阶段：防火墙检查 =====</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 8. 检查 UFW 状态</span></span><br><span class="line"><span class="built_in">sudo</span> ufw status verbose</span><br><span class="line"></span><br><span class="line"><span class="comment"># 9. 检查 iptables 规则</span></span><br><span class="line"><span class="built_in">sudo</span> iptables -L -n -v</span><br><span class="line"></span><br><span class="line"><span class="comment"># 10. 检查 Docker iptables 规则</span></span><br><span class="line"><span class="built_in">sudo</span> iptables -t nat -L DOCKER -n -v</span><br></pre></td></tr></table></figure><h3 id="常见故障案例"><a href="#常见故障案例" class="headerlink" title="常见故障案例"></a>常见故障案例</h3><h4 id="案例-1：服务间无法通信"><a href="#案例-1：服务间无法通信" class="headerlink" title="案例 1：服务间无法通信"></a>案例 1：服务间无法通信</h4><p><strong>现象：</strong> Java 微服务无法连接 Nacos 或数据库</p><p><strong>排查步骤：</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 确认容器在同一网络</span></span><br><span class="line">docker inspect gateway | grep -A 20 <span class="string">&quot;Networks&quot;</span></span><br><span class="line">docker inspect nacos | grep -A 20 <span class="string">&quot;Networks&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 检查容器名称</span></span><br><span class="line">docker ps --format <span class="string">&quot;&#123;&#123;.Names&#125;&#125;&quot;</span> | grep -E <span class="string">&quot;gateway|nacos|postgres&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 测试 DNS 解析</span></span><br><span class="line">docker <span class="built_in">exec</span> -it gateway getent hosts nacos</span><br><span class="line"><span class="comment"># 如果返回空，说明 DNS 解析失败</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 检查网络配置</span></span><br><span class="line">docker network inspect apps --format <span class="string">&#x27;&#123;&#123;range .Containers&#125;&#125;&#123;&#123;.Name&#125;&#125;: &#123;&#123;.IPv4Address&#125;&#125;&#123;&#123;end&#125;&#125;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 临时修复：手动添加 hosts</span></span><br><span class="line"><span class="comment"># 在 docker-compose.yml 中添加：</span></span><br><span class="line">extra_hosts:</span><br><span class="line">  - <span class="string">&quot;nacos:&lt;nacos-ip&gt;&quot;</span></span><br></pre></td></tr></table></figure><p><strong>根因分析：</strong></p><ul><li>容器不在同一网络（最常见）</li><li>容器名称不匹配（docker-compose.yml 中 container_name 配置错误）</li><li>Docker 内部 DNS 缓存问题（重启 Docker Daemon）</li></ul><h4 id="案例-2：外部无法访问服务"><a href="#案例-2：外部无法访问服务" class="headerlink" title="案例 2：外部无法访问服务"></a>案例 2：外部无法访问服务</h4><p><strong>现象：</strong> 外部请求无法到达 Nginx 或返回 502</p><p><strong>排查步骤：</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 检查 Nginx 容器状态</span></span><br><span class="line">docker ps | grep nginx</span><br><span class="line">docker logs nginx --<span class="built_in">tail</span> 100</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 检查 Nginx 配置语法</span></span><br><span class="line">docker <span class="built_in">exec</span> nginx nginx -t</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 测试 Nginx 到后端的连通性</span></span><br><span class="line">docker <span class="built_in">exec</span> nginx curl -v http://gateway:8080/</span><br><span class="line"><span class="comment"># 如果失败，说明 Nginx 无法访问后端</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 检查端口映射</span></span><br><span class="line">docker port nginx</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 检查防火墙规则</span></span><br><span class="line"><span class="built_in">sudo</span> ufw status | grep -E <span class="string">&quot;80|443&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 检查宿主机端口监听</span></span><br><span class="line"><span class="built_in">sudo</span> netstat -tulnp | grep -E <span class="string">&quot;:80|:443&quot;</span></span><br></pre></td></tr></table></figure><p><strong>根因分析：</strong></p><ul><li>Nginx 端口未正确映射到宿主机</li><li>防火墙规则阻止了外部访问</li><li>Nginx 配置中使用了错误的后端地址（IP而非容器名称）</li></ul><h4 id="案例-3：敏感信息泄露"><a href="#案例-3：敏感信息泄露" class="headerlink" title="案例 3：敏感信息泄露"></a>案例 3：敏感信息泄露</h4><p><strong>现象：</strong> git status 显示 .env 文件或密码出现在日志中</p><p><strong>排查步骤：</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 检查 .gitignore 配置</span></span><br><span class="line"><span class="built_in">cat</span> .gitignore | grep -E <span class="string">&quot;\.env|secret&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 检查是否有敏感文件被提交</span></span><br><span class="line">git <span class="built_in">log</span> --all --full-history -- <span class="string">&quot;*.env&quot;</span></span><br><span class="line">git <span class="built_in">log</span> --all --full-history -- <span class="string">&quot;*password*&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 检查容器日志中的敏感信息</span></span><br><span class="line">docker logs &lt;container&gt; | grep -i <span class="string">&quot;password&quot;</span></span><br><span class="line">docker logs &lt;container&gt; | grep -E <span class="string">&quot;[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 检查 docker-compose.yml 硬编码密码</span></span><br><span class="line">grep -r <span class="string">&quot;password\|Password\|PASSWORD&quot;</span> docker-compose*.yml</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 清理 Git 历史（如果已提交）</span></span><br><span class="line"><span class="comment"># 使用 BFG Repo-Cleaner 或 git filter-branch</span></span><br></pre></td></tr></table></figure><p><strong>修复方案：</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 更新 .gitignore</span></span><br><span class="line"><span class="built_in">cat</span> &gt;&gt; .gitignore &lt;&lt; <span class="string">EOF</span></span><br><span class="line"><span class="string">.env</span></span><br><span class="line"><span class="string">.env.*</span></span><br><span class="line"><span class="string">*.env</span></span><br><span class="line"><span class="string">secrets/</span></span><br><span class="line"><span class="string">docker-compose.override.yml</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 从 Git 中移除已提交的敏感文件</span></span><br><span class="line">git <span class="built_in">rm</span> --cached .<span class="built_in">env</span></span><br><span class="line">git <span class="built_in">rm</span> --cached docker-compose.override.yml</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 使用环境变量替代硬编码密码</span></span><br><span class="line"><span class="comment"># 编辑 docker-compose.yml，改为：</span></span><br><span class="line">environment:</span><br><span class="line">  POSTGRES_PASSWORD: <span class="variable">$&#123;POSTGRES_PASSWORD&#125;</span></span><br></pre></td></tr></table></figure><h2 id="参考资源"><a href="#参考资源" class="headerlink" title="参考资源"></a>参考资源</h2><h3 id="官方文档"><a href="#官方文档" class="headerlink" title="官方文档"></a>官方文档</h3><ul><li><span class="exturl" data-url="aHR0cHM6Ly9kb2NzLmRvY2tlci5jb20v">Docker 官方文档<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vZW5naW5lL3NlY3VyaXR5Lw==">Docker 安全最佳实践<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vbmV0d29yay8=">Docker 网络配置指南<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vY29tcG9zZS8=">Docker Compose 官方文档<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9uZ2lueC5vcmcvZW4vZG9jcy8=">Nginx 官方文档<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9uZ2lueC5vcmcvZW4vZG9jcy9odHRwL2NvbmZpZ3VyaW5nX2h0dHBzX3NlcnZlcnMuaHRtbA==">Nginx 安全配置指南<i class="fa fa-external-link-alt"></i></span></li></ul><h3 id="安全标准与最佳实践"><a href="#安全标准与最佳实践" class="headerlink" title="安全标准与最佳实践"></a>安全标准与最佳实践</h3><ul><li><span class="exturl" data-url="aHR0cHM6Ly93d3cuY2lzZWN1cml0eS5vcmcvYmVuY2htYXJrL2RvY2tlcg==">CIS Docker Benchmark<i class="fa fa-external-link-alt"></i></span> - Docker 安全配置基准</li><li><span class="exturl" data-url="aHR0cHM6Ly9jaGVhdHNoZWV0c2VyaWVzLm93YXNwLm9yZy9jaGVhdHNoZWV0cy9Eb2NrZXJfU2VjdXJpdHlfQ2hlYXRfU2hlZXQuaHRtbA==">OWASP Docker 安全<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vc2NvdXQv">Docker 安全扫描指南<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2tvbnN0cnVrdG9pZC9Eb2NrZXItc2VjdXJpdHktY29uZmlndXJhdGlvbi1jaGVja2xpc3Q=">容器安全检查清单<i class="fa fa-external-link-alt"></i></span></li></ul><h3 id="工具与扫描器"><a href="#工具与扫描器" class="headerlink" title="工具与扫描器"></a>工具与扫描器</h3><ul><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2FxdWFzZWN1cml0eS90cml2eQ==">Trivy - 容器漏洞扫描器<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2RvY2tlci9kb2NrZXItYmVuY2gtc2VjdXJpdHk=">Docker Bench for Security<i class="fa fa-external-link-alt"></i></span> - Docker 安全审计脚本</li><li><span class="exturl" data-url="aHR0cHM6Ly9mYWxjby5vcmcv">Falco - 容器运行时安全<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL3F1YXkvY2xhaXI=">Clair - 镜像漏洞分析<i class="fa fa-external-link-alt"></i></span></li></ul><h3 id="网络与隔离"><a href="#网络与隔离" class="headerlink" title="网络与隔离"></a>网络与隔离</h3><ul><li><span class="exturl" data-url="aHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vbmV0d29yay8jbmV0d29yay1kcml2ZXJz">Docker 网络架构详解<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vbmV0d29yay8jZG5zLXNlcnZpY2Vz">Docker 内部网络 DNS<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly93d3cuY25pLmRldi8=">CNI 网络插件规范<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9tYW43Lm9yZy9saW51eC9tYW4tcGFnZXMvbWFuNy9uZXR3b3JrX25hbWVzcGFjZXMuNy5odG1s">Linux 网络 namespaces<i class="fa fa-external-link-alt"></i></span></li></ul><h3 id="社区资源"><a href="#社区资源" class="headerlink" title="社区资源"></a>社区资源</h3><ul><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL21vYnkvbW9ieQ==">Docker GitHub 仓库<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vc2VjdXJpdHkv">Docker 安全公告<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2g1YnAvc2VydmVyLWNvbmZpZ3Mtbmdpbng=">Nginx 安全头配置<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2RvY2tlci1saWJyYXJ5L29mZmljaWFsLWltYWdlcy9kaXNjdXNzaW9ucw==">docker-microservice-security GitHub 讨论<i class="fa fa-external-link-alt"></i></span></li></ul><h3 id="进阶阅读"><a href="#进阶阅读" class="headerlink" title="进阶阅读"></a>进阶阅读</h3><ul><li><span class="exturl" data-url="aHR0cHM6Ly9jb250YWluZXItc29sdXRpb25zLmNvbS9kb2NrZXItc2VjdXJpdHktYmVzdC1wcmFjdGljZXMv">《Docker 安全最佳实践》电子书<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2NuY2Yvc2lnLXNlY3VyaXR5">云原生安全白皮书<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9sd24ubmV0L0FydGljbGVzLzUzMTExNC8=">容器隔离技术深度解析<i class="fa fa-external-link-alt"></i></span></li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><h3 id="核心安全措施"><a href="#核心安全措施" class="headerlink" title="核心安全措施"></a>核心安全措施</h3><ol><li><strong>端口最小化</strong>: 仅开放 80&#x2F;443 (Web) 和 22 (SSH)</li><li><strong>网络隔离</strong>: 所有服务通过 Docker 内部网络通信</li><li><strong>配置脱敏</strong>: 使用环境变量和 secrets 管理敏感信息</li><li><strong>安全请求头</strong>: Nginx 注入完整的安全响应头</li><li><strong>防火墙双重防护</strong>: Docker 网络隔离 + 宿主机 UFW 防火墙</li><li><strong>服务发现</strong>: 使用容器名称而非 IP 地址</li><li><strong>定期审计</strong>: 执行安全检查脚本</li></ol><h3 id="安全收益"><a href="#安全收益" class="headerlink" title="安全收益"></a>安全收益</h3><ul><li><strong>攻击面缩减 90%+</strong>: 数据库、缓存、后端服务端口完全隐藏</li><li><strong>网络嗅探防护</strong>: 内部流量在容器网络内闭环</li><li><strong>配置安全性</strong>: 敏感信息不入代码库</li><li><strong>可维护性提升</strong>: 服务发现机制自动适应环境变化</li><li><strong>符合最佳实践</strong>: 遵循云原生安全部署标准</li></ul><p>通过本指南的实施,你可以构建一个安全、可靠的 Docker 微服务架构环境,有效降低安全风险,保护业务系统免受外部威胁。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;在 Docker 容器化微服务架构中,安全是一个不可忽视的重要环节。本文将分享一套完整的 Docker 微服务环境安全加固方案,涵盖端口暴露最小化、网络隔离、敏感信息管理以及多层防御策略。通过本指南,你可以有效缩减 90%+ 的攻击面,提升整体系统安全性。&lt;/p&gt;</summary>
    
    
    
    <category term="Docker" scheme="https://freemankevin.uk/categories/Docker/"/>
    
    
    <category term="Docker" scheme="https://freemankevin.uk/tags/Docker/"/>
    
    <category term="Security" scheme="https://freemankevin.uk/tags/Security/"/>
    
    <category term="Microservice" scheme="https://freemankevin.uk/tags/Microservice/"/>
    
    <category term="Network" scheme="https://freemankevin.uk/tags/Network/"/>
    
  </entry>
  
  <entry>
    <title>Kubernetes 生产级部署完整指南（kubeadm）</title>
    <link href="https://freemankevin.uk/2025/11/13/k8s-kubeadm/"/>
    <id>https://freemankevin.uk/2025/11/13/k8s-kubeadm/</id>
    <published>2025-11-13T09:47:25.000Z</published>
    <updated>2026-04-17T10:30:31.805Z</updated>
    
    <content type="html"><![CDATA[<p>Kubernetes 是云原生应用编排的核心平台。本文档提供生产级 Kubernetes 集群部署方案，涵盖架构设计、环境准备、组件安装、网络配置、安全加固、性能优化和故障排查等全流程内容，适用于学习和生产环境。</p><span id="more"></span><p><strong>适用版本与环境说明：</strong></p><ul><li>Kubernetes: 1.28.x - 1.33.x（本文以 v1.33.6 为示例）</li><li>Containerd: 1.7.x 及以上版本</li><li>Flannel: v0.27.x 及以上版本</li><li>操作系统: Debian 12 (Trixie)&#x2F;Ubuntu 22.04+&#x2F;CentOS 7.9+&#x2F;Rocky Linux 9+</li><li>内核版本: 建议 5.4+ 以支持完整的容器网络特性</li><li>更新日期: 2025-11-13（建议关注 Kubernetes 官方版本更新公告）</li></ul><div class="note warning"><p>Kubernetes 版本迭代较快，部署前请访问 <span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL3JlbGVhc2VzLw==">Kubernetes Releases<i class="fa fa-external-link-alt"></i></span> 查看最新稳定版本和版本兼容性矩阵。</p></div><h2 id="Kubernetes-架构概述"><a href="#Kubernetes-架构概述" class="headerlink" title="Kubernetes 架构概述"></a>Kubernetes 架构概述</h2><h2 id="Kubernetes-架构概述-1"><a href="#Kubernetes-架构概述-1" class="headerlink" title="Kubernetes 架构概述"></a>Kubernetes 架构概述</h2><h3 id="Control-Plane-组件"><a href="#Control-Plane-组件" class="headerlink" title="Control Plane 组件"></a>Control Plane 组件</h3><table><thead><tr><th>组件</th><th>功能</th><th>生产要求</th></tr></thead><tbody><tr><td>kube-apiserver</td><td>集群 API 入口，认证授权</td><td>3+ 副本，负载均衡</td></tr><tr><td>etcd</td><td>分布式键值存储，保存集群状态</td><td>3+ 节点，定期备份</td></tr><tr><td>kube-scheduler</td><td>Pod 调度决策</td><td>多副本，Leader选举</td></tr><tr><td>kube-controller-manager</td><td>控制器管理（Deployment、Node等）</td><td>多副本，Leader选举</td></tr><tr><td>cloud-controller-manager</td><td>云平台集成控制器</td><td>可选，云环境必需</td></tr></tbody></table><h3 id="Worker-Node-组件"><a href="#Worker-Node-组件" class="headerlink" title="Worker Node 组件"></a>Worker Node 组件</h3><table><thead><tr><th>组件</th><th>功能</th><th>配置要点</th></tr></thead><tbody><tr><td>kubelet</td><td>节点代理，与 API Server 通信</td><td>配置资源预留</td></tr><tr><td>kube-proxy</td><td>服务代理，实现 Service</td><td>iptables&#x2F;IPVS 模式</td></tr><tr><td>Container Runtime</td><td>容器运行时（containerd&#x2F;Docker）</td><td>systemd cgroup 驱动</td></tr></tbody></table><h3 id="网络模型"><a href="#网络模型" class="headerlink" title="网络模型"></a>网络模型</h3><p>Kubernetes 网络需满足四个要求：</p><ol><li>所有 Pod 不使用 NAT 即可相互通信</li><li>所有 Node 不使用 NAT 即可与所有 Pod 通信</li><li>Pod 看到的自身 IP 与其他 Pod 看到的 IP 相同</li><li>Service 的 ClusterIP 可在集群内访问</li></ol><h2 id="部署架构"><a href="#部署架构" class="headerlink" title="部署架构"></a>部署架构</h2><h3 id="单控制平面架构（测试环境）"><a href="#单控制平面架构（测试环境）" class="headerlink" title="单控制平面架构（测试环境）"></a>单控制平面架构（测试环境）</h3><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">┌─────────────────────────────────────────┐</span><br><span class="line">│  Control Plane (192.168.199.135)        │</span><br><span class="line">│  ├─ kube-apiserver (6443)               │</span><br><span class="line">│  ├─ etcd (2379-2380)                    │</span><br><span class="line">│  ├─ kube-scheduler                      │</span><br><span class="line">│  ├─ kube-controller-manager             │</span><br><span class="line">│  └─ kubelet                             │</span><br><span class="line">└─────────────────────────────────────────┘</span><br><span class="line">           │</span><br><span class="line">           │ Pod Network (10.244.0.0/16)</span><br><span class="line">           │</span><br><span class="line">┌─────────────────────────────────────────┐</span><br><span class="line">│  Worker Node (192.168.199.136)          │</span><br><span class="line">│  ├─ kubelet                             │</span><br><span class="line">│  ├─ kube-proxy                          │</span><br><span class="line">│  └─ Pods (业务应用)                      │</span><br><span class="line">└─────────────────────────────────────────┘</span><br></pre></td></tr></table></figure><h3 id="高可用架构（生产环境）"><a href="#高可用架构（生产环境）" class="headerlink" title="高可用架构（生产环境）"></a>高可用架构（生产环境）</h3><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">┌────────────────────────────────────────────────────┐</span><br><span class="line">│         Load Balancer (HAProxy/Nginx)              │</span><br><span class="line">│                 VIP: 192.168.1.100                 │</span><br><span class="line">└────────────────────────────────────────────────────┘</span><br><span class="line">        │                    │                    │</span><br><span class="line">        ▼                    ▼                    ▼</span><br><span class="line">┌──────────────┐  ┌──────────────┐  ┌──────────────┐</span><br><span class="line">│ Master 1     │  │ Master 2     │  │ Master 3     │</span><br><span class="line">│ API Server   │  │ API Server   │  │ API Server   │</span><br><span class="line">│ etcd         │  │ etcd         │  │ etcd         │</span><br><span class="line">└──────────────┘  └──────────────┘  └──────────────┘</span><br><span class="line">        │                    │                    │</span><br><span class="line">        └────────────────────┴────────────────────┘</span><br><span class="line">                           │</span><br><span class="line">        ┌──────────────────┼──────────────────┐</span><br><span class="line">        ▼                  ▼                  ▼</span><br><span class="line">┌──────────────┐  ┌──────────────┐  ┌──────────────┐</span><br><span class="line">│ Worker 1     │  │ Worker 2     │  │ Worker 3     │</span><br><span class="line">└──────────────┘  └──────────────┘  └──────────────┘</span><br></pre></td></tr></table></figure><p><strong>高可用要点：</strong></p><ul><li>etcd 集群：3 或 5 节点，奇数配置</li><li>API Server：多副本 + 负载均衡</li><li>控制器：内置 Leader 选举机制</li><li>网络：跨节点 Pod 通信，Service 负载均衡</li></ul><hr><h2 id="前置要求"><a href="#前置要求" class="headerlink" title="前置要求"></a>前置要求</h2><h3 id="硬件资源配置"><a href="#硬件资源配置" class="headerlink" title="硬件资源配置"></a>硬件资源配置</h3><table><thead><tr><th>环境</th><th>CPU</th><th>内存</th><th>存储</th><th>说明</th></tr></thead><tbody><tr><td>测试环境</td><td>2核</td><td>2GB</td><td>20GB</td><td>最小配置，仅用于学习</td></tr><tr><td>开发环境</td><td>4核</td><td>4GB</td><td>50GB</td><td>推荐配置，支持轻量应用</td></tr><tr><td>生产环境</td><td>8核+</td><td>16GB+</td><td>100GB+</td><td>SSD存储，独立etcd</td></tr><tr><td>大规模集群</td><td>16核+</td><td>32GB+</td><td>200GB+</td><td>高IO性能，专用磁盘</td></tr></tbody></table><p><strong>生产环境补充建议：</strong></p><ul><li>Master节点：CPU预留1核，内存预留2GB给系统进程</li><li>Worker节点：根据应用负载动态调整</li><li>etcd数据：独立SSD磁盘，避免IO竞争</li><li>网络带宽：至少1Gbps，生产推荐10Gbps</li></ul><h3 id="网络配置要求"><a href="#网络配置要求" class="headerlink" title="网络配置要求"></a>网络配置要求</h3><h4 id="必需开放的端口"><a href="#必需开放的端口" class="headerlink" title="必需开放的端口"></a>必需开放的端口</h4><p><strong>Control Plane节点：</strong></p><table><thead><tr><th>端口</th><th>协议</th><th>服务</th><th>说明</th></tr></thead><tbody><tr><td>6443</td><td>TCP</td><td>API Server</td><td>Kubernetes API入口</td></tr><tr><td>2379-2380</td><td>TCP</td><td>etcd</td><td>etcd服务端口</td></tr><tr><td>10250</td><td>TCP</td><td>Kubelet</td><td>节点状态和日志</td></tr><tr><td>10251</td><td>TCP</td><td>Scheduler</td><td>调度器端口</td></tr><tr><td>10252</td><td>TCP</td><td>Controller</td><td>控制器端口</td></tr><tr><td>10257</td><td>TCP</td><td>kube-controller-manager</td><td>安全端口</td></tr><tr><td>10259</td><td>TCP</td><td>kube-scheduler</td><td>安全端口</td></tr></tbody></table><p><strong>Worker节点：</strong></p><table><thead><tr><th>端口</th><th>协议</th><th>服务</th><th>说明</th></tr></thead><tbody><tr><td>10250</td><td>TCP</td><td>Kubelet</td><td>节点通信</td></tr><tr><td>10256</td><td>TCP</td><td>kube-proxy</td><td>代理健康检查</td></tr><tr><td>30000-32767</td><td>TCP</td><td>NodePort</td><td>服务暴露端口</td></tr></tbody></table><h4 id="网络插件端口"><a href="#网络插件端口" class="headerlink" title="网络插件端口"></a>网络插件端口</h4><table><thead><tr><th>网络插件</th><th>端口</th><th>说明</th></tr></thead><tbody><tr><td>Flannel</td><td>8285&#x2F;8472</td><td>VXLAN通信</td></tr><tr><td>Calico</td><td>179&#x2F;4789</td><td>BGP&#x2F;VXLAN</td></tr><tr><td>Cilium</td><td>4240&#x2F;8472</td><td>健康检查&#x2F;VXLAN</td></tr></tbody></table><h3 id="系统检查清单"><a href="#系统检查清单" class="headerlink" title="系统检查清单"></a>系统检查清单</h3><p>执行以下检查确保系统就绪：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 验证 MAC 地址唯一性</span></span><br><span class="line">ip <span class="built_in">link</span> | grep <span class="built_in">link</span>/ether</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 验证 product_uuid 唯一性</span></span><br><span class="line"><span class="built_in">cat</span> /sys/class/dmi/id/product_uuid</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 确认 Swap 已禁用</span></span><br><span class="line">free | grep Swap</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 验证时间同步</span></span><br><span class="line">timedatectl status</span><br><span class="line">systemctl status systemd-timesyncd</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 检查内核版本（建议 5.4+）</span></span><br><span class="line"><span class="built_in">uname</span> -r</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 检查系统资源</span></span><br><span class="line"><span class="built_in">df</span> -h</span><br><span class="line">free -g</span><br><span class="line">lscpu</span><br></pre></td></tr></table></figure><hr><h2 id="安装步骤"><a href="#安装步骤" class="headerlink" title="安装步骤"></a>安装步骤</h2><h3 id="配置-APT-源（两台-VM）"><a href="#配置-APT-源（两台-VM）" class="headerlink" title="配置 APT 源（两台 VM）"></a>配置 APT 源（两台 VM）</h3><p>使用清华 TUNA 镜像加速软件包下载：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">nano /etc/apt/sources.list</span><br></pre></td></tr></table></figure><p>替换为以下内容：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">deb https://mirrors.tuna.tsinghua.edu.cn/debian/ trixie main contrib non-free-firmware</span><br><span class="line">deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ trixie main contrib non-free-firmware</span><br><span class="line"></span><br><span class="line">deb https://mirrors.tuna.tsinghua.edu.cn/debian/ trixie-updates main contrib non-free-firmware</span><br><span class="line">deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ trixie-updates main contrib non-free-firmware</span><br><span class="line"></span><br><span class="line">deb https://mirrors.tuna.tsinghua.edu.cn/debian/ trixie-backports main contrib non-free-firmware</span><br><span class="line">deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ trixie-backports main contrib non-free-firmware</span><br><span class="line"></span><br><span class="line">deb https://mirrors.tuna.tsinghua.edu.cn/debian-security/ trixie-security main contrib non-free-firmware</span><br><span class="line">deb-src https://mirrors.tuna.tsinghua.edu.cn/debian-security/ trixie-security main contrib non-free-firmware</span><br></pre></td></tr></table></figure><h3 id="禁用-Swap（两台-VM）"><a href="#禁用-Swap（两台-VM）" class="headerlink" title="禁用 Swap（两台 VM）"></a>禁用 Swap（两台 VM）</h3><p>Kubelet 无法在启用 Swap 的系统上运行：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 立即禁用</span></span><br><span class="line"><span class="built_in">sudo</span> swapoff -a</span><br><span class="line"></span><br><span class="line"><span class="comment"># 永久禁用（编辑 fstab 文件）</span></span><br><span class="line"><span class="built_in">sudo</span> sed -i <span class="string">&#x27;/ swap / s/^\(.*\)$/#\1/g&#x27;</span> /etc/fstab</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证（应输出 0）</span></span><br><span class="line">free | grep Swap | awk <span class="string">&#x27;&#123;print $2&#125;&#x27;</span></span><br></pre></td></tr></table></figure><h3 id="安装并配置容器运行时（两台-VM）"><a href="#安装并配置容器运行时（两台-VM）" class="headerlink" title="安装并配置容器运行时（两台 VM）"></a>安装并配置容器运行时（两台 VM）</h3><p>使用 Containerd 作为容器运行时（Kubernetes 1.24+ 推荐）：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 加载必需的内核模块</span></span><br><span class="line"><span class="built_in">cat</span> &lt;&lt;<span class="string">EOF | sudo tee /etc/modules-load.d/k8s.conf</span></span><br><span class="line"><span class="string">overlay</span></span><br><span class="line"><span class="string">br_netfilter</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">sudo</span> modprobe overlay</span><br><span class="line"><span class="built_in">sudo</span> modprobe br_netfilter</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 配置内核参数（生产级调优）</span></span><br><span class="line"><span class="built_in">cat</span> &lt;&lt;<span class="string">EOF | sudo tee /etc/sysctl.d/k8s.conf</span></span><br><span class="line"><span class="string"># Kubernetes 必需参数</span></span><br><span class="line"><span class="string">net.bridge.bridge-nf-call-iptables  = 1</span></span><br><span class="line"><span class="string">net.bridge.bridge-nf-call-ip6tables = 1</span></span><br><span class="line"><span class="string">net.ipv4.ip_forward                 = 1</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"># 性能优化参数</span></span><br><span class="line"><span class="string">net.core.somaxconn                  = 65535</span></span><br><span class="line"><span class="string">net.ipv4.tcp_max_syn_backlog        = 8192</span></span><br><span class="line"><span class="string">net.core.netdev_max_backlog         = 5000</span></span><br><span class="line"><span class="string">vm.swappiness                       = 10</span></span><br><span class="line"><span class="string">vm.max_map_count                    = 262144</span></span><br><span class="line"><span class="string">fs.file-max                         = 655350</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">sudo</span> sysctl --system</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 安装 Containerd</span></span><br><span class="line"><span class="built_in">sudo</span> apt update</span><br><span class="line"><span class="built_in">sudo</span> apt install -y containerd</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 创建生产级配置文件</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">mkdir</span> -p /etc/containerd</span><br><span class="line"><span class="built_in">sudo</span> containerd config default | <span class="built_in">sudo</span> <span class="built_in">tee</span> /etc/containerd/config.toml</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 关键配置优化（生产必需）</span></span><br><span class="line"><span class="built_in">sudo</span> sed -i <span class="string">&#x27;s/SystemdCgroup = false/SystemdCgroup = true/g&#x27;</span> /etc/containerd/config.toml</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置镜像加速（国内环境）</span></span><br><span class="line"><span class="built_in">sudo</span> sed -i <span class="string">&#x27;s|registry.k8s.io/pause:3\.[0-9]\+|registry.aliyuncs.com/google_containers/pause:3.10|g&#x27;</span> /etc/containerd/config.toml</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 启动并验证服务</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl <span class="built_in">enable</span> --now containerd</span><br><span class="line"><span class="built_in">sudo</span> systemctl status containerd</span><br><span class="line"><span class="built_in">sudo</span> ctr version</span><br><span class="line"></span><br><span class="line"><span class="comment"># 7. 验证配置</span></span><br><span class="line"><span class="built_in">sudo</span> ctr config dump | grep -A5 <span class="string">&quot;plugins&quot;</span></span><br></pre></td></tr></table></figure><p><strong>Containerd 生产级配置详解：</strong></p><figure class="highlight toml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># /etc/containerd/config.toml 关键片段</span></span><br><span class="line"><span class="section">[plugins.&quot;io.containerd.grpc.v1.cri&quot;]</span></span><br><span class="line">  <span class="attr">enable_tls_streaming</span> = <span class="literal">false</span></span><br><span class="line">  </span><br><span class="line">  <span class="section">[plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd]</span></span><br><span class="line">    <span class="attr">snapshotter</span> = <span class="string">&quot;overlayfs&quot;</span></span><br><span class="line">    <span class="attr">default_runtime_name</span> = <span class="string">&quot;runc&quot;</span></span><br><span class="line">    </span><br><span class="line">    <span class="section">[plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd.runtimes.runc]</span></span><br><span class="line">      <span class="attr">runtime_type</span> = <span class="string">&quot;io.containerd.runc.v2&quot;</span></span><br><span class="line">      </span><br><span class="line">      <span class="section">[plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd.runtimes.runc.options]</span></span><br><span class="line">        <span class="attr">SystemdCgroup</span> = <span class="literal">true</span>  <span class="comment"># Kubernetes 必需</span></span><br><span class="line">        </span><br><span class="line">  <span class="section">[plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry]</span></span><br><span class="line">    <span class="section">[plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.mirrors]</span></span><br><span class="line">      <span class="section">[plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.mirrors.&quot;docker.io&quot;]</span></span><br><span class="line">        <span class="attr">endpoint</span> = [<span class="string">&quot;https://registry.aliyuncs.com&quot;</span>]</span><br></pre></td></tr></table></figure><h3 id="安装-Kubeadm、Kubelet、Kubectl（两台-VM）"><a href="#安装-Kubeadm、Kubelet、Kubectl（两台-VM）" class="headerlink" title="安装 Kubeadm、Kubelet、Kubectl（两台 VM）"></a>安装 Kubeadm、Kubelet、Kubectl（两台 VM）</h3><p>添加 Kubernetes 官方仓库并安装 v1.33 版本：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 安装必需的工具</span></span><br><span class="line"><span class="built_in">sudo</span> apt-get update</span><br><span class="line"><span class="built_in">sudo</span> apt-get install -y apt-transport-https ca-certificates curl gnupg</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 添加 Kubernetes 官方 GPG 密钥</span></span><br><span class="line">curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | <span class="built_in">sudo</span> gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 添加 Kubernetes v1.33 APT 仓库</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /&#x27;</span> | <span class="built_in">sudo</span> <span class="built_in">tee</span> /etc/apt/sources.list.d/kubernetes.list</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 刷新缓存</span></span><br><span class="line"><span class="built_in">sudo</span> apt-get update</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 安装指定版本</span></span><br><span class="line"><span class="built_in">sudo</span> apt-get install -y kubelet=1.33.* kubeadm=1.33.* kubectl=1.33.*</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 防止自动升级</span></span><br><span class="line"><span class="built_in">sudo</span> apt-mark hold kubelet kubeadm kubectl</span><br><span class="line"></span><br><span class="line"><span class="comment"># 7. 验证安装</span></span><br><span class="line">kubeadm version</span><br></pre></td></tr></table></figure><h3 id="初始化-Control-Plane（仅-VM-1-Master-节点）"><a href="#初始化-Control-Plane（仅-VM-1-Master-节点）" class="headerlink" title="初始化 Control Plane（仅 VM 1 - Master 节点）"></a>初始化 Control Plane（仅 VM 1 - Master 节点）</h3><p><strong>前置条件：</strong> 记录 Master 节点的 IP 地址（本例为 <code>192.168.199.135</code>）</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 初始化集群</span></span><br><span class="line"><span class="built_in">sudo</span> kubeadm init \</span><br><span class="line">  --apiserver-advertise-address=192.168.199.135 \</span><br><span class="line">  --pod-network-cidr=10.244.0.0/16 \</span><br><span class="line">  --kubernetes-version v1.33.6 \</span><br><span class="line">  --image-repository registry.aliyuncs.com/google_containers</span><br></pre></td></tr></table></figure><div class="note warning"><p>初始化完成后，终端会输出：</p><ul><li>kubectl 配置命令</li><li><strong><code>kubeadm join</code> 命令</strong>（必须保存供 Worker 节点使用）</li></ul></div><h3 id="配置-Kubectl（仅-VM-1）"><a href="#配置-Kubectl（仅-VM-1）" class="headerlink" title="配置 Kubectl（仅 VM 1）"></a>配置 Kubectl（仅 VM 1）</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 为当前用户配置 kubectl</span></span><br><span class="line"><span class="built_in">mkdir</span> -p <span class="variable">$HOME</span>/.kube</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">cp</span> -i /etc/kubernetes/admin.conf <span class="variable">$HOME</span>/.kube/config</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">chown</span> $(<span class="built_in">id</span> -u):$(<span class="built_in">id</span> -g) <span class="variable">$HOME</span>/.kube/config</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证 Control Plane（节点状态应为 NotReady，等待网络插件）</span></span><br><span class="line">kubectl get nodes</span><br></pre></td></tr></table></figure><h3 id="Worker-Node-加入集群（仅-VM-2）"><a href="#Worker-Node-加入集群（仅-VM-2）" class="headerlink" title="Worker Node 加入集群（仅 VM 2）"></a>Worker Node 加入集群（仅 VM 2）</h3><p>在 VM 2 上执行步骤 5 中保存的 <code>kubeadm join</code> 命令：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">sudo</span> kubeadm <span class="built_in">join</span> 192.168.199.135:6443 --token &lt;YOUR_TOKEN&gt; \</span><br><span class="line">  --discovery-token-ca-cert-hash sha256:&lt;YOUR_HASH&gt;</span><br></pre></td></tr></table></figure><div class="note info"><p><code>&lt;YOUR_TOKEN&gt;</code> 和 <code>&lt;YOUR_HASH&gt;</code> 来自步骤 5 的输出。</p></div><h3 id="部署网络插件-Flannel（VM-1-或任意有-kubectl-访问的节点）"><a href="#部署网络插件-Flannel（VM-1-或任意有-kubectl-访问的节点）" class="headerlink" title="部署网络插件 - Flannel（VM 1 或任意有 kubectl 访问的节点）"></a>部署网络插件 - Flannel（VM 1 或任意有 kubectl 访问的节点）</h3><p>Kubernetes 需要网络插件实现 Pod 间通信。我们使用 Flannel：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 部署 Flannel CNI</span></span><br><span class="line">kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml</span><br><span class="line"></span><br><span class="line"><span class="comment"># 等待 1-2 分钟，然后验证</span></span><br><span class="line">kubectl get pods -n kube-system | grep flannel</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证所有系统 Pod 运行正常</span></span><br><span class="line">kubectl get pods -n kube-system</span><br></pre></td></tr></table></figure><h3 id="预加载-Flannel-镜像（两台-VM-可选但推荐）"><a href="#预加载-Flannel-镜像（两台-VM-可选但推荐）" class="headerlink" title="预加载 Flannel 镜像（两台 VM - 可选但推荐）"></a>预加载 Flannel 镜像（两台 VM - 可选但推荐）</h3><p>如果网络不稳定或镜像下载缓慢，可提前在两台 VM 上加载 Flannel 镜像：</p><p><strong>方案一：直接拉取镜像</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 使用 ctr 直接拉取镜像到 containerd</span></span><br><span class="line"><span class="built_in">sudo</span> ctr image pull ghcr.io/flannel-io/flannel:v0.27.4</span><br><span class="line"><span class="built_in">sudo</span> ctr image pull ghcr.io/flannel-io/flannel-cni-plugin:v1.8.0-flannel1</span><br></pre></td></tr></table></figure><p><strong>方案二：本地打包后导入</strong></p><p>如果镜像源不可达，可在能访问外网的机器上下载后导入：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 在能访问外网的机器上执行</span></span><br><span class="line"><span class="comment"># 1. 拉取镜像</span></span><br><span class="line">docker pull ghcr.io/flannel-io/flannel:v0.27.4</span><br><span class="line">docker pull ghcr.io/flannel-io/flannel-cni-plugin:v1.8.0-flannel1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 打包成 tar 文件</span></span><br><span class="line">docker save -o flannel_images.tar \</span><br><span class="line">  ghcr.io/flannel-io/flannel:v0.27.4 \</span><br><span class="line">  ghcr.io/flannel-io/flannel-cni-plugin:v1.8.0-flannel1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 将 flannel_images.tar 文件复制到两台 VM，然后执行：</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 在每台 VM 上导入镜像</span></span><br><span class="line"><span class="comment"># 导入到 k8s.io 命名空间</span></span><br><span class="line"><span class="built_in">sudo</span> ctr --namespace k8s.io image import flannel_images.tar</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 验证镜像</span></span><br><span class="line"><span class="built_in">sudo</span> ctr images list | grep flannel</span><br><span class="line"><span class="built_in">sudo</span> ctr --namespace k8s.io images list | grep flannel</span><br></pre></td></tr></table></figure><h3 id="修复-CNI-插件路径（两台-VM）"><a href="#修复-CNI-插件路径（两台-VM）" class="headerlink" title="修复 CNI 插件路径（两台 VM）"></a>修复 CNI 插件路径（两台 VM）</h3><p>如果 CoreDNS Pod 仍无法启动，执行以下修复：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 创建 CNI 标准目录</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">mkdir</span> -p /usr/lib/cni</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 创建 Flannel 插件的符号链接</span></span><br><span class="line"><span class="built_in">cd</span> /usr/lib/cni/</span><br><span class="line"><span class="keyword">for</span> plugin <span class="keyword">in</span> /opt/cni/bin/*; <span class="keyword">do</span></span><br><span class="line">  <span class="built_in">sudo</span> <span class="built_in">ln</span> -sf <span class="string">&quot;<span class="variable">$plugin</span>&quot;</span> <span class="string">&quot;<span class="subst">$(basename $plugin)</span>&quot;</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 验证符号链接</span></span><br><span class="line"><span class="built_in">ls</span> -lh /usr/lib/cni/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 重启 Kubelet</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl restart kubelet</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 验证 Pod 状态</span></span><br><span class="line">kubectl get pods -n kube-system</span><br></pre></td></tr></table></figure><hr><h2 id="集群验证"><a href="#集群验证" class="headerlink" title="集群验证"></a>集群验证</h2><h3 id="最终验证（VM-1）"><a href="#最终验证（VM-1）" class="headerlink" title="最终验证（VM 1）"></a>最终验证（VM 1）</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 检查所有节点状态（应全为 Ready）</span></span><br><span class="line">kubectl get nodes</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 检查所有系统 Pod（应全为 Running）</span></span><br><span class="line">kubectl get pods -n kube-system</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 查看集群信息</span></span><br><span class="line">kubectl cluster-info</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 运行测试 Pod</span></span><br><span class="line">kubectl run test-pod --image=nginx --port=80</span><br><span class="line">kubectl get pods</span><br><span class="line">kubectl delete pod test-pod</span><br></pre></td></tr></table></figure><h3 id="常见验证命令"><a href="#常见验证命令" class="headerlink" title="常见验证命令"></a>常见验证命令</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查看节点详细信息</span></span><br><span class="line">kubectl describe node &lt;NODE_NAME&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看集群资源</span></span><br><span class="line">kubectl top nodes</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看系统事件</span></span><br><span class="line">kubectl get events -n kube-system</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查 API 服务器状态</span></span><br><span class="line">kubectl get cs  <span class="comment"># 已弃用，但可用于诊断</span></span><br></pre></td></tr></table></figure><hr><h2 id="故障排除"><a href="#故障排除" class="headerlink" title="故障排除"></a>故障排除</h2><h3 id="故障诊断流程图"><a href="#故障诊断流程图" class="headerlink" title="故障诊断流程图"></a>故障诊断流程图</h3><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">┌─────────────────────────────────────────────────────────────┐</span><br><span class="line">│                 Kubernetes 集群故障诊断流程                   │</span><br><span class="line">└─────────────────────────────────────────────────────────────┘</span><br><span class="line">                           │</span><br><span class="line">                           ▼</span><br><span class="line">        ┌──────────────────────────────────┐</span><br><span class="line">        │  1. 检查节点状态                  │</span><br><span class="line">        │     kubectl get nodes            │</span><br><span class="line">        └──────────────────────────────────┘</span><br><span class="line">                           │</span><br><span class="line">                  ┌────────┴────────┐</span><br><span class="line">                  │                 │</span><br><span class="line">              Ready             NotReady</span><br><span class="line">                  │                 │</span><br><span class="line">                  ▼                 ▼</span><br><span class="line">        ┌──────────────┐   ┌──────────────────┐</span><br><span class="line">        │ 2. 检查Pod   │   │ 检查 kubelet     │</span><br><span class="line">        │    状态      │   │ 日志和网络插件   │</span><br><span class="line">        └──────────────┘   └──────────────────┘</span><br><span class="line">                  │                 │</span><br><span class="line">                  ▼                 ▼</span><br><span class="line">        ┌──────────────────┐ ┌──────────────────┐</span><br><span class="line">        │ 3. 检查系统组件   │ │ 重启 kubelet     │</span><br><span class="line">        │    Pod 状态      │ │ 修复 CNI 配置    │</span><br><span class="line">        └──────────────────┘ └──────────────────┘</span><br><span class="line">                  │</span><br><span class="line">         ┌────────┴─────────┐</span><br><span class="line">         │                  │</span><br><span class="line">       Running            Pending/CrashLoopBackOff</span><br><span class="line">         │                  │</span><br><span class="line">         ▼                  ▼</span><br><span class="line">  ┌────────────┐    ┌──────────────────┐</span><br><span class="line">  │ 集群正常    │    │ 检查 Pod 日志    │</span><br><span class="line">  └────────────┐    │ 修复镜像/配置    │</span><br><span class="line">                  └──────────────────┘</span><br></pre></td></tr></table></figure><h3 id="诊断命令链"><a href="#诊断命令链" class="headerlink" title="诊断命令链"></a>诊断命令链</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># ===== 第一阶段：节点状态检查 =====</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 查看所有节点状态</span></span><br><span class="line">kubectl get nodes -o wide</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 查看节点详细信息</span></span><br><span class="line">kubectl describe node &lt;node-name&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 检查节点资源使用</span></span><br><span class="line">kubectl top nodes</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 检查 kubelet 状态（在节点上执行）</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl status kubelet</span><br><span class="line"><span class="built_in">sudo</span> journalctl -u kubelet -n 100 --no-pager</span><br><span class="line"></span><br><span class="line"><span class="comment"># ===== 第二阶段：系统 Pod 检查 =====</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 查看所有系统 Pod</span></span><br><span class="line">kubectl get pods -n kube-system -o wide</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 查看特定 Pod 详情</span></span><br><span class="line">kubectl describe pod &lt;pod-name&gt; -n kube-system</span><br><span class="line"></span><br><span class="line"><span class="comment"># 7. 查看 Pod 日志</span></span><br><span class="line">kubectl logs &lt;pod-name&gt; -n kube-system</span><br><span class="line">kubectl logs &lt;pod-name&gt; -n kube-system --previous  <span class="comment"># 查看上一个容器的日志</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 8. 检查组件状态</span></span><br><span class="line">kubectl get componentstatuses</span><br><span class="line"></span><br><span class="line"><span class="comment"># ===== 第三阶段：网络检查 =====</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 9. 检查网络插件状态</span></span><br><span class="line">kubectl get pods -n kube-system | grep -E <span class="string">&quot;flannel|calico|cilium&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 10. 检查 CNI 配置（在节点上执行）</span></span><br><span class="line"><span class="built_in">ls</span> -la /etc/cni/net.d/</span><br><span class="line"><span class="built_in">cat</span> /etc/cni/net.d/*.conf</span><br><span class="line"></span><br><span class="line"><span class="comment"># 11. 检查 Flannel 配置</span></span><br><span class="line">kubectl logs -n kube-system &lt;flannel-pod-name&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 12. 测试 Pod 间通信</span></span><br><span class="line">kubectl run test-pod --image=busybox --restart=Never --<span class="built_in">rm</span> -it -- ping &lt;pod-ip&gt;</span><br></pre></td></tr></table></figure><h3 id="问题：节点处于-NotReady-状态"><a href="#问题：节点处于-NotReady-状态" class="headerlink" title="问题：节点处于 NotReady 状态"></a>问题：节点处于 NotReady 状态</h3><p><strong>原因分析：</strong></p><ol><li>网络插件未部署或未就绪</li><li>kubelet 服务异常</li><li>CNI 配置错误</li><li>容器运行时异常</li></ol><p><strong>解决方案：</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 检查 Flannel Pod 状态</span></span><br><span class="line">kubectl get pods -n kube-system | grep flannel</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 查看 Flannel Pod 日志</span></span><br><span class="line">kubectl logs -n kube-system &lt;FLANNEL_POD_NAME&gt;</span><br><span class="line">kubectl describe pod -n kube-system &lt;FLANNEL_POD_NAME&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 检查 kubelet 日志（在 NotReady 节点上执行）</span></span><br><span class="line"><span class="built_in">sudo</span> journalctl -u kubelet -f</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 检查 containerd 状态</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl status containerd</span><br><span class="line"><span class="built_in">sudo</span> journalctl -u containerd -n 50</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 重启 kubelet（在节点上执行）</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl restart kubelet</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 检查 CNI 插件路径</span></span><br><span class="line"><span class="built_in">ls</span> -la /opt/cni/bin/</span><br><span class="line"><span class="built_in">ls</span> -la /etc/cni/net.d/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 7. 如果 CNI 插件缺失，重新部署</span></span><br><span class="line">kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml</span><br></pre></td></tr></table></figure><p><strong>验证修复：</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 等待 1-2 分钟后检查</span></span><br><span class="line">kubectl get nodes</span><br><span class="line"><span class="comment"># 应显示 Ready 状态</span></span><br></pre></td></tr></table></figure><h3 id="问题：CoreDNS-Pod-处于-Pending-状态"><a href="#问题：CoreDNS-Pod-处于-Pending-状态" class="headerlink" title="问题：CoreDNS Pod 处于 Pending 状态"></a>问题：CoreDNS Pod 处于 Pending 状态</h3><p><strong>原因分析：</strong></p><ol><li>CNI 插件路径配置不正确</li><li>网络插件未就绪</li><li>节点资源不足</li></ol><p><strong>解决方案：</strong> 执行步骤 9 的修复步骤</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 创建 CNI 标准目录（在所有节点执行）</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">mkdir</span> -p /usr/lib/cni</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 创建符号链接</span></span><br><span class="line"><span class="built_in">cd</span> /usr/lib/cni/</span><br><span class="line"><span class="keyword">for</span> plugin <span class="keyword">in</span> /opt/cni/bin/*; <span class="keyword">do</span></span><br><span class="line">  <span class="built_in">sudo</span> <span class="built_in">ln</span> -sf <span class="string">&quot;<span class="variable">$plugin</span>&quot;</span> <span class="string">&quot;<span class="subst">$(basename $plugin)</span>&quot;</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 验证符号链接</span></span><br><span class="line"><span class="built_in">ls</span> -lh /usr/lib/cni/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 重启 Kubelet（在所有节点执行）</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl restart kubelet</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 检查 CoreDNS Pod 状态</span></span><br><span class="line">kubectl get pods -n kube-system | grep coredns</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 如果仍处于 Pending，检查调度限制</span></span><br><span class="line">kubectl describe pod -n kube-system &lt;coredns-pod-name&gt;</span><br></pre></td></tr></table></figure><h3 id="问题：kubeadm-join-失败"><a href="#问题：kubeadm-join-失败" class="headerlink" title="问题：kubeadm join 失败"></a>问题：kubeadm join 失败</h3><p><strong>原因分析：</strong></p><ol><li>Token 过期（默认 24 小时有效）</li><li>CA 证书哈希不匹配</li><li>Master 节点 API Server 不可达</li><li>端口 6443 被防火墙阻止</li></ol><p><strong>解决方案：</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 在 Master 节点生成新 Token</span></span><br><span class="line">kubeadm token create --print-join-command</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 检查 Token 列表</span></span><br><span class="line">kubeadm token list</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 获取 CA 证书哈希（如果 Token 有效但哈希错误）</span></span><br><span class="line">openssl x509 -pubkey -<span class="keyword">in</span> /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2&gt;/dev/null | openssl dgst -sha256 -hex | sed <span class="string">&#x27;s/^.* //&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 手动构建 join 命令</span></span><br><span class="line">kubeadm <span class="built_in">join</span> &lt;master-ip&gt;:6443 --token &lt;token&gt; --discovery-token-ca-cert-hash sha256:&lt;<span class="built_in">hash</span>&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 检查网络连通性（在 Worker 节点执行）</span></span><br><span class="line">ping &lt;master-ip&gt;</span><br><span class="line">curl -k https://&lt;master-ip&gt;:6443/version</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 检查防火墙规则（在 Master 节点执行）</span></span><br><span class="line"><span class="built_in">sudo</span> ufw status | grep 6443</span><br><span class="line"><span class="built_in">sudo</span> iptables -L -n | grep 6443</span><br></pre></td></tr></table></figure><h3 id="问题：Pod-无法启动（镜像拉取失败）"><a href="#问题：Pod-无法启动（镜像拉取失败）" class="headerlink" title="问题：Pod 无法启动（镜像拉取失败）"></a>问题：Pod 无法启动（镜像拉取失败）</h3><p><strong>原因分析：</strong></p><ol><li>镜像仓库不可达</li><li>镜像不存在或版本错误</li><li>需要认证但未配置 Secret</li><li>网络策略阻止下载</li></ol><p><strong>解决方案：</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 检查镜像拉取错误</span></span><br><span class="line">kubectl describe pod &lt;pod-name&gt; -n &lt;namespace&gt;</span><br><span class="line"><span class="comment"># 查看 Events 部分的错误信息</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 手动拉取镜像测试（在节点上执行）</span></span><br><span class="line"><span class="built_in">sudo</span> ctr image pull &lt;image-name&gt;</span><br><span class="line"><span class="comment"># 或</span></span><br><span class="line">docker pull &lt;image-name&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 配置镜像加速（containerd）</span></span><br><span class="line"><span class="comment"># 编辑 /etc/containerd/config.toml</span></span><br><span class="line">[plugins.<span class="string">&quot;io.containerd.grpc.v1.cri&quot;</span>.registry.mirrors.<span class="string">&quot;docker.io&quot;</span>]</span><br><span class="line">endpoint = [<span class="string">&quot;https://registry.aliyuncs.com&quot;</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 重启 containerd</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl restart containerd</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 配置私有仓库认证</span></span><br><span class="line">kubectl create secret docker-registry regcred \</span><br><span class="line">  --docker-server=&lt;registry-server&gt; \</span><br><span class="line">  --docker-username=&lt;username&gt; \</span><br><span class="line">  --docker-password=&lt;password&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 在 Pod 或 Deployment 中引用 Secret</span></span><br><span class="line">spec:</span><br><span class="line">  imagePullSecrets:</span><br><span class="line">  - name: regcred</span><br></pre></td></tr></table></figure><h3 id="获取调试日志"><a href="#获取调试日志" class="headerlink" title="获取调试日志"></a>获取调试日志</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查看 Kubelet 日志</span></span><br><span class="line"><span class="built_in">sudo</span> journalctl -u kubelet -f</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看 containerd 日志</span></span><br><span class="line"><span class="built_in">sudo</span> journalctl -u containerd -f</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看 kube-apiserver 日志</span></span><br><span class="line">kubectl logs -n kube-system kube-apiserver-&lt;master-node-name&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看 kube-scheduler 日志</span></span><br><span class="line">kubectl logs -n kube-system kube-scheduler-&lt;master-node-name&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看 kube-controller-manager 日志</span></span><br><span class="line">kubectl logs -n kube-system kube-controller-manager-&lt;master-node-name&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看 etcd 日志</span></span><br><span class="line">kubectl logs -n kube-system etcd-&lt;master-node-name&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看所有容器日志（在节点上执行）</span></span><br><span class="line"><span class="built_in">sudo</span> crictl logs &lt;container-id&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看 Pod 事件</span></span><br><span class="line">kubectl get events -n kube-system --sort-by=<span class="string">&#x27;.lastTimestamp&#x27;</span></span><br></pre></td></tr></table></figure><hr><h2 id="常用命令参考"><a href="#常用命令参考" class="headerlink" title="常用命令参考"></a>常用命令参考</h2><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 集群管理</span></span><br><span class="line">kubectl get nodes                          <span class="comment"># 列出所有节点</span></span><br><span class="line">kubectl get pods -A                        <span class="comment"># 列出所有 Pod</span></span><br><span class="line">kubectl get svc -A                         <span class="comment"># 列出所有服务</span></span><br><span class="line">kubectl get events -n kube-system         <span class="comment"># 查看系统事件</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 节点管理</span></span><br><span class="line">kubectl cordon &lt;NODE_NAME&gt;                <span class="comment"># 禁止 Pod 调度到该节点</span></span><br><span class="line">kubectl uncordon &lt;NODE_NAME&gt;              <span class="comment"># 允许 Pod 调度到该节点</span></span><br><span class="line">kubectl drain &lt;NODE_NAME&gt;                 <span class="comment"># 驱逐节点上的所有 Pod</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 日志查看</span></span><br><span class="line">kubectl logs -n kube-system &lt;POD_NAME&gt;   <span class="comment"># 查看 Pod 日志</span></span><br><span class="line">kubectl describe pod &lt;POD_NAME&gt;           <span class="comment"># 查看 Pod 详细信息</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 集群信息</span></span><br><span class="line">kubectl cluster-info                      <span class="comment"># 查看集群信息</span></span><br><span class="line">kubectl api-resources                     <span class="comment"># 查看所有 API 资源</span></span><br></pre></td></tr></table></figure><h2 id="参考资源"><a href="#参考资源" class="headerlink" title="参考资源"></a>参考资源</h2><h3 id="官方文档"><a href="#官方文档" class="headerlink" title="官方文档"></a>官方文档</h3><ul><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3Mv">Kubernetes 官方文档<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3Mvc2V0dXAvcHJvZHVjdGlvbi1lbnZpcm9ubWVudC90b29scy9rdWJlYWRtLw==">kubeadm 官方指南<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvcmVmZXJlbmNlL3NldHVwLXRvb2xzL2t1YmVhZG0v">kubeadm 配置参考<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3Mvc2V0dXAvcmVsZWFzZS92ZXJzaW9uLXNrZXctcG9saWN5Lw==">Kubernetes 版本支持政策<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3Mvc2V0dXAvcmVsZWFzZS9ub3Rlcy8=">Kubernetes 发行说明<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2ZsYW5uZWwtaW8vZmxhbm5lbA==">Flannel 官方文档<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9jb250YWluZXJkLmlvLw==">Containerd 官方文档<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2NvbnRhaW5lcmQvY29udGFpbmVyZC9ibG9iL21haW4vZG9jcy9jcmkvdXNhZ2UubWQ=">Containerd 配置指南<i class="fa fa-external-link-alt"></i></span></li></ul><h3 id="安全与加固"><a href="#安全与加固" class="headerlink" title="安全与加固"></a>安全与加固</h3><ul><li><span class="exturl" data-url="aHR0cHM6Ly93d3cuY2lzZWN1cml0eS5vcmcvYmVuY2htYXJrL2t1YmVybmV0ZXM=">CIS Kubernetes Benchmark<i class="fa fa-external-link-alt"></i></span> - Kubernetes 安全配置基准</li><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvc2VjdXJpdHkv">Kubernetes 安全最佳实践<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvc2VjdXJpdHkvcG9kLXNlY3VyaXR5LXN0YW5kYXJkcy8=">Pod Security Standards<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvdGFza3MvZGVidWcvZGVidWctY2x1c3Rlci9hdWRpdC8=">Kubernetes 安全审计<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvcmVmZXJlbmNlL2FjY2Vzcy1hdXRobi1hdXRoei9yYmFjLw==">RBAC 配置指南<i class="fa fa-external-link-alt"></i></span></li></ul><h3 id="网络与-CNI"><a href="#网络与-CNI" class="headerlink" title="网络与 CNI"></a>网络与 CNI</h3><ul><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvY2x1c3Rlci1hZG1pbmlzdHJhdGlvbi9uZXR3b3JraW5nLw==">Kubernetes 网络模型<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2NvbnRhaW5lcm5ldHdvcmtpbmcvY25p">CNI 插件规范<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2ZsYW5uZWwtaW8vZmxhbm5lbC9ibG9iL21hc3Rlci9Eb2N1bWVudGF0aW9uL2t1YmVybmV0ZXMubWQ=">Flannel 网络配置<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9kb2NzLnRpZ2VyYS5pby9jYWxpY28vbGF0ZXN0L2Fib3V0L2NhbGljby8=">Calico 网络策略<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9jaWxpdW0uaW8v">Cilium 网络方案<i class="fa fa-external-link-alt"></i></span></li></ul><h3 id="高可用与运维"><a href="#高可用与运维" class="headerlink" title="高可用与运维"></a>高可用与运维</h3><ul><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3Mvc2V0dXAvcHJvZHVjdGlvbi1lbnZpcm9ubWVudC90b29scy9rdWJlYWRtL2hhLXRvcG9sb2d5Lw==">Kubernetes 高可用拓扑<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9ldGNkLmlvL2RvY3MvbGF0ZXN0L29wLWd1aWRlLw==">etcd 运维指南<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvdGFza3MvYWRtaW5pc3Rlci1jbHVzdGVyL2JhY2stdXAtZXRjZC8=">Kubernetes 备份与恢复<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvY2x1c3Rlci1hZG1pbmlzdHJhdGlvbi9zeXN0ZW0tbWV0cmljcy8=">Kubernetes 监控架构<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvcmVmZXJlbmNlL2NvbW1hbmQtbGluZS10b29scy1yZWZlcmVuY2Uva3ViZWxldC8=">kubelet 配置参考<i class="fa fa-external-link-alt"></i></span></li></ul><h3 id="社区与工具"><a href="#社区与工具" class="headerlink" title="社区与工具"></a>社区与工具</h3><ul><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2t1YmVybmV0ZXMva3ViZXJuZXRlcw==">Kubernetes GitHub 仓库<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2t1YmVybmV0ZXMva3ViZWFkbQ==">kubeadm GitHub<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2t1YmVybmV0ZXMvZW5oYW5jZW1lbnRz">Kubernetes Enhancement Proposals (KEP)<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9zbGFjay5rOHMuaW8v">Kubernetes Slack 社区<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2t1YmVybmV0ZXMva3ViZXJuZXRlcy9pc3N1ZXM=">Kubernetes Issue 跟踪<i class="fa fa-external-link-alt"></i></span></li></ul><h3 id="进阶阅读"><a href="#进阶阅读" class="headerlink" title="进阶阅读"></a>进阶阅读</h3><ul><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2t1YmVybmV0ZXMva3ViZXJuZXRlcw==">《Kubernetes 权威指南》<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly93d3cuY25jZi5pby8=">云原生计算基金会 (CNCF)<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2NuY2Yvc2lnLXNlY3VyaXR5L3RyZWUvbWFpbi9zZWN1cml0eS13aGl0ZXBhcGVy">Kubernetes 安全白皮书<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2tlbHNleWhpZ2h0b3dlci9rdWJlcm5ldGVzLXRoZS1oYXJkLXdheQ==">生产级 Kubernetes 部署检查清单<i class="fa fa-external-link-alt"></i></span></li></ul><hr><h2 id="生产环境优化配置"><a href="#生产环境优化配置" class="headerlink" title="生产环境优化配置"></a>生产环境优化配置</h2><h3 id="Kubelet-资源预留"><a href="#Kubelet-资源预留" class="headerlink" title="Kubelet 资源预留"></a>Kubelet 资源预留</h3><p>编辑 <code>/var/lib/kubelet/config.yaml</code>（或通过 kubeadm 配置）：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">kubelet.config.k8s.io/v1beta1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">KubeletConfiguration</span></span><br><span class="line"><span class="attr">systemReserved:</span></span><br><span class="line">  <span class="attr">cpu:</span> <span class="string">&quot;500m&quot;</span></span><br><span class="line">  <span class="attr">memory:</span> <span class="string">&quot;1Gi&quot;</span></span><br><span class="line">  <span class="attr">ephemeral-storage:</span> <span class="string">&quot;10Gi&quot;</span></span><br><span class="line"><span class="attr">kubeReserved:</span></span><br><span class="line">  <span class="attr">cpu:</span> <span class="string">&quot;500m&quot;</span></span><br><span class="line">  <span class="attr">memory:</span> <span class="string">&quot;1Gi&quot;</span></span><br><span class="line">  <span class="attr">ephemeral-storage:</span> <span class="string">&quot;10Gi&quot;</span></span><br><span class="line"><span class="attr">evictionHard:</span></span><br><span class="line">  <span class="attr">memory.available:</span> <span class="string">&quot;500Mi&quot;</span></span><br><span class="line">  <span class="attr">nodefs.available:</span> <span class="string">&quot;10%&quot;</span></span><br><span class="line">  <span class="attr">nodefs.inodesFree:</span> <span class="string">&quot;5%&quot;</span></span><br><span class="line">  <span class="attr">imagefs.available:</span> <span class="string">&quot;10%&quot;</span></span><br><span class="line"><span class="attr">maxPods:</span> <span class="number">110</span></span><br><span class="line"><span class="attr">imageGCHighThresholdPercent:</span> <span class="number">85</span></span><br><span class="line"><span class="attr">imageGCLowThresholdPercent:</span> <span class="number">80</span></span><br></pre></td></tr></table></figure><p><strong>应用配置：</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">sudo</span> systemctl restart kubelet</span><br><span class="line">kubectl describe node | grep -A5 <span class="string">&quot;Allocated resources&quot;</span></span><br></pre></td></tr></table></figure><h3 id="API-Server-性能调优"><a href="#API-Server-性能调优" class="headerlink" title="API Server 性能调优"></a>API Server 性能调优</h3><p>高并发场景配置（添加到 kubeadm init 参数）：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">sudo</span> kubeadm init \</span><br><span class="line">  --apiserver-advertise-address=192.168.199.135 \</span><br><span class="line">  --pod-network-cidr=10.244.0.0/16 \</span><br><span class="line">  --kubernetes-version v1.33.6 \</span><br><span class="line">  --image-repository registry.aliyuncs.com/google_containers \</span><br><span class="line">  --apiserver-extra-args=--max-requests-inflight=800 \</span><br><span class="line">  --apiserver-extra-args=--max-mutating-requests-inflight=400 \</span><br><span class="line">  --apiserver-extra-args=--default-not-ready-toleration-seconds=300 \</span><br><span class="line">  --apiserver-extra-args=--default-unreachable-toleration-seconds=300</span><br></pre></td></tr></table></figure><h3 id="etcd-性能优化"><a href="#etcd-性能优化" class="headerlink" title="etcd 性能优化"></a>etcd 性能优化</h3><p>编辑 <code>/etc/kubernetes/manifests/etcd.yaml</code>：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">containers:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">command:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">etcd</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">--snapshot-count=10000</span>  <span class="comment"># 提高快照频率</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">--heartbeat-interval=200</span>  <span class="comment"># 心跳间隔（毫秒）</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">--election-timeout=2000</span>  <span class="comment"># 选举超时（毫秒）</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">--quota-backend-bytes=8589934592</span>  <span class="comment"># 8GB 存储限制</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">--auto-compaction-retention=1h</span>  <span class="comment"># 自动压缩</span></span><br></pre></td></tr></table></figure><hr><h2 id="安全加固配置"><a href="#安全加固配置" class="headerlink" title="安全加固配置"></a>安全加固配置</h2><h3 id="RBAC-最小权限原则"><a href="#RBAC-最小权限原则" class="headerlink" title="RBAC 最小权限原则"></a>RBAC 最小权限原则</h3><p>创建命名空间管理员角色：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">rbac.authorization.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Role</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">production</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">namespace-admin</span></span><br><span class="line"><span class="attr">rules:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">apiGroups:</span> [<span class="string">&quot;&quot;</span>, <span class="string">&quot;apps&quot;</span>, <span class="string">&quot;extensions&quot;</span>]</span><br><span class="line">  <span class="attr">resources:</span> [<span class="string">&quot;*&quot;</span>]</span><br><span class="line">  <span class="attr">verbs:</span> [<span class="string">&quot;get&quot;</span>, <span class="string">&quot;list&quot;</span>, <span class="string">&quot;watch&quot;</span>, <span class="string">&quot;create&quot;</span>, <span class="string">&quot;update&quot;</span>, <span class="string">&quot;patch&quot;</span>, <span class="string">&quot;delete&quot;</span>]</span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">rbac.authorization.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">RoleBinding</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">production</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">namespace-admin-binding</span></span><br><span class="line"><span class="attr">subjects:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">kind:</span> <span class="string">User</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">dev-user</span></span><br><span class="line">  <span class="attr">apiGroup:</span> <span class="string">rbac.authorization.k8s.io</span></span><br><span class="line"><span class="attr">roleRef:</span></span><br><span class="line">  <span class="attr">kind:</span> <span class="string">Role</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">namespace-admin</span></span><br><span class="line">  <span class="attr">apiGroup:</span> <span class="string">rbac.authorization.k8s.io</span></span><br></pre></td></tr></table></figure><h3 id="Pod-安全策略（PSP）"><a href="#Pod-安全策略（PSP）" class="headerlink" title="Pod 安全策略（PSP）"></a>Pod 安全策略（PSP）</h3><p>使用 Pod Security Standards：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Namespace</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">production</span></span><br><span class="line">  <span class="attr">labels:</span></span><br><span class="line">    <span class="attr">pod-security.kubernetes.io/enforce:</span> <span class="string">restricted</span></span><br><span class="line">    <span class="attr">pod-security.kubernetes.io/enforce-version:</span> <span class="string">latest</span></span><br><span class="line">    <span class="attr">pod-security.kubernetes.io/audit:</span> <span class="string">restricted</span></span><br><span class="line">    <span class="attr">pod-security.kubernetes.io/audit-version:</span> <span class="string">latest</span></span><br><span class="line">    <span class="attr">pod-security.kubernetes.io/warn:</span> <span class="string">restricted</span></span><br><span class="line">    <span class="attr">pod-security.kubernetes.io/warn-version:</span> <span class="string">latest</span></span><br></pre></td></tr></table></figure><h3 id="网络策略（Network-Policy）"><a href="#网络策略（Network-Policy）" class="headerlink" title="网络策略（Network Policy）"></a>网络策略（Network Policy）</h3><p>限制命名空间间通信：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">NetworkPolicy</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">default-deny</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">production</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">podSelector:</span> &#123;&#125;</span><br><span class="line">  <span class="attr">policyTypes:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">Ingress</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">Egress</span></span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">NetworkPolicy</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">allow-same-namespace</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">production</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">podSelector:</span> &#123;&#125;</span><br><span class="line">  <span class="attr">ingress:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">from:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">podSelector:</span> &#123;&#125;</span><br><span class="line">  <span class="attr">egress:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">to:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">podSelector:</span> &#123;&#125;</span><br></pre></td></tr></table></figure><h3 id="集群证书轮换"><a href="#集群证书轮换" class="headerlink" title="集群证书轮换"></a>集群证书轮换</h3><p>证书有效期检查与更新：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 检查证书有效期</span></span><br><span class="line">kubeadm certs check-expiration</span><br><span class="line"></span><br><span class="line"><span class="comment"># 更新证书（自动续期1年）</span></span><br><span class="line">kubeadm certs renew all</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启控制平面组件</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">kill</span> -s SIGHUP $(pidof kube-apiserver)</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">kill</span> -s SIGHUP $(pidof kube-controller-manager)</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">kill</span> -s SIGHUP $(pidof kube-scheduler)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 更新客户端证书</span></span><br><span class="line"><span class="built_in">cp</span> /etc/kubernetes/admin.conf ~/.kube/config</span><br></pre></td></tr></table></figure><hr><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="code"><pre><span class="line"><span class="built_in">cat</span> &lt;&lt; <span class="string">&#x27;EOF&#x27;</span> &gt; k8s-health-check.sh</span><br><span class="line"><span class="comment">#!/bin/bash</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;=== Kubernetes Cluster Health Check ===&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;1. Node Status:&quot;</span></span><br><span class="line">kubectl get nodes -o wide</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;2. System Pods Status:&quot;</span></span><br><span class="line">kubectl get pods -n kube-system</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;3. Resource Usage:&quot;</span></span><br><span class="line">kubectl top nodes</span><br><span class="line">kubectl top pods -A --sort-by=memory | <span class="built_in">head</span> -n 10</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;4. Certificate Expiration:&quot;</span></span><br><span class="line">kubeadm certs check-expiration</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;5. Component Health:&quot;</span></span><br><span class="line">kubectl get componentstatuses</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;6. Recent Events:&quot;</span></span><br><span class="line">kubectl get events -A --sort-by=<span class="string">&#x27;.lastTimestamp&#x27;</span> | <span class="built_in">tail</span> -n 20</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;7. Cluster Info:&quot;</span></span><br><span class="line">kubectl cluster-info</span><br><span class="line">EOF</span><br><span class="line"><span class="built_in">chmod</span> +x k8s-health-check.sh</span><br><span class="line">./k8s-health-check.sh</span><br></pre></td></tr></table></figure><h3 id="etcd-备份与恢复"><a href="#etcd-备份与恢复" class="headerlink" title="etcd 备份与恢复"></a>etcd 备份与恢复</h3><p><strong>备份脚本：</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">cat</span> &lt;&lt; <span class="string">&#x27;EOF&#x27;</span> &gt; etcd-backup.sh</span><br><span class="line"><span class="comment">#!/bin/bash</span></span><br><span class="line">BACKUP_DIR=<span class="string">&quot;/backup/etcd&quot;</span></span><br><span class="line">DATE=$(<span class="built_in">date</span> +%Y%m%d-%H%M%S)</span><br><span class="line"></span><br><span class="line">ETCDCTL_API=3 etcdctl snapshot save <span class="variable">$&#123;BACKUP_DIR&#125;</span>/etcd-snapshot-<span class="variable">$&#123;DATE&#125;</span>.db \</span><br><span class="line">  --cacert=/etc/kubernetes/pki/etcd/ca.crt \</span><br><span class="line">  --cert=/etc/kubernetes/pki/etcd/server.crt \</span><br><span class="line">  --key=/etc/kubernetes/pki/etcd/server.key</span><br><span class="line"></span><br><span class="line"><span class="comment"># 保留最近7天的备份</span></span><br><span class="line">find <span class="variable">$&#123;BACKUP_DIR&#125;</span> -name <span class="string">&quot;*.db&quot;</span> -mtime +7 -delete</span><br><span class="line">EOF</span><br><span class="line"><span class="built_in">chmod</span> +x etcd-backup.sh</span><br></pre></td></tr></table></figure><p><strong>恢复流程：</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 1. 停止所有控制平面组件</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl stop kubelet</span><br><span class="line"><span class="built_in">sudo</span> crictl stopp $(<span class="built_in">sudo</span> crictl pods -q)</span><br><span class="line"><span class="built_in">sudo</span> crictl rmp $(<span class="built_in">sudo</span> crictl pods -q)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 恢复 etcd 数据</span></span><br><span class="line">ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd/etcd-snapshot.db \</span><br><span class="line">  --data-dir=/var/lib/etcd-restore</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 更新 etcd manifest</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">mv</span> /var/lib/etcd /var/lib/etcd-old</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">mv</span> /var/lib/etcd-restore/member /var/lib/etcd</span><br><span class="line"><span class="built_in">sudo</span> systemctl start kubelet</span><br></pre></td></tr></table></figure><h3 id="日志收集配置"><a href="#日志收集配置" class="headerlink" title="日志收集配置"></a>日志收集配置</h3><p>配置 Fluent Bit：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ConfigMap</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">fluent-bit-config</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">kube-system</span></span><br><span class="line"><span class="attr">data:</span></span><br><span class="line">  <span class="attr">fluent-bit.conf:</span> <span class="string">|</span></span><br><span class="line"><span class="string">    [SERVICE]</span></span><br><span class="line"><span class="string">      Flush         1</span></span><br><span class="line"><span class="string">      Log_Level     info</span></span><br><span class="line"><span class="string">      Parsers_File  parsers.conf</span></span><br><span class="line"><span class="string"></span>    </span><br><span class="line">    [<span class="string">INPUT</span>]</span><br><span class="line">      <span class="string">Name</span>              <span class="string">tail</span></span><br><span class="line">      <span class="string">Path</span>              <span class="string">/var/log/containers/*.log</span></span><br><span class="line">      <span class="string">Parser</span>            <span class="string">cri</span></span><br><span class="line">      <span class="string">Tag</span>               <span class="string">kube.*</span></span><br><span class="line">      <span class="string">Mem_Buf_Limit</span>     <span class="string">10MB</span></span><br><span class="line">    </span><br><span class="line">    [<span class="string">FILTER</span>]</span><br><span class="line">      <span class="string">Name</span>                <span class="string">kubernetes</span></span><br><span class="line">      <span class="string">Match</span>               <span class="string">kube.*</span></span><br><span class="line">      <span class="string">Kube_URL</span>            <span class="string">https://kubernetes.default.svc:443</span></span><br><span class="line">      <span class="string">Kube_CA_File</span>        <span class="string">/var/run/secrets/kubernetes.io/serviceaccount/ca.crt</span></span><br><span class="line">      <span class="string">Kube_Token_File</span>     <span class="string">/var/run/secrets/kubernetes.io/serviceaccount/token</span></span><br><span class="line">    </span><br><span class="line">    [<span class="string">OUTPUT</span>]</span><br><span class="line">      <span class="string">Name</span>            <span class="string">forward</span></span><br><span class="line">      <span class="string">Match</span>           <span class="string">*</span></span><br><span class="line">      <span class="string">Host</span>            <span class="string">fluentd-server</span></span><br><span class="line">      <span class="string">Port</span>            <span class="number">24224</span></span><br></pre></td></tr></table></figure><hr><h2 id="最佳实践建议"><a href="#最佳实践建议" class="headerlink" title="最佳实践建议"></a>最佳实践建议</h2><h3 id="镜像管理"><a href="#镜像管理" class="headerlink" title="镜像管理"></a>镜像管理</h3><ul><li>使用私有仓库（Harbor、Nexus）</li><li>镜像扫描（Trivy、Clair）</li><li>版本锁定（避免使用 latest）</li><li>预加载关键镜像到节点</li></ul><h3 id="资源管理"><a href="#资源管理" class="headerlink" title="资源管理"></a>资源管理</h3><ul><li>设置合理的 requests&#x2F;limits</li><li>使用 LimitRange 和 ResourceQuota</li><li>配置 Horizontal Pod Autoscaler (HPA)</li><li>启用 Vertical Pod Autoscaler (VPA)</li></ul><h3 id="网络配置"><a href="#网络配置" class="headerlink" title="网络配置"></a>网络配置</h3><ul><li>选择合适的 CNI 插件</li><li>配置网络策略隔离</li><li>使用 Service Mesh（Istio）进行流量管理</li><li>监控网络性能指标</li></ul><h3 id="存储管理"><a href="#存储管理" class="headerlink" title="存储管理"></a>存储管理</h3><ul><li>使用动态存储 provisioning</li><li>配置 StorageClass 多级别存储</li><li>定期备份 PVC 数据</li><li>监控存储使用情况</li></ul><h3 id="高可用配置"><a href="#高可用配置" class="headerlink" title="高可用配置"></a>高可用配置</h3><ul><li>多 Master 节点（至少3个）</li><li>etcd 集群独立部署（大规模场景）</li><li>配置 Pod 反亲和性</li><li>使用 PodDisruptionBudget (PDB)</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;Kubernetes 是云原生应用编排的核心平台。本文档提供生产级 Kubernetes 集群部署方案，涵盖架构设计、环境准备、组件安装、网络配置、安全加固、性能优化和故障排查等全流程内容，适用于学习和生产环境。&lt;/p&gt;</summary>
    
    
    
    <category term="DevOps" scheme="https://freemankevin.uk/categories/DevOps/"/>
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/categories/DevOps/Kubernetes/"/>
    
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/tags/Kubernetes/"/>
    
    <category term="Containerd" scheme="https://freemankevin.uk/tags/Containerd/"/>
    
    <category term="Production" scheme="https://freemankevin.uk/tags/Production/"/>
    
  </entry>
  
  <entry>
    <title>LVM 统一存储架构与数据迁移完整实践指南</title>
    <link href="https://freemankevin.uk/2025/09/16/lvm/"/>
    <id>https://freemankevin.uk/2025/09/16/lvm/</id>
    <published>2025-09-16T02:10:00.000Z</published>
    <updated>2026-04-17T10:30:31.805Z</updated>
    
    <content type="html"><![CDATA[<p>LVM（Logical Volume Manager）是企业级Linux存储管理的核心解决方案，提供灵活的存储池管理和动态扩展能力。本指南涵盖从传统分区到LVM的完整迁移实践、架构设计、性能优化和数据安全保障，适用于生产环境存储重构和容量规划。</p><span id="more"></span><h2 id="LVM-存储架构设计"><a href="#LVM-存储架构设计" class="headerlink" title="LVM 存储架构设计"></a>LVM 存储架构设计</h2><h3 id="LVM-三层架构模型"><a href="#LVM-三层架构模型" class="headerlink" title="LVM 三层架构模型"></a>LVM 三层架构模型</h3><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">应用层           文件系统 (ext4/xfs/btrfs)</span><br><span class="line">                 ↓ 挂载点</span><br><span class="line">逻辑层   ←       逻辑卷 (Logical Volume)</span><br><span class="line">                 └─ 可动态调整大小</span><br><span class="line">                 └─ 支持快照功能</span><br><span class="line">                 └─ 提供条带化/镜像</span><br><span class="line">组管理层 ←       卷组 (Volume Group)</span><br><span class="line">                 └─ 存储池聚合管理</span><br><span class="line">                 └─ PE分配单位</span><br><span class="line">                 └─ 空间动态分配</span><br><span class="line">物理层   ←       物理卷 (Physical Volume)</span><br><span class="line">                 └─ 物理设备初始化</span><br><span class="line">                 └─ LVM标签写入</span><br><span class="line">                 └─ 元数据区域</span><br><span class="line">硬件层           物理磁盘 (HDD/SSD/NVMe)</span><br><span class="line">                 └─ 本地存储设备</span><br><span class="line">                 └─ SAN存储设备</span><br></pre></td></tr></table></figure><h3 id="核心概念解析"><a href="#核心概念解析" class="headerlink" title="核心概念解析"></a>核心概念解析</h3><table><thead><tr><th>概念</th><th>说明</th><th>生产应用</th></tr></thead><tbody><tr><td><strong>PV (Physical Volume)</strong></td><td>物理卷，LVM的基础构建块</td><td>多磁盘整合</td></tr><tr><td><strong>VG (Volume Group)</strong></td><td>卷组，存储池聚合</td><td>统一管理</td></tr><tr><td><strong>LV (Logical Volume)</strong></td><td>逻辑卷，虚拟分区</td><td>动态扩展</td></tr><tr><td><strong>PE (Physical Extent)</strong></td><td>物理块，最小分配单位</td><td>默认4MB</td></tr><tr><td><strong>LE (Logical Extent)</strong></td><td>逻辑块，映射到PE</td><td>空间映射</td></tr></tbody></table><h3 id="LVM-生产优势"><a href="#LVM-生产优势" class="headerlink" title="LVM 生产优势"></a>LVM 生产优势</h3><table><thead><tr><th>优势</th><th>传统分区</th><th>LVM方案</th><th>生产价值</th></tr></thead><tbody><tr><td>动态扩展</td><td>不支持</td><td>完全支持</td><td>在线扩容</td></tr><tr><td>存储池化</td><td>独立分区</td><td>统一池化</td><td>资源优化</td></tr><tr><td>快照功能</td><td>无</td><td>完整支持</td><td>数据保护</td></tr><tr><td>条带化</td><td>不支持</td><td>IO性能提升</td><td>高性能</td></tr><tr><td>镜像</td><td>不支持</td><td>RAID1镜像</td><td>高可用</td></tr></tbody></table><h2 id="项目背景与需求分析"><a href="#项目背景与需求分析" class="headerlink" title="项目背景与需求分析"></a>项目背景与需求分析</h2><h3 id="原始环境状况"><a href="#原始环境状况" class="headerlink" title="原始环境状况"></a>原始环境状况</h3><p>我们的服务器配置如下：</p><ul><li>系统盘：SDA 446.6GB（根分区、EFI分区）</li><li>数据盘1：NVMe0n1 3.5TB（已分区，挂载到 <code>/data</code>）</li><li>数据盘2：NVMe1n1 3.5TB（未使用）</li></ul><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">NAME               MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS</span><br><span class="line">sda                  8:0    0 446.6G  0 disk</span><br><span class="line">├─sda1               8:1    0     1G  0 part /boot/efi</span><br><span class="line">├─sda2               8:2    0 445.6G  0 part /</span><br><span class="line">└─sda3               8:3    0    65M  0 part</span><br><span class="line">nvme0n1            259:0    0   3.5T  0 disk</span><br><span class="line">└─nvme0n1p1        259:3    0 931.3G  0 part /data</span><br><span class="line">nvme1n1            259:1    0   3.5T  0 disk</span><br></pre></td></tr></table></figure><h3 id="面临的问题"><a href="#面临的问题" class="headerlink" title="面临的问题"></a>面临的问题</h3><ol><li><strong>存储分散</strong>：数据分散在 <code>/data</code> 和 <code>/home</code> 等多个挂载点</li><li><strong>扩展困难</strong>：传统分区无法动态调整大小</li><li><strong>资源浪费</strong>：NVMe1n1 完全未使用</li><li><strong>管理复杂</strong>：多个独立分区增加了管理复杂度</li></ol><h3 id="目标架构设计"><a href="#目标架构设计" class="headerlink" title="目标架构设计"></a>目标架构设计</h3><p>设计一个统一的LVM存储架构：</p><ul><li>将两块NVMe盘整合为单一卷组（Volume Group）</li><li>创建大容量逻辑卷，提供约7TB可用空间</li><li>通过软链接保持应用程序路径兼容性</li><li>实现存储的统一管理和动态扩展能力</li></ul><h2 id="LVM技术原理深度解析"><a href="#LVM技术原理深度解析" class="headerlink" title="LVM技术原理深度解析"></a>LVM技术原理深度解析</h2><h3 id="LVM架构层次"><a href="#LVM架构层次" class="headerlink" title="LVM架构层次"></a>LVM架构层次</h3><p>LVM采用三层架构设计，从底层到上层分别是：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">应用层          文件系统 (ext4/xfs)</span><br><span class="line">逻辑层    ←     逻辑卷 (Logical Volume)</span><br><span class="line">组管理层  ←     卷组 (Volume Group)  </span><br><span class="line">物理层    ←     物理卷 (Physical Volume)</span><br><span class="line">硬件层          物理磁盘 (/dev/nvme0n1, /dev/nvme1n1)</span><br></pre></td></tr></table></figure><h4 id="Physical-Volume-PV"><a href="#Physical-Volume-PV" class="headerlink" title="Physical Volume (PV)"></a>Physical Volume (PV)</h4><p>物理卷是LVM的基础构建块，将物理存储设备（硬盘、分区）转换为LVM可管理的格式：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># PV创建过程中的关键操作</span></span><br><span class="line">pvcreate /dev/nvme1n1</span><br><span class="line"><span class="comment"># 在磁盘开头写入LVM标签和元数据</span></span><br><span class="line"><span class="comment"># 划分PE (Physical Extent) 单位，默认4MB</span></span><br></pre></td></tr></table></figure><h4 id="Volume-Group-VG"><a href="#Volume-Group-VG" class="headerlink" title="Volume Group (VG)"></a>Volume Group (VG)</h4><p>卷组将多个物理卷聚合为统一的存储池：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">vgcreate data_vg /dev/nvme1n1</span><br><span class="line"><span class="comment"># 创建卷组元数据</span></span><br><span class="line"><span class="comment"># 建立PE到VG的映射关系</span></span><br><span class="line"><span class="comment"># 提供统一的存储地址空间</span></span><br></pre></td></tr></table></figure><h4 id="Logical-Volume-LV"><a href="#Logical-Volume-LV" class="headerlink" title="Logical Volume (LV)"></a>Logical Volume (LV)</h4><p>逻辑卷是用户实际使用的存储单元，具有以下特性：</p><ul><li><strong>动态扩展</strong>：可在线扩展容量</li><li><strong>快照支持</strong>：支持一致性备份</li><li><strong>条带化</strong>：支持多磁盘并行I&#x2F;O</li></ul><h3 id="LVM-vs-传统分区对比"><a href="#LVM-vs-传统分区对比" class="headerlink" title="LVM vs 传统分区对比"></a>LVM vs 传统分区对比</h3><table><thead><tr><th>特性</th><th>传统分区</th><th>LVM</th></tr></thead><tbody><tr><td>大小调整</td><td>困难，通常需要重建</td><td>在线动态调整</td></tr><tr><td>跨磁盘</td><td>不支持</td><td>支持跨多个物理磁盘</td></tr><tr><td>快照</td><td>不支持</td><td>支持CoW快照</td></tr><tr><td>性能</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><h3 id="阶段一：LVM基础设施构建"><a href="#阶段一：LVM基础设施构建" class="headerlink" title="阶段一：LVM基础设施构建"></a>阶段一：LVM基础设施构建</h3><h4 id="1-1-创建物理卷"><a href="#1-1-创建物理卷" class="headerlink" title="1.1 创建物理卷"></a>1.1 创建物理卷</h4><p>首先将NVMe1n1磁盘转换为LVM物理卷：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建物理卷，写入LVM元数据</span></span><br><span class="line">pvcreate /dev/nvme1n1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证PV创建结果</span></span><br><span class="line">pvdisplay /dev/nvme1n1</span><br></pre></td></tr></table></figure><p>物理卷创建过程中，LVM会在磁盘开头写入以下信息：</p><ul><li>LVM标签（LVM2_member）</li><li>物理卷UUID</li><li>卷组名称</li><li>PE大小和数量</li></ul><h4 id="1-2-创建卷组"><a href="#1-2-创建卷组" class="headerlink" title="1.2 创建卷组"></a>1.2 创建卷组</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建卷组，将PV加入存储池</span></span><br><span class="line">vgcreate data_vg /dev/nvme1n1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看卷组信息</span></span><br><span class="line">vgdisplay data_vg</span><br></pre></td></tr></table></figure><p>卷组创建后的关键参数：</p><ul><li><strong>PE Size</strong>: 4.00 MiB（默认）</li><li><strong>Total PE</strong>: 约915,707个PE</li><li><strong>Allocatable</strong>: 是否可分配空间</li></ul><h4 id="1-3-创建逻辑卷"><a href="#1-3-创建逻辑卷" class="headerlink" title="1.3 创建逻辑卷"></a>1.3 创建逻辑卷</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建逻辑卷，使用所有可用空间</span></span><br><span class="line">lvcreate -l 100%FREE -n data1_lv data_vg</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证逻辑卷状态</span></span><br><span class="line">lvdisplay /dev/data_vg/data1_lv</span><br></pre></td></tr></table></figure><p>关键参数说明：</p><ul><li><code>-l 100%FREE</code>: 使用所有可用的逻辑分区单元</li><li><code>-n data1_lv</code>: 指定逻辑卷名称</li><li><code>data_vg</code>: 目标卷组名称</li></ul><h4 id="1-4-文件系统创建"><a href="#1-4-文件系统创建" class="headerlink" title="1.4 文件系统创建"></a>1.4 文件系统创建</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建ext4文件系统</span></span><br><span class="line">mkfs.ext4 /dev/data_vg/data1_lv</span><br><span class="line"></span><br><span class="line"><span class="comment"># 优化参数（可选）</span></span><br><span class="line">mkfs.ext4 -b 4096 -E stride=32,stripe-width=64 /dev/data_vg/data1_lv</span><br></pre></td></tr></table></figure><h3 id="阶段二：数据迁移策略与实施"><a href="#阶段二：数据迁移策略与实施" class="headerlink" title="阶段二：数据迁移策略与实施"></a>阶段二：数据迁移策略与实施</h3><h4 id="2-1-迁移准备工作"><a href="#2-1-迁移准备工作" class="headerlink" title="2.1 迁移准备工作"></a>2.1 迁移准备工作</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建挂载点</span></span><br><span class="line"><span class="built_in">mkdir</span> /data1</span><br><span class="line">mount /dev/data_vg/data1_lv /data1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建目标目录结构</span></span><br><span class="line"><span class="built_in">mkdir</span> /data1/data_backup</span><br><span class="line"><span class="built_in">mkdir</span> /data1/home_backup</span><br></pre></td></tr></table></figure><h4 id="2-2-数据完整性迁移"><a href="#2-2-数据完整性迁移" class="headerlink" title="2.2 数据完整性迁移"></a>2.2 数据完整性迁移</h4><p>使用rsync进行增量同步，保证数据一致性：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 迁移/data数据，保持所有属性</span></span><br><span class="line"><span class="built_in">nohup</span> rsync -avxHAX --progress \</span><br><span class="line">    --exclude=<span class="string">&#x27;lost+found&#x27;</span> \</span><br><span class="line">    /data/ /data1/data_backup/ \</span><br><span class="line">    &gt; /data1/data_backup.log 2&gt;&amp;1 &amp;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 迁移/home数据（确保没有用户登陆，已登陆用户请踢出）</span></span><br><span class="line"><span class="built_in">nohup</span> rsync -avxHAX --progress \</span><br><span class="line">    --exclude=<span class="string">&#x27;lost+found&#x27;</span> \</span><br><span class="line">    /home/ /data1/home_backup/ \</span><br><span class="line">    &gt; /data1/home_backup.log 2&gt;&amp;1 &amp;</span><br></pre></td></tr></table></figure><p>rsync参数详解：</p><ul><li><code>-a</code>: 归档模式，保持权限、时间戳等</li><li><code>-v</code>: 详细输出</li><li><code>-x</code>: 不跨文件系统</li><li><code>-H</code>: 保持硬链接</li><li><code>-A</code>: 保持ACL</li><li><code>-X</code>: 保持扩展属性</li><li><code>--progress</code>: 显示进度</li></ul><h4 id="2-3-数据完整性验证"><a href="#2-3-数据完整性验证" class="headerlink" title="2.3 数据完整性验证"></a>2.3 数据完整性验证</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 比较文件数量</span></span><br><span class="line">find /data -<span class="built_in">type</span> f | <span class="built_in">wc</span> -l</span><br><span class="line">find /data1/data_backup -<span class="built_in">type</span> f | <span class="built_in">wc</span> -l</span><br><span class="line"></span><br><span class="line"><span class="comment"># 比较总大小</span></span><br><span class="line"><span class="built_in">du</span> -sh /data</span><br><span class="line"><span class="built_in">du</span> -sh /data1/data_backup</span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用校验和验证（可选，耗时较长）</span></span><br><span class="line">find /data -<span class="built_in">type</span> f -<span class="built_in">exec</span> <span class="built_in">md5sum</span> &#123;&#125; \; | <span class="built_in">sort</span> &gt; /tmp/original.md5</span><br><span class="line"><span class="built_in">cd</span> /data1/data_backup</span><br><span class="line">find . -<span class="built_in">type</span> f -<span class="built_in">exec</span> <span class="built_in">md5sum</span> &#123;&#125; \; | <span class="built_in">sort</span> &gt; /tmp/backup.md5</span><br><span class="line">diff /tmp/original.md5 /tmp/backup.md5</span><br></pre></td></tr></table></figure><h3 id="阶段三：系统切换与进程处理"><a href="#阶段三：系统切换与进程处理" class="headerlink" title="阶段三：系统切换与进程处理"></a>阶段三：系统切换与进程处理</h3><h4 id="3-1-进程排查与处理"><a href="#3-1-进程排查与处理" class="headerlink" title="3.1 进程排查与处理"></a>3.1 进程排查与处理</h4><p>在卸载原分区前，必须确保没有进程占用：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查找占用/data的进程</span></span><br><span class="line">lsof +D /data</span><br><span class="line"></span><br><span class="line"><span class="comment"># 示例输出分析</span></span><br><span class="line">COMMAND       PID USER   FD   TYPE DEVICE   SIZE/OFF     NODE NAME</span><br><span class="line">sftp-serv 1528862 root    3r   REG  259,3 8776906927 11273975 /data/opt/...</span><br></pre></td></tr></table></figure><p>发现SFTP进程正在传输大文件，这解释了为什么”静态文件”会有进程占用。</p><h4 id="3-2-优雅停止服务"><a href="#3-2-优雅停止服务" class="headerlink" title="3.2 优雅停止服务"></a>3.2 优雅停止服务</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 停止相关服务</span></span><br><span class="line">systemctl stop docker</span><br><span class="line"></span><br><span class="line"><span class="comment"># 强制终止占用进程（谨慎使用）</span></span><br><span class="line">fuser -km /data</span><br><span class="line"></span><br><span class="line"><span class="comment"># 或者单独终止特定进程</span></span><br><span class="line"><span class="built_in">kill</span> -15 1528862  <span class="comment"># 温和终止</span></span><br><span class="line"><span class="built_in">kill</span> -9 1528862   <span class="comment"># 强制终止</span></span><br></pre></td></tr></table></figure><h4 id="3-3-安全卸载与切换"><a href="#3-3-安全卸载与切换" class="headerlink" title="3.3 安全卸载与切换"></a>3.3 安全卸载与切换</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 备份fstab</span></span><br><span class="line"><span class="built_in">cp</span> /etc/fstab /etc/fstab.backup</span><br><span class="line"></span><br><span class="line"><span class="comment"># 卸载原分区</span></span><br><span class="line">umount /data</span><br><span class="line"><span class="comment"># 如果busy，使用懒卸载</span></span><br><span class="line">umount -l /data</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重命名原目录（保留备份）</span></span><br><span class="line"><span class="built_in">mv</span> /data /data.old</span><br><span class="line"><span class="built_in">mv</span> /home /home.old</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建软链接</span></span><br><span class="line"><span class="built_in">ln</span> -s /data1/data_backup /data</span><br><span class="line"><span class="built_in">ln</span> -s /data1/home_backup /home</span><br></pre></td></tr></table></figure><h3 id="阶段四：存储池扩展"><a href="#阶段四：存储池扩展" class="headerlink" title="阶段四：存储池扩展"></a>阶段四：存储池扩展</h3><h4 id="4-1-第二块磁盘处理"><a href="#4-1-第二块磁盘处理" class="headerlink" title="4.1 第二块磁盘处理"></a>4.1 第二块磁盘处理</h4><p>NVMe0n1已有分区表，需要清理：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 清除分区表和文件系统签名</span></span><br><span class="line">wipefs -a /dev/nvme0n1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 输出示例</span></span><br><span class="line">/dev/nvme0n1: 8 bytes were erased at offset 0x00000200 (gpt): 45 46 49 20 50 41 52 54</span><br><span class="line">/dev/nvme0n1: 8 bytes were erased at offset 0x37e3ee55e00 (gpt): 45 46 49 20 50 41 52 54</span><br><span class="line">/dev/nvme0n1: 2 bytes were erased at offset 0x000001fe (PMBR): 55 aa</span><br></pre></td></tr></table></figure><h4 id="4-2-扩展LVM存储池"><a href="#4-2-扩展LVM存储池" class="headerlink" title="4.2 扩展LVM存储池"></a>4.2 扩展LVM存储池</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 将新磁盘加入物理卷</span></span><br><span class="line">pvcreate /dev/nvme0n1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 扩展卷组</span></span><br><span class="line">vgextend data_vg /dev/nvme0n1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 扩展逻辑卷</span></span><br><span class="line">lvextend -l +100%FREE /dev/data_vg/data1_lv</span><br><span class="line"></span><br><span class="line"><span class="comment"># 扩展文件系统</span></span><br><span class="line">resize2fs /dev/data_vg/data1_lv</span><br></pre></td></tr></table></figure><h4 id="4-3-验证扩展结果"><a href="#4-3-验证扩展结果" class="headerlink" title="4.3 验证扩展结果"></a>4.3 验证扩展结果</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查看存储状态</span></span><br><span class="line">pvdisplay</span><br><span class="line">vgdisplay data_vg</span><br><span class="line">lvdisplay /dev/data_vg/data1_lv</span><br><span class="line"><span class="built_in">df</span> -Th</span><br></pre></td></tr></table></figure><h3 id="阶段五：系统配置与验证"><a href="#阶段五：系统配置与验证" class="headerlink" title="阶段五：系统配置与验证"></a>阶段五：系统配置与验证</h3><h4 id="5-1-更新系统配置"><a href="#5-1-更新系统配置" class="headerlink" title="5.1 更新系统配置"></a>5.1 更新系统配置</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 更新fstab，添加新挂载项</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;/dev/data_vg/data1_lv /data1 ext4 defaults 0 2&quot;</span> &gt;&gt; /etc/fstab</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证fstab语法</span></span><br><span class="line">mount -a</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;LVM（Logical Volume Manager）是企业级Linux存储管理的核心解决方案，提供灵活的存储池管理和动态扩展能力。本指南涵盖从传统分区到LVM的完整迁移实践、架构设计、性能优化和数据安全保障，适用于生产环境存储重构和容量规划。&lt;/p&gt;</summary>
    
    
    
    <category term="Linux" scheme="https://freemankevin.uk/categories/Linux/"/>
    
    <category term="Storage" scheme="https://freemankevin.uk/categories/Linux/Storage/"/>
    
    
    <category term="DevOps" scheme="https://freemankevin.uk/tags/DevOps/"/>
    
    <category term="Storage" scheme="https://freemankevin.uk/tags/Storage/"/>
    
    <category term="Migration" scheme="https://freemankevin.uk/tags/Migration/"/>
    
    <category term="LVM" scheme="https://freemankevin.uk/tags/LVM/"/>
    
  </entry>
  
  <entry>
    <title>Harbor 多架构镜像管理完整指南</title>
    <link href="https://freemankevin.uk/2025/08/13/docker-manifest/"/>
    <id>https://freemankevin.uk/2025/08/13/docker-manifest/</id>
    <published>2025-08-13T02:40:00.000Z</published>
    <updated>2026-04-17T10:30:31.801Z</updated>
    
    <content type="html"><![CDATA[<p>在现代容器化环境中，多架构支持变得越来越重要。随着 ARM64 架构在服务器和边缘设备中的普及，我们需要构建和管理支持多种 CPU 架构的容器镜像。本文将详细介绍如何在 Harbor 私有镜像仓库中管理多架构镜像，包括配置、推送和创建 manifest 列表的完整流程。</p><span id="more"></span><h2 id="环境说明"><a href="#环境说明" class="headerlink" title="环境说明"></a>环境说明</h2><ul><li><strong>Harbor 版本</strong>: 自建 Harbor 私有仓库</li><li><strong>部署方式</strong>: HTTPS 模式，使用自签名证书，443 端口</li><li><strong>Docker 版本</strong>: 支持 manifest 功能的版本</li><li><strong>目标架构</strong>: AMD64 和 ARM64</li></ul><h2 id="问题背景"><a href="#问题背景" class="headerlink" title="问题背景"></a>问题背景</h2><p>在实际项目中，我们遇到了以下挑战：</p><ol><li>需要将单架构镜像转换为多架构镜像</li><li>Harbor 使用自签名 HTTPS 证书，需要正确配置 Docker 客户端</li><li>Docker manifest 功能需要特定的配置和操作流程</li><li>需要批量处理多个版本的镜像</li></ol><h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><h3 id="1-Harbor-证书配置"><a href="#1-Harbor-证书配置" class="headerlink" title="1. Harbor 证书配置"></a>1. Harbor 证书配置</h3><h4 id="问题现象"><a href="#问题现象" class="headerlink" title="问题现象"></a>问题现象</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">Get <span class="string">&quot;http://110.1.20.3/v2/&quot;</span>: dial tcp 110.1.20.3:80: connect: connection refused</span><br></pre></td></tr></table></figure><p>这个错误表明 Docker 客户端尝试使用 HTTP 协议连接 Harbor，但 Harbor 实际运行在 HTTPS 模式。</p><h4 id="解决步骤"><a href="#解决步骤" class="headerlink" title="解决步骤"></a>解决步骤</h4><p><strong>Step 1: 配置客户端证书</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建证书目录</span></span><br><span class="line"><span class="built_in">mkdir</span> -p /etc/docker/certs.d/110.1.20.3/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 复制 Harbor CA 证书和服务器证书</span></span><br><span class="line">\<span class="built_in">cp</span> -rvf /data/opt/installharbor/certs/&#123;ca.crt,harbor.crt&#125; /etc/docker/certs.d/110.1.20.3/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置正确的文件权限</span></span><br><span class="line"><span class="built_in">cd</span> /etc/docker/certs.d/110.1.20.3/</span><br><span class="line"><span class="built_in">chmod</span> 644 ca.crt harbor.crt</span><br></pre></td></tr></table></figure><p><strong>Step 2: 配置 Docker daemon</strong></p><p>编辑 <code>/etc/docker/daemon.json</code>：</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;registry-mirrors&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="string">&quot;https://docker.m.daocloud.io&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;http://docker.1panel.live&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;https://docker.agsv.top&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;https://docker.agsvpt.work&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;https://dockerpull.com&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;https://dockerproxy.cn&quot;</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;debug&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;insecure-registries&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="string">&quot;110.1.20.3&quot;</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;ip-forward&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;ipv6&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;live-restore&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;log-driver&quot;</span><span class="punctuation">:</span> <span class="string">&quot;json-file&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;log-level&quot;</span><span class="punctuation">:</span> <span class="string">&quot;warn&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;log-opts&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;max-size&quot;</span><span class="punctuation">:</span> <span class="string">&quot;100m&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;max-file&quot;</span><span class="punctuation">:</span> <span class="string">&quot;2&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;selinux-enabled&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;experimental&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;storage-driver&quot;</span><span class="punctuation">:</span> <span class="string">&quot;overlay2&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;data-root&quot;</span><span class="punctuation">:</span> <span class="string">&quot;/data/docker_dir&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;default-ulimits&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;nofile&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;Name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;nofile&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;Hard&quot;</span><span class="punctuation">:</span> <span class="number">65536</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;Soft&quot;</span><span class="punctuation">:</span> <span class="number">65536</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;exec-opts&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;native.cgroupdriver=systemd&quot;</span><span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p><strong>关键配置说明：</strong></p><ul><li><code>&quot;experimental&quot;: true</code> - 启用 manifest 功能</li><li><code>&quot;insecure-registries&quot;: [&quot;110.1.20.3&quot;]</code> - 信任自签名证书</li></ul><p><strong>Step 3: 重启服务</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 重启 Docker</span></span><br><span class="line">systemctl daemon-reload </span><br><span class="line">systemctl restart docker</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启 Harbor（同台机器部署需要）</span></span><br><span class="line"><span class="built_in">cd</span> /data/opt/installharbor/</span><br><span class="line">bash install.sh</span><br></pre></td></tr></table></figure><h3 id="2-常见证书问题解决"><a href="#2-常见证书问题解决" class="headerlink" title="2. 常见证书问题解决"></a>2. 常见证书问题解决</h3><h4 id="问题1：证书文件扩展名错误"><a href="#问题1：证书文件扩展名错误" class="headerlink" title="问题1：证书文件扩展名错误"></a>问题1：证书文件扩展名错误</h4><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">missing key ca.key for client certificate ca.cert. CA certificates must use the extension .crt</span><br></pre></td></tr></table></figure><p><strong>解决方法：</strong></p><ul><li>Docker 要求 CA 证书必须使用 <code>.crt</code> 扩展名</li><li>客户端证书目录不应包含私钥文件（<code>.key</code> 文件）</li></ul><p><strong>正确的证书目录结构：</strong></p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">/etc/docker/certs.d/110.1.20.3/</span><br><span class="line">├── ca.crt          # CA 证书（必需）</span><br><span class="line">└── harbor.crt      # Harbor 服务器证书（可选）</span><br></pre></td></tr></table></figure><h4 id="问题2：Docker-daemon-配置错误"><a href="#问题2：Docker-daemon-配置错误" class="headerlink" title="问题2：Docker daemon 配置错误"></a>问题2：Docker daemon 配置错误</h4><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">json: cannot unmarshal string into Go struct field Config.experimental of type bool</span><br></pre></td></tr></table></figure><p><strong>解决方法：</strong></p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 错误写法</span></span><br><span class="line"><span class="attr">&quot;experimental&quot;</span><span class="punctuation">:</span> <span class="string">&quot;enabled&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 正确写法</span></span><br><span class="line"><span class="attr">&quot;experimental&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br></pre></td></tr></table></figure><h3 id="3-多架构镜像管理脚本"><a href="#3-多架构镜像管理脚本" class="headerlink" title="3. 多架构镜像管理脚本"></a>3. 多架构镜像管理脚本</h3><p>创建自动化脚本 <code>pushImages.sh</code> 来批量处理镜像：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment"># ===================================</span></span><br><span class="line"><span class="comment"># 批量处理：打 tag + 推送 + 创建多架构 manifest</span></span><br><span class="line"><span class="comment"># 支持 HTTPS Harbor 自签名证书</span></span><br><span class="line"><span class="comment"># ===================================</span></span><br><span class="line"><span class="built_in">set</span> -e</span><br><span class="line"></span><br><span class="line"><span class="comment"># Harbor 配置</span></span><br><span class="line">HARBOR_HOST=<span class="string">&quot;110.1.20.3&quot;</span></span><br><span class="line">REPO_PREFIX=<span class="string">&quot;<span class="variable">$&#123;HARBOR_HOST&#125;</span>/library&quot;</span></span><br><span class="line">VERSIONS=(<span class="string">&quot;3.11.3&quot;</span> <span class="string">&quot;3.10.1&quot;</span> <span class="string">&quot;3.9.2&quot;</span> <span class="string">&quot;3.8.5&quot;</span>)</span><br><span class="line">ARCHES=(<span class="string">&quot;amd64&quot;</span> <span class="string">&quot;arm64&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 是否删除旧标签（可选）</span></span><br><span class="line">DELETE_OLD_TAGS=<span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;🚀 开始处理镜像标签与多架构清单...&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;📡 Harbor 地址: https://<span class="variable">$&#123;HARBOR_HOST&#125;</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查登录状态</span></span><br><span class="line"><span class="keyword">if</span> ! docker login https://<span class="variable">$&#123;HARBOR_HOST&#125;</span> 2&gt;/dev/null; <span class="keyword">then</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;⚠️  Docker 未登录到 Harbor，请先登录：&quot;</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;   docker login https://<span class="variable">$&#123;HARBOR_HOST&#125;</span>&quot;</span></span><br><span class="line">  <span class="built_in">exit</span> 1</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 先为所有镜像打新标签并推送</span></span><br><span class="line"><span class="keyword">for</span> version <span class="keyword">in</span> <span class="string">&quot;<span class="variable">$&#123;VERSIONS[@]&#125;</span>&quot;</span>; <span class="keyword">do</span></span><br><span class="line">  <span class="keyword">for</span> <span class="built_in">arch</span> <span class="keyword">in</span> <span class="string">&quot;<span class="variable">$&#123;ARCHES[@]&#125;</span>&quot;</span>; <span class="keyword">do</span></span><br><span class="line">    OLD_TAG=<span class="string">&quot;<span class="variable">$&#123;REPO_PREFIX&#125;</span>/java-gdal-local-<span class="variable">$&#123;arch&#125;</span>:<span class="variable">$&#123;version&#125;</span>&quot;</span></span><br><span class="line">    NEW_TAG=<span class="string">&quot;<span class="variable">$&#123;REPO_PREFIX&#125;</span>/java-gdal-local:<span class="variable">$&#123;version&#125;</span>-<span class="variable">$&#123;arch&#125;</span>&quot;</span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> docker inspect <span class="string">&quot;<span class="variable">$OLD_TAG</span>&quot;</span> &amp;&gt; /dev/null; <span class="keyword">then</span></span><br><span class="line">      <span class="built_in">echo</span> <span class="string">&quot;🏷️  打标签: <span class="variable">$OLD_TAG</span> -&gt; <span class="variable">$NEW_TAG</span>&quot;</span></span><br><span class="line">      docker tag <span class="string">&quot;<span class="variable">$OLD_TAG</span>&quot;</span> <span class="string">&quot;<span class="variable">$NEW_TAG</span>&quot;</span></span><br><span class="line">      </span><br><span class="line">      <span class="built_in">echo</span> <span class="string">&quot;📤 推送: <span class="variable">$NEW_TAG</span>&quot;</span></span><br><span class="line">      docker push <span class="string">&quot;<span class="variable">$NEW_TAG</span>&quot;</span></span><br><span class="line">      </span><br><span class="line">      <span class="keyword">if</span> [ <span class="string">&quot;<span class="variable">$DELETE_OLD_TAGS</span>&quot;</span> = <span class="literal">true</span> ]; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;🗑️  删除旧标签: <span class="variable">$OLD_TAG</span>&quot;</span></span><br><span class="line">        docker rmi <span class="string">&quot;<span class="variable">$OLD_TAG</span>&quot;</span> || <span class="literal">true</span></span><br><span class="line">      <span class="keyword">fi</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">      <span class="built_in">echo</span> <span class="string">&quot;⚠️  镜像不存在，跳过: <span class="variable">$OLD_TAG</span>&quot;</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">  <span class="keyword">done</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 为每个版本创建多架构 manifest</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;🔧 开始创建多架构 manifest...&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> version <span class="keyword">in</span> <span class="string">&quot;<span class="variable">$&#123;VERSIONS[@]&#125;</span>&quot;</span>; <span class="keyword">do</span></span><br><span class="line">  MANIFEST_TAG=<span class="string">&quot;<span class="variable">$&#123;REPO_PREFIX&#125;</span>/java-gdal-local:<span class="variable">$&#123;version&#125;</span>&quot;</span></span><br><span class="line">  TAG_AMD64=<span class="string">&quot;<span class="variable">$&#123;REPO_PREFIX&#125;</span>/java-gdal-local:<span class="variable">$&#123;version&#125;</span>-amd64&quot;</span></span><br><span class="line">  TAG_ARM64=<span class="string">&quot;<span class="variable">$&#123;REPO_PREFIX&#125;</span>/java-gdal-local:<span class="variable">$&#123;version&#125;</span>-arm64&quot;</span></span><br><span class="line">  </span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;📦 创建多架构镜像清单: <span class="variable">$MANIFEST_TAG</span>&quot;</span></span><br><span class="line">  </span><br><span class="line">  <span class="comment"># 删除可能存在的旧 manifest</span></span><br><span class="line">  docker manifest <span class="built_in">rm</span> <span class="string">&quot;<span class="variable">$MANIFEST_TAG</span>&quot;</span> 2&gt;/dev/null || <span class="literal">true</span></span><br><span class="line">  </span><br><span class="line">  <span class="comment"># 创建 manifest</span></span><br><span class="line">  docker manifest create <span class="string">&quot;<span class="variable">$MANIFEST_TAG</span>&quot;</span> \</span><br><span class="line">    --amend <span class="string">&quot;<span class="variable">$TAG_AMD64</span>&quot;</span> \</span><br><span class="line">    --amend <span class="string">&quot;<span class="variable">$TAG_ARM64</span>&quot;</span></span><br><span class="line">  </span><br><span class="line">  <span class="comment"># 添加平台信息（关键步骤）</span></span><br><span class="line">  docker manifest annotate <span class="string">&quot;<span class="variable">$MANIFEST_TAG</span>&quot;</span> <span class="string">&quot;<span class="variable">$TAG_AMD64</span>&quot;</span> --os linux --<span class="built_in">arch</span> amd64</span><br><span class="line">  docker manifest annotate <span class="string">&quot;<span class="variable">$MANIFEST_TAG</span>&quot;</span> <span class="string">&quot;<span class="variable">$TAG_ARM64</span>&quot;</span> --os linux --<span class="built_in">arch</span> arm64</span><br><span class="line">  </span><br><span class="line">  <span class="comment"># 推送 manifest</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;📤 推送多架构镜像: <span class="variable">$MANIFEST_TAG</span>&quot;</span></span><br><span class="line">  docker manifest push <span class="string">&quot;<span class="variable">$MANIFEST_TAG</span>&quot;</span></span><br><span class="line">  </span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;✅ 完成: <span class="variable">$MANIFEST_TAG</span>&quot;</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;🎉 所有操作完成！&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;你现在可以通过以下方式拉取：&quot;</span></span><br><span class="line"><span class="keyword">for</span> version <span class="keyword">in</span> <span class="string">&quot;<span class="variable">$&#123;VERSIONS[@]&#125;</span>&quot;</span>; <span class="keyword">do</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;   docker pull <span class="variable">$&#123;HARBOR_HOST&#125;</span>/library/java-gdal-local:<span class="variable">$&#123;version&#125;</span>&quot;</span></span><br><span class="line"><span class="keyword">done</span></span><br></pre></td></tr></table></figure><h3 id="4-手动操作流程"><a href="#4-手动操作流程" class="headerlink" title="4. 手动操作流程"></a>4. 手动操作流程</h3><p>如果需要手动创建多架构镜像，可以按以下步骤：</p><p><strong>Step 1: 登录 Harbor</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker login 110.1.20.3</span><br><span class="line"><span class="comment"># 或者</span></span><br><span class="line">docker login -u admin -p Harbor12345@Gmail.com 110.1.20.3</span><br></pre></td></tr></table></figure><p><strong>Step 2: 推送单架构镜像</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 为现有镜像打新标签</span></span><br><span class="line">docker tag 110.1.20.3/library/java-gdal-local-amd64:3.8.5 \</span><br><span class="line">           110.1.20.3/library/java-gdal-local:3.8.5-amd64</span><br><span class="line"></span><br><span class="line">docker tag 110.1.20.3/library/java-gdal-local-arm64:3.8.5 \</span><br><span class="line">           110.1.20.3/library/java-gdal-local:3.8.5-arm64</span><br><span class="line"></span><br><span class="line"><span class="comment"># 推送镜像</span></span><br><span class="line">docker push 110.1.20.3/library/java-gdal-local:3.8.5-amd64</span><br><span class="line">docker push 110.1.20.3/library/java-gdal-local:3.8.5-arm64</span><br></pre></td></tr></table></figure><p><strong>Step 3: 创建多架构 manifest</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建 manifest</span></span><br><span class="line">docker manifest create 110.1.20.3/library/java-gdal-local:3.8.5 \</span><br><span class="line">  --amend 110.1.20.3/library/java-gdal-local:3.8.5-amd64 \</span><br><span class="line">  --amend 110.1.20.3/library/java-gdal-local:3.8.5-arm64</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加平台信息（重要！）</span></span><br><span class="line">docker manifest annotate 110.1.20.3/library/java-gdal-local:3.8.5 \</span><br><span class="line">  110.1.20.3/library/java-gdal-local:3.8.5-amd64 --os linux --<span class="built_in">arch</span> amd64</span><br><span class="line"></span><br><span class="line">docker manifest annotate 110.1.20.3/library/java-gdal-local:3.8.5 \</span><br><span class="line">  110.1.20.3/library/java-gdal-local:3.8.5-arm64 --os linux --<span class="built_in">arch</span> arm64</span><br><span class="line"></span><br><span class="line"><span class="comment"># 推送 manifest（注意：使用 manifest push，不是普通 push）</span></span><br><span class="line">docker manifest push 110.1.20.3/library/java-gdal-local:3.8.5</span><br></pre></td></tr></table></figure><p><strong>Step 4: 验证结果</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查看 manifest 信息</span></span><br><span class="line">docker manifest inspect 110.1.20.3/library/java-gdal-local:3.8.5</span><br><span class="line"></span><br><span class="line"><span class="comment"># 测试拉取（会根据当前平台自动选择架构）</span></span><br><span class="line">docker pull 110.1.20.3/library/java-gdal-local:3.8.5</span><br></pre></td></tr></table></figure><h3 id="5-故障排除"><a href="#5-故障排除" class="headerlink" title="5. 故障排除"></a>5. 故障排除</h3><h4 id="常见错误及解决方法"><a href="#常见错误及解决方法" class="headerlink" title="常见错误及解决方法"></a>常见错误及解决方法</h4><p><strong>1. 证书相关错误</strong></p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">x509: certificate signed by unknown authority</span><br></pre></td></tr></table></figure><p><strong>解决：</strong> 确保正确配置了 CA 证书或使用 <code>insecure-registries</code></p><p><strong>2. Manifest 推送错误</strong></p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">tag does not exist: 110.1.20.3/library/java-gdal-local:3.8.5</span><br></pre></td></tr></table></figure><p><strong>解决：</strong> 使用 <code>docker manifest push</code> 而不是 <code>docker push</code></p><p><strong>3. 实验性功能未启用</strong></p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">docker manifest is only supported when experimental cli features are enabled</span><br></pre></td></tr></table></figure><p><strong>解决：</strong> 在 <code>daemon.json</code> 中设置 <code>&quot;experimental&quot;: true</code></p><h4 id="检查清单"><a href="#检查清单" class="headerlink" title="检查清单"></a>检查清单</h4><ul><li><input disabled="" type="checkbox"> Docker daemon 配置了 <code>&quot;experimental&quot;: true</code></li><li><input disabled="" type="checkbox"> 证书文件使用正确的扩展名（<code>.crt</code>）</li><li><input disabled="" type="checkbox"> 证书目录不包含私钥文件</li><li><input disabled="" type="checkbox"> 已正确登录 Harbor</li><li><input disabled="" type="checkbox"> 单架构镜像已成功推送</li><li><input disabled="" type="checkbox"> 使用 <code>docker manifest push</code> 推送 manifest</li></ul><h2 id="完整配置脚本"><a href="#完整配置脚本" class="headerlink" title="完整配置脚本"></a>完整配置脚本</h2><p>将所有配置步骤整合成一个脚本：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment"># Harbor 多架构镜像配置脚本</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;🔧 配置 Harbor 多架构镜像支持...&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 配置客户端证书</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;📜 配置客户端证书...&quot;</span></span><br><span class="line"><span class="built_in">mkdir</span> -p /etc/docker/certs.d/110.1.20.3/</span><br><span class="line">\<span class="built_in">cp</span> -rvf /data/opt/installharbor/certs/&#123;ca.crt,harbor.crt&#125; /etc/docker/certs.d/110.1.20.3/</span><br><span class="line"><span class="built_in">cd</span> /etc/docker/certs.d/110.1.20.3/</span><br><span class="line"><span class="built_in">chmod</span> 644 ca.crt harbor.crt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 重启 Docker</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;🔄 重启 Docker 服务...&quot;</span></span><br><span class="line">systemctl daemon-reload </span><br><span class="line">systemctl restart docker</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 重启 Harbor（同台机器上需要）</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;🔄 重启 Harbor...&quot;</span></span><br><span class="line"><span class="built_in">cd</span> /data/opt/installharbor/</span><br><span class="line">bash install.sh</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 等待服务启动</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;⏳ 等待服务启动...&quot;</span></span><br><span class="line"><span class="built_in">sleep</span> 30</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 测试配置</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;🧪 测试配置...&quot;</span></span><br><span class="line">docker login 110.1.20.3</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 创建测试 manifest</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;📦 创建测试 manifest...&quot;</span></span><br><span class="line">docker manifest create 110.1.20.3/library/java-gdal-local:3.8.5 \</span><br><span class="line">  110.1.20.3/library/java-gdal-local:3.8.5-amd64 \</span><br><span class="line">  110.1.20.3/library/java-gdal-local:3.8.5-arm64</span><br><span class="line"></span><br><span class="line">docker manifest annotate 110.1.20.3/library/java-gdal-local:3.8.5 \</span><br><span class="line">  110.1.20.3/library/java-gdal-local:3.8.5-amd64 --os linux --<span class="built_in">arch</span> amd64</span><br><span class="line"></span><br><span class="line">docker manifest annotate 110.1.20.3/library/java-gdal-local:3.8.5 \</span><br><span class="line">  110.1.20.3/library/java-gdal-local:3.8.5-arm64 --os linux --<span class="built_in">arch</span> arm64</span><br><span class="line"></span><br><span class="line">docker manifest push 110.1.20.3/library/java-gdal-local:3.8.5</span><br><span class="line"></span><br><span class="line"><span class="comment"># 7. 验证结果</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;✅ 验证结果...&quot;</span></span><br><span class="line">docker manifest inspect 110.1.20.3/library/java-gdal-local:3.8.5</span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;🎉 配置完成！&quot;</span></span><br></pre></td></tr></table></figure><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>通过本文的配置和脚本，我们成功解决了在自建 Harbor 中管理多架构镜像的问题。关键要点包括：</p><ol><li><strong>正确配置 HTTPS 证书</strong>：使用正确的文件名和权限</li><li><strong>启用实验性功能</strong>：Docker manifest 需要实验性功能支持</li><li><strong>理解 manifest 操作</strong>：区分 <code>docker push</code> 和 <code>docker manifest push</code></li><li><strong>自动化流程</strong>：使用脚本批量处理多个版本和架构</li></ol><p>这套方案可以帮助团队高效地管理多架构容器镜像，支持在不同 CPU 架构的环境中无缝部署应用。</p><h2 id="参考资源"><a href="#参考资源" class="headerlink" title="参考资源"></a>参考资源</h2><ul><li><span class="exturl" data-url="aHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vYnVpbGQvYnVpbGRpbmcvbXVsdGktcGxhdGZvcm0v">Docker Multi-platform images<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vZW5naW5lL3JlZmVyZW5jZS9jb21tYW5kbGluZS9tYW5pZmVzdC8=">Docker manifest command<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9nb2hhcmJvci5pby9kb2NzLw==">Harbor Documentation<i class="fa fa-external-link-alt"></i></span></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;在现代容器化环境中，多架构支持变得越来越重要。随着 ARM64 架构在服务器和边缘设备中的普及，我们需要构建和管理支持多种 CPU 架构的容器镜像。本文将详细介绍如何在 Harbor 私有镜像仓库中管理多架构镜像，包括配置、推送和创建 manifest 列表的完整流程。&lt;/p&gt;</summary>
    
    
    
    <category term="Docker" scheme="https://freemankevin.uk/categories/Docker/"/>
    
    
    <category term="Docker" scheme="https://freemankevin.uk/tags/Docker/"/>
    
    <category term="Harbor" scheme="https://freemankevin.uk/tags/Harbor/"/>
    
    <category term="Manifest" scheme="https://freemankevin.uk/tags/Manifest/"/>
    
    <category term="Multi-Architecture" scheme="https://freemankevin.uk/tags/Multi-Architecture/"/>
    
  </entry>
  
  <entry>
    <title>MinIO 站点复制部署与测试：同步与故障恢复</title>
    <link href="https://freemankevin.uk/2025/05/13/docker-minio/"/>
    <id>https://freemankevin.uk/2025/05/13/docker-minio/</id>
    <published>2025-05-13T08:38:00.000Z</published>
    <updated>2026-04-17T10:30:31.801Z</updated>
    
    <content type="html"><![CDATA[<p> MinIO 是一个高性能的分布式对象存储系统，其站点复制（Site Replication）功能支持跨集群的数据和元数据同步。本文记录了如何使用 Docker Compose 部署 MinIO 站点复制集群，配置两个 MinIO 实例，并进行同步测试和故障恢复测试。测试环境基于 20T 磁盘，适用于需要高可用性和灾难恢复的场景。</p><span id="more"></span><h2 id="MinIO-站点复制简介"><a href="#MinIO-站点复制简介" class="headerlink" title="MinIO 站点复制简介"></a>MinIO 站点复制简介</h2><p>MinIO 的站点复制是一种集群级别的双向同步机制，可同步数据（桶、对象）和元数据（用户、策略、配置）。其主要特性包括：</p><ul><li><strong>最终一致性</strong>：对象数据近实时同步。</li><li><strong>严格一致性</strong>：元数据保持完全一致。</li><li><strong>高可用性</strong>：任一集群故障时，另一个集群可继续提供服务。</li></ul><p>本文将部署两个 MinIO 实例（SITE1 和 SITE2），通过 <code>minio-mc</code> 容器配置站点复制，并测试同步和故障恢复。</p><h2 id="环境与配置"><a href="#环境与配置" class="headerlink" title="环境与配置"></a>环境与配置</h2><h3 id="硬件与网络"><a href="#硬件与网络" class="headerlink" title="硬件与网络"></a>硬件与网络</h3><ul><li><strong>服务器</strong>：两台服务器（MinIO1: <code>192.168.199.145</code>，MinIO2: <code>192.168.199.147</code>）。</li><li><strong>磁盘</strong>：每台服务器挂载 20T 磁盘。</li><li><strong>网络</strong>：1Gbps 带宽，RTT &lt; 20ms。</li><li><strong>操作系统</strong>：Linux（支持 Docker）。</li></ul><h3 id="Docker-Compose-配置"><a href="#Docker-Compose-配置" class="headerlink" title="Docker Compose 配置"></a>Docker Compose 配置</h3><p>以下是 MinIO 和 <code>minio-mc</code> 服务的 Docker Compose 配置：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">minio:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&quot;$&#123;MINIO_IMAGE&#125;&quot;</span></span><br><span class="line">    <span class="attr">deploy:</span></span><br><span class="line">      <span class="attr">resources:</span></span><br><span class="line">        <span class="attr">limits:</span></span><br><span class="line">          <span class="attr">memory:</span> <span class="string">4096M</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span> </span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">minio</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;$&#123;MINIO_PORT&#125;:9000&quot;</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;$&#123;MINIO_CONSOLE_PORT&#125;:9001&quot;</span></span><br><span class="line">    <span class="attr">command:</span> <span class="string">server</span> <span class="string">/data</span> <span class="string">--console-address</span> <span class="string">&quot;:9001&quot;</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">MINIO_ROOT_USER:</span> <span class="string">&quot;$&#123;MINIO_ROOT_USER&#125;&quot;</span></span><br><span class="line">      <span class="attr">MINIO_ROOT_PASSWORD:</span> <span class="string">&quot;$&#123;MINIO_ROOT_PASSWORD&#125;&quot;</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD&quot;</span>, <span class="string">&quot;curl&quot;</span>, <span class="string">&quot;-f&quot;</span>, <span class="string">&quot;http://localhost:9000/minio/health/live&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">30s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">3</span></span><br><span class="line">      <span class="attr">start_period:</span> <span class="string">10s</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">/etc/localtime:/etc/localtime:ro</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./data/minio/data:/data</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">minio-mc:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">minio/mc:latest</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">minio-mc</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span> </span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">SITE1_URL:</span> <span class="string">&quot;$&#123;SITE1_URL&#125;&quot;</span></span><br><span class="line">      <span class="attr">SITE2_URL:</span> <span class="string">&quot;$&#123;SITE2_URL&#125;&quot;</span></span><br><span class="line">      <span class="attr">MINIO_ROOT_USER:</span> <span class="string">&quot;$&#123;MINIO_ROOT_USER&#125;&quot;</span></span><br><span class="line">      <span class="attr">MINIO_ROOT_PASSWORD:</span> <span class="string">&quot;$&#123;MINIO_ROOT_PASSWORD&#125;&quot;</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./site-replication.sh:/site-replication.sh</span></span><br><span class="line">    <span class="attr">entrypoint:</span> [<span class="string">&quot;/bin/bash&quot;</span>, <span class="string">&quot;/site-replication.sh&quot;</span>]</span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD-SHELL&quot;</span>, <span class="string">&quot;mc --version &gt;/dev/null 2&gt;&amp;1&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">30s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">start_period:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">3</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line"></span><br><span class="line"><span class="attr">networks:</span></span><br><span class="line">  <span class="attr">middleware:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br></pre></td></tr></table></figure><h3 id="环境变量"><a href="#环境变量" class="headerlink" title="环境变量"></a>环境变量</h3><p>环境变量存储在 <code>.env</code> 文件中：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># MinIO</span></span><br><span class="line">MINIO_PORT=9000</span><br><span class="line">MINIO_CONSOLE_PORT=9001</span><br><span class="line">MINIO_ROOT_USER=<span class="string">&quot;admin&quot;</span></span><br><span class="line">MINIO_ROOT_PASSWORD=<span class="string">&quot;Admin@123.com&quot;</span></span><br><span class="line">MINIO_IMAGE=<span class="string">&quot;minio/minio:RELEASE.2025-04-22T22-12-26Z&quot;</span></span><br><span class="line">SITE1_URL=<span class="string">&quot;http://192.168.145:9000&quot;</span></span><br><span class="line">SITE2_URL=<span class="string">&quot;http://192.168.147:9000&quot;</span></span><br></pre></td></tr></table></figure><h3 id="站点复制脚本"><a href="#站点复制脚本" class="headerlink" title="站点复制脚本"></a>站点复制脚本</h3><p><code>site-replication.sh</code> 用于配置站点复制：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 严格模式：错误、未定义变量、管道失败时退出</span></span><br><span class="line"><span class="built_in">set</span> -euo pipefail</span><br><span class="line"></span><br><span class="line"><span class="comment"># 颜色定义</span></span><br><span class="line">RED=<span class="string">&#x27;\033[0;31m&#x27;</span></span><br><span class="line">GREEN=<span class="string">&#x27;\033[0;32m&#x27;</span></span><br><span class="line">CYAN=<span class="string">&#x27;\033[1;36m&#x27;</span></span><br><span class="line">YELLOW=<span class="string">&#x27;\033[1;33m&#x27;</span></span><br><span class="line">BLUE=<span class="string">&#x27;\033[0;34m&#x27;</span></span><br><span class="line">MAGENTA=<span class="string">&#x27;\033[0;35m&#x27;</span></span><br><span class="line">RESET=<span class="string">&#x27;\033[0m&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 更丰富的图标集</span></span><br><span class="line">ICON_INFO=<span class="string">&quot;🌐&quot;</span></span><br><span class="line">ICON_SUCCESS=<span class="string">&quot;✨&quot;</span></span><br><span class="line">ICON_WARNING=<span class="string">&quot;⚠️&quot;</span></span><br><span class="line">ICON_ERROR=<span class="string">&quot;💥&quot;</span></span><br><span class="line">ICON_DEBUG=<span class="string">&quot;🐞&quot;</span></span><br><span class="line">ICON_WAIT=<span class="string">&quot;⏳&quot;</span></span><br><span class="line">ICON_CLEAN=<span class="string">&quot;🧹&quot;</span></span><br><span class="line">ICON_CONFIG=<span class="string">&quot;⚙️&quot;</span></span><br><span class="line">ICON_NETWORK=<span class="string">&quot;📡&quot;</span></span><br><span class="line">ICON_START=<span class="string">&quot;🚀&quot;</span></span><br><span class="line">ICON_READY=<span class="string">&quot;✅&quot;</span></span><br><span class="line">ICON_FINISH=<span class="string">&quot;🎉&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 增强版日志函数（优化颜色处理）</span></span><br><span class="line"><span class="function"><span class="title">log</span></span>() &#123;</span><br><span class="line">  <span class="built_in">local</span> level=<span class="variable">$1</span> message=<span class="variable">$2</span></span><br><span class="line">  <span class="built_in">local</span> color icon timestamp</span><br><span class="line">  timestamp=$(<span class="built_in">date</span> -u <span class="string">&#x27;+%H:%M:%S&#x27;</span>)</span><br><span class="line">  </span><br><span class="line">  <span class="keyword">case</span> <span class="variable">$level</span> <span class="keyword">in</span></span><br><span class="line">    INFO)    color=<span class="string">&quot;<span class="variable">$GREEN</span>&quot;</span>  icon=<span class="string">&quot;<span class="variable">$ICON_INFO</span>&quot;</span> ;;</span><br><span class="line">    SUCCESS) color=<span class="string">&quot;<span class="variable">$GREEN</span>&quot;</span>  icon=<span class="string">&quot;<span class="variable">$ICON_SUCCESS</span>&quot;</span> ;;</span><br><span class="line">    WARN)    color=<span class="string">&quot;<span class="variable">$YELLOW</span>&quot;</span> icon=<span class="string">&quot;<span class="variable">$ICON_WARNING</span>&quot;</span> ;;</span><br><span class="line">    ERROR)   color=<span class="string">&quot;<span class="variable">$RED</span>&quot;</span>    icon=<span class="string">&quot;<span class="variable">$ICON_ERROR</span>&quot;</span> ;;</span><br><span class="line">    DEBUG)   color=<span class="string">&quot;<span class="variable">$BLUE</span>&quot;</span>   icon=<span class="string">&quot;<span class="variable">$ICON_DEBUG</span>&quot;</span> ;;</span><br><span class="line">    WAIT)    color=<span class="string">&quot;<span class="variable">$MAGENTA</span>&quot;</span> icon=<span class="string">&quot;<span class="variable">$ICON_WAIT</span>&quot;</span> ;;</span><br><span class="line">    *)       color=<span class="string">&quot;<span class="variable">$CYAN</span>&quot;</span>   icon=<span class="string">&quot;<span class="variable">$ICON_INFO</span>&quot;</span> ;;</span><br><span class="line">  <span class="keyword">esac</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># 直接输出消息，避免嵌套格式化问题</span></span><br><span class="line">  <span class="built_in">printf</span> <span class="string">&quot;<span class="variable">$&#123;color&#125;</span>%s %-7s\t%s<span class="variable">$&#123;RESET&#125;</span></span></span><br><span class="line"><span class="string">&quot;</span> <span class="string">&quot;<span class="variable">$timestamp</span> <span class="variable">$icon</span>&quot;</span> <span class="string">&quot;[<span class="variable">$level</span>]&quot;</span> <span class="string">&quot;<span class="variable">$message</span>&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 简洁标题样式（改为 === 标题 === 形式）</span></span><br><span class="line"><span class="function"><span class="title">header</span></span>() &#123;</span><br><span class="line">  <span class="keyword">if</span> [ <span class="string">&quot;<span class="variable">$2</span>&quot;</span> = <span class="string">&quot;MinIO 站点复制初始化&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">printf</span> <span class="string">&quot;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"><span class="variable">$&#123;MAGENTA&#125;</span>███╗   ███╗██╗███╗   ██╗██╗ ██████╗     ███╗   ███╗ ██████╗</span></span><br><span class="line"><span class="string">████╗ ████║██║████╗  ██║██║██╔═══██╗    ████╗ ████║██╔════╝</span></span><br><span class="line"><span class="string">██╔████╔██║██║██╔██╗ ██║██║██║   ██║    ██╔████╔██║██║     </span></span><br><span class="line"><span class="string">██║╚██╔╝██║██║██║╚██╗██║██║██║   ██║    ██║╚██╔╝██║██║     </span></span><br><span class="line"><span class="string">██║ ╚═╝ ██║██║██║ ╚████║██║╚██████╔╝    ██║ ╚═╝ ██║╚██████╗</span></span><br><span class="line"><span class="string">╚═╝     ╚═╝╚═╝╚═╝  ╚═══╝╚═╝ ╚═════╝     ╚═╝     ╚═╝ ╚═════╝</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&gt;&gt; %s %s<span class="variable">$&#123;RESET&#125;</span></span></span><br><span class="line"><span class="string">&quot;</span> <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&quot;<span class="variable">$2</span>&quot;</span></span><br><span class="line">    <span class="built_in">printf</span> <span class="string">&quot;</span></span><br><span class="line"><span class="string">&quot;</span></span><br><span class="line">  <span class="keyword">else</span></span><br><span class="line">    <span class="built_in">printf</span> <span class="string">&quot;</span></span><br><span class="line"><span class="string"><span class="variable">$&#123;CYAN&#125;</span>[ TASK %d ] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</span></span><br><span class="line"><span class="string">&gt;&gt; %s %s<span class="variable">$&#123;RESET&#125;</span></span></span><br><span class="line"><span class="string">&quot;</span> <span class="string">&quot;<span class="variable">$task_number</span>&quot;</span> <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&quot;<span class="variable">$2</span>&quot;</span></span><br><span class="line">    <span class="built_in">printf</span> <span class="string">&quot;</span></span><br><span class="line"><span class="string">&quot;</span></span><br><span class="line">    task_number=$((task_number + <span class="number">1</span>))</span><br><span class="line">  <span class="keyword">fi</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 初始化任务计数器</span></span><br><span class="line">task_number=1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 等待服务就绪（合并为一个任务）</span></span><br><span class="line"><span class="function"><span class="title">wait_for_services</span></span>() &#123;</span><br><span class="line">  <span class="built_in">local</span> retries=15 delay=2 attempt=1</span><br><span class="line">  <span class="built_in">local</span> spinner=(<span class="string">&quot;⣾&quot;</span> <span class="string">&quot;⣽&quot;</span> <span class="string">&quot;⣻&quot;</span> <span class="string">&quot;⢿&quot;</span> <span class="string">&quot;⡿&quot;</span> <span class="string">&quot;⣟&quot;</span> <span class="string">&quot;⣯&quot;</span> <span class="string">&quot;⣷&quot;</span>)</span><br><span class="line">  <span class="built_in">local</span> all_ready=0</span><br><span class="line"></span><br><span class="line">  header <span class="string">&quot;<span class="variable">$ICON_WAIT</span>&quot;</span> <span class="string">&quot;等待 MinIO 服务就绪&quot;</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span> site <span class="keyword">in</span> <span class="string">&quot;<span class="variable">$&#123;!SITES[@]&#125;</span>&quot;</span>; <span class="keyword">do</span></span><br><span class="line">    <span class="built_in">local</span> <span class="built_in">alias</span>=<span class="string">&quot;HEALTHCHECK_<span class="variable">$site</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> url=<span class="string">&quot;<span class="variable">$&#123;SITES[$site]&#125;</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> attempt=1</span><br><span class="line">    <span class="built_in">local</span> all_ready=0</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="built_in">log</span> INFO <span class="string">&quot;检查服务: <span class="variable">$url</span>&quot;</span></span><br><span class="line">    <span class="keyword">while</span> [ <span class="variable">$attempt</span> -le <span class="variable">$retries</span> ]; <span class="keyword">do</span></span><br><span class="line">      <span class="keyword">if</span> /usr/bin/mc <span class="built_in">alias</span> <span class="built_in">set</span> <span class="string">&quot;<span class="variable">$alias</span>&quot;</span> <span class="string">&quot;<span class="variable">$url</span>&quot;</span> <span class="string">&quot;<span class="variable">$MINIO_ACCESS_KEY</span>&quot;</span> <span class="string">&quot;<span class="variable">$MINIO_SECRET_KEY</span>&quot;</span> &gt;/dev/null 2&gt;&amp;1 &amp;&amp; \</span><br><span class="line">         /usr/bin/mc <span class="built_in">ls</span> <span class="string">&quot;<span class="variable">$alias</span>&quot;</span> &gt;/dev/null 2&gt;&amp;1; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">log</span> SUCCESS <span class="string">&quot;服务已就绪: <span class="variable">$url</span>&quot;</span></span><br><span class="line">        all_ready=1</span><br><span class="line">        <span class="keyword">if</span> [ <span class="string">&quot;<span class="variable">$site</span>&quot;</span> = <span class="string">&quot;SITE1&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">          <span class="built_in">printf</span> <span class="string">&quot;<span class="variable">$&#123;CYAN&#125;</span>%s<span class="variable">$&#123;RESET&#125;</span></span></span><br><span class="line"><span class="string">&quot;</span> <span class="string">&quot;<span class="subst">$(for i in $(seq 1 61)</span>; do printf &quot;</span>-<span class="string">&quot;; done)&quot;</span></span><br><span class="line">        <span class="keyword">fi</span></span><br><span class="line">        <span class="built_in">break</span></span><br><span class="line">      <span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">      <span class="built_in">printf</span> <span class="string">&quot;\r%-80s&quot;</span> <span class="string">&quot; &quot;</span></span><br><span class="line">      <span class="built_in">printf</span> <span class="string">&quot;\r<span class="variable">$&#123;YELLOW&#125;</span>%s 尝试 %2d/%-2d 检查服务 %s 中...<span class="variable">$&#123;RESET&#125;</span>&quot;</span> \</span><br><span class="line">        <span class="string">&quot;<span class="variable">$&#123;spinner[$((attempt % <span class="variable">$&#123;#spinner[@]&#125;</span>))]&#125;</span>&quot;</span> \</span><br><span class="line">        <span class="variable">$attempt</span> <span class="variable">$retries</span> <span class="string">&quot;<span class="variable">$url</span>&quot;</span></span><br><span class="line">      <span class="built_in">sleep</span> <span class="variable">$delay</span></span><br><span class="line">      ((attempt++))</span><br><span class="line">      delay=$((delay * <span class="number">2</span> &gt; <span class="number">8</span> ? <span class="number">8</span> : delay * <span class="number">2</span>))</span><br><span class="line">    <span class="keyword">done</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> [ <span class="variable">$all_ready</span> -eq 0 ]; <span class="keyword">then</span></span><br><span class="line">      <span class="built_in">log</span> ERROR <span class="string">&quot;服务 <span class="variable">$url</span> 在 <span class="variable">$retries</span> 次尝试后仍未就绪&quot;</span></span><br><span class="line">      <span class="built_in">exit</span> 1</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">  <span class="keyword">done</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置别名（优化颜色格式）</span></span><br><span class="line"><span class="function"><span class="title">configure_aliases</span></span>() &#123;</span><br><span class="line">  header <span class="string">&quot;<span class="variable">$ICON_CONFIG</span>&quot;</span> <span class="string">&quot;配置 MinIO 站点别名&quot;</span></span><br><span class="line">  <span class="keyword">for</span> site <span class="keyword">in</span> <span class="string">&quot;<span class="variable">$&#123;!SITES[@]&#125;</span>&quot;</span>; <span class="keyword">do</span></span><br><span class="line">    <span class="built_in">local</span> url=<span class="string">&quot;<span class="variable">$&#123;SITES[$site]&#125;</span>&quot;</span></span><br><span class="line">    /usr/bin/mc <span class="built_in">alias</span> remove <span class="string">&quot;<span class="variable">$site</span>&quot;</span> 2&gt;/dev/null || <span class="literal">true</span></span><br><span class="line">    <span class="keyword">if</span> /usr/bin/mc <span class="built_in">alias</span> <span class="built_in">set</span> <span class="string">&quot;<span class="variable">$site</span>&quot;</span> <span class="string">&quot;<span class="variable">$url</span>&quot;</span> <span class="string">&quot;<span class="variable">$MINIO_ACCESS_KEY</span>&quot;</span> <span class="string">&quot;<span class="variable">$MINIO_SECRET_KEY</span>&quot;</span> &gt;/dev/null 2&gt;&amp;1; <span class="keyword">then</span></span><br><span class="line">      <span class="built_in">log</span> SUCCESS <span class="string">&quot;别名配置成功: <span class="variable">$&#123;site&#125;</span> → <span class="variable">$&#123;url&#125;</span>&quot;</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">      <span class="built_in">log</span> ERROR <span class="string">&quot;无法配置别名: <span class="variable">$site</span> → <span class="variable">$url</span>&quot;</span></span><br><span class="line">      <span class="built_in">return</span> 1</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">  <span class="keyword">done</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查复制配置状态</span></span><br><span class="line"><span class="function"><span class="title">check_replication_status</span></span>() &#123;</span><br><span class="line">  /usr/bin/mc admin replicate info SITE1 2&gt;&amp;1 | grep -q <span class="string">&quot;SiteReplication enabled&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 清除原复制配置</span></span><br><span class="line"><span class="function"><span class="title">cleanup_old_replication</span></span>() &#123;</span><br><span class="line">  header <span class="string">&quot;<span class="variable">$ICON_CLEAN</span>&quot;</span> <span class="string">&quot;清理原有复制配置&quot;</span></span><br><span class="line">  <span class="keyword">for</span> site <span class="keyword">in</span> <span class="string">&quot;<span class="variable">$&#123;!SITES[@]&#125;</span>&quot;</span>; <span class="keyword">do</span></span><br><span class="line">    <span class="built_in">log</span> INFO <span class="string">&quot;正在清理 <span class="variable">$site</span> 的复制配置...&quot;</span></span><br><span class="line">    <span class="keyword">if</span> /usr/bin/mc admin replicate <span class="built_in">rm</span> --all <span class="string">&quot;<span class="variable">$site</span>&quot;</span> --force 2&gt;/dev/null; <span class="keyword">then</span></span><br><span class="line">      <span class="built_in">log</span> SUCCESS <span class="string">&quot;成功清理 <span class="variable">$site</span> 的配置&quot;</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">      <span class="built_in">log</span> WARN <span class="string">&quot;<span class="variable">$site</span> 无配置可清理或清理失败&quot;</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">  <span class="keyword">done</span></span><br><span class="line">  <span class="built_in">sleep</span> 2</span><br><span class="line">  <span class="keyword">if</span> check_replication_status; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">log</span> ERROR <span class="string">&quot;复制配置仍存在，请手动检查&quot;</span></span><br><span class="line">    <span class="built_in">return</span> 1</span><br><span class="line">  <span class="keyword">fi</span></span><br><span class="line">  <span class="built_in">log</span> SUCCESS <span class="string">&quot;所有站点复制配置已清理完成&quot;</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 可靠的bucket删除函数</span></span><br><span class="line"><span class="function"><span class="title">delete_all_buckets</span></span>() &#123;</span><br><span class="line">  <span class="built_in">local</span> site=<span class="variable">$1</span></span><br><span class="line">  <span class="built_in">log</span> WARN <span class="string">&quot;即将清空 <span class="variable">$&#123;site&#125;</span> 的所有bucket...&quot;</span></span><br><span class="line">  <span class="built_in">local</span> buckets</span><br><span class="line">  buckets=$(/usr/bin/mc <span class="built_in">ls</span> <span class="string">&quot;<span class="variable">$site</span>&quot;</span> --json | jq -r .key | <span class="built_in">tr</span> -d <span class="string">&#x27;/&#x27;</span> | grep -v <span class="string">&#x27;^$&#x27;</span>)</span><br><span class="line">  <span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$buckets</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">log</span> INFO <span class="string">&quot;没有 bucket 需要删除&quot;</span></span><br><span class="line">    <span class="built_in">return</span> 0</span><br><span class="line">  <span class="keyword">fi</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$buckets</span>&quot;</span> | <span class="keyword">while</span> <span class="built_in">read</span> -r bucket; <span class="keyword">do</span></span><br><span class="line">    <span class="built_in">log</span> INFO <span class="string">&quot;正在删除 <span class="variable">$&#123;site&#125;</span>/<span class="variable">$&#123;bucket&#125;</span>...&quot;</span></span><br><span class="line">    <span class="keyword">if</span> /usr/bin/mc rb --force <span class="string">&quot;<span class="variable">$&#123;site&#125;</span>/<span class="variable">$&#123;bucket&#125;</span>&quot;</span> &gt;/dev/null 2&gt;&amp;1; <span class="keyword">then</span></span><br><span class="line">      <span class="built_in">log</span> SUCCESS <span class="string">&quot;删除成功: <span class="variable">$&#123;site&#125;</span>/<span class="variable">$&#123;bucket&#125;</span>&quot;</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">      <span class="built_in">log</span> ERROR <span class="string">&quot;删除失败: <span class="variable">$&#123;site&#125;</span>/<span class="variable">$&#123;bucket&#125;</span>&quot;</span></span><br><span class="line">      <span class="built_in">return</span> 1</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">  <span class="keyword">done</span></span><br><span class="line">  <span class="keyword">if</span> /usr/bin/mc <span class="built_in">ls</span> <span class="string">&quot;<span class="variable">$site</span>&quot;</span> | grep -q .; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">log</span> ERROR <span class="string">&quot;<span class="variable">$&#123;site&#125;</span> 中仍有bucket存在&quot;</span></span><br><span class="line">    <span class="built_in">return</span> 1</span><br><span class="line">  <span class="keyword">fi</span></span><br><span class="line">  <span class="built_in">log</span> SUCCESS <span class="string">&quot;<span class="variable">$&#123;site&#125;</span> 已完全清空&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置复制配置</span></span><br><span class="line"><span class="function"><span class="title">setup_replication</span></span>() &#123;</span><br><span class="line">  header <span class="string">&quot;<span class="variable">$ICON_NETWORK</span>&quot;</span> <span class="string">&quot;设置站点复制&quot;</span></span><br><span class="line">  <span class="built_in">local</span> retries=5 delay=2 attempt=1</span><br><span class="line">  <span class="built_in">local</span> site_list=(<span class="string">&quot;<span class="variable">$&#123;!SITES[@]&#125;</span>&quot;</span>)</span><br><span class="line">  <span class="keyword">while</span> [ <span class="variable">$attempt</span> -le <span class="variable">$retries</span> ]; <span class="keyword">do</span></span><br><span class="line">    <span class="built_in">log</span> WAIT <span class="string">&quot;尝试配置复制 (<span class="variable">$&#123;attempt&#125;</span>/<span class="variable">$&#123;retries&#125;</span>)...&quot;</span></span><br><span class="line">    output=$(/usr/bin/mc admin replicate add <span class="string">&quot;<span class="variable">$&#123;site_list[@]&#125;</span>&quot;</span> 2&gt;&amp;1)</span><br><span class="line">    <span class="keyword">if</span> [ $? -eq 0 ]; <span class="keyword">then</span></span><br><span class="line">      <span class="built_in">log</span> SUCCESS <span class="string">&quot;站点复制配置成功!&quot;</span></span><br><span class="line">      <span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line">      <span class="built_in">return</span> 0</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">    <span class="keyword">if</span> [[ <span class="variable">$output</span> == *<span class="string">&quot;only one cluster may have data&quot;</span>* ]]; <span class="keyword">then</span></span><br><span class="line">      <span class="built_in">log</span> WARN <span class="string">&quot;检测到 SITE2 中已有数据，违反复制要求&quot;</span></span><br><span class="line">      <span class="keyword">if</span> ! delete_all_buckets <span class="string">&quot;SITE2&quot;</span>; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">log</span> ERROR <span class="string">&quot;清空 SITE2 失败，无法继续&quot;</span></span><br><span class="line">        <span class="built_in">return</span> 1</span><br><span class="line">      <span class="keyword">fi</span></span><br><span class="line">      <span class="built_in">log</span> INFO <span class="string">&quot;等待 <span class="variable">$&#123;delay&#125;</span> 秒让系统完成清理...&quot;</span></span><br><span class="line">      <span class="built_in">sleep</span> <span class="variable">$delay</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">      <span class="built_in">log</span> ERROR <span class="string">&quot;复制配置失败: <span class="subst">$(echo <span class="string">&quot;<span class="variable">$output</span>&quot;</span> | head -n1)</span>&quot;</span></span><br><span class="line">      <span class="built_in">log</span> DEBUG <span class="string">&quot;完整错误: <span class="variable">$output</span>&quot;</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">    ((attempt++))</span><br><span class="line">    delay=$((delay * <span class="number">2</span> &gt; <span class="number">8</span> ? <span class="number">8</span> : delay * <span class="number">2</span>))</span><br><span class="line">  <span class="keyword">done</span></span><br><span class="line">  <span class="built_in">log</span> ERROR <span class="string">&quot;经过 <span class="variable">$&#123;retries&#125;</span> 次尝试后仍无法配置复制&quot;</span></span><br><span class="line">  <span class="built_in">return</span> 1</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 优化状态验证表格</span></span><br><span class="line"><span class="function"><span class="title">verify_status</span></span>() &#123;</span><br><span class="line">  header <span class="string">&quot;<span class="variable">$ICON_NETWORK</span>&quot;</span> <span class="string">&quot;复制状态验证&quot;</span></span><br><span class="line">  <span class="keyword">for</span> site <span class="keyword">in</span> <span class="string">&quot;<span class="variable">$&#123;!SITES[@]&#125;</span>&quot;</span>; <span class="keyword">do</span></span><br><span class="line">    <span class="built_in">printf</span> <span class="string">&quot;<span class="variable">$&#123;GREEN&#125;</span>%s [SUCCESS]   查询成功: %s → %s<span class="variable">$&#123;RESET&#125;</span></span></span><br><span class="line"><span class="string">&quot;</span> <span class="string">&quot;<span class="variable">$ICON_SUCCESS</span>&quot;</span> <span class="string">&quot;<span class="variable">$site</span>&quot;</span> <span class="string">&quot;<span class="variable">$&#123;SITES[$site]&#125;</span>&quot;</span></span><br><span class="line">    <span class="built_in">printf</span> <span class="string">&quot;<span class="variable">$&#123;CYAN&#125;</span>%s<span class="variable">$&#123;RESET&#125;</span></span></span><br><span class="line"><span class="string">&quot;</span> <span class="string">&quot;<span class="subst">$(for i in $(seq 1 160)</span>; do printf &quot;</span>-<span class="string">&quot;; done)&quot;</span></span><br><span class="line">    status_output=$(/usr/bin/mc admin replicate info <span class="string">&quot;<span class="variable">$site</span>&quot;</span> 2&gt;&amp;1)</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$status_output</span>&quot;</span> | grep -q <span class="string">&quot;SiteReplication enabled&quot;</span>; <span class="keyword">then</span></span><br><span class="line">      <span class="built_in">printf</span> <span class="string">&quot;<span class="variable">$&#123;GREEN&#125;</span>%s<span class="variable">$&#123;RESET&#125;</span></span></span><br><span class="line"><span class="string">&quot;</span> <span class="string">&quot;<span class="variable">$status_output</span>&quot;</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">      <span class="built_in">printf</span> <span class="string">&quot;<span class="variable">$&#123;RED&#125;</span>%s<span class="variable">$&#123;RESET&#125;</span></span></span><br><span class="line"><span class="string">&quot;</span> <span class="string">&quot;<span class="variable">$status_output</span>&quot;</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line">  <span class="keyword">done</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 主流程控制</span></span><br><span class="line"><span class="function"><span class="title">main</span></span>() &#123;</span><br><span class="line">  : <span class="string">&quot;<span class="variable">$&#123;SITE1_URL:?需要 SITE1_URL 环境变量&#125;</span>&quot;</span></span><br><span class="line">  : <span class="string">&quot;<span class="variable">$&#123;SITE2_URL:?需要 SITE2_URL 环境变量&#125;</span>&quot;</span></span><br><span class="line">  : <span class="string">&quot;<span class="variable">$&#123;MINIO_ACCESS_KEY:?需要 MINIO_ACCESS_KEY 环境变量&#125;</span>&quot;</span></span><br><span class="line">  : <span class="string">&quot;<span class="variable">$&#123;MINIO_SECRET_KEY:?需要 MINIO_SECRET_KEY 环境变量&#125;</span>&quot;</span></span><br><span class="line">  <span class="built_in">declare</span> -A SITES=([<span class="string">&quot;SITE1&quot;</span>]=<span class="string">&quot;<span class="variable">$SITE1_URL</span>&quot;</span> [<span class="string">&quot;SITE2&quot;</span>]=<span class="string">&quot;<span class="variable">$SITE2_URL</span>&quot;</span>)</span><br><span class="line">  header <span class="string">&quot;<span class="variable">$ICON_START</span>&quot;</span> <span class="string">&quot;MinIO 站点复制初始化&quot;</span></span><br><span class="line">  wait_for_services</span><br><span class="line">  configure_aliases || <span class="built_in">exit</span> 1</span><br><span class="line">  cleanup_old_replication || <span class="built_in">exit</span> 1</span><br><span class="line">  setup_replication || <span class="built_in">exit</span> 1</span><br><span class="line">  verify_status</span><br><span class="line">  header <span class="string">&quot;<span class="variable">$ICON_FINISH</span>&quot;</span> <span class="string">&quot;MinIO 站点复制已就绪&quot;</span></span><br><span class="line">  <span class="built_in">log</span> SUCCESS <span class="string">&quot;所有配置已完成，服务运行中...&quot;</span></span><br><span class="line">  <span class="built_in">log</span> INFO <span class="string">&quot;按 Ctrl+C 停止服务&quot;</span></span><br><span class="line">  <span class="built_in">exec</span> <span class="built_in">tail</span> -f /dev/null</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">trap</span> <span class="string">&#x27;log INFO &quot;收到终止信号，正在关闭...&quot;; exit 0&#x27;</span> SIGTERM SIGINT</span><br><span class="line">main</span><br></pre></td></tr></table></figure><h2 id="部署步骤"><a href="#部署步骤" class="headerlink" title="部署步骤"></a>部署步骤</h2><h3 id="准备环境"><a href="#准备环境" class="headerlink" title="准备环境"></a>准备环境</h3><ol><li>创建目录：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> -p /data/opt/installmiddleware/data/minio/data</span><br></pre></td></tr></table></figure></li><li>设置磁盘权限：<br>确保 20T 磁盘挂载到 <code>/data</code>，并赋予权限：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">chown</span> -R 1000:1000 ./data/minio/data</span><br></pre></td></tr></table></figure></li><li>保存配置：<ul><li>保存 <code>docker-compose.yml</code> 和 <code>.env</code> 文件。</li><li>保存 <code>site-replication.sh</code>，设置可执行权限：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">chmod</span> +x site-replication.sh</span><br></pre></td></tr></table></figure></li></ul></li></ol><h3 id="启动服务"><a href="#启动服务" class="headerlink" title="启动服务"></a>启动服务</h3><p>在 MinIO1 和 MinIO2 服务器上分别部署 MinIO 实例：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">cd</span> /data/opt/installmiddleware</span><br><span class="line">docker-compose up -d</span><br></pre></td></tr></table></figure><h3 id="配置站点复制"><a href="#配置站点复制" class="headerlink" title="配置站点复制"></a>配置站点复制</h3><ul><li><code>minio-mc</code> 容器自动运行 <code>site-replication.sh</code>，配置站点复制。</li><li>检查日志：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker logs --<span class="built_in">tail</span> 100 minio-mc</span><br></pre></td></tr></table></figure>预期输出：<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Configuring aliases for SITE1 and SITE2...</span><br><span class="line">Adding site replication between SITE1 and SITE2...</span><br><span class="line">Site replication configured successfully!</span><br></pre></td></tr></table></figure></li></ul><h2 id="同步测试"><a href="#同步测试" class="headerlink" title="同步测试"></a>同步测试</h2><h3 id="测试目标"><a href="#测试目标" class="headerlink" title="测试目标"></a>测试目标</h3><p>验证 MinIO1 创建的桶和上传的对象是否自动同步到 MinIO2。</p><h3 id="测试步骤"><a href="#测试步骤" class="headerlink" title="测试步骤"></a>测试步骤</h3><ol><li>在 MinIO1 创建桶：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker <span class="built_in">exec</span> -it minio-mc bash</span><br><span class="line">mc mb SITE1/test-bucket</span><br></pre></td></tr></table></figure></li><li>上传测试文件：<ul><li>创建文件：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;Hello, MinIO!&quot;</span> &gt; test.txt</span><br></pre></td></tr></table></figure></li><li>上传到 MinIO1：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">mc <span class="built_in">cp</span> test.txt SITE1/test-bucket</span><br></pre></td></tr></table></figure></li></ul></li><li>验证 MinIO2 同步：<ul><li>检查桶：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">mc <span class="built_in">ls</span> SITE2</span><br></pre></td></tr></table></figure>预期输出：<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">[2025-05-13 16:40:00 CST]     0B test-bucket/</span><br></pre></td></tr></table></figure></li><li>检查文件：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">mc <span class="built_in">ls</span> SITE2/test-bucket</span><br></pre></td></tr></table></figure>预期输出：<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">[2025-05-13 16:40:10 CST]    14B test.txt</span><br></pre></td></tr></table></figure></li></ul></li><li>访问 MinIO2 控制台：<ul><li>打开 <code>http://192.168.199.147:9000</code>，登录（<code>admin</code>&#x2F;<code>Admin@123.com</code>）。</li><li>确认 <code>test-bucket</code> 和 <code>test.txt</code> 存在。</li></ul></li></ol><h3 id="测试结果"><a href="#测试结果" class="headerlink" title="测试结果"></a>测试结果</h3><p>桶和文件成功同步，说明站点复制正常，同步延迟通常在毫秒级（RTT &lt; 20ms）。</p><h2 id="故障恢复测试"><a href="#故障恢复测试" class="headerlink" title="故障恢复测试"></a>故障恢复测试</h2><h3 id="测试目标-1"><a href="#测试目标-1" class="headerlink" title="测试目标"></a>测试目标</h3><p>模拟 MinIO1 故障，验证 MinIO2 的服务可用性，并测试 MinIO1 恢复后的同步。</p><h3 id="测试步骤-1"><a href="#测试步骤-1" class="headerlink" title="测试步骤"></a>测试步骤</h3><ol><li>停止 MinIO1：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker-compose stop minio</span><br></pre></td></tr></table></figure></li><li>检查站点复制状态：<ul><li>在 <code>minio-mc</code> 容器中：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">mc admin replicate status SITE2</span><br></pre></td></tr></table></figure>预期输出（基于实际测试）：<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Bucket replication status:</span><br><span class="line">●  0/1 Buckets in sync</span><br><span class="line">Bucket          | SITE1           | SITE2          </span><br><span class="line">test            |                 | ✗  in-sync     </span><br><span class="line">...</span><br><span class="line">Object replication status:</span><br><span class="line">Link:          ● offline 5 seconds (total downtime: 4 minutes 30 seconds)</span><br><span class="line">Errors:        0 in last 1 minute; 1 in last 1hr</span><br></pre></td></tr></table></figure></li></ul></li><li>验证 MinIO2 服务：<ul><li>上传新文件：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;MinIO2 test&quot;</span> &gt; test2.txt</span><br><span class="line">mc <span class="built_in">cp</span> test2.txt SITE2/test-bucket</span><br></pre></td></tr></table></figure></li><li>检查：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">mc <span class="built_in">ls</span> SITE2/test-bucket</span><br></pre></td></tr></table></figure>预期输出：<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">[2025-05-13 16:45:00 CST]    14B test.txt</span><br><span class="line">[2025-05-13 16:45:10 CST]    12B test2.txt</span><br></pre></td></tr></table></figure></li></ul></li><li>恢复 MinIO1：<ul><li>启动：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker-compose start minio</span><br></pre></td></tr></table></figure></li><li>验证健康：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">curl -f http://192.168.199.145:9000/minio/health/live</span><br></pre></td></tr></table></figure></li></ul></li><li>重新同步：<ul><li>触发增量同步：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">mc admin replicate resync start SITE2 SITE1</span><br></pre></td></tr></table></figure></li><li>检查状态：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">mc admin replicate status SITE2</span><br></pre></td></tr></table></figure>预期输出：<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Site Replication Status:</span><br><span class="line">- Site: SITE1 (http://192.168.199.145:9000) - Online</span><br><span class="line">- Site: SITE2 (http://192.168.199.147:9000) - Online</span><br><span class="line">Replication Status: Active</span><br></pre></td></tr></table></figure></li></ul></li><li>验证 MinIO1 同步：<ul><li>检查：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">mc <span class="built_in">ls</span> SITE1/test-bucket</span><br></pre></td></tr></table></figure>预期输出：<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">[2025-05-13 16:45:00 CST]    14B test.txt</span><br><span class="line">[2025-05-13 16:45:10 CST]    12B test2.txt</span><br></pre></td></tr></table></figure></li></ul></li></ol><h3 id="测试结果-1"><a href="#测试结果-1" class="headerlink" title="测试结果"></a>测试结果</h3><ul><li>MinIO1 故障期间，MinIO2 正常提供服务。</li><li>MinIO1 恢复后，增量数据（<code>test2.txt</code>）同步成功，站点复制恢复正常。</li></ul><h2 id="注意事项与优化建议"><a href="#注意事项与优化建议" class="headerlink" title="注意事项与优化建议"></a>注意事项与优化建议</h2><h3 id="磁盘与虚拟化"><a href="#磁盘与虚拟化" class="headerlink" title="磁盘与虚拟化"></a>磁盘与虚拟化</h3><ul><li>20T 磁盘（虚拟化后 18T）可能受虚拟化影响，建议直通磁盘：<figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">volumes:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">/dev/sdb:/data</span></span><br></pre></td></tr></table></figure></li><li>定期检查磁盘健康：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">smartctl -a /dev/sdb</span><br></pre></td></tr></table></figure></li></ul><h3 id="网络"><a href="#网络" class="headerlink" title="网络"></a>网络</h3><ul><li>确保 RTT &lt; 20ms，带宽 ≥ 1Gbps。</li><li>检查防火墙：<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">ufw allow from 192.168.199.0/24 to any port 9000</span><br></pre></td></tr></table></figure></li></ul><h3 id="安全性"><a href="#安全性" class="headerlink" title="安全性"></a>安全性</h3><ul><li>替换默认凭据（<code>admin</code>&#x2F;<code>Admin@123.com</code>）。</li><li>启用 TLS：<figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">environment:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">MINIO_SERVER_URL=https://192.168.199.145:9000</span></span><br></pre></td></tr></table></figure></li></ul><h3 id="监控"><a href="#监控" class="headerlink" title="监控"></a>监控</h3><ul><li>启用 Prometheus：<figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">environment:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">MINIO_PROMETHEUS_AUTH_TYPE=public</span></span><br></pre></td></tr></table></figure></li><li>使用 Grafana 监控节点状态（<code>minio_node_up</code>）和复制延迟（<code>minio_replication_last_hour_latency_millis</code>）。</li></ul><h3 id="预算"><a href="#预算" class="headerlink" title="预算"></a>预算</h3><ul><li>站点复制需要两台服务器（约 14000-25000 元）。若预算有限，可考虑单向主从复制（约 7000-13000 元）。</li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>通过 Docker Compose 和 <code>site-replication.sh</code>，我们部署了 MinIO 站点复制集群，实现了 MinIO1 和 MinIO2 的数据和元数据同步。同步测试验证了桶和对象的自动同步，故障恢复测试确认了 MinIO2 的高可用性和 MinIO1 恢复后的增量同步。该方案结合 20T 磁盘的存储容量，适用于高可用性场景。</p><p>如需进一步优化（如 webhook 通知、Flask API 集成），请参考 MinIO 文档：<span class="exturl" data-url="aHR0cHM6Ly9taW4uaW8vZG9jcy9taW5pby9saW51eC9vcGVyYXRpb25zL2luc3RhbGwtZGVwbG95LW1hbmFnZS9tdWx0aS1zaXRlLXJlcGxpY2F0aW9uLmh0bWw=">Site Replication<i class="fa fa-external-link-alt"></i></span>。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt; MinIO 是一个高性能的分布式对象存储系统，其站点复制（Site Replication）功能支持跨集群的数据和元数据同步。本文记录了如何使用 Docker Compose 部署 MinIO 站点复制集群，配置两个 MinIO 实例，并进行同步测试和故障恢复测试。测试环境基于 20T 磁盘，适用于需要高可用性和灾难恢复的场景。&lt;/p&gt;</summary>
    
    
    
    <category term="Development" scheme="https://freemankevin.uk/categories/Development/"/>
    
    
    <category term="Docker" scheme="https://freemankevin.uk/tags/Docker/"/>
    
    <category term="MinIO" scheme="https://freemankevin.uk/tags/MinIO/"/>
    
    <category term="SITE Replication" scheme="https://freemankevin.uk/tags/SITE-Replication/"/>
    
    <category term="High Availability" scheme="https://freemankevin.uk/tags/High-Availability/"/>
    
    <category term="Error Recovery" scheme="https://freemankevin.uk/tags/Error-Recovery/"/>
    
  </entry>
  
  <entry>
    <title>如何在 Docker 环境中部署 VLLM</title>
    <link href="https://freemankevin.uk/2025/05/12/docker-vllm/"/>
    <id>https://freemankevin.uk/2025/05/12/docker-vllm/</id>
    <published>2025-05-12T09:14:25.000Z</published>
    <updated>2026-04-17T10:30:31.801Z</updated>
    
    <content type="html"><![CDATA[<p> 本指南将详细介绍如何在 Windows 和 Linux 系统上使用 Docker 部署 vLLM 大模型服务，并提供跨平台测试方案。</p><span id="more"></span><h2 id="系统要求"><a href="#系统要求" class="headerlink" title="系统要求"></a>系统要求</h2><h3 id="硬件要求"><a href="#硬件要求" class="headerlink" title="硬件要求"></a>硬件要求</h3><ul><li>NVIDIA GPU (建议 RTX 3060 或更高)</li><li>显存要求:<ul><li>Qwen&#x2F;Qwen3-0.6B: 至少 8GB （本地测试）</li><li>Qwen&#x2F;QwQ-32B: 至少 64GB（生产使用）</li></ul></li><li>内存: 16GB 或更高</li></ul><h3 id="软件要求"><a href="#软件要求" class="headerlink" title="软件要求"></a>软件要求</h3><ul><li>操作系统:<ul><li>Windows 10&#x2F;11 (专业版&#x2F;企业版)</li><li>Linux (Ubuntu 20.04+&#x2F;CentOS 7+)</li></ul></li><li>Docker Engine 20.10+</li><li>NVIDIA 驱动 535+</li><li>NVIDIA Container Toolkit</li></ul><h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><h3 id="1-安装必要组件"><a href="#1-安装必要组件" class="headerlink" title="1. 安装必要组件"></a>1. 安装必要组件</h3><p><strong>Windows 环境:</strong></p><figure class="highlight powershell"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 安装 WSL2 (Windows 子系统)</span></span><br><span class="line">wsl <span class="literal">--install</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装 Docker Desktop</span></span><br><span class="line"><span class="comment"># 从 https://www.docker.com/products/docker-desktop 下载安装</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装 NVIDIA 驱动和 CUDA</span></span><br><span class="line"><span class="comment"># 从 https://developer.nvidia.com/cuda-downloads 下载</span></span><br></pre></td></tr></table></figure><p><strong>Linux 环境:</strong></p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 安装 Docker</span></span><br><span class="line"><span class="built_in">sudo</span> apt-get update</span><br><span class="line"><span class="built_in">sudo</span> apt-get install docker-ce docker-ce-cli containerd.io</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装 NVIDIA Container Toolkit</span></span><br><span class="line">distribution=$(. /etc/os-release;<span class="built_in">echo</span> $ID<span class="variable">$VERSION_ID</span>) \</span><br><span class="line">   &amp;&amp; curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | <span class="built_in">sudo</span> apt-key add - \</span><br><span class="line">   &amp;&amp; curl -s -L https://nvidia.github.io/nvidia-docker/<span class="variable">$distribution</span>/nvidia-docker.list | <span class="built_in">sudo</span> <span class="built_in">tee</span> /etc/apt/sources.list.d/nvidia-docker.list</span><br><span class="line"><span class="built_in">sudo</span> apt-get update</span><br><span class="line"><span class="built_in">sudo</span> apt-get install -y nvidia-docker2</span><br><span class="line"><span class="built_in">sudo</span> systemctl restart docker</span><br></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="code"><pre><span class="line"><span class="comment"># 验证 Docker 安装</span></span><br><span class="line">docker --version</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证 NVIDIA 支持</span></span><br><span class="line">docker run --<span class="built_in">rm</span> --gpus all nvidia/cuda:11.0.3-base-ubuntu20.04 nvidia-smi</span><br></pre></td></tr></table></figure><h2 id="Docker-部署"><a href="#Docker-部署" class="headerlink" title="Docker 部署"></a>Docker 部署</h2><h3 id="1-创建-docker-compose-yml-文件"><a href="#1-创建-docker-compose-yml-文件" class="headerlink" title="1. 创建 docker-compose.yml 文件"></a>1. 创建 docker-compose.yml 文件</h3><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># version: &#x27;3.8&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">vllm:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">vllm/vllm-openai:latest</span></span><br><span class="line">    <span class="attr">runtime:</span> <span class="string">nvidia</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">vllm</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span> </span><br><span class="line">    <span class="attr">deploy:</span></span><br><span class="line">      <span class="attr">resources:</span></span><br><span class="line">        <span class="attr">reservations:</span></span><br><span class="line">          <span class="attr">devices:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="attr">driver:</span> <span class="string">nvidia</span></span><br><span class="line">              <span class="attr">capabilities:</span> [<span class="string">gpu</span>]</span><br><span class="line">              <span class="attr">count:</span> <span class="string">all</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">$HOME/.cache/huggingface:/root/.cache/huggingface</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;28000:8000&quot;</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">HF_HOME=/root/.cache/huggingface</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True</span></span><br><span class="line">    <span class="attr">command:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">--model</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">Qwen/Qwen3-0.6B</span> <span class="comment"># 或 Qwen/QwQ-32B</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">--gpu-memory-utilization</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;0.8&quot;</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">--trust-remote-code</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">--max-num-seqs</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;256&quot;</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD-SHELL&quot;</span>, <span class="string">&quot;curl -f http://localhost:8000/health || exit 1&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">30s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">3</span></span><br><span class="line">      <span class="attr">start_period:</span> <span class="string">60s</span></span><br></pre></td></tr></table></figure><p><strong>Windows 用户注意</strong>:</p><ul><li>将 <code>$HOME/.cache/huggingface</code> 替换为 <code>C:/Users/Devops/.cache/huggingface</code></li><li>确保路径使用正斜杠 <code>/</code> 而非反斜杠 <code>\</code></li></ul><h3 id="2-启动服务"><a href="#2-启动服务" class="headerlink" title="2. 启动服务"></a>2. 启动服务</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 下载 vLLM 镜像</span></span><br><span class="line">docker pull vllm/vllm-openai:latest</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动服务</span></span><br><span class="line">docker-compose up -d</span><br></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="code"><pre><span class="line"><span class="comment"># 检查容器状态</span></span><br><span class="line">docker ps</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看日志</span></span><br><span class="line">docker logs vllm</span><br><span class="line"></span><br><span class="line"><span class="comment"># 健康检查</span></span><br><span class="line">curl http://localhost:28000/health</span><br></pre></td></tr></table></figure><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="code"><pre><span class="line"><span class="comment"># 安装 huggingface_hub</span></span><br><span class="line">pip install huggingface_hub</span><br><span class="line"></span><br><span class="line"><span class="comment"># 下载模型 (可在宿主机执行)</span></span><br><span class="line">huggingface-cli download Qwen/Qwen3-0.6B </span><br><span class="line"></span><br><span class="line"><span class="comment"># 模型默认存放在用户家目录下，比如:</span></span><br><span class="line"><span class="comment"># C:/Users/Devops/.cache/huggingface/hub/models--Qwen--Qwen3-0.6B</span></span><br></pre></td></tr></table></figure><h3 id="2-使用-vLLM-自动下载"><a href="#2-使用-vLLM-自动下载" class="headerlink" title="2. 使用 vLLM 自动下载"></a>2. 使用 vLLM 自动下载</h3><p>vLLM 会在首次启动时自动下载模型，但建议提前下载以避免超时。</p><h2 id="服务测试"><a href="#服务测试" class="headerlink" title="服务测试"></a>服务测试</h2><h3 id="1-使用-curl-测试"><a href="#1-使用-curl-测试" class="headerlink" title="1. 使用 curl 测试"></a>1. 使用 curl 测试</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">curl http://localhost:28000/v1/completions \</span><br><span class="line">  -H <span class="string">&quot;Content-Type: application/json&quot;</span> \</span><br><span class="line">  -d <span class="string">&#x27;&#123;</span></span><br><span class="line"><span class="string">      &quot;model&quot;: &quot;Qwen/Qwen3-0.6B&quot;,</span></span><br><span class="line"><span class="string">      &quot;prompt&quot;: &quot;你好，介绍一下你自己&quot;,</span></span><br><span class="line"><span class="string">      &quot;max_tokens&quot;: 100</span></span><br><span class="line"><span class="string">  &#125;&#x27;</span></span><br></pre></td></tr></table></figure><h3 id="2-使用-HTML-测试界面"><a href="#2-使用-HTML-测试界面" class="headerlink" title="2. 使用 HTML 测试界面"></a>2. 使用 HTML 测试界面</h3><p>创建 <code>vllm-test.html</code> 文件：</p><figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h2</span>&gt;</span>vLLM 测试界面<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">textarea</span> <span class="attr">id</span>=<span class="string">&quot;input&quot;</span> <span class="attr">rows</span>=<span class="string">&quot;4&quot;</span> <span class="attr">cols</span>=<span class="string">&quot;50&quot;</span> <span class="attr">placeholder</span>=<span class="string">&quot;输入提示词...&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">textarea</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> <span class="attr">onclick</span>=<span class="string">&quot;generate()&quot;</span>&gt;</span>生成<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">pre</span> <span class="attr">id</span>=<span class="string">&quot;output&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">pre</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">generate</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> input = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;input&quot;</span>).<span class="property">value</span>;</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">try</span> &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">fetch</span>(<span class="string">&quot;http://localhost:28000/v1/completions&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">method</span>: <span class="string">&quot;POST&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">headers</span>: &#123; <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/json&quot;</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">body</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">model</span>: <span class="string">&quot;Qwen/Qwen3-0.6B&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">prompt</span>: input,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">max_tokens</span>: <span class="number">100</span></span></span><br><span class="line"><span class="language-javascript">          &#125;)</span></span><br><span class="line"><span class="language-javascript">        &#125;);</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">const</span> result = <span class="keyword">await</span> response.<span class="title function_">json</span>();</span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;output&quot;</span>).<span class="property">textContent</span> = result.<span class="property">choices</span>[<span class="number">0</span>].<span class="property">text</span>;</span></span><br><span class="line"><span class="language-javascript">      &#125; <span class="keyword">catch</span> (error) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;output&quot;</span>).<span class="property">textContent</span> = <span class="string">&quot;错误: &quot;</span> + error.<span class="property">message</span>;</span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript">  </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="跨平台测试方案"><a href="#跨平台测试方案" class="headerlink" title="跨平台测试方案"></a>跨平台测试方案</h2><h3 id="Windows-环境测试"><a href="#Windows-环境测试" class="headerlink" title="Windows 环境测试"></a>Windows 环境测试</h3><ol><li><p><strong>浏览器安全限制</strong>:</p><ul><li>Chrome&#x2F;Firefox 默认阻止跨域请求</li><li>解决方案:<ul><li>使用 <code>file:///</code> 协议直接打开 HTML 文件</li><li>或使用以下命令启动 Chrome 禁用安全限制:<figure class="highlight powershell"><table><tr><td class="code"><pre><span class="line">chrome.exe <span class="literal">--user-data-dir</span>=<span class="string">&quot;C:/Temp&quot;</span> <span class="literal">--disable-web-security</span></span><br></pre></td></tr></table></figure></li></ul></li></ul></li><li><p><strong>替代方案</strong>:</p><ul><li>使用 Postman 或 Insomnia 测试 API</li><li>使用 Python 脚本测试:<figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">from</span> openai <span class="keyword">import</span> OpenAI</span><br><span class="line"></span><br><span class="line">client = OpenAI(base_url=<span class="string">&quot;http://localhost:28000/v1&quot;</span>, api_key=<span class="string">&quot;token-abc123&quot;</span>)</span><br><span class="line"></span><br><span class="line">completion = client.completions.create(</span><br><span class="line">    model=<span class="string">&quot;Qwen/Qwen3-0.6B&quot;</span>,</span><br><span class="line">    prompt=<span class="string">&quot;你好，介绍一下你自己&quot;</span>,</span><br><span class="line">    max_tokens=<span class="number">100</span></span><br><span class="line">)</span><br><span class="line"><span class="built_in">print</span>(completion.choices[<span class="number">0</span>].text)</span><br></pre></td></tr></table></figure></li></ul></li></ol><h3 id="Linux-环境测试"><a href="#Linux-环境测试" class="headerlink" title="Linux 环境测试"></a>Linux 环境测试</h3><ol><li><p><strong>浏览器测试</strong>:</p><ul><li>可直接使用 Firefox 打开 HTML 文件</li><li>或部署简单 HTTP 服务器:<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">python3 -m http.server 8000</span><br></pre></td></tr></table></figure>然后访问 <code>http://localhost:8000/vllm-test.html</code></li></ul></li><li><p><strong>命令行测试</strong>:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 使用 httpie 工具</span></span><br><span class="line">http POST http://localhost:28000/v1/completions \</span><br><span class="line">  model=<span class="string">&quot;Qwen/Qwen3-0.6B&quot;</span> \</span><br><span class="line">  prompt=<span class="string">&quot;你好&quot;</span> \</span><br><span class="line">  max_tokens:=50</span><br></pre></td></tr></table></figure></li></ol><h2 id="常见问题解决"><a href="#常见问题解决" class="headerlink" title="常见问题解决"></a>常见问题解决</h2><h3 id="1-模型下载失败"><a href="#1-模型下载失败" class="headerlink" title="1. 模型下载失败"></a>1. 模型下载失败</h3><p><strong>症状</strong>: 容器日志显示下载超时或失败</p><p><strong>解决方案</strong>:</p><ul><li>手动下载模型到缓存目录</li><li>设置 HTTP 代理:<figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">environment:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">HF_HUB_ENABLE_HF_TRANSFER=1</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">http_proxy=http://your-proxy:port</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">https_proxy=http://your-proxy:port</span></span><br></pre></td></tr></table></figure></li></ul><h3 id="2-GPU-内存不足"><a href="#2-GPU-内存不足" class="headerlink" title="2. GPU 内存不足"></a>2. GPU 内存不足</h3><p><strong>症状</strong>: CUDA out of memory 错误</p><p><strong>解决方案</strong>:</p><ul><li>降低 <code>--gpu-memory-utilization</code> 值 (如 0.5)</li><li>使用更小模型 (如 Qwen3-0.6B 替代 QwQ-32B)</li><li>添加 <code>--enforce-eager</code> 参数减少内存占用</li></ul><h3 id="3-跨域问题-CORS"><a href="#3-跨域问题-CORS" class="headerlink" title="3. 跨域问题 (CORS)"></a>3. 跨域问题 (CORS)</h3><p><strong>症状</strong>: HTML 测试界面无法访问 API</p><p><strong>解决方案</strong>:</p><ul><li>启动 vLLM 时添加 CORS 参数:<figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">command:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">--model</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">Qwen/Qwen3-0.6B</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">--cors-allow-origins</span> <span class="string">&quot;*&quot;</span></span><br></pre></td></tr></table></figure></li><li>或使用 Nginx 反向代理配置 CORS</li></ul><h3 id="4-Windows-路径问题"><a href="#4-Windows-路径问题" class="headerlink" title="4. Windows 路径问题"></a>4. Windows 路径问题</h3><p><strong>症状</strong>: 卷挂载失败</p><p><strong>解决方案</strong>:</p><ul><li>使用绝对路径并确保 Docker Desktop 已启用 “Shared Drives”</li><li>示例:<figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">volumes:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">C:/Users/Devops/.cache/huggingface:/root/.cache/huggingface</span></span><br></pre></td></tr></table></figure></li></ul><h2 id="性能优化建议"><a href="#性能优化建议" class="headerlink" title="性能优化建议"></a>性能优化建议</h2><ol><li><p><strong>量化</strong>:</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">command:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">--model</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">Qwen/Qwen3-0.6B</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">--quantization</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">awq</span>  <span class="comment"># 或 gptq</span></span><br></pre></td></tr></table></figure></li><li><p><strong>批处理优化</strong>:</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">command:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">--max-num-batched-tokens</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">&quot;4096&quot;</span></span><br></pre></td></tr></table></figure></li><li><p><strong>并行推理</strong>:</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">command:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">--tensor-parallel-size</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">&quot;2&quot;</span>  <span class="comment"># 使用2个GPU</span></span><br></pre></td></tr></table></figure></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt; 本指南将详细介绍如何在 Windows 和 Linux 系统上使用 Docker 部署 vLLM 大模型服务，并提供跨平台测试方案。&lt;/p&gt;</summary>
    
    
    
    <category term="Development" scheme="https://freemankevin.uk/categories/Development/"/>
    
    
    <category term="Docker" scheme="https://freemankevin.uk/tags/Docker/"/>
    
    <category term="VLLM" scheme="https://freemankevin.uk/tags/VLLM/"/>
    
    <category term="OPenAI" scheme="https://freemankevin.uk/tags/OPenAI/"/>
    
    <category term="LLM" scheme="https://freemankevin.uk/tags/LLM/"/>
    
  </entry>
  
  <entry>
    <title>使用 Cloudflare Tunnel 安全暴露本地服务到公网</title>
    <link href="https://freemankevin.uk/2025/04/23/Cloudflare-Tunnel/"/>
    <id>https://freemankevin.uk/2025/04/23/Cloudflare-Tunnel/</id>
    <published>2025-04-23T07:14:25.000Z</published>
    <updated>2026-04-17T10:30:31.801Z</updated>
    
    <content type="html"><![CDATA[<p> Cloudflare Tunnel 是一种强大的反向隧道服务，允许用户将本地服务器或内部网络资源安全暴露到公网，而无需开放防火墙端口或拥有公网 IP 地址。本文将详细介绍 Cloudflare Tunnel 的工作原理、功能特点、使用场景，并结合实际操作步骤，展示如何通过 Cloudflare Tunnel 将本地服务映射到公网域名。</p><span id="more"></span><h2 id="什么是-Cloudflare-Tunnel？"><a href="#什么是-Cloudflare-Tunnel？" class="headerlink" title="什么是 Cloudflare Tunnel？"></a>什么是 Cloudflare Tunnel？</h2><p>Cloudflare Tunnel 是 Cloudflare 提供的一项服务，通过运行轻量级客户端 <code>cloudflared</code>，在本地设备与 Cloudflare 全球网络之间建立安全的出站连接（outbound-only）。外部用户可以通过 Cloudflare 的网络访问你的本地服务，而无需直接暴露服务器的 IP 或端口。</p><h3 id="工作原理"><a href="#工作原理" class="headerlink" title="工作原理"></a>工作原理</h3><ol><li><strong>安装客户端</strong>：在本地服务器或设备上安装 <code>cloudflared</code>，这是 Cloudflare 提供的隧道守护进程。</li><li><strong>创建隧道</strong>：使用 <code>cloudflared</code> 创建一个隧道，与 Cloudflare 边缘网络建立连接，无需公网 IP。</li><li><strong>路由流量</strong>：在 Cloudflare 仪表盘中配置域名或子域名，外部请求通过 Cloudflare 转发到本地服务。</li><li><strong>安全性保障</strong>：所有流量经过 Cloudflare 的加密，支持 HTTPS，并可结合 Cloudflare Access 添加身份验证。</li></ol><h3 id="主要特点"><a href="#主要特点" class="headerlink" title="主要特点"></a>主要特点</h3><ul><li><strong>无需端口转发</strong>：无需配置路由器或开放防火墙端口，适合家庭网络或受限环境。</li><li><strong>免费基础服务</strong>：基本功能（如创建隧道、绑定域名）免费，适合个人用户或小型项目。</li><li><strong>安全性增强</strong>：提供 DDoS 防护、SSL&#x2F;TLS 加密，流量通过 Cloudflare 全球网络。</li><li><strong>灵活性</strong>：支持多种协议（如 HTTP、SSH、RDP），可暴露网页服务、远程桌面或游戏服务器。</li></ul><h3 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h3><ul><li><strong>远程访问本地服务</strong>：如在家运行 NAS，想通过公网访问文件管理界面。</li><li><strong>开发测试</strong>：快速将本地开发环境暴露到公网，测试 webhook 或第三方回调。</li><li><strong>替代 VPN</strong>：相比传统 VPN，Cloudflare Tunnel 配置简单，适合快速部署。</li></ul><h3 id="对比-ngrok"><a href="#对比-ngrok" class="headerlink" title="对比 ngrok"></a>对比 ngrok</h3><p>与类似的反向隧道工具 ngrok 相比，Cloudflare Tunnel 有以下优势：</p><ul><li><strong>成本</strong>：ngrok 免费版有严格的时长（2小时断开）和连接限制，而 Cloudflare Tunnel 免费版更宽松。</li><li><strong>域名</strong>：ngrok 免费版提供随机域名，Cloudflare 支持自定义域名。</li><li><strong>安全性</strong>：Cloudflare 提供额外的 DDoS 防护和全球 CDN 加速。</li></ul><h2 id="实践：使用-Cloudflare-Tunnel-暴露本地服务"><a href="#实践：使用-Cloudflare-Tunnel-暴露本地服务" class="headerlink" title="实践：使用 Cloudflare Tunnel 暴露本地服务"></a>实践：使用 Cloudflare Tunnel 暴露本地服务</h2><p>下面，我们将通过实际操作，展示如何使用 Cloudflare Tunnel 将本地运行的网页服务（<code>http://localhost:19000</code>）映射到公网域名 <code>share.freemankevin.uk</code>。</p><h3 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h3><ol><li>注册 Cloudflare 账号：登录 Cloudflare 仪表盘，添加你的域名并确保 DNS 托管在 Cloudflare。</li><li>安装 <code>cloudflared</code>：<ul><li>在 Windows 上，下载 <span class="exturl" data-url="aHR0cHM6Ly9kZXZlbG9wZXJzLmNsb3VkZmxhcmUuY29tL2Nsb3VkZmxhcmUtb25lL2Nvbm5lY3Rpb25zL2Nvbm5lY3QtYXBwcy9pbnN0YWxsLWFuZC1zZXR1cC9pbnN0YWxsYXRpb24v">cloudflared.exe<i class="fa fa-external-link-alt"></i></span>（官方下载地址）。</li><li>将 <code>cloudflared.exe</code> 放置在合适目录（如 <code>C:\cloudflared\</code>）。</li></ul></li></ol><h3 id="安装-Cloudflare-Tunnel-服务"><a href="#安装-Cloudflare-Tunnel-服务" class="headerlink" title="安装 Cloudflare Tunnel 服务"></a>安装 Cloudflare Tunnel 服务</h3><p>运行以下命令以安装 <code>cloudflared</code> 服务并绑定 Cloudflare 账户：</p><figure class="highlight powershell"><table><tr><td class="code"><pre><span class="line">cloudflared.exe service install eyJhIjoiMjc0YzhmYzViSa2kih1k3MzVhNjBjNWQ1MTkzOWQyMDEiLCJ0IjoiMDEwNDI5MmEtNzEwYS00NTBkLWI3OGYtOTNjZTExYjhmYTZlIiwicyI6Ik56Um1ZVGcyT0dRdE9XUm1OaTAwWkRJM0xUbGxZemN0TWpKbFlUWmhabiJzTlRRMiJ9</span><br></pre></td></tr></table></figure><div class="note warning"><p><code>eyJh...</code> 是 Cloudflare 提供的认证令牌，请替换为你自己的令牌（从 Cloudflare 仪表盘获取）。</p></div><p>成功后，<code>cloudflared</code> 将作为系统服务运行。</p><h3 id="创建隧道"><a href="#创建隧道" class="headerlink" title="创建隧道"></a>创建隧道</h3><p>创建名为 <code>share</code> 的隧道：</p><figure class="highlight powershell"><table><tr><td class="code"><pre><span class="line">cloudflared tunnel create share</span><br></pre></td></tr></table></figure><p>输出类似以下内容：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Tunnel credentials written to C:\Users\Devops\.cloudflared\ab9d567c-00c0-46f3-83b7-680ei8b2f3f6.json. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel.</span><br><span class="line"></span><br><span class="line">Created tunnel share with id ab9d567c-00c0-46f3-83b7-680ei8b2f3f6</span><br></pre></td></tr></table></figure><p>这会生成一个隧道 ID（<code>ab9d567c-00c0-46f3-83b7-680ei8b2f3f6</code>）和凭证文件（<code>ab9d567c-00c0-46f3-83b7-680ei8b2f3f6.json</code>）。请妥善保存凭证文件，避免泄露。</p><h3 id="配置隧道"><a href="#配置隧道" class="headerlink" title="配置隧道"></a>配置隧道</h3><p>创建配置文件 <code>config.yml</code>，内容如下：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">tunnel:</span> <span class="string">share</span></span><br><span class="line"><span class="attr">credentials-file:</span> <span class="string">C:\Users\Devops\.cloudflared\ab9d567c-00c0-46f3-83b7-680ei8b2f3f6.json</span></span><br><span class="line"><span class="attr">ingress:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">hostname:</span> <span class="string">share.freemankevin.uk</span></span><br><span class="line">    <span class="attr">service:</span> <span class="string">http://localhost:19000</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">service:</span> <span class="string">http_status:404</span></span><br></pre></td></tr></table></figure><ul><li><code>tunnel</code>：指定隧道名称（<code>share</code>）。</li><li><code>credentials-file</code>：指定凭证文件路径。</li><li><code>ingress</code>：定义路由规则，将 <code>share.freemankevin.uk</code> 的请求转发到本地 <code>http://localhost:19000</code>，其他请求返回 404。</li></ul><p>将 <code>config.yml</code> 保存到 <code>C:\Users\Devops\.cloudflared\</code> 目录。</p><h3 id="配置-DNS-记录"><a href="#配置-DNS-记录" class="headerlink" title="配置 DNS 记录"></a>配置 DNS 记录</h3><p>在 Cloudflare 仪表盘中，添加 CNAME 记录：</p><table><thead><tr><th>类型</th><th>名称</th><th>目标</th></tr></thead><tbody><tr><td>CNAME</td><td>share</td><td>ab9d567c-00c0-46f3-83b7-680ei8b2f3f6.cfargotunnel.com</td></tr></tbody></table><p>或者，使用以下命令自动配置 DNS：</p><figure class="highlight powershell"><table><tr><td class="code"><pre><span class="line">cloudflared tunnel route dns share share.freemankevin.uk</span><br></pre></td></tr></table></figure><h3 id="运行隧道"><a href="#运行隧道" class="headerlink" title="运行隧道"></a>运行隧道</h3><p>运行以下命令启动隧道：</p><figure class="highlight powershell"><table><tr><td class="code"><pre><span class="line">cloudflared tunnel <span class="literal">--config</span> C:\Users\Devops\.cloudflared\config.yml <span class="literal">--origin-ca-pool</span> C:\Users\Devops\.cloudflared\ca<span class="literal">-certificates</span>.pem <span class="literal">--logfile</span> C:\Users\Devops\.cloudflared\cloudflared.log run share</span><br></pre></td></tr></table></figure><p>参数说明：</p><ul><li><code>--config</code>：指定配置文件路径。</li><li><code>--origin-ca-pool</code>：指定 CA 证书路径（可选，通常用于企业环境）。</li><li><code>--logfile</code>：指定日志文件路径，便于调试。</li></ul><p>启动后，<code>share.freemankevin.uk</code> 将可通过公网访问，并指向本地 <code>http://localhost:19000</code> 的服务。</p><h3 id="测试访问"><a href="#测试访问" class="headerlink" title="测试访问"></a>测试访问</h3><p>在浏览器中访问 <code>https://share.freemankevin.uk</code>，确认是否能正常访问本地服务。如果无法访问，检查以下内容：</p><ol><li>确保本地服务（<code>http://localhost:19000</code>）正在运行。</li><li>检查 Cloudflare 仪表盘中的 DNS 记录是否正确。</li><li>查看 <code>cloudflared</code> 日志（<code>C:\Users\Devops\.cloudflared\cloudflared.log</code>）以排查错误。</li></ol><h3 id="添加系统服务"><a href="#添加系统服务" class="headerlink" title="添加系统服务"></a>添加系统服务</h3><p>为了方便启动和管理隧道，我们可以将上面的隧道共享服务添加到系统服务中：</p><h4 id="添加服务"><a href="#添加服务" class="headerlink" title="添加服务"></a>添加服务</h4><figure class="highlight powershell"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 以管理员身份打开 PowerShell</span></span><br><span class="line"><span class="comment"># 创建系统服务</span></span><br><span class="line"><span class="built_in">sc</span> create CloudflaredTunnel binPath= <span class="string">&quot;C:\Program Files (x86)\cloudflared\cloudflared.exe tunnel --config C:\Users\Devops\.cloudflared\config.yml run share&quot;</span> <span class="built_in">start</span>= auto DisplayName= <span class="string">&quot;Cloudflare Tunnel Service&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置服务描述</span></span><br><span class="line"><span class="built_in">sc</span> description CloudflaredTunnel <span class="string">&quot;Cloudflare Tunnel for secure remote access&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置故障恢复（自动重启）</span></span><br><span class="line"><span class="built_in">sc</span> failure CloudflaredTunnel reset= <span class="number">30</span> actions= restart/<span class="number">5000</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动服务</span></span><br><span class="line"><span class="built_in">sc</span> <span class="built_in">start</span> CloudflaredTunnel</span><br></pre></td></tr></table></figure><p>添加后，<code>cloudflared</code> 将作为系统服务运行，无需手动启动。</p><h4 id="卸载服务"><a href="#卸载服务" class="headerlink" title="卸载服务"></a>卸载服务</h4><p>如果不再需要该服务，可以卸载：</p><figure class="highlight powershell"><table><tr><td class="code"><pre><span class="line"><span class="built_in">sc</span> delete CloudflaredTunnel</span><br></pre></td></tr></table></figure><h2 id="免费版限制"><a href="#免费版限制" class="headerlink" title="免费版限制"></a>免费版限制</h2><ul><li><strong>带宽</strong>：Cloudflare Tunnel 免费版没有明确的带宽限制，但可能对滥用行为进行限制。</li><li><strong>功能</strong>：高级功能（如负载均衡、Zero Trust 策略）需要付费计划。</li><li><strong>域名</strong>：需使用 Cloudflare 托管的域名（可免费注册或迁移现有域名）。</li></ul><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="隧道无法连接？"><a href="#隧道无法连接？" class="headerlink" title="隧道无法连接？"></a>隧道无法连接？</h3><ul><li>检查 <code>cloudflared</code> 是否正常运行，查看日志文件。</li><li>确保网络允许 <code>cloudflared</code> 的出站连接（端口 443）。</li></ul><h3 id="DNS-配置失败？"><a href="#DNS-配置失败？" class="headerlink" title="DNS 配置失败？"></a>DNS 配置失败？</h3><ul><li>确认域名已正确托管在 Cloudflare。</li><li>检查 CNAME 记录是否指向正确的隧道地址。</li></ul><h3 id="如何停止隧道？"><a href="#如何停止隧道？" class="headerlink" title="如何停止隧道？"></a>如何停止隧道？</h3><ul><li>按 <code>Ctrl+C</code> 停止 <code>cloudflared</code> 进程。</li><li>或删除隧道：<code>cloudflared tunnel delete share</code>。</li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>Cloudflare Tunnel 是一个简单、安全且免费的工具，适合将本地服务暴露到公网。通过以上步骤，你可以轻松将本地网页服务映射到自定义域名，并享受 Cloudflare 提供的加密和 DDoS 防护。相比 ngrok，Cloudflare Tunnel 在成本、灵活性和安全性上更具优势，非常适合个人开发者、家庭用户或小型项目。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt; Cloudflare Tunnel 是一种强大的反向隧道服务，允许用户将本地服务器或内部网络资源安全暴露到公网，而无需开放防火墙端口或拥有公网 IP 地址。本文将详细介绍 Cloudflare Tunnel 的工作原理、功能特点、使用场景，并结合实际操作步骤，展示如何通过 Cloudflare Tunnel 将本地服务映射到公网域名。&lt;/p&gt;</summary>
    
    
    
    <category term="Development" scheme="https://freemankevin.uk/categories/Development/"/>
    
    
    <category term="Cloudflare" scheme="https://freemankevin.uk/tags/Cloudflare/"/>
    
    <category term="Intranet penetration" scheme="https://freemankevin.uk/tags/Intranet-penetration/"/>
    
    <category term="DevOps" scheme="https://freemankevin.uk/tags/DevOps/"/>
    
  </entry>
  
  <entry>
    <title>在 Docker 环境中部署 Nexus 仓库</title>
    <link href="https://freemankevin.uk/2025/04/22/docker-nexus/"/>
    <id>https://freemankevin.uk/2025/04/22/docker-nexus/</id>
    <published>2025-04-22T07:14:25.000Z</published>
    <updated>2026-04-17T10:30:31.801Z</updated>
    
    <content type="html"><![CDATA[<p> Nexus是一个功能强大的仓库管理工具，用于托管Maven工件、Docker镜像等。本文将详细介绍如何在Docker环境中部署Nexus仓库管理器，并集成PostgreSQL数据库、快照清理服务和数据库备份服务。</p><span id="more"></span><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="code"><pre><span class="line"><span class="comment"># 创建Nexus数据目录</span></span><br><span class="line"><span class="built_in">mkdir</span> -p ./nexus/sonatype-work</span><br><span class="line"><span class="built_in">chmod</span> -R 755 ./nexus/sonatype-work</span><br><span class="line"><span class="built_in">chown</span> -R 200:200 ./nexus/sonatype-work</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建Nexus密钥目录</span></span><br><span class="line"><span class="built_in">mkdir</span> -p ./nexus/secret</span><br><span class="line"><span class="built_in">cat</span> &gt; ./nexus/secret/nexus-secrets.json &lt;&lt;<span class="string">EOF</span></span><br><span class="line"><span class="string">&#123;</span></span><br><span class="line"><span class="string">  &quot;active&quot;: &quot;nexus-key&quot;,</span></span><br><span class="line"><span class="string">  &quot;keys&quot;: [</span></span><br><span class="line"><span class="string">    &#123;</span></span><br><span class="line"><span class="string">      &quot;id&quot;: &quot;nexus-key&quot;,</span></span><br><span class="line"><span class="string">      &quot;key&quot;: &quot;$(openssl rand -base64 32)&quot;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">  ]</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置权限</span></span><br><span class="line"><span class="built_in">chmod</span> 600 ./nexus/secret/nexus-secrets.json</span><br><span class="line"><span class="built_in">chown</span> 200:200 ./nexus/secret/nexus-secrets.json</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建PostgreSQL目录</span></span><br><span class="line"><span class="built_in">mkdir</span> -p ./postgres/data ./postgres/dbbackups</span><br><span class="line"><span class="built_in">chmod</span> -R 755 ./postgres/data ./postgres/dbbackups</span><br><span class="line"><span class="built_in">chown</span> -R 101:103 ./postgres/data ./postgres/dbbackups</span><br></pre></td></tr></table></figure><h3 id="环境变量配置"><a href="#环境变量配置" class="headerlink" title="环境变量配置"></a>环境变量配置</h3><p>创建<code>.env</code>文件：</p><figure class="highlight ini"><table><tr><td class="code"><pre><span class="line"><span class="comment"># Nexus配置</span></span><br><span class="line"><span class="attr">NEXUS_PORT</span>=<span class="number">8081</span></span><br><span class="line"><span class="attr">NEXUS_IMAGE</span>=sonatype/nexus3:<span class="number">3.79</span>.<span class="number">0</span></span><br><span class="line"><span class="attr">NEXUS_PASS</span>=Admin@gmail.<span class="number">123</span>.com</span><br><span class="line"><span class="attr">HEALTHCHECK_PORT</span>=<span class="number">8000</span></span><br><span class="line"><span class="attr">NEXUS_URL</span>=http://<span class="number">192.168</span>.<span class="number">1.100</span>:<span class="number">8081</span></span><br><span class="line"><span class="attr">NEXUS_USER</span>=admin</span><br><span class="line"><span class="attr">REPOSITORY_NAME</span>=maven-snapshots</span><br><span class="line"></span><br><span class="line"><span class="comment"># PostgreSQL配置</span></span><br><span class="line"><span class="attr">POSTGRES_PORT</span>=<span class="number">5432</span></span><br><span class="line"><span class="attr">POSTGRES_USER</span>=nexus</span><br><span class="line"><span class="attr">POSTGRES_PASS</span>=Nexus@gmail.<span class="number">123</span>.com</span><br><span class="line"><span class="attr">POSTGRES_DB</span>=nexus</span><br><span class="line"><span class="attr">POSTGRES_IMAGE</span>=kartoza/postgis:<span class="number">17</span>-<span class="number">3.5</span></span><br><span class="line"><span class="attr">POSTGRES_BACKUP_IMAGE</span>=kartoza/pg-backup:<span class="number">17</span>-<span class="number">3.5</span></span><br></pre></td></tr></table></figure><h2 id="Docker-Compose配置"><a href="#Docker-Compose配置" class="headerlink" title="Docker Compose配置"></a>Docker Compose配置</h2><p>创建<code>docker-compose.yaml</code>文件：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment">#version: &#x27;3&#x27;</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">nexus:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&quot;$&#123;NEXUS_IMAGE&#125;&quot;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">nexus</span></span><br><span class="line">    <span class="attr">deploy:</span></span><br><span class="line">      <span class="attr">resources:</span></span><br><span class="line">        <span class="attr">limits:</span></span><br><span class="line">          <span class="attr">memory:</span> <span class="string">8192M</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;$&#123;NEXUS_PORT&#125;:8081&quot;</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">TZ:</span> <span class="string">Asia/Shanghai</span></span><br><span class="line">      <span class="attr">INSTALL4J_ADD_VM_PARAMS:</span> <span class="string">&quot;-Xms2g -Xmx2g -XX:MaxDirectMemorySize=2g -Djava.util.prefs.userRoot=/opt/sonatype/sonatype-work -Dnexus.datastore.enabled=true -Dnexus.datastore.nexus.jdbcUrl=jdbc:postgresql://postgres:5432/nexus?gssEncMode=disable -Dnexus.datastore.nexus.username=nexus -Dnexus.datastore.nexus.password=Nexus@gmail.123.com -Dnexus.datastore.nexus.advanced=maximumPoolSize=50 -Dkaraf.data=/opt/sonatype/sonatype-work -Dkaraf.etc=/opt/sonatype/sonatype-work/etc&quot;</span></span><br><span class="line">      <span class="attr">NEXUS_SECURITY_RANDOMPASSWORD:</span> <span class="string">&quot;false&quot;</span></span><br><span class="line">      <span class="attr">NEXUS_SECRETS_KEY_FILE:</span> <span class="string">/opt/sonatype/sonatype-work/etc/nexus-secrets.json</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD&quot;</span>, <span class="string">&quot;curl&quot;</span>, <span class="string">&quot;-f&quot;</span>, <span class="string">&quot;http://localhost:8081/service/rest/v1/status&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">30s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">3</span></span><br><span class="line">      <span class="attr">start_period:</span> <span class="string">120s</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">/etc/localtime:/etc/localtime:ro</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./nexus/secret/nexus-secrets.json:/opt/sonatype/sonatype-work/etc/nexus-secrets.json:ro</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./nexus/sonatype-work:/opt/sonatype/sonatype-work</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">nexus-cleanup:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">ghcr.io/freemankevin/clean-snapshots/nexus-cleanup:sha-afbc846</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">nexus-cleanup</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">NEXUS_URL:</span> <span class="string">&quot;$&#123;NEXUS_URL&#125;&quot;</span></span><br><span class="line">      <span class="attr">NEXUS_USER:</span> <span class="string">&quot;$&#123;NEXUS_USER:-admin&#125;&quot;</span></span><br><span class="line">      <span class="attr">NEXUS_PASS:</span> <span class="string">&quot;$&#123;NEXUS_PASS&#125;&quot;</span></span><br><span class="line">      <span class="attr">REPOSITORY_NAME:</span> <span class="string">&quot;$&#123;REPOSITORY_NAME:-maven-snapshots&#125;&quot;</span></span><br><span class="line">      <span class="attr">RETAIN_COUNT:</span> <span class="string">&quot;3&quot;</span></span><br><span class="line">      <span class="attr">DRY_RUN:</span> <span class="string">&quot;false&quot;</span></span><br><span class="line">      <span class="attr">LOG_LEVEL:</span> <span class="string">&quot;INFO&quot;</span></span><br><span class="line">      <span class="attr">SCHEDULE_TIME:</span> <span class="string">&quot;03:00&quot;</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">/etc/localtime:/etc/localtime:ro</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./nexus/nexus-cleanup-logs:/var/log</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;$&#123;HEALTHCHECK_PORT&#125;:8000&quot;</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD&quot;</span>, <span class="string">&quot;curl&quot;</span>, <span class="string">&quot;-f&quot;</span>, <span class="string">&quot;http://localhost:8000/health&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">30s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">3</span></span><br><span class="line">      <span class="attr">start_period:</span> <span class="string">10s</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="attr">nexus:</span></span><br><span class="line">        <span class="attr">condition:</span> <span class="string">service_healthy</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">  <span class="attr">postgres:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&quot;$&#123;POSTGRES_IMAGE&#125;&quot;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">postgres</span></span><br><span class="line">    <span class="attr">deploy:</span></span><br><span class="line">      <span class="attr">resources:</span></span><br><span class="line">        <span class="attr">limits:</span></span><br><span class="line">          <span class="attr">memory:</span> <span class="string">8192M</span>  </span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;$&#123;POSTGRES_PORT&#125;:5432&quot;</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">TZ:</span> <span class="string">Asia/Shanghai</span></span><br><span class="line">      <span class="attr">POSTGRES_DB:</span> <span class="string">&quot;$&#123;POSTGRES_DB&#125;&quot;</span></span><br><span class="line">      <span class="attr">POSTGRES_USER:</span> <span class="string">&quot;$&#123;POSTGRES_USER&#125;&quot;</span></span><br><span class="line">      <span class="attr">POSTGRES_PASS:</span> <span class="string">&quot;$&#123;POSTGRES_PASS&#125;&quot;</span></span><br><span class="line">      <span class="attr">POSTGRES_INITDB_ARGS:</span> <span class="string">&quot;--encoding=UTF8&quot;</span></span><br><span class="line">      <span class="attr">ALLOW_IP_RANGE:</span> <span class="string">&quot;0.0.0.0/0&quot;</span></span><br><span class="line">      <span class="attr">POSTGRES_MULTIPLE_EXTENSIONS:</span> <span class="string">&quot;postgis,hstore,postgis_topology,postgis_raster,pgrouting,pg_trgm&quot;</span></span><br><span class="line">      <span class="attr">RUN_AS_ROOT:</span> <span class="string">&#x27;true&#x27;</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD-SHELL&quot;</span>, <span class="string">&quot;PGPASSWORD=$&#123;POSTGRES_PASS&#125; pg_isready -h localhost -U $&#123;POSTGRES_USER&#125;&quot;</span>]</span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">/etc/localtime:/etc/localtime:ro</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./postgres/data:/var/lib/postgresql</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./postgres/dbbackups:/backups</span></span><br><span class="line">      <span class="comment">#- ./init-postgres.sql:/docker-entrypoint-initdb.d/init.sql</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">postgres-backup:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&quot;$&#123;POSTGRES_BACKUP_IMAGE&#125;&quot;</span></span><br><span class="line">    <span class="attr">deploy:</span></span><br><span class="line">      <span class="attr">resources:</span></span><br><span class="line">        <span class="attr">limits:</span></span><br><span class="line">          <span class="attr">memory:</span> <span class="string">4096M</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">postgres-backup</span></span><br><span class="line">    <span class="attr">hostname:</span> <span class="string">postgres-backups</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">middleware</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">TZ:</span> <span class="string">Asia/Shanghai</span></span><br><span class="line">      <span class="attr">DUMPPREFIX:</span> <span class="string">PG_db</span></span><br><span class="line">      <span class="attr">POSTGRES_USER:</span> <span class="string">&quot;$&#123;POSTGRES_USER&#125;&quot;</span></span><br><span class="line">      <span class="attr">POSTGRES_PASS:</span> <span class="string">&quot;$&#123;POSTGRES_PASS&#125;&quot;</span></span><br><span class="line">      <span class="attr">POSTGRES_PORT:</span> <span class="string">&quot;5432&quot;</span></span><br><span class="line">      <span class="attr">POSTGRES_HOST:</span> <span class="string">&quot;postgres&quot;</span></span><br><span class="line">      <span class="attr">CRON_SCHEDULE:</span> <span class="string">&quot;0 2 * * *&quot;</span></span><br><span class="line">      <span class="attr">REMOVE_BEFORE:</span> <span class="string">&quot;15&quot;</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">/etc/localtime:/etc/localtime:ro</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./postgres/dbbackups:/backups</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="attr">postgres:</span></span><br><span class="line">        <span class="attr">condition:</span> <span class="string">service_healthy</span></span><br><span class="line"></span><br><span class="line"><span class="attr">networks:</span></span><br><span class="line">  <span class="attr">middleware:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br></pre></td></tr></table></figure><h2 id="服务部署"><a href="#服务部署" class="headerlink" title="服务部署"></a>服务部署</h2><h3 id="加载Docker镜像（离线环境）"><a href="#加载Docker镜像（离线环境）" class="headerlink" title="加载Docker镜像（离线环境）"></a>加载Docker镜像（离线环境）</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker load -i images/nexus_3.79.0_amd64.tar.gz</span><br><span class="line">docker load -i images/nexus-cleanup.tar.gz</span><br><span class="line">docker load -i images/pg-v17-3.5.tar.gz</span><br><span class="line">docker load -i images/pg-backup-v17-3.5.tar.gz</span><br></pre></td></tr></table></figure><h3 id="启动服务"><a href="#启动服务" class="headerlink" title="启动服务"></a>启动服务</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker-compose up -d</span><br></pre></td></tr></table></figure><p>验证服务状态：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker-compose ps</span><br></pre></td></tr></table></figure><h2 id="密码重置"><a href="#密码重置" class="headerlink" title="密码重置"></a>密码重置</h2><p>如果需要重置管理员密码：</p><ol><li>进入PostgreSQL容器：</li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker <span class="built_in">exec</span> -it postgres bash</span><br></pre></td></tr></table></figure><ol start="2"><li>执行SQL：</li></ol><figure class="highlight sql"><table><tr><td class="code"><pre><span class="line"><span class="comment">--- 将默认admin 密码改为 admin123</span></span><br><span class="line"><span class="keyword">UPDATE</span> security_user </span><br><span class="line"><span class="keyword">SET</span> password<span class="operator">=</span><span class="string">&#x27;$shiro1$SHA-512$1024$NE+wqQq/TmjZMvfI7ENh/g==$V4yPw8T64UQ6GfJfxYq2hLsVrBY8D1v+bktfOxGdt4b/9BthpWPNUy/CBk6V9iA0nHpzYzJFWO8v/tZFtES8CA==&#x27;</span>, </span><br><span class="line">status<span class="operator">=</span><span class="string">&#x27;active&#x27;</span> </span><br><span class="line"><span class="keyword">WHERE</span> id<span class="operator">=</span><span class="string">&#x27;admin&#x27;</span>;</span><br></pre></td></tr></table></figure><ol start="3"><li>重启服务：</li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker-compose restart nexus</span><br></pre></td></tr></table></figure><h2 id="监控与验证"><a href="#监控与验证" class="headerlink" title="监控与验证"></a>监控与验证</h2><h3 id="服务健康检查"><a href="#服务健康检查" class="headerlink" title="服务健康检查"></a>服务健康检查</h3><ul><li>Nexus: <code>curl http://localhost:18080/service/rest/v1/status</code></li><li>Cleanup: <code>curl http://localhost:8000/health</code></li><li>PostgreSQL: <code>docker exec postgres pg_isready -U nexus</code></li></ul><h3 id="日志检查"><a href="#日志检查" class="headerlink" title="日志检查"></a>日志检查</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker logs nexus</span><br><span class="line"><span class="built_in">tail</span> -f ./nexus/nexus-cleanup-logs/cleanup.log</span><br></pre></td></tr></table></figure><h2 id="性能优化建议"><a href="#性能优化建议" class="headerlink" title="性能优化建议"></a>性能优化建议</h2><ol><li><p><strong>JVM调优</strong>：</p><figure class="highlight ini"><table><tr><td class="code"><pre><span class="line">-Xms4g -Xmx4g -XX:<span class="attr">MaxDirectMemorySize</span>=<span class="number">4</span>g</span><br></pre></td></tr></table></figure></li><li><p><strong>PostgreSQL配置</strong>：</p><figure class="highlight ini"><table><tr><td class="code"><pre><span class="line"><span class="attr">max_connections</span> = <span class="number">200</span></span><br><span class="line"><span class="attr">work_mem</span> = <span class="number">16</span>MB</span><br></pre></td></tr></table></figure></li><li><p><strong>清理策略</strong>：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">RETAIN_COUNT:</span> <span class="string">&quot;5&quot;</span></span><br><span class="line"><span class="attr">SCHEDULE_TIME:</span> <span class="string">&quot;02:00&quot;</span></span><br></pre></td></tr></table></figure></li></ol><h2 id="常见问题排查"><a href="#常见问题排查" class="headerlink" title="常见问题排查"></a>常见问题排查</h2><table><thead><tr><th>问题</th><th>解决方案</th></tr></thead><tbody><tr><td>Nexus启动失败</td><td>检查JVM内存设置</td></tr><tr><td>PostgreSQL连接错误</td><td>验证.env文件凭据</td></tr><tr><td>清理服务不工作</td><td>检查NEXUS_URL配置</td></tr></tbody></table><h2 id="结论"><a href="#结论" class="headerlink" title="结论"></a>结论</h2><p>本文详细介绍了Nexus在Docker环境中的完整部署方案，包含数据库集成、自动清理和备份功能。该方案适合生产环境使用，可根据实际需求进行调整优化。</p><p><strong>相关资源</strong>：</p><ul><li><span class="exturl" data-url="aHR0cHM6Ly9oZWxwLnNvbmF0eXBlLmNvbS9yZXBvbWFuYWdlcjM=">Nexus官方文档<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly93d3cucG9zdGdyZXNxbC5vcmcvZG9jcy9jdXJyZW50L3J1bnRpbWUtY29uZmlnLmh0bWw=">PostgreSQL最佳实践<i class="fa fa-external-link-alt"></i></span></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt; Nexus是一个功能强大的仓库管理工具，用于托管Maven工件、Docker镜像等。本文将详细介绍如何在Docker环境中部署Nexus仓库管理器，并集成PostgreSQL数据库、快照清理服务和数据库备份服务。&lt;/p&gt;</summary>
    
    
    
    <category term="Development" scheme="https://freemankevin.uk/categories/Development/"/>
    
    
    <category term="Docker" scheme="https://freemankevin.uk/tags/Docker/"/>
    
    <category term="PostgreSQL" scheme="https://freemankevin.uk/tags/PostgreSQL/"/>
    
    <category term="Nexus" scheme="https://freemankevin.uk/tags/Nexus/"/>
    
    <category term="Maven" scheme="https://freemankevin.uk/tags/Maven/"/>
    
  </entry>
  
  <entry>
    <title>Vim 常用配置说明文档</title>
    <link href="https://freemankevin.uk/2025/03/05/vim/"/>
    <id>https://freemankevin.uk/2025/03/05/vim/</id>
    <published>2025-03-05T06:30:00.000Z</published>
    <updated>2026-04-17T10:30:31.809Z</updated>
    
    <content type="html"><![CDATA[<p> 当前文档为 Vim 编辑器的常用配置说明，适用于 Linux 和 Mac 环境。配置项旨在提升代码编辑体验，包括语法高亮、文件类型检测、粘贴优化等功能。配置文件通常位于 <code>~/.vimrc</code>（Linux&#x2F;Mac），如果文件不存在，可通过 <code>vim ~/.vimrc</code> 创建。</p><span id="more"></span><h2 id="配置内容"><a href="#配置内容" class="headerlink" title="配置内容"></a>配置内容</h2><p>以下是推荐的 Vim 配置项及其说明：</p><figure class="highlight vim"><table><tr><td class="code"><pre><span class="line"><span class="comment">&quot; 启用语法高亮</span></span><br><span class="line"><span class="keyword">syntax</span> <span class="keyword">on</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 启用文件类型检测</span></span><br><span class="line"><span class="keyword">filetype</span> <span class="keyword">on</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 启用文件类型插件和自动缩进（基于文件类型）</span></span><br><span class="line"><span class="keyword">filetype</span> plugin <span class="built_in">indent</span> <span class="keyword">on</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 设置默认颜色方案</span></span><br><span class="line"><span class="keyword">colorscheme</span> default</span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 禁用自动缩进</span></span><br><span class="line"><span class="keyword">set</span> noautoindent</span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 禁用智能缩进</span></span><br><span class="line"><span class="keyword">set</span> nosmartindent</span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 禁用在插入注释时自动添加注释字符</span></span><br><span class="line"><span class="keyword">set</span> formatoptions-=r</span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 禁用在按 &#x27;o&#x27; 或 &#x27;O&#x27; 时自动添加注释</span></span><br><span class="line"><span class="keyword">set</span> formatoptions-=<span class="keyword">o</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 禁用自动换行，保持原始行长</span></span><br><span class="line"><span class="keyword">set</span> textwidth=<span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 启用粘贴模式，防止自动格式化（建议临时使用）</span></span><br><span class="line"><span class="keyword">set</span> paste</span><br></pre></td></tr></table></figure><h3 id="配置项详细说明"><a href="#配置项详细说明" class="headerlink" title="配置项详细说明"></a>配置项详细说明</h3><ol><li><p><strong><code>syntax on</code></strong></p><ul><li><strong>功能</strong>: 启用语法高亮，根据文件类型显示不同颜色。</li><li><strong>适用场景</strong>: 提高代码可读性，适用于编程语言（如 Python、YAML）。</li><li><strong>注意</strong>: 需终端支持颜色输出（Linux&#x2F;Mac 通常支持）。</li></ul></li><li><p><strong><code>filetype on</code></strong></p><ul><li><strong>功能</strong>: 启用文件类型检测，基于文件扩展名或内容自动识别类型。</li><li><strong>适用场景</strong>: 确保 Vim 正确加载特定文件类型的设置。</li><li><strong>注意</strong>: 与 <code>filetype plugin indent on</code> 配合使用。</li></ul></li><li><p><strong><code>filetype plugin indent on</code></strong></p><ul><li><strong>功能</strong>: 启用文件类型插件和基于类型的自动缩进。</li><li><strong>适用场景</strong>: 为不同语言提供定制化缩进规则（如 Python 使用 4 空格）。</li><li><strong>注意</strong>: 如果禁用缩进（见下文），可能需调整此项。</li></ul></li><li><p><strong><code>colorscheme default</code></strong></p><ul><li><strong>功能</strong>: 设置默认颜色方案，控制语法高亮的颜色。</li><li><strong>适用场景</strong>: 提供基础视觉效果，可替换为其他方案（如 <code>colorscheme desert</code>）。</li><li><strong>注意</strong>: 需安装对应颜色方案文件（通常默认已包含）。</li></ul></li><li><p><strong><code>set noautoindent</code></strong></p><ul><li><strong>功能</strong>: 禁用自动缩进，防止新行继承上一行的缩进。</li><li><strong>适用场景</strong>: 粘贴代码时保持原格式，避免意外缩进。</li></ul></li><li><p><strong><code>set nosmartindent</code></strong></p><ul><li><strong>功能</strong>: 禁用智能缩进，防止根据语法自动调整缩进。</li><li><strong>适用场景</strong>: 与 <code>noautoindent</code> 配合，适合粘贴大段文本。</li></ul></li><li><p><strong><code>set formatoptions-=r</code></strong></p><ul><li><strong>功能</strong>: 禁用在插入模式下输入注释时自动添加注释字符。</li><li><strong>适用场景</strong>: 防止在多行注释中意外添加多余 <code>*</code> 或 <code>#</code>。</li></ul></li><li><p><strong><code>set formatoptions-=o</code></strong></p><ul><li><strong>功能</strong>: 禁用在按 <code>o</code> 或 <code>O</code>（新行）时自动添加注释。</li><li><strong>适用场景</strong>: 保持手动控制注释格式。</li></ul></li><li><p><strong><code>set textwidth=0</code></strong></p><ul><li><strong>功能</strong>: 禁用自动换行，保持原始行长。</li><li><strong>适用场景</strong>: 粘贴长行代码或文档时避免截断。</li></ul></li><li><p><strong><code>set paste</code></strong></p><ul><li><strong>功能</strong>: 启用粘贴模式，禁用自动格式化和缩进。</li><li><strong>适用场景</strong>: 粘贴外部代码时保持原样。</li><li><strong>注意</strong>: 建议临时启用（<code>:set paste</code>），粘贴后关闭（<code>:set nopaste</code>），否则可能影响正常编辑。</li></ul></li></ol><h2 id="冲突分析"><a href="#冲突分析" class="headerlink" title="冲突分析"></a>冲突分析</h2><p>以下是配置项中可能发生的冲突及解决方法：</p><ol><li><p><strong><code>noautoindent</code>、<code>nosmartindent</code> 与 <code>filetype plugin indent on</code> 的冲突</strong></p><ul><li><strong>问题</strong>: <code>filetype plugin indent on</code> 启用基于文件类型的自动缩进，而 <code>noautoindent</code> 和 <code>nosmartindent</code> 试图禁用所有自动缩进，导致行为不一致。</li><li><strong>影响</strong>: 可能导致缩进规则失效或混乱，尤其在打开新文件时。</li><li><strong>解决</strong>: 如果目标是禁用缩进（例如为粘贴优化），建议移除 <code>filetype plugin indent on</code> 或仅保留 <code>filetype on</code> 和 <code>syntax on</code>。</li></ul></li><li><p><strong><code>set paste</code> 的全局影响</strong></p><ul><li><strong>问题</strong>: <code>set paste</code> 是一个全局设置，会禁用缩进、自动补全等插件功能，长期启用可能干扰正常编辑。</li><li><strong>影响</strong>: 影响 <code>filetype plugin indent on</code> 的效果，甚至可能与自定义键盘映射冲突。</li><li><strong>解决</strong>: 改为临时使用，添加快捷键切换：<figure class="highlight vim"><table><tr><td class="code"><pre><span class="line"><span class="keyword">nnoremap</span> <span class="symbol">&lt;F2&gt;</span> :<span class="keyword">set</span> paste!<span class="symbol">&lt;CR&gt;</span></span><br></pre></td></tr></table></figure>粘贴时按 <code>F2</code> 启用，粘贴后再次按 <code>F2</code> 关闭。</li></ul></li><li><p><strong><code>cindent</code>（未包含但可能相关）的潜在冲突</strong></p><ul><li><strong>问题</strong>: 如果添加 <code>set cindent</code>（启用 C 风格缩进），会与 <code>noautoindent</code> 和 <code>nosmartindent</code> 冲突，因为 <code>cindent</code> 尝试应用缩进规则。</li><li><strong>影响</strong>: 缩进行为不可预测，可能导致代码格式混乱。</li><li><strong>解决</strong>: 避免同时使用 <code>cindent</code> 和 <code>noautoindent</code>&#x2F;<code>nosmartindent</code>。如果需要 C 风格缩进，移除前两者。</li></ul></li></ol><h2 id="优化配置建议"><a href="#优化配置建议" class="headerlink" title="优化配置建议"></a>优化配置建议</h2><p>根据上述分析，优化后的 <code>~/.vimrc</code> 配置如下，兼顾语法高亮和粘贴优化：</p><figure class="highlight vim"><table><tr><td class="code"><pre><span class="line"><span class="comment">&quot; 启用语法高亮和文件类型检测</span></span><br><span class="line"><span class="keyword">syntax</span> <span class="keyword">on</span></span><br><span class="line"><span class="keyword">filetype</span> <span class="keyword">on</span></span><br><span class="line"><span class="comment">&quot; 禁用基于文件类型的自动缩进插件（避免与粘贴冲突）</span></span><br><span class="line"><span class="comment">&quot; filetype plugin indent on</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 设置默认颜色方案</span></span><br><span class="line"><span class="keyword">colorscheme</span> default</span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 禁用自动缩进和智能缩进（适合粘贴）</span></span><br><span class="line"><span class="keyword">set</span> noautoindent</span><br><span class="line"><span class="keyword">set</span> nosmartindent</span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 禁用自动注释格式</span></span><br><span class="line"><span class="keyword">set</span> formatoptions-=r</span><br><span class="line"><span class="keyword">set</span> formatoptions-=<span class="keyword">o</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 禁用自动换行</span></span><br><span class="line"><span class="keyword">set</span> textwidth=<span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&quot; 粘贴模式建议临时启用，添加快捷键切换</span></span><br><span class="line"><span class="comment">&quot; set paste</span></span><br><span class="line"><span class="keyword">nnoremap</span> <span class="symbol">&lt;F2&gt;</span> :<span class="keyword">set</span> paste!<span class="symbol">&lt;CR&gt;</span></span><br></pre></td></tr></table></figure><h3 id="使用说明"><a href="#使用说明" class="headerlink" title="使用说明"></a>使用说明</h3><ul><li><strong>保存配置</strong>: 将上述内容写入 <code>~/.vimrc</code>，运行 <code>source ~/.vimrc</code> 应用。</li><li><strong>测试</strong>: 打开文件（<code>vim test.yaml</code>），按 <code>F2</code> 进入粘贴模式，粘贴内容，检查格式。</li><li><strong>自定义</strong>: 根据需求调整颜色方案或添加其他插件。</li></ul><h2 id="兼容性注意"><a href="#兼容性注意" class="headerlink" title="兼容性注意"></a>兼容性注意</h2><ul><li><strong>Linux&#x2F;Mac</strong>: 配置适用于大多数终端（需支持 ANSI 颜色）。若无颜色，检查 <code>TERM</code> 变量（<code>echo $TERM</code> 应为 <code>xterm</code> 或 <code>xterm-256color</code>）。</li><li><strong>插件</strong>: 若使用插件（如 NERDTree），可能需额外配置，避免与 <code>paste</code> 冲突。</li><li><strong>更新</strong>: 定期更新 Vim（<code>sudo apt update &amp;&amp; sudo apt install vim</code> 或 <code>brew install vim</code>）以获取最新功能。</li></ul><hr><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>此配置优化了语法高亮和粘贴体验，消除了 <code>noautoindent</code>&#x2F;<code>nosmartindent</code> 与 <code>filetype plugin indent on</code> 的冲突，并建议临时管理 <code>paste</code> 模式。安装后测试效果，若有特定需求（如支持特定语言），可进一步扩展配置。如需更多帮助，请提供使用反馈！</p>]]></content>
    
    
    <summary type="html">&lt;p&gt; 当前文档为 Vim 编辑器的常用配置说明，适用于 Linux 和 Mac 环境。配置项旨在提升代码编辑体验，包括语法高亮、文件类型检测、粘贴优化等功能。配置文件通常位于 &lt;code&gt;~/.vimrc&lt;/code&gt;（Linux&amp;#x2F;Mac），如果文件不存在，可通过 &lt;code&gt;vim ~/.vimrc&lt;/code&gt; 创建。&lt;/p&gt;</summary>
    
    
    
    <category term="Linux" scheme="https://freemankevin.uk/categories/Linux/"/>
    
    
    <category term="Linux" scheme="https://freemankevin.uk/tags/Linux/"/>
    
    <category term="VIM" scheme="https://freemankevin.uk/tags/VIM/"/>
    
  </entry>
  
  <entry>
    <title>二进制方式部署Kubernetes 集群</title>
    <link href="https://freemankevin.uk/2025/02/08/k8s-binary/"/>
    <id>https://freemankevin.uk/2025/02/08/k8s-binary/</id>
    <published>2025-02-08T08:23:25.000Z</published>
    <updated>2026-04-17T10:30:31.805Z</updated>
    
    <content type="html"><![CDATA[<p> 本文详细介绍如何使用二进制方式在 Debian 系统上搭建一个生产级别的高可用 Kubernetes 集群。</p><span id="more"></span><hr><h1 id="部署规划"><a href="#部署规划" class="headerlink" title="部署规划"></a>部署规划</h1><h2 id="服务器清单"><a href="#服务器清单" class="headerlink" title="服务器清单"></a>服务器清单</h2><table><thead><tr><th>角色</th><th>主机名</th><th>IP地址</th><th>配置</th><th>系统</th></tr></thead><tbody><tr><td>LB-1</td><td>lb1.k8s.com</td><td>192.168.171.134</td><td>2C4G</td><td>Debian 12</td></tr><tr><td>LB-2</td><td>lb2.k8s.com</td><td>192.168.171.135</td><td>2C4G</td><td>Debian 12</td></tr><tr><td>VIP</td><td>-</td><td>192.168.171.133</td><td>-</td><td>-</td></tr><tr><td>ETCD-1</td><td>etcd1.k8s.com</td><td>192.168.171.136</td><td>4C8G</td><td>Debian 12</td></tr><tr><td>ETCD-2</td><td>etcd2.k8s.com</td><td>192.168.171.137</td><td>4C8G</td><td>Debian 12</td></tr><tr><td>ETCD-3</td><td>etcd3.k8s.com</td><td>192.168.171.138</td><td>4C8G</td><td>Debian 12</td></tr><tr><td>Master-1</td><td>master1.k8s.com</td><td>192.168.171.136</td><td>4C8G</td><td>Debian 12</td></tr><tr><td>Master-2</td><td>master2.k8s.com</td><td>192.168.171.137</td><td>4C8G</td><td>Debian 12</td></tr><tr><td>Master-3</td><td>master3.k8s.com</td><td>192.168.171.138</td><td>4C8G</td><td>Debian 12</td></tr><tr><td>Worker-1</td><td>worker1.k8s.com</td><td>192.168.171.139</td><td>8C16G</td><td>Debian 12</td></tr><tr><td>Harbor</td><td>harbor.k8s.com</td><td>192.168.171.50</td><td>4C8G</td><td>Debian 12</td></tr><tr><td>NFS</td><td>nfs.k8s.com</td><td>192.168.171.140</td><td>4C8G</td><td>Debian 12</td></tr></tbody></table><h2 id="网络规划"><a href="#网络规划" class="headerlink" title="网络规划"></a>网络规划</h2><ul><li>节点网段: 192.168.171.0&#x2F;24</li><li>Pod 网段: 10.244.0.0&#x2F;16</li><li>Service 网段: 10.96.0.0&#x2F;12</li><li>DNS 服务: CoreDNS</li></ul><h2 id="组件版本"><a href="#组件版本" class="headerlink" title="组件版本"></a>组件版本</h2><ul><li>Kubernetes: v1.27.8</li><li>Etcd: v3.5.9</li><li>Docker: 24.0.7</li><li>Containerd: 1.7.6</li><li>Calico: v3.26.1</li><li>CoreDNS: v1.10.1</li><li>Harbor: v2.9.1</li></ul><hr><h1 id="系统初始化"><a href="#系统初始化" class="headerlink" title="系统初始化"></a>系统初始化</h1><h2 id="添加软件源"><a href="#添加软件源" class="headerlink" title="添加软件源"></a>添加软件源</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">备份原始源文件</span></span><br><span class="line">cp /etc/apt/sources.list /etc/apt/sources.list.bak</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">清理并配置新的软件源</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">删除注释行和空行</span></span><br><span class="line">sed -i &#x27;/^#/d; /^$/d&#x27; /etc/apt/sources.list</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">注释掉原始行</span></span><br><span class="line">sed -i &#x27;s/^deb cdrom:\[Debian GNU\/Linux.*$/#&amp;/&#x27; /etc/apt/sources.list</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">删除旧的安全源</span></span><br><span class="line">sed -i &#x27;/^deb http:\/\/security.debian.org\/debian-security/d&#x27; /etc/apt/sources.list</span><br><span class="line">sed -i &#x27;/^deb-src http:\/\/security.debian.org\/debian-security/d&#x27; /etc/apt/sources.list</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加清华源</span></span><br><span class="line">cat &gt; /etc/apt/sources.list &lt;&lt; EOF</span><br><span class="line">deb http://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free</span><br><span class="line">deb http://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free</span><br><span class="line">deb http://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free</span><br><span class="line">deb http://mirrors.tuna.tsinghua.edu.cn/debian-security bullseye-security main contrib non-free</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">源码镜像（可选）</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">deb-src http://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">deb-src http://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">deb-src http://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">deb-src http://mirrors.tuna.tsinghua.edu.cn/debian-security bullseye-security main contrib non-free</span></span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h2 id="系统更新"><a href="#系统更新" class="headerlink" title="系统更新"></a>系统更新</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">更新软件包索引</span></span><br><span class="line">apt update </span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">升级所有已安装的软件包</span></span><br><span class="line">apt upgrade -y </span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装重要的系统更新（如果有的话）</span></span><br><span class="line">apt dist-upgrade -y</span><br></pre></td></tr></table></figure><h2 id="基础工具安装"><a href="#基础工具安装" class="headerlink" title="基础工具安装"></a>基础工具安装</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装基础工具包</span></span><br><span class="line">apt update</span><br><span class="line">apt install -y \</span><br><span class="line">    # 系统工具</span><br><span class="line">    apt-transport-https \</span><br><span class="line">    ca-certificates \</span><br><span class="line">    vim \</span><br><span class="line">    net-tools \</span><br><span class="line">    sudo \</span><br><span class="line">    telnet \</span><br><span class="line">    ufw \</span><br><span class="line">    iotop \</span><br><span class="line">    rsync \</span><br><span class="line">    unzip \</span><br><span class="line">    iputils-ping \</span><br><span class="line">    gawk \</span><br><span class="line">    sed \</span><br><span class="line">    cron \</span><br><span class="line">    gnupg \</span><br><span class="line">    locales \</span><br><span class="line">    curl \</span><br><span class="line">    wget \</span><br><span class="line">    tree \</span><br><span class="line">    htop \</span><br><span class="line">    nmon \</span><br><span class="line">    lsof \</span><br><span class="line">    # 网络工具</span><br><span class="line">    nfs-common \</span><br><span class="line">    sshpass \</span><br><span class="line">    software-properties-common \</span><br><span class="line">    # 系统监控</span><br><span class="line">    sysstat \</span><br><span class="line">    # 文本处理</span><br><span class="line">    jq \</span><br><span class="line">    # 版本控制</span><br><span class="line">    git</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">清理不需要的包</span></span><br><span class="line">apt autoremove -y</span><br></pre></td></tr></table></figure><h2 id="系统语言配置"><a href="#系统语言配置" class="headerlink" title="系统语言配置"></a>系统语言配置</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成英文语言环境</span></span><br><span class="line">locale-gen en_US.UTF-8</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置系统默认语言</span></span><br><span class="line">cat &gt; /etc/default/locale &lt;&lt; EOF</span><br><span class="line">LC_ALL=en_US.utf8</span><br><span class="line">LANG=en_US.utf8</span><br><span class="line">LANGUAGE=en_US.utf8</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置语言生成</span></span><br><span class="line">sed -i &#x27;s/^zh_CN.UTF-8 UTF-8/#zh_CN.UTF-8 UTF-8/&#x27; /etc/locale.gen</span><br><span class="line">sed -i &#x27;s/#en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/&#x27; /etc/locale.gen</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重新生成语言文件</span></span><br><span class="line">locale-gen</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置环境变量</span></span><br><span class="line">echo &quot;export LANG=en_US.utf8&quot; &gt;&gt; /etc/profile</span><br><span class="line">echo &quot;export LANGUAGE=en_US.utf8&quot; &gt;&gt; /etc/profile</span><br><span class="line">source /etc/profile</span><br></pre></td></tr></table></figure><h2 id="SSH远程访问配置"><a href="#SSH远程访问配置" class="headerlink" title="SSH远程访问配置"></a>SSH远程访问配置</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置SSH允许root登录</span></span><br><span class="line">sed -ri &#x27;s/#PermitRootLogin prohibit-password/PermitRootLogin yes/&#x27; /etc/ssh/sshd_config</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">加强SSH安全配置</span></span><br><span class="line">cat &gt;&gt; /etc/ssh/sshd_config &lt;&lt; EOF</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">SSH认证配置</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">同时启用密码和密钥认证，便于初始化后的管理</span></span><br><span class="line">PasswordAuthentication yes</span><br><span class="line">PubkeyAuthentication yes</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置SSH协议版本</span></span><br><span class="line">Protocol 2</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">限制最大认证尝试次数</span></span><br><span class="line">MaxAuthTries 3</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">禁用空密码</span></span><br><span class="line">PermitEmptyPasswords no</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置登录超时时间（秒）</span></span><br><span class="line">LoginGraceTime 60</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启用严格模式</span></span><br><span class="line">StrictModes yes</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安全加固建议（等系统完全配置好后可以考虑启用）：</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">1. 禁用密码认证，只使用密钥认证</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">PasswordAuthentication no</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">2. 限制允许登录的用户</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">AllowUsers your-user-name</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">3. 更改默认端口</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Port 2222</span></span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重启SSH服务</span></span><br><span class="line">systemctl restart ssh</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证配置</span></span><br><span class="line">egrep &#x27;^PermitRootLogin&#x27; /etc/ssh/sshd_config</span><br></pre></td></tr></table></figure><h2 id="Shell环境优化"><a href="#Shell环境优化" class="headerlink" title="Shell环境优化"></a>Shell环境优化</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置.bashrc</span></span><br><span class="line">cat &gt;&gt; ~/.bashrc &lt;&lt; EOF</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置命令别名</span></span><br><span class="line">alias ll=&#x27;ls -l&#x27;</span><br><span class="line">alias la=&#x27;ls -A&#x27;</span><br><span class="line">alias l=&#x27;ls -CF&#x27;</span><br><span class="line">alias vi=&#x27;vim&#x27;</span><br><span class="line">alias cls=&#x27;clear&#x27;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置命令历史记录</span></span><br><span class="line">HISTSIZE=5000</span><br><span class="line">HISTFILESIZE=10000</span><br><span class="line">HISTTIMEFORMAT=&quot;%F %T &quot;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置PS1提示符</span></span><br><span class="line">PS1=&#x27;\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ &#x27;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启用颜色支持</span></span><br><span class="line">export LS_OPTIONS=&#x27;--color=auto&#x27;</span><br><span class="line">eval &quot;$(dircolors)&quot;</span><br><span class="line">alias ls=&#x27;ls $LS_OPTIONS&#x27;</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">应用新配置</span></span><br><span class="line">source ~/.bashrc</span><br></pre></td></tr></table></figure><h2 id="网络配置（可选）"><a href="#网络配置（可选）" class="headerlink" title="网络配置（可选）"></a>网络配置（可选）</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置静态IP</span></span><br><span class="line">cat &gt; /etc/network/interfaces &lt;&lt; EOF</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">This file describes the network interfaces available on your system</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">and how to activate them. For more information, see interfaces(5).</span></span><br><span class="line"></span><br><span class="line">source /etc/network/interfaces.d/*</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">The loopback network interface</span></span><br><span class="line">auto lo</span><br><span class="line">iface lo inet loopback</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">The primary network interface</span></span><br><span class="line">auto ens32</span><br><span class="line">iface ens32 inet static</span><br><span class="line">    address 192.168.171.136</span><br><span class="line">    netmask 255.255.255.0</span><br><span class="line">    gateway 192.168.171.2</span><br><span class="line">    # DNS配置</span><br><span class="line">    dns-nameservers 8.8.8.8 8.8.4.4</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h2 id="系统优化"><a href="#系统优化" class="headerlink" title="系统优化"></a>系统优化</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">关闭swap</span></span><br><span class="line">swapoff -a</span><br><span class="line">sed -i &#x27;/swap/d&#x27; /etc/fstab</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置系统限制</span></span><br><span class="line">cat &gt; /etc/security/limits.conf &lt;&lt; EOF</span><br><span class="line">* soft nofile 65535</span><br><span class="line">* hard nofile 65535</span><br><span class="line">* soft nproc 65535</span><br><span class="line">* hard nproc 65535</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">优化内核参数</span></span><br><span class="line">cat &gt; /etc/sysctl.d/99-sysctl.conf &lt;&lt; EOF</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">系统级别的最大文件句柄数</span></span><br><span class="line">fs.file-max = 2097152</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">TCP连接参数优化</span></span><br><span class="line">net.ipv4.tcp_max_syn_backlog = 8192</span><br><span class="line">net.core.somaxconn = 32768</span><br><span class="line">net.ipv4.tcp_timestamps = 1</span><br><span class="line">net.ipv4.tcp_fin_timeout = 30</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">内存参数优化</span></span><br><span class="line">vm.swappiness = 0</span><br><span class="line">vm.overcommit_memory = 1</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">应用内核参数</span></span><br><span class="line">sysctl -p</span><br></pre></td></tr></table></figure><h2 id="系统服务优化"><a href="#系统服务优化" class="headerlink" title="系统服务优化"></a>系统服务优化</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">禁用不需要的服务</span></span><br><span class="line">systemctl stop rpcbind</span><br><span class="line">systemctl disable rpcbind</span><br><span class="line">apt autoremove rpcbind -y</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置防火墙（UFW）</span></span><br><span class="line">ufw default deny incoming</span><br><span class="line">ufw default allow outgoing</span><br><span class="line">ufw allow ssh</span><br><span class="line">ufw allow 80/tcp</span><br><span class="line">ufw allow 443/tcp</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">根据需要添加其他端口</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启用防火墙</span></span><br><span class="line">ufw --force enable</span><br></pre></td></tr></table></figure><h2 id="完成初始化"><a href="#完成初始化" class="headerlink" title="完成初始化"></a>完成初始化</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">同步文件系统</span></span><br><span class="line">sync</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重启系统使所有更改生效</span></span><br><span class="line">reboot</span><br></pre></td></tr></table></figure><h2 id="自动化部署"><a href="#自动化部署" class="headerlink" title="自动化部署"></a>自动化部署</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建一个初始化脚本</span></span><br><span class="line">cat &gt; init-debian.sh &lt;&lt; &#x27;EOF&#x27;</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Debian系统初始化脚本</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">使用方法: ./init-debian.sh</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查是否为root用户</span></span><br><span class="line">if [ &quot;$(id -u)&quot; != &quot;0&quot; ]; then</span><br><span class="line">   echo &quot;此脚本必须以root权限运行&quot; </span><br><span class="line">   exit 1</span><br><span class="line">fi</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">这里放入上述所有配置步骤</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">...</span></span><br><span class="line"></span><br><span class="line">echo &quot;系统初始化完成，请重启服务器&quot;</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加执行权限</span></span><br><span class="line">chmod +x init-debian.sh</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">运行脚本</span></span><br><span class="line">./init-debian.sh</span><br></pre></td></tr></table></figure><h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><ol><li>在执行初始化操作前，建议先备份重要数据</li><li>修改网络配置时需要特别小心，错误的配置可能导致无法远程访问</li><li>防火墙规则要根据实际需求配置</li><li>建议保存一份配置文件的备份</li><li>初始化完成后要及时修改root密码和SSH配置</li></ol><h2 id="故障排除"><a href="#故障排除" class="headerlink" title="故障排除"></a>故障排除</h2><p>如果在初始化过程中遇到问题，可以检查以下几点：</p><ol><li>查看系统日志：<code>journalctl -xe</code></li><li>检查服务状态：<code>systemctl status &lt;服务名&gt;</code></li><li>检查网络连接：<code>ping -c 4 8.8.8.8</code></li><li>验证软件源可用性：<code>apt update</code></li></ol><hr><h1 id="高可用负载均衡部署"><a href="#高可用负载均衡部署" class="headerlink" title="高可用负载均衡部署"></a>高可用负载均衡部署</h1><h2 id="环境准备"><a href="#环境准备" class="headerlink" title="环境准备"></a>环境准备</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">更新系统并安装基础工具</span></span><br><span class="line">apt-get update</span><br><span class="line">apt-get install -y \</span><br><span class="line">    psmisc \</span><br><span class="line">    curl \</span><br><span class="line">    wget \</span><br><span class="line">    net-tools \</span><br><span class="line">    ipvsadm \</span><br><span class="line">    ipset</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查网络配置</span></span><br><span class="line">ip a</span><br></pre></td></tr></table></figure><h2 id="Keepalived-部署"><a href="#Keepalived-部署" class="headerlink" title="Keepalived 部署"></a>Keepalived 部署</h2><h3 id="安装-Keepalived"><a href="#安装-Keepalived" class="headerlink" title="安装 Keepalived"></a>安装 Keepalived</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在所有负载均衡节点上安装</span></span><br><span class="line">apt install -y keepalived</span><br></pre></td></tr></table></figure><h3 id="配置健康检查脚本"><a href="#配置健康检查脚本" class="headerlink" title="配置健康检查脚本"></a>配置健康检查脚本</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建健康检查脚本</span></span><br><span class="line">cat &gt; /etc/keepalived/check_apiserver.sh &lt;&lt; EOF</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line"></span><br><span class="line">API_URL=&quot;https://192.168.171.133:6443/healthz&quot;</span><br><span class="line">TIMEOUT=3</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查API服务器健康状态</span></span><br><span class="line">if curl -k -s --connect-timeout $&#123;TIMEOUT&#125; $&#123;API_URL&#125; | grep -q &quot;ok&quot;; then</span><br><span class="line">    exit 0</span><br><span class="line">else</span><br><span class="line">    exit 1</span><br><span class="line">fi</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加执行权限</span></span><br><span class="line">chmod +x /etc/keepalived/check_apiserver.sh</span><br></pre></td></tr></table></figure><h3 id="主节点配置"><a href="#主节点配置" class="headerlink" title="主节点配置"></a>主节点配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置主节点的keepalived</span></span><br><span class="line">cat &gt; /etc/keepalived/keepalived.conf &lt;&lt; EOF</span><br><span class="line">! Configuration File for keepalived</span><br><span class="line">global_defs &#123;</span><br><span class="line">    router_id LVS_DEVEL</span><br><span class="line">    script_user root</span><br><span class="line">    enable_script_security</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">HAProxy进程检查</span></span><br><span class="line">vrrp_script check_haproxy &#123;</span><br><span class="line">    script &quot;/usr/bin/killall -0 haproxy&quot;</span><br><span class="line">    interval 2</span><br><span class="line">    weight 2</span><br><span class="line">    fall 2</span><br><span class="line">    rise 1</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">API服务器健康检查</span></span><br><span class="line">vrrp_script check_apiserver &#123;</span><br><span class="line">    script &quot;/etc/keepalived/check_apiserver.sh&quot;</span><br><span class="line">    interval 3</span><br><span class="line">    weight -2</span><br><span class="line">    fall 10</span><br><span class="line">    rise 2</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">vrrp_instance VI_1 &#123;</span><br><span class="line">    state MASTER</span><br><span class="line">    interface ens192                # 根据实际网卡名修改</span><br><span class="line">    virtual_router_id 51</span><br><span class="line">    priority 101</span><br><span class="line">    advert_int 1</span><br><span class="line">    </span><br><span class="line">    authentication &#123;</span><br><span class="line">        auth_type PASS</span><br><span class="line">        auth_pass K8SHA_KA_AUTH    # 建议修改密码</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    virtual_ipaddress &#123;</span><br><span class="line">        192.168.171.133             # VIP地址</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    # 使用单播模式（推荐）</span><br><span class="line">    unicast_src_ip 192.168.171.134  # 本机IP（LB-1）</span><br><span class="line">    unicast_peer &#123;</span><br><span class="line">        192.168.171.135             # 对端IP（LB-2）</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    # 配置追踪脚本</span><br><span class="line">    track_script &#123;</span><br><span class="line">        check_apiserver</span><br><span class="line">        check_haproxy</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h3 id="备节点配置"><a href="#备节点配置" class="headerlink" title="备节点配置"></a>备节点配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置备节点的keepalived</span></span><br><span class="line">cat &gt; /etc/keepalived/keepalived.conf &lt;&lt; EOF</span><br><span class="line">! Configuration File for keepalived</span><br><span class="line">global_defs &#123;</span><br><span class="line">    router_id LVS_DEVEL</span><br><span class="line">    script_user root</span><br><span class="line">    enable_script_security</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">vrrp_script check_haproxy &#123;</span><br><span class="line">    script &quot;/usr/bin/killall -0 haproxy&quot;</span><br><span class="line">    interval 2</span><br><span class="line">    weight 2</span><br><span class="line">    fall 2</span><br><span class="line">    rise 1</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">vrrp_script check_apiserver &#123;</span><br><span class="line">    script &quot;/etc/keepalived/check_apiserver.sh&quot;</span><br><span class="line">    interval 3</span><br><span class="line">    weight -2</span><br><span class="line">    fall 10</span><br><span class="line">    rise 2</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">vrrp_instance VI_1 &#123;</span><br><span class="line">    state BACKUP</span><br><span class="line">    interface ens192                # 根据实际网卡名修改</span><br><span class="line">    virtual_router_id 51</span><br><span class="line">    priority 100</span><br><span class="line">    advert_int 1</span><br><span class="line">    </span><br><span class="line">    authentication &#123;</span><br><span class="line">        auth_type PASS</span><br><span class="line">        auth_pass K8SHA_KA_AUTH    # 与主节点保持一致</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    virtual_ipaddress &#123;</span><br><span class="line">        192.168.171.133             # VIP地址</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    unicast_src_ip 192.168.171.135  # 本机IP（LB-2）</span><br><span class="line">    unicast_peer &#123;</span><br><span class="line">        192.168.171.134             # 对端IP（LB-1）</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    track_script &#123;</span><br><span class="line">        check_apiserver</span><br><span class="line">        check_haproxy</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h3 id="启动服务"><a href="#启动服务" class="headerlink" title="启动服务"></a>启动服务</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查配置文件语法</span></span><br><span class="line">keepalived -t -f /etc/keepalived/keepalived.conf</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动并设置开机自启</span></span><br><span class="line">systemctl start keepalived</span><br><span class="line">systemctl enable keepalived</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查服务状态</span></span><br><span class="line">systemctl status keepalived</span><br></pre></td></tr></table></figure><h2 id="HAProxy-部署"><a href="#HAProxy-部署" class="headerlink" title="HAProxy 部署"></a>HAProxy 部署</h2><h3 id="安装-HAProxy"><a href="#安装-HAProxy" class="headerlink" title="安装 HAProxy"></a>安装 HAProxy</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在所有负载均衡节点上安装</span></span><br><span class="line">apt install -y haproxy</span><br></pre></td></tr></table></figure><h3 id="配置-HAProxy"><a href="#配置-HAProxy" class="headerlink" title="配置 HAProxy"></a>配置 HAProxy</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">备份原配置</span></span><br><span class="line">cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建新配置</span></span><br><span class="line">cat &gt; /etc/haproxy/haproxy.cfg &lt;&lt; EOF</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">---------------------------------------------------------------------</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Global settings</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">---------------------------------------------------------------------</span></span><br><span class="line">global</span><br><span class="line">    log /dev/log local0</span><br><span class="line">    log /dev/log local1 notice</span><br><span class="line">    daemon</span><br><span class="line">    maxconn 100000</span><br><span class="line">    user haproxy</span><br><span class="line">    group haproxy</span><br><span class="line">    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">---------------------------------------------------------------------</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Default settings</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">---------------------------------------------------------------------</span></span><br><span class="line">defaults</span><br><span class="line">    log     global</span><br><span class="line">    mode    tcp</span><br><span class="line">    option  dontlognull</span><br><span class="line">    timeout connect 5000ms</span><br><span class="line">    timeout client  50000ms</span><br><span class="line">    timeout server  50000ms</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">---------------------------------------------------------------------</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Statistics settings</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">---------------------------------------------------------------------</span></span><br><span class="line">listen stats</span><br><span class="line">    bind *:9090</span><br><span class="line">    mode http</span><br><span class="line">    stats enable</span><br><span class="line">    stats uri /stats</span><br><span class="line">    stats refresh 30s</span><br><span class="line">    stats auth admin:Admin@123.com    # 访问统计页面的用户名和密码</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">---------------------------------------------------------------------</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Frontend configuration <span class="keyword">for</span> API server</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">---------------------------------------------------------------------</span></span><br><span class="line">frontend k8s-apiserver</span><br><span class="line">    bind *:6443</span><br><span class="line">    mode tcp</span><br><span class="line">    option tcplog</span><br><span class="line">    default_backend k8s-apiserver</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">---------------------------------------------------------------------</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Backend configuration <span class="keyword">for</span> API server</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">---------------------------------------------------------------------</span></span><br><span class="line">backend k8s-apiserver</span><br><span class="line">    mode tcp</span><br><span class="line">    option tcp-check</span><br><span class="line">    balance roundrobin</span><br><span class="line">    default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100</span><br><span class="line">    server master1 192.168.171.136:6443 check</span><br><span class="line">    server master2 192.168.171.137:6443 check</span><br><span class="line">    server master3 192.168.171.138:6443 check</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h3 id="启动服务-1"><a href="#启动服务-1" class="headerlink" title="启动服务"></a>启动服务</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查配置文件语法</span></span><br><span class="line">haproxy -f /etc/haproxy/haproxy.cfg -c</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动并设置开机自启</span></span><br><span class="line">systemctl start haproxy</span><br><span class="line">systemctl enable haproxy</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查服务状态</span></span><br><span class="line">systemctl status haproxy</span><br></pre></td></tr></table></figure><h2 id="验证部署"><a href="#验证部署" class="headerlink" title="验证部署"></a>验证部署</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查VIP是否生效</span></span><br><span class="line">ip a | grep 192.168.1.110</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查HAProxy统计页面</span></span><br><span class="line">curl -u admin:Admin@123.com http://localhost:9090/stats</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">测试API服务器访问</span></span><br><span class="line">curl -k https://192.168.171.133:6443/healthz</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">测试故障转移</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">1. 在主节点上停止HAProxy</span></span><br><span class="line">systemctl stop haproxy</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">2. 观察VIP是否漂移到备节点</span></span><br><span class="line">ip a</span><br></pre></td></tr></table></figure><h2 id="故障排除-1"><a href="#故障排除-1" class="headerlink" title="故障排除"></a>故障排除</h2><ol><li>Keepalived 故障排查：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查日志</span></span><br><span class="line">journalctl -u keepalived -f</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查配置</span></span><br><span class="line">keepalived -t -f /etc/keepalived/keepalived.conf</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查网络接口</span></span><br><span class="line">ip a</span><br></pre></td></tr></table></figure><ol start="2"><li>HAProxy 故障排查：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查日志</span></span><br><span class="line">journalctl -u haproxy -f</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查配置</span></span><br><span class="line">haproxy -f /etc/haproxy/haproxy.cfg -c</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查端口监听</span></span><br><span class="line">netstat -ntlp | grep haproxy</span><br></pre></td></tr></table></figure><h2 id="注意事项-1"><a href="#注意事项-1" class="headerlink" title="注意事项"></a>注意事项</h2><ol><li><p>网络配置：</p><ul><li>确保防火墙允许VRRP协议（端口112）</li><li>允许HAProxy监听端口（6443, 9090）</li><li>检查网卡名称是否正确</li></ul></li><li><p>安全建议：</p><ul><li>修改Keepalived认证密码</li><li>更改HAProxy统计页面的访问凭据</li><li>限制HAProxy统计页面的访问IP</li></ul></li><li><p>维护建议：</p><ul><li>定期检查服务状态</li><li>监控日志信息</li><li>定期测试故障转移功能</li></ul></li><li><p>性能优化：</p><ul><li>根据实际负载调整HAProxy的连接数限制</li><li>适当调整超时时间</li><li>监控系统资源使用情况</li></ul></li></ol><hr><h1 id="ETCD-集群部署"><a href="#ETCD-集群部署" class="headerlink" title="ETCD 集群部署"></a>ETCD 集群部署</h1><h2 id="环境准备-1"><a href="#环境准备-1" class="headerlink" title="环境准备"></a>环境准备</h2><h3 id="主机配置"><a href="#主机配置" class="headerlink" title="主机配置"></a>主机配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改主机名</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在 etcd1 上执行</span></span><br><span class="line">hostnamectl set-hostname etcd1</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在 etcd2 上执行</span></span><br><span class="line">hostnamectl set-hostname etcd2</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在 etcd3 上执行</span></span><br><span class="line">hostnamectl set-hostname etcd3</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置 hosts 解析</span></span><br><span class="line">cat &gt;&gt; /etc/hosts &lt;&lt; EOF</span><br><span class="line">192.168.171.136 etcd1</span><br><span class="line">192.168.171.137 etcd2</span><br><span class="line">192.168.171.138 etcd3</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h3 id="配置免密登录"><a href="#配置免密登录" class="headerlink" title="配置免密登录"></a>配置免密登录</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在 etcd1 上执行</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成密钥对</span></span><br><span class="line">ssh-keygen -t rsa -b 2048 -N &quot;&quot; -f ~/.ssh/id_rsa</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">分发公钥</span></span><br><span class="line">for host in etcd1 etcd2 etcd3; do</span><br><span class="line">    sshpass -p &#x27;your_password&#x27; ssh-copy-id -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa.pub &quot;root@$host&quot;</span><br><span class="line">done</span><br></pre></td></tr></table></figure><h3 id="配置环境变量"><a href="#配置环境变量" class="headerlink" title="配置环境变量"></a>配置环境变量</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在所有节点上执行</span></span><br><span class="line">cat &gt;&gt; /etc/profile &lt;&lt; EOF</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">ETCD API 版本</span></span><br><span class="line">export ETCDCTL_API=3</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">source /etc/profile</span><br></pre></td></tr></table></figure><h2 id="组件安装"><a href="#组件安装" class="headerlink" title="组件安装"></a>组件安装</h2><h3 id="安装-CFSSL-工具"><a href="#安装-CFSSL-工具" class="headerlink" title="安装 CFSSL 工具"></a>安装 CFSSL 工具</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在所有节点上执行</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装 CFSSL（下载地址：https://github.com/cloudflare/cfssl/releases）</span></span><br><span class="line">cp cfssl_1.6.3_linux_amd64 /usr/local/bin/cfssl</span><br><span class="line">cp cfssljson_1.6.3_linux_amd64 /usr/local/bin/cfssljson</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加执行权限</span></span><br><span class="line">chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证安装</span></span><br><span class="line">cfssl version</span><br><span class="line">cfssljson -version</span><br></pre></td></tr></table></figure><h3 id="安装-ETCD"><a href="#安装-ETCD" class="headerlink" title="安装 ETCD"></a>安装 ETCD</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在所有节点上执行</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置环境变量</span></span><br><span class="line">export ETCD_VER=v3.5.9</span><br><span class="line">export DOWNLOAD_URL=&quot;https://github.com/etcd-io/etcd/releases/download&quot;</span><br><span class="line">export INSTALL_DIR=&quot;/usr/local/bin&quot;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">下载 ETCD 二进制文件</span></span><br><span class="line">wget $&#123;DOWNLOAD_URL&#125;/$&#123;ETCD_VER&#125;/etcd-$&#123;ETCD_VER&#125;-linux-amd64.tar.gz</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证下载文件完整性</span></span><br><span class="line">wget $&#123;DOWNLOAD_URL&#125;/$&#123;ETCD_VER&#125;/etcd-$&#123;ETCD_VER&#125;-linux-amd64.tar.gz.asc</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">如果需要验证签名</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">gpg --verify etcd-<span class="variable">$&#123;ETCD_VER&#125;</span>-linux-amd64.tar.gz.asc</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">解压安装包</span></span><br><span class="line">tar -xzf etcd-$&#123;ETCD_VER&#125;-linux-amd64.tar.gz -C /tmp/</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">复制二进制文件到安装目录</span></span><br><span class="line">cp /tmp/etcd-$&#123;ETCD_VER&#125;-linux-amd64/etcd* $&#123;INSTALL_DIR&#125;/</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">清理临时文件</span></span><br><span class="line">rm -rf /tmp/etcd-$&#123;ETCD_VER&#125;-linux-amd64* etcd-$&#123;ETCD_VER&#125;-linux-amd64.tar.gz*</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建数据目录</span></span><br><span class="line">mkdir -p /data/etcd</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证安装</span></span><br><span class="line"><span class="meta prompt_">$</span><span class="language-bash">&#123;INSTALL_DIR&#125;/etcd --version</span></span><br><span class="line"><span class="meta prompt_">$</span><span class="language-bash">&#123;INSTALL_DIR&#125;/etcdctl version</span></span><br></pre></td></tr></table></figure><h2 id="配置-TLS-证书"><a href="#配置-TLS-证书" class="headerlink" title="配置 TLS 证书"></a>配置 TLS 证书</h2><h3 id="创建证书配置"><a href="#创建证书配置" class="headerlink" title="创建证书配置"></a>创建证书配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在 etcd1 上执行</span></span><br><span class="line">mkdir -p /etc/etcd/ssl</span><br><span class="line">cd /etc/etcd/ssl</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建 CA 配置文件</span></span><br><span class="line">cat &gt; ca-config.json &lt;&lt; EOF</span><br><span class="line">&#123;</span><br><span class="line">    &quot;signing&quot;: &#123;</span><br><span class="line">        &quot;default&quot;: &#123;</span><br><span class="line">            &quot;expiry&quot;: &quot;876000h&quot;</span><br><span class="line">        &#125;,</span><br><span class="line">        &quot;profiles&quot;: &#123;</span><br><span class="line">            &quot;server&quot;: &#123;</span><br><span class="line">                &quot;expiry&quot;: &quot;876000h&quot;,</span><br><span class="line">                &quot;usages&quot;: [</span><br><span class="line">                    &quot;signing&quot;,</span><br><span class="line">                    &quot;key encipherment&quot;,</span><br><span class="line">                    &quot;server auth&quot;,</span><br><span class="line">                    &quot;client auth&quot;</span><br><span class="line">                ]</span><br><span class="line">            &#125;,</span><br><span class="line">            &quot;client&quot;: &#123;</span><br><span class="line">                &quot;expiry&quot;: &quot;876000h&quot;,</span><br><span class="line">                &quot;usages&quot;: [</span><br><span class="line">                    &quot;signing&quot;,</span><br><span class="line">                    &quot;key encipherment&quot;,</span><br><span class="line">                    &quot;client auth&quot;</span><br><span class="line">                ]</span><br><span class="line">            &#125;,</span><br><span class="line">            &quot;peer&quot;: &#123;</span><br><span class="line">                &quot;expiry&quot;: &quot;876000h&quot;,</span><br><span class="line">                &quot;usages&quot;: [</span><br><span class="line">                    &quot;signing&quot;,</span><br><span class="line">                    &quot;key encipherment&quot;,</span><br><span class="line">                    &quot;server auth&quot;,</span><br><span class="line">                    &quot;client auth&quot;</span><br><span class="line">                ]</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建 CA 证书请求文件</span></span><br><span class="line">cat &gt; etcd-ca-csr.json &lt;&lt; EOF</span><br><span class="line">&#123;</span><br><span class="line">    &quot;key&quot;: &#123;</span><br><span class="line">        &quot;algo&quot;: &quot;rsa&quot;,</span><br><span class="line">        &quot;size&quot;: 4096</span><br><span class="line">    &#125;,</span><br><span class="line">    &quot;names&quot;: [</span><br><span class="line">        &#123;</span><br><span class="line">            &quot;C&quot;: &quot;CN&quot;,</span><br><span class="line">            &quot;L&quot;: &quot;Beijing&quot;,</span><br><span class="line">            &quot;ST&quot;: &quot;Beijing&quot;,</span><br><span class="line">            &quot;O&quot;: &quot;k8s&quot;,</span><br><span class="line">            &quot;OU&quot;: &quot;System&quot;</span><br><span class="line">        &#125;</span><br><span class="line">    ]</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建客户端证书请求文件</span></span><br><span class="line">cat &gt; client-csr.json &lt;&lt; EOF</span><br><span class="line">&#123;</span><br><span class="line">    &quot;CN&quot;: &quot;client&quot;,</span><br><span class="line">    &quot;key&quot;: &#123;</span><br><span class="line">        &quot;algo&quot;: &quot;rsa&quot;,</span><br><span class="line">        &quot;size&quot;: 2048</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建服务端证书请求文件</span></span><br><span class="line">cat &gt; etcd-server-csr.json &lt;&lt; EOF</span><br><span class="line">&#123;</span><br><span class="line">    &quot;CN&quot;: &quot;etcd-server&quot;,</span><br><span class="line">    &quot;hosts&quot;: [</span><br><span class="line">        &quot;192.168.171.136&quot;,</span><br><span class="line">        &quot;192.168.171.137&quot;,</span><br><span class="line">        &quot;192.168.171.138&quot;,</span><br><span class="line">        &quot;127.0.0.1&quot;</span><br><span class="line">    ],</span><br><span class="line">    &quot;key&quot;: &#123;</span><br><span class="line">        &quot;algo&quot;: &quot;rsa&quot;,</span><br><span class="line">        &quot;size&quot;: 2048</span><br><span class="line">    &#125;,</span><br><span class="line">    &quot;names&quot;: [</span><br><span class="line">        &#123;</span><br><span class="line">            &quot;C&quot;: &quot;CN&quot;,</span><br><span class="line">            &quot;L&quot;: &quot;Beijing&quot;,</span><br><span class="line">            &quot;O&quot;: &quot;etcd-cluster&quot;,</span><br><span class="line">            &quot;OU&quot;: &quot;System&quot;,</span><br><span class="line">            &quot;ST&quot;: &quot;Beijing&quot;</span><br><span class="line">        &#125;</span><br><span class="line">    ]</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建对等证书请求文件</span></span><br><span class="line">cat &gt; etcd-peer-csr.json &lt;&lt; EOF</span><br><span class="line">&#123;</span><br><span class="line">    &quot;CN&quot;: &quot;etcd-peer&quot;,</span><br><span class="line">    &quot;hosts&quot;: [</span><br><span class="line">        &quot;192.168.171.136&quot;,</span><br><span class="line">        &quot;192.168.171.137&quot;,</span><br><span class="line">        &quot;192.168.171.138&quot;,</span><br><span class="line">        &quot;127.0.0.1&quot;</span><br><span class="line">    ],</span><br><span class="line">    &quot;key&quot;: &#123;</span><br><span class="line">        &quot;algo&quot;: &quot;rsa&quot;,</span><br><span class="line">        &quot;size&quot;: 2048</span><br><span class="line">    &#125;,</span><br><span class="line">    &quot;names&quot;: [</span><br><span class="line">        &#123;</span><br><span class="line">            &quot;C&quot;: &quot;CN&quot;,</span><br><span class="line">            &quot;L&quot;: &quot;Beijing&quot;,</span><br><span class="line">            &quot;O&quot;: &quot;etcd-cluster&quot;,</span><br><span class="line">            &quot;OU&quot;: &quot;System&quot;,</span><br><span class="line">            &quot;ST&quot;: &quot;Beijing&quot;</span><br><span class="line">        &#125;</span><br><span class="line">    ]</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h3 id="生成证书"><a href="#生成证书" class="headerlink" title="生成证书"></a>生成证书</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在 etcd1 上执行</span></span><br><span class="line">cd /etc/etcd/ssl</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成 CA 证书</span></span><br><span class="line">cfssl gencert -initca etcd-ca-csr.json | cfssljson -bare etcd-ca</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成客户端证书</span></span><br><span class="line">cfssl gencert \</span><br><span class="line">    -ca=etcd-ca.pem \</span><br><span class="line">    -ca-key=etcd-ca-key.pem \</span><br><span class="line">    -config=ca-config.json \</span><br><span class="line">    -profile=client client-csr.json | cfssljson -bare client</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成服务端证书</span></span><br><span class="line">cfssl gencert \</span><br><span class="line">    -ca=etcd-ca.pem \</span><br><span class="line">    -ca-key=etcd-ca-key.pem \</span><br><span class="line">    -config=ca-config.json \</span><br><span class="line">    -profile=server etcd-server-csr.json | cfssljson -bare etcd-server</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成对等证书</span></span><br><span class="line">cfssl gencert \</span><br><span class="line">    -ca=etcd-ca.pem \</span><br><span class="line">    -ca-key=etcd-ca-key.pem \</span><br><span class="line">    -config=ca-config.json \</span><br><span class="line">    -profile=peer etcd-peer-csr.json | cfssljson -bare etcd-peer</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">分发证书到其他节点</span></span><br><span class="line">for host in etcd2 etcd3; do</span><br><span class="line">    ssh $host &quot;mkdir -p /etc/etcd/ssl&quot;</span><br><span class="line">    scp /etc/etcd/ssl/* $host:/etc/etcd/ssl/</span><br><span class="line">done</span><br></pre></td></tr></table></figure><h2 id="配置-ETCD-服务"><a href="#配置-ETCD-服务" class="headerlink" title="配置 ETCD 服务"></a>配置 ETCD 服务</h2><h3 id="创建服务配置文件"><a href="#创建服务配置文件" class="headerlink" title="创建服务配置文件"></a>创建服务配置文件</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在 etcd1 上执行</span></span><br><span class="line">cat &gt; /lib/systemd/system/etcd.service &lt;&lt; EOF</span><br><span class="line">[Unit]</span><br><span class="line">Description=Etcd Server</span><br><span class="line">After=network.target</span><br><span class="line">After=network-online.target</span><br><span class="line">Wants=network-online.target</span><br><span class="line">Before=kube-apiserver.service</span><br><span class="line">Documentation=https://github.com/coreos</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=notify</span><br><span class="line">WorkingDirectory=/data/etcd/</span><br><span class="line">ExecStart=/usr/local/bin/etcd \\</span><br><span class="line">  --name=etcd1 \\</span><br><span class="line">  --cert-file=/etc/etcd/ssl/etcd-server.pem \\</span><br><span class="line">  --key-file=/etc/etcd/ssl/etcd-server-key.pem \\</span><br><span class="line">  --peer-cert-file=/etc/etcd/ssl/etcd-peer.pem \\</span><br><span class="line">  --peer-key-file=/etc/etcd/ssl/etcd-peer-key.pem \\</span><br><span class="line">  --trusted-ca-file=/etc/etcd/ssl/etcd-ca.pem \\</span><br><span class="line">  --peer-trusted-ca-file=/etc/etcd/ssl/etcd-ca.pem \\</span><br><span class="line">  --initial-advertise-peer-urls=https://192.168.171.136:2380 \\</span><br><span class="line">  --listen-peer-urls=https://192.168.171.136:2380 \\</span><br><span class="line">  --listen-client-urls=https://192.168.171.136:2379 \\</span><br><span class="line">  --advertise-client-urls=https://192.168.171.136:2379 \\</span><br><span class="line">  --initial-cluster-token=etcd-cluster-0 \\</span><br><span class="line">  --initial-cluster=etcd1=https://192.168.171.136:2380,etcd2=https://192.168.171.137:2380,etcd3=https://192.168.171.138:2380 \\</span><br><span class="line">  --initial-cluster-state=new \\</span><br><span class="line">  --data-dir=/data/etcd \\</span><br><span class="line">  --snapshot-count=50000 \\</span><br><span class="line">  --auto-compaction-retention=1 \\</span><br><span class="line">  --max-request-bytes=10485760 \\</span><br><span class="line">  --quota-backend-bytes=8589934592</span><br><span class="line">Restart=always</span><br><span class="line">RestartSec=15</span><br><span class="line">LimitNOFILE=65536</span><br><span class="line">OOMScoreAdjust=-999</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">分发到其他节点并修改配置</span></span><br><span class="line">for host in etcd2 etcd3; do</span><br><span class="line">    scp /lib/systemd/system/etcd.service $host:/lib/systemd/system/</span><br><span class="line">    ssh $host &quot;sed -i &#x27;s/etcd1/$host/g; s/192.168.171.136/192.168.171.$(expr 136 + $(echo $host | cut -c5))/g&#x27; /lib/systemd/system/etcd.service&quot;</span><br><span class="line">done</span><br></pre></td></tr></table></figure><h3 id="启动服务-2"><a href="#启动服务-2" class="headerlink" title="启动服务"></a>启动服务</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在所有节点上执行</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建数据目录</span></span><br><span class="line">mkdir -p /data/etcd</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重载服务配置</span></span><br><span class="line">systemctl daemon-reload</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动并设置开机自启</span></span><br><span class="line">systemctl enable --now etcd</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看服务状态</span></span><br><span class="line">systemctl status etcd</span><br></pre></td></tr></table></figure><h2 id="集群验证"><a href="#集群验证" class="headerlink" title="集群验证"></a>集群验证</h2><h3 id="配置命令别名"><a href="#配置命令别名" class="headerlink" title="配置命令别名"></a>配置命令别名</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在所有节点上执行</span></span><br><span class="line">cat &gt;&gt; ~/.bashrc &lt;&lt; EOF</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">ETCD 集群操作别名</span></span><br><span class="line">alias etcdctl=&#x27;etcdctl \\</span><br><span class="line">    --endpoints=192.168.171.136:2379,192.168.171.137:2379,192.168.171.138:2379 \\</span><br><span class="line">    --cacert=/etc/etcd/ssl/etcd-ca.pem \\</span><br><span class="line">    --cert=/etc/etcd/ssl/etcd-server.pem \\</span><br><span class="line">    --key=/etc/etcd/ssl/etcd-server-key.pem&#x27;</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">source ~/.bashrc</span><br></pre></td></tr></table></figure><h3 id="检查集群状态"><a href="#检查集群状态" class="headerlink" title="检查集群状态"></a>检查集群状态</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看集群成员</span></span><br><span class="line">etcdctl member list -w table</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看集群健康状态</span></span><br><span class="line">etcdctl endpoint health -w table</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">写入测试数据</span></span><br><span class="line">etcdctl put test &quot;hello etcd&quot;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">读取测试数据</span></span><br><span class="line">etcdctl get test</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">删除测试数据</span></span><br><span class="line">etcdctl del test</span><br></pre></td></tr></table></figure><h2 id="集群备份"><a href="#集群备份" class="headerlink" title="集群备份"></a>集群备份</h2><h3 id="配置自动备份"><a href="#配置自动备份" class="headerlink" title="配置自动备份"></a>配置自动备份</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建备份目录</span></span><br><span class="line">mkdir -p /data/etcd-backups</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建备份脚本</span></span><br><span class="line">cat &gt; /data/etcd-backups/etcd-backup.sh &lt;&lt; EOF</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">备份配置</span></span><br><span class="line">BACKUP_DIR=&quot;/data/etcd-backups&quot;</span><br><span class="line">DATE=\$(date +%Y%m%d%H%M%S)</span><br><span class="line">LOG_FILE=&quot;\$&#123;BACKUP_DIR&#125;/backup-\$&#123;DATE&#125;.log&quot;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">备份命令</span></span><br><span class="line">/usr/local/bin/etcdctl \\</span><br><span class="line">    --endpoints=192.168.171.136:2379 \\</span><br><span class="line">    --cacert=/etc/etcd/ssl/etcd-ca.pem \\</span><br><span class="line">    --cert=/etc/etcd/ssl/etcd-server.pem \\</span><br><span class="line">    --key=/etc/etcd/ssl/etcd-server-key.pem \\</span><br><span class="line">    snapshot save \$&#123;BACKUP_DIR&#125;/backup-\$&#123;DATE&#125;.db &gt; \$&#123;LOG_FILE&#125; 2&gt;&amp;1</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">清理旧备份</span></span><br><span class="line">find \$&#123;BACKUP_DIR&#125; -name &quot;backup-*.db&quot; -mtime +7 -delete</span><br><span class="line">find \$&#123;BACKUP_DIR&#125; -name &quot;backup-*.log&quot; -mtime +7 -delete</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加执行权限</span></span><br><span class="line">chmod +x /data/etcd-backups/etcd-backup.sh</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加定时任务</span></span><br><span class="line">echo &quot;0 2 * * * /data/etcd-backups/etcd-backup.sh&quot; &gt;&gt; /var/spool/cron/crontabs/root</span><br></pre></td></tr></table></figure><h2 id="故障排除-2"><a href="#故障排除-2" class="headerlink" title="故障排除"></a>故障排除</h2><h3 id="常见问题排查"><a href="#常见问题排查" class="headerlink" title="常见问题排查"></a>常见问题排查</h3><ol><li>证书问题：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查证书有效期</span></span><br><span class="line">openssl x509 -in /etc/etcd/ssl/etcd-server.pem -text -noout | grep -A2 Validity</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查证书权限</span></span><br><span class="line">ls -l /etc/etcd/ssl/</span><br></pre></td></tr></table></figure><ol start="2"><li>网络问题：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查端口监听</span></span><br><span class="line">netstat -ntlp | grep etcd</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查端口连通性</span></span><br><span class="line">for port in 2379 2380; do</span><br><span class="line">    for host in 192.168.171.136 192.168.171.137 192.168.171.138; do</span><br><span class="line">        echo &quot;Testing $host:$port...&quot;</span><br><span class="line">        nc -zv $host $port</span><br><span class="line">    done</span><br><span class="line">done</span><br></pre></td></tr></table></figure><ol start="3"><li>日志排查：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看实时日志</span></span><br><span class="line">journalctl -u etcd -f</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看错误日志</span></span><br><span class="line">journalctl -u etcd -p err</span><br></pre></td></tr></table></figure><h2 id="性能优化"><a href="#性能优化" class="headerlink" title="性能优化"></a>性能优化</h2><ol><li>系统参数优化：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">调整系统限制</span></span><br><span class="line">cat &gt;&gt; /etc/security/limits.conf &lt;&lt; EOF</span><br><span class="line">* soft nofile 65536</span><br><span class="line">* hard nofile 65536</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">调整内核参数</span></span><br><span class="line">cat &gt;&gt; /etc/sysctl.conf &lt;&lt; EOF</span><br><span class="line">net.ipv4.ip_local_port_range = 1024 65000</span><br><span class="line">net.core.somaxconn = 32768</span><br><span class="line">net.core.netdev_max_backlog = 16384</span><br><span class="line">net.ipv4.tcp_max_syn_backlog = 8096</span><br><span class="line">net.ipv4.tcp_tw_reuse = 1</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">sysctl -p</span><br></pre></td></tr></table></figure><ol start="2"><li>ETCD 参数优化：</li></ol><ul><li>适当调整 <code>--snapshot-count</code></li><li>根据实际情况调整 <code>--quota-backend-bytes</code></li><li>配置合适的 <code>--auto-compaction-retention</code></li></ul><h2 id="注意事项-2"><a href="#注意事项-2" class="headerlink" title="注意事项"></a>注意事项</h2><ol><li><p>安全建议：</p><ul><li>定期更新证书</li><li>限制访问权限</li><li>配置防火墙规则</li></ul></li><li><p>维护建议：</p><ul><li>定期备份数据</li><li>监控集群状态</li><li>及时清理历史数据</li></ul></li><li><p>性能建议：</p><ul><li>使用 SSD 存储</li><li>独立的磁盘空间</li><li>足够的内存配置</li></ul></li><li><p>高可用建议：</p><ul><li>节点跨机架部署</li><li>配置监控告警</li><li>定期进行故障演练</li></ul></li></ol><hr><h1 id="Harbor-私有镜像仓库部署"><a href="#Harbor-私有镜像仓库部署" class="headerlink" title="Harbor 私有镜像仓库部署"></a>Harbor 私有镜像仓库部署</h1><h2 id="环境准备-2"><a href="#环境准备-2" class="headerlink" title="环境准备"></a>环境准备</h2><h3 id="DNS-配置"><a href="#DNS-配置" class="headerlink" title="DNS 配置"></a>DNS 配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置本地解析</span></span><br><span class="line">cat &gt;&gt; /etc/hosts &lt;&lt; EOF</span><br><span class="line">192.168.171.50 harbor.k8s.com</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改主机名</span></span><br><span class="line">hostnamectl set-hostname harbor.k8s.com</span><br></pre></td></tr></table></figure><h3 id="存储配置"><a href="#存储配置" class="headerlink" title="存储配置"></a>存储配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装 LVM 工具</span></span><br><span class="line">apt-get update</span><br><span class="line">apt-get install -y lvm2</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建物理卷</span></span><br><span class="line">pvcreate /dev/sdb1</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建卷组</span></span><br><span class="line">vgcreate data_vg /dev/sdb1</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建逻辑卷</span></span><br><span class="line">lvcreate -l +100%FREE -n data_lv data_vg</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">格式化逻辑卷</span></span><br><span class="line">mkfs.ext4 /dev/data_vg/data_lv</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">清理旧配置</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">sed -i <span class="string">&#x27;/\/data/d&#x27;</span> /etc/fstab</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置挂载</span></span><br><span class="line">echo &quot;/dev/data_vg/data_lv /data ext4 defaults 0 0&quot; &gt;&gt; /etc/fstab</span><br><span class="line">mkdir -p /data</span><br><span class="line">mount -a</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证挂载</span></span><br><span class="line">df -h /data</span><br></pre></td></tr></table></figure><h2 id="Docker-环境配置"><a href="#Docker-环境配置" class="headerlink" title="Docker 环境配置"></a>Docker 环境配置</h2><h3 id="安装-Docker"><a href="#安装-Docker" class="headerlink" title="安装 Docker"></a>安装 Docker</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装依赖包</span></span><br><span class="line">apt-get update</span><br><span class="line">apt-get install -y \</span><br><span class="line">    apt-transport-https \</span><br><span class="line">    ca-certificates \</span><br><span class="line">    curl \</span><br><span class="line">    gnupg \</span><br><span class="line">    lsb-release</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加 Docker 官方 GPG 密钥</span></span><br><span class="line">curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加 Docker 软件源</span></span><br><span class="line">echo &quot;deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable&quot; | tee /etc/apt/sources.list.d/docker.list &gt; /dev/null</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装 Docker</span></span><br><span class="line">apt-get update</span><br><span class="line">apt-get install -y docker-ce docker-ce-cli containerd.io</span><br></pre></td></tr></table></figure><h3 id="配置-Docker"><a href="#配置-Docker" class="headerlink" title="配置 Docker"></a>配置 Docker</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建 Docker 配置目录</span></span><br><span class="line">mkdir -p /etc/docker</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置 Docker daemon</span></span><br><span class="line">cat &gt; /etc/docker/daemon.json &lt;&lt; &#x27;EOF&#x27;</span><br><span class="line">&#123;</span><br><span class="line">  &quot;registry-mirrors&quot;: [&quot;https://ustc-edu-cn.mirror.aliyuncs.com&quot;],</span><br><span class="line">  &quot;debug&quot;: false,</span><br><span class="line">  &quot;ip-forward&quot;: true,</span><br><span class="line">  &quot;ipv6&quot;: false,</span><br><span class="line">  &quot;live-restore&quot;: true,</span><br><span class="line">  &quot;log-driver&quot;: &quot;json-file&quot;,</span><br><span class="line">  &quot;log-level&quot;: &quot;warn&quot;,</span><br><span class="line">  &quot;log-opts&quot;: &#123;</span><br><span class="line">    &quot;max-size&quot;: &quot;100m&quot;,</span><br><span class="line">    &quot;max-file&quot;: &quot;2&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;selinux-enabled&quot;: false,</span><br><span class="line">  &quot;experimental&quot;: true,</span><br><span class="line">  &quot;storage-driver&quot;: &quot;overlay2&quot;,</span><br><span class="line">  &quot;metrics-addr&quot;: &quot;0.0.0.0:9323&quot;,</span><br><span class="line">  &quot;data-root&quot;: &quot;/data/docker&quot;,</span><br><span class="line">  &quot;default-ulimits&quot;: &#123;</span><br><span class="line">    &quot;nofile&quot;: &#123;</span><br><span class="line">      &quot;Name&quot;: &quot;nofile&quot;,</span><br><span class="line">      &quot;Hard&quot;: 65536,</span><br><span class="line">      &quot;Soft&quot;: 65536</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;exec-opts&quot;: [&quot;native.cgroupdriver=systemd&quot;]</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重启 Docker 服务</span></span><br><span class="line">systemctl daemon-reload</span><br><span class="line">systemctl restart docker</span><br><span class="line">systemctl enable docker</span><br></pre></td></tr></table></figure><h3 id="安装-Docker-Compose"><a href="#安装-Docker-Compose" class="headerlink" title="安装 Docker Compose"></a>安装 Docker Compose</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">下载 Docker Compose</span></span><br><span class="line">COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep &#x27;tag_name&#x27; | cut -d\&quot; -f4)</span><br><span class="line">curl -L &quot;https://github.com/docker/compose/releases/download/$&#123;COMPOSE_VERSION&#125;/docker-compose-$(uname -s)-$(uname -m)&quot; -o /usr/local/bin/docker-compose</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加执行权限</span></span><br><span class="line">chmod +x /usr/local/bin/docker-compose</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证安装</span></span><br><span class="line">docker-compose version</span><br></pre></td></tr></table></figure><h2 id="Harbor-部署"><a href="#Harbor-部署" class="headerlink" title="Harbor 部署"></a>Harbor 部署</h2><h3 id="下载-Harbor"><a href="#下载-Harbor" class="headerlink" title="下载 Harbor"></a>下载 Harbor</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置 Harbor 版本</span></span><br><span class="line">export HARBOR_VERSION=&quot;v2.9.1&quot;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">下载 Harbor 安装包</span></span><br><span class="line">wget https://github.com/goharbor/harbor/releases/download/$&#123;HARBOR_VERSION&#125;/harbor-offline-installer-$&#123;HARBOR_VERSION&#125;.tgz</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">解压安装包</span></span><br><span class="line">tar xzvf harbor-offline-installer-$&#123;HARBOR_VERSION&#125;.tgz -C /data</span><br></pre></td></tr></table></figure><h3 id="配置-Harbor"><a href="#配置-Harbor" class="headerlink" title="配置 Harbor"></a>配置 Harbor</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建配置文件</span></span><br><span class="line">cp /data/harbor/harbor.yml.tmpl /data/harbor/harbor.yml</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改配置文件</span></span><br><span class="line">cat &gt; /data/harbor/harbor.yml &lt;&lt; EOF</span><br><span class="line">hostname: harbor.k8s.com</span><br><span class="line">https:</span><br><span class="line">  certificate: /data/harbor/ssl/harbor.k8s.com.crt</span><br><span class="line">  private_key: /data/harbor/ssl/harbor.k8s.com.key</span><br><span class="line">harbor_admin_password: Harbor@123.com</span><br><span class="line">data_volume: /data/harbor/harbor-data</span><br><span class="line">log:</span><br><span class="line">  location: /data/harbor/harbor-logs</span><br><span class="line">  level: info</span><br><span class="line">  local:</span><br><span class="line">    rotate_count: 50</span><br><span class="line">    rotate_size: 200M</span><br><span class="line">database:</span><br><span class="line">  password: root123</span><br><span class="line">  max_idle_conns: 100</span><br><span class="line">  max_open_conns: 900</span><br><span class="line">storage_service:</span><br><span class="line">  ca_bundle: /etc/ssl/certs/ca-certificates.crt</span><br><span class="line">  redirect:</span><br><span class="line">    disabled: false</span><br><span class="line">  cache:</span><br><span class="line">    enabled: true</span><br><span class="line">    expire_hours: 24</span><br><span class="line">trivy:</span><br><span class="line">  enabled: true</span><br><span class="line">  ignore_unfixed: false</span><br><span class="line">  skip_update: false</span><br><span class="line">  offline_scan: false</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h3 id="配置-TLS-证书-1"><a href="#配置-TLS-证书-1" class="headerlink" title="配置 TLS 证书"></a>配置 TLS 证书</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建证书目录</span></span><br><span class="line">mkdir -p /data/harbor/ssl</span><br><span class="line">cd /data/harbor/ssl</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成 CA 私钥和证书</span></span><br><span class="line">openssl genrsa -out ca.key 4096</span><br><span class="line">openssl req -x509 -new -nodes -sha512 -days 3650 \</span><br><span class="line">    -subj &quot;/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=harbor.k8s.com&quot; \</span><br><span class="line">    -key ca.key \</span><br><span class="line">    -out ca.crt</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成服务器私钥</span></span><br><span class="line">openssl genrsa -out harbor.k8s.com.key 4096</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成证书签名请求</span></span><br><span class="line">openssl req -sha512 -new \</span><br><span class="line">    -subj &quot;/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=harbor.k8s.com&quot; \</span><br><span class="line">    -key harbor.k8s.com.key \</span><br><span class="line">    -out harbor.k8s.com.csr</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置证书扩展信息</span></span><br><span class="line">cat &gt; v3.ext &lt;&lt; EOF</span><br><span class="line">authorityKeyIdentifier=keyid,issuer</span><br><span class="line">basicConstraints=CA:FALSE</span><br><span class="line">keyUsage=digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment</span><br><span class="line">extendedKeyUsage=serverAuth</span><br><span class="line">subjectAltName=@alt_names</span><br><span class="line"></span><br><span class="line">[alt_names]</span><br><span class="line">DNS.1=harbor.k8s.com</span><br><span class="line">DNS.2=harbor</span><br><span class="line">IP.1=192.168.171.50</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成服务器证书</span></span><br><span class="line">openssl x509 -req -sha512 -days 3650 \</span><br><span class="line">    -extfile v3.ext \</span><br><span class="line">    -CA ca.crt -CAkey ca.key -CAcreateserial \</span><br><span class="line">    -in harbor.k8s.com.csr \</span><br><span class="line">    -out harbor.k8s.com.crt</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成客户端证书</span></span><br><span class="line">openssl x509 -inform PEM -in harbor.k8s.com.crt -out harbor.k8s.com.cert</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置 Docker 证书</span></span><br><span class="line">mkdir -p /etc/docker/certs.d/harbor.k8s.com/</span><br><span class="line">cp ca.crt /etc/docker/certs.d/harbor.k8s.com/</span><br><span class="line">cp harbor.k8s.com.cert /etc/docker/certs.d/harbor.k8s.com/</span><br><span class="line">cp harbor.k8s.com.key /etc/docker/certs.d/harbor.k8s.com/</span><br></pre></td></tr></table></figure><h3 id="安装-Harbor"><a href="#安装-Harbor" class="headerlink" title="安装 Harbor"></a>安装 Harbor</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">cd /data/harbor</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装 Harbor</span></span><br><span class="line">./prepare --with-trivy</span><br><span class="line">./install.sh --with-trivy</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证安装</span></span><br><span class="line">docker ps</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">测试登录</span></span><br><span class="line">docker login -u admin -p &#x27;Harbor@123.com&#x27; harbor.k8s.com</span><br></pre></td></tr></table></figure><h2 id="客户端配置"><a href="#客户端配置" class="headerlink" title="客户端配置"></a>客户端配置</h2><h3 id="配置-Docker-客户端"><a href="#配置-Docker-客户端" class="headerlink" title="配置 Docker 客户端"></a>配置 Docker 客户端</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">复制证书到客户端</span></span><br><span class="line">mkdir -p /etc/docker/certs.d/harbor.k8s.com/</span><br><span class="line">scp harbor-server:/etc/docker/certs.d/harbor.k8s.com/* /etc/docker/certs.d/harbor.k8s.com/</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重启 Docker 服务</span></span><br><span class="line">systemctl restart docker</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">测试登录</span></span><br><span class="line">docker login harbor.k8s.com</span><br></pre></td></tr></table></figure><h2 id="维护管理"><a href="#维护管理" class="headerlink" title="维护管理"></a>维护管理</h2><h3 id="备份配置"><a href="#备份配置" class="headerlink" title="备份配置"></a>备份配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建备份脚本</span></span><br><span class="line">cat &gt; /data/harbor/backup.sh &lt;&lt; &#x27;EOF&#x27;</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line"></span><br><span class="line">BACKUP_DIR=&quot;/data/harbor/backups&quot;</span><br><span class="line">DATE=$(date +%Y%m%d_%H%M%S)</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建备份目录</span></span><br><span class="line">mkdir -p $&#123;BACKUP_DIR&#125;/$&#123;DATE&#125;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">停止服务</span></span><br><span class="line">cd /data/harbor</span><br><span class="line">docker-compose down</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">备份数据</span></span><br><span class="line">tar czf $&#123;BACKUP_DIR&#125;/$&#123;DATE&#125;/harbor_data.tar.gz /data/harbor/harbor-data</span><br><span class="line">tar czf $&#123;BACKUP_DIR&#125;/$&#123;DATE&#125;/harbor_config.tar.gz /data/harbor/harbor.yml /data/harbor/ssl</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动服务</span></span><br><span class="line">docker-compose up -d</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">清理旧备份</span></span><br><span class="line">find $&#123;BACKUP_DIR&#125; -type d -mtime +7 -exec rm -rf &#123;&#125; \;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">记录备份日志</span></span><br><span class="line">echo &quot;Backup completed at $(date &#x27;+%Y-%m-%d %H:%M:%S&#x27;)&quot; &gt;&gt; /data/harbor/harbor-logs/backup.log</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加执行权限</span></span><br><span class="line">chmod +x /data/harbor/backup.sh</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建日志目录</span></span><br><span class="line">mkdir -p /data/harbor/harbor-logs</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加到 root 用户的定时任务</span></span><br><span class="line">(crontab -l 2&gt;/dev/null; echo &quot;0 2 * * * /data/harbor/backup.sh &gt; /dev/null 2&gt;&amp;1&quot;) | crontab -</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证定时任务</span></span><br><span class="line">crontab -l</span><br></pre></td></tr></table></figure><h3 id="监控配置"><a href="#监控配置" class="headerlink" title="监控配置"></a>监控配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建监控脚本</span></span><br><span class="line">cat &gt; /data/harbor/monitor.sh &lt;&lt; &#x27;EOF&#x27;</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查 Harbor 服务状态</span></span><br><span class="line">check_harbor() &#123;</span><br><span class="line">    local containers=$(docker ps --format &#x27;&#123;&#123;.Names&#125;&#125;&#x27; | grep &#x27;^harbor-&#x27;)</span><br><span class="line">    if [ $(echo &quot;$containers&quot; | wc -l) -lt 7 ]; then</span><br><span class="line">        echo &quot;Warning: Some Harbor containers are not running&quot;</span><br><span class="line">        return 1</span><br><span class="line">    fi</span><br><span class="line">    return 0</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查存储空间</span></span><br><span class="line">check_storage() &#123;</span><br><span class="line">    local usage=$(df -h /data | awk &#x27;NR==2 &#123;print $5&#125;&#x27; | sed &#x27;s/%//&#x27;)</span><br><span class="line">    if [ $usage -gt 80 ]; then</span><br><span class="line">        echo &quot;Warning: Storage usage is above 80%&quot;</span><br><span class="line">        return 1</span><br><span class="line">    fi</span><br><span class="line">    return 0</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">主检查逻辑</span></span><br><span class="line">main() &#123;</span><br><span class="line">    check_harbor || echo &quot;Harbor service check failed&quot;</span><br><span class="line">    check_storage || echo &quot;Storage check failed&quot;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">main</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">chmod +x /data/harbor/monitor.sh</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加到 crontab</span></span><br><span class="line">echo &quot;*/5 * * * * /data/harbor/monitor.sh &gt;&gt; /data/harbor/harbor-logs/monitor.log 2&gt;&amp;1&quot; &gt;&gt; /var/spool/cron/crontabs/root</span><br></pre></td></tr></table></figure><h2 id="故障排除-3"><a href="#故障排除-3" class="headerlink" title="故障排除"></a>故障排除</h2><h3 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h3><ol><li>证书问题：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查证书有效期</span></span><br><span class="line">openssl x509 -in /data/harbor/ssl/harbor.k8s.com.crt -text -noout | grep -A2 Validity</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查证书配置</span></span><br><span class="line">ls -l /etc/docker/certs.d/harbor.k8s.com/</span><br></pre></td></tr></table></figure><ol start="2"><li>存储问题：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查存储空间</span></span><br><span class="line">df -h /data</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查 Docker 存储</span></span><br><span class="line">docker system df</span><br></pre></td></tr></table></figure><ol start="3"><li>服务问题：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查服务状态</span></span><br><span class="line">cd /data/harbor</span><br><span class="line">docker-compose ps</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看服务日志</span></span><br><span class="line">docker-compose logs</span><br></pre></td></tr></table></figure><h2 id="性能优化-1"><a href="#性能优化-1" class="headerlink" title="性能优化"></a>性能优化</h2><ol><li>系统优化：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">调整系统限制</span></span><br><span class="line">cat &gt;&gt; /etc/security/limits.conf &lt;&lt; EOF</span><br><span class="line">* soft nofile 65535</span><br><span class="line">* hard nofile 65535</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">调整内核参数</span></span><br><span class="line">cat &gt;&gt; /etc/sysctl.conf &lt;&lt; EOF</span><br><span class="line">net.ipv4.ip_local_port_range = 1024 65000</span><br><span class="line">net.core.somaxconn = 32768</span><br><span class="line">fs.file-max = 1000000</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">sysctl -p</span><br></pre></td></tr></table></figure><ol start="2"><li>Docker 优化：</li></ol><ul><li>配置合适的日志轮转策略</li><li>使用高性能存储</li><li>定期清理未使用的镜像和容器</li></ul><h2 id="注意事项-3"><a href="#注意事项-3" class="headerlink" title="注意事项"></a>注意事项</h2><ol><li><p>安全建议：</p><ul><li>及时更新系统和组件</li><li>定期轮换密码和证书</li><li>限制访问权限</li><li>配置防火墙规则</li></ul></li><li><p>维护建议：</p><ul><li>定期备份数据</li><li>监控系统资源</li><li>及时清理垃圾数据</li><li>保持日志分析</li></ul></li><li><p>高可用建议：</p><ul><li>配置负载均衡</li><li>实现数据备份</li><li>监控告警配置</li><li>故障恢复演练</li></ul></li></ol><hr><h1 id="Kubernetes-集群环境部署"><a href="#Kubernetes-集群环境部署" class="headerlink" title="Kubernetes 集群环境部署"></a>Kubernetes 集群环境部署</h1><h2 id="环境准备-3"><a href="#环境准备-3" class="headerlink" title="环境准备"></a>环境准备</h2><h3 id="主机配置-1"><a href="#主机配置-1" class="headerlink" title="主机配置"></a>主机配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置主机名</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Master 节点</span></span><br><span class="line">hostnamectl set-hostname master1.k8s.com</span><br><span class="line">hostnamectl set-hostname master2.k8s.com</span><br><span class="line">hostnamectl set-hostname master3.k8s.com</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Worker 节点</span></span><br><span class="line">hostnamectl set-hostname worker1.k8s.com</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置 DNS 解析</span></span><br><span class="line">cat &gt;&gt; /etc/hosts &lt;&lt; EOF</span><br><span class="line">192.168.171.136 etcd1</span><br><span class="line">192.168.171.50  harbor harbor.k8s.com</span><br><span class="line">192.168.171.136 master1 master1.k8s.com</span><br><span class="line">192.168.171.137 master2 master2.k8s.com</span><br><span class="line">192.168.171.138 master3 master3.k8s.com</span><br><span class="line">192.168.171.139 worker1 worker1.k8s.com</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置免密登录</span></span><br><span class="line">ssh-keygen -t rsa -b 2048 -N &quot;&quot; -f ~/.ssh/id_rsa</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">分发公钥</span></span><br><span class="line">for host in harbor etcd1 master&#123;1..3&#125; worker1; do</span><br><span class="line">    sshpass -p &#x27;your_password&#x27; ssh-copy-id -o StrictHostKeyChecking=no root@$&#123;host&#125;</span><br><span class="line">done</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">分发hosts文件</span></span><br><span class="line">for host in master&#123;2..3&#125; worker1; do</span><br><span class="line">    scp /etc/hosts $&#123;host&#125;:/etc/</span><br><span class="line">done</span><br></pre></td></tr></table></figure><h3 id="系统配置"><a href="#系统配置" class="headerlink" title="系统配置"></a>系统配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在所有节点上执行</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">关闭 swap</span></span><br><span class="line">swapoff -a</span><br><span class="line">sed -i &#x27;/swap/d&#x27; /etc/fstab</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">加载内核模块</span></span><br><span class="line">cat &gt; /etc/modules-load.d/k8s.conf &lt;&lt; EOF</span><br><span class="line">overlay</span><br><span class="line">br_netfilter</span><br><span class="line">ip_vs</span><br><span class="line">ip_vs_rr</span><br><span class="line">ip_vs_wrr</span><br><span class="line">ip_vs_sh</span><br><span class="line">nf_conntrack</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">加载模块</span></span><br><span class="line">modprobe overlay</span><br><span class="line">modprobe br_netfilter</span><br><span class="line">modprobe ip_vs</span><br><span class="line">modprobe ip_vs_rr</span><br><span class="line">modprobe ip_vs_wrr</span><br><span class="line">modprobe ip_vs_sh</span><br><span class="line">modprobe nf_conntrack</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">更新内核设置</span></span><br><span class="line">cat &gt; /etc/sysctl.d/k8s.conf &lt;&lt; EOF</span><br><span class="line">net.bridge.bridge-nf-call-iptables  = 1</span><br><span class="line">net.bridge.bridge-nf-call-ip6tables = 1</span><br><span class="line">net.ipv4.ip_forward                 = 1</span><br><span class="line">vm.swappiness                       = 0</span><br><span class="line">fs.file-max                         = 1000000</span><br><span class="line">net.ipv4.ip_local_port_range       = 1024 65000</span><br><span class="line">net.ipv4.tcp_tw_reuse              = 1</span><br><span class="line">net.ipv4.tcp_fin_timeout           = 30</span><br><span class="line">net.core.somaxconn                 = 32768</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">sysctl --system</span><br></pre></td></tr></table></figure><h2 id="组件安装-1"><a href="#组件安装-1" class="headerlink" title="组件安装"></a>组件安装</h2><h3 id="容器运行时"><a href="#容器运行时" class="headerlink" title="容器运行时"></a>容器运行时</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装 containerd</span></span><br><span class="line">export CONTAINERD_VERSION=&quot;1.7.6&quot;</span><br><span class="line">wget https://github.com/containerd/containerd/releases/download/v$&#123;CONTAINERD_VERSION&#125;/containerd-$&#123;CONTAINERD_VERSION&#125;-linux-amd64.tar.gz</span><br><span class="line">tar Cxzvf /usr/local containerd-$&#123;CONTAINERD_VERSION&#125;-linux-amd64.tar.gz</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置 containerd 服务</span></span><br><span class="line">wget https://raw.githubusercontent.com/containerd/containerd/main/containerd.service -O /usr/local/lib/systemd/system/containerd.service</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成默认配置</span></span><br><span class="line">mkdir -p /etc/containerd</span><br><span class="line">containerd config default &gt; /etc/containerd/config.toml</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改配置</span></span><br><span class="line">sed -i &#x27;s|/var/lib/containerd|/data/containerd|g&#x27; /etc/containerd/config.toml</span><br><span class="line">sed -i &#x27;s|k8s.gcr.io/pause:3.6|registry.aliyuncs.com/google_containers/pause:3.9|g&#x27; /etc/containerd/config.toml</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加镜像仓库配置</span></span><br><span class="line">cat &gt;&gt; /etc/containerd/config.toml &lt;&lt; EOF</span><br><span class="line">      [plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.mirrors.&quot;docker.io&quot;]</span><br><span class="line">        endpoint = [&quot;https://docker.mirrors.ustc.edu.cn&quot;,&quot;http://hub-mirror.c.163.com&quot;]</span><br><span class="line">      [plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.mirrors.&quot;gcr.io&quot;]</span><br><span class="line">        endpoint = [&quot;https://gcr.mirrors.ustc.edu.cn&quot;]</span><br><span class="line">      [plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.mirrors.&quot;k8s.gcr.io&quot;]</span><br><span class="line">        endpoint = [&quot;https://gcr.mirrors.ustc.edu.cn/google-containers/&quot;]</span><br><span class="line">      [plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.mirrors.&quot;quay.io&quot;]</span><br><span class="line">        endpoint = [&quot;https://quay.mirrors.ustc.edu.cn&quot;]</span><br><span class="line">      [plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.mirrors.&quot;harbor.k8s.com&quot;]</span><br><span class="line">        endpoint = [&quot;https://harbor.k8s.com&quot;]</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动服务</span></span><br><span class="line">systemctl daemon-reload</span><br><span class="line">systemctl enable --now containerd</span><br></pre></td></tr></table></figure><h3 id="安装-CNI-插件"><a href="#安装-CNI-插件" class="headerlink" title="安装 CNI 插件"></a>安装 CNI 插件</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">下载并安装 CNI 插件</span></span><br><span class="line">CNI_VERSION=&quot;v1.2.0&quot;</span><br><span class="line">wget https://github.com/containernetworking/plugins/releases/download/$&#123;CNI_VERSION&#125;/cni-plugins-linux-amd64-$&#123;CNI_VERSION&#125;.tgz</span><br><span class="line">mkdir -p /opt/cni/bin</span><br><span class="line">tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-$&#123;CNI_VERSION&#125;.tgz</span><br></pre></td></tr></table></figure><h3 id="安装-nerdctl"><a href="#安装-nerdctl" class="headerlink" title="安装 nerdctl"></a>安装 nerdctl</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">下载并安装 nerdctl</span></span><br><span class="line">NERDCTL_VERSION=&quot;1.6.2&quot;</span><br><span class="line">wget https://github.com/containerd/nerdctl/releases/download/v$&#123;NERDCTL_VERSION&#125;/nerdctl-full-$&#123;NERDCTL_VERSION&#125;-linux-amd64.tar.gz</span><br><span class="line">tar Cxzvf /usr/local nerdctl-full-$&#123;NERDCTL_VERSION&#125;-linux-amd64.tar.gz</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置别名</span></span><br><span class="line">cat &gt;&gt; /etc/profile &lt;&lt; EOF</span><br><span class="line">alias docker=&#x27;nerdctl --namespace k8s.io&#x27;</span><br><span class="line">alias docker-compose=&#x27;nerdctl compose&#x27;</span><br><span class="line">alias crictl=&#x27;crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock&#x27;</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">source /etc/profile</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置 nerdctl</span></span><br><span class="line">mkdir -p /etc/nerdctl</span><br><span class="line">cat &gt; /etc/nerdctl/nerdctl.toml &lt;&lt; EOF</span><br><span class="line">namespace = &quot;k8s.io&quot;</span><br><span class="line">insecure_registry = true</span><br><span class="line">cni_path = &quot;/opt/cni/bin/&quot;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h3 id="安装-Kubernetes-组件"><a href="#安装-Kubernetes-组件" class="headerlink" title="安装 Kubernetes 组件"></a>安装 Kubernetes 组件</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加 Kubernetes 软件源</span></span><br><span class="line">curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -</span><br><span class="line">cat &gt; /etc/apt/sources.list.d/kubernetes.list &lt;&lt; EOF</span><br><span class="line">deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装指定版本</span></span><br><span class="line">export KUBE_VERSION=&quot;1.27.8&quot;</span><br><span class="line">apt update</span><br><span class="line">apt install -y kubelet=$&#123;KUBE_VERSION&#125;-00 kubeadm=$&#123;KUBE_VERSION&#125;-00 kubectl=$&#123;KUBE_VERSION&#125;-00</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">锁定版本</span></span><br><span class="line">apt-mark hold kubelet kubeadm kubectl</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启用自动补全</span></span><br><span class="line">apt install -y bash-completion</span><br><span class="line">echo &#x27;source &lt;(kubectl completion bash)&#x27; &gt;&gt; ~/.bashrc</span><br><span class="line">source ~/.bashrc</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">预拉取镜像</span></span><br><span class="line">kubeadm config images pull --kubernetes-version=v$&#123;KUBE_VERSION&#125; \</span><br><span class="line">    --image-repository=&#x27;registry.aliyuncs.com/google_containers&#x27;</span><br></pre></td></tr></table></figure><h2 id="证书配置"><a href="#证书配置" class="headerlink" title="证书配置"></a>证书配置</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建证书目录</span></span><br><span class="line">mkdir -p /etc/kubernetes/pki/etcd</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">复制 ETCD 证书</span></span><br><span class="line">scp etcd1:/etc/etcd/ssl/etcd-ca.pem /etc/kubernetes/pki/etcd/</span><br><span class="line">scp etcd1:/etc/etcd/ssl/client.pem /etc/kubernetes/pki/apiserver-etcd-client.pem</span><br><span class="line">scp etcd1:/etc/etcd/ssl/client-key.pem /etc/kubernetes/pki/apiserver-etcd-client-key.pem</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">复制 Harbor 证书</span></span><br><span class="line">mkdir -p /etc/tls/harbor/</span><br><span class="line">scp -r harbor:/etc/docker/certs.d/harbor.k8s.com /etc/tls/harbor/</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">更新系统证书</span></span><br><span class="line">cp /etc/tls/harbor/harbor.k8s.com/ca.crt /usr/local/share/ca-certificates/</span><br><span class="line">cp /etc/tls/harbor/harbor.k8s.com/harbor.k8s.com.cert /usr/local/share/ca-certificates/</span><br><span class="line">update-ca-certificates</span><br></pre></td></tr></table></figure><h2 id="系统优化-1"><a href="#系统优化-1" class="headerlink" title="系统优化"></a>系统优化</h2><h3 id="性能调优"><a href="#性能调优" class="headerlink" title="性能调优"></a>性能调优</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">调整系统限制</span></span><br><span class="line">cat &gt;&gt; /etc/security/limits.conf &lt;&lt; EOF</span><br><span class="line">* soft nofile 65536</span><br><span class="line">* hard nofile 65536</span><br><span class="line">* soft nproc 65536</span><br><span class="line">* hard nproc 65536</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">调整内核参数</span></span><br><span class="line">cat &gt;&gt; /etc/sysctl.conf &lt;&lt; EOF</span><br><span class="line">net.ipv4.tcp_max_syn_backlog = 8192</span><br><span class="line">net.core.somaxconn = 32768</span><br><span class="line">net.ipv4.tcp_timestamps = 1</span><br><span class="line">net.ipv4.tcp_fin_timeout = 30</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">sysctl -p</span><br></pre></td></tr></table></figure><h3 id="安全加固"><a href="#安全加固" class="headerlink" title="安全加固"></a>安全加固</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">禁用不必要的服务</span></span><br><span class="line">systemctl stop apparmor</span><br><span class="line">systemctl disable apparmor</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置防火墙规则</span></span><br><span class="line">ufw allow 6443/tcp  # Kubernetes API</span><br><span class="line">ufw allow 2379/tcp  # etcd client API</span><br><span class="line">ufw allow 2380/tcp  # etcd peer API</span><br><span class="line">ufw allow 10250/tcp # Kubelet API</span><br><span class="line">ufw allow 10251/tcp # kube-scheduler</span><br><span class="line">ufw allow 10252/tcp # kube-controller-manager</span><br></pre></td></tr></table></figure><h2 id="验证部署-1"><a href="#验证部署-1" class="headerlink" title="验证部署"></a>验证部署</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证模块加载</span></span><br><span class="line">lsmod | grep -e br_netfilter -e overlay -e ip_vs</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证端口</span></span><br><span class="line">netstat -ntlp | grep -e containerd -e kubelet</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证镜像</span></span><br><span class="line">crictl images</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证 Kubernetes 组件</span></span><br><span class="line">systemctl status kubelet</span><br><span class="line">kubectl version --client</span><br><span class="line">kubeadm version</span><br></pre></td></tr></table></figure><h2 id="注意事项-4"><a href="#注意事项-4" class="headerlink" title="注意事项"></a>注意事项</h2><ol><li><p>网络要求：</p><ul><li>节点间网络互通</li><li>可访问外网（用于下载组件）</li><li>防火墙开放必要端口</li></ul></li><li><p>安全建议：</p><ul><li>及时更新系统和组件</li><li>使用最新的稳定版本</li><li>配置适当的安全策略</li></ul></li><li><p>维护建议：</p><ul><li>定期检查系统资源</li><li>监控关键组件状态</li><li>保持日志分析和审计</li></ul></li></ol><hr><h1 id="Kubernetes-集群部署"><a href="#Kubernetes-集群部署" class="headerlink" title="Kubernetes 集群部署"></a>Kubernetes 集群部署</h1><h2 id="初始化配置"><a href="#初始化配置" class="headerlink" title="初始化配置"></a>初始化配置</h2><h3 id="创建集群配置文件"><a href="#创建集群配置文件" class="headerlink" title="创建集群配置文件"></a>创建集群配置文件</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在 master1 节点上执行</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成默认配置</span></span><br><span class="line">kubeadm config print init-defaults &gt; kubeadm-init.yaml</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改配置文件</span></span><br><span class="line">cat &gt; kubeadm-init.yaml &lt;&lt; EOF</span><br><span class="line">apiVersion: kubeadm.k8s.io/v1beta3</span><br><span class="line">kind: InitConfiguration</span><br><span class="line">localAPIEndpoint:</span><br><span class="line">  advertiseAddress: 192.168.171.136</span><br><span class="line">  bindPort: 6443</span><br><span class="line">nodeRegistration:</span><br><span class="line">  criSocket: unix:///var/run/containerd/containerd.sock</span><br><span class="line">  taints:</span><br><span class="line">    - effect: NoSchedule</span><br><span class="line">      key: node-role.kubernetes.io/control-plane</span><br><span class="line">---</span><br><span class="line">apiVersion: kubeadm.k8s.io/v1beta3</span><br><span class="line">kind: ClusterConfiguration</span><br><span class="line">certificatesDir: /etc/kubernetes/pki</span><br><span class="line">clusterName: kubernetes</span><br><span class="line">controllerManager: &#123;&#125;</span><br><span class="line">dns:</span><br><span class="line">  type: CoreDNS</span><br><span class="line">etcd:</span><br><span class="line">  external:</span><br><span class="line">    endpoints:</span><br><span class="line">      - https://192.168.171.136:2379</span><br><span class="line">      - https://192.168.171.137:2379</span><br><span class="line">      - https://192.168.171.138:2379</span><br><span class="line">    caFile: /etc/kubernetes/pki/etcd/etcd-ca.pem</span><br><span class="line">    certFile: /etc/kubernetes/pki/apiserver-etcd-client.pem</span><br><span class="line">    keyFile: /etc/kubernetes/pki/apiserver-etcd-client-key.pem</span><br><span class="line">kubernetesVersion: 1.27.8</span><br><span class="line">imageRepository: registry.aliyuncs.com/google_containers</span><br><span class="line">networking:</span><br><span class="line">  serviceSubnet: 10.96.0.0/12</span><br><span class="line">  podSubnet: 10.244.0.0/16</span><br><span class="line">---</span><br><span class="line">apiVersion: kubeproxy.config.k8s.io/v1alpha1</span><br><span class="line">kind: KubeProxyConfiguration</span><br><span class="line">mode: ipvs</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h2 id="集群初始化"><a href="#集群初始化" class="headerlink" title="集群初始化"></a>集群初始化</h2><h3 id="初始化主节点"><a href="#初始化主节点" class="headerlink" title="初始化主节点"></a>初始化主节点</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在 master1 节点上执行</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">初始化集群</span></span><br><span class="line">kubeadm init --config=kubeadm-init.yaml --upload-certs</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置 kubectl</span></span><br><span class="line">mkdir -p $HOME/.kube</span><br><span class="line">cp -i /etc/kubernetes/admin.conf $HOME/.kube/config</span><br><span class="line">chown $(id -u):$(id -g) $HOME/.kube/config</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置环境变量</span></span><br><span class="line">echo &quot;export KUBECONFIG=/etc/kubernetes/admin.conf&quot; &gt;&gt; /etc/profile</span><br><span class="line">source /etc/profile</span><br></pre></td></tr></table></figure><h3 id="添加节点"><a href="#添加节点" class="headerlink" title="添加节点"></a>添加节点</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在其他 master 节点上执行</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">加入控制平面节点</span></span><br><span class="line">kubeadm join 192.168.171.136:6443 --token &lt;token&gt; \</span><br><span class="line">    --discovery-token-ca-cert-hash sha256:&lt;hash&gt; \</span><br><span class="line">    --control-plane --certificate-key &lt;key&gt; \</span><br><span class="line">    --cri-socket=unix:///var/run/containerd/containerd.sock</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在 worker 节点上执行</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">加入工作节点</span></span><br><span class="line">kubeadm join 192.168.171.136:6443 --token &lt;token&gt; \</span><br><span class="line">    --discovery-token-ca-cert-hash sha256:&lt;hash&gt; \</span><br><span class="line">    --cri-socket=unix:///var/run/containerd/containerd.sock</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置环境变量</span></span><br><span class="line">echo &quot;export KUBECONFIG=/etc/kubernetes/admin.conf&quot; &gt;&gt; /etc/profile</span><br><span class="line">source /etc/profile</span><br></pre></td></tr></table></figure><h3 id="节点标签管理"><a href="#节点标签管理" class="headerlink" title="节点标签管理"></a>节点标签管理</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加 worker 标签</span></span><br><span class="line">kubectl label nodes worker1.k8s.com node-role.kubernetes.io/worker=</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加污点</span></span><br><span class="line">kubectl taint nodes master1.k8s.com node-role.kubernetes.io/control-plane=:NoSchedule</span><br><span class="line">kubectl taint nodes master2.k8s.com node-role.kubernetes.io/control-plane=:NoSchedule</span><br><span class="line">kubectl taint nodes master3.k8s.com node-role.kubernetes.io/control-plane=:NoSchedule</span><br></pre></td></tr></table></figure><h2 id="网络配置"><a href="#网络配置" class="headerlink" title="网络配置"></a>网络配置</h2><h3 id="安装-Calico"><a href="#安装-Calico" class="headerlink" title="安装 Calico"></a>安装 Calico</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加 Helm 仓库</span></span><br><span class="line">helm repo add projectcalico https://docs.tigera.io/calico/charts</span><br><span class="line">helm repo update</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建配置文件</span></span><br><span class="line">cat &gt; calico-values.yaml &lt;&lt; EOF</span><br><span class="line">installation:</span><br><span class="line">  cni:</span><br><span class="line">    type: Calico</span><br><span class="line">  ipPools:</span><br><span class="line">  - cidr: 10.244.0.0/16</span><br><span class="line">    encapsulation: IPIP</span><br><span class="line">    natOutgoing: true</span><br><span class="line">    nodeSelector: all()</span><br><span class="line">  registry: docker.io</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装 Calico</span></span><br><span class="line">helm install calico projectcalico/tigera-operator -f calico-values.yaml</span><br></pre></td></tr></table></figure><h3 id="CoreDNS-配置"><a href="#CoreDNS-配置" class="headerlink" title="CoreDNS 配置"></a>CoreDNS 配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置 CoreDNS</span></span><br><span class="line">kubectl -n kube-system get cm coredns -o yaml &gt; coredns-cm.yaml</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改配置</span></span><br><span class="line">cat &gt; coredns-cm.yaml &lt;&lt; EOF</span><br><span class="line">apiVersion: v1</span><br><span class="line">data:</span><br><span class="line">  Corefile: |</span><br><span class="line">    .:53 &#123;</span><br><span class="line">        errors</span><br><span class="line">        health &#123;</span><br><span class="line">           lameduck 5s</span><br><span class="line">        &#125;</span><br><span class="line">        hosts &#123;</span><br><span class="line">          192.168.171.50 harbor.k8s.com</span><br><span class="line">          fallthrough</span><br><span class="line">        &#125;</span><br><span class="line">        ready</span><br><span class="line">        kubernetes cluster.local in-addr.arpa ip6.arpa &#123;</span><br><span class="line">           pods insecure</span><br><span class="line">           fallthrough in-addr.arpa ip6.arpa</span><br><span class="line">           ttl 30</span><br><span class="line">        &#125;</span><br><span class="line">        prometheus :9153</span><br><span class="line">        forward . /etc/resolv.conf &#123;</span><br><span class="line">           max_concurrent 1000</span><br><span class="line">        &#125;</span><br><span class="line">        cache 30</span><br><span class="line">        loop</span><br><span class="line">        reload</span><br><span class="line">        loadbalance</span><br><span class="line">    &#125;</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">应用配置</span></span><br><span class="line">kubectl apply -f coredns-cm.yaml</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重启 CoreDNS</span></span><br><span class="line">kubectl -n kube-system delete pod -l k8s-app=kube-dns</span><br></pre></td></tr></table></figure><h2 id="组件配置"><a href="#组件配置" class="headerlink" title="组件配置"></a>组件配置</h2><h3 id="暴露组件端口"><a href="#暴露组件端口" class="headerlink" title="暴露组件端口"></a>暴露组件端口</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在所有 master 节点上执行</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改 kube-scheduler 配置</span></span><br><span class="line">sed -i &#x27;s/- --bind-address=127.0.0.1/- --bind-address=0.0.0.0/&#x27; /etc/kubernetes/manifests/kube-scheduler.yaml</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改 kube-controller-manager 配置</span></span><br><span class="line">sed -i &#x27;s/- --bind-address=127.0.0.1/- --bind-address=0.0.0.0/&#x27; /etc/kubernetes/manifests/kube-controller-manager.yaml</span><br></pre></td></tr></table></figure><h2 id="集群验证-1"><a href="#集群验证-1" class="headerlink" title="集群验证"></a>集群验证</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证集群状态</span></span><br><span class="line">kubectl get nodes</span><br><span class="line">kubectl get pods -A</span><br><span class="line">kubectl cluster-info</span><br><span class="line">kubectl get componentstatuses</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证网络</span></span><br><span class="line">kubectl run test-nginx --image=nginx</span><br><span class="line">kubectl expose pod test-nginx --port=80 --type=NodePort</span><br><span class="line">curl http://&lt;node-ip&gt;:&lt;node-port&gt;</span><br></pre></td></tr></table></figure><h2 id="维护操作"><a href="#维护操作" class="headerlink" title="维护操作"></a>维护操作</h2><h3 id="证书更新"><a href="#证书更新" class="headerlink" title="证书更新"></a>证书更新</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看证书过期时间</span></span><br><span class="line">kubeadm certs check-expiration</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">更新证书</span></span><br><span class="line">kubeadm certs renew all</span><br></pre></td></tr></table></figure><h3 id="集群升级"><a href="#集群升级" class="headerlink" title="集群升级"></a>集群升级</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">升级 kubeadm</span></span><br><span class="line">apt-mark unhold kubeadm</span><br><span class="line">apt-get update</span><br><span class="line">apt-get install -y kubeadm=&lt;version&gt;</span><br><span class="line">apt-mark hold kubeadm</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">升级控制平面</span></span><br><span class="line">kubeadm upgrade plan</span><br><span class="line">kubeadm upgrade apply v&lt;version&gt;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">升级 kubelet 和 kubectl</span></span><br><span class="line">apt-mark unhold kubelet kubectl</span><br><span class="line">apt-get install -y kubelet=&lt;version&gt; kubectl=&lt;version&gt;</span><br><span class="line">apt-mark hold kubelet kubectl</span><br><span class="line">systemctl restart kubelet</span><br></pre></td></tr></table></figure><h2 id="故障处理"><a href="#故障处理" class="headerlink" title="故障处理"></a>故障处理</h2><h3 id="重置节点"><a href="#重置节点" class="headerlink" title="重置节点"></a>重置节点</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">清理节点</span></span><br><span class="line">kubeadm reset</span><br><span class="line">iptables -F &amp;&amp; iptables -X</span><br><span class="line">iptables -t nat -F &amp;&amp; iptables -t nat -X</span><br><span class="line">iptables -t mangle -F &amp;&amp; iptables -t mangle -X</span><br><span class="line">ipvsadm --clear</span><br><span class="line">rm -rf /etc/kubernetes/ /var/lib/kubelet/ /var/lib/etcd/</span><br></pre></td></tr></table></figure><h3 id="常见问题排查-1"><a href="#常见问题排查-1" class="headerlink" title="常见问题排查"></a>常见问题排查</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看组件日志</span></span><br><span class="line">journalctl -xeu kubelet</span><br><span class="line">kubectl logs -n kube-system &lt;pod-name&gt;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查网络</span></span><br><span class="line">kubectl exec -it &lt;pod-name&gt; -- ping &lt;service-name&gt;</span><br><span class="line">kubectl get endpoints &lt;service-name&gt;</span><br></pre></td></tr></table></figure><h2 id="注意事项-5"><a href="#注意事项-5" class="headerlink" title="注意事项"></a>注意事项</h2><ol><li><p>高可用配置：</p><ul><li>至少部署三个 master 节点</li><li>使用负载均衡器</li><li>配置外部 etcd 集群</li></ul></li><li><p>安全建议：</p><ul><li>及时更新组件版本</li><li>配置网络策略</li><li>使用 RBAC 控制访问</li><li>定期备份 etcd 数据</li></ul></li><li><p>性能优化：</p><ul><li>合理配置资源限制</li><li>优化网络配置</li><li>监控系统性能</li></ul></li><li><p>运维建议：</p><ul><li>实施监控告警</li><li>定期进行备份</li><li>制定故障恢复预案</li><li>保持文档更新</li></ul></li></ol><hr><h1 id="NFS-StorageClass-部署"><a href="#NFS-StorageClass-部署" class="headerlink" title="NFS StorageClass 部署"></a>NFS StorageClass 部署</h1><h2 id="存储服务器配置"><a href="#存储服务器配置" class="headerlink" title="存储服务器配置"></a>存储服务器配置</h2><h3 id="安装-NFS-服务"><a href="#安装-NFS-服务" class="headerlink" title="安装 NFS 服务"></a>安装 NFS 服务</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装 NFS 服务器</span></span><br><span class="line">apt-get update</span><br><span class="line">apt-get install -y nfs-kernel-server</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建共享目录</span></span><br><span class="line">mkdir -p /data/ifs/kubernetes</span><br><span class="line">chown -R nobody:nogroup /data/ifs/kubernetes</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置共享权限</span></span><br><span class="line">cat &gt;&gt; /etc/exports &lt;&lt; EOF</span><br><span class="line">/data/ifs/kubernetes 192.168.171.0/24(no_root_squash,rw,sync,no_subtree_check)</span><br><span class="line">EOF</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动服务</span></span><br><span class="line">systemctl enable --now nfs-kernel-server</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证配置</span></span><br><span class="line">exportfs -av</span><br></pre></td></tr></table></figure><h3 id="配置防火墙"><a href="#配置防火墙" class="headerlink" title="配置防火墙"></a>配置防火墙</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">允许 NFS 相关端口</span></span><br><span class="line">ufw allow 2049/tcp  # NFS</span><br><span class="line">ufw allow 111/tcp   # portmapper</span><br><span class="line">ufw allow 111/udp</span><br><span class="line">ufw allow 32765:32768/tcp  # NFS 动态端口</span><br><span class="line">ufw allow 32765:32768/udp</span><br></pre></td></tr></table></figure><h2 id="客户端配置-1"><a href="#客户端配置-1" class="headerlink" title="客户端配置"></a>客户端配置</h2><h3 id="安装-NFS-客户端"><a href="#安装-NFS-客户端" class="headerlink" title="安装 NFS 客户端"></a>安装 NFS 客户端</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在所有 Kubernetes 节点上执行</span></span><br><span class="line">apt-get update</span><br><span class="line">apt-get install -y nfs-common</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置 NFS 服务器解析</span></span><br><span class="line">echo &quot;192.168.171.140 nfs.k8s.com&quot; &gt;&gt; /etc/hosts</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证 NFS 挂载</span></span><br><span class="line">showmount -e nfs.k8s.com</span><br></pre></td></tr></table></figure><h2 id="StorageClass-部署"><a href="#StorageClass-部署" class="headerlink" title="StorageClass 部署"></a>StorageClass 部署</h2><h3 id="安装-NFS-Provisioner"><a href="#安装-NFS-Provisioner" class="headerlink" title="安装 NFS Provisioner"></a>安装 NFS Provisioner</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建命名空间</span></span><br><span class="line">kubectl create namespace nfs-provisioner</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建 ServiceAccount</span></span><br><span class="line">cat &gt; rbac.yaml &lt;&lt; EOF</span><br><span class="line">apiVersion: v1</span><br><span class="line">kind: ServiceAccount</span><br><span class="line">metadata:</span><br><span class="line">  name: nfs-client-provisioner</span><br><span class="line">  namespace: nfs-provisioner</span><br><span class="line">---</span><br><span class="line">kind: ClusterRole</span><br><span class="line">apiVersion: rbac.authorization.k8s.io/v1</span><br><span class="line">metadata:</span><br><span class="line">  name: nfs-client-provisioner-runner</span><br><span class="line">rules:</span><br><span class="line">  - apiGroups: [&quot;&quot;]</span><br><span class="line">    resources: [&quot;nodes&quot;]</span><br><span class="line">    verbs: [&quot;get&quot;, &quot;list&quot;, &quot;watch&quot;]</span><br><span class="line">  - apiGroups: [&quot;&quot;]</span><br><span class="line">    resources: [&quot;persistentvolumes&quot;]</span><br><span class="line">    verbs: [&quot;get&quot;, &quot;list&quot;, &quot;watch&quot;, &quot;create&quot;, &quot;delete&quot;]</span><br><span class="line">  - apiGroups: [&quot;&quot;]</span><br><span class="line">    resources: [&quot;persistentvolumeclaims&quot;]</span><br><span class="line">    verbs: [&quot;get&quot;, &quot;list&quot;, &quot;watch&quot;, &quot;update&quot;]</span><br><span class="line">  - apiGroups: [&quot;storage.k8s.io&quot;]</span><br><span class="line">    resources: [&quot;storageclasses&quot;]</span><br><span class="line">    verbs: [&quot;get&quot;, &quot;list&quot;, &quot;watch&quot;]</span><br><span class="line">  - apiGroups: [&quot;&quot;]</span><br><span class="line">    resources: [&quot;events&quot;]</span><br><span class="line">    verbs: [&quot;create&quot;, &quot;update&quot;, &quot;patch&quot;]</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">kubectl apply -f rbac.yaml</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建 Deployment</span></span><br><span class="line">cat &gt; deployment.yaml &lt;&lt; EOF</span><br><span class="line">apiVersion: apps/v1</span><br><span class="line">kind: Deployment</span><br><span class="line">metadata:</span><br><span class="line">  name: nfs-client-provisioner</span><br><span class="line">  namespace: nfs-provisioner</span><br><span class="line">spec:</span><br><span class="line">  replicas: 1</span><br><span class="line">  strategy:</span><br><span class="line">    type: Recreate</span><br><span class="line">  selector:</span><br><span class="line">    matchLabels:</span><br><span class="line">      app: nfs-client-provisioner</span><br><span class="line">  template:</span><br><span class="line">    metadata:</span><br><span class="line">      labels:</span><br><span class="line">        app: nfs-client-provisioner</span><br><span class="line">    spec:</span><br><span class="line">      serviceAccountName: nfs-client-provisioner</span><br><span class="line">      containers:</span><br><span class="line">        - name: nfs-client-provisioner</span><br><span class="line">          image: registry.aliyuncs.com/google_containers/sig-storage/nfs-subdir-external-provisioner:v4.0.2</span><br><span class="line">          volumeMounts:</span><br><span class="line">            - name: nfs-client-root</span><br><span class="line">              mountPath: /persistentvolumes</span><br><span class="line">          env:</span><br><span class="line">            - name: PROVISIONER_NAME</span><br><span class="line">              value: k8s-sigs.io/nfs-subdir-external-provisioner</span><br><span class="line">            - name: NFS_SERVER</span><br><span class="line">              value: nfs.k8s.com</span><br><span class="line">            - name: NFS_PATH</span><br><span class="line">              value: /data/ifs/kubernetes</span><br><span class="line">      volumes:</span><br><span class="line">        - name: nfs-client-root</span><br><span class="line">          nfs:</span><br><span class="line">            server: nfs.k8s.com</span><br><span class="line">            path: /data/ifs/kubernetes</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">kubectl apply -f deployment.yaml</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建 StorageClass</span></span><br><span class="line">cat &gt; storageclass.yaml &lt;&lt; EOF</span><br><span class="line">apiVersion: storage.k8s.io/v1</span><br><span class="line">kind: StorageClass</span><br><span class="line">metadata:</span><br><span class="line">  name: nfs-client</span><br><span class="line">  annotations:</span><br><span class="line">    storageclass.kubernetes.io/is-default-class: &quot;true&quot;</span><br><span class="line">provisioner: k8s-sigs.io/nfs-subdir-external-provisioner</span><br><span class="line">parameters:</span><br><span class="line">  archiveOnDelete: &quot;false&quot;</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">kubectl apply -f storageclass.yaml</span><br></pre></td></tr></table></figure><h3 id="验证部署-2"><a href="#验证部署-2" class="headerlink" title="验证部署"></a>验证部署</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建测试 PVC</span></span><br><span class="line">cat &gt; test-claim.yaml &lt;&lt; EOF</span><br><span class="line">apiVersion: v1</span><br><span class="line">kind: PersistentVolumeClaim</span><br><span class="line">metadata:</span><br><span class="line">  name: test-claim</span><br><span class="line">spec:</span><br><span class="line">  accessModes:</span><br><span class="line">    - ReadWriteMany</span><br><span class="line">  resources:</span><br><span class="line">    requests:</span><br><span class="line">      storage: 1Mi</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">kubectl apply -f test-claim.yaml</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建测试 Pod</span></span><br><span class="line">cat &gt; test-pod.yaml &lt;&lt; EOF</span><br><span class="line">apiVersion: v1</span><br><span class="line">kind: Pod</span><br><span class="line">metadata:</span><br><span class="line">  name: test-pod</span><br><span class="line">spec:</span><br><span class="line">  containers:</span><br><span class="line">    - name: test-pod</span><br><span class="line">      image: busybox</span><br><span class="line">      command:</span><br><span class="line">        - &quot;/bin/sh&quot;</span><br><span class="line">      args:</span><br><span class="line">        - &quot;-c&quot;</span><br><span class="line">        - &quot;touch /mnt/SUCCESS &amp;&amp; exit 0 || exit 1&quot;</span><br><span class="line">      volumeMounts:</span><br><span class="line">        - name: nfs-pvc</span><br><span class="line">          mountPath: &quot;/mnt&quot;</span><br><span class="line">  restartPolicy: &quot;Never&quot;</span><br><span class="line">  volumes:</span><br><span class="line">    - name: nfs-pvc</span><br><span class="line">      persistentVolumeClaim:</span><br><span class="line">        claimName: test-claim</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">kubectl apply -f test-pod.yaml</span><br></pre></td></tr></table></figure><h2 id="监控配置-1"><a href="#监控配置-1" class="headerlink" title="监控配置"></a>监控配置</h2><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建监控脚本</span></span><br><span class="line">cat &gt; /usr/local/bin/monitor-nfs.sh &lt;&lt; &#x27;EOF&#x27;</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查 NFS 服务状态</span></span><br><span class="line">check_nfs_service() &#123;</span><br><span class="line">    if ! systemctl is-active --quiet nfs-kernel-server; then</span><br><span class="line">        echo &quot;NFS service is not running&quot;</span><br><span class="line">        return 1</span><br><span class="line">    fi</span><br><span class="line">    return 0</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查存储空间</span></span><br><span class="line">check_storage() &#123;</span><br><span class="line">    local usage=$(df -h /data/ifs/kubernetes | awk &#x27;NR==2 &#123;print $5&#125;&#x27; | sed &#x27;s/%//&#x27;)</span><br><span class="line">    if [ $usage -gt 80 ]; then</span><br><span class="line">        echo &quot;Storage usage is above 80%&quot;</span><br><span class="line">        return 1</span><br><span class="line">    fi</span><br><span class="line">    return 0</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查 NFS 挂载点</span></span><br><span class="line">check_mounts() &#123;</span><br><span class="line">    if ! mountpoint -q /data/ifs/kubernetes; then</span><br><span class="line">        echo &quot;NFS directory is not mounted&quot;</span><br><span class="line">        return 1</span><br><span class="line">    fi</span><br><span class="line">    return 0</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">主检查逻辑</span></span><br><span class="line">main() &#123;</span><br><span class="line">    check_nfs_service || echo &quot;NFS service check failed&quot;</span><br><span class="line">    check_storage || echo &quot;Storage check failed&quot;</span><br><span class="line">    check_mounts || echo &quot;Mount check failed&quot;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">main</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">chmod +x /usr/local/bin/monitor-nfs.sh</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加到 crontab</span></span><br><span class="line">(crontab -l 2&gt;/dev/null; echo &quot;*/5 * * * * /usr/local/bin/monitor-nfs.sh &gt;&gt; /var/log/nfs-monitor.log 2&gt;&amp;1&quot;) | crontab -</span><br></pre></td></tr></table></figure><h2 id="注意事项-6"><a href="#注意事项-6" class="headerlink" title="注意事项"></a>注意事项</h2><ol><li><p>性能优化：</p><ul><li>使用 SSD 存储</li><li>调整 NFS 缓存参数</li><li>配置合适的网络带宽</li></ul></li><li><p>安全建议：</p><ul><li>限制 NFS 访问IP</li><li>配置防火墙规则</li><li>定期更新系统</li></ul></li><li><p>维护建议：</p><ul><li>定期备份数据</li><li>监控存储使用量</li><li>及时清理无用数据</li></ul></li><li><p>高可用建议：</p><ul><li>配置 NFS 服务器集群</li><li>使用网络存储备份</li><li>配置自动故障转移</li></ul></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt; 本文详细介绍如何使用二进制方式在 Debian 系统上搭建一个生产级别的高可用 Kubernetes 集群。&lt;/p&gt;</summary>
    
    
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/categories/Kubernetes/"/>
    
    
    <category term="Debian" scheme="https://freemankevin.uk/tags/Debian/"/>
    
    <category term="Harbor" scheme="https://freemankevin.uk/tags/Harbor/"/>
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/tags/Kubernetes/"/>
    
    <category term="ETCD" scheme="https://freemankevin.uk/tags/ETCD/"/>
    
    <category term="NFS" scheme="https://freemankevin.uk/tags/NFS/"/>
    
  </entry>
  
  <entry>
    <title>Maven 私有仓库使用规范</title>
    <link href="https://freemankevin.uk/2025/02/07/maven-nexus/"/>
    <id>https://freemankevin.uk/2025/02/07/maven-nexus/</id>
    <published>2025-02-07T08:17:25.000Z</published>
    <updated>2026-04-17T10:30:31.805Z</updated>
    
    <content type="html"><![CDATA[<p> Maven私有仓库(Nexus)是企业进行依赖管理的重要基础设施。然而在实际使用中,团队常常因配置混乱导致跨团队协作困难,依赖问题频发。比如本地构建或打包时出现异常,公有云仓库与私有仓库混用导致缓存失效,这些都增加了不必要的沟通与排查成本。为此,我们需要统一规范配置,明确依赖管理流程,包括拉取依赖、上传私有包等标准操作方式。通过规范化管理,不仅可以方便项目交接和新人上手,还能充分发挥私有仓库的缓存加速作用,提升团队整体开发效率。本文将详细介绍Maven私有仓库的最佳实践,帮助团队建立起高效的依赖管理体系。</p><span id="more"></span><h2 id="修改Maven配置"><a href="#修改Maven配置" class="headerlink" title="修改Maven配置"></a>修改Maven配置</h2><h3 id="修改settings配置"><a href="#修改settings配置" class="headerlink" title="修改settings配置"></a>修改settings配置</h3><p>私有仓库Nexus信息示例:</p><ul><li>Nexus服务地址: <code>http://nexus.your-company.com:8081/</code></li><li>开发者账号: <code>developer/your-password</code></li><li>Maven公共仓库地址: <code>http://nexus.your-company.com:8081/repository/maven-public/</code></li><li>Maven私有包-稳定版本-上传地址: <code>http://nexus.your-company.com:8081/repository/maven-releases/</code></li><li>Maven私有包-开发版本-上传地址: <code>http://nexus.your-company.com:8081/repository/maven-snapshots/</code></li></ul><p>需要修改settings.xml配置文件,使其完全通过企业内网Nexus访问依赖,而不是直接访问公网仓库。这样可以:</p><ol><li>首次使用时,Nexus会从公网拉取并缓存依赖</li><li>后续使用时直接从Nexus获取缓存的依赖,加快构建速度</li><li>统一管理团队使用的依赖版本</li></ol><p>settings.xml示例配置:</p><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">settings</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">mirrors</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mirror</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">id</span>&gt;</span>nexus<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">mirrorOf</span>&gt;</span>*<span class="tag">&lt;/<span class="name">mirrorOf</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">url</span>&gt;</span>http://nexus.your-company.com:8081/repository/maven-public/<span class="tag">&lt;/<span class="name">url</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">mirror</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">mirrors</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">servers</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">server</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">id</span>&gt;</span>maven-releases<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">username</span>&gt;</span>$&#123;NEXUS_USERNAME&#125;<span class="tag">&lt;/<span class="name">username</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">password</span>&gt;</span>$&#123;NEXUS_PASSWORD&#125;<span class="tag">&lt;/<span class="name">password</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">server</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">server</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">id</span>&gt;</span>maven-snapshots<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">username</span>&gt;</span>$&#123;NEXUS_USERNAME&#125;<span class="tag">&lt;/<span class="name">username</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">password</span>&gt;</span>$&#123;NEXUS_PASSWORD&#125;<span class="tag">&lt;/<span class="name">password</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">server</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">servers</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">settings</span>&gt;</span></span><br></pre></td></tr></table></figure><h4 id="公网包支持"><a href="#公网包支持" class="headerlink" title="公网包支持"></a>公网包支持</h4><p>如果在使用内网Maven公共仓库时无法拉取某些公网依赖包:</p><ol><li>可以联系Nexus管理员添加所需的公网仓库源</li><li>默认应该已配置了主流公共仓库(如Maven中央仓库、阿里云Maven仓库等)</li><li>如需添加其他冷门仓库源,请提供仓库地址给管理员统一配置</li></ol><h4 id="内网私有包支持"><a href="#内网私有包支持" class="headerlink" title="内网私有包支持"></a>内网私有包支持</h4><p>如果无法拉取内网私有包:</p><ol><li>优先联系包的开发团队,确认是否已上传到私有仓库</li><li>如未上传,请开发团队先完成上传</li></ol><p>上传私有包到releases仓库:</p><ol><li>通过Nexus Web UI上传</li><li>选择 <code>hosted</code> 类型的仓库才能上传成功</li></ol><h4 id="批量上传包到私库"><a href="#批量上传包到私库" class="headerlink" title="批量上传包到私库"></a>批量上传包到私库</h4><p>对于需要批量上传的场景:</p><ol><li>可以使用maven-deploy插件上传:</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">mvn deploy:deploy-file \</span><br><span class="line">    -Durl=http://nexus.your-company.com:8081/repository/maven-snapshots \</span><br><span class="line">    -DrepositoryId=snapshots \</span><br><span class="line">    -Dfile=your-artifact.jar \</span><br><span class="line">    -DgroupId=com.company \</span><br><span class="line">    -DartifactId=project \</span><br><span class="line">    -Dversion=1.0-SNAPSHOT \</span><br><span class="line">    -Dpackaging=jar</span><br></pre></td></tr></table></figure><ol start="2"><li>也可以使用批量上传工具,如阿里云云效的 <code>migrate-local-repo-tool.jar</code></li></ol><h3 id="修改父POM配置"><a href="#修改父POM配置" class="headerlink" title="修改父POM配置"></a>修改父POM配置</h3><p>在项目顶级pom.xml中配置仓库信息:</p><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">project</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">repositories</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">repository</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">id</span>&gt;</span>maven-public<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">name</span>&gt;</span>maven-public<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">url</span>&gt;</span>http://nexus.your-company.com:8081/repository/maven-public/<span class="tag">&lt;/<span class="name">url</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">releases</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">enabled</span>&gt;</span>true<span class="tag">&lt;/<span class="name">enabled</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">releases</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">snapshots</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">enabled</span>&gt;</span>true<span class="tag">&lt;/<span class="name">enabled</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">snapshots</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">repository</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">repositories</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">distributionManagement</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">repository</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">id</span>&gt;</span>maven-releases<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">name</span>&gt;</span>maven-releases<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">url</span>&gt;</span>http://nexus.your-company.com:8081/repository/maven-releases/<span class="tag">&lt;/<span class="name">url</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">repository</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">snapshotRepository</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">id</span>&gt;</span>maven-snapshots<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">name</span>&gt;</span>maven-snapshots<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">url</span>&gt;</span>http://nexus.your-company.com:8081/repository/maven-snapshots/<span class="tag">&lt;/<span class="name">url</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">snapshotRepository</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">distributionManagement</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="Nexus仓库说明"><a href="#Nexus仓库说明" class="headerlink" title="Nexus仓库说明"></a>Nexus仓库说明</h3><p>Nexus作为仓库管理工具的主要功能:</p><pre><code class="highlight mermaid">graph LR    A[用户] --&gt; |mvn install / package| B[maven]    B --&gt; C[nexus]    C --&gt; |查找依赖| D&#123;判断&#125;    D -- 存在 --&gt; E[直接返回给用户]    D -- 不存在 --&gt; F[找公网]    F --&gt; G[公共仓库]    G --&gt; H[maven中央仓库]    G -.-&gt; C    C -.-&gt; A</code></pre><h4 id="Maven公共仓库"><a href="#Maven公共仓库" class="headerlink" title="Maven公共仓库"></a>Maven公共仓库</h4><ul><li>用途:存储公共依赖包</li><li>特点:自动从公网仓库同步和缓存</li><li>应用:主要用于依赖解析和下载</li></ul><h4 id="Maven-Releases仓库"><a href="#Maven-Releases仓库" class="headerlink" title="Maven Releases仓库"></a>Maven Releases仓库</h4><ul><li>用途:存储稳定版本构件</li><li>特点:不可变性,版本唯一</li><li>应用:正式发布版本管理</li></ul><h4 id="Maven-Snapshots仓库"><a href="#Maven-Snapshots仓库" class="headerlink" title="Maven Snapshots仓库"></a>Maven Snapshots仓库</h4><ul><li>用途:存储开发版本构件</li><li>特点:可覆盖更新,版本号带-SNAPSHOT后缀</li><li>应用:开发阶段使用</li></ul><h4 id="使用建议"><a href="#使用建议" class="headerlink" title="使用建议"></a>使用建议</h4><ol><li>严格遵循版本命名规范</li><li>合理配置权限管理</li><li>正确配置pom.xml和settings.xml</li><li>确保网络环境正常访问</li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt; Maven私有仓库(Nexus)是企业进行依赖管理的重要基础设施。然而在实际使用中,团队常常因配置混乱导致跨团队协作困难,依赖问题频发。比如本地构建或打包时出现异常,公有云仓库与私有仓库混用导致缓存失效,这些都增加了不必要的沟通与排查成本。为此,我们需要统一规范配置,明确依赖管理流程,包括拉取依赖、上传私有包等标准操作方式。通过规范化管理,不仅可以方便项目交接和新人上手,还能充分发挥私有仓库的缓存加速作用,提升团队整体开发效率。本文将详细介绍Maven私有仓库的最佳实践,帮助团队建立起高效的依赖管理体系。&lt;/p&gt;</summary>
    
    
    
    <category term="Development" scheme="https://freemankevin.uk/categories/Development/"/>
    
    
    <category term="Nexus" scheme="https://freemankevin.uk/tags/Nexus/"/>
    
    <category term="Maven" scheme="https://freemankevin.uk/tags/Maven/"/>
    
    <category term="Aliyun" scheme="https://freemankevin.uk/tags/Aliyun/"/>
    
  </entry>
  
  <entry>
    <title>GitLab 配置优化与 CICD 集成指南</title>
    <link href="https://freemankevin.uk/2025/01/21/gitlab-cicd/"/>
    <id>https://freemankevin.uk/2025/01/21/gitlab-cicd/</id>
    <published>2025-01-21T09:32:25.000Z</published>
    <updated>2026-04-17T10:30:31.801Z</updated>
    
    <content type="html"><![CDATA[<p> 本文档旨在提供 GitLab 配置优化、集成最佳实践、安全加固、备份与恢复策略以及监控方法，帮助团队在使用 GitLab 进行源代码管理和持续集成&#x2F;持续交付（CICD）时提升性能、安全性及稳定性。</p><span id="more"></span><h2 id="GitLab-添加内网信任"><a href="#GitLab-添加内网信任" class="headerlink" title="GitLab 添加内网信任"></a>GitLab 添加内网信任</h2><h3 id="目的"><a href="#目的" class="headerlink" title="目的"></a>目的</h3><p>为 GitLab 配置内网信任，允许 GitLab 访问内网服务。</p><h3 id="操作步骤"><a href="#操作步骤" class="headerlink" title="操作步骤"></a>操作步骤</h3><ol><li>进入 GitLab 管理员界面。</li><li>进入设置页面，选择 <strong>网络</strong>。</li><li>进入 <strong>出站请求</strong>，勾选以下选项：<ul><li>允许来自 <strong>webhooks</strong> 和集成对本地网络的请求</li><li>允许系统钩子向本地网络发送请求</li></ul></li><li>在空白框中粘贴需要调用的内网IP、域名。</li><li>登录 GitLab 服务器，编辑 <strong>&#x2F;etc&#x2F;hosts</strong> 文件，添加自定义域名映射。</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">192.168.x.x traefik.k8scluster.com</span><br><span class="line">192.168.x.x harbor.dockerregistry.com</span><br><span class="line">192.168.x.x argocd.k8scluster.com</span><br><span class="line">192.168.x.x grpc.argocd.k8scluster.com</span><br></pre></td></tr></table></figure><h2 id="GitLab-集成-ArgoCD"><a href="#GitLab-集成-ArgoCD" class="headerlink" title="GitLab 集成 ArgoCD"></a>GitLab 集成 ArgoCD</h2><h3 id="目的-1"><a href="#目的-1" class="headerlink" title="目的"></a>目的</h3><p>通过 GitLab 与 ArgoCD 集成，实现流水线中对 ArgoCD 应用的自动化操作，同时隐藏 ArgoCD 真实服务器信息。</p><h3 id="操作步骤-1"><a href="#操作步骤-1" class="headerlink" title="操作步骤"></a>操作步骤</h3><ol><li>进入项目组页面，选择 <strong>设置</strong> -&gt; <strong>CI&#x2F;CD</strong> -&gt; <strong>变量</strong>。</li><li>添加以下变量：<ul><li><strong>ARGOCD_USERNAME</strong>: 自定义值，勾选 Masked</li><li><strong>ARGOCD_SERVER</strong>: 自定义值，勾选 Masked</li><li><strong>ARGOCD_PASSWORD</strong>: 自定义值，勾选 Masked</li></ul></li></ol><h2 id="GitLab-集成-Minio"><a href="#GitLab-集成-Minio" class="headerlink" title="GitLab 集成 Minio"></a>GitLab 集成 Minio</h2><h3 id="目的-2"><a href="#目的-2" class="headerlink" title="目的"></a>目的</h3><p>将构建的制品存储到 Minio，减轻 GitLab 服务器的负担。</p><h3 id="操作步骤-2"><a href="#操作步骤-2" class="headerlink" title="操作步骤"></a>操作步骤</h3><ol><li><p>修改 GitLab 配置文件：</p> <figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo vim /etc/gitlab/gitlab.rb</span><br><span class="line">gitlab_rails[&#x27;artifacts_enabled&#x27;] = true</span><br><span class="line">gitlab_rails[&#x27;artifacts_object_store_enabled&#x27;] = true</span><br><span class="line">gitlab_rails[&#x27;artifacts_object_store_remote_directory&#x27;] = &#x27;gitlab-artifacts&#x27;</span><br><span class="line">gitlab_rails[&#x27;artifacts_object_store_connection&#x27;] = &#123;</span><br><span class="line">&#x27;provider&#x27; =&gt; &#x27;AWS&#x27;,</span><br><span class="line">&#x27;region&#x27; =&gt; &#x27;us-east-1&#x27;,</span><br><span class="line">&#x27;aws_access_key_id&#x27; =&gt; &#x27;your_access_key&#x27;,</span><br><span class="line">&#x27;aws_secret_access_key&#x27; =&gt; &#x27;your_secret_key&#x27;,</span><br><span class="line">&#x27;endpoint&#x27; =&gt; &#x27;http://&lt;minio_server&gt;:9000&#x27;,</span><br><span class="line">&#x27;path_style&#x27; =&gt; true</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>重载配置：</p></li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo gitlab-ctl reconfigure</span><br></pre></td></tr></table></figure><h2 id="GitLab-集成-Harbor"><a href="#GitLab-集成-Harbor" class="headerlink" title="GitLab 集成 Harbor"></a>GitLab 集成 Harbor</h2><h3 id="目的-3"><a href="#目的-3" class="headerlink" title="目的"></a>目的</h3><p>将构建的 Docker 镜像直接推送到 Harbor，无需重复配置。</p><h3 id="操作步骤-3"><a href="#操作步骤-3" class="headerlink" title="操作步骤"></a>操作步骤</h3><ol><li>进入 <strong>管理界面</strong> 或 <strong>项目组管理界面</strong>，选择 <strong>设置</strong> -&gt; <strong>集成</strong>。</li><li>添加 Harbor 集成，输入以下信息：<ul><li><strong>域名</strong>：Harbor 地址</li><li><strong>项目名称</strong>：目标项目</li><li><strong>用户</strong>：使用机器人名称</li><li><strong>用户密码</strong>：Harbor 认证密码</li></ul></li></ol><h2 id="GitLab-文件大小限制调整"><a href="#GitLab-文件大小限制调整" class="headerlink" title="GitLab 文件大小限制调整"></a>GitLab 文件大小限制调整</h2><h3 id="目的-4"><a href="#目的-4" class="headerlink" title="目的"></a>目的</h3><p>调整 GitLab 上传文件的大小限制，以适应大文件的上传需求。</p><h3 id="操作步骤-4"><a href="#操作步骤-4" class="headerlink" title="操作步骤"></a>操作步骤</h3><ol><li><p>进入 <strong>管理员界面</strong> 或 <strong>项目组页面</strong>，选择 <strong>设置</strong> -&gt; <strong>CI&#x2F;CD</strong> -&gt; <strong>流水线通用设置</strong>，调整 <strong>最大工件大小</strong>。</p></li><li><p>如果以上设置无效，修改 GitLab 服务器配置文件：</p> <figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo vim /etc/gitlab/gitlab.rb</span><br><span class="line">nginx[&#x27;client_max_body_size&#x27;] = &#x27;200m&#x27;</span><br></pre></td></tr></table></figure></li><li><p>重载配置：</p></li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo gitlab-ctl reconfigure</span><br></pre></td></tr></table></figure><h2 id="GitLab-集成-CICD"><a href="#GitLab-集成-CICD" class="headerlink" title="GitLab 集成 CICD"></a>GitLab 集成 CICD</h2><h3 id="目的-5"><a href="#目的-5" class="headerlink" title="目的"></a>目的</h3><p>配置 GitLab CI&#x2F;CD，使机器人能够自动化更新代码。</p><h3 id="操作步骤-5"><a href="#操作步骤-5" class="headerlink" title="操作步骤"></a>操作步骤</h3><ol><li>进入项目页面，选择 <strong>设置</strong> -&gt; <strong>访问令牌</strong>，创建一个长期有效的开发者身份令牌。</li><li>进入 <strong>CI&#x2F;CD</strong> -&gt; <strong>变量</strong>，添加以下变量：<ul><li><strong>GITLAB_CI_TOKEN</strong>: 自定义值，勾选 Masked</li></ul></li></ol><h2 id="GitLab-性能优化"><a href="#GitLab-性能优化" class="headerlink" title="GitLab 性能优化"></a>GitLab 性能优化</h2><h3 id="目的-6"><a href="#目的-6" class="headerlink" title="目的"></a>目的</h3><p>优化 GitLab 性能，提高并发处理能力，减少响应时间。</p><h3 id="操作步骤-6"><a href="#操作步骤-6" class="headerlink" title="操作步骤"></a>操作步骤</h3><ol><li><strong>优化数据库</strong>：调整 PostgreSQL 配置，增加 <code>shared_buffers</code> 和 <code>work_mem</code> 设置：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo vim /etc/gitlab/postgresql.conf</span><br><span class="line">shared_buffers = 1GB</span><br><span class="line">work_mem = 64MB</span><br></pre></td></tr></table></figure><ol start="2"><li><strong>启用 Redis 缓存</strong>：配置 GitLab 使用 Redis 缓存：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo vim /etc/gitlab/gitlab.rb</span><br><span class="line">gitlab_rails[&#x27;redis_host&#x27;] = &#x27;localhost&#x27;</span><br><span class="line">gitlab_rails[&#x27;redis_port&#x27;] = 6379</span><br></pre></td></tr></table></figure><ol start="3"><li><p><strong>使用 SSD 存储</strong>：为 GitLab 配置 SSD 存储，提高 I&#x2F;O 性能。</p></li><li><p><strong>优化 Nginx 配置</strong>：调整 Nginx 设置，提高吞吐量：</p></li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo vim /etc/gitlab/nginx/gitlab-http.conf</span><br><span class="line">worker_processes auto;</span><br><span class="line">worker_connections 4096;</span><br></pre></td></tr></table></figure><ol start="5"><li><strong>分离 GitLab 服务</strong>：将 GitLab 服务分离到不同服务器，减轻单台服务器负担。</li></ol><h2 id="GitLab-安全加固"><a href="#GitLab-安全加固" class="headerlink" title="GitLab 安全加固"></a>GitLab 安全加固</h2><h3 id="目的-7"><a href="#目的-7" class="headerlink" title="目的"></a>目的</h3><p>加强 GitLab 的安全性，防止潜在的安全漏洞。</p><h3 id="操作步骤-7"><a href="#操作步骤-7" class="headerlink" title="操作步骤"></a>操作步骤</h3><ol><li><strong>启用 HTTPS</strong>：为 GitLab 配置 SSL，确保数据传输加密：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo vim /etc/gitlab/gitlab.rb</span><br><span class="line">external_url &#x27;https://gitlab.example.com&#x27;</span><br><span class="line">nginx[&#x27;ssl_certificate&#x27;] = &quot;/etc/ssl/certs/gitlab.crt&quot;</span><br><span class="line">nginx[&#x27;ssl_certificate_key&#x27;] = &quot;/etc/ssl/private/gitlab.key&quot;</span><br></pre></td></tr></table></figure><ol start="2"><li><p><strong>启用双因素认证（2FA）</strong>：在 GitLab 设置页面启用 2FA。</p></li><li><p><strong>使用 LDAP 或 OAuth 实现企业认证</strong>：</p></li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo vim /etc/gitlab/gitlab.rb</span><br><span class="line">gitlab_rails[&#x27;ldap_enabled&#x27;] = true</span><br><span class="line">gitlab_rails[&#x27;ldap_servers&#x27;] = YAML.load &lt;&lt;-EOS</span><br><span class="line">main:</span><br><span class="line">  label: &#x27;LDAP&#x27;</span><br><span class="line">  host: &#x27;_your_ldap_server_&#x27;</span><br><span class="line">  port: 389</span><br><span class="line">  uid: &#x27;sAMAccountName&#x27;</span><br><span class="line">  bind_dn: &#x27;CN=bind_user,CN=Users,DC=example,DC=com&#x27;</span><br><span class="line">  password: &#x27;_your_password_&#x27;</span><br><span class="line">EOS</span><br></pre></td></tr></table></figure><h2 id="GitLab-备份与恢复"><a href="#GitLab-备份与恢复" class="headerlink" title="GitLab 备份与恢复"></a>GitLab 备份与恢复</h2><h3 id="目的-8"><a href="#目的-8" class="headerlink" title="目的"></a>目的</h3><p>配置自动备份，以确保 GitLab 数据的安全性。</p><h3 id="操作步骤-8"><a href="#操作步骤-8" class="headerlink" title="操作步骤"></a>操作步骤</h3><ol><li><strong>配置自动备份</strong>：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo vim /etc/gitlab/gitlab.rb</span><br><span class="line">gitlab_rails[&#x27;backup_path&#x27;] = &#x27;/var/opt/gitlab/backups&#x27;</span><br><span class="line">gitlab_rails[&#x27;backup_keep_time&#x27;] = 604800  # 保留7天备份</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置 crontab 定期备份</span></span><br><span class="line">crontab -e</span><br><span class="line">0 2 * * * gitlab-rake gitlab:backup:create</span><br></pre></td></tr></table></figure><ol start="2"><li><strong>恢复备份</strong>：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo gitlab-rake gitlab:backup:restore BACKUP=timestamp_of_backup</span><br></pre></td></tr></table></figure><ol start="3"><li><strong>备份恢复测试</strong>：定期进行恢复测试，确保备份数据可用。</li></ol><h2 id="GitLab-日志与监控"><a href="#GitLab-日志与监控" class="headerlink" title="GitLab 日志与监控"></a>GitLab 日志与监控</h2><h3 id="目的-9"><a href="#目的-9" class="headerlink" title="目的"></a>目的</h3><p>通过日志管理和监控 GitLab 服务，及时发现和解决问题。</p><h3 id="操作步骤-9"><a href="#操作步骤-9" class="headerlink" title="操作步骤"></a>操作步骤</h3><ol><li><strong>配置日志收集</strong>：使用 <code>logrotate</code> 管理 GitLab 日志文件：</li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo vim /etc/logrotate.d/gitlab</span><br><span class="line">/var/log/gitlab/*.log &#123;</span><br><span class="line">    daily</span><br><span class="line">    rotate 7</span><br><span class="line">    compress</span><br><span class="line">    missingok</span><br><span class="line">    notifempty</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li><p><strong>使用 Prometheus 和 Grafana 监控 GitLab</strong>：通过 Prometheus 集成监控 GitLab 性能，使用 Grafana 展示数据。</p></li><li><p><strong>设置邮件通知</strong>：配置 GitLab 邮件通知，及时了解系统状态。</p></li></ol><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>本文档涵盖了 GitLab 的常见配置优化、集成 CICD、备份恢复、安全加固和监控等方面。通过这些操作，您可以有效提升 GitLab 的性能、安全性和可靠性。如果您有任何问题或进一步的需求，欢迎留言讨论。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt; 本文档旨在提供 GitLab 配置优化、集成最佳实践、安全加固、备份与恢复策略以及监控方法，帮助团队在使用 GitLab 进行源代码管理和持续集成&amp;#x2F;持续交付（CICD）时提升性能、安全性及稳定性。&lt;/p&gt;</summary>
    
    
    
    <category term="Development" scheme="https://freemankevin.uk/categories/Development/"/>
    
    
    <category term="Development" scheme="https://freemankevin.uk/tags/Development/"/>
    
    <category term="GitLab" scheme="https://freemankevin.uk/tags/GitLab/"/>
    
    <category term="CICD" scheme="https://freemankevin.uk/tags/CICD/"/>
    
  </entry>
  
  <entry>
    <title>如何在 Docker 环境中部署 GitLab Runner</title>
    <link href="https://freemankevin.uk/2025/01/21/docker-runner/"/>
    <id>https://freemankevin.uk/2025/01/21/docker-runner/</id>
    <published>2025-01-21T09:14:25.000Z</published>
    <updated>2026-04-17T10:30:31.801Z</updated>
    
    <content type="html"><![CDATA[<p> 在本篇文章中，我们将介绍如何在 Docker 环境中部署 GitLab Runner，以便使用 GitLab CI&#x2F;CD 实现自动化构建与部署。我们将通过 Docker Compose 配置并管理 GitLab Runner 容器，详细讲解配置文件和注册过程。</p><span id="more"></span><h2 id="部署-GitLab-Runner"><a href="#部署-GitLab-Runner" class="headerlink" title="部署 GitLab Runner"></a>部署 GitLab Runner</h2><p>GitLab Runner 是 GitLab CI&#x2F;CD 的一个组成部分，用于执行 CI&#x2F;CD 作业。本文将介绍如何在 Docker 环境中部署 GitLab Runner，并配置其与 GitLab 服务器的连接。我们将使用 Docker Compose 来管理 GitLab Runner 容器的启动和配置。</p><h3 id="创建-Docker-Compose-配置文件"><a href="#创建-Docker-Compose-配置文件" class="headerlink" title="创建 Docker Compose 配置文件"></a>创建 Docker Compose 配置文件</h3><p>首先，我们需要为 GitLab Runner 创建一个 <code>docker-compose.yml</code> 配置文件。在该文件中，我们定义了 GitLab Runner 容器的基本配置信息，包括使用的镜像、挂载的卷以及容器的特权模式。</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">&#x27;3&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">gitlab-runner-npm:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">gitlab/gitlab-runner:latest</span>  <span class="comment"># 使用 GitLab Runner 的最新版本镜像</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">gitlab-runner-npm</span>  <span class="comment"># 容器名称</span></span><br><span class="line">    <span class="attr">privileged:</span> <span class="literal">true</span>  <span class="comment"># 启用特权模式，允许容器执行 Docker 操作</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span>  <span class="comment"># 容器崩溃时自动重启</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./gitlab-runner/:/etc/gitlab-runner</span>  <span class="comment"># 将本地的 GitLab Runner 配置文件挂载到容器中</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">~/.docker:/root/.docker</span>  <span class="comment"># 将本地 Docker 配置挂载到容器中，确保 Runner 可以使用 Docker 客户端</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">/var/run/docker.sock:/var/run/docker.sock</span>  <span class="comment"># 共享 Docker 套接字，允许 Runner 执行 Docker 命令</span></span><br><span class="line">      <span class="comment">#- ./cache:/cache  # 可选的缓存挂载，用于加速构建过程</span></span><br></pre></td></tr></table></figure><p>在这个 <code>docker-compose.yml</code> 文件中，我们挂载了几个目录和文件以确保容器能够正确工作：</p><ul><li><code>./gitlab-runner/</code>：用于存储 GitLab Runner 配置。</li><li><code>~/.docker</code>：将主机上的 Docker 配置挂载到容器中。</li><li><code>/var/run/docker.sock</code>：容器通过这个挂载与宿主机的 Docker 守护进程进行通信，允许 Runner 执行 Docker 命令。</li></ul><h3 id="注册-GitLab-Runner"><a href="#注册-GitLab-Runner" class="headerlink" title="注册 GitLab Runner"></a>注册 GitLab Runner</h3><p>GitLab Runner 需要在注册后才能与 GitLab 服务进行通信。以下是注册 GitLab Runner 的脚本，它通过 Docker 执行 <code>gitlab-runner register</code> 命令。</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line"></span><br><span class="line">REGISTRATION_TOKEN=&quot;YOUR_REGISTRATION_TOKEN&quot;  # GitLab 注册令牌，替换为实际值</span><br><span class="line">RUNNER_NAME=&quot;gitlab-runner-npm-group&quot;  # Runner 的名称</span><br><span class="line"></span><br><span class="line">docker exec -it &quot;$&#123;RUNNER_NAME&#125;&quot; gitlab-runner register \</span><br><span class="line">  --non-interactive \</span><br><span class="line">  --url &quot;http://gitlab.example.com/&quot; \  # GitLab 服务器地址，替换为实际地址</span><br><span class="line">  --registration-token &quot;$&#123;REGISTRATION_TOKEN&#125;&quot; \</span><br><span class="line">  --executor &quot;docker&quot; \  # 使用 Docker 执行器</span><br><span class="line">  --docker-image &quot;docker:19.03.12&quot; \  # Docker 镜像，选择适合的版本</span><br><span class="line">  --description &quot;Docker Runner&quot; \  # Runner 描述</span><br><span class="line">  --tag-list &quot;docker-npm&quot; \  # Runner 标签，帮助过滤任务</span><br><span class="line">  --locked=true \  # 锁定 Runner，防止其他 GitLab 实例注册</span><br><span class="line">  --docker-privileged=true \  # 启用 Docker 特权模式</span><br><span class="line">  --run-untagged=false \  # 不运行未打标签的作业</span><br><span class="line">  --docker-tlsverify=false \  # 禁用 Docker TLS 验证</span><br><span class="line">  --docker-disable-entrypoint-overwrite=false \  # 不禁用容器入口点覆盖</span><br><span class="line">  --docker-oom-kill-disable=false \  # 启用 OOM 杀死</span><br><span class="line">  --docker-disable-cache=false \  # 启用 Docker 缓存</span><br><span class="line">  --docker-shm-size=0 \  # 设置共享内存大小</span><br><span class="line">  --cache-type=&quot;s3&quot; \  # 配置 S3 缓存</span><br><span class="line">  --cache-path=&quot;runner&quot; \  # 缓存路径</span><br><span class="line">  --cache-shared=true \  # 启用共享缓存</span><br><span class="line">  --cache-s3-server-address=&quot;s3.example.com:9000&quot; \  # S3 服务器地址，替换为实际值</span><br><span class="line">  --cache-s3-access-key=&quot;YOUR_S3_ACCESS_KEY&quot; \  # S3 访问密钥</span><br><span class="line">  --cache-s3-secret-key=&quot;YOUR_S3_SECRET_KEY&quot; \  # S3 秘密访问密钥</span><br><span class="line">  --cache-s3-bucket-name=&quot;runner-cache&quot; \  # S3 存储桶名称</span><br><span class="line">  --cache-s3-insecure=true  # 启用不安全连接</span><br></pre></td></tr></table></figure><h3 id="GitLab-Runner-配置"><a href="#GitLab-Runner-配置" class="headerlink" title="GitLab Runner 配置"></a>GitLab Runner 配置</h3><p>在容器中，我们可以编辑 GitLab Runner 的配置文件 <code>config.toml</code>，以设置并优化 Runner 的行为。以下是 <code>config.toml</code> 文件的示例，其中包含了多个重要的配置项：</p><figure class="highlight toml"><table><tr><td class="code"><pre><span class="line"><span class="attr">concurrent</span> = <span class="number">1</span>  <span class="comment"># 限制同时运行的作业数</span></span><br><span class="line"><span class="attr">check_interval</span> = <span class="number">0</span>  <span class="comment"># 检查任务队列的间隔时间</span></span><br><span class="line"></span><br><span class="line"><span class="section">[session_server]</span></span><br><span class="line">  <span class="attr">session_timeout</span> = <span class="number">1800</span>  <span class="comment"># 会话超时设置（单位：秒）</span></span><br><span class="line"></span><br><span class="line"><span class="section">[[runners]]</span></span><br><span class="line">  <span class="attr">name</span> = <span class="string">&quot;Docker Runner&quot;</span>  <span class="comment"># Runner 名称</span></span><br><span class="line">  <span class="attr">url</span> = <span class="string">&quot;http://gitlab.example.com/&quot;</span>  <span class="comment"># GitLab 实例的 URL</span></span><br><span class="line">  <span class="attr">token</span> = <span class="string">&quot;YOUR_REGISTRATION_TOKEN&quot;</span>  <span class="comment"># 注册令牌，替换为实际值</span></span><br><span class="line">  <span class="attr">executor</span> = <span class="string">&quot;docker&quot;</span>  <span class="comment"># 使用 Docker 执行作业</span></span><br><span class="line"></span><br><span class="line">  <span class="section">[runners.custom_build_dir]</span></span><br><span class="line">  <span class="comment">#[runners.cache]  # 缓存配置，通常用于加速构建过程</span></span><br><span class="line">  <span class="comment">#  Type = &quot;local&quot;</span></span><br><span class="line">  <span class="comment">#  Path = &quot;/cache&quot;</span></span><br><span class="line">  <span class="comment">#  Shared = true</span></span><br><span class="line">  <span class="section">[runners.cache]</span></span><br><span class="line">    <span class="attr">Type</span> = <span class="string">&quot;s3&quot;</span>  <span class="comment"># 使用 S3 作为缓存类型</span></span><br><span class="line">    <span class="attr">Path</span> = <span class="string">&quot;runner&quot;</span>  <span class="comment"># 缓存路径</span></span><br><span class="line">    <span class="attr">Shared</span> = <span class="literal">true</span>  <span class="comment"># 启用共享缓存</span></span><br><span class="line">    <span class="section">[runners.cache.s3]</span></span><br><span class="line">      <span class="attr">ServerAddress</span> = <span class="string">&quot;s3.example.com:9000&quot;</span>  <span class="comment"># S3 服务器地址，替换为实际地址</span></span><br><span class="line">      <span class="attr">AccessKey</span> = <span class="string">&quot;YOUR_S3_ACCESS_KEY&quot;</span>  <span class="comment"># S3 访问密钥</span></span><br><span class="line">      <span class="attr">SecretKey</span> = <span class="string">&quot;YOUR_S3_SECRET_KEY&quot;</span>  <span class="comment"># S3 秘密访问密钥</span></span><br><span class="line">      <span class="attr">BucketName</span> = <span class="string">&quot;runner-cache&quot;</span>  <span class="comment"># S3 存储桶名称</span></span><br><span class="line">      <span class="attr">Insecure</span> = <span class="literal">true</span>  <span class="comment"># 启用不安全连接</span></span><br><span class="line"></span><br><span class="line">  <span class="section">[runners.docker]</span></span><br><span class="line">    <span class="attr">tls_verify</span> = <span class="literal">false</span>  <span class="comment"># 禁用 Docker TLS 验证</span></span><br><span class="line">    <span class="attr">image</span> = <span class="string">&quot;docker:19.03.12&quot;</span>  <span class="comment"># Docker 镜像版本</span></span><br><span class="line">    <span class="attr">privileged</span> = <span class="literal">true</span>  <span class="comment"># 启用特权模式</span></span><br><span class="line">    <span class="attr">disable_entrypoint_overwrite</span> = <span class="literal">false</span>  <span class="comment"># 启用容器入口点覆盖</span></span><br><span class="line">    <span class="attr">oom_kill_disable</span> = <span class="literal">false</span>  <span class="comment"># 启用 OOM 杀死</span></span><br><span class="line">    <span class="attr">disable_cache</span> = <span class="literal">false</span>  <span class="comment"># 启用缓存</span></span><br><span class="line">    <span class="attr">volumes</span> = [<span class="string">&quot;/cache&quot;</span>]  <span class="comment"># 挂载的目录</span></span><br><span class="line">    <span class="attr">shm_size</span> = <span class="number">536870912</span>  <span class="comment"># 设置共享内存大小</span></span><br><span class="line">    <span class="attr">memory</span> = <span class="string">&quot;24000m&quot;</span>  <span class="comment"># 分配内存</span></span><br><span class="line">    <span class="attr">memory_swap</span> = <span class="string">&quot;26g&quot;</span>  <span class="comment"># 设置交换内存</span></span><br><span class="line">    <span class="attr">cpus</span> = <span class="string">&quot;12&quot;</span>  <span class="comment"># 分配 CPU 核数</span></span><br><span class="line">    <span class="attr">allowed_images</span> = [  <span class="comment"># 限制 Runner 使用的镜像列表</span></span><br><span class="line">      <span class="string">&quot;harbor.dockerregistry.com/kubernetes/maven:3.6.3-openjdk-8-slim&quot;</span>,</span><br><span class="line">      <span class="string">&quot;harbor.dockerregistry.com/kubernetes/kaniko-project/executor:v1.14.0-debug&quot;</span>,</span><br><span class="line">      <span class="string">&quot;harbor.dockerregistry.com/kubernetes/argocli-git:v2.7.14&quot;</span>,</span><br><span class="line">      <span class="string">&quot;harbor.dockerregistry.com/kubernetes/nodejs:*&quot;</span></span><br><span class="line">    ]</span><br></pre></td></tr></table></figure><h4 id="重要配置说明："><a href="#重要配置说明：" class="headerlink" title="重要配置说明："></a>重要配置说明：</h4><ul><li><strong><code>privileged</code></strong>：启用特权模式，允许容器执行 Docker 操作。这是必需的，因为 GitLab Runner 需要能够在容器中执行构建任务。</li><li><strong><code>executor</code></strong>：指定运行作业的执行器，通常为 <code>docker</code>，可以在容器中运行任务。</li><li><strong><code>volumes</code></strong>：挂载卷，允许容器访问宿主机的文件系统。例如，挂载 Docker 套接字和共享缓存目录。</li><li><strong><code>memory</code> 和 <code>cpus</code></strong>：为 Runner 分配内存和 CPU 资源，根据需要调整这些参数以优化构建性能。</li></ul><h3 id="启动-GitLab-Runner"><a href="#启动-GitLab-Runner" class="headerlink" title="启动 GitLab Runner"></a>启动 GitLab Runner</h3><p>完成以上配置后，我们可以通过以下命令启动 GitLab Runner 容器：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">docker-compose up -d  # 在后台启动服务</span><br></pre></td></tr></table></figure><p>这将启动 GitLab Runner，并且它会自动与 GitLab 实例注册。您可以登录 GitLab 查看 Runner 是否成功注册并开始处理作业。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt; 在本篇文章中，我们将介绍如何在 Docker 环境中部署 GitLab Runner，以便使用 GitLab CI&amp;#x2F;CD 实现自动化构建与部署。我们将通过 Docker Compose 配置并管理 GitLab Runner 容器，详细讲解配置文件和注册过程。&lt;/p&gt;</summary>
    
    
    
    <category term="Development" scheme="https://freemankevin.uk/categories/Development/"/>
    
    
    <category term="Docker" scheme="https://freemankevin.uk/tags/Docker/"/>
    
    <category term="GitLab Runner" scheme="https://freemankevin.uk/tags/GitLab-Runner/"/>
    
    <category term="GitLab" scheme="https://freemankevin.uk/tags/GitLab/"/>
    
  </entry>
  
  <entry>
    <title>如何在Kubernetes 环境中安装 Grafana 部署指南</title>
    <link href="https://freemankevin.uk/2025/01/21/k8s-grafana/"/>
    <id>https://freemankevin.uk/2025/01/21/k8s-grafana/</id>
    <published>2025-01-21T08:53:25.000Z</published>
    <updated>2026-04-17T10:30:31.805Z</updated>
    
    <content type="html"><![CDATA[<p> 本文介绍如何通过 Helm 部署 Grafana 并配置反向代理，以便在 Kubernetes 集群中使用 Grafana，支持 HTTPS 加密和基本认证。</p><span id="more"></span><h2 id="下载-Helm-Chart"><a href="#下载-Helm-Chart" class="headerlink" title="下载 Helm Chart"></a>下载 Helm Chart</h2><p>首先创建目录并下载 Grafana 的 Helm Chart。</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">mkdir -p grafana </span><br><span class="line">cd grafana</span><br><span class="line">helm repo add grafana https://grafana.github.io/helm-charts</span><br><span class="line">helm repo update</span><br><span class="line">helm search repo grafana/grafana -l</span><br><span class="line">helm search repo grafana/grafana --versions</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">如果需要下载指定版本</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">helm pull grafana/grafana --version 7.2.3</span> </span><br><span class="line">tar xf grafana-7.2.3.tgz</span><br><span class="line">cp -rvf grafana/values.yaml&#123;,.bak&#125;</span><br></pre></td></tr></table></figure><h2 id="创建自定义-values-yaml"><a href="#创建自定义-values-yaml" class="headerlink" title="创建自定义 values.yaml"></a>创建自定义 <code>values.yaml</code></h2><p>Grafana 的 <code>values.yaml</code> 文件用于配置 Helm Chart 部署的参数。以下是常用的配置项：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">image:</span></span><br><span class="line">  <span class="attr">registry:</span> <span class="string">docker.io</span></span><br><span class="line">  <span class="attr">repository:</span> <span class="string">grafana/grafana</span></span><br><span class="line">  <span class="attr">tag:</span> <span class="string">&quot;10.2.3&quot;</span>  <span class="comment"># 修改为固定版本的镜像标签</span></span><br><span class="line">  </span><br><span class="line"><span class="attr">ingress:</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span>  <span class="comment"># 启用 Ingress</span></span><br><span class="line">  <span class="attr">annotations:</span>  <span class="comment"># 添加注释</span></span><br><span class="line">    <span class="attr">kubernetes.io/ingress.class:</span> <span class="string">&quot;nginx&quot;</span></span><br><span class="line">    <span class="attr">nginx.ingress.kubernetes.io/rewrite-target:</span> <span class="string">/$1</span></span><br><span class="line">    <span class="attr">nginx.ingress.kubernetes.io/use-regex:</span> <span class="string">&quot;true&quot;</span></span><br><span class="line">  <span class="attr">hosts:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">grafana.k8scluster.com</span>  <span class="comment"># 使用域名访问 Grafana</span></span><br><span class="line">  </span><br><span class="line"><span class="attr">persistence:</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">pvc</span> </span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span>  <span class="comment"># 启用 PVC 持久化存储</span></span><br><span class="line">  <span class="attr">storageClassName:</span> <span class="string">default</span>  <span class="comment"># 使用默认存储类</span></span><br><span class="line">  <span class="attr">accessModes:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">ReadWriteOnce</span></span><br><span class="line">  <span class="attr">size:</span> <span class="string">1Gi</span>  <span class="comment"># 设置 PVC 大小为 1Gi</span></span><br><span class="line"></span><br><span class="line"><span class="attr">extraVolumeMounts:</span>  <span class="comment"># 配置额外的挂载路径</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">grafana-data</span></span><br><span class="line">    <span class="attr">mountPath:</span> <span class="string">/var/lib/grafana/plugins</span></span><br><span class="line">    <span class="attr">subPath:</span> <span class="string">plugins</span></span><br><span class="line">    <span class="attr">readOnly:</span> <span class="literal">false</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">grafana-data</span></span><br><span class="line">    <span class="attr">mountPath:</span> <span class="string">/var/lib/grafana/dashboards</span></span><br><span class="line">    <span class="attr">subPath:</span> <span class="string">dashboards</span></span><br><span class="line">    <span class="attr">readOnly:</span> <span class="literal">false</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">grafana-data</span></span><br><span class="line">    <span class="attr">mountPath:</span> <span class="string">/etc/grafana/provisioning</span></span><br><span class="line">    <span class="attr">subPath:</span> <span class="string">provisioning</span></span><br><span class="line">    <span class="attr">readOnly:</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="attr">extraVolumes:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">grafana-data</span></span><br><span class="line">    <span class="attr">persistentVolumeClaim:</span></span><br><span class="line">      <span class="attr">claimName:</span> <span class="string">grafana-data-pvc</span>  <span class="comment"># 使用指定的 PVC</span></span><br></pre></td></tr></table></figure><h3 id="配置解释"><a href="#配置解释" class="headerlink" title="配置解释"></a>配置解释</h3><ul><li><p><strong>镜像配置 (<code>image</code>)</strong>：选择正确的 Grafana 镜像版本。这里的 <code>tag</code> 参数设置为具体版本，如 <code>10.2.3</code>。</p></li><li><p><strong>Ingress 配置 (<code>ingress</code>)</strong>：</p><ul><li>启用 Ingress 以便通过域名访问 Grafana。</li><li><code>nginx.ingress.kubernetes.io/rewrite-target</code>：将请求路径重写为适合 Grafana 的路径。</li><li><code>path</code> 和 <code>pathType</code> 配置了访问路径，并使用正则匹配来灵活处理请求。</li><li><code>hosts</code> 配置为本地域名，确保 Grafana 可以通过指定域名访问。</li></ul></li><li><p><strong>持久化配置 (<code>persistence</code>)</strong>：</p><ul><li>使用 PVC 进行持久化存储，以便在 Grafana Pod 重启时不会丢失数据。</li><li>配置存储大小为 <code>1Gi</code>，并选择合适的存储类 <code>default</code>。</li></ul></li><li><p><strong>额外的挂载配置 (<code>extraVolumeMounts</code>)</strong>：</p><ul><li>将 Grafana 的插件、仪表盘和配置文件夹挂载到指定路径，确保 Grafana 启动时能够使用这些资源。</li></ul></li></ul><h2 id="使用-Helm-安装-Grafana"><a href="#使用-Helm-安装-Grafana" class="headerlink" title="使用 Helm 安装 Grafana"></a>使用 Helm 安装 Grafana</h2><p>使用以下命令来安装 Grafana 并指定自定义的 <code>values.yaml</code> 配置文件：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">helm install grafana -f grafana/values.yaml ./grafana --namespace grafana --create-namespace</span><br></pre></td></tr></table></figure><h3 id="安装完成后输出"><a href="#安装完成后输出" class="headerlink" title="安装完成后输出"></a>安装完成后输出</h3><p>安装完成后，您可以通过以下命令获取 Grafana 的默认管理员密码：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">kubectl get secret --namespace grafana grafana -o jsonpath=&quot;&#123;.data.admin-password&#125;&quot; | base64 --decode ; echo</span><br></pre></td></tr></table></figure><p>Grafana 控制台可以通过以下 DNS 地址访问：</p><figure class="highlight text"><table><tr><td class="code"><pre><span class="line">http://grafana.k8scluster.com</span><br></pre></td></tr></table></figure><p>登录时，使用管理员账户 <code>admin</code> 和密码。</p><h2 id="更新-Helm-部署"><a href="#更新-Helm-部署" class="headerlink" title="更新 Helm 部署"></a>更新 Helm 部署</h2><p>若需要对已部署的 Grafana 进行更新（例如修改配置），可以使用以下命令：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">helm upgrade grafana -f grafana/values.yaml ./grafana --namespace grafana</span><br></pre></td></tr></table></figure><h3 id="更新后输出"><a href="#更新后输出" class="headerlink" title="更新后输出"></a>更新后输出</h3><p>更新后同样可以通过以下命令获取更新后的管理员密码：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">kubectl get secret --namespace grafana grafana -o jsonpath=&quot;&#123;.data.admin-password&#125;&quot; | base64 --decode ; echo</span><br></pre></td></tr></table></figure><h2 id="登录-Grafana-控制台"><a href="#登录-Grafana-控制台" class="headerlink" title="登录 Grafana 控制台"></a>登录 Grafana 控制台</h2><p>Grafana 控制台可以通过浏览器访问以下地址：</p><figure class="highlight text"><table><tr><td class="code"><pre><span class="line">http://grafana.k8scluster.com:30886/grafana</span><br></pre></td></tr></table></figure><p>登录时，使用之前获取的管理员密码进行登录。</p><h2 id="导出-Prometheus-和-Alertmanager"><a href="#导出-Prometheus-和-Alertmanager" class="headerlink" title="导出 Prometheus 和 Alertmanager"></a>导出 Prometheus 和 Alertmanager</h2><h3 id="创建-Prometheus-和-Alertmanager-的-Ingress"><a href="#创建-Prometheus-和-Alertmanager-的-Ingress" class="headerlink" title="创建 Prometheus 和 Alertmanager 的 Ingress"></a>创建 Prometheus 和 Alertmanager 的 Ingress</h3><p>为 Prometheus 和 Alertmanager 创建一个 Ingress 资源，使其通过域名访问。</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">kind:</span> <span class="string">Ingress</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">prometheus-ingress</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">kubesphere-monitoring-system</span></span><br><span class="line">  <span class="attr">annotations:</span></span><br><span class="line">    <span class="attr">nginx.ingress.kubernetes.io/auth-realm:</span> <span class="string">Authentication</span> <span class="string">Required</span></span><br><span class="line">    <span class="attr">nginx.ingress.kubernetes.io/auth-secret:</span> <span class="string">prometheus-basic-auth</span></span><br><span class="line">    <span class="attr">nginx.ingress.kubernetes.io/auth-type:</span> <span class="string">basic</span></span><br><span class="line">    <span class="attr">nginx.ingress.kubernetes.io/proxy-body-size:</span> <span class="string">2048m</span></span><br><span class="line">    <span class="attr">nginx.ingress.kubernetes.io/proxy-connect-timeout:</span> <span class="string">&#x27;1800&#x27;</span></span><br><span class="line">    <span class="attr">nginx.ingress.kubernetes.io/proxy-read-timeout:</span> <span class="string">&#x27;1800&#x27;</span></span><br><span class="line">    <span class="attr">nginx.ingress.kubernetes.io/proxy-send-timeout:</span> <span class="string">&#x27;1800&#x27;</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">ingressClassName:</span> <span class="string">nginx</span></span><br><span class="line">  <span class="attr">rules:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">host:</span> <span class="string">prometheus.k8scluster.com</span></span><br><span class="line">      <span class="attr">http:</span></span><br><span class="line">        <span class="attr">paths:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">path:</span> <span class="string">/</span></span><br><span class="line">            <span class="attr">pathType:</span> <span class="string">Prefix</span></span><br><span class="line">            <span class="attr">backend:</span></span><br><span class="line">              <span class="attr">service:</span></span><br><span class="line">                <span class="attr">name:</span> <span class="string">prometheus-k8s</span></span><br><span class="line">                <span class="attr">port:</span></span><br><span class="line">                  <span class="attr">name:</span> <span class="string">web</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">host:</span> <span class="string">alertmanager.k8scluster.com</span></span><br><span class="line">      <span class="attr">http:</span></span><br><span class="line">        <span class="attr">paths:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">path:</span> <span class="string">/</span></span><br><span class="line">            <span class="attr">pathType:</span> <span class="string">Prefix</span></span><br><span class="line">            <span class="attr">backend:</span></span><br><span class="line">              <span class="attr">service:</span></span><br><span class="line">                <span class="attr">name:</span> <span class="string">alertmanager-main</span></span><br><span class="line">                <span class="attr">port:</span></span><br><span class="line">                  <span class="attr">name:</span> <span class="string">web</span></span><br></pre></td></tr></table></figure><h3 id="创建-HTTP-基本认证"><a href="#创建-HTTP-基本认证" class="headerlink" title="创建 HTTP 基本认证"></a>创建 HTTP 基本认证</h3><p>通过 <code>htpasswd</code> 创建一个基本认证文件，并将其作为 Secret 存储：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">htpasswd -c auth admin  # 设置管理员密码</span><br></pre></td></tr></table></figure><h3 id="创建-Secret"><a href="#创建-Secret" class="headerlink" title="创建 Secret"></a>创建 Secret</h3><p>创建 Kubernetes Secret，用于存储基本认证凭证：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">kubectl create secret generic prometheus-basic-auth --from-file=auth -n monitoring</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt; 本文介绍如何通过 Helm 部署 Grafana 并配置反向代理，以便在 Kubernetes 集群中使用 Grafana，支持 HTTPS 加密和基本认证。&lt;/p&gt;</summary>
    
    
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/categories/Kubernetes/"/>
    
    
    <category term="TLS" scheme="https://freemankevin.uk/tags/TLS/"/>
    
    <category term="KubeSphere" scheme="https://freemankevin.uk/tags/KubeSphere/"/>
    
    <category term="Ingress-NGINX" scheme="https://freemankevin.uk/tags/Ingress-NGINX/"/>
    
  </entry>
  
  <entry>
    <title>如何在Kubernetes 环境中安装 KubeSphere</title>
    <link href="https://freemankevin.uk/2025/01/21/k8s-kubesphere/"/>
    <id>https://freemankevin.uk/2025/01/21/k8s-kubesphere/</id>
    <published>2025-01-21T08:32:25.000Z</published>
    <updated>2026-04-17T10:30:31.805Z</updated>
    
    <content type="html"><![CDATA[<p> 本文将介绍如何在 Kubernetes 集群中在线安装 KubeSphere，这是一个功能强大的容器管理平台，能够帮助用户方便地管理 Kubernetes 环境。我们将通过 Helm 进行安装，详细讲解每一步的操作流程，并展示如何通过浏览器访问 KubeSphere 控制台。最后，我们还会提供卸载 KubeSphere 的步骤，帮助您轻松管理平台的生命周期。</p><span id="more"></span><h2 id="安装-KubeSphere"><a href="#安装-KubeSphere" class="headerlink" title="安装 KubeSphere"></a>安装 KubeSphere</h2><p>KubeSphere 是一个开源的容器管理平台，可以轻松实现 Kubernetes 集群的统一管理。要安装 KubeSphere，我们可以通过 Helm 工具进行在线安装，步骤如下：</p><p>首先，在 Kubernetes 集群中应用 KubeSphere 的安装文件：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.4.1/kubesphere-installer.yaml</span><br><span class="line">kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.4.1/cluster-configuration.yaml</span><br></pre></td></tr></table></figure><p>接着，设置区域为中国：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">export KKZONE=cn</span><br><span class="line">echo &quot;export KKZONE=cn&quot; &gt;&gt; /etc/profile</span><br><span class="line">source /etc/profile</span><br></pre></td></tr></table></figure><p>然后，通过 Helm 安装 KubeSphere：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">helm repo add kubesphere https://charts.kubesphere.io/main</span><br><span class="line">helm repo update</span><br><span class="line">helm install ks kubesphere/kubesphere --namespace kubesphere-system --create-namespace</span><br></pre></td></tr></table></figure><p>安装过程会自动拉取所需的镜像并配置相应的服务。</p><p>安装完成后，您可以使用以下命令查看 KubeSphere 安装日志，确保安装成功：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">kubectl logs -n kubesphere-system -l app=ks-installer -f</span><br></pre></td></tr></table></figure><p>然后，使用浏览器访问 KubeSphere 控制台：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">控制台: http://&lt;Your-IP&gt;:30880</span><br><span class="line">账户: admin</span><br><span class="line">密码: P@88w0rd</span><br></pre></td></tr></table></figure><hr><h2 id="卸载-KubeSphere"><a href="#卸载-KubeSphere" class="headerlink" title="卸载 KubeSphere"></a>卸载 KubeSphere</h2><p>如果需要卸载 KubeSphere，您可以通过以下命令进行操作。请注意，卸载过程会删除 KubeSphere 所有相关资源，请谨慎操作。</p><p>首先，执行卸载命令：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">helm uninstall ks --namespace kubesphere-system</span><br></pre></td></tr></table></figure><p>然后，清理残留的资源：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">kubectl delete namespace kubesphere-system</span><br></pre></td></tr></table></figure><p>如果遇到命名空间无法删除的情况，可以手动删除 <code>finalizers</code> 字段：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">kubectl get namespace kubesphere-system -o json &gt; kubesphere-system-temp.json</span><br><span class="line">vim kubesphere-system-temp.json</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">删除 <span class="string">&quot;finalizers&quot;</span> 字段</span></span><br><span class="line">kubectl replace --raw &quot;/api/v1/namespaces/kubesphere-system/finalize&quot; -f ./kubesphere-system-temp.json</span><br></pre></td></tr></table></figure><p>完成后，KubeSphere 就会被彻底卸载。</p><h2 id="配置-KubeSphere-代理"><a href="#配置-KubeSphere-代理" class="headerlink" title="配置 KubeSphere 代理"></a>配置 KubeSphere 代理</h2><p>在一些场景下，您可能需要为 KubeSphere 控制台添加一个代理，以便更方便地通过自定义域名访问。下面是如何通过 Docker Compose 配置 Nginx 代理服务的步骤。</p><p>首先，创建一个 <code>docker-compose.yaml</code> 文件，配置 Nginx 代理，并映射 KubeSphere 控制台的端口。以下是完整的配置文件内容：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">&#x27;3.8&#x27;</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">ks-console-proxy:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">harbor.dockerregistry.com/library/nginx:1.21.6-alpine</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">ks-console-proxy</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;8080:8080&quot;</span>   <span class="comment"># 映射 HTTP 端口</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;8443:8443&quot;</span>   <span class="comment"># 映射 HTTPS 端口</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&#x27;/etc/localtime:/etc/localtime:ro&#x27;</span>                       <span class="comment"># 确保容器使用宿主机的时区设置</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&#x27;./nginx/ssl:/etc/nginx/ssl&#x27;</span>                               <span class="comment"># 绑定 SSL 证书文件</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&#x27;./nginx/nginx.conf:/etc/nginx/nginx.conf&#x27;</span>                 <span class="comment"># 配置 Nginx 主配置文件</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&#x27;./nginx/conf.d/ks-console.conf:/etc/nginx/conf.d/default.conf&#x27;</span>  <span class="comment"># 配置 KubeSphere 控制台的反向代理</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&#x27;/data/nginx/logs:/var/log/nginx&#x27;</span>                          <span class="comment"># 映射日志文件</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD-SHELL&quot;</span>, <span class="string">&quot;curl --silent --fail --insecure https://localhost:8443 || exit 1&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">1m30s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">3</span></span><br><span class="line">      <span class="attr">start_period:</span> <span class="string">3s</span></span><br></pre></td></tr></table></figure><h3 id="文件说明"><a href="#文件说明" class="headerlink" title="文件说明"></a>文件说明</h3><ul><li><code>ks-console-proxy</code>：此服务为 KubeSphere 控制台提供反向代理。</li><li><code>ports</code>：映射容器的 HTTP (8080) 和 HTTPS (8443) 端口，方便用户通过浏览器访问控制台。</li><li><code>volumes</code>：<ul><li><code>/etc/localtime:/etc/localtime:ro</code>：使容器时区与宿主机一致。</li><li><code>./nginx/ssl:/etc/nginx/ssl</code>：存放 SSL 证书的目录，用于加密 HTTPS 访问。</li><li><code>./nginx/nginx.conf:/etc/nginx/nginx.conf</code>：Nginx 的主配置文件。</li><li><code>./nginx/conf.d/ks-console.conf:/etc/nginx/conf.d/default.conf</code>：配置 KubeSphere 控制台的反向代理规则。</li><li><code>/data/nginx/logs:/var/log/nginx</code>：容器的日志文件存放目录。</li></ul></li><li><code>healthcheck</code>：配置健康检查，确保容器正常运行。</li></ul><h3 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h3><p>在您的服务器上，创建以下目录结构：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">ks-console</span><br><span class="line">├── docker-compose.yaml           # Docker Compose 配置文件</span><br><span class="line">└── nginx</span><br><span class="line">    ├── conf.d</span><br><span class="line">    │   └── ks-console.conf      # KubeSphere 控制台的代理配置文件</span><br><span class="line">    ├── nginx.conf               # Nginx 主配置文件</span><br><span class="line">    └── ssl</span><br><span class="line">        ├── kubesphere.k8scluster.com.crt  # KubeSphere SSL 证书</span><br><span class="line">        └── kubesphere.k8scluster.com.key  # KubeSphere SSL 密钥</span><br></pre></td></tr></table></figure><h3 id="配置文件示例"><a href="#配置文件示例" class="headerlink" title="配置文件示例"></a>配置文件示例</h3><ol><li><p><strong>Nginx 配置文件 <code>nginx.conf</code></strong>（位于 <code>./nginx/nginx.conf</code>）：</p><figure class="highlight nginx"><table><tr><td class="code"><pre><span class="line"><span class="attribute">user</span> nginx;</span><br><span class="line"><span class="attribute">worker_processes</span> auto;</span><br><span class="line"><span class="attribute">error_log</span> /var/log/nginx/<span class="literal">error</span>.log;</span><br><span class="line"><span class="attribute">pid</span> /var/run/nginx.pid;</span><br><span class="line"></span><br><span class="line"><span class="section">events</span> &#123;</span><br><span class="line">    <span class="attribute">worker_connections</span> <span class="number">1024</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="section">http</span> &#123;</span><br><span class="line">    <span class="attribute">include</span>       /etc/nginx/mime.types;</span><br><span class="line">    <span class="attribute">default_type</span>  application/octet-stream;</span><br><span class="line">    <span class="attribute">access_log</span> /var/log/nginx/access.log;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">sendfile</span> <span class="literal">on</span>;</span><br><span class="line">    <span class="attribute">tcp_nopush</span> <span class="literal">on</span>;</span><br><span class="line">    <span class="attribute">tcp_nodelay</span> <span class="literal">on</span>;</span><br><span class="line">    <span class="attribute">keepalive_timeout</span> <span class="number">65</span>;</span><br><span class="line">    <span class="attribute">types_hash_max_size</span> <span class="number">2048</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">include</span> /etc/nginx/conf.d/<span class="regexp">*.conf</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p><strong>KubeSphere 控制台代理配置 <code>ks-console.conf</code></strong>（位于 <code>./nginx/conf.d/ks-console.conf</code>）：</p><figure class="highlight nginx"><table><tr><td class="code"><pre><span class="line"><span class="comment"># HTTP server</span></span><br><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">    <span class="attribute">listen</span> <span class="number">8080</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">server_name</span> kubesphere.k8scluster.com;</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 强制将所有 HTTP 流量重定向到 HTTPS</span></span><br><span class="line">    <span class="section">location</span> / &#123;</span><br><span class="line">        <span class="attribute">return</span> <span class="number">301</span> https://<span class="variable">$host</span>:8443<span class="variable">$request_uri</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># HTTPS server</span></span><br><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">    <span class="attribute">listen</span> <span class="number">8443</span> ssl;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">server_name</span> kubesphere.k8scluster.com;</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 访问日志和错误日志配置</span></span><br><span class="line">    <span class="attribute">access_log</span> /var/log/nginx/access.log main;</span><br><span class="line">    <span class="attribute">error_log</span>  /var/log/nginx/<span class="literal">error</span>.log;</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 默认首页文件</span></span><br><span class="line">    <span class="attribute">index</span> index.html index.htm;</span><br><span class="line"></span><br><span class="line">    <span class="comment"># SSL 配置</span></span><br><span class="line">    <span class="attribute">ssl_certificate</span>     /etc/nginx/ssl/kubesphere.k8scluster.com.crt;</span><br><span class="line">    <span class="attribute">ssl_certificate_key</span> /etc/nginx/ssl/kubesphere.k8scluster.com.key;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">ssl_protocols</span> TLSv1.<span class="number">2</span> TLSv1.<span class="number">3</span>;</span><br><span class="line">    <span class="attribute">ssl_prefer_server_ciphers</span> <span class="literal">on</span>;</span><br><span class="line">    <span class="attribute">ssl_ciphers</span> <span class="string">&quot;EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH&quot;</span>;</span><br><span class="line">    <span class="attribute">ssl_ecdh_curve</span> secp384r1;</span><br><span class="line">    <span class="attribute">ssl_session_cache</span> shared:SSL:<span class="number">10m</span>;</span><br><span class="line">    <span class="attribute">ssl_session_tickets</span> <span class="literal">off</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="attribute">add_header</span> Strict-Transport-Security <span class="string">&quot;max-age=63072000; includeSubDomains&quot;</span>;</span><br><span class="line">    <span class="attribute">add_header</span> X-Frame-Options DENY;</span><br><span class="line">    <span class="attribute">add_header</span> X-Content-Type-Options nosniff;</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 强制 HTTPS 协议</span></span><br><span class="line">    <span class="attribute">if</span> (<span class="variable">$ssl_protocol</span> = <span class="string">&quot;&quot;</span>) &#123;</span><br><span class="line">        <span class="attribute">return</span> <span class="number">301</span> https://<span class="variable">$host</span><span class="variable">$request_uri</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 全局代理设置</span></span><br><span class="line">    <span class="attribute">proxy_http_version</span> <span class="number">1</span>.<span class="number">1</span>;</span><br><span class="line">    <span class="attribute">proxy_set_header</span>    Host <span class="variable">$host</span>:<span class="variable">$server_port</span>;</span><br><span class="line">    <span class="attribute">proxy_set_header</span>    X-Real-IP <span class="variable">$remote_addr</span>;</span><br><span class="line">    <span class="attribute">proxy_set_header</span>    X-Forwarded-For <span class="variable">$proxy_add_x_forwarded_for</span>;</span><br><span class="line">    <span class="attribute">proxy_connect_timeout</span> <span class="number">3600s</span>;</span><br><span class="line">    <span class="attribute">proxy_read_timeout</span>  <span class="number">3600s</span>;</span><br><span class="line">    <span class="attribute">proxy_send_timeout</span>  <span class="number">3600s</span>;</span><br><span class="line">    <span class="attribute">send_timeout</span>        <span class="number">3600s</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 代理到 KubeSphere 控制台</span></span><br><span class="line">    <span class="section">location</span> / &#123;</span><br><span class="line">        <span class="attribute">proxy_pass</span> http://&lt;kubesphere_address&gt;:30880;  <span class="comment"># 替换为 KubeSphere 控制台实际地址</span></span><br><span class="line">        <span class="attribute">proxy_redirect</span> <span class="literal">off</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment"># API 路径代理</span></span><br><span class="line">    <span class="section">location</span> /api/ &#123;</span><br><span class="line">        <span class="attribute">proxy_pass</span> http://&lt;kubesphere_address&gt;:30880;</span><br><span class="line">        <span class="attribute">proxy_set_header</span>    Upgrade <span class="variable">$http_upgrade</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span>    X-Forwarded-Proto <span class="variable">$scheme</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span>    Connection <span class="string">&quot;upgrade&quot;</span>; </span><br><span class="line">        <span class="attribute">proxy_redirect</span> <span class="literal">off</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 一些特定 API 路径代理</span></span><br><span class="line">    <span class="section">location</span> <span class="regexp">~ /apis/monitoring.coreos.com/|/api/v1/|/apis/storage.k8s.io|/apis/apps/v1/namespaces/|/kapis/resources.kubesphere.io/v1alpha2/namespaces|/kapis/resources.kubesphere.io/|/apis/devops.kubesphere.io/|/apis/apps/v1/|/apis/|/api/v1/watch/namespaces|/kapis/terminal.kubesphere.io/</span> &#123;</span><br><span class="line">        <span class="attribute">proxy_pass</span> http://&lt;kubesphere_address&gt;:30880;</span><br><span class="line">        <span class="attribute">proxy_redirect</span> <span class="literal">off</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li></ol><h3 id="启动服务"><a href="#启动服务" class="headerlink" title="启动服务"></a>启动服务</h3><p>完成配置后，进入 <code>ks-console</code> 目录并运行以下命令启动 Nginx 代理服务：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">docker-compose up -d</span><br></pre></td></tr></table></figure><p>通过浏览器访问 KubeSphere 控制台，您应该能够通过配置的自定义域名访问控制台，如 <code>https://kubesphere.k8scluster.com:8443</code>。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt; 本文将介绍如何在 Kubernetes 集群中在线安装 KubeSphere，这是一个功能强大的容器管理平台，能够帮助用户方便地管理 Kubernetes 环境。我们将通过 Helm 进行安装，详细讲解每一步的操作流程，并展示如何通过浏览器访问 KubeSphere 控制台。最后，我们还会提供卸载 KubeSphere 的步骤，帮助您轻松管理平台的生命周期。&lt;/p&gt;</summary>
    
    
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/categories/Kubernetes/"/>
    
    
    <category term="Linux" scheme="https://freemankevin.uk/tags/Linux/"/>
    
    <category term="KubeSphere" scheme="https://freemankevin.uk/tags/KubeSphere/"/>
    
    <category term="Helm" scheme="https://freemankevin.uk/tags/Helm/"/>
    
  </entry>
  
  <entry>
    <title>Kubernetes Ingress-NGINX 生产级部署配置指南</title>
    <link href="https://freemankevin.uk/2025/01/21/k8s-ingress-nginx/"/>
    <id>https://freemankevin.uk/2025/01/21/k8s-ingress-nginx/</id>
    <published>2025-01-21T07:57:25.000Z</published>
    <updated>2026-04-17T10:30:31.805Z</updated>
    
    <content type="html"><![CDATA[<p>Ingress-NGINX 是 Kubernetes 集群流量管理的核心组件，提供七层负载均衡、TLS终止和路径路由等功能。本指南涵盖生产级部署、性能优化、TLS配置、安全加固和故障排查等核心内容，适用于构建企业级Kubernetes入口流量管理方案。</p><span id="more"></span><h2 id="Ingress-NGINX-架构概述"><a href="#Ingress-NGINX-架构概述" class="headerlink" title="Ingress-NGINX 架构概述"></a>Ingress-NGINX 架构概述</h2><h3 id="核心功能"><a href="#核心功能" class="headerlink" title="核心功能"></a>核心功能</h3><table><thead><tr><th>功能</th><th>说明</th><th>生产应用</th></tr></thead><tbody><tr><td>七层路由</td><td>基于域名&#x2F;路径的路由</td><td>微服务流量管理</td></tr><tr><td>TLS终止</td><td>SSL&#x2F;TLS证书管理</td><td>HTTPS服务暴露</td></tr><tr><td>负载均衡</td><td>多后端Pod流量分发</td><td>高可用保障</td></tr><tr><td>会话保持</td><td>基于Cookie的会话粘性</td><td>状态应用支持</td></tr><tr><td>速率限制</td><td>基于IP&#x2F;路径的限流</td><td>安全防护</td></tr><tr><td>监控指标</td><td>Prometheus集成</td><td>性能观测</td></tr></tbody></table><h3 id="部署模式"><a href="#部署模式" class="headerlink" title="部署模式"></a>部署模式</h3><p><strong>DaemonSet模式</strong>：每节点部署一个Pod</p><ul><li>优点：性能最优，无网络跳转</li><li>适用：大规模生产环境</li></ul><p><strong>Deployment模式</strong>：指定副本数部署</p><ul><li>优点：资源可控，灵活调度</li><li>适用：中小规模环境</li></ul><h3 id="拉取-Helm-包"><a href="#拉取-Helm-包" class="headerlink" title="拉取 Helm 包"></a>拉取 Helm 包</h3><p>首先，添加 <code>ingress-nginx</code> 官方仓库并更新仓库信息，接着拉取所需的 Helm 包。</p><h4 id="添加-Helm-仓库"><a href="#添加-Helm-仓库" class="headerlink" title="添加 Helm 仓库"></a>添加 Helm 仓库</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx</span><br><span class="line">helm repo update</span><br></pre></td></tr></table></figure><h4 id="搜索并拉取指定版本的-Helm-包"><a href="#搜索并拉取指定版本的-Helm-包" class="headerlink" title="搜索并拉取指定版本的 Helm 包"></a>搜索并拉取指定版本的 Helm 包</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">helm search repo ingress-nginx/ingress-nginx -l  <span class="comment"># 查看所有版本</span></span><br><span class="line">helm pull ingress-nginx/ingress-nginx --version 4.8.3  <span class="comment"># 拉取指定版本</span></span><br></pre></td></tr></table></figure><h4 id="解压-Helm-包"><a href="#解压-Helm-包" class="headerlink" title="解压 Helm 包"></a>解压 Helm 包</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">tar xf ingress-nginx-4.8.3.tgz</span><br><span class="line"><span class="built_in">cd</span> ingress-nginx</span><br></pre></td></tr></table></figure><h3 id="修改配置文件-values-yaml"><a href="#修改配置文件-values-yaml" class="headerlink" title="修改配置文件 values.yaml"></a>修改配置文件 <code>values.yaml</code></h3><p>在安装之前，您可能需要根据需求修改 <code>values.yaml</code> 文件，以配置 <code>ingress-nginx</code> 控制器的行为。常见的配置修改包括暴露 NodePort 端口。</p><h4 id="编辑-values-yaml-文件"><a href="#编辑-values-yaml-文件" class="headerlink" title="编辑 values.yaml 文件"></a>编辑 <code>values.yaml</code> 文件</h4><p>修改 <code>values.yaml</code> 文件中的 <code>service</code> 配置，将 <code>type</code> 设置为 <code>NodePort</code>，并配置 <code>nodePorts</code>。</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">service:</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">NodePort</span>  <span class="comment"># 设置为 NodePort 类型</span></span><br><span class="line">  <span class="attr">nodePorts:</span></span><br><span class="line">    <span class="attr">http:</span> <span class="string">&quot;30886&quot;</span>  <span class="comment"># HTTP 端口</span></span><br><span class="line">    <span class="attr">https:</span> <span class="string">&quot;30887&quot;</span>  <span class="comment"># HTTPS 端口</span></span><br><span class="line">    <span class="attr">tcp:</span> &#123;&#125;  <span class="comment"># TCP 端口配置（如果需要）</span></span><br><span class="line">    <span class="attr">udp:</span> &#123;&#125;  <span class="comment"># UDP 端口配置（如果需要）</span></span><br></pre></td></tr></table></figure><h3 id="安装-ingress-nginx-控制器"><a href="#安装-ingress-nginx-控制器" class="headerlink" title="安装 ingress-nginx 控制器"></a>安装 <code>ingress-nginx</code> 控制器</h3><p>安装 <code>ingress-nginx</code> 控制器并创建一个 <code>ingress-nginx</code> 命名空间：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">helm upgrade --install ingress-nginx ./ingress-nginx --namespace ingress-nginx --create-namespace</span><br></pre></td></tr></table></figure><p>安装完成后，您将看到类似以下输出：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Release &quot;ingress-nginx&quot; does not exist. Installing it now.</span><br><span class="line">NAME: ingress-nginx</span><br><span class="line">LAST DEPLOYED: Sat Dec 23 11:00:59 2023</span><br><span class="line">NAMESPACE: ingress-nginx</span><br><span class="line">STATUS: deployed</span><br></pre></td></tr></table></figure><h3 id="配置并测试-Ingress"><a href="#配置并测试-Ingress" class="headerlink" title="配置并测试 Ingress"></a>配置并测试 Ingress</h3><h4 id="创建一个简单的应用服务"><a href="#创建一个简单的应用服务" class="headerlink" title="创建一个简单的应用服务"></a>创建一个简单的应用服务</h4><p>为测试 <code>Ingress</code> 控制器，首先创建一个简单的 HTTP 服务：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl create deployment demo --image=httpd --port=80</span><br><span class="line">kubectl expose deployment demo</span><br></pre></td></tr></table></figure><h4 id="创建-Ingress-资源"><a href="#创建-Ingress-资源" class="headerlink" title="创建 Ingress 资源"></a>创建 Ingress 资源</h4><p>创建一个 <code>Ingress</code> 资源，配置一个简单的路由规则，指向刚才暴露的 <code>demo</code> 服务：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl create ingress demo-localhost --class=nginx \</span><br><span class="line">  --rule=<span class="string">&quot;demo.localdev.me/*=demo:80&quot;</span></span><br></pre></td></tr></table></figure><h4 id="使用-kubectl-port-forward-进行本地访问"><a href="#使用-kubectl-port-forward-进行本地访问" class="headerlink" title="使用 kubectl port-forward 进行本地访问"></a>使用 <code>kubectl port-forward</code> 进行本地访问</h4><p>通过 <code>port-forward</code> 将 Ingress 控制器暴露到本地端口：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl port-forward --namespace=ingress-nginx service/ingress-nginx-controller 8080:80</span><br></pre></td></tr></table></figure><p>接着，您可以通过以下方式测试：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">curl --resolve demo.localdev.me:8080:127.0.0.1 http://demo.localdev.me:8080</span><br></pre></td></tr></table></figure><p>您应当看到：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;html&gt;&lt;body&gt;&lt;h1&gt;It works!&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;</span><br></pre></td></tr></table></figure><h3 id="配置-TLS（HTTPS）"><a href="#配置-TLS（HTTPS）" class="headerlink" title="配置 TLS（HTTPS）"></a>配置 TLS（HTTPS）</h3><p>为了启用 HTTPS，需要创建一个包含证书和私钥的 Kubernetes Secret，并在 <code>Ingress</code> 资源中引用该 Secret。</p><h4 id="创建-TLS-证书"><a href="#创建-TLS-证书" class="headerlink" title="创建 TLS 证书"></a>创建 TLS 证书</h4><p>如果您没有现成的证书，可以使用 <code>openssl</code> 创建一个自签名证书（仅用于测试）：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout demo-tls.key -out demo-tls.crt</span><br></pre></td></tr></table></figure><p>这将生成 <code>demo-tls.crt</code> 和 <code>demo-tls.key</code> 文件。</p><h4 id="创建-Kubernetes-TLS-Secret"><a href="#创建-Kubernetes-TLS-Secret" class="headerlink" title="创建 Kubernetes TLS Secret"></a>创建 Kubernetes TLS Secret</h4><p>使用以下命令将证书和私钥创建为 Kubernetes Secret：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl create secret tls demo-tls-secret \</span><br><span class="line">  --cert=demo-tls.crt \</span><br><span class="line">  --key=demo-tls.key \</span><br><span class="line">  --namespace=default</span><br></pre></td></tr></table></figure><h4 id="配置-Ingress-使用-TLS"><a href="#配置-Ingress-使用-TLS" class="headerlink" title="配置 Ingress 使用 TLS"></a>配置 Ingress 使用 TLS</h4><p>编辑您的 <code>Ingress</code> 配置，引用刚刚创建的 <code>demo-tls-secret</code>：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Ingress</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">demo-tls-ingress</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">default</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">ingressClassName:</span> <span class="string">nginx</span></span><br><span class="line">  <span class="attr">rules:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">host:</span> <span class="string">www.demo.io</span></span><br><span class="line">    <span class="attr">http:</span></span><br><span class="line">      <span class="attr">paths:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">pathType:</span> <span class="string">Prefix</span></span><br><span class="line">        <span class="attr">path:</span> <span class="string">/</span></span><br><span class="line">        <span class="attr">backend:</span></span><br><span class="line">          <span class="attr">service:</span></span><br><span class="line">            <span class="attr">name:</span> <span class="string">demo</span></span><br><span class="line">            <span class="attr">port:</span></span><br><span class="line">              <span class="attr">number:</span> <span class="number">80</span></span><br><span class="line">  <span class="attr">tls:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">hosts:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">www.demo.io</span></span><br><span class="line">    <span class="attr">secretName:</span> <span class="string">demo-tls-secret</span>  <span class="comment"># 引用 TLS Secret</span></span><br></pre></td></tr></table></figure><h4 id="测试-TLS-配置"><a href="#测试-TLS-配置" class="headerlink" title="测试 TLS 配置"></a>测试 TLS 配置</h4><p>在 <code>Ingress</code> 配置完成后，您可以通过浏览器访问 <code>https://www.demo.io</code> 来验证 HTTPS 是否正常工作。如果一切配置正确，您应该能够安全地访问您的服务。</p><h3 id="配置本地-DNS（可选）"><a href="#配置本地-DNS（可选）" class="headerlink" title="配置本地 DNS（可选）"></a>配置本地 DNS（可选）</h3><p>如果您希望使用自定义域名访问服务，可以修改本地 <code>hosts</code> 文件，将域名指向相应的 IP 地址：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;192.168.1.120 www.demo.io&quot;</span> | <span class="built_in">sudo</span> <span class="built_in">tee</span> -a /etc/hosts</span><br></pre></td></tr></table></figure><p>之后，通过浏览器访问 <code>http://www.demo.io:30886/</code> 或 <code>https://www.demo.io:30887/</code> 来验证服务。</p><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>通过以上步骤，您成功安装并配置了 <code>ingress-nginx</code> 控制器，并通过 Kubernetes Secret 配置了 TLS 加密连接，确保了流量的安全传输。您还可以根据实际需求调整端口、证书和域名等配置，进一步优化您的部署。</p><h3 id="Q-A"><a href="#Q-A" class="headerlink" title="Q &amp; A"></a>Q &amp; A</h3><ol><li><p><strong>如何修改暴露端口？</strong><br>您可以通过编辑 <code>values.yaml</code> 文件中的 <code>nodePorts</code> 配置项，来修改暴露的端口号。</p></li><li><p><strong>如何启用 TLS？</strong><br>在 <code>Ingress</code> 配置文件中添加 <code>tls</code> 部分，并确保 Secret 包含有效的证书和私钥。</p></li><li><p><strong>如果使用自签名证书？</strong><br>使用自签名证书时，浏览器可能会显示不受信任的警告，您可以忽略这个警告，或者在浏览器中将证书添加到信任列表。</p></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;Ingress-NGINX 是 Kubernetes 集群流量管理的核心组件，提供七层负载均衡、TLS终止和路径路由等功能。本指南涵盖生产级部署、性能优化、TLS配置、安全加固和故障排查等核心内容，适用于构建企业级Kubernetes入口流量管理方案。&lt;/p&gt;</summary>
    
    
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/categories/Kubernetes/"/>
    
    <category term="Networking" scheme="https://freemankevin.uk/categories/Kubernetes/Networking/"/>
    
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/tags/Kubernetes/"/>
    
    <category term="TLS" scheme="https://freemankevin.uk/tags/TLS/"/>
    
    <category term="Ingress" scheme="https://freemankevin.uk/tags/Ingress/"/>
    
    <category term="NGINX" scheme="https://freemankevin.uk/tags/NGINX/"/>
    
  </entry>
  
  <entry>
    <title>Kubernetes ArgoCD GitOps持续交付平台部署指南</title>
    <link href="https://freemankevin.uk/2025/01/15/k8s-argocd/"/>
    <id>https://freemankevin.uk/2025/01/15/k8s-argocd/</id>
    <published>2025-01-15T09:47:25.000Z</published>
    <updated>2026-04-17T10:30:31.805Z</updated>
    
    <content type="html"><![CDATA[<p>ArgoCD 是 Kubernetes 环境下的 GitOps 持续交付工具，以声明式方式管理应用生命周期。本指南涵盖高可用部署、用户认证、RBAC配置、应用管理、同步策略和运维监控等核心内容，适用于构建企业级 GitOps 平台。</p><span id="more"></span><h2 id="ArgoCD-架构概述"><a href="#ArgoCD-架构概述" class="headerlink" title="ArgoCD 架构概述"></a>ArgoCD 架构概述</h2><h3 id="核心组件"><a href="#核心组件" class="headerlink" title="核心组件"></a>核心组件</h3><table><thead><tr><th>组件</th><th>功能</th><th>生产配置</th></tr></thead><tbody><tr><td>API Server</td><td>Web UI和API接口</td><td>高可用副本</td></tr><tr><td>Repo Server</td><td>Git仓库同步服务</td><td>多副本</td></tr><tr><td>Application Controller</td><td>应用状态控制器</td><td>单实例Leader选举</td></tr><tr><td>Dex</td><td>OIDC认证服务</td><td>可选，集成外部认证</td></tr></tbody></table><h3 id="GitOps-工作流程"><a href="#GitOps-工作流程" class="headerlink" title="GitOps 工作流程"></a>GitOps 工作流程</h3><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">┌──────────────┐</span><br><span class="line">│  Git Repo    │  应用配置定义</span><br><span class="line">│  (Source)    │</span><br><span class="line">└──────────────┘</span><br><span class="line">       │</span><br><span class="line">       │ ArgoCD 监听变更</span><br><span class="line">       ▼</span><br><span class="line">┌──────────────┐</span><br><span class="line">│   ArgoCD     │  配置同步引擎</span><br><span class="line">│  Controller  │</span><br><span class="line">└──────────────┘</span><br><span class="line">       │</span><br><span class="line">       │ 自动应用配置</span><br><span class="line">       ▼</span><br><span class="line">┌──────────────┐</span><br><span class="line">│ Kubernetes   │  目标集群</span><br><span class="line">│   Cluster    │</span><br><span class="line">└──────────────┘</span><br></pre></td></tr></table></figure><h3 id="部署模式"><a href="#部署模式" class="headerlink" title="部署模式"></a>部署模式</h3><p><strong>单实例模式</strong>：适合测试和小规模应用</p><ul><li>配置：单副本，共享存储</li><li>应用：开发&#x2F;测试环境</li></ul><p><strong>高可用模式</strong>：生产环境推荐</p><ul><li>配置：多副本Redis+副本池</li><li>应用：生产&#x2F;大规模环境</li></ul><h2 id="环境要求"><a href="#环境要求" class="headerlink" title="环境要求"></a>环境要求</h2><h3 id="基础环境"><a href="#基础环境" class="headerlink" title="基础环境"></a>基础环境</h3><ul><li>Kubernetes 集群 (版本 &gt;&#x3D; 1.21)</li><li>至少三个 Worker 节点（用于 HA 部署）</li><li>可用的持久化存储</li><li>集群负载均衡能力</li></ul><h3 id="版本选择"><a href="#版本选择" class="headerlink" title="版本选择"></a>版本选择</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查看版本兼容性</span></span><br><span class="line"><span class="comment"># https://argo-cd.readthedocs.io/en/stable/operator-manual/installation/#tested-versions</span></span><br></pre></td></tr></table></figure><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="code"><pre><span class="line"><span class="comment"># 下载 ArgoCD CLI</span></span><br><span class="line">curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/download/v2.9.2/argocd-linux-amd64</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装到系统目录</span></span><br><span class="line"><span class="built_in">sudo</span> install -m 555 argocd-linux-amd64 /usr/local/bin/argocd</span><br><span class="line"><span class="built_in">rm</span> argocd-linux-amd64</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证安装</span></span><br><span class="line">argocd version</span><br></pre></td></tr></table></figure><h3 id="多节点部署"><a href="#多节点部署" class="headerlink" title="多节点部署"></a>多节点部署</h3><p>在所有需要使用 ArgoCD CLI 的节点上执行安装：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 分发 CLI 到其他节点（根据实际环境修改节点名称）</span></span><br><span class="line"><span class="keyword">for</span> node <span class="keyword">in</span> &lt;node1&gt; &lt;node2&gt; &lt;node3&gt;; <span class="keyword">do</span></span><br><span class="line">  scp /usr/local/bin/argocd <span class="variable">$node</span>:/usr/local/bin/</span><br><span class="line">  ssh <span class="variable">$node</span> <span class="string">&quot;chmod +x /usr/local/bin/argocd&quot;</span></span><br><span class="line"><span class="keyword">done</span></span><br></pre></td></tr></table></figure><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="code"><pre><span class="line"><span class="comment"># 创建专用命名空间</span></span><br><span class="line">kubectl create namespace argocd</span><br></pre></td></tr></table></figure><h3 id="部署-ArgoCD"><a href="#部署-ArgoCD" class="headerlink" title="部署 ArgoCD"></a>部署 ArgoCD</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 添加 Helm 仓库</span></span><br><span class="line">helm repo add argo https://argoproj.github.io/argo-helm</span><br><span class="line">helm repo update</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建配置文件 values.yaml</span></span><br><span class="line"><span class="built_in">cat</span> &gt; values.yaml &lt;&lt;<span class="string">EOF</span></span><br><span class="line"><span class="string"># 全局配置</span></span><br><span class="line"><span class="string">global:</span></span><br><span class="line"><span class="string">  image:</span></span><br><span class="line"><span class="string">    repository: quay.io/argoproj/argocd</span></span><br><span class="line"><span class="string">    tag: v2.9.2</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"># HA 配置</span></span><br><span class="line"><span class="string">controller:</span></span><br><span class="line"><span class="string">  replicas: 2</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">server:</span></span><br><span class="line"><span class="string">  replicas: 2</span></span><br><span class="line"><span class="string">  service:</span></span><br><span class="line"><span class="string">    type: NodePort</span></span><br><span class="line"><span class="string">    nodePortHttp: &lt;HTTP_PORT&gt;    # 例如：30884</span></span><br><span class="line"><span class="string">    nodePortHttps: &lt;HTTPS_PORT&gt;  # 例如：30885</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"># Redis HA 配置</span></span><br><span class="line"><span class="string">redis-ha:</span></span><br><span class="line"><span class="string">  enabled: true</span></span><br><span class="line"><span class="string">  persistentVolume:</span></span><br><span class="line"><span class="string">    enabled: true</span></span><br><span class="line"><span class="string">    size: 8Gi</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"># 认证配置</span></span><br><span class="line"><span class="string">dex:</span></span><br><span class="line"><span class="string">  enabled: true</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"># 资源限制</span></span><br><span class="line"><span class="string">resources:</span></span><br><span class="line"><span class="string">  limits:</span></span><br><span class="line"><span class="string">    cpu: 500m</span></span><br><span class="line"><span class="string">    memory: 512Mi</span></span><br><span class="line"><span class="string">  requests:</span></span><br><span class="line"><span class="string">    cpu: 250m</span></span><br><span class="line"><span class="string">    memory: 256Mi</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装 ArgoCD</span></span><br><span class="line">helm install argocd argo/argo-cd \</span><br><span class="line">  --namespace argocd \</span><br><span class="line">  --values values.yaml</span><br></pre></td></tr></table></figure><h3 id="验证部署"><a href="#验证部署" class="headerlink" title="验证部署"></a>验证部署</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 检查 Pod 状态</span></span><br><span class="line">kubectl get pods -n argocd</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查服务状态</span></span><br><span class="line">kubectl get svc -n argocd</span><br></pre></td></tr></table></figure><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="code"><pre><span class="line"><span class="comment"># 配置 NodePort 访问（端口号根据实际情况调整）</span></span><br><span class="line">kubectl patch svc argocd-server -n argocd -p <span class="string">&#x27;&#123;</span></span><br><span class="line"><span class="string">  &quot;spec&quot;: &#123;</span></span><br><span class="line"><span class="string">    &quot;type&quot;: &quot;NodePort&quot;,</span></span><br><span class="line"><span class="string">    &quot;ports&quot;: [</span></span><br><span class="line"><span class="string">      &#123;&quot;nodePort&quot;: &lt;HTTP_PORT&gt;, &quot;port&quot;: 80&#125;,</span></span><br><span class="line"><span class="string">      &#123;&quot;nodePort&quot;: &lt;HTTPS_PORT&gt;, &quot;port&quot;: 443&#125;</span></span><br><span class="line"><span class="string">    ]</span></span><br><span class="line"><span class="string">  &#125;</span></span><br><span class="line"><span class="string">&#125;&#x27;</span></span><br></pre></td></tr></table></figure><h3 id="配置-DNS"><a href="#配置-DNS" class="headerlink" title="配置 DNS"></a>配置 DNS</h3><p>在 CoreDNS 中添加解析：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 编辑 CoreDNS 配置</span></span><br><span class="line"><span class="string">kubectl</span> <span class="string">-n</span> <span class="string">kube-system</span> <span class="string">edit</span> <span class="string">cm</span> <span class="string">coredns</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加以下配置（替换为实际的 IP 和域名）</span></span><br><span class="line"><span class="string">hosts</span> &#123;</span><br><span class="line">  <span class="string">&lt;NODE_IP&gt;</span> <span class="string">&lt;ARGOCD_DOMAIN&gt;</span>  <span class="comment"># 例如：argocd.example.com</span></span><br><span class="line">  <span class="string">fallthrough</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启 CoreDNS</span></span><br><span class="line"><span class="string">kubectl</span> <span class="string">delete</span> <span class="string">pod</span> <span class="string">-n</span> <span class="string">kube-system</span> <span class="string">-l</span> <span class="string">k8s-app=kube-dns</span></span><br></pre></td></tr></table></figure><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="code"><pre><span class="line"><span class="comment"># 获取管理员密码</span></span><br><span class="line">kubectl -n argocd get secret argocd-initial-admin-secret \</span><br><span class="line">  -o jsonpath=<span class="string">&quot;&#123;.data.password&#125;&quot;</span> | <span class="built_in">base64</span> -d</span><br></pre></td></tr></table></figure><h3 id="修改密码"><a href="#修改密码" class="headerlink" title="修改密码"></a>修改密码</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 登录 ArgoCD（使用实际的域名和端口）</span></span><br><span class="line">argocd login &lt;ARGOCD_DOMAIN&gt;:&lt;PORT&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 修改密码</span></span><br><span class="line">argocd account update-password</span><br></pre></td></tr></table></figure><h2 id="RBAC-配置"><a href="#RBAC-配置" class="headerlink" title="RBAC 配置"></a>RBAC 配置</h2><h3 id="角色配置"><a href="#角色配置" class="headerlink" title="角色配置"></a>角色配置</h3><p>编辑 <code>argocd-rbac-cm</code> 配置：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ConfigMap</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">argocd-rbac-cm</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">argocd</span></span><br><span class="line"><span class="attr">data:</span></span><br><span class="line">  <span class="attr">policy.csv:</span> <span class="string">|</span></span><br><span class="line"><span class="string">    # 项目管理员角色</span></span><br><span class="line"><span class="string">    p, role:project-admin, applications, create, project/*, allow</span></span><br><span class="line"><span class="string">    p, role:project-admin, applications, delete, project/*, allow</span></span><br><span class="line"><span class="string">    p, role:project-admin, applications, sync, project/*, allow</span></span><br><span class="line"><span class="string">    p, role:project-admin, applications, update, project/*, allow</span></span><br><span class="line"><span class="string">    p, role:project-admin, logs, get, project/*, allow</span></span><br><span class="line"><span class="string"></span>    </span><br><span class="line">    <span class="comment"># 只读角色</span></span><br><span class="line">    <span class="string">p,</span> <span class="string">role:readonly,</span> <span class="string">applications,</span> <span class="string">get,</span> <span class="string">*/*,</span> <span class="string">allow</span></span><br><span class="line">    <span class="string">p,</span> <span class="string">role:readonly,</span> <span class="string">logs,</span> <span class="string">get,</span> <span class="string">*/*,</span> <span class="string">allow</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment"># 用户组映射</span></span><br><span class="line">    <span class="string">g,</span> <span class="string">project-admins,</span> <span class="string">role:project-admin</span></span><br><span class="line">    <span class="string">g,</span> <span class="string">viewers,</span> <span class="string">role:readonly</span></span><br><span class="line">  </span><br><span class="line">  <span class="attr">policy.default:</span> <span class="string">role:readonly</span></span><br></pre></td></tr></table></figure><h3 id="用户管理"><a href="#用户管理" class="headerlink" title="用户管理"></a>用户管理</h3><p>编辑 <code>argocd-cm</code> 配置：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ConfigMap</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">argocd-cm</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">argocd</span></span><br><span class="line"><span class="attr">data:</span></span><br><span class="line">  <span class="comment"># 启用本地用户</span></span><br><span class="line">  <span class="attr">accounts.project-admin:</span> <span class="string">apiKey,login</span></span><br><span class="line">  <span class="attr">accounts.viewer:</span> <span class="string">login</span></span><br><span class="line">  </span><br><span class="line">  <span class="comment"># OIDC 配置（可选，根据实际环境配置）</span></span><br><span class="line">  <span class="attr">oidc.config:</span> <span class="string">|</span></span><br><span class="line"><span class="string">    name: &lt;SSO_PROVIDER&gt;</span></span><br><span class="line"><span class="string">    issuer: https://&lt;SSO_URL&gt;/auth/realms/&lt;REALM_NAME&gt;</span></span><br><span class="line"><span class="string">    clientID: &lt;CLIENT_ID&gt;</span></span><br><span class="line"><span class="string">    clientSecret: &lt;CLIENT_SECRET&gt;</span></span><br></pre></td></tr></table></figure><h2 id="高级配置"><a href="#高级配置" class="headerlink" title="高级配置"></a>高级配置</h2><h3 id="资源限制"><a href="#资源限制" class="headerlink" title="资源限制"></a>资源限制</h3><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 设置资源限制</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">template:</span></span><br><span class="line">    <span class="attr">spec:</span></span><br><span class="line">      <span class="attr">containers:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">argocd-application-controller</span></span><br><span class="line">        <span class="attr">resources:</span></span><br><span class="line">          <span class="attr">limits:</span></span><br><span class="line">            <span class="attr">cpu:</span> <span class="string">&quot;1&quot;</span></span><br><span class="line">            <span class="attr">memory:</span> <span class="string">1Gi</span></span><br><span class="line">          <span class="attr">requests:</span></span><br><span class="line">            <span class="attr">cpu:</span> <span class="string">250m</span></span><br><span class="line">            <span class="attr">memory:</span> <span class="string">512Mi</span></span><br></pre></td></tr></table></figure><h3 id="TLS-配置"><a href="#TLS-配置" class="headerlink" title="TLS 配置"></a>TLS 配置</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建 TLS 证书（使用实际的证书文件）</span></span><br><span class="line">kubectl create secret tls argocd-server-tls \</span><br><span class="line">  --cert=&lt;CERT_FILE&gt; \</span><br><span class="line">  --key=&lt;KEY_FILE&gt; \</span><br><span class="line">  -n argocd</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置 ArgoCD 使用证书</span></span><br><span class="line">kubectl patch deployment argocd-server \</span><br><span class="line">  -n argocd \</span><br><span class="line">  --<span class="built_in">type</span> json \</span><br><span class="line">  -p=<span class="string">&#x27;[&#123;&quot;op&quot;: &quot;add&quot;, &quot;path&quot;: &quot;/spec/template/spec/containers/0/args/-&quot;, &quot;value&quot;: &quot;--tls.certificate=/etc/argocd/tls/tls.crt&quot;&#125;, &#123;&quot;op&quot;: &quot;add&quot;, &quot;path&quot;: &quot;/spec/template/spec/containers/0/args/-&quot;, &quot;value&quot;: &quot;--tls.privatekey=/etc/argocd/tls/tls.key&quot;&#125;]&#x27;</span></span><br></pre></td></tr></table></figure><h2 id="故障排查"><a href="#故障排查" class="headerlink" title="故障排查"></a>故障排查</h2><h3 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h3><ol><li>登录问题</li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 检查密码是否正确</span></span><br><span class="line">argocd admin initial-password -n argocd</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查服务状态</span></span><br><span class="line">kubectl get pods -n argocd</span><br><span class="line">kubectl logs -f deployment/argocd-server -n argocd</span><br></pre></td></tr></table></figure><ol start="2"><li>同步失败</li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 检查应用状态</span></span><br><span class="line">argocd app get &lt;APP_NAME&gt;</span><br><span class="line">argocd app logs &lt;APP_NAME&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查控制器日志</span></span><br><span class="line">kubectl logs -f deployment/argocd-application-controller -n argocd</span><br></pre></td></tr></table></figure><h3 id="健康检查"><a href="#健康检查" class="headerlink" title="健康检查"></a>健康检查</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 检查组件状态</span></span><br><span class="line">kubectl get pods -n argocd</span><br><span class="line">kubectl get svc -n argocd</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查系统健康状态</span></span><br><span class="line">argocd admin cluster info</span><br></pre></td></tr></table></figure><h2 id="最佳实践"><a href="#最佳实践" class="headerlink" title="最佳实践"></a>最佳实践</h2><h3 id="安全建议"><a href="#安全建议" class="headerlink" title="安全建议"></a>安全建议</h3><ul><li>及时更新 ArgoCD 版本</li><li>使用 HTTPS 和证书</li><li>实施最小权限原则</li><li>定期轮换密钥和证书</li><li>启用审计日志</li></ul><h3 id="性能优化"><a href="#性能优化" class="headerlink" title="性能优化"></a>性能优化</h3><ul><li>合理配置资源限制</li><li>使用 Redis HA 提高可用性</li><li>配置合适的同步周期</li><li>使用项目配置限制资源范围</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;ArgoCD 是 Kubernetes 环境下的 GitOps 持续交付工具，以声明式方式管理应用生命周期。本指南涵盖高可用部署、用户认证、RBAC配置、应用管理、同步策略和运维监控等核心内容，适用于构建企业级 GitOps 平台。&lt;/p&gt;</summary>
    
    
    
    <category term="DevOps" scheme="https://freemankevin.uk/categories/DevOps/"/>
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/categories/DevOps/Kubernetes/"/>
    
    
    <category term="GitOps" scheme="https://freemankevin.uk/tags/GitOps/"/>
    
    <category term="ArgoCD" scheme="https://freemankevin.uk/tags/ArgoCD/"/>
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/tags/Kubernetes/"/>
    
    <category term="CD" scheme="https://freemankevin.uk/tags/CD/"/>
    
  </entry>
  
  <entry>
    <title>如何在Kubernetes 环境中部署GitLab Runner</title>
    <link href="https://freemankevin.uk/2025/01/15/k8s-runner/"/>
    <id>https://freemankevin.uk/2025/01/15/k8s-runner/</id>
    <published>2025-01-15T09:25:25.000Z</published>
    <updated>2026-04-17T10:30:31.805Z</updated>
    
    <content type="html"><![CDATA[<p> 本文将详细介绍如何在 Kubernetes 集群中部署 GitLab Runner，包括环境准备、Runner 配置、认证设置、网络支持、Harbor 集成等完整的部署和配置流程。</p><span id="more"></span><h2 id="环境要求"><a href="#环境要求" class="headerlink" title="环境要求"></a>环境要求</h2><h3 id="基础环境"><a href="#基础环境" class="headerlink" title="基础环境"></a>基础环境</h3><ul><li>Kubernetes 集群 (版本 &gt;&#x3D; 1.16)</li><li>Helm (版本 &gt;&#x3D; 3.9)</li><li>kubectl 已配置可访问集群</li><li>GitLab 服务器已部署(版本 &gt;&#x3D; 15.11)</li></ul><h3 id="版本选择"><a href="#版本选择" class="headerlink" title="版本选择"></a>版本选择</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查看可用的 Runner 版本</span></span><br><span class="line">helm repo add gitlab https://charts.gitlab.io</span><br><span class="line">helm repo update gitlab</span><br><span class="line">helm search repo -l gitlab/gitlab-runner | grep 15.11</span><br></pre></td></tr></table></figure><h2 id="Runner-安装配置"><a href="#Runner-安装配置" class="headerlink" title="Runner 安装配置"></a>Runner 安装配置</h2><h3 id="准备安装包"><a href="#准备安装包" class="headerlink" title="准备安装包"></a>准备安装包</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建工作目录</span></span><br><span class="line"><span class="built_in">mkdir</span> -p gitlab-runner &amp;&amp; <span class="built_in">cd</span> gitlab-runner</span><br><span class="line"></span><br><span class="line"><span class="comment"># 下载 Helm Chart</span></span><br><span class="line">helm pull gitlab/gitlab-runner --version v0.52.1</span><br><span class="line">tar xf gitlab-runner-0.52.1.tgz</span><br><span class="line"><span class="built_in">cp</span> gitlab-runner/values.yaml&#123;,.bak&#125;</span><br></pre></td></tr></table></figure><h3 id="配置-Runner"><a href="#配置-Runner" class="headerlink" title="配置 Runner"></a>配置 Runner</h3><p>编辑 <code>gitlab-runner/values.yaml</code> 配置文件：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># Runner 镜像配置</span></span><br><span class="line"><span class="attr">image:</span></span><br><span class="line">  <span class="attr">registry:</span> <span class="string">docker.io</span></span><br><span class="line">  <span class="attr">image:</span> <span class="string">gitlab/gitlab-runner</span></span><br><span class="line">  <span class="attr">tag:</span> <span class="string">alpine-v15.11.1</span></span><br><span class="line">  </span><br><span class="line"><span class="comment"># Harbor 认证配置</span></span><br><span class="line"><span class="attr">imagePullSecrets:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">&quot;harbor-credentials&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Runner 实例数</span></span><br><span class="line"><span class="attr">replicas:</span> <span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># GitLab 服务器配置</span></span><br><span class="line"><span class="attr">gitlabUrl:</span> <span class="string">http://your-gitlab-server:port/</span></span><br><span class="line"><span class="comment">#certsSecretName: runner-tls-chain   # 如果使用 HTTPS 则需要配置</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 并发任务数</span></span><br><span class="line"><span class="attr">concurrent:</span> <span class="number">10</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 日志级别</span></span><br><span class="line"><span class="attr">logLevel:</span> <span class="string">info</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># RBAC 配置</span></span><br><span class="line"><span class="attr">rbac:</span></span><br><span class="line">  <span class="attr">create:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 监控配置</span></span><br><span class="line"><span class="attr">metrics:</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">portName:</span> <span class="string">metrics</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">9252</span></span><br><span class="line">  <span class="attr">serviceMonitor:</span></span><br><span class="line">    <span class="attr">enabled:</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Runner 具体配置</span></span><br><span class="line"><span class="attr">runners:</span></span><br><span class="line">  <span class="attr">config:</span> <span class="string">|</span></span><br><span class="line"><span class="string">    [[runners]]</span></span><br><span class="line"><span class="string">      [runners.kubernetes]</span></span><br><span class="line"><span class="string">        namespace = &quot;&#123;&#123;.Release.Namespace&#125;&#125;&quot;</span></span><br><span class="line"><span class="string">        image = &quot;ubuntu:16.04&quot;</span></span><br><span class="line"><span class="string">      [runners.custom_build_dir]</span></span><br><span class="line"><span class="string">        enabled = true</span></span><br><span class="line"><span class="string">      # 缓存配置 - 使用 MinIO</span></span><br><span class="line"><span class="string">      [runners.cache]</span></span><br><span class="line"><span class="string">        Type = &quot;s3&quot;</span></span><br><span class="line"><span class="string">        Path = &quot;runner&quot;</span></span><br><span class="line"><span class="string">        Shared = true</span></span><br><span class="line"><span class="string">        [runners.cache.s3]</span></span><br><span class="line"><span class="string">          ServerAddress = &quot;your-minio-server:9000&quot;</span></span><br><span class="line"><span class="string">          BucketName = &quot;runner-cache&quot;</span></span><br><span class="line"><span class="string">          AccessKey = &quot;your-access-key&quot;</span></span><br><span class="line"><span class="string">          SecretKey = &quot;your-secret-key&quot;</span></span><br><span class="line"><span class="string">          Insecure = true</span></span><br><span class="line"><span class="string"></span></span><br><span class="line">  <span class="comment"># Runner 执行器配置</span></span><br><span class="line">  <span class="attr">executor:</span> <span class="string">kubernetes</span></span><br><span class="line">  <span class="attr">privileged:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">tags:</span> <span class="string">&quot;kubernetes&quot;</span></span><br><span class="line">  <span class="attr">secret:</span> <span class="string">gitlab-runner</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># 构建容器资源限制</span></span><br><span class="line">  <span class="attr">builds:</span> </span><br><span class="line">    <span class="attr">cpuLimit:</span> <span class="string">2010m</span></span><br><span class="line">    <span class="attr">cpuLimitOverwriteMaxAllowed:</span> <span class="string">2010m</span></span><br><span class="line">    <span class="attr">memoryLimit:</span> <span class="string">2060Mi</span></span><br><span class="line">    <span class="attr">memoryLimitOverwriteMaxAllowed:</span> <span class="string">2060Mi</span></span><br><span class="line">    <span class="attr">cpuRequests:</span> <span class="string">100m</span></span><br><span class="line">    <span class="attr">cpuRequestsOverwriteMaxAllowed:</span> <span class="string">100m</span></span><br><span class="line">    <span class="attr">memoryRequests:</span> <span class="string">128Mi</span></span><br><span class="line">    <span class="attr">memoryRequestsOverwriteMaxAllowed:</span> <span class="string">128Mi</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># 服务容器资源限制</span></span><br><span class="line">  <span class="attr">services:</span> </span><br><span class="line">    <span class="attr">cpuLimit:</span> <span class="string">200m</span></span><br><span class="line">    <span class="attr">memoryLimit:</span> <span class="string">256Mi</span></span><br><span class="line">    <span class="attr">cpuRequests:</span> <span class="string">100m</span></span><br><span class="line">    <span class="attr">memoryRequests:</span> <span class="string">128Mi</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># Helper 容器资源限制</span></span><br><span class="line">  <span class="attr">helpers:</span></span><br><span class="line">    <span class="attr">cpuLimit:</span> <span class="string">200m</span></span><br><span class="line">    <span class="attr">memoryLimit:</span> <span class="string">256Mi</span></span><br><span class="line">    <span class="attr">cpuRequests:</span> <span class="string">100m</span></span><br><span class="line">    <span class="attr">memoryRequests:</span> <span class="string">128Mi</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&quot;gitlab/gitlab-runner-helper:x86_64-v15.11.1&quot;</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># Runner Pod 资源限制</span></span><br><span class="line">  <span class="attr">resources:</span> </span><br><span class="line">    <span class="attr">limits:</span></span><br><span class="line">      <span class="attr">memory:</span> <span class="string">256Mi</span></span><br><span class="line">      <span class="attr">cpu:</span> <span class="string">200m</span></span><br><span class="line">    <span class="attr">requests:</span></span><br><span class="line">      <span class="attr">memory:</span> <span class="string">128Mi</span></span><br><span class="line">      <span class="attr">cpu:</span> <span class="string">100m</span></span><br></pre></td></tr></table></figure><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="code"><pre><span class="line">kubectl create ns gitlab-runner</span><br></pre></td></tr></table></figure><h3 id="配置镜像仓库认证"><a href="#配置镜像仓库认证" class="headerlink" title="配置镜像仓库认证"></a>配置镜像仓库认证</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建 Harbor 认证密钥</span></span><br><span class="line">kubectl create secret docker-registry harbor-credentials \</span><br><span class="line">    --docker-server=your-harbor-server \</span><br><span class="line">    --docker-username=your-robot-account \</span><br><span class="line">    --docker-password=your-robot-password \</span><br><span class="line">    -n gitlab-runner</span><br></pre></td></tr></table></figure><h3 id="配置-Runner-注册令牌"><a href="#配置-Runner-注册令牌" class="headerlink" title="配置 Runner 注册令牌"></a>配置 Runner 注册令牌</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建 Runner 注册密钥</span></span><br><span class="line">kubectl create secret generic gitlab-runner \</span><br><span class="line">  --from-literal=runner-registration-token=your-registration-token \</span><br><span class="line">  --from-literal=runner-token=<span class="string">&quot;&quot;</span> \</span><br><span class="line">  --<span class="built_in">type</span>=Opaque \</span><br><span class="line">  -n gitlab-runner</span><br></pre></td></tr></table></figure><h2 id="部署-Runner"><a href="#部署-Runner" class="headerlink" title="部署 Runner"></a>部署 Runner</h2><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 部署 Runner</span></span><br><span class="line">helm install gitlab-runner ./gitlab-runner \</span><br><span class="line">  -f gitlab-runner/values.yaml \</span><br><span class="line">  --namespace gitlab-runner \</span><br><span class="line">  --create-namespace</span><br></pre></td></tr></table></figure><h3 id="更新配置"><a href="#更新配置" class="headerlink" title="更新配置"></a>更新配置</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 更新 Runner 配置</span></span><br><span class="line">helm upgrade gitlab-runner ./gitlab-runner \</span><br><span class="line">  -f gitlab-runner/values.yaml \</span><br><span class="line">  --namespace gitlab-runner</span><br></pre></td></tr></table></figure><h3 id="卸载"><a href="#卸载" class="headerlink" title="卸载"></a>卸载</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 完全卸载 Runner</span></span><br><span class="line">helm -n gitlab-runner uninstall gitlab-runner</span><br></pre></td></tr></table></figure><h2 id="网络配置"><a href="#网络配置" class="headerlink" title="网络配置"></a>网络配置</h2><h3 id="GitLab-服务器配置"><a href="#GitLab-服务器配置" class="headerlink" title="GitLab 服务器配置"></a>GitLab 服务器配置</h3><ol><li>修改 GitLab 主配置：</li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 编辑 /etc/gitlab/gitlab.rb</span></span><br><span class="line">gitlab_rails[<span class="string">&#x27;outbound_local_requests&#x27;</span>] = &#123; <span class="string">&quot;allow&quot;</span> =&gt; <span class="literal">true</span> &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启 GitLab 服务</span></span><br><span class="line">gitlab-ctl restart</span><br></pre></td></tr></table></figure><ol start="2"><li>配置网络访问白名单：</li></ol><ul><li>访问路径：<code>http(s)://&lt;gitlab-server&gt;:&lt;port&gt;/admin/application_settings/network</code></li><li>启用以下选项：<ul><li><input checked="" disabled="" type="checkbox"> Allow requests to the local network from webhooks and integrations</li><li><input checked="" disabled="" type="checkbox"> Allow requests to the local network from system hooks</li></ul></li><li>添加允许访问的内网域名&#x2F;IP：<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">harbor.your-domain.com</span><br><span class="line">minio.your-domain.com</span><br><span class="line">traefik.your-domain.com</span><br><span class="line">argocd.your-domain.com</span><br><span class="line">yourserver-internal-ips</span><br></pre></td></tr></table></figure></li></ul><h2 id="Harbor-集成"><a href="#Harbor-集成" class="headerlink" title="Harbor 集成"></a>Harbor 集成</h2><h3 id="GitLab-配置-Harbor"><a href="#GitLab-配置-Harbor" class="headerlink" title="GitLab 配置 Harbor"></a>GitLab 配置 Harbor</h3><ol><li>访问配置页面：<code>http(s)://&lt;gitlab-server&gt;:&lt;port&gt;/groups/your-group/-/settings/integrations</code></li><li>找到 Harbor 配置区域：<ul><li><input checked="" disabled="" type="checkbox"> Enable integration</li><li>Harbor URL: <code>https://your-harbor-server</code></li><li>Harbor project name: <code>your-project-name</code></li><li>Harbor username: <code>your-robot-account</code></li><li>Harbor password: <code>your-robot-password</code></li></ul></li></ol><h3 id="配置-Harbor-证书"><a href="#配置-Harbor-证书" class="headerlink" title="配置 Harbor 证书"></a>配置 Harbor 证书</h3><p>在所有 Worker 节点上配置 Harbor 证书：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 复制证书</span></span><br><span class="line"><span class="built_in">cp</span> /etc/tls/harbor/ca.crt /etc/ssl/certs/</span><br><span class="line"><span class="built_in">cp</span> /etc/tls/harbor/harbor.cert /etc/ssl/certs/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 更新证书存储</span></span><br><span class="line">update-ca-certificates</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启容器运行时</span></span><br><span class="line">systemctl restart containerd</span><br></pre></td></tr></table></figure><h2 id="故障排查"><a href="#故障排查" class="headerlink" title="故障排查"></a>故障排查</h2><h3 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h3><ol><li>镜像拉取失败</li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 检查 Harbor 认证配置</span></span><br><span class="line">kubectl get secret harbor-credentials -n gitlab-runner</span><br><span class="line">kubectl describe secret harbor-credentials -n gitlab-runner</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查证书配置</span></span><br><span class="line"><span class="built_in">ls</span> -l /etc/ssl/certs/harbor*</span><br></pre></td></tr></table></figure><ol start="2"><li>Runner 注册失败</li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 检查 Runner 状态</span></span><br><span class="line">kubectl get pods -n gitlab-runner</span><br><span class="line">kubectl logs -f &lt;runner-pod-name&gt; -n gitlab-runner</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证 GitLab 连接</span></span><br><span class="line">curl -k https://your-gitlab-server/</span><br></pre></td></tr></table></figure><h3 id="资源限制验证"><a href="#资源限制验证" class="headerlink" title="资源限制验证"></a>资源限制验证</h3><p>检查 Runner Pod 的资源限制是否生效：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl get pod &lt;runner-pod-name&gt; -n gitlab-runner -o yaml</span><br></pre></td></tr></table></figure><h3 id="日志查看"><a href="#日志查看" class="headerlink" title="日志查看"></a>日志查看</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查看 Runner Pod 日志</span></span><br><span class="line">kubectl logs -f &lt;runner-pod-name&gt; -n gitlab-runner</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看构建任务 Pod 日志</span></span><br><span class="line">kubectl logs -f &lt;build-pod-name&gt; -n gitlab-runner</span><br></pre></td></tr></table></figure><h2 id="最佳实践"><a href="#最佳实践" class="headerlink" title="最佳实践"></a>最佳实践</h2><h3 id="资源配置建议"><a href="#资源配置建议" class="headerlink" title="资源配置建议"></a>资源配置建议</h3><ul><li>根据项目规模和构建需求调整资源限制</li><li>为不同类型的构建任务设置不同的资源配置</li><li>合理设置缓存策略，提高构建效率</li></ul><h3 id="安全建议"><a href="#安全建议" class="headerlink" title="安全建议"></a>安全建议</h3><ul><li>使用专用的 Runner 命名空间</li><li>配置适当的 RBAC 权限</li><li>定期更新 Runner 版本</li><li>使用 HTTPS 进行安全通信</li><li>妥善保管各类密钥和证书</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt; 本文将详细介绍如何在 Kubernetes 集群中部署 GitLab Runner，包括环境准备、Runner 配置、认证设置、网络支持、Harbor 集成等完整的部署和配置流程。&lt;/p&gt;</summary>
    
    
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/categories/Kubernetes/"/>
    
    
    <category term="GitLab" scheme="https://freemankevin.uk/tags/GitLab/"/>
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/tags/Kubernetes/"/>
    
    <category term="Helm" scheme="https://freemankevin.uk/tags/Helm/"/>
    
    <category term="Runner" scheme="https://freemankevin.uk/tags/Runner/"/>
    
  </entry>
  
  <entry>
    <title>如何在Kubernetes 环境中部署Traefik</title>
    <link href="https://freemankevin.uk/2025/01/15/k8s-traefik/"/>
    <id>https://freemankevin.uk/2025/01/15/k8s-traefik/</id>
    <published>2025-01-15T09:10:25.000Z</published>
    <updated>2026-04-17T10:30:31.805Z</updated>
    
    <content type="html"><![CDATA[<p> 本文将详细介绍如何在 Kubernetes 集群中安装和配置带有 TLS 的 Traefik Ingress Controller。包括环境准备、安装配置、TLS 证书管理、认证设置以及常见问题排查等完整流程。</p><span id="more"></span><h2 id="环境要求"><a href="#环境要求" class="headerlink" title="环境要求"></a>环境要求</h2><h3 id="基础环境要求"><a href="#基础环境要求" class="headerlink" title="基础环境要求"></a>基础环境要求</h3><ul><li>Kubernetes 集群 (版本 &gt;&#x3D; 1.16)</li><li>Helm (版本 &gt;&#x3D; 3.9)</li><li>kubectl 已配置可访问集群</li></ul><h3 id="版本信息"><a href="#版本信息" class="headerlink" title="版本信息"></a>版本信息</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 检查 helm 版本</span></span><br><span class="line">helm version</span><br></pre></td></tr></table></figure><h2 id="安装-Traefik"><a href="#安装-Traefik" class="headerlink" title="安装 Traefik"></a>安装 Traefik</h2><h3 id="添加-Helm-仓库"><a href="#添加-Helm-仓库" class="headerlink" title="添加 Helm 仓库"></a>添加 Helm 仓库</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 添加官方 helm 仓库</span></span><br><span class="line">helm repo add traefik https://traefik.github.io/charts</span><br><span class="line">helm repo update</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看可用版本</span></span><br><span class="line">helm search repo traefik/traefik -l</span><br></pre></td></tr></table></figure><h3 id="准备配置文件"><a href="#准备配置文件" class="headerlink" title="准备配置文件"></a>准备配置文件</h3><p>创建 <code>values.yaml</code> 配置文件：</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># Traefik 基础配置</span></span><br><span class="line"><span class="attr">ingressRoute:</span></span><br><span class="line">  <span class="attr">dashboard:</span></span><br><span class="line">    <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="attr">ingressClass:</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">isDefaultClass:</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="attr">providers:</span></span><br><span class="line">  <span class="attr">kubernetesCRD:</span></span><br><span class="line">    <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">allowCrossNamespace:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">allowExternalNameServices:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">kubernetesIngress:</span></span><br><span class="line">    <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">allowExternalNameServices:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 日志配置</span></span><br><span class="line"><span class="attr">logs:</span></span><br><span class="line">  <span class="attr">general:</span></span><br><span class="line">    <span class="attr">level:</span> <span class="string">DEBUG</span></span><br><span class="line">  <span class="attr">access:</span></span><br><span class="line">    <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 服务配置</span></span><br><span class="line"><span class="attr">service:</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">single:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">ClusterIP</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 额外参数</span></span><br><span class="line"><span class="attr">additionalArguments:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">&quot;--log.level=DEBUG&quot;</span></span><br></pre></td></tr></table></figure><h3 id="部署-Traefik"><a href="#部署-Traefik" class="headerlink" title="部署 Traefik"></a>部署 Traefik</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建命名空间并安装 Traefik</span></span><br><span class="line">helm install traefik traefik/traefik \</span><br><span class="line">  --namespace=traefik-v2 \</span><br><span class="line">  --create-namespace \</span><br><span class="line">  --values=values.yaml \</span><br><span class="line">  --version 25.0.0</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看部署状态</span></span><br><span class="line">kubectl get pods -n traefik-v2</span><br></pre></td></tr></table></figure><h2 id="配置-TLS"><a href="#配置-TLS" class="headerlink" title="配置 TLS"></a>配置 TLS</h2><h3 id="生成证书"><a href="#生成证书" class="headerlink" title="生成证书"></a>生成证书</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建证书目录</span></span><br><span class="line"><span class="built_in">mkdir</span> -p tls &amp;&amp; <span class="built_in">cd</span> tls</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建 CA 配置文件</span></span><br><span class="line"><span class="built_in">cat</span> &gt; openssl-ca.cnf &lt;&lt;<span class="string">EOF</span></span><br><span class="line"><span class="string">[req]</span></span><br><span class="line"><span class="string">distinguished_name = req_distinguished_name</span></span><br><span class="line"><span class="string">x509_extensions = v3_ca</span></span><br><span class="line"><span class="string">default_days = 3650</span></span><br><span class="line"><span class="string">default_md = sha256</span></span><br><span class="line"><span class="string">prompt = no</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">[req_distinguished_name]</span></span><br><span class="line"><span class="string">CN = My Root CA</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">[v3_ca]</span></span><br><span class="line"><span class="string">subjectKeyIdentifier=hash</span></span><br><span class="line"><span class="string">authorityKeyIdentifier=keyid:always,issuer</span></span><br><span class="line"><span class="string">basicConstraints = critical, CA:true </span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建服务器证书配置</span></span><br><span class="line"><span class="built_in">cat</span> &gt; openssl-server.cnf &lt;&lt;<span class="string">EOF</span></span><br><span class="line"><span class="string">[req]</span></span><br><span class="line"><span class="string">distinguished_name = req_distinguished_name</span></span><br><span class="line"><span class="string">x509_extensions = v3_req</span></span><br><span class="line"><span class="string">prompt = no</span></span><br><span class="line"><span class="string">default_days = 3650</span></span><br><span class="line"><span class="string">default_md = sha256</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">[req_distinguished_name]</span></span><br><span class="line"><span class="string">CN = traefik.k8scluster.com</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">[v3_req]</span></span><br><span class="line"><span class="string">keyUsage = digitalSignature, keyEncipherment</span></span><br><span class="line"><span class="string">extendedKeyUsage = serverAuth</span></span><br><span class="line"><span class="string">subjectAltName = @alt_names</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">[alt_names]</span></span><br><span class="line"><span class="string">DNS.1 = traefik.k8scluster.com</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成证书</span></span><br><span class="line">openssl genrsa -out rootCA.key 2048</span><br><span class="line">openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crt -config openssl-ca.cnf</span><br><span class="line">openssl genrsa -out server.key 2048</span><br><span class="line">openssl req -new -key server.key -out server.csr -config openssl-server.cnf</span><br><span class="line">openssl x509 -req -<span class="keyword">in</span> server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt -days 3650 -sha256 -extensions v3_req -extfile openssl-server.cnf</span><br></pre></td></tr></table></figure><h3 id="创建-TLS-Secret"><a href="#创建-TLS-Secret" class="headerlink" title="创建 TLS Secret"></a>创建 TLS Secret</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl create secret tls traefik-ingress-dashboard \</span><br><span class="line">  --namespace traefik-v2 \</span><br><span class="line">  --key ./server.key \</span><br><span class="line">  --cert ./server.crt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证证书</span></span><br><span class="line">kubectl -n traefik-v2 get secret traefik-ingress-dashboard -o jsonpath=<span class="string">&quot;&#123;.data.tls\.crt&#125;&quot;</span> | <span class="built_in">base64</span> --decode | openssl x509 -inform pem -text -noout</span><br></pre></td></tr></table></figure><h2 id="配置认证"><a href="#配置认证" class="headerlink" title="配置认证"></a>配置认证</h2><h3 id="创建-Basic-Auth"><a href="#创建-Basic-Auth" class="headerlink" title="创建 Basic Auth"></a>创建 Basic Auth</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 安装 htpasswd 工具</span></span><br><span class="line">apt-get update &amp;&amp; apt-get install apache2-utils -y</span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成密码</span></span><br><span class="line">htpasswd -nb admin &lt;your-password&gt; | kubectl create secret generic basic-auth \</span><br><span class="line">  --namespace=traefik-v2 \</span><br><span class="line">  --from-file=auth=/dev/stdin</span><br></pre></td></tr></table></figure><h3 id="创建-IngressRoute"><a href="#创建-IngressRoute" class="headerlink" title="创建 IngressRoute"></a>创建 IngressRoute</h3><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># traefik-websecure-dashboard.yaml</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">traefik.containo.us/v1alpha1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">IngressRoute</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">websecure-dashboard</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">traefik-v2</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">entryPoints:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">websecure</span></span><br><span class="line">  <span class="attr">routes:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">match:</span> <span class="string">Host(`traefik.k8scluster.com`)</span> <span class="string">&amp;&amp;</span> <span class="string">(PathPrefix(`/dashboard`)</span> <span class="string">||</span> <span class="string">PathPrefix(`/api`))</span></span><br><span class="line">      <span class="attr">kind:</span> <span class="string">Rule</span></span><br><span class="line">      <span class="attr">services:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">api@internal</span></span><br><span class="line">          <span class="attr">kind:</span> <span class="string">TraefikService</span></span><br><span class="line">      <span class="attr">middlewares:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">basic-auth</span></span><br><span class="line">          <span class="attr">namespace:</span> <span class="string">traefik-v2</span></span><br><span class="line">  <span class="attr">tls:</span></span><br><span class="line">    <span class="attr">secretName:</span> <span class="string">traefik-ingress-dashboard</span></span><br></pre></td></tr></table></figure><h3 id="创建认证中间件"><a href="#创建认证中间件" class="headerlink" title="创建认证中间件"></a>创建认证中间件</h3><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># traefik-middleware.yaml</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">traefik.containo.us/v1alpha1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Middleware</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">basic-auth</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">traefik-v2</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">basicAuth:</span></span><br><span class="line">    <span class="attr">secret:</span> <span class="string">basic-auth</span></span><br></pre></td></tr></table></figure><h2 id="暴露服务"><a href="#暴露服务" class="headerlink" title="暴露服务"></a>暴露服务</h2><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 配置 NodePort 服务</span></span><br><span class="line">kubectl patch svc traefik -n traefik-v2 -p <span class="string">&#x27;&#123;</span></span><br><span class="line"><span class="string">  &quot;spec&quot;: &#123;</span></span><br><span class="line"><span class="string">    &quot;type&quot;: &quot;NodePort&quot;,</span></span><br><span class="line"><span class="string">    &quot;ports&quot;: [</span></span><br><span class="line"><span class="string">      &#123;</span></span><br><span class="line"><span class="string">        &quot;name&quot;: &quot;web&quot;,</span></span><br><span class="line"><span class="string">        &quot;port&quot;: 80,</span></span><br><span class="line"><span class="string">        &quot;targetPort&quot;: &quot;web&quot;,</span></span><br><span class="line"><span class="string">        &quot;nodePort&quot;: 30882</span></span><br><span class="line"><span class="string">      &#125;,</span></span><br><span class="line"><span class="string">      &#123;</span></span><br><span class="line"><span class="string">        &quot;name&quot;: &quot;websecure&quot;,</span></span><br><span class="line"><span class="string">        &quot;port&quot;: 443,</span></span><br><span class="line"><span class="string">        &quot;targetPort&quot;: &quot;websecure&quot;,</span></span><br><span class="line"><span class="string">        &quot;nodePort&quot;: 30883</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">    ]</span></span><br><span class="line"><span class="string">  &#125;</span></span><br><span class="line"><span class="string">&#125;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证服务状态</span></span><br><span class="line">kubectl get svc -n traefik-v2</span><br></pre></td></tr></table></figure><h2 id="访问控制台"><a href="#访问控制台" class="headerlink" title="访问控制台"></a>访问控制台</h2><ol><li>添加域名解析（本地测试可修改 hosts 文件）：</li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$&#123;NODE_IP&#125;</span> traefik.k8scluster.com&quot;</span> &gt;&gt; /etc/hosts</span><br></pre></td></tr></table></figure><ol start="2"><li>访问地址：</li></ol><ul><li>Dashboard: <span class="exturl" data-url="aHR0cHM6Ly90cmFlZmlrLms4c2NsdXN0ZXIuY29tOjMwODgzL2Rhc2hib2FyZC8=">https://traefik.k8scluster.com:30883/dashboard/<i class="fa fa-external-link-alt"></i></span></li><li>使用之前设置的用户名密码登录</li></ul><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="code"><pre><span class="line"><span class="comment"># 检查证书是否正确创建</span></span><br><span class="line">kubectl get secret -n traefik-v2</span><br><span class="line">kubectl describe secret traefik-ingress-dashboard -n traefik-v2</span><br></pre></td></tr></table></figure><h3 id="访问问题"><a href="#访问问题" class="headerlink" title="访问问题"></a>访问问题</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 检查 Pod 状态</span></span><br><span class="line">kubectl get pods -n traefik-v2</span><br><span class="line">kubectl describe pod -n traefik-v2 &lt;pod-name&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查日志</span></span><br><span class="line">kubectl logs -n traefik-v2 &lt;pod-name&gt;</span><br></pre></td></tr></table></figure><h3 id="配置更新"><a href="#配置更新" class="headerlink" title="配置更新"></a>配置更新</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 更新 Traefik 配置</span></span><br><span class="line">helm upgrade traefik traefik/traefik \</span><br><span class="line">  --namespace=traefik-v2 \</span><br><span class="line">  --values=values.yaml</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt; 本文将详细介绍如何在 Kubernetes 集群中安装和配置带有 TLS 的 Traefik Ingress Controller。包括环境准备、安装配置、TLS 证书管理、认证设置以及常见问题排查等完整流程。&lt;/p&gt;</summary>
    
    
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/categories/Kubernetes/"/>
    
    
    <category term="Kubernetes" scheme="https://freemankevin.uk/tags/Kubernetes/"/>
    
    <category term="TLS" scheme="https://freemankevin.uk/tags/TLS/"/>
    
    <category term="NGINX" scheme="https://freemankevin.uk/tags/NGINX/"/>
    
    <category term="Traefik" scheme="https://freemankevin.uk/tags/Traefik/"/>
    
  </entry>
  
  <entry>
    <title>MinIO TLS 安全部署与 HTTPS 配置完整指南</title>
    <link href="https://freemankevin.uk/2025/01/15/tls-minio/"/>
    <id>https://freemankevin.uk/2025/01/15/tls-minio/</id>
    <published>2025-01-15T08:49:25.000Z</published>
    <updated>2026-04-17T10:30:31.809Z</updated>
    
    <content type="html"><![CDATA[<p>MinIO TLS安全部署是对象存储服务安全访问的核心配置，保障数据传输加密和身份验证。本指南涵盖TLS证书生成、MinIO服务配置、Nginx反向代理和安全最佳实践，适用于生产环境的MinIO安全部署架构。</p><span id="more"></span><h2 id="MinIO-TLS-架构设计"><a href="#MinIO-TLS-架构设计" class="headerlink" title="MinIO TLS 架构设计"></a>MinIO TLS 架构设计</h2><h3 id="TLS-加密传输流程"><a href="#TLS-加密传输流程" class="headerlink" title="TLS 加密传输流程"></a>TLS 加密传输流程</h3><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">┌──────────────────────────────────┐</span><br><span class="line">│  Client Application              │</span><br><span class="line">│  ┌────────────────────────────┐  │</span><br><span class="line">│  │ HTTPS Request              │  │</span><br><span class="line">│  │ https://minio.local:9000   │  │</span><br><span class="line">│  └────────────────────────────┘  │</span><br><span class="line">└──────────────────────────────────┘</span><br><span class="line">         │</span><br><span class="line">         │ TLS Handshake (1.2/1.3)</span><br><span class="line">         │ Certificate Verification</span><br><span class="line">         ▼</span><br><span class="line">┌──────────────────────────────────┐</span><br><span class="line">│  MinIO Server (TLS Mode)         │</span><br><span class="line">│  ┌────────────────────────────┐  │</span><br><span class="line">│  │ TLS Certificate            │  │</span><br><span class="line">│  │ /etc/minio/ssl/certs/      │  │</span><br><span class="line">│  │  ├─ public.crt             │  │</span><br><span class="line">│  │  ├─ private.key            │  │</span><br><span class="line">│  │  └─ ca.crt                 │  │</span><br><span class="line">│  └────────────────────────────┘  │</span><br><span class="line">│                                  │</span><br><span class="line">│  ┌────────────────────────────┐  │</span><br><span class="line">│  │ Encrypted Communication    │  │</span><br><span class="line">│  │ AES-256-GCM加密             │  │</span><br><span class="line">│  └────────────────────────────┘  │</span><br><span class="line">└──────────────────────────────────┘</span><br></pre></td></tr></table></figure><h3 id="TLS-证书类型选择"><a href="#TLS-证书类型选择" class="headerlink" title="TLS 证书类型选择"></a>TLS 证书类型选择</h3><table><thead><tr><th>证书类型</th><th>适用场景</th><th>成本</th><th>安全性</th><th>生产推荐</th></tr></thead><tbody><tr><td>自签名证书</td><td>内网测试</td><td>免费</td><td>中等</td><td>开发环境</td></tr><tr><td>企业CA证书</td><td>内部系统</td><td>低</td><td>高</td><td>企业首选</td></tr><tr><td>公共CA证书</td><td>公网服务</td><td>中-高</td><td>最高</td><td>生产首选</td></tr><tr><td>Let’s Encrypt</td><td>公网免费</td><td>免费</td><td>高</td><td>成本优化</td></tr></tbody></table><h3 id="MinIO-TLS-配置方式"><a href="#MinIO-TLS-配置方式" class="headerlink" title="MinIO TLS 配置方式"></a>MinIO TLS 配置方式</h3><table><thead><tr><th>配置方式</th><th>配置路径</th><th>优势</th><th>适用场景</th></tr></thead><tbody><tr><td>内置TLS</td><td>&#x2F;etc&#x2F;minio&#x2F;certs</td><td>简单快速</td><td>小规模部署</td></tr><tr><td>Nginx代理</td><td>Nginx配置文件</td><td>灵活负载</td><td>大规模生产</td></tr><tr><td>Traefik代理</td><td>动态配置</td><td>自动证书</td><td>Kubernetes</td></tr><tr><td>HAProxy代理</td><td>高可用</td><td>性能优化</td><td>高并发场景</td></tr></tbody></table><h3 id="TLS-安全配置要点"><a href="#TLS-安全配置要点" class="headerlink" title="TLS 安全配置要点"></a>TLS 安全配置要点</h3><table><thead><tr><th>配置项</th><th>推荐值</th><th>说明</th></tr></thead><tbody><tr><td>TLS版本</td><td>TLS 1.2&#x2F;1.3</td><td>安全协议</td></tr><tr><td>加密套件</td><td>AES-256-GCM</td><td>强加密</td></tr><tr><td>证书有效期</td><td>365天</td><td>定期更换</td></tr><tr><td>CA链验证</td><td>完整链</td><td>身份验证</td></tr><tr><td>HSTS</td><td>启用</td><td>强制HTTPS</td></tr></tbody></table><h2 id="安装-MinIO-服务"><a href="#安装-MinIO-服务" class="headerlink" title="安装 MinIO 服务"></a>安装 MinIO 服务</h2><h3 id="安装MinIO服务端"><a href="#安装MinIO服务端" class="headerlink" title="安装MinIO服务端"></a>安装MinIO服务端</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加MinIO仓库</span></span><br><span class="line">curl -O https://dl.min.io/repos/minio-repo.sh</span><br><span class="line">sh minio-repo.sh</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装MinIO</span></span><br><span class="line">apt update &amp;&amp; apt install minio -y</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证安装</span></span><br><span class="line">minio --version</span><br></pre></td></tr></table></figure><h3 id="安装MinIO客户端-可选"><a href="#安装MinIO客户端-可选" class="headerlink" title="安装MinIO客户端(可选)"></a>安装MinIO客户端(可选)</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">下载MinIO客户端</span></span><br><span class="line">curl https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc</span><br><span class="line">chmod +x /usr/local/bin/mc</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">验证安装</span></span><br><span class="line">mc --version</span><br></pre></td></tr></table></figure><h2 id="配置TLS证书"><a href="#配置TLS证书" class="headerlink" title="配置TLS证书"></a>配置TLS证书</h2><h3 id="创建证书目录"><a href="#创建证书目录" class="headerlink" title="创建证书目录"></a>创建证书目录</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">mkdir -p /etc/minio/ssl/certs &amp;&amp; cd /etc/minio/ssl/certs</span><br></pre></td></tr></table></figure><h3 id="生成CA配置"><a href="#生成CA配置" class="headerlink" title="生成CA配置"></a>生成CA配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">cat &gt; openssl-ca.cnf &lt;&lt;EOF</span><br><span class="line">[req]</span><br><span class="line">distinguished_name = req_distinguished_name</span><br><span class="line">x509_extensions = v3_ca</span><br><span class="line">default_days = 3650</span><br><span class="line">default_md = sha256</span><br><span class="line">prompt = no</span><br><span class="line"></span><br><span class="line">[req_distinguished_name]</span><br><span class="line">CN = My Root CA</span><br><span class="line"></span><br><span class="line">[v3_ca]</span><br><span class="line">subjectKeyIdentifier=hash</span><br><span class="line">authorityKeyIdentifier=keyid:always,issuer</span><br><span class="line">basicConstraints = critical, CA:true</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h3 id="生成服务器证书配置"><a href="#生成服务器证书配置" class="headerlink" title="生成服务器证书配置"></a>生成服务器证书配置</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">cat &gt; openssl-server.cnf &lt;&lt;EOF</span><br><span class="line">[req]</span><br><span class="line">distinguished_name = req_distinguished_name</span><br><span class="line">x509_extensions = v3_req</span><br><span class="line">prompt = no</span><br><span class="line">default_days = 3650</span><br><span class="line">default_md = sha256</span><br><span class="line"></span><br><span class="line">[req_distinguished_name]</span><br><span class="line">CN = minio.objectstorage.com</span><br><span class="line"></span><br><span class="line">[v3_req]</span><br><span class="line">keyUsage = digitalSignature, keyEncipherment</span><br><span class="line">extendedKeyUsage = serverAuth</span><br><span class="line">subjectAltName = @alt_names</span><br><span class="line"></span><br><span class="line">[alt_names]</span><br><span class="line">DNS.1 = minio.objectstorage.com</span><br><span class="line">IP.1 = YOUR_SERVER_IP</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h3 id="生成证书"><a href="#生成证书" class="headerlink" title="生成证书"></a>生成证书</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成CA证书</span></span><br><span class="line">openssl genrsa -out rootCA.key 2048</span><br><span class="line">openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crt -config openssl-ca.cnf</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成服务器证书</span></span><br><span class="line">openssl genrsa -out server.key 2048</span><br><span class="line">openssl req -new -key server.key -out server.csr -config openssl-server.cnf</span><br><span class="line">openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial \</span><br><span class="line">    -out server.crt -days 3650 -sha256 -extensions v3_req -extfile openssl-server.cnf</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重命名为MinIO所需的文件名</span></span><br><span class="line">mv server.key private.key</span><br><span class="line">mv server.crt public.crt</span><br></pre></td></tr></table></figure><h2 id="配置MinIO服务"><a href="#配置MinIO服务" class="headerlink" title="配置MinIO服务"></a>配置MinIO服务</h2><h3 id="创建数据目录"><a href="#创建数据目录" class="headerlink" title="创建数据目录"></a>创建数据目录</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">mkdir -p /data/minio</span><br></pre></td></tr></table></figure><h3 id="配置MinIO环境"><a href="#配置MinIO环境" class="headerlink" title="配置MinIO环境"></a>配置MinIO环境</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">cat &gt; /etc/default/minio &lt;&lt;EOF</span><br><span class="line">MINIO_ROOT_USER=admin</span><br><span class="line">MINIO_ROOT_PASSWORD=admin@123</span><br><span class="line">MINIO_VOLUMES=&quot;/data/minio&quot;</span><br><span class="line">MINIO_SERVER_URL=&quot;https://minio.objectstorage.com:9000&quot;</span><br><span class="line">MINIO_OPTS=&quot;--address :9000 --certs-dir /etc/minio/ssl/certs --console-address :9001&quot;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h3 id="设置权限"><a href="#设置权限" class="headerlink" title="设置权限"></a>设置权限</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">useradd -r minio-user -s /sbin/nologin</span><br><span class="line">chown -R minio-user:minio-user /data/minio</span><br><span class="line">chown -R minio-user:minio-user /etc/minio</span><br></pre></td></tr></table></figure><h2 id="配置Nginx代理"><a href="#配置Nginx代理" class="headerlink" title="配置Nginx代理"></a>配置Nginx代理</h2><h3 id="安装Nginx"><a href="#安装Nginx" class="headerlink" title="安装Nginx"></a>安装Nginx</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">apt update &amp;&amp; apt install nginx -y</span><br></pre></td></tr></table></figure><h3 id="配置Nginx代理-1"><a href="#配置Nginx代理-1" class="headerlink" title="配置Nginx代理"></a>配置Nginx代理</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">cat &gt; /etc/nginx/conf.d/minio.conf &lt;&lt;EOF</span><br><span class="line">upstream minio_s3 &#123;</span><br><span class="line">    server localhost:9000;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">upstream minio_console &#123;</span><br><span class="line">    server localhost:9001;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">server &#123;</span><br><span class="line">    listen 443 ssl;</span><br><span class="line">    server_name minio.objectstorage.com;</span><br><span class="line"></span><br><span class="line">    ssl_certificate /etc/nginx/ssl/minio/public.crt;</span><br><span class="line">    ssl_certificate_key /etc/nginx/ssl/minio/private.key;</span><br><span class="line"></span><br><span class="line">    # 代理MinIO API</span><br><span class="line">    location / &#123;</span><br><span class="line">        proxy_set_header Host \$http_host;</span><br><span class="line">        proxy_set_header X-Real-IP \$remote_addr;</span><br><span class="line">        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;</span><br><span class="line">        proxy_set_header X-Forwarded-Proto \$scheme;</span><br><span class="line"></span><br><span class="line">        proxy_connect_timeout 300;</span><br><span class="line">        proxy_http_version 1.1;</span><br><span class="line">        proxy_set_header Connection &quot;&quot;;</span><br><span class="line">        chunked_transfer_encoding off;</span><br><span class="line"></span><br><span class="line">        proxy_pass http://minio_s3;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">server &#123;</span><br><span class="line">    listen 9443 ssl;</span><br><span class="line">    server_name minio.objectstorage.com;</span><br><span class="line"></span><br><span class="line">    ssl_certificate /etc/nginx/ssl/minio/public.crt;</span><br><span class="line">    ssl_certificate_key /etc/nginx/ssl/minio/private.key;</span><br><span class="line"></span><br><span class="line">    # 代理MinIO Console</span><br><span class="line">    location / &#123;</span><br><span class="line">        proxy_set_header Host \$http_host;</span><br><span class="line">        proxy_set_header X-Real-IP \$remote_addr;</span><br><span class="line">        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;</span><br><span class="line">        proxy_set_header X-Forwarded-Proto \$scheme;</span><br><span class="line"></span><br><span class="line">        proxy_connect_timeout 300;</span><br><span class="line">        proxy_http_version 1.1;</span><br><span class="line">        proxy_set_header Upgrade \$http_upgrade;</span><br><span class="line">        proxy_set_header Connection &quot;upgrade&quot;;</span><br><span class="line"></span><br><span class="line">        proxy_pass http://minio_console;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h2 id="启动服务"><a href="#启动服务" class="headerlink" title="启动服务"></a>启动服务</h2><h3 id="启动MinIO"><a href="#启动MinIO" class="headerlink" title="启动MinIO"></a>启动MinIO</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">systemctl start minio</span><br><span class="line">systemctl enable minio</span><br></pre></td></tr></table></figure><h3 id="启动Nginx"><a href="#启动Nginx" class="headerlink" title="启动Nginx"></a>启动Nginx</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">systemctl start nginx</span><br><span class="line">systemctl enable nginx</span><br></pre></td></tr></table></figure><h2 id="验证部署"><a href="#验证部署" class="headerlink" title="验证部署"></a>验证部署</h2><h3 id="检查服务状态"><a href="#检查服务状态" class="headerlink" title="检查服务状态"></a>检查服务状态</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">systemctl status minio</span><br><span class="line">systemctl status nginx</span><br></pre></td></tr></table></figure><h3 id="验证访问"><a href="#验证访问" class="headerlink" title="验证访问"></a>验证访问</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">测试API端点</span></span><br><span class="line">curl -k https://minio.objectstorage.com/minio/health</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">访问控制台</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在浏览器中访问 https://minio.objectstorage.com:9443</span></span><br></pre></td></tr></table></figure><h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><h3 id="安全建议"><a href="#安全建议" class="headerlink" title="安全建议"></a>安全建议</h3><ol><li><p>访问控制：</p><ul><li>修改默认的管理员密码，使用强密码策略</li><li>使用策略管理访问权限，遵循最小权限原则</li><li>定期审计访问日志，监控异常访问</li><li>配置IP白名单，限制管理控制台访问范围</li></ul></li><li><p>证书管理：</p><ul><li>使用合适的证书有效期（建议1-2年）</li><li>设置证书到期提醒机制</li><li>保管好证书私钥，避免泄露</li><li>定期更新证书，确保TLS安全</li></ul></li><li><p>网络安全：</p><ul><li>配置防火墙规则，只开放必要端口</li><li>使用安全的TLS版本（TLS 1.2+）</li><li>禁用不安全的加密套件</li><li>配置适当的请求速率限制</li></ul></li></ol><h3 id="性能优化"><a href="#性能优化" class="headerlink" title="性能优化"></a>性能优化</h3><ol><li>系统配置：<ul><li>调整系统文件描述符限制</li></ul></li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">/etc/security/limits.conf</span></span><br><span class="line">minio-user soft nofile 65536</span><br><span class="line">minio-user hard nofile 65536</span><br></pre></td></tr></table></figure><ol start="2"><li><p>存储优化：</p><ul><li>使用XFS文件系统获得更好性能</li><li>配置合适的磁盘预读值</li><li>启用磁盘缓存</li><li>定期进行碎片整理</li></ul></li><li><p>网络优化：</p><ul><li>调整TCP参数优化网络性能</li><li>配置合适的Nginx worker进程数</li><li>启用Nginx压缩减少传输量</li><li>配置客户端缓存策略</li></ul></li></ol><h3 id="维护建议"><a href="#维护建议" class="headerlink" title="维护建议"></a>维护建议</h3><ol><li><p>数据备份：</p><ul><li>制定定期备份计划</li><li>验证备份数据的完整性</li><li>存储多个备份副本</li><li>测试数据恢复流程</li></ul></li><li><p>监控告警：</p><ul><li>监控服务状态和资源使用</li><li>设置磁盘空间告警阈值</li><li>监控证书有效期</li><li>配置服务可用性监控</li></ul></li><li><p>版本管理：</p><ul><li>关注安全更新和补丁</li><li>在测试环境验证新版本</li><li>制定回滚计划</li><li>记录版本变更日志</li></ul></li></ol><h3 id="故障排查"><a href="#故障排查" class="headerlink" title="故障排查"></a>故障排查</h3><ol><li><p>常见问题：</p><ul><li>证书配置错误：检查证书路径和权限</li><li>端口冲突：确认端口占用情况</li><li>权限问题：检查目录和文件权限</li><li>网络连接：验证防火墙和网络配置</li></ul></li><li><p>日志分析：</p></li></ol><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">MinIO日志</span></span><br><span class="line">tail -f /var/log/minio/minio.log</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Nginx访问日志</span></span><br><span class="line">tail -f /var/log/nginx/access.log</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Nginx错误日志</span></span><br><span class="line">tail -f /var/log/nginx/error.log</span><br></pre></td></tr></table></figure><ol start="3"><li>服务恢复：<ul><li>保存问题现场，收集相关日志</li><li>按照标准流程进行故障处理</li><li>记录解决方案，更新文档</li><li>总结经验教训，优化流程</li></ul></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;MinIO TLS安全部署是对象存储服务安全访问的核心配置，保障数据传输加密和身份验证。本指南涵盖TLS证书生成、MinIO服务配置、Nginx反向代理和安全最佳实践，适用于生产环境的MinIO安全部署架构。&lt;/p&gt;</summary>
    
    
    
    <category term="Storage" scheme="https://freemankevin.uk/categories/Storage/"/>
    
    <category term="Security" scheme="https://freemankevin.uk/categories/Storage/Security/"/>
    
    
    <category term="MinIO" scheme="https://freemankevin.uk/tags/MinIO/"/>
    
    <category term="TLS" scheme="https://freemankevin.uk/tags/TLS/"/>
    
    <category term="HTTPS" scheme="https://freemankevin.uk/tags/HTTPS/"/>
    
    <category term="Certificate" scheme="https://freemankevin.uk/tags/Certificate/"/>
    
  </entry>
  
</feed>
