<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://cloudnative.love/blog</id>
    <title>CloudNative.love 💕 Blog</title>
    <updated>2025-01-11T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://cloudnative.love/blog"/>
    <subtitle>CloudNative.love 💕 Blog</subtitle>
    <icon>https://cloudnative.love/img/favicon.png</icon>
    <entry>
        <title type="html"><![CDATA[terraform libvirt fix debug]]></title>
        <id>https://cloudnative.love/blog/2025/01/11/terraform-libvirt debug/README</id>
        <link href="https://cloudnative.love/blog/2025/01/11/terraform-libvirt debug/README"/>
        <updated>2025-01-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[我本地使用 terraform 管理我的 kvm libvirt 。]]></summary>
        <content type="html"><![CDATA[<p>我本地使用 terraform 管理我的 kvm libvirt 。</p>
<p>当使用 qemu-guest-agent 获取 ip 时遇到了问题，本文记录排查和代码修复过程。</p>
<ul>
<li>我提的 issue：<a href="https://github.com/dmacvicar/terraform-provider-libvirt/issues/1091#event-16519515888" target="_blank" rel="noopener noreferrer">https://github.com/dmacvicar/terraform-provider-libvirt/issues/1091#event-16519515888</a></li>
<li>我提的 pull request 已经合并：<a href="https://github.com/dmacvicar/terraform-provider-libvirt/pull/1144" target="_blank" rel="noopener noreferrer">https://github.com/dmacvicar/terraform-provider-libvirt/pull/1144</a></li>
<li>在 release v0.8.2 中已经发布：<a href="https://github.com/dmacvicar/terraform-provider-libvirt/discussions/1162" target="_blank" rel="noopener noreferrer">https://github.com/dmacvicar/terraform-provider-libvirt/discussions/1162</a></li>
</ul>
<p><img decoding="async" loading="lazy" alt="alt text" src="https://cloudnative.love/assets/images/image-59469377b5af11def34dbe54281359ed.png" width="1503" height="1593" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="debug">debug<a href="https://cloudnative.love/blog/2025/01/11/terraform-libvirt%20debug/README#debug" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>经过分析，了关键的区别如下：</p>
<ol>
<li>在 0.7.1 版本中，<code>domainGetIfacesInfo</code>&nbsp; 函数对错误处理有特殊的逻辑：</li>
</ol>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> virErr </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> err</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">type</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Error</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Agent can be unresponsive if being installed/setup</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> addrsrc </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">uint32</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">DomainInterfaceAddressesSrcLease</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> virErr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Code </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">uint32</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ErrOperationInvalid</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        addrsrc </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">uint32</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">DomainInterfaceAddressesSrcAgent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> virErr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Code </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">uint32</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ErrAgentUnresponsive</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> interfaces</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> fmt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Errorf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Error retrieving interface addresses: %w"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> err</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ol start="2">
<li>而在最新版本中，错误处理变得更简单：</li>
</ol>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> interfaces</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> fmt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Errorf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"error retrieving interface addresses: %w"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> err</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>这就是导致问题的关键：</p>
<ol>
<li>
<p>在 0.7.1 版本中，如果使用 qemu-agent 获取 IP 地址时遇到 &nbsp;<code>ErrAgentUnresponsive</code>&nbsp; 错误，代码会忽略这个错误并继续尝试，这给了 qemu-agent 启动和响应的时间。</p>
</li>
<li>
<p>在新版本中，任何错误都会直接返回，包括 &nbsp;<code>ErrAgentUnresponsive</code>，这导致在 qemu-agent 还没有完全启动和响应时就失败了。</p>
</li>
</ol>
<p>解决方案有 2 个：</p>
<ol>
<li>修改 provider 代码，恢复 0.7.1 版本的错误处理逻辑，提交 PR 到上游。修改内容大致如下：</li>
</ol>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">domainGetIfacesInfo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">virConn </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Libvirt</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> domain libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Domain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> rd </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">schema</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ResourceData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">DomainInterface</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//...省略</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 这里开始修改</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// get all the interfaces attached to libvirt networks</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> interfaces </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">DomainInterface</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	interfaces</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> virConn</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">DomainInterfaceAddresses</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">domain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> addrsrc</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> virErr </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> err</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">type</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Error</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token comment" style="color:#999988;font-style:italic">// Agent can be unresponsive if being installed/setup</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> addrsrc </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">uint32</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">DomainInterfaceAddressesSrcLease</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> virErr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Code </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">uint32</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ErrOperationInvalid</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">				addrsrc </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">uint32</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">DomainInterfaceAddressesSrcAgent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> virErr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Code </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">uint32</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">libvirt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ErrAgentUnresponsive</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">				</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> interfaces</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> fmt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Errorf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"error retrieving interface addresses: %w"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> err</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token comment" style="color:#999988;font-style:italic">// 如果是 ErrAgentUnresponsive，继续尝试</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> interfaces</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">default</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> interfaces</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> fmt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Errorf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"error retrieving interface addresses: %w"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> virErr</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> interfaces</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="terraform-本地插件">terraform 本地插件<a href="https://cloudnative.love/blog/2025/01/11/terraform-libvirt%20debug/README#terraform-%E6%9C%AC%E5%9C%B0%E6%8F%92%E4%BB%B6" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>由于上游合并需要时间，在此间我是用本地插件机制来使用我编译后的插件，如下放入指定位置然后引用既可。</p>
<div class="language-terraform codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-terraform codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">  required_providers {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    libvirt = {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      source  = "local/providers/libvirt"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      version = "1.0.0"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">```</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">```bash</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">~/.terraform.d/plugins/local/providers/libvirt/1.0.0/linux_amd64/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">~/.terraform.d/plugins/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└── local</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    └── providers</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        └── libvirt</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            └── 1.0.0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                └── linux_amd64</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    └── terraform-provider-libvirt</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>当然我尝试过 pulumi ，结果发现 pulumi 是对 tf 进行了一层包装本质还是使用的 terraform libvirt 插件，所以有同样的问题。</p>]]></content>
        <category label="terraform" term="terraform"/>
        <category label="Iac" term="Iac"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Kubernetes 共享 GPU 调度指南]]></title>
        <id>https://cloudnative.love/blog/2023/10/18/Kubernetes 共享 GPU 调度指南/README</id>
        <link href="https://cloudnative.love/blog/2023/10/18/Kubernetes 共享 GPU 调度指南/README"/>
        <updated>2023-10-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[本篇博文介绍了如何在 Kubernetes 集群中使用 GPU 资源，以及如何设置共享 Nvidia GPU 的详细步骤。]]></summary>
        <content type="html"><![CDATA[<p>本篇博文介绍了如何在 Kubernetes 集群中使用 GPU 资源，以及如何设置共享 Nvidia GPU 的详细步骤。</p>
<p>依照本文操作你将完成如下内容：</p>
<ul>
<li>Nvidia 和 CUDA 驱动安装</li>
<li>Nvidia Container Runtime 的配置</li>
<li>Kubernetes 通过 GPU plugin 实现 GPU 调度支持</li>
<li>Kubernetes 开启共享 Nvidia GPU 资源配置</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="前言">前言<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>Kubernetes 已经成为云原生应用编排和管理的事实标准。在 v1.26 版本 <a href="https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/" target="_blank" rel="noopener noreferrer">Scheduling GPUs</a> 进入 stable 状态，通过 <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/" target="_blank" rel="noopener noreferrer">device plugins</a> 可以让 Pods 可以访问特定硬件如 GPUs。</p>
<p>越来越多的机器学习（ML）和人工智能（AI）领域的开发者希望利用 Kubernetes 平台的优势，来管理 GPU 调度任务。</p>
<p>相比本地 GPU 管理方案，Kubernetes 通过对 GPU 资源的高效分时复用和动态调度，从而降本增效。声明式的容器化配置，使部署过程可以固化和复用，避免了重复配置机器学习环境。同时容器隔离可以避单一进程占用过多共享资源，保障系统稳定性。</p>
<p>尽管本文以 Arch Linux 作为基本环境，但同样适用于其他发行版。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="nvidia-驱动安装">Nvidia 驱动安装<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#nvidia-%E9%A9%B1%E5%8A%A8%E5%AE%89%E8%A3%85" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>参考链接</div><div class="admonitionContent_BuS1"><ul>
<li><a href="https://docs.nvidia.com/datacenter/tesla/tesla-installation-notes/index.html" target="_blank" rel="noopener noreferrer">NVIDIA Driver Installation Quickstart Guide</a></li>
<li>在开始安装 NVIDIA 驱动程序前请参照<a href="https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#pre-installation-actions" target="_blank" rel="noopener noreferrer">《 适用于 Linux 的 CUDA 安装指南》</a>中的 <strong>2. Pre-installation Actions（预安装操作）</strong> 对环境进行预检查。</li>
</ul></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="安装方式">安装方式<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E5%AE%89%E8%A3%85%E6%96%B9%E5%BC%8F" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>NVIDIA 驱动程序提供三种格式：</p>
<ul>
<li><a href="https://docs.nvidia.com/datacenter/tesla/tesla-installation-notes/index.html#runfile" target="_blank" rel="noopener noreferrer">runfile 安装程序</a>
<ul>
<li><a href="https://www.nvidia.com/Download/Find.aspx" target="_blank" rel="noopener noreferrer">NVIDIA Driver Downloads</a></li>
<li><a href="https://www.nvidia.com/en-us/drivers/unix/" target="_blank" rel="noopener noreferrer">Unix Driver Archive</a></li>
</ul>
</li>
<li><a href="https://docs.nvidia.com/datacenter/tesla/tesla-installation-notes/index.html#package-manager" target="_blank" rel="noopener noreferrer">包管理器</a></li>
<li><a href="https://docs.nvidia.com/datacenter/cloud-native/driver-containers/overview.html" target="_blank" rel="noopener noreferrer">容器化驱动程序</a></li>
</ul>
<p>推荐使用包管理器安装驱动，方便以后的维护和升级。</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="安装示例">安装示例<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E5%AE%89%E8%A3%85%E7%A4%BA%E4%BE%8B" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>以下是在 Arch Linux 上安装 Nvidia 驱动的示例：</p>
<p><a href="https://wiki.archlinux.org/title/NVIDIAN#Installation" target="_blank" rel="noopener noreferrer">Arch Linux Wiki for NVIDIAN</a> 介绍了 Arch Linux 官方提供的 Nvidia 驱动包和内核的对应关系，如下所示：</p>
<ul>
<li><a href="https://archlinux.org/packages/?name=nvidia" target="_blank" rel="noopener noreferrer">nvidia</a> 软件包（用于 <a href="https://archlinux.org/packages/?name=linux" target="_blank" rel="noopener noreferrer">linux</a>内核 ）</li>
<li><a href="https://archlinux.org/packages/?name=nvidia-lts" target="_blank" rel="noopener noreferrer">nvidia-lts</a> 软件包（用于 <a href="https://archlinux.org/packages/?name=linux-lts" target="_blank" rel="noopener noreferrer">linux-lts</a>内核 ）</li>
<li><a href="https://archlinux.org/packages/?name=nvidia-dkms" target="_blank" rel="noopener noreferrer">nvidia-dkms</a> 软件包（用于所有其他内核）。</li>
</ul>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>DKMS 是什么呢？</div><div class="admonitionContent_BuS1"><p>DKMS（Dynamic Kernel Module Support）是一个框架，用于在Linux系统中构建和安装内核模块。它允许在内核更新时自动重建已注册的内核模块。</p></div></div>
<p>下面以我的 Arch Linux 环境为例，我日常使用的内核为 <a href="https://archlinux.org/packages/?name=linux" target="_blank" rel="noopener noreferrer">linux</a> ，同时也安装了 <a href="https://archlinux.org/packages/?name=linux-lts" target="_blank" rel="noopener noreferrer">linux-lts</a> 内核作为备用，我想要 Nvidia 驱动在这俩内核中都正常工作，所以需要安装 <a href="https://archlinux.org/packages/?name=nvidia" target="_blank" rel="noopener noreferrer">nvidia</a> 和 <a href="https://archlinux.org/packages/?name=nvidia-lts" target="_blank" rel="noopener noreferrer">nvidia-lts</a> 命令如下：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># 查看显卡</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">lspci </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-i</span><span class="token plain"> nvidia </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> VGA</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 构建工具</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> pacman </span><span class="token parameter variable" style="color:#36acaa">-S</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--needed</span><span class="token plain"> base-devel</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># nvidia 驱动</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> pacman </span><span class="token parameter variable" style="color:#36acaa">-S</span><span class="token plain"> nvidia nvidia-lts</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>其他发行版请参考<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E5%AE%89%E8%A3%85%E6%96%B9%E5%BC%8F">安装方式</a>中提到的 <code>NVIDIA 驱动程序提供三种格式</code> 进行安装。</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="驱动验证">驱动验证<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E9%A9%B1%E5%8A%A8%E9%AA%8C%E8%AF%81" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>完成驱动安装好执行 nvidia-smi 验证是否可用</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ nvidia-smi</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Wed Aug </span><span class="token number" style="color:#36acaa">16</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">17</span><span class="token plain">:04:35 </span><span class="token number" style="color:#36acaa">2023</span><span class="token plain">       </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+---------------------------------------------------------------------------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> NVIDIA-SMI </span><span class="token number" style="color:#36acaa">535.98</span><span class="token plain">                 Driver Version: </span><span class="token number" style="color:#36acaa">535.98</span><span class="token plain">       CUDA Version: </span><span class="token number" style="color:#36acaa">12.2</span><span class="token plain">     </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">-----------------------------------------+----------------------+----------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> GPU  Name                 Persistence-M </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> Bus-Id        Disp.A </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> Volatile Uncorr. ECC </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> Fan  Temp   Perf          Pwr:Usage/Cap </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">         Memory-Usage </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> GPU-Util  Compute M. </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                                         </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                      </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">               MIG M. </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">+=</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">+=</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">   </span><span class="token number" style="color:#36acaa">0</span><span class="token plain">  NVIDIA GeForce RTX </span><span class="token number" style="color:#36acaa">3080</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">.    Off </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> 00000000:01:00.0 Off </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                  N/A </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> N/A   50C    P8              11W / 115W </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">      8MiB / 16384MiB </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">      </span><span class="token number" style="color:#36acaa">0</span><span class="token plain">%      Default </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                                         </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                      </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                  N/A </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+-----------------------------------------+----------------------+----------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                                                         </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+---------------------------------------------------------------------------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> Processes:                                                                            </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">  GPU   GI   CI        PID   Type   Process name                            GPU Memory </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">        ID   ID                                                             Usage      </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">    </span><span class="token number" style="color:#36acaa">0</span><span class="token plain">   N/A  N/A      </span><span class="token number" style="color:#36acaa">1067</span><span class="token plain">      G   /usr/bin/gnome-shell                          3MiB </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+---------------------------------------------------------------------------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">❯ nvidia-smi --query-gpu</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">gpu_name </span><span class="token parameter variable" style="color:#36acaa">--format</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">csv,noheader</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NVIDIA GeForce RTX </span><span class="token number" style="color:#36acaa">3080</span><span class="token plain"> Ti Laptop GPU</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">❯ nvidia-smi </span><span class="token parameter variable" style="color:#36acaa">-L</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">GPU </span><span class="token number" style="color:#36acaa">0</span><span class="token plain">: NVIDIA GeForce RTX </span><span class="token number" style="color:#36acaa">3080</span><span class="token plain"> Ti Laptop GPU </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">UUID: GPU-1b17e588-c712-9244-37de-93a8a77ebe6d</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>上述驱动为单卡配置，其他情况请参考以下文档</p><ul>
<li>多卡支持 <a href="https://docs.nvidia.com/datacenter/tesla/mig-user-guide/index.html" target="_blank" rel="noopener noreferrer">NVIDIA Multi-Instance GPU User Guide</a></li>
<li>开启 VGPU 支持 <a href="https://www.nvidia.com/en-us/data-center/virtual-solutions/" target="_blank" rel="noopener noreferrer">VGPU</a></li>
<li>开启消费级显卡的 vgpu 功能 <a href="https://github.com/DualCoder/vgpu_unlock" target="_blank" rel="noopener noreferrer">vgpu_unlock</a></li>
<li>更多文档 <a href="https://docs.nvidia.com/datacenter/tesla/index.html" target="_blank" rel="noopener noreferrer">https://docs.nvidia.com/datacenter/tesla/index.html</a></li>
</ul></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="cuda-驱动安装">CUDA 驱动安装<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#cuda-%E9%A9%B1%E5%8A%A8%E5%AE%89%E8%A3%85" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>CUDA（Compute Unified Device Architecture）是 NVIDIA 推出的通用并行计算架构，该架构使 GPU 能够解决复杂的计算问题。</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>参考链接</div><div class="admonitionContent_BuS1"><ul>
<li><a href="https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html" target="_blank" rel="noopener noreferrer">NVIDIA CUDA Installation Guide for Linux</a></li>
</ul></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="安装方式-1">安装方式<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E5%AE%89%E8%A3%85%E6%96%B9%E5%BC%8F-1" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>CUDA 提供了两种安装方式，你可以使用两种不同的安装机制之一来安装 CUDA 工具包：</p>
<ul>
<li><a href="https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#package-manager-installation" target="_blank" rel="noopener noreferrer">通过包管理器安装</a></li>
<li><a href="https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#runfile-installation" target="_blank" rel="noopener noreferrer">通过 runfile 安装</a></li>
<li><a href="https://developer.nvidia.com/cuda-downloads?target_os=Linux&amp;target_arch=x86_64&amp;Distribution=Rocky&amp;target_version=9&amp;target_type=runfile_local" target="_blank" rel="noopener noreferrer">runfile download</a></li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="安装示例-1">安装示例<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E5%AE%89%E8%A3%85%E7%A4%BA%E4%BE%8B-1" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>以下是在 Arch Linux 上安装 CUDA 驱动的示例：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">paru </span><span class="token parameter variable" style="color:#36acaa">-S</span><span class="token plain"> cuda</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>根据<a href="https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#post-installation-actions" target="_blank" rel="noopener noreferrer">安装后操作</a>配置环境变量。</p>
<p>Arch Linux 环境会将 CUDA 相关文件安装至 <code>/opt/cuda</code>，将 CUDA 的 PATH 加到 <code>rc</code> 中(如~/.bashrc,~/.zshrc)，此路径引永远指向最新版的 CUDA。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'export CUDA_PATH=/opt/cuda</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">export PATH=$PATH:/opt/cuda/bin:/opt/cuda/nsight_compute:/opt/cuda/nsight_systems/bin'</span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tee</span><span class="token plain"> /etc/profile.d/cuda.sh</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">source</span><span class="token plain"> /etc/profile</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="驱动验证-1">驱动验证<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E9%A9%B1%E5%8A%A8%E9%AA%8C%E8%AF%81-1" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>输入以下命令来检查 CUDA 版本：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯  nvcc </span><span class="token parameter variable" style="color:#36acaa">--version</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">nvcc: NVIDIA </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">R</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> Cuda compiler driver</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Copyright </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">c</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2005</span><span class="token plain">-2023 NVIDIA Corporation</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Built on Tue_Jun_13_19:16:58_PDT_2023</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Cuda compilation tools, release </span><span class="token number" style="color:#36acaa">12.2</span><span class="token plain">, V12.2.91</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Build cuda_12.2.r12.2/compiler.32965470_0</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="container-runtime">Container Runtime<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#container-runtime" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>这里选符合 oci 标准的运行时，本文选用 contianerd。</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="containerd-安装">Containerd 安装<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#containerd-%E5%AE%89%E8%A3%85" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>驱动加载</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># 写入持久化配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">cat</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token string" style="color:#e3116c">EOF</span><span class="token string bash punctuation" style="color:#393A34"> </span><span class="token string bash punctuation operator" style="color:#393A34">|</span><span class="token string bash punctuation" style="color:#393A34"> </span><span class="token string bash punctuation function" style="color:#d73a49">sudo</span><span class="token string bash punctuation" style="color:#393A34"> </span><span class="token string bash punctuation function" style="color:#d73a49">tee</span><span class="token string bash punctuation" style="color:#393A34"> /etc/modules-load.d/containerd.conf</span><span class="token string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">overlay</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">br_netfilter</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">EOF</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 重载配置使其生效</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl restart systemd-modules-load.service</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 或者手动加载</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> modprobe overlay </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> modprobe br_netfilte</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>安装软件包</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">paru </span><span class="token parameter variable" style="color:#36acaa">-S</span><span class="token plain"> containerd</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl </span><span class="token builtin class-name">enable</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--now</span><span class="token plain"> containerd </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="containerd-验证">Containerd 验证<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#containerd-%E9%AA%8C%E8%AF%81" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>执行如下命令，进行验证</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> ctr image pull docker.io/library/hello-world:latest </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> ctr run </span><span class="token parameter variable" style="color:#36acaa">--rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> docker.io/library/hello-world:latest hello-world</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="nvidia-container-runtime-安装">Nvidia-Container-Runtime 安装<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#nvidia-container-runtime-%E5%AE%89%E8%A3%85" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>Containerd 默认使用 runc 不支持 GPU 设备，nvidia-container-runtime 是 runc 的修补版本，它添加了自定义 pre-start hook 从而在容器内启用 GPU 支持。</p>
<p>安装 NVIDIA Container Toolkit 会在 Containerd（或任何其他运行时）周围提供一个shim，用于处理 GPU 请求。需要 GPU 的容器创建由 nvidia-container-runtime 处理。</p>
<p>当检测到 NVIDIA_VISIBLE_DEVICES 环境变量时，会调用 libnvidia-container 库将 GPU Device 和 CUDA Driver 附加到容器，配置 GPU 访问权限后，NVIDIA 系统会调用常规容器运行时来继续其余的启动过程。如果没有检测到 NVIDIA_VISIBLE_DEVICES 则会执行默认的 runc。</p>
<p>以 NVIDIA 的 GPU 设备为例，运行 GPU 容器后容器内将会出现 GPU 设备和驱动目录：</p>
<ul>
<li>GPU 设备，比如 /dev/nvidia0；</li>
<li>GPU 驱动目录，比如 /usr/local/nvidia/*。</li>
</ul>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span><a href="https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/arch-overview.html#arch-overview" target="_blank" rel="noopener noreferrer">NVIDIA container stack  架构概述</a></div><div class="admonitionContent_BuS1"><p><a href="https://gitlab.com/nvidia/container-toolkit/container-toolkit" target="_blank" rel="noopener noreferrer">NVIDIA Container Toolkit</a> 是一个容器工具包，它包含了一系列的工具和组件，用于在GPU环境中管理和运行容器化应用程序:</p><ul>
<li>nvidia-container-runtime<br>
<!-- -->NVIDIA公司开发的一种容器运行时，可以用于在GPU环境中运行容器化应用程序。</li>
<li>NVIDIA 容器运行时挂钩 ( nvidia-container-toolkit/ nvidia-container-runtime-hook)</li>
<li>NVIDIA 容器库和 CLI ( libnvidia-container1, nvidia-container-cli)</li>
</ul></div></div>
<p><strong>下面开始安装</strong> NVIDIA 容器运行时</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>参考文档</div><div class="admonitionContent_BuS1"><ul>
<li><a href="https://github.com/NVIDIA/nvidia-container-runtime/" target="_blank" rel="noopener noreferrer">nvidia-container-runtime 项目地址</a></li>
<li><a href="https://nvidia.github.io/nvidia-container-runtime/" target="_blank" rel="noopener noreferrer">nvidia-container-runtime 安装文档</a></li>
<li><a href="https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html" target="_blank" rel="noopener noreferrer">NVIDIA Container Toolkit 安装指南</a></li>
<li><a href="https://github.com/containerd/containerd/issues/4834" target="_blank" rel="noopener noreferrer">containerd/issues-4834</a></li>
</ul></div></div>
<p>使用以下命令将完整的 NVIDIA Container Toolkit 添加到系统中：</p>
<p>NVIDIA 容器运行时依赖于容器映像中现有的 CUDA 库。其他图像仍然可以工作，但它们看不到 GPU 硬件。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">paru </span><span class="token parameter variable" style="color:#36acaa">-S</span><span class="token plain"> nvidia-container-runtime nvidia-container-toolkit</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="配置-containerd-使用-nvidia-container-runtime">配置 Containerd 使用 Nvidia-Container-Runtime<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E9%85%8D%E7%BD%AE-containerd-%E4%BD%BF%E7%94%A8-nvidia-container-runtime" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>我们需要在启动 kubelet 之前将 Containerd 默认运行时从 runc 更改为 nvidia-container-runtime 。</p>
<p>生成默认配置文件</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">mkdir</span><span class="token plain"> /etc/containerd</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sh</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-c</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"containerd config default &gt;  /etc/containerd/config.toml"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>添加 nvidia 容器运行时，并设为默认</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">version </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">plugins</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">plugins.</span><span class="token string" style="color:#e3116c">"io.containerd.grpc.v1.cri"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">plugins.</span><span class="token string" style="color:#e3116c">"io.containerd.grpc.v1.cri"</span><span class="token plain">.containerd</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">      default_runtime_name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"nvidia"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">plugins.</span><span class="token string" style="color:#e3116c">"io.containerd.grpc.v1.cri"</span><span class="token plain">.containerd.runtimes</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">plugins.</span><span class="token string" style="color:#e3116c">"io.containerd.grpc.v1.cri"</span><span class="token plain">.containerd.runtimes.nvidia</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">          privileged_without_host_devices </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">          runtime_engine </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">          runtime_root </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">          runtime_type </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"io.containerd.runc.v2"</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">          </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">plugins.</span><span class="token string" style="color:#e3116c">"io.containerd.grpc.v1.cri"</span><span class="token plain">.containerd.runtimes.nvidia.options</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">            BinaryName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/usr/bin/nvidia-container-runtime"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>注意要和 kubelet 保持相同的 Cgroup 控制器，这里将 SystemdCgroup<code>设为</code>true`。</p><div class="language-toml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-toml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]</span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">  SystemdCgroup = true</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div>
<p>添加完成后重启 containerd 服务</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl restart containerd</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="nvidia-container-runtime-验证">Nvidia-Container-Runtime 验证<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#nvidia-container-runtime-%E9%AA%8C%E8%AF%81" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> ctr images pull docker.io/nvidia/cuda:12.2.0-devel-ubuntu20.04</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> ctr run </span><span class="token parameter variable" style="color:#36acaa">--rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--gpus</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> docker.io/nvidia/cuda:12.2.0-devel-ubuntu20.04 nvidia-smi nvidia-smi</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Thu Aug </span><span class="token number" style="color:#36acaa">24</span><span class="token plain"> 06:43:06 </span><span class="token number" style="color:#36acaa">2023</span><span class="token plain">       </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+---------------------------------------------------------------------------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> NVIDIA-SMI </span><span class="token number" style="color:#36acaa">535.98</span><span class="token plain">                 Driver Version: </span><span class="token number" style="color:#36acaa">535.98</span><span class="token plain">       CUDA Version: </span><span class="token number" style="color:#36acaa">12.2</span><span class="token plain">     </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">-----------------------------------------+----------------------+----------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> GPU  Name                 Persistence-M </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> Bus-Id        Disp.A </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> Volatile Uncorr. ECC </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> Fan  Temp   Perf          Pwr:Usage/Cap </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">         Memory-Usage </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> GPU-Util  Compute M. </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                                         </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                      </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">               MIG M. </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">+=</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">+=</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">   </span><span class="token number" style="color:#36acaa">0</span><span class="token plain">  NVIDIA GeForce RTX </span><span class="token number" style="color:#36acaa">3080</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">.    Off </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> 00000000:01:00.0 Off </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                  N/A </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> N/A   45C    P0              29W / 115W </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">     10MiB / 16384MiB </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">      </span><span class="token number" style="color:#36acaa">0</span><span class="token plain">%      Default </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                                         </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                      </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                  N/A </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+-----------------------------------------+----------------------+----------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                                                         </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+---------------------------------------------------------------------------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> Processes:                                                                            </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">  GPU   GI   CI        PID   Type   Process name                            GPU Memory </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">        ID   ID                                                             Usage      </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+---------------------------------------------------------------------------------------+</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>多 runtime 配置</div><div class="admonitionContent_BuS1"><p>如果有多 runtime 共存需求，需要在 Kubernetes 中创建相应的 runtime class。</p><p>例如我们想让 containerd 默认 runtime 设置为 runc ，只在使用 GPU 设备时使用 Nvidia-Container-Runtime 该怎么做呢？</p><p>首先配置 containerd <code>[plugins."io.containerd.grpc.v1.cri".containerd]</code>中 <code> default_runtime_name</code> 设置为 <code>runc</code>。</p><p>然后 <code>[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]</code> 下面多 runtime 配置创建 <code>runtime class</code> 资源：</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> node.k8s.io/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> RuntimeClass</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> nvidia</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">handler</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> nvidia</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>最后在 pod 资源清单中添加 <code>runtimeClassName: nvidia</code> 配置即可。</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="在-kubernetes-中启用-gpu-支持">在 Kubernetes 中启用 GPU 支持<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E5%9C%A8-kubernetes-%E4%B8%AD%E5%90%AF%E7%94%A8-gpu-%E6%94%AF%E6%8C%81" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>Kubernetes 通过设备插件（Device Plugins） 以允许 Pod 访问类似 GPU 这类特殊的硬件功能特性。不同厂商提供了不同的 Device Plugin，本小节部署 <a href="https://github.com/NVIDIA/k8s-device-plugin" target="_blank" rel="noopener noreferrer">NVIDIA/k8s-device-plugin</a></p>
<p>来做基本演示。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.14.0/nvidia-device-plugin.yml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 查看日志</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> kube-system logs </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">kubectl </span><span class="token variable parameter variable" style="color:#36acaa">-n</span><span class="token variable" style="color:#36acaa"> kube-system get pods  </span><span class="token variable parameter variable" style="color:#36acaa">-l</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable assign-left variable" style="color:#36acaa">name</span><span class="token variable operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">nvidia-device-plugin-ds  </span><span class="token variable parameter variable" style="color:#36acaa">-o</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable assign-left variable" style="color:#36acaa">jsonpath</span><span class="token variable operator" style="color:#393A34">=</span><span class="token variable string" style="color:#e3116c">"{.items[*].metadata.name}"</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">I0822 07:26:02.687308       </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> main.go:256</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> Retreiving plugins.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">I0822 07:26:02.687912       </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> factory.go:107</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> Detected NVML platform: found NVML library</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">I0822 07:26:02.687946       </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> factory.go:107</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> Detected non-Tegra platform: /sys/devices/soc0/family </span><span class="token function" style="color:#d73a49">file</span><span class="token plain"> not found</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">I0822 07:26:02.698806       </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> server.go:165</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> Starting GRPC server </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'nvidia.com/gpu'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">I0822 07:26:02.699008       </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> server.go:117</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> Starting to serve </span><span class="token string" style="color:#e3116c">'nvidia.com/gpu'</span><span class="token plain"> on /var/lib/kubelet/device-plugins/nvidia-gpu.sock</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">I0822 07:26:02.700674       </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> server.go:125</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> Registered device plugin </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'nvidia.com/gpu'</span><span class="token plain"> with Kubelet</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="运行-gpu-作业进行验收">运行 GPU 作业进行验收<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E8%BF%90%E8%A1%8C-gpu-%E4%BD%9C%E4%B8%9A%E8%BF%9B%E8%A1%8C%E9%AA%8C%E6%94%B6" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>部署 nvidia-device-plugin 后，容器现在可以使用 NVIDIA GPU nvidia.com/gpu 类型的 <a href="https://kubernetes.io/docs/tasks/administer-cluster/extended-resource-node/" target="_blank" rel="noopener noreferrer">Extended Resource </a>。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">cat</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token string" style="color:#e3116c">EOF</span><span class="token string bash punctuation" style="color:#393A34"> </span><span class="token string bash punctuation operator" style="color:#393A34">|</span><span class="token string bash punctuation" style="color:#393A34"> kubectl apply </span><span class="token string bash punctuation parameter variable" style="color:#36acaa">-f</span><span class="token string bash punctuation" style="color:#393A34"> -</span><span class="token string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">apiVersion: v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">kind: Pod</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">  name: gpu-pod</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">  restartPolicy: Never</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">  containers:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">    - name: cuda-container</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">      image: nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">      resources:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">        limits:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">          nvidia.com/gpu: 1 # requesting 1 GPU</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">  tolerations:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">  - key: nvidia.com/gpu</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">    operator: Exists</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">    effect: NoSchedule</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>查看日志结果</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$ kubectl logs gpu-pod</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Vector addition of </span><span class="token number" style="color:#36acaa">50000</span><span class="token plain"> elements</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Copy input data from the </span><span class="token function" style="color:#d73a49">host</span><span class="token plain"> memory to the CUDA device</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">CUDA kernel launch with </span><span class="token number" style="color:#36acaa">196</span><span class="token plain"> blocks of </span><span class="token number" style="color:#36acaa">256</span><span class="token plain"> threads</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Copy output data from the CUDA device to the </span><span class="token function" style="color:#d73a49">host</span><span class="token plain"> memory</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Test PASSED</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Done</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>可以通过 <a href="https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/getting-started.html" target="_blank" rel="noopener noreferrer">NVIDIA GPU Operator</a> 可以避免在每个节点上手动安装和配置 nvidia drive 和 nvidia-container-runtime。从而简化 GPU 工作负载的管理和操作。</p></div></div>
<p>到此已依照英伟达官方 device plugin 实现了 Kubernetes 集群对 gpu 的支持。</p>
<p>现在每个容器可以请求一个或者多个 GPU，但多容器无法共享一块 GPU ，因为 limit 只能是整数来指定单卡数量，无法请求 GPU 的一小部分，结果是单个容器占用了整个 GPU，导致推理阶段 GPU 利用率极低。</p>
<p>下面我们来看看如何让更多容器可以共享 GPU 来提高利用率。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="gpu-共享的可能性">GPU 共享的可能性<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#gpu-%E5%85%B1%E4%BA%AB%E7%9A%84%E5%8F%AF%E8%83%BD%E6%80%A7" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>硬件方案：vGPU 技术可以将显卡资源虚拟化成多块小显卡，会有部分性能损耗。通常需要特定的硬件支持，例如 NVIDIA GRID 卡或 AMD MxGPU 卡，并且需要购买额外的GPU许可证，会增加成本和管理负担。</p>
<p>软件方案：工作负载的调度是在软件层面完成，虽然可以利用整块 GPU 的算力，但无法对工作负载的显存进行限制，这意味着我们需要在代码中进行限制。例如 TensorFlow 允许按照<a href="https://www.tensorflow.org/guide/gpu" target="_blank" rel="noopener noreferrer">此处</a>的指令限制 GPU 功率。</p>
<p>在机器学习的背景下，训练期间可能会在一项训练作业中利用完整的 GPU 容量，但在推理期间很可能希望在可用的 GPU 上分布多个实例。</p>
<p>下面，我们利用软件层的 GPU 共享，将个工作负载扩展到单个 GPU 上。</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>更多共享方案</div><div class="admonitionContent_BuS1"><p>你可以在下面文章中了解更多的共享方案</p><ul>
<li><a href="https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-sharing.html" target="_blank" rel="noopener noreferrer">Time-Slicing GPUs in Kubernetes</a></li>
<li>技术阐述 <a href="https://www.arrikto.com/blog/gpu-virtualization-in-k8s-challenges-and-state-of-the-art/" target="_blank" rel="noopener noreferrer">https://www.arrikto.com/blog/gpu-virtualization-in-k8s-challenges-and-state-of-the-art/</a></li>
<li>技术阐述 <a href="https://developer.nvidia.com/blog/improving-gpu-utilization-in-kubernetes/" target="_blank" rel="noopener noreferrer">https://developer.nvidia.com/blog/improving-gpu-utilization-in-kubernetes/</a></li>
<li><a href="https://qiankunli.github.io/2021/08/18/gpu_utilization.html" target="_blank" rel="noopener noreferrer">https://qiankunli.github.io/2021/08/18/gpu_utilization.html</a></li>
<li><a href="https://github.com/volcano-sh/devices" target="_blank" rel="noopener noreferrer">https://github.com/volcano-sh/devices</a></li>
<li><a href="https://github.com/volcano-sh/volcano/blob/master/docs/user-guide/how_to_use_gpu_sharing.md" target="_blank" rel="noopener noreferrer">https://github.com/volcano-sh/volcano/blob/master/docs/user-guide/how_to_use_gpu_sharing.md</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/65543866" target="_blank" rel="noopener noreferrer">https://zhuanlan.zhihu.com/p/65543866</a></li>
<li><a href="https://houmin.cc/posts/cf391335/" target="_blank" rel="noopener noreferrer">https://houmin.cc/posts/cf391335/</a></li>
<li><a href="https://xie.infoq.cn/article/32b6e04e53419c35465acc699" target="_blank" rel="noopener noreferrer">https://xie.infoq.cn/article/32b6e04e53419c35465acc699</a></li>
</ul></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="安装-gpu-sharing-extension">安装 GPU sharing extension<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E5%AE%89%E8%A3%85-gpu-sharing-extension" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>我们将安装 <a href="https://github.com/AliyunContainerService/gpushare-scheduler-extender/" target="_blank" rel="noopener noreferrer">阿里 GPU 共享调度扩展</a>和<a href="https://github.com/AliyunContainerService/gpushare-device-plugin" target="_blank" rel="noopener noreferrer">阿里 GPU 共享设备插件</a>。官方文档可见 <a href="https://github.com/AliyunContainerService/gpushare-scheduler-extender/blob/master/docs/install.md" target="_blank" rel="noopener noreferrer">安装指南</a>。</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="1-在控制平面部署gpu共享调度扩展器">1. 在控制平面部署GPU共享调度扩展器<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#1-%E5%9C%A8%E6%8E%A7%E5%88%B6%E5%B9%B3%E9%9D%A2%E9%83%A8%E7%BD%B2gpu%E5%85%B1%E4%BA%AB%E8%B0%83%E5%BA%A6%E6%89%A9%E5%B1%95%E5%99%A8" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> https://raw.githubusercontent.com/AliyunContainerService/gpushare-scheduler-extender/master/config/gpushare-schd-extender.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="2修改-kube-scheduler-配置kubernetes-v123">2.修改 kube-scheduler 配置(Kubernetes v1.23+)<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#2%E4%BF%AE%E6%94%B9-kube-scheduler-%E9%85%8D%E7%BD%AEkubernetes-v123" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>添加 lable</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl label </span><span class="token function" style="color:#d73a49">node</span><span class="token plain"> archlinux </span><span class="token assign-left variable" style="color:#36acaa">gpushare</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl label </span><span class="token function" style="color:#d73a49">node</span><span class="token plain"> archlinux node-role.kubernetes.io/master</span><span class="token operator" style="color:#393A34">=</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>配置 kube-scheduler</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token builtin class-name">cd</span><span class="token plain"> /etc/kubernetes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-O</span><span class="token plain"> https://raw.githubusercontent.com/AliyunContainerService/gpushare-scheduler-extender/master/config/scheduler-policy-config.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>编辑 kube-scheduler.yaml</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">sudo vim manifests/kube-scheduler.yaml</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Pod</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">creationTimestamp</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token null important">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">component</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> kube</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">scheduler</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">tier</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> control</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">plane</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> kube</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">scheduler</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">namespace</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> kube</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">system</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">containers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">command</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> kube</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">scheduler</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">authentication</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">kubeconfig=/etc/kubernetes/scheduler.conf</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">authorization</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">kubeconfig=/etc/kubernetes/scheduler.conf</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">bind</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">address=127.0.0.1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">kubeconfig=/etc/kubernetes/scheduler.conf</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">leader</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">elect=true</span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">config=/etc/kubernetes/scheduler</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">policy</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">config.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> registry.k8s.io/kube</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">scheduler</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">v1.28.0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">imagePullPolicy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> IfNotPresent</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">livenessProbe</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">failureThreshold</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">httpGet</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 127.0.0.1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /healthz</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10259</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">scheme</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> HTTPS</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">initialDelaySeconds</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">periodSeconds</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">timeoutSeconds</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> kube</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">scheduler</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">resources</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">requests</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">cpu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 100m</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">startupProbe</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">failureThreshold</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">24</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">httpGet</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 127.0.0.1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /healthz</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10259</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">scheme</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> HTTPS</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">initialDelaySeconds</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">periodSeconds</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">timeoutSeconds</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">volumeMounts</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">mountPath</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /etc/kubernetes/scheduler</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">policy</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">config.yaml</span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> scheduler</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">policy</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">config</span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">readOnly</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain">      </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">mountPath</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /etc/kubernetes/scheduler.conf</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> kubeconfig</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">readOnly</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">hostNetwork</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">priority</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2000001000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">priorityClassName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> system</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">node</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">critical</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">securityContext</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">seccompProfile</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> RuntimeDefault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">volumes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">hostPath</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /etc/kubernetes/scheduler</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">policy</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">config.yaml</span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> FileOrCreate</span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> scheduler</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">policy</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">config</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">hostPath</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /etc/kubernetes/scheduler.conf</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> FileOrCreate</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> kubeconfig</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>kubernetes v1.28 scheduler 错误处理</div><div class="admonitionContent_BuS1"><p>注意在 v1.28 中 KubeSchedulerConfiguration api 版本放生了改变：</p><ul>
<li>KubeSchedulerConfiguration: v1beta2 ➜ v1.</li>
</ul><blockquote>
<p>以下为引用的部分 <a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.28.md#api-change" target="_blank" rel="noopener noreferrer">CHANGELOG-1.28</a></p>
<p>kube-scheduler component config (KubeSchedulerConfiguration) kubescheduler.config.k8s.io/v1beta2 is removed in v1.28. Migrate kube-scheduler configuration files to kubescheduler.config.k8s.io/v1. (<a href="https://github.com/kubernetes/kubernetes/pull/117649" target="_blank" rel="noopener noreferrer">#117649</a>, <a href="https://github.com/SataQiu" target="_blank" rel="noopener noreferrer">@SataQiu</a>)</p>
</blockquote><p>默认情况下你会看到如下报错</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ kubectl </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> kube-system logs kube-scheduler-archlinux</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">I0911 07:15:36.217495       </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> serving.go:348</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> Generated self-signed cert in-memory</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">E0911 07:15:36.217622       </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> run.go:74</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"command failed"</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">err</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">"no kind </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain">"KubeSchedulerConfiguration</span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain">" is registered </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> version </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain">"kubescheduler.config.k8s.io/v1beta2</span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain">" </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> scheme </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain">"pkg/scheduler/apis/config/scheme/scheme.go:30</span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain">"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>修正 api 版本后重启 kubelet 即可解决</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">vim</span><span class="token plain">  scheduler-policy-config.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  apiVersion: kubescheduler.config.k8s.io/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">systemctl restart kubelet.service</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="3-部署设备插件">3. 部署设备插件<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#3-%E9%83%A8%E7%BD%B2%E8%AE%BE%E5%A4%87%E6%8F%92%E4%BB%B6" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>注意：请删除默认的GPU设备插件，例如，如果您使用的是 <a href="https://github.com/NVIDIA/k8s-device-plugin" target="_blank" rel="noopener noreferrer">nvidia-device-plugin</a>，则可以运行<code>kubectl delete ds -n kube-system nvidia-device-plugin-daemonset</code>删除。</p></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> https://raw.githubusercontent.com/AliyunContainerService/gpushare-device-plugin/master/device-plugin-rbac.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> https://raw.githubusercontent.com/AliyunContainerService/gpushare-device-plugin/master/device-plugin-ds.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="4为需要gpu共享的节点添加gpushare节点标签">4.为需要GPU共享的节点添加gpushare节点标签<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#4%E4%B8%BA%E9%9C%80%E8%A6%81gpu%E5%85%B1%E4%BA%AB%E7%9A%84%E8%8A%82%E7%82%B9%E6%B7%BB%E5%8A%A0gpushare%E8%8A%82%E7%82%B9%E6%A0%87%E7%AD%BE" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl label node archlinux gpushare=true</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="5安装kubectl扩展">5.安装Kubectl扩展<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#5%E5%AE%89%E8%A3%85kubectl%E6%89%A9%E5%B1%95" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">cd /usr/bin/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">wget https://github.com/AliyunContainerService/gpushare-device-plugin/releases/download/v0.3.0/kubectl-inspect-gpushare</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">chmod u+x /usr/bin/kubectl-inspect-gpushare</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>当然你也可以使用 <a href="https://krew.sigs.k8s.io/docs/user-guide/setup/install/" target="_blank" rel="noopener noreferrer">krew</a> 来安装</p>
<p>device plugin 将公开 GPU 内存容量并跟踪 GPU 内存分配：</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ kubectl describe nodes archlinux|grep Capacity -A 20</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Capacity:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  aliyun.com/gpu-count:  1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  aliyun.com/gpu-mem:    16</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  cpu:                   20</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ephemeral-storage:     1907216Mi</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  hugepages-1Gi:         0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  hugepages-2Mi:         0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  memory:                32518820Ki</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  nvidia.com/gpu:        0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  pods:                  110</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Allocatable:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  aliyun.com/gpu-count:  1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  aliyun.com/gpu-mem:    16</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  cpu:                   20</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ephemeral-storage:     1799874828995</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  hugepages-1Gi:         0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  hugepages-2Mi:         0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  memory:                32416420Ki</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  nvidia.com/gpu:        0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  pods:                  110</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">System Info:</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>您可以通过运行 <code>kubectl inspect gpushare</code> 来验证 kubectl gpushare 客户端：
目前，集群上没有运行启用 GPU 的工作负载，因此 GPU 内存的分配为 0%。</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ sudo chmod +x /usr/bin/kubectl-inspect-gpushare</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">❯ sudo ls -l  /usr/bin/kubectl-inspect-gpushare</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-rwxr-xr-x 1 root root 37310113 2021年12月 7日 /usr/bin/kubectl-inspect-gpushare</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">❯ kubectl inspect gpushare</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME       IPADDRESS      GPU0(Allocated/Total)  GPU Memory(GiB)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">archlinux  192.168.8.100  0/16                   0/16</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">------------------------------------------------------</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Allocated/Total GPU Memory In Cluster:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">0/16 (0%)  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> /usr/bin </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="共享-gpu-冒烟测试">共享 GPU 冒烟测试<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E5%85%B1%E4%BA%AB-gpu-%E5%86%92%E7%83%9F%E6%B5%8B%E8%AF%95" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>测试用例参考</div><div class="admonitionContent_BuS1"><ul>
<li><a href="https://docs.deep-hybrid-datacloud.eu/en/latest/technical/kubernetes/gpu-kubernetes-centos7.html" target="_blank" rel="noopener noreferrer">测试和调度的完整用例</a></li>
<li><a href="https://blog.ml6.eu/a-guide-to-gpu-sharing-on-top-of-kubernetes-6097935ababf" target="_blank" rel="noopener noreferrer">https://blog.ml6.eu/a-guide-to-gpu-sharing-on-top-of-kubernetes-6097935ababf</a></li>
<li><a href="https://github.com/NVIDIA/gpu-operator/tree/master/tests" target="_blank" rel="noopener noreferrer">https://github.com/NVIDIA/gpu-operator/tree/master/tests</a></li>
<li><a href="https://catalog.ngc.nvidia.com/orgs/nvidia/helm-charts/video-analytics-demo" target="_blank" rel="noopener noreferrer">https://catalog.ngc.nvidia.com/orgs/nvidia/helm-charts/video-analytics-demo</a></li>
</ul></div></div>
<p>让我们看看如何为特定工作负载请求 GPU 内存：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">cat</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token string" style="color:#e3116c">EOF</span><span class="token string bash punctuation" style="color:#393A34"> </span><span class="token string bash punctuation operator" style="color:#393A34">|</span><span class="token string bash punctuation" style="color:#393A34"> kubectl apply </span><span class="token string bash punctuation parameter variable" style="color:#36acaa">-f</span><span class="token string bash punctuation" style="color:#393A34"> -</span><span class="token string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">apiVersion: v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">kind: Pod</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">  name: gpu-share-pod1</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">  restartPolicy: OnFailure</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">  containers:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">    - name: gpu-share-pod1</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">      image: "docker.io/cheyang/gpu-player:v2"</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">      env:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">        - name: NVIDIA_VISIBLE_DEVICES</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">          value: "all"</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">      resources:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">        limits:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">         aliyun.com/gpu-mem: 3</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>在检查 GPU 共享指标时，我们可以看到 Pod 已“虚拟”分配了 3 GB 的 VRAM。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl inspect gpushare</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">❯ kubectl inspect gpushare</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME       IPADDRESS      GPU0</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Allocated/Total</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  GPU Memory</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">GiB</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">archlinux  </span><span class="token number" style="color:#36acaa">192.168</span><span class="token plain">.8.100  </span><span class="token number" style="color:#36acaa">3</span><span class="token plain">/16                   </span><span class="token number" style="color:#36acaa">3</span><span class="token plain">/16</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">------------------------------------------------------</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Allocated/Total GPU Memory In Cluster:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">3</span><span class="token plain">/16 </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">18</span><span class="token plain">%</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>当我们验证 pod 本身的日志时，我们可以看到 TensorFlow 成功找到了 GPU 设备：</p>
<p>我们可以启动另一个工作负载，以确保不同的 pod 可以到达相同的底层 GPU：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">cat &lt;&lt;EOF </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> kubectl apply </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">f </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Pod</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> gpu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">share</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">pod2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">restartPolicy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> OnFailure</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">containers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> gpu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">share</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">pod2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"docker.io/cheyang/gpu-player:v2"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> NVIDIA_VISIBLE_DEVICES</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"all"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">resources</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">limits</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token key atrule" style="color:#00a4db">aliyun.com/gpu-mem</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>应用清单后，我们可以看到可分配内存已成功更新：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ kubectl inspect gpushare</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME       IPADDRESS      GPU0</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Allocated/Total</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  GPU Memory</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">GiB</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">archlinux  </span><span class="token number" style="color:#36acaa">192.168</span><span class="token plain">.8.100  </span><span class="token number" style="color:#36acaa">8</span><span class="token plain">/16                   </span><span class="token number" style="color:#36acaa">8</span><span class="token plain">/16</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">------------------------------------------------------</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Allocated/Total GPU Memory In Cluster:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">8</span><span class="token plain">/16 </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">50</span><span class="token plain">%</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>当我们再次查看 pod 的日志时，我们可以看到 TensorFlow 能够看到 GPU 设备，并注意到现在的 freeMemory 不是 11Gig 而是 8Gig：
作为最终测试，我们可以通过 SSH 连接到 GPU 工作节点并检查 GPU 进程：nvidia-msi Nvidia-smi 输出显示两个进程已连接到 GPU</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ nvidia-smi</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Thu Aug </span><span class="token number" style="color:#36acaa">24</span><span class="token plain"> 09:46:49 </span><span class="token number" style="color:#36acaa">2023</span><span class="token plain">       </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+---------------------------------------------------------------------------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> NVIDIA-SMI </span><span class="token number" style="color:#36acaa">535.98</span><span class="token plain">                 Driver Version: </span><span class="token number" style="color:#36acaa">535.98</span><span class="token plain">       CUDA Version: </span><span class="token number" style="color:#36acaa">12.2</span><span class="token plain">     </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">-----------------------------------------+----------------------+----------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> GPU  Name                 Persistence-M </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> Bus-Id        Disp.A </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> Volatile Uncorr. ECC </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> Fan  Temp   Perf          Pwr:Usage/Cap </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">         Memory-Usage </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> GPU-Util  Compute M. </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                                         </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                      </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">               MIG M. </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">+=</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">+=</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">   </span><span class="token number" style="color:#36acaa">0</span><span class="token plain">  NVIDIA GeForce RTX </span><span class="token number" style="color:#36acaa">3080</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">.    Off </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> 00000000:01:00.0 Off </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                  N/A </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> N/A   51C    P0              31W / 105W </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">   5226MiB / 16384MiB </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">      </span><span class="token number" style="color:#36acaa">4</span><span class="token plain">%      Default </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                                         </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                      </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">                  N/A </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+-----------------------------------------+----------------------+----------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                                                         </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+---------------------------------------------------------------------------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> Processes:                                                                            </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">  GPU   GI   CI        PID   Type   Process name                            GPU Memory </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">        ID   ID                                                             Usage      </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">==</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">    </span><span class="token number" style="color:#36acaa">0</span><span class="token plain">   N/A  N/A    </span><span class="token number" style="color:#36acaa">267687</span><span class="token plain">      G   /usr/lib/Xorg                                 4MiB </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">    </span><span class="token number" style="color:#36acaa">0</span><span class="token plain">   N/A  N/A    </span><span class="token number" style="color:#36acaa">274247</span><span class="token plain">      C   python                                     1798MiB </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">|</span><span class="token plain">    </span><span class="token number" style="color:#36acaa">0</span><span class="token plain">   N/A  N/A    </span><span class="token number" style="color:#36acaa">274573</span><span class="token plain">      C   python                                     3410MiB </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+---------------------------------------------------------------------------------------+</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="总结">总结<a href="https://cloudnative.love/blog/2023/10/18/Kubernetes%20%E5%85%B1%E4%BA%AB%20GPU%20%E8%B0%83%E5%BA%A6%E6%8C%87%E5%8D%97/README#%E6%80%BB%E7%BB%93" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>在机器学习的背景下，由于 GPU 设备成本高昂，因此充分利用它们极其重要。特别是在本地环境中，您的机器和 GPU 数量有限，因此能够在不同的工作负载之间共享 GPU 容量非常重要。例如，在训练期间，您可能会在一项训练作业中占用全部 GPU 容量，但在推理期间，您很可能会在可用 GPU 上分布多个实例。</p>
<p>目前，标准 Kubernetes 版本不支持跨 pod 共享 GPU。然而，通过扩展 kubernetes 调度程序模块，我们确认可以实际虚拟化 GPU 内存，就像 Kubernetes 虚拟化工作节点的计算和内存一样。值得注意的是，这种共享机制发生在软件层，并且在 GPU 上运行的工作负载（例如 <a href="https://www.tensorflow.org/guide/gpu#limiting_gpu_memory_growth" target="_blank" rel="noopener noreferrer">TensorFlow 限制_gpu_内存增长</a>）中也应该正确处理 GPU 隔离。</p>]]></content>
        <category label="Kubernetes" term="Kubernetes"/>
        <category label="GPU" term="GPU"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Kubernetes 中如何改善 JVM 预热（Warm-up）]]></title>
        <id>https://cloudnative.love/blog/2023/08/15/Kubernetes 中如何改善 JVM 预热（Warm-up）/README</id>
        <link href="https://cloudnative.love/blog/2023/08/15/Kubernetes 中如何改善 JVM 预热（Warm-up）/README"/>
        <updated>2023-08-15T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<!-- java项目的启动加速和可观测性jvm优化，还有服务发现下沉]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Alt text" src="https://cloudnative.love/assets/images/image-1-d402fb00e50598555a0a0b24b9362fea.png" width="1100" height="518" class="img_ev3q"></p>
