<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Kalyan的小书房</title>
  <icon>https://www.gravatar.com/avatar/26add54e467101c6779c59a0ed4ee504</icon>
  <subtitle>Kalyan is working hard</subtitle>
  <link href="https://kalyan-zitiu.github.io/atom.xml" rel="self"/>
  
  <link href="https://kalyan-zitiu.github.io/"/>
  <updated>2024-08-29T08:38:52.336Z</updated>
  <id>https://kalyan-zitiu.github.io/</id>
  
  <author>
    <name>Kalyan</name>
    <email>3148862192@qq.com</email>
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>ES</title>
    <link href="https://kalyan-zitiu.github.io/2024/08/29/ES/"/>
    <id>https://kalyan-zitiu.github.io/2024/08/29/ES/</id>
    <published>2024-08-29T08:21:07.000Z</published>
    <updated>2024-08-29T08:38:52.336Z</updated>
    
    <content type="html"><![CDATA[<h3 id="中间件ES（Elastic-Search）"><a href="#中间件ES（Elastic-Search）" class="headerlink" title="中间件ES（Elastic Search）"></a>中间件ES（Elastic Search）</h3><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240816142759894.png" alt="image-20240816142759894"></p><p>分词操作个人理解就是在做一个表来记录term和id的关系，可能会再存储一大段信息的时候会出现一定时间的延迟创建。</p><p>优化，先按字典序排序通过二分查找来找到词项。</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240816143228788.png" alt="image-20240816143228788"></p><p>Term dictionary过大所以不可能会放在内存里面，但是放在磁盘里面，搜索过程又会很慢。</p><h4 id="优化"><a href="#优化" class="headerlink" title="优化"></a>优化</h4><p>每一个词项会有相似的地方，那么把这些相似的地方拎出来进行复用，然后就能构建出一个目录树的结构，进行偏移量的辅助指向后续拼接的term。感觉有一点像计算机的存储方式结构。</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240816160254477.png" alt="image-20240816160254477"></p><h5 id="term-index（上面优化出来的目录树结构就是index）"><a href="#term-index（上面优化出来的目录树结构就是index）" class="headerlink" title="term index（上面优化出来的目录树结构就是index）"></a>term index（上面优化出来的目录树结构就是index）</h5><p>通过index能够找到term的大概位置，通过少量的检索找到target.</p><h4 id="Stored-Fields"><a href="#Stored-Fields" class="headerlink" title="Stored Fields"></a>Stored Fields</h4><p>存放完整文档内容，行式存储结构</p><h4 id="Doc-Values"><a href="#Doc-Values" class="headerlink" title="Doc Values"></a>Doc Values</h4><p>空间换时间，把形同的字段归纳在一起，列式存储结构。</p><h4 id="segment"><a href="#segment" class="headerlink" title="segment"></a>segment</h4><p>具备完整搜索功能的最小单元</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240816161638829.png" alt="image-20240816161638829"></p><h4 id="Lucene"><a href="#Lucene" class="headerlink" title="Lucene"></a>Lucene</h4><ul><li>因为segment结构特殊，若是有数据写入，则需要刷新整个segment架构的所有信息。这样读取和写入若是并行的话，性能会大量降低。因此为了规避这个风险，所以不允许新的信息写入segment，所以只能生成新的segment，那么问题就来了，我怎么知道我要取的信息在哪个Segment里面呢。</li><li>为了解决上面的问题，所以需要程序进行并发读取，但是随着数据量过大，并发读取的任务就会变得很重。导致文件句柄耗尽。</li><li>为了解决句柄消耗严重的问题引出了段合并，segment merging，这个功能就是解决了segment过多的问题，是用来把小一点的segment合并成一个大的segment。和前面的不允许新的信息写入是不冲突的。 </li></ul><p>到这里都还没有解释到lucene，综合上面多个segment组成的一个单机文本检索库，这个就是一个有名的开源基础搜索库Lucene</p><h5 id="Lucene高性能"><a href="#Lucene高性能" class="headerlink" title="Lucene高性能"></a>Lucene高性能</h5><p>其实和kafka的原理基本都是一样的，为了用多用户并发读取，所以就回用topic来继续区分，在Lucene中我们叫index name，继续topic里面可能存在的问题，所以会把这个topic区分片，形成partition，我们这里叫作shard。其实每一个shard就是一个独立Lucene库。</p><h5 id="Lucene高扩展"><a href="#Lucene高扩展" class="headerlink" title="Lucene高扩展"></a>Lucene高扩展</h5><ul><li>为了避免多个分片shard过多导致性能过高，存在宕机隐患。我们可以把它们不定的shard放在不同的node里面，来防止性能过高。</li></ul><h5 id="Lucene高可用"><a href="#Lucene高可用" class="headerlink" title="Lucene高可用"></a>Lucene高可用</h5><ul><li>为了避免node换了，到时分片shard不能服务，保证高可用，添加副本，分词主分片和负分片，主分片会同步到副分片，副本分片不仅能够提供读操作也能够保证主分片挂了时候顶上</li></ul><h6 id="node分化"><a href="#node分化" class="headerlink" title="node分化"></a>node分化</h6><ul><li>为了避免某个集群压力过大，若是每个node都需要集群管理，存储数据，和处理请求的功能，这会导致node的压力还是会变大。所以会进行角色分化的一个操作，每一个node负责不一样的功能。</li></ul><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240816164543933.png" alt="image-20240816164543933"></p><h6 id="去中心化"><a href="#去中心化" class="headerlink" title="去中心化"></a>去中心化</h6><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240816164646524.png" alt="image-20240816164646524"></p><h3 id="总图-这就是ES"><a href="#总图-这就是ES" class="headerlink" title="总图 这就是ES"></a>总图 这就是ES</h3><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240816164731547.png" alt="image-20240816164731547"></p><h3 id="写入流程"><a href="#写入流程" class="headerlink" title="写入流程"></a>写入流程</h3><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240816165843222.png" alt="image-20240816165843222"></p><h3 id="搜索流程"><a href="#搜索流程" class="headerlink" title="搜索流程"></a>搜索流程</h3><h4 id="查询阶段"><a href="#查询阶段" class="headerlink" title="查询阶段"></a>查询阶段</h4><p>搜索内容：跳过。</p><p>转发：是通过index name了解信息在哪个分片和哪个node上面，让后Lucene会并发搜索segment来获取倒排索引的文档id和docvalues获取排序信息。</p><p>返回：聚合返回协调节点，然后排序聚合。</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240816170246591.png" alt="image-20240816170246591"></p><h4 id="获取阶段"><a href="#获取阶段" class="headerlink" title="获取阶段"></a>获取阶段</h4><p>找寻分片：通过文档id，在Stored Fields获取完整文档，然后返回给协调节点，然后返回给客户。</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240816170854349.png" alt="image-20240816170854349"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;中间件ES（Elastic-Search）&quot;&gt;&lt;a href=&quot;#中间件ES（Elastic-Search）&quot; class=&quot;headerlink&quot; title=&quot;中间件ES（Elastic Search）&quot;&gt;&lt;/a&gt;中间件ES（Elastic Search）&lt;/</summary>
      
    
    
    
    <category term="ES" scheme="https://kalyan-zitiu.github.io/categories/ES/"/>
    
    
    <category term="ES" scheme="https://kalyan-zitiu.github.io/tags/ES/"/>
    
  </entry>
  
  <entry>
    <title>CM，Sercet,DeployMent</title>
    <link href="https://kalyan-zitiu.github.io/2024/08/29/CM%EF%BC%8CSercet,DeployMent/"/>
    <id>https://kalyan-zitiu.github.io/2024/08/29/CM%EF%BC%8CSercet,DeployMent/</id>
    <published>2024-08-29T07:43:07.000Z</published>
    <updated>2024-08-29T08:09:22.677Z</updated>
    
    <content type="html"><![CDATA[<h3 id="尝试编写deploy使用configmap以及serct进行重要消息存储的卷挂载"><a href="#尝试编写deploy使用configmap以及serct进行重要消息存储的卷挂载" class="headerlink" title="尝试编写deploy使用configmap以及serct进行重要消息存储的卷挂载"></a>尝试编写deploy使用configmap以及serct进行重要消息存储的卷挂载</h3><h4 id="实践策划"><a href="#实践策划" class="headerlink" title="实践策划"></a>实践策划</h4><ol><li><strong>目标设定</strong>：<ul><li>在Kubernetes中使用ConfigMap和Secret存储重要的配置数据和敏感信息。</li><li>将这些数据以卷的形式挂载到Pod中，使其在容器内可用。</li><li>通过实际操作掌握如何管理和使用ConfigMap和Secret，并了解它们的权限控制和安全性。</li><li>验证在容器内的读取和修改操作，以及了解ConfigMap和Secret的更新机制对Pod的影响。</li></ul></li><li><strong>内容规划</strong>：<ul><li>创建ConfigMap和Secret资源。</li><li>使用ConfigMap和Secret挂载卷到Pod中。</li><li>验证挂载成功以及在容器内读取数据。</li><li>测试ConfigMap和Secret的更新机制。</li><li>讨论ConfigMap和Secret的最佳实践与安全管理。</li></ul></li></ol><h5 id="创建命名空间"><a href="#创建命名空间" class="headerlink" title="创建命名空间"></a>创建命名空间</h5><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl create namespace config-secret-practice</span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240813102335321.png" alt="image-20240813102335321"></p><h5 id="创建ConfigMap"><a href="#创建ConfigMap" class="headerlink" title="创建ConfigMap"></a>创建ConfigMap</h5><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span>                <span class="comment"># 指定Kubernetes API版本为v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ConfigMap</span>               <span class="comment"># 定义资源类型为ConfigMap</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">app-config</span>            <span class="comment"># ConfigMap的名称</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">config-secret-practice</span>  <span class="comment"># ConfigMap所在的命名空间</span></span><br><span class="line"><span class="attr">data:</span></span><br><span class="line">  <span class="attr">config.json:</span> <span class="string">|</span>              <span class="comment"># 使用多行文本格式存储名为config.json的配置信息</span></span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">&quot;setting1&quot;:</span> <span class="string">&quot;value1&quot;</span>,   <span class="comment"># JSON格式的配置，包含多个键值对</span></span><br><span class="line">      <span class="attr">&quot;setting2&quot;:</span> <span class="string">&quot;value2&quot;</span>,</span><br><span class="line">      <span class="attr">&quot;setting3&quot;:</span> <span class="string">&quot;value3&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">  <span class="attr">database_url:</span> <span class="string">&quot;mongodb://mongo-svc:27017&quot;</span>  <span class="comment"># 另一个键值对，存储数据库URL</span></span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240813102910539.png" alt="image-20240813102910539"></p><h5 id="创建Secret"><a href="#创建Secret" class="headerlink" title="创建Secret"></a>创建Secret</h5><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span>                <span class="comment"># 指定Kubernetes API版本为v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Secret</span>                  <span class="comment"># 定义资源类型为Secret</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">db-secret</span>             <span class="comment"># Secret的名称</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">config-secret-practice</span>  <span class="comment"># Secret所在的命名空间</span></span><br><span class="line"><span class="attr">type:</span> <span class="string">Opaque</span>                  <span class="comment"># Secret的类型为Opaque，用于存储任意二进制数据或字符串</span></span><br><span class="line"><span class="attr">data:</span></span><br><span class="line">  <span class="attr">db-password:</span> <span class="string">bXlwYXNzd29yZA==</span>  <span class="comment"># Base64编码的敏感信息，这里是数据库密码&#x27;mypassword&#x27;的编码形式</span></span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240813103145177.png" alt="image-20240813103145177"></p><h5 id="创建deploy"><a href="#创建deploy" class="headerlink" title="创建deploy"></a>创建deploy</h5><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">apps/v1</span>           <span class="comment"># 定义API版本为apps/v1，这是Deployment的API组</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Deployment</span>              <span class="comment"># 资源类型为Deployment</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">app-deployment</span>        <span class="comment"># Deployment的名称</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">config-secret-practice</span>  <span class="comment"># Deployment所在的命名空间</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">replicas:</span> <span class="number">2</span>                 <span class="comment"># 定义Pod副本的数量，设为2个</span></span><br><span class="line">  <span class="attr">selector:</span></span><br><span class="line">    <span class="attr">matchLabels:</span>              <span class="comment"># 用于选择标签匹配的Pod</span></span><br><span class="line">      <span class="attr">app:</span> <span class="string">my-app</span>             <span class="comment"># 这里定义标签app=my-app</span></span><br><span class="line">  <span class="attr">template:</span></span><br><span class="line">    <span class="attr">metadata:</span></span><br><span class="line">      <span class="attr">labels:</span></span><br><span class="line">        <span class="attr">app:</span> <span class="string">my-app</span>           <span class="comment"># Pod模板的标签，与selector中的标签匹配</span></span><br><span class="line">    <span class="attr">spec:</span></span><br><span class="line">      <span class="attr">containers:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">my-app-container</span> <span class="comment"># 容器名称</span></span><br><span class="line">        <span class="attr">image:</span> <span class="string">docker.m.daocloud.io/library/busybox</span> <span class="comment"># 容器使用的镜像，这里是busybox适合进行简单的命令执行</span></span><br><span class="line">        <span class="attr">command:</span> [<span class="string">&quot;/bin/sh&quot;</span>, <span class="string">&quot;-c&quot;</span>, <span class="string">&quot;while true; do sleep 3600; done&quot;</span>] <span class="comment"># 让容器保持运行，方便测试</span></span><br><span class="line">        <span class="attr">volumeMounts:</span>          <span class="comment"># 定义容器内的卷挂载</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">config-volume</span>  <span class="comment"># ConfigMap卷挂载的名称</span></span><br><span class="line">          <span class="attr">mountPath:</span> <span class="string">/etc/config</span>  <span class="comment"># 挂载路径，容器内的文件系统路径</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">secret-volume</span>  <span class="comment"># Secret卷挂载的名称</span></span><br><span class="line">          <span class="attr">mountPath:</span> <span class="string">/etc/secret</span>  <span class="comment"># 挂载路径，容器内的文件系统路径</span></span><br><span class="line">        <span class="attr">env:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">DB_PASSWORD</span>    <span class="comment"># 定义一个环境变量</span></span><br><span class="line">          <span class="attr">valueFrom:</span></span><br><span class="line">            <span class="attr">secretKeyRef:</span>      <span class="comment"># 从Secret引用获取值</span></span><br><span class="line">              <span class="attr">name:</span> <span class="string">db-secret</span>  <span class="comment"># Secret名称</span></span><br><span class="line">              <span class="attr">key:</span> <span class="string">db-password</span> <span class="comment"># Secret中的键，指向数据库密码</span></span><br><span class="line">      <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">config-volume</span>    <span class="comment"># 定义一个卷，来源于ConfigMap</span></span><br><span class="line">        <span class="attr">configMap:</span></span><br><span class="line">          <span class="attr">name:</span> <span class="string">app-config</span>     <span class="comment"># 关联的ConfigMap的名称</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">secret-volume</span>    <span class="comment"># 定义一个卷，来源于Secret</span></span><br><span class="line">        <span class="attr">secret:</span></span><br><span class="line">          <span class="attr">secretName:</span> <span class="string">db-secret</span> <span class="comment"># 关联的Secret的名称</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h5 id="验证卷挂载"><a href="#验证卷挂载" class="headerlink" title="验证卷挂载"></a>验证卷挂载</h5><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240813104055190.png" alt="image-20240813104055190"></p><h5 id="查看环境变量"><a href="#查看环境变量" class="headerlink" title="查看环境变量"></a>查看环境变量</h5><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240813104136482.png" alt="image-20240813104136482"></p><h5 id="修改configmap测试是否实时更新"><a href="#修改configmap测试是否实时更新" class="headerlink" title="修改configmap测试是否实时更新"></a>修改configmap测试是否实时更新</h5><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240813104806428.png" alt="image-20240813104806428"></p><h5 id="更新secret"><a href="#更新secret" class="headerlink" title="更新secret:"></a>更新secret:</h5><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">echo</span> -n <span class="string">&#x27;newpassword&#x27;</span> | <span class="built_in">base64</span>   <span class="comment"># 使用echo命令和base64编码工具对新密码进行编码</span></span><br><span class="line">kubectl apply -f db-secret.yaml  <span class="comment"># 重新应用Secret，以测试其在Pod中的更新</span></span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240813105107739.png" alt="image-20240813105107739"></p><p>这里为什么没有被修改到,因为secret作为环境变量时候需要重新启动pod</p><h5 id="启动自动滚动更新"><a href="#启动自动滚动更新" class="headerlink" title="启动自动滚动更新"></a>启动自动滚动更新</h5><p>我们在deploy选项下面添加serect的optinal为true</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240813105622261.png" alt="image-20240813105622261"></p><p>apply后直接</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl rollout status deployment/app-deployment -n config-secret-practice</span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240813105934430.png" alt="image-20240813105934430"></p><h5 id="使用RBAC-限制对ConfigMap和Secret的访问"><a href="#使用RBAC-限制对ConfigMap和Secret的访问" class="headerlink" title="使用RBAC,限制对ConfigMap和Secret的访问"></a>使用RBAC,限制对ConfigMap和Secret的访问</h5><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl create serviceaccount app-user -n config-secret-practice</span><br></pre></td></tr></table></figure><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">rbac.authorization.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Role</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">config-secret-practice</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">config-secret-role</span></span><br><span class="line"><span class="attr">rules:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">apiGroups:</span> [<span class="string">&quot;&quot;</span>]</span><br><span class="line">  <span class="attr">resources:</span> [<span class="string">&quot;configmaps&quot;</span>, <span class="string">&quot;secrets&quot;</span>]</span><br><span class="line">  <span class="attr">resourceNames:</span> [<span class="string">&quot;app-config&quot;</span>, <span class="string">&quot;db-secret&quot;</span>]</span><br><span class="line">  <span class="attr">verbs:</span> [<span class="string">&quot;get&quot;</span>, <span class="string">&quot;list&quot;</span>, <span class="string">&quot;watch&quot;</span>]</span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">rbac.authorization.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">RoleBinding</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">config-secret-rolebinding</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">config-secret-practice</span></span><br><span class="line"><span class="attr">roleRef:</span></span><br><span class="line">  <span class="attr">apiGroup:</span> <span class="string">rbac.authorization.k8s.io</span></span><br><span class="line">  <span class="attr">kind:</span> <span class="string">Role</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">config-secret-role</span></span><br><span class="line"><span class="attr">subjects:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">kind:</span> <span class="string">ServiceAccount</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">app-user</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">config-secret-practice</span></span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl auth can-i get configmap/app-config --as=system:serviceaccount:config-secret-practice:app-user -n config-secret-practice</span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240813110615550.png" alt="image-20240813110615550"></p><h5 id="使用一个带有serviceAccount的pod验证"><a href="#使用一个带有serviceAccount的pod验证" class="headerlink" title="使用一个带有serviceAccount的pod验证"></a>使用一个带有serviceAccount的pod验证</h5><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">test-pod</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">config-secret-practice</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">serviceAccountName:</span> <span class="string">app-user</span>  <span class="comment"># 指定使用的ServiceAccount</span></span><br><span class="line">  <span class="attr">containers:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">test-container</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">docker.m.daocloud.io/library/busybox</span></span><br><span class="line">    <span class="attr">command:</span> [<span class="string">&quot;/bin/sh&quot;</span>, <span class="string">&quot;-c&quot;</span>, <span class="string">&quot;sleep 3600&quot;</span>]  <span class="comment"># 让容器保持运行</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;尝试编写deploy使用configmap以及serct进行重要消息存储的卷挂载&quot;&gt;&lt;a href=&quot;#尝试编写deploy使用configmap以及serct进行重要消息存储的卷挂载&quot; class=&quot;headerlink&quot; title=&quot;尝试编写deploy使用</summary>
      
    
    
    
    <category term="kubernetes" scheme="https://kalyan-zitiu.github.io/categories/kubernetes/"/>
    
    
    <category term="kubernetes" scheme="https://kalyan-zitiu.github.io/tags/kubernetes/"/>
    
  </entry>
  
  <entry>
    <title>hwameistor操盘常见问题</title>
    <link href="https://kalyan-zitiu.github.io/2024/08/29/hwameistor%E6%93%8D%E7%9B%98%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98/"/>
    <id>https://kalyan-zitiu.github.io/2024/08/29/hwameistor%E6%93%8D%E7%9B%98%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98/</id>
    <published>2024-08-29T06:08:42.000Z</published>
    <updated>2024-08-29T06:45:01.898Z</updated>
    
    <content type="html"><![CDATA[<h3 id="无空盘"><a href="#无空盘" class="headerlink" title="无空盘"></a>无空盘</h3><ul><li>添加干净的空磁盘</li></ul><h3 id="手动添盘"><a href="#手动添盘" class="headerlink" title="手动添盘"></a>手动添盘</h3><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240813100739543.png" alt="image-20240813100739543"></p><ol><li><p>编写ldc</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">cat &lt;&lt;\EOF &gt; ldc.yaml</span><br><span class="line">apiVersion: hwameistor.io/v1alpha1</span><br><span class="line">kind: LocalDiskClaim</span><br><span class="line">metadata:</span><br><span class="line">  name: hostname-ld-name</span><br><span class="line">spec:</span><br><span class="line">  nodeName: g-master # 获取节点名字。</span><br><span class="line">  owner: local-storage</span><br><span class="line">  description:</span><br><span class="line">    localDiskNames:</span><br><span class="line">      - localdisk-0cfade4286bfce385512af7244265e0d # kubectl get ld 获取绑定的ld名字</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><p>或</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 获取所有可用磁盘信息</span></span><br><span class="line">AVAILABLE_DISKS=$(kubectl get ld -o wide | grep Available | awk <span class="string">&#x27;&#123;print $1&#125;&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 定义节点名称</span></span><br><span class="line">NODE_NAME=<span class="string">&quot;g-master&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 遍历每一个可用磁盘，生成对应的ldc.yaml文件</span></span><br><span class="line"><span class="keyword">for</span> DISK_NAME <span class="keyword">in</span> <span class="variable">$AVAILABLE_DISKS</span>; <span class="keyword">do</span></span><br><span class="line">  <span class="comment"># 提取磁盘ID</span></span><br><span class="line">  DISK_ID=$(<span class="built_in">echo</span> <span class="variable">$DISK_NAME</span> | <span class="built_in">cut</span> -d<span class="string">&#x27;-&#x27;</span> -f2)</span><br><span class="line"></span><br><span class="line">  <span class="comment"># 替换模板并生成对应的ldc.yaml</span></span><br><span class="line">  <span class="built_in">cat</span> &lt;&lt;<span class="string">EOF &gt; ldc-$DISK_ID.yaml</span></span><br><span class="line"><span class="string">apiVersion: hwameistor.io/v1alpha1</span></span><br><span class="line"><span class="string">kind: LocalDiskClaim</span></span><br><span class="line"><span class="string">metadata:</span></span><br><span class="line"><span class="string">  name: $&#123;NODE_NAME&#125;-ld-$DISK_ID</span></span><br><span class="line"><span class="string">spec:</span></span><br><span class="line"><span class="string">  nodeName: $NODE_NAME</span></span><br><span class="line"><span class="string">  owner: local-storage</span></span><br><span class="line"><span class="string">  description:</span></span><br><span class="line"><span class="string">    localDiskNames:</span></span><br><span class="line"><span class="string">      - $DISK_NAME</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;Generated ldc-<span class="variable">$DISK_ID</span>.yaml for disk: <span class="variable">$DISK_NAME</span>&quot;</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p>应用</p></li></ol><p>应用ldc.yaml<code>kubectl apply -f ldc.yaml</code></p><ol start="3"><li>查询磁盘状态</li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl get ld</span><br></pre></td></tr></table></figure><ol start="4"><li>查询ldc状态</li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl get ldc</span><br></pre></td></tr></table></figure><ol start="5"><li><p>一般能看到有ldc的话都是没有成功的，基本上都是在pending</p></li><li><p>修改对应的localdisk是否处于保留政策</p></li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 获取处于 pending 状态的 LDC 名称</span></span><br><span class="line">PENDING_LDC=$(kubectl get ldc --no-headers | awk <span class="string">&#x27;$3==&quot;Pending&quot; &#123;print $1&#125;&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 遍历每一个处于 pending 状态的 LDC</span></span><br><span class="line"><span class="keyword">for</span> LDC <span class="keyword">in</span> <span class="variable">$PENDING_LDC</span>; <span class="keyword">do</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;Checking LDC: <span class="variable">$LDC</span>&quot;</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># 获取对应的 LD 名称</span></span><br><span class="line">  LD_NAME=$(kubectl get ldc <span class="variable">$LDC</span> -o jsonpath=<span class="string">&#x27;&#123;.spec.description.localDiskNames[0]&#125;&#x27;</span>)</span><br><span class="line"></span><br><span class="line">  <span class="comment"># 检查 LD 的 reserved 字段状态</span></span><br><span class="line">  RESERVED_STATUS=$(kubectl get ld <span class="variable">$LD_NAME</span> -o jsonpath=<span class="string">&#x27;&#123;.spec.reserved&#125;&#x27;</span>)</span><br><span class="line"></span><br><span class="line">  <span class="comment"># 如果 reserved 为 true，则修改为 false</span></span><br><span class="line">  <span class="keyword">if</span> [ <span class="string">&quot;<span class="variable">$RESERVED_STATUS</span>&quot;</span> == <span class="string">&quot;true&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;Modifying reserved status of LD: <span class="variable">$LD_NAME</span> from true to false&quot;</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment"># 修改 reserved 字段为 false</span></span><br><span class="line">    kubectl patch ld <span class="variable">$LD_NAME</span> --<span class="built_in">type</span>=json -p=<span class="string">&#x27;[&#123;&quot;op&quot;: &quot;replace&quot;, &quot;path&quot;: &quot;/spec/reserved&quot;, &quot;value&quot;: false&#125;]&#x27;</span></span><br><span class="line">    </span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;LD <span class="variable">$LD_NAME</span> reserved status set to false.&quot;</span></span><br><span class="line">  <span class="keyword">else</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;LD <span class="variable">$LD_NAME</span> reserved status is already false.&quot;</span></span><br><span class="line">  <span class="keyword">fi</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="在资源紧缺或者无法添盘操作时候，可以进行清盘"><a href="#在资源紧缺或者无法添盘操作时候，可以进行清盘" class="headerlink" title="在资源紧缺或者无法添盘操作时候，可以进行清盘"></a>在资源紧缺或者无法添盘操作时候，可以进行清盘</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查看清理盘的设备信息,看不需要哪个目录</span></span><br><span class="line">mount | grep xxxx</span><br><span class="line"><span class="comment"># 查看清理设备的具体信息UUID，LABEL</span></span><br><span class="line">blkid</span><br><span class="line"><span class="comment"># 编辑fstab，解除挂载</span></span><br><span class="line">vim /etc/fstab</span><br><span class="line"><span class="comment"># 重新挂载，进行解除</span></span><br><span class="line">mount -a</span><br><span class="line"><span class="comment"># 检查挂载情况</span></span><br><span class="line">mount | grep /mnt/data</span><br><span class="line"><span class="comment"># 移除所有对应设备的lv和vg,pv</span></span><br><span class="line">lvremove xxxxx</span><br><span class="line">vgremove xxxx</span><br><span class="line"><span class="comment"># 查看分区，解除分区</span></span><br><span class="line">fdisk xxxx(d,w)</span><br><span class="line">pvremove xxxxx</span><br><span class="line">blkid | grep xxxx</span><br><span class="line"><span class="comment"># 擦除设备签名</span></span><br><span class="line">wipefs -a xxxxx</span><br><span class="line"><span class="comment"># 解除挂载</span></span><br><span class="line">mount -a</span><br><span class="line"><span class="comment"># 检查hwameistor资源</span></span><br><span class="line">kubectl api-resources | grep hwamei</span><br><span class="line"><span class="comment"># 查看hwameistor存储节点状态</span></span><br><span class="line">kubectl get lsn</span><br><span class="line"><span class="comment"># 查看sc</span></span><br><span class="line">kubectl get sc</span><br></pre></td></tr></table></figure><h3 id=""><a href="#" class="headerlink" title=""></a></h3>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;无空盘&quot;&gt;&lt;a href=&quot;#无空盘&quot; class=&quot;headerlink&quot; title=&quot;无空盘&quot;&gt;&lt;/a&gt;无空盘&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;添加干净的空磁盘&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;手动添盘&quot;&gt;&lt;a href=&quot;#手动添盘&quot; class=&quot;hea</summary>
      
    
    
    
    <category term="hwameistor" scheme="https://kalyan-zitiu.github.io/categories/hwameistor/"/>
    
    
    <category term="hwameistor" scheme="https://kalyan-zitiu.github.io/tags/hwameistor/"/>
    
  </entry>
  
  <entry>
    <title>原生Kubernetes部署Prometheus</title>
    <link href="https://kalyan-zitiu.github.io/2024/08/29/%E5%8E%9F%E7%94%9FKubernetes%E9%83%A8%E7%BD%B2Prometheus/"/>
    <id>https://kalyan-zitiu.github.io/2024/08/29/%E5%8E%9F%E7%94%9FKubernetes%E9%83%A8%E7%BD%B2Prometheus/</id>
    <published>2024-08-29T06:05:04.000Z</published>
    <updated>2024-08-29T06:06:03.915Z</updated>
    
    <content type="html"><![CDATA[<h2 id="部署Prometheus"><a href="#部署Prometheus" class="headerlink" title="部署Prometheus"></a>部署Prometheus</h2><h3 id="1-创建一个命名空间"><a href="#1-创建一个命名空间" class="headerlink" title="1. 创建一个命名空间"></a>1. 创建一个命名空间</h3><p>首先，我们可以创建一个专门用于Prometheus的命名空间，以便管理和隔离资源。</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl create namespace monitoring</span><br></pre></td></tr></table></figure><h3 id="2-配置Prometheus的ConfigMap"><a href="#2-配置Prometheus的ConfigMap" class="headerlink" title="2. 配置Prometheus的ConfigMap"></a>2. 配置Prometheus的ConfigMap</h3><p>为了配置Prometheus的抓取目标（scrape targets），我们需要创建一个ConfigMap，用于存储<code>prometheus.yml</code>配置文件。</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ConfigMap</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">prometheus-config</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">monitoring</span></span><br><span class="line"><span class="attr">data:</span></span><br><span class="line">  <span class="attr">prometheus.yml:</span> <span class="string">|</span></span><br><span class="line"><span class="string">    global:</span></span><br><span class="line"><span class="string">      scrape_interval: 15s</span></span><br><span class="line"><span class="string"></span></span><br><span class="line">    <span class="attr">scrape_configs:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">job_name:</span> <span class="string">&#x27;kubernetes-nodes&#x27;</span></span><br><span class="line">        <span class="attr">kubernetes_sd_configs:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">role:</span> <span class="string">node</span></span><br><span class="line">        <span class="attr">scheme:</span> <span class="string">https</span></span><br><span class="line">        <span class="attr">tls_config:</span></span><br><span class="line">          <span class="attr">ca_file:</span> <span class="string">/var/run/secrets/kubernetes.io/serviceaccount/ca.crt</span></span><br><span class="line">          <span class="attr">insecure_skip_verify:</span> <span class="literal">false</span></span><br><span class="line">        <span class="attr">bearer_token_file:</span> <span class="string">/var/run/secrets/kubernetes.io/serviceaccount/token</span></span><br><span class="line">        <span class="attr">relabel_configs:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">action:</span> <span class="string">labelmap</span></span><br><span class="line">            <span class="attr">regex:</span> <span class="string">__meta_kubernetes_node_label_(.+)</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">target_label:</span> <span class="string">__address__</span></span><br><span class="line">            <span class="attr">replacement:</span> <span class="string">kubernetes.default.svc:443</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">source_labels:</span> [<span class="string">__meta_kubernetes_node_name</span>]</span><br><span class="line">            <span class="attr">regex:</span> <span class="string">(.+)</span></span><br><span class="line">            <span class="attr">target_label:</span> <span class="string">__metrics_path__</span></span><br><span class="line">            <span class="attr">replacement:</span> <span class="string">/api/v1/nodes/$&#123;1&#125;/proxy/metrics</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">job_name:</span> <span class="string">&#x27;kubernetes-pods&#x27;</span></span><br><span class="line">        <span class="attr">kubernetes_sd_configs:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">role:</span> <span class="string">pod</span></span><br><span class="line">        <span class="attr">relabel_configs:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">action:</span> <span class="string">labelmap</span></span><br><span class="line">            <span class="attr">regex:</span> <span class="string">__meta_kubernetes_pod_label_(.+)</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">action:</span> <span class="string">replace</span></span><br><span class="line">            <span class="attr">source_labels:</span> [<span class="string">__meta_kubernetes_namespace</span>]</span><br><span class="line">            <span class="attr">target_label:</span> <span class="string">kubernetes_namespace</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">action:</span> <span class="string">replace</span></span><br><span class="line">            <span class="attr">source_labels:</span> [<span class="string">__meta_kubernetes_pod_name</span>]</span><br><span class="line">            <span class="attr">target_label:</span> <span class="string">kubernetes_pod_name</span></span><br></pre></td></tr></table></figure><p>将上述配置保存为<code>prometheus-config.yaml</code>文件，并应用它：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl apply -f prometheus-config.yaml</span><br></pre></td></tr></table></figure><h3 id="3-创建Prometheus-Pod和Service"><a href="#3-创建Prometheus-Pod和Service" class="headerlink" title="3. 创建Prometheus Pod和Service"></a>3. 创建Prometheus Pod和Service</h3><p>接下来，创建一个Pod来运行Prometheus，并通过NodePort暴露它的服务。</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">prometheus-pod</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">monitoring</span></span><br><span class="line">  <span class="attr">labels:</span></span><br><span class="line">    <span class="attr">app:</span> <span class="string">prometheus</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">containers:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">prometheus</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">quay.io/prometheus/prometheus:v2.44.0</span></span><br><span class="line">    <span class="attr">args:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">--config.file=/etc/prometheus/prometheus.yml</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">--storage.tsdb.path=/prometheus/</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">containerPort:</span> <span class="number">9090</span></span><br><span class="line">    <span class="attr">volumeMounts:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">prometheus-config-volume</span></span><br><span class="line">        <span class="attr">mountPath:</span> <span class="string">/etc/prometheus/</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">prometheus-data-volume</span></span><br><span class="line">        <span class="attr">mountPath:</span> <span class="string">/prometheus/</span></span><br><span class="line">  <span class="attr">volumes:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">prometheus-config-volume</span></span><br><span class="line">      <span class="attr">configMap:</span></span><br><span class="line">        <span class="attr">name:</span> <span class="string">prometheus-config</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">prometheus-data-volume</span></span><br><span class="line">      <span class="attr">emptyDir:</span> &#123;&#125;</span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Service</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">prometheus-service</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">monitoring</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">NodePort</span></span><br><span class="line">  <span class="attr">ports:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">port:</span> <span class="number">9090</span></span><br><span class="line">      <span class="attr">targetPort:</span> <span class="number">9090</span></span><br><span class="line">      <span class="attr">nodePort:</span> <span class="number">30000</span></span><br><span class="line">  <span class="attr">selector:</span></span><br><span class="line">    <span class="attr">app:</span> <span class="string">prometheus</span></span><br></pre></td></tr></table></figure><p>将上述配置保存为<code>prometheus-pod-service.yaml</code>文件，并应用它：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl apply -f prometheus-pod-service.yaml</span><br></pre></td></tr></table></figure><h3 id="4-设置适当的权限"><a href="#4-设置适当的权限" class="headerlink" title="4. 设置适当的权限"></a>4. 设置适当的权限</h3><p>确保Prometheus有足够的权限访问Kubernetes API。创建一个ClusterRole和ClusterRoleBinding。</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">rbac.authorization.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ClusterRole</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">prometheus</span></span><br><span class="line"><span class="attr">rules:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">apiGroups:</span> [<span class="string">&quot;&quot;</span>]</span><br><span class="line">  <span class="attr">resources:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">nodes</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">nodes/proxy</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">services</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">endpoints</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">pods</span></span><br><span class="line">  <span class="attr">verbs:</span> [<span class="string">&quot;get&quot;</span>, <span class="string">&quot;list&quot;</span>, <span class="string">&quot;watch&quot;</span>]</span><br><span class="line"><span class="bullet">-</span> <span class="attr">apiGroups:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">extensions</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">apps</span></span><br><span class="line">  <span class="attr">resources:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">deployments</span></span><br><span class="line">  <span class="attr">verbs:</span> [<span class="string">&quot;get&quot;</span>, <span class="string">&quot;list&quot;</span>, <span class="string">&quot;watch&quot;</span>]</span><br><span class="line"></span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">rbac.authorization.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ClusterRoleBinding</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">prometheus</span></span><br><span class="line"><span class="attr">roleRef:</span></span><br><span class="line">  <span class="attr">apiGroup:</span> <span class="string">rbac.authorization.k8s.io</span></span><br><span class="line">  <span class="attr">kind:</span> <span class="string">ClusterRole</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">prometheus</span></span><br><span class="line"><span class="attr">subjects:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">kind:</span> <span class="string">ServiceAccount</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">default</span></span><br><span class="line">  <span class="attr">namespace:</span> <span class="string">monitoring</span></span><br></pre></td></tr></table></figure><p>将上述配置保存为<code>prometheus-rbac.yaml</code>文件，并应用它：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl apply -f prometheus-rbac.yaml</span><br></pre></td></tr></table></figure><h3 id="5-访问Prometheus"><a href="#5-访问Prometheus" class="headerlink" title="5. 访问Prometheus"></a>5. 访问Prometheus</h3><p>你现在可以通过<code>NodePort</code>访问Prometheus的Web界面。假设你的集群中的节点IP为<code>&lt;Node-IP&gt;</code>，你可以通过以下URL访问Prometheus：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">http://&lt;Node-IP&gt;:30000</span><br></pre></td></tr></table></figure><h3 id="6-验证抓取目标"><a href="#6-验证抓取目标" class="headerlink" title="6. 验证抓取目标"></a>6. 验证抓取目标</h3><p>访问Prometheus Web界面后，在“Status” -&gt; “Targets”页面查看Prometheus是否正确发现并抓取了Kubernetes节点和Pod的监控数据。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;部署Prometheus&quot;&gt;&lt;a href=&quot;#部署Prometheus&quot; class=&quot;headerlink&quot; title=&quot;部署Prometheus&quot;&gt;&lt;/a&gt;部署Prometheus&lt;/h2&gt;&lt;h3 id=&quot;1-创建一个命名空间&quot;&gt;&lt;a href=&quot;#1-创</summary>
      
    
    
    
    <category term="Prometheus" scheme="https://kalyan-zitiu.github.io/categories/Prometheus/"/>
    
    
    <category term="Prometheus" scheme="https://kalyan-zitiu.github.io/tags/Prometheus/"/>
    
  </entry>
  
  <entry>
    <title>Gitlab+jenkins+k8s/CICD</title>
    <link href="https://kalyan-zitiu.github.io/2024/08/29/Gitlab+jenkins+k8s_CICD/"/>
    <id>https://kalyan-zitiu.github.io/2024/08/29/Gitlab+jenkins+k8s_CICD/</id>
    <published>2024-08-29T05:12:45.000Z</published>
    <updated>2024-08-29T05:55:41.112Z</updated>
    
    <content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="Oh, this is an invalid password. Check and try again, please." data-whm="OOPS, these decrypted content may changed, but you can still have a look.">  <script id="hbeData" type="hbeData" data-hmacdigest="4e681e13b3f5dc5c09355321572b26269b2eb6f9a9ded5bd699c3c921a8c6fe1">bf490c8d2c5f5e906426eca9095b233208acf251987c9c4ecfaf29ecdb4a8d72abe378b0c736f7387affb29b4fc46c143f1b678509a83526741325166bdd8859e389cbe132b622196aaeeb98765a406f875bd29d3698b55e87c7580ca0c1fee5c784e885d680548676e39371a4bb15bd4836ca5347032d7e85a0b2b937d0f9fe42f0160f22764a406fcc8942ba7bfa86749a49d4f833bc8cf061d48ac278da1e6d55827769f5651d581e75eb1c85af8cd1b5fa37d505685608c0876d4bcf3e482a2ec3b5271d86f8b6e0e99eac45ddacee796b2bdd95188e82dc8d8dc9672bce8c903a5ff072eb90c9b5cdf59c42a62f2146d537ffad507145a18b98092744150cb26e1e04ab543736b8cee49c48a3eda66de8369809848e9462f056c5f1f4c6c38b5ef830b045d7baa232a84036d67447d36b6bd2b113925628be4c99fe04c099b0d68cf9437159d4f6ddb2a988bd4d0756064f17a18ea7e2a07c1bc209315c8df903dbb6cd443df70a37bd4b649ba412e174a2dcd588d163598d9a977f7a745feeb2f029b7e05372297688d0d59d8f6d2170b9896ef9dff4587eff4f2250a4b3d794e1fb423ef84aeb455daa6dd4289cd7a84866bad26bf868903e09fb72a72b6d1d7427a5b60d9cc92f95f271c67a7a049dd2cf977874f729c0ea9c8b0f26e652686d31225d79b7f1a47af5728e41c347df6e20c60471da2994ca68931eec0ea4442fde3e74b7f19070ef68f17204b5e9938bc8364117db508fc74bf31860914d0443e643efac8093e5e25f75fba49f67c6b07f69b775c6a935ef35644cc0edb34a9272c5c1ba9814ebce673694c99c1576b416e0afb49605f4848a12414806ce2c47ae48d9c4991a552fdaa3d1fdda5bbb32e329e38cd664a22fc5ee88f8d0ea1f0efb6110d4775f9db052af66ba895a72298dae46cba4481c1e16ec07172d2ab56df347c0416298951b21054201771f3420d8d3fc72c9d330defd4d5aa12c43da573940ed9d4aba673567248922b57b5b4c1362086624be2a007387be96dc708e93efa408db074bdf0286e2b9f8bfa1c6b22766b5d00d7aed545783d29554c7102636cae0181dcde311ec9c63a2158c081d242465b79b038a7eee5bf2b30eb993f8707c6237e23de088f9d63722813914c39d5ea8b7d31bb50081089f155db5e6ed33ce0c517a382417a37ade1fb0a84f6aeda2d9a81680fc5ac5fa459f5de1d0712ec217f8d4add276689d32e2b49c71f162d3619b46e631df4027efe1fe1d4c171fb8085dca60ef30a4ec80a304cfefe2c870d6e51625fca4e489e38775c7c93ad3f5fbc7deafcfcc7f5dac2b4e8c19c577a1180e513b9d873ba42b8e4e12b8adcecc013ddfe6a5fbaa529cd83e0663cd965e4208ade1636ac4b75fc20735484fb048c72f1885b51a15e18b0ded7dbc651e3b3807011a70aae964f0f4b9d1b136fccf6b2769d6a54e100789a303f5e38a11bff8a34cc7ac9e5ad5b95a3be3ee1e552c460a3257a0da868f13a32f3e4aac538fa31b4614d4e4ea1df8fe02940f8cdf6cc96fe4e799a22e442e13118c78ddeb4ed7d3fe76f2857abd222aee78bc89cf73663ae93d5a55824581aa4f5956a2a6ac604d84ed74414ba2e3648b8ef151af0d362260d85b42157dbfc6a9a7b76f8254f9b8d3aa27b49eebeb97291f666621d9ff99c6f1b8ce1841297a54f47a80b0c3d668fdfe20510cce43ddedc048a1db4b297503cb6257c5763717fc0bf15305400f59f422347cb2796e37d7d6a87cdbf00452696be8096ab6ab891f140da10b3d479fc3745d411a91abe7b1e173b381fd88f834301c1971cf09eaa69fcd14a8c9b95f0478f07dbf1cbab29d358bb187a34b3d2bc420e3b64e2c6e20820104e781f5a98a7c192e74021200da7e9e5e075ec16647071b48837f97b6f15ef5dc2d908870e45e28d84e76fa51af9f297965906d51379fefe597cce60afdb55632634bac7b4c905dca8d792b1fa0714ec829bb25a2a55e68f39bf95674365b50de43b3022d532eb6d02f37ac4a28172222e1fab10801a7778f9e3e6981769fdf0a69c2c87d87bc483f2cd995896c193db268a0f486c87cddae59f1945fc1a858e1419ab40afd6e324a100d7dfb7d56056c7036d45910d58fe8c9c4ea2db5ca9f91e256d257d496771fc96aa728d415dea9ad1179d6236c7003c323fadc3832d29ce7a83a463085afd61443771bbcbaf7af023d3c14be0b8f1d8bbb5566a41bf7f0836e1ebb50aa3abf03befa9d92ffc5b5c426a905d54d3d2f4e9d193dbc8f890a3fcbd0f5f8e517e94e511f583a369b0bd1721e50b7eddf230e9218adb6cfe616756de831bef8cde1dd812efcf0694832959abc51b85276bceab86203a1268b79af716a72a6398068614dc4323c3cc2ee09099883bf21374b56c4dbcd965cdb7831a9dfd30a9d080862618176b214e3281436801fe623fb689cf29a6a0969748bca40dedfd5a4534be3915a88089f784752687b7a3d7fe750bb2f3fbc8cb3734015ddce90bd2c22278f344aac3355c238452344caa9c9858856deb6554b099b2ca475ffa5c9e64598ec9d55145465cc879068df3c68ef95401d09353d09a147c66974a3252db10c94e56d85699800b20ace117d893f0527b82e12da82251eb08c0ee0d977e5ad92a039e586ca00d04b50411fc984cd8070caa3fdd5959aebc53102e1fdd5e3f1b0b0eec954a23d2ffdb88a155153d07917a2d9d0a288061b3ba0361926263b6c74b514e40780b14b4f2e51b1d7e5d54c6abee5be9b28924c475efe80910e25d8a8c85ae7d70b425ec6f612533b74421d7c6a8712932c2693d5a7c670c987f387f7eefab1c567d1e3b75dd63c7825c072891c1b7fa86723156deb712a7e98a02f9ec6779df405d5a5add688a80813acae708252204f60aa36c4516e2ca671e7a346c631af43c3cc26c4592984d9a7635bbadcf73b9c2a7d1bacb9a6e244fc05189792bb4753e719fdba7ef763050f6889094de1429322e83559168c5a92e643778422121fd35d0d86d16b0772bdf732005c7be62488487f0693b53cb0ee205c3fc9113db5fbc06f7e4335124fbb6ba2bc111801dc5d42d6eefe91e217cff38b24d55e00b6d479185421aeb31bed5002586c26c7b7d4cd964464900ecf286fb0251aa1364aedde2d117c582609d1e62b38528419b04b977f6ef890463c0d6244690550951adadf7cd2e3d69b3a435a037d0f6353a2738d65ad213bfc0b2548119c6f6441d5132ce8bdf9dbe286455ae1626c335f60a2d50ee9540df0433a46503a298b0554fcdd07e3cfed26a97af46ccddf7e95a76840b965a0eeb12c7ec299da77e13b3baa00656f621ccc88d126d234bf56239795e1d7c95ed04551e1daf5c65251e5c6ceee0f76d36739a839772fe8f6a9dcd7b3e452412663901291577797dcacaba0e6f14fa8a8e31c2c17a905574ab6261dfc8194cc8570c9b72c19c021571b193668630f5b8ac5ab72679f310527b4ba8b49baa8db5649686104c41bb0f51f946275576dd9ebd9119a9eb26d7ba3c9d00ec9d018434ff209e6ba7c86958389bef968e8fc7ab6497406b35c526d289f90360dfcc57bf9d3317e2f421a8893e156b42245cbdd767506773db693f042fabdf518f827a28e6d449290fc0508e44b3b864fb95b64a7f6fb13525dc0d72badd0e763323f4ab8577eb6c4d878100536e0c004b82e659a66a266715f89a60fec9216f50dfecf5dd9863d2f996865a7b8868a49cc6ddffc2c67e24af19d39d4e5d5abfbf2794106ec5ac1e2205eaedff3babd49b2cb5a837aeaf8673c7ba3553a12dc2a10f8eb1d87758d8a9d75c9f77832a1fdb89f169e0f34a70d197d23d2b160f82333b1afd096a52e1c253c5ab9e49f7ae77fb81bc77c58af5e188936e15658443317fb3b7e97f7e2bc21e4686152af56ecfe302e3b513203ae5f54447b2ca8f3358c33e976fe991b284fa12ff895fd52055ef7d67fee90d0c0a5c21ac0b5a4588bf65897066d34a6b30e6adef5ffe9780f247dbf9c4b8a57b47c8eefa67eb94827132987b1ed9b6b61aa49558fa184ccc44f5dca3faf3824b860a8db44755f82605f785ac38de453928db04722c057c3cda5a9decf94acac7aae8d60bf712533b666a96af6f248e00bd3af1d0bb33e15a1359cd00d9e9444859d097ae969d980823cbc36a7bcb65c1298538b0fc19080c7f06d98ea71c97e24d81de5e896b3f521824442999ee8717e032e1bcd843e9e61b28558f7c23b65394c88247d50ff7f1233e18684b993e446bfe9a5d4d02bb4b8f4400ac4c5f24af956d3061bb93fb4ba9978ee882adc77028a93d0d86108103ebd224b6c556d1345bedec021882519ec5e5dffa407a728a6c35a41758c986c30c0f0c1e1c33e5cc8b0a9254ecb232d66fc77f1bcd2906a24f82d926ec789bf4acfd8225fa4afa9a97467b6541031b2831ac6f7b3cd38cd4e7499f4731c0ec9b53aef9c8a27e61d27852c63896b4975b2407af04f7bedeb2cde9bb84815fc94502bdaf4a5456efa1fe167373568fda281efeb4e9d76363e0d56d39a08067b0d00b2870395504ddb7ec5cf2409f061c10a111b3c351e7f6283c2f929c21cbf6a1acbce311c8887a2f90119cd4e694af4d0ba2fefd2dd41f84e7fc2a6b84e2763b4a4ca5929f0980391b48df30661e8c0a83b208843c87e28e6b74117533515940f3c935dae70006497b18c6d84cd5e1e0bea65c2a10532d85cb467193c2ddc97f3f1e54df07d6d6e4ec581d90af63de2edd1dd641cacc7c69df240f961c9835eeaa34b456fe036b3add4d44362263441218ba9c25cfaf5528725279319fd930ce71b2f709948c7c148baf37fbb1ecf5f768291479b7b563f2d75500d1d541bd200fe1eda311a7fa1a08f83708bee87f07034ad4f00c6321ed8e07c1baf1db8cc2f9fc42ad7c92401d764bf0bb679b20cb3f41bfced723e3e929a875c219b8d923938bfe5bad68c9ed1e64687973af6b4add129bd523787b696df8df071fe8af63c0aa3c65b3508df314c7b29c65c1d64d6869c0b18d947d099e905988960517c1bb2a782aabcf34bd8456dff0ecfe7e7754419bb3584c371c1ca0f9d14b48b936e5405f2b477452181c5d122b9afc41fd88fc6a26d41543e3594483911b1b3b012009f58dcbc2476397431a2dae62ad389f600b78c5231eaef9e46013a468f8cdbf37ea850dc1db6c72fe7a2c3d80945f953afb28f9c18220fff2c8ee098c8b80cbea1527ddc6f5d87b76331b016e0c5b8e70f20f5f3d4e488efce0d7b53481db0cb27606d403b0437aa6b5bfc10bd5e1138959df30b9eca9a709324968d5fb99d4dcf32ab8c394f91f0cd33413580ba11defa8c279677bbff1758917cb75ee85a038d67aa6659e05bcd636ced81acdb69aed3191dfe362708649194b4d37eaf3275fa3e143c9503379f33bddfe40f4d51a70376d714d30b9c1bf788be3ac2a793bd858aa19058a688da7adf1af765515bf31e500851570727c27c7fd69c951c222dfd43d08a37f0e11d945fa9a96e0ae76893db434f9145c2003cb065d8fe01529600d84dfe8836f715c8df01b6af53f5f2aac36351a1f92afd98e599eaedf057fcb1afa863c74c36d80f6abfda3a88a9e7744125ea29b8fba63a890396d4b9c241a8bdb79d04a4dbf6c2f7ea4a4b1b423579184610c5732ecc8d9e95685888eaf024c6175e0b1422423600794a2f7b7d09ce454f22135b8836d89aedfec69fdd04a6fe0698c9306902901fe140ae64393fdd51ceea07d2179beb85e68d159e4bcfd8d78cd22d3a832c26f42e8a717a875648a5870a4f9bdaf8ba16c1045dad414988c2bde51600f79fda1dc7cf665246e1dce1947499d88e215f5708bf23dc6cafd38e5716d686715bd9845910ddc8c3e14b4c578fac23e23897a8c920f7e4db7367ef9a76e7d5ff1aebf18e69844b4c66c6241f2d603032301a4585376828cf3663406063e7090b52ac9bc1da7857ef09095540b924e1e4a7af043d4a6dd42aa1a43af7af3d507944ddecb6c8ec8b3a3dbef315b2423c57ca99f9d63f677f527248c76e08cff71e5104e3c171277f1e67ddf1b6acb9f5e101a5c624d9610beb0aeeb35ccd8b117fe4b6cdd80076243617dc2b0de811241966496b2d06f48c1f7d820c8c7f383c8034c9412c344ff4b5d4e2f5c277c7d2a545ed1eb163fa9cc63bd7ade8d3a563939ea419e7d7b70d4f3e9924b53610c1fbbb0446daca60520ac5b31787358344ff0a452bee8ad892e837b5f9662fec9ab72732c4b2584f60f6730ebce4f088918a9234e7809b17338528791b78faa6c79394ed38727339625a46ab75be85dd177b27536dab88ca6d6102ac39e66ca690fd1baac3d46205e6a0e0d395a5cc9621d40c6e96cb7dbcf968a6a04d62d71046bef5f1a66a80825eb5b27710956550d81e94c8c19b44e31d3e81a3ca72680bf7329c17a323e49e42f568810cd5e2acfab6ae9b2df6020ac8c3fb57c4ce0dd5446de584d756a254d3e70bf0b93ec5719470250ea311f5d9888e6bfd09201586dcb92dbced1da129978f93c9d9d7dc05f3b87187aee8a510b3245af23b4611251936e07b952c6d5aab07f73006950cafab173dc7cd003a2831fcae1cd7a931058789d8e7e30b771aeea43844d6134b8dff24a1acea2b7c62970ceb444fc46ce99777b33e094c921efab1be49d944ce52baa2d8aab67b2c3af3e3e2ba9dfb4440ed3332608202eb19b19ad691cb56627eabb1e1be2f4209971343589f7f0045aee317ed793e925981b63b0255bdd0f97665f3a9c28f57c72af2430935c285f4f5c3d7c66b6661366b0cb8f827569313fad2fee85f6046b952d142f0ef4088d9b50abb98464e8024cfb377815aa8e4761709872eac54fbf11188403ae230308a57541a65f25106a833fd1244808a8c319a7cb91e4933804dfa24886835f9cd78cb921e44c4ed8d0364fe949b723554226a7ef45db552ce3ee8e2d3b04cd653740315ca135c360b70a0a689ab8efde539e0bc04b20fffc5dcccb941310d3d95a5c1f46dc3ff8f04b0d277e7a51adfc50f082519f7d45d1702d3ffe01ff3c849c3d51e1c00f57722e36ac757b749a9fb38700a398598537e972bbfc3d6936b1dde8207534f60261477875df79831f53e98bd435f724b6b73011f7da81f299a287b04ea17a1b61559a29cdc9fe1a0e1cd7e8c59d7a2e18852eeb080f8d081ef9fe253e5dbe93f8be762df0b24de1df7a405cf85f5b91d264726696a8c4258f7d244c1cb1728ed1179c39762ecfc84880adb81c0688663d9bbade1a7fadd1d2213a8945fffe2c64ed186e8d13c9e3e732844abcef728c8748b452ca4478b455de0b696777ff31445f394a48246a374ce05f2fdcece8a35744357f42bf4071abccc413c6df795d2988ecf44ed17e6c5e9798a1fc87983de25b0fef599244050f7997957c7350c7200c48145cfaafd45c51eac49ffc0e61ea4dabe34fd4f3c4e36a94a73c1e374a9bd608d5314e3c338bc1525b483d1d3c06e35549da6b7c48147e9b1514a03a3dab268f414af118f8f3b033a8eb8887b691526d10e3f7c33e4626f28d9d857b919924a8af523fb41313ec6c7514d958736ace2c4ce9e765b7cf9a15508c47d68f1d5f8243cb051556983524c2389179d695bea7a914833207fc916ad046396eb12915edf02662dbd94afc8e23cef9ce0ccfd1e926acf7cf6e3eaf039924b11965ae22497cccd307650f4e589eb9363ab3e43df40e2346c993c6837c638f0b6a99447025fb84a14b71ecd45011da2e907c1b2f2942476548645688bc2d884839a91f026898170d9b9e253757f1a6e4dcfcb7602bc2dc0c53e6d815640df30c6bb42584204439ff65079ad0efc82b2a90747383d8c1579ffe80121bcdf82bf6ad11c10a025005d15c3a3a2b35dc0609f500378bd84e7e5e4f1adaaf342ee7c14e3819de5ec3a412e220e6459d1464ea0df2bcc75a395c68ac8cdbbe96c08697b6f80fbf0682768b6491d6b77cf8f92d335b9c94d093b40ea845cff43c850b259467e471c2fc54737795cbc58905335900d45b94ac2223c2a89cd8a717eb95b9a3ffa538cb44e8ee74ea265e3cc68350447cbb3fb28917fc978f23f17e5894a6b249c192d1e4c7cb2a2485bf7de94921f6ef8761cce9deccaa6325e973f4e8e48cea7a150731f9a62454db6f30d7d135513c4255a16d3b383f0eb0ab1ab474e4d05ba01fbc6ab4c7c258e3e66a456860ce94363244ae4f06b7b9ab81a6bb89bfdf5e1657c711af247c9f4c7f820c4e83628241837d57efb56b3b338ebd4ab6800e10e2446302bda761bfc5b0a70155bfddeb37acb48343967260aa3449485c53ea2335c8dfbf4fc0f7577d475d293b41378ca305e6c232170bcb3d0b97e39780d6419dce53f58fddee89afcc5d31a048c7a24cd97cb1e906769a1869373c945567dad886d7006c85038015e94cb276feac635244f643f8b5446870395c9d0fbbc05ccfefec9ff92d2209d0aa3b7c8923d831d018110fd765130e04a4d2205eab8ded4e096e9d9765fc4e1a4d26491d193dc7fa65ed7fb7473ac3179ca76a3dbcb6cb151e13151610316408d6fb8a4a6dae8192a5b24a6babd15abe5d88fea046a13f2a014254425c04d35f6eb781a40d8c290176cb526f7a2a8fc159e41a3f949aa2b9064e0e72ba2ea3e669b96bbf1860154c4688a70bfd5d623e114fde0bda5762bf95670d18e921c8e9328fec471af5500987486b29d1cac219d78109371694001900dc16b3fae3500d6e98c3ed16fdaed80e0f0fd3443127a0d2b2441e733cfdaa7fd28fd3251705d879839b4fd089e7c17fff66dc8626a155b7acaad31d5f206e28d8b2c2e4599bac40a6d7073e931b5cf806a286d00b528b299ccae0e657d59dd8680d159bccdcf567950a2f8f6233b1a1392ca61423b2a19430e16a95ff8fafcb743770c3a03739834d03c48008fd03cca7e4a6c2d6b5d3f53855d9278ef496194b4a7ece6bf2b3829ba77cb700f48dcda9172a89747dff5414dc28b020faddeb380cccbbcde75a34c8020a488c6c147bc2b2a3a3b36756aeb72fde4ad2d1841cee634a083137ce70cdfe0bdcc1b576777ac07c7800801a190d3aa0a708e4c3c45c112ed116e6a59b89f0d8cdc9bc165dbabcbdaff3edd2dc9164f9ba226579dfdb69048630c990a5c77a05e4efffeecd66894f92b5a5b6c5a8ddf791863fd363f9e0262487fdd984e911efdce4e153468a2faa74a136329c07bd853cf7001cb9ab5bbd43941e38059a9d44c1b25c9586b277cad2908997c6c43964e780b45c1e33f59134161b27d090d70e9522b71fbc893024ed01e2669e3de51d506fe0d88b8a587f84b485c1407b32c5d461a459e9d1565686d02f3229f5ab24ef94e8600ca66690bc7aa21575b977f56b769d7c3adec4f5056ead76845d0f74f6762434721f2100fe720b056c223c657ac1b4476ad1d65928e8a7b0b35a49d946566413c107b75dfca605081da9b5ff31828c1c6e4000f8c3c6f3c8cf0b672c60f54b1468f42f6d9dee8e3e61dbc2e1052c4a11507e304c426b2225181a99601634bc5e111c06ef46563731349c0ffc9a3d2f40baa94334fddfc54dcdc1cb66f2ab66d64d2bf25d851794a5b67d0e4a3537a4e86802d7de9fde430c3fa8fe8d7ff6fc4da402bf84f322b2127ff81e1862e57c99fcae2b4a66198c693a56bd5b7c9161f81f0e2bd7cdf00961ce766a12d119d45775c76c5e91edcfdc538b1d262c19e238314726d2a57f56aec4e81f4c42f0355febfd586f0cf23bbd962f3306480a00024210877236f766e4863bba8c34cf59c7ba19d012d3ea6db8805420d194348da42564ea5563d6ee4691c26a83b6175a24a1c2d236fe3dc3324db568834bc1a0bda559a3d23108164a559779a47703a69374619211921e4452f50f4ae6e16cd090344fd9da41348baf1467ee48f8244ab7951346ef0fa827e854ff30c773a3ac43ed511673e768e9911ae0b6d177b53d6dcd6c3501c5669805681cba506d43f0144688c9f2e6f2757245c249278266b8aa4c90d0baa30495f0301c43dd93920e6d51aa5d5b3f3673a40f68da8b32e24f77d82b24d6431c6dbf1503c8e3e057d10c4097bc573bfc02d6276de2ddb95c8e0934392550af75f3b3a9cfeec77a93de9f99f276a32d0f18e8b1945b41ed08b98492dceea0ba95e71f5534874533acc23da75a2044837697e221f6556089bc948885874ee2b0bc63f6379ea680d1bb081e0b1ebf2535f0b2598e59c5560663601139bf0ce9a0039f9000da09526d7059eb9dc2b2c12d95d40bdc3864fbfeb39c17f97efdcd3ba8ed03d3b83404726188308a1ca960457599845e3f22ab60d2643f2380bb63e98897a5258dfe9d178ed76022fb155ab2a2c6298394d5d516cbf593b9693a1f012bd9d0afc120964effea0cc3d6a1eed0ec0c4ce697eba2d5bf86b552e08f3595e8cd3a07ed3d51bd5621f340ec38d9cd789fbf8cfb0e93ca5c18d895e09dd4190da8b03bcda8951b7dd2abaca268edb2ec831d268d98175c3d0bb98d6e787f5304cee8461149866cec189e26063114a6a0c860962aa00e7124551b7b6fad479069c32405148c4f828e4e7ae34f4d5d365b1151ba866e864d8a63b71daa5fc7e108cb1294f95af0d03c222ee8f434834a361237dfb2dab30e50681526d10f97d428fe277a0443418e969f09fd0618acdc62eecd77a975a496ab51a8e011f6fcf2cc29aa54688486931a2065506a9ff3c9fca153b465f29a89c752f930f59ee25958824a6f3cadef5eed7e788335a31c1768edc7580d04062f8e1f5c2ce67bd94748bfbb14cdb3e7af871e3c3463e6f7ff676669f8afc1271f1686c844eee49ba21153d34b52f03aa75ba24998d1c71bb2f5d9d3701e043cbc355a8e1d09a4453acb0585655dc3e11a4dbfb20a70c77e09a61752656ca8362c0536ac4ae91161adf284b4ee77c4560bddf7673be89a342f84f536d5521888d1ceaf89a7a8ae693da1c1d665fe493f6cec4e092c2e386e1d5f59d2f92a877a5236c1bb7aa5c721236900b6f9e2d393c946d6967348fedc7bf2c3ec28b68a060077559b97b4d038f3a34116e62e703783b2611bec2af15a2b8fba638f29b53dc6ded55cc8a63603414020fab8d329193713e3c6a69a6b0ac48b43f6fc4b61ef849f8f19627d469e60f29c8b2c81d554a5217ed69b05f8ab6a3655a797446302712cd453067ffb5231208ac090a8aec8587837e92514b0fd123f4397b71cd8795ad9f06937f9c64e3747b0c9c18d3f96ba052be8d1fdf4230c0a653e15d8d1355713d29ff48419e91b175a2026c2caee0ca3626bb6d3824a3373b0a95148bfaed8a63c41446af223ad284209937507b412db3bc399011edfe7d7525955e46fa22fb0491f9bec787a1f334e36135d98a04e5576142cd087b3f7641769cb5629e0b24ca3019faa02394126819db2a92bb93db4351bf33e9f11fb38f4d556d90f7e6604f50ece6f5eed99c54136c9906c34e3d306e2d384a5545687e7b9a1235739829bf1e6291ff15bd0734c3671c916b9eb25d6791c3e4a2ce918de3671018ec9ee5ceda5ee5fae6aef0e57af0c9a53004af23914222152fc583d270fbbcc0c41ccb0c327056ed70d7ff7d04cba39018d2b279fcb8f42b18be06115fdac0aeb1e7737d0fcefa2b6f729319caeab60e7234a242dfe8ebe3211f073ac71d3c27b377841a737d4cc02a992a7769849f29a3943ec50982824e03212c4a0d2b680fe809c0d9516f2aa91564c6eeba04d6faa2171e0a4192246015bb0f3081da5400a0ab628808e49290b614bb48502a21c0b0660c404563afed280376cd915ab14f1ee2b05273a232d6ed06d3d6458f04f5cf393e2e8ab6859723665915d341b8f94092939b4f73e5741c83d7e75d3fcf31cff168fb396933f3843f366d0e493d013b6816f4f1a1e66b35b46d07edba65b51fb5dade3c8cf404cd6c6bf7e9a26b0ae6d2c962106f0c78510bacc825c084d62734cad25ab9e2b854a7fe4b5287f1cfdded5de9e6395668db3b74e7a04928ddb9082d3362209fadd4213953744e069a962d30b7759e0f491ce2e4741a198997f4f4c82717d019042dd9030006065a6a3dad1713e1ae31a8b4afa42ce78177360f59ba7b27147e834b263c844b708835377543ce7b8fb923d3203d3621765283bd72c33fa2ab0a4fd4ed43dd9e594284d3d34779a498218e668aed9e80db76261bac49d73941227db0baa78cdcd7382930d6b8332e20e2e1b08ba03e67c987d18e1eb12acf5c74a4aa41aa2b206b01a562c8f915d19f08da135c1ca30a00a3cf80c5a084fffd657ec1f82295f2f19f47a8767762eaa0b6f360f224a4590670eba0ce81767d67d597c01f143d39f77b0c769fce22a18d565841b1bcf1751f21fb6437b57db029fdf8b77ba10033ecca0bd50ee9036960793921b50d4f7c4a227978a4311ae4ff6316f1711210ddc30202e9b801647370744268c01ad9963dcf5fe18bcc50b9695dacb170909ae22eff683e6570c57e014f6e6f5c67adf62cb11a81d9ab54ea90a0733e9796daefc168c3ba45f0a851e07f1e63baac4c96a50e0a4921bb84f5830388ec101c34441f45757b8ebcbee869016e7e44a0c681d67da60b8318daaaded76c26b145d99b9a050e56870a577771b167e3f516081112b1ab89f0f020f796fd66c431e51cb93f568e10c95420de95b61c1a113874c78d147fb3685ca8e1afc426cba03552d44cc2a663b40b750376143457b648cae83ec2f5a3fd0b67245292d15fca510dcf2ff7961be93a57bce3026601c6ff72124ac5ead2109bb872cfed6c648775e70695cfea81d4ab3335b4a5437e42737b3ccd81c8aa1200c8a10f9e0ea04627e19f1c850acc75671174e44073c20da3d7a775f88ea626ecb5327a11450ce242b811b77e48eb325be35fdfcb949566b6f4a7209b28cb203677ce78de7caa92ec48dcbded927cbeb3aa096a83a3fb163570fb5657ff089a76fa7a3d858f3c9348ce8d73da660c6f40ba01252efb54c83dd32e2e97f9afd1088971eb92d8aea405a18fcf786e6e7b87ff56b98735c21fcbbaa6a577ee3e9c684746c23b52bcfe06d9270717073a3a1f23a0904b9a0b38a22da35e65d775c377a18a3f25fe843db4fe8afc82134c5b38c7710cda0016e6e45b7a45b1270406f86cdbcdec41851bec64b1a9a30e9f54be6f1fc9cd2704662847945bcfb301a12aca9cd46eec58d18657f188e61fe4713711a9d15386d511b562955d76e247e5f089c8326a3a9813d0d2b26dbeceb9f1562a81a02643f8c32f40599e3aaff72789a07dbabeefc780dd5da3ca7a3fcd0c9856250afdfef48e8ae73f79502c77e01e2f5185365f3215bb91633102063fc07c454fd6e1fce49031c0bcd009a3fc67e4182f018cd6b7499494b8098f235b4699fd89d4411efbc6446c9c1a306ce2382558b726dcbd9d4ab98064e9f16acfb1a4d6674f95266ab0131fc0e6dd56a104c9aa877c0be5d5b076a5f47d74eb05ab97d10c9dc8d34b3eed6dc2da552f1172745b41a2a2fc3c42ad68254559ebe5d0e8390d9be2e4b25ab2e259b2652e6f350d53fb95e8a248c0c452cc783ea6ac3f2f66ae9fb8204614390e564186dccbb522957598bc3d8a2d3790c9f81b1b296ba9095a6543d6a5e46fa5a2bd586a0de74684266949c3e84b2933ab84dae7767f379e50ebd0a00a76f41a78a65b8daff38dacda4e7ef66b17d6167bc7776bc09a4323295e1734456aabf2f6567f8dd1eceaf944dfbf94e39cc56df520d2efed700f5c34199a16b3abc64f244018fb68f1756d8136d97463da50c056cfa6fc1ba80b2e55f9cc03b3a73b237140ce4bd71f6088e2de241da78c45d27db1c2501994297a695bbc3959eb847273508f9ba0404ec56436f22f45c60a5cc8452338b7ab229b2d115fe2a1c1d1a41060e61c6b6cdd0be7d3e9713ac553994b11acecbbf85ffc813b10772ba47323effd6453ae60960734bd919e2c6f8e66e3168070337d4f5575516eafde1673525718feb4833e296c9680bfc27af4a2a1ded7af09a3f874553a758262c9420ab5fe8096ae62b4e2128ae36ba35136ef59a7b0a6b5b49b5f11d8e4cac8a9a56fb014157fecd39943cfdf5087dcf0b9835bf375cf5d43280b845e89e579087bc01dc2daa2e1978d368b97941018e55968c39dd84d2abbc95e0f7167576e6e089dccf6050ba8ccae8cd23ad3bef05412fa80fe0703c0185dcf6c6e8bba6e52bf5221846275b49998a264f24bc48e23f3d7297306bdddd85f7dae0d9b836021f016916f865df79b50996c010183e8d58b18b84122abb5b6f8247c7d7b356027575973e4ad0d475d5891d6976b201fd9b9186426b972d47f131fd5a95c9ee5db3ead361cc34bcad0df75029696aa447e961904ba6d5559059727a417d321d53a2d8ad5d815e47524b1a2a1d1ed159ce2a58c0a95fd30dd4f06350a2f6b45019892b17f12c66c638f6117f575e8b15066fea7498c2ffad88ca44d8e33841b9feb895369f0a956768f5811a03ae13e5d82c1e453ae2af26cba003cc6b3adcaa5f1dab03673c087ac96ca38f6c766af0bb22c67b2e7e0e5ed3ef82ad5d469aed1461f20a09089e7082bcbc5fc1ce899b9f169f9caebd528063e8fef15bf0e7cd7ef0acb9ec1d64a403fd562143d479bcbf7b7a6a97750ebcf45bf1158931726c0e4e9c40265ec2ed126ae6f8c9cd230aaf834d2dd4f5111d41cf6f5e1e0404b0e00d924237a08453e2a1600fe560193fa30b3b8facbc6d3df8ce7711ae04c6ab4d768eedb9d721dca8a65148ead0dcb15bf4564c427d8d055e3701476027171be18372a1889c7b0b433a57b542946041f245227f49fbeaf3c548662e8c52f54bc9123d8c18eb4a8e186303c191db3d292a50e396edf9a2e1f8fa3281a6dc526a4d1cd677a7c31ffb25a4e3183509d79d1763c82e00c27c9d6e5e7366aa87c2f3de437b5ccfb470e054691475fd6f90eca8312ca793ccfbb061af382f71e5af3686ced003ba6aa03d50ea93b69523c002bcc43f7b7e883fd7655071a35d483be616d18d0a6524f36281e9067d7e499e8d5136cf0362b9ee22f7b8f1f5f7ec97653948ca318578f1ebb4afa445089da13b1a1d71476c4c009245eb7614d2d1084dc3ff637414a093d06678ea8387089e4419e64a5d74dc0c2cc09b404d98845df2d0b106bc2136ad07c9cd150bdc287e160e8eb200f3e2a06bfd5f941bb5588b805a8e642b54ffb0f08651962585983b448b631bad07240330161ad093b4bce0769b8063e75f27de74952220aa5c9ad8c3e605230cf0e51d4f6abdf725ce494d9b6513b7da86f3067a8924422d81dab3a41744e23d422bf8967588abc6f83c64b292f046dd5ea979d4d3e473386793e48d1fdd8464519886f498f7b284c18cd8794915cd97128c57411512d40613652dac29f2b1bade65d7165485b4c98c200cebf371114c3c9a766fe876f27229157578eb8005c5680536bf48e21080910569d881ad53e3143f579509e4527c8ca1069f5f30854c0effcc08e0686fc396d79c34b3997366bdc890745bdf88b4e4fb0b68d81efb59947617f08c7f6d232f0df9e34b38854b70ff7e5edec477a56798a7b31d000f3a2a19abbfd56f2a0fb202d9a1d189b560016f3e24e5703cefcc20fa9f0cf663f166bc537d0c4729aa8e9fdf99cf9acb6f0086f19779b48a978b88d022825e394bc5c4d90986c53822328b522edce7c2886f52ccf26b116f682c315388d9c78f0d5d5cc8b2d239f9fbc829d7f3fb4f53033457d8aa16191f93b34905e3521a35c0a5562475d998fb57c4049729690104ea6cf449112aa8215659f47e6710d8515468096b01f0cbf546a6d201eeedaded90182859695600ef0c57607a88fc9438dade79c67e433b58932c6dc503e257b9460d046b3435b48bb23ae6c6bee3345921a28c11b39cad30aaf1f21ada87587913a3724c49c41d301704c6bb7f3158fb890eee0d3b86f54b59f82b640dbc08b5777b8b1fc9b700fc822196fb8070a95aa6c2e30079b64ef1fbe0600c269e38e96581f1bf9fa14638b240eb7211c4b43e1fca7bc496581f9c011cbe31c434cdd2c9f122d691803b1a240c2b65b15039177972f63b970a3f29946e1395c12bad70229079aef5811bf8ce051f515712d22082654fe8476605b5625b300b052907a162bdd56b1318b46dc8a241053a3d4824f0c41c41c0c2c37878c07090c8b9c21bde7bace2ceb9b1706a546169c7efb701c6a607b8bf60944804d2ead9c217b1a53bc28d77d66560216f011efcca28902982f85aee5dcd92c5731d99cd2a7489c8d0f33385248bad1fcbe8cf65c2150caf91df8f96d505686c0ce86db8a9382e028bdbedb4afc0d69967739a99c87573e70009ce112647dd0e74cb4414771fb65ed46657f2eab756f167cf5c727bf281ba273c53c1c55464d2fe301606a3f9e72da57b4a62d9dbc30c9eefa8b2d54d8878ed07a28f733c6bc3b9611bd5708178c42d9fb7197a42081d0ef66c1c05768bce2421a796c0f58301a0410c6a2cf3d321f76d136d97118659edc43c933402a9fcc3464830db0ffaa04b5a6237f719da5756f99e5ac59e03ee63555ccfb9856c5b950752ba5ff764751334b785606a44403a74e966941570554bdb6acd9ef25a4d21b973e9bb1b1e4c9417399f02a70cc85511325a68400d8e0c651bfad7b974992083cdd0d19a8d39e2774c55da038d62ca1f6464c81b6d4236308b449101f8541102a3ff0576857ec50d1413a83c8ab43d4ec1feb4d36e709deac3eccd16058b85fec6c17d6d09e4645a18b5e7beeb67de9902d02056aea24dff0ed42392c404e3fc6624b3d79d80dd1d82bc09f86e1ad2c7ae801d3bf874039c2beec8b78b1d7bf976c2dfc94f4a809458ed4fa3cb2c855d13baab6a01bb8ba57a10a1b6fedef7750eea457cf795b805ab6718019577c4d91fd7d4d7508e68fe791809e69d798f3ce52afec7e4b741ea79ccba336b4063c0aef9d339f4348c226039dacf5675ae92f5a493e9b5bc8ec496a1438afc6640903676e63ae523cc740c85cbcb9e07c6326ae84186253637640d1e44e26be175977a45100d5ccf503ee90a76d5c7b0e4be94899ec09a209beadeaee1e20afa3e42557bf5561219eadffb85479103adb9e8e27b5be0ab3176a30e19a6b598f6dadf30cf9da2a75187555f9913861cedce3c683eb0e684e3b264411afbb29253e6e71b58d9575bc945bf128f1e92b185c643108a30235e2d7220c547edbbcb9aa2ffe29e945f135484c603cbb2bd0e0f2688308ea533b3ea23a3f293daa2ce2db5a80f7932a436313ab80683632ffa24367dbc28df2b82655d239054ce9e42792571c5c8ec2fab2e93511168283ef4a0932a8daa2d2e59d43e7f46a67fd7e94a5bf2ec9e1434fa929441214a25978504fdd93cb1af8c0c7292bfe6a6cba48a7fd13d9f2231a763d7e4a10e76f7f5d13943c351e94930e12e9daf0be6613688aa6e8ce43e1d3e6b7f6e11fbd781b79c3794d41f090445bb7b73098a9b41478b05dc1813d6cdd526cdc47e41eda2875582a2b7c68f94727b99b17e77ce218f6c818aab9435ae0aaa7f736a8263d1f2d0a8acbcea107ad79b5b88e04c9875df7ec7e4839205c951750bdc6bcc842db70b7a12bf16e1811c82aa2b86fcfbaab9e0865afa0b5e99c10d6df78130bd78df39a500339f97761da1e668e1896a99caa2c5fb56e4e4876a5fbeada4fbbb2b16be4cfc7</script>  <div class="hbe hbe-content">    <div class="hbe hbe-input hbe-input-default">      <input class="hbe hbe-input-field hbe-input-field-default" type="password" id="hbePass">      <label class="hbe hbe-input-label hbe-input-label-default" for="hbePass">        <span class="hbe hbe-input-label-content hbe-input-label-content-default">Hey, password is required here.</span>      </label>    </div>  </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
    
    
    <summary type="html">Here&#39;s something encrypted, password is required to continue reading.</summary>
    
    
    
    <category term="DevOps" scheme="https://kalyan-zitiu.github.io/categories/DevOps/"/>
    
    
    <category term="DevOps" scheme="https://kalyan-zitiu.github.io/tags/DevOps/"/>
    
  </entry>
  
  <entry>
    <title>外部etcd集群搭建</title>
    <link href="https://kalyan-zitiu.github.io/2024/08/26/%E6%90%AD%E5%BB%BAETCD%E9%9B%86%E7%BE%A4/"/>
    <id>https://kalyan-zitiu.github.io/2024/08/26/%E6%90%AD%E5%BB%BAETCD%E9%9B%86%E7%BE%A4/</id>
    <published>2024-08-26T07:16:29.000Z</published>
    <updated>2024-09-09T08:32:50.667Z</updated>
    
    <content type="html"><![CDATA[<h3 id="Start"><a href="#Start" class="headerlink" title="Start"></a>Start</h3><ul><li>需要提前把前提步骤完成，可以参考<a href="https://blog.kalyan.life/2024/07/26/%E5%9F%BA%E4%BA%8Econtainerd%E7%9A%84kubernetes%E9%9B%86%E7%BE%A4%E5%BB%BA%E8%AE%BE/">集群创建前置</a></li><li>把每个节点进行kubelet,kubeadm,containerd以及一些环境配置好即可，先不需要进行初始化</li><li>可以通过克隆加快速度，3master/3work/3etcd模式，资源消耗可能有点多。</li></ul><h3 id="创建高可用的ETCD外部集群"><a href="#创建高可用的ETCD外部集群" class="headerlink" title="创建高可用的ETCD外部集群"></a>创建高可用的ETCD外部集群</h3><h4 id="节点准备"><a href="#节点准备" class="headerlink" title="节点准备"></a>节点准备</h4><ul><li>按照之前，可以把所有环境都准备好备用。</li><li>然后保持系统时钟同步</li></ul><h4 id="使用chrony进行同步"><a href="#使用chrony进行同步" class="headerlink" title="使用chrony进行同步"></a>使用chrony进行同步</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 每台ETCD节点安装chrony</span></span><br><span class="line">apt update &amp;&amp; apt install chrony</span><br><span class="line"></span><br><span class="line"><span class="comment"># 修改 /etc/chrony/chrony.conf,添加或者修改NTP服务器配置,自己可以添加主机或者用公共NTP</span></span><br><span class="line">server 192.168.154.20 iburst</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启</span></span><br><span class="line">systemctl restart chronyd</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证同步</span></span><br><span class="line">chronyc tracking</span><br><span class="line">chronyc sources -v</span><br><span class="line">root@etcd3:/etc/chrony<span class="comment"># chronyc sources -v</span></span><br><span class="line"></span><br><span class="line">  .-- Source mode  <span class="string">&#x27;^&#x27;</span> = server, <span class="string">&#x27;=&#x27;</span> = peer, <span class="string">&#x27;#&#x27;</span> = <span class="built_in">local</span> clock.</span><br><span class="line"> / .- Source state <span class="string">&#x27;*&#x27;</span> = current best, <span class="string">&#x27;+&#x27;</span> = combined, <span class="string">&#x27;-&#x27;</span> = not combined,</span><br><span class="line">| /             <span class="string">&#x27;x&#x27;</span> = may be <span class="keyword">in</span> error, <span class="string">&#x27;~&#x27;</span> = too variable, <span class="string">&#x27;?&#x27;</span> = unusable.</span><br><span class="line">||                                                 .- xxxx [ yyyy ] +/- zzzz</span><br><span class="line">||      Reachability register (octal) -.           |  xxxx = adjusted offset,</span><br><span class="line">||      Log2(Polling interval) --.      |          |  yyyy = measured offset,</span><br><span class="line">||                                \     |          |  zzzz = estimated error.</span><br><span class="line">||                                 |    |           \</span><br><span class="line">MS Name/IP address         Stratum Poll Reach LastRx Last sample               </span><br><span class="line">===============================================================================</span><br><span class="line">^? 192.168.154.20                0   7     0     -     +0ns[   +0ns] +/-    0ns</span><br></pre></td></tr></table></figure><h4 id="安装ETCD，整机跑"><a href="#安装ETCD，整机跑" class="headerlink" title="安装ETCD，整机跑"></a>安装ETCD，整机跑</h4><p>ps：个人建议可以在每个节点准备Go环境，虽然不需要严格和Kubernetes版本进行对应，但是还是需要注意版本兼容问题。</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># golang</span></span><br><span class="line">apt update &amp;&amp; apt search golang</span><br><span class="line">apt info golang</span><br><span class="line">apt install golang</span><br><span class="line"><span class="comment"># 注意版本，这里是使用3.12.0，自己斟酌</span></span><br><span class="line"><span class="comment"># ps: https://mirrors.huaweicloud.com/etcd/v3.5.12/ wget 不到这里可以获取。</span></span><br><span class="line">wget https://github.com/etcd-io/etcd/releases/download/v3.12.0/etcd-v3.12.0-linux-amd64.tar.gz</span><br><span class="line">tar -xvf etcd-v3.12.0-linux-amd64.tar.gz</span><br><span class="line">sudo <span class="built_in">mv</span> etcd-v3.12.0-linux-amd64/etcd* /usr/local/bin/</span><br></pre></td></tr></table></figure><h5 id="创建etcd-conf-yml"><a href="#创建etcd-conf-yml" class="headerlink" title="创建etcd.conf.yml"></a>创建etcd.conf.yml</h5><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 一般在/etc/etcd/ 下面</span></span><br><span class="line"><span class="built_in">mkdir</span> -p /etc/etcd</span><br><span class="line"><span class="built_in">touch</span> /etc/etcd/etcd.conf.yaml</span><br><span class="line"></span><br><span class="line"><span class="comment"># 每一个etcd节点都需要进行配置</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># etcd 配置文件示例</span></span><br><span class="line">name: <span class="string">&#x27;etcd1&#x27;</span>  <span class="comment"># 当前节点的名称</span></span><br><span class="line">data-dir: /var/lib/etcd  <span class="comment"># 数据存储路径</span></span><br><span class="line">wal-dir:  <span class="comment"># 日志文件存储路径，通常省略</span></span><br><span class="line">snapshot-count: 10000  <span class="comment"># 多少事务后进行一次快照</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 与其他 etcd 节点的通信设置</span></span><br><span class="line">initial-advertise-peer-urls: https://&lt;etcd1-cluster-ip&gt;:2380  <span class="comment"># 当前节点的 peer URL</span></span><br><span class="line">listen-peer-urls: https://&lt;etcd1-cluster-ip&gt;:2380  <span class="comment"># 当前节点监听的 peer URL</span></span><br><span class="line">listen-client-urls: https://&lt;etcd1-cluster-ip&gt;:2379,http://127.0.0.1:2379  <span class="comment"># 当前节点监听的 client URL</span></span><br><span class="line">advertise-client-urls: https://&lt;etcd1-cluster-ip&gt;:2379  <span class="comment"># 广播给其他服务的 client URL</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 初始化集群信息</span></span><br><span class="line">initial-cluster: <span class="string">&#x27;etcd1=https://&lt;etcd1-cluster-ip&gt;:2380,etcd2=https://&lt;etcd2-cluster-ip&gt;:2380,etcd3=https://&lt;etcd3-cluster-ip&gt;:2380&#x27;</span></span><br><span class="line">initial-cluster-state: <span class="string">&#x27;new&#x27;</span>  <span class="comment"># &#x27;new&#x27; 用于初始引导，&#x27;existing&#x27; 用于已有集群加入新节点</span></span><br><span class="line">initial-cluster-token: <span class="string">&#x27;etcd-cluster-1&#x27;</span>  <span class="comment"># 集群标识</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 安全性设置</span></span><br><span class="line">client-transport-security:</span><br><span class="line">  cert-file: /etc/etcd/etcd-client.crt  <span class="comment"># 客户端证书路径</span></span><br><span class="line">  key-file: /etc/etcd/etcd-client.key  <span class="comment"># 客户端密钥路径</span></span><br><span class="line">  client-cert-auth: <span class="literal">true</span>  <span class="comment"># 启用客户端认证</span></span><br><span class="line">  trusted-ca-file: /etc/etcd/ca.crt  <span class="comment"># 可信 CA 证书路径</span></span><br><span class="line"></span><br><span class="line">peer-transport-security:</span><br><span class="line">  cert-file: /etc/etcd/etcd-peer.crt  <span class="comment"># 节点间通信证书路径</span></span><br><span class="line">  key-file: /etc/etcd/etcd-peer.key  <span class="comment"># 节点间通信密钥路径</span></span><br><span class="line">  peer-client-cert-auth: <span class="literal">true</span>  <span class="comment"># 启用节点间认证</span></span><br><span class="line">  trusted-ca-file: /etc/etcd/ca.crt  <span class="comment"># 可信 CA 证书路径</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="创建etcd-service"><a href="#创建etcd-service" class="headerlink" title="创建etcd.service"></a>创建etcd.service</h3><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line">[<span class="string">Unit</span>]</span><br><span class="line"><span class="string">Description=etcd</span> <span class="string">key-value</span> <span class="string">store</span>  <span class="comment"># 描述该服务的用途</span></span><br><span class="line"><span class="string">Documentation=https://github.com/etcd-io/etcd</span>  <span class="comment"># 提供服务相关的文档链接</span></span><br><span class="line"><span class="string">After=network.target</span>  <span class="comment"># 确保网络服务启动后再启动 etcd</span></span><br><span class="line"></span><br><span class="line">[<span class="string">Service</span>]</span><br><span class="line"><span class="string">Type=notify</span>  <span class="comment"># 服务类型为 notify，表示 etcd 会在准备好后通知 systemd</span></span><br><span class="line"><span class="string">ExecStart=/usr/local/bin/etcd</span> <span class="string">\</span>  <span class="comment"># 指定 etcd 二进制文件的路径及命令行参数</span></span><br><span class="line">  <span class="string">--name</span> &#123;<span class="string">NODE_NAME</span>&#125; <span class="string">\</span>  <span class="comment"># 设置节点名称，需替换为实际节点名称，如 etcd1, etcd2</span></span><br><span class="line">  <span class="string">--data-dir=/var/lib/etcd</span> <span class="string">\</span>  <span class="comment"># 数据存储目录，指定 etcd 数据存放的路径</span></span><br><span class="line">  <span class="string">--initial-advertise-peer-urls</span> <span class="string">http://&#123;NODE_IP&#125;:2380</span> <span class="string">\</span>  <span class="comment"># 通告给集群其他节点的 URL，替换 &#123;NODE_IP&#125; 为实际节点 IP</span></span><br><span class="line">  <span class="string">--listen-peer-urls</span> <span class="string">http://&#123;NODE_IP&#125;:2380</span> <span class="string">\</span>  <span class="comment"># 当前节点监听其他节点连接的 URL</span></span><br><span class="line">  <span class="string">--listen-client-urls</span> <span class="string">http://&#123;NODE_IP&#125;:2379,http://127.0.0.1:2379</span> <span class="string">\</span>  <span class="comment"># 客户端访问的 URL，包括本地回环地址</span></span><br><span class="line">  <span class="string">--advertise-client-urls</span> <span class="string">http://&#123;NODE_IP&#125;:2379</span> <span class="string">\</span>  <span class="comment"># 通告给客户端的访问 URL</span></span><br><span class="line">  <span class="string">--initial-cluster-token</span> <span class="string">etcd-cluster-1</span> <span class="string">\</span>  <span class="comment"># 集群标识符，用于区分不同的 etcd 集群</span></span><br><span class="line">  <span class="string">--initial-cluster</span> <span class="string">etcd1=http://192.168.154.16:2380,etcd2=http://192.168.154.17:2380,etcd3=http://192.168.154.18:2380</span> <span class="string">\</span>  <span class="comment"># 定义集群中所有节点及其 IP 地址</span></span><br><span class="line">  <span class="string">--initial-cluster-state</span> <span class="string">new</span>  <span class="comment"># 集群的初始状态，&quot;new&quot; 表示新建集群，已有集群用 &quot;existing&quot;</span></span><br><span class="line"><span class="string">Restart=always</span>  <span class="comment"># 服务退出时自动重启</span></span><br><span class="line"><span class="string">RestartSec=5</span>  <span class="comment"># 重启前等待 5 秒</span></span><br><span class="line"><span class="string">LimitNOFILE=40000</span>  <span class="comment"># 设置服务进程可打开文件的最大数量，通常设为较高值以避免资源限制</span></span><br><span class="line"></span><br><span class="line">[<span class="string">Install</span>]</span><br><span class="line"><span class="string">WantedBy=multi-user.target</span>  <span class="comment"># 在多用户模式下启动服务</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="启动etcd-service"><a href="#启动etcd-service" class="headerlink" title="启动etcd.service"></a>启动etcd.service</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">systemctl daemon-reload</span><br><span class="line">systemctl restart etcd</span><br><span class="line">systemctl <span class="built_in">enable</span> etcd</span><br><span class="line">systemctl status etcd</span><br></pre></td></tr></table></figure><h3 id="签发证书"><a href="#签发证书" class="headerlink" title="签发证书"></a>签发证书</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 目录可以任意</span></span><br><span class="line"><span class="built_in">mkdir</span> -p /etc/etcd/pki/pki-json</span><br><span class="line"><span class="built_in">cd</span> /etc/etcd/pki</span><br><span class="line"><span class="built_in">touch</span> ca-config.json</span><br><span class="line"><span class="built_in">touch</span> ca-csr.json</span><br><span class="line"><span class="built_in">touch</span> etcd-csr.json</span><br></pre></td></tr></table></figure><figure class="highlight json"><table><tr><td class="code"><pre><span class="line"># ca-config.json</span><br></pre></td></tr></table></figure><h3 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h3><ul><li>有时候进行一些服务变更之后呢，这个etcd的服务可能会进入一个长时间的阻塞，他会不断的进行节点查询和选举过程。这是一直既是正常又是不正常的状态，这个时候你可以：</li></ul><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 停止etcd服务</span></span><br><span class="line">systemctl stop etcd</span><br><span class="line"><span class="comment"># 清理数据目录</span></span><br><span class="line"><span class="built_in">rm</span> -rf /var/lib/etcd/*</span><br><span class="line"><span class="comment"># 再次确认配置文件没有问题之后，进行重启服务</span></span><br><span class="line">systemctl daemon-reload</span><br><span class="line">systemctl start etcd</span><br><span class="line">systemctl status etcd </span><br><span class="line"><span class="comment"># 检查集群健康</span></span><br><span class="line">etcdctl --endpoints=http://192.168.154.11:2379,http://192.168.154.13:2379,http://192.168.154.14:2379 endpoint health</span><br></pre></td></tr></table></figure><ul><li><p>有时候你的集群节点数量在某种场合中很庞大，所以每次查询集群状态时候会显得吃力，所以你可以：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 本来你是需要这样子，&lt;endpoints&gt;里面需要填写所有节点的监听地址</span></span><br><span class="line">etcdctl --endpoints=&lt;endpoints&gt; member list</span><br><span class="line"><span class="comment"># 你可以使用环境变量进行export</span></span><br><span class="line">nano ~/.bashrc</span><br><span class="line"><span class="comment"># 在最后一行你需要添加，需要注意的是ETCDCTL_ENDPOINTS这个字段是必须的，etcd才能够意识到</span></span><br><span class="line"><span class="built_in">export</span> ETCDCTL_ENDPOINTS=<span class="string">&quot;http://192.168.154.11:2379,http://192.168.154.13:2379,http://192.168.154.14:2379&quot;</span></span><br><span class="line"><span class="comment"># 进行配置生效。</span></span><br><span class="line"><span class="built_in">source</span> ~/.bashrc</span><br><span class="line"><span class="comment"># 然后再进行查询</span></span><br><span class="line">etcdctl member list</span><br><span class="line"><span class="comment"># 还有另外一种方式就是，能够使用etcd专用的etcdctl.config.yaml</span></span><br><span class="line">endpoints:</span><br><span class="line">  - http://192.168.154.11:2379</span><br><span class="line">  - http://192.168.154.13:2379</span><br><span class="line">  - http://192.168.154.14:2379</span><br><span class="line"><span class="comment"># 然后可以进行环境变量的指定</span></span><br><span class="line"><span class="built_in">export</span> ETCDCTL_CONFIG_FILE=~/.etcdctl.config.yml</span><br></pre></td></tr></table></figure></li><li><p>还有其他的集群情况查询命令（已经设置环境变量的情况，未设置的话请添加–endpoint）</p></li></ul><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查看集群成员信息</span></span><br><span class="line">etcdctl member list</span><br><span class="line"><span class="comment"># 查看集群状况</span></span><br><span class="line">etcdctl endpoint status --write-out=table</span><br><span class="line"><span class="comment"># 查看每个节点的健康情况</span></span><br><span class="line">etcdctl endpoint health</span><br><span class="line"><span class="comment"># 查看当前集群的leader</span></span><br><span class="line">etcdctl endpoint status --write-out=table | grep <span class="literal">true</span></span><br><span class="line"><span class="comment"># 查看集群报警情况</span></span><br><span class="line">etcdctl alarm list</span><br><span class="line"><span class="comment"># 查看当前的节点和角色的投票情况</span></span><br><span class="line">etcdctl endpoint status --write-out=table | grep -E <span class="string">&#x27;ID|IS LEADER&#x27;</span></span><br><span class="line"><span class="comment"># Raft leader</span></span><br><span class="line">etcdctl endpoint status --write-out=json | jq .</span><br></pre></td></tr></table></figure><ul><li><code>etcdctl endpoint status --write-out=table</code>字段解释</li></ul><table><thead><tr><th>ENDPOINT</th><th>ID</th><th>VERSION</th><th>DB SIZE</th><th>IS LEADER</th><th>IS LEARNER</th><th>RAFT TERM</th><th>RAFT INDEX</th><th>RAFT APPLIED INDEX</th><th>ERRORS</th></tr></thead><tbody><tr><td><a href="http://192.168.154.11:2379/">http://192.168.154.11:2379</a></td><td>1797a0c135947e8d</td><td>3.5.12</td><td>20 kB</td><td>false</td><td>false</td><td>2</td><td>20</td><td>20</td><td></td></tr><tr><td><a href="http://192.168.154.13:2379/">http://192.168.154.13:2379</a></td><td>bbd3763358eec0a1</td><td>3.5.12</td><td>20 kB</td><td>true</td><td>false</td><td>2</td><td>20</td><td>20</td><td></td></tr><tr><td><a href="http://192.168.154.14:2379/">http://192.168.154.14:2379</a></td><td>29834402d195db92</td><td>3.5.12</td><td>20 kB</td><td>false</td><td>false</td><td>2</td><td>20</td><td>20</td><td></td></tr></tbody></table><ol><li>Raft Term:<ul><li>当前节点所在的 Raft 任期编号。</li><li>常见排查：能够通过这个值判断这个ETCD是否稳定。</li></ul></li><li>Raft Index：<ul><li>表示当前节点上已经应用的日志索引号，Raft日志中最新提交位置，证明有东西写入ETCD中</li><li>若是不同节点的这个值相差较大，证明可能存在网络延迟或者节点不健康的情况</li></ul></li><li> Raft Applied Index：</li></ol><ul><li>表示当前节点已经应用的日志条目索引号，已经应用于状态机。</li><li>如果此值明显小于上一个值证明，应用日志存在延迟问题，会产生一些性能瓶颈。</li></ul><ol start="4"><li>Errors：<ul><li>节点存在故障异常</li></ul></li></ol><h3 id="如何让K8S集群使用到这个外部ETCD集群"><a href="#如何让K8S集群使用到这个外部ETCD集群" class="headerlink" title="如何让K8S集群使用到这个外部ETCD集群"></a>如何让K8S集群使用到这个外部ETCD集群</h3><h4 id="再补充一些正式的的一些注意事项"><a href="#再补充一些正式的的一些注意事项" class="headerlink" title="再补充一些正式的的一些注意事项"></a>再补充一些正式的的一些注意事项</h4><ul><li>需要注意的是，etcd集群的每一个节点都需要一个统一的ca进行签发，不然不统一后面kubernetes集群连接的时候可能会出现问题。其次在所有的pem进行移动到其他节点的操作，可能会存在pem过于暴露的提示，这个时候就需要进行一定的授权。</li></ul><p>ps:证书公私钥的拷贝移动个人是觉得比较危险的行为，但是好像我暂时没有发现什么新的办法去解决。</p><ol><li><p>这里的意思是说，先在一个节点创建一个ca-config和ca-csr的json然后签发统一的cd然后拷贝分发到其他的节点，其他节点再用这个分发来的ca进行etcd的证书创建。</p></li><li><p>所以你可以为了方便，在克隆之前先颁发ca.pem,ca-key.pem和定义ca-config.json和ca-csr.json等操作</p></li><li><p>理论上在kubernentes使用外部etcd的时候只需要进行用统一ca证书配置的pem即可。</p></li></ol><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240902103651225.png" alt="image-20240902103651225"></p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240902103705259.png" alt="image-20240902103705259"></p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240902103821289.png" alt="image-20240902103821289"></p><h3 id="常见问题-1"><a href="#常见问题-1" class="headerlink" title="常见问题"></a>常见问题</h3><h4 id="证书配置"><a href="#证书配置" class="headerlink" title="证书配置"></a>证书配置</h4><ul><li>证书最好由统一的ca根证书颁发，然后用统一的json进行签发。</li></ul><h4 id="配置文件格式问题"><a href="#配置文件格式问题" class="headerlink" title="配置文件格式问题"></a>配置文件格式问题</h4><ul><li><p>最好注意service的排版格式以及配置config的排版格式，以及证书的路径位置</p></li><li><p>这里需要非常注意到是，证书签发后，上面涉及到的环境变量问题需要改成https并且在查看集群情况的时候你需要带上你的证书参书</p></li></ul><h4 id="靠谱的证书签发过程-（个人过程，不要直接黏贴）"><a href="#靠谱的证书签发过程-（个人过程，不要直接黏贴）" class="headerlink" title="靠谱的证书签发过程,（个人过程，不要直接黏贴）"></a>靠谱的证书签发过程,（个人过程，不要直接黏贴）</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 这里是有准备ansible工具,删除集群信息。</span></span><br><span class="line">ansible etcd -m shell -a <span class="string">&#x27;rm -rf /var/lib/etcd/member&#x27;</span></span><br><span class="line"><span class="comment"># 签发证书，参考下面,其次你需要把之前的环境变量清楚掉改成https，然后把目录上的证书也expost到环境中。然后就可以了。</span></span><br></pre></td></tr></table></figure><h4 id="提供环境变量的名字"><a href="#提供环境变量的名字" class="headerlink" title="提供环境变量的名字"></a>提供环境变量的名字</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">export</span> ETCDCTL_ENDPOINTS=<span class="string">&quot;https://192.168.154.11:2379,https://192.168.154.13:2379,https://192.168.154.14:2379&quot;</span></span><br><span class="line"><span class="built_in">export</span> ETCDCTL_CACERT=<span class="string">&quot;/etc/etcd/pki/ca/pem&quot;</span></span><br><span class="line"><span class="built_in">export</span> ETCDCTL_CERT=<span class="string">&quot;/etc/etcd/pki/etcd-client.pem&quot;</span></span><br><span class="line"><span class="built_in">export</span> ETCDCTL_KEY=<span class="string">&quot;/etc/etcd/pki/etcd-client-key.pem&quot;</span></span><br><span class="line"><span class="built_in">export</span> ETCDCTL_SKIP_TLS_VERIFY=<span class="literal">true</span></span><br><span class="line"><span class="comment"># 清除环境变量</span></span><br><span class="line"><span class="built_in">unset</span> xxx</span><br><span class="line"><span class="comment"># 搜寻环境变量</span></span><br><span class="line"><span class="built_in">env</span> | grep ETCDCTL</span><br></pre></td></tr></table></figure><h3 id="证书生成"><a href="#证书生成" class="headerlink" title="证书生成"></a>证书生成</h3><p>根据你的命令记录，以下是生成 <code>etcd</code> 集群所需证书的完整步骤。这个过程包括创建自签名的 CA 证书，以及为 <code>etcd</code> 服务器、客户端、和 peer 节点生成相关证书。</p><h4 id="生产证书的步骤"><a href="#生产证书的步骤" class="headerlink" title="生产证书的步骤"></a>生产证书的步骤</h4><p>首先，为 <code>etcd</code> 集群生成一个自签名的 CA 证书，用于签署其他的 <code>etcd</code> 组件证书。</p><ul><li><p>创建 CA 配置文件 <code>ca-config.cnf</code>（可以包含基本配置信息）。</p></li><li><p>生成 CA 的私钥 <code>ca-key.pem</code>：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">openssl genrsa -out ca-key.pem 4096</span><br></pre></td></tr></table></figure></li><li><p>使用 CA 私钥生成自签名的 CA 证书 <code>ca.pem</code>：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">openssl req -x509 -new -nodes -key ca-key.pem -sha256 -days 3650 -out ca.pem -config ca-config.cnf</span><br></pre></td></tr></table></figure></li></ul><h4 id="2-为-etcd-Peer-节点生成证书"><a href="#2-为-etcd-Peer-节点生成证书" class="headerlink" title="2. 为 etcd Peer 节点生成证书"></a>2. 为 etcd Peer 节点生成证书</h4><p>Peer 证书用于 <code>etcd</code> 节点之间的通信。</p><ul><li><p>创建 Peer CSR 配置文件 <code>etcd-peer-csr.cnf</code>。</p></li><li><p>生成 Peer 节点的私钥 <code>etcd-peer-key.pem</code>：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">openssl genrsa -out etcd-peer-key.pem 2048</span><br></pre></td></tr></table></figure></li><li><p>创建 Peer 节点的证书签名请求 <code>etcd-peer.csr</code>：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">openssl req -new -key etcd-peer-key.pem -out etcd-peer.csr -config etcd-peer-csr.cnf</span><br></pre></td></tr></table></figure></li><li><p>使用 CA 证书和私钥签署 Peer 证书 <code>etcd-peer.pem</code>：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">openssl x509 -req -<span class="keyword">in</span> etcd-peer.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out etcd-peer.pem -days 365 -extensions req_ext -extfile etcd-peer-csr.cnf</span><br></pre></td></tr></table></figure></li></ul><h4 id="3-为-etcd-服务器生成证书"><a href="#3-为-etcd-服务器生成证书" class="headerlink" title="3. 为 etcd 服务器生成证书"></a>3. 为 etcd 服务器生成证书</h4><p>服务器证书用于 <code>etcd</code> 节点与客户端的通信。</p><ul><li><p>创建服务器 CSR 配置文件 <code>etcd-server-csr.cnf</code>。</p></li><li><p>生成服务器的私钥 <code>etcd-server-key.pem</code>：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">openssl genrsa -out etcd-server-key.pem 2048</span><br></pre></td></tr></table></figure></li><li><p>创建服务器证书签名请求 <code>etcd-server.csr</code>：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">openssl req -new -key etcd-server-key.pem -out etcd-server.csr -config etcd-server-csr.cnf</span><br></pre></td></tr></table></figure></li><li><p>使用 CA 证书和私钥签署服务器证书 <code>etcd-server.pem</code>：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">openssl x509 -req -<span class="keyword">in</span> etcd-server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out etcd-server.pem -days 365 -extensions req_ext -extfile etcd-server-csr.cnf</span><br></pre></td></tr></table></figure></li></ul><h4 id="4-为-etcd-客户端生成证书"><a href="#4-为-etcd-客户端生成证书" class="headerlink" title="4. 为 etcd 客户端生成证书"></a>4. 为 etcd 客户端生成证书</h4><p>客户端证书用于 <code>etcdctl</code> 等客户端工具与 <code>etcd</code> 集群的安全通信。</p><ul><li><p>创建客户端 CSR 配置文件 <code>etcd-client-csr.cnf</code>。</p></li><li><p>生成客户端的私钥 <code>etcd-client-key.pem</code>：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">openssl genrsa -out etcd-client-key.pem 2048</span><br></pre></td></tr></table></figure></li><li><p>创建客户端证书签名请求 <code>etcd-client.csr</code>：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">openssl req -new -key etcd-client-key.pem -out etcd-client.csr -config etcd-client-csr.cnf</span><br></pre></td></tr></table></figure></li><li><p>使用 CA 证书和私钥签署客户端证书 <code>etcd-client.pem</code>：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">openssl x509 -req -<span class="keyword">in</span> etcd-client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out etcd-client.pem -days 365 -extensions req_ext -extfile etcd-client-csr.cnf</span><br></pre></td></tr></table></figure></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;Start&quot;&gt;&lt;a href=&quot;#Start&quot; class=&quot;headerlink&quot; title=&quot;Start&quot;&gt;&lt;/a&gt;Start&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;需要提前把前提步骤完成，可以参考&lt;a href=&quot;https://blog.kalyan.life/20</summary>
      
    
    
    
    <category term="kubernetes" scheme="https://kalyan-zitiu.github.io/categories/kubernetes/"/>
    
    <category term="etcd" scheme="https://kalyan-zitiu.github.io/categories/kubernetes/etcd/"/>
    
    
    <category term="kubernetes" scheme="https://kalyan-zitiu.github.io/tags/kubernetes/"/>
    
    <category term="etcd" scheme="https://kalyan-zitiu.github.io/tags/etcd/"/>
    
  </entry>
  
  <entry>
    <title>MySQL MGR &amp;&amp; Master - Slave 基本原理以及工作流程</title>
    <link href="https://kalyan-zitiu.github.io/2024/08/12/MySQL_Group_Replication%EF%BC%88MGR%E6%A8%A1%E5%BC%8F%EF%BC%89%E5%8E%9F%E7%90%86%E4%BB%A5%E5%8F%8A%E6%90%AD%E5%BB%BA/"/>
    <id>https://kalyan-zitiu.github.io/2024/08/12/MySQL_Group_Replication%EF%BC%88MGR%E6%A8%A1%E5%BC%8F%EF%BC%89%E5%8E%9F%E7%90%86%E4%BB%A5%E5%8F%8A%E6%90%AD%E5%BB%BA/</id>
    <published>2024-08-12T01:14:17.000Z</published>
    <updated>2024-08-12T03:02:10.240Z</updated>
    
    <content type="html"><![CDATA[<h3 id="相似"><a href="#相似" class="headerlink" title="相似"></a>相似</h3><ul><li>都是为了高可用以及高扩展而存在的模式。</li></ul><h3 id="共识算法Paxos"><a href="#共识算法Paxos" class="headerlink" title="共识算法Paxos"></a>共识算法Paxos</h3><ul><li>分布式系统领域经典的共识算法有很多，如Raft和paxos，这一次我们先详细了解Paxox</li></ul><h4 id="Paoxs解决的问题"><a href="#Paoxs解决的问题" class="headerlink" title="Paoxs解决的问题"></a>Paoxs解决的问题</h4><ul><li>Paxos主要解决在一个由多个节点（或服务器）组成的分布式系统中，如何确保这些节点在面对网络延迟、节点故障或分区等不确定性情况下，能够对某一个值达成一致。</li></ul><h4 id="Paxos基本原理"><a href="#Paxos基本原理" class="headerlink" title="Paxos基本原理"></a>Paxos基本原理</h4><ul><li>Paxos算法分为基本Paxos和多Paxos两种变体。</li></ul><h5 id="基本Paxos"><a href="#基本Paxos" class="headerlink" title="基本Paxos"></a>基本Paxos</h5><ul><li>提议者 (Proposer) 发起提案，提出一个编号和值，希望获得多数接受者的同意。</li><li>接受者 (Acceptor) 对提案进行投票，并根据之前已经接受的提案决定是否同意新的提案。</li><li>学习者 (Learner) 观察已经被多数接受者接受的提案，最终学习到共识值</li></ul><h6 id="基本Paxos阶段"><a href="#基本Paxos阶段" class="headerlink" title="基本Paxos阶段"></a>基本Paxos阶段</h6><p>Prepare 阶段：<br>提议者选择一个提案编号 n，向所有接受者发送 Prepare(n) 请求。<br>每个接受者在收到 Prepare(n) 请求后，如果 n 大于其之前响应过的所有提案编号，则承诺不再接受编号小于 n 的提案，并返回其已经接受的提案及其编号。</p><p>Accept 阶段：<br>提议者在收到多数接受者的响应后，选择最高编号的提案值（如果有），并发送 Accept(n, v) 请求，其中 v 是被选择的提案值或提议者自己的新值。<br>接受者在收到 Accept(n, v) 请求后，如果尚未承诺接受比 n 更大的编号，则接受该提</p><h5 id="Multi-Paxos"><a href="#Multi-Paxos" class="headerlink" title="Multi-Paxos"></a>Multi-Paxos</h5><p>  多Paxos是Paxos协议的一个扩展和优化，用于在分布式系统中处理多个值的共识问题。它通过将多个共识实例串联在一起，提高了效率，使得在一组节点中可以连续不断地达成多个值的共识。</p><ul><li><p>在多Paxos中，提议者通常是固定的，这个固定的提议者称为领导（Leader）。领导者负责发起提案，并在一段时间内主导多个共识实例。</p></li><li><p>多Paxos的每一个提案编号 n 对应于一个特定的共识实例。这样，领导者只需要在初次选举时进行Prepare阶段的操作，后续的提案就可以直接进入Accept阶段，大幅减少了通信轮次。</p></li></ul><h6 id="具体优化"><a href="#具体优化" class="headerlink" title="具体优化"></a>具体优化</h6><ul><li>领导者选举：在多Paxos中，系统首先通过Paxos协议选出一个领导者。领导者负责在它的任期内发起多个提案。在每个共识实例中，领导者只需进行Accept阶段操作。</li><li>省略Prepare阶段：一旦领导者被选定且多数接受者同意，它可以直接在每个共识实例中发起</li><li>Accept请求，而无需每次都从Prepare阶段开始。管道化：多Paxos可以支持管道化操作，即允许多个提案同时进行，以提高吞吐量。</li></ul><h3 id="MySQL-Group-Replication"><a href="#MySQL-Group-Replication" class="headerlink" title="MySQL Group Replication"></a>MySQL Group Replication</h3><h4 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h4><ul><li><p><strong>多主架构：</strong> MGR是一个多主复制解决方案，允许多个节点同时接收和处理写操作。每个节点都可以处理读写请求，这样系统可以实现高可用性和负载均衡。</p></li><li><p><strong>一致性协议：</strong> MGR使用Paxos或Raft等一致性协议来确保多个节点之间的数据一致性。每次事务提交时，都会在组内传播，并通过一致性协议来决定事务是否提交成功。</p></li><li><p><strong>自动故障转移：</strong> 如果一个节点出现故障，MGR可以自动检测并将其从组中移除，同时其他节点继续提供服务。系统可以自动将新节点加入到复制组中，实现自动化管理。</p></li><li><p><strong>读写分离：</strong> 由于每个节点都可以接受写操作，因此在实现高可用性的同时，也具备一定的扩展能力。不过，通常建议设置部分节点为读专用，以分散负载。</p></li></ul><h4 id="流程架构"><a href="#流程架构" class="headerlink" title="流程架构"></a>流程架构</h4><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/20740860-0086f93ae7e5d638.jpg" alt="img"></p><ol><li>Execute (执行)<br>Master 1: 开始执行某个事务。这个操作是在本地节点上执行的，但尚未传播到其他节点。</li><li>Certify (认证)<br>所有参与共识的节点（Master 1、Master 2、Master 3）都会对事务进行认证。认证的目的是确保当前事务不会与其他事务产生冲突。这一步是基于全局事务顺序（GTS）来实现的。<br>Master 1: 在本地节点上执行完事务后，会将其传递给其他节点进行认证。其他节点在收到这个事务后也会进行认证。</li><li>Relay Log (中继日志)<br>Master 2 和 Master 3: 在认证通过后，将事务记录到中继日志中。这一步是为了确保即使发生故障，也能够在恢复时继续执行未完成的事务。</li><li>Apply (应用)<br>Master 2 和 Master 3: 将中继日志中的事务应用到本地数据库中。这个步骤是将接收到的事务内容真正写入到数据库，从而保持与其他节点的数据一致性。</li><li>Binlog (二进制日志)<br>所有的 Master 节点在成功应用事务后，会将事务记录到二进制日志中（Binlog）。二进制日志记录了所有数据更改，通常用于数据恢复、复制等场景。</li><li>Commit (提交)<br>最后，所有 Master 节点都会将事务提交，正式结束这次事务处理。事务在所有节点上达成一致后，才会进行最终提交，这样可以确保整个集群的一致性。</li></ol><h4 id="使用限制"><a href="#使用限制" class="headerlink" title="使用限制"></a>使用限制</h4><ol><li>事务一致性<br>MySQL MGR 强制要求使用 InnoDB 存储引擎，因为它支持事务和行级锁。<br>不支持非事务性存储引擎（如 MyISAM），使用这些引擎的表不会被复制，从而导致数据不一致。</li><li>全局事务标识符（GTID）<br>MySQL MGR 依赖 GTID 进行复制，因此在配置时必须启用 GTID（gtid_mode=ON）。<br>不能在同一个实例上同时使用 MGR 和传统的基于二进制日志的复制。</li><li>表的主键<br>表中必须有主键或唯一索引，MGR 依赖这些来确保数据一致性和避免冲突。<br>没有主键的表可能导致冲突检测机制失效，进而造成数据不一致。</li><li>写入冲突<br>多主模式下，多个节点可以同时写入数据，可能会产生写入冲突。MGR 通过冲突检测机制解决这些冲突，但在高并发情况下，可能影响性能或导致事务回滚。</li><li>网络延迟和分区<br>MGR 对网络延迟敏感，延迟较高时可能会影响复制的性能。<br>在网络分区的情况下，MGR 可能会分裂为多个子组，这可能会导致服务不可用或数据不一致。</li><li>兼容性限制<br>MGR 不支持部分 MySQL 特性，例如：<br>不支持外部锁（例如 LOCK TABLES 和 FLUSH TABLES WITH READ LOCK）。<br>不支持临时表的跨节点复制。<br>不支持在不同模式下（READ_WRITE, READ_ONLY, OFF）进行组内成员角色的动态切换。</li><li>资源消耗<br>由于 MGR 需要维护组内成员的一致性，尤其在多主模式下，资源消耗（如 CPU 和内存）比传统主从复制要高。<br>在大数据量高并发写入的场景下，可能会影响性能，必须注意容量规划。</li></ol><h3 id="MySQL-Master-Slave"><a href="#MySQL-Master-Slave" class="headerlink" title="MySQL Master-Slave"></a>MySQL Master-Slave</h3><h4 id="原理："><a href="#原理：" class="headerlink" title="原理："></a>原理：</h4><ol><li><strong>单主多从架构：</strong> 在Master-Slave模式中，一个数据库作为主库（Master），其他数据库作为从库（Slave）。所有写操作都由主库处理，而从库只接收来自主库的复制日志进行更新。</li><li><strong>异步复制：</strong> 通常情况下，从库以异步方式从主库获取更新。主库完成写操作后，立即返回给客户端，从库稍后复制这些更新。这种模式下，从库的数据可能会有短暂的延迟。<strong>异步复制是mysql默认的复制方式，主库写入binlog即可成功后返回给客户端，不等待binlog日志传递的过程，如果主库宕机，就有可能会出现丢失数据的情况。</strong></li><li><strong>半同步复制</strong>：加了数据的安全性。因为主库在提交事务前确保至少一个从库已经接收并应用了该事务，从而降低了主库故障时数据丢失的风险。坏处也有由于主库在提交事务之前需要等待从库的 ACK，增加了事务的等待时间，这可能会对性能产生一定影响。如果从库的响应速度较慢，或者网络延迟较大，都会导致主库提交事务的时间延长。</li><li><strong>手动故障切换：</strong> 当主库故障时，需要手动将其中一个从库提升为主库，并重新配置其他从库指向新的主库。这通常需要借助外部工具或手动操作来完成。</li><li><strong>读写分离：</strong> 通过配置读写分离，客户端可以将读请求发送到从库，而写请求发送到主库，从而减轻主库的负载。</li></ol><h4 id="流程架构之异步复制"><a href="#流程架构之异步复制" class="headerlink" title="流程架构之异步复制"></a>流程架构之异步复制</h4><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240812102902244.png" alt="image-20240812102902244"></p><h5 id="Master-端的操作"><a href="#Master-端的操作" class="headerlink" title="Master 端的操作"></a>Master 端的操作</h5><p>Binlog（Binary Log）：<br>主服务器（Master）在处理写操作（如 INSERT、UPDATE、DELETE 等）时，会将这些操作记录在二进制日志（Binlog）中。二进制日志是一个顺序写入的文件，记录了所有对数据库进行更改的 SQL 语句，这些语句将用于在从服务器上重放。</p><p>Dump：<br>在主服务器上，Dump 线程负责从 Binlog 中读取这些变化，并将其发送给请求同步数据的从服务器（Slave）。这个线程会持续运行</p><h5 id="Slave-端的操作"><a href="#Slave-端的操作" class="headerlink" title="Slave 端的操作"></a>Slave 端的操作</h5><p>IO Thread（IO 线程）：<br>从服务器上有一个 IO 线程，它向主服务器发送请求，要求主服务器发送新的 Binlog 数据。IO 线程接收到主服务器发送的二进制日志更新后，会将其写入到本地的中继日志（Relay Log）中。</p><p>Relay Log（中继日志）：<br>中继日志是从服务器上的一个临时存储区域，用于保存从主服务器接收到的二进制日志数据。这个日志可以被视为主服务器 Binlog 的本地副本。</p><p>SQL Thread（SQL 线程）：<br>从服务器上的 SQL 线程负责从中继日志中读取 SQL 语句并在从服务器上执行这些语句。这些 SQL 语句是从主服务器同步过来的，执行这些语句的目的是让从服务器的数据库状态与主服务器保持一致。</p><h4 id="流程架构之半同步复制"><a href="#流程架构之半同步复制" class="headerlink" title="流程架构之半同步复制"></a>流程架构之半同步复制</h4><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240812103919203.png" alt="image-20240812103919203"></p><h3 id="MySQL-半同步复制工作原理"><a href="#MySQL-半同步复制工作原理" class="headerlink" title="MySQL 半同步复制工作原理"></a>MySQL 半同步复制工作原理</h3><h4 id="1-主库执行事务-Execute-："><a href="#1-主库执行事务-Execute-：" class="headerlink" title="1. **主库执行事务 (Execute)**："></a>1. **主库执行事务 (Execute)**：</h4><ul><li>当主库（Master）接收到一个写操作时，首先会在主库上执行这个事务。此时，事务被记录在主库的二进制日志（Binlog）中。</li></ul><h4 id="2-生成-Binlog-并发送给从库-Binlog-："><a href="#2-生成-Binlog-并发送给从库-Binlog-：" class="headerlink" title="2. **生成 Binlog 并发送给从库 (Binlog)**："></a>2. **生成 Binlog 并发送给从库 (Binlog)**：</h4><ul><li>主库在执行事务后，会将该事务生成的二进制日志（Binlog）发送给所有配置了半同步复制的从库（Slave）。</li></ul><h4 id="3-从库接收并写入中继日志-Relay-Log-："><a href="#3-从库接收并写入中继日志-Relay-Log-：" class="headerlink" title="3. **从库接收并写入中继日志 (Relay Log)**："></a>3. **从库接收并写入中继日志 (Relay Log)**：</h4><ul><li>从库接收到主库发送的 Binlog 后，将其写入到中继日志（Relay Log）中。</li></ul><h4 id="4-从库应用日志-Apply-："><a href="#4-从库应用日志-Apply-：" class="headerlink" title="4. **从库应用日志 (Apply)**："></a>4. **从库应用日志 (Apply)**：</h4><ul><li>从库将中继日志中的内容应用到本地数据库，完成对数据的更新。</li></ul><h4 id="5-从库返回-ACK："><a href="#5-从库返回-ACK：" class="headerlink" title="5. 从库返回 ACK："></a>5. <strong>从库返回 ACK</strong>：</h4><ul><li>在从库成功应用完日志后，会发送一个确认信号（ACK）给主库。这个步骤确保了主库知道至少有一个从库已经成功应用了该事务。</li></ul><h4 id="6-主库提交事务-Commit-："><a href="#6-主库提交事务-Commit-：" class="headerlink" title="6. **主库提交事务 (Commit)**："></a>6. **主库提交事务 (Commit)**：</h4><ul><li>主库在收到至少一个从库的 ACK 后，才会正式提交该事务。这就是“半同步”复制的关键点：主库确保至少有一个从库成功接收并应用了事务后，才认为事务提交成功。</li></ul><h4 id="7-主库继续处理其他事务："><a href="#7-主库继续处理其他事务：" class="headerlink" title="7. 主库继续处理其他事务："></a>7. <strong>主库继续处理其他事务</strong>：</h4><ul><li>在事务提交之后，主库可以继续处理后续的事务操作。</li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;相似&quot;&gt;&lt;a href=&quot;#相似&quot; class=&quot;headerlink&quot; title=&quot;相似&quot;&gt;&lt;/a&gt;相似&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;都是为了高可用以及高扩展而存在的模式。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;共识算法Paxos&quot;&gt;&lt;a href=&quot;#共识算法</summary>
      
    
    
    
    <category term="Mysql" scheme="https://kalyan-zitiu.github.io/categories/Mysql/"/>
    
    
    <category term="Mysql" scheme="https://kalyan-zitiu.github.io/tags/Mysql/"/>
    
  </entry>
  
  <entry>
    <title>浅聊消息队列中间件-rocketmq</title>
    <link href="https://kalyan-zitiu.github.io/2024/08/08/%E6%B5%85%E8%81%8A%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E4%B8%AD%E9%97%B4%E4%BB%B6-rocketmq/"/>
    <id>https://kalyan-zitiu.github.io/2024/08/08/%E6%B5%85%E8%81%8A%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E4%B8%AD%E9%97%B4%E4%BB%B6-rocketmq/</id>
    <published>2024-08-08T08:40:52.000Z</published>
    <updated>2024-08-08T09:31:28.153Z</updated>
    
    <content type="html"><![CDATA[<h3 id="消息队列RocketMQ"><a href="#消息队列RocketMQ" class="headerlink" title="消息队列RocketMQ"></a>消息队列RocketMQ</h3><ul><li>为什么有了Kafka还是会有其他的的消息队列中间件呢，是因为KafKa不好用吗，并不是的，其实RocketMQ是有参考KafKa进行开发的，总的一句话说就是在<strong>架构上做减法，在功能上做加法</strong></li></ul><h3 id="减法"><a href="#减法" class="headerlink" title="减法"></a>减法</h3><ul><li>RcketMQ在KafKa的架构上除去了过重的Zookeeper分布式协调服务的组件，选择使用了更轻量级的nameserver。为什么要舍弃Zookeeper呢，主要是Zookeeper的功能多样而且强大，在KafKa中使用太过了。后续KafKa的新版本中也舍弃了Zookeeper选择使用了Raft一致性算法进行数据的统一协调。为什么新版本后还是有很多人选择使用RocketMQ呢，第一是新的东西总是有坑，第二就是RocketMQ还有不同KafKa的过人之处。</li></ul><h3 id="相似"><a href="#相似" class="headerlink" title="相似"></a>相似</h3><ul><li>RocketMQ还是和KafKa一样，在不同topic上分不同的Partition，接着就是Broker进行高可用和高扩展，只是不一样的是RocketMQ把partition改名成了Queue</li></ul><h3 id="不同"><a href="#不同" class="headerlink" title="不同"></a>不同</h3><h4 id="消息体的存储位置"><a href="#消息体的存储位置" class="headerlink" title="消息体的存储位置"></a>消息体的存储位置</h4><ul><li>和KafKa不同的是，KafKa在partition中存储的是完整的消息题，而RocketMQ则是在Queue中只存储简要的信息，用来堆消息进行导向，比如offset。而实际的消息体会放在一个commitLog上面进行存储，通过offset来堆消息体进行定位获取。</li></ul><p>@ 小白debug<br><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240808171332666.png" alt="image-20240808171332666"></p><h4 id="持久化磁盘的区别"><a href="#持久化磁盘的区别" class="headerlink" title="持久化磁盘的区别"></a>持久化磁盘的区别</h4><p>因为RocketMQ的消息体是放在一个commitLog里面，自然在写入磁盘时候也是顺序写入，非常通畅</p><h4 id="备份简化"><a href="#备份简化" class="headerlink" title="备份简化"></a>备份简化</h4><ul><li>RocketMQ为了不拆分commitLog干脆把主从副本升级成为了broker的级别，这样就不需要再多个Broker维护主从副本，直接改成了主从Broker。</li></ul><h3 id="加法"><a href="#加法" class="headerlink" title="加法"></a>加法</h3><h4 id="细分类"><a href="#细分类" class="headerlink" title="细分类"></a>细分类</h4><p>RocketMQ做的加法其实就是再Queue再进行细分类上打上tag的标签，比如，我在Queue中的索引某个消息打上vip的标签这样消费者就能够直接获取标签上的offset来获取vip标签。而KafKa则需要再一个partition里面进行筛选最终选出消息体给出消息。</p><h4 id="加入延时队列"><a href="#加入延时队列" class="headerlink" title="加入延时队列"></a>加入延时队列</h4><ul><li>RocketMQ能够使用延时队列，顾名思义就是能够延迟被消费者进行消费的队列消息。</li></ul><h4 id="加入死信队列"><a href="#加入死信队列" class="headerlink" title="加入死信队列"></a>加入死信队列</h4><ul><li>RockerMQ会对重复失败处理的消息放入，专门处理失败的独立Queue队列也就是死信队列。</li></ul><h3 id="附上总图-小白debug"><a href="#附上总图-小白debug" class="headerlink" title="附上总图 @ 小白debug"></a>附上总图 @ 小白debug</h3><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240808171926411.png" alt="image-20240808171926411"></p><h3 id="sum"><a href="#sum" class="headerlink" title="sum"></a>sum</h3><p>看似RocketMQ在KafKa的基础上做了如此多的优化，其实性能却远不及KafKa这又是为什么呢？？？</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;消息队列RocketMQ&quot;&gt;&lt;a href=&quot;#消息队列RocketMQ&quot; class=&quot;headerlink&quot; title=&quot;消息队列RocketMQ&quot;&gt;&lt;/a&gt;消息队列RocketMQ&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;为什么有了Kafka还是会有其他的的消息队列中间</summary>
      
    
    
    
    <category term="中间件" scheme="https://kalyan-zitiu.github.io/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/"/>
    
    
    <category term="中间件" scheme="https://kalyan-zitiu.github.io/tags/%E4%B8%AD%E9%97%B4%E4%BB%B6/"/>
    
  </entry>
  
  <entry>
    <title>浅聊消息队列中间件-kafka</title>
    <link href="https://kalyan-zitiu.github.io/2024/08/08/%E6%B5%85%E8%81%8A%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E4%B8%AD%E9%97%B4%E4%BB%B6-kafka/"/>
    <id>https://kalyan-zitiu.github.io/2024/08/08/%E6%B5%85%E8%81%8A%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E4%B8%AD%E9%97%B4%E4%BB%B6-kafka/</id>
    <published>2024-08-08T06:02:57.000Z</published>
    <updated>2024-08-08T08:48:02.310Z</updated>
    
    <content type="html"><![CDATA[<h3 id="为什么需要中间件消息队列"><a href="#为什么需要中间件消息队列" class="headerlink" title="为什么需要中间件消息队列"></a>为什么需要中间件消息队列</h3><p>  假设你有两台服务器，服务器A不断地发送需要处理的消息给服务器B，但是处理的速度赶不上发送的速度，就会导致消息堆积以至于是服务器B负载升高。要是服务B宕机了存储在内存里面的需要处理的消息就消失了，服务A又不知道导致各种消息没有得到处理后的回应，于是就有了消息队列kafka的诞生，没有什么是不能增加一个中间件解决不了的。</p><h3 id="什么是KafKa"><a href="#什么是KafKa" class="headerlink" title="什么是KafKa"></a>什么是KafKa</h3><p>一种分布式流处理平台，主要用途是构建实时数据流应用和数据管道。</p><h3 id="KafKa的架构"><a href="#KafKa的架构" class="headerlink" title="KafKa的架构"></a>KafKa的架构</h3><ul><li>首先既然是一个中间件，它要是单独的跑一个消息队列进行消息的存储，当消息过多也会造成中间件的崩溃，所以需要一个高性能，高可用，有备份的中间件是必要的。</li></ul><h3 id="KafKa是怎么实现高性能的。"><a href="#KafKa是怎么实现高性能的。" class="headerlink" title="KafKa是怎么实现高性能的。"></a>KafKa是怎么实现高性能的。</h3><ul><li>我们把对参与消息的分为Producer和Consumer，意思就是生产者和消费者，更简单点就是发布消息者和订阅消息者。按自己理解来。</li><li>KafKa是通过消息的分类和分组的方式来区分不同类型的消息，我们管它叫<strong>Topic</strong></li><li>在每一个Topic它又会分为多个Partition，每个Partition能过够被Consumer独立消费</li></ul><p>ps：到以上能够解决了KafKa的性能问题，那么这多的partition在一节点上，要是节点炸了，那么消息一样全没了，所以又引导出高扩展的问题</p><h3 id="KafKa是怎么实现高扩展的"><a href="#KafKa是怎么实现高扩展的" class="headerlink" title="KafKa是怎么实现高扩展的"></a>KafKa是怎么实现高扩展的</h3><ul><li>大佬们是这么解决的，是通过服务器节点，我们把它叫<strong>Broker</strong>，Broker里面可以放不同数量的Partition，所以能够通过添加Broker节点来达到增加Partition，从何提高Topic的性能情况下，减少所有Partition放在同一个节点的方式的高负荷问题，那么要是就算某一个Broker还是因为高负荷坏了，该怎么解决，那么又能引发出高可用的问题</li></ul><h3 id="KafKa是怎么实现高可用"><a href="#KafKa是怎么实现高可用" class="headerlink" title="KafKa是怎么实现高可用"></a>KafKa是怎么实现高可用</h3><ul><li>KafKa是通过子不同的Borker里面存放副本进行高可用的实现，这些副本分为主从，若是主副本的Broker宕机了，那么从副本就会升级为主副本被Consumer消费。现在问题又来了，怎么保证他们每一个Broker之间的通信呢。</li></ul><h3 id="KafKa怎么解决组件之间通信的"><a href="#KafKa怎么解决组件之间通信的" class="headerlink" title="KafKa怎么解决组件之间通信的"></a>KafKa怎么解决组件之间通信的</h3><ul><li>KafKa最后处理组件一致性和通信问题是用了Zookeeper，Zookeeper有着服务发现的功能，能够很好的协调KafKa集群的分布式服务。通信问题解决了。要是在很极端的情况下，所有的高性能高可用以及高扩展出来的东西，还是因为负载过高而全部宕机呢。那么就需要考虑到持久化存储，既然放在内存里面的消息如此不稳定。那么我们就持久化到磁盘里面。</li></ul><h3 id="KafKa的底层存储"><a href="#KafKa的底层存储" class="headerlink" title="KafKa的底层存储"></a>KafKa的底层存储</h3><ul><li>KafKa是对每一个Partiton分区进行顺序写入的操作，Partiton分区下面是实际上是一堆堆segment，顺序写入Partition实际上是顺序把消息写入segment里面。然后再<strong>随机</strong>写入磁盘中，这里为什么要注意随机呢。</li></ul><h4 id="KafKa的持久化存储为什么最终是随机写入磁盘"><a href="#KafKa的持久化存储为什么最终是随机写入磁盘" class="headerlink" title="KafKa的持久化存储为什么最终是随机写入磁盘"></a>KafKa的持久化存储为什么最终是随机写入磁盘</h4><ul><li>众所周知顺序写入磁盘会比随机写入要快很多，那么为什么KafKa明明是对segment顺序写入的，最终还是成为随机呢。</li><li>因为每一堆segment是partition下面的，既然你那么多的partition，所以就会有很多份segment，对于sgement本身虽然是顺序写入，但是对于每一份segment确实随机写入。</li></ul><h3 id="最终附上up：小白debug的总图"><a href="#最终附上up：小白debug的总图" class="headerlink" title="最终附上up：小白debug的总图"></a>最终附上up：小白debug的总图</h3><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240808164328969.png" alt="image-20240808164328969"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;为什么需要中间件消息队列&quot;&gt;&lt;a href=&quot;#为什么需要中间件消息队列&quot; class=&quot;headerlink&quot; title=&quot;为什么需要中间件消息队列&quot;&gt;&lt;/a&gt;为什么需要中间件消息队列&lt;/h3&gt;&lt;p&gt;  假设你有两台服务器，服务器A不断地发送需要处理的消息给服</summary>
      
    
    
    
    <category term="中间件" scheme="https://kalyan-zitiu.github.io/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/"/>
    
    
    <category term="中间件" scheme="https://kalyan-zitiu.github.io/tags/%E4%B8%AD%E9%97%B4%E4%BB%B6/"/>
    
  </entry>
  
  <entry>
    <title>浅解析Containerd</title>
    <link href="https://kalyan-zitiu.github.io/2024/08/07/Containerd/"/>
    <id>https://kalyan-zitiu.github.io/2024/08/07/Containerd/</id>
    <published>2024-08-07T09:51:41.000Z</published>
    <updated>2024-08-08T04:31:40.930Z</updated>
    
    <content type="html"><![CDATA[<h3 id="导言"><a href="#导言" class="headerlink" title="导言"></a>导言</h3><p>最近在集群中遇到了很多containerd的问题，所以不禁思考我真的懂containerd吗？？?</p><h3 id="前提"><a href="#前提" class="headerlink" title="前提"></a>前提</h3><p>本文假设你熟悉了</p><ol><li>CRI的概念 &amp;&amp; gRPC &amp;&amp; socket 参考：<a href="https://blog.kalyan.life/2024/07/04/CRI/">https://blog.kalyan.life/2024/07/04/CRI/</a></li><li>shim垫片概念</li></ol><h3 id="containerd是什么就不说啦"><a href="#containerd是什么就不说啦" class="headerlink" title="containerd是什么就不说啦"></a>containerd是什么就不说啦</h3><h3 id="架构（理解就好，主要在于如何使用，想要研究可以去看源码）"><a href="#架构（理解就好，主要在于如何使用，想要研究可以去看源码）" class="headerlink" title="架构（理解就好，主要在于如何使用，想要研究可以去看源码）"></a>架构（理解就好，主要在于如何使用，想要研究可以去看源码）</h3><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240808100725408.png" alt="image-20240808100725408"></p><h4 id="1-API-层"><a href="#1-API-层" class="headerlink" title="1. API 层"></a>1. API 层</h4><ul><li><strong>gRPC API</strong>: 提供给客户端的 gRPC API，支持包括容器管理、镜像管理、存储管理等操作。</li><li><strong>CRI</strong>: 容器运行时接口，允许 Kubernetes 通过 gRPC API 与 containerd 交互。</li><li><strong>Prometheus</strong>: 用于监控的指标接口，收集和暴露 containerd 的运行时数据。</li></ul><h4 id="2-核心层-Core"><a href="#2-核心层-Core" class="headerlink" title="2. 核心层 (Core)"></a>2. 核心层 (Core)</h4><ul><li><p>Services</p><p>: 包含多种服务，每种服务负责不同的功能模块。</p><ul><li><strong>Containers Service</strong>: 管理容器的生命周期。</li><li><strong>Content Service</strong>: 负责内容管理，处理镜像层的数据。</li><li><strong>Diff Service</strong>: 负责镜像层之间的差异计算。</li><li><strong>Images Service</strong>: 负责镜像的管理。</li><li><strong>Leases Service</strong>: 管理临时资源。</li><li><strong>Namespaces Service</strong>: 提供命名空间支持，隔离不同的容器组。</li><li><strong>Snapshots Service</strong>: 管理快照。</li><li><strong>Tasks Service</strong>: 管理任务的运行。</li></ul></li><li><p>Metadata</p><p>: 提供命名空间支持和元数据管理。</p><ul><li><strong>Containers, Content, Images, Leases, Namespaces, Snapshots</strong>: 各种元数据的管理模块。</li></ul></li></ul><h4 id="3-后端层-Backend"><a href="#3-后端层-Backend" class="headerlink" title="3. 后端层 (Backend)"></a>3. 后端层 (Backend)</h4><ul><li><p><strong>Content Store</strong>: 负责存储内容，可以通过插件和本地存储实现。</p></li><li><p>Snapshotter</p><p>: 管理文件系统的快照。</p><ul><li><strong>overlay, btrfs, devmapper, native, windows, plugin</strong>: 支持多种文件系统和快照技术。</li></ul></li><li><p>Runtime</p><p>: 支持容器运行时。</p><ul><li><strong>runc, runhcs, kata, Firecracker, gVisor, shim</strong>: 支持多种运行时，包括 runc、runhcs、kata containers、Firecracker 和 gVisor。</li><li><strong>v2 shim client</strong>: 每个容器都有一个 shim 进程，隔离容器的生命周期管理，确保容器的独立运行。</li></ul></li></ul><h4 id="4-系统层-System"><a href="#4-系统层-System" class="headerlink" title="4. 系统层 (System)"></a>4. 系统层 (System)</h4><ul><li>支持多种硬件架构和操作系统，包括 ARM、Intel、Windows、Linux。</li></ul><h3 id="简化版"><a href="#简化版" class="headerlink" title="简化版"></a>简化版</h3><ul><li>分为三⼤块：Storage 管理镜像⽂件的存储；Metadata 管理镜像和容器的元数据；另外由 Task<br>触发运⾏时。对外提供 GRPC ⽅式的 API 以及 Metrics 接⼝。</li></ul><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240808102354598.png" alt="image-20240808102354598"></p><h3 id="然后我们讲一下重要的配置文件"><a href="#然后我们讲一下重要的配置文件" class="headerlink" title="然后我们讲一下重要的配置文件"></a>然后我们讲一下重要的配置文件</h3><h4 id="config-toml"><a href="#config-toml" class="headerlink" title="config.toml"></a>config.toml</h4><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240808103459459.png" alt="image-20240808103459459"></p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="string">version</span> <span class="string">=</span> <span class="number">2</span></span><br><span class="line"><span class="comment"># 配置文件版本</span></span><br><span class="line"></span><br><span class="line"><span class="string">root</span> <span class="string">=</span> <span class="string">&quot;/var/lib/containerd&quot;</span></span><br><span class="line"><span class="comment"># containerd 数据存储的根目录</span></span><br><span class="line"></span><br><span class="line"><span class="string">state</span> <span class="string">=</span> <span class="string">&quot;/run/containerd&quot;</span></span><br><span class="line"><span class="comment"># containerd 状态信息存储目录</span></span><br><span class="line"></span><br><span class="line"><span class="string">oom_score</span> <span class="string">=</span> <span class="number">0</span></span><br><span class="line"><span class="comment"># OOM（Out of Memory）分数调整值，用于内存不足时的优先级</span></span><br><span class="line"></span><br><span class="line">[<span class="string">grpc</span>]</span><br><span class="line"><span class="comment"># gRPC 配置部分</span></span><br><span class="line"></span><br><span class="line">  <span class="string">max_recv_message_size</span> <span class="string">=</span> <span class="number">16777216</span></span><br><span class="line">  <span class="comment"># gRPC 最大接收消息大小</span></span><br><span class="line"></span><br><span class="line">  <span class="string">max_send_message_size</span> <span class="string">=</span> <span class="number">16777216</span></span><br><span class="line">  <span class="comment"># gRPC 最大发送消息大小</span></span><br><span class="line"></span><br><span class="line">[<span class="string">debug</span>]</span><br><span class="line"><span class="comment"># 调试配置部分</span></span><br><span class="line"></span><br><span class="line">  <span class="string">level</span> <span class="string">=</span> <span class="string">&quot;info&quot;</span></span><br><span class="line">  <span class="comment"># 日志级别，info 表示信息级别日志</span></span><br><span class="line"></span><br><span class="line">[<span class="string">metrics</span>]</span><br><span class="line"><span class="comment"># 指标配置部分</span></span><br><span class="line"></span><br><span class="line">  <span class="string">address</span> <span class="string">=</span> <span class="string">&quot;&quot;</span></span><br><span class="line">  <span class="comment"># 指标服务监听地址，空表示不启用</span></span><br><span class="line"></span><br><span class="line">  <span class="string">grpc_histogram</span> <span class="string">=</span> <span class="literal">false</span></span><br><span class="line">  <span class="comment"># 是否启用 gRPC 直方图</span></span><br><span class="line"></span><br><span class="line">[<span class="string">plugins</span>]</span><br><span class="line"><span class="comment"># 插件配置部分</span></span><br><span class="line"></span><br><span class="line">  [<span class="string">plugins.&quot;io.containerd.grpc.v1.cri&quot;</span>]</span><br><span class="line">  <span class="comment"># CRI 插件配置部分</span></span><br><span class="line"></span><br><span class="line">    <span class="string">sandbox_image</span> <span class="string">=</span> <span class="string">&quot;192.168.154.2/registry.k8s.io/pause:3.9&quot;</span></span><br><span class="line">    <span class="comment"># 沙箱镜像，用于 Pod 的基础镜像</span></span><br><span class="line"></span><br><span class="line">    <span class="string">max_container_log_line_size</span> <span class="string">=</span> <span class="number">-1</span></span><br><span class="line">    <span class="comment"># 容器日志行的最大长度，-1 表示不限制</span></span><br><span class="line"></span><br><span class="line">    <span class="string">enable_unprivileged_ports</span> <span class="string">=</span> <span class="literal">false</span></span><br><span class="line">    <span class="comment"># 是否启用非特权端口</span></span><br><span class="line"></span><br><span class="line">    <span class="string">enable_unprivileged_icmp</span> <span class="string">=</span> <span class="literal">false</span></span><br><span class="line">    <span class="comment"># 是否启用非特权 ICMP</span></span><br><span class="line"></span><br><span class="line">    [<span class="string">plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd</span>]</span><br><span class="line">    <span class="comment"># containerd 相关配置</span></span><br><span class="line"></span><br><span class="line">      <span class="string">default_runtime_name</span> <span class="string">=</span> <span class="string">&quot;runc&quot;</span></span><br><span class="line">      <span class="comment"># 默认运行时名称</span></span><br><span class="line"></span><br><span class="line">      <span class="string">snapshotter</span> <span class="string">=</span> <span class="string">&quot;overlayfs&quot;</span></span><br><span class="line">      <span class="comment"># 默认使用的快照器类型</span></span><br><span class="line"></span><br><span class="line">      <span class="string">discard_unpacked_layers</span> <span class="string">=</span> <span class="literal">true</span></span><br><span class="line">      <span class="comment"># 是否丢弃解包的层</span></span><br><span class="line"></span><br><span class="line">    [<span class="string">plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd.runtimes</span>]</span><br><span class="line">    <span class="comment"># 容器运行时配置部分</span></span><br><span class="line"></span><br><span class="line">      [<span class="string">plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd.runtimes.runc</span>]</span><br><span class="line">      <span class="comment"># runc 运行时配置部分</span></span><br><span class="line"></span><br><span class="line">        <span class="string">runtime_type</span> <span class="string">=</span> <span class="string">&quot;io.containerd.runc.v2&quot;</span></span><br><span class="line">        <span class="comment"># 运行时类型</span></span><br><span class="line"></span><br><span class="line">        <span class="string">runtime_engine</span> <span class="string">=</span> <span class="string">&quot;&quot;</span></span><br><span class="line">        <span class="comment"># 运行时引擎</span></span><br><span class="line"></span><br><span class="line">        <span class="string">runtime_root</span> <span class="string">=</span> <span class="string">&quot;&quot;</span></span><br><span class="line">        <span class="comment"># 运行时根目录</span></span><br><span class="line"></span><br><span class="line">        <span class="string">base_runtime_spec</span> <span class="string">=</span> <span class="string">&quot;/etc/containerd/cri-base.json&quot;</span></span><br><span class="line">        <span class="comment"># 基础运行时规格文件</span></span><br><span class="line"></span><br><span class="line">      [<span class="string">plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd.runtimes.runc.options</span>]</span><br><span class="line">      <span class="comment"># runc 运行时选项配置部分</span></span><br><span class="line"></span><br><span class="line">        <span class="string">SystemdCgroup</span> <span class="string">=</span> <span class="literal">true</span></span><br><span class="line">        <span class="comment"># 是否启用 systemd cgroup</span></span><br><span class="line"></span><br><span class="line">        <span class="string">BinaryName</span> <span class="string">=</span> <span class="string">&quot;/usr/local/bin/runc&quot;</span></span><br><span class="line">        <span class="comment"># runc 二进制文件路径</span></span><br><span class="line"></span><br><span class="line">    [<span class="string">plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry</span>]</span><br><span class="line">    <span class="comment"># 镜像仓库配置部分</span></span><br><span class="line"></span><br><span class="line">      [<span class="string">plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.mirrors</span>]</span><br><span class="line">      <span class="comment"># 镜像仓库镜像配置部分</span></span><br><span class="line"></span><br><span class="line">        [<span class="string">plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.mirrors.&quot;192.168.154.2&quot;</span>]</span><br><span class="line">        <span class="comment"># 指定的镜像仓库</span></span><br><span class="line">          <span class="string">endpoint</span> <span class="string">=</span> [<span class="string">&quot;https://192.168.154.2&quot;</span>]</span><br><span class="line">          <span class="comment"># 镜像仓库的端点 URL</span></span><br><span class="line"></span><br><span class="line">      [<span class="string">plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.configs.&quot;192.168.154.2&quot;.tls</span>]</span><br><span class="line">      <span class="comment"># 镜像仓库 TLS 配置部分</span></span><br><span class="line"></span><br><span class="line">        <span class="string">insecure_skip_verify</span> <span class="string">=</span> <span class="literal">true</span></span><br><span class="line">        <span class="comment"># 是否跳过 TLS 证书验证</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="值得注意的是这里的镜像仓库有两种加载方式-到了2-0版本就可以用"><a href="#值得注意的是这里的镜像仓库有两种加载方式-到了2-0版本就可以用" class="headerlink" title="值得注意的是这里的镜像仓库有两种加载方式,到了2.0版本就可以用"></a>值得注意的是这里的镜像仓库有两种加载方式,到了2.0版本就可以用</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">[plugins.<span class="string">&quot;io.containerd.grpc.v1.cri&quot;</span>.registry]</span><br><span class="line">config_path= <span class="string">&quot;/etc/containerd/certs.d&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 然后再certs.d目录下面添加你的镜像仓库就好了.</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="run-containerd-里面的是什么"><a href="#run-containerd-里面的是什么" class="headerlink" title="/run/containerd/里面的是什么"></a>/run/containerd/里面的是什么</h3><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240808111628400.png" alt="image-20240808111628400"></p><ol><li><strong>containerd.sock</strong>:</li></ol><ul><li>这是 containerd 的主 Unix socket 文件，用于与 containerd 守护进程进行通信。客户端（例如 Docker 或 Kubernetes）通过这个 socket 文件发送管理指令。</li></ul><ol start="2"><li><strong>containerd.sock.ttrpc</strong>:</li></ol><ul><li>这是 containerd 用于 ttrpc（Tiny Transport RPC）通信的 socket 文件。ttrpc 是一种轻量级的 RPC 框架，用于在性能敏感的环境中提供高效的进程间通信。</li></ul><ol start="3"><li><strong>io.containerd.grpc.v1.cri</strong>:</li></ol><ul><li>这个目录包含与 Kubernetes CRI（Container Runtime Interface）集成相关的 socket 文件和配置。containerd 支持 CRI，使得 Kubernetes 可以直接通过 containerd 来管理容器。</li></ul><ol start="4"><li><strong>io.containerd.runtime.v1.linux</strong>:</li></ol><ul><li>这个目录包含与 v1 版本的 containerd 运行时相关的文件和配置，主要用于 Linux 系统上的容器管理。</li></ul><ol start="5"><li><strong>io.containerd.runtime.v2.task</strong>:</li></ol><ul><li>这个目录包含与 v2 版本的 containerd 任务管理相关的文件和配置。v2 版本引入了一些新的特性和改进，用于更高效地管理容器任务。</li></ul><ol start="6"><li><strong>runc</strong>:</li></ol><ul><li>这是 runc 运行时的目录。runc 是一个 CLI 工具，用于根据 OCI（Open Container Initiative）规范创建和运行容器。containerd 使用 runc 作为默认的容器运行时。</li></ul><ol start="7"><li><strong>s</strong>:</li></ol><ul><li>这个目录的具体用途可能需要根据系统的实际配置来确定。它可能是用于存储临时文件、状态文件或特定插件的目录。</li></ul><h3 id="var-lib-containerd-里面的是什么"><a href="#var-lib-containerd-里面的是什么" class="headerlink" title="/var/lib/containerd 里面的是什么"></a>/var/lib/containerd 里面的是什么</h3><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240808113725285.png" alt="image-20240808113725285"></p><ol><li><strong>io.containerd.content.v1.content:</strong></li></ol><ul><li>存储镜像和容器层的内容，包括所有下载的镜像数据。这里的文件通常以内容地址（例如 SHA256 哈希）进行命名和存储。</li></ul><ol start="2"><li><strong>io.containerd.snapshotter.v1.overlayfs:</strong></li></ol><ul><li>这是一个与文件系统快照相关的目录，特别是使用 OverlayFS 作为存储后端时。这个目录包含快照和层的数据，用于构建和管理容器的文件系统层。</li></ul><ol start="3"><li><strong>io.containerd.snapshotter.v1.btrfs:</strong></li></ol><ul><li>类似于 overlayfs 目录，但用于 Btrfs 文件系统。它存储使用 Btrfs 作为存储后端时的快照和层的数据。</li></ul><ol start="4"><li><strong>io.containerd.snapshotter.v1.devmapper:</strong> </li></ol><ul><li>用于 Device Mapper 存储后端的快照数据，存储容器层的信息。</li></ul><ol start="5"><li><strong>io.containerd.grpc.v1.cri:</strong></li></ol><ul><li>包含与 Kubernetes CRI 集成相关的数据和配置。Kubernetes 通过这个目录与 containerd 进行通信和数据交换。</li></ul><ol start="6"><li><strong>tmpmounts:</strong></li></ol><ul><li>临时挂载点目录，用于存储容器运行时的临时文件和挂载点信息。</li></ul><h3 id="命令工具"><a href="#命令工具" class="headerlink" title="命令工具"></a>命令工具</h3><h4 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h4><table><thead><tr><th>命令</th><th>描述</th><th>docker</th><th>ctr</th><th>crictl</th><th>nerdctl</th></tr></thead><tbody><tr><td>显示镜像列表</td><td>显示本地主机上的镜像列表</td><td>docker images</td><td>ctr images list</td><td>crictl images</td><td>nerdctl images list</td></tr><tr><td>下载镜像</td><td>从 registry 中下载指定的镜像</td><td>docker pull</td><td>ctr images pull</td><td>crictl pull</td><td>nerdctl pull</td></tr><tr><td>上传镜像</td><td>将本地的镜像上传到 registry</td><td>docker push</td><td>ctr images push</td><td>不支持</td><td>nerdctl images push</td></tr></tbody></table><h4 id="其他命令"><a href="#其他命令" class="headerlink" title="其他命令"></a>其他命令</h4><table><thead><tr><th>命令</th><th>描述</th><th>docker</th><th>ctr</th><th>crictl</th><th>nerdctl</th></tr></thead><tbody><tr><td>删除镜像</td><td>删除指定的镜像</td><td>docker rmi</td><td>ctr images remove/delete</td><td>crictl rmi</td><td>nerdctl rmi</td></tr><tr><td>启动容器</td><td>创建并启动容器</td><td>docker run</td><td>ctr run</td><td>crictl run</td><td>nerdctl run</td></tr><tr><td>显示容器列表</td><td>显示本地主机上的容器列表</td><td>docker ps</td><td>ctr tasks ls</td><td>crictl ps</td><td>nerdctl ps</td></tr><tr><td>显示容器详情</td><td>显示容器的详细信息</td><td>docker inspect</td><td>ctr task info</td><td>crictl inspect</td><td>nerdctl inspect</td></tr><tr><td>停止容器</td><td>停止容器的运行</td><td>docker stop</td><td>ctr task kill</td><td>crictl stop</td><td>nerdctl stop</td></tr><tr><td>删除容器</td><td>删除指定的容器</td><td>docker rm</td><td>ctr task delete</td><td>crictl rm</td><td>nerdctl delete</td></tr><tr><td>进入容器</td><td>进入正在运行的容器</td><td>docker exec</td><td>ctr task exec</td><td>crictl exec</td><td>nerdctl exec</td></tr><tr><td>查看容器日志</td><td>显示容器的日志输出</td><td>docker logs</td><td>ctr task logs</td><td>crictl logs</td><td>nerdctl logs</td></tr><tr><td>导出容器</td><td>导出容器文件系统为 tar 包</td><td>docker export</td><td>ctr task export</td><td>不支持</td><td>nerdctl export</td></tr><tr><td>导入容器</td><td>从导出的 tar 包创建一个新的容器</td><td>docker import</td><td>ctr image import</td><td>不支持</td><td>nerdctl import</td></tr><tr><td>构建镜像</td><td>从 Dockerfile 构建镜像</td><td>docker build</td><td>不支持</td><td>不支持</td><td>nerdctl build</td></tr><tr><td>显示网络列表</td><td>显示本地主机上的网络列表</td><td>docker network ls</td><td>ctr network list</td><td>不支持</td><td>nerdctl network ls</td></tr><tr><td>创建网络</td><td>创建一个新的网络</td><td>docker network create</td><td>ctr network create</td><td>不支持</td><td>nerdctl network create</td></tr><tr><td>删除网络</td><td>删除指定的网络</td><td>docker network rm</td><td>ctr network remove</td><td>不支持</td><td>nerdctl network rm</td></tr></tbody></table><h4 id="Containerd-如何存储镜像和容器。⽬录结构是什么样的。是否⽀持-容量限制"><a href="#Containerd-如何存储镜像和容器。⽬录结构是什么样的。是否⽀持-容量限制" class="headerlink" title="Containerd 如何存储镜像和容器。⽬录结构是什么样的。是否⽀持 容量限制"></a>Containerd 如何存储镜像和容器。⽬录结构是什么样的。是否⽀持 容量限制</h4><p>  Containerd 是⼀个容器运⾏时管理程序，它使⽤ OCI（Open Container Initiative）标准来定义容器和镜像。镜像通常被存储在⼀个容器镜像存储库（Container Image Store）中，例如 Docker Hub，或者本地的 OCI 镜像存储库。Containerd 会从存储库中下载镜像，并在本地存储。容器则是使⽤镜像创建的运⾏实例。Containerd 将容器的元数据存储在称为 “snapshots” 的⽬录中。每个容器都有⼀个独⽴的快照⽬录，其中包含容器的根⽂件系统和元数据。Containerd 还⽀持将容器存储在可移动的磁盘上，这种⽅式称为 “offline snapshots”。Containerd ⽀持容器资源限制，可以设置 CPU 和内存的限制，也可以设置 I/O 和⽹络带宽等限制。这些限制是通过使⽤ Linux 内核的 cgroup 和 namespace 功能来实现的。</p><h4 id="Containerd-如何处理⽇志，是否⽀持轮滚"><a href="#Containerd-如何处理⽇志，是否⽀持轮滚" class="headerlink" title="Containerd 如何处理⽇志，是否⽀持轮滚"></a>Containerd 如何处理⽇志，是否⽀持轮滚</h4><p>  Containerd 本身并不负责处理容器的⽇志，⽽是将⽇志处理交给容器运⾏时，如 runc 或 CRI- O。这些容器运⾏时⽀持使⽤各种不同的⽅式来处理容器的⽇志，如直接输出到控制台、将⽇志写⼊⽂件或使⽤⽇志聚合⼯具，如 Fluentd 或ELK Stack。对于容器的⽇志轮滚，⼀般是由容器运⾏时负责实现。例如，runc 可以通过指定 –log-opt max-size 和 –log-opt max-file 参数来控制容器⽇志的⼤⼩和轮滚。当容器⽇志⽂件⼤⼩达到指定的⼤⼩时，runc 会⾃动创建⼀个新的⽇志⽂件，并将旧的⽇志⽂件压缩和删除。类似地，CRI- O 也⽀持使⽤ –log-max-file 和 –log-max-size 参数来控制容器⽇志的轮滚。</p><h4 id="Containerd-重启，是否会导致容器重启"><a href="#Containerd-重启，是否会导致容器重启" class="headerlink" title="Containerd 重启，是否会导致容器重启"></a>Containerd 重启，是否会导致容器重启</h4><p>  当 Containerd 重启时，已经在运⾏的容器不会⽴即停⽌或重启。这是因为容器本身是由容器运⾏时（例如 runc 或CRI- O）管理的，⽽不是由 Containerd 直接控制。因此，Containerd 重启不会直接影响容器的运⾏状态。当 Containerd 重启后，容器运⾏时会重新连接到新的 Containerd 进程，以便继续管理容器。在此过程中，容器运⾏时可能会暂停⼀段时间，导致容器内的应⽤程序暂时⽆法访问，但通常这个时间⾮常短暂，只会影响到容器内正在进⾏的临时操作。需要注意的是，如果 Containerd 重启导致容器存储被破坏或不可⽤，那么容器本身可能会受到影响，因为容器的根⽂<br>件系统和元数据存储在 Containerd 的快照⽬录中。在这种情况下，容器运⾏时可能会⽆法连接到 Containerd，导致容器⽆法正常运⾏。因此，在重启 Containerd 之前，需要确保容器存储的完整性和可⽤性。</p><h4 id="Containerd-的⽹络命名空间是什么样的，⽆-CNI-下的容器，是否⽀持⽹络"><a href="#Containerd-的⽹络命名空间是什么样的，⽆-CNI-下的容器，是否⽀持⽹络" class="headerlink" title="Containerd 的⽹络命名空间是什么样的，⽆ CNI 下的容器，是否⽀持⽹络"></a>Containerd 的⽹络命名空间是什么样的，⽆ CNI 下的容器，是否⽀持⽹络</h4><p>  Containerd 使⽤ Linux 内核的⽹络命名空间（network namespace）来隔离容器的⽹络栈和⽹络配置，以便容器可以拥有⾃⼰独⽴的⽹络栈和⽹络环境。每个容器都有⾃⼰的⽹络命名空间，并且容器之间默认是隔离的，不能相互访问。在没有 CNI（Container Networking Interface）插件的情况下，Containerd 本身并不提供⽹络功能，需要⼿动配置容器的⽹络。可以使⽤ Linux 的⽹络⼯具，如 ip 和 iptables，来⼿动配置容器的⽹络，例如分配 IP 地址、设置路由和防⽕墙规则等。这种⽅式需要⼿动配置和管理，⽐较繁琐。不过，Containerd 可以与 CNI 插件配合使⽤，以便⾃动化配置容器的⽹络。CNI 插件可以在容器创建时⾃动配置⽹络，例如分配 IP 地址、设置⽹络接⼝和路由等。常⻅的 CNI 插件包括 Flannel、Calico、Weave Net 等，它们可以与Containerd 集成，以提供⾃动化的⽹络配置和管理。</p><h4 id="Containerd-有没有-KMEM-泄露-的问题"><a href="#Containerd-有没有-KMEM-泄露-的问题" class="headerlink" title="Containerd 有没有 KMEM 泄露 的问题"></a>Containerd 有没有 KMEM 泄露 的问题</h4><p>  在早期版本的 Containerd 中曾经存在⼀些 KMEM 泄漏的问题。具体来说，这些问题通常与 Containerd 在处理⾼负载情况下使⽤了⼤量的内核内存（KMEM），导致内存泄漏和系统不稳定。不过，Containerd 的开发团队已经在后续版本中修复了这些问题，并采取了⼀些措施来避免 KMEM 泄漏。例如，Containerd 1.4.0 版本中引⼊了 KMEM 限制和监控功能，以便在 Containerd 使⽤⼤量 KMEM 时⾃动降低容器的资源配额，从⽽避免 KMEM 泄漏和系统不稳定。总的来说，如果您使⽤的是较新版本的 Containerd，并且在运⾏期间遇到了 KMEM 泄漏的问题，建议升级到最新版本并检查您的系统配置，以确保已经正确配置了 KMEM 限制和监控。同时，如果您的系统遇到了 KMEM 泄漏等其他问题，也可以向 Containerd 的开发团队报告问题并寻求技术⽀持。</p><h4 id="Containerd-shim-runc-v1与v2的区别"><a href="#Containerd-shim-runc-v1与v2的区别" class="headerlink" title="Containerd-shim-runc-v1与v2的区别"></a>Containerd-shim-runc-v1与v2的区别</h4><p>  containerd-shim-runc-v1 和 containerd-shim-runc-v2 是 containerd 中使⽤的两个 shim 实现。这两个 shim 实现都是使⽤ runc 来启动和管理容器的。containerd-shim-runc-v1 是 containerd 中旧的 shim 实现，它使⽤进程间通信 (IPC) 来与 containerd 守护进程进⾏通信，通常会使⽤ UNIX 域套接字或 FIFO 进⾏通信。它是在 containerd 1.0 中引⼊的，主要⽤于运⾏ Docker 容器，但现在已经被 containerd-shim-runc-v2 替代。containerd-shim-runc-v2 是 containerd 中新的 shim 实现，它使⽤ gRPC 来与 containerd 守护进程进⾏通信。它是在 containerd 1.1 中引⼊的，其⽬标是提供更好的性能和可靠性，并为后续的扩展提供更好的基础设施。与containerd-shim-runc-v1 相⽐，它更加轻量级，并且可以通过 API 配置各种容器和执⾏参数。总的来说，containerd-shim-runc-v2 是 containerd 中更加现代和⾼效的 shim 实现，它⽐ containerd-shimrunc-v1 更具扩展性和可维护性，因此在使⽤ containerd 时应该尽可能地使⽤ containerd-shim-runc-v2。</p><h4 id="Containerd的grpc⽅法是如何注册的？"><a href="#Containerd的grpc⽅法是如何注册的？" class="headerlink" title="Containerd的grpc⽅法是如何注册的？"></a>Containerd的grpc⽅法是如何注册的？</h4><p>   containerd 的 gRPC ⽅法是通过⽣成的 protobuf ⽂件和相应的代码实现的。protobuf ⽂件描述了 containerd ⽀持的API ⽅法和数据结构，然后使⽤这个⽂件⽣成对应的代码（包括客户端和服务器端代码）。这些⾃动⽣成的代码提供了实现⽅法的框架，开发⼈员可以在其中添加⾃⼰的代码以实现具体功能。在 containerd 中，服务器端的 gRPC ⽅法是在 services ⽬录下实现的。每个服务都实现了⼀个接⼝（在 protobuf⽂件中定义），并提供了⼀些⽅法来处理请求。这些⽅法通常采⽤ context 参数来获取请求上下⽂和取消信号，然后使⽤⾃动⽣成的代码处理 protobuf 消息。在这些⽅法中，使⽤的核⼼实现代码通常在 containers、images 或content 等核⼼ package 中实现。服务注册是通过 init 函数实现的，每个服务都在其对应的包中实现了⼀个名为 Register 的函数，该函数在包被导⼊时⾃动运⾏，将⾃⼰注册到 containerd 的 gRPC 服务器上。在 Register 函数中，使⽤<br>server.RegisterService 函数将⾃⼰的服务实现注册到 containerd 的 gRPC 服务器上，以便客户端可以调⽤。</p><h4 id="Containerd与containerd-shim是如何交互的？"><a href="#Containerd与containerd-shim是如何交互的？" class="headerlink" title="Containerd与containerd-shim是如何交互的？"></a>Containerd与containerd-shim是如何交互的？</h4><p>  在 Containerd 中，containerd-shim 是负责启动容器进程并与 Containerd API 通信的组件。Containerd 通过 gRPC接⼝与 containerd-shim 通信，以便进⾏容器的创建、启动、停⽌、删除等操作。具体⽽⾔，Containerd 与containerd-shim 之间的交互过程如下：</p><ol><li>Containerd 使⽤ gRPC 接⼝向 containerd-shim 发送创建容器的请求，包括容器的 ID、镜像、⽂件系统等参数。</li><li>containerd-shim 接收到创建容器的请求后，会根据请求中的参数启动⼀个新的容器进程，并创建⼀个对应的Linux namespace。</li><li>containerd-shim 将容器的 PID、Stdin、Stdout 和 Stderr 等信息发送回给 Containerd，以便后者能够管理和监控容器的运⾏状态。</li><li>在容器运⾏过程中，Containerd 可以通过 gRPC 接⼝向 containerd-shim 发送信号以启动、停⽌、暂停或恢复容器的运⾏。</li><li>当容器进程退出后，containerd-shim 会向 Containerd 发送容器的退出状态和退出码，Containerd 在接收到这些信息后，会更新容器的状态并删除对应的容器对象。需要注意的是，Containerd 和 containerd-shim 都是独⽴的进程，它们之间通过 gRPC 接⼝通信，因此 Containerd和 containerd-shim 可以在不同的计算机上运⾏，这也为 Containerd 的分布式部署提供了便利。</li></ol><h4 id="Containerd-shim与runc是如何交互的？"><a href="#Containerd-shim与runc是如何交互的？" class="headerlink" title="Containerd-shim与runc是如何交互的？"></a>Containerd-shim与runc是如何交互的？</h4><p>  在容器技术中，runc 是⼀个⽤于启动和管理容器的轻量级⼯具，⽽ containerd-shim 是 containerd ⽤于管理容器⽣命周期的代理。在容器启动的过程中，runc 和 containerd-shim 之间会进⾏以下交互：</p><ol><li>Containerd-shim 通过 Containerd API 向 Containerd 发送创建容器的请求。</li><li>Containerd 接收到请求后，将请求转发给 runc 来创建容器。runc 将通过 system call 创建新的容器进程，并设置容器的隔离环境（⽐如 namespace、cgroups、rootfs）等参数。</li><li>runc 启动新的容器进程并返回 PID 给 Containerd-shim。</li><li>Containerd-shim 接收到容器进程的 PID 后，会将 PID 发送回给 Containerd。Containerd 会继续管理和监控容器的⽣命周期。</li><li>在容器运⾏期间，Containerd 可以通过 Containerd API 向 Containerd-shim 发送命令，⽐如停⽌、暂停、恢复、删除容器等操作。</li><li>当容器进程退出后，runc 将容器的退出状态和退出码发送给 Containerd-shim。Containerd-shim 将这些信息发送回给 Containerd，Containerd 将更新容器的状态并删除对应的容器对象。需要注意的是，runc 是⼀个独⽴的⼯具，它与 containerd-shim 的交互是在容器启动时发⽣的。在容器启动成功后，runc 将直接与容器进程交互，⽽ containerd-shim 的作⽤将逐渐变⼩。</li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;导言&quot;&gt;&lt;a href=&quot;#导言&quot; class=&quot;headerlink&quot; title=&quot;导言&quot;&gt;&lt;/a&gt;导言&lt;/h3&gt;&lt;p&gt;最近在集群中遇到了很多containerd的问题，所以不禁思考我真的懂containerd吗？？?&lt;/p&gt;
&lt;h3 id=&quot;前提&quot;&gt;&lt;a h</summary>
      
    
    
    
    <category term="Kubernetes" scheme="https://kalyan-zitiu.github.io/categories/Kubernetes/"/>
    
    
    <category term="Kubernetes" scheme="https://kalyan-zitiu.github.io/tags/Kubernetes/"/>
    
  </entry>
  
  <entry>
    <title>Kubernetes-StorageClass实践2</title>
    <link href="https://kalyan-zitiu.github.io/2024/08/05/Kubernetes-StorageClass%E5%AE%9E%E8%B7%B52/"/>
    <id>https://kalyan-zitiu.github.io/2024/08/05/Kubernetes-StorageClass%E5%AE%9E%E8%B7%B52/</id>
    <published>2024-08-05T02:16:48.000Z</published>
    <updated>2024-08-08T06:04:57.432Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前提"><a href="#前提" class="headerlink" title="前提"></a>前提</h2><p>你需要提前了解，hwameistor的组件生命周期管理：</p><h3 id="1-LocalDiskManager"><a href="#1-LocalDiskManager" class="headerlink" title="1. LocalDiskManager"></a>1. LocalDiskManager</h3><p><strong>作用</strong>: <code>LocalDiskManager</code> 负责管理节点上的物理磁盘资源。它发现、监控和维护节点的本地磁盘信息，确保系统对可用磁盘资源的了解是最新的。</p><p><strong>生命周期管理</strong>:</p><ul><li><strong>启动</strong>: 当 <code>LocalDiskManager</code> 启动时，它扫描节点上的所有可用磁盘，收集磁盘的元数据（例如大小、型号、状态等）。</li><li><strong>运行中</strong>: 持续监控磁盘状态变化，更新磁盘元数据信息，并根据需要调整磁盘的可用性状态。</li><li><strong>停止</strong>: 在组件停止时，需要确保停止对磁盘的监控，并正确释放资源。</li></ul><h3 id="2-LocalStorage"><a href="#2-LocalStorage" class="headerlink" title="2. LocalStorage"></a>2. LocalStorage</h3><p><strong>作用</strong>: <code>LocalStorage</code> 提供节点级别的存储资源管理。它负责将物理磁盘抽象为可用的存储卷，并执行卷的创建、删除、扩展等操作。</p><p><strong>生命周期管理</strong>:</p><ul><li><strong>启动</strong>: 初始化本地存储卷的管理逻辑，确保节点上的物理磁盘可以被正确识别和使用。</li><li><strong>运行中</strong>: 管理存储卷的生命周期，包括创建、删除、扩展、快照等操作，监控卷的健康状态。</li><li><strong>停止</strong>: 停止管理存储卷，确保所有资源被安全释放。</li></ul><h3 id="3-Scheduler"><a href="#3-Scheduler" class="headerlink" title="3. Scheduler"></a>3. Scheduler</h3><p><strong>作用</strong>: <code>Scheduler</code> 是一个自定义调度器插件，用于优化工作负载调度到具有特定存储要求的节点上。</p><p><strong>生命周期管理</strong>:</p><ul><li><strong>启动</strong>: 注册自定义调度逻辑，将其集成到 Kubernetes 调度流程中。</li><li><strong>运行中</strong>: 根据工作负载的存储需求和节点的存储资源情况，执行优化调度。</li><li><strong>停止</strong>: 取消注册自定义调度逻辑，从 Kubernetes 调度器中安全移除。</li></ul><h3 id="4-AdmissionController"><a href="#4-AdmissionController" class="headerlink" title="4. AdmissionController"></a>4. AdmissionController</h3><p><strong>作用</strong>: <code>AdmissionController</code> 在工作负载被提交到 Kubernetes 集群时，对其进行预处理，确保其符合存储策略和要求。</p><p><strong>生命周期管理</strong>:</p><ul><li><strong>启动</strong>: 注册到 Kubernetes 的准入控制器链中，准备对即将创建的资源进行预处理。</li><li><strong>运行中</strong>: 拦截工作负载请求，根据存储策略进行验证和调整。</li><li><strong>停止</strong>: 从准入控制器链中移除，停止对新请求的拦截和处理。</li></ul><h3 id="5-VolumeEvictor"><a href="#5-VolumeEvictor" class="headerlink" title="5. VolumeEvictor"></a>5. VolumeEvictor</h3><p><strong>作用</strong>: <code>VolumeEvictor</code> 负责在节点维护或失败时，将存储卷从受影响的节点上安全地迁移到其他节点。</p><p><strong>生命周期管理</strong>:</p><ul><li><strong>启动</strong>: 初始化卷迁移逻辑，确保在节点发生问题时，卷可以被安全转移。</li><li><strong>运行中</strong>: 持续监控节点状态和卷的健康状况，执行必要的迁移操作。</li><li><strong>停止</strong>: 停止监控和迁移操作，确保当前迁移过程安全完成。</li></ul><h3 id="6-Exporter"><a href="#6-Exporter" class="headerlink" title="6. Exporter"></a>6. Exporter</h3><p><strong>作用</strong>: <code>Exporter</code> 收集和导出存储系统的监控指标，供外部监控系统（如 Prometheus）使用。</p><p><strong>生命周期管理</strong>:</p><ul><li><strong>启动</strong>: 初始化监控指标的收集和导出逻辑。</li><li><strong>运行中</strong>: 持续收集系统指标，提供给监控系统进行实时监控和分析。</li><li><strong>停止</strong>: 停止指标的收集和导出，释放相关资源。</li></ul><h3 id="7-Apiserver"><a href="#7-Apiserver" class="headerlink" title="7. Apiserver"></a>7. Apiserver</h3><p><strong>作用</strong>: <code>Apiserver</code> 提供对 HwameiStor 的管理接口，使用户能够通过 RESTful API 进行操作。</p><p><strong>生命周期管理</strong>:</p><ul><li><strong>启动</strong>: 初始化 API 服务，注册可用的接口端点。</li><li><strong>运行中</strong>: 处理用户请求，执行存储管理操作。</li><li><strong>停止</strong>: 停止 API 服务，确保当前请求被正确处理完成。</li></ul><h2 id="目标"><a href="#目标" class="headerlink" title="目标"></a>目标</h2><p>手速StorageClass用hwameistor的方式进行pvc申领动态制备PV</p><h2 id="简要步骤"><a href="#简要步骤" class="headerlink" title="简要步骤"></a>简要步骤</h2><ol><li>保证helm存在</li><li>添加 hwameistor-operator Helm Repo</li><li>通过hwameistor-operator部署HwameiStor</li></ol><h2 id="amp-amp-实战开始"><a href="#amp-amp-实战开始" class="headerlink" title="@&amp;^%!*&amp;@$实战开始"></a>@&amp;^%!*&amp;@$实战开始</h2><h3 id="检查是否有空盘，至于hwameistor是否能再无空盘情况下中断安装后续再尝试"><a href="#检查是否有空盘，至于hwameistor是否能再无空盘情况下中断安装后续再尝试" class="headerlink" title="检查是否有空盘，至于hwameistor是否能再无空盘情况下中断安装后续再尝试"></a>检查是否有空盘，至于hwameistor是否能再无空盘情况下中断安装后续再尝试</h3><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240805105748731.png" alt="image-20240805105748731"></p><h3 id="添加源"><a href="#添加源" class="headerlink" title="添加源"></a>添加源</h3><p>其实这个步骤是挺简单的，全都是自动创建，所以建议就是最后需要了解一下改csi驱动的特点。比如分布式以及自动搜盘。</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">helm repo add hwameistor-operator https://hwameistor.io/hwameistor-operator</span><br><span class="line">helm repo update hwameistor-operator</span><br></pre></td></tr></table></figure><h3 id="通过hwameistor-operator进行部署HwameiStor"><a href="#通过hwameistor-operator进行部署HwameiStor" class="headerlink" title="通过hwameistor-operator进行部署HwameiStor"></a>通过hwameistor-operator进行部署HwameiStor</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">helm install hwameistor-operator hwameistor-operator/hwameistor-operator -n hwameistor --create-namespace</span><br></pre></td></tr></table></figure><p>ps:HwameiStor默认会把所有干净的磁盘纳入到LSD的存储池里面，但是也可以预留，通过helm的values来设置</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">--<span class="built_in">set</span> diskReserve\[0\].nodeName=node1 \</span><br><span class="line">--<span class="built_in">set</span> diskReserve\[0\].devices=&#123;/dev/sdc\,/dev/sdd&#125; \</span><br><span class="line">--<span class="built_in">set</span> diskReserve\[1\].nodeName=node2 \</span><br><span class="line">--<span class="built_in">set</span> diskReserve\[1\].devices=&#123;/dev/sdc\,/dev/sde&#125;</span><br></pre></td></tr></table></figure><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="comment"># -f diskReserve.yaml</span></span><br><span class="line"><span class="comment"># diskReserve.yaml 如下</span></span><br><span class="line"><span class="attr">diskReserve:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">nodeName:</span> <span class="string">node1</span></span><br><span class="line">  <span class="attr">devices:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">/dev/sdc</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">/dev/sdd</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">nodeName:</span> <span class="string">node2</span></span><br><span class="line">  <span class="attr">devices:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">/dev/sdc</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">/dev/sde</span></span><br></pre></td></tr></table></figure><h3 id="结束"><a href="#结束" class="headerlink" title="结束"></a>结束</h3><p>理论来说，镜像拉取没有问题的话，就基本都可以了，HwameiStor就是这么的nb，可以自己做完所有事情。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;前提&quot;&gt;&lt;a href=&quot;#前提&quot; class=&quot;headerlink&quot; title=&quot;前提&quot;&gt;&lt;/a&gt;前提&lt;/h2&gt;&lt;p&gt;你需要提前了解，hwameistor的组件生命周期管理：&lt;/p&gt;
&lt;h3 id=&quot;1-LocalDiskManager&quot;&gt;&lt;a href=&quot;</summary>
      
    
    
    
    <category term="Kubernetes" scheme="https://kalyan-zitiu.github.io/categories/Kubernetes/"/>
    
    
    <category term="Kubernetes" scheme="https://kalyan-zitiu.github.io/tags/Kubernetes/"/>
    
  </entry>
  
  <entry>
    <title>Kubernetes-StorageClass实践1</title>
    <link href="https://kalyan-zitiu.github.io/2024/08/01/Kubernetes%E5%AD%98%E5%82%A8%E5%AE%9E%E6%88%98/"/>
    <id>https://kalyan-zitiu.github.io/2024/08/01/Kubernetes%E5%AD%98%E5%82%A8%E5%AE%9E%E6%88%98/</id>
    <published>2024-08-01T02:16:47.000Z</published>
    <updated>2024-08-01T07:52:21.171Z</updated>
    
    <content type="html"><![CDATA[<h3 id="前提"><a href="#前提" class="headerlink" title="前提"></a>前提</h3><p>该实战基于假设了解并清楚，<strong>ServiceAccount</strong>，<strong>ClusterRole</strong>，<strong>ClusterRoleBinding</strong>等<br>以下是简要介绍：</p><ol><li>ServiceAccount：为Pod提供了一个身份，允许Pod与Kubernetes API进行安全交互。Local Path Provisioner需要访问和管理PV、PVC、Nodes等资源</li><li>ClusterRole：定义了一组权限，允许某个身份（如ServiceAccount）对Kubernetes集群中的资源执行特定操作。</li><li>ClusterRoleBinding：ClusterRoleBinding将ClusterRole与一个或多个主体（如ServiceAccount）绑定，以便这些主体获得ClusterRole定义的权限<h3 id="目标"><a href="#目标" class="headerlink" title="目标"></a>目标</h3>手撕StorageClass用rancher的local-path的方式进行PVC申领动态制备PV</li></ol><h3 id="简要步骤"><a href="#简要步骤" class="headerlink" title="简要步骤"></a>简要步骤</h3><ol><li>建立命名空间进行资源隔离</li><li>创建ServiceAccount、ClusterRole和ClusterRoleBinding（前提解释）</li><li>创建deploy，控制pod副本数量</li><li>创建configMap，存储不含机密信息的配置数据。（参考：存储基础）</li><li>创建StorageClass（参考第4条）</li></ol><h3 id="废话不多说-￥-……-amp-实战开始"><a href="#废话不多说-￥-……-amp-实战开始" class="headerlink" title="废话不多说@#￥%……&amp;*实战开始"></a>废话不多说@#￥%……&amp;*实战开始</h3><h4 id="namespace"><a href="#namespace" class="headerlink" title="namespace"></a>namespace</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 好的，已经成功一半了</span></span><br><span class="line">kubectl create namespace(ns) local-path-storage</span><br></pre></td></tr></table></figure><h4 id="ServiceAccount"><a href="#ServiceAccount" class="headerlink" title="ServiceAccount"></a>ServiceAccount</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">apiVersion: v1</span><br><span class="line">kind: ServiceAccount</span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-provisioner-service-account</span><br><span class="line">  namespace: local-path-storage </span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240801104527213.png" alt="image-20240801104527213"></p><h4 id="ClusterRole，直接拿官方的"><a href="#ClusterRole，直接拿官方的" class="headerlink" title="ClusterRole，直接拿官方的"></a>ClusterRole，直接拿官方的</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">apiVersion: rbac.authorization.k8s.io/v1 <span class="comment"># 指定API版本，这里是rbac.authorization.k8s.io/v1</span></span><br><span class="line">kind: ClusterRole <span class="comment"># 资源类型，这里是ClusterRole，表示集群级别的权限定义</span></span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-provisioner-role <span class="comment"># ClusterRole的名称，这里是local-path-provisioner-role</span></span><br><span class="line">rules: <span class="comment"># 定义该角色的权限规则列表</span></span><br><span class="line">- apiGroups: [<span class="string">&quot;&quot;</span>] <span class="comment"># 指定API组，空字符串表示核心API组</span></span><br><span class="line">  resources: [<span class="string">&quot;nodes&quot;</span>, <span class="string">&quot;persistentvolumeclaims&quot;</span>, <span class="string">&quot;persistentvolumes&quot;</span>] <span class="comment"># 资源类型列表，包括nodes、persistentvolumeclaims和persistentvolumes</span></span><br><span class="line">  verbs: [<span class="string">&quot;get&quot;</span>, <span class="string">&quot;list&quot;</span>, <span class="string">&quot;watch&quot;</span>, <span class="string">&quot;create&quot;</span>, <span class="string">&quot;delete&quot;</span>] <span class="comment"># 允许的操作，包括获取、列出、监视、创建和删除</span></span><br><span class="line">- apiGroups: [<span class="string">&quot;&quot;</span>] <span class="comment"># 再次指定核心API组</span></span><br><span class="line">  resources: [<span class="string">&quot;pods&quot;</span>] <span class="comment"># 资源类型是pods</span></span><br><span class="line">  verbs: [<span class="string">&quot;get&quot;</span>, <span class="string">&quot;list&quot;</span>, <span class="string">&quot;watch&quot;</span>] <span class="comment"># 允许的操作，包括获取、列出和监视</span></span><br><span class="line">- apiGroups: [<span class="string">&quot;storage.k8s.io&quot;</span>] <span class="comment"># 指定API组storage.k8s.io</span></span><br><span class="line">  resources: [<span class="string">&quot;storageclasses&quot;</span>] <span class="comment"># 资源类型是storageclasses</span></span><br><span class="line">  verbs: [<span class="string">&quot;get&quot;</span>, <span class="string">&quot;list&quot;</span>, <span class="string">&quot;watch&quot;</span>] <span class="comment"># 允许的操作，包括获取、列出和监视</span></span><br><span class="line">- apiGroups: [<span class="string">&quot;batch&quot;</span>, <span class="string">&quot;extensions&quot;</span>] <span class="comment"># 指定API组batch和extensions</span></span><br><span class="line">  resources: [<span class="string">&quot;jobs&quot;</span>] <span class="comment"># 资源类型是jobs</span></span><br><span class="line">  verbs: [<span class="string">&quot;get&quot;</span>, <span class="string">&quot;list&quot;</span>, <span class="string">&quot;watch&quot;</span>, <span class="string">&quot;create&quot;</span>, <span class="string">&quot;delete&quot;</span>] <span class="comment"># 允许的操作，包括获取、列出、监视、创建和删除</span></span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240801105301424.png" alt="image-20240801105301424"></p><h4 id="ClusterRoleBinding"><a href="#ClusterRoleBinding" class="headerlink" title="ClusterRoleBinding"></a>ClusterRoleBinding</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">apiVersion: rbac.authorization.k8s.io/v1 <span class="comment"># 指定API版本，这里是rbac.authorization.k8s.io/v1</span></span><br><span class="line">kind: ClusterRoleBinding <span class="comment"># 资源类型，这里是ClusterRoleBinding，表示集群级别的角色绑定</span></span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-provisioner-bindings <span class="comment"># ClusterRoleBinding的名称，这里是local-path-provisioner-bindings</span></span><br><span class="line">roleRef: <span class="comment"># 指定要绑定的角色</span></span><br><span class="line">  apiGroup: rbac.authorization.k8s.io <span class="comment"># 角色所属的API组，这里是rbac.authorization.k8s.io</span></span><br><span class="line">  kind: ClusterRole <span class="comment"># 角色类型，这里是ClusterRole</span></span><br><span class="line">  name: local-path-provisioner-role <span class="comment"># 角色名称，这里是local-path-provisioner-role</span></span><br><span class="line">subjects: <span class="comment"># 定义该角色绑定的主体列表</span></span><br><span class="line">- kind: ServiceAccount <span class="comment"># 主体类型，这里是ServiceAccount（服务账户）</span></span><br><span class="line">  name: local-path-provisioner-service-account <span class="comment"># 服务账户的名称，这里是local-path-provisioner-service-account</span></span><br><span class="line">  namespace: local-path-storage <span class="comment"># 服务账户所属的命名空间，这里是local-path-storage</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240801105734783.png" alt="image-20240801105734783"></p><h4 id="Deploy"><a href="#Deploy" class="headerlink" title="Deploy"></a>Deploy</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">apiVersion: apps/v1 <span class="comment"># 指定API版本，这里是apps/v1</span></span><br><span class="line">kind: Deployment <span class="comment"># 资源类型，这里是Deployment，表示部署一个应用</span></span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-provisioner <span class="comment"># Deployment的名称，这里是local-path-provisioner</span></span><br><span class="line">  namespace: local-path-storage <span class="comment"># Deployment所属的命名空间，这里是local-path-storage</span></span><br><span class="line">spec: <span class="comment"># Deployment的规格定义</span></span><br><span class="line">  replicas: 1 <span class="comment"># 副本数，这里是1，表示只部署一个副本</span></span><br><span class="line">  selector: <span class="comment"># 用于选择要部署的Pod</span></span><br><span class="line">    matchLabels:</span><br><span class="line">    <span class="comment"># 标签选择器，选择标签为app: local-path-provisioner的Pod</span></span><br><span class="line">      app: local-path-provisioner </span><br><span class="line">  template: <span class="comment"># Pod模板定义</span></span><br><span class="line">    metadata:</span><br><span class="line">      labels:</span><br><span class="line">        app: local-path-provisioner <span class="comment"># 为Pod设置的标签，这里是app: local-path-provisioner</span></span><br><span class="line">    spec: <span class="comment"># Pod的规格定义</span></span><br><span class="line">    <span class="comment"># 使用的服务账户名称，这里是local-path-provisioner-service-account</span></span><br><span class="line">      serviceAccountName: local-path-provisioner-service-account </span><br><span class="line">      containers: <span class="comment"># 容器列表</span></span><br><span class="line">      - name: provisioner <span class="comment"># 容器名称，这里是provisioner</span></span><br><span class="line">      <span class="comment"># 容器镜像，这里是rancher/local-path-provisioner:latest</span></span><br><span class="line">        image: rancher/local-path-provisioner:master-head <span class="comment"># 换加速啊啊啊啊啊啊啊啊叼毛</span></span><br><span class="line">        imagePullPolicy: Always <span class="comment"># 镜像拉取策略，总是拉取最新的镜像</span></span><br><span class="line">        volumeMounts: <span class="comment"># 挂载的卷列表</span></span><br><span class="line">        - name: config-volume <span class="comment"># 卷名称，这里是config-volume</span></span><br><span class="line">          mountPath: /etc/config <span class="comment"># 挂载路径，这里是/etc/config</span></span><br><span class="line">        - name: local-path-storage <span class="comment"># 卷名称，这里是local-path-storage</span></span><br><span class="line">          mountPath: /opt/local-path-storage <span class="comment"># 挂载路径，这里是/opt/local-path-storage</span></span><br><span class="line">      volumes: <span class="comment"># 定义Pod中使用的卷</span></span><br><span class="line">      - name: config-volume <span class="comment"># 卷名称，这里是config-volume</span></span><br><span class="line">        configMap: <span class="comment"># 使用ConfigMap作为卷</span></span><br><span class="line">          name: local-path-config <span class="comment"># ConfigMap的名称，这里是local-path-config</span></span><br><span class="line">      - name: local-path-storage <span class="comment"># 卷名称，这里是local-path-storage</span></span><br><span class="line">        hostPath: <span class="comment"># 使用主机路径作为卷</span></span><br><span class="line">          path: /opt/local-path-storage <span class="comment"># 主机路径，这里是/opt/local-path-storage</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240801110044796.png" alt="image-20240801110044796"></p><h4 id="config"><a href="#config" class="headerlink" title="config"></a>config</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">apiVersion: v1 <span class="comment"># 指定API版本，这里是v1</span></span><br><span class="line">kind: ConfigMap <span class="comment"># 资源类型，这里是ConfigMap，用于存储配置信息</span></span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-config <span class="comment"># ConfigMap的名称，这里是local-path-config</span></span><br><span class="line">  namespace: local-path-storage <span class="comment"># ConfigMap所属的命名空间，这里是local-path-storage</span></span><br><span class="line">data: <span class="comment"># 配置数据</span></span><br><span class="line">  config.json: | <span class="comment"># 配置文件的名称，这里是config.json，使用多行字符串格式</span></span><br><span class="line">    &#123;</span><br><span class="line">      <span class="string">&quot;nodePathMap&quot;</span>:[</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="string">&quot;node&quot;</span>:<span class="string">&quot;DEFAULT_PATH_FOR_NON_LISTED_NODES&quot;</span>, <span class="comment"># 节点名称，表示未列出的节点的默认路径</span></span><br><span class="line">          <span class="string">&quot;paths&quot;</span>:[<span class="string">&quot;/opt/local-path-storage&quot;</span>] <span class="comment"># 路径列表，这里是/opt/local-path-storage</span></span><br><span class="line">        &#125;</span><br><span class="line">        ]</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240801110611178.png" alt="image-20240801110611178"></p><h4 id="StorageClass"><a href="#StorageClass" class="headerlink" title="StorageClass"></a>StorageClass</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">apiVersion: storage.k8s.io/v1 <span class="comment"># 指定API版本，这里是storage.k8s.io/v1</span></span><br><span class="line">kind: StorageClass <span class="comment"># 资源类型，这里是StorageClass，表示存储类</span></span><br><span class="line">metadata:</span><br><span class="line">  name: local-path <span class="comment"># StorageClass的名称，这里是local-path</span></span><br><span class="line">provisioner: rancher.io/local-path <span class="comment"># 指定的provisioner，这里是rancher.io/local-path</span></span><br><span class="line">reclaimPolicy: Delete <span class="comment"># 回收策略，这里是Delete，表示当持久卷被释放时删除它</span></span><br><span class="line"><span class="comment"># 卷绑定模式，这里是WaitForFirstConsumer，表示延迟绑定，直到Pod被调度到节点上</span></span><br><span class="line">volumeBindingMode: WaitForFirstConsumer </span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240801110811688.png" alt="image-20240801110811688"></p><h4 id="验证"><a href="#验证" class="headerlink" title="验证"></a>验证</h4><h5 id="创建pvc-yaml"><a href="#创建pvc-yaml" class="headerlink" title="创建pvc yaml"></a>创建pvc yaml</h5><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">apiVersion: v1</span><br><span class="line">kind: PersistentVolumeClaim</span><br><span class="line">metadata:</span><br><span class="line">  name: my-local-pvc</span><br><span class="line">spec:</span><br><span class="line">  accessModes:</span><br><span class="line">    - ReadWriteOnce</span><br><span class="line">  resources:</span><br><span class="line">    requests:</span><br><span class="line">      storage: 1Gi</span><br><span class="line">  storageClassName: local-path</span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240801142550578.png" alt="image-20240801142550578"></p><p>因为设计的是WaitForFirstConsumer，所以需要设计一个pod</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">apiVersion: v1</span><br><span class="line">kind: Pod</span><br><span class="line">metadata:</span><br><span class="line">  name: myapp-pod</span><br><span class="line">spec:</span><br><span class="line">  containers:</span><br><span class="line">  - name: myapp-container</span><br><span class="line">    image: m.daocloud.io/docker.io/library/nginx</span><br><span class="line">    volumeMounts:</span><br><span class="line">    - mountPath: <span class="string">&quot;/usr/share/nginx/html&quot;</span></span><br><span class="line">      name: my-local-storage</span><br><span class="line">  volumes:</span><br><span class="line">  - name: my-local-storage</span><br><span class="line">    persistentVolumeClaim:</span><br><span class="line">      claimName: my-local-pvc</span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240801145710135.png" alt="image-20240801145710135"></p><h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><p>以上的配置文件只是一个参考，实际的可以用官方的配置文件,需要注意的是换加速镜像地址时候要换全哦，带image的都换。配置不正确多半进入cashloopbackoff的问题。</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">apiVersion: v1</span><br><span class="line">kind: Namespace</span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-storage</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">apiVersion: v1</span><br><span class="line">kind: ServiceAccount</span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-provisioner-service-account</span><br><span class="line">  namespace: local-path-storage</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">apiVersion: rbac.authorization.k8s.io/v1</span><br><span class="line">kind: Role</span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-provisioner-role</span><br><span class="line">  namespace: local-path-storage</span><br><span class="line">rules:</span><br><span class="line">  - apiGroups: [<span class="string">&quot;&quot;</span>]</span><br><span class="line">    resources: [<span class="string">&quot;pods&quot;</span>]</span><br><span class="line">    verbs: [<span class="string">&quot;get&quot;</span>, <span class="string">&quot;list&quot;</span>, <span class="string">&quot;watch&quot;</span>, <span class="string">&quot;create&quot;</span>, <span class="string">&quot;patch&quot;</span>, <span class="string">&quot;update&quot;</span>, <span class="string">&quot;delete&quot;</span>]</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">apiVersion: rbac.authorization.k8s.io/v1</span><br><span class="line">kind: ClusterRole</span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-provisioner-role</span><br><span class="line">rules:</span><br><span class="line">  - apiGroups: [<span class="string">&quot;&quot;</span>]</span><br><span class="line">    resources: [<span class="string">&quot;nodes&quot;</span>, <span class="string">&quot;persistentvolumeclaims&quot;</span>, <span class="string">&quot;configmaps&quot;</span>, <span class="string">&quot;pods&quot;</span>, <span class="string">&quot;pods/log&quot;</span>]</span><br><span class="line">    verbs: [<span class="string">&quot;get&quot;</span>, <span class="string">&quot;list&quot;</span>, <span class="string">&quot;watch&quot;</span>]</span><br><span class="line">  - apiGroups: [<span class="string">&quot;&quot;</span>]</span><br><span class="line">    resources: [<span class="string">&quot;persistentvolumes&quot;</span>]</span><br><span class="line">    verbs: [<span class="string">&quot;get&quot;</span>, <span class="string">&quot;list&quot;</span>, <span class="string">&quot;watch&quot;</span>, <span class="string">&quot;create&quot;</span>, <span class="string">&quot;patch&quot;</span>, <span class="string">&quot;update&quot;</span>, <span class="string">&quot;delete&quot;</span>]</span><br><span class="line">  - apiGroups: [<span class="string">&quot;&quot;</span>]</span><br><span class="line">    resources: [<span class="string">&quot;events&quot;</span>]</span><br><span class="line">    verbs: [<span class="string">&quot;create&quot;</span>, <span class="string">&quot;patch&quot;</span>]</span><br><span class="line">  - apiGroups: [<span class="string">&quot;storage.k8s.io&quot;</span>]</span><br><span class="line">    resources: [<span class="string">&quot;storageclasses&quot;</span>]</span><br><span class="line">    verbs: [<span class="string">&quot;get&quot;</span>, <span class="string">&quot;list&quot;</span>, <span class="string">&quot;watch&quot;</span>]</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">apiVersion: rbac.authorization.k8s.io/v1</span><br><span class="line">kind: RoleBinding</span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-provisioner-bind</span><br><span class="line">  namespace: local-path-storage</span><br><span class="line">roleRef:</span><br><span class="line">  apiGroup: rbac.authorization.k8s.io</span><br><span class="line">  kind: Role</span><br><span class="line">  name: local-path-provisioner-role</span><br><span class="line">subjects:</span><br><span class="line">  - kind: ServiceAccount</span><br><span class="line">    name: local-path-provisioner-service-account</span><br><span class="line">    namespace: local-path-storage</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">apiVersion: rbac.authorization.k8s.io/v1</span><br><span class="line">kind: ClusterRoleBinding</span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-provisioner-bind</span><br><span class="line">roleRef:</span><br><span class="line">  apiGroup: rbac.authorization.k8s.io</span><br><span class="line">  kind: ClusterRole</span><br><span class="line">  name: local-path-provisioner-role</span><br><span class="line">subjects:</span><br><span class="line">  - kind: ServiceAccount</span><br><span class="line">    name: local-path-provisioner-service-account</span><br><span class="line">    namespace: local-path-storage</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">apiVersion: apps/v1</span><br><span class="line">kind: Deployment</span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-provisioner</span><br><span class="line">  namespace: local-path-storage</span><br><span class="line">spec:</span><br><span class="line">  replicas: 1</span><br><span class="line">  selector:</span><br><span class="line">    matchLabels:</span><br><span class="line">app: local-path-provisioner</span><br><span class="line">  template:</span><br><span class="line">    metadata:</span><br><span class="line">      labels:</span><br><span class="line">        app: local-path-provisioner</span><br><span class="line">    spec:</span><br><span class="line">      serviceAccountName: local-path-provisioner-service-account</span><br><span class="line">      containers:</span><br><span class="line">        - name: local-path-provisioner</span><br><span class="line">          image: docker.m.daocloud.io/rancher/local-path-provisioner:master-head  <span class="comment"># ps：换</span></span><br><span class="line">          imagePullPolicy: IfNotPresent</span><br><span class="line">          <span class="built_in">command</span>:</span><br><span class="line">            - local-path-provisioner</span><br><span class="line">            - --debug</span><br><span class="line">            - start</span><br><span class="line">            - --config</span><br><span class="line">            - /etc/config/config.json</span><br><span class="line">          volumeMounts:</span><br><span class="line">            - name: config-volume</span><br><span class="line">              mountPath: /etc/config/</span><br><span class="line">          <span class="built_in">env</span>:</span><br><span class="line">            - name: POD_NAMESPACE</span><br><span class="line">              valueFrom:</span><br><span class="line">                fieldRef:</span><br><span class="line">                  fieldPath: metadata.namespace</span><br><span class="line">            - name: CONFIG_MOUNT_PATH</span><br><span class="line">              value: /etc/config/</span><br><span class="line">      volumes:</span><br><span class="line">        - name: config-volume</span><br><span class="line">          configMap:</span><br><span class="line">            name: local-path-config</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">apiVersion: storage.k8s.io/v1</span><br><span class="line">kind: StorageClass</span><br><span class="line">metadata:</span><br><span class="line">  name: local-path</span><br><span class="line">provisioner: rancher.io/local-path</span><br><span class="line">volumeBindingMode: Immediate</span><br><span class="line">reclaimPolicy: Delete</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">kind: ConfigMap</span><br><span class="line">apiVersion: v1</span><br><span class="line">metadata:</span><br><span class="line">  name: local-path-config</span><br><span class="line">  namespace: local-path-storage</span><br><span class="line">data:</span><br><span class="line">  config.json: |-</span><br><span class="line">    &#123;</span><br><span class="line">            <span class="string">&quot;nodePathMap&quot;</span>:[</span><br><span class="line">            &#123;</span><br><span class="line">                    <span class="string">&quot;node&quot;</span>:<span class="string">&quot;DEFAULT_PATH_FOR_NON_LISTED_NODES&quot;</span>,</span><br><span class="line">                    <span class="string">&quot;paths&quot;</span>:[<span class="string">&quot;/opt/local-path-provisioner&quot;</span>]</span><br><span class="line">            &#125;</span><br><span class="line">            ]</span><br><span class="line">    &#125;</span><br><span class="line">  setup: |-</span><br><span class="line">    <span class="comment">#!/bin/sh</span></span><br><span class="line">    <span class="built_in">set</span> -eu</span><br><span class="line">    <span class="built_in">mkdir</span> -m 0777 -p <span class="string">&quot;<span class="variable">$VOL_DIR</span>&quot;</span></span><br><span class="line">  teardown: |-</span><br><span class="line">    <span class="comment">#!/bin/sh</span></span><br><span class="line">    <span class="built_in">set</span> -eu</span><br><span class="line">    <span class="built_in">rm</span> -rf <span class="string">&quot;<span class="variable">$VOL_DIR</span>&quot;</span></span><br><span class="line">  helperPod.yaml: |-</span><br><span class="line">    apiVersion: v1</span><br><span class="line">    kind: Pod</span><br><span class="line">    metadata:</span><br><span class="line">      name: helper-pod</span><br><span class="line">    spec:</span><br><span class="line">      priorityClassName: system-node-critical</span><br><span class="line">      tolerations:</span><br><span class="line">        - key: node.kubernetes.io/disk-pressure</span><br><span class="line">          operator: Exists</span><br><span class="line">          effect: NoSchedule</span><br><span class="line">      containers:</span><br><span class="line">      - name: helper-pod</span><br><span class="line">        image: m.daocloud.io/docker.io/library/busybox <span class="comment"># ps：换</span></span><br><span class="line">        imagePullPolicy: IfNotPresent</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">手撕StorageClass用local-path的方式进行PVC申领动态制备PV</summary>
    
    
    
    <category term="Kubernentes" scheme="https://kalyan-zitiu.github.io/categories/Kubernentes/"/>
    
    
    <category term="Kubernetes" scheme="https://kalyan-zitiu.github.io/tags/Kubernetes/"/>
    
  </entry>
  
  <entry>
    <title>Kubernetes 证书</title>
    <link href="https://kalyan-zitiu.github.io/2024/07/31/Kubernetes_pki/"/>
    <id>https://kalyan-zitiu.github.io/2024/07/31/Kubernetes_pki/</id>
    <published>2024-07-31T06:58:28.000Z</published>
    <updated>2024-08-01T08:07:45.606Z</updated>
    
    <content type="html"><![CDATA[<h3 id="PKI证书"><a href="#PKI证书" class="headerlink" title="PKI证书"></a>PKI证书</h3><p>kubernetes是需要PKI才能执行多数操作:</p><ol><li>kubelet的客户端证书:用于API服务器身份验证</li><li>kubelet服务证书:用于API服务器与Kubelet的会话</li><li>API服务器端点证书:用于HTTPS加密，确保通信加密</li><li>集群管理员的客户端证书：管理员（我）的工作证明</li><li>API 服务器的客户端证书：用于和 Kubelet 的会话</li><li>API 服务器的客户端证书：用于和 etcd 的会话</li><li>控制器管理器的客户端证书或 kubeconfig：用于和 API 服务器的会话</li><li>调度器的客户端证书或 kubeconfig：用于和 API 服务器的会话</li><li>前端代理的客户端及服务端证书</li></ol><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240731153548422.png" alt="image-20240731153548422"></p><h3 id="自定义证书"><a href="#自定义证书" class="headerlink" title="自定义证书"></a>自定义证书</h3><ul><li>首先用kubeadm创建的kubernetes会生成集群所需地全部证书。</li><li>其次你可以自定义，通过<code>--cert-dir</code>来指定不同的目录</li><li>默认位置/etc/kubernetes/pki里面</li><li><code>kubeadm init --cert-dir /自定义目录/</code>或者在kubeadm自定义的config的<code>certificatesDir</code>字段进行目录指定</li></ul><h3 id="外部CA"><a href="#外部CA" class="headerlink" title="外部CA"></a>外部CA</h3><p>指在 Kubernetes 集群中使用由外部证书颁发机构（CA）签发的证书，而不是由 kubeadm 自行生成和管理 CA 证书。这种模式下，所有的证书和密钥都是由外部的 CA 签发的，提供更高的安全性和信任度，尤其在有严格合规性要求的环境中。</p><h4 id="使用外部-CA-模式配置-Kubernetes-集群"><a href="#使用外部-CA-模式配置-Kubernetes-集群" class="headerlink" title="使用外部 CA 模式配置 Kubernetes 集群"></a>使用外部 CA 模式配置 Kubernetes 集群</h4><ol><li><p><strong>准备外部 CA 签发的证书和密钥</strong></p><ul><li>你需要从外部 CA 获取以下证书和密钥：<ul><li>CA 证书 (<code>ca.crt</code>)</li><li>kube-apiserver 证书及其密钥 (<code>apiserver.crt</code> 和 <code>apiserver.key</code>)</li><li>kube-controller-manager 证书及其密钥（可选，如果需要）</li><li>kube-scheduler 证书及其密钥（可选，如果需要）</li><li>其他组件所需的证书及其密钥（如 etcd 等）</li></ul></li></ul></li><li><p><strong>创建并配置 Kubernetes 配置文件</strong></p><ul><li>创建一个 kubeadm 配置文件，如 <code>kubeadm-config.yaml</code>，并在其中指定 <code>certificatesDir</code> 和 <code>ClusterConfiguration</code>。示例如下：<figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">kubeadm.k8s.io/v1beta2</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ClusterConfiguration</span></span><br><span class="line"><span class="attr">kubernetesVersion:</span> <span class="string">stable-1.21</span></span><br><span class="line"><span class="attr">certificatesDir:</span> <span class="string">/etc/kubernetes/pki</span></span><br><span class="line"><span class="attr">apiServer:</span></span><br><span class="line">  <span class="attr">certSANs:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">&quot;your.domain.com&quot;</span></span><br><span class="line">   <span class="attr">extraArgs:</span></span><br><span class="line">      <span class="attr">&quot;tls-cert-file&quot;:</span> <span class="string">&quot;/etc/kubernetes/pki/apiserver.crt&quot;</span></span><br><span class="line">      <span class="attr">&quot;tls-private-key-file&quot;:</span> <span class="string">&quot;/etc/kubernetes/pki/apiserver.key&quot;</span></span><br></pre></td></tr></table></figure></li></ul></li><li><p><strong>将外部 CA 签发的证书和密钥放置在指定目录</strong></p><ul><li>复制外部 CA 签发的证书和密钥到 <code>/etc/kubernetes/pki</code> 目录或你在配置文件中指定</li></ul></li></ol><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">sudo <span class="built_in">cp</span> /path/to/ca.crt /etc/kubernetes/pki/ca.crt</span><br><span class="line">sudo <span class="built_in">cp</span> /path/to/apiserver.crt /etc/kubernetes/pki/apiserver.crt</span><br><span class="line">sudo <span class="built_in">cp</span> /path/to/apiserver.key /etc/kubernetes/pki/apiserver.key</span><br></pre></td></tr></table></figure><ol start="4"><li><strong>运行 kubeadm 初始化命令</strong></li></ol><ul><li>使用 kubeadm 初始化命令并指定配置文件来初始化 Kubernetes 集群：<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">sudo kubeadm init --config kubeadm-config.yaml</span><br></pre></td></tr></table></figure></li></ul><h3 id="检查证书"><a href="#检查证书" class="headerlink" title="检查证书"></a>检查证书</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubeadm certs check-expiration</span><br></pre></td></tr></table></figure><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240731161509499.png" alt="image-20240731161509499"></p><p>ps:</p><ol><li><p>kubeadm不能管理外部ca</p></li><li><p>没有kubelet.conf的原因是kubeadm会将kubelet配置为自动更新证书，轮换在<code>/var/lib/kubelet/pki</code></p></li></ol><ul><li>轮询失败暂时参考：<a href="https://kubernetes.io/zh-cn/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm/#kubelet-client-cert">https://kubernetes.io/zh-cn/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm/#kubelet-client-cert</a></li></ul><h3 id="自动更新证书"><a href="#自动更新证书" class="headerlink" title="自动更新证书"></a>自动更新证书</h3><p><code>kubeadm</code> 提供了一种机制，在集群控制面（control plane）升级时自动更新所有证书。这种方式简化了证书管理，并确保在定期升级 Kubernetes 版本时保持集群的安全性。下面是详细的操作步骤和相关说明。</p><h4 id="自动更新证书的机制"><a href="#自动更新证书的机制" class="headerlink" title="自动更新证书的机制"></a>自动更新证书的机制</h4><p>当你使用 <code>kubeadm upgrade apply</code> 命令升级控制面节点时，<code>kubeadm</code> 会自动更新所有的证书。</p><p>进。</p><h4 id="禁用自动证书更新"><a href="#禁用自动证书更新" class="headerlink" title="禁用自动证书更新"></a>禁用自动证书更新</h4><p>如果你有更复杂的证书管理需求，可以选择在升级时禁用自动证书更新。可以通过传递 <code>--certificate-renewal=false</code> 参数来实现。</p><ol><li><p><strong>升级控制面节点时禁用证书更新</strong>：</p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">sudo kubeadm upgrade apply v1.xx.x --certificate-renewal=<span class="literal">false</span></span><br></pre></td></tr></table></figure><p>其中 <code>v1.xx.x</code> 为目标 Kubernetes 版本。</p></li><li><p><strong>升级 worker 节点时禁用证书更新</strong>：</p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">sudo kubeadm upgrade node --certificate-renewal=<span class="literal">false</span></span><br></pre></td></tr></table></figure></li></ol><h4 id="手动启用证书更新"><a href="#手动启用证书更新" class="headerlink" title="手动启用证书更新"></a>手动启用证书更新</h4><p>在 Kubernetes 1.17 版本之前，<code>kubeadm upgrade node</code> 命令的 <code>--certificate-renewal</code> 参数默认值为 <code>false</code>，需要显式地设置为 <code>true</code>。</p><h5 id="显式启用证书更新的操作步骤"><a href="#显式启用证书更新的操作步骤" class="headerlink" title="显式启用证书更新的操作步骤"></a>显式启用证书更新的操作步骤</h5><ol><li><p><strong>升级控制面节点时显式启用证书更新</strong>：</p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">sudo kubeadm upgrade apply v1.xx.x --certificate-renewal=<span class="literal">true</span></span><br></pre></td></tr></table></figure></li><li><p><strong>升级 worker 节点时显式启用证书更新</strong>：</p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">sudo kubeadm upgrade node --certificate-renewal=<span class="literal">true</span></span><br></pre></td></tr></table></figure></li></ol><h3 id="手动更新证书"><a href="#手动更新证书" class="headerlink" title="手动更新证书"></a>手动更新证书</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 执行完此命令之后你需要重启控制面 Pod,运行了一个 HA 集群，这个命令需要在所有控制面板节点上执行。</span></span><br><span class="line">kubeadm certs renew (all)</span><br></pre></td></tr></table></figure><p>ps:kubeadm通常会把<code>admin.conf</code> 证书复制到 <code>$HOME/.kube/config</code> 中，在这样的系统中，为了在更新 <code>admin.conf</code> 后更新 <code>$HOME/.kube/config</code> 的内容， 你必须运行以下命令：</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config</span><br><span class="line">sudo chown $(id -u):$(id -g) $HOME/.kube/config</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;PKI证书&quot;&gt;&lt;a href=&quot;#PKI证书&quot; class=&quot;headerlink&quot; title=&quot;PKI证书&quot;&gt;&lt;/a&gt;PKI证书&lt;/h3&gt;&lt;p&gt;kubernetes是需要PKI才能执行多数操作:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;kubelet的客户端证书:用于API</summary>
      
    
    
    
    <category term="Kubernetes" scheme="https://kalyan-zitiu.github.io/categories/Kubernetes/"/>
    
    
    <category term="Kubernetes" scheme="https://kalyan-zitiu.github.io/tags/Kubernetes/"/>
    
  </entry>
  
  <entry>
    <title>Kubernetes存储基础</title>
    <link href="https://kalyan-zitiu.github.io/2024/07/30/Kubernetes%E5%AD%98%E5%82%A8/"/>
    <id>https://kalyan-zitiu.github.io/2024/07/30/Kubernetes%E5%AD%98%E5%82%A8/</id>
    <published>2024-07-30T07:42:49.000Z</published>
    <updated>2024-08-01T07:53:40.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="卷"><a href="#卷" class="headerlink" title="卷"></a>卷</h2><h3 id="PVC"><a href="#PVC" class="headerlink" title="PVC"></a>PVC</h3><ul><li>用于请求和绑定持久化存储卷pv,PVC 独立于具体的存储实现，可以通过存储类（StorageClass）来动态配置和管理存储资源。</li></ul><h4 id="yaml参考"><a href="#yaml参考" class="headerlink" title="yaml参考"></a>yaml参考</h4><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">PersistentVolumeClaim</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">my-pvc</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">accessModes:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">ReadWriteOnce</span></span><br><span class="line">  <span class="attr">resources:</span></span><br><span class="line">    <span class="attr">requests:</span></span><br><span class="line">      <span class="attr">storage:</span> <span class="string">10Gih</span> </span><br></pre></td></tr></table></figure><h4 id="K-os"><a href="#K-os" class="headerlink" title="K.os"></a>K.os</h4><ul><li>应该是可以理解为通过pvc进行申请后，StorageClass会根据pvc来动态创建pv<h3 id="configMap"><a href="#configMap" class="headerlink" title="configMap"></a>configMap</h3></li><li>于在集群中管理非机密数据配置，将配置信息从代码中分离出来，注入配置数据的方法，便于管理和更新。</li></ul><h4 id="K-os-1"><a href="#K-os-1" class="headerlink" title="K.os"></a>K.os</h4><ul><li>可以用键值得形式存储重要数据</li></ul><h3 id="secret"><a href="#secret" class="headerlink" title="secret"></a>secret</h3><p>可以参考： </p><h2 id="持久卷"><a href="#持久卷" class="headerlink" title="持久卷"></a>持久卷</h2><p>为Pod提供独立于Pod生命周期的持久存储。</p><h3 id="PV"><a href="#PV" class="headerlink" title="PV"></a>PV</h3><ul><li>一块存储资源。它是集群级别的资源，与Pod的生命周期分离。PV可以由管理员预先创建，也可以通过存储类动态创建。</li></ul><h4 id="静态"><a href="#静态" class="headerlink" title="静态"></a>静态</h4><ul><li>写完直接apply<figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">PersistentVolumeClaim</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">my-pvc</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">accessModes:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">ReadWriteOnce</span></span><br><span class="line">  <span class="attr">resources:</span></span><br><span class="line">    <span class="attr">requests:</span></span><br><span class="line">      <span class="attr">storage:</span> <span class="string">10Gi</span></span><br></pre></td></tr></table></figure><h4 id="动态"><a href="#动态" class="headerlink" title="动态"></a>动态</h4></li><li>需要一个存储类StorageClass进行动态申领，就是想定义好StorageClass，再进行pvc进行获取</li></ul><h4 id="绑定"><a href="#绑定" class="headerlink" title="绑定"></a>绑定</h4><ul><li>Kubernetes会根据PVC的需求自动寻找和绑定合适的PV。</li></ul><h4 id="回收"><a href="#回收" class="headerlink" title="回收"></a>回收</h4><ul><li>当PVC被删除后，PV的回收策略决定了PV的处理方式。回收策略有三种：Retain、Recycle和Delete。</li></ul><ol><li>Retain：保留数据，管理员可以手动处理数据。</li><li>Recycle：清空数据后重新供PVC使用（已弃用）。</li><li>Delete：删除PV和存储数据。</li></ol><h4 id="K-os-2"><a href="#K-os-2" class="headerlink" title="K.os"></a>K.os</h4><ul><li>可以理解成物理卷一样，都是可以当作一块存储。但是后续的操作不一样，this.pv是能够通过StorageClass动态创建。</li></ul><h3 id="投射卷"><a href="#投射卷" class="headerlink" title="投射卷"></a>投射卷</h3><ul><li>将多种不同类型的数据源投射到 Pod 内的单个卷中。这些数据源包括 Secret、ConfigMap、Downward API 和 ServiceAccount Token 等。投射卷的一个主要优势是，它可以将多个来源的数据整合到一个挂载点，从而简化了数据管理和使用。</li></ul><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">projected-volume-pod</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">containers:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">my-container</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">nginx</span></span><br><span class="line">    <span class="attr">volumeMounts:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">my-projected-volume</span></span><br><span class="line">      <span class="attr">mountPath:</span> <span class="string">/etc/projected-volume</span></span><br><span class="line">  <span class="attr">volumes:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">my-projected-volume</span></span><br><span class="line"><span class="comment"># 这里11111</span></span><br><span class="line">    <span class="attr">projected:</span></span><br><span class="line">      <span class="attr">sources:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">configMap:</span></span><br><span class="line">          <span class="attr">name:</span> <span class="string">my-config</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">secret:</span></span><br><span class="line">          <span class="attr">name:</span> <span class="string">my-secret</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">downwardAPI:</span></span><br><span class="line">          <span class="attr">items:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">path:</span> <span class="string">&quot;labels&quot;</span></span><br><span class="line">            <span class="attr">fieldRef:</span></span><br><span class="line">              <span class="attr">fieldPath:</span> <span class="string">metadata.labels</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">serviceAccountToken:</span></span><br><span class="line">          <span class="attr">path:</span> <span class="string">&quot;token&quot;</span></span><br><span class="line">          <span class="attr">expirationSeconds:</span> <span class="number">3600</span></span><br><span class="line">          <span class="attr">audience:</span> <span class="string">&quot;api&quot;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="存储类"><a href="#存储类" class="headerlink" title="存储类"></a><strong>存储类</strong></h3><p>用来定义PV的资源对象</p><h4 id="属性"><a href="#属性" class="headerlink" title="属性"></a>属性</h4><p>Provisioner：定义由谁负责提供存储资源。不同的 Provisioner 对应不同的存储系统，如 kubernetes.io/aws-ebs 对应 AWS 的 EBS 存储，kubernetes.io/gce-pd 对应 Google Cloud 的 Persistent Disk，等等。</p><p>Parameters：提供给存储系统的参数。例如，对于 AWS EBS，可以指定卷类型（如 gp2、io1 等）、IOPS 等参数。</p><p>ReclaimPolicy：定义 PV 被释放后如何处理。有两种策略：</p><p>Retain：保留存储资源供管理员手动回收。<br>Delete：自动删除存储资源。<br>AllowVolumeExpansion：指示是否允许动态扩展存储卷大小。</p><p>MountOptions：提供给挂载卷的选项，这些选项会应用于挂载存储卷时。</p><p>VolumeBindingMode：定义 PV 的绑定模式，主要有两种：</p><p>Immediate：PV 会立即绑定到 PVC。<br>WaitForFirstConsumer：PV 会等待第一个消费者（Pod）出现后再绑定，以便更好地优化存储资源分配。</p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">storage.k8s.io/v1</span>  <span class="comment"># 指定API版本</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">StorageClass</span>            <span class="comment"># 声明资源类型为StorageClass</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">fast</span>                  <span class="comment"># StorageClass的名称，用户定义的标识</span></span><br><span class="line"><span class="attr">provisioner:</span> <span class="string">kubernetes.io/aws-ebs</span>  <span class="comment"># 指定Provisioner类型，这里使用AWS EBS作为存储提供者</span></span><br><span class="line"><span class="attr">parameters:</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">io1</span>                   <span class="comment"># 指定AWS EBS卷的类型，这里使用io1类型</span></span><br><span class="line">  <span class="attr">iopsPerGB:</span> <span class="string">&quot;10&quot;</span>             <span class="comment"># 指定每GB卷的IOPS（仅对io1类型有效）</span></span><br><span class="line">  <span class="attr">fsType:</span> <span class="string">ext4</span>                <span class="comment"># 指定文件系统类型，默认为ext4</span></span><br><span class="line"><span class="attr">reclaimPolicy:</span> <span class="string">Retain</span>         <span class="comment"># 设置回收策略，Retain表示保留PV供管理员手动回收</span></span><br><span class="line"><span class="attr">allowVolumeExpansion:</span> <span class="literal">true</span>    <span class="comment"># 允许动态扩展存储卷大小</span></span><br><span class="line"><span class="attr">mountOptions:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">debug</span>                     <span class="comment"># 挂载卷时的选项，这里使用debug模式</span></span><br><span class="line"><span class="attr">volumeBindingMode:</span> <span class="string">WaitForFirstConsumer</span>  <span class="comment"># 设置卷绑定模式，WaitForFirstConsumer表示等待第一个消费者出现再绑定</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;卷&quot;&gt;&lt;a href=&quot;#卷&quot; class=&quot;headerlink&quot; title=&quot;卷&quot;&gt;&lt;/a&gt;卷&lt;/h2&gt;&lt;h3 id=&quot;PVC&quot;&gt;&lt;a href=&quot;#PVC&quot; class=&quot;headerlink&quot; title=&quot;PVC&quot;&gt;&lt;/a&gt;PVC&lt;/h3&gt;&lt;ul&gt;
&lt;</summary>
      
    
    
    
    <category term="kubernetes" scheme="https://kalyan-zitiu.github.io/categories/kubernetes/"/>
    
    
    <category term="kubernetes" scheme="https://kalyan-zitiu.github.io/tags/kubernetes/"/>
    
  </entry>
  
  <entry>
    <title>基于containerd的kubernetes集群建设</title>
    <link href="https://kalyan-zitiu.github.io/2024/07/26/%E5%9F%BA%E4%BA%8Econtainerd%E7%9A%84kubernetes%E9%9B%86%E7%BE%A4%E5%BB%BA%E8%AE%BE/"/>
    <id>https://kalyan-zitiu.github.io/2024/07/26/%E5%9F%BA%E4%BA%8Econtainerd%E7%9A%84kubernetes%E9%9B%86%E7%BE%A4%E5%BB%BA%E8%AE%BE/</id>
    <published>2024-07-26T01:40:58.000Z</published>
    <updated>2024-08-20T03:02:08.217Z</updated>
    
    <content type="html"><![CDATA[<h2 id="环境准备"><a href="#环境准备" class="headerlink" title="环境准备"></a>环境准备</h2><h3 id="节点资源规划（仅学习）"><a href="#节点资源规划（仅学习）" class="headerlink" title="节点资源规划（仅学习）"></a>节点资源规划（仅学习）</h3><p>资源规划：一个master，两个work（非测试不建议这种模式，无高可用）<br>master： 16c,32g,200G,200G(空)<br>work : 16c,32g,200G,200G(空)</p><h3 id="选择安装工具"><a href="#选择安装工具" class="headerlink" title="选择安装工具"></a>选择安装工具</h3><ol><li>首先DNS更正223.5.5.5，223.6.6.6</li><li>选择后国内清华源的K8s软件库：</li></ol><ul><li><a href="https://mirrors.tuna.tsinghua.edu.cn/help/kubernetes/">https://mirrors.tuna.tsinghua.edu.cn/help/kubernetes/</a></li></ul><ol start="3"><li>选择containerd运行时</li><li>安装ipvs</li></ol><p>个人理解：环境主要在三节点上有kubelet，kubectl，主节点多一个初始化的kubeadm。然后主节点用kubeadm进行初始化主节点，然后进行containerd运行时进行组件的拉取和运行。组成一个集群。</p><h3 id="设置"><a href="#设置" class="headerlink" title="设置"></a>设置</h3><p>各种安装过程我们跳过哈,然后我们深度聊一聊一些环境的设置</p><h4 id="环境设置"><a href="#环境设置" class="headerlink" title="环境设置"></a>环境设置</h4><h5 id="内核参数调整"><a href="#内核参数调整" class="headerlink" title="内核参数调整"></a>内核参数调整</h5><h6 id="什么是内核参数呢，会影响什么"><a href="#什么是内核参数呢，会影响什么" class="headerlink" title="什么是内核参数呢，会影响什么"></a>什么是内核参数呢，会影响什么</h6><p>内核参数是配置Linux内核行为的设置。这些参数控制系统的各种功能，如内存管理、网络设置、文件系统行为等。内核参数通常通过/etc/sysctl.conf文件进行配置，并通过sysctl命令加载和应用。常用的内核参数请看<br><a href="https://blog.zitiu.top/2024/07/01/linux%E4%B8%8D%E5%90%8C%E5%8F%91%E8%A1%8C%E7%89%88%E7%9A%84%E5%8C%BA%E5%88%AB/">Linux从核心到边缘 | Kalyan的小书房 (zitiu.top)</a></p><h6 id="需要调整的内核参数"><a href="#需要调整的内核参数" class="headerlink" title="需要调整的内核参数"></a>需要调整的内核参数</h6><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="string">vm.swappiness</span> <span class="string">=</span> <span class="number">0</span>  <span class="comment"># 减少swap分区使用</span></span><br><span class="line"><span class="string">net.ipv4.ip_forward</span> <span class="string">=</span> <span class="number">1</span> <span class="comment"># 允许linux内核将网络流量从一个网络接口转发到另一个网络接口</span></span><br><span class="line"><span class="string">net.bridge.bridge-nf-call-iptables=1</span> <span class="comment"># 启用 bridge-nf-call-iptables</span></span><br><span class="line"><span class="string">net.ipv4.ip_forward=1</span> <span class="comment"># 启用 IP 转发</span></span><br></pre></td></tr></table></figure><p>这里通常会有一个问题，当你sysctl -p采用的时候可能会报错</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">sysctl: cannot <span class="built_in">stat</span> /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory</span><br><span class="line">sysctl: cannot <span class="built_in">stat</span> /proc/sys/net/bridge/bridge-nf-call-ip6tables: No such file or directory</span><br></pre></td></tr></table></figure><p>这个时候你可以</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 启用 bridge-nf-call-iptables</span></span><br><span class="line">sudo modprobe br_netfilter</span><br><span class="line"><span class="built_in">echo</span> 1 | sudo <span class="built_in">tee</span> /proc/sys/net/bridge/bridge-nf-call-iptables</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;net.bridge.bridge-nf-call-iptables=1&quot;</span> | sudo <span class="built_in">tee</span> -a /etc/sysctl.conf</span><br><span class="line">sudo sysctl -p</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启用 IP 转发</span></span><br><span class="line"><span class="built_in">echo</span> 1 | sudo <span class="built_in">tee</span> /proc/sys/net/ipv4/ip_forward</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;net.ipv4.ip_forward=1&quot;</span> | sudo <span class="built_in">tee</span> -a /etc/sysctl.conf</span><br><span class="line">sudo sysctl -p</span><br></pre></td></tr></table></figure><p>最后进行微调</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建一个文件，将需要的内核模块写入其中，以便在系统启动时自动加载这些模块</span></span><br><span class="line"><span class="built_in">tee</span> /etc/modules-load.d/k8s.conf &lt;&lt;<span class="string">&#x27;EOF&#x27;</span></span><br><span class="line"><span class="comment"># netfilter 模块，允许 iptables 检查桥接流量</span></span><br><span class="line">br_netfilter</span><br><span class="line"><span class="comment"># containerd 文件系统支持</span></span><br><span class="line">overlay</span><br><span class="line"><span class="comment"># IPVS (IP Virtual Server) 模块，用于负载均衡</span></span><br><span class="line">ip_vs</span><br><span class="line"><span class="comment"># 轮叫调度算法</span></span><br><span class="line">ip_vs_rr</span><br><span class="line"><span class="comment"># 加权轮叫调度算法</span></span><br><span class="line">ip_vs_wrr</span><br><span class="line"><span class="comment"># 源地址散列调度算法</span></span><br><span class="line">ip_vs_sh</span><br><span class="line"><span class="comment"># 连接跟踪模块，用于跟踪网络连接状态</span></span><br><span class="line">nf_conntrack</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 创建目录以存放模块加载脚本</span></span><br><span class="line"><span class="built_in">mkdir</span> -vp /etc/modules.d/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建一个脚本文件，立即加载所需的内核模块</span></span><br><span class="line"><span class="built_in">cat</span> &gt; /etc/modules.d/k8s.modules &lt;&lt;<span class="string">EOF</span></span><br><span class="line"><span class="string">#!/bin/bash</span></span><br><span class="line"><span class="string"># 允许 iptables 检查桥接流量</span></span><br><span class="line"><span class="string">modprobe -- br_netfilter</span></span><br><span class="line"><span class="string"># containerd 文件系统支持</span></span><br><span class="line"><span class="string">modprobe -- overlay</span></span><br><span class="line"><span class="string"># IPVS 模块，用于负载均衡</span></span><br><span class="line"><span class="string">modprobe -- ip_vs</span></span><br><span class="line"><span class="string"># 轮叫调度算法</span></span><br><span class="line"><span class="string">modprobe -- ip_vs_rr</span></span><br><span class="line"><span class="string"># 加权轮叫调度算法</span></span><br><span class="line"><span class="string">modprobe -- ip_vs_wrr</span></span><br><span class="line"><span class="string"># 源地址散列调度算法</span></span><br><span class="line"><span class="string">modprobe -- ip_vs_sh</span></span><br><span class="line"><span class="string"># 连接跟踪模块，用于跟踪网络连接状态</span></span><br><span class="line"><span class="string">modprobe -- nf_conntrack</span></span><br><span class="line"><span class="string">EOF</span></span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 给脚本文件赋予执行权限</span></span><br><span class="line"><span class="built_in">chmod</span> 755 /etc/modules.d/k8s.modules</span><br><span class="line"></span><br><span class="line"><span class="comment"># 运行脚本，立即加载所需的内核模块</span></span><br><span class="line">bash /etc/modules.d/k8s.modules</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证内核模块是否加载成功，查看加载的模块列表中是否包含 ip_vs 和 nf_conntrack 模块</span></span><br><span class="line">lsmod | grep -e ip_vs -e nf_conntrack</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 应用 sysctl 配置，确保所有内核参数设置立即生效</span></span><br><span class="line">sysctl --system</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 重启系统，确保所有配置在系统重启后自动生效</span></span><br><span class="line">reboot</span><br></pre></td></tr></table></figure><h5 id="什么是swap分区-为什么要删除"><a href="#什么是swap分区-为什么要删除" class="headerlink" title="什么是swap分区,为什么要删除."></a>什么是swap分区,为什么要删除.</h5><ul><li>你可以把swap分区简单理解成是为了分担RAM的负担的这么一个作用,你可以想象一下你有一个书桌,你工作的时候,为了快速获取资料,你会在书桌上堆满书本,这个时候swap就像书架一样,在书架取书会有点慢,但是你起码有位置放书.</li></ul><ul><li><p>那么为什么我们要在kubernetes中要删除呢,继续刚刚的比喻,现在一个研究馆内,有很多书桌(节点),管理人员(k8s调度器)会根据每个人的书桌的容量进行任务的合理分配.如果启动了书架(swap),管理人员可能不知道,你书桌上的实际容量,要是书桌(RAM)把大量资源放到了书架(swap)上,管理人员(调度器)看你的书桌(RAM)空闲,把大量的资源工作丢给你,可能会导致书桌(RAM)的坍塌</p></li><li><p>一句话:k8s调度器无法知道swap分区里面的情况.</p></li></ul><h5 id="防火墙"><a href="#防火墙" class="headerlink" title="防火墙"></a>防火墙</h5><p>这个就不说了,主要是为了更好的后续node以及pod会有自己的网络体系,为了适配关掉最好.</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">ufw <span class="built_in">disable</span> &amp;&amp; systemctl <span class="built_in">disable</span> ufw</span><br><span class="line">swapoff -a &amp;&amp; sed -i <span class="string">&#x27;s|^/swap.img|#/swap.ing|g&#x27;</span> /etc/fstab</span><br></pre></td></tr></table></figure><h5 id="加入清华源后安装系列工具"><a href="#加入清华源后安装系列工具" class="headerlink" title="加入清华源后安装系列工具"></a>加入清华源后安装系列工具</h5><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">apt install containerd -y </span><br><span class="line"><span class="comment"># 启动</span></span><br><span class="line">systemctl daemon-reload</span><br><span class="line">systemctl <span class="built_in">enable</span> containerd</span><br><span class="line">systemctl restart containerd</span><br></pre></td></tr></table></figure><h5 id="containerd设置-配置runtime-endpoint"><a href="#containerd设置-配置runtime-endpoint" class="headerlink" title="containerd设置-配置runtime-endpoint"></a>containerd设置-配置runtime-endpoint</h5><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># containerd - 运行时设置,这一步不能出错</span></span><br><span class="line">crictl config runtime-endpoint /run/containerd/containerd.sock</span><br></pre></td></tr></table></figure><p>要是出现无法连接的情况就检查三个地方</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 是否有/etc/containerd/config.toml 用于配置管理containerd容器运行时守护进程的行为。</span></span><br><span class="line"><span class="built_in">mkdir</span> -vp /etc/containerd/</span><br><span class="line">containerd config default &gt; /etc/containerd/config.toml</span><br><span class="line"><span class="comment"># 将配置文件中所有出现的 k8s.gcr.io 替换为 registry.cn-hangzhou.aliyuncs.com/google_containers</span></span><br><span class="line">sed -i <span class="string">&quot;s#k8s.gcr.io#registry.cn-hangzhou.aliyuncs.com/google_containers#g&quot;</span>  /etc/containerd/config.toml</span><br><span class="line"><span class="comment"># 这里有点问题，需要提前把SystemdCgroup = false删除掉，否则会有重复定义的错误。</span></span><br><span class="line">sed -i <span class="string">&#x27;/containerd.runtimes.runc.options/a\ \ \ \ \ \ \ \ \ \ \ \ SystemdCgroup = true&#x27;</span> /etc/containerd/config.toml</span><br><span class="line"><span class="comment"># 修改版</span></span><br><span class="line">CONFIG_FILE=<span class="string">&quot;/etc/containerd/config.toml&quot;</span>; grep -q <span class="string">&#x27;SystemdCgroup&#x27;</span> <span class="string">&quot;<span class="variable">$CONFIG_FILE</span>&quot;</span> &amp;&amp; sed -i <span class="string">&#x27;s/SystemdCgroup =.*/SystemdCgroup = true/&#x27;</span> <span class="string">&quot;<span class="variable">$CONFIG_FILE</span>&quot;</span> || sed -i <span class="string">&#x27;/containerd.runtimes.runc.options/a\ \ \ \ \ \ \ \ \ \ \ \ SystemdCgroup = true&#x27;</span> <span class="string">&quot;<span class="variable">$CONFIG_FILE</span>&quot;</span></span><br><span class="line"><span class="comment"># 将配置文件中所有出现的 https://registry-1.docker.io 替换为 https://xlx9erfu.mirror.aliyuncs.com。</span></span><br><span class="line">sed -i <span class="string">&quot;s#https://registry-1.docker.io#https://xlx9erfu.mirror.aliyuncs.com#g&quot;</span>  /etc/containerd/config.toml</span><br><span class="line"><span class="comment"># 是否有/etc/crictl.yaml</span></span><br><span class="line">runtime-endpoint: <span class="string">&quot;unix:///run/containerd/containerd.sock&quot;</span></span><br><span class="line">image-endpoint: <span class="string">&quot;&quot;</span></span><br><span class="line"><span class="built_in">timeout</span>: 0</span><br><span class="line">debug: <span class="literal">false</span></span><br><span class="line">pull-image-on-create: <span class="literal">false</span></span><br><span class="line">disable-pull-on-run: <span class="literal">false</span></span><br><span class="line"><span class="comment"># 是否有/run/containerd/containerd.sock</span></span><br></pre></td></tr></table></figure><h5 id="验证containerd的情况"><a href="#验证containerd的情况" class="headerlink" title="验证containerd的情况"></a>验证containerd的情况</h5><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 能看这个套接字sock是否有正常连接到crictl工具</span></span><br><span class="line">crictl info </span><br><span class="line"><span class="comment"># 能够查询失败部署容器</span></span><br><span class="line">crictl ps -a | grep kube | grep -v pause</span><br><span class="line"><span class="comment"># 能够查看日志</span></span><br><span class="line">crictl  logs CONTAINERID</span><br></pre></td></tr></table></figure><h3 id="初始化主节点"><a href="#初始化主节点" class="headerlink" title="初始化主节点"></a>初始化主节点</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 生产配置模板，自己把imageRepository改成自己加速的镜像源。</span></span><br><span class="line">kubeadm config <span class="built_in">print</span> init-defaults &gt; kubeadm.yaml</span><br><span class="line"><span class="comment">#初始化</span></span><br><span class="line">kubeadm init --config=kubeadm.yaml --v=5</span><br><span class="line"><span class="comment"># 查看镜像列表</span></span><br><span class="line">kubeadm config images list</span><br><span class="line"><span class="comment"># 然后进行拉取</span></span><br><span class="line">crictl pull</span><br></pre></td></tr></table></figure><p>ps:一定要仔细配置kubeadm。</p><p>要是containerd有问题的话，修改过config.toml，记得restart一下然后记得</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubeadm reset -f --cri-socket unix:///run/containerd/containerd.sock</span><br></pre></td></tr></table></figure><p>ps:修改镜像源后记得修改一下containerd里面的pause的镜像源。</p><p>给个样板在这里：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">apiVersion: kubeadm.k8s.io/v1beta3</span><br><span class="line">bootstrapTokens:</span><br><span class="line">- <span class="built_in">groups</span>:</span><br><span class="line">  - system:bootstrappers:kubeadm:default-node-token</span><br><span class="line">  token: abcdef.0123456789abcdef</span><br><span class="line">  ttl: 24h0m0s</span><br><span class="line">  usages:</span><br><span class="line">  - signing</span><br><span class="line">  - authentication</span><br><span class="line">kind: InitConfiguration</span><br><span class="line">localAPIEndpoint:</span><br><span class="line">  advertiseAddress: 10.70.49.131 <span class="comment"># 必填</span></span><br><span class="line">  bindPort: 6443</span><br><span class="line">nodeRegistration:</span><br><span class="line">  criSocket: unix:///run/containerd/containerd.sock <span class="comment">#最好加上unix://</span></span><br><span class="line">  imagePullPolicy: IfNotPresent <span class="comment"># 可以忽略镜像拉取，后续可以手动拉</span></span><br><span class="line">  name: masternode-1 <span class="comment"># 必填</span></span><br><span class="line">  taints: null</span><br><span class="line">---</span><br><span class="line">apiServer:</span><br><span class="line">  timeoutForControlPlane: 4m0s</span><br><span class="line">apiVersion: kubeadm.k8s.io/v1beta3</span><br><span class="line">certificatesDir: /etc/kubernetes/pki</span><br><span class="line">clusterName: kubernetes</span><br><span class="line">controllerManager: &#123;&#125;</span><br><span class="line">dns: <span class="comment"># dns有点ex，注意镜像源</span></span><br><span class="line">  <span class="built_in">type</span>: CoreDNS</span><br><span class="line">  imageRepository: k8s.m.daocloud.io/coredns</span><br><span class="line">  imageTag: v1.10.1</span><br><span class="line">etcd:</span><br><span class="line">  <span class="built_in">local</span>:</span><br><span class="line">    dataDir: /var/lib/etcd</span><br><span class="line">imageRepository: k8s.m.daocloud.io</span><br><span class="line">kind: ClusterConfiguration</span><br><span class="line">kubernetesVersion: 1.28.0</span><br><span class="line">networking:</span><br><span class="line">  dnsDomain: cluster.local</span><br><span class="line">  serviceSubnet: 10.96.0.0/12</span><br><span class="line">  podSubnet: 10.244.0.0/16</span><br><span class="line">scheduler: &#123;&#125;</span><br><span class="line">---</span><br><span class="line">apiVersion: kubeproxy.config.k8s.io/v1alpha1</span><br><span class="line">kind: KubeProxyConfiguration</span><br><span class="line">mode: ipvs <span class="comment"># 开启ipvs模式</span></span><br><span class="line">---</span><br><span class="line">apiVersion: kubelet.config.k8s.io/v1beta1</span><br><span class="line">kind: KubeletConfiguration</span><br><span class="line">cgroupDriver: systemd</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="calico"><a href="#calico" class="headerlink" title="calico"></a>calico</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">wget https://docs.projectcalico.org/v3.18/manifests/calico.yaml</span><br></pre></td></tr></table></figure><p>然后自己配置一下</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240730105948262.png" alt="image-20240730105948262"></p><p>然后apply一下。等待跑起来</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240730143740906.png" alt="image-20240730143740906"></p><p>哪个拉不起来就去对应的controlby，或者直接deploy上修改image。然后正常来说的话就基本node全部ready</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240730143852876.png" alt="image-20240730143852876"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;环境准备&quot;&gt;&lt;a href=&quot;#环境准备&quot; class=&quot;headerlink&quot; title=&quot;环境准备&quot;&gt;&lt;/a&gt;环境准备&lt;/h2&gt;&lt;h3 id=&quot;节点资源规划（仅学习）&quot;&gt;&lt;a href=&quot;#节点资源规划（仅学习）&quot; class=&quot;headerlink&quot; ti</summary>
      
    
    
    
    <category term="kubernetes" scheme="https://kalyan-zitiu.github.io/categories/kubernetes/"/>
    
    
    <category term="kubernetes" scheme="https://kalyan-zitiu.github.io/tags/kubernetes/"/>
    
  </entry>
  
  <entry>
    <title>排错杂记（pod error）</title>
    <link href="https://kalyan-zitiu.github.io/2024/07/24/%E6%8E%92%E9%9A%9C%E6%97%A5%E5%BF%97%EF%BC%88updating%EF%BC%89/"/>
    <id>https://kalyan-zitiu.github.io/2024/07/24/%E6%8E%92%E9%9A%9C%E6%97%A5%E5%BF%97%EF%BC%88updating%EF%BC%89/</id>
    <published>2024-07-24T02:44:28.000Z</published>
    <updated>2024-07-24T08:28:41.582Z</updated>
    
    <content type="html"><![CDATA[<h3 id="尝试排错"><a href="#尝试排错" class="headerlink" title="尝试排错"></a>尝试排错</h3><p>起因是拉起某个pod的时候持续不断的错误边拉边寄，显示的不是image问题。</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724104653156.png" alt="image-20240724104653156"></p><p>尝试describe一下，发现调度，拉取，创建，启动似乎都正常</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724104802500.png" alt="image-20240724104802500"></p><p>这个时候就得去看日志kubectl log一下，</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724104835975.png" alt="image-20240724104835975"></p><p>？？？timeout？？？kubectl 正常能get不至于访问不到api，api是包正常的。</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724104918625.png" alt="image-20240724104918625"></p><p>那就是网络问题，先看一下插件，插件也正常。</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724105000612.png" alt="image-20240724105000612"></p><p>再看DNS，似乎有点问题，丢了master3的conredns？？？</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724105033529.png" alt="image-20240724105033529"></p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724105351232.png" alt="image-20240724105351232"></p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724105355465.png" alt="image-20240724105355465"></p><p>但是查询后这个pod的是属于master1的pod所以不是dns的问题，缺一个的问题后面再解决。<br>按着尝试手动再吃连接api服务器,草pod fail了，所以用不了，先标记</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">kubectl <span class="built_in">exec</span> -it kcollie-pre-hook-install-crds-bdb4g -n kcollie-system -- /bin/sh</span><br><span class="line">curl -k https://10.233.0.1:433</span><br></pre></td></tr></table></figure><p>再check一下kube-system的pod</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724110135451.png" alt="image-20240724110135451"></p><p>md草了，有屎啊，节点二怎么就timeout了，相继的节点一三也爆屎了。</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724111053894.png" alt="image-20240724111053894"></p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724111922571.png" alt="image-20240724111922571"></p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724112010432.png" alt="image-20240724112010432"></p><p>看一下节点情况，感觉可以rollout整个kube-system，完蛋，怎么查个pod状态，查到整个kube崩了</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724112656575.png" alt="image-20240724112656575"></p><p>直接rollout所有</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 重启所有 Deployments</span></span><br><span class="line"><span class="keyword">for</span> deployment <span class="keyword">in</span> $(kubectl get deployments -n kube-system -o jsonpath=<span class="string">&#x27;&#123;.items[*].metadata.name&#125;&#x27;</span>); <span class="keyword">do</span></span><br><span class="line">  kubectl rollout restart deployment <span class="variable">$deployment</span> -n kube-system</span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启所有 StatefulSets</span></span><br><span class="line"><span class="keyword">for</span> statefulset <span class="keyword">in</span> $(kubectl get statefulsets -n kube-system -o jsonpath=<span class="string">&#x27;&#123;.items[*].metadata.name&#125;&#x27;</span>); <span class="keyword">do</span></span><br><span class="line">  kubectl rollout restart statefulset <span class="variable">$statefulset</span> -n kube-system</span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启所有 DaemonSets</span></span><br><span class="line"><span class="keyword">for</span> daemonset <span class="keyword">in</span> $(kubectl get daemonsets -n kube-system -o jsonpath=<span class="string">&#x27;&#123;.items[*].metadata.name&#125;&#x27;</span>); <span class="keyword">do</span></span><br><span class="line">  kubectl rollout restart daemonset <span class="variable">$daemonset</span> -n kube-system</span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>总算是起来了，然后有一个node还是not ready，估计是node3的某些pod还没好，但是报错还是</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724125055556.png" alt="image-20240724125055556"></p><p>不懂，node1的apiserver明明好好的，coredns也没问题。</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240724130355768.png" alt="image-20240724130355768"></p><p>又死了，草啊啊啊啊啊啊啊啊啊啊。节点不知道为什么十分的不稳定，似乎不断崩溃重启，直接停机加内存。</p><p>估计上面的Error是不怎么影响的。。。。。。。。重启然后就没事了。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;尝试排错&quot;&gt;&lt;a href=&quot;#尝试排错&quot; class=&quot;headerlink&quot; title=&quot;尝试排错&quot;&gt;&lt;/a&gt;尝试排错&lt;/h3&gt;&lt;p&gt;起因是拉起某个pod的时候持续不断的错误边拉边寄，显示的不是image问题。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https:</summary>
      
    
    
    
    <category term="杂记" scheme="https://kalyan-zitiu.github.io/categories/%E6%9D%82%E8%AE%B0/"/>
    
    
    <category term="杂记" scheme="https://kalyan-zitiu.github.io/tags/%E6%9D%82%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>Kind基础</title>
    <link href="https://kalyan-zitiu.github.io/2024/07/24/Kind/"/>
    <id>https://kalyan-zitiu.github.io/2024/07/24/Kind/</id>
    <published>2024-07-24T01:58:31.000Z</published>
    <updated>2024-07-24T08:22:58.302Z</updated>
    
    <content type="html"><![CDATA[<h2 id="KIND（Kubernetes-IN-Docker）"><a href="#KIND（Kubernetes-IN-Docker）" class="headerlink" title="KIND（Kubernetes IN Docker）"></a>KIND（Kubernetes IN Docker）</h2><h3 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h3><p>KIND，全称“Kubernetes IN Docker”，是一个开源工具，用于在本地开发和测试 Kubernetes 集群。KIND 允许在 Docker 容器中运行 Kubernetes 集群，从而便于开发者快速创建和销毁 Kubernetes 集群，提升开发效率。</p><h3 id="安装和配置"><a href="#安装和配置" class="headerlink" title="安装和配置"></a>安装和配置</h3><h4 id="前置条件"><a href="#前置条件" class="headerlink" title="前置条件"></a>前置条件</h4><p>在使用 KIND 之前，你需要确保以下软件已经正确安装：<br>Docker<br>kubectl<br>确保 Docker 已经启动，并且你的用户在 docker 组中，以便能够运行 Docker 命令而无需 sudo。</p><h4 id="安装-KIND"><a href="#安装-KIND" class="headerlink" title="安装 KIND"></a>安装 KIND</h4><p>在 Linux 环境中，可以通过以下命令获取和安装 KIND：</p><p>curl -Lo ./kind <a href="https://kind.sigs.k8s.io/dl/v0.11.1/kind-linux-amd64">https://kind.sigs.k8s.io/dl/v0.11.1/kind-linux-amd64</a><br>chmod +x ./kind<br>sudo mv ./kind /usr/local/bin/kind</p><h4 id="检查安装"><a href="#检查安装" class="headerlink" title="检查安装"></a>检查安装</h4><p>验证 KIND 是否安装成功：</p><p>kind –version<br>你应该看到类似 kind v0.11.1 的输出。</p><h3 id="创建-Kubernetes-集群"><a href="#创建-Kubernetes-集群" class="headerlink" title="创建 Kubernetes 集群"></a>创建 Kubernetes 集群</h3><h4 id="简单创建一个集群"><a href="#简单创建一个集群" class="headerlink" title="简单创建一个集群"></a>简单创建一个集群</h4><p>使用以下命令创建一个默认的 Kubernetes 集群：</p><p>kind create cluster<br>成功创建后，你会看到与集群相关的信息输出。</p><h4 id="自定义配置创建集群"><a href="#自定义配置创建集群" class="headerlink" title="自定义配置创建集群"></a>自定义配置创建集群</h4><p>为了更具定制化，可以使用 YAML 文件：</p><p>创建 kind-config.yaml 文件：</p><p>kind: Cluster<br>apiVersion: kind.x-k8s.io/v1alpha4<br>nodes:</p><ul><li>role: control-plane</li><li>role: worker</li><li>role: worker<br>使用以下命令创建集群：</li></ul><p>kind create cluster –config kind-config.yaml</p><h4 id="查看集群状态"><a href="#查看集群状态" class="headerlink" title="查看集群状态"></a>查看集群状态</h4><p>验证集群状态：</p><p>kubectl cluster-info –context kind-kind</p><h3 id="实战操作"><a href="#实战操作" class="headerlink" title="实战操作"></a>实战操作</h3><h4 id="部署应用到-KIND-集群"><a href="#部署应用到-KIND-集群" class="headerlink" title="部署应用到 KIND 集群"></a>部署应用到 KIND 集群</h4><p>创建一个名为 nginx-deployment.yaml 的文件：</p><p>apiVersion: apps/v1<br>kind: Deployment<br>metadata:<br>  name: nginx-deployment<br>spec:<br>  replicas: 3<br>  selector:<br>    matchLabels:<br>      app: nginx<br>  template:<br>    metadata:<br>      labels:<br>        app: nginx<br>    spec:<br>      containers:<br>      - name: nginx<br>        image: nginx:1.14.2<br>        ports:<br>        - containerPort: 80<br>使用 kubectl 部署：</p><p>kubectl apply -f nginx-deployment.yaml</p><h4 id="验证部署"><a href="#验证部署" class="headerlink" title="验证部署"></a>验证部署</h4><p>查看部署的状态：</p><p>kubectl get deployments<br>查看 Pods 状态：</p><p>kubectl get pods</p><h4 id="暴露服务"><a href="#暴露服务" class="headerlink" title="暴露服务"></a>暴露服务</h4><p>创建一个名为 nginx-service.yaml 的文件：</p><p>kind: Service<br>apiVersion: v1<br>metadata:<br>  name: nginx-service<br>spec:<br>  selector:<br>    app: nginx<br>  ports:</p><ul><li>protocol: TCP<br>port: 80<br>targetPort: 80<br>type: LoadBalancer<br>使用 kubectl 暴露服务：</li></ul><p>kubectl apply -f nginx-service.yaml</p><h3 id="KIND的应用场景和作用"><a href="#KIND的应用场景和作用" class="headerlink" title="KIND的应用场景和作用"></a>KIND的应用场景和作用</h3><h4 id="开发和测试环境"><a href="#开发和测试环境" class="headerlink" title="开发和测试环境"></a>开发和测试环境</h4><p>在本地开发和测试 Kubernetes 应用，KIND 的特性让开发者可以快速创建和删除集群，大大提高了开发效率。</p><h4 id="CI-CD管道"><a href="#CI-CD管道" class="headerlink" title="CI/CD管道"></a>CI/CD管道</h4><p>在 CI/CD 管道中，KIND 可以在每次代码变更时快速创建一个新的 Kubernetes 集群用于测试，确保代码的稳定性和一致性。</p><h4 id="学习和培训"><a href="#学习和培训" class="headerlink" title="学习和培训"></a>学习和培训</h4><p>KIND 非常适合用于学习和培训，可以在本地快速搭建 Kubernetes 环境，使学习者掌握 Kubernetes 基本操作和概念。</p><h3 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h3><p>KIND 是基于 Docker 容器的，因此某些 Kubernetes 高级功能可能不完全支持。<br>偶尔你可能需要手动清理 Docker 容器和网络设置，特别是在多次创建和删除集群后。<br>不建议在生产环境中使用 KIND，它更适用于开发和测试用途。</p><h3 id="结论"><a href="#结论" class="headerlink" title="结论"></a>结论</h3><p>KIND 是一个非常方便的工具，可以帮助我们在本地快速搭建和管理 Kubernetes 集群。无论是开发测试、CI/CD 还是学习培训，KIND 都能发挥其巨大的作用。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;KIND（Kubernetes-IN-Docker）&quot;&gt;&lt;a href=&quot;#KIND（Kubernetes-IN-Docker）&quot; class=&quot;headerlink&quot; title=&quot;KIND（Kubernetes IN Docker）&quot;&gt;&lt;/a&gt;KIND（Kub</summary>
      
    
    
    
    <category term="Kubernetes" scheme="https://kalyan-zitiu.github.io/categories/Kubernetes/"/>
    
    
    <category term="Kubernetes" scheme="https://kalyan-zitiu.github.io/tags/Kubernetes/"/>
    
  </entry>
  
  <entry>
    <title>Prometheus基础</title>
    <link href="https://kalyan-zitiu.github.io/2024/07/23/Prometheus%E5%9F%BA%E7%A1%80/"/>
    <id>https://kalyan-zitiu.github.io/2024/07/23/Prometheus%E5%9F%BA%E7%A1%80/</id>
    <published>2024-07-23T08:10:02.000Z</published>
    <updated>2024-07-23T08:10:28.035Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Prometheus"><a href="#Prometheus" class="headerlink" title="Prometheus"></a>Prometheus</h2><p>一个开源的监控和告警系统</p><h3 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h3><h4 id="多维数据模型"><a href="#多维数据模型" class="headerlink" title="多维数据模型"></a>多维数据模型</h4><ul><li>使用时间序列数据，每个序列有一个度量指标（metricname）和一组键值对（labels）标识，这样可以灵活对同一类进行细分。<h5 id="度量指标"><a href="#度量指标" class="headerlink" title="度量指标"></a>度量指标</h5></li><li>counter：计数器，用于记录累计值，例如请求次数。</li><li>gauge：测量值，可增可减，例如当前内存使用量。</li><li>histogram：直方图，用于记录值分布，例如请求延迟。</li><li>summary：摘要，用于统计分位数和总和，例如响应时间的分位数。</li></ul><h5 id="标签"><a href="#标签" class="headerlink" title="标签"></a>标签</h5><ul><li>一组键值对，用于对时间序列进行细分和区分。例如，监控一个 HTTP 请求的计数器可以通过标签区分不同的请求路径和状态码</li></ul><figure class="highlight lua"><table><tr><td class="code"><pre><span class="line">http_requests_total&#123;method=<span class="string">&quot;POST&quot;</span>, handler=<span class="string">&quot;/api/v1&quot;</span>, <span class="built_in">status</span>=<span class="string">&quot;200&quot;</span>&#125;</span><br><span class="line">http_requests_total&#123;method=<span class="string">&quot;GET&quot;</span>, handler=<span class="string">&quot;/api/v1&quot;</span>, <span class="built_in">status</span>=<span class="string">&quot;500&quot;</span>&#125;</span><br></pre></td></tr></table></figure><h3 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h3><p>假设我们有一个 Web 服务，它记录了每个请求的数量和响应时间。我们可以定义以下指标：</p><ol><li>记录请求数量的计数器：<ul><li>Metric Name: <code>http_requests_total</code></li><li>Labels: <code>method</code>, <code>handler</code>, <code>status</code></li></ul></li><li>记录响应时间的直方图：<ul><li>Metric Name: <code>http_request_duration_seconds</code></li><li>Labels: <code>method</code>, <code>handler</code></li></ul></li></ol><p>每次有新的请求进来，计数器和直方图都会更新。例如：</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">http_requests_total&#123;method=<span class="string">&quot;POST&quot;</span>, handler=<span class="string">&quot;/api/v1&quot;</span>, status=<span class="string">&quot;200&quot;</span>&#125; 1234</span><br><span class="line">http_requests_total&#123;method=<span class="string">&quot;GET&quot;</span>, handler=<span class="string">&quot;/api/v1&quot;</span>, status=<span class="string">&quot;500&quot;</span>&#125; 56</span><br><span class="line">http_request_duration_seconds_bucket&#123;method=<span class="string">&quot;POST&quot;</span>, handler=<span class="string">&quot;/api/v1&quot;</span>, le=<span class="string">&quot;0.1&quot;</span>&#125; 5</span><br><span class="line">http_request_duration_seconds_bucket&#123;method=<span class="string">&quot;POST&quot;</span>, handler=<span class="string">&quot;/api/v1&quot;</span>, le=<span class="string">&quot;0.5&quot;</span>&#125; 50</span><br></pre></td></tr></table></figure><h4 id="支持PromQL"><a href="#支持PromQL" class="headerlink" title="支持PromQL"></a>支持PromQL</h4><p>查询所有 POST 请求的数量：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">promql</span><br><span class="line">复制代码</span><br><span class="line">sum(http_requests_total&#123;method=&quot;POST&quot;&#125;)</span><br></pre></td></tr></table></figure><p>查询 <code>/api/v1</code> 接口的所有请求数量：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">promql</span><br><span class="line">复制代码</span><br><span class="line">sum(http_requests_total&#123;handler=&quot;/api/v1&quot;&#125;)</span><br></pre></td></tr></table></figure><p>查询状态码为 200 的请求数量：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">promql</span><br><span class="line">复制代码</span><br><span class="line">sum(http_requests_total&#123;status=&quot;200&quot;&#125;)</span><br></pre></td></tr></table></figure><h5 id="优化使用标签"><a href="#优化使用标签" class="headerlink" title="优化使用标签"></a>优化使用标签</h5><ul><li><strong>标签数目不要过多</strong>：过多的标签会导致时间序列爆炸，影响性能。</li><li><strong>标签值尽量稳定</strong>：标签值变化太频繁会增加存储和查询负担。</li><li><strong>合理设计标签</strong>：确保标签的选择能够满足查询需求，同时不过度细化。</li></ul><h4 id="时间序列数据库"><a href="#时间序列数据库" class="headerlink" title="时间序列数据库"></a>时间序列数据库</h4><h5 id="TSDB-Prometheus自带时序数据库"><a href="#TSDB-Prometheus自带时序数据库" class="headerlink" title="TSDB Prometheus自带时序数据库"></a>TSDB Prometheus自带时序数据库</h5><h6 id="特点-1"><a href="#特点-1" class="headerlink" title="特点"></a>特点</h6><p>高效写入：Prometheus 的 TSDB 能够每秒写入数百万个样本，适合高频数据采集。<br>高效查询：针对时间序列数据优化的查询性能。<br>数据压缩：使用差分编码和 Gorilla 压缩算法减少存储空间。<br>局部存储：数据默认存储在本地磁盘上，可以通过远程存储扩展。</p><h6 id="数据结构"><a href="#数据结构" class="headerlink" title="数据结构"></a>数据结构</h6><p>样本 (Sample)：包含一个时间戳和一个值。<br>时间序列 (Time Series)：由一个度量名和一组标签唯一标识的一组样本。<br>块 (Block)：TSDB 中的数据以块的形式存储，每个块通常覆盖 2 小时的数据。<br>WAL (Write-Ahead Log)：在写入到块之前，数据先写入 WAL，以确保数据持久化。</p><h6 id="数据存储和管理"><a href="#数据存储和管理" class="headerlink" title="数据存储和管理"></a>数据存储和管理</h6><ol><li>数据存储路径：默认存储路径为 /var/lib/prometheus，可以在 Prometheus 配置文件中通过 storage.tsdb.path 参数修改。</li><li>数据保留策略：默认保留 15 天的数据，可以通过 –storage.tsdb.retention.time 参数设置。</li><li>数据压缩和删除：Prometheus 会自动压缩和删除过期数据。<h4 id="独立抓取模型："><a href="#独立抓取模型：" class="headerlink" title="独立抓取模型："></a>独立抓取模型：</h4></li></ol><h5 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h5><ol><li><strong>Scrape</strong>：Prometheus 从目标处获取监控数据的过程。</li><li><strong>Target</strong>：被监控的对象，可以是服务器、应用程序、数据库等。</li><li><strong>Job</strong>：一组相似目标的集合。</li><li><strong>Exporter</strong>：用于将目标的数据暴露给 Prometheus 的组件，通常是 HTTP 端点</li></ol><h5 id="配置文件’prometheus-yml’"><a href="#配置文件’prometheus-yml’" class="headerlink" title="配置文件’prometheus.yml’"></a>配置文件’prometheus.yml’</h5><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">global:</span><br><span class="line">  scrape_interval: 15s     <span class="comment"># 每15秒抓取一次数据</span></span><br><span class="line">  evaluation_interval: 15s <span class="comment"># 每15秒评估一次规则</span></span><br></pre></td></tr></table></figure><h6 id="抓取配置"><a href="#抓取配置" class="headerlink" title="抓取配置"></a>抓取配置</h6><p>抓取配置定义了 Prometheus 如何发现和抓取目标数据。</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">scrape_configs:</span><br><span class="line">  - job_name: <span class="string">&#x27;prometheus&#x27;</span></span><br><span class="line">    static_configs:</span><br><span class="line">      - targets: [<span class="string">&#x27;localhost:9090&#x27;</span>]</span><br></pre></td></tr></table></figure><h6 id="动态服务发现"><a href="#动态服务发现" class="headerlink" title="动态服务发现"></a>动态服务发现</h6><p>Prometheus 支持多种服务发现机制，允许动态发现目标。例如，可以使用 Kubernetes、Consul、Etcd 等进行服务发现。</p><p>####### Exporter<br>Exporter 是将监控数据暴露给 Prometheus 的组件，不同的应用和系统有不同的 Exporter。例如：</p><ul><li>Node Exporter：用于监控操作系统的资源使用情况。</li><li>Blackbox Exporter：用于进行探测和检查（如 HTTP、HTTPS、TCP）。</li><li>MySQL Exporter：用于监控 MySQL 数据库。</li></ul><h4 id="多种数据支持："><a href="#多种数据支持：" class="headerlink" title="多种数据支持："></a>多种数据支持：</h4><p>支持包括通过导出器（exporters）收集第三方系统的数据，支持服务发现（Service Discovery），如 Kubernetes、Consul、Etcd 等</p><h4 id="告警："><a href="#告警：" class="headerlink" title="告警："></a>告警：</h4><p>内置了 Alertmanager，用于处理告警通知和管理告警规则。</p><h3 id="结构"><a href="#结构" class="headerlink" title="结构"></a>结构</h3><ol><li>Prometheus Server：<br>存储：使用基于时间序列数据库（TSDB）的本地存储来存储监控数据。<br>抓取（Scrape）：定期从目标端点（如应用程序、数据库等）拉取指标数据。<br>PromQL 查询引擎：允许用户通过 PromQL 查询存储的数据。</li><li>数据导出器（Exporters）：<br>节点导出器（Node Exporter）：收集系统级别的指标，如 CPU、内存、磁盘使用等。<br>应用程序导出器：如 MySQL Exporter、Redis Exporter，专门用于从特定应用中收集指标。</li><li>服务发现（Service Discovery）：<br>支持多种服务发现机制，如 Kubernetes、Consul、DNS 等，自动发现并监控动态变化的服务和主机。</li><li>Alertmanager：<br>告警规则：定义告警规则，当满足条件时触发告警。<br>告警通知：管理告警的路由和发送，支持多种通知方式，如电子邮件、Slack、PagerDuty 等。<br>告警抑制和分组：可以配置告警抑制规则和告警分组，避免告警风暴。</li><li>Pushgateway：<br>用于接收临时性任务（如批处理任务）的指标数据，这些任务无法被 Prometheus 定期拉取。</li></ol><h3 id="工作流程"><a href="#工作流程" class="headerlink" title="工作流程"></a>工作流程</h3><ol><li>配置和服务发现：通过配置文件或服务发现机制，Prometheus 确定需要监控的目标。</li><li>抓取数据：Prometheus 定期从目标端点拉取指标数据。</li><li>存储数据：将拉取到的指标数据存储在本地的时间序列数据库中。</li><li>查询和可视化：通过 PromQL 查询数据，结合 Grafana 等可视化工具展示监控结果。</li><li>告警处理：根据定义的告警规则，Prometheus 触发告警并通过 Alertmanager 发送通知。</li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Prometheus&quot;&gt;&lt;a href=&quot;#Prometheus&quot; class=&quot;headerlink&quot; title=&quot;Prometheus&quot;&gt;&lt;/a&gt;Prometheus&lt;/h2&gt;&lt;p&gt;一个开源的监控和告警系统&lt;/p&gt;
&lt;h3 id=&quot;特点&quot;&gt;&lt;a href=&quot;</summary>
      
    
    
    
    <category term="kubernetes" scheme="https://kalyan-zitiu.github.io/categories/kubernetes/"/>
    
    
    <category term="Prometheus" scheme="https://kalyan-zitiu.github.io/tags/Prometheus/"/>
    
  </entry>
  
  <entry>
    <title>简单ansible操作</title>
    <link href="https://kalyan-zitiu.github.io/2024/07/22/%E7%AE%80%E5%8D%95ansible%E6%93%8D%E4%BD%9C/"/>
    <id>https://kalyan-zitiu.github.io/2024/07/22/%E7%AE%80%E5%8D%95ansible%E6%93%8D%E4%BD%9C/</id>
    <published>2024-07-22T06:59:35.000Z</published>
    <updated>2024-07-22T07:00:01.256Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Ansible"><a href="#Ansible" class="headerlink" title="Ansible"></a>Ansible</h2><p>用于配置管理、应用程序部署、任务自动化</p><h3 id="ansible主机清单"><a href="#ansible主机清单" class="headerlink" title="ansible主机清单"></a>ansible主机清单</h3><h4 id="定义组"><a href="#定义组" class="headerlink" title="定义组"></a>定义组</h4><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">[webservers] <span class="comment"># 定义组</span></span><br><span class="line">xxx.xxx.com</span><br><span class="line">xxx.xxx.com</span><br><span class="line"></span><br><span class="line">[dbserver] <span class="comment"># 定义组</span></span><br><span class="line">xxx.xxx.com</span><br><span class="line">xxx.xxx.com</span><br><span class="line"></span><br><span class="line">[dce5_nodes]</span><br><span class="line">10.70.49.17[2:4]</span><br><span class="line"></span><br><span class="line">[all:vars] <span class="comment"># 定义全局变量适用于全部主机</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Ansible SSH 用户名，用于连接到目标主机</span></span><br><span class="line">ansible_ssh_user: guest2admin</span><br><span class="line"></span><br><span class="line"><span class="comment"># Ansible SSH 密码，用于连接到目标主机</span></span><br><span class="line">ansible_ssh_pass: @<span class="built_in">users</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Ansible 使用的 Python 解释器路径</span></span><br><span class="line">ansible_python_interpreter: /usr/bin/python</span><br><span class="line"></span><br><span class="line"><span class="comment"># SSH 连接的通用参数，这里指定了加密算法为 AES-256-CBC</span></span><br><span class="line">ansible_ssh_common_args: -c aes256-cbc</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定 Ansible 连接到主机的方式，这里使用 SSH</span></span><br><span class="line">ansible_connection: ssh</span><br><span class="line"></span><br><span class="line"><span class="comment"># 提权操作时使用的密码（例如切换到 root 用户时的密码）</span></span><br><span class="line">ansible_become_password: root@root@su</span><br><span class="line"></span><br><span class="line"><span class="comment"># 提权方法，这里使用 su 命令切换用户</span></span><br><span class="line">ansible_become_method: su</span><br><span class="line"></span><br><span class="line"><span class="comment"># 提权执行命令，这里指定了使用 sudo su - 命令来切换到超级用户</span></span><br><span class="line">ansible_become_exe: sudo su -</span><br><span class="line"></span><br><span class="line"><span class="comment"># 还可以组别变量</span></span><br><span class="line">[webserver:vars]</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="o打"><a href="#o打" class="headerlink" title="o打"></a>o打</h3><ol><li><p><strong>Ping 模块</strong></p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ansible all -m ping</span><br></pre></td></tr></table></figure><p>通过 Ping 模块测试所有主机是否可达。</p></li><li><p><strong>Shell 模块</strong></p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ansible all -m shell -a <span class="string">&#x27;uptime&#x27;</span></span><br></pre></td></tr></table></figure><p>在所有主机上执行 <code>uptime</code> 命令。</p></li><li><p><strong>Command 模块</strong></p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ansible all -m <span class="built_in">command</span> -a <span class="string">&#x27;ls /tmp&#x27;</span></span><br></pre></td></tr></table></figure><p>使用 <code>command</code> 模块列出 <code>/tmp</code> 目录下的文件。</p></li><li><p><strong>Copy 模块</strong></p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ansible all -m copy -a <span class="string">&#x27;src=/path/to/source dest=/path/to/destination&#x27;</span></span><br></pre></td></tr></table></figure><p>将本地文件复制到远程主机。</p></li><li><p><strong>File 模块</strong></p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ansible all -m file -a <span class="string">&#x27;path=/tmp/testfile state=touch&#x27;</span></span><br></pre></td></tr></table></figure><p>在远程主机上创建一个空文件。</p></li><li><p><strong>Service 模块</strong></p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ansible all -m service -a <span class="string">&#x27;name=httpd state=started&#x27;</span></span><br></pre></td></tr></table></figure><p>启动所有主机上的 httpd 服务。</p></li><li><p><strong>User 模块</strong></p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ansible all -m user -a <span class="string">&#x27;name=johndoe state=present&#x27;</span></span><br></pre></td></tr></table></figure><p>创建一个名为 <code>johndoe</code> 的用户。</p></li></ol><h3 id="常用选项"><a href="#常用选项" class="headerlink" title="常用选项"></a>常用选项</h3><ul><li><code>-i &lt;inventory&gt;</code>：指定主机清单文件。例如 <code>-i hosts</code>。</li><li><code>--list-hosts</code>：列出将运行任务的主机。</li><li><code>-l &lt;subset&gt;</code>：指定要执行任务的主机子集。例如 <code>-l webservers</code>。</li><li><code>-u &lt;user&gt;</code>：指定远程主机用户。例如 <code>-u root</code>。</li><li><code>-k</code>：提示输入 SSH 密码。</li><li><code>--ask-become-pass</code>：提示输入 sudo 密码。</li><li><code>-e &lt;extra_vars&gt;</code>：传递额外变量。例如 <code>-e &quot;var1=value1 var2=value2&quot;</code>。</li></ul><h3 id="示例详解"><a href="#示例详解" class="headerlink" title="示例详解"></a>示例详解</h3><ol><li><p><strong>列出主机</strong></p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ansible all --list-hosts</span><br></pre></td></tr></table></figure><p>列出所有在清单中的主机。</p></li><li><p><strong>指定用户和密码执行命令</strong></p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ansible all -m shell -a <span class="string">&#x27;df -h&#x27;</span> -u root -k</span><br></pre></td></tr></table></figure><p>使用 root 用户执行 <code>df -h</code> 命令，并提示输入密码。</p></li><li><p><strong>传递额外变量</strong></p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ansible all -m shell -a <span class="string">&#x27;echo &#123;&#123; var_name &#125;&#125;&#x27;</span> -e <span class="string">&#x27;var_name=HelloWorld&#x27;</span></span><br></pre></td></tr></table></figure><p>传递变量 <code>var_name</code>，并在命令中使用。</p></li></ol><h3 id="高级用法"><a href="#高级用法" class="headerlink" title="高级用法"></a>高级用法</h3><ol><li><p><strong>使用标签</strong></p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ansible all -m shell -a <span class="string">&#x27;systemctl restart httpd&#x27;</span> --tags <span class="string">&quot;restart&quot;</span></span><br></pre></td></tr></table></figure><p>使用标签来组织和执行特定的任务。</p></li><li><p><strong>检查主机连通性</strong></p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">ansible all -m ping -i inventory/hosts</span><br></pre></td></tr></table></figure><p>使用指定的主机清单文件检查连通性。</p></li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Ansible&quot;&gt;&lt;a href=&quot;#Ansible&quot; class=&quot;headerlink&quot; title=&quot;Ansible&quot;&gt;&lt;/a&gt;Ansible&lt;/h2&gt;&lt;p&gt;用于配置管理、应用程序部署、任务自动化&lt;/p&gt;
&lt;h3 id=&quot;ansible主机清单&quot;&gt;&lt;a hr</summary>
      
    
    
    
    <category term="ansible" scheme="https://kalyan-zitiu.github.io/categories/ansible/"/>
    
    
    <category term="ansible" scheme="https://kalyan-zitiu.github.io/tags/ansible/"/>
    
  </entry>
  
  <entry>
    <title>Kubernetes服务网格</title>
    <link href="https://kalyan-zitiu.github.io/2024/07/22/Kubernetes%E6%9C%8D%E5%8A%A1%E7%BD%91%E6%A0%BC/"/>
    <id>https://kalyan-zitiu.github.io/2024/07/22/Kubernetes%E6%9C%8D%E5%8A%A1%E7%BD%91%E6%A0%BC/</id>
    <published>2024-07-22T03:31:12.000Z</published>
    <updated>2024-07-22T03:35:22.878Z</updated>
    
    <content type="html"><![CDATA[<h2 id="kubernetes服务网格"><a href="#kubernetes服务网格" class="headerlink" title="kubernetes服务网格"></a>kubernetes服务网格</h2><p>是一种架构，为了解决服务和服务之间的通信。</p><h3 id="服务网格接口（打算理解）"><a href="#服务网格接口（打算理解）" class="headerlink" title="服务网格接口（打算理解）"></a>服务网格接口（打算理解）</h3><h4 id="SMI"><a href="#SMI" class="headerlink" title="SMI"></a>SMI</h4><p>  用于定义服务网格标准化接口的规范，旨在提供一个通用的接口，让不同的服务网格实现可以互操作。SMI的主要目的是简化服务网格的使用和集成，使用户可以使用统一的API管理不同的服务网格实现，如Istio、Linkerd、Consul Connect等。</p><h4 id="CRD"><a href="#CRD" class="headerlink" title="CRD"></a>CRD</h4><p>  是Kubernetes中的一种机制，用于扩展Kubernetes API，使用户可以定义自己的资源类型。通过CRD，用户可以创建自定义资源（CR），这些资源可以与Kubernetes内置资源（如Pod、Service）一样进行管理和操作。</p><h3 id="数据平面代理"><a href="#数据平面代理" class="headerlink" title="数据平面代理"></a>数据平面代理</h3><p>负责处理和管理服务间流量的代理组件。</p><p>核心职责:<br>流量转发：代理组件负责接收、转发和负载均衡服务之间的流量。这包括 HTTP、gRPC、TCP 等多种协议。<br>服务发现：代理可以自动发现 Kubernetes 中的服务，根据服务的配置进行相应的流量路由。<br>流量管理：包括流量控制、重试策略、断路器、故障注入等功能，以保证服务间通信的可靠性和稳定性。<br>安全：提供 mTLS（双向 TLS）加密来确保服务间通信的安全性，支持认证和授权策略。<br>监控和可观测性：代理会收集并上报各种流量指标和日志，帮助管理员监控和诊断服务间的通信问题。</p><h4 id="数据平面架构"><a href="#数据平面架构" class="headerlink" title="数据平面架构"></a>数据平面架构</h4><h5 id="代理附件"><a href="#代理附件" class="headerlink" title="代理附件"></a>代理附件</h5><p>一般部署在工作负载的pod上，后续会拦截进出服务的所有通信，但是在一些升级上，代理附件不能保证在不重建Pod的条件下进行升级</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240722112524609.png" alt="image-20240722112524609"></p><h5 id="代理节点"><a href="#代理节点" class="headerlink" title="代理节点"></a>代理节点</h5><p>由代理节点来处理运行服务的所有流量。但是会存在很大的网络瓶颈。</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240722112926402.png" alt="image-20240722112926402"></p><h4 id="Envoy"><a href="#Envoy" class="headerlink" title="Envoy"></a>Envoy</h4><p>  一个高性能的开源边缘和服务代理，主要用于微服务架构中的通信管理</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240722102428515.png" alt="image-20240722102428515"></p><h5 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h5><h6 id="API网关："><a href="#API网关：" class="headerlink" title="API网关："></a>API网关：</h6><p>Envoy可以作为API网关，处理外部请求并将其路由到内部服务，同时提供认证、限流、缓存等功能。</p><h6 id="边车代理："><a href="#边车代理：" class="headerlink" title="边车代理："></a>边车代理：</h6><ul><li>是一种设计模式，在这种模式下，一个代理程序（如Envoy）被部署在每个服务实例的旁边，这样每个服务实例都有一个独立的代理来处理进出流量。</li><li>在服务网格架构中，Envoy通常以边车代理的形式部署在每个服务实例旁，拦截和处理所有入站和出站流量。</li><li>边车注入是将边车代理自动注入到服务实例的Pod中，以便在微服务架构中实现服务网格功能的过程。分为手动与自动，自动注入似乎能够用istio来进行自动注入。</li><li>Sidecar 模式：Envoy 通常以 sidecar 容器的形式部署在每个微服务 Pod 内，与应用容器共享网络命名空间。所有进出微服务的流量都会通过 Envoy 代理。</li></ul><h6 id="中介层代理："><a href="#中介层代理：" class="headerlink" title="中介层代理："></a>中介层代理：</h6><p>Envoy可以部署在不同的服务层之间，作为中介层代理，处理跨服务的流量和策略管理。</p><h5 id="模块化架构"><a href="#模块化架构" class="headerlink" title="模块化架构"></a>模块化架构</h5><p>Listener：<br>作用：Listener是Envoy用于监听网络端口的组件，负责接受客户端的连接请求。每个Listener都绑定到一个特定的IP地址和端口，并根据配置将流量传递给相应的处理模块。<br>配置：Listener的配置包括监听的地址和端口、使用的协议（如HTTP、TCP）、以及关联的过滤器链。</p><p>Filter：<br>作用：Filter是Envoy用于处理请求和响应的中间处理模块。Filter可以用于修改请求、添加日志、执行身份验证、路由选择等。Envoy的Filter分为多种类型，包括网络过滤器、HTTP过滤器和TCP过滤器。<br>类型：<br>网络过滤器：处理TCP连接层面的流量，如TLS终止、连接限速等。<br>HTTP过滤器：处理HTTP请求和响应，如修改头部信息、执行认证和授权、负载均衡等。<br>TCP过滤器：处理TCP层流量，如TCP代理、流量镜像等。</p><p>Cluster：<br>作用：Cluster是Envoy用于表示一组上游服务实例的组件。Cluster负责服务发现、负载均衡、健康检查等。每个Cluster包含多个主机（即上游服务实例），并定义了如何将流量分配到这些主机上。<br>配置：Cluster的配置包括服务发现类型（静态、DNS、EDS等）、负载均衡策略（如轮询、随机、加权轮询等）、健康检查配置等。</p><p>Route：<br>作用：Route组件定义了Envoy如何将请求路由到不同的Cluster。Route规则基于请求的属性（如路径、头部信息、方法等）来决定具体的路由目标。<br>配置：Route的配置包括匹配规则、路由目标Cluster、重试策略、超时设置等。</p><p>Admin：<br>作用：Admin组件提供了管理和监控Envoy的接口。通过Admin接口，用户可以查看Envoy的运行状态、统计信息、配置详情，并进行管理操作。<br>配置：Admin接口通常通过HTTP API暴露，可以在Envoy配置中指定Admin的监听地址和端口。</p><h5 id="配置管理"><a href="#配置管理" class="headerlink" title="配置管理"></a>配置管理</h5><p>配置管理<br>Envoy的配置管理可以通过静态文件配置，也可以通过动态配置API（xDS）实现。xDS（Envoy Dynamic Configuration API）包括以下几个部分：<br>ADS（Aggregated Discovery Service）：聚合配置服务，统一管理其他xDS服务。<br>CDS（Cluster Discovery Service）：动态管理Cluster的配置。<br>EDS（Endpoint Discovery Service）：动态管理Cluster中上游服务实例的配置。<br>LDS（Listener Discovery Service）：动态管理Listener的配置。<br>RDS（Route Discovery Service）：动态管理路由配置。<br>SDS（Secret Discovery Service）：动态管理密钥和证书。</p><h3 id="控制平面"><a href="#控制平面" class="headerlink" title="控制平面"></a>控制平面</h3><p>负责管理和协调数据平面代理</p><p>配置管理：提供统一的配置接口，管理服务网格中所有代理的配置，包括路由规则、负载均衡策略、故障恢复策略等。<br>服务发现：集成服务发现机制，实时感知集群中服务的变化，并通知数据平面代理更新其配置。<br>安全管理：实现服务间的认证和授权，管理 TLS 证书的分发和轮换，确保服务间通信的安全性。<br>流量管理：提供流量路由、灰度发布、A/B 测试等高级流量控制功能，帮助开发和运维人员灵活管理服务间的流量。<br>可观测性：收集和聚合数据平面代理的监控指标、日志和分布式追踪数据，提供全局的可观测性视图，帮助排查和诊断问题。</p><h4 id="istio"><a href="#istio" class="headerlink" title="istio"></a>istio</h4><p>istiod为基于envoy的服务网络提供控制平面，他包括三个核心组件，Galley，Pilot，Citidel</p><p>Pilot：一个Envoy的配置服务器，实现 xDS API，并将配置流向与应用程序一起运行的Envoy代理。</p><p>Citadel：负责网格内的证书管理，建立服务器身份和相互TLS。</p><p>Galley：与外部系统互动，Kubernetes等。</p><h4 id="webhook"><a href="#webhook" class="headerlink" title="webhook"></a>webhook</h4><p>用于在 Kubernetes 集群中实现动态配置和策略控制的关键组件。 Istio 中的主要用途包括服务网格控制、资源变更管理和策略执行等。</p><ul><li>自动注入 Sidecar 容器:Istio 使用一个变异（Mutating）Webhook 自动将 Envoy 代理（Sidecar）注入到新创建的 Kubernetes Pod 中。这个过程确保每个服务都能被 Istio 管理和监控。当你为集群启用了自动注入，Webhook 会拦截 Pod 创建请求，在 Pod 完成调度之前往其定义中添加 Envoy 容器以及必要的配置信息。</li><li>配置验证（Validating Webhook）:验证（Validating）Webhook 用于在新的 Istio 配置资源（如 VirtualService、DestinationRule 等）创建或更新时执行验证过程，确保这些配置符合要求，避免因错误配置导致服务故障。这个 Webhook 会在配置提交到 etcd 之前进行执行，起到一个“守门人”的作用，阻止不符合标准的配置生效。</li><li>动态配置和策略控制:Webhook 还可以用于执行动态配置和策略决策。例如，通过 Webhook，可以向运行时注入配置参数或更新策略以应对瞬时需求或安全要求。</li></ul><h4 id="通过iptable达到工作负载通过Envoy发送流量。"><a href="#通过iptable达到工作负载通过Envoy发送流量。" class="headerlink" title="通过iptable达到工作负载通过Envoy发送流量。"></a>通过iptable达到工作负载通过Envoy发送流量。</h4><p>Istio的iptables规则是通过init-containner来进行安装，拦截pod网络流量路由到Envoy。</p><p><img src="https://gcore.jsdelivr.net/gh/Kalyan-zitiu/TyporaIMG/img/image-20240722111557580.png" alt="image-20240722111557580"></p><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">initContainers:</span></span><br><span class="line"><span class="string">”argS:</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">istio-iptables</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">--envoy-port</span> <span class="comment">#捕获出站的所有流量，并且发送到Envoy这个端口</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">&quot;15001&quot;</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">--inbound-capture-port</span> <span class="comment">#捕获入站的所有流量，并且发送Envoy这个端口1</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">&quot;15006&quot;</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">--proxy-uid</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">&quot;1337”</span></span><br><span class="line"><span class="string">- --istio-inbound-interception-mode</span></span><br><span class="line"><span class="string">- REDIRECT</span></span><br><span class="line"><span class="string">--istio-service-cidr </span></span><br><span class="line"><span class="string">- &#x27;*&#x27;</span></span><br><span class="line"><span class="string">--istio-inbound-ports </span></span><br><span class="line"><span class="string">- &#x27;*&#x27;</span></span><br><span class="line"><span class="string">- --istio-local-exclude-ports</span></span><br><span class="line"><span class="string">- 15090,15021,15020</span></span><br><span class="line"><span class="string">image: docker.io/istio/proxyv2:1.6.7</span></span><br><span class="line"><span class="string">imagePullPolicy: Always</span></span><br><span class="line"><span class="string">name: istio-init</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;kubernetes服务网格&quot;&gt;&lt;a href=&quot;#kubernetes服务网格&quot; class=&quot;headerlink&quot; title=&quot;kubernetes服务网格&quot;&gt;&lt;/a&gt;kubernetes服务网格&lt;/h2&gt;&lt;p&gt;是一种架构，为了解决服务和服务之间的通信。&lt;</summary>
      
    
    
    
    <category term="Kubernetes" scheme="https://kalyan-zitiu.github.io/categories/Kubernetes/"/>
    
    
    <category term="Kubernetes" scheme="https://kalyan-zitiu.github.io/tags/Kubernetes/"/>
    
  </entry>
  
</feed>
