<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>理想的路上</title>
  
  <subtitle>一路前行</subtitle>
  <link href="http://aoxn.github.io/atom.xml" rel="self"/>
  
  <link href="http://aoxn.github.io/"/>
  <updated>2022-06-08T12:18:41.061Z</updated>
  <id>http://aoxn.github.io/</id>
  
  <author>
    <name>spacexnice</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>云原生应用示例</title>
    <link href="http://aoxn.github.io/2022/06/08/%E4%BA%91%E5%8E%9F%E7%94%9F%E5%BA%94%E7%94%A8%E7%A4%BA%E4%BE%8B/"/>
    <id>http://aoxn.github.io/2022/06/08/%E4%BA%91%E5%8E%9F%E7%94%9F%E5%BA%94%E7%94%A8%E7%A4%BA%E4%BE%8B/</id>
    <published>2022-06-08T11:39:25.000Z</published>
    <updated>2022-06-08T12:18:41.061Z</updated>
    
    <content type="html"><![CDATA[<h2 id="DEMO-APPLICATION"><a href="#DEMO-APPLICATION" class="headerlink" title="DEMO-APPLICATION"></a>DEMO-APPLICATION</h2><p>请先将示例应用部署配置文件<code>git clone</code>到本地.</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ git clone https://github.com/aoxn/wdrip.git</span><br></pre></td></tr></table></figure><h3 id="示例应用一：-文件共享服务器"><a href="#示例应用一：-文件共享服务器" class="headerlink" title="示例应用一： 文件共享服务器"></a>示例应用一： 文件共享服务器</h3><p><code>filebrowser</code> 应用提供文件共享服务，存储使用阿里云OSS存储系统。因此需要配置阿里云ACCESS_KEY_ID和ACCESS_KEY_SEC与REGION。<br>请先git clone 代码到本地，安装filebrowser的脚本位于<code>hack/example/filebrowser.sh</code></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ export REGION=cn-hangzhou</span><br><span class="line">(base) ➜ export ACCESS_KEY_ID=xxxx</span><br><span class="line">(base) ➜ export ACCESS_KEY_SECRET=yyyyy</span><br><span class="line">(base) ➜ export KUBECONFIG=~/.kube/config.wdrip</span><br><span class="line">(base) ➜ bash hack/example/filebrowser.sh</span><br><span class="line">(base) ➜</span><br><span class="line">(base) ➜ kubectl get svc</span><br><span class="line">NAME          TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE</span><br><span class="line">filebrowser   LoadBalancer   172.19.4.156   47.110.243.41   80:31295/TCP   22d</span><br><span class="line">kubernetes    ClusterIP      172.19.0.1     &lt;none&gt;          443/TCP        22d</span><br><span class="line"></span><br></pre></td></tr></table></figure><span id="more"></span><p>访问<code>http://47.110.243.41</code>开始玩转filebrowser. 初始密码admin&#x2F;admin ? 记得改密码<br><img src="/upload/img.png" alt="img.png"></p><p>等待10分钟后，wdrip会自动snapshot整个etcd配置。此时可以尝试带着应用场景测试wdrip的基础设施复原力。</p><h3 id="示例应用二：wordpress"><a href="#示例应用二：wordpress" class="headerlink" title="示例应用二：wordpress"></a>示例应用二：wordpress</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ export KUBECONFIG=~/.kube/config.wdrip</span><br><span class="line">(base) ➜ bash hack/example/wordpress.sh</span><br><span class="line">(base) ➜</span><br><span class="line">(base) ➜ kubectl get svc</span><br><span class="line">NAME          TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE</span><br><span class="line">filebrowser   LoadBalancer   172.19.4.157   47.110.243.30   80:31295/TCP   22d</span><br><span class="line">kubernetes    ClusterIP      172.19.0.1     &lt;none&gt;          443/TCP        22d</span><br></pre></td></tr></table></figure><p>访问<code>http://47.110.243.30</code></p><h3 id="示例应用三：蓝绿发布应用"><a href="#示例应用三：蓝绿发布应用" class="headerlink" title="示例应用三：蓝绿发布应用"></a>示例应用三：蓝绿发布应用</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ export KUBECONFIG=~/.kube/config.wdrip</span><br><span class="line">(base) ➜ kubectl apply -f hack/example/blue.yml</span><br><span class="line">(base) ➜</span><br><span class="line">(base) ➜ kubectl get svc</span><br><span class="line">NAME          TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE</span><br><span class="line">filebrowser   LoadBalancer   172.19.4.158   47.110.243.50   80:31295/TCP   22d</span><br><span class="line">kubernetes    ClusterIP      172.19.0.1     &lt;none&gt;          443/TCP        22d</span><br></pre></td></tr></table></figure><p>访问<code>http://47.110.243.50</code></p>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;DEMO-APPLICATION&quot;&gt;&lt;a href=&quot;#DEMO-APPLICATION&quot; class=&quot;headerlink&quot; title=&quot;DEMO-APPLICATION&quot;&gt;&lt;/a&gt;DEMO-APPLICATION&lt;/h2&gt;&lt;p&gt;请先将示例应用部署配置文件&lt;code&gt;git clone&lt;/code&gt;到本地.&lt;/p&gt;
&lt;figure class=&quot;highlight shell&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;(base) ➜ git clone https://github.com/aoxn/wdrip.git&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;

&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;&lt;code&gt;filebrowser&lt;/code&gt; 应用提供文件共享服务，存储使用阿里云OSS存储系统。因此需要配置阿里云ACCESS_KEY_ID和ACCESS_KEY_SEC与REGION。&lt;br&gt;请先git clone 代码到本地，安装filebrowser的脚本位于&lt;code&gt;hack/example/filebrowser.sh&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;highlight shell&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;(base) ➜ export REGION=cn-hangzhou&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;(base) ➜ export ACCESS_KEY_ID=xxxx&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;(base) ➜ export ACCESS_KEY_SECRET=yyyyy&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;(base) ➜ export KUBECONFIG=~/.kube/config.wdrip&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;(base) ➜ bash hack/example/filebrowser.sh&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;(base) ➜&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;(base) ➜ kubectl get svc&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;NAME          TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;filebrowser   LoadBalancer   172.19.4.156   47.110.243.41   80:31295/TCP   22d&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;kubernetes    ClusterIP      172.19.0.1     &amp;lt;none&amp;gt;          443/TCP        22d&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>管理集群</title>
    <link href="http://aoxn.github.io/2022/06/08/%E7%AE%A1%E7%90%86%E9%9B%86%E7%BE%A4/"/>
    <id>http://aoxn.github.io/2022/06/08/%E7%AE%A1%E7%90%86%E9%9B%86%E7%BE%A4/</id>
    <published>2022-06-08T10:56:51.000Z</published>
    <updated>2022-06-08T14:43:26.458Z</updated>
    
    <content type="html"><![CDATA[<h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><p><strong>安装wdrip</strong><br>下载最新版本wdrip.当前版本0.1.1</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ curl -sSL --retry 3 https://host-wdrip-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/wdrip/install.sh |bash</span><br><span class="line">(base) ➜ <span class="built_in">ls</span> -lht /usr/local/bin/wdrip</span><br><span class="line"></span><br><span class="line"><span class="comment"># use wdrip -h to see wdrip help command</span></span><br><span class="line">(base) ➜ wdrip -h</span><br><span class="line"></span><br><span class="line">wdrip creates and manages infrastructure agnostic Kubernetes clusters</span><br><span class="line">            _         _</span><br><span class="line">           | |       (_)</span><br><span class="line"> _ _ _   __| |  ____  _  ____</span><br><span class="line">| | | | / _  | / ___)| ||  _ \</span><br><span class="line">| | | |( (_| || |    | || |_| |</span><br><span class="line"> \___/  \____||_|    |_||  __/</span><br><span class="line">                        |_|</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">wdrip creates and manages infrastructure agnostic Kubernetes clusters and empower strong auto heal ability and easy recovery</span><br><span class="line"></span><br><span class="line">Usage:</span><br><span class="line">  wdrip [<span class="built_in">command</span>]</span><br><span class="line"></span><br><span class="line">Available Commands:</span><br><span class="line">  bootstrap   Bootstrap a Kubernetes cluster</span><br><span class="line">  build       Kubernetes cluster build package</span><br><span class="line">  ......</span><br><span class="line"></span><br><span class="line">Use <span class="string">&quot;wdrip [command] --help&quot;</span> <span class="keyword">for</span> more information about a <span class="built_in">command</span>.</span><br></pre></td></tr></table></figure><span id="more"></span><p><strong>配置wdrip</strong><br>wdrip 目前仅支持阿里云上管理k8s集群，更多的CloudProvider未来会逐步加入。<br>wdrip 需要您的阿里云账号信息来帮助您管理您的云上k8s资源。将<code>replace-with-your-own-accessKeyId</code>及<code>replace-with-your-own-accessKeySecret</code>替换成您自己的主账号AK信息。<br>wdrip 会额外为您创建OSS bucket，用来备份集群，用来紧急修复。bucket名称见下面的<code>wdrip-index</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ vi ~/.wdrip/config</span><br><span class="line"></span><br><span class="line">apiVersion: alibabacloud.com/v1</span><br><span class="line">contexts:</span><br><span class="line">- context:</span><br><span class="line">    provider-key: alibaba.dev</span><br><span class="line">  name: devEnv</span><br><span class="line">current-context: devEnv</span><br><span class="line">kind: Config</span><br><span class="line">providers:</span><br><span class="line">- name: alibaba.dev</span><br><span class="line">  provider:</span><br><span class="line">    name: alibaba</span><br><span class="line">    value:</span><br><span class="line">      accessKeyId: &#123;replace-with-your-own-accessKeyId&#125;</span><br><span class="line">      accessKeySecret: &#123;replace-with-your-own-accessKeySecret&#125;</span><br><span class="line">      bucketName: &#123;replace-with-your-bucketName, any valid string <span class="built_in">which</span> not collide with other user&#125;</span><br><span class="line">      region: cn-hangzhou</span><br><span class="line"></span><br><span class="line">(base) ➜ wdrip get</span><br><span class="line">I0608 21:53:07.759770   50502 provider.go:272] use HOME <span class="built_in">dir</span>: [/Users/aoxn]</span><br><span class="line">I0608 21:53:07.759928   50502 provider.go:287] trying to load context config from: /Users/aoxn/.wdrip/config</span><br><span class="line">I0608 21:53:08.109595   50502 oss.go:42] oss get object from [oss://index-test-aoxn/wdrip/clusters/kubernetes-id-001.json]</span><br><span class="line">I0608 21:53:08.164366   50502 iaas.go:326]</span><br><span class="line">NAME                          ENDPOINT</span><br></pre></td></tr></table></figure><p>如果<code>wdrip get</code> 报错<code>Status Code: 403 Code: AccessDenied Message: The bucket you access does not belong to you.</code> 请换一个bucketName,因为你指定的bucket名称在全局范围内与其他人的名称冲突了。</p><h2 id="创建集群"><a href="#创建集群" class="headerlink" title="创建集群"></a>创建集群</h2><p>wdrip遵循结构化原则，最小核心原则，模块化设计，因此具有非常高的灵活性。<br>wdrip会首先在云上初始化一个单Master节点的k8s集群（最小可用原则），这个阶段的速度最快，并且具有最小的故障面，具有最高的系统稳定性。<br>以下配置为您创建一个最小k8s集群，仅有一个master节点。预计3分钟内完成。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ <span class="built_in">export</span> CLUSTER_NAME=kubernetes-id-001 \</span><br><span class="line">              REGION=cn-hangzhou ZONE_ID=cn-hangzhou-k \</span><br><span class="line">              IMAGE_ID=centos_7_9_x64_20G_alibase_20210623.vhd \</span><br><span class="line">              DISK_TYPE=cloud_essd \</span><br><span class="line">              INSTANCE_TYPE=ecs.c6.xlarge \</span><br><span class="line">              TOKEN=$(/usr/local/bin/wdrip token new)</span><br><span class="line"></span><br><span class="line">(base) ➜ <span class="built_in">cat</span> &gt; config.yaml &lt;&lt; <span class="string">EOF</span></span><br><span class="line"><span class="string">clusterid: &quot;$&#123;CLUSTER_NAME&#125;&quot;</span></span><br><span class="line"><span class="string">iaas:</span></span><br><span class="line"><span class="string">  workerCount: 1</span></span><br><span class="line"><span class="string">  image: &quot;$&#123;IMAGE_ID&#125;&quot;</span></span><br><span class="line"><span class="string">  disk:</span></span><br><span class="line"><span class="string">    size: 40G</span></span><br><span class="line"><span class="string">    type: &quot;$&#123;DISK_TYPE&#125;&quot;</span></span><br><span class="line"><span class="string">  region: &quot;$&#123;REGION&#125;&quot;</span></span><br><span class="line"><span class="string">  zoneid: $&#123;ZONE_ID&#125;</span></span><br><span class="line"><span class="string">  instance: &quot;$&#123;INSTANCE_TYPE&#125;&quot;</span></span><br><span class="line"><span class="string">registry: registry-vpc.$&#123;REGION&#125;.aliyuncs.com</span></span><br><span class="line"><span class="string">namespace: default</span></span><br><span class="line"><span class="string">cloudType: public</span></span><br><span class="line"><span class="string">kubernetes:</span></span><br><span class="line"><span class="string">  name: kubernetes</span></span><br><span class="line"><span class="string">  version: 1.20.4-aliyun.1</span></span><br><span class="line"><span class="string">  kubeadmToken: $&#123;TOKEN&#125;</span></span><br><span class="line"><span class="string">etcd:</span></span><br><span class="line"><span class="string">  name: etcd</span></span><br><span class="line"><span class="string">  version: v3.4.3</span></span><br><span class="line"><span class="string">runtime:</span></span><br><span class="line"><span class="string">  name: docker</span></span><br><span class="line"><span class="string">  version: 19.03.5</span></span><br><span class="line"><span class="string">sans:</span></span><br><span class="line"><span class="string">  - 192.168.0.1</span></span><br><span class="line"><span class="string">network:</span></span><br><span class="line"><span class="string">  mode: ipvs</span></span><br><span class="line"><span class="string">  podcidr: 172.16.0.1/16</span></span><br><span class="line"><span class="string">  svccidr: 172.19.0.1/20</span></span><br><span class="line"><span class="string">  domain: cluster.domain</span></span><br><span class="line"><span class="string">  netMask: 25</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"></span><br><span class="line">(base) ➜ wdrip create --config config.yaml</span><br><span class="line"></span><br><span class="line">wdrip: kubernetes cluster lifecycle management.</span><br><span class="line">            _         _</span><br><span class="line">           | |       (_)</span><br><span class="line"> _ _ _   __| |  ____  _  ____</span><br><span class="line">| | | | / _  | / ___)| ||  _ \</span><br><span class="line">| | | |( (_| || |    | || |_| |</span><br><span class="line"> \___/  \____||_|    |_||  __/</span><br><span class="line">                        |_|</span><br><span class="line"></span><br><span class="line">I1002 15:31:37.593094   96000 provider.go:268] use HOME <span class="built_in">dir</span>: [/Users/aoxn]</span><br><span class="line">I1002 15:31:37.593265   96000 provider.go:283] trying to load context config from: /Users/aoxn/.wdrip/config</span><br><span class="line">I1002 15:31:37.595669   96000 provider.go:52] use <span class="built_in">command</span> line config as bootconfig: [config.yaml] with provider[alibaba]</span><br><span class="line">I1002 15:31:37.726288   96000 oss.go:32] oss get object from [oss://wdrip-index/wdrip/clusters/kubernetes-id-001.json]</span><br><span class="line">....</span><br><span class="line"></span><br><span class="line">I1002 15:31:41.989201   96000 iaas.go:96] watch cluster create progress with <span class="built_in">command</span>:  [ wdrip watch --name kubernetes-id-001 ]</span><br></pre></td></tr></table></figure><h3 id="观测集群的创建过程"><a href="#观测集群的创建过程" class="headerlink" title="观测集群的创建过程"></a>观测集群的创建过程</h3><p>创建的集群是一个异步的过程，因此我们提供了一个watch命令，用来观测创建的进度。执行watch命令前请将terminal窗口最大化，保证最佳输出效果。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  wdrip watch --name kubernetes-id-001</span><br><span class="line">I1002 15:42:05.600911   96142 provider.go:268] use HOME <span class="built_in">dir</span>: [/Users/aoxn]</span><br><span class="line">I1002 15:42:05.601063   96142 provider.go:283] trying to load context config from: /Users/aoxn/.wdrip/config</span><br><span class="line">✓ 【ALIYUN::ROS::Stack                  】(kubernetes-id-001         ) [CREATE_COMPLETE,23, 23] 2021-10-02T15:31:42 2021-10-02T15:35:52</span><br><span class="line">✓ 【ALIYUN::ROS::WaitCondition          】(k8s_master_waiter         ) [CREATE_COMPLETE,23, 23] 2021-10-02T15:31:52 2021-10-02T15:35:51</span><br><span class="line"></span><br><span class="line">.....</span><br><span class="line"></span><br><span class="line">✓ 【ALIYUN::RAM::Role                   】(KubernetesWorkerRole      ) [CREATE_COMPLETE,23, 23] 2021-10-02T15:31:42 2021-10-02T15:31:52</span><br><span class="line">✓ 【WDRIP::MESSAGE::OUTPUT              】(extra_mesage_id           ) [CREATE_COMPLETE,23, 23]  TimeElapse: 251s</span><br><span class="line">I1002 15:42:14.446231   96142 ros.go:477] ===========================================================</span><br><span class="line">I1002 15:42:14.446254   96142 ros.go:478] StackName: kubernetes-id-001</span><br><span class="line">I1002 15:42:14.446259   96142 ros.go:479]   StackId: 2d302c6c-24b3-4535-8875-8c7dd9a48bd7</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="查看集群列表"><a href="#查看集群列表" class="headerlink" title="查看集群列表"></a>查看集群列表</h3><p>wdrip提供了命令用来查看本账号的provider所创建的集群列表</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ wdrip get</span><br><span class="line">I1002 16:16:59.615092   97592 provider.go:268] use HOME <span class="built_in">dir</span>: [/Users/aoxn]</span><br><span class="line">I1002 16:16:59.615225   97592 provider.go:283] trying to load context config from: /Users/aoxn/.wdrip/config</span><br><span class="line">I1002 16:16:59.670775   97592 index.go:76] get cluster: [wdrip/clusters/kubernetes-id-001.json]</span><br><span class="line">I1002 16:16:59.670802   97592 oss.go:32] oss get object from [oss://wdrip-index/wdrip/clusters/kubernetes-id-001.json]</span><br><span class="line">I1002 16:16:59.735396   97592 index.go:76] get cluster: [wdrip/clusters/kubernetes-wdrip-77.json]</span><br><span class="line">I1002 16:16:59.735420   97592 oss.go:32] oss get object from [oss://wdrip-index/wdrip/clusters/kubernetes-wdrip-77.json]</span><br><span class="line">I1002 16:16:59.807551   97592 iaas.go:190]</span><br><span class="line">NAME                  ENDPOINT</span><br><span class="line">kubernetes-id-001     47.96.27.46/192.168.0.75</span><br><span class="line">kubernetes-wdrip-77   116.62.24.127/192.168.0.53</span><br></pre></td></tr></table></figure><p>通过<code>wdrip get -n kubernetes-id-001 -o yaml</code> 可以查看该集群的详细信息</p><h3 id="连接集群"><a href="#连接集群" class="headerlink" title="连接集群"></a>连接集群</h3><p>当集群创建完成后,可以通过wdrip get命令下载kubeconfig文件来访问我们的集群。 当前wdrip创建的集群通过EIP在公网暴露了apiserver，因此可以通过公网本地访问。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ wdrip get -r kubeconfig -n kubernetes-id-001 -w ~/.kube/config.txt</span><br><span class="line"></span><br><span class="line">I1002 16:14:38.136200   97541 provider.go:268] use HOME <span class="built_in">dir</span>: [/Users/aoxn]</span><br><span class="line">I1002 16:14:38.136349   97541 provider.go:283] trying to load context config from: /Users/aoxn/.wdrip/config</span><br><span class="line">I1002 16:14:38.136730   97541 oss.go:32] oss get object from [oss://wdrip-index/wdrip/clusters/kubernetes-id-001.json]</span><br><span class="line">I1002 16:14:40.241796   97541 sign.go:223] sign kubernetes: []</span><br><span class="line">I1002 16:14:40.612558   97541 iaas.go:301] write kubeconfig to file [/Users/aoxn/.kube/config.txt]</span><br><span class="line"></span><br><span class="line">(base) ➜  kubectl --kubeconfig ~/.kube/config.txt get no</span><br><span class="line"></span><br><span class="line">NAME                                  STATUS   ROLES                  AGE    VERSION</span><br><span class="line">192.168.0.77.i-bp12a2wcmbrd4383cai3   Ready    control-plane,master   2m2s   v1.20.4-aliyun.1</span><br></pre></td></tr></table></figure><h2 id="添加工作节点"><a href="#添加工作节点" class="headerlink" title="添加工作节点"></a>添加工作节点</h2><h3 id="创建节点池"><a href="#创建节点池" class="headerlink" title="创建节点池"></a>创建节点池</h3><p>wdrip 提供了NodePool的概念，将一组具有相同的配置的节点组作为一个节点池统一管理。通过以下yaml可以创建具有N个节点的节点池。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ kubectl --kubeconfig ~/.kube/config.txt apply -f - &lt;&lt;<span class="string">EOF</span></span><br><span class="line"><span class="string">apiVersion: alibabacloud.com/v1</span></span><br><span class="line"><span class="string">kind: NodePool</span></span><br><span class="line"><span class="string">metadata:</span></span><br><span class="line"><span class="string">  name: nodepool-01</span></span><br><span class="line"><span class="string">  namespace: kube-system</span></span><br><span class="line"><span class="string">spec:</span></span><br><span class="line"><span class="string">  id: &quot;very-long-id-xxxxx&quot;</span></span><br><span class="line"><span class="string">  infra:</span></span><br><span class="line"><span class="string">    desiredCapacity: 1</span></span><br><span class="line"><span class="string">    cpu: 4</span></span><br><span class="line"><span class="string">    memory: 8</span></span><br><span class="line"><span class="string">    imageId: centos_7_9_x64_20G_alibase_20210623.vhd</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># output</span></span><br><span class="line">nodepool.alibabacloud.com/nodepool-01 created</span><br></pre></td></tr></table></figure><p>通过<code>kubectl --kubeconfig ~/.kube/config.txt get no -w</code> 观测节点的创建。 节点的创建及加入过程大约需要等待90s。请等待</p><p>同样的方式可以创建多个具有不同配置的节点池。</p><h3 id="扩容节点池"><a href="#扩容节点池" class="headerlink" title="扩容节点池"></a>扩容节点池</h3><p>节点池的管理规划是完全面向终态的，但目前的实现还在早期阶段，您可以通过edit对应的NodePool的CRD的desiredCapacity的值来调整节点池的节点数量。<br>观测节点池的加入的过程参考上面方法。可以调大，也可以调小节点池的大小。<br>自动扩容节点池的功能Coming Soon。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ kubectl --kubeconfig ~/.kube/config.txt edit nodepool default-nodepool</span><br></pre></td></tr></table></figure><h2 id="集群高可用"><a href="#集群高可用" class="headerlink" title="集群高可用"></a>集群高可用</h2><p>一切都是面向终态的</p><h3 id="构建高可用的k8s集群"><a href="#构建高可用的k8s集群" class="headerlink" title="构建高可用的k8s集群"></a>构建高可用的k8s集群</h3><p>单个Master的k8s集群不具备高可用，但已足够用作测试集群，经济适用。wdrip同样提供了灵活简单的方式将已有集群扩展成高可用集群。wdrip适用<code>MasterSet</code>的CRD资源代表Master节点组。<br>以下命令扩展当前集群的Master副本数量到3个。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ kubectl --kubeconfig ~/.kube/config.txt edit masterset</span><br><span class="line">apiVersion: alibabacloud.com/v1</span><br><span class="line">kind: MasterSet</span><br><span class="line">metadata:</span><br><span class="line">  <span class="comment"># 请不要改masterset这个名称，没做支持，也没意义。</span></span><br><span class="line">  name: masterset</span><br><span class="line">  namespace: kube-system</span><br><span class="line">spec:</span><br><span class="line">  replicas: 3</span><br></pre></td></tr></table></figure><p>wdrip需要2分钟左右的时间来初始化额外的2个Master节点，请等待。可以通过<code>kubectl --kubeconfig ~/.kube/config.txt get no -w</code> 观测Master节点的加入过程。</p><h3 id="大规模集群场景"><a href="#大规模集群场景" class="headerlink" title="大规模集群场景"></a>大规模集群场景</h3><p>当你的集群规模进一步扩大后，3个Master已经不能满足你的需求了，那么你也可以通过MasterSet的<code>replicas</code>方便快速的将Master副本数量调整成您喜欢的任意的数量，不过一般不建议超过7个。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ kubectl --kubeconfig ~/.kube/config.txt -n kube-system edit masterset</span><br><span class="line"><span class="comment"># set replicas to 5</span></span><br></pre></td></tr></table></figure><p>然后通过上面的命令观测Master节点数量的变化，同样需要等待大约2分钟时间。</p><h3 id="缩减集群规模"><a href="#缩减集群规模" class="headerlink" title="缩减集群规模"></a>缩减集群规模</h3><p>一切都是面向终态的，当您的集群规模降低后，不在需要这么多的Master后，同样可以通过调整MasterSet的<code>replicas</code>来调整Master的数量。可以调整到3个副本，也可以调整到1个Master副本。Master缩减的过程中需要保持多数quorum，因此缩减是逐步发生的。并且在系统未达到稳态以前，缩减也不会立即发生。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ kubectl --kubeconfig ~/.kube/config.txt -n kube-system edit masterset</span><br><span class="line"><span class="comment"># set replicas to 3 or 1</span></span><br></pre></td></tr></table></figure><p>然后通过上面的命令观测Master节点数量的变化。</p><h2 id="集群灾难恢复"><a href="#集群灾难恢复" class="headerlink" title="集群灾难恢复"></a>集群灾难恢复</h2><h3 id="备份机制"><a href="#备份机制" class="headerlink" title="备份机制"></a>备份机制</h3><p>wdrip定期备份您的集群的k8s的etcd数据，用于发生集群级别故障的时候快速恢复。默认每10分钟备份一次，保留最近4个备份副本。<br>您可用通过<code>wdrip get -r backup</code>来查看当前的备份信息。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ wdrip get -r backup -n kubernetes-id-001</span><br><span class="line">I1002 18:28:13.072037   98760 provider.go:268] use HOME <span class="built_in">dir</span>: [/Users/aoxn]</span><br><span class="line">I1002 18:28:13.072184   98760 provider.go:283] trying to load context config from: /Users/aoxn/.wdrip/config</span><br><span class="line">I1002 18:28:13.072557   98760 oss.go:32] oss get object from [oss://wdrip-index/wdrip/backup/kubernetes-id-001/index.json]</span><br><span class="line">I1002 18:28:13.140780   98760 iaas.go:243]</span><br><span class="line">NAME                PREFIX                DATE                PATH</span><br><span class="line">kubernetes-id-001   wdrip/backup          20211002-1024       wdrip/backup/kubernetes-id-001/20211002-1024/snapshot.db</span><br><span class="line">kubernetes-id-001   wdrip/backup          20211002-1014       wdrip/backup/kubernetes-id-001/20211002-1014/snapshot.db</span><br><span class="line">kubernetes-id-001   wdrip/backup          20211002-1004       wdrip/backup/kubernetes-id-001/20211002-1004/snapshot.db</span><br><span class="line">kubernetes-id-001   wdrip/backup          20211002-0954       wdrip/backup/kubernetes-id-001/20211002-0954/snapshot.db</span><br></pre></td></tr></table></figure><h3 id="恢复场景一：在原基础设施上恢复"><a href="#恢复场景一：在原基础设施上恢复" class="headerlink" title="恢复场景一：在原基础设施上恢复"></a>恢复场景一：在原基础设施上恢复</h3><p>如果k8s因未知因素管控完全故障，wdrip没有能够自行恢复，那么您可以手动触发命令执行恢复。仅需要一行命令即可</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -n 指定恢复的目标集群（本体）。</span></span><br><span class="line">(base) ➜ wdrip recover -n kubernetes-id-001</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>等待大概2到3分钟后，通过kubectl get no 查看节点恢复情况。</p><h3 id="恢复场景二：恢复到新的基础设施上"><a href="#恢复场景二：恢复到新的基础设施上" class="headerlink" title="恢复场景二：恢复到新的基础设施上"></a>恢复场景二：恢复到新的基础设施上</h3><p>有些情况下，集群所对应的基础设施被损坏，人为的或者灾难性的，以至于无法在原有基础设施上恢复，那么我们可以通过新建一个具有相同规格的基础设施的集群，然后在本基础设施上恢复出原有集群的备份意识。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建具有相同规格的新的集群kubernetes-id-002，步骤参考【创建集群】Section</span></span><br><span class="line">(base) ➜ wdrip create --config config.yaml</span><br><span class="line"></span><br><span class="line"><span class="comment"># 将备份的旧的kubernetes-wdrip-120集群配置（意识）恢复到新建的集群121上。</span></span><br><span class="line"><span class="comment"># -n 指定恢复的目标集群（本体）， -f 指定恢复的配置来源于哪个集群（意识）。</span></span><br><span class="line">(base) ➜ wdrip recover -n kubernetes-id-002 -f kubernetes-id-001</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="节点修复机制"><a href="#节点修复机制" class="headerlink" title="节点修复机制"></a>节点修复机制</h2><p>节点是运行负载的工具而已，无需像对待宠物那样对待节点，对于失效的节点，替换是成本最小的方案，替换之前我们会尝试重启来恢复。</p><h2 id="自定义集群参数能力"><a href="#自定义集群参数能力" class="headerlink" title="自定义集群参数能力"></a>自定义集群参数能力</h2><p>规划中（节点、集群）</p><h2 id="运维简化机制"><a href="#运维简化机制" class="headerlink" title="运维简化机制"></a>运维简化机制</h2><p>节点故障后快速恢复，定位问题很难。 在wdrip这里，你可以直接删掉故障节点，让系统直接拉起一个新的节点副本即可。</p><h2 id="附录"><a href="#附录" class="headerlink" title="附录"></a>附录</h2><p>以上示例所涉及到的脚步均保存于wdrip项目中，使用前请<code>git clone</code>到本地.</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ git clone https://github.com/aoxn/wdrip.git</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;p&gt;&lt;strong&gt;安装wdrip&lt;/strong&gt;&lt;br&gt;下载最新版本wdrip.当前版本0.1.1&lt;/p&gt;
&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;(base) ➜ curl -sSL --retry 3 https://host-wdrip-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/wdrip/install.sh |bash&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;(base) ➜ &lt;span class=&quot;built_in&quot;&gt;ls&lt;/span&gt; -lht /usr/local/bin/wdrip&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# use wdrip -h to see wdrip help command&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;(base) ➜ wdrip -h&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;wdrip creates and manages infrastructure agnostic Kubernetes clusters&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            _         _&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           | |       (_)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; _ _ _   __| |  ____  _  ____&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;| | | | / _  | / ___)| ||  _ \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;| | | |( (_| || |    | || |_| |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; \___/  \____||_|    |_||  __/&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        |_|&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;wdrip creates and manages infrastructure agnostic Kubernetes clusters and empower strong auto heal ability and easy recovery&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Usage:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  wdrip [&lt;span class=&quot;built_in&quot;&gt;command&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Available Commands:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  bootstrap   Bootstrap a Kubernetes cluster&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  build       Kubernetes cluster build package&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Use &lt;span class=&quot;string&quot;&gt;&amp;quot;wdrip [command] --help&amp;quot;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; more information about a &lt;span class=&quot;built_in&quot;&gt;command&lt;/span&gt;.&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>遇见复原力</title>
    <link href="http://aoxn.github.io/2022/06/08/%E9%81%87%E8%A7%81%E5%A4%8D%E5%8E%9F%E5%8A%9B/"/>
    <id>http://aoxn.github.io/2022/06/08/%E9%81%87%E8%A7%81%E5%A4%8D%E5%8E%9F%E5%8A%9B/</id>
    <published>2022-06-08T04:32:49.000Z</published>
    <updated>2022-06-08T14:58:51.197Z</updated>
    
    <content type="html"><![CDATA[<h2 id="复原力"><a href="#复原力" class="headerlink" title="复原力"></a>复原力</h2><p>复原力一词来源于微软创新研究院，全称是社会复原力，它研究的是通过大规模部署可以适应未来各种变数以及不确定性的创新技术来应对社会的各种潜在危机，从而增强社会复原力。如COVID-19、全球气候变暖、环境污染，探索在危机来临前中后的创新技术储备，快速应对方法，快速复原的能力。是一种从无序和混乱中回归秩序的能力。这也是运维所要解决的问题，让系统回归秩序。</p><p>本文探索的是云原生时代下容器基础设施在面临各种危机时的复原力问题，即基础设施复原力。</p><span id="more"></span><h2 id="基础设施复原力"><a href="#基础设施复原力" class="headerlink" title="基础设施复原力"></a>基础设施复原力</h2><p>随着容器技术的不断发展，k8s已经成为了云原生时代下的基础设施，它为应用向下屏蔽了云上基础设施的复杂性，向上提供了应用的全生命周期管理能力，将分布式应用管理的复杂性收敛转化到了分布式系统本身的管理问题上。然而，它虽然解决了应用在分布式环境下的编排问题，但自身的分布式系统的运维复杂性仍然存在。底层基础设施失效，可用区故障，节点故障，组件失效，网络分区，抖动，甚至地震、火灾等风险始终存在，如何保证系统的稳定性以及面对这些危机时候的系统复原力是一项非常具有挑战的工作，这也构成了云原生时代下的基础设施复原力问题。</p><p>事实上，k8s面向终态的设计已经让应用具备了从外部扰动中回到稳态的能力，面对应用进程异常退出，容器失败，网络故障，配置紊乱等问题，k8s能够实现检测并自行原地恢复，或者替换掉失效应用副本来使应用处于预期状态，这是k8s的应用复原力。通过以上理念，我们希望云原生时代的基础设施也能具备从外部扰动中自动回归稳态的能力，同时以一种尽可能小的代价去解决k8s平台自身运维复杂性的问题，因此我们设计了<code>wdrip</code>，以一种逐渐收敛的方案来解决k8s分布式系统的自动化运维问题，实现基础设施的复原力。</p><h2 id="故障复原场景示例"><a href="#故障复原场景示例" class="headerlink" title="故障复原场景示例"></a>故障复原场景示例</h2><p>k8s 面向终态的设计为应用的复原力提供了支撑。从终态设计上你能看到k8s 让应用从外部扰动中回归稳态的思想, wdrip也同样采用面向终态的思想，在基础设施层解决k8s的自运维问题。下面会演示一些常见的k8s故障场景，并且观察系统是如何在无人为干预的情况下自动恢复的。</p><h3 id="前置条件"><a href="#前置条件" class="headerlink" title="前置条件"></a>前置条件</h3><p>wdrip的基本功能及其使用，请移步<a href="/2022/06/08/%E7%AE%A1%E7%90%86%E9%9B%86%E7%BE%A4/" title="管理集群">管理集群</a></p><ul><li><p>请使用wdrip创建一个k8s集群。</p></li><li><p>请部署示例应用，或者部署您自己觉得合适的[容器化应用]<a href="/2022/06/08/%E4%BA%91%E5%8E%9F%E7%94%9F%E5%BA%94%E7%94%A8%E7%A4%BA%E4%BE%8B/" title="云原生应用示例">云原生应用示例</a>。</p></li></ul><h3 id="场景一：节点故障"><a href="#场景一：节点故障" class="headerlink" title="场景一：节点故障"></a>场景一：节点故障</h3><p>节点故障是k8s集群故障里最常见的一种场景了，也是危害相对较小的故障，wdrip可以侦测节点的异常状态，然后尝试修复。修复的流程如下<br>如果节点状态变为NotReady，那么等待2个heartbeat周期</p><ul><li>如果周期内持续NotReady，wdrip尝试重启kubelet，并等待节点Ready</li><li>如果节点仍然NotReady，wdrip尝试驱逐节点Pod，然后继续尝试重启ECS，并等待节点Ready</li><li>如果节点仍然NotReady，wdrip继续尝试重置ECS（替换节点的系统盘，并重新初始化节点），并等待节点Ready</li><li>如果节点仍然NotReady，wdrip删除这个节点，等待系统重启创建一个全新的节点副本。</li><li>如果节点仍然NotReady，修复失败。等待throttle周期后重复以上步骤。</li></ul><p>通常可以通过以下手段模拟节点故障：</p><ol><li>方法一：通过<code>kubectl delete no $&#123;your-node&#125;</code> 删除对应的Node Object。等待节点自动恢复并注册回来，恢复全程无需人工干预，时长约2分钟。</li><li>方法二：登录ECS节点，systemctl stop kubelet&#x2F;docker等。等待节点NotReady后，系统会自行恢复节点状态。恢复全程无需人工干预。</li><li>方法三：到ECS控制台上【关闭】节点对应的ECS。系统会自行恢复节点状态。恢复全程无需人工干预。</li><li>方法四：到ECS控制台上【删除】节点对应的ECS。系统会自行恢复节点状态。恢复全程无需人工干预。</li></ol><p>[去试一试]<a href="/2022/06/08/%E7%AE%A1%E7%90%86%E9%9B%86%E7%BE%A4/" title="管理集群">管理集群</a></p><h3 id="场景二：管控故障"><a href="#场景二：管控故障" class="headerlink" title="场景二：管控故障"></a>场景二：管控故障</h3><p>管控故障通常情况下是比较严重的，k8s集群依赖etcd组成高可用集群，一旦etcd quorum丢失，集群管控将会直接不可用。因此正常情况下管控的恢复要更加的复杂。<br>wdrip精心抽象了管控的恢复流程，操作前会尽量确保etcd quorum始终保持在可用状态。但仍然具备在quorum丢失的情况下从混乱中使用snapshot恢复集群管控。</p><p>通常可以通过以下方法模拟管控故障：</p><ol><li>方法一：通过kubectl命令删除master node。</li><li>方法二：登录Master节点ECS，stop ETCD服务，删除etcd数据，stop kubelet服务，stop docker服务等。</li><li>方法三：登录ECS控制台【关闭】一台Master节点ECS。</li><li>方法四：登录ECS控制台【删除】一台Master节点ECS。</li></ol><p>对于3个master或更多个master副本的集群，你可以操作让一台ECS节点故障，等待查看系统如何回复到稳定状态，这个过程中整个系统全程仍然可以提供服务。重要的是，你可以操作多台Master ECS节点，让他们同时处于故障状态，这时候系统大概率会因为quorum丢失从而造成集群不可用，但你仍然能够观察到wdrip会通过各种手段将集群恢复到正常的稳定状态，并且无需人工干预。<br>对于worker节点，只要不涉及到管控面访问相关的业务，恢复的过程中用户的业务将不受任何影响，实现业务的连续性。</p><h3 id="场景三：可用区故障"><a href="#场景三：可用区故障" class="headerlink" title="场景三：可用区故障"></a>场景三：可用区故障</h3><p>虽然可用区级别的故障的概率非常低，但我们仍然在设计的时候考虑到这种场景，wdrip支持创建跨可用区的集群，添加多个不同可用区的节点池可以让节点分布到不同可用区，提高集群面对可用区故障时候的韧性。</p><p>当管控所在的可用区出现故障时候，集群不可用，集群上的应用大概率也会不可用，wdrip支持snapshot整个k8s集群，然后在其他可用区使用该snapshot一键重新拉起一个一模一样的集群，这种恢复方式保留了所有原集群的配置，唯一变化的是承载集群运行的基础设施，如ECS、SLB等等。相当于在一个新的克隆体中恢复之前备份的大脑，意识下载。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ wdrip recover -n kubernetes-wdrip-121 -f kubernetes-wdrip-120</span><br></pre></td></tr></table></figure><h3 id="场景四：Region故障"><a href="#场景四：Region故障" class="headerlink" title="场景四：Region故障"></a>场景四：Region故障</h3><p>整个Region发生故障的概率应该是非常非常的低的了，但wdrip设计上仍然能够处理这种灾难。wdrip在运行时会定期备份集群的状态到OSS（可以跨Region写多份实现高可用），当Region出现故障的时候，可以尝试在另外一个Region创建一个新的集群，然后通过备份的snapshot快速恢复业务。参考可用区故障。但目前很多存储资源是可用区级别的，因此还需要进一步考虑存储的跨Region恢复。</p><h3 id="场景五：删库跑路"><a href="#场景五：删库跑路" class="headerlink" title="场景五：删库跑路"></a>场景五：删库跑路</h3><p>一直想提的一个场景就是删库跑路。wdrip定期备份了整个集群的意识，无论你怎么折腾集群，只要备份存在，意识就存在，wdrip就可以再完完全全的还原出一个集群的克隆体出来，恢复现场到以前的状态。</p><p><strong>删库跑路？不存在的。</strong></p><p>你可以尝试删除集群试试，删除方法</p><ol><li>到ROS控制台删除该集群对应的ROS模板，按名称搜索即可找到对应的模板</li><li><code>wdrip delete -n kubernetes-id-001</code> 不用担心，即便删除了集群，但备份还在，我们仍然能完整的恢复该集群，这也是wdrip的魅力。</li></ol><p>恢复的方法：</p><ol><li>创建新的集群kubernetes-id-002。<code>wdrip create --config cluster.yml</code></li><li>恢复集群的意识备份到这个新建的集群本体上。 <code>wdrip recover -n kubernetes-id-002 -f kubernetes-id-001</code></li></ol><h3 id="灾难恢复（手动）"><a href="#灾难恢复（手动）" class="headerlink" title="灾难恢复（手动）"></a>灾难恢复（手动）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -n 指定恢复的目标集群（本体）， -f 指定恢复的配置来源于哪个集群（意识）。</span></span><br><span class="line">(base) ➜ wdrip recover -n kubernetes-id-002 -f kubernetes-id-001</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="ChaosMonkey"><a href="#ChaosMonkey" class="headerlink" title="ChaosMonkey"></a>ChaosMonkey</h3><p>为了测试基础设施复原力我们专门编写了ChaosMonkey部署在集群中，他能够定期破坏集群(删除集群ECS资源、停止关键组件)，等待系统自愈。</p><p>如何使用</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  export CLUSTER_NAME=kubernetes-id-001</span><br><span class="line">(base) ➜  bash hack/wdrip.sh config</span><br><span class="line">(base) ➜  bash hack/wdrip.sh chaos</span><br><span class="line">(base) ➜  kubectl --kubeconfig ~/.kube/config.wdrip -n kube-system get po|grep monkey</span><br></pre></td></tr></table></figure><h2 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h2><p>k8s的复杂性虽然让让人生畏，但wdrip提供的复原力让我们在面对危机的时候能够更加的从容。</p><p>以上示例所涉及到的脚步均保存于wdrip项目中，使用前请<code>git clone</code>到本地.</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜ git clone https://github.com/aoxn/wdrip.git</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;p&gt;复原力一词来源于微软创新研究院，全称是社会复原力，它研究的是通过大规模部署可以适应未来各种变数以及不确定性的创新技术来应对社会的各种潜在危机，从而增强社会复原力。如COVID-19、全球气候变暖、环境污染，探索在危机来临前中后的创新技术储备，快速应对方法，快速复原的能力。是一种从无序和混乱中回归秩序的能力。这也是运维所要解决的问题，让系统回归秩序。&lt;/p&gt;
&lt;p&gt;本文探索的是云原生时代下容器基础设施在面临各种危机时的复原力问题，即基础设施复原力。&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>Kubernetes API设计哲学</title>
    <link href="http://aoxn.github.io/2017/12/16/KuberntesAPI%E8%AE%BE%E8%AE%A1%E5%93%B2%E5%AD%A6/"/>
    <id>http://aoxn.github.io/2017/12/16/KuberntesAPI%E8%AE%BE%E8%AE%A1%E5%93%B2%E5%AD%A6/</id>
    <published>2017-12-16T07:21:02.000Z</published>
    <updated>2022-06-08T02:09:14.806Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Kubernetes-API设计哲学"><a href="#Kubernetes-API设计哲学" class="headerlink" title="Kubernetes API设计哲学"></a>Kubernetes API设计哲学</h1><p>kubernetes API设计时遵循了如下几个特征，声明式的API设计、水平触发的reconcile、异步的pull模式</p><h2 id="声明式（Declarative）"><a href="#声明式（Declarative）" class="headerlink" title="声明式（Declarative）"></a>声明式（Declarative）</h2><p>用户指定的是期望达到的状态，而不是操作命令。<br>Kubernetes API设计的理念如下： 用户将一个资源对象的期望状态通过描述文件的方式发送给API接口，然后API接口通过不间断的操作使资源对象达到并稳定在期望的状态之上。例如，用户将一个具有多个副本、及指定版本的deployment发送到API接口时，API首先对该资源对象做校验然后进行持久化存储，接下来一个reconcile操作会取回该资源并执行该资源的定义操作，直到该资源的实际状态与定义的期望状态一致。期间如果实际状态被意外更改，仍然会被reconcile到期望状态。</p><p><strong>reconcile</strong><br>reconcile是一组预定义的循环操作(通常的实现是controller-manager)，watch storage上资源对象的期望状态的变化，并对比资源的本地实际状态，执行相关操作使资源最终达到该期望的一致状态，具有幂等性。<br><img src="/upload/15134909004013.jpg"></p><h2 id="水平触发（Level-trigger）"><a href="#水平触发（Level-trigger）" class="headerlink" title="水平触发（Level trigger）"></a>水平触发（Level trigger）</h2><p>Kubernetes API是基于水平触发的实现，系统会驱动资源达到当前所期望的状态，而不管在此之前被设置了哪些不同的期望状态，以当前为基准。例如对当前正在进行rollout的deployment更改其镜像，会促使系统放弃执行当前未完成的rollout,转而进入新的desired state reconcile 流程，即切换到最新的修改上。</p><h2 id="异步性（Asynchronous）"><a href="#异步性（Asynchronous）" class="headerlink" title="异步性（Asynchronous）"></a>异步性（Asynchronous）</h2><p>Kubernetes API接口异步的执行资源的desired state reconcile操作。这意味着创建资源的API请求会在完成校验并存储后立刻返回给调用方而不会立刻执行任何的资源创建动作。这也会导致许多创建中的错误不会在这个阶段返回给用户。解决的方式是定义良好的事件通知机制，资源reconcile过程中产生的错误信息写入到资源关联的事件中，用户通过watch事件了解创建过程。</p><h2 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h2><p><a href="https://github.com/kubernetes-incubator/apiserver-builder/blob/master/docs/concepts/api_building_overview.md">Building and using Kubernetes API</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;Kubernetes-API设计哲学&quot;&gt;&lt;a href=&quot;#Kubernetes-API设计哲学&quot; class=&quot;headerlink&quot; title=&quot;Kubernetes API设计哲学&quot;&gt;&lt;/a&gt;Kubernetes API设计哲学&lt;/h1&gt;&lt;p&gt;kubern</summary>
      
    
    
    
    <category term="Kubernetes" scheme="http://aoxn.github.io/categories/Kubernetes/"/>
    
    <category term="Container" scheme="http://aoxn.github.io/categories/Kubernetes/Container/"/>
    
    <category term="容器" scheme="http://aoxn.github.io/categories/Kubernetes/Container/%E5%AE%B9%E5%99%A8/"/>
    
    
    <category term="Kubernetes" scheme="http://aoxn.github.io/tags/Kubernetes/"/>
    
  </entry>
  
  <entry>
    <title>内核页表的传递</title>
    <link href="http://aoxn.github.io/2016/01/27/pagetable/"/>
    <id>http://aoxn.github.io/2016/01/27/pagetable/</id>
    <published>2016-01-27T01:24:44.000Z</published>
    <updated>2022-06-08T02:09:14.807Z</updated>
    
    <content type="html"><![CDATA[<h2 id="问题一："><a href="#问题一：" class="headerlink" title="问题一："></a>问题一：</h2><p>每个用户进程都有自己的页全局目录及页表，然后内核代表进程在内核态执行，此时如果内核代码修改了内核页表，那么这些修改是如何传递到其他用户进程的？毕竟所有用户进程维护自己的页表，同时关于内核线性空间的页表还必须相同，这个是如何做到的？</p><span id="more"></span><p>答案是:</p><p>map_vm_area()并不触及当前进程页表，而是直接修改init进程页表也就是主内核页表。一旦内核代表当前进程访问非连续内存区是，缺页发生，缺页处理程序会检查该地址是否是内核地址，并且该线性地址是否在主内核页表中。一旦处理程序发现一个主内核页表的有一个该线性地址的非空项，则将该项拷贝到当前进程的页表中。</p><h2 id="问题二："><a href="#问题二：" class="headerlink" title="问题二："></a>问题二：</h2><p>那么问题又来了，第一次内核访问非连续存储区的时候，由于进程页表的相应项为空会发生缺页异常，但是如果此后主内核页表项被修改，然后内核再次代表该进程访问非连续物理内存区的时候，由于页表已经被拷贝过旧的值，因此不会发生缺页异常，因此就会访问都错误的非连续的内存区，是这样么？</p><p>答案是：</p><p>因为在上一步的页表拷贝中，只拷贝了页全局目录的部分项，因此当前进程与主内核页表共享相同的页表项，并且这些页表项一旦被分配就不会被回收，但可以修改。这样所有对主内核页表的修改都会传递到当前进程。如果进程试图访问一个已经被释放发非连续内存区也会引发缺页异。</p><p>参见《深入理解Linux内核》</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;每个用户进程都有自己的页全局目录及页表，然后内核代表进程在内核态执行，此时如果内核代码修改了内核页表，那么这些修改是如何传递到其他用户进程的？毕竟所有用户进程维护自己的页表，同时关于内核线性空间的页表还必须相同，这个是如何做到的？&lt;/p&gt;</summary>
    
    
    
    <category term="操作系统" scheme="http://aoxn.github.io/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/"/>
    
    <category term="Linux内核" scheme="http://aoxn.github.io/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/Linux%E5%86%85%E6%A0%B8/"/>
    
    
    <category term="页表" scheme="http://aoxn.github.io/tags/%E9%A1%B5%E8%A1%A8/"/>
    
  </entry>
  
  <entry>
    <title>进程切换时的现场保护问题</title>
    <link href="http://aoxn.github.io/2015/11/05/swithprocess/"/>
    <id>http://aoxn.github.io/2015/11/05/swithprocess/</id>
    <published>2015-11-05T14:53:06.000Z</published>
    <updated>2022-06-08T02:09:14.806Z</updated>
    
    <content type="html"><![CDATA[<h2 id="进程切换流程"><a href="#进程切换流程" class="headerlink" title="进程切换流程"></a>进程切换流程</h2><p>进程的切换只会发生在内核精心定义的点上：schedule()函数。从本质上来说进程的切换由两个步骤完成，或两个标志性动作：  </p><ul><li>1.切换页全局目录来安装一个新的地址空间，cr3寄存器。<br>这里请考虑这样一个问题，一旦页全局目录被切换成其他进程的，那么eip在取下一条指令时通过页表映射的方式还能正常的取到当前执行流的下一条指令吗？毕竟两个进程的页全局目录、页表大部分情况肯定会不一样。<br>答案是：进程切换发生在内核态，所有代码的引用的地址空间大于0xC0000000,这部分页表属于主内核页表，而所有进程具有相同的主内核页表（至于为何具有相同主内核也表，见下一节），所以指令可以正常取并执行。  </li><li>2.切换内核态堆栈与硬件上下文。<br>那么切换时的现场保护问题，尤其是SS段寄存器和esp寄存器的保护 。由于进程的切换发生在内核态，通常在进入内核态中断发生时，硬件上下文会被自动保存。</li></ul><span id="more"></span><h2 id="切换问题"><a href="#切换问题" class="headerlink" title="切换问题"></a>切换问题</h2><p>一直有一个疑问，在中断发生时上下文切换的时候会发生栈的切换，并且把原来的栈段寄存器SS和esp寄存器的值一起保存到新的内核栈段寄存器SS和esp寄存器指向的内核栈，而且这个时候还不能使用任何的其他寄存器辅助（因为硬件上下文还没有保存，任何对寄存器的引用都会破坏进程的上下文），并且任何的push操作都会改变当前的esp，这个切换过程究竟是如何实现的？</p><h2 id="答案"><a href="#答案" class="headerlink" title="答案"></a>答案</h2><p>MDD，硬件上下文的切换是硬件自动完成的，不需要软件做。软件做的只是提供好中断号、idtr寄存器、gdtr寄存器、tr寄存器的值。<br>中断发生时，硬件做了一系列工作，包含获取中断号，从idtr寄存器根据中断号找到中断处理程序入口地址CS：EIP，根据CS及gdtr寄存器找到中断入口代码的段基址及特权位，判断如果特权位发生变化则需要切换到内核栈，切换的过程是从tr寄存器找到当前进程的TSS段，然后把TSS段里保存的当前进程的内核栈SS：ESP放入当前SS：ESP中，并将原来的SS：ESP值push到当前栈中，然后push CS,EIP,EFLAG等寄存器。注意这些都是硬件完成的。而通用寄存器的保护工作应该是由中断处理程序ISR做的。</p><pre><code>参见《深入理解Linux内核》</code></pre>]]></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;进程的切换只会发生在内核精心定义的点上：schedule()函数。从本质上来说进程的切换由两个步骤完成，或两个标志性动作：  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1.切换页全局目录来安装一个新的地址空间，cr3寄存器。&lt;br&gt;这里请考虑这样一个问题，一旦页全局目录被切换成其他进程的，那么eip在取下一条指令时通过页表映射的方式还能正常的取到当前执行流的下一条指令吗？毕竟两个进程的页全局目录、页表大部分情况肯定会不一样。&lt;br&gt;答案是：进程切换发生在内核态，所有代码的引用的地址空间大于0xC0000000,这部分页表属于主内核页表，而所有进程具有相同的主内核页表（至于为何具有相同主内核也表，见下一节），所以指令可以正常取并执行。  &lt;/li&gt;
&lt;li&gt;2.切换内核态堆栈与硬件上下文。&lt;br&gt;那么切换时的现场保护问题，尤其是SS段寄存器和esp寄存器的保护 。由于进程的切换发生在内核态，通常在进入内核态中断发生时，硬件上下文会被自动保存。&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="操作系统" scheme="http://aoxn.github.io/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/"/>
    
    <category term="Linux内核" scheme="http://aoxn.github.io/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/Linux%E5%86%85%E6%A0%B8/"/>
    
    
    <category term="进程切换" scheme="http://aoxn.github.io/tags/%E8%BF%9B%E7%A8%8B%E5%88%87%E6%8D%A2/"/>
    
  </entry>
  
  <entry>
    <title>关于从x86实模式到保护模式的关键一跳的指令连续执行问题</title>
    <link href="http://aoxn.github.io/2015/11/05/keyjump/"/>
    <id>http://aoxn.github.io/2015/11/05/keyjump/</id>
    <published>2015-11-05T14:06:15.000Z</published>
    <updated>2022-06-08T02:09:14.807Z</updated>
    
    <content type="html"><![CDATA[<h2 id="问题描述"><a href="#问题描述" class="headerlink" title="问题描述"></a>问题描述</h2><p>关于实模式与保护模式的基础可以参考《深入理解linux内核》，或相关博文。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">1.实模式下的寻址方式</span><br><span class="line">      cs &lt;&lt;<span class="string">4 + ip</span></span><br><span class="line"><span class="string">2.保护模式下的寻址方式</span></span><br><span class="line"><span class="string">      base(index(cs)) +eip</span></span><br><span class="line"><span class="string">3.x86实模式进入保护模式的代码</span></span><br><span class="line"><span class="string">       lgdt  GdtPtr        //加载 GDTR</span></span><br><span class="line"><span class="string">       cli                       //关中断</span></span><br><span class="line"><span class="string">                                 //打开地址线A20等</span></span><br><span class="line"><span class="string">                                 //下面准备切换到保护模式</span></span><br><span class="line"><span class="string">       mov   %cr0，%eax</span></span><br><span class="line"><span class="string">       or       0x1,%eax</span></span><br><span class="line"><span class="string">       mov   %eax,%cr0 //将cr0的PE位置1，进入保护模式</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">       jmp   dword SelectorSode32:0x0</span></span><br></pre></td></tr></table></figure><p><strong>问题:</strong><br>当打开cr0的PE位的瞬间，处理器进入保护模式，寻址方式改变。此时cs的值并没有改变，并且打开cr0瞬间处理器对cs的解释方式完全不一样，那么问题来了，如何确保在进入保护模式后下一条指令被顺利执行？</p><span id="more"></span><h2 id="解决过程"><a href="#解决过程" class="headerlink" title="解决过程"></a>解决过程</h2><p>你可能会想  </p><ul><li>1.是不是cs段寄存器的内容足够特别，使得无论此时采用实模式的寻址方式还是保护模式的寻址方式所解释出来的地址相等？然后你会发现其实这个cs目前值没有任何规律，完全不对头。</li><li>2.翻一翻x86指令集，发现x86规定，在cpu执行长跳转指令的时候才会自动改变cs寄存器的值。然后你会去找，是不是前后有哪些地方执行过长跳转指令？然后没找到。</li><li>3.然后没招的时候你还可能想是不是并不一定就是接着下一条指令执行呢？然后就真的按照当前cs段的值以实模式的方式计算一下下条指令会在那个地方，最后发现根本行不通。</li></ul><p>** 图书馆、百度、Google齐上阵后发现**</p><h2 id="问题答案"><a href="#问题答案" class="headerlink" title="问题答案"></a>问题答案</h2><p>段寄存器后面都有隐藏的高速缓冲寄存器，当cs寄存器值被更新时，这个高速缓冲寄存器的值会根据当时的寻址方式更新，比如实模式下就是cs&lt;&lt;4后放入高速缓冲寄存器，等需要取指令的时候就直接取高速缓冲寄存器的值与eip相加即可，并不会真的再去cs段寄存器找这个值然后做像保护模式下的寻址方式那样推导。这样就解释了上面的情况，虽然寻址方式改变了，但是cs段寄存器的值没变，高速缓冲寄存器的值就不会变，基址仍然是实模式时的值，从而实际上计算出来的还是实模式的地址，保证了指令流的持续执行。内核在等到切换准备就绪的时候就会执行一个长跳转指令来刷新cs段寄存器的值，从而真的跳转导保护模式下了。</p><pre><code> 可以参考《x86汇编语言：从实模式到保护模式》，里面也做了相关描述。</code></pre>]]></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;关于实模式与保护模式的基础可以参考《深入理解linux内核》，或相关博文。&lt;/p&gt;
&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1.实模式下的寻址方式&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      cs &amp;lt;&amp;lt;&lt;span class=&quot;string&quot;&gt;4 + ip&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;2.保护模式下的寻址方式&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;      base(index(cs)) +eip&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;3.x86实模式进入保护模式的代码&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;       lgdt  GdtPtr        //加载 GDTR&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;       cli                       //关中断&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;                                 //打开地址线A20等&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;                                 //下面准备切换到保护模式&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;       mov   %cr0，%eax&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;       or       0x1,%eax&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;       mov   %eax,%cr0 //将cr0的PE位置1，进入保护模式&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;       jmp   dword SelectorSode32:0x0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;问题:&lt;/strong&gt;&lt;br&gt;当打开cr0的PE位的瞬间，处理器进入保护模式，寻址方式改变。此时cs的值并没有改变，并且打开cr0瞬间处理器对cs的解释方式完全不一样，那么问题来了，如何确保在进入保护模式后下一条指令被顺利执行？&lt;/p&gt;</summary>
    
    
    
    <category term="操作系统" scheme="http://aoxn.github.io/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/"/>
    
    <category term="Linux内核" scheme="http://aoxn.github.io/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/Linux%E5%86%85%E6%A0%B8/"/>
    
    
    <category term="实模式" scheme="http://aoxn.github.io/tags/%E5%AE%9E%E6%A8%A1%E5%BC%8F/"/>
    
    <category term="保护模式" scheme="http://aoxn.github.io/tags/%E4%BF%9D%E6%8A%A4%E6%A8%A1%E5%BC%8F/"/>
    
  </entry>
  
  <entry>
    <title>基于haproxy和keepalived的高可用的私有docker registry</title>
    <link href="http://aoxn.github.io/2015/11/04/highavailableregistry/"/>
    <id>http://aoxn.github.io/2015/11/04/highavailableregistry/</id>
    <published>2015-11-04T14:02:11.000Z</published>
    <updated>2022-06-08T02:09:14.806Z</updated>
    
    <content type="html"><![CDATA[<p>本文用于搭建一个基于haproxy和keepalived的高可用的私有docker registry</p><h2 id="部署结构"><a href="#部署结构" class="headerlink" title="部署结构"></a>部署结构</h2><ul><li>haproxy keepalived 主：221.228.86.4</li><li>haproxy keepalived 备：221.228.86.5</li><li>docker registry 1：    221.228.86.6</li><li>docker registry 2：    221.228.86.67</li><li>VIP : 221.228.86.70</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">                    221.228.86.100</span><br><span class="line">             +-----------VIP----------+   </span><br><span class="line">             |                        |</span><br><span class="line">             |                        |</span><br><span class="line">           Master                   Backup</span><br><span class="line">        221.228.86.4             221.228.86.6</span><br><span class="line">        +----------+             +----------+</span><br><span class="line">        | HAProxy  |             | HAProxy  |</span><br><span class="line">        |keepalived|             |keepalived|</span><br><span class="line">        +----------+             +----------+</span><br><span class="line">             |  </span><br><span class="line">             v  </span><br><span class="line">    +--------+---------+ </span><br><span class="line">    |        |         |</span><br><span class="line">    |        |         |</span><br><span class="line">    v        v         v</span><br><span class="line">+------+  +------+  +------+</span><br><span class="line">| WEB1 |  | WEB2 |  | WEB3 |</span><br><span class="line">+------+  +------+  +------+</span><br></pre></td></tr></table></figure><span id="more"></span><h4 id="修改docker-daemon-启动参数"><a href="#修改docker-daemon-启动参数" class="headerlink" title="修改docker daemon 启动参数"></a>修改docker daemon 启动参数</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">修改/etc/default/docker文件，在DOCKER_OPTS=<span class="string">&quot;--insecure-registry vip:5000&quot;</span></span><br></pre></td></tr></table></figure><h2 id="Docker-Registry-配置"><a href="#Docker-Registry-配置" class="headerlink" title="Docker Registry 配置"></a>Docker Registry 配置</h2><ul><li>参考 <a href="https://github.com/docker/distribution/blob/master/docs/configuration.md">https://github.com/docker/distribution/blob/master/docs/configuration.md</a></li><li>221.228.86.5 221.228.86.67</li><li>在&#x2F;var&#x2F;lib&#x2F;pri_docker_registry&#x2F;目录下建立config.yml配置文件,内容如下：</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">version: 0.1</span><br><span class="line"><span class="built_in">log</span>:</span><br><span class="line">  level: debug</span><br><span class="line">  formatter: json</span><br><span class="line">  fields:</span><br><span class="line">    service: registry</span><br><span class="line">  hooks:</span><br><span class="line">    - <span class="built_in">type</span>: mail</span><br><span class="line">      disabled: <span class="literal">true</span></span><br><span class="line">      levels:</span><br><span class="line">        - panic</span><br><span class="line">      options:</span><br><span class="line">        smtp:</span><br><span class="line">          addr: mail.yy.com:25</span><br><span class="line">          username: xxx</span><br><span class="line">          password: pass</span><br><span class="line">          insecure: <span class="literal">true</span></span><br><span class="line">        from: sender@yy.com</span><br><span class="line">        to:</span><br><span class="line">          - errors@yy.com</span><br><span class="line">storage:</span><br><span class="line">    filesystem:</span><br><span class="line">        rootdirectory: /var/lib/registry</span><br><span class="line">    delete:</span><br><span class="line">      enabled: <span class="literal">true</span></span><br><span class="line">    redirect:</span><br><span class="line">      <span class="built_in">disable</span>: <span class="literal">false</span></span><br><span class="line">http:</span><br><span class="line">    addr: :5000</span><br><span class="line">    headers:</span><br><span class="line">        X-Content-Type-Options: [nosniff]</span><br><span class="line">health:</span><br><span class="line">  storagedriver:</span><br><span class="line">    enabled: <span class="literal">true</span></span><br><span class="line">    interval: 10s</span><br><span class="line">    threshold: 3</span><br></pre></td></tr></table></figure><ul><li>在docker registry 1 、2、3上分别执行如下命令</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ <span class="built_in">mkdir</span> -p /var/lib/registry</span><br><span class="line">$ docker run -d -p 5000:5000 --net=host --restart=always -v /var/lib/pri_docker_registry/config.yml:/etc/docker/registry/config.yml -v /var/lib/registry:/var/lib/registry -v /etc/ceph/:/etc/ceph/ --name docker-registry registry:2.1</span><br></pre></td></tr></table></figure><p>一定要将ceph的配置文件挂载进入容器，rados访问ceph需要</p><ul><li>配置iptables规则，只允许proxy机器访问</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">$ iptables -A INPUT -d 221.228.86.67/32 -m comment --comment <span class="string">&quot;not allow to be connected except proxy&quot;</span> -j DROP</span><br><span class="line">$ iptables -I INPUT 1 -s 221.228.86.4 -d 221.228.86.67 -j ACCEPT</span><br><span class="line">$ iptables -I INPUT 1 -s 221.228.86.6 -d 221.228.86.67 -j ACCEPT</span><br><span class="line"><span class="comment"># 添加办公网的访问</span></span><br><span class="line">$ iptables -I INPUT -s 183.60.177.224/27 -d 221.228.86.70/32 -j ACCEPT</span><br><span class="line">  <span class="comment"># 配置221.228.86.6</span></span><br><span class="line">$ iptables -A INPUT -d 221.228.86.5/32 -m comment --comment <span class="string">&quot;not allow to be connected except proxy&quot;</span> -j DROP</span><br><span class="line">$ iptables -I INPUT 1 -s 221.228.86.4 -d 221.228.86.5 -j ACCEPT</span><br><span class="line">$ iptables -I INPUT 1 -s 221.228.86.6 -d 221.228.86.5 -j ACCEPT</span><br><span class="line">$ iptables -I INPUT -s 183.60.177.224/27 -d 221.228.86.70/32 -j ACCEPT</span><br></pre></td></tr></table></figure><h2 id="Haproxy-配置"><a href="#Haproxy-配置" class="headerlink" title="Haproxy 配置"></a>Haproxy 配置</h2><ul><li>参考 <a href="https://hub.docker.com/_/haproxy/">https://hub.docker.com/_/haproxy/</a></li><li>在haproxy 主备上分别执行下面命令,在&#x2F;var&#x2F;lib&#x2F;hadporxy&#x2F;目录下建立haproxy.cfg配置文件,内容如下:</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">global</span><br><span class="line">    <span class="built_in">log</span> 127.0.0.1 local3 info</span><br><span class="line">    maxconn 4096</span><br><span class="line">    nbproc 1</span><br><span class="line">    pidfile /var/lib/haproxy/haproxy.pid</span><br><span class="line">defaults</span><br><span class="line">    maxconn 2000</span><br><span class="line">    <span class="built_in">timeout</span> connect 5000</span><br><span class="line">    <span class="built_in">timeout</span> client 30000</span><br><span class="line">    <span class="built_in">timeout</span> server 30000</span><br><span class="line">    mode http</span><br><span class="line">    stats uri /admin?stats</span><br><span class="line">    option forwardfor</span><br><span class="line">frontend http_server</span><br><span class="line">    <span class="built_in">bind</span> :5000</span><br><span class="line">    <span class="built_in">log</span> global</span><br><span class="line">    default_backend docker-registry</span><br><span class="line">    <span class="comment">#acl test hdr_dom(host) -i test.domain.com</span></span><br><span class="line">    <span class="comment">#use_backend cache_test if test</span></span><br><span class="line">backend docker-registry</span><br><span class="line">    <span class="comment">#balance roundrobin</span></span><br><span class="line">    balance <span class="built_in">source</span></span><br><span class="line">    option httpchk GET /v2/ HTTP/1.1\r\nHost:221.228.86.6</span><br><span class="line">    server inst1 221.228.86.5:5000 check inter 5000 fall 3</span><br><span class="line">    server inst2 221.228.86.67:5000 check inter 5000 fall 3</span><br><span class="line"><span class="comment">#HAProxy管理页面 </span></span><br><span class="line">listen admin_stat</span><br><span class="line">    <span class="built_in">bind</span> *:1158                    <span class="comment">#管理页面端口</span></span><br><span class="line">    mode http                        </span><br><span class="line">    stats refresh 10s                <span class="comment">#自动刷新时间</span></span><br><span class="line">    stats uri /haproxy                 <span class="comment">#页面名称</span></span><br><span class="line">    stats realm Haproxy\ Statistics     <span class="comment">#登录提示</span></span><br><span class="line">    stats auth admin:admin    <span class="comment">#帐号密码</span></span><br><span class="line">    stats hide-version </span><br><span class="line">stats admin <span class="keyword">if</span> TRUE</span><br></pre></td></tr></table></figure><h4 id="创建haproxy-registry容器"><a href="#创建haproxy-registry容器" class="headerlink" title="创建haproxy-registry容器"></a>创建haproxy-registry容器</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ <span class="built_in">mkdir</span> -p /var/lib/haproxy</span><br><span class="line">$ docker run -d --name haproxy-registry --net=host -v /var/lib/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro haproxy:1.5</span><br></pre></td></tr></table></figure><h4 id="清除Iptables-规则，目前让所有机器都能访问该proxy"><a href="#清除Iptables-规则，目前让所有机器都能访问该proxy" class="headerlink" title="清除Iptables 规则，目前让所有机器都能访问该proxy"></a>清除Iptables 规则，目前让所有机器都能访问该proxy</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ iptables -D INPUT -d 221.228.86.5/32 -m comment --comment sigma -j DROP</span><br></pre></td></tr></table></figure><h2 id="Keepalived主备配置"><a href="#Keepalived主备配置" class="headerlink" title="Keepalived主备配置"></a>Keepalived主备配置</h2><p>使用Keeplalived管理浮动IP</p><ul><li>在221.228.86.4 221.228.86.6机器上同时安装keepalived，keepalived配置文件区别设置<h4 id="Ubuntu-Keepalived安装"><a href="#Ubuntu-Keepalived安装" class="headerlink" title="Ubuntu Keepalived安装"></a>Ubuntu Keepalived安装</h4></li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ apt-get install keepalived</span><br></pre></td></tr></table></figure><h4 id="Master（221-228-86-4）服务器配置-x2F-etc-x2F-keepalived-x2F-keepalived-conf"><a href="#Master（221-228-86-4）服务器配置-x2F-etc-x2F-keepalived-x2F-keepalived-conf" class="headerlink" title="Master（221.228.86.4）服务器配置 &#x2F;etc&#x2F;keepalived&#x2F;keepalived.conf"></a>Master（221.228.86.4）服务器配置 &#x2F;etc&#x2F;keepalived&#x2F;keepalived.conf</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">global_defs &#123;</span><br><span class="line">   notification_email &#123;</span><br><span class="line">       xieyaoyao@yy.com</span><br><span class="line">   &#125;</span><br><span class="line">   notification_email_from mail@example.org</span><br><span class="line">   smtp_server mail.yy.com</span><br><span class="line">   smtp_connect_timeout 30</span><br><span class="line">   router_id LVS_DEVEL</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">#监测haproxy进程状态，每2秒执行一次</span></span><br><span class="line">vrrp_script chk_haproxy &#123;</span><br><span class="line">    script <span class="string">&quot;/usr/local/keepalived/chk_haproxy.sh&quot;</span></span><br><span class="line">    interval 2</span><br><span class="line">    weight 2</span><br><span class="line">&#125;</span><br><span class="line">vrrp_instance VI_1 &#123;</span><br><span class="line">    state MASTER <span class="comment">#标示状态为MASTER</span></span><br><span class="line">    interface eth0</span><br><span class="line">    virtual_router_id 51</span><br><span class="line">    priority 101   <span class="comment">#MASTER权重要高于BACKUP</span></span><br><span class="line">    advert_int 1</span><br><span class="line">    mcast_src_ip 221.228.86.4 <span class="comment">#Master服务器IP</span></span><br><span class="line">    authentication &#123;</span><br><span class="line">        auth_type PASS <span class="comment">#主从服务器验证方式</span></span><br><span class="line">        auth_pass 1111</span><br><span class="line">    &#125;</span><br><span class="line">    track_script &#123;</span><br><span class="line">        chk_haproxy <span class="comment">#监测haproxy进程状态</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">#VIP</span></span><br><span class="line">    virtual_ipaddress &#123;</span><br><span class="line">        221.228.86.70 <span class="comment">#虚拟IP</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="Backup（221-228-86-6）服务器上的配置-x2F-etc-x2F-keepalived-x2F-keepalived-conf"><a href="#Backup（221-228-86-6）服务器上的配置-x2F-etc-x2F-keepalived-x2F-keepalived-conf" class="headerlink" title="Backup（221.228.86.6）服务器上的配置 &#x2F;etc&#x2F;keepalived&#x2F;keepalived.conf"></a>Backup（221.228.86.6）服务器上的配置 &#x2F;etc&#x2F;keepalived&#x2F;keepalived.conf</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">global_defs &#123;</span><br><span class="line">   notification_email &#123;</span><br><span class="line">   user@example.com</span><br><span class="line">   &#125;</span><br><span class="line">   notification_email_from mail@example.org</span><br><span class="line">   smtp_server 192.168.x.x</span><br><span class="line">   smtp_connect_timeout 30</span><br><span class="line">   router_id LVS_DEVEL</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">#监测haproxy进程状态，每2秒执行一次</span></span><br><span class="line">vrrp_script chk_haproxy &#123;</span><br><span class="line">    script <span class="string">&quot;/usr/local/keepalived/chk_haproxy.sh&quot;</span></span><br><span class="line">    interval 2</span><br><span class="line">    weight 2</span><br><span class="line">&#125;</span><br><span class="line">vrrp_instance VI_1 &#123;</span><br><span class="line">    state BACKUP <span class="comment">#状态为BACKUP</span></span><br><span class="line">    interface eth0</span><br><span class="line">    virtual_router_id 51</span><br><span class="line">    priority 100  <span class="comment">#权重要低于MASTER</span></span><br><span class="line">    advert_int 1</span><br><span class="line">    mcast_src_ip 221.228.86.6 <span class="comment">#Backup服务器的IP</span></span><br><span class="line">    authentication &#123;</span><br><span class="line">        auth_type PASS</span><br><span class="line">        auth_pass 1111</span><br><span class="line">    &#125;</span><br><span class="line">    track_script &#123;</span><br><span class="line">        chk_haproxy <span class="comment">#监测haproxy进程状态</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">#VIP</span></span><br><span class="line">    virtual_ipaddress &#123;</span><br><span class="line">        221.228.86.70 <span class="comment">#虚拟IP</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="chk-haproxy-sh内容-x2F-usr-x2F-local-x2F-keepalived-x2F-chk-haproxy-sh"><a href="#chk-haproxy-sh内容-x2F-usr-x2F-local-x2F-keepalived-x2F-chk-haproxy-sh" class="headerlink" title="chk_haproxy.sh内容 &#x2F;usr&#x2F;local&#x2F;keepalived&#x2F;chk_haproxy.sh"></a>chk_haproxy.sh内容 &#x2F;usr&#x2F;local&#x2F;keepalived&#x2F;chk_haproxy.sh</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># author: weizhifeng</span></span><br><span class="line"><span class="comment"># description: </span></span><br><span class="line"><span class="comment"># 定时查看haproxy是否存在，如果不存在则启动haproxy，</span></span><br><span class="line"><span class="comment"># 如果启动失败，则停止keepalived</span></span><br><span class="line"><span class="comment"># </span></span><br><span class="line">status=$(docker inspect  -f <span class="string">&quot;&#123;&#123;.State.Running&#125;&#125;&quot;</span> haproxy-registry)</span><br><span class="line"><span class="keyword">if</span> [ <span class="string">&quot;<span class="variable">$&#123;status&#125;</span>&quot;</span> = <span class="string">&quot;false&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    docker start haproxy-registry</span><br><span class="line">    status2=$(docker inspect  -f <span class="string">&quot;&#123;&#123;.State.Running&#125;&#125;&quot;</span> haproxy-registry)</span><br><span class="line">    <span class="keyword">if</span> [ <span class="string">&quot;<span class="variable">$&#123;status2&#125;</span>&quot;</span> = <span class="string">&quot;false&quot;</span>  ]; <span class="keyword">then</span></span><br><span class="line">            service keepalived stop</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line"><span class="keyword">fi</span></span><br></pre></td></tr></table></figure><h4 id="启动keepalived服务"><a href="#启动keepalived服务" class="headerlink" title="启动keepalived服务"></a>启动keepalived服务</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ service keepalived start</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;本文用于搭建一个基于haproxy和keepalived的高可用的私有docker registry&lt;/p&gt;
&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;ul&gt;
&lt;li&gt;haproxy keepalived 主：221.228.86.4&lt;/li&gt;
&lt;li&gt;haproxy keepalived 备：221.228.86.5&lt;/li&gt;
&lt;li&gt;docker registry 1：    221.228.86.6&lt;/li&gt;
&lt;li&gt;docker registry 2：    221.228.86.67&lt;/li&gt;
&lt;li&gt;VIP : 221.228.86.70&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;                    221.228.86.100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             +-----------VIP----------+   &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             |                        |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             |                        |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           Master                   Backup&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        221.228.86.4             221.228.86.6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        +----------+             +----------+&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        | HAProxy  |             | HAProxy  |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        |keepalived|             |keepalived|&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        +----------+             +----------+&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             |  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             v  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    +--------+---------+ &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    |        |         |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    |        |         |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    v        v         v&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;+------+  +------+  +------+&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;| WEB1 |  | WEB2 |  | WEB3 |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;+------+  +------+  +------+&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;</summary>
    
    
    
    <category term="容器" scheme="http://aoxn.github.io/categories/%E5%AE%B9%E5%99%A8/"/>
    
    <category term="Docker" scheme="http://aoxn.github.io/categories/%E5%AE%B9%E5%99%A8/Docker/"/>
    
    
    <category term="Docker" scheme="http://aoxn.github.io/tags/Docker/"/>
    
    <category term="Registry" scheme="http://aoxn.github.io/tags/Registry/"/>
    
  </entry>
  
</feed>