<p>本文介绍了如何将 Spring Cloud 服务发现下沉到 Kubernetes ，同时结合 Istio 解决 JVM 预热的一些思路。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="背景">背景<a href="https://cloudnative.love/blog/2023/08/15/Kubernetes%20%E4%B8%AD%E5%A6%82%E4%BD%95%E6%94%B9%E5%96%84%20JVM%20%E9%A2%84%E7%83%AD%EF%BC%88Warm-up%EF%BC%89/README#%E8%83%8C%E6%99%AF" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>在我们的生产环境中 spring 应用滚动发布时候会出现少量非200状态码，同时伴随着 cpu req 激增。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="原因分析">原因分析<a href="https://cloudnative.love/blog/2023/08/15/Kubernetes%20%E4%B8%AD%E5%A6%82%E4%BD%95%E6%94%B9%E5%96%84%20JVM%20%E9%A2%84%E7%83%AD%EF%BC%88Warm-up%EF%BC%89/README#%E5%8E%9F%E5%9B%A0%E5%88%86%E6%9E%90" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>JVM 在启动时往往不能立即达到其最佳性能，需要经过一段时间的“预热”才能达到最优的执行速度。</p>
<p>在预热阶段 JIT 编译器会将热点代码编译成本地机器码，以提高执行效率。这个阶段，如果突然接收到大量请求，将会导致CPU使用率急剧上升。这是因为：</p>
<ol>
<li><strong>JIT即时编译</strong>：在预热期间，JVM需要不断地将热点代码编译成本地代码，这个过程本身就需要消耗CPU资源。</li>
<li><strong>大量请求处理</strong>：同时处理大量的请求，尤其是在代码还没有被充分优化时，会增加CPU的负担。</li>
</ol>
<p>扩大 limit 可以缓解出现响应错误的现象，但这治标不治本。但过小的 limit 结合 HPA 容易产生 <a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#flapping" target="_blank" rel="noopener noreferrer">HPA Flapping</a> 现象，比如Java程序启动时因为JVM预热、框架初始化等原因，通常资源使用率超高。HPA就会觉得资源不足，于是再新起一个Pod，结果新起的Pod还是资源使用率超高，导致HPA不断起新Pods直到hit预设的max Pod number。</p>
<ul>
<li><a href="https://medium.com/blablacar/warm-up-the-relationship-between-java-and-kubernetes-7fc5741f9a23" target="_blank" rel="noopener noreferrer">https://medium.com/blablacar/warm-up-the-relationship-between-java-and-kubernetes-7fc5741f9a23</a></li>
<li><a href="https://tech.olx.com/improving-jvm-warm-up-on-kubernetes-1b27dd8ecd58" target="_blank" rel="noopener noreferrer">https://tech.olx.com/improving-jvm-warm-up-on-kubernetes-1b27dd8ecd58</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="目的">目的<a href="https://cloudnative.love/blog/2023/08/15/Kubernetes%20%E4%B8%AD%E5%A6%82%E4%BD%95%E6%94%B9%E5%96%84%20JVM%20%E9%A2%84%E7%83%AD%EF%BC%88Warm-up%EF%BC%89/README#%E7%9B%AE%E7%9A%84" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>我需要一个解决方案来预热，在 pod 准备就绪时，随着时间的推移而逐渐增加负载 pod 的 qps。</p>
<p>这样启动时少量的请求可以帮助 JVM 进行 JIT 编译，同时可以帮助减缓CPU的暴涨。</p>
<ul>
<li><strong>渐进式优化</strong>：JVM有更多的时间来识别热点代码，并进行优化编译，使得后续的请求处理更加高效。</li>
<li><strong>避免突然负载增加</strong>：避免了因突然增加大量请求导致的CPU使用率急剧上升。</li>
</ul>
<p>例如：让我希望预热时间为 120 秒。 现有 2 个 Pod 分别拥有 50% 的流量，当新的 Pod 启动时，它将处理低流量并随着时间的推移而增加，并将在 120 秒内达到 33%。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="spring-cloud-服务发现下沉">Spring Cloud 服务发现下沉<a href="https://cloudnative.love/blog/2023/08/15/Kubernetes%20%E4%B8%AD%E5%A6%82%E4%BD%95%E6%94%B9%E5%96%84%20JVM%20%E9%A2%84%E7%83%AD%EF%BC%88Warm-up%EF%BC%89/README#spring-cloud-%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%E4%B8%8B%E6%B2%89" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>我们的Spring Cloud框架采用的nacos服务发现机制，服务间调用会绕过Kubernetes的路由过程，流量直接定向到达目标服务的Pod IP，导致 istio 的相关策略失效，需要如下配置将其服务发现下沉到K8S中。</p>
<p>使用Nacos作为服务注册中心时，需配置：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">spring.cloud.nacos.discovery.ip </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> your-service-name</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>同时需要保证服务间调用时在调用链路上透传请求头信息：</p>
<p>由于Spring Cloud的RibbonClient组件在发送HTTP请求时默认不会携带Istio路由所需的Host请求头[1]，开发者还需要自行添加HTTP Client的拦截器来在请求发出前添加内容为Host: 当前服务名的Header，使得请求能被Istio Sidecar处理。</p>
<ul>
<li><a href="https://github.com/IBM/spring-cloud-kubernetes-with-istio/blob/master/README.md#discovery-client-and-istio" target="_blank" rel="noopener noreferrer">https://github.com/IBM/spring-cloud-kubernetes-with-istio/blob/master/README.md#discovery-client-and-istio</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="warmupdurationsecs自动预热">WarmupDurationSecs自动预热<a href="https://cloudnative.love/blog/2023/08/15/Kubernetes%20%E4%B8%AD%E5%A6%82%E4%BD%95%E6%94%B9%E5%96%84%20JVM%20%E9%A2%84%E7%83%AD%EF%BC%88Warm-up%EF%BC%89/README#warmupdurationsecs%E8%87%AA%E5%8A%A8%E9%A2%84%E7%83%AD" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>在 v1.14 之后，Istio 在目标规则中提供了预热功能（envoy 中的慢启动模式）。</p>
<p>对于基于 JVM 的服务来说，这是一个很棒的功能，我们计划使用它来解决 java 服务的慢启动问题。启动时少量的请求可以帮助 JVM 进行 JIT 编译，同时不会耗尽所有 cpu 资源。</p>
<p><a href="https://istio.io/latest/docs/reference/config/networking/destination-rule/#LoadBalancerSettings" target="_blank" rel="noopener noreferrer">Istio DestinationRule</a>中 LoadBalancerSettings 部分的 WarmupDurationSecs 参数可用于控制新 pod 的流量逐渐增加。当应用新版本的部署时，Istio 可以在指定的时间段内逐渐增加更新的部署到 pod 的流量。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> networking.istio.io/v1alpha3</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DestinationRule</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">service</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">destination</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">rule</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">service</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">trafficPolicy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">loadBalancer</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">simple</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ROUND_ROBIN</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">warmupDurationSecs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 180s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">subsets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">version</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">version</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v2</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>因此，在 180 秒内，istio 将增加发送到 pod 的流量，增长速度几乎是线性的：
<img decoding="async" loading="lazy" alt="Alt text" src="https://cloudnative.love/assets/images/image-338d9ff8d96118e656caa86ffcd12269.png" width="2916" height="1771" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="virtualservice-优化发布策略">VirtualService 优化发布策略<a href="https://cloudnative.love/blog/2023/08/15/Kubernetes%20%E4%B8%AD%E5%A6%82%E4%BD%95%E6%94%B9%E5%96%84%20JVM%20%E9%A2%84%E7%83%AD%EF%BC%88Warm-up%EF%BC%89/README#virtualservice-%E4%BC%98%E5%8C%96%E5%8F%91%E5%B8%83%E7%AD%96%E7%95%A5" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>理想的情况是新启动的实例可以进入慢启动模式并接收流量，但旧实例应保持接收流量，直到新实例完成预热。</p>
<p>当服务处于慢启动模式（预热）时，它需要接收流量为 ready 状态，此时，在kubernetes滚动更新时，控制器会认为它已经准备好，去更新下一个实例，这可能会导致该服务的<strong>所有可用实例都处于慢启动模式</strong>。</p>
<p>注意这里使用perstop无法解决，因为进入perstop后 pod 也会停止接收流量，ip 会从 endpoint上摘除，控制器仍会更新下一个实例。</p>
<ul>
<li><a href="https://discuss.istio.io/t/how-to-coordinate-warm-up-and-kubernetes-rolling-update/14154" target="_blank" rel="noopener noreferrer">https://discuss.istio.io/t/how-to-coordinate-warm-up-and-kubernetes-rolling-update/14154</a></li>
</ul>
<p>这时我们可以借助 VirtualService 定义具有两条具有不同权重的路由，来进行渐进式发布：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> networking.istio.io/v1alpha3</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> VirtualService</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> reviews</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">hosts</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> reviews</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">route</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">destination</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> reviews</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">subset</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">weight</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">90</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">destination</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> reviews</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">subset</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">weight</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>然后可以手动流量权重来完成发布，参考<a href="https://istio.io/latest/docs/tasks/traffic-management/traffic-shifting/" target="_blank" rel="noopener noreferrer">istio 文档</a>。</p>
<p>当然这不够自动化，所以我们一般会可以结合 Flagger 或者 Argo Rollouts 来实现权重的自动切换和发布回退。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="参考文章">参考文章<a href="https://cloudnative.love/blog/2023/08/15/Kubernetes%20%E4%B8%AD%E5%A6%82%E4%BD%95%E6%94%B9%E5%96%84%20JVM%20%E9%A2%84%E7%83%AD%EF%BC%88Warm-up%EF%BC%89/README#%E5%8F%82%E8%80%83%E6%96%87%E7%AB%A0" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<ul>
<li><a href="https://stackoverflow.com/questions/74517652/gradually-warm-java-application-in-k8s-with-istio" target="_blank" rel="noopener noreferrer">https://stackoverflow.com/questions/74517652/gradually-warm-java-application-in-k8s-with-istio</a></li>
<li><a href="https://github.com/IBM/spring-cloud-kubernetes-with-istio/blob/master/README.md#discovery-client-and-istio" target="_blank" rel="noopener noreferrer">https://github.com/IBM/spring-cloud-kubernetes-with-istio/blob/master/README.md#discovery-client-and-istio</a></li>
<li><a href="https://github.com/argoproj/argo-rollouts/issues/617" target="_blank" rel="noopener noreferrer">https://github.com/argoproj/argo-rollouts/issues/617</a></li>
</ul>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[加密 Secrets 资源：Sealed Secrets 使用指南]]></title>
        <id>https://cloudnative.love/blog/2023/06/20/加密 Secrets 资源：Sealed Secrets 使用指南/README</id>
        <link href="https://cloudnative.love/blog/2023/06/20/加密 Secrets 资源：Sealed Secrets 使用指南/README"/>
        <updated>2023-06-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Sealed Secrets是一种在版本控制中存储加密的Kubernetes秘密的解决方案。]]></summary>
        <content type="html"><![CDATA[<p>Sealed Secrets是一种在版本控制中存储加密的Kubernetes秘密的解决方案。</p>
<p>在这篇博文中，我们将学习如何安装和使用它。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="安装">安装<a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#%E5%AE%89%E8%A3%85" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>Sealed Secrets 由两个部分组成：</p>
<ul>
<li>Client-side CLI tool: kubeseal<br>
<!-- -->客户端CLI工具 kubeseal，用于加密机密和创建密封机密</li>
<li>Server-side controller<br>
<!-- -->服务器端控制器，用于解密 SealedSecret CRD 和 创建 secrets</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="controller-安装">controller 安装<a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#controller-%E5%AE%89%E8%A3%85" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p><a href="https://artifacthub.io/packages/helm/bitnami-labs/sealed-secrets" target="_blank" rel="noopener noreferrer">sealed-secrets artifacthub</a></p>
<p>添加仓库并将其安装到 kube-system 命名空间：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token assign-left variable" style="color:#36acaa">Repo</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">https://bitnami-labs.github.io/sealed-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">Chart</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">sealed-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">Target</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">sealed-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">NameSpace</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">kube-system</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">helm upgrade </span><span class="token parameter variable" style="color:#36acaa">--install</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">${Target}</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">${Chart}</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">--repo</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">${Repo}</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">--namespace</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">${NameSpace}</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --create-namespace </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --set-string </span><span class="token assign-left variable" style="color:#36acaa">fullnameOverride</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">sealed-secrets-controller </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># --set customKey=YOUR_CUSTOM_KEY_HERE </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># key-renew-period=0</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ul>
<li>--namespace
将其安装在<code>kube-systems</code>使得kubeseal命令不用显示声明<code>--controller-namespace=kube-systems</code></li>
<li>--set-string fullnameOverride=sealed-secrets-controller
这个参数会 kube-system 命名空间里创建 sealed-secrets-controller service 使得 kubeseal 命令不用显示声明 <code>controller-name=sealed-secrets-controller </code></li>
<li>控制器在首次部署时会生成自己的证书，它还会为您管理续订。但您也可以自带证书，以便控制器也可以使用它们。</li>
<li>控制器使用任何标记为 sealedsecrets.bitnami.com/sealed-secrets-key=active 的密钥中包含的证书，该密钥必须与控制器位于同一命名空间中。可以有多个这样的秘密。</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="kubeseal-安装">kubeseal 安装<a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#kubeseal-%E5%AE%89%E8%A3%85" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p><a href="https://github.com/bitnami-labs/sealed-secrets/releases" target="_blank" rel="noopener noreferrer">kubeseal CLI</a> 使用当前 <a href="https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/" target="_blank" rel="noopener noreferrer"> kubectl 上下文访问集群</a>。在继续之前，请确保 kubectl 已连接到应安装 Sealed Secrets 的群集。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># macos</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">brew </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> kubeseal</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># linux</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">wget</span><span class="token plain"> https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.13.1/kubeseal-linux-amd64 </span><span class="token parameter variable" style="color:#36acaa">-O</span><span class="token plain"> kubeseal</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-m</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">755</span><span class="token plain"> kubeseal /usr/local/bin/kubeseal</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="工作原理">工作原理<a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p><img decoding="async" loading="lazy" src="https://d2908q01vomqb2.cloudfront.net/ca3512f4dfa95a03169c5a670a4c91a19b3077b4/2020/04/10/Screen-Shot-2020-04-09-at-8.06.32-PM.png" alt="1" class="img_ev3q"></p>
<p>启动时，控制器会在其命名空间中搜索带有 sealedsecrets.bitnami.com/sealed-secrets-key 标签的 Secret 读取其中存放的私钥/公钥对。如果找不到，控制器则会生成一个新的 4096 位 RSA 密钥对，并在其命名空间中创建新的 Secret 将其保存其中。随后会将公钥部分打印到输出日志中。您可以使用以下命令以 YAML 格式查看此 Secret（包含公有/私有密钥对）的内容：</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>配套的 CLI 工具 kubeseal 使用公钥加密 Secret 资源生成 SealedSecret 定制化资源定义 (CRD)we文件。将 SealedSecret 自定义资源部署到 Kubernetes 集群时，控制器会拾取该资源，然后使用私钥将其解封并创建一个 Secret 资源。加密和解密时会使用 SealedSecret 的命名空间/名称作为输入参数，这样可以确保 SealedSecret 和 Secret 严格绑定到相同的命名空间和名称。</p>
<p>kubeseal 可以通过 Kubernetes API 服务器与控制器进行通信，并在运行时检索加密 Secret 所需的公钥。您也可以从控制器下载公钥并保存在本地以便离线使用。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="基础使用">基础使用<a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#%E5%9F%BA%E7%A1%80%E4%BD%BF%E7%94%A8" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="sealedsecret-作用域">SealedSecret 作用域<a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#sealedsecret-%E4%BD%9C%E7%94%A8%E5%9F%9F" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<ul>
<li>SealedSecret 和 Secret 必须具有相同的命名空间和名称。此功能可防止同一集群上的其他用户重复使用您密封的密钥。</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># 默认限制命名空间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubeseal </span><span class="token parameter variable" style="color:#36acaa">--format</span><span class="token plain"> yaml </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> mysecret.yaml </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> mysealedsecret.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># --scope 全局可用生成的密文可以在整个集群中使用，而不是仅限于特定的命名空间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubeseal </span><span class="token parameter variable" style="color:#36acaa">--format</span><span class="token plain"> yaml </span><span class="token parameter variable" style="color:#36acaa">--scope</span><span class="token plain"> cluster-wide </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> mysecret.yaml </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> mysealedsecret2.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="加密-secret">加密 secret<a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#%E5%8A%A0%E5%AF%86-secret" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>kubeseal CLI 将 Kubernetes Secret 清单作为输入，对其进行加密并输出清单 SealedSecret 。</p>
<p>在本教程中，我们将使用此机密清单作为输入：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">creationTimestamp</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token null important">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">password</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> YmFy</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">username</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Zm9v</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>将清单存储在名为 secret.yaml and encrypt it 的文件中：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">cat</span><span class="token plain"> secret.yaml </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> kubeseal </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --controller-namespace kube-system </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --controller-name sealed-secrets </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token parameter variable" style="color:#36acaa">--format</span><span class="token plain"> yaml </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> sealed-secret.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>sealed-secret.yaml 文件的内容应如下所示：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> bitnami.com/v1alpha1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> SealedSecret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">creationTimestamp</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token null important">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">namespace</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> default</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">encryptedData</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">password</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> AgA</span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">username</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> AgA</span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">template</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">creationTimestamp</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token null important">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">namespace</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> default</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>我们现在应该有秘密在里面 secret.yaml ，把密封的秘密在里面 sealed-secret.yaml 。此时已不再需要与该 Secret 有关的 YAML 清单，您可以将其删除。SealedSecret 将会是唯一被部署到集群的资源，如下所示：</p>
<p>请注意，原始 Secret 中的键（即username 和 password）在 SealedSecret 中未被加密，只有这些键对应的值被加密。您可以根据需要在 SealedSecret YAML 文件中更改这些键的名称，并且仍能够将更改后的键成功部署到集群中。但是，您不能更改 SealedSecret 的 name 和 namespace，否则会使 SealedSecret 无效，因为原始 Secret 的名称和命名空间会在加密过程中用作输入参数。这种方式提供了额外的保护措施，即使用户获得了对 SealedSecret 的 YAML 清单的访问权限（此 SealedSecret 是为在用户无权访问的 Kubernetes 集群中的特定命名空间而创建），他们也无法仅编辑清单和将 SealedSecret 部署到不同的命名空间（包括同一集群中的不同命名空间）。</p>
<p>为了部署密封的密钥，我们使用 kubectl 应用清单：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> sealed-secret.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>集群中的控制器会注意到已创建资源 SealedSecret ，对其进行解密并创建已 Secret 解密的 .</p>
<p>让我们获取密钥以确保控制器已成功解封unsealed 它：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get secret my-secret </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>数据应包含我们的 base64 编码用户名和密码：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">password</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> YmFy</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">username</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Zm9v</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>一切都很顺利。秘密已被成功解封unsealed。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="进阶指南">进阶指南<a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#%E8%BF%9B%E9%98%B6%E6%8C%87%E5%8D%97" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="自定义密钥">自定义密钥<a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%86%E9%92%A5" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<ul>
<li><a href="https://github.com/bitnami-labs/sealed-secrets/blob/main/docs/bring-your-own-certificates.md" target="_blank" rel="noopener noreferrer">https://github.com/bitnami-labs/sealed-secrets/blob/main/docs/bring-your-own-certificates.md</a>
设置变量</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">PRIVATEKEY</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"default.key"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">PUBLICKEY</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"default.crt"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">NAMESPACE</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"sealed-secrets"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">SECRETNAME</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"mycustomkeys"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">DAYS</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"3650"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>生成新的 RSA 密钥对（证书）</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">openssl req </span><span class="token parameter variable" style="color:#36acaa">-x509</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-days</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">${DAYS}</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-nodes</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-newkey</span><span class="token plain"> rsa:4096 </span><span class="token parameter variable" style="color:#36acaa">-keyout</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$PRIVATEKEY</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-out</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$PUBLICKEY</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-subj</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/CN=sealed-secret/O=sealed-secret"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>使用您最近创建的 RSA 密钥对创建 tls k8s 密钥</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$NAMESPACE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> create secret tls </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$SECRETNAME</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--cert</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$PUBLICKEY</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--key</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$PRIVATEKEY</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$NAMESPACE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> label secret </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$SECRETNAME</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> sealedsecrets.bitnami.com/sealed-secrets-key</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">active</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>需要删除控制器 Pod 才能选择新密钥</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain">  </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$NAMESPACE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> delete pod </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">name</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">sealed-secrets-controller</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>查看控制器日志中的新证书（私钥）</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$NAMESPACE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> logs </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">name</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">sealed-secrets-controller</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">controller version: v0.12.1+dirty</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2020</span><span class="token plain">/06/09 </span><span class="token number" style="color:#36acaa">14</span><span class="token plain">:30:45 Starting sealed-secrets controller version: v0.12.1+dirty</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2020</span><span class="token plain">/06/09 </span><span class="token number" style="color:#36acaa">14</span><span class="token plain">:30:45 Searching </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> existing private keys</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2020</span><span class="token plain">/06/09 </span><span class="token number" style="color:#36acaa">14</span><span class="token plain">:30:45 ----- sealed-secrets-key5rxd9</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2020</span><span class="token plain">/06/09 </span><span class="token number" style="color:#36acaa">14</span><span class="token plain">:30:45 ----- mycustomkeys</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2020</span><span class="token plain">/06/09 </span><span class="token number" style="color:#36acaa">14</span><span class="token plain">:30:45 HTTP server serving on :8080</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>现在，您可以尝试使用自己的证书来密封密钥，而不是使用控制器提供的证书。</p>
<p>使用 --cert 以下标志使用自己的证书（密钥）：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubeseal </span><span class="token parameter variable" style="color:#36acaa">--cert</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"./</span><span class="token string variable" style="color:#36acaa">${PUBLICKEY}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--scope</span><span class="token plain"> cluster-wide </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> mysecret.yaml </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> kubectl apply -f-</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>我们可以看到秘密已经成功解封</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$NAMESPACE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> logs </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">name</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">sealed-secrets-controller</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">controller version: v0.12.1+dirty</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2020</span><span class="token plain">/06/09 </span><span class="token number" style="color:#36acaa">14</span><span class="token plain">:30:45 Starting sealed-secrets controller version: v0.12.1+dirty</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2020</span><span class="token plain">/06/09 </span><span class="token number" style="color:#36acaa">14</span><span class="token plain">:30:45 Searching </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> existing private keys</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2020</span><span class="token plain">/06/09 </span><span class="token number" style="color:#36acaa">14</span><span class="token plain">:30:45 ----- sealed-secrets-key5rxd9</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2020</span><span class="token plain">/06/09 </span><span class="token number" style="color:#36acaa">14</span><span class="token plain">:30:45 ----- mycustomkeys</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2020</span><span class="token plain">/06/09 </span><span class="token number" style="color:#36acaa">14</span><span class="token plain">:30:45 HTTP server serving on :8080</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2020</span><span class="token plain">/06/09 </span><span class="token number" style="color:#36acaa">14</span><span class="token plain">:37:55 Updating test-namespace/mysecret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2020</span><span class="token plain">/06/09 </span><span class="token number" style="color:#36acaa">14</span><span class="token plain">:37:55 Event</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v1.ObjectReference</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">Kind:</span><span class="token string" style="color:#e3116c">"SealedSecret"</span><span class="token plain">, Namespace:</span><span class="token string" style="color:#e3116c">"test-namespace"</span><span class="token plain">, Name:</span><span class="token string" style="color:#e3116c">"mysecret"</span><span class="token plain">, </span><span class="token environment constant" style="color:#36acaa">UID</span><span class="token builtin class-name">:</span><span class="token string" style="color:#e3116c">"f3a6c537-d254-4c06-b08f-ab9548f28f5b"</span><span class="token plain">, APIVersion:</span><span class="token string" style="color:#e3116c">"bitnami.com/v1alpha1"</span><span class="token plain">, ResourceVersion:</span><span class="token string" style="color:#e3116c">"20469957"</span><span class="token plain">, FieldPath:</span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">: type: </span><span class="token string" style="color:#e3116c">'Normal'</span><span class="token plain"> reason: </span><span class="token string" style="color:#e3116c">'Unsealed'</span><span class="token plain"> SealedSecret unsealed successfully</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>PRIVATEKEY 是您的私钥，控制器使用它来解封您的密钥。不要与任何你不信任的人分享它，并将其保存在一个安全的地方！</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="导出公钥和加密">导出公钥和加密<a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#%E5%AF%BC%E5%87%BA%E5%85%AC%E9%92%A5%E5%92%8C%E5%8A%A0%E5%AF%86" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h4>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubeseal --fetch-cert </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> public-key-cert.pem</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>然后使用 kubeseal 使用公钥文件创建 SealedSecret CRD，如下所示：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubeseal </span><span class="token parameter variable" style="color:#36acaa">--format</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">yaml </span><span class="token parameter variable" style="color:#36acaa">--cert</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">public-key-cert.pem </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> secret.yaml </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> sealed-secret.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="导出私钥和解密">导出私钥和解密<a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#%E5%AF%BC%E5%87%BA%E7%A7%81%E9%92%A5%E5%92%8C%E8%A7%A3%E5%AF%86" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> kube-system get secret </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"> sealedsecrets.bitnami.com/sealed-secrets-key</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">active </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> yaml  </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> kubectl neat </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> allsealkeys.yml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="解密文件"><a href="https://stackoverflow.com/questions/75812591/how-can-i-locally-decrypt-already-sealed-secrets" target="_blank" rel="noopener noreferrer">解密文件</a><a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#%E8%A7%A3%E5%AF%86%E6%96%87%E4%BB%B6" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get secret </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> kube-system </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"> sealedsecrets.bitnami.com/sealed-secrets-key </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> yaml </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> sealed-secrets-key.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubeseal </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> sealed-secret.yaml --recovery-unseal --recovery-private-key sealed-secrets-key.yaml </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion-结论">Conclusion 结论<a href="https://cloudnative.love/blog/2023/06/20/%E5%8A%A0%E5%AF%86%20Secrets%20%E8%B5%84%E6%BA%90%EF%BC%9ASealed%20Secrets%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/README#conclusion-%E7%BB%93%E8%AE%BA" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>Sealed Secrets 是一种在版本控制中管理 Kubernetes 机密的安全方法。在集群中存储加密密钥并解密机密。客户端无权访问加密密钥。</p>
<p>客户端使用 kubeseal CLI 工具生成 SealedSecret 保存加密数据的清单。应用文件后，服务器端控制器将识别新的密封密钥资源并对其进行解密以创建 Secret 资源。</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[CKA CKAD CKS 考试通关指南]]></title>
        <id>https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README</id>
        <link href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README"/>
        <updated>2022-12-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[这里有考试 CKA CKAD CKS 省钱攻略，和对中国区参加考试的注意事项，以及开源的考前学习料哦~]]></summary>
        <content type="html"><![CDATA[<p align=""><a href="https://www.credly.com/badges/7f665fcf-c0a4-44e7-8b09-06584280dfc2"><img width="200" height="200" src="https://images.credly.com/size/680x680/images/8b8ed108-e77d-4396-ac59-2504583b9d54/cka_from_cncfsite__281_29.png" alt="CKA"></a><a href="https://www.credly.com/badges/c37a3b97-5438-4c05-a28b-6ea2d6f38905"><img width="200" height="200" src="https://images.credly.com/size/680x680/images/f88d800c-5261-45c6-9515-0458e31c3e16/ckad_from_cncfsite.png" alt="CKAD"></a><a href="https://www.credly.com/badges/02d42601-dfd8-41de-a90b-6e1aba0c716d"><img width="200" height="200" src="https://images.credly.com/size/680x680/images/9945dfcb-1cca-4529-85e6-db1be3782210/kubernetes-security-specialist-logo2.png" alt="CKS"></a></p>
<p>这里有考试 CKA CKAD CKS 省钱攻略，和对中国区参加考试的注意事项，以及开源的考前学习料哦~</p>
<p>哦对了，点击上面徽章就可以对我的证书进行验证哦~</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="关于购买考试券">关于购买考试券<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E5%85%B3%E4%BA%8E%E8%B4%AD%E4%B9%B0%E8%80%83%E8%AF%95%E5%88%B8" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="购买地址">购买地址：<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E8%B4%AD%E4%B9%B0%E5%9C%B0%E5%9D%80" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<ul>
<li><a href="https://www.cncf.io/certification/cka/" target="_blank" rel="noopener noreferrer">Certified Kubernetes Administrator (CKA)</a></li>
<li><a href="https://www.cncf.io/certification/cks/" target="_blank" rel="noopener noreferrer">Certified Kubernetes Security Specialist (CKS)</a></li>
<li><a href="https://www.cncf.io/certification/ckad/" target="_blank" rel="noopener noreferrer">Certified Kubernetes Application Developer (CKAD)</a></li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="省钱技巧">省钱技巧<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E7%9C%81%E9%92%B1%E6%8A%80%E5%B7%A7" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<ul>
<li>
<p>网络星期一 (Cyber Monday)</p>
<p>建议在每年的11月左右购买考试，你可以享受到一年一度的 <code>Cyber Monday</code> 可以帮你节省 <strong>65%</strong> 的费用</p>
</li>
<li>
<p>黑色星期五（Black Friday）</p>
<p>在11月份还有 <code>Black Friday</code> 活动， 可以帮你节省 <strong>35%</strong> 的费用</p>
</li>
<li>
<p>优惠券</p>
<p>Linux Foundation 会不定期放出一些优惠券。这里给大家列举了几个优惠券。</p>
<ul>
<li>SCOFFER15</li>
<li>DCUBEOFFER</li>
<li>DEVOPS15DEVOPS15</li>
<li><a href="https://couponbarrow.com/store/linux-foundation-coupons/?coupon_type=code" target="_blank" rel="noopener noreferrer">更多优惠券</a></li>
</ul>
</li>
<li>
<p>捆绑购买</p>
<p>捆绑购买结合 <code>Cyber Monday</code> 将节省一大半费用，强烈推荐！！</p>
</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="关于中国区考试">关于中国区考试<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E5%85%B3%E4%BA%8E%E4%B8%AD%E5%9B%BD%E5%8C%BA%E8%80%83%E8%AF%95" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p><code>Linux Foundation</code> 使用 <code>PSI</code>在线考试，无论购买那种语言进入考试系统后均可切换考试题的显示语言，目前支持 中文、英文、日文切换，但是考官语言无法更改。
当购买 CKA-CN、CKAD-CN、CKS-CN，中文试题后默认题目为中文，与考官发给你的消息会自动译为中文。</p>
<ul>
<li><a href="https://training.linuxfoundation.cn/" target="_blank" rel="noopener noreferrer">中国区考试购买地址</a></li>
</ul>
<p>当你购买完成后会获得<strong>考试激活码</strong>，然后需要去 <a href="https://trainingportal.linuxfoundation.org/learn/dashboard" target="_blank" rel="noopener noreferrer">linuxfoundation learn</a> 激活考试（申请考试，查看考试结果等都是这个链接，建议收藏到书签）。</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>无论在哪里购买最后都是在 <a href="https://trainingportal.linuxfoundation.org/learn/dashboard" target="_blank" rel="noopener noreferrer">linuxfoundation learn</a> 进行登记考试，<a href="https://training.linuxfoundation.cn/" target="_blank" rel="noopener noreferrer">中国区考试购买地址</a>只提供激活码。</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="激活考试券">激活考试券<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E6%BF%80%E6%B4%BB%E8%80%83%E8%AF%95%E5%88%B8" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2><p><code>CKA-CN</code> 购买后需要在 <code>个人中心-我的考试-查看考试券</code> 复制激活码到 <a href="https://trainingportal.linuxfoundation.org/learn/dashboard" target="_blank" rel="noopener noreferrer">linuxfoundation learn</a>
点击 <code>Apply Registration Code</code> 输入进行激活。
<img decoding="async" loading="lazy" alt="1665369054044" src="https://cloudnative.love/assets/images/1665369054044-659586ea0f52ea950346760c63cf91bc.png" title="考试激活" width="1423" height="453" class="img_ev3q"></p></div></div>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>我遇到的奇怪问题</div><div class="admonitionContent_BuS1"><p>我买的 CKA-CN 在 Arch Linux 上安装 PSI 安全浏览器后却进入了英文考场。。。用英语和考官沟通示是否可以使用中文，考官表示英语是 PSI 系统选择的他不会说中文也没法更改。而且在核对身份时候多了一步他要求提供我的地址信息，后来因为网络卡了考官看不见我的相机串流画面，我就退出去重启了电脑换了科学网络，然后这次变为了中文考场。。。。。这可能是 PSI 浏览器在 Linux 上的 BUG 吧，初次安装后默认会进入英文考场。
这也说明了不同语言的考场核对信息流程可能会不一样。像 HashiCorp 的考试也用 PSI 系统，它们就把这些考前检查内容和 Linux Foundation 基本一致，但是需要自己上传图片和视频，考官只负责核对。 Linux Foundation 则是考官帮你录制上传，你只要按照考官的要求移动你的相机既可。这里建议有一个外置广角的相机，不然你就要抱着笔记本满世界转圈圈了。尽量让每个步骤的时间控制在 15s 内（HashiCorp 的考试 PSI 默认视频长度为 15 秒 应该都一样）。不然考官可能要求你重新录制周围环境。</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="考试注意事项">考试注意事项<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E8%80%83%E8%AF%95%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>大家在考试前按照流程仔细阅读相关手册。</p>
<ul>
<li>
<p>候选人手册: <a href="https://www.cncf.io/certification/candidate-han-dbook" target="_blank" rel="noopener noreferrer">candidate-handbook</a></p>
</li>
<li>
<p>注意事项：<a href="http://training.linuxfoundation.org/go/Important-Tips-CKA-CKAD" target="_blank" rel="noopener noreferrer">Important Instructions: CKA and CKAD</a></p>
</li>
<li>
<p>常见问题：<a href="https://docs.linuxfoundation.org/tc-docs/certification/faq-cka-ckad-cks" target="_blank" rel="noopener noreferrer">faq-cka-ckad-cks</a></p>
</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="考纲和考试资料">考纲和考试资料<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E8%80%83%E7%BA%B2%E5%92%8C%E8%80%83%E8%AF%95%E8%B5%84%E6%96%99" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>下面是我找到的一些考试的资料，同时购买考试附赠的 killer.sh <a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E6%A8%A1%E6%8B%9F%E8%80%83%E8%AF%95">模拟考试</a>不要放过.</p>
<ul>
<li>官方考试大纲： <a href="https://github.com/cncf/curriculum" target="_blank" rel="noopener noreferrer">github.com/cncf/curriculum</a></li>
</ul>
<p>关于课程，我不建议买 Linux Foundation 出的课因为太贵了，非要购买的话推荐下面 udemy 的课程</p>
<ul>
<li><a href="https://www.udemy.com/course/certified-kubernetes-administrator-with-practice-tests/" target="_blank" rel="noopener noreferrer">Certified Kubernetes Administrator (CKA) with Practice Tests</a></li>
<li><a href="https://www.udemy.com/course/certified-kubernetes-application-developer/" target="_blank" rel="noopener noreferrer">Kubernetes Certified Application Developer (CKAD) with Tests</a></li>
<li><a href="https://www.udemy.com/course/certified-kubernetes-security-specialist/" target="_blank" rel="noopener noreferrer">Kubernetes CKS 2022 Complete Course - Theory - Practice</a></li>
</ul>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>udemy 课程经常搞活动。如果你的帐号没有出现优惠券，你可以打开浏览器无痕模式然后换个公网IP再试试。上面的课程平均 10 美元左右不要买贵了哦。</p></div></div>
<ul>
<li>
<p><strong>CKA 资料</strong></p>
<ul>
<li>
<p>推荐 <a href="https://github.com/walidshaari/Kubernetes-Certified-Administrator" target="_blank" rel="noopener noreferrer">https://github.com/walidshaari/Kubernetes-Certified-Administrator</a></p>
</li>
<li>
<p>推荐 <a href="https://github.com/ahmetb/kubernetes-network-policy-recipes" target="_blank" rel="noopener noreferrer">https://github.com/ahmetb/kubernetes-network-policy-recipes</a></p>
<p>下面这些我没看过</p>
<ul>
<li><a href="https://github.com/ramitsurana/awesome-kubernetes" target="_blank" rel="noopener noreferrer">https://github.com/ramitsurana/awesome-kubernetes</a></li>
<li><a href="https://github.com/David-VTUK/CKA-StudyGuide" target="_blank" rel="noopener noreferrer">https://github.com/David-VTUK/CKA-StudyGuide</a></li>
<li><a href="https://github.com/arush-sal/cka-practice-environment" target="_blank" rel="noopener noreferrer">https://github.com/arush-sal/cka-practice-environment</a></li>
<li><a href="https://github.com/alijahnas/CKA-practice-exercises" target="_blank" rel="noopener noreferrer">https://github.com/alijahnas/CKA-practice-exercises</a></li>
<li><a href="https://github.com/stretchcloud/cka-lab-practice" target="_blank" rel="noopener noreferrer">https://github.com/stretchcloud/cka-lab-practice</a></li>
<li><a href="https://github.com/chadmcrowell/CKA-Exercises" target="_blank" rel="noopener noreferrer">https://github.com/chadmcrowell/CKA-Exercises</a></li>
<li><a href="https://github.com/kabary/kubernetes-cka/wiki" target="_blank" rel="noopener noreferrer">https://github.com/kabary/kubernetes-cka/wiki</a></li>
</ul>
</li>
</ul>
</li>
<li>
<p><strong>CKAD 资料</strong></p>
<ul>
<li>
<p>推荐 <a href="https://github.com/dgkanatsios/CKAD-exercises" target="_blank" rel="noopener noreferrer">https://github.com/dgkanatsios/CKAD-exercises</a></p>
</li>
<li>
<p>推荐 <a href="https://medium.com/bb-tutorials-and-thoughts/practice-enough-with-these-questions-for-the-ckad-exam-2f42d1228552" target="_blank" rel="noopener noreferrer">https://medium.com/bb-tutorials-and-thoughts/practice-enough-with-these-questions-for-the-ckad-exam-2f42d1228552</a></p>
<p>下面这些我没看过</p>
<ul>
<li><a href="https://github.com/twajr/ckad-prep-notes" target="_blank" rel="noopener noreferrer">https://github.com/twajr/ckad-prep-notes</a></li>
<li><a href="https://github.com/lucassha/CKAD-resources" target="_blank" rel="noopener noreferrer">https://github.com/lucassha/CKAD-resources</a></li>
<li><a href="https://github.com/StenlyTU/K8s-training-official" target="_blank" rel="noopener noreferrer">https://github.com/StenlyTU/K8s-training-official</a></li>
<li><a href="https://github.com/saripurigopi/CKAD" target="_blank" rel="noopener noreferrer">https://github.com/saripurigopi/CKAD</a></li>
<li><a href="https://github.com/DStorck/cka-prep" target="_blank" rel="noopener noreferrer">https://github.com/DStorck/cka-prep</a></li>
</ul>
</li>
</ul>
</li>
<li>
<p><strong>CKS 资料</strong></p>
<ul>
<li>推荐 <a href="https://github.com/walidshaari/Certified-Kubernetes-Security-Specialist" target="_blank" rel="noopener noreferrer">https://github.com/walidshaari/Certified-Kubernetes-Security-Specialist</a></li>
<li>推荐 <a href="https://kubernetes-security.info/" target="_blank" rel="noopener noreferrer">https://kubernetes-security.info/</a></li>
</ul>
</li>
<li>
<p>其他人的经验</p>
<ul>
<li><a href="https://www.zhaohuabing.com/tags/cka/" target="_blank" rel="noopener noreferrer">https://www.zhaohuabing.com/tags/cka/</a></li>
<li><a href="https://www.reddit.com/r/kubernetes/comments/rzpu5i/i_just_passed_the_cka_here_are_some_tips_2022/" target="_blank" rel="noopener noreferrer">https://www.reddit.com/r/kubernetes/comments/rzpu5i/i_just_passed_the_cka_here_are_some_tips_2022/</a></li>
<li><a href="https://www.reddit.com/r/kubernetes/comments/s6l7xs/just_passed_the_cka_here_are_some_tips_and_tricks/" target="_blank" rel="noopener noreferrer">https://www.reddit.com/r/kubernetes/comments/s6l7xs/just_passed_the_cka_here_are_some_tips_and_tricks/</a></li>
</ul>
</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="考试信息登记">考试信息登记<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E8%80%83%E8%AF%95%E4%BF%A1%E6%81%AF%E7%99%BB%E8%AE%B0" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p><a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E6%BF%80%E6%B4%BB%E8%80%83%E8%AF%95%E5%88%B8">激活考试券</a>后下拉页面进行考试信息登记</p>
<p><img decoding="async" loading="lazy" alt="1665368927925" src="https://cloudnative.love/assets/images/1665368895806-bd8d032c7fda2b79a7047bff2bd9fe7a.png" title="激活后在此填写信息" width="1276" height="445" class="img_ev3q"></p>
<p>按照登记要求仔细阅读相关手册</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>2022 年 6 月 25 日，Linux 基金会将 CKA、CKAD 和 CKS 程序从 PSI 的 ExamsLocal 监考平台迁移到PSI Bridge，因为考生收到了去年开始的通知，并提醒了上个月。考试内容没有变化。主要变化是候选人：</p><ul>
<li>不再需要与监考人员共享桌面</li>
<li>无需等待监考人员即可自行办理登机手续</li>
<li>只能有一个活动监视器（内置或外置）</li>
<li>现在将使用 PSI 安全浏览器而不是 Chrome</li>
</ul></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="证件准备">证件准备<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E8%AF%81%E4%BB%B6%E5%87%86%E5%A4%87" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>认真阅读 <a href="https://docs.linuxfoundation.org/tc-docs/certification/lf-cert-agreement#4-1-candidate-id-and-consent-to-photo-video-and-audio-recording" target="_blank" rel="noopener noreferrer">Linux 基金会全球认证和保密协议——4.1 候选人 ID 和对照片、视频和录音的同意</a></p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>截取部分内容</div><div class="admonitionContent_BuS1"><blockquote>
<p>2022 年 8 月更新</p>
<p>候选人需要提供符合以下要求的身份证明（ID）：</p>
<ul>
<li>所有身份证件必须是政府签发的有效（未过期）<strong>原件</strong>（即非复印件）</li>
<li>身份证件必须包括候选人的姓名、照片和签名<!-- -->
<ul>
<li>政府签发的不包含签名的生物识别 ID 将被接受</li>
</ul>
</li>
<li>身份证件上的名字和姓氏必须与 考试清单中输入的经过验证的姓名<strong>完全一致</strong></li>
</ul>
<p>可接受的身份证件形式：</p>
<ul>
<li>国际旅行护照</li>
<li>政府颁发的驾驶执照/许可证</li>
<li>政府签发的当地语言身份证（带照片和签名）</li>
<li>国民身份证 国家或省签发的身份证</li>
<li>外国人登记卡（绿卡或永久居民/签证）</li>
<li>住民基本台帐（附照片的住民基本台帐）或マイナンバーカード（个人编号卡）</li>
</ul>
</blockquote></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="考试清单名字填写">考试清单名字填写<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E8%80%83%E8%AF%95%E6%B8%85%E5%8D%95%E5%90%8D%E5%AD%97%E5%A1%AB%E5%86%99" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>打开考试清单填写页面</p>
<p><img decoding="async" loading="lazy" alt="1665369589388" src="https://cloudnative.love/assets/images/1665369589388-b4ea54112cbc32990024f486c46b13d4.png" width="1200" height="327" class="img_ev3q"></p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>显示的名称必须与您提交的政府发行的照片ID相匹配，以验证您的身份。这将是在您的证书上打印的名称，直到此证书续订后才能更改。</p></div></div>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>FAQ</div><div class="admonitionContent_BuS1"><p><strong>填写中文名还是英文名？</strong></p><p>按照官方的建议 <code>保证考试清单姓名和提供证件一致</code>。如果使用身份证要填写中文名，护照则填写英文名。</p><p>ps: 我使用身份证填写的中文名</p><p><strong>填写中文名考试证书会乱码嘛？</strong></p><p>考试清单名字填写格式：<code>firstName空格lastName</code></p><p>正确格式如下
<code>Zhang San</code>
<code>Li Xiaosi</code>
<code>李 小四</code>
如果使用 <code>李小四</code> 则最后证书上面会变成 <code>. 李小四</code>
系统认为 <code>firstName</code> 不存在默认使用 <code>.</code> 代替导致</p></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="模拟考试">模拟考试<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E6%A8%A1%E6%8B%9F%E8%80%83%E8%AF%95" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>在考试清单填写页面，可以看到考试附赠了你两次 <code>killer.sh</code> 模拟考试 <a href="https://killer.sh/faq" target="_blank" rel="noopener noreferrer">FAQ</a>
<img decoding="async" loading="lazy" alt="1665369649975" src="https://cloudnative.love/assets/images/1665369649975-4782481aecb466b2d05fa347d8c54559.png" width="1186" height="124" class="img_ev3q">
点击 <code>Click here to access the Exam Simulator</code> 跳转到 <a href="https://killer.sh/dashboard" target="_blank" rel="noopener noreferrer">killer.sh</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="答题技巧">答题技巧<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E7%AD%94%E9%A2%98%E6%8A%80%E5%B7%A7" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<ol>
<li>多用命令生成资源和 yaml <code>--dry-run=client -o yaml</code></li>
<li>禁止优雅关闭加快删除 POD 时间 <code>--force --grace-period 0</code></li>
<li>使用explain 查询 Kubernetes 资源的声明参数</li>
</ol>
<ul>
<li>如查询Pod的metadata 使用<code>--recursive</code>递归式列出所有参数<!-- -->
<ul>
<li><code>kubectl explain Pod.metadata --recursive</code></li>
</ul>
</li>
</ul>
<ol start="4">
<li>考试使用远程桌面，你不能像以前那样把书签提前存到浏览器，好在题中自带相关文档连接，只是个别有些不准，最好记住每个细节在文档中的位置。</li>
<li>显示器越大越好，因为远程桌面只占你屏幕的三分之二，我17寸的笔记本屏幕感觉有点小体验不是很好。</li>
<li>如果你不想举着笔记本转圈的话建议购买外置摄像头，注意要买可视角度大的，不然很不方便。</li>
<li>你的考试带有一次免费补考，两次考试内容基本一致，所以你可以将不确定的题截取下来</li>
</ol>
<ul>
<li>Linux GDE 截屏快捷键 Alt+PrtScr ，建议 Gnome 在考试时候开启 <code>请勿打扰</code> 屏蔽系统通知，降低系统声音音量 <code>设置-声音-音量级别-系统声音</code> ，Linux 还要注意你的麦克风声音不要过噪。</li>
<li>windows 截屏快捷键 Win+PrtScr</li>
<li>MAC 截屏快捷键 Shift+Command+3</li>
</ul>
<ol start="8">
<li>考试时间建议早上8点，我晚上考很卡而且有时候不用科学网络会连不上远程桌面。。。</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="证书与徽章">证书与徽章<a href="https://cloudnative.love/blog/2022/12/20/CKA-CKAD-CKS-Tutoral/README#%E8%AF%81%E4%B9%A6%E4%B8%8E%E5%BE%BD%E7%AB%A0" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>考完试别忘记激活领取你的徽章哦~</p>
<p>目前考完24小时后可在 <a href="https://trainingportal.linuxfoundation.org/learn/dashboard" target="_blank" rel="noopener noreferrer">linuxfoundation learn</a> 查看证书。</p>
<p>注意邮件查收，并到 <a href="https://info.credly.com/" target="_blank" rel="noopener noreferrer">https://info.credly.com/</a> 领取你的徽章。</p>
<p>领取后你可以参考如下代码将它添加到你的 Github Profile 中去~</p>
<div class="playgroundContainer_X_Ta"><div class="playgroundHeader_dyrN">结果</div><div class="playgroundPreview_DzOI"><div>Loading...</div></div><div class="playgroundHeader_dyrN">实时编辑器</div><div class="playgroundEditor_Q6Y7"><pre class="prism-code language-tsx" style="margin:0;outline:none;padding:10px;font-family:inherit;color:#393A34;background-color:#f6f8fa" spellcheck="false"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">p</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">align</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"> </span>
</span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">a</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">href</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">https://www.credly.com/badges/7f665fcf-c0a4-44e7-8b09-06584280dfc2</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span>
</span><span class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">width</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">200</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">height</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">200</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">https://images.credly.com/size/680x680/images/8b8ed108-e77d-4396-ac59-2504583b9d54/cka_from_cncfsite__281_29.png</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">alt</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">CKA</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span>
</span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">a</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"> </span>
</span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">a</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">href</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">https://www.credly.com/badges/c37a3b97-5438-4c05-a28b-6ea2d6f38905</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span>
</span><span class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">width</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">200</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">height</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">200</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">https://images.credly.com/size/680x680/images/f88d800c-5261-45c6-9515-0458e31c3e16/ckad_from_cncfsite.png</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">alt</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">CKAD</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span>
</span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">a</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"> </span>
</span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">a</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">href</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">https://www.credly.com/badges/02d42601-dfd8-41de-a90b-6e1aba0c716d</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span>
</span><span class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">width</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">200</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">height</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">200</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">https://images.credly.com/size/680x680/images/9945dfcb-1cca-4529-85e6-db1be3782210/kubernetes-security-specialist-logo2.png</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">alt</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">CKS</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span>
</span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">a</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"> </span>
</span><span class="token-line" style="color:#393A34"><span class="token plain-text"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span>
</span></pre></div></div>]]></content>
        <category label="CKA" term="CKA"/>
        <category label="CKAD" term="CKAD"/>
        <category label="CKS" term="CKS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[镜像优化：Spring Boot 分层打包最佳实践]]></title>
        <id>https://cloudnative.love/blog/2022/11/21/镜像优化：Spring Boot 分层打包最佳实践/README</id>
        <link href="https://cloudnative.love/blog/2022/11/21/镜像优化：Spring Boot 分层打包最佳实践/README"/>
        <updated>2022-11-21T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[1673346680164]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="1673346680164" src="https://cloudnative.love/assets/images/1673346680164-1826352337256217f70ac0401e115f36.png" width="1600" height="576" class="img_ev3q">
Java 容器镜像通常会有一个体积巨大的 JAR 包（fat-JAR）独占一个文件系统层，我们对应用程序代码所做的每一次更改都会更改该层。这是非常糟糕的，事实上这个 JAR 包含外部依赖和内部依赖，我们可以进一步通过分层来优化，充分利用分层缓存机制使其共享依赖层。</p>
<p>本文将通过 <code>解压 JAR 分层优化</code> 和 <code>Spring Boot 2.3 引入的分层索引特性</code> 将 JAR 分成多个层来改进这一点。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="先复习一下基本操作">先复习一下基本操作<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#%E5%85%88%E5%A4%8D%E4%B9%A0%E4%B8%80%E4%B8%8B%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>从 Docker 1.10 开始，COPY、ADD 和 RUN 语句会向镜像中添加新层，为了缩小最终制品体积常用 Docker 的多阶段构建来进行优化。</p>
<div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">一般 Dockerfile</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">多阶段构建 Dockerfile</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> ubuntu</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> apt-get update</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> apt-get install vim</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><img decoding="async" loading="lazy" alt="1,gif" src="https://cloudnative.love/assets/images/1-59f816f602fd736cff33e218f0c5cdb7.gif" width="800" height="372" class="img_ev3q"></p></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> node:8 </span><span class="token instruction keyword" style="color:#00009f">as</span><span class="token instruction"> build</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">WORKDIR</span><span class="token instruction"> /app</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> package.json index.js ./</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> npm install</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> node:8</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--from</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">build</span><span class="token instruction"> /app /</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">EXPOSE</span><span class="token instruction"> 3000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">CMD</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"index.js"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><img decoding="async" loading="lazy" alt="2,gif" src="https://cloudnative.love/assets/images/2-644a10aa455c8ab94a3a1cb1f7fa15bb.gif" width="800" height="372" class="img_ev3q"></p></div></div></div>
<p>在没有带 --no-cache=true 指令的情况下如果某一层没有改动，Docker 不会重新构建这一层而是会使用缓存
默认情况下如果第n层有改动，则n层以后的缓存都会失效，大多数情况下判断有无改动的方法是判断这层的指令和缓存中的构建指令是否一致，但是对于 COPY 和 ADD 命令会计算镜像内的文件和构建目录文件的校验和然后做比较来判断本层是否有改动。</p>
<p>最理想的情况下，我们希望将变化最快的东西放在最高层，并与其他应用程序共享尽可能多的大型、较低层，如 <code>package.json</code> 或者 <code>composer.json</code> 之类的包管理声明文件变动的时候会重新的安装包，在没有变动的情况下使用缓存缩短构建时间。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="一个基础-dockerfile">一个基础 Dockerfile<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#%E4%B8%80%E4%B8%AA%E5%9F%BA%E7%A1%80-dockerfile" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">VOLUME</span><span class="token instruction"> /tmp</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ARG</span><span class="token instruction"> JAR_FILE</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${JAR_FILE}</span><span class="token instruction"> app.jar</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"java"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"-jar"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"/app.jar"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>您可以把 <code>JAR_FILE</code> 作为命令的一部分传递给 docker（Maven 和 Gradle 不同）。</p>
<div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">Maven</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Gradle</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> build --build-arg </span><span class="token assign-left variable" style="color:#36acaa">JAR_FILE</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">target/*.jar </span><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> myorg/myapp </span><span class="token builtin class-name">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> build --build-arg </span><span class="token assign-left variable" style="color:#36acaa">JAR_FILE</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">build/libs/*.jar </span><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> myorg/myapp </span><span class="token builtin class-name">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></div>
<p>如果 ENTRYPOINT 命令行有点长，您可以将其提取到 shell 脚本中，如下所示：</p>
<div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">dockerfile</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">shell</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">VOLUME</span><span class="token instruction"> /tmp</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> run.sh .</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> target/*.jar app.jar</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"run.sh"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/sh</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">exec</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">java</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-jar</span><span class="token plain"> /app.jar</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>记住使用 exec 启动 java 进程（以便它可以处理KILL信号）：</p></div></div></div></div></div>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>ENTRYPOINT 注意事项:</div><div class="admonitionContent_BuS1"><div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">exec 格式与 shell 格式</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">ENTRYPOINT 自定义变量</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">自定义 ENTRYPOINT 子参数</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><ul>
<li>使用 exec 格式 java 进程可以响应发送到容器 KILL 的信号。</li>
<li>而 shell 格式是由 "/bin/sh -e" 启动的子进程。 /bin/sh 进程 PID 为1，而被启动的进程不是 PID 不为 1 ，从而无法收到 Unix 的信号，自然不能收到从 docker stop 发来的 SIGTERM 信号。</li>
<li>像 distroless 之类的基础镜像中没有 sh 也无法使用 shell 格式。</li>
</ul></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>ENTRYPOINT 方便我们在运行时将环境变量注入 Java 进程。例如，假设您希望可以选择在运行时添加 Java 命令行选项。您可以尝试这样做：</p><div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">错误示范</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">正确示范</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction">  [</span><span class="token instruction string" style="color:#e3116c">"java"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"${JAVA_OPTS}"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"-jar"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"/app.jar"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">9000</span><span class="token plain">:9000 </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">JAVA_OPTS</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">-Dserver.port</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">9000</span><span class="token plain"> myorg/myapp</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这会失败，因为想要使用 <code>${ }</code> 变量需要一个 shell。exec 形式不使用 shell 来启动进程。</p></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>您可以通过将入口点移动到脚本（如run.sh前面所示的示例）或通过在 ENTRYPOINT 中创建显式 shell （ENTRYPOINT with an explicit shell）来解决这个问题，如下所示：</p><div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"sh"</span><span class="token instruction">, </span><span class="token instruction string" style="color:#e3116c">"-c"</span><span class="token instruction">, </span><span class="token instruction string" style="color:#e3116c">"java ${JAVA_OPTS} -jar /app.jar"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain">:8080 </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"JAVA_OPTS=-Ddebug -Xmx128m"</span><span class="token plain"> myorg/myapp</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">错误示范</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">正确示范</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"sh"</span><span class="token instruction">, </span><span class="token instruction string" style="color:#e3116c">"-c"</span><span class="token instruction">, </span><span class="token instruction string" style="color:#e3116c">"java ${JAVA_OPTS} -jar /app.jar"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">9000</span><span class="token plain">:9000 myorg/myapp </span><span class="token parameter variable" style="color:#36acaa">--server.port</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">9000</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>它会失败，因为 <code>--server.port=9000</code> 部分被传递到 ENTRYPOINT (sh)，而不是它启动的 Java 进程。要解决此问题，您需要将命令行从 CMD 添加到 ENTRYPOINT ：</p></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">VOLUME</span><span class="token instruction"> /tmp</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ARG</span><span class="token instruction"> JAR_FILE=target/*.jar</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${JAR_FILE}</span><span class="token instruction"> app.jar</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"sh"</span><span class="token instruction">, </span><span class="token instruction string" style="color:#e3116c">"-c"</span><span class="token instruction">, </span><span class="token instruction string" style="color:#e3116c">"java ${JAVA_OPTS} -jar /app.jar ${0} ${@}"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>请注意<code>${0}</code>（第一个参数）和<code>${@}</code>（其余参数）的使用。如果您使用脚本作为 ENTRYPOINT，则不需要<code>${0}</code>（/app/run.sh 在前面的示例中）。</p><p>以下列表显示了脚本文件中的正确命令：</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/sh</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">exec</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">java</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">${JAVA_OPTS}</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-jar</span><span class="token plain"> /app.jar </span><span class="token variable" style="color:#36acaa">${@}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></div></div></div></div></div></div>
<p>目前为止 docker 配置很简单，但 docker 镜像有一个包含 <code>fat JAR</code> 的文件系统层，我们对应用程序代码所做的每一次更改都会更改该层。即使你只改了几kb的class，一样会导致这200Mb-300Mb 的 <code>fat JAR</code> 层缓存失效，这会占用大量更新服务时镜像下拉时间，而且在国内外镜像仓库同步时会占用大量带宽。</p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">VOLUME</span><span class="token instruction"> /tmp</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> run.sh .</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> target/*.jar app.jar</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"run.sh"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>这时我们可以利用 <code>解压 JAR 分层优化</code> 或者 <code>Spring Boot 2.3 引入的分层索引特性</code> 将 JAR 分成多个层来改进这一点。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="一般-jar-分层优化">一般 JAR 分层优化<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#%E4%B8%80%E8%88%AC-jar-%E5%88%86%E5%B1%82%E4%BC%98%E5%8C%96" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>由于 JAR 本身的打包方式，Spring Boot <code>fat JAR</code> 自身为一层。我们可以先解压它，将其分为外部依赖和内部依赖，使更多的层可以被缓存。以下演示解压缩 Spring Boot fat JAR：（使用 Maven 但 Gradle 版本非常相似）</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">mkdir</span><span class="token plain"> target/dependency</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cd target/dependency</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> jar </span><span class="token parameter variable" style="color:#36acaa">-xf</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">/*.jar</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> build </span><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> myorg/myapp </span><span class="token builtin class-name">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>然后我们可以使用下面的Dockerfile</p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">VOLUME</span><span class="token instruction"> /tmp</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ARG</span><span class="token instruction"> DEPENDENCY=target/dependency</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${DEPENDENCY}</span><span class="token instruction">/BOOT-INF/lib /app/lib</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${DEPENDENCY}</span><span class="token instruction">/META-INF /app/META-INF</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${DEPENDENCY}</span><span class="token instruction">/BOOT-INF/classes /app</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"java"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"-cp"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"app:app/lib/*"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"hello.Application"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>现在是三层，所有的应用资源都在后两层。如果应用程序依赖关系没有改变，第一层（from BOOT-INF/lib）不需要改变，所以构建速度更快，并且容器在运行时的启动也更快，只要基础层已经被缓存。</p>
<p>写成多阶段构建形式如下所示：</p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine </span><span class="token instruction keyword" style="color:#00009f">as</span><span class="token instruction"> build</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">WORKDIR</span><span class="token instruction"> /workspace/app</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> mvnw .</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> .mvn .mvn</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> pom.xml .</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> src src</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> ./mvnw install -DskipTests</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> mkdir -p target/dependency &amp;&amp; (cd target/dependency; jar -xf ../*.jar)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">VOLUME</span><span class="token instruction"> /tmp</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ARG</span><span class="token instruction"> DEPENDENCY=/workspace/app/target/dependency</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--from</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">build</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${DEPENDENCY}</span><span class="token instruction">/BOOT-INF/lib /app/lib</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--from</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">build</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${DEPENDENCY}</span><span class="token instruction">/META-INF /app/META-INF</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--from</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">build</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${DEPENDENCY}</span><span class="token instruction">/BOOT-INF/classes /app</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"java"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"-cp"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"app:app/lib/*"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"hello.Application"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>这里示例为 hello.Application 可能与您的应用程序不同。如果你愿意，你可以用另一个 ARG 参数代替它。</p><p>您还可以将 Spring Boot fat 复制 JarLauncher 到映像中并使用它来运行应用程序。通过 JarLauncher 你将不需要指定主类，但它在启动时会有点慢。</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="spring-boot-分层索引">Spring Boot 分层索引<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#spring-boot-%E5%88%86%E5%B1%82%E7%B4%A2%E5%BC%95" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>从 Spring Boot 2.3.0 开始，在 JAR 文件中包含<a href="https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.container-images.layering" target="_blank" rel="noopener noreferrer">层信息</a>。该层信息根据应用程序构建之间更改的可能性将应用程序的各个部分分开。这可用于使 Docker 图像层更加高效。</p>
<p>层信息可用于将 JAR 内容提取到每个层的目录中：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">mkdir</span><span class="token plain"> target/extracted</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">java</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-Djarmode</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">layertools </span><span class="token parameter variable" style="color:#36acaa">-jar</span><span class="token plain"> target/*.jar extract </span><span class="token parameter variable" style="color:#36acaa">--destination</span><span class="token plain"> target/extracted</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> build </span><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> myorg/myapp </span><span class="token builtin class-name">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>然后我们可以使用以下内容Dockerfile：</p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">VOLUME</span><span class="token instruction"> /tmp</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ARG</span><span class="token instruction"> EXTRACTED=/workspace/app/target/extracted</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${EXTRACTED}</span><span class="token instruction">/dependencies/ ./</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${EXTRACTED}</span><span class="token instruction">/spring-boot-loader/ ./</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${EXTRACTED}</span><span class="token instruction">/snapshot-dependencies/ ./</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${EXTRACTED}</span><span class="token instruction">/application/ ./</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"java"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"org.springframework.boot.loader.JarLauncher"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>Spring Boot fatJarLauncher 是从 JAR 中提取到镜像中的，因此它可以用于启动应用程序而无需指定 main class。</p><p>有关使用分层功能的更多信息，请参阅<a href="https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#container-images.dockerfiles" target="_blank" rel="noopener noreferrer">Spring Boot 文档</a>。</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="安全方面">安全方面<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#%E5%AE%89%E5%85%A8%E6%96%B9%E9%9D%A2" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>遵循最小特权原则，进程不应以 root 权限运行，镜像应该包含运行应用程序的非根用户。</p>
<p>在 Dockerfile 中，您可以通过添加另一层添加系统用户和组并将其设置为当前用户（而不是默认的 root）来实现此目的：</p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> addgroup -S demo &amp;&amp; adduser -S demo -G demo</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">USER</span><span class="token instruction"> demo</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>一些 Dockerfile 命令只能以 root 身份使用，因此您可能必须将 USER 命令向下一层移动（例如，如果您计划在容器中安装更多包，容器只能以 root 身份使用）。</p></div></div>
<p>另一个考虑因素是，大多数应用程序在运行时可能不需要完整的 JDK，因此一旦我们进行了多阶段构建，我们就可以安全地切换到 JRE 基础映像。因此，在前面显示的多阶段构建中，我们可以使用最终的可运行图像：</p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jre-alpine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>如前所述，这也节省了图像中的一些空间，这些空间将被运行时不需要的工具占用。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="基础镜像的选择">基础镜像的选择<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#%E5%9F%BA%E7%A1%80%E9%95%9C%E5%83%8F%E7%9A%84%E9%80%89%E6%8B%A9" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="alpine">alpine<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#alpine" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>前面示例中的基本图像是 eclipse-temurin:17-jdk-alpine. 这些 alpine 图像小于来自 Dockerhub eclipse-temurin 的标准库图像。</p>
<ul>
<li>Alpine 使用非标准的 C 库  musl libc 而不是 glibc 。muslibc 可能导致异常的 dns 解析，以及不支持 <code>/etc/resolv.conf</code> 的部分配置</li>
<li>Alpine 并不比其他发行版小。 一旦你添加了任何需要的包，一个 Alpine Linux 镜像就和更主流的发行版一样大。</li>
<li>Alpine 并不安全，没有为 alpine 维护的安全漏洞 (CVE) 列表，因此像 Clair (SAST) 这样的工具无法正确扫描它</li>
<li>无法使用 LXCFS 来提升容器资源可见性</li>
<li>alpine 的镜像有性能问题超过 4 core 以上的应用场景，会发现 CPU 使用率上不去，原因未知,所以我们认为是 alpine 这个镜像本身，不适合 API 网关应用场景 (对性能有极致要求)</li>
<li>详情请参考以下文章<!-- -->
<ul>
<li><a href="https://www.dotcms.com/blog/post/moving-to-ubuntu-for-our-docker-image" target="_blank" rel="noopener noreferrer">Moving to Ubuntu for our Docker image</a></li>
<li><a href="https://medium.com/inside-sumup/stop-using-alpine-docker-images-fbf122c63010" target="_blank" rel="noopener noreferrer">Stop using Alpine Docker images</a></li>
<li><a href="https://megamorf.gitlab.io/2020/05/06/why-it-s-better-not-to-use-alpine-linux-for-python-projects/" target="_blank" rel="noopener noreferrer">Why it's better not to use Alpine Linux for python projects</a></li>
<li><a href="https://ttys3.dev/post/do-not-use-alpine-in-production-environment/" target="_blank" rel="noopener noreferrer">不要在生产环境中使用alpine基础镜像 – 容器基础镜像的选择</a></li>
<li><a href="https://pythonspeed.com/articles/alpine-docker-python/" target="_blank" rel="noopener noreferrer">Using Alpine can make Python Docker builds 50× slower</a>
<ul>
<li>有一种特殊情况会同时遇到 Alpine 的绝大多数问题：将 Python 用于数据科学。numpy 和 pandas 之类的包都被预编译成了 wheel，wheel 是 Python 新的打包格式，被编译成了二进制，用于替代 Python 传统的 egg 文件，可以通过 pip 直接安装。但这些 wheel 都绑定了特定的 C 库，这就意味着在大多数使用 glibc 的镜像中都可以正常安装，但 Alpine 就不行。如果非要在 Alpine 中安装，你需要安装很多依赖，重头构建，耗时又费力。</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="distrolessubibazel">distroless/ubi/bazel<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#distrolessubibazel" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>distroless/ubi都可以从容器中移除所有不必要的 cruft，它们仅包含您的应用程序及其运行时依赖项。它们不包含包管理器、shell 以及您希望在标准 Linux 发行版中找到的任何其他程序。它有着更小的攻击面和更小的体积。</p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">示例</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> node:8 </span><span class="token instruction keyword" style="color:#00009f">as</span><span class="token instruction"> build</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">WORKDIR</span><span class="token instruction"> /app</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> package.json index.js ./</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> npm install</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> gcr.io/distroless/nodejs</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--from</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">build</span><span class="token instruction"> /app /</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">EXPOSE</span><span class="token instruction"> 3000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">CMD</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"index.js"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>如果你要问 <a href="https://github.com/GoogleCloudPlatform/distroless" target="_blank" rel="noopener noreferrer">GoogleCloudPlatform/distroless</a> 和 <a href="https://developers.redhat.com/products/rhel/ubi" target="_blank" rel="noopener noreferrer">redhat ubi</a> 有什么区别呢？</p>
<p>那么可以参考：</p>
<ul>
<li>红帽的这篇文章 <a href="https://www.redhat.com/en/blog/why-distroless-containers-arent-security-solution-you-think-they-are" target="_blank" rel="noopener noreferrer">Why distroless containers aren't the security solution you think they are</a></li>
<li>和这个仓库 <a href="https://github.com/raif-ahmed/ubi-vs-distroless-images" target="_blank" rel="noopener noreferrer">raif-ahmed/ubi-vs-distroless-images</a></li>
</ul>
<p>调试它们可以参考 linux 下 通过 nsenter 进入命名空间 或者 kubectl-debug 插件 或者 <a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/ephemeral-containers/" target="_blank" rel="noopener noreferrer">kubernetes 临时容器（ephemeral-containers）</a>，本文不再赘述。</p>
<p>扩展阅读：</p>
<ul>
<li>识别应用程序运行时依赖性 <a href="https://unrealcontainers.com/blog/identifying-application-runtime-dependencies/#types-of-dependencies" target="_blank" rel="noopener noreferrer">Identifying application runtime dependencies</a></li>
<li><a href="https://bazel.build/" target="_blank" rel="noopener noreferrer">https://bazel.build/</a></li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="选择合适的-jre-jdk">选择合适的 JRE JDK<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#%E9%80%89%E6%8B%A9%E5%90%88%E9%80%82%E7%9A%84-jre-jdk" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>我们可以在多阶段构建的 build 阶段使用 JDK 作为基础镜像，run 阶段使用 JRE 作为基础镜像。（并非所有应用程序都可以使用 JRE（相对于 JDK），但大多数都可以。由于存在滥用某些 JDK 功能（例如编译）的风险，一些组织强制要求每个应用程序都必须使用 JRE 。）</p>
<ul>
<li>JRE 即 Java 运行时环境（Java Runtime Environment），包含了运行 Java 程序所需要的环境，即 JVM。</li>
<li>JDK 即 Java 开发工具包（Java Development Kit），既包含了 JRE，也包含了开发 Java 程序所需的工具，即 Java 编译器。</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="jlink">JLink<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#jlink" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>JLink 与 OpenJDK 11 及更高版本捆绑在一起。JLink 允许您从完整 JDK 中的模块子集构建自定义 JRE 分发，因此您不需要基础映像中的 JRE 或 JDK。这将使您获得比官方JRE/JDK图像更小的总图像大小。</p>
<p>缺点是自定义的 JRE 不能在其他应用程序之间共享，因为它们需要不同的自定义。因此，您的所有应用程序的图像可能都较小，但它们仍然需要更长的时间才能启动，因为它们无法从缓存 JRE 层中获益。</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>目标镜像并不一定总是要建立尽可能小。较小的图像通常是一个好主意，因为在它们中的任何一个层都没有被缓存时它们上传和下载的时间较短。
由于Docker用的是overlay fs, 这个fs的魔法之处在于，base image其实你只需要pull一次，存储在磁盘上也只需要存储一次而已。
因为镜像仓库支持分层缓存，如果使用公共基础镜像你只需要缓存一次，所以镜像的总大小不太受关注。随着镜像格式和镜像分发方式的发展，如 <a href="https://nydus.dev/" target="_blank" rel="noopener noreferrer">nydus 镜像格式</a> 和 <a href="https://d7y.io/" target="_blank" rel="noopener noreferrer">Dragonfly p2p 分发方案</a> 镜像大小将会越来越不受关注。</p><p>尽管如此，在我们的应用镜像中尝试优化层仍然是重要的，而且是有用的。原则是将变化最快的东西放在最高层，并与其他应用程序共享尽可能多的大型、较低层。</p></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="graalvm-native-image">GraalVM native-image<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#graalvm-native-image" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>在云原生大背景下，对应用要求之一是 Disposability (易处置 - 快速启动和优雅退出), 而 java-jvm 存在预热慢、冷启动慢，而且内存占用巨大，不适合 serverless 场景，这里有基于 AWS Lambda 的所有语言的冷/热启动性能对比 <a href="https://filia-aleks.medium.com/aws-lambda-battle-2021-performance-comparison-for-all-languages-c1b441005fd1" target="_blank" rel="noopener noreferrer">AWS Lambda battle 2021: performance comparison for all languages (cold and warm start)</a>。</p>
<p>所以 GraalVM 推出了 <a href="https://www.graalvm.org/22.3/reference-manual/native-image/basics/" target="_blank" rel="noopener noreferrer">native-image</a>，它可以将 Java 字节码作为输入来生成独立的二进制文件，所以不需要 JVM/GraalVM 之类 runtime，同时极大的降低了冷启动时间、内存消耗和应用体积。当然 Graalvm native-image 也是存在缺点的，比如夸张的编译时间，暂时不支持JVMTI、Java代理、JMX、JFR，不支持线程转储和堆转储等，更多请参考 <a href="https://www.graalvm.org/22.3/reference-manual/native-image/metadata/Compatibility/" target="_blank" rel="noopener noreferrer">native-image 兼容性指南</a> 这部分提供了有关 GraalVM 限制的更多详细信息。</p>
<p>Spring 官方在下 2021 年 3 月 11 日 宣布了 <a href="https://spring.io/blog/2021/03/11/announcing-spring-native-beta" target="_blank" rel="noopener noreferrer">Spring Native Beta</a> 以支持 GraalVM native-image ，
2022 年 11月24日 Spring Boot 3 正式发布，与此同时	Spring Native 被 Spring Boot 3 官方原生支持所取代 <a href="https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html" target="_blank" rel="noopener noreferrer">相关参考文档</a>。这方便了在 Spring 中使用 GraalVM native-image 进行编译。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="补充">补充<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#%E8%A1%A5%E5%85%85" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<ul>
<li>如果你想尽快启动你的应用程序，你可能会考虑一些调整，参考文档：<a href="https://spring.io/guides/topicals/spring-boot-docker/#_tweaks" target="_blank" rel="noopener noreferrer">tweaks</a></li>
<li>这里还有一些自动化构建插件，参考文档：<a href="https://spring.io/guides/topicals/spring-boot-docker/#_build_plugins" target="_blank" rel="noopener noreferrer">build_plugins</a></li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="jib-插件">Jib 插件<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#jib-%E6%8F%92%E4%BB%B6" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>下面简单的介绍一个插件 GoogleContainerTools/jib 参考文档：<a href="https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin#quickstart" target="_blank" rel="noopener noreferrer">Jib quickstart</a>，</p>
<p>Jib  可以自动帮你完成 JAR 分层以及一些其他的镜像优化。最重要的是 Jib 和 BuildKit、kaniko 一样都是 Dockerless 的，因此你不需要 docker 环境来运行它！这非常适合 CI/CD !</p>
<p>同时 Jib 不需要 Dockerfile（它无论如何都会被忽略）它的参数在 pom.xml 中定义，或者也可以作为参数传递给它。</p>
<p>以下示例在不更改的情况下使用 Maven pom.xml：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">mvn com.google.cloud.tools:jib-maven-plugin:build </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">-Djib.from.image</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">${FROM_IMAGE}</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">-Djib.to.image</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$CI_REGISTRY_IMAGE</span><span class="token builtin class-name">:</span><span class="token variable" style="color:#36acaa">$CI_COMMIT_REF_NAME</span><span class="token plain">-</span><span class="token variable" style="color:#36acaa">$CI_COMMIT_SHORT_SHA</span><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">-Djib.to.auth.username</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$CI_REGISTRY_USER</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">-Djib.to.auth.password</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$CI_REGISTRY_PASSWORD</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>这里有一篇来自 Google 关于容器构建工具的对比文章推荐阅读 <a href="https://cloud.google.com/blog/topics/developers-practitioners/comparing-containerization-methods-buildpacks-jib-and-dockerfile" target="_blank" rel="noopener noreferrer">Buildpacks vs Jib vs Dockerfile: Comparing containerization methods</a></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="docker-实验功能">Docker 实验功能<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#docker-%E5%AE%9E%E9%AA%8C%E5%8A%9F%E8%83%BD" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>Docker 18.06 带有一些“实验性”功能，包括缓存构建依赖项的方法。要打开它们，您需要守护程序中的标志 ( dockerd) 和运行客户端时的环境变量。</p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># syntax=docker/dockerfile:experimental</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>该RUN指令然后接受一个新标志：--mount。以下清单显示了一个完整的示例：</p>
<div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">Maven</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Gradle</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">Dockerfile for Maven</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># syntax=docker/dockerfile:experimental</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine </span><span class="token instruction keyword" style="color:#00009f">as</span><span class="token instruction"> build</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">WORKDIR</span><span class="token instruction"> /workspace/app</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> mvnw .</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> .mvn .mvn</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> pom.xml .</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> src src</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--mount</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">type=cache,target=/root/.m2</span><span class="token instruction"> ./mvnw install -DskipTests</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> mkdir -p target/dependency &amp;&amp; (cd target/dependency; jar -xf ../*.jar)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">VOLUME</span><span class="token instruction"> /tmp</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ARG</span><span class="token instruction"> DEPENDENCY=/workspace/app/target/dependency</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--from</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">build</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${DEPENDENCY}</span><span class="token instruction">/BOOT-INF/lib /app/lib</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--from</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">build</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${DEPENDENCY}</span><span class="token instruction">/META-INF /app/META-INF</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--from</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">build</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${DEPENDENCY}</span><span class="token instruction">/BOOT-INF/classes /app</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"java"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"-cp"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"app:app/lib/*"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"hello.Application"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">Dockerfile for Gradle</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># syntax=docker/dockerfile:experimental</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine </span><span class="token instruction keyword" style="color:#00009f">AS</span><span class="token instruction"> build</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">WORKDIR</span><span class="token instruction"> /workspace/app</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> . /workspace/app</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--mount</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">type=cache,target=/root/.gradle</span><span class="token instruction"> ./gradlew clean build</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> mkdir -p build/dependency &amp;&amp; (cd build/dependency; jar -xf ../libs/*.jar)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> eclipse-temurin:17-jdk-alpine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">VOLUME</span><span class="token instruction"> /tmp</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ARG</span><span class="token instruction"> DEPENDENCY=/workspace/app/build/dependency</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--from</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">build</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${DEPENDENCY}</span><span class="token instruction">/BOOT-INF/lib /app/lib</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--from</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">build</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${DEPENDENCY}</span><span class="token instruction">/META-INF /app/META-INF</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--from</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">build</span><span class="token instruction"> </span><span class="token instruction variable" style="color:#36acaa">${DEPENDENCY}</span><span class="token instruction">/BOOT-INF/classes /app</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"java"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"-cp"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"app:app/lib/*"</span><span class="token instruction">,</span><span class="token instruction string" style="color:#e3116c">"hello.Application"</span><span class="token instruction">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></div>
<p>然后你可以运行它：</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">DOCKER_BUILDKIT=1 docker build -t myorg/myapp .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">=&gt; /bin/sh -c ./mvnw install -DskipTests              5.7s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">=&gt; exporting to image                                 0.0s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">=&gt; =&gt; exporting layers                                0.0s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">=&gt; =&gt; writing image sha256:3defa...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">=&gt; =&gt; naming to docker.io/myorg/myapp</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>使用实验性功能，您可以在控制台上获得不同的输出，但您可以看到 Maven 构建现在只需要几秒钟而不是几分钟，前提是缓存是热的。</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>虽然这些功能处于实验阶段，但打开和关闭 buildkit 的选项取决于docker您使用的版本。检查您拥有的版本的文档（前面显示的示例适用于docker18.0.6）。</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="参考文档">参考文档<a href="https://cloudnative.love/blog/2022/11/21/%E9%95%9C%E5%83%8F%E4%BC%98%E5%8C%96%EF%BC%9ASpring%20Boot%20%E5%88%86%E5%B1%82%E6%89%93%E5%8C%85%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/README#%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<ul>
<li><a href="https://spring.io/guides/topicals/spring-boot-docker/" target="_blank" rel="noopener noreferrer">Spring Boot Docker</a></li>
<li><a href="https://itnext.io/3-simple-tricks-for-smaller-docker-images-f0d2bda17d1e" target="_blank" rel="noopener noreferrer">3 simple tricks for smaller Docker images</a></li>
</ul>]]></content>
        <category label="Images" term="Images"/>
        <category label="Spring Boot" term="Spring Boot"/>
        <category label="Docker" term="Docker"/>
        <category label="Java" term="Java"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[管理 GitOps 中的 Secret：Argocd-Vault-Plugin]]></title>
        <id>https://cloudnative.love/blog/2022/07/23/管理 GitOps 中的 Secret：Argocd-Vault-Plugin/README</id>
        <link href="https://cloudnative.love/blog/2022/07/23/管理 GitOps 中的 Secret：Argocd-Vault-Plugin/README"/>
        <updated>2022-07-23T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Argocd-Vault-Plugin(AVP) 是一个自定义的 ArgoCD 插件，这个插件旨在帮助解决 GitOps 和 Argo CD 的 Secret 管理问题。用于从 HashiCorp Vault 等秘密管理器中检索秘密并将其注入 Kubernetes YAML 文件中，从而无需依赖 Operator 或 Custom Resource，这使得它不仅可以用于 Secrets 资源，还可以能够 parameterize 任何 Kubernetes 资源，甚至是自定义资源。]]></summary>
        <content type="html"><![CDATA[<p>Argocd-Vault-Plugin(AVP) 是一个自定义的 ArgoCD 插件，这个插件旨在帮助解决 GitOps 和 Argo CD 的 Secret 管理问题。用于从 HashiCorp Vault 等秘密管理器中检索秘密并将其注入 Kubernetes YAML 文件中，从而无需依赖 Operator 或 Custom Resource，这使得它不仅可以用于 Secrets 资源，还可以能够 parameterize 任何 Kubernetes 资源，甚至是自定义资源。</p>
<p>本文将介绍如何使用 Argocd-Vault-Plugin 管理 GitOps 中的 Secret</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="先决条件">先决条件<a href="https://cloudnative.love/blog/2022/07/23/%E7%AE%A1%E7%90%86%20GitOps%20%E4%B8%AD%E7%9A%84%20Secret%EF%BC%9AArgocd-Vault-Plugin/README#%E5%85%88%E5%86%B3%E6%9D%A1%E4%BB%B6" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>在开始本教程之前，请确保您已经部署ArgoCD/Vault。我们不会在本文中向您展示如何做到这一点，但您可以参考下面给出的文档和演示用例。</p>
<ul>
<li>ArgoCD — <a href="https://argoproj.github.io/argo-cd/getting_started/" target="_blank" rel="noopener noreferrer">https://argoproj.github.io/argo-cd/getting_started/</a>
快速开始 参考我的配置</li>
<li>Vault — <a href="https://www.vaultproject.io/docs/platform/k8s/helm/run" target="_blank" rel="noopener noreferrer">https://www.vaultproject.io/docs/platform/k8s/helm/run</a>
快速开始 使用开发模式</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="工作原理">工作原理<a href="https://cloudnative.love/blog/2022/07/23/%E7%AE%A1%E7%90%86%20GitOps%20%E4%B8%AD%E7%9A%84%20Secret%EF%BC%9AArgocd-Vault-Plugin/README#%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>该插件的工作原理是首先根据可以指定为环境变量或 YAML 文件内部的注释的路径从 Vault 等秘密管理器中检索值，然后将值注入到模板化的输出 yaml 中，该 yaml 使用 <code>&lt;&gt;</code> 作为模板标记。例如：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> example</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">annotations</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">avp.kubernetes.io/path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"path/to/secret"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Opaque</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">stringData</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">password</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> &lt;password</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">vault</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>在上面的yaml中，可以看到有一个标准的Kubernetes Secret定义。有一个名为 password 的秘密，但值是 <code>&lt;password-vault-key&gt;</code> ，如果插件在Vault中找到 password-vault-key 密钥，它将注入一个值。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="准备-vault-环境">准备 Vault 环境<a href="https://cloudnative.love/blog/2022/07/23/%E7%AE%A1%E7%90%86%20GitOps%20%E4%B8%AD%E7%9A%84%20Secret%EF%BC%9AArgocd-Vault-Plugin/README#%E5%87%86%E5%A4%87-vault-%E7%8E%AF%E5%A2%83" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>vault 部署后查看 vault-0 的日志来获取登录 token等信息</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl logs vault-0  </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> vault </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">WARNING</span><span class="token operator" style="color:#393A34">!</span><span class="token plain"> dev mode is enabled</span><span class="token operator" style="color:#393A34">!</span><span class="token plain"> In this mode, Vault runs entirely in-memory</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">and starts unsealed with a single unseal key. The root token is already</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">authenticated to the CLI, so you can immediately begin using Vault.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">You may need to </span><span class="token builtin class-name">set</span><span class="token plain"> the following environment variables:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    $ </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">VAULT_ADDR</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'http://[::]:8200'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">The unseal key and root token are displayed below </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> you want to</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">seal/unseal the Vault or re-authenticate.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Unseal Key: </span><span class="token assign-left variable" style="color:#36acaa">7MY282Sz3te29uktYXqAFEBZ04GMIs5fkceWYPzRwos</span><span class="token operator" style="color:#393A34">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Root Token: root</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Development mode should NOT be used </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> production installations</span><span class="token operator" style="color:#393A34">!</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>这时候，我们可以使用获取到的<code>Root Token</code> 进行登录。</p>
<p>你可以通过本地客户端登录</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">VAULT_ADDR</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">https://vault.cloudnative.love/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">vault login </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">your_token</span><span class="token operator" style="color:#393A34">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>或者进入 vault-0 容器内登录</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> vault </span><span class="token builtin class-name">exec</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-it</span><span class="token plain"> vault-0 -- </span><span class="token function" style="color:#d73a49">sh</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">vault login </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">your_token</span><span class="token operator" style="color:#393A34">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>登录后将看到如下提示</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Success</span><span class="token operator" style="color:#393A34">!</span><span class="token plain"> You are now authenticated. The token information displayed below</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">is already stored </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> the token helper. You </span><span class="token keyword" style="color:#00009f">do</span><span class="token plain"> NOT need to run </span><span class="token string" style="color:#e3116c">"vault login"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">again. Future Vault requests will automatically use this token.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Key                  Value</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">---                  -----</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">token                </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">your_token</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">token_accessor       </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">your_token_accessors</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">token_duration       ∞</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">token_renewable      </span><span class="token boolean" style="color:#36acaa">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">token_policies       </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"root"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">identity_policies    </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">policies             </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"root"</span><span class="token punctuation" style="color:#393A34">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="创建-vault-认证模式">创建 Vault 认证模式<a href="https://cloudnative.love/blog/2022/07/23/%E7%AE%A1%E7%90%86%20GitOps%20%E4%B8%AD%E7%9A%84%20Secret%EF%BC%9AArgocd-Vault-Plugin/README#%E5%88%9B%E5%BB%BA-vault-%E8%AE%A4%E8%AF%81%E6%A8%A1%E5%BC%8F" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>在使用 avp 此之前，让我们快速了解一下 vault 常用的<a href="https://argocd-vault-plugin.readthedocs.io/en/stable/backends/" target="_blank" rel="noopener noreferrer">认身份验证方式</a>。</p>
<ul>
<li>Userpass Authentication: 用户名密码身份验证</li>
<li>Token Authentication: 令牌身份验证，令牌身份验证自动启用。当您启动开发服务器时，输出显示一个 root 令牌。</li>
<li>AppRole Authentication(推荐)：应用角色授权</li>
<li>Kubernetes Authentication(推荐): Kubernetes身份验证，可用于使用Kubernetes的 service account 令牌对 Vault 进行身份验证。这种身份验证方法可以轻松地将Vault令牌引入Kubernetes Pod。</li>
</ul>
<p>下面我们来配置 vault 的身份验证</p>
<div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">Userpass Authentication</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Token Authentication</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">AppRole Authentication</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Kubernetes Authentication</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><p>比较简单此处省略</p><ul>
<li>官方文档：<a href="https://developer.hashicorp.com/vault/docs/auth/userpass" target="_blank" rel="noopener noreferrer">Userpass Authentication</a></li>
</ul></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><ul>
<li>参考文档 <a href="https://developer.hashicorp.com/vault/docs/commands/token/create" target="_blank" rel="noopener noreferrer">https://developer.hashicorp.com/vault/docs/commands/token/create</a>
可以运行 <code>vault token create</code> 命令，创建Vault 认证的token，运行此命令后，您将获得形式为hvs** 的令牌。保留该令牌</li>
</ul></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><ul>
<li>官方文档：<a href="https://developer.hashicorp.com/vault/docs/auth/approle" target="_blank" rel="noopener noreferrer">AppRole Authentication</a></li>
</ul><ol>
<li>启用 AppRole 身份验证方法：</li>
</ol><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">vault auth </span><span class="token builtin class-name">enable</span><span class="token plain"> approle</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><ol>
<li>创建一个命名角色：</li>
</ol><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">vault </span><span class="token function" style="color:#d73a49">write</span><span class="token plain"> auth/approle/role/avp-role </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token assign-left variable" style="color:#36acaa">secret_id_ttl</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">10m </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token assign-left variable" style="color:#36acaa">token_num_uses</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">10</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token assign-left variable" style="color:#36acaa">token_ttl</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">20m </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token assign-left variable" style="color:#36acaa">token_max_ttl</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">30m </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token assign-left variable" style="color:#36acaa">secret_id_num_uses</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">40</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>注意</div><div class="admonitionContent_BuS1"><p>如果您的approle发行的令牌需要创建子令牌的能力，您需要将token_num_uses设置为0。</p></div></div><ol start="3">
<li>获取AppRole的RoleID：</li>
</ol><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">vault </span><span class="token builtin class-name">read</span><span class="token plain"> auth/approle/role/avp-role/role-id</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Key        Value</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">---        -----</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">role_id    6f944878-1e02-c842-9251-5d8caa1af3f8</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><ol start="4">
<li>获取针对 AppRole 颁发的 SecretID：</li>
</ol><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">vault </span><span class="token function" style="color:#d73a49">write</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> auth/approle/role/avp-role/secret-id</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Key                   Value</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">---                   -----</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">secret_id             8e4732c5-5210-37a6-8d9b-2338d96b8018</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">secret_id_accessor    7d8a9fbb-4bcb-92ec-a909-25233838529d</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">secret_id_num_uses    </span><span class="token number" style="color:#36acaa">40</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">secret_id_ttl         10m</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><ol start="5">
<li>登录验证</li>
</ol><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">vault </span><span class="token function" style="color:#d73a49">write</span><span class="token plain"> auth/approle/login </span><span class="token assign-left variable" style="color:#36acaa">role_id</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">db02de05-fa39-4855-059b-67221c5c2f63 </span><span class="token assign-left variable" style="color:#36acaa">secret_id</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">6a174c20-f6de-a53c-74d2-6018fcceff64</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>由于我们在 Kubernetes 上运行它，所以更推荐使用更加原生的方法进行认证。</p><ol>
<li>启用 Kubernetes 身份验证</li>
</ol><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">vault auth </span><span class="token builtin class-name">enable</span><span class="token plain"> kubernetes</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><ol start="2">
<li>配置 kubernetes 认证。</li>
</ol><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">## get Kubernetes host address</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">K8S_HOST</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"https://</span><span class="token string variable" style="color:#36acaa">$(</span><span class="token string variable" style="color:#36acaa"> kubectl </span><span class="token string variable builtin class-name" style="color:#36acaa">exec</span><span class="token string variable" style="color:#36acaa"> </span><span class="token string variable parameter variable" style="color:#36acaa">-n</span><span class="token string variable" style="color:#36acaa"> vault vault-0 -- </span><span class="token string variable function" style="color:#d73a49">env</span><span class="token string variable" style="color:#36acaa"> </span><span class="token string variable operator" style="color:#393A34">|</span><span class="token string variable" style="color:#36acaa"> </span><span class="token string variable function" style="color:#d73a49">grep</span><span class="token string variable" style="color:#36acaa"> KUBERNETES_PORT_443_TCP_ADDR</span><span class="token string variable operator" style="color:#393A34">|</span><span class="token string variable" style="color:#36acaa"> </span><span class="token string variable function" style="color:#d73a49">cut</span><span class="token string variable" style="color:#36acaa"> </span><span class="token string variable parameter variable" style="color:#36acaa">-f2</span><span class="token string variable" style="color:#36acaa"> -d</span><span class="token string variable string" style="color:#e3116c">'='</span><span class="token string variable" style="color:#36acaa">)</span><span class="token string" style="color:#e3116c">:443"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## get Service Account token from Vault Pod</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">SA_TOKEN</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">kubectl </span><span class="token variable parameter variable" style="color:#36acaa">-n</span><span class="token variable" style="color:#36acaa"> vault </span><span class="token variable builtin class-name" style="color:#36acaa">exec</span><span class="token variable" style="color:#36acaa"> vault-0 -- </span><span class="token variable function" style="color:#d73a49">cat</span><span class="token variable" style="color:#36acaa"> /var/run/secrets/kubernetes.io/serviceaccount/token</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## get Service Account CA certificate from Vault Pod</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">SA_CERT</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">kubectl </span><span class="token variable parameter variable" style="color:#36acaa">-n</span><span class="token variable" style="color:#36acaa"> vault </span><span class="token variable builtin class-name" style="color:#36acaa">exec</span><span class="token variable" style="color:#36acaa"> vault-0 -- </span><span class="token variable function" style="color:#d73a49">cat</span><span class="token variable" style="color:#36acaa"> /var/run/secrets/kubernetes.io/serviceaccount/ca.crt</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## configure Kubernetes Auth Method</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">vault </span><span class="token function" style="color:#d73a49">write</span><span class="token plain"> auth/kubernetes/config </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token assign-left variable" style="color:#36acaa">token_reviewer_jwt</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$SA_TOKEN</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token assign-left variable" style="color:#36acaa">kubernetes_host</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$K8S_HOST</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token assign-left variable" style="color:#36acaa">kubernetes_ca_cert</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$SA_CERT</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><ol start="3">
<li>create authenticate Role for ArgoCD</li>
</ol><p>ArgoCD Vault 插件将使用该角色对 Vault 服务器进行身份验证。我们需要提供 ArgoCD 的命名空间以及 ArgoCD Repo 服务器使用的 Kubernetes service account 的名称。我们的令牌将在 24 小时后过期。</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">vault </span><span class="token function" style="color:#d73a49">write</span><span class="token plain"> auth/kubernetes/role/argocd </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token assign-left variable" style="color:#36acaa">bound_service_account_names</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">your-service-account</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token assign-left variable" style="color:#36acaa">bound_service_account_namespaces</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">argocd </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token assign-left variable" style="color:#36acaa">policies</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">argocd </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token assign-left variable" style="color:#36acaa">ttl</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">1h</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>该角色在默认命名空间中授权 <code>&lt;your-service-account&gt;</code> 服务帐户，并为其提供默认策略。</p><p>helm安装默认repo-server的SA为 <code>${RELASENAME}-argo-cd-argocd-repo-server</code></p><p>也可以 ArgoCD 实例的命名空间中创建自定义 SA。</p></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="配置-argo-vault-plugin">配置 Argo-Vault-Plugin<a href="https://cloudnative.love/blog/2022/07/23/%E7%AE%A1%E7%90%86%20GitOps%20%E4%B8%AD%E7%9A%84%20Secret%EF%BC%9AArgocd-Vault-Plugin/README#%E9%85%8D%E7%BD%AE-argo-vault-plugin" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>要想让avp通过vault认证，我们可以将认证参数作为环境变量保存为secret，并通过envFrom传入repo-server的pod中：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">envFrom</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">secretRef</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> argocd</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">vault</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">plugin</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">credentials</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>或者在avp命令中添加<code>--secret-name</code>指定包含认证参数的secret</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">argocd-vault-plugin generate --secret-name &lt;namespace&gt;:&lt;name&gt; .</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>不同认证模式所需环境变量参考<a href="https://argocd-vault-plugin.readthedocs.io/en/stable/backends/" target="_blank" rel="noopener noreferrer">官方文档 backends 部分</a></p>
<div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">Userpass/Token/AppRole Authentication</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Kubernetes Authentication</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>Userpass/Token/AppRole 认证所需环境变量</summary><div><div class="collapsibleContent_i85q"><p>Userpass 所需环境变量</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">VAULT_ADDR</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Your HashiCorp Vault Address</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">VAULT_TOKEN</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Your Vault token</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">AVP_TYPE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> vault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">AVP_AUTH_TYPE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> token</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Token 所需环境变量</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">VAULT_ADDR</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Your HashiCorp Vault Address</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">AVP_TYPE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> vault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">AVP_AUTH_TYPE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> userpass</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">AVP_USERNAME</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Your Username</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">AVP_PASSWORD</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Your Password</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>AppRole 所需环境变量</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">VAULT_ADDR</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Your HashiCorp Vault Address</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">AVP_TYPE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> vault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">AVP_AUTH_TYPE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> approle</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">AVP_ROLE_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Your AppRole Role ID</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">AVP_SECRET_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Your AppRole Secret ID</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></details><p>以AppRole为例创建secret</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create secret generic argocd-vault-plugin-credentials </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--from-literal</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">VAULT_ADDR</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">vault.cloudnative.love </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--from-literal</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">AVP_TYPE</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">vault </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--from-literal</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">AVP_AUTH_TYPE</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">approle </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--from-literal</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">AVP_ROLE_ID</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">6f944878-1e02-c842-9251-5d8caa1af3f8 </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--from-literal</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">AVP_SECRET_ID</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">8e4732c5-5210-37a6-8d9b-2338d96b8018 </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">--type</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">Opaque </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--dry-run</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">client  </span><span class="token parameter variable" style="color:#36acaa">-oyaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>生产如下内容</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">AVP_AUTH_TYPE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> YXBwcm9sZQ==</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">AVP_ROLE_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> NmY5NDQ4NzgtMWUwMi1jODQyLTkyNTEtNWQ4Y2FhMWFmM2Y4</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">AVP_SECRET_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> OGU0NzMyYzUtNTIxMC0zN2E2LThkOWItMjMzOGQ5NmI4MDE4</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">AVP_TYPE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> dmF1bHQ=</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">VAULT_ADDR</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> dmF1bHQuY2xvdWRuYXRpdmUubG92ZQ==</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">creationTimestamp</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token null important">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> argocd</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">vault</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">plugin</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">credentials</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Opaque</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>为了使用 <a href="https://www.vaultproject.io/docs/auth/kubernetes#configuring-kubernetes" target="_blank" rel="noopener noreferrer">Kubernetes 身份验证</a>，需要做一些事情。</p><p>您可以使用自己的服务帐户或默认的 Argo CD 服务帐户。要使用默认的 Argo CD 服务帐户，您只需automountServiceAccountToken在argocd-repo-server.</p><p>helm安装repo-server默认SA为 <code>${RELASENAME}-argo-cd-argocd-repo-server</code></p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> apps/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> argocd</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">repo</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">server</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">template</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic"># serviceAccount: your-service-account # 如果你需要自定义SA，在此指定</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">automountServiceAccountToken</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这会将服务帐户令牌放入默认路径/var/run/secrets/kubernetes.io/serviceaccount/token.</p></div></div></div>
<p>通过 argocd-cm ConfigMap安装<a href="https://github.com/argoproj/argo-cd/issues/2173" target="_blank" rel="noopener noreferrer">已被移除</a>（旧选项，从ArgoCD版本 2.6.0 弃用）,通过sidecar容器安装（新选项，ArgoCD版本 2.4.0 支持），因此我们将选择基于 sidecar 的选项。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="测试插件">测试插件<a href="https://cloudnative.love/blog/2022/07/23/%E7%AE%A1%E7%90%86%20GitOps%20%E4%B8%AD%E7%9A%84%20Secret%EF%BC%9AArgocd-Vault-Plugin/README#%E6%B5%8B%E8%AF%95%E6%8F%92%E4%BB%B6" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>注意：仅 Vault KV-V2 后端支持版本控制。使用 KV-V1 Vault 指定的版本将被忽略，并将检索最新版本。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># enable kv-v2 engine in Vault</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">vault secrets </span><span class="token builtin class-name">enable</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-path</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">avp kv-v2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># create kv-v2 secret with two keys</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">vault kv put avp/argo-vault-plugin-example-secret </span><span class="token assign-left variable" style="color:#36acaa">user</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"secret_user"</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">password</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"secret_password"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># create policy to enable reading above secret</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># https://www.vaultproject.io/docs/concepts/policies</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">vault policy </span><span class="token function" style="color:#d73a49">write</span><span class="token plain"> avp-policy - </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token string" style="color:#e3116c">EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">path "avp/data/argo-vault-plugin-example-secret" {</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">  capabilities = ["read"]</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>现在我们可以继续使用argocd-vault-plugin来部署ArgoCD应用程序。</p>
<p>参考此例子创建argocd appliction</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: argoproj.io/v1alpha1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: Application</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: example-secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  destination:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    name: ""</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    namespace: default</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    server: "https://kubernetes.default.svc"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  source:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    path: .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    repoURL: "git@github.com:SJFCS/arogcd-vault-plugin-demo.git"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    targetRevision: HEAD</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    plugin:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      name: argocd-vault-plugin</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  project: default</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  syncPolicy:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    automated: null</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>查看并同步</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">argocd app list</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">argocd app get </span><span class="token parameter variable" style="color:#36acaa">--refresh</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>最终检查生成的资源文件</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl  </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> default get secret example-secret </span><span class="token parameter variable" style="color:#36acaa">-ojson</span><span class="token plain">  </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">jq </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'.data | map_values(@base64d)'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>该插件的一个优点是，如果Vault中的值发生变化，我们可以毫不费力地更新集群中的值。因此，更新vault中的值：</p>
<p>更新值</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">vault kv put avp/argo-vault-plugin-example-secret user="secret_user2" password="secret_password2"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>这里需要hard-refresh，否则redis中的缓存的  <code>mfst|argocd.argoproj.io/instance|vault-secret|*</code> key会导致无法更新</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">argocd app get vault-secret --hard-refresh</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl  </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> default get secret example-secret </span><span class="token parameter variable" style="color:#36acaa">-ojson</span><span class="token plain">  </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">jq </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'.data | map_values(@base64d)'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">argocd app </span><span class="token function" style="color:#d73a49">diff</span><span class="token plain"> 命令传递 --hard-refresh 标志。</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Promethuse Recording Rules 优化实践]]></title>
        <id>https://cloudnative.love/blog/2022/04/11/Promethuse Recording Rules 优化实践/README</id>
        <link href="https://cloudnative.love/blog/2022/04/11/Promethuse Recording Rules 优化实践/README"/>
        <updated>2022-04-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<!-- https://deploy.live/blog/today-i-learned-prometheus-recording-rules/]]></summary>
        <content type="html"><![CDATA[<p>随着时间的推移，Prometheus 中存储的指标数量越来越多，查询的频率也越来越高。随着越来越多的仪表板被添加到 Grafana，我开始遇到 Grafana 无法按时呈现图形和 Prometheus 查询超时的情况，尤其在长时间聚合大量指标时这种现象更为严重。</p>
<p>本文用到了 Prometheus Recording Rule 实现对高维度指标查询的 PromQL 语句的性能优化，提高查询效率。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="规则的语法检查">规则的语法检查<a href="https://cloudnative.love/blog/2022/04/11/Promethuse%20Recording%20Rules%20%E4%BC%98%E5%8C%96%E5%AE%9E%E8%B7%B5/README#%E8%A7%84%E5%88%99%E7%9A%84%E8%AF%AD%E6%B3%95%E6%A3%80%E6%9F%A5" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>要在不启动 Prometheus 服务器的情况下快速检查规则文件的语法是否正确，请安装并运行 promtool 。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">go get github.com/prometheus/prometheus/cmd/promtool</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">promtool check rules /path/to/example.rules.yml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 如果文件语法正确，检查器将解析的规则作为文本打印到标准输出，并以返回码 0 退出。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 如果存在任何语法错误或输入参数无效，则将错误消息打印到标准错误并以返回码 1 退出。</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="recording-rules">Recording rules<a href="https://cloudnative.love/blog/2022/04/11/Promethuse%20Recording%20Rules%20%E4%BC%98%E5%8C%96%E5%AE%9E%E8%B7%B5/README#recording-rules" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>Recording rules 允许您预先计算经常需要或计算量大的表达式，并将结果保存为新的时间序列。对预先计算的结果进行查询通常比每次需要时都执行原始表达式要快得多。这对于每次刷新时需要重复查询相同表达式的仪表板特别有用。</p>
<p>一个简单的示例规则文件可能如下所示：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">alerting_rules.yml</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">groups</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> example</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">rules</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">record</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> job</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">http_inprogress_requests</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">sum</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">expr</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sum(http_inprogress_requests) by (job)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>例如我们把下面 Grafana 中的规则改为 Recording rules</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">sum (rate (container_network_receive_bytes_total</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">))by (node)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">sum (rate (container_network_transmit_bytes_total</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">)) by (node)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">sum (rate (wmi_container_network_receive_bytes_total</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">))by (node)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">sum (rate (wmi_container_network_transmit_bytes_total</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">))by (node)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>编写对应的 prometheus rule 配置文件</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> monitoring.coreos.com/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> PrometheusRule</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">generation</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> exporter</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">kubernetes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">chart</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> exporter</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">kubernetes</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">0.0.1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">heritage</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Tiller</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">io.cattle.field/appId</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> cluster</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">monitoring</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">release</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> cluster</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">monitoring</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">source</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> rancher</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">monitoring</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> custom</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">namespace</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> cattle</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">prometheus</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">groups</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> network_IO</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">rules</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">record</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> custom_container_network_receive_bytes_total</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">expr</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sum (rate (container_network_receive_bytes_total</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">))by (node)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">record</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> custom_container_network_transmit_bytes_total</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">expr</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sum (rate (container_network_transmit_bytes_total</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">)) by (node)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">record</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> custom_wmi_container_network_receive_bytes_total</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">expr</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sum (rate (wmi_container_network_receive_bytes_total</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">))by (node)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">record</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> custom_wmi_container_network_transmit_bytes_total</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">expr</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sum (rate (wmi_container_network_transmit_bytes_total</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">))by (node)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="案例问题">案例问题<a href="https://cloudnative.love/blog/2022/04/11/Promethuse%20Recording%20Rules%20%E4%BC%98%E5%8C%96%E5%AE%9E%E8%B7%B5/README#%E6%A1%88%E4%BE%8B%E9%97%AE%E9%A2%98" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>比如我们想要了解 Kubernetes 节点之间 CPU 和内存的实际利用率，我们可以通过使用 <code>container_cpu_usage_seconds_total</code> 和 <code>container_memory_usage_bytes</code> 这两个指标来查询 CPU 和内存的利用率。因为每个运行中的容器都会收集这两个指标进行，但是需要知道，对于稍微大点的线上环境，可能我们同时运行着成千上万的容器，比如现在我们以每5分钟的频率去查询下一周内数千个容器的数据的时候，Prometheus 就比较难以快速进行数据查询了。</p>
<p>比如我们用 <code>container_cpu_usage_seconds_total</code> 总数除以 <code>kube_node_status_allocatable_cpu_cores</code> 总数得出 CPU 利用率：</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">rate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">container_cpu_usage_seconds_total</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">avg_over_time</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">sum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">kube_node_status_allocatable_cpu_cores</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Load time</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 15723ms</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>使用 <code>avg_over_time</code> 将 <code>container_memory_usage_bytes</code> 总数除以 <code>kube_node_status_allocatable_memory_bytes</code> 总数来计算内存利用率：</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">avg_over_time</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">sum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">container_memory_usage_bytes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">15m</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">15m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">avg_over_time</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">sum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">kube_node_status_allocatable_memory_bytes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Load time</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 18656ms</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="优化方案">优化方案<a href="https://cloudnative.love/blog/2022/04/11/Promethuse%20Recording%20Rules%20%E4%BC%98%E5%8C%96%E5%AE%9E%E8%B7%B5/README#%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p><a href="https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/" target="_blank" rel="noopener noreferrer">Prometheus Recording Rules</a> 允许您基于其他时间序列创建自定义的元时间序列。如果您是 Prometheus Operator 用户——您可能已经在 Prometheus 中运行了大量此类规则。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">groups</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> k8s.rules</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">rules</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">expr</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">        sum(rate(container_cpu_usage_seconds_total{job="kubelet", image!="", container_name!=""}[5m])) by (namespace)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">record</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> namespace</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">container_cpu_usage_seconds_total</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">sum_rate</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">expr</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">        sum(container_memory_usage_bytes{job="kubelet", image!="", container_name!=""}) by (namespace)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">record</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> namespace</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">container_memory_usage_bytes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">sum</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>上面的两个规则完全符合我在查询中所做的，但它们会连续执行并将结果存储在非常小的时间序列中。<code>sum(rate(container_cpu_usage_seconds_total{job="kubelet", image!="", container_name!=""}[5m])) by (namespace)</code> 将以预定义的时间间隔进行评估，并存储为新的度量标准 <code>namespace:container_cpu_usage_seconds_total:sum_rate</code> ，与内存查询相同。</p>
<p>现在我可以将我的查询更改为如下所示：将 <code>container_cpu_usage_seconds_total</code> 总数除以 <code>kube_node_status_allocatable_cpu_cores</code> 总数计算得出 CPU 利用率：</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">namespace</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">container_cpu_usage_seconds_total</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">sum_rate</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">avg_over_time</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">sum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">kube_node_status_allocatable_cpu_cores</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Load time</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 1077ms</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>现在运行速度提高了14倍！</p>
<p>将查询更改为如下 <code>container_memory_usage_bytes</code> 总数除以 <code>kube_node_status_allocatable_memory_bytes</code> 总数来计算内存利用率：</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">namespace</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">container_memory_usage_bytes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">sum</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">avg_over_time</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">sum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">kube_node_status_allocatable_memory_bytes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">5m</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Load time</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 677ms</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>现在运行速度提高了27倍！</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="参考文档">参考文档<a href="https://cloudnative.love/blog/2022/04/11/Promethuse%20Recording%20Rules%20%E4%BC%98%E5%8C%96%E5%AE%9E%E8%B7%B5/README#%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p><a href="https://deploy.live/blog/today-i-learned-prometheus-recording-rules/" target="_blank" rel="noopener noreferrer">Today I Learned: Prometheus Recording Rules</a></p>]]></content>
        <category label="Kubernetes" term="Kubernetes"/>
        <category label="Promethuse" term="Promethuse"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[使用 Kind 部署 KubeSphere 实验环境]]></title>
        <id>https://cloudnative.love/blog/2021/11/20/使用 Kind 部署 KubeSphere 实验环境/README</id>
        <link href="https://cloudnative.love/blog/2021/11/20/使用 Kind 部署 KubeSphere 实验环境/README"/>
        <updated>2021-11-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[现在安装 Kubernetes 集群已经变得越来越简单了，Kubernetes in Docker（KinD）这个工具就可以通过创建容器来作为 Kubernetes 的节点，我们只需要在机器上安装 Docker 就可以使用，它允许我们在很短的时间内就启动一个多节点的集群，而不依赖任何其他工具或云服务商。]]></summary>
        <content type="html"><![CDATA[<p>现在安装 Kubernetes 集群已经变得越来越简单了，Kubernetes in Docker（KinD）这个工具就可以通过创建容器来作为 Kubernetes 的节点，我们只需要在机器上安装 Docker 就可以使用，它允许我们在很短的时间内就启动一个多节点的集群，而不依赖任何其他工具或云服务商。</p>
<p>本文将介绍 <a href="https://kind.sigs.k8s.io/" target="_blank" rel="noopener noreferrer">Kind</a> 中 extra-port-mappings，kubernetes-version，image-registry，api-server-acl 等基本配置。
并带有一个 <a href="https://kubesphere.io/" target="_blank" rel="noopener noreferrer">kubesphere</a> 部署示例，还演示了在不删除 Kind 集群的情况下的暂停和重启，以及 Kind 开启 IPVS 导致相关错误的排查记录。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="rtfm">RTFM<a href="https://cloudnative.love/blog/2021/11/20/%E4%BD%BF%E7%94%A8%20Kind%20%E9%83%A8%E7%BD%B2%20KubeSphere%20%E5%AE%9E%E9%AA%8C%E7%8E%AF%E5%A2%83/README#rtfm" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>在开始之前我们需要读一下相关文档。</p>
<ul>
<li>指定具体的集群版本可以查看 <a href="https://kind.sigs.k8s.io/docs/user/configuration/#kubernetes-version" target="_blank" rel="noopener noreferrer">kubernetes-version</a> 。</li>
<li>默认情况下你无法访问 Kind 集群的 nodeport 你需要通过 <a href="https://kind.sigs.k8s.io/docs/user/configuration/#extra-port-mappings" target="_blank" rel="noopener noreferrer">nodeport with port mappings</a> 添加外部端口映射到宿主机。</li>
<li>出于安全原因默认情况下 Kind 部署的 api-server 仅允许 127.0.0.1 访问，你可以参考 <a href="https://kind.sigs.k8s.io/docs/user/configuration/#api-server" target="_blank" rel="noopener noreferrer">api-server</a> 进行更改，如改为宿主机 IP 实现外部访问 。<!-- -->
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">否则你将收到报错</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">The connection to the server </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">YourIP</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">:6443 was refused - did you specify the right </span><span class="token function" style="color:#d73a49">host</span><span class="token plain"> or port?</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>手动指定仓库地址 <a href="https://kind.sigs.k8s.io/docs/user/local-registry/" target="_blank" rel="noopener noreferrer">image-registry</a> 。</li>
<li>参考 <a href="https://kind.sigs.k8s.io/docs/user/configuration/#kubeadm-config-patches" target="_blank" rel="noopener noreferrer">kubeadm-config-patches</a> 可以对 kubeadm 进行额外的参数调整</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="新建-kind-集群">新建 Kind 集群<a href="https://cloudnative.love/blog/2021/11/20/%E4%BD%BF%E7%94%A8%20Kind%20%E9%83%A8%E7%BD%B2%20KubeSphere%20%E5%AE%9E%E9%AA%8C%E7%8E%AF%E5%A2%83/README#%E6%96%B0%E5%BB%BA-kind-%E9%9B%86%E7%BE%A4" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p><strong>Kind 配置文件参考 <a href="https://cloudnative.love/assets/files/kubesphere-1e430dcd8ce841e25cea79216d35f2ad.yaml" target="_blank">kubesphere.yaml</a></strong></p>
<!-- -->
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">kubesphere.yaml</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Cluster</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> kind.x</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">k8s.io/v1alpha4</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">networking</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">apiServerAddress</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"127.0.0.1"</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># 默认 "127.0.0.1" ，如果你需要在外部访问则需要修改为 "Node IP"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">apiServerPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">6443</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">kubeProxyMode</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"iptables"</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># 默认 "iptables", Kind 中开启 IPVS 可能会导致错误 https://github.com/kubernetes-sigs/kind/issues/2326</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">podSubnet</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"10.244.0.0/16"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">serviceSubnet</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"10.96.0.0/12"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">disableDefaultCNI</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">false</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># 默认 "false" ，如果你需要自己部署 CNI 则设为 "true"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">containerdConfigPatches</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># 根据需要指定镜像仓库</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># 下面列举了一些镜像加速地址。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># - Docker 中国区官方镜像加速：https://registry.docker-cn.com</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># - 网易镜像加速：http://hub-mirror.c.163.com</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># - 中国科技大学镜像加速：https://docker.mirrors.ustc.edu.cn</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># - 腾讯云镜像加速：https://mirror.ccs.tencentyun.com</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    endpoint = </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"https://mirror.ccs.tencentyun.com"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">nodes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">role</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> control</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">plane</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">extraPortMappings</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic"># 只在一台节点配置 nodePort 端口映射既可，</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic"># 因为当指定 nodePort 后 k8s 集群每台节点都会暴露 nodePort ，访问任意一个既可路由到 ClusterIP Service。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">containerPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30880</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># containerPort（kind 节点想要映射到主机的 nodePort 端口）默认 30000-32767</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">hostPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30880</span><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic"># hostPort（宿主机端口）默认 0-65535 （注意不可重复）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">protocol</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> tcp </span><span class="token comment" style="color:#999988;font-style:italic"># 默认 "tcp"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">listenAddress</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"0.0.0.0"</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># 默认 "0.0.0.0"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">containerPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30080</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">hostPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">protocol</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> tcp</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">listenAddress</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"0.0.0.0"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> kindest/node</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">v1.21.14@sha256</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">9d9eb5fb26b4fbc0c6d95fa8c790414f9750dd583f5d7cee45d92e8c26670aa1  </span><span class="token comment" style="color:#999988;font-style:italic"># images 发布地址 https://github.com/kubernetes-sigs/kind/releases</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">role</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> worker</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> kindest/node</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">v1.21.14@sha256</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">9d9eb5fb26b4fbc0c6d95fa8c790414f9750dd583f5d7cee45d92e8c26670aa1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>创建集群</strong></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kind create cluster </span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token plain"> kubesphere </span><span class="token parameter variable" style="color:#36acaa">--config</span><span class="token plain"> kubesphere.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>删除集群</strong></p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kind delete  cluster --name kubesphere</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="测试用例">测试用例<a href="https://cloudnative.love/blog/2021/11/20/%E4%BD%BF%E7%94%A8%20Kind%20%E9%83%A8%E7%BD%B2%20KubeSphere%20%E5%AE%9E%E9%AA%8C%E7%8E%AF%E5%A2%83/README#%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>这里我们对 NodePort 进行一个简单地测试，看看是否能正常访问。</p>
<p>创建测试 pod</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl run nginx-demo  </span><span class="token parameter variable" style="color:#36acaa">--image</span><span class="token plain"> nginx </span><span class="token parameter variable" style="color:#36acaa">--port</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>创建 NodePort 类型的 Service ，并指定 <code>nodePort: 30080</code></p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">kubectl expose pod nginx-demo --type NodePort --port 80 --target-port 80  --protocol TCP --dry-run=client -oyaml</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">cat &lt;&lt;EOF </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> kubectl apply </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">f </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Service</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">creationTimestamp</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token null important">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> nginx</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">demo</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> nginx</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">demo</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">protocol</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TCP</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">targetPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">nodePort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30080</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">selector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> nginx</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">demo</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> NodePort</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">loadBalancer</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>在创建集群时候我们将 30080 映射到了本地的 80 端口，所以在本地使用 <code>curl -I http://localhost:80/</code> 来验证结果</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ </span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-I</span><span class="token plain"> http://localhost:80/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">HTTP/1.1 </span><span class="token number" style="color:#36acaa">200</span><span class="token plain"> OK</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Server: nginx/1.23.3</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Date: Wed, 04 Jan </span><span class="token number" style="color:#36acaa">2023</span><span class="token plain"> 03:49:50 GMT</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Content-Type: text/html</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Content-Length: </span><span class="token number" style="color:#36acaa">615</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Last-Modified: Tue, </span><span class="token number" style="color:#36acaa">13</span><span class="token plain"> Dec </span><span class="token number" style="color:#36acaa">2022</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15</span><span class="token plain">:53:53 GMT</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Connection: keep-alive</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ETag: </span><span class="token string" style="color:#e3116c">"6398a011-267"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Accept-Ranges: bytes</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="部署-kubesphere">部署 KubeSphere<a href="https://cloudnative.love/blog/2021/11/20/%E4%BD%BF%E7%94%A8%20Kind%20%E9%83%A8%E7%BD%B2%20KubeSphere%20%E5%AE%9E%E9%AA%8C%E7%8E%AF%E5%A2%83/README#%E9%83%A8%E7%BD%B2-kubesphere" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p><a href="https://kubesphere.io/" target="_blank" rel="noopener noreferrer">KubeSphere</a> 安装十分简单。</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>注意事项:</div><div class="admonitionContent_BuS1"><ul>
<li>Kubernetes 版本要求 v1.19.x、v1.20.x、v1.21.x、* v1.22.x、* v1.23.x 和 * v1.24.x。带星号的版本可能出现边缘节点部分功能不可用的情况。</li>
<li>Kubernetes 集群需存在默认的 StorageClass</li>
<li><a href="https://kubesphere.io/zh/docs/v3.3/quick-start/minimal-kubesphere-on-k8s/" target="_blank" rel="noopener noreferrer">参考安装文档</a></li>
</ul></div></div>
<p>我们本次实用的是 Kubernetes v1.21.14，而且 Kind 已经创建了一个默认的 StorageClass 来配置本地存储。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ kubectl get sc</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME                 PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">standard </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">default</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">   rancher.io/local-path   Delete          WaitForFirstConsumer   </span><span class="token boolean" style="color:#36acaa">false</span><span class="token plain">                  96m</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>我们符合准备工作的要求，下面让我们来安装 KubeSphere 吧</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># 部署 KubeSphere</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> https://github.com/kubesphere/ks-installer/releases/download/v3.3.1/kubesphere-installer.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> https://github.com/kubesphere/ks-installer/releases/download/v3.3.1/cluster-configuration.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 查看安装日志</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl logs </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> kubesphere-system </span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">kubectl get pod </span><span class="token variable parameter variable" style="color:#36acaa">-n</span><span class="token variable" style="color:#36acaa"> kubesphere-system </span><span class="token variable parameter variable" style="color:#36acaa">-l</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">'app in (ks-install, ks-installer)'</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">-o</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable assign-left variable" style="color:#36acaa">jsonpath</span><span class="token variable operator" style="color:#393A34">=</span><span class="token variable string" style="color:#e3116c">'{.items[0].metadata.name}'</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 查看 Service 名字</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get svc/ks-console </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> kubesphere-system</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>你可以参考<a href="https://kubesphere.io/zh/docs/v3.3/pluggable-components/overview/" target="_blank" rel="noopener noreferrer">启用热插拔组件</a>继续安装其他组件，这里不再赘述。</p>
<p>我们部署 Kind 时已将 NodePort 30880 映射到了宿主机 30880 端口，现在打开浏览器访问 <code>http://localhost:30880/</code> 既可。默认帐户 <code>admin</code> 默认密码 <code>P@88w0rd</code> 。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="kind-集群状态查看">Kind 集群状态查看<a href="https://cloudnative.love/blog/2021/11/20/%E4%BD%BF%E7%94%A8%20Kind%20%E9%83%A8%E7%BD%B2%20KubeSphere%20%E5%AE%9E%E9%AA%8C%E7%8E%AF%E5%A2%83/README#kind-%E9%9B%86%E7%BE%A4%E7%8A%B6%E6%80%81%E6%9F%A5%E7%9C%8B" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>我们可以使用 <a href="https://docs.docker.com/config/formatting/" target="_blank" rel="noopener noreferrer">--format</a> 来对结果进行格式化输出，使用 <a href="https://docs.docker.com/engine/reference/commandline/ps/#filtering" target="_blank" rel="noopener noreferrer">--filter</a> 进行对结果进行过滤。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token assign-left variable" style="color:#36acaa">KIND_CLUSTER</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">kubesphere</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 列出 Kind cluster 容器列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ps</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-a</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">--format</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"table {{.ID}}</span><span class="token string entity" style="color:#36acaa">\t</span><span class="token string" style="color:#e3116c">{{.Image}}</span><span class="token string entity" style="color:#36acaa">\t</span><span class="token string" style="color:#e3116c">{{.Names}}</span><span class="token string entity" style="color:#36acaa">\t</span><span class="token string" style="color:#e3116c">{{.Status}}</span><span class="token string entity" style="color:#36acaa">\t</span><span class="token string" style="color:#e3116c">{{.Networks}}"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">--filter</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"label=io.x-k8s.kind.cluster=</span><span class="token string variable" style="color:#36acaa">${KIND_CLUSTER}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 列出 Kind cluster 资源状态</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> stats   </span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable function" style="color:#d73a49">docker</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable function" style="color:#d73a49">ps</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">-q</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">--filter</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">"label=io.x-k8s.kind.cluster=kubesphere"</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 列出 Kind cluster 容器 IP</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> inspect </span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable function" style="color:#d73a49">docker</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable function" style="color:#d73a49">ps</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">-q</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">--filter</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">"label=io.x-k8s.kind.cluster=</span><span class="token variable string variable" style="color:#36acaa">${KIND_CLUSTER}</span><span class="token variable string" style="color:#e3116c">"</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">--format</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'{{ printf "%-50s" .Name}} {{range .NetworkSettings.Networks}}{{.IPAddress}} {{end}}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>注意本文 Kind 创建的集群名字为 <code>kubesphere</code> 请视情况更改变量 <code>${KIND_CLUSTER}</code> 。
可以通过 <code>kind get clusters</code> 和 <code>kubectl config get-clusters</code> 获取你正在使用的集群名字</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ kind get clusters</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubesphere</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">❯ kubectl config get-clusters</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind-kubesphere</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="kind-集群暂停与开启">Kind 集群暂停与开启<a href="https://cloudnative.love/blog/2021/11/20/%E4%BD%BF%E7%94%A8%20Kind%20%E9%83%A8%E7%BD%B2%20KubeSphere%20%E5%AE%9E%E9%AA%8C%E7%8E%AF%E5%A2%83/README#kind-%E9%9B%86%E7%BE%A4%E6%9A%82%E5%81%9C%E4%B8%8E%E5%BC%80%E5%90%AF" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>创建集群后，是否可以在不删除集群的情况下停止并重新启动它？参考这个 <a href="https://github.com/kubernetes-sigs/kind/issues/831" target="_blank" rel="noopener noreferrer">Issue</a></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token assign-left variable" style="color:#36acaa">KIND_CLUSTER</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">kubesphere</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 暂停容器 此时容器 STATUS 变为 (Paused)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> pause </span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable function" style="color:#d73a49">docker</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable function" style="color:#d73a49">ps</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">-q</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">--filter</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">"label=io.x-k8s.kind.cluster=kubesphere"</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 取消暂停容器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> unpause </span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable function" style="color:#d73a49">docker</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable function" style="color:#d73a49">ps</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">-q</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">--filter</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">"label=io.x-k8s.kind.cluster=kubesphere"</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"> </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="troubleshooting">Troubleshooting<a href="https://cloudnative.love/blog/2021/11/20/%E4%BD%BF%E7%94%A8%20Kind%20%E9%83%A8%E7%BD%B2%20KubeSphere%20%E5%AE%9E%E9%AA%8C%E7%8E%AF%E5%A2%83/README#troubleshooting" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="ipvs-和-dns-解析错误排查">IPVS 和 DNS 解析错误排查<a href="https://cloudnative.love/blog/2021/11/20/%E4%BD%BF%E7%94%A8%20Kind%20%E9%83%A8%E7%BD%B2%20KubeSphere%20%E5%AE%9E%E9%AA%8C%E7%8E%AF%E5%A2%83/README#ipvs-%E5%92%8C-dns-%E8%A7%A3%E6%9E%90%E9%94%99%E8%AF%AF%E6%8E%92%E6%9F%A5" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>参考 <a href="https://github.com/kubernetes-sigs/kind/issues/2326" target="_blank" rel="noopener noreferrer">issues/2326</a></p>
<p>在 Kind 中开启 <code>networking.kubeProxyMode: "ipvs"</code> 时，</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">Kind 部分配置截取</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">networking</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">kubeProxyMode</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"ipvs"</span><span class="token plain"> </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>部分 k8s 版本会出现无法初始化 node 错误，node 节点会一直卡在 <code>Starting kube-proxy</code>。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ kubectl describe </span><span class="token function" style="color:#d73a49">node</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Events:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Type    Reason                   Age                From             Message</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ----    ------                   ----               ----             -------</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Normal  NodeHasSufficientMemory  15m </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x8 over 15m</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  kubelet          Node kubesphere-worker status is now: NodeHasSufficientMemory</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Normal  NodeHasNoDiskPressure    15m </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x8 over 15m</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  kubelet          Node kubesphere-worker status is now: NodeHasNoDiskPressure</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Normal  RegisteredNode           15m                node-controller  Node kubesphere-worker event: Registered Node kubesphere-worker </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> Controller</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Normal  Starting                 14m                kube-proxy       Starting kube-proxy.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Normal  Starting                 33s                kubelet          Starting kubelet.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Normal  NodeAllocatableEnforced  33s                kubelet          Updated Node Allocatable limit across pods</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Normal  NodeHasSufficientMemory  27s </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x7 over 33s</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  kubelet          Node kubesphere-worker status is now: NodeHasSufficientMemory</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Normal  NodeHasNoDiskPressure    27s </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x7 over 33s</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  kubelet          Node kubesphere-worker status is now: NodeHasNoDiskPressure</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Normal  NodeHasSufficientPID     27s </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x7 over 33s</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  kubelet          Node kubesphere-worker status is now: NodeHasSufficientPID</span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">  Normal  Starting                 22s                kube-proxy       Starting kube-proxy.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>这时候我们登录到 node 节点，正常情况下可以看见 IPVS 相关模块</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ lsmod </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ip</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> vs</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ip_vs_sh               </span><span class="token number" style="color:#36acaa">16384</span><span class="token plain">  </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ip_vs_wrr              </span><span class="token number" style="color:#36acaa">16384</span><span class="token plain">  </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ip_vs_rr               </span><span class="token number" style="color:#36acaa">16384</span><span class="token plain">  </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ip_vs                 </span><span class="token number" style="color:#36acaa">172032</span><span class="token plain">  </span><span class="token number" style="color:#36acaa">6</span><span class="token plain"> ip_vs_rr,ip_vs_sh,ip_vs_wrr</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">nf_nat                 </span><span class="token number" style="color:#36acaa">45056</span><span class="token plain">  </span><span class="token number" style="color:#36acaa">6</span><span class="token plain"> ip6t_MASQUERADE,ipt_MASQUERADE,xt_nat,openvswitch,nft_chain_nat,xt_REDIRECT</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">nf_conntrack          </span><span class="token number" style="color:#36acaa">172032</span><span class="token plain">  </span><span class="token number" style="color:#36acaa">11</span><span class="token plain"> xt_conntrack,nf_nat,ip6t_MASQUERADE,nfnetlink_cttimeout,ipt_MASQUERADE,xt_nat,openvswitch,nf_conntrack_netlink,nf_conncount,ip_vs,xt_REDIRECT</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">nf_defrag_ipv6         </span><span class="token number" style="color:#36acaa">20480</span><span class="token plain">  </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"> nf_conntrack,openvswitch,ip_vs</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">libcrc32c              </span><span class="token number" style="color:#36acaa">16384</span><span class="token plain">  </span><span class="token number" style="color:#36acaa">6</span><span class="token plain"> nf_conntrack,nf_nat,openvswitch,nf_tables,xfs,ip_vs</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>若没有则需手动在所有节点上安装 IPVS</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> update </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"> ipvsadm</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">❯ ipvsadm-save</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>并且可能伴随着无法解析 DNS 。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ kubectl run </span><span class="token parameter variable" style="color:#36acaa">-i</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> busybox </span><span class="token parameter variable" style="color:#36acaa">--image</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">busybox </span><span class="token parameter variable" style="color:#36acaa">--restart</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">Never </span><span class="token parameter variable" style="color:#36acaa">--rm</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">If you don</span><span class="token string" style="color:#e3116c">'t see a command prompt, try pressing enter.</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">/ # ping wwww.baidu.com</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">ping: bad address '</span><span class="token plain">wwww.baidu.com'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>你还需要在 node 节点设置 <code>sysctl net.ipv4.conf.all.route_localnet = 1</code> 来解决 DNS 解析错误。</p>
<p>然后重启 Kind 容器。</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="cni-错误排查">CNI 错误排查<a href="https://cloudnative.love/blog/2021/11/20/%E4%BD%BF%E7%94%A8%20Kind%20%E9%83%A8%E7%BD%B2%20KubeSphere%20%E5%AE%9E%E9%AA%8C%E7%8E%AF%E5%A2%83/README#cni-%E9%94%99%E8%AF%AF%E6%8E%92%E6%9F%A5" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>当你在 Kind 中开启 <code>networking.disableDefaultCNI: true</code> 时意味着你需要手安装 CNI 插件</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">Kind 部分配置截取</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">networking</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">disableDefaultCNI</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>在安装 CNI 插件之前 Node 状态为 NotReady 。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ kubectl get </span><span class="token function" style="color:#d73a49">node</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME                       STATUS     ROLES                  AGE    VERSION</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubesphere-control-plane   NotReady   control-plane,master   140m   v1.21.14</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubesphere-worker          NotReady   </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">none</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain">                 139m   v1.21.14</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">❯ kubectl describe </span><span class="token function" style="color:#d73a49">node</span><span class="token plain"> kubesphere-worker</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Conditions:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Type             Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ----             ------  -----------------                 ------------------                ------                       -------</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  MemoryPressure   False   Wed, 04 Jan </span><span class="token number" style="color:#36acaa">2023</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15</span><span class="token plain">:47:54 +0800   Wed, 04 Jan </span><span class="token number" style="color:#36acaa">2023</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">13</span><span class="token plain">:33:06 +0800   KubeletHasSufficientMemory   kubelet has sufficient memory available</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  DiskPressure     False   Wed, 04 Jan </span><span class="token number" style="color:#36acaa">2023</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15</span><span class="token plain">:47:54 +0800   Wed, 04 Jan </span><span class="token number" style="color:#36acaa">2023</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">13</span><span class="token plain">:33:06 +0800   KubeletHasNoDiskPressure     kubelet has no disk pressure</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  PIDPressure      False   Wed, 04 Jan </span><span class="token number" style="color:#36acaa">2023</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15</span><span class="token plain">:47:54 +0800   Wed, 04 Jan </span><span class="token number" style="color:#36acaa">2023</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">13</span><span class="token plain">:33:06 +0800   KubeletHasSufficientPID      kubelet has sufficient PID available</span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#393A34"><span class="token plain">  Ready            False   Wed, 04 Jan </span><span class="token number" style="color:#36acaa">2023</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15</span><span class="token plain">:47:54 +0800   Wed, 04 Jan </span><span class="token number" style="color:#36acaa">2023</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">13</span><span class="token plain">:33:06 +0800   KubeletNotReady              container runtime network not ready: </span><span class="token assign-left variable" style="color:#36acaa">NetworkReady</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content>
        <category label="Kind" term="Kind"/>
        <category label="KubeSphere" term="KubeSphere"/>
        <category label="Docker" term="Docker"/>
        <category label="Kubernetes" term="Kubernetes"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[自动化域名管理：External-DNS 实践指南]]></title>
        <id>https://cloudnative.love/blog/2021/07/22/自动化域名管理：External-DNS 实践指南/README</id>
        <link href="https://cloudnative.love/blog/2021/07/22/自动化域名管理：External-DNS 实践指南/README"/>
        <updated>2021-07-22T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[External-DNS 简化了 DNS 记录的管理，它通过监视 Kubernetes 资源，并利用外部 DNS 提供商来配置相应的 DNS 记录。]]></summary>
        <content type="html"><![CDATA[<p>External-DNS 简化了 DNS 记录的管理，它通过监视 Kubernetes 资源，并利用外部 DNS 提供商来配置相应的 DNS 记录。</p>
<p>本文介绍如何部署 External-DNS ，并通过示例验证其功能特性。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="什么是-external-dns">什么是 External-DNS<a href="https://cloudnative.love/blog/2021/07/22/%E8%87%AA%E5%8A%A8%E5%8C%96%E5%9F%9F%E5%90%8D%E7%AE%A1%E7%90%86%EF%BC%9AExternal-DNS%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#%E4%BB%80%E4%B9%88%E6%98%AF-external-dns" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>External-DNS 通过给 ingress、service <a href="https://github.com/kubernetes-sigs/external-dns/tree/master/charts/external-dns#support-matrix" target="_blank" rel="noopener noreferrer">等资源</a> 添加注解的方式，自动给外部 DNS 提供商添加 DNS 记录。</p>
<p><img decoding="async" loading="lazy" alt="1708607515393" src="https://cloudnative.love/assets/images/1708607515393-044667421ebd9095de5d6dcb04aa43fc.png" width="2048" height="1400" class="img_ev3q"></p>
<p>ExternalDNS会很好的解决了下面的问题：</p>
<ul>
<li>创建了很多的 ingress，但是这些 ingress 的解析需要你手动在你 dns 提供商中同步</li>
<li>创建了很多的 svc，有时候这些 svc 的 ip 是动态的，你需要有一个东西去做同步</li>
<li>修改了 ingress controller 的 ip，你需要修改大量的dns 解析</li>
</ul>
<p>external-dns可以根据txt记录判断是否为自己创建的dns记录。如果是自己创建的，当资源在 Kubernetes 中被移出时则会在dns提供商里删除这个记录。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="安装">安装<a href="https://cloudnative.love/blog/2021/07/22/%E8%87%AA%E5%8A%A8%E5%8C%96%E5%9F%9F%E5%90%8D%E7%AE%A1%E7%90%86%EF%BC%9AExternal-DNS%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#%E5%AE%89%E8%A3%85" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>我们要准备 cloudflare 的密钥，不推荐使用全局的 API_KEY，推荐使用 API_TOKEN，打开页面 <a href="https://dash.cloudflare.com/profile/api-tokens" target="_blank" rel="noopener noreferrer">User API Tokens</a>，创建权限为 <code>Zone:Read</code>， <code>DNS：Edit</code> 的 token，并记录下来。</p>
<p>打开 cloudflare domain 域名页面，在右侧下拉找到 zone-id 将其记录下来。</p>
<p>下面我们创建 secret，填入前面记录的值。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create secret generic cloudflare-api-token-for-external-dns-secret </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> external-dns </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--from-literal</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">cf-api-token</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"&lt;your-cd-api-token&gt;"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--from-literal</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">zone-id</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"&lt;your-zone-id&gt;"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--from-literal</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">domain</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"&lt;your-domain&gt;"</span><span class="token plain"> --dry-run</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">client </span><span class="token parameter variable" style="color:#36acaa">-oyaml</span><span class="token plain"> </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>部署 helm 前先创建自定义 valuse 文件</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">extraArgs:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - --domain-filter</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">DOMAIN</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - --zone-id-filter</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">ZONE_ID</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># (optional) limit to a specific zone. It’s in the Overview tab for that domain. Right hand column in the API section. Scroll down a bit.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - --cloudflare-proxied </span><span class="token comment" style="color:#999988;font-style:italic"># (optional) enable the proxy feature of Cloudflare (DDOS protection, CDN...)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - --cloudflare-dns-records-per-page</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">5000</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># (optional) configure how many DNS records to fetch per request 增大单词请求数据量减少请求次数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># - --namespace=$(POD_NAMESPACE)   #只会处理该命名空间中的Ingress/Service资源。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># - --source=service #默认已有无需重复添加</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># - --source=ingress #默认已有无需重复添加</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># - --provider=cloudflare #此参数需要 通过 provider 来定义。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">policy: </span><span class="token function" style="color:#d73a49">sync</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">#默认upsert-only不允许删除记录</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">provider:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: cloudflare</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">env:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - name: CF_API_TOKEN</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    valueFrom:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      secretKeyRef:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        name: cloudflare-api-token-for-external-dns-secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        key: cf-api-token</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - name: DOMAIN</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    valueFrom:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      secretKeyRef:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        name: cloudflare-api-token-for-external-dns-secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        key: domain</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - name: ZONE_ID</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    valueFrom:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      secretKeyRef:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        name: cloudflare-api-token-for-external-dns-secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        key: zone-id</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>执行下面命令完成安装</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">helm upgrade </span><span class="token parameter variable" style="color:#36acaa">--install</span><span class="token plain"> external-dns external-dns </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">--repo</span><span class="token plain"> https://kubernetes-sigs.github.io/external-dns/ </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">--namespace</span><span class="token plain"> external-dns </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --create-namespace </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">--version</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.14</span><span class="token plain">.3 </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> values.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="external-dns-结合-certmanager">External-DNS 结合 CertManager<a href="https://cloudnative.love/blog/2021/07/22/%E8%87%AA%E5%8A%A8%E5%8C%96%E5%9F%9F%E5%90%8D%E7%AE%A1%E7%90%86%EF%BC%9AExternal-DNS%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#external-dns-%E7%BB%93%E5%90%88-certmanager" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>External-DNS 结合 CertManager，实现全自动的dns配置和证书签发，下面为演示案例。</p>
<blockquote>
<p>关于 CertManager 的使用可以参考 <a href="http://localhost:3000/blog/2022/03/18/%E5%A6%82%E4%BD%95%E5%9C%A8%20Kubernetes%20%E4%BD%BF%E7%94%A8%20Cert-Manager%20%E7%AE%A1%E7%90%86%E8%AF%81%E4%B9%A6/README" target="_blank" rel="noopener noreferrer">早期的博客</a></p>
</blockquote>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># 创建例子</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create deployment hello-cert-annotation </span><span class="token parameter variable" style="color:#36acaa">--image</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">hashicorp/http-echo -- /http-echo </span><span class="token parameter variable" style="color:#36acaa">-listen</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">:5678 </span><span class="token parameter variable" style="color:#36acaa">-text</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"Hello Cert Annotation"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl expose deployment hello-cert-annotation </span><span class="token parameter variable" style="color:#36acaa">--type</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">ClusterIP </span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">hello-cert-annotation-svc </span><span class="token parameter variable" style="color:#36acaa">--port</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">80</span><span class="token plain"> --target-port</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">5678</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create ingress hello-cert-annotation </span><span class="token parameter variable" style="color:#36acaa">--class</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">nginx </span><span class="token parameter variable" style="color:#36acaa">--rule</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"hello-cert-annotation.cloudnative.love/*=hello-cert-annotation-svc:80,tls=lts-hello-cert-annotation.cloudnative.love"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 添加certmanager注解</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl annotate ingress hello-cert-annotation cert-manager.io/cluster-issuer</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">cluster-issuer-cloudflare-letsencrypt-staging</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 添加External-DNS注解</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl annotate ingress hello-cert-annotation external-dns.alpha.kubernetes.io/hostname</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">kubectl get ingress hello-cert-annotation </span><span class="token variable parameter variable" style="color:#36acaa">-o</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable assign-left variable" style="color:#36acaa">jsonpath</span><span class="token variable operator" style="color:#393A34">=</span><span class="token variable string" style="color:#e3116c">'{.spec.tls[0].hosts[0]}'</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--overwrite</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl annotate ingress hello-cert-annotation external-dns.alpha.kubernetes.io/ttl</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"120"</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">#optional</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl annotate ingress hello-cert-annotation external-dns.alpha.kubernetes.io/cloudflare-proxied</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"false"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>注意私网地址是无法享受 cloudflare-proxied ，所以这里我关闭了。</p>]]></content>
        <category label="Kubernetes" term="Kubernetes"/>
        <category label="External-DNS" term="External-DNS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[自动化证书管理：Cert-Manager 实践指南]]></title>
        <id>https://cloudnative.love/blog/2021/06/18/自动化证书管理：Cert-Manager 实践指南/README</id>
        <link href="https://cloudnative.love/blog/2021/06/18/自动化证书管理：Cert-Manager 实践指南/README"/>
        <updated>2021-06-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Cert-Manager 是 Kubernetes 上的全能证书管理工具，本文将介绍如何使用 Cert-Manager 的 ACME Issuer 进行申请免费证书并为证书自动续期。]]></summary>
        <content type="html"><![CDATA[<p>Cert-Manager 是 Kubernetes 上的全能证书管理工具，本文将介绍如何使用 Cert-Manager 的 ACME Issuer 进行申请免费证书并为证书自动续期。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="传统的证书申请流程">传统的证书申请流程<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#%E4%BC%A0%E7%BB%9F%E7%9A%84%E8%AF%81%E4%B9%A6%E7%94%B3%E8%AF%B7%E6%B5%81%E7%A8%8B" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>在开始前我们先复习一下传统的证书申请流程，通常包括以下几个步骤：</p>
<ol>
<li>当为服务器或网站申请 SSL/TLS 证书时，需要先生成一对密钥（公钥和私钥）。</li>
<li>然后创建一个证书签名请求（Certificate Signing Request, CSR），CSR 中包含了公钥以及证书的主题信息，如组织名称、域名等。CSR是未签名的，它需要被CA签名以证明其有效性。</li>
<li>再将 CSR 提交给证书颁发机构（Certificate Authority, CA），CA 在验证你的身份和域名所有权之后，使用它的私钥来签名你的 CSR，生成一个 SSL/TLS 证书。这个过程涉及到用 CA 的私钥加密你 CSR 中的信息的哈希值，生成的加密哈希就是签名。</li>
<li>关于签名的验证：当用户的浏览器连接到你的安全网站时，它会接收到你的证书，并使用 CA 的公钥来验证签名。如果 CA 的公钥能成功解密签名并且得到的哈希值与证书信息的哈希值相匹则证明连接是安全的。</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="cert-manager-证书生命周期">Cert-Manager 证书生命周期<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#cert-manager-%E8%AF%81%E4%B9%A6%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>Cert-Manager 是一个非常简单的工具，用户只需两步即可获得证书，极大的简化了繁琐的操作。</p>
<ul>
<li>第一步：定义颁发证书的颁发者（Issuer/ClusterIssuer）。<!-- -->
<blockquote>
<p><strong>Issuer</strong> 只能用来签发自身所在 namespace 下的证书</p>
<p><strong>ClusterIssuer</strong> 可以签发任意 namespace 下的证书。</p>
</blockquote>
</li>
<li>第二步：创建 Certificate 对象向该颁发者请求证书。<!-- -->
<blockquote>
<p><strong>Certificate</strong> 用于向 Cert-Manager 传递域名证书的信息、签发证书所需要的配置，以及对 Issuer/ClusterIssuer 的引用。</p>
<p>可以手动创建 Certificate ，也可以通过 ingress 资源的 annotation 来自动创建。</p>
</blockquote>
</li>
</ul>
<p>简而言之，先创建 Issuer 定义证书的颁发者，在创建 Certificate 证书对象，一旦创建了 Certificate 证书对象，它就会创建一个 Certificate Request 证书请求，并告诉 Cert-Manager 使用关联的 Issuer 为请求的域颁发证书。然后，Issuer 将创建 Order 订单和 Challenge 质询以满足请求。Order 将管理此证书的 ACME 订单的生命周期。<a href="https://cert-manager.io/docs/concepts/certificate/#certificate-lifecycle" target="_blank" rel="noopener noreferrer">官方文档</a>解释证书的生命周期非常清楚。</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">                      ┌──────────┐                         ┌─────────────┐</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                      │          │                         │             │</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       ┌──────────────►  Issuer  ├────────────┐        ┌───►  Challenge  │</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       │              │          │            │        │   │             │</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       │              └──────────┘            │        │   └─────────────┘</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       │                                      │        │</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">┌──────┴────────┐                        ┌────▼────┐   │   ┌─────────────┐</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│               │                        │         │   │   │             │</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│  Certificate  │                        │  Order  ◄───┼───►  Challenge  │</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│               │                        │         │   │   │             │</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└──────▲────────┘                        └────┬────┘   │   └─────────────┘</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       │                                      │        │</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       │        ┌───────────────────────┐     │        │   ┌─────────────┐</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       │        │                       │     │        │   │             │</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       └───────►│   CertificateRequest  ◄─────┘        └───►  Challenge  │</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                │                       │                  │             │</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                └───────────────────────┘                  └─────────────┘</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="安装-cert-manager">安装 Cert-Manager<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#%E5%AE%89%E8%A3%85-cert-manager" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>版本列表：<a href="https://cert-manager.io/docs/releases/" target="_blank" rel="noopener noreferrer">https://cert-manager.io/docs/releases/</a></p>
<p>我们使用下面的命令来安装证书管理器，它创建命名空间 cert-manager，安装 CRD 并将名称服务器设置为 8.8.8.8:53,1.1.1.1:53DNS01 验证。</p>
<blockquote>
<p>8.8.8.8这是 Google 的 DNS 服务器，1.1.1.1是 Cloudflare 的 DNS 服务器</p>
</blockquote>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">helm upgrade </span><span class="token parameter variable" style="color:#36acaa">--install</span><span class="token plain"> cert-manager cert-manager </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">--repo</span><span class="token plain"> https://charts.jetstack.io </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">--namespace</span><span class="token plain"> cert-manager </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --create-namespace </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">--version</span><span class="token plain"> v1.14.2 </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">--set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">installCRDs</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">true </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">--set</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'extraArgs={--dns01-recursive-nameservers-only,--dns01-recursive-nameservers=8.8.8.8:53\,1.1.1.1:53}'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>让我们等待所有部署完成。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get deploy </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> name </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> cert-manager </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">xargs</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-n1</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> kubectl rollout status </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> cert-manager</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>安装 cert-manager 后，您需要配置的第一件事是创建 ClusterIssuer 或 Issuer。这些资源表示能够对证书进行签名以响应证书签名请求的证书颁发机构 （CA）。下面让我们来看看如何创建它们吧。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="什么是-acme">什么是 ACME<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#%E4%BB%80%E4%B9%88%E6%98%AF-acme" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p><a href="https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment" target="_blank" rel="noopener noreferrer">ACME</a> (Automated Certificate Management Environment (ACME) Certificate Authority server) 证书自动化申请与管理协议。</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="acme-免费提供商">ACME 免费提供商<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#acme-%E5%85%8D%E8%B4%B9%E6%8F%90%E4%BE%9B%E5%95%86" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<ul>
<li>
<p>Let's Encrypt: 三个月有效期的免费证书。一个星期内只为同一个域名颁发 5 次证书。免费证书有效期只有90天，需在到期前再校验一次实现续期。</p>
</li>
<li>
<p>ZeroSSL: 不限数量的三个月有效期的免费证书，也支持多域名证书与泛域名证书。 还提供了一个额外的 Dashboard 查看与管理所有申请的证书。</p>
</li>
<li>
<p>Buypass：三个月有效期的免费证书。</p>
<table><thead><tr><th>free ACME</th><th>production ACME directory URLs</th></tr></thead><tbody><tr><td>Let’sEncrypt</td><td><a href="https://acme-v02.api.letsencrypt.org/directory" target="_blank" rel="noopener noreferrer">https://acme-v02.api.letsencrypt.org/directory</a></td></tr><tr><td>Buypass</td><td><a href="https://api.buypass.com/acme/directory" target="_blank" rel="noopener noreferrer">https://api.buypass.com/acme/directory</a></td></tr><tr><td>ZeroSSL</td><td><a href="https://acme.zerossl.com/v2/DV90" target="_blank" rel="noopener noreferrer">https://acme.zerossl.com/v2/DV90</a></td></tr></tbody></table>
</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="acme-校验方式">ACME 校验方式<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#acme-%E6%A0%A1%E9%AA%8C%E6%96%B9%E5%BC%8F" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>ACME CA 服务器用来验证客户端是否有权申请特定域名证书的过程被称为质询(challenges) ，用来防止非域名持有者申请并获取证书来冒充网站。</p>
<p>按照 <a href="https://datatracker.ietf.org/doc/html/rfc8555#section-8.3" target="_blank" rel="noopener noreferrer">RFC8555</a> 的规定 ACME 校验域名归属的两种方式分别是 <strong>HTTP-01</strong> 和 <strong>DNS-01</strong>，详情可参见 <a href="https://letsencrypt.org/zh-cn/docs/challenge-types/" target="_blank" rel="noopener noreferrer">验证方式</a>。</p>
<ul>
<li>
<p>HTTP-01 验证要求在你的网站上放置特定的验证文件，证明你对该域名有控制权。</p>
<ul>
<li>HTTP-01 要求 ACME 能够访问到你的服务器的 80 端口，如果不暴露公网或不使用此端口则不能使用此方法。用法详见 <a href="https://cert-manager.io/docs/configuration/acme/http01/#configuring-the-http01-ingress-solver" target="_blank" rel="noopener noreferrer">Configuring the HTTP01 Ingress solver</a></li>
</ul>
</li>
<li>
<p>DNS-01 验证则需要你在域名系统（DNS）中添加特定的记录，也是用来证明域名的拥有权。</p>
<ul>
<li>DNS-01 DNS 提供商众多，Cert-Manager 内置部分 DNS 提供商的支持，详细列表和用法详见 <a href="https://cert-manager.io/docs/configuration/acme/dns01/#supported-dns01-providers" target="_blank" rel="noopener noreferrer">Supported DNS01 providers</a>。</li>
</ul>
</li>
</ul>
<p>若需要使用非 Cert-Manager 内置的 DNS 提供商，可参考以下两种方案：</p>
<ol>
<li>设置 Custom Nameserver<br>
<!-- -->在 DNS 提供商后台设置 custom nameserver，指向例如 cloudflare 此类可管理其它 DNS 提供商域名的 nameserver 地址。这样配置 Issuer 指定 DNS-01 验证时，添加 cloudflare 的信息即可。<br>
<!-- -->修改 Nameserver 也是保证域名迁移期间解析可用的常见做法，如果你做过一定不会陌生。</li>
<li>使用 Webhook
使用 Cert-Manager 的 Webhook 来扩展 Cert-Manager 的 DNS-01 验证所支持的 DNS 提供商，已经有许多第三方实现，包括国内常用的 DNSPod 与阿里 DNS，详细列表和用法请参见 <a href="https://cert-manager.io/docs/configuration/acme/dns01/#webhook" target="_blank" rel="noopener noreferrer">Webhook</a>。</li>
</ol>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>DNS-01 验证是我经常使用的方法。使用此方法有两个主要原因：</p><ul>
<li>无需担心防火墙、负载均衡器、代理等，它们可能会阻止 http 验证。</li>
<li>支持申请通配符证书。</li>
</ul></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="创建-issuer">创建 Issuer<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#%E5%88%9B%E5%BB%BA-issuer" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p><img decoding="async" loading="lazy" alt="1708522565686" src="https://cloudnative.love/assets/images/1708522565686-ca5e60d6ca47a61406ebfa74bb6dc4a3.png" width="1086" height="330" class="img_ev3q"></p>
<p>下面开始使用 Cloudflare 提供的 DNS 解析服务，实现通过 DNS-01 质询方式申请证书。</p>
<p>您需要从 Cloudflare 获取 API token。登录 <a href="https://dash.cloudflare.com/" target="_blank" rel="noopener noreferrer">Cloudflare控制面板</a> ，打开 <a href="https://dash.cloudflare.com/profile/api-tokens" target="_blank" rel="noopener noreferrer">API Tokens</a> 页面，按照 <a href="https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/#api-tokens" target="_blank" rel="noopener noreferrer">cert-manager文档</a> 中的说明，创建一个 API Token ，记录该 API Token 的值填入下方。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">---</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> cloudflare</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">api</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">token</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># namespace: cert-manager</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># 如果创建 ClusterIssuer 则需要将其放在 cert-manager namespace 下面</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Opaque</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">stringData</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">api-token</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> &lt;Cloudflare API token</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">---</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> cert</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">manager.io/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># kind: ClusterIssuer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Issuer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> &lt;Issuer Name</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">acme</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">email</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> &lt;Your Email</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 生产环境</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># server: https://acme-v02.api.letsencrypt.org/directory</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 演练环境使用Staging环境 注意：curl会提示 curl: (60) SSL 不用担心浏览器访问是没问题的。切换到生产环境就会解决。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">server</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> https</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//acme</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">staging</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">v02.api.letsencrypt.org/directory</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">privateKeySecretRef</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> cluster</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">issuer</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">account</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">key</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">solvers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">dns01</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">cloudflare</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">apiTokenSecretRef</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> cloudflare</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">api</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">token</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token key atrule" style="color:#00a4db">key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> api</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">token</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">❯ kubectl apply </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> - </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">EOF   </span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">...</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">...</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">EOF</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME                                 TYPE     DATA   AGE</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">secret/cloudflare-api-token-secret   Opaque   </span><span class="token number" style="color:#36acaa">1</span><span class="token plain">      31s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME                                              READY   AGE</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">clusterissuer.cert-manager.io/cloudflare-issuer   True    31s</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><ul>
<li>
<p>email：请在此处使用真实的电子邮件，因为某些 CA 不允许虚假电子邮件，并且当您的证书即将到期时，他们会与您联系。</p>
</li>
<li>
<p>server：ACME 目录 URL。有关免费 CA ACME 目录 URL 的列表见<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#acme-%E5%85%8D%E8%B4%B9%E6%8F%90%E4%BE%9B%E5%95%86">ACME 免费服务提供商</a>。</p>
</li>
<li>
<p>privateKeySecretRef：
在Cert-manager中，这个由privateKeySecretRef指定的Secret扮演了存储TLS私钥的角色。</p>
<p>这个Secret可以是手动创建的，如果没有提前创建对应的Secret，Cert-manager会自动生成一个新的Secret来存储私钥</p>
<p>私钥有何用途？</p>
<ul>
<li>证书签发：当你请求一个新的证书时，Cert-manager会使用这个私钥来生成一个证书签名请求（Certificate Signing Request, CSR）。CSR会发送给你选择的证书颁发机构（CA），CA会验证CSR的信息，并用它们的根证书对你的公钥进行签名，从而生成你的TLS证书。</li>
<li>TLS加密：在TLS握手过程中，私钥用于加密信息，确保只有对应的公钥持有者才能解密，从而实现安全通信。公钥包含在TLS证书中，而私钥应当保密，不被外界知晓。</li>
<li>如有疑问请复习<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#%E4%BC%A0%E7%BB%9F%E7%9A%84%E8%AF%81%E4%B9%A6%E7%94%B3%E8%AF%B7%E6%B5%81%E7%A8%8B">传统的证书申请流程</a>。</li>
</ul>
</li>
<li>
<p>disableAccountKeyGeneration（可选）：如果您有要重用的现有帐户密钥，请将其设置为 true 。</p>
</li>
<li>
<p>External Account Binding（可选）：外部帐户绑定，大多数商业 CA 倾向于对其 ACME 服务器使用外部帐户绑定。如果您使用的 CA（Sectigo、ZeroSSL、Digicert 等）需要它，请按照官方文档添加它。</p>
</li>
</ul></div></div>
<p>我希望您在阅读上述内容后知道您将使用哪种类型的发行人以及如何定义发行人issuer 。我们将在下一部分开始请求证书。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="申请-certificate">申请 Certificate<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#%E7%94%B3%E8%AF%B7-certificate" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>可以通过手动创建或基于注解自动创建Certificate资源，cert-manager会自动管理签发证书并保存至指定的Secret对象中，并自动管理续期。</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="手动创建">手动创建<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#%E6%89%8B%E5%8A%A8%E5%88%9B%E5%BB%BA" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>申请证书最可靠的方法是手动创建Certificate资源。证书请求失败的原因太多了，我需要在使用证书之前确保证书存在，所以通常会通过手动创建Certificate资源</p>
<p>首选，创建一个Certificate对象，这会触发spec.issuerRef字段指定的Issuer或ClusterIssuer签发TLS证书。证书颁发后，将存储在spec.secretName字段指定的Secret对象中。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> cert</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">manager.io/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Certificate</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> example</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">example</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">com</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">dnsNames</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'example.example.com'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">issuerRef</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ClusterIssuer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> cloudflare</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">acme</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">cluster</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">issuer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">secretName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> lts</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">example</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">example</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">com</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>更多Certificate示例</summary><div><div class="collapsibleContent_i85q"><p>如果您想了解更多关于可以在证书资源上使用哪些选项的信息，请在查看 <a href="https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources" target="_blank" rel="noopener noreferrer">手动签发证书</a> 和 <a href="https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec" target="_blank" rel="noopener noreferrer">v1.CertificateSpec</a>。</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Cert</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Manager.io/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Certificate</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> example</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">com</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">namespace</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> default</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">secretName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> tls</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">example.com </span><span class="token comment" style="color:#999988;font-style:italic"># 证书保存的 secret 名。Istio Gateway/Ingress/Gateway API 都可以通过直接引用这个 secret 来添加 TLS 加密。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># The use of the common name field has been deprecated since 2000 and is</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># discouraged from being used.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">commonName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> example.com</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">privateKey</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">rotationPolicy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Always </span><span class="token comment" style="color:#999988;font-style:italic"># renew 时总是重新创建新的私钥</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">algorithm</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ECDSA </span><span class="token comment" style="color:#999988;font-style:italic"># RSA/ECDSA/Ed25519，其中 RSA 应用最广泛，Ed25519 被认为最安全</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">encoding</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> PKCS1 </span><span class="token comment" style="color:#999988;font-style:italic"># PKCS1/PKCS8 对于 TLS 加密，通常都用 PKCS1 格式</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">size</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">256</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># RSA 默认为 2048，ECDSA 默认为 256，而 Ed25519 不使用此属性！</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">usages</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> server auth</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> client auth</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># At least one of a DNS Name, URI, or IP address is required.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># I can add wildcard domain here because I use an issuer using dns01 method.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">dnsNames</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> example.com</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"*.example.com"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">isCA</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># Issuer references are always required.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">issuerRef</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> letsencrypt</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">prod</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">alidns</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Issuer </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">group</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Cert</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Manager.io</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># secretTemplate is optional. If set, these annotations and labels will be</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># copied to the Secret named tls-example.com. These labels and annotations will</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># be re-reconciled if the Certificate's secretTemplate changes. secretTemplate</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># is also enforced, so relevant label and annotation changes on the Secret by a</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># third party will be overwriten by Cert-Manager to match the secretTemplate.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">secretTemplate</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">annotations</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">my-secret-annotation-1</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"foo"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">my-secret-annotation-2</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"bar"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">my-secret-label</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> foo</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">duration</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 2160h </span><span class="token comment" style="color:#999988;font-style:italic"># 90d</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">renewBefore</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 360h </span><span class="token comment" style="color:#999988;font-style:italic"># 15d</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># https://Cert-Manager.io/docs/reference/api-docs/#Cert-Manager.io/v1.CertificatePrivateKey</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># uris:  # 如果想在证书的 subjectAltNames 中添加 URI，就补充在这里</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">#   - spiffe://cluster.local/ns/sandbox/sa/example</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># ipAddresses:  # 如果想在证书的 subjectAltNames 添加 ip 地址，就补充在这里</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">#   - 192.168.0.5</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">subject</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 证书的补充信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 字段索引：https://Cert-Manager.io/docs/reference/api-docs/#Cert-Manager.io/v1.X509Subject</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">organizations</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> xxx</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></details>
<p>我们可用配置Ingress使用指定的Secret实现TLS。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create deployment hello-cert </span><span class="token parameter variable" style="color:#36acaa">--image</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">hashicorp/http-echo -- /http-echo </span><span class="token parameter variable" style="color:#36acaa">-listen</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">:5678 </span><span class="token parameter variable" style="color:#36acaa">-text</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"Hello Cert"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl expose deployment hello-cert </span><span class="token parameter variable" style="color:#36acaa">--type</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">ClusterIP </span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">hello-cert-svc </span><span class="token parameter variable" style="color:#36acaa">--port</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">80</span><span class="token plain"> --target-port</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">5678</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create ingress hello-cert </span><span class="token parameter variable" style="color:#36acaa">--class</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">nginx </span><span class="token parameter variable" style="color:#36acaa">--rule</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"hello-cert.cloudnative.love/*=hello-cert-svc:80,tls=lts-hello-cert.cloudnative.love"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>此时配置一下 DNS 后浏览器访问即可验证成功，注意如果使用letsencrypt的演练环境curl是无法验证证书的，需要使用生产环境的地址。</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="ingress-注解">Ingress 注解<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#ingress-%E6%B3%A8%E8%A7%A3" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>申请证书最常用的方法是添加 Ingress Annotation ，然后让 Cert-Manager 为您完成剩下的工作。</p>
<p>添加Ingress注解指定Issuer/ClusterIssuer后，Cert-Manager 将创建一个 Certificate 对象，并触发指定的Issuer/ClusterIssuer签发TLS证书，并保存至spec.tls[*].secretName字段指定的Secret对象中。</p>
<ul>
<li>注解指定 issuer</li>
</ul>
<p>如果不想指定要用于证书的私钥类型，则唯一需要的注释是 cert-manager.io/cluster-issuer/cert-manager.io/issuer。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl annotate ingress </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">ingress_name</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> cert-manager.io/cluster-issuer</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">cluster_issuer_name</span><span class="token operator" style="color:#393A34">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ul>
<li>注解添加 自动续期(可选)</li>
</ul>
<p>当 kubernetes.io/tls-acme 设置为 "true" 时，ACME 证书管理器会自动处理证书的获取和续订。证书到期时，ACME 证书管理器将自动执行续订操作，而当此选项被禁用时，证书只会在创建时自动申请，但到期时不会自动续期。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl annotate ingress </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">ingress_name</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> kubernetes.io/tls-acme: </span><span class="token string" style="color:#e3116c">"true"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ul>
<li>注解添加 ECC 证书和强制密钥轮换(可选)
建议使用 ECC 私钥，并强制轮换新证书的密钥。您可以通过向入口对象添加另外 3 个注释来轻松完成。</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl annotate ingress httpbin-route cert-manager.io/private-key-algorithm</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">ECDSA</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl annotate ingress httpbin-route cert-manager.io/private-key-size</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">256</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl annotate ingress httpbin-route cert-manager.io/private-key-rotation-policy</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">Always</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>生成的 yaml 示例如下</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> networking.k8s.io/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Ingress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> example</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">ingress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">annotations</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">cert-manager.io/cluster-issuer</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"&lt;cluster_issuer_name&gt;"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">kubernetes.io/tls-acme</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"true"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">cert-manager.io/private-key-algorithm</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ECDSA</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">cert-manager.io/private-key-rotation-policy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Always</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">cert-manager.io/private-key-size</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"256"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">tls</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">hosts</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> example.example.com</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">secretName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> test</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">example.example.com</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>要了解更多 ingress annotations 信息，请在此处查看<a href="https://cert-manager.io/docs/usage/ingress/#supported-annotations" target="_blank" rel="noopener noreferrer">supported-annotations</a>。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="排错--handbook">排错 &amp; HandBook<a href="https://cloudnative.love/blog/2021/06/18/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86%EF%BC%9ACert-Manager%20%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/README#%E6%8E%92%E9%94%99--handbook" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>如果发现证书长时间未 Ready，可以参考<a href="https://cert-manager.io/v1.9-docs/faq/troubleshooting/" target="_blank" rel="noopener noreferrer">故障排除指南</a> <a href="https://cert-manager.io/v1.9-docs/faq/acme/" target="_blank" rel="noopener noreferrer">颁发 ACME 证书故障排除</a>按证书申请流程进行逐层排查。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># checking your certificate</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get secrets --field-selector </span><span class="token assign-left variable" style="color:#36acaa">type</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">kubernetes.io/tls </span><span class="token parameter variable" style="color:#36acaa">-A</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># get certificate info</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get secret </span><span class="token variable" style="color:#36acaa">${secret_name}</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">jsonpath</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'{.data.tls\.crt}'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> base64 </span><span class="token parameter variable" style="color:#36acaa">-d</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> openssl x509 </span><span class="token parameter variable" style="color:#36acaa">-text</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get secret </span><span class="token variable" style="color:#36acaa">${secret_name}</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">jsonpath</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'{.data.tls\.key}'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> base64 </span><span class="token parameter variable" style="color:#36acaa">-d</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> openssl rsa </span><span class="token parameter variable" style="color:#36acaa">-text</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">openssl s_client </span><span class="token parameter variable" style="color:#36acaa">-connect</span><span class="token plain"> example.example.com:443</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># secert 定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create secret generic cloudflare-api-token-for-external-dns </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> external-dns </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--from-literal</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">cf-api-token</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">aaa </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--from-literal</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">zone-id</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">bbb </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--from-literal</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">domain</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">ccc --dry-run</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">client </span><span class="token parameter variable" style="color:#36acaa">-oyaml</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># secert 查看</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get secret cloudflare-api-token-for-external-dns </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> external-dns </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> json </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> jq </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'.data["api-token"]'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> base64 </span><span class="token parameter variable" style="color:#36acaa">--decode</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get secret cloudflare-api-token-for-external-dns </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> external-dns </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> json </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> jq </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'.data | map_values(@base64d)'</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># troubleshooting</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get Issuers,ClusterIssuers,Certificates,CertificateRequests,Orders,Challenges </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl describe challenges.acme.cert-manager.io</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl describe orders.acme.cert-manager.io</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># tip</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl label namespace cert-manager certmanager.k8s.io/disable-validation</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">true </span><span class="token comment" style="color:#999988;font-style:italic">#标记 cert-manager 命名空间以禁用资源验证</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># curl</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># curl -kL --resolve www.example.com:80:ip http://www.example.com'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># curl -kivL -H 'Host: www.example.com' 'http://ip</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content>
        <category label="Kubernetes" term="Kubernetes"/>
        <category label="Cert-Manager" term="Cert-Manager"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[使用 Helm 与 Kustomize 实践声明式管理]]></title>
        <id>https://cloudnative.love/blog/2021/05/09/使用 Helm 与 Kustomize 实践声明式管理/README</id>
        <link href="https://cloudnative.love/blog/2021/05/09/使用 Helm 与 Kustomize 实践声明式管理/README"/>
        <updated>2021-05-09T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[1673345511901]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="1673345511901" src="https://cloudnative.love/assets/images/1673345511901-4271e446ce734d56ed5c6c300acf96ab.png" width="2401" height="701" class="img_ev3q"></p>
<p>Kubernetes 于 2014 年夏季登陆 GitHub ，2015 年夏季推出 Kubernetes 的第一个 1.0 版本，其发展速度和进步在许多人的脑海中仍然记忆犹新。</p>
<p>像任何应用基础设施一样，workloads 的操作开始在 Kubernetes 上变得越来越重要。所以 Kubernetes 提出了 resources 的概念，通常由基于 YAML 的 manifests 来描述各种各样的 workloads，如 deployment.yaml。</p>
<p>随着需要部署的 manifests 数量和需要维护的 Kubernetes 集群数量的双重增加，我们需要更高效的 manifests 管理方式，以便在 cluster-to-cluster 之间获得更容易的部署，和更灵活的配置。</p>
<p>本文将介绍如何使用 Heml 和 Kustomize 来对 Kubernetes 生态系统内的对象进行声明式配置和包管理。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="什么是-helm-">什么是 Helm ？<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E4%BB%80%E4%B9%88%E6%98%AF-helm-" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>Helm 是 Kubernetes 的应用程序包管理器，您可使用 Helm Charts 描述应用程序的结构，使用 Helm 命令行界面，您可以回滚部署、监控应用程序的状态并跟踪每项部署的历史记录。</p>
<p>Helm 最初由<a href="https://blogs.microsoft.com/blog/2017/04/10/microsoft-acquire-deis-help-companies-innovate-containers/" target="_blank" rel="noopener noreferrer">Deis</a>于 2015 年开发，并在首届 Kubecon 上展出。2019 年 4 月，CNCF 宣布 Helm 的孵化期结束，成为一个完整的项目。</p>
<p>Tiller是 Helm v2 平台的一部分。它来自与 Google 的 Deployment Manager 项目集成的部分，旨在成为一个工作运行器，与Cloud Foundry 的 Bosh没有太大区别。简而言之，Tiller 是 Helm 的集群内部分，它运行 Helm 的命令和图表。由于 Tiller 可以不受限制地访问 Kubernetes 集群成为集群安全的痛点，因此在 Helm V3 中将其删除了。</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="基本概念">基本概念<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<ul>
<li>Chart：Helm 使用的包格式称为 chart。 chart 就是一个描述Kubernetes相关资源的文件集合。</li>
<li>Release：在 Kubernetes 集群上运行的 Chart 的一个实例。在同一个集群上，一个 Chart 可以安装很多次。每次安装都会创建一个新的 release。</li>
<li>Repository：用于发布和存储 Chart 的存储库。</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="helm-charts">Helm Charts<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#helm-charts" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p><a href="https://helm.sh/zh/docs/topics/charts/" target="_blank" rel="noopener noreferrer">Helm Charts 官方文档</a></p>
<ul>
<li>Helm 图表在创建时必须具有遵循<a href="https://semver.org/spec/v2.0.0.html" target="_blank" rel="noopener noreferrer">语义版本控制</a>的版本号。</li>
<li>Helm Charts 可以引用其他 Charts 作为依赖项，这是任何包管理器的核心。</li>
<li>Helm Charts 的更多高级功能如<a href="https://helm.sh/docs/topics/charts_hooks/" target="_blank" rel="noopener noreferrer">Chart Hooks</a>和<a href="https://helm.sh/docs/topics/chart_tests/" target="_blank" rel="noopener noreferrer">Chart Tests</a>，它们允许与 Release 的生命周期进行交互，以及分别针对 Chart 运行命令/测试的能力。</li>
</ul>
<p>运行 <code>helm create eg-Helm</code> 创建一个 Helm Charts</p>
<p>可以看到 Chart 的基本目录结构包括：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">eg-Helm/                                   </span><span class="token comment" style="color:#999988;font-style:italic"># chart 包目录名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── charts                              </span><span class="token comment" style="color:#999988;font-style:italic"># 包含 chart 依赖的其他 chart</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── Chart.yaml                          </span><span class="token comment" style="color:#999988;font-style:italic"># 包含了chart信息的YAML文件，如chart的名字，版本号信息。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── crds                                </span><span class="token comment" style="color:#999988;font-style:italic"># 自定义资源的定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── templates                           </span><span class="token comment" style="color:#999988;font-style:italic"># 模板目录，和 values 结合时，可生成有效的 Kubernetes manifest</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├── deployment.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├── _helpers.tpl                   </span><span class="token comment" style="color:#999988;font-style:italic"># helm视为公共库定义文件，主要用于定义通用的子模版、函数等</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├── hpa.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├── ingress.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├── NOTES.txt                      </span><span class="token comment" style="color:#999988;font-style:italic"># 帮助信息文件，helm install 安装成功后会输出帮助信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├── serviceaccount.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├── service.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   └── tests</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│       └── test-connection.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└── values.yaml                         </span><span class="token comment" style="color:#999988;font-style:italic"># chart 默认的配置值，模版可以引用这里参数。</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="简单示例">简单示例<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E7%AE%80%E5%8D%95%E7%A4%BA%E4%BE%8B" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>下面给出了 deployment、service、ingress 三个配置文件。</p>
<div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">Deployment</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Service</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Ingress</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> apps/v1beta2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> myapp           </span><span class="token comment" style="color:#999988;font-style:italic">#deployment应用名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> myapp          </span><span class="token comment" style="color:#999988;font-style:italic">#deployment应用标签定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">replicas</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain">           </span><span class="token comment" style="color:#999988;font-style:italic">#pod副本数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">selector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">matchLabels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> myapp          </span><span class="token comment" style="color:#999988;font-style:italic">#pod选择器标签</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">template</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> myapp          </span><span class="token comment" style="color:#999988;font-style:italic">#pod标签定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> myapp           </span><span class="token comment" style="color:#999988;font-style:italic">#容器名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> xxxxxx</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">1.7.9    </span><span class="token comment" style="color:#999988;font-style:italic">#镜像地址</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token key atrule" style="color:#00a4db">containerPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token key atrule" style="color:#00a4db">protocol</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TCP</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Service</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> myapp</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">svc </span><span class="token comment" style="color:#999988;font-style:italic">#服务名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">selector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">#pod选择器定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> myapp</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">protocol</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TCP </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">targetPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> extensions/v1beta1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Ingress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> myapp</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">ingress </span><span class="token comment" style="color:#999988;font-style:italic">#ingress应用名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">rules</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> www.xxxxx.com  </span><span class="token comment" style="color:#999988;font-style:italic">#域名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">paths</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">backend</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token key atrule" style="color:#00a4db">serviceName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> myapp</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">svc </span><span class="token comment" style="color:#999988;font-style:italic">#服务名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token key atrule" style="color:#00a4db">servicePort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></div>
<p>提取 k8s 应用部署配置文件中的参数，作为 chart 包参数。</p>
<p><code>{{  }}</code> 两个花括号包裹的内容为模版表达式。</p>
<div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">Deployment</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Service</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Ingress</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">values</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> apps/v1beta2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Release.Name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">#deployment应用名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Release.Name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">#deployment应用标签定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">replicas</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Values.replicas</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">           </span><span class="token comment" style="color:#999988;font-style:italic">#pod副本数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">selector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">matchLabels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Release.Name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">#pod选择器标签</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">template</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Release.Name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">#pod标签定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Release.Name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">           </span><span class="token comment" style="color:#999988;font-style:italic">#容器名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Values.image </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Values.imageTag </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">#镜像地址</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token key atrule" style="color:#00a4db">containerPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token key atrule" style="color:#00a4db">protocol</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TCP</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Service</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Release.Name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">svc </span><span class="token comment" style="color:#999988;font-style:italic">#服务名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">selector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">#pod选择器定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Release.Name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">protocol</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TCP </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">targetPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> extensions/v1beta1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Ingress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Release.Name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">ingress </span><span class="token comment" style="color:#999988;font-style:italic">#ingress应用名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">rules</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Values.host </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">#域名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">paths</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">backend</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token key atrule" style="color:#00a4db">serviceName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Release.Name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">svc </span><span class="token comment" style="color:#999988;font-style:italic">#服务名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token key atrule" style="color:#00a4db">servicePort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">#域名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> www.XXX.com</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">#镜像参数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> XXXXXXXXXXXXXXXXXX</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">imageTag</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 1.7.9</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">#pod 副本数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">replicas</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="helm-模版语法">Helm 模版语法<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#helm-%E6%A8%A1%E7%89%88%E8%AF%AD%E6%B3%95" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="表达式">表达式<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E8%A1%A8%E8%BE%BE%E5%BC%8F" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<ul>
<li>模版表达式： <code>{{ 模版表达式 }}</code></li>
<li><code>{{- 模版表达式 -}}</code> 表示去掉表达式输出结果前面和后面的空格</li>
<li><code>{{- 模版表达式 }}</code>  表示去掉前面空格</li>
<li><code>{{ 模版表达式 -}}</code>  表示去掉后面空格</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="变量">变量<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E5%8F%98%E9%87%8F" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>默认情况点( . ), 代表全局作用域，用于引用全局对象。</p>
<p>helm 全局作用域中有三个重要的全局对象：<strong>Values</strong> 、 <strong>Release</strong> 和 <strong>自定义模版变量</strong></p>
<ul>
<li>
<p>Values 代表的就是 values.yaml 定义的参数，通过.Values可以引用任意参数。</p>
<p>例如：
<code>{{ .Values.images.repository }}</code> 引用了全局作用域下的 Values 中的 image 对象的 repository。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">values.yaml</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">images</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">repository</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> gcr.io</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>
<p>Release 作为 Helm 内置变量为我们提供了如下的属性字段：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Release.Name            </span><span class="token comment" style="color:#999988;font-style:italic"># release 名字，一般通过Chart.yaml定义，或者通过helm命令在安装应用的时候指定。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Release.Time            </span><span class="token comment" style="color:#999988;font-style:italic"># release 安装时间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Release.Namespace       </span><span class="token comment" style="color:#999988;font-style:italic"># 命名空间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Release.Revision        </span><span class="token comment" style="color:#999988;font-style:italic"># release 版本号，是一个递增值，每次更新都会加一</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Release.IsUpgrade       </span><span class="token comment" style="color:#999988;font-style:italic"># true 代表，当前release是一次更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Release.IsInstall       </span><span class="token comment" style="color:#999988;font-style:italic"># true 代表，当前release是一次安装</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>
<p>自定义模版变量</p>
<p>自定义模版变量名以 $ 开头， 赋值运算符为 <code>:=</code></p>
<p>例如：<code>{{- $relname := .Release.Name -}}</code></p>
</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="函数--管道运算符">函数 &amp; 管道运算符<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E5%87%BD%E6%95%B0--%E7%AE%A1%E9%81%93%E8%BF%90%E7%AE%97%E7%AC%A6" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>Go templates 为我们提供了很多好用的函数，详见<a href="https://masterminds.github.io/sprig/strings.html" target="_blank" rel="noopener noreferrer">文档</a></p>
<ol>
<li>
<p>调用函数的语法：<code>{{ functionName arg1 arg2... }}</code></p>
</li>
<li>
<p>管道（pipelines）运算符 <code>|</code>，用于将模版输出的结果传递给下一个函数处理。例子如下：</p>
</li>
</ol>
<ul>
<li>
<p>将.Values.favorite.food 传递给 quote 函数处理，然后在输出结果：
<code>{{ .Values.favorite.food | quote  }}</code></p>
</li>
<li>
<p>先将.Values.favorite.food的值传递给upper函数将字符转换成大写，然后专递给quote加上引号包括起来：
<code>{{ .Values.favorite.food | upper | quote }}</code></p>
</li>
<li>
<p>如果.Values.favorite.food为空，则使用default定义的默认值：
<code>{{ .Values.favorite.food | default "默认值" }}</code></p>
</li>
<li>
<p>将.Values.favorite.food输出5次：
<code>{{ .Values.favorite.food | repeat 5 }}</code></p>
</li>
<li>
<p>对输出结果缩进2个空格：
<code>{{ .Values.favorite.food | nindent 2 }}</code></p>
</li>
</ul>
<ol start="3">
<li>常用的关系运算符 <code>&gt;</code>、 <code>&gt;=</code>、 <code>&lt;</code>、<code>!=</code>、与或非在 helm 模版中都以函数的形式实现。</li>
</ol>
<p>关系运算函数定义：</p>
<ul>
<li>eq  相当于<code>=</code></li>
<li>ne  相当于 <code>!=</code></li>
<li>lt  相当于 <code>&lt;=</code></li>
<li>gt  相当于 <code>&gt;=</code></li>
<li>and  相当于 <code>&amp;&amp;</code></li>
<li>or   相当于 <code>||</code></li>
<li>not  相当于 <code>!</code></li>
</ul>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">例子</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> and </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Values</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">fooString </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">eq </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Values</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">fooString </span><span class="token string" style="color:#e3116c">"foo"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">...</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> end </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 相当于 if (.Values.fooString &amp;&amp; (.Values.fooString == "foo")) </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="流程控制语句">流程控制语句<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6%E8%AF%AD%E5%8F%A5" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<ol>
<li>if/else</li>
</ol>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">语法</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> 条件表达式 </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Do something</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> 条件表达式 </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Do something </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Default </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> end </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">例子:</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConfigMap</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Release.Name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">configmap</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">myvalue</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Hello World"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">drink</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Values.favorite.drink </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> default "tea" </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> quote </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">food</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> .Values.favorite.food </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> upper </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> quote </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">if eq .Values.favorite.drink "coffee"</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">mug</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">end</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ol>
<li>with</li>
</ol>
<p>with主要就是用来修改 . 作用域的，默认 . 代表全局作用域，with语句可以修改.的含义.</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">语法</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> with 引用的对象 </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">这里可以使用 </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">点</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">， 直接引用with指定的对象</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> end </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">例子</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// .Values.favorite 是一个 object 类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> with </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Values</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">favorite </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// .drink 相当于.Values.favorite.drink</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">drink</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">drink </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"tea"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> quote </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">   </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">food</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">food </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> upper </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> quote </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> end </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>如果需要在 with 作用域内引用全局对象，可以使用 <code>$</code> 指向根的上下文，当在一个范围内循环时会很有用。
例如：<code>{{ $.Chart.Name }}</code></p></div></div>
<ol>
<li>range</li>
</ol>
<p>range主要用于循环遍历数组类型。</p>
<p>遍历map类型，用于遍历键值对象，变量key代表对象的属性名，val代表属性值</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">语法1</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">range</span><span class="token plain"> key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">val </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> 键值对象 </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> $key </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> $val </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> quote </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> end</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">语法2</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">range</span><span class="token plain"> 数组 </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> title </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> quote </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// `.` 引用数组元素值。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> end </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">values.yaml</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">#map类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">favorite</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">drink</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> coffee</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">food</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> pizza</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">#数组类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">pizzaToppings</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> mushrooms</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> cheese</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> peppers</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> onions</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">例子</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// map类型遍历例子:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">range</span><span class="token plain"> $key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> $val </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Values</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">favorite </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> $key </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> $val </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> quote </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> end</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 数组类型遍历例子:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">range</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Values</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">pizzaToppings</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> quote </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> end</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="子模版定义">子模版定义<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E5%AD%90%E6%A8%A1%E7%89%88%E5%AE%9A%E4%B9%89" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>_helpers.tpl 方法允许开发者在模板中使用字符串作为模板。将模板字符串作为值传给chart或渲染额外的配置文件时会很有用。</p>
<p>helm create默认为我们创建了_helpers.tpl 公共库定义文件，可以直接在里面定义子模版，也可以新建一个，只要以下划线开头命名即可。</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">子模版语法</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 定义模版</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> define </span><span class="token string" style="color:#e3116c">"模版名字"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> 模版内容 </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> end </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 引用模版:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> include </span><span class="token string" style="color:#e3116c">"模版名字"</span><span class="token plain"> 作用域</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">例子</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 模版定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> define </span><span class="token string" style="color:#e3116c">"mychart.app"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">app_name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Chart</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">app_version</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"{{ .Chart.Version }}+{{ .Release.Time.Seconds }}"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> end </span><span class="token operator" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 引用模版:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConfigMap</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Release</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token operator" style="color:#393A34">-</span><span class="token plain">configmap</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> include </span><span class="token string" style="color:#e3116c">"mychart.app"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> nindent </span><span class="token number" style="color:#36acaa">4</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 引用mychart.app模版内容，并对输出结果缩进4个空格</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  myvalue</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Hello World"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="模板调试">模板调试<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E6%A8%A1%E6%9D%BF%E8%B0%83%E8%AF%95" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<p>以下命令有助于你的调试：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">helm lint                                               </span><span class="token comment" style="color:#999988;font-style:italic"># 验证chart是否遵循最佳实践的首选工具</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">helm </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> --dry-run </span><span class="token parameter variable" style="color:#36acaa">--debug</span><span class="token plain">                          </span><span class="token comment" style="color:#999988;font-style:italic"># 或者 helm template --debug 仅渲染模板。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">helm get manifest RELEASE_NAME </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">flags</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">                  </span><span class="token comment" style="color:#999988;font-style:italic"># 这是查看服务器上安装了哪些模板的好方法。</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="什么是-kustomize">什么是 Kustomize？<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E4%BB%80%E4%B9%88%E6%98%AF-kustomize" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>Kustomize是 Kubernetes 生态系统的配置管理工具。与 Kubernetes 本身一样，Kustomize 是作为 Google 的一个开源项目开发的——因此从 Kubernetes 1.14 开始，Kustomize 作为默认 Kubernetes 命令行工具 kubectl 的一部分直接集成到 k8s 中也就不足为奇了。</p>
<p>正如它的名字，Kustomize 侧重于定制，你可以轻松地对 Kubernetes manifests 文件进行 patch(根据文件中定义的逻辑进行重构/替换)。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">目录结构</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">eg-Kustomize/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── base</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├── kustomization.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├── namespace.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├── networkpolicy.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├── rolebinding.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   └── role.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└── overlays</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ├── team-a</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    │   └── kustomization.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ├── team-b</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    │   └── kustomization.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    └── team-c</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        └── kustomization.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>例如，如果您想为您的开发和生产环境指定不同的补丁，您只需在 YAML 文件中指定这些更改，这些文件位于它们自己的目录中，组织在位于项目树中公共"base"旁边的"overlays"目录中.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="3-种-patch-方法"><a href="https://stackoverflow.com/questions/63604579/what-is-the-difference-between-patches-vs-patchesjson6902-in-kustomize" target="_blank" rel="noopener noreferrer">3 种 patch 方法</a><a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#3-%E7%A7%8D-patch-%E6%96%B9%E6%B3%95" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<ul>
<li>patches/patchesJson6902<!-- -->
<ul>
<li>用于指定 kubernetes 资源的“目标”属性，“路径”属性指定资源中的哪个属性被修改、添加或删除。</li>
<li>patchJson6902是一个较旧的关键字，它只能通过target（无通配符）匹配一个资源，并且只接受 Group-version-kind (GVK)、命名空间和名称。</li>
</ul>
</li>
<li>patchesStrategicMerge<!-- -->
<ul>
<li>需要 kubernetes 资源的重复结构来标识正在修补的基础资源，然后是规范的修改部分以表示更改（或删除）的内容。</li>
</ul>
</li>
</ul>
<p>输入以下命令即可将它们有选择地应用于正在运行的集群：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kustomize build ~/app-project/overlays/development </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> kubectl apply </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> -</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 或者</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply </span><span class="token parameter variable" style="color:#36acaa">-k</span><span class="token plain"> ~/app-project/overlays/development</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 查看渲染结果</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl kustomize </span><span class="token builtin class-name">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="利用-kustomize-插件-chartinflator-渲染-helm-charts">利用 Kustomize 插件 ChartInflator 渲染 Helm Charts<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E5%88%A9%E7%94%A8-kustomize-%E6%8F%92%E4%BB%B6-chartinflator-%E6%B8%B2%E6%9F%93-helm-charts" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>实际使用 helm 时，我们经常的要对上游的 Helm Chart 包做一些定制化的 patch ，这些 patch 通常受限于定制化场景下，不能直接贡献给上游仓库，通过 fork 来维护自己的定制化修改后的 helm chart 包十分麻烦。这个时候我们可以利用 Kustomize 来对现有的 Helm Chart 打 patch。</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="安装-chartinflator-插件">安装 <a href="https://github.com/kubernetes-sigs/kustomize/blob/v3.3.1/plugin/someteam.example.com/v1/chartinflator/ChartInflator" target="_blank" rel="noopener noreferrer">ChartInflator</a> 插件：<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E5%AE%89%E8%A3%85-chartinflator-%E6%8F%92%E4%BB%B6" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">安装ChartInflator</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token assign-left variable" style="color:#36acaa">chartinflator_dir</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"./kustomize/plugin/kustomize.config.k8s.io/v1/chartinflator"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">mkdir</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">${chartinflator_dir}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-L</span><span class="token plain"> https://raw.githubusercontent.com/kubernetes-sigs/kustomize/kustomize/v3.8.2/plugin/someteam.example.com/v1/chartinflator/ChartInflator </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">${chartinflator_dir}</span><span class="token plain">/ChartInflator</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">chmod</span><span class="token plain"> u+x </span><span class="token variable" style="color:#36acaa">${chartinflator_dir}</span><span class="token plain">/ChartInflator</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="创建-chartinflator-资源清单和-helm-的-valuesyaml-值文件">创建 ChartInflator 资源清单和 Helm 的 values.yaml 值文件：<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E5%88%9B%E5%BB%BA-chartinflator-%E8%B5%84%E6%BA%90%E6%B8%85%E5%8D%95%E5%92%8C-helm-%E7%9A%84-valuesyaml-%E5%80%BC%E6%96%87%E4%BB%B6" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">chartinflator.yaml 创建 ChartInflator 资源清单</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">cat</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">EOF</span><span class="token string bash punctuation" style="color:#393A34"> </span><span class="token string bash punctuation operator" style="color:#393A34">&gt;&gt;</span><span class="token string bash punctuation" style="color:#393A34"> chartinflator.yaml</span><span class="token string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">apiVersion: kustomize.config.k8s.io/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">kind: ChartInflator</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">  name: vault-official-helm-chart</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">chartRepo: https://helm.releases.hashicorp.com  </span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">chartName: vault</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">chartRelease: hashicorp</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">chartVersion: 0.7.0</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">releaseName: vault</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">values: values.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">创建 values 值文件</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">helm repo </span><span class="token function" style="color:#d73a49">add</span><span class="token plain"> hashicorp https://helm.releases.hashicorp.com </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">helm show values </span><span class="token parameter variable" style="color:#36acaa">--version</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.23</span><span class="token plain">.0 hashicorp/vault </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> values.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">创建 Kustomize 文件</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># kustomize init 创建 Kustomize 文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># kustomize edit add label env:dev 为所有资源添加一个 label 标签</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">cat</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">EOF</span><span class="token string bash punctuation" style="color:#393A34"> </span><span class="token string bash punctuation operator" style="color:#393A34">&gt;&gt;</span><span class="token string bash punctuation" style="color:#393A34"> kustomization.yaml</span><span class="token string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">apiVersion: kustomize.config.k8s.io/v1beta1</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">kind: Kustomization</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">generators:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">- chartinflator.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">commonLabels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">  env: dev</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Ktv7">资源清单目录结构</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">├── chartinflator.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── kustomization.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── kustomize</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   └── plugin</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│       └── kustomize.config.k8s.io</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│           └── v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│               └── chartinflator</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│                   └── ChartInflator</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└── values.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="渲染-chart-模板">渲染 Chart 模板<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E6%B8%B2%E6%9F%93-chart-%E6%A8%A1%E6%9D%BF" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">KUSTOMIZE_PLUGIN_HOME</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"./kustomize/plugin/"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kustomize build --enable-alpha-plugins </span><span class="token builtin class-name">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>正常渲染完成后我们可以看到所有的资源上都被添加了一个 env: dev 的标签，这是实时完成的，不需要维护任何额外的文件的。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="还有哪些其他-kubernetes-模板工具">还有哪些其他 Kubernetes 模板工具？<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E8%BF%98%E6%9C%89%E5%93%AA%E4%BA%9B%E5%85%B6%E4%BB%96-kubernetes-%E6%A8%A1%E6%9D%BF%E5%B7%A5%E5%85%B7" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<ul>
<li>Jsonnet/Ksonnnet<!-- -->
<ul>
<li><a href="https://jsonnet.org/" target="_blank" rel="noopener noreferrer">Jsonnet</a>是一种模板语言和引擎。Jsonnett 有一个面向对象的模板方法，允许创建复杂的和基于关系的模板。如果您需要制作某些东西的副本，只需创建一个新对象，支持模板就会接管。</li>
<li><a href="https://github.com/ksonnet/ksonnet" target="_blank" rel="noopener noreferrer">Ksonnnet</a>由<a href="https://tanzu.vmware.com/content/blog/welcoming-heptio-open-source-projects-to-vmware" target="_blank" rel="noopener noreferrer">Heptio</a>创建，是专为 Kubernetes 设计的 Jsonnet 的一个分支。最近，Ksonnet 背后的团队不再支持该项目。</li>
</ul>
</li>
<li>Skaffold<!-- -->
<ul>
<li><a href="https://skaffold.dev/" target="_blank" rel="noopener noreferrer">Skaffold</a>是 Google 最新推出的 Kubernetes 管理项目之一。Skaffold 比 Jsonnet、Helm 甚至 Kustomize 更具包容性。由于 Skaffold 具有构建和部署组件，因此它被设计为 Kubernetes 应用程序所需的一个配方。Skaffold 在部署阶段可插入<a href="https://skaffold.dev/docs/pipeline-stages/deployers/helm/" target="_blank" rel="noopener noreferrer">Helm</a>和</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="参考文档">参考文档<a href="https://cloudnative.love/blog/2021/05/09/%E4%BD%BF%E7%94%A8%20Helm%20%E4%B8%8E%20Kustomize%20%E5%AE%9E%E8%B7%B5%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%AE%A1%E7%90%86/README#%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<ul>
<li><a href="https://github.com/kubernetes-sigs/kustomize/blob/master/examples/zh/chart.md" target="_blank" rel="noopener noreferrer">kubernetes-sigs/kustomize/使用 kustomize 对 helm charts 进行修改</a></li>
<li><a href="https://www.qikqiak.com/post/use-kustomize-custom-helm-charts/" target="_blank" rel="noopener noreferrer">使用 Kustomize 定制 Helm Charts</a></li>
</ul>]]></content>
        <category label="Kubernetes" term="Kubernetes"/>
        <category label="Helm" term="Helm"/>
        <category label="Kustomize" term="Kustomize"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Kubernetes 外部服务映射]]></title>
        <id>https://cloudnative.love/blog/2021/03/05/Kubernetes 外部服务映射/README</id>
        <link href="https://cloudnative.love/blog/2021/03/05/Kubernetes 外部服务映射/README"/>
        <updated>2021-03-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<!--]]></summary>
        <content type="html"><![CDATA[<p>集群内的应用有时候需要调用外部的服务，我们知道集群内部服务调用都是通过 Service 互相访问，那么针对外部的服务是否也可以保持统一使用 Service 呢？</p>
<p>答案是肯定的，通过 Service 访问外部服务，除了方式统一以外，还能带来其他好处。如应用配置统一，可以通过 Service 映射保持两边配置统一，实现不同环境的应用通过相同 Service Name 访问不同的外部数据库。</p>
<p>如图 <code>test-1</code> 和 <code>test-2</code> 两个空间为两个不同的业务环境，通过服务映射，不同空间相同的 Service 访问到对应外部不同环境的数据库：</p>
<p><img decoding="async" loading="lazy" alt="1672451742771" src="https://cloudnative.love/assets/images/1672451742771-7cb4e706ef35ae5c096b41dd90431745.png" width="591" height="281" class="img_ev3q"></p>
<p>另外，还可以保证最小化变更，如果外部数据库 IP 之类的变动，只需要修改 Service 对应映射即可，服务本身配置无需变动。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="外部域名映射到-service">外部域名映射到 Service<a href="https://cloudnative.love/blog/2021/03/05/Kubernetes%20%E5%A4%96%E9%83%A8%E6%9C%8D%E5%8A%A1%E6%98%A0%E5%B0%84/README#%E5%A4%96%E9%83%A8%E5%9F%9F%E5%90%8D%E6%98%A0%E5%B0%84%E5%88%B0-service" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>通过 service 的 ExternalName 既可实现</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Service</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mysql</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">externalName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mysql.example.com</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ExternalName</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>创建之后，同一空间 Pod 就可以通过 mysql:3306 访问外部的 MySQL 服务。</p>
<p>需要注意的是，虽然 externalName 也支持填写 IP，但是并不会被 Ingress 和 CoreDNS 解析（KubeDNS 支持）。如果有 IP 相关的需求，则可以使用 Headless Service -&gt; Type ExternalName 。另外一个需要注意的是，因为 CNAME 的缘故，如果外部的服务又经过一层代理转发，如 Nginx，除非配置对应的 server_name ，否则映射无效。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="外部-ip-映射到-service">外部 IP 映射到 Service<a href="https://cloudnative.love/blog/2021/03/05/Kubernetes%20%E5%A4%96%E9%83%A8%E6%9C%8D%E5%8A%A1%E6%98%A0%E5%B0%84/README#%E5%A4%96%E9%83%A8-ip-%E6%98%A0%E5%B0%84%E5%88%B0-service" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>前文提过，虽然 externalName 字段可以配置为 IP 地址，但是 Ingress 和 CoreDNS 并不会解析，如果外部服务为 IP 提供，那么可以使用 Headless Service 实现映射。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Service</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mysql</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">clusterIP</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> None</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ClusterIP</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">---</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Endpoints</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mysql</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">subsets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">addresses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">ip</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 192.168.1.10</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>service 不指定 selector，手动维护创建 endpoint，创建之后就可以通过 mysql:3306 访问 192.168.1.10:3306 服务的目的。Headless Service 不能修改端口相关，如果要修改访问端口，则需要进一步操作。</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="外部-ip--端口-映射到-service">外部 IP + 端口 映射到 Service<a href="https://cloudnative.love/blog/2021/03/05/Kubernetes%20%E5%A4%96%E9%83%A8%E6%9C%8D%E5%8A%A1%E6%98%A0%E5%B0%84/README#%E5%A4%96%E9%83%A8-ip--%E7%AB%AF%E5%8F%A3-%E6%98%A0%E5%B0%84%E5%88%B0-service" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>如果外部的端口不是标准的端口，想通过 Service 访问时候使用标准端口，如外部 MySQL 提供端口为 3307，内部想通过 Service 3306 访问，这个时候则可以通过如下方式实现：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Service</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mysql</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ClusterIP</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3306</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token key atrule" style="color:#00a4db">targetPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3307</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">---</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Endpoints</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mysql</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">subsets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">addresses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">ip</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 192.168.1.10</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3307</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>service 不指定 selector，手动维护创建 endpoint，创建之后就可以通过 mysql:3306 达到访问外部 192.168.1.10:3307 服务的目的。</p>
<ul>
<li>参考 <a href="https://cloud.google.com/blog/products/gcp/kubernetes-best-practices-mapping-external-services" target="_blank" rel="noopener noreferrer">Kubernetes best practices: mapping external services</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="小结">小结<a href="https://cloudnative.love/blog/2021/03/05/Kubernetes%20%E5%A4%96%E9%83%A8%E6%9C%8D%E5%8A%A1%E6%98%A0%E5%B0%84/README#%E5%B0%8F%E7%BB%93" class="hash-link" aria-label="标题的直接链接" title="标题的直接链接">​</a></h2>
<p>我们可以看出以上外部服务映射，externalName 和 Headless Service 方式映射外部服务是没有经过中间层代理的，都是通过 DNS 劫持实现。而有端口变更需求的时候，则要经过内部 kube-proxy 层转发。正常情况下，能尽可能少的引入中间层就少引用，特别是数据库类的应用，因为引入中间层虽然带来了便利，但也意味着可能会带来性能损耗，特别是那些对延迟比较敏感的服务。</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_BuS1"><p>转载自 <a href="https://blog.opskumu.com/kubernetes-ext-service.html" target="_blank" rel="noopener noreferrer">https://blog.opskumu.com/kubernetes-ext-service.html</a></p></div></div>]]></content>
        <category label="Kubernetes" term="Kubernetes"/>
        <category label="Service" term="Service"/>
    </entry>
</feed>