<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>为个人日志</title>
  
  <subtitle>Whyvv Blog</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://www.whyvv.top/"/>
  <updated>2020-06-09T11:07:01.353Z</updated>
  <id>http://www.whyvv.top/</id>
  
  <author>
    <name>Roy Luo</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>grafana-强大的可视化web面板</title>
    <link href="http://www.whyvv.top/grafana.html"/>
    <id>http://www.whyvv.top/grafana.html</id>
    <published>2020-06-09T11:00:00.000Z</published>
    <updated>2020-06-09T11:07:01.353Z</updated>
    
    <content type="html"><![CDATA[<h1>简介</h1><blockquote><p>Grafana 是一个开箱即用的可视化工具，具有功能齐全的度量仪表盘和图形编辑器，有灵活丰富的图形化选项，可以混合多种风格，支持多个数据源特点，大多使用在时序数据的监控方面，如同Kibana类似。Grafana的UI更加灵活，有丰富的插件，功能强大。</p></blockquote><p><a href="https://grafana.com/" target="_blank" rel="noopener">官方地址</a></p><p>grafana监控页面展示：</p><p><img src="/images/gfa_grafana.png" alt="grafana展示"></p><h1>grafana安装配置（结合prometheus）</h1><p>官方链接：</p><ul><li><p><a href="https://grafana.com/grafana/download?platform=linux" target="_blank" rel="noopener">下载地址</a></p></li><li><p><a href="http://docs.grafana.org/" target="_blank" rel="noopener">官方文档</a></p></li></ul><p>架构图：</p><p><img src="/images/gfa_structure.png" alt="架构图"></p><p>环境：</p><ul><li>CentOS7.5_x64</li><li>grafana-5.3.4-1</li></ul><p>默认端口：3000</p><h3 id="1-下载安装"><a class="header-anchor" href="#1-下载安装"></a>1. 下载安装</h3><p>安装依赖go环境</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">yum install -y go</span><br></pre></td></tr></table></figure><figure class="highlight shell"><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">wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-5.3.4-1.x86_64.rpm</span><br><span class="line">yum install -y grafana-5.3.4-1.x86_64.rpm</span><br></pre></td></tr></table></figure><p>安装包信息：</p><ul><li><p>二进制文件： /usr/sbin/grafana-server</p></li><li><p>init.d 脚本： /etc/init.d/grafana-server</p></li><li><p>环境变量文件： /etc/sysconfig/grafana-server</p></li><li><p>配置文件： /etc/grafana/grafana.ini</p></li><li><p>启动项： grafana-server.service</p></li><li><p>日志文件：/var/log/grafana/grafana.log</p></li><li><p>默认配置的sqlite3数据库：/var/lib/grafana/grafana.db</p></li></ul><h3 id="2-服务管理"><a class="header-anchor" href="#2-服务管理"></a>2. 服务管理</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></pre></td><td class="code"><pre><span class="line">systemctl daemon-reload</span><br><span class="line">systemctl start/stop/status/restart grafana-server</span><br><span class="line">systemctl enable grafana-server.service</span><br></pre></td></tr></table></figure><p>默认以grafana用户启动grafana进程，grafana 用户是在安装过程中自动创建的，默认http端口：3000，默认用户和密码是都admin</p><h3 id="3-安装图像渲染依赖"><a class="header-anchor" href="#3-安装图像渲染依赖"></a>3. 安装图像渲染依赖</h3><p>服务器端图像（PNG）渲染是可选的功能，但在共享可视化时非常有用，例如在警报通知中。如果图像缺少文本，请确保已安装字体包。</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">yum install -y fontconfig freetype* urw-fonts</span><br></pre></td></tr></table></figure><h3 id="配置grafana"><a class="header-anchor" href="#配置grafana"></a>配置grafana</h3><p>配置文件：/etc/grafana/grafana.ini</p><p>grafana.ini注释是分号’;’，</p><p>下面列出的配置文件中的选项都可以被环境变量覆盖，即’.‘会被’_'替换，语法：</p><p><code>GF_&lt;SectionName&gt;_&lt;KeyName&gt;</code></p><p>配置文件选项：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># default section</span><br><span class="line">instance_name = $&#123;HOSTNAME&#125;</span><br><span class="line"></span><br><span class="line">[security]</span><br><span class="line">admin_user = admin</span><br><span class="line"></span><br><span class="line">[auth.google]</span><br><span class="line">client_secret = 0ldS3cretKey</span><br></pre></td></tr></table></figure><p>环境变量替换：</p><figure class="highlight plain"><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">export GF_DEFAULT_INSTANCE_NAME=my-instance</span><br><span class="line">export GF_SECURITY_ADMIN_USER=true</span><br><span class="line">export GF_AUTH_GOOGLE_CLIENT_SECRET=newS3cretKey</span><br></pre></td></tr></table></figure><p>配置详细参考<a href="http://docs.grafana.org/installation/configuration/" target="_blank" rel="noopener">官方文档</a></p><p>配置好后，启动grafana</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">systemctl start grafana-server</span><br></pre></td></tr></table></figure><p>访问链接:http://host_ip:3000，也可使用nginx做反向代理</p><h3 id="grafana基本概念"><a class="header-anchor" href="#grafana基本概念"></a>grafana基本概念</h3><h4 id="1-数据源"><a class="header-anchor" href="#1-数据源"></a>1. 数据源</h4><blockquote><p>Grafana支持许多不同的时间序列数据（数据源）存储后端。每个数据源都有一个特定的查询编辑器，该特定的查询编辑器是针对特定数据源公开的功能和功能而定制的。</p></blockquote><p>正式支持以下数据源：</p><ul><li>Graphite</li><li>InfluxDB</li><li>OpenTSDB</li><li>Prometheus</li><li>Elasticsearch</li><li>CloudWatch。</li></ul><p>每个数据源的查询语言和功能显然是非常不同的。您可以将来自多个数据源的数据合并到单个仪表板上，但每个面板都与属于特定组织的特定数据源相关联。</p><h4 id="2-组织"><a class="header-anchor" href="#2-组织"></a>2. 组织</h4><blockquote><p>Grafana支持多个组织，以支持各种部署模式，包括使用单个Grafana实例为多个潜在的不受信任的组织提供服务。</p></blockquote><p>在很多情况下，Grafana将部署在一个单一的组织中。</p><p>每个组织都可以有一个或多个数据源。</p><p>所有仪表板由特定组织拥有。</p><p>注意：请务必记住，大多数度量数据库不提供任何类型的个人用户系列身份验证。因此，在Grafana中，数据源和仪表板可用于特定组织中的所有用户。</p><h4 id="3-用户"><a class="header-anchor" href="#3-用户"></a>3. 用户</h4><blockquote><p>用户是Grafana的命名帐户。用户可以属于一个或多个组织，并可以通过角色分配不同级别的权限。</p></blockquote><p>Grafana支持各种各样的内部和外部方式供用户验证自己。这些包括从其自己的集成数据库，外部SQL服务器或外部LDAP服务器。</p><h4 id="4-行"><a class="header-anchor" href="#4-行"></a>4. 行</h4><blockquote><p>行是仪表板内的逻辑分隔符，用于将面板组合在一起。</p></blockquote><p>行总是12“单位”宽。这些单位根据浏览器的水平分辨率自动缩放。您可以通过设置自己的宽度来控制一行中面板的相对宽度。</p><p>使用抽象单位，使Grafana在所有的屏幕上看起来都很棒，而且体积很小。</p><p>注意：使用MaxDataPoint功能，无论您的分辨率还是时间范围，Grafana都可以为您显示完美的数据点数量。<br>根据所选的模板变量，利用重复行功能动态创建或删除整个行（可以填充面板）。</p><p>可以通过单击行标题来折叠行。如果您保存了一个折叠的行的仪表板，它将保存在该状态，并且不会预加载这些图，直到该行被展开。</p><h4 id="5-面板"><a class="header-anchor" href="#5-面板"></a>5. 面板</h4><blockquote><p>面板是Grafana的基本可视化构建块。每个面板提供一个查询编辑器（取决于面板中选择的数据源），允许您通过使用查询编辑器提取完美的可视化以在Panel上显示<br>每个Panel都有各种各样的造型和格式化选项，让您创建完美的图片。</p></blockquote><p>面板可以在仪表板上拖放并重新排列。他们也可以调整大小。<br>目前有四种面板类型：Graph，Singlestat，Dashlist，Table和Text。<br>像“ 图形”面板的面板允许您根据需要绘制出许多指标和系列。像Singlestat这样的其他面板需要将单个查询减少到单个数字。Dashlist和Text是不连接到任何数据源的特殊面板。</p><p>通过在面板配置中使用Dashboard Templating变量字符串（包括通过查询编辑器配置的数据源的查询），可以使面板更具动态性。<br>利用重复面板功能，根据所选择的模板化变量动态创建或删除面板。</p><p>面板上的时间范围通常是仪表板时间选择器中设置的时间范围，但可以通过使用面板特定时间覆盖来覆盖。</p><p>面板（或整个仪表板）可以通过各种方式轻松共享。您可以发送链接到有谁登录您的Grafana的人。您可以使用快照功能将当前正在查看的所有数据编码为静态和交互式JSON文档; 它比通过电子邮件屏幕截图好得多！</p><h4 id="6-查询编辑器"><a class="header-anchor" href="#6-查询编辑器"></a>6. 查询编辑器</h4><blockquote><p>查询编辑器公开了数据源的功能，并允许您查询其包含的指标。<br>使用查询编辑器在时间序列数据库中构建一个或多个查询（一个或多个系列）。该面板将立即更新，允许您实时有效地探索数据，并为该特定面板构建完美的查询。</p></blockquote><p>您可以在查询本身的查询编辑器中使用模板变量。这提供了一种基于“仪表板”上选择的“模板化”变量动态探索数据的强大方法。</p><p>Grafana允许您在查询编辑器中按照它们所在的行来引用查询。如果您向图形添加第二个查询，则可以通过键入#A来引用第一个查询。这提供了一种简单而方便的方法来构建复合查询。</p><h4 id="7-仪表板"><a class="header-anchor" href="#7-仪表板"></a>7. 仪表板</h4><blockquote><p>仪表板是所有在一起的地方。仪表板可以被认为是由一组或多组组成并排列成一行或多行的组件。<br>仪表板的时间段可以由仪表板右上方的仪表板时间选择器控制。</p></blockquote><p>仪表板可以利用模板来使它们更具动态性和交互性。<br>仪表板可以使用注释来显示面板上的事件数据。这可以帮助将Panel中的时间序列数据与其他事件相关联。<br>仪表板（或特定面板）可以通过各种方式轻松共享。您可以发送链接到有谁登录您的Grafana的人。您可以使用快照功能将当前正在查看的所有数据编码为静态和交互式JSON文档; 它比通过电子邮件屏幕截图好得多！</p><p>仪表板可以被标记，仪表板选择器可以快速，可搜索访问特定机构中的所有仪表板。</p><h3 id="grafana使用"><a class="header-anchor" href="#grafana使用"></a>grafana使用</h3><h4 id="1-登录"><a class="header-anchor" href="#1-登录"></a>1. 登录</h4><p>浏览器访问grafana主机3000端口，默认账号密码均为admin，首次登录会要求更改admin密码</p><p><img src="/images/gfa_login.png" alt="登录界面"></p><h4 id="2-创建数据源"><a class="header-anchor" href="#2-创建数据源"></a>2. 创建数据源</h4><p>首先登入后，第一步是需要配置grafana的数据源，我们以prometheus为数据源来演示</p><p><img src="/images/gfa_datasource.png" alt="配置数据源"></p><p>配置以下几个参数即可，按prometheus server的实际情况来配置</p><p><img src="/images/gfa_datasource2.png" alt="配置prometheus"></p><h4 id="3-创建或导入dashboard仪表盘"><a class="header-anchor" href="#3-创建或导入dashboard仪表盘"></a>3. 创建或导入Dashboard仪表盘</h4><ul><li>导入仪表盘</li></ul><p>若已有仪表盘模板文件(json格式)或直接从官网下载的，可直接导入</p><p><img src="/images/gfa_import_dashboard.png" alt="导入模板"></p><p><a href="https://grafana.com/dashboards" target="_blank" rel="noopener">官方Dashboard模板下载地址</a></p><ul><li>创建仪表盘</li></ul><p>点击导航栏&quot;+&quot;按键，选择dashboard，即可进入仪表盘创建界面</p><p><img src="/images/gfa_dashboard.png" alt="创建dashbaord"></p><p>注意，在add下方的插件列表中，只有一些常用的基本仪表盘/面板/应用等插件，若需要其它的插件，可直接在grafana主机上通过以下命令安装并重载grafana服务</p><figure class="highlight shell"><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">grafana-cli plugins install 插件名称</span><br><span class="line">systemctl restart grafana</span><br></pre></td></tr></table></figure><p><a href="https://grafana.com/plugins" target="_blank" rel="noopener">官方插件下载地址</a></p><p>我们以Graph图表示例，选中Graph，点击Edit编辑</p><p><img src="/images/gfa_new_graph_edit.png" alt="添加graph"></p><p>填写好对应的数据源，指定图形对应的prometheus监控项，然后保存</p><p><img src="/images/gfa_new_graph_edit1.png" alt="编辑graph"></p><h4 id="4-grafana深入用法"><a class="header-anchor" href="#4-grafana深入用法"></a>4. grafana深入用法</h4><ul><li><p>告警及规则</p></li><li><p>用户及组权限管理</p></li><li><p>模板变量</p></li><li><p>面板编辑器</p></li><li><p>高级函数</p></li><li><p>其它</p></li></ul><p><a href="https://segmentfault.com/a/1190000013565079" target="_blank" rel="noopener">见链接</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1&gt;简介&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Grafana 是一个开箱即用的可视化工具，具有功能齐全的度量仪表盘和图形编辑器，有灵活丰富的图形化选项，可以混合多种风格，支持多个数据源特点，大多使用在时序数据的监控方面，如同Kibana类似。Grafana的UI更加灵活
      
    
    </summary>
    
      <category term="技术" scheme="http://www.whyvv.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="grafana" scheme="http://www.whyvv.top/tags/grafana/"/>
    
      <category term="可视化" scheme="http://www.whyvv.top/tags/%E5%8F%AF%E8%A7%86%E5%8C%96/"/>
    
      <category term="仪表盘" scheme="http://www.whyvv.top/tags/%E4%BB%AA%E8%A1%A8%E7%9B%98/"/>
    
  </entry>
  
  <entry>
    <title>grafana高可用架构搭建</title>
    <link href="http://www.whyvv.top/grafana_ha.html"/>
    <id>http://www.whyvv.top/grafana_ha.html</id>
    <published>2020-01-20T02:00:00.000Z</published>
    <updated>2020-01-20T03:12:13.251Z</updated>
    
    <content type="html"><![CDATA[<p>环境：</p><ul><li>OS：CentOS7_x86</li><li>grafana: v5.4.2</li><li>MySQL: 5.7.28</li></ul><p>主机：</p><table><thead><tr><th style="text-align:center">Hostname</th><th style="text-align:center">IP</th><th style="text-align:center">Role</th></tr></thead><tbody><tr><td style="text-align:center">centos1</td><td style="text-align:center">192.168.2.87</td><td style="text-align:center">grafana</td></tr><tr><td style="text-align:center">centos2</td><td style="text-align:center">192.168.2.88</td><td style="text-align:center">grafana</td></tr><tr><td style="text-align:center">centos3</td><td style="text-align:center">192.168.2.89</td><td style="text-align:center">grafana,mysql</td></tr><tr><td style="text-align:center">haproxy1</td><td style="text-align:center">192.168.2.99</td><td style="text-align:center">haproxy</td></tr></tbody></table><p>架构图：</p><p><img src="/images/grafana-ha.png" alt="架构图"></p><p>其中haproxy换成nginx也可以。</p><p>效果：</p><ul><li>Dashboard及用户等配置共享存储，以此达到多grafana高可用性。共享的完整列表如下：</li></ul><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><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></pre></td><td class="code"><pre><span class="line">+--------------------------+</span><br><span class="line">| alert                    |</span><br><span class="line">| alert_notification       |</span><br><span class="line">| alert_notification_state |</span><br><span class="line">| annotation               |</span><br><span class="line">| annotation_tag           |</span><br><span class="line">| api_key                  |</span><br><span class="line">| dashboard                |</span><br><span class="line">| dashboard_acl            |</span><br><span class="line">| dashboard_provisioning   |</span><br><span class="line">| dashboard_snapshot       |</span><br><span class="line">| dashboard_tag            |</span><br><span class="line">| dashboard_version        |</span><br><span class="line">| data_source              |</span><br><span class="line">| login_attempt            |</span><br><span class="line">| migration_log            |</span><br><span class="line">| org                      |</span><br><span class="line">| org_user                 |</span><br><span class="line">| playlist                 |</span><br><span class="line">| playlist_item            |</span><br><span class="line">| plugin_setting           |</span><br><span class="line">| preferences              |</span><br><span class="line">| quota                    |</span><br><span class="line">| session                  |</span><br><span class="line">| star                     |</span><br><span class="line">| tag                      |</span><br><span class="line">| team                     |</span><br><span class="line">| team_member              |</span><br><span class="line">| temp_user                |</span><br><span class="line">| test_data                |</span><br><span class="line">| user                     |</span><br><span class="line">| user_auth                |</span><br><span class="line">+--------------------------+</span><br></pre></td></tr></table></figure><ul><li>session会话保持：启用多grafana实例反向代理访问，存在会话保持问题；若代理层不支持session sticky，则可将session存储在共享数据库中，解决session无法跨节点同步的问题。</li></ul><h1>mysql安装配置</h1><h3 id="mysql安装"><a class="header-anchor" href="#mysql安装"></a>mysql安装</h3><p>mysql安装配置此处略，连接信息如下：</p><ul><li>地址：192.168.2.89:3306</li><li>用户：root</li><li>密码：root_pw</li></ul><h3 id="创建grafana库及session表"><a class="header-anchor" href="#创建grafana库及session表"></a>创建grafana库及session表</h3><p>创建grafana库</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">DATABASE</span> grafana <span class="keyword">default</span> <span class="built_in">CHARACTER</span> <span class="keyword">SET</span> utf8;</span><br></pre></td></tr></table></figure><p>在grafana库中创建session表</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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="keyword">USE</span> grafana;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`session`</span> (</span><br><span class="line">    <span class="string">`key`</span>       <span class="built_in">CHAR</span>(<span class="number">16</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">    <span class="string">`data`</span>      <span class="built_in">BLOB</span>,</span><br><span class="line">    <span class="string">`expiry`</span>    <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">    PRIMARY <span class="keyword">KEY</span> (<span class="string">`key`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=MyISAM <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8;</span><br></pre></td></tr></table></figure><h1>grafana安装及配置</h1><p>所有garfana节点安装配置均相同</p><h3 id="安装grafana"><a class="header-anchor" href="#安装grafana"></a>安装grafana</h3><p>此处直接使用官方rpm包安装</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></pre></td><td class="code"><pre><span class="line">yum install grafana-5.4.2-1.x86_64.rpm</span><br><span class="line">systemctl deamon-reload</span><br><span class="line">systemctl enable grafana-server</span><br></pre></td></tr></table></figure><h3 id="配置grafana"><a class="header-anchor" href="#配置grafana"></a>配置grafana</h3><p>配置文件：/etc/grafana/grafana.ini，仅列出自定义配置项</p><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">#################################### Server ####################################</span><br><span class="line">[server]</span><br><span class="line"># The full public facing url you use in browser, used for redirects and emails</span><br><span class="line"># If you use reverse proxy and sub path specify full url (with sub path)</span><br><span class="line">root_url = http://192.168.2.99:3001</span><br><span class="line"></span><br><span class="line">#################################### Database ####################################</span><br><span class="line">[database]</span><br><span class="line"># use mysql to store grafana data</span><br><span class="line">type = mysql</span><br><span class="line"># mysql databse connection url</span><br><span class="line">host = 192.168.2.89:3306</span><br><span class="line"># mysql db name</span><br><span class="line">name = grafana</span><br><span class="line"># mysql user</span><br><span class="line">user = root</span><br><span class="line"># If the password contains # or ; you have to wrap it with triple quotes. Ex &quot;&quot;&quot;#password;&quot;&quot;&quot;</span><br><span class="line">password = root_pw</span><br><span class="line"># Set to true to log the sql calls and execution times.</span><br><span class="line">log_queries =</span><br><span class="line"></span><br><span class="line">#################################### Session ####################################</span><br><span class="line">[session]</span><br><span class="line"># session provide use mysql</span><br><span class="line">provider = mysql</span><br><span class="line"># mysql provider connection config</span><br><span class="line">provider_config = root:root_pw@tcp(192.168.2.89:3306)/grafana</span><br><span class="line"># Session cookie name</span><br><span class="line">cookie_name = grafana_sess</span><br><span class="line"># If you use session in https only, default is false</span><br><span class="line">cookie_secure = false</span><br><span class="line"># Session life time, default is 86400</span><br><span class="line">session_life_time = 86400</span><br></pre></td></tr></table></figure><p>注意<code>root_url</code>为haproxy/nginx反向代理后的地址或域名，这里若设置不正确，会导致grafana页面跳转不正常。</p><h3 id="启动grafana"><a class="header-anchor" href="#启动grafana"></a>启动grafana</h3><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">systemctl start grafana-server</span><br></pre></td></tr></table></figure><h1>反向代理配置</h1><p>haproxy添加配置</p><figure class="highlight plain"><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">listen grafana-ha-test</span><br><span class="line">  bind 192.168.2.99:3001</span><br><span class="line">  mode  tcp</span><br><span class="line">  option  tcplog</span><br><span class="line">  server centos1    192.168.2.87:3000 check</span><br><span class="line">  server centos2    192.168.2.88:3000 check</span><br><span class="line">  server centos3    192.168.2.89:3000 check</span><br></pre></td></tr></table></figure><p>重载haproxy</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">systemctl reload haproxy</span><br></pre></td></tr></table></figure><p>访问grafana-ha：<a href="http://192.168.2.99:3001" target="_blank" rel="noopener">http://192.168.2.99:3001</a>，默认用户名密码admin/admin</p><h1>使用grafana</h1><h3 id="dashboard共享"><a class="header-anchor" href="#dashboard共享"></a>dashboard共享</h3><p>通过grafana web页面导入的dashboard会自动存储到数据库中，所以一经导入（无论通过哪个节点，包括代理节点），所有节点即可生效。此工作原理也对所有共享列表（上述列出，如用户和session等）均有效。</p><h3 id="插件安装"><a class="header-anchor" href="#插件安装"></a>插件安装</h3><p>由于grafana的插件是本地安装，所以额外插件必须要在三个节点都安装才完全生效。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;环境：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OS：CentOS7_x86&lt;/li&gt;
&lt;li&gt;grafana: v5.4.2&lt;/li&gt;
&lt;li&gt;MySQL: 5.7.28&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主机：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;tex
      
    
    </summary>
    
      <category term="技术" scheme="http://www.whyvv.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="grafana" scheme="http://www.whyvv.top/tags/grafana/"/>
    
  </entry>
  
  <entry>
    <title>haproxy2.0安装配置</title>
    <link href="http://www.whyvv.top/haproxy2.html"/>
    <id>http://www.whyvv.top/haproxy2.html</id>
    <published>2019-12-27T07:00:00.000Z</published>
    <updated>2019-12-27T09:01:21.312Z</updated>
    
    <content type="html"><![CDATA[<p>环境</p><ul><li>OS: CentOS7.7_x64</li><li>Haproxy: 2.0.111</li></ul><h3 id="1-安装依赖"><a class="header-anchor" href="#1-安装依赖"></a>1. 安装依赖</h3><ul><li>gcc</li><li>readline-devel</li><li>systemd-devel</li><li>openssl</li><li>openssl-devel</li><li>lua5.3</li></ul><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">[root@centos7 ~] yum install gcc readline-devel systemd-devel openssl openssl-devel</span><br></pre></td></tr></table></figure><p>安装lua5.3至/usr/local/lua</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></pre></td><td class="code"><pre><span class="line">[root@centos7 ~] wget http://www.lua.org/ftp/lua-5.3.5.tar.gz</span><br><span class="line">[root@centos7 ~] tar zxvf lua-5.3.5.tar.gz</span><br><span class="line">[root@centos7 ~] cd lua-5.3.5</span><br><span class="line">[root@centos7 ~] make linux</span><br><span class="line">[root@centos7 ~] make INSTALL_TOP=/usr/local/lua install</span><br></pre></td></tr></table></figure><h3 id="2-安装haproxy"><a class="header-anchor" href="#2-安装haproxy"></a>2. 安装haproxy</h3><p>下载并安装至/usr/local/haproxy</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></pre></td><td class="code"><pre><span class="line">[root@centos7 ~] wget https://www.haproxy.org/download/2.0/src/haproxy-2.0.11.tar.gz</span><br><span class="line">[root@centos7 ~] tar zxvf haproxy-2.0.11.tar.gz </span><br><span class="line">[root@centos7 ~] cd haproxy-2.0.11</span><br><span class="line">[root@centos7 ~] make -j $(nproc) TARGET=linux-glibc USE_OPENSSL=1 USE_ZLIB=1 USE_LUA=1 LUA_LIB=/usr/local/lua/lib/ LUA_INC=/usr/local/lua/include/ USE_PCRE=1 USE_SYSTEMD=1 </span><br><span class="line">[root@centos7 ~] make install PREFIX=/usr/local/haproxy</span><br></pre></td></tr></table></figure><p>创建配置文件/etc/haproxy/haproxy.cfg</p><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">global</span><br><span class="line">#  daemon</span><br><span class="line">  cpu-map  1 0</span><br><span class="line">  log  127.0.0.1 local2</span><br><span class="line">  nbproc  1</span><br><span class="line">  stats socket  /var/run/haproxy.sock mode 600 level admin</span><br><span class="line">  stats timeout  2m</span><br><span class="line">  tune.ssl.default-dh-param  2048</span><br><span class="line"></span><br><span class="line">defaults</span><br><span class="line">  backlog  100000</span><br><span class="line">  balance  leastconn</span><br><span class="line">  log  global</span><br><span class="line">  maxconn  14000</span><br><span class="line">  option  redispatch</span><br><span class="line">  option  tcpka</span><br><span class="line">  option  http-keep-alive</span><br><span class="line">  option  dontlog-normal</span><br><span class="line">  option  dontlognull</span><br><span class="line">  option  tcp-smart-accept</span><br><span class="line">  option  tcp-smart-connect</span><br><span class="line">  retries  5</span><br><span class="line">  timeout  http-request 2m</span><br><span class="line">  timeout  queue 1m</span><br><span class="line">  timeout  connect 1m</span><br><span class="line">  timeout  client 7d</span><br><span class="line">  timeout  server 7d</span><br><span class="line">  timeout  check 10s</span><br><span class="line">  timeout  tunnel 7d</span><br><span class="line"></span><br><span class="line">frontend cmdt</span><br><span class="line">  bind *:8080</span><br><span class="line">  mode http</span><br><span class="line">  option httplog</span><br><span class="line"></span><br><span class="line">  # ACL ENVIRONMENTS</span><br><span class="line">  default_backend empty</span><br><span class="line"></span><br><span class="line">backend empty</span><br><span class="line">  mode http</span><br><span class="line"></span><br><span class="line">listen stats</span><br><span class="line">  mode http</span><br><span class="line">  bind 0.0.0.0:1080</span><br><span class="line">  stats enable</span><br><span class="line">  stats hide-version</span><br><span class="line">  stats uri /haproxy?status</span><br><span class="line">  stats realm  Haproxy\ Statistics</span><br><span class="line">  stats auth   admin:admin</span><br><span class="line">  stats admin  if TRUE</span><br><span class="line"></span><br><span class="line">listen mgmt-ssh</span><br><span class="line">    bind 0.0.0.0:222</span><br><span class="line">    mode  tcp</span><br><span class="line">    balance roundrobin</span><br><span class="line">    option tcplog</span><br><span class="line">    option tcpka</span><br><span class="line">    server centos-test 192.168.1.88:22</span><br></pre></td></tr></table></figure><h3 id="3-运行"><a class="header-anchor" href="#3-运行"></a>3. 运行</h3><p>指定配置文件运行haproxy</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">[root@centos7 ~] /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/haproxy.cfg</span><br></pre></td></tr></table></figure><p>拷贝systemd服务配置文件</p><figure class="highlight shell"><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">[root@centos7 ~] cd haproxy-2.0.11/contrib/systemd</span><br><span class="line">[root@centos7 ~] cp haproxy.service.in /lib/systemd/system/haproxy.service</span><br></pre></td></tr></table></figure><p>修改haproxy服务执行路径：</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">[root@centos7 ~] sed -i 's/@SBINDIR@/\/usr\/local\/haproxy\/sbin/g' /lib/systemd/system/haproxy.service</span><br></pre></td></tr></table></figure><p>修改完后haproxy.service配置如下：</p><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">[Unit]</span><br><span class="line">Description=HAProxy Load Balancer</span><br><span class="line">After=network.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">EnvironmentFile=-/etc/default/haproxy</span><br><span class="line">EnvironmentFile=-/etc/sysconfig/haproxy</span><br><span class="line">Environment=&quot;CONFIG=/etc/haproxy/haproxy.cfg&quot; &quot;PIDFILE=/run/haproxy.pid&quot; &quot;EXTRAOPTS=-S /run/haproxy-master.sock&quot;</span><br><span class="line">ExecStartPre=/usr/local/haproxy/sbin/haproxy -f $CONFIG -c -q $EXTRAOPTS</span><br><span class="line">ExecStart=/usr/local/haproxy/sbin/haproxy -Ws -f $CONFIG -p $PIDFILE $EXTRAOPTS</span><br><span class="line">ExecReload=/usr/local/haproxy/sbin/haproxy -f $CONFIG -c -q $EXTRAOPTS</span><br><span class="line">ExecReload=/bin/kill -USR2 $MAINPID</span><br><span class="line">KillMode=mixed</span><br><span class="line">Restart=always</span><br><span class="line">SuccessExitStatus=143</span><br><span class="line">Type=notify</span><br><span class="line"></span><br><span class="line"># The following lines leverage SystemD&apos;s sandboxing options to provide</span><br><span class="line"># defense in depth protection at the expense of restricting some flexibility</span><br><span class="line"># in your setup (e.g. placement of your configuration files) or possibly</span><br><span class="line"># reduced performance. See systemd.service(5) and systemd.exec(5) for further</span><br><span class="line"># information.</span><br><span class="line"></span><br><span class="line"># NoNewPrivileges=true</span><br><span class="line"># ProtectHome=true</span><br><span class="line"># If you want to use &apos;ProtectSystem=strict&apos; you should whitelist the PIDFILE,</span><br><span class="line"># any state files and any other files written using &apos;ReadWritePaths&apos; or</span><br><span class="line"># &apos;RuntimeDirectory&apos;.</span><br><span class="line"># ProtectSystem=true</span><br><span class="line"># ProtectKernelTunables=true</span><br><span class="line"># ProtectKernelModules=true</span><br><span class="line"># ProtectControlGroups=true</span><br><span class="line"># If your SystemD version supports them, you can add: @reboot, @swap, @sync</span><br><span class="line"># SystemCallFilter=~@cpu-emulation @keyring @module @obsolete @raw-io</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br></pre></td></tr></table></figure><p>启动haproxy</p><figure class="highlight shell"><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">[root@centos7 ~] systemctl daemon-reload</span><br><span class="line">[root@centos7 ~] systemctl start haproxy</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;环境&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OS: CentOS7.7_x64&lt;/li&gt;
&lt;li&gt;Haproxy: 2.0.111&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;1-安装依赖&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#1-安装依赖&quot;&gt;&lt;/a&gt;1. 安装依
      
    
    </summary>
    
      <category term="技术" scheme="http://www.whyvv.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="haproxy" scheme="http://www.whyvv.top/tags/haproxy/"/>
    
      <category term="代理" scheme="http://www.whyvv.top/tags/%E4%BB%A3%E7%90%86/"/>
    
  </entry>
  
  <entry>
    <title>Chrony-替换你的NTP服务</title>
    <link href="http://www.whyvv.top/chrony.html"/>
    <id>http://www.whyvv.top/chrony.html</id>
    <published>2019-11-20T07:00:00.000Z</published>
    <updated>2019-11-20T07:58:42.552Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>linux在运行时间长了之后，尤其在虚拟环境中。系统时间可能会存在一定的误差，时间同步在大型集群环境中是很重要的，而通过ntp协议来同步时间，则是一个很好的解决方案。linux默认使用ntpd来同步时间的，但ntpd同步时间并不理想，有可能需要数小时来同步时间，所以在Centos7中可换成chrony来实现时间同步。chrony兼容ntpd监听在udp123端口上，另外还监听在udp的323端口上。</p></blockquote><h1>Chrony</h1><p>Chrony是一个开源的自由软件，如果在chrony配置文件中指定了ntp服务器的地址，那么chrony就是一台客户端，会去同步ntp服务器的时间，如果在chrony配置了允许某些客户端来向自己同步时间，则chrony也充当了一台服务器，所以，安装了chrony即可充当客户端也可以充当服务端。</p><p>Chrony有两个核心组件，分别是：chronyd：是守护进程，主要用于调整内核中运行的系统时间和时间服务器同步。它确定计算机增减时间的比率，并对此进行调整补偿。chronyc：提供一个用户界面，用于监控性能并进行多样化的配置。它可以在chronyd实例控制的计算机上工作，也可以在一台不同的远程计算机上工作。</p><h1>安装配置</h1><h3 id="环境"><a class="header-anchor" href="#环境"></a>环境</h3><p>OS: CentOS7.4_x64</p><table><thead><tr><th style="text-align:center">主机名</th><th style="text-align:center">角色</th><th style="text-align:left">配置目录</th><th style="text-align:left">端口</th></tr></thead><tbody><tr><td style="text-align:center">centos-test1</td><td style="text-align:center">Chrony Server</td><td style="text-align:left">/etc/chrony.conf</td><td style="text-align:left">udp/123,udp/323</td></tr><tr><td style="text-align:center">centos-test2</td><td style="text-align:center">Chrony Client</td><td style="text-align:left">/etc/chrony.conf</td><td style="text-align:left">udp/123,udp/323</td></tr></tbody></table><h3 id="安装"><a class="header-anchor" href="#安装"></a>安装</h3><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">yum install -y chrony</span><br></pre></td></tr></table></figure><h3 id="配置详解"><a class="header-anchor" href="#配置详解"></a>配置详解</h3><p>配置文件：/etc/chrony.conf</p><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"># 使用pool.ntp.org项目中的公共服务器。以server开，理论上你想添加多少时间服务器都可以。</span><br><span class="line"># Please consider joining the pool (http://www.pool.ntp.org/join.html).</span><br><span class="line">server 0.centos.pool.ntp.org iburst</span><br><span class="line">server 1.centos.pool.ntp.org iburst</span><br><span class="line">server 2.centos.pool.ntp.org iburst</span><br><span class="line">server 3.centos.pool.ntp.org iburst</span><br><span class="line"></span><br><span class="line"># 根据实际时间计算出服务器增减时间的比率，然后记录到一个文件中，在系统重启后为系统做出最佳时间补偿调整。</span><br><span class="line">driftfile /var/lib/chrony/drift</span><br><span class="line"></span><br><span class="line"># chronyd根据需求减慢或加速时间调整，</span><br><span class="line"># 在某些情况下系统时钟可能漂移过快，导致时间调整用时过长。</span><br><span class="line"># 该指令强制chronyd调整时期，大于某个阀值时步进调整系统时钟。</span><br><span class="line"># 只有在因chronyd启动时间超过指定的限制时（可使用负值来禁用限制）没有更多时钟更新时才生效。</span><br><span class="line">makestep 1.0 3</span><br><span class="line"></span><br><span class="line"># 将启用一个内核模式，在该模式中，系统时间每11分钟会拷贝到实时时钟（RTC）。</span><br><span class="line">rtcsync</span><br><span class="line"></span><br><span class="line"># Enable hardware timestamping on all interfaces that support it.</span><br><span class="line"># 通过使用hwtimestamp指令启用硬件时间戳</span><br><span class="line">#hwtimestamp eth0</span><br><span class="line">#hwtimestamp eth1</span><br><span class="line">#hwtimestamp *</span><br><span class="line"></span><br><span class="line"># Increase the minimum number of selectable sources required to adjust</span><br><span class="line"># the system clock.</span><br><span class="line">#minsources 2</span><br><span class="line"></span><br><span class="line"># 指定一台主机、子网，或者网络以允许或拒绝NTP连接到扮演时钟服务器的机器</span><br><span class="line">#allow 192.168.0.0/16</span><br><span class="line">#deny 192.168/16</span><br><span class="line"></span><br><span class="line"># Serve time even if not synchronized to a time source.</span><br><span class="line">local stratum 10</span><br><span class="line"></span><br><span class="line"># 指定包含NTP验证密钥的文件。</span><br><span class="line">#keyfile /etc/chrony.keys</span><br><span class="line"></span><br><span class="line"># 指定日志文件的目录。</span><br><span class="line">logdir /var/log/chrony</span><br><span class="line"></span><br><span class="line"># Select which information is logged.</span><br><span class="line">#log measurements statistics tracking</span><br></pre></td></tr></table></figure><p>一般主要配置以下参数：</p><figure class="highlight plain"><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">server：指明时间服务器地址；</span><br><span class="line">allow NETADD/NETMASK</span><br><span class="line">allow all：允许所有客户端主机；</span><br><span class="line">deny NETADDR/NETMASK</span><br><span class="line">deny all：拒绝所有客户端；</span><br><span class="line">bindcmdaddress：命令管理接口监听的地址；</span><br><span class="line">local stratum 10：即使自己未能通过网络时间服务器同步到时间，也允许将本地时间作为标准时间授时给其它客户端；</span><br></pre></td></tr></table></figure><p><code>客户端与服务端的区别就在于把自己的server指定为服务主机，而服务端的server就指向上游（外网）NTP服务器。</code></p><h3 id="防火墙规则"><a class="header-anchor" href="#防火墙规则"></a>防火墙规则</h3><figure class="highlight shell"><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">firewall-cmd --add-service=ntp --permanent</span><br><span class="line">firewall-cmd --reload</span><br></pre></td></tr></table></figure><h3 id="设置时区"><a class="header-anchor" href="#设置时区"></a>设置时区</h3><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">timedatectl set-timezone Asia/Shanghai</span><br></pre></td></tr></table></figure><p>强制同步系统时钟</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">chronyc -a makestep</span><br></pre></td></tr></table></figure><h3 id="启动"><a class="header-anchor" href="#启动"></a>启动</h3><figure class="highlight shell"><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">systemctl enable chronyd</span><br><span class="line">systemctl restart chronyd</span><br></pre></td></tr></table></figure><h1>常用命令</h1><ul><li>查看时间同步源：</li></ul><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">chronyc sources -v</span><br></pre></td></tr></table></figure><ul><li>查看时间同步源状态：</li></ul><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">chronyc sourcestats -v</span><br></pre></td></tr></table></figure><ul><li>设置硬件时间</li></ul><p>硬件时间默认为UTC：</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">timedatectl set-local-rtc 1</span><br></pre></td></tr></table></figure><ul><li>启用NTP时间同步：</li></ul><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">timedatectl set-ntp yes</span><br></pre></td></tr></table></figure><ul><li>校准时间服务器：</li></ul><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">chronyc tracking</span><br></pre></td></tr></table></figure><ul><li>chrony的交互工具chronyc</li></ul><p>chrony自带一个交互式工具chronyc，在配置文件中指定了时间服务器之后，如果想查看同步状态，可以进入这个交互式工具的交互界面。</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><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></pre></td><td class="code"><pre><span class="line">chronyc有很多的子命令，可以输入help来查看</span><br><span class="line"><span class="meta">chronyc&gt;</span> help</span><br><span class="line">    选项：</span><br><span class="line">    sources [-v]    显示关于当前来源的信息</span><br><span class="line">    sourcestats [-v]      显示时间同步状态（如时间偏移了多少之类）</span><br><span class="line">   </span><br><span class="line"><span class="meta">#</span>例如：</span><br><span class="line"><span class="meta">chronyc&gt;</span> sources -v</span><br><span class="line">210 Number of sources = 1</span><br><span class="line"></span><br><span class="line">  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.</span><br><span class="line"> / .- Source state '*' = current synced, '+' = combined , '-' = not combined,</span><br><span class="line">| /   '?' = unreachable, 'x' = time may be in error, '~' = time too variable.</span><br><span class="line">||                                                 .- xxxx [ yyyy ] +/- zzzz</span><br><span class="line">||      Reachability register (octal) -.           |  xxxx = adjusted offset,</span><br><span class="line">||      Log2(Polling interval) --.      |          |  yyyy = measured offset,</span><br><span class="line">||                                \     |          |  zzzz = estimated error.</span><br><span class="line">||                                 |    |           \</span><br><span class="line">MS Name/IP address         Stratum Poll Reach LastRx Last sample               </span><br><span class="line">===============================================================================</span><br><span class="line">^* 203.107.6.88                  2  10   104   64m  +1485us[ +417us] +/-   81ms</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>主要关注第一列的MS，</span><br><span class="line">^*  ^是指该行所给出的IP是服务器，也就是我们指定的互联网时间服务器；*是指当前已同步</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>#######</span><br><span class="line"><span class="meta">chronyc&gt;</span> </span><br><span class="line"><span class="meta">chronyc&gt;</span> sourcestats -v #sourcestats是显示同步状态，-v是详细西信息</span><br><span class="line">210 Number of sources = 1</span><br><span class="line">                             .- Number of sample points in measurement set.</span><br><span class="line">                            /    .- Number of residual runs with same sign.</span><br><span class="line">                           |    /    .- Length of measurement set (time).</span><br><span class="line">                           |   |    /      .- Est. clock freq error (ppm).</span><br><span class="line">                           |   |   |      /           .- Est. error in freq.</span><br><span class="line">                           |   |   |     |           /         .- Est. offset.</span><br><span class="line">                           |   |   |     |          |          |   On the -.</span><br><span class="line">                           |   |   |     |          |          |   samples. \</span><br><span class="line">                           |   |   |     |          |          |             |</span><br><span class="line">Name/IP Address            NP  NR  Span  Frequency  Freq Skew  Offset  Std Dev</span><br><span class="line">==============================================================================</span><br><span class="line">203.107.6.88               29  18   18h     -0.003      0.132    -14us  5055us</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;blockquote&gt;
&lt;p&gt;linux在运行时间长了之后，尤其在虚拟环境中。系统时间可能会存在一定的误差，时间同步在大型集群环境中是很重要的，而通过ntp协议来同步时间，则是一个很好的解决方案。linux默认使用ntpd来同步时间的，但ntpd同步时间并不理想，有可能需要数小
      
    
    </summary>
    
      <category term="技术" scheme="http://www.whyvv.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="NTP" scheme="http://www.whyvv.top/tags/NTP/"/>
    
      <category term="时间同步" scheme="http://www.whyvv.top/tags/%E6%97%B6%E9%97%B4%E5%90%8C%E6%AD%A5/"/>
    
  </entry>
  
  <entry>
    <title>Roy学Kubernetes(22)：Kubernetes日常维护</title>
    <link href="http://www.whyvv.top/k8s_maintance.html"/>
    <id>http://www.whyvv.top/k8s_maintance.html</id>
    <published>2019-11-05T04:00:00.000Z</published>
    <updated>2019-11-05T09:50:28.919Z</updated>
    
    <content type="html"><![CDATA[<h1>kubernetes维护</h1><p>kubernetes版本：v1.11.1/2</p><p>文档参考：</p><p><a href="http://docs.kubernetes.org.cn/" target="_blank" rel="noopener">http://docs.kubernetes.org.cn/</a><br><a href="https://www.kubernetes.org.cn/docs" target="_blank" rel="noopener">https://www.kubernetes.org.cn/docs</a></p><h2 id="一-节点"><a class="header-anchor" href="#一-节点"></a>一、 节点</h2><h3 id="1-节点查看"><a class="header-anchor" href="#1-节点查看"></a>1. 节点查看</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></pre></td><td class="code"><pre><span class="line">[root@centos-t1 ~]# kubect get nodes</span><br><span class="line">NAME      STATUS    ROLES     AGE       VERSION</span><br><span class="line">centos-t1    Ready     master    6d        v1.11.2</span><br><span class="line">centos-t2    Ready     &lt;none&gt;    6d        v1.11.2</span><br><span class="line">centos-t3    Ready     &lt;none&gt;    6d        v1.11.2</span><br></pre></td></tr></table></figure><h3 id="2-节点调度"><a class="header-anchor" href="#2-节点调度"></a>2. 节点调度</h3><p>停止调度：仅阻止后续调度任务，已被调度到的pods不受影响</p><figure class="highlight shell"><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">[root@centos-t1 ~]# kubect cordon centos-t2</span><br><span class="line">node/centos-t2 already cordoned</span><br></pre></td></tr></table></figure><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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[root@centos-t1 ~]# kubect get nodes</span><br><span class="line">NAME      STATUS                     ROLES     AGE       VERSION</span><br><span class="line">centos-t1    Ready                      master    6d        v1.11.2</span><br><span class="line">centos-t2    Ready,SchedulingDisabled   &lt;none&gt;    6d        v1.11.2</span><br><span class="line">centos-t3    Ready                      &lt;none&gt;    6d        v1.11.2</span><br></pre></td></tr></table></figure><p>恢复调度</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">[root@centos-t1 ~]# kubect uncordon centos-t2</span><br></pre></td></tr></table></figure><h3 id="3-节点维护"><a class="header-anchor" href="#3-节点维护"></a>3. 节点维护</h3><p>节点维护：清除此节点上所有用户deployment运行的pods，未使用deployment的pods需要手动清理，或者使用–force参数</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></pre></td><td class="code"><pre><span class="line">[root@centos-t1 ~]# kubect drain centos-t2 --ignore-daemonsets --delete-local-data</span><br><span class="line">node/centos-t2 already cordoned</span><br><span class="line">WARNING: Ignoring DaemonSet-managed pods: kube-flannel-ds-fmvbn, kube-proxy-bjwvs; Deleting pods with local storage: kubernetes-dashboard-744894d884-jwfrn, metrics-server-67cd98b87f-wlmbw</span><br></pre></td></tr></table></figure><p>参数解析：</p><ul><li>–ignore-daemonsets   忽略k8s的守护进程副本集pods</li><li>–delete-local-data   pods使用的本地空目录将被一起清理</li></ul><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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[root@centos-t1 ~]# kubect get nodes</span><br><span class="line">NAME      STATUS                     ROLES     AGE       VERSION</span><br><span class="line">centos-t1    Ready                      master    6d        v1.11.2</span><br><span class="line">centos-t2    Ready,SchedulingDisabled   &lt;none&gt;    6d        v1.11.2</span><br><span class="line">centos-t3    Ready                      &lt;none&gt;    6d        v1.11.2</span><br></pre></td></tr></table></figure><p>节点恢复</p><figure class="highlight shell"><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">[root@centos-t1 ~]# kubect uncordon centos-t2</span><br><span class="line">node/centos-t2 uncordoned</span><br></pre></td></tr></table></figure><h3 id="4-节点移除"><a class="header-anchor" href="#4-节点移除"></a>4. 节点移除</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></pre></td><td class="code"><pre><span class="line">[root@centos-t1 ~]# kubectl delete node centos-t2</span><br><span class="line">node "centos-t2" deleted</span><br><span class="line">[root@centos-t1 ~]# kubectl get nodes</span><br><span class="line">NAME      STATUS    ROLES     AGE       VERSION</span><br><span class="line">centos-t1    Ready     master    6d        v1.11.2</span><br><span class="line">centos-t3    Ready     &lt;none&gt;    6d        v1.11.2</span><br></pre></td></tr></table></figure><p>为了节点能重新加入到k8s集群，必须清理掉节点上原来加入到集群成生成的一部分文件，否则再次加入会失败，文件列表如下：</p><ul><li>/etc/kubernetes/pki/ca.crt</li><li>/etc/kubernetes/kubelet.conf</li><li>/etc/kubernetes/bootstrap-kubelet.conf</li></ul><p>然后需要关闭kubelet服务，否则会报端口10250被占用。重新加入请使用原来初始化生成的kubeadm join命令串</p><h2 id="二-pod"><a class="header-anchor" href="#二-pod"></a>二、pod</h2><p>pod是k8s中最小管理单元，由一个或多个容器组合在一起得共享资源，这此资源包括:</p><ul><li>共享存储，如Volumes卷</li><li>网络，唯一的集群IP地址</li><li>每个容器运行的信息，例如:容器镜像版本</li></ul><p>Pod模型是特定应用程序的“逻辑主机”，Pod中的容器共享IP地址和端口。</p><h2 id="三-service"><a class="header-anchor" href="#三-service"></a>三、service</h2><p>kubernetes的service定义了Pod的逻辑分组和一种可以访问它们的策略，这组Pod能被Service访问，使用YAML（优先）或JSON来定义Service，Service所针对的一组Pod通常由LabelSelector实现,可以通过type在ServiceSpec中指定一个需要的类型的 Service，Service的四种type:</p><ul><li>ClusterIP（默认） - 在集群中内部IP上暴露服务。此类型使Service只能从群集中访问。</li><li>NodePort - 通过每个 Node 上的 IP 和静态端口（NodePort）暴露服务。NodePort 服务会路由到 ClusterIP 服务，这个 ClusterIP 服务会自动创建。通过请求 - <nodeip>:<nodeport>，可以从集群的外部访问一个 NodePort 服务。</nodeport></nodeip></li><li>LoadBalancer - 使用云提供商的负载均衡器（如果支持），可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。</li><li>ExternalName - 通过返回 CNAME 和它的值，可以将服务映射到 externalName 字段的内容，没有任何类型代理被创建。这种类型需要v1.7版本或更高版本kube-dnsc才支持。</li></ul><h2 id="四-deployment"><a class="header-anchor" href="#四-deployment"></a>四、deployment</h2><p>Deployment负责创建和更新应用。创建Deployment后，Kubernetes master 会将Deployment创建好的应用实例调度到集群中的各个节点。</p><h2 id="五-secret"><a class="header-anchor" href="#五-secret"></a>五、secret</h2><p>k8s密钥是保存各类组件连接之间认证的服务</p><h2 id="六-namespace"><a class="header-anchor" href="#六-namespace"></a>六、namespace</h2><p>Namespace是对一组资源和对象的抽象集合，比如可以用来将系统内部的对象划分为不同的项目组或用户组。常见的pods, services, replication controllers和deployments等都是属于某一个namespace的（默认是default），而node, persistentVolumes等则不属于任何namespace。Namespace常用来隔离不同的用户，比如Kubernetes自带的服务一般运行在kube-system namespace中。</p><h3 id="1-系统默认命名空间-不可删除"><a class="header-anchor" href="#1-系统默认命名空间-不可删除"></a>1. 系统默认命名空间（不可删除）</h3><ul><li>default: 给用户定义的默认命名空间</li><li>kube-public: k8s系统公共服务的命名空间</li><li>kube-system: k8s系统服务及组件的命名空间</li></ul><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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[root@centos-t1 kubernetes]# kubectl get namespace</span><br><span class="line">NAME          STATUS    AGE</span><br><span class="line">default       Active    6d</span><br><span class="line">kube-public   Active    6d</span><br><span class="line">kube-system   Active    6d</span><br></pre></td></tr></table></figure><h3 id="2-创新命名空间"><a class="header-anchor" href="#2-创新命名空间"></a>2. 创新命名空间</h3><figure class="highlight shell"><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">[root@centos-t1 ~]# kubectl create namespace prod</span><br><span class="line">namespace/prod created</span><br></pre></td></tr></table></figure><p>然后，你可以将你所有创建的k8s资源放在这个命名空间内，可以做到逻辑集合在一起，方便统一管理的好处</p><h2 id="七-lables"><a class="header-anchor" href="#七-lables"></a>七、lables</h2><p>Labels其实就一对 key/value ，被关联到对象上，标签的使用我们倾向于能够标示对象的特殊特点，并且对用户而言是有意义的（就是一眼就看出了这个Pod是尼玛数据库）</p><h2 id="八-volume"><a class="header-anchor" href="#八-volume"></a>八、volume</h2><p>默认情况下容器中的磁盘文件是非持久化的，对于运行在容器中的应用来说面临两个问题，第一：当容器挂掉kubelet将重启启动它时，文件将会丢失；第二：当Pod中同时运行多个容器，容器之间需要共享文件时。Kubernetes的Volume解决了这两个问题。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1&gt;kubernetes维护&lt;/h1&gt;
&lt;p&gt;kubernetes版本：v1.11.1/2&lt;/p&gt;
&lt;p&gt;文档参考：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://docs.kubernetes.org.cn/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
      
    
    </summary>
    
      <category term="Kubernetes教程" scheme="http://www.whyvv.top/categories/Kubernetes%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Kubernetes" scheme="http://www.whyvv.top/tags/Kubernetes/"/>
    
      <category term="K8s" scheme="http://www.whyvv.top/tags/K8s/"/>
    
  </entry>
  
  <entry>
    <title>ES数据备份和恢复</title>
    <link href="http://www.whyvv.top/es.html"/>
    <id>http://www.whyvv.top/es.html</id>
    <published>2019-10-16T05:00:00.000Z</published>
    <updated>2019-10-16T07:39:02.341Z</updated>
    
    <content type="html"><![CDATA[<p>Elasticsearch 5.x 数据备份和恢复可由<a href="https://www.elastic.co/guide/en/elasticsearch/reference/5.5/modules-snapshots.html" target="_blank" rel="noopener">snapshot</a> 模块来完成，snapshot模块可以通过文件共享系统为单个索引或整个集群远程创建快照和进行数据恢复。</p><h1>数据备份</h1><p>索引快照时增量的。在创建快照前es会分析已有快照仓库，只对上次备份后更改的内容进行增量备份。在创建备份时同一个集群中只能运行一个es snapshot进程。</p><h2 id="es-基础命令"><a class="header-anchor" href="#es-基础命令"></a>Es 基础命令</h2><p><strong>创建快照仓库</strong></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></pre></td><td class="code"><pre><span class="line">curl -X PUT "node1:9200/_snapshot/my_backup" -H 'Content-Type: application/json' -d'&#123;</span><br><span class="line">  "type": "fs",</span><br><span class="line">  "settings": &#123;</span><br><span class="line">    "location": "sys_backup"</span><br><span class="line">  &#125;</span><br><span class="line">&#125;'</span><br></pre></td></tr></table></figure><p><strong>查看已注册的快照仓库</strong></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">curl -X GET "node1:9200/_snapshot/my_backup"</span><br></pre></td></tr></table></figure><p>可以使用逗号间隔多个仓库，星号通配符匹配所有仓库名字，下面示例返回仓库名以repo开头的和包含backup的仓库信息：</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">curl -X GET "node1:9200/_snapshot/repo*,*backup*"</span><br></pre></td></tr></table></figure><p>获取所有已注册快照仓库，省略仓库名或者使用_all</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">curl -X GET "node1:9200/_snapshot"</span><br></pre></td></tr></table></figure><p>或者</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">curl -X GET "node1:9200/_snapshot/_all"</span><br></pre></td></tr></table></figure><p><strong>查看快照仓库列表</strong></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">curl -X GET "node1:9200/_cat/repositories?v"</span><br></pre></td></tr></table></figure><h2 id="准备工作"><a class="header-anchor" href="#准备工作"></a>准备工作</h2><p><strong>文件共享系统</strong></p><p>nfs、hdfs？</p><p>共享文件系统仓库（“type”: “fs”）使用共享文件系统存快照，如果要注册共享文件系统仓库，必须在所有master和data节点挂载相同的共享文件系统到同一个路径位置。这个路径位置（或者它的一个父目录）必须在所有master和data节点的path.repo设置上注册。</p><p>假设共享文件系统挂载到 /data/backups/es_backup ，应该在elasticsearch.yml文件中添加如下配置：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">path.repo:</span> <span class="string">["/data/backups",</span> <span class="string">"/data/longterm_backups"</span><span class="string">]</span></span><br></pre></td></tr></table></figure><p><strong>创建快照仓库</strong></p><p>所有节点重启之后，执行下面的命令注册名字为 es_backup 的共享文件系统仓库：</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></pre></td><td class="code"><pre><span class="line">curl -X PUT 'node1:9200/_snapshot/es_backup?verify=false' -H 'Content-Type: application/json' -d'&#123;</span><br><span class="line">    "type": "fs",</span><br><span class="line">    "settings": &#123;</span><br><span class="line">        "location": "/mount/backups/es_backup",</span><br><span class="line">        "compress": true,</span><br><span class="line">        "max_restore_bytes_per_sec": 50m,</span><br><span class="line">        "max_snapshot_bytes_per_sec": 30m</span><br><span class="line">    &#125;</span><br><span class="line">&#125;'</span><br></pre></td></tr></table></figure><p>如果使用相对路径，该路径将根据在path.repo中定义的第一个路径决定：</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></pre></td><td class="code"><pre><span class="line">curl -XPUT 'http://node1:9200/_snapshot/es_backup?verify=false' -H 'Content-Type: application/json' -d '&#123;</span><br><span class="line">    "type": "fs",</span><br><span class="line">    "settings": &#123;</span><br><span class="line">        "location": "es_backup",</span><br><span class="line">        "compress": true,</span><br><span class="line">        "max_restore_bytes_per_sec": 50m,</span><br><span class="line">        "max_snapshot_bytes_per_sec": 30m</span><br><span class="line">    &#125;</span><br><span class="line">&#125;'</span><br></pre></td></tr></table></figure><p>参数说明</p><table><thead><tr><th style="text-align:center">参数</th><th style="text-align:center">含义</th></tr></thead><tbody><tr><td style="text-align:center">location</td><td style="text-align:center">快照存储位置</td></tr><tr><td style="text-align:center">compress</td><td style="text-align:center">是否压缩源文件，默认为true</td></tr><tr><td style="text-align:center">chunk_size</td><td style="text-align:center">如果有需要，可以将大文件分解为多个小文件，默认不开启</td></tr><tr><td style="text-align:center">max_restore_bytes_per_sec</td><td style="text-align:center">指定数据恢复速度，默认为 40m/s</td></tr><tr><td style="text-align:center">max_snapshot_bytes_per_sec</td><td style="text-align:center">指定创建快照时的速度，默认为 40m/s</td></tr><tr><td style="text-align:center">readonly</td><td style="text-align:center">设置为只读仓库，默认为false</td></tr></tbody></table><p><strong>Repository Verification</strong></p><p>在创建一个仓库时，会即刻在集群所有节点验证确保其功能在所有节点可用，verify 参数可以用来取消该验证（如果想使用验证功能，创建仓库时去掉 ?verify=false 参数即可）：</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">curl -XPUT 'http://node1:9200/_snapshot/es_backup?verify=false' -H 'Content-Type: application/json' -d '&#123;</span><br><span class="line">    "type": fs</span><br><span class="line">    ... ...</span><br><span class="line">&#125;'</span><br></pre></td></tr></table></figure><p>验证过程可以通过下面命令手动执行：</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">curl -X POST "node1:9200/_snapshot/es_backup/_verify"</span><br></pre></td></tr></table></figure><h2 id="snapshot"><a class="header-anchor" href="#snapshot"></a>Snapshot</h2><p><strong>创建快照</strong></p><p>一个仓库可以拥有同一个集群的多个快照。在一个集群中快照拥有一个唯一名字作为标识。</p><p>示例： 在仓库 es_backup 中创建名字为 test_snapshot 的快照，可以通过执行下面的命令来实现。</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">curl -X PUT "node1:9200/_snapshot/es_backup/test_snapshot?wait_for_completion=true"</span><br></pre></td></tr></table></figure><p>参数 wait_for_completion 决定请求是在快照初始化后立即返回（默认），还是等快照创建完成之后再返回。快照初始化时，所有之前的快照信息会被加载到内存，所以在一个大的仓库中改请求需要若干秒（甚至分钟）才能返回，即使参数 wait_for_completion 的值设置为 false。</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><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">curl -X PUT "node1:9200/_snapshot/es_backup/test_snapshot_2?wait_for_completion=true" -H 'Content-Type: application/json' -d'</span><br><span class="line">&#123;</span><br><span class="line">  "indices": "index_1,index_2",</span><br><span class="line">  "ignore_unavailable": true,</span><br><span class="line">  "include_global_state": false</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>要包含到快照中索引列表可以使用支持多个索引语法的 indices 参数来指定。快照请求也支持 ignore_unavailable 选项，该选项设置为 true 时，在创建快照时会忽略不存在的索引。默认情况下，如果选项 ignore_unavailable 没有设值，一个索引缺失，快照请求会失败。</p><p>通过设置 include_global_state 为 false，可以阻止集群全局状态信息被保存为快照的一部分。默认情况下，如果如果一个快照中的一个或者多个索引没有所有主分片可用，整个快照创建会失败，该情况可以通过设置 partial 为 true 来改变。</p><p>快照名可以通过使用 date_math_expressions 来自动获得，和创建新索引时类似。注意特殊字符需要 URI 转码处理。</p><p>例如，在名字中使用当前日期，比如 snapshot-2018.05.11，来创建快照，可以使用如下命令完成：</p><figure class="highlight shell"><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="meta">#</span> PUT /_snapshot/es_backup/&lt;snapshot-&#123;now/d&#125;&gt;</span><br><span class="line">curl -X PUT "node1:9200/_snapshot/es_backup/%3Csnapshot-%7Bnow%2Fd%7D%3E"</span><br></pre></td></tr></table></figure><p><strong>创建快照</strong></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></pre></td><td class="code"><pre><span class="line">curl -X PUT "node1:9200/_snapshot/es_backup/syslog?wait_for_completion=true" -H 'Content-Type: application/json' -d'</span><br><span class="line">&#123;</span><br><span class="line">  "indices": "bash_history.log*,secure.log*,cron.log*",</span><br><span class="line">  "ignore_unavailable": true,</span><br><span class="line">  "include_global_state": false</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>查看快照信息</strong></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">curl -X GET "node1:9200/_snapshot/es_backup/syslog"</span><br></pre></td></tr></table></figure><p>这个命令返回快照的基本信息，包括开始合结束时间、创建快照的 ElasticSearch 版本、包含的索引列表、快照当前状态和快照期间产生的失败索引列表。快照的状态有：</p><table><thead><tr><th style="text-align:center">状态</th><th style="text-align:center">含义</th></tr></thead><tbody><tr><td style="text-align:center">IN_PROGRESS</td><td style="text-align:center">正在创建快照</td></tr><tr><td style="text-align:center">SUCCESS</td><td style="text-align:center">快照创建成功</td></tr><tr><td style="text-align:center">FAILED</td><td style="text-align:center">快照创建完成，但是有错误，数据不会保存</td></tr><tr><td style="text-align:center">PARTIAL</td><td style="text-align:center">整个集群备份完成，但是至少有一个shard数据存贮失败，会有更具体报错信息</td></tr><tr><td style="text-align:center">INCOMPATIBLE</td><td style="text-align:center">创建快照的es版本和当前集群es版本不一致</td></tr></tbody></table><p>查看某仓库下所有快照信息：</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">curl -X GET "node1:9200/_snapshot/es_backup/_all"</span><br></pre></td></tr></table></figure><p>查看当前正在运行的快照：</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">curl -X GET "localhost:9200/_snapshot/my_backup/_current"</span><br></pre></td></tr></table></figure><p><strong>删除快照</strong></p><p>从仓库中删除一个快照，使用如下命令：</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">curl -X DELETE "node1:9200/_snapshot/es_backup/test_snapshot_2"</span><br></pre></td></tr></table></figure><p>当一个快照从仓库中删除，ElasticSearch 将删除该快照关联的但不被其他快照使用的所有文件。如果在快照创建的时候执行快照删除操作，此快照创建进程将终止且所有该进程已创建的文件也将被清理。所以，快照删除操作可以用来取消错误启动的长时间运行的快照操作。</p><p><strong>删除仓库</strong></p><p>可以使用下面命令注销仓库：</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">curl -X DELETE "node1:9200/_snapshot/es_backup"</span><br></pre></td></tr></table></figure><h2 id="数据恢复"><a class="header-anchor" href="#数据恢复"></a>数据恢复</h2><p><strong>全量恢复</strong></p><p>快照可以通过执行以下命令恢复</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">curl -X POST "node1:9200/_snapshot/es_backup/syslog/_restore"</span><br></pre></td></tr></table></figure><p>默认情况下，快照中的所有索引将被恢复，集群状态不被恢复。可以通过在恢复请求中使用 indices 和 include_global_state 选项来指定要恢复的索引和允许恢复集群全局状态。索引列表支持多索引语法。rename_pattern 和 rename_replacement 选项在恢复时通过正则表达式来重命名索引。设置 include_aliases 为 false 可以防止与索引关联的别名被一起恢复。</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></pre></td><td class="code"><pre><span class="line">curl -X POST "localhost:9200/_snapshot/my_backup/snapshot_1/_restore" -H 'Content-Type: application/json' -d'</span><br><span class="line">&#123;</span><br><span class="line">  "indices": "index_1,index_2",</span><br><span class="line">  "ignore_unavailable": true,</span><br><span class="line">  "include_global_state": true,</span><br><span class="line">  "rename_pattern": "index_(.+)",</span><br><span class="line">  "rename_replacement": "restored_index_$1"</span><br><span class="line">&#125;'</span><br></pre></td></tr></table></figure><p>恢复操作可以在正常运行的集群上执行。已存在的索引只能在关闭状态下才能恢复，并且要跟快照中索引拥有相同数目的分片。还原操作自动打开关闭状态的索引，如果被还原索引在集群不存在，将创建新索引。如果集群状态通过 include_global_state （默认是 false）选项被还原，在集群中不存在的模板会被新增，已存在的同名模板会被快照中的模板替换。持久化设置会被添加到现有的持久化设置中。</p><p><strong>参考</strong></p><ul><li>官方：<a href="https://www.elastic.co/guide/en/elasticsearch/reference/5.5/modules-snapshots.html" target="_blank" rel="noopener">https://www.elastic.co/guide/en/elasticsearch/reference/5.5/modules-snapshots.html</a></li><li>示例1：<a href="https://blog.csdn.net/ale2012/article/details/82702128" target="_blank" rel="noopener">https://blog.csdn.net/ale2012/article/details/82702128</a></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Elasticsearch 5.x 数据备份和恢复可由&lt;a href=&quot;https://www.elastic.co/guide/en/elasticsearch/reference/5.5/modules-snapshots.html&quot; target=&quot;_blank&quot; r
      
    
    </summary>
    
      <category term="技术" scheme="http://www.whyvv.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="ELK/EFK" scheme="http://www.whyvv.top/tags/ELK-EFK/"/>
    
      <category term="日志收集" scheme="http://www.whyvv.top/tags/%E6%97%A5%E5%BF%97%E6%94%B6%E9%9B%86/"/>
    
  </entry>
  
  <entry>
    <title>Roy学Kubernetes(21)：Persistent Volumes</title>
    <link href="http://www.whyvv.top/k8s21.html"/>
    <id>http://www.whyvv.top/k8s21.html</id>
    <published>2019-09-23T01:30:00.000Z</published>
    <updated>2019-09-23T09:52:15.908Z</updated>
    
    <content type="html"><![CDATA[<h1>概述</h1><p>PersistentVolume子系统提供了用户和管理员使用和管理存储的抽象API。在这个子系统中，引进了两个新的API资源：PersistentVolume和PersistentVolumeClaim。</p><p>**PersistentVolume（PV）**是已经由管理员提供或者使用Storage类动态地从k8s Volume中配备的一块存储器。PV是Volume的插件，它有自己独立的生命周期，不受使用PV的Pod的生命周期影响。这个API对象描述了存储的实现细节，例如NFS、iSCSI或云提供商特定的存储系统。</p><p>**PersistentVolumeClaim（PVC）**是由用户申请存储的请求。 它和Pod类似：Pod消耗节点资源而PVC消耗PV资源；Pod可以配置请求资源的限制（CPU和存储器）而PVC可以配置存储特定的大小和访问模式（例如，挂载一次读/写或多次只读的存储）。</p><p>**StorageClass（存储类）**PVC允许用户消耗抽象存储资源，且一般带有存储参数需求：例如性能、访问模式等，且不希望暴露这些卷底层实现的细节。针对这些需，k8s提供了StorageClass资源来实现。</p><h1>PV和PVC的生命周期</h1><p>PV和PVC都遵循如下生命周期：</p><p>Provisioning–&gt;Binding–&gt;Using–&gt;Releasing–&gt;Recycling</p><h3 id="存储供应"><a class="header-anchor" href="#存储供应"></a>存储供应</h3><p>PV有二种类型：静态PV和动态PV。</p><p><strong>静态PV</strong></p><p>可供k8s集群用户使用的真实存储实现的PV，他们存在于Kubernetes API中，且可直接被消费。</p><p><strong>动态PV</strong></p><p>当管理员没有为匹配的用户PVC而创建的静态PV时，可以尝试动态地为PVC提供volume卷。此配置是基于StorageClasses：必须先配置和创建好StorageClasses，然后在PVC请求此存储类。要使用StorageClasses，请确保在API服务器上启用DefaultStorageClass控制器。可通过对apiserver的启动参数–enable-admission-plugins添加DefaultStorageClass生效。</p><p><strong>Binding</strong></p><p>在动态配置的情况下，用户创建或已经创建了具有特定数量的存储请求和特定访问模式的PersistentVolumeClaim。 主机中的控制回路监视新的PVC，找到匹配的PV（如果可能），并将它们绑定在一起。 如果为新的PVC动态配置PV，则循环将始终将该PV绑定到PVC。 否则，用户总是至少得到他们要求的内容，但是卷可能超出了要求。 一旦绑定，PersistentVolumeClaim绑定是排他的，不管用于绑定它们的模式。</p><p>如果匹配的卷不存在，PVC将保持无限期。 随着匹配卷变得可用，PVC将被绑定。 例如，提供许多50Gi PV的集群将不匹配要求100Gi的PVC。 当集群中添加100Gi PV时，可以绑定PVC。</p><p><strong>Using</strong></p><p>Pod使用PVC作为卷。 集群检查声明以找到绑定的卷并挂载该卷的卷。 对于支持多种访问模式的卷，用户在将其声明用作pod中的卷时指定所需的模式。</p><p>一旦用户有声明并且该声明被绑定，绑定的PV属于用户，只要他们需要它。 用户通过在其Pod的卷块中包含persistentVolumeClaim来安排Pods并访问其声明的PV。</p><p><strong>Releasing</strong></p><p>当用户完成卷时，他们可以从允许资源回收的API中删除PVC对象。 当声明被删除时，卷被认为是“释放的”，但是它还不能用于另一个声明。 以前的索赔人的数据仍然保留在必须根据政策处理的卷上.</p><p><strong>Reclaiming</strong></p><p>PersistentVolume的回收策略告诉集群在释放其声明后，该卷应该如何处理。 目前，卷可以是保留，回收或删除。 保留可以手动回收资源。 对于那些支持它的卷插件，删除将从Kubernetes中删除PersistentVolume对象，以及删除外部基础架构（如AWS EBS，GCE PD，Azure Disk或Cinder卷）中关联的存储资产。 动态配置的卷始终被删除</p><p><strong>Recycling</strong></p><p>如果受适当的卷插件支持，回收将对卷执行基本的擦除（rm -rf / thevolume / *），并使其再次可用于新的声明。<br>但是，管理员可以使用Kubernetes控制器管理器命令行参数来配置自定义的回收站pod模板，如这里所述。 定制回收站模板必须包含卷规范，</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1&gt;概述&lt;/h1&gt;
&lt;p&gt;PersistentVolume子系统提供了用户和管理员使用和管理存储的抽象API。在这个子系统中，引进了两个新的API资源：PersistentVolume和PersistentVolumeClaim。&lt;/p&gt;
&lt;p&gt;**PersistentVol
      
    
    </summary>
    
      <category term="Kubernetes教程" scheme="http://www.whyvv.top/categories/Kubernetes%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Kubernetes" scheme="http://www.whyvv.top/tags/Kubernetes/"/>
    
      <category term="K8s" scheme="http://www.whyvv.top/tags/K8s/"/>
    
  </entry>
  
  <entry>
    <title>Roy学Kubernetes(20)：Volumes</title>
    <link href="http://www.whyvv.top/k8s20.html"/>
    <id>http://www.whyvv.top/k8s20.html</id>
    <published>2019-09-02T01:30:00.000Z</published>
    <updated>2019-09-02T05:48:47.148Z</updated>
    
    <content type="html"><![CDATA[<p>Container中的磁盘文件（生命周期）是短暂的，这在容器中运行时会给部分特殊的应用程序带来一些问题。首先，当容器崩溃时，kubelet在重新启动它，数据文件会丢失（Container会以干净的状态启动）。其次，在Pod中运行多个Container时，通常需要在这些容器之间共享文件。Kubernetes Volume（卷）抽象的解决了这两个问题。</p><h1>背景</h1><p>Docker也有卷的概念，虽然它有点宽松和较少管理。在Docker中，卷只是磁盘上或另一个Container中的目录。生命周期不受管理，直到最近才有本地磁盘支持的卷。 Docker现在提供了卷驱动程序，但是现在功能非常有限（例如，从Docker 1.7开始，每个Container只允许一个卷驱动程序，并且无法将参数传递给卷）。</p><p>另一方面，Kubernetes卷具有明确的生命周期：与使用它的Pod相同。因此，卷可以比Pod中运行的任何Container更长，并且可以在Container重新启动之间保留数据。当然，当Pod不再存在时，卷也将不复存在。Kubernetes支持多种类型的卷，Pod可以同时使用任意数量的卷。</p><p>从本质上讲，卷只是一个目录，可能包含一些数据，Pod中的容器可以访问它。该目录是如何形成的，支持它的介质以及它的内容由所使用的特定卷类型决定。要使用卷，Pod指定要为Pod提供的卷（<code>.spec.volumes</code>字段）以及将这些卷挂载到Container中的位置（<code>.spec.containers.volumeMounts</code>字段）。</p><p>容器中的进程可以看到由Docker镜像和卷组成的文件系统视图。Docker镜像位于文件系统层次结构的根目录下，任何卷都挂载在镜像中的指定路径上。 卷无法挂载其他卷或具有到其他卷的硬链接。Pod中的每个Container必须独立指定每个卷的挂载位置。</p><h1>volumes类型</h1><p>Kubernetes支持如下多种类型的Volume：</p><ul><li>awsElasticBlockStore</li><li>azureDisk</li><li>azureFile</li><li>cephfs</li><li>cinder</li><li>configMap</li><li>csi</li><li>downwardAPI</li><li>emptyDir</li><li>fc (fibre channel)</li><li>flexVolume</li><li>flocker</li><li>gcePersistentDisk</li><li>gitRepo (deprecated)</li><li>glusterfs</li><li>hostPath</li><li>iscsi</li><li>local</li><li>nfs</li><li>persistentVolumeClaim</li><li>projected</li><li>portworxVolume</li><li>quobyte</li><li>rbd</li><li>scaleIO</li><li>secret</li><li>storageos</li><li>vsphereVolume</li></ul><h3 id="awselasticblockstore"><a class="header-anchor" href="#awselasticblockstore"></a>awsElasticBlockStore</h3><p>awsElasticBlockStore卷将Amazon Web Services（AWS）EBS卷挂载到你的Pod中。与删除Pod时删除的emptyDir不同，EBS卷的内容将被保留，并且仅卸载卷。这意味着可以使用数据预先填充EBS卷，并且可以在Pod之间“切换”该数据。</p><p>注意：必须先使用aws ec2 create-volume或AWS API创建EBS卷，然后才能使用它。</p><p>使用awsElasticBlockStore卷时有一些限制：</p><ul><li>正在运行Pod的节点必须是AWS EC2实例</li><li>这些实例需要与EBS卷位于同一区域和可用区域</li><li>EBS仅支持挂载卷的单个EC2实例</li></ul><p><strong>创建EBS卷</strong></p><p>在将Pod与EBS卷一起使用之前，需要先创建它。</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">aws ec2 create-volume --availability-zone=eu-west-1a --size=10 --volume-type=gp2</span><br></pre></td></tr></table></figure><p>确保该区域与你启动群集的区域匹配。（并检查大小和EBS卷类型是否适合你的使用！）</p><p>示例:</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">test-ebs</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">  - image:</span> <span class="string">k8s.gcr.io/test-webserver</span></span><br><span class="line"><span class="attr">    name:</span> <span class="string">test-container</span></span><br><span class="line"><span class="attr">    volumeMounts:</span></span><br><span class="line"><span class="attr">    - mountPath:</span> <span class="string">/test-ebs</span></span><br><span class="line"><span class="attr">      name:</span> <span class="string">test-volume</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">test-volume</span></span><br><span class="line">    <span class="comment"># This AWS EBS volume must already exist.</span></span><br><span class="line"><span class="attr">    awsElasticBlockStore:</span></span><br><span class="line"><span class="attr">      volumeID:</span> <span class="string">&lt;volume-id&gt;</span></span><br><span class="line"><span class="attr">      fsType:</span> <span class="string">ext4</span></span><br></pre></td></tr></table></figure><h3 id="azuredisk"><a class="header-anchor" href="#azuredisk"></a>azureDisk</h3><p>azureDisk用于将Microsoft Azure数据磁盘挂载到Pod。更多详细信息可以在<a href="https://github.com/kubernetes/examples/tree/master/staging/volumes/azure_disk/README.md" target="_blank" rel="noopener">这里</a>找到。</p><h3 id="azurefile"><a class="header-anchor" href="#azurefile"></a>azureFile</h3><p>azureFile用于将Microsoft Azure文件卷（SMB 2.1和3.0）挂载到Pod中。更多详细信息可以在<a href="https://github.com/kubernetes/examples/tree/master/staging/volumes/azure_file/README.md" target="_blank" rel="noopener">这里</a>找到。</p><h3 id="cephfs"><a class="header-anchor" href="#cephfs"></a>cephfs</h3><p>cephfs卷允许将现有的CephFS卷挂载到Pod中。 与删除Pod时删除的emptyDir不同，将保留cephfs卷的内容，并且仅卸载卷。这意味着可以使用数据预先填充CephFS卷，并且可以在Pod之间“切换”该数据。 CephFS可以由多个编写器同时挂载。</p><p>注意：在使用共享之前，必须运行自己的Ceph服务器并创建共享。有关更多详细信息，请参阅<a href="https://github.com/kubernetes/examples/tree/master/volumes/cephfs/" target="_blank" rel="noopener">CephFS示例</a>。</p><h3 id="cinder"><a class="header-anchor" href="#cinder"></a>cinder</h3><p>先决条件：已配置OpenStack Cloud Provider的Kubernetes。对于cloudprovider配置，请参阅云提供商<a href="https://kubernetes.io/docs/concepts/cluster-administration/cloud-providers/#openstack" target="_blank" rel="noopener">openstack</a>。</p><p>cinder用于将OpenStack Cinder Volume挂载到Pod中。</p><p>示例：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">test-cinder</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">  - image:</span> <span class="string">k8s.gcr.io/test-webserver</span></span><br><span class="line"><span class="attr">    name:</span> <span class="string">test-cinder-container</span></span><br><span class="line"><span class="attr">    volumeMounts:</span></span><br><span class="line"><span class="attr">    - mountPath:</span> <span class="string">/test-cinder</span></span><br><span class="line"><span class="attr">      name:</span> <span class="string">test-volume</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">test-volume</span></span><br><span class="line">    <span class="comment"># This OpenStack volume must already exist.</span></span><br><span class="line"><span class="attr">    cinder:</span></span><br><span class="line"><span class="attr">      volumeID:</span> <span class="string">&lt;volume-id&gt;</span></span><br><span class="line"><span class="attr">      fsType:</span> <span class="string">ext4</span></span><br></pre></td></tr></table></figure><h3 id="configmap"><a class="header-anchor" href="#configmap"></a>configMap</h3><p>configMap资源提供了一种将<strong>配置数据</strong>注入Pod的方法。存储在ConfigMap对象中的数据可以在configMap类型的卷中引用，然后由在Pod中运行的容器化应用程序使用。引用configMap对象时，只需在卷中提供其名称即可引用它。还可以自定义ConfigMap中特定条目的路径。例如，要将<code>log-config</code> ConfigMap挂载到名为<code>configmap-pod</code>的Pod上，可以使用下面的YAML：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">configmap-pod</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">    - name:</span> <span class="string">test</span></span><br><span class="line"><span class="attr">      image:</span> <span class="string">busybox</span></span><br><span class="line"><span class="attr">      volumeMounts:</span></span><br><span class="line"><span class="attr">        - name:</span> <span class="string">config-vol</span></span><br><span class="line"><span class="attr">          mountPath:</span> <span class="string">/etc/config</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">    - name:</span> <span class="string">config-vol</span></span><br><span class="line"><span class="attr">      configMap:</span></span><br><span class="line"><span class="attr">        name:</span> <span class="string">log-config</span></span><br><span class="line"><span class="attr">        items:</span></span><br><span class="line"><span class="attr">          - key:</span> <span class="string">log_level</span></span><br><span class="line"><span class="attr">            path:</span> <span class="string">log_level</span></span><br></pre></td></tr></table></figure><p><code>log-config</code> ConfigMap作为卷挂载，存储在其log_level条目中的所有内容都挂载在路径“/etc/config/log_level”的Pod中。注意，此路径派生自卷的mountPath和使用log_level键入的路径，且必须先创建ConfigMap才能使用它。</p><p>注意：使用ConfigMap作为<code>subPath</code>卷挂载的Container将不会收到ConfigMap更新。</p><h3 id="downwardapi"><a class="header-anchor" href="#downwardapi"></a>downwardAPI</h3><p><a href="https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/" target="_blank" rel="noopener">downwardAPI</a>卷用于向应用程序提供downward的API数据。它挂载目录并将所请求的数据写入纯文本文件。</p><p>注意：使用downwardAPI作为<code>subPath</code>卷挂载的Container不会接收downwardAPI更新。</p><h3 id="emptydir"><a class="header-anchor" href="#emptydir"></a>emptyDir</h3><p>将Pod分配给节点时，首先会创建一个emptyDir卷，只要Pod在该节点上运行，就会存在。 顾名思义，它最初是空的。Pod中的容器都可以在emptyDir卷中读取和写入相同的文件。当从节点中删除Pod时，将永久删除emptyDir中的数据。</p><p>注意：容器崩溃不会从节点中删除Pod，因此emptyDir卷中的数据在Container崩溃中是安全的。</p><p>emptyDir的一些用途是：</p><ul><li>临时空间，例如基于磁盘的合并排序</li><li>检查从崩溃中恢复的长计算</li><li>保存内容管理器容器在Web服务器容器提供数据时提取的文件</li></ul><p>默认情况下，emptyDir卷存储在支持节点的任何介质上：可能是磁盘或SSD或网络存储，具体取决于你的环境。但是，可以将<code>emptyDir.medium</code>字段设置为“Memory”，以告知Kubernetes挂载tmpfs（RAM支持的文件系统）。虽然tmpfs非常快，但请注意，与磁盘不同，tmpfs在节点重新启动时被清除，并且你编写的任何文件都将计入Container的内存限制。</p><p>示例Pod：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">test-pd</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">  - image:</span> <span class="string">k8s.gcr.io/test-webserver</span></span><br><span class="line"><span class="attr">    name:</span> <span class="string">test-container</span></span><br><span class="line"><span class="attr">    volumeMounts:</span></span><br><span class="line"><span class="attr">    - mountPath:</span> <span class="string">/cache</span></span><br><span class="line"><span class="attr">      name:</span> <span class="string">cache-volume</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">cache-volume</span></span><br><span class="line"><span class="attr">    emptyDir:</span> <span class="string">&#123;&#125;</span></span><br></pre></td></tr></table></figure><h3 id="fc光纤通道"><a class="header-anchor" href="#fc光纤通道"></a>fc光纤通道</h3><p>fc卷允许将现有光纤通道卷挂载在Pod中。可以使用卷配置中的参数<code>targetWWNs</code>指定单个或多个目标全局通用名称。如果指定了多个WWN，则<code>targetWWN</code>期望这些WWN来自多路径连接。</p><p>注意：你必须配置FC SAN分区以预先将这些LUN（卷）分配和屏蔽到目标WWN，以便Kubernetes主机可以访问它们。<a href="https://github.com/kubernetes/examples/tree/master/staging/volumes/fibre_channel" target="_blank" rel="noopener">详见</a></p><h3 id="flocker"><a class="header-anchor" href="#flocker"></a>flocker</h3><p>Flocker是一个开源的集群Container数据卷管理器。它提供由各种存储后端支持的数据卷的管理和编排。</p><p>flocker卷允许将Flocker数据集挂载到Pod中。 如果Flocker中尚不存在数据集，则需要首先使用Flocker CLI或使用Flocker API创建数据集。 如果数据集已经存在，它将被Flocker重新附加到调度Pod的节点。这意味着可以根据需要在Pod之间“切换”数据。</p><p>注意：必须先运行自己的Flocker挂载才能使用它。有关更多详细信息，请参阅<a href="https://github.com/kubernetes/examples/tree/master/staging/volumes/flocker" target="_blank" rel="noopener">Flocker示例</a>。</p><h3 id="gcepersistentdisk"><a class="header-anchor" href="#gcepersistentdisk"></a>gcePersistentDisk</h3><p>gcePersistentDisk卷将Google Compute Engine（GCE）永久磁盘装入Pod。与删除Pod时删除的emptyDir不同，PD的内容将被保留，并且仅卸载卷。 这意味着PD可以预先填充数据，并且该数据可以在Pod之间“切换”。</p><p>注意：必须先使用gcloud或GCE API或UI创建PD，然后才能使用它。</p><p>使用gcePersistentDisk时有一些限制：</p><ul><li>运行Pod的节点必须是GCE VM</li><li>这些VM需要与PD处于同一GCE项目和区域</li></ul><p>PD的一个特征是它们可以同时由多个消费者以只读方式挂载。这意味着可以使用数据集预先填充PD，然后根据需要从多个Pod中并行提供。不幸的是，PD只能由一个消费者以读写模式挂载：不允许同时写入。</p><p>除非PD是只读的或副本计数为0或1，否则在由ReplicationController控制的Pod上使用PD将失败。</p><p><strong>创建PD</strong></p><p>在将GCE PD与Pod一起使用之前，需要先创建它：</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">gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk</span><br></pre></td></tr></table></figure><p>示例Pod:</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">test-pd</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">  - image:</span> <span class="string">k8s.gcr.io/test-webserver</span></span><br><span class="line"><span class="attr">    name:</span> <span class="string">test-container</span></span><br><span class="line"><span class="attr">    volumeMounts:</span></span><br><span class="line"><span class="attr">    - mountPath:</span> <span class="string">/test-pd</span></span><br><span class="line"><span class="attr">      name:</span> <span class="string">test-volume</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">test-volume</span></span><br><span class="line">    <span class="comment"># This GCE PD must already exist.</span></span><br><span class="line"><span class="attr">    gcePersistentDisk:</span></span><br><span class="line"><span class="attr">      pdName:</span> <span class="string">my-data-disk</span></span><br><span class="line"><span class="attr">      fsType:</span> <span class="string">ext4</span></span><br></pre></td></tr></table></figure><p><strong>手动配置区域PD PersistentVolume</strong></p><p>使用StorageClass for GCE PD可以进行动态配置。 在创建PersistentVolume之前，先必须创建PD：</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></pre></td><td class="code"><pre><span class="line">gcloud beta compute disks create --size=500GB my-data-disk</span><br><span class="line">    --region us-central1</span><br><span class="line">    --replica-zones us-central1-a,us-central1-b</span><br></pre></td></tr></table></figure><p>PersistentVolume spec配置示例：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">PersistentVolume</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">test-volume</span></span><br><span class="line"><span class="attr">  labels:</span></span><br><span class="line">    <span class="string">failure-domain.beta.kubernetes.io/zone:</span> <span class="string">us-central1-a__us-central1-b</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  capacity:</span></span><br><span class="line"><span class="attr">    storage:</span> <span class="number">400</span><span class="string">Gi</span></span><br><span class="line"><span class="attr">  accessModes:</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">ReadWriteOnce</span></span><br><span class="line"><span class="attr">  gcePersistentDisk:</span></span><br><span class="line"><span class="attr">    pdName:</span> <span class="string">my-data-disk</span></span><br><span class="line"><span class="attr">    fsType:</span> <span class="string">ext4</span></span><br></pre></td></tr></table></figure><h3 id="glusterfs"><a class="header-anchor" href="#glusterfs"></a>glusterfs</h3><p>glusterfs卷允许将Glusterfs（开源网络文件系统）卷挂载到Pod中。与删除Pod时删除的emptyDir不同，glusterfs卷的内容将被保留，并且仅卸载卷。 这意味着可以使用数据预先填充glusterfs卷，并且可以在Pod之间“切换”该数据。GlusterFS可以由多个编写器同时挂载。</p><p>注意：必须先运行自己的GlusterFS挂载，然后才能使用它。</p><p>有关更多详细信息，请参阅<a href="https://github.com/kubernetes/examples/tree/master/volumes/glusterfs" target="_blank" rel="noopener">GlusterFS示例</a>。</p><h3 id="hostpath"><a class="header-anchor" href="#hostpath"></a>hostPath</h3><p>hostPath卷将文件或目录从主机节点的文件系统挂载到Pod中。这不是大多数Pod需要的东西，但它为某些应用程序提供了强大的用途。</p><p>例如，hostPath的一些用途是：</p><ul><li>运行需要访问Docker内部的Container; 使用/var/lib/docker的hostPath</li><li>在容器中运行cAdvisor; 使用/sys的hostPath</li><li>允许Pod指定在Pod运行之前是否应该存在给定的hostPath，是否应该创建它以及它应该存在的内容</li></ul><p>除了必需的path属性之外，用户还可以选择为hostPath卷指定类型。</p><p>字段类型支持的值为：</p><table><thead><tr><th style="text-align:left">Value</th><th style="text-align:left">Behavior</th></tr></thead><tbody><tr><td style="text-align:left"></td><td style="text-align:left">Empty string (default) is for backward compatibility, which means that no checks will be performed before mounting the hostPath volume.</td></tr><tr><td style="text-align:left">DirectoryOrCreate</td><td style="text-align:left">If nothing exists at the given path, an empty directory will be created there as needed with permission set to 0755, having the same group and ownership with Kubelet.</td></tr><tr><td style="text-align:left">Directory</td><td style="text-align:left">A directory must exist at the given path</td></tr><tr><td style="text-align:left">FileOrCreate</td><td style="text-align:left">If nothing exists at the given path, an empty file will be created there as needed with permission set to 0644, having the same group and ownership with Kubelet.</td></tr><tr><td style="text-align:left">File</td><td style="text-align:left">A file must exist at the given path</td></tr><tr><td style="text-align:left">Socket</td><td style="text-align:left">A UNIX socket must exist at the given path</td></tr><tr><td style="text-align:left">CharDevice</td><td style="text-align:left">A character device must exist at the given path</td></tr><tr><td style="text-align:left">BlockDevice</td><td style="text-align:left">A block device must exist at the given path</td></tr></tbody></table><p>请注意何时使用此类型的卷，因为：</p><ul><li>由于节点上的文件不同，具有相同配置的Pod（例如从podTemplate创建）在不同节点上的行为可能会有所不同</li><li>当Kubernetes按计划添加资源调度时，它将无法考虑hostPath使用的资源</li><li>在底层主机上创建的文件或目录只能由root写入。需要以特权Container中的root身份运行你的进程，或者修改主机上的文件权限以便能够写入hostPath卷</li></ul><p>示例Pod：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">test-pd</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">  - image:</span> <span class="string">k8s.gcr.io/test-webserver</span></span><br><span class="line"><span class="attr">    name:</span> <span class="string">test-container</span></span><br><span class="line"><span class="attr">    volumeMounts:</span></span><br><span class="line"><span class="attr">    - mountPath:</span> <span class="string">/test-pd</span></span><br><span class="line"><span class="attr">      name:</span> <span class="string">test-volume</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">test-volume</span></span><br><span class="line"><span class="attr">    hostPath:</span></span><br><span class="line">      <span class="comment"># directory location on host</span></span><br><span class="line"><span class="attr">      path:</span> <span class="string">/data</span></span><br><span class="line">      <span class="comment"># this field is optional</span></span><br><span class="line"><span class="attr">      type:</span> <span class="string">Directory</span></span><br></pre></td></tr></table></figure><h3 id="iscsi"><a class="header-anchor" href="#iscsi"></a>iscsi</h3><p>iscsi卷允许将现有iSCSI（SCSI over IP）卷挂载到Pod中。 与删除Pod时删除的emptyDir不同，iscsi卷的内容将被保留，并且仅卸载卷。这意味着可以使用数据预先填充iscsi卷，并且可以在Pod之间“切换”该数据。</p><p>注意：必须先使用创建的卷运行自己的iSCSI服务器，然后才能使用它。</p><p>iSCSI的一个特性是它可以同时由多个消费者以只读方式挂载。这意味着你可以使用数据集预填充卷，然后根据需要从多个Pod中并行提供。 遗憾的是，iSCSI卷只能由单个用户以读写模式挂载：不允许同时写入。</p><p>有关更多详细信息，请参阅<a href="https://github.com/kubernetes/examples/tree/master/volumes/iscsi" target="_blank" rel="noopener">iSCSI示例</a>。</p><h3 id="local"><a class="header-anchor" href="#local"></a>local</h3><p>本地卷表示已挂载的本地存储设备，例如磁盘，分区或目录。</p><p>本地卷只能用作静态创建的PersistentVolume（持久卷）。尚不支持动态配置。</p><p>与hostPath卷相比，可以以持久且可移植的方式使用本地卷，而无需手动将Pod调度到节点，因为系统通过查看PersistentVolume上的节点关联性来了解卷的节点约束。但是，本地卷仍受基础节点可用性的限制，并不适用于所有应用程序。 如果节点变得不健康，则本地卷也将变得不可访问，并且使用它的Pod将无法运行。使用本地卷的应用程序必须能够容忍这种降低的可用性以及潜在的数据丢失，具体取决于底层磁盘的持久性特征。</p><p>以下是使用本地卷和nodeAffinity的PersistentVolume规范的示例：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">PersistentVolume</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">example-pv</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  capacity:</span></span><br><span class="line"><span class="attr">    storage:</span> <span class="number">100</span><span class="string">Gi</span></span><br><span class="line">  <span class="comment"># volumeMode field requires BlockVolume Alpha feature gate to be enabled.</span></span><br><span class="line"><span class="attr">  volumeMode:</span> <span class="string">Filesystem</span></span><br><span class="line"><span class="attr">  accessModes:</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">ReadWriteOnce</span></span><br><span class="line"><span class="attr">  persistentVolumeReclaimPolicy:</span> <span class="string">Delete</span></span><br><span class="line"><span class="attr">  storageClassName:</span> <span class="string">local-storage</span></span><br><span class="line"><span class="attr">  local:</span></span><br><span class="line"><span class="attr">    path:</span> <span class="string">/mnt/disks/ssd1</span></span><br><span class="line"><span class="attr">  nodeAffinity:</span></span><br><span class="line"><span class="attr">    required:</span></span><br><span class="line"><span class="attr">      nodeSelectorTerms:</span></span><br><span class="line"><span class="attr">      - matchExpressions:</span></span><br><span class="line"><span class="attr">        - key:</span> <span class="string">kubernetes.io/hostname</span></span><br><span class="line"><span class="attr">          operator:</span> <span class="string">In</span></span><br><span class="line"><span class="attr">          values:</span></span><br><span class="line"><span class="bullet">          -</span> <span class="string">example-node</span></span><br></pre></td></tr></table></figure><p>使用本地卷时需要配置PersistentVolume的<code>nodeAffinity</code>。 它使Kubernetes调度程序能够使用本地卷正确地将Pod调度到正确的节点。</p><p>PersistentVolume的<code>volumeMode</code>现在可以设置为“Block”（而不是默认值“Filesystem”），以将本地卷公开为原始块设备。volumeMode字段需要启用BlockVolume的Alpha功能。</p><p>使用本地卷时，建议创建一个将<code>volumeBindingMode</code>设置为WaitForFirstConsumer的StorageClass。延迟卷绑定可确保PersistentVolumeClaim绑定决策也将使用Pod可能具有的任何其他节点约束进行评估，例如节点资源要求，节点选择器，Pod关联和Pod反关联。</p><p>可以单独运行外部静态配置程序，以改进对本地卷生命周期的管理。请注意，此配置程序尚不支持动态配置。有关如何运行外部本地配置程序的示例，请参阅<a href="https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner" target="_blank" rel="noopener">本地卷配置程序用户指南</a>。</p><p>注意：如果外部静态配置器未用于管理卷生命周期，则本地PersistentVolume需要用户手动清理和删除。</p><h3 id="nfs"><a class="header-anchor" href="#nfs"></a>NFS</h3><p>nfs卷允许将现有NFS（网络文件系统）共享挂载到Pod中。与删除Pod时删除的emptyDir不同，nfs仅卸载卷，卷的内容将被保留。这意味着可以使用数据预先填充NFS卷，并且可以在Pod之间“切换”该数据。NFS可以由多个编写器同时挂载。</p><p>注意：必须先使用已导出的共享运行自己的NFS服务器，然后才能使用它。</p><p>用法示例请<a href="https://github.com/kubernetes/examples/tree/master/staging/volumes/nfs" target="_blank" rel="noopener">查看</a></p><h3 id="persistentvolumeclaim"><a class="header-anchor" href="#persistentvolumeclaim"></a>persistentVolumeClaim</h3><p>persistentVolumeClaim卷（持久卷声明）用于将PersistentVolume挂载到Pod中。PersistentVolumes是用户在不知道特定云环境的详细信息的情况下“声明”持久存储（例如GCE PersistentDisk或iSCSI卷）的一种方式。</p><p>有关更多详细信息，请参阅<a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/" target="_blank" rel="noopener">PersistentVolumes示例</a>。</p><h3 id="projected"><a class="header-anchor" href="#projected"></a>projected</h3><p>projected卷将几个现有卷源映射到同一目录中。</p><p>目前，可以映射以下类型的卷源：</p><ul><li>secret</li><li>downwardAPI</li><li>configMap</li><li>serviceAccountToken</li></ul><p>所有源都需要与Pod在同一名称空间中。serviceAccountToken的是Kubernetes 1.11中引入的功能，并在1.12中提升为Beta。要在1.11上启用此功能，需要将TokenRequestProjection功能门显式设置为True。</p><p>示例Pod包含密钥，downwardAPI和configmap：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">volume-test</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">container-test</span></span><br><span class="line"><span class="attr">    image:</span> <span class="string">busybox</span></span><br><span class="line"><span class="attr">    volumeMounts:</span></span><br><span class="line"><span class="attr">    - name:</span> <span class="string">all-in-one</span></span><br><span class="line"><span class="attr">      mountPath:</span> <span class="string">"/projected-volume"</span></span><br><span class="line"><span class="attr">      readOnly:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">all-in-one</span></span><br><span class="line"><span class="attr">    projected:</span></span><br><span class="line"><span class="attr">      sources:</span></span><br><span class="line"><span class="attr">      - secret:</span></span><br><span class="line"><span class="attr">          name:</span> <span class="string">mysecret</span></span><br><span class="line"><span class="attr">          items:</span></span><br><span class="line"><span class="attr">            - key:</span> <span class="string">username</span></span><br><span class="line"><span class="attr">              path:</span> <span class="string">my-group/my-username</span></span><br><span class="line"><span class="attr">      - downwardAPI:</span></span><br><span class="line"><span class="attr">          items:</span></span><br><span class="line"><span class="attr">            - path:</span> <span class="string">"labels"</span></span><br><span class="line"><span class="attr">              fieldRef:</span></span><br><span class="line"><span class="attr">                fieldPath:</span> <span class="string">metadata.labels</span></span><br><span class="line"><span class="attr">            - path:</span> <span class="string">"cpu_limit"</span></span><br><span class="line"><span class="attr">              resourceFieldRef:</span></span><br><span class="line"><span class="attr">                containerName:</span> <span class="string">container-test</span></span><br><span class="line"><span class="attr">                resource:</span> <span class="string">limits.cpu</span></span><br><span class="line"><span class="attr">      - configMap:</span></span><br><span class="line"><span class="attr">          name:</span> <span class="string">myconfigmap</span></span><br><span class="line"><span class="attr">          items:</span></span><br><span class="line"><span class="attr">            - key:</span> <span class="string">config</span></span><br><span class="line"><span class="attr">              path:</span> <span class="string">my-group/my-config</span></span><br></pre></td></tr></table></figure><p>以下示例为具有多个secret的示例Pod，其中设置了非默认权限模式：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">volume-test</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">container-test</span></span><br><span class="line"><span class="attr">    image:</span> <span class="string">busybox</span></span><br><span class="line"><span class="attr">    volumeMounts:</span></span><br><span class="line"><span class="attr">    - name:</span> <span class="string">all-in-one</span></span><br><span class="line"><span class="attr">      mountPath:</span> <span class="string">"/projected-volume"</span></span><br><span class="line"><span class="attr">      readOnly:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">all-in-one</span></span><br><span class="line"><span class="attr">    projected:</span></span><br><span class="line"><span class="attr">      sources:</span></span><br><span class="line"><span class="attr">      - secret:</span></span><br><span class="line"><span class="attr">          name:</span> <span class="string">mysecret</span></span><br><span class="line"><span class="attr">          items:</span></span><br><span class="line"><span class="attr">            - key:</span> <span class="string">username</span></span><br><span class="line"><span class="attr">              path:</span> <span class="string">my-group/my-username</span></span><br><span class="line"><span class="attr">      - secret:</span></span><br><span class="line"><span class="attr">          name:</span> <span class="string">mysecret2</span></span><br><span class="line"><span class="attr">          items:</span></span><br><span class="line"><span class="attr">            - key:</span> <span class="string">password</span></span><br><span class="line"><span class="attr">              path:</span> <span class="string">my-group/my-password</span></span><br><span class="line"><span class="attr">              mode:</span> <span class="number">511</span></span><br></pre></td></tr></table></figure><p>每个projected卷源都列在源的规范中。参数几乎相同，但有两个例外：</p><ul><li>对于secret，secretName字段已更改为name以与ConfigMap命名一致。</li><li>defaultMode只能在预计级别指定，而不能在每个卷源中指定。但是，如上所示，可以为每个单独的卷映射明确设置mode模式。</li></ul><p>启用TokenRequestProjection功能后，可以将当前service account的令牌注入指定路径的Pod。 以下是一个例子：</p><figure class="highlight yml"><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></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">sa-token-test</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">container-test</span></span><br><span class="line"><span class="attr">    image:</span> <span class="string">busybox</span></span><br><span class="line"><span class="attr">    volumeMounts:</span></span><br><span class="line"><span class="attr">    - name:</span> <span class="string">token-vol</span></span><br><span class="line"><span class="attr">      mountPath:</span> <span class="string">"/service-account"</span></span><br><span class="line"><span class="attr">      readOnly:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">token-vol</span></span><br><span class="line"><span class="attr">    projected:</span></span><br><span class="line"><span class="attr">      sources:</span></span><br><span class="line"><span class="attr">      - serviceAccountToken:</span></span><br><span class="line"><span class="attr">          audience:</span> <span class="string">api</span></span><br><span class="line"><span class="attr">          expirationSeconds:</span> <span class="number">3600</span></span><br><span class="line"><span class="attr">          path:</span> <span class="string">token</span></span><br></pre></td></tr></table></figure><p>示例Pod具有包含注入的服务帐户令牌的projected卷。 例如，Pod容器可以使用此标记来访问Kubernetes API服务器。 受众群体字段包含令牌的目标受众。令牌的接收者必须使用令牌的受众中指定的标识符来标识自己，否则应拒绝该令牌。此字段是可选字段，默认为API服务器的标识符。</p><p>expirationSeconds是服务帐户令牌的预期有效期。默认为1小时，且必须至少为10分钟（600秒）。管理员还可以通过为API服务器指定–service-account-max-token-expiration选项来限制其最大值。 path字段指定投影体积的挂载点的相对路径。</p><p>同样，projected卷也不支持对shubPath的更新。</p><p>###　portworxVolume</p><p>portworxVolume是一个弹性块存储层，与Kubernetes运行超融合。Portworx指纹存储在服务器中，基于功能层，并聚合多个服务器之间的容量。 Portworx在虚拟机或裸机Linux节点上运行in-guest。</p><p>portworxVolume可以通过Kubernetes动态创建，也可以在Kubernetes Pod中预先配置和引用。以下是引用预先配置的PortworxVolume的Pod示例：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">test-portworx-volume-pod</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">  - image:</span> <span class="string">k8s.gcr.io/test-webserver</span></span><br><span class="line"><span class="attr">    name:</span> <span class="string">test-container</span></span><br><span class="line"><span class="attr">    volumeMounts:</span></span><br><span class="line"><span class="attr">    - mountPath:</span> <span class="string">/mnt</span></span><br><span class="line"><span class="attr">      name:</span> <span class="string">pxvol</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">pxvol</span></span><br><span class="line">    <span class="comment"># This Portworx volume must already exist.</span></span><br><span class="line"><span class="attr">    portworxVolume:</span></span><br><span class="line"><span class="attr">      volumeID:</span> <span class="string">"pxvol"</span></span><br><span class="line"><span class="attr">      fsType:</span> <span class="string">"&lt;fs-type&gt;"</span></span><br></pre></td></tr></table></figure><p>更多细节<a href="https://github.com/kubernetes/examples/tree/master/staging/volumes/portworx/README.md" target="_blank" rel="noopener">参考</a></p><h3 id="quobyte"><a class="header-anchor" href="#quobyte"></a>quobyte</h3><p>一个quobyte卷允许将现有的Quobyte卷挂载到Pod中。</p><p>注意：必须先使用创建的卷运行自己的Quobyte设置，然后才能使用它。</p><p>Quobyte支持容器存储接口。CSI是推荐在Kubernetes中使用Quobyte卷的插件。Quobyte的<a href="https://github.com/quobyte/quobyte-csi#quobyte-csi" target="_blank" rel="noopener">GitHub项目</a>提供了使用CSI部署Quobyte的说明以及示例。</p><h3 id="rbd"><a class="header-anchor" href="#rbd"></a>rbd</h3><p>rbd卷允许将Rados Block Device卷挂载到Pod中。与删除Pod时删除的emptyDir不同，rbd卷的内容将被保留，并且仅卸载卷。这意味着RBD卷可以预先填充数据，并且该数据可以在Pod之间“切换”。</p><p>注意：在使用RBD之前，必须先运行自己的Ceph挂载。</p><p>RBD的一个特点是它可以同时由多个消费者以只读方式挂载。这意味着您可以使用数据集预填充卷，然后根据需要从多个Pod中并行提供。不幸的是，RBD卷只能由一个消费者以读写模式挂载 - 不允许同时写入。</p><p>有关更多详细信息，请参阅<a href="https://github.com/kubernetes/examples/tree/master/volumes/rbd" target="_blank" rel="noopener">RBD示例</a>。</p><h3 id="scaleio"><a class="header-anchor" href="#scaleio"></a>scaleIO</h3><p>ScaleIO是一个基于软件的存储平台，可以使用现有硬件来创建可伸缩共享块网络存储的集群。scaleIO卷插件允许已部署的Pod访问现有的ScaleIO卷（或者可以为持久卷声明动态配置新卷，请参阅ScaleIO持久卷）。</p><p>注意：必须先挂载现有的ScaleIO群集，并在创建卷之前运行它们，然后才能使用它们。</p><p>以下是使用ScaleIO的Pod配置示例：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">pod-0</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">  - image:</span> <span class="string">k8s.gcr.io/test-webserver</span></span><br><span class="line"><span class="attr">    name:</span> <span class="string">pod-0</span></span><br><span class="line"><span class="attr">    volumeMounts:</span></span><br><span class="line"><span class="attr">    - mountPath:</span> <span class="string">/test-pd</span></span><br><span class="line"><span class="attr">      name:</span> <span class="string">vol-0</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">vol-0</span></span><br><span class="line"><span class="attr">    scaleIO:</span></span><br><span class="line"><span class="attr">      gateway:</span> <span class="attr">https://localhost:443/api</span></span><br><span class="line"><span class="attr">      system:</span> <span class="string">scaleio</span></span><br><span class="line"><span class="attr">      protectionDomain:</span> <span class="string">sd0</span></span><br><span class="line"><span class="attr">      storagePool:</span> <span class="string">sp1</span></span><br><span class="line"><span class="attr">      volumeName:</span> <span class="string">vol-0</span></span><br><span class="line"><span class="attr">      secretRef:</span></span><br><span class="line"><span class="attr">        name:</span> <span class="string">sio-secret</span></span><br><span class="line"><span class="attr">      fsType:</span> <span class="string">xfs</span></span><br></pre></td></tr></table></figure><p>有关详细信息，请参阅<a href="https://github.com/kubernetes/examples/tree/master/staging/volumes/scaleio" target="_blank" rel="noopener">ScaleIO示例</a>。</p><h3 id="secret"><a class="header-anchor" href="#secret"></a>secret</h3><p>secret卷用于将敏感信息（如密码）传递给Pod。 可以将密钥存储在Kubernetes API中，并将其作为文件挂载以供Pod使用，而无需直接耦合到Kubernetes。secret卷由tmpfs（RAM支持的文件系统）支持，因此它们永远不会写入非易失性存储。</p><p>注意：您必须先在Kubernetes API中创建一个secret，然后才能使用它。且使用Secret作为子路径卷装入的Container将不会收到Secret更新。</p><p><a href="https://kubernetes.io/docs/user-guide/secrets" target="_blank" rel="noopener">这里</a>将更详细地描述secret。</p><h3 id="storageos"><a class="header-anchor" href="#storageos"></a>storageOS</h3><p>storageos卷允许将现有StorageOS卷挂载到Pod中。</p><p>StorageOS在Kubernetes环境中作为Container运行，从而可以从Kubernetes集群中的任何节点访问本地或附加存储。可以复制数据以防止节点故障。 精简配置和压缩可以提高利用率并降低成本。</p><p>StorageOS的核心是为容器提供块存储，可通过文件系统访问。</p><p>StorageOS Container需要64位Linux，并且没有其他依赖项。 提供免费的开发人员许可。</p><p>注意：必须在要访问StorageOS卷的每个节点上运行StorageOS Container，或者为池提供存储容量。有关挂载说明，请参阅<a href="https://docs.storageos.com/" target="_blank" rel="noopener">StorageOS文档</a>。</p><h3 id="vspherevolume"><a class="header-anchor" href="#vspherevolume"></a>vsphereVolume</h3><p>先决条件：已配置vSphere Cloud Provider的Kubernetes。有关cloudprovider配置，请参阅<a href="https://vmware.github.io/vsphere-storage-for-kubernetes/documentation/" target="_blank" rel="noopener">vSphere入门指南</a>。</p><p>vsphereVolume用于将vSphere VMDK卷装入Pod。在卸载卷时，将保留卷的内容。它支持VMFS和VSAN数据存储。</p><p>注意：在使用Pod之前，必须使用以下方法之一创建VMDK。</p><p>使用示例：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">test-vmdk</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">  - image:</span> <span class="string">k8s.gcr.io/test-webserver</span></span><br><span class="line"><span class="attr">    name:</span> <span class="string">test-container</span></span><br><span class="line"><span class="attr">    volumeMounts:</span></span><br><span class="line"><span class="attr">    - mountPath:</span> <span class="string">/test-vmdk</span></span><br><span class="line"><span class="attr">      name:</span> <span class="string">test-volume</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">test-volume</span></span><br><span class="line">    <span class="comment"># This VMDK volume must already exist.</span></span><br><span class="line"><span class="attr">    vsphereVolume:</span></span><br><span class="line"><span class="attr">      volumePath:</span> <span class="string">"[DatastoreName] volumes/myDisk"</span></span><br><span class="line"><span class="attr">      fsType:</span> <span class="string">ext4</span></span><br></pre></td></tr></table></figure><h1>使用subPath</h1><p>有时，在单个Pod中共享一个卷用于多个用途很有用。volumeMounts.subPath属性可用于指定引用卷内的子路径而不是其根。</p><p>下面是使用单个共享卷的Pod与LAMP堆栈（Linux Apache Mysql PHP）的示例。HTML内容映射到其html文件夹，数据库将存储在其mysql文件夹中：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">my-lamp-site</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">    containers:</span></span><br><span class="line"><span class="attr">    - name:</span> <span class="string">mysql</span></span><br><span class="line"><span class="attr">      image:</span> <span class="string">mysql</span></span><br><span class="line"><span class="attr">      env:</span></span><br><span class="line"><span class="attr">      - name:</span> <span class="string">MYSQL_ROOT_PASSWORD</span></span><br><span class="line"><span class="attr">        value:</span> <span class="string">"rootpasswd"</span></span><br><span class="line"><span class="attr">      volumeMounts:</span></span><br><span class="line"><span class="attr">      - mountPath:</span> <span class="string">/var/lib/mysql</span></span><br><span class="line"><span class="attr">        name:</span> <span class="string">site-data</span></span><br><span class="line"><span class="attr">        subPath:</span> <span class="string">mysql</span></span><br><span class="line"><span class="attr">    - name:</span> <span class="string">php</span></span><br><span class="line"><span class="attr">      image:</span> <span class="attr">php:7.0-apache</span></span><br><span class="line"><span class="attr">      volumeMounts:</span></span><br><span class="line"><span class="attr">      - mountPath:</span> <span class="string">/var/www/html</span></span><br><span class="line"><span class="attr">        name:</span> <span class="string">site-data</span></span><br><span class="line"><span class="attr">        subPath:</span> <span class="string">html</span></span><br><span class="line"><span class="attr">    volumes:</span></span><br><span class="line"><span class="attr">    - name:</span> <span class="string">site-data</span></span><br><span class="line"><span class="attr">      persistentVolumeClaim:</span></span><br><span class="line"><span class="attr">        claimName:</span> <span class="string">my-lamp-site-data</span></span><br></pre></td></tr></table></figure><h3 id="使用带有扩展环境变量的subpath"><a class="header-anchor" href="#使用带有扩展环境变量的subpath"></a>使用带有扩展环境变量的subPath</h3><p>API版本：Kubernetes v1.15 beta</p><p>使用subPathExpr字段从Downward API环境变量构造subPath目录名。 在使用此功能之前，必须启用VolumeSubpathEnvExpansion功能。subPath和subPathExpr属性是互斥的。</p><p>在如下示例中，Pod使用subPathExpr使用Downward API中的pod名称在hostPath卷/var/log/pods中创建目录pod1。 主机目录/var/log/pods/pod1挂载在容器中的/logs中。</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">pod1</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  containers:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">container1</span></span><br><span class="line"><span class="attr">    env:</span></span><br><span class="line"><span class="attr">    - name:</span> <span class="string">POD_NAME</span></span><br><span class="line"><span class="attr">      valueFrom:</span></span><br><span class="line"><span class="attr">        fieldRef:</span></span><br><span class="line"><span class="attr">          apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">          fieldPath:</span> <span class="string">metadata.name</span></span><br><span class="line"><span class="attr">    image:</span> <span class="string">busybox</span></span><br><span class="line"><span class="attr">    command:</span> <span class="string">[</span> <span class="string">"sh"</span><span class="string">,</span> <span class="string">"-c"</span><span class="string">,</span> <span class="string">"while [ true ]; do echo 'Hello'; sleep 10; done | tee -a /logs/hello.txt"</span> <span class="string">]</span></span><br><span class="line"><span class="attr">    volumeMounts:</span></span><br><span class="line"><span class="attr">    - name:</span> <span class="string">workdir1</span></span><br><span class="line"><span class="attr">      mountPath:</span> <span class="string">/logs</span></span><br><span class="line"><span class="attr">      subPathExpr:</span> <span class="string">$(POD_NAME)</span></span><br><span class="line"><span class="attr">  restartPolicy:</span> <span class="string">Never</span></span><br><span class="line"><span class="attr">  volumes:</span></span><br><span class="line"><span class="attr">  - name:</span> <span class="string">workdir1</span></span><br><span class="line"><span class="attr">    hostPath:</span></span><br><span class="line"><span class="attr">      path:</span> <span class="string">/var/log/pods</span></span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Container中的磁盘文件（生命周期）是短暂的，这在容器中运行时会给部分特殊的应用程序带来一些问题。首先，当容器崩溃时，kubelet在重新启动它，数据文件会丢失（Container会以干净的状态启动）。其次，在Pod中运行多个Container时，通常需要在这些容器之
      
    
    </summary>
    
      <category term="Kubernetes教程" scheme="http://www.whyvv.top/categories/Kubernetes%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Kubernetes" scheme="http://www.whyvv.top/tags/Kubernetes/"/>
    
      <category term="K8s" scheme="http://www.whyvv.top/tags/K8s/"/>
    
  </entry>
  
  <entry>
    <title>Roy学Kubernetes(19)：网络策略</title>
    <link href="http://www.whyvv.top/k8s19.html"/>
    <id>http://www.whyvv.top/k8s19.html</id>
    <published>2019-08-30T01:30:00.000Z</published>
    <updated>2019-08-30T03:06:07.226Z</updated>
    
    <content type="html"><![CDATA[<p>网络策略<code>NetworkPolicy</code>是允许pod组彼此之间以及和其他网络Endpoint端点通信的规则。<code>NetworkPolicy</code>资源使用标签来选择Pods并定义规则，这些规则指定允许所选Pods的流量请求。</p><h3 id="前提条件"><a class="header-anchor" href="#前提条件"></a>前提条件</h3><p>网络策略由网络插件实现，因此你必须使用支持<code>NetworkPolicy</code>的网络解决方案，例如calico就支持。</p><h3 id="隔离和非隔离的pods"><a class="header-anchor" href="#隔离和非隔离的pods"></a>隔离和非隔离的Pods</h3><p>默认情况下，pod是非隔离的; 他们接受任何来源的流量。通过使用选择它们的NetworkPolicy，Pod会变成隔离状态。一旦Namespace中有任何NetworkPolicy选择了指定的pod，该pod将拒绝在NetworkPolicy规则中任何不被允许的连接。（Namespace中未被任何NetworkPolicy选中的其他pod将继续接受所有流量。）</p><h3 id="networkpolicy"><a class="header-anchor" href="#networkpolicy"></a>NetworkPolicy</h3><p>NetworkPolicy示例：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">NetworkPolicy</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">test-network-policy</span></span><br><span class="line"><span class="attr">  namespace:</span> <span class="string">default</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  podSelector:</span></span><br><span class="line"><span class="attr">    matchLabels:</span></span><br><span class="line"><span class="attr">      role:</span> <span class="string">db</span></span><br><span class="line"><span class="attr">  policyTypes:</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">Ingress</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">Egress</span></span><br><span class="line"><span class="attr">  ingress:</span></span><br><span class="line"><span class="attr">  - from:</span></span><br><span class="line"><span class="attr">    - ipBlock:</span></span><br><span class="line"><span class="attr">        cidr:</span> <span class="number">172.17</span><span class="number">.0</span><span class="number">.0</span><span class="string">/16</span></span><br><span class="line"><span class="attr">        except:</span></span><br><span class="line"><span class="bullet">        -</span> <span class="number">172.17</span><span class="number">.1</span><span class="number">.0</span><span class="string">/24</span></span><br><span class="line"><span class="attr">    - namespaceSelector:</span></span><br><span class="line"><span class="attr">        matchLabels:</span></span><br><span class="line"><span class="attr">          project:</span> <span class="string">myproject</span></span><br><span class="line"><span class="attr">    - podSelector:</span></span><br><span class="line"><span class="attr">        matchLabels:</span></span><br><span class="line"><span class="attr">          role:</span> <span class="string">frontend</span></span><br><span class="line"><span class="attr">    ports:</span></span><br><span class="line"><span class="attr">    - protocol:</span> <span class="string">TCP</span></span><br><span class="line"><span class="attr">      port:</span> <span class="number">6379</span></span><br><span class="line"><span class="attr">  egress:</span></span><br><span class="line"><span class="attr">  - to:</span></span><br><span class="line"><span class="attr">    - ipBlock:</span></span><br><span class="line"><span class="attr">        cidr:</span> <span class="number">10.0</span><span class="number">.0</span><span class="number">.0</span><span class="string">/24</span></span><br><span class="line"><span class="attr">    ports:</span></span><br><span class="line"><span class="attr">    - protocol:</span> <span class="string">TCP</span></span><br><span class="line"><span class="attr">      port:</span> <span class="number">5978</span></span><br></pre></td></tr></table></figure><ul><li>必填字段：与所有其他Kubernetes配置一样，NetworkPolicy需要apiVersion，kind和metadata字段。有关使用配置文件的一般信息，请参阅<a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/object-management/" target="_blank" rel="noopener">使用ConfigMap配置容器和对象管理</a>。</li><li>spec：NetworkPolicy规范具有在给定Namespace中定义特定网络策略所需的所有信息。</li><li>podSelector：每个NetworkPolicy都包含一个podSelector，用于选择策略适用的pod分组。示例策略选择标签为“role=db”的pod。podSelector为空则会选择Namespace中的所有pod。</li><li>policyTypes：每个NetworkPolicy都包含一个policyTypes列表，其中可能包含Ingress，Egress或两者都有。policyTypes字段指示给定策略是否适用于所选Pod的Ingress或Egress流量。如果在NetworkPolicy上未指定policyTypes，除非指定了Egress，否则默认情况下将只设置Ingress流量。</li><li>ingress（入口）：每个NetworkPolicy可能包含Ingress规则白名单列表。每个规则允许匹配from和ports部分的流量。示例策略包含单个规则，该规则匹配单个端口上的流量，来自三个源中的一个，第一个通过ipBlock指定，第二个通过namespaceSelector，第三个通过podSelector。</li><li>egress（出口）：每个NetworkPolicy可以包括Egress规则白名单列表。每个规则允许匹配to和ports部分的流量。示例策略包含单个规则，该规则将单个端口上的流量与10.0.0.0/24中的任何目标进行匹配。</li></ul><p>那么，示例NetworkPolicy即表示：</p><ul><li><ol><li>在“default”命名空间中隔离“role=db”的pod的入口和出口请求流量</li></ol></li><li><ol start="2"><li>（入口规则）允许带有标签“role=db”的以下Pod连接到“default”命名空间中的所有pod的6379端口：</li></ol><ul><li>“default”命名空间中标签为“role=frontend”的任何pod，</li><li>标签带“project=myproject”的任何命名空间中的Pod</li><li>172.17.0.0-172.17.0.255和172.17.2.0-172.17.255.255范围内的IP地址（即172.17.0.0/16除172.17.1.0/24外的IP）</li></ul></li><li><ol start="3"><li>（出口规则）允许“default”命名空间中的任何Pod连接到标签带“role=db”且CIDR IP段为10.0.0.0/24的tcp5978端口</li></ol></li></ul><h3 id="出入口选择器行为"><a class="header-anchor" href="#出入口选择器行为"></a>出入口选择器行为</h3><p>通过<code>ingress from</code>或<code>egress to</code>可以指定四种选择器：</p><ul><li>podSelector：允许与NetworkPolicy同一命名空间中的指定Pod作为入口源或出口目的地。</li><li>namespaceSelector：允许所有特定命名空间的Pod作为入口源或出口目标的。</li><li>namespaceSelector和podSelector：指定namespaceSelector和podSelector的单个to/from条目选择特定命名空间中的特定Pod。policy示例：</li></ul><figure class="highlight yml"><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"><span class="string">...</span></span><br><span class="line"><span class="attr">ingress:</span></span><br><span class="line"><span class="attr">- from:</span></span><br><span class="line"><span class="attr">  - namespaceSelector:</span></span><br><span class="line"><span class="attr">      matchLabels:</span></span><br><span class="line"><span class="attr">        user:</span> <span class="string">alice</span></span><br><span class="line"><span class="attr">    podSelector:</span></span><br><span class="line"><span class="attr">      matchLabels:</span></span><br><span class="line"><span class="attr">        role:</span> <span class="string">client</span></span><br><span class="line"><span class="string">...</span></span><br></pre></td></tr></table></figure><p>上述示例包含1个from入口流量策略，允许来自命名空间本身带有标签为user=alice、且此命令空间中标签为role=client的Pod的所有连接（and关系）。但是如果二者是并列关系的policy：</p><figure class="highlight yml"><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"><span class="string">...</span></span><br><span class="line"><span class="attr">ingress:</span></span><br><span class="line"><span class="attr">- from:</span></span><br><span class="line"><span class="attr">  - namespaceSelector:</span></span><br><span class="line"><span class="attr">      matchLabels:</span></span><br><span class="line"><span class="attr">        user:</span> <span class="string">alice</span></span><br><span class="line"><span class="attr">  - podSelector:</span></span><br><span class="line"><span class="attr">      matchLabels:</span></span><br><span class="line"><span class="attr">        role:</span> <span class="string">client</span></span><br><span class="line"><span class="string">...</span></span><br></pre></td></tr></table></figure><p>上述示例相当于包含2个from入口流量策略，允许来自同一Namespace中的Pod带有标签role=client的连接，或来自任何命名空间中具有标签user=alice的任何Pod的连接（or关系）。</p><ul><li>ipBlock：选择特定的IP CIDR范围以允许作为入口源或出口目的地。这些应该是集群外部IP，因为Pod IP是短暂的和不可预测的。</li></ul><p>群集入口和出口机制通常需要重写数据包的源IP或目标IP。如果发生这种情况，则无法确定是在NetworkPolicy处理之前还是之后发生这种情况，并且对于网络插件，云提供商，服务实施等的不同组合，行为可能会有所不同。</p><p>在入口的情况下，这意味着在某些情况下，w你可能能够根据实际的原始源IP过滤传入的数据包，而在其他情况下，NetworkPolicy作用的“源IP”可能是LoadBalancer的IP或Pod的节点等，所以需要按实际需求配置。</p><p>对于出口，这意味着从pod到服务IP的连接被重写为集群外部IP可能会不受基于ipBlock的策略的约束。</p><h3 id="默认策略"><a class="header-anchor" href="#默认策略"></a>默认策略</h3><p>默认情况下，如果命名空间中不存在任何NetworkPolicy策略，则允许所有入口和出口流量进出该命名空间中的pod。以下示例为更改该命名空间中的默认策略。</p><p><strong>默认拒绝所有入口流量</strong></p><p>可以通过创建NetworkPolicy为命名空间创建“默认”隔离策略，该策略选择所有Pod且不允许任何入口流量到这些Pod。</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">NetworkPolicy</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">default-deny</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  podSelector:</span> <span class="string">&#123;&#125;</span></span><br><span class="line"><span class="attr">  policyTypes:</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">Ingress</span></span><br></pre></td></tr></table></figure><p>这可确保即使是未被任何其他NetworkPolicy选择的pod也仍将被隔离。此策略不会更改默认的出口隔离行为。</p><p><strong>默认允许所有入口流量</strong></p><p>如果要允许所有流量到命名空间中的所有Pod（即使添加了导致某些Pod被“隔离”的策略），你也可以创建一个明确允许该命名空间中所有流量的策略。</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">NetworkPolicy</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">allow-all</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  podSelector:</span> <span class="string">&#123;&#125;</span></span><br><span class="line"><span class="attr">  ingress:</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">&#123;&#125;</span></span><br><span class="line"><span class="attr">  policyTypes:</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">Ingress</span></span><br></pre></td></tr></table></figure><p><strong>默认拒绝所有出口流量</strong></p><p>可以通过创建NetworkPolicy来为命名空间创建“默认”出口隔离策略，该策略选择所有Pod且不允许来自这些Pod的任何出口流量。</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">NetworkPolicy</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">default-deny</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  podSelector:</span> <span class="string">&#123;&#125;</span></span><br><span class="line"><span class="attr">  policyTypes:</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">Egress</span></span><br></pre></td></tr></table></figure><p>这可确保即使是未被任何其他NetworkPolicy选择的pod也不会被允许出口流量。此策略不会更改默认的入口隔离行为。</p><p><strong>默认允许所有出口流量</strong></p><p>如果要允许来自命名空间中所有Pod的所有流量（即使添加了导致某些Pod被视为“隔离”的策略），你也可以创建一个明确允许该命名空间中所有出口流量的策略。</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">NetworkPolicy</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">allow-all</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  podSelector:</span> <span class="string">&#123;&#125;</span></span><br><span class="line"><span class="attr">  egress:</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">&#123;&#125;</span></span><br><span class="line"><span class="attr">  policyTypes:</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">Egress</span></span><br></pre></td></tr></table></figure><p><strong>默认拒绝所有入口和所有出口流量</strong></p><p>可以为命名空间创建“默认”策略，通过在该命名空间中创建以下NetworkPolicy来阻止所有入口和出口流量。</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">NetworkPolicy</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">default-deny</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  podSelector:</span> <span class="string">&#123;&#125;</span></span><br><span class="line"><span class="attr">  policyTypes:</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">Ingress</span></span><br><span class="line"><span class="bullet">  -</span> <span class="string">Egress</span></span><br></pre></td></tr></table></figure><p>这可确保即使是未被任何其他NetworkPolicy选择的pod也不会被允许入口或出口流量。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;网络策略&lt;code&gt;NetworkPolicy&lt;/code&gt;是允许pod组彼此之间以及和其他网络Endpoint端点通信的规则。&lt;code&gt;NetworkPolicy&lt;/code&gt;资源使用标签来选择Pods并定义规则，这些规则指定允许所选Pods的流量请求。&lt;/p&gt;
&lt;h3
      
    
    </summary>
    
      <category term="Kubernetes教程" scheme="http://www.whyvv.top/categories/Kubernetes%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Kubernetes" scheme="http://www.whyvv.top/tags/Kubernetes/"/>
    
      <category term="K8s" scheme="http://www.whyvv.top/tags/K8s/"/>
    
  </entry>
  
  <entry>
    <title>Roy学Kubernetes(18)：Ingress Controller</title>
    <link href="http://www.whyvv.top/k8s18.html"/>
    <id>http://www.whyvv.top/k8s18.html</id>
    <published>2019-08-27T01:30:00.000Z</published>
    <updated>2019-08-27T09:06:35.066Z</updated>
    
    <content type="html"><![CDATA[<p>在创建Ingress资源之前，k8s群集必须先运行Ingress Controller。</p><p>与作为kube-controller-manager二进制文件的一部分运行的其他类型的控制器（详见前面关于控制器的章节）不同，Ingress控制器不会自动与集群一起启动。 Ingress Controller有多种类型，在使用时请选择最适合你的Ingress Controller。GCE和nginx controller是kubernetes官方维护的Ingress Controller。</p><h1>各类Ingress Controller</h1><ul><li>Ambassador API Gateway是一个基于Envoy的Ingress Controller，具有Datawire的社区或商业支持。</li><li>AppsCode Inc.为最广泛使用的基于HAProxy的Ingress ControllerVoyager提供支持和维护。</li><li>Contour是由Heptio提供和支持的基于Envoy的Ingress Controller。</li><li>Citrix为其硬件（MPX），虚拟化（VPX）和免费容器化（CPX）ADC提供Ingress Controller，用于裸机和云部署。</li><li>F5 Networks为Kubernetes的F5 BIG-IP控制器提供支持和维护。</li><li>Gloo是一个基于Envoy的开源Ingress Controller，它提供API网关功能，并提供solo.io的企业支持。</li><li>HAProxy Technologies为Kubernetes的HAProxy Ingress控制器提供支持和维护。</li><li>基于Istio的Ingress Controller控制ingress流量。</li><li>Kong为Kungsnetes的Kong Ingress Controller提供社区或商业支持和维护。</li><li>NGINX，Inc。为Kubernetes的NGINX Ingress控制器提供支持和维护。</li><li>用于服务组合的Skipper HTTP路由器和反向代理，包括Kubernetes Ingress等用例，用作构建自定义代理的库</li><li>Traefik是一个功能齐全的Ingress Controller（Let’s Encrypt，secrets，http2，websocket），它还带有Containous的商业支持。</li></ul><h1>使用多个Ingress Controllers</h1><p>你可以在k8s群集中部署任意数量的Ingress Controller。 创建Ingress时，应使用适当的ingress.class描述每个Ingress，以指示在群集中存在多个Ingress Controller时应使用哪个Ingress Controller。（关于多Ingress Controllers的使用，后面我会专门写一个章节来做实际应用介绍）</p><p>如果您没有定义ingress.class类，则云提供商可能会使用默认的Ingress Controller。</p><p>理想情况下，所有Ingress Controller都应满足此规范，但各种Ingress Controller的运行方式略有不同。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;在创建Ingress资源之前，k8s群集必须先运行Ingress Controller。&lt;/p&gt;
&lt;p&gt;与作为kube-controller-manager二进制文件的一部分运行的其他类型的控制器（详见前面关于控制器的章节）不同，Ingress控制器不会自动与集群一起启动。
      
    
    </summary>
    
      <category term="Kubernetes教程" scheme="http://www.whyvv.top/categories/Kubernetes%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Kubernetes" scheme="http://www.whyvv.top/tags/Kubernetes/"/>
    
      <category term="K8s" scheme="http://www.whyvv.top/tags/K8s/"/>
    
  </entry>
  
  <entry>
    <title>Roy学Kubernetes(17)：Ingress</title>
    <link href="http://www.whyvv.top/k8s17.html"/>
    <id>http://www.whyvv.top/k8s17.html</id>
    <published>2019-08-26T01:30:00.000Z</published>
    <updated>2019-08-26T09:41:01.863Z</updated>
    
    <content type="html"><![CDATA[<p>Ingress是管理k8s群集中服务的外部访问（通常是HTTP/HTTPS访问请求）的API对象，它可以提供负载均衡和基于域名的虚拟主机服务（实现nginx的功能）。<br>在了解Ingress之前，我们需要先知道以下术语：</p><ul><li>Node：k8s集群工作节点</li><li>Cluster：k8s集群</li><li>Edge router：为你的集群强制执行防火墙策略的路由器，这可以是由云提供商或物理硬件管理的网关。</li><li>Cluster network：一组逻辑或物理链接的网络，根据Kubernetes网络模型实现集群内的通信。</li><li>Service：Kubernetes服务，使用标签选择器标识一组Pod。默认情况下服务具有仅在k8s集群网络内可路由的虚拟IP。</li></ul><h1>什么是ingress</h1><p>Ingress将集群外部的HTTP和HTTPS请求路由给集群中的Service服务，路由流量可以通过Ingress资源上定义的规则控制，结构如下：</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></pre></td><td class="code"><pre><span class="line"> internet</span><br><span class="line">     |</span><br><span class="line">[ Ingress ]</span><br><span class="line">--|-----|--</span><br><span class="line">[ Services ]</span><br></pre></td></tr></table></figure><p>可以通过Ingress配置为服务提供外部可访问的URL、负载均衡流量、SSL/TLS以及提供基于域名的虚拟主机。Ingress controllers控制器负责实现Ingress配置的功能，通常使用load balancer负载均衡器，同时Ingress也支持配置边缘路由器或其他前端来处理请求流量。</p><p>Ingress不会暴露任意端口或协议。 将HTTP和HTTPS以外的服务公开给Internet通常使用Service.Type = NodePort或Service.Type = LoadBalancer类型的服务。</p><p><strong>使用ingress的必要条件</strong></p><p>必须先创建<code>ingress controller</code>，仅创建Ingress资源无效。Ingress控制器有多种类型，例如常用的ingress-nginx。各种Ingress控制器的运行方式略有不同，请按规范要求配置运行。</p><h1>Ingress资源</h1><p>一个ingress资源（请求）示例如下：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1beta1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Ingress</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">test-ingress</span></span><br><span class="line"><span class="attr">  annotations:</span></span><br><span class="line">    <span class="string">nginx.ingress.kubernetes.io/rewrite-target:</span> <span class="string">/</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  rules:</span></span><br><span class="line"><span class="attr">  - http:</span></span><br><span class="line"><span class="attr">      paths:</span></span><br><span class="line"><span class="attr">      - path:</span> <span class="string">/testpath</span></span><br><span class="line"><span class="attr">        backend:</span></span><br><span class="line"><span class="attr">          serviceName:</span> <span class="string">test</span></span><br><span class="line"><span class="attr">          servicePort:</span> <span class="number">80</span></span><br></pre></td></tr></table></figure><p>与所有其他Kubernetes资源一样，Ingress需要apiVersion，kind和metadata字段。Ingress经常使用annotations注释来配置一些选项，具体取决于Ingress控制器类别，上述例子是重写目标路径的注释。不同的Ingress控制器支持不同的注释。详细配置请查看你选择的Ingress控制器的文档。</p><p>Ingress spec项具有配置负载均衡器或代理服务器所需的所有信息。最重要的是，它包含与所有传入请求匹配的规则列表。Ingress资源仅支持HTTP流量的规则。</p><h3 id="ingress规则"><a class="header-anchor" href="#ingress规则"></a>Ingress规则</h3><p>每个HTTP规则都包含以下信息：</p><ul><li>可选主机： 在上述示例中，未指定主机，因此该规则适用于通过指定的IP地址的所有入站HTTP流量。如果提供了主机（例如，<a href="http://foo.bar.com" target="_blank" rel="noopener">foo.bar.com</a>），则规则仅适用于该主机。</li><li>路径列表（例如，/testpath）：每个路径都有一个使用serviceName和servicePort定义的关联后端。在负载均衡器将流量定向到引用的服务之前，主机和路径都必须与传入请求的内容匹配。</li><li>后端为服务和端口名称的组合：向Ingress发出的与主机和规则路径匹配的HTTP（和HTTPS）请求将发送到列出的后端。</li></ul><p>默认后端通常在Ingress控制器中配置，以便为与spec规范中的路径不匹配的任何请求提供服务。</p><h3 id="默认后端"><a class="header-anchor" href="#默认后端"></a>默认后端</h3><p>没有规则的Ingress将所有流量发送到单个默认后端。 默认后端通常是Ingress控制器的配置选项，并且未在Ingress资源中指定。</p><p>如果没有任何主机或路径与Ingress对象中的HTTP请求匹配，则流量将路由到您的默认后端。</p><h1>Ingress类型</h1><h3 id="单服务ingress"><a class="header-anchor" href="#单服务ingress"></a>单服务ingress</h3><p>现有的Kubernetes概念允许公开单个服务，也可以通过指定没有规则的默认后端来使用Ingress执行此操作。</p><p>示例：ingress.yaml</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1beta1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Ingress</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">test-ingress</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  backend:</span></span><br><span class="line"><span class="attr">    serviceName:</span> <span class="string">testsvc</span></span><br><span class="line"><span class="attr">    servicePort:</span> <span class="number">80</span></span><br></pre></td></tr></table></figure><p>创建ingress</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">kubectl apply -f ingress.yaml</span><br><span class="line">kubectl get ingress test-ingress</span><br><span class="line">NAME           HOSTS     ADDRESS           PORTS     AGE</span><br><span class="line">test-ingress   *         107.178.254.228   80        59s</span><br></pre></td></tr></table></figure><p>其中107.178.254.228是Ingress控制器为满足此Ingress需求而分配的IP。（Ingress controllers和load balancers可能需要一两分钟来分配IP地址。在此之前，你经常会看到列为<pending>的地址）</pending></p><h3 id="多路由配置"><a class="header-anchor" href="#多路由配置"></a>多路由配置</h3><p>多路由配置根据请求的HTTP URI将流量从单个IP地址路由到多个服务。 Ingress允许你将负载均衡器的数量降至最低。例如，请求规划如下：</p><figure class="highlight shell"><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">foo.bar.com -&gt; 178.91.123.132 -&gt; / foo    service1:4200</span><br><span class="line">                                 / bar    service2:8080</span><br></pre></td></tr></table></figure><p>按上述请求配置的ingress如下：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1beta1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Ingress</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">simple-fanout-example</span></span><br><span class="line"><span class="attr">  annotations:</span></span><br><span class="line">    <span class="string">nginx.ingress.kubernetes.io/rewrite-target:</span> <span class="string">/</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  rules:</span></span><br><span class="line"><span class="attr">  - host:</span> <span class="string">foo.bar.com</span></span><br><span class="line"><span class="attr">    http:</span></span><br><span class="line"><span class="attr">      paths:</span></span><br><span class="line"><span class="attr">      - path:</span> <span class="string">/foo</span></span><br><span class="line"><span class="attr">        backend:</span></span><br><span class="line"><span class="attr">          serviceName:</span> <span class="string">service1</span></span><br><span class="line"><span class="attr">          servicePort:</span> <span class="number">4200</span></span><br><span class="line"><span class="attr">      - path:</span> <span class="string">/bar</span></span><br><span class="line"><span class="attr">        backend:</span></span><br><span class="line"><span class="attr">          serviceName:</span> <span class="string">service2</span></span><br><span class="line"><span class="attr">          servicePort:</span> <span class="number">8080</span></span><br></pre></td></tr></table></figure><p>创建后查看此ingress</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><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">kubectl describe ingress simple-fanout-example</span><br><span class="line">Name:             simple-fanout-example</span><br><span class="line">Namespace:        default</span><br><span class="line">Address:          178.91.123.132</span><br><span class="line">Default backend:  default-http-backend:80 (10.8.2.3:8080)</span><br><span class="line">Rules:</span><br><span class="line">  Host         Path  Backends</span><br><span class="line">  ----         ----  --------</span><br><span class="line">  foo.bar.com</span><br><span class="line">               /foo   service1:4200 (10.8.0.90:4200)</span><br><span class="line">               /bar   service2:8080 (10.8.0.91:8080)</span><br><span class="line">Annotations:</span><br><span class="line">  nginx.ingress.kubernetes.io/rewrite-target:  /</span><br><span class="line">Events:</span><br><span class="line">  Type     Reason  Age                From                     Message</span><br><span class="line">  ----     ------  ----               ----                     -------</span><br><span class="line">  Normal   ADD     22s                loadbalancer-controller  default/test</span><br></pre></td></tr></table></figure><p>只要服务（service1，service2）存在，Ingress控制器就会提供满足Ingress的负载均衡器。 创建完成后，你可以在地址字段中查看负载均衡器的地址。（注意：根据你使用的Ingress控制器类型，有此可能需要创建default-http-backend服务）</p><h3 id="基于名称的虚拟主机ingress"><a class="header-anchor" href="#基于名称的虚拟主机ingress"></a>基于名称的虚拟主机ingress</h3><p>基于名称的虚拟主机支持将HTTP流量路由到同一IP地址的多个主机名。</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></pre></td><td class="code"><pre><span class="line">foo.bar.com --|                 |-&gt; foo.bar.com service1:80</span><br><span class="line">              | 178.91.123.132  |</span><br><span class="line">bar.foo.com --|                 |-&gt; bar.foo.com service2:80</span><br></pre></td></tr></table></figure><p>以下Ingress告诉负载均衡器根据主机header来路由请求：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1beta1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Ingress</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">name-virtual-host-ingress</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  rules:</span></span><br><span class="line"><span class="attr">  - host:</span> <span class="string">foo.bar.com</span></span><br><span class="line"><span class="attr">    http:</span></span><br><span class="line"><span class="attr">      paths:</span></span><br><span class="line"><span class="attr">      - backend:</span></span><br><span class="line"><span class="attr">          serviceName:</span> <span class="string">service1</span></span><br><span class="line"><span class="attr">          servicePort:</span> <span class="number">80</span></span><br><span class="line"><span class="attr">  - host:</span> <span class="string">bar.foo.com</span></span><br><span class="line"><span class="attr">    http:</span></span><br><span class="line"><span class="attr">      paths:</span></span><br><span class="line"><span class="attr">      - backend:</span></span><br><span class="line"><span class="attr">          serviceName:</span> <span class="string">service2</span></span><br><span class="line"><span class="attr">          servicePort:</span> <span class="number">80</span></span><br></pre></td></tr></table></figure><p>如果你创建的ingress没有在规则中定义任何主机，则可以匹配任何到Ingress控制器的IP地址的Web流量（不需要匹配基于名称的虚拟主机）。</p><p>例如，以下Ingress资源会将<code>first.bar.com</code>请求的流量路由到service1，将<code>second.foo.com</code>路由到service2，以及没有在请求中定义的主机名的IP地址的任何流量（即，没有请求头存在）路由到服务3。</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1beta1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Ingress</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">name-virtual-host-ingress</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  rules:</span></span><br><span class="line"><span class="attr">  - host:</span> <span class="string">first.bar.com</span></span><br><span class="line"><span class="attr">    http:</span></span><br><span class="line"><span class="attr">      paths:</span></span><br><span class="line"><span class="attr">      - backend:</span></span><br><span class="line"><span class="attr">          serviceName:</span> <span class="string">service1</span></span><br><span class="line"><span class="attr">          servicePort:</span> <span class="number">80</span></span><br><span class="line"><span class="attr">  - host:</span> <span class="string">second.foo.com</span></span><br><span class="line"><span class="attr">    http:</span></span><br><span class="line"><span class="attr">      paths:</span></span><br><span class="line"><span class="attr">      - backend:</span></span><br><span class="line"><span class="attr">          serviceName:</span> <span class="string">service2</span></span><br><span class="line"><span class="attr">          servicePort:</span> <span class="number">80</span></span><br><span class="line"><span class="attr">  - http:</span></span><br><span class="line"><span class="attr">      paths:</span></span><br><span class="line"><span class="attr">      - backend:</span></span><br><span class="line"><span class="attr">          serviceName:</span> <span class="string">service3</span></span><br><span class="line"><span class="attr">          servicePort:</span> <span class="number">80</span></span><br></pre></td></tr></table></figure><h3 id="配置tls"><a class="header-anchor" href="#配置tls"></a>配置TLS</h3><p>可以通过指定包含TLS私钥和证书的Secret来保护Ingress。目前，Ingress仅支持单个TLS端口443，如果Ingress中的TLS配置部分指定了不同的主机，则它们将根据通过SNI TLS扩展指定的主机名在同一端口上进行多路复用（前提是Ingress控制器支持SNI）。TLS Secret必须包含名为tls.crt和tls.key的密钥，其中包含用于TLS的证书和私钥。例如：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Secret</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">testsecret-tls</span></span><br><span class="line"><span class="attr">  namespace:</span> <span class="string">default</span></span><br><span class="line"><span class="attr">data:</span></span><br><span class="line">  <span class="string">tls.crt:</span> <span class="string">base64</span> <span class="string">encoded</span> <span class="string">cert</span></span><br><span class="line">  <span class="string">tls.key:</span> <span class="string">base64</span> <span class="string">encoded</span> <span class="string">key</span></span><br><span class="line"><span class="attr">type:</span> <span class="string">kubernetes.io/tls</span></span><br></pre></td></tr></table></figure><p>在Ingress中引用此Secret告诉Ingress控制器使用TLS将客户端到负载均衡器的通道进行TLS加密通讯。当然了，前提你已经创建好了对应的密钥和证书。</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">networking.k8s.io/v1beta1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Ingress</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">tls-example-ingress</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  tls:</span></span><br><span class="line"><span class="attr">  - hosts:</span></span><br><span class="line"><span class="bullet">    -</span> <span class="string">sslexample.foo.com</span></span><br><span class="line"><span class="attr">    secretName:</span> <span class="string">testsecret-tls</span></span><br><span class="line"><span class="attr">  rules:</span></span><br><span class="line"><span class="attr">    - host:</span> <span class="string">sslexample.foo.com</span></span><br><span class="line"><span class="attr">      http:</span></span><br><span class="line"><span class="attr">        paths:</span></span><br><span class="line"><span class="attr">        - path:</span> <span class="string">/</span></span><br><span class="line"><span class="attr">          backend:</span></span><br><span class="line"><span class="attr">            serviceName:</span> <span class="string">service1</span></span><br><span class="line"><span class="attr">            servicePort:</span> <span class="number">80</span></span><br></pre></td></tr></table></figure><h1>更新ingress</h1><p>如要对现有的Ingress添加新host主机，可以通过编辑ingress资源来更新它：</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">kubectl edit ingress test</span><br></pre></td></tr></table></figure><p>修改如下内容：</p><figure class="highlight yml"><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"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  rules:</span></span><br><span class="line"><span class="attr">  - host:</span> <span class="string">foo.bar.com</span></span><br><span class="line"><span class="attr">    http:</span></span><br><span class="line"><span class="attr">      paths:</span></span><br><span class="line"><span class="attr">      - backend:</span></span><br><span class="line"><span class="attr">          serviceName:</span> <span class="string">service1</span></span><br><span class="line"><span class="attr">          servicePort:</span> <span class="number">80</span></span><br><span class="line"><span class="attr">        path:</span> <span class="string">/foo</span></span><br><span class="line"><span class="attr">  - host:</span> <span class="string">bar.baz.com</span></span><br><span class="line"><span class="attr">    http:</span></span><br><span class="line"><span class="attr">      paths:</span></span><br><span class="line"><span class="attr">      - backend:</span></span><br><span class="line"><span class="attr">          serviceName:</span> <span class="string">service2</span></span><br><span class="line"><span class="attr">          servicePort:</span> <span class="number">80</span></span><br><span class="line"><span class="attr">        path:</span> <span class="string">/foo</span></span><br><span class="line"><span class="string">..</span></span><br></pre></td></tr></table></figure><p>保存更改后，kubectl会更新API服务器中的资源，告知Ingress控制器重新配置负载均衡器。</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><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">kubectl describe ingress test</span><br><span class="line">Name:             test</span><br><span class="line">Namespace:        default</span><br><span class="line">Address:          178.91.123.132</span><br><span class="line">Default backend:  default-http-backend:80 (10.8.2.3:8080)</span><br><span class="line">Rules:</span><br><span class="line">  Host         Path  Backends</span><br><span class="line">  ----         ----  --------</span><br><span class="line">  foo.bar.com</span><br><span class="line">               /foo   service1:80 (10.8.0.90:80)</span><br><span class="line">  bar.baz.com</span><br><span class="line">               /foo   service2:80 (10.8.0.91:80)</span><br><span class="line">Annotations:</span><br><span class="line">  nginx.ingress.kubernetes.io/rewrite-target:  /</span><br><span class="line">Events:</span><br><span class="line">  Type     Reason  Age                From                     Message</span><br><span class="line">  ----     ------  ----               ----                     -------</span><br><span class="line">  Normal   ADD     45s                loadbalancer-controller  default/test</span><br></pre></td></tr></table></figure><p>你可以通过在修改后的Ingress YAML文件上执行kubectl replace -f来实现相同的结果。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Ingress是管理k8s群集中服务的外部访问（通常是HTTP/HTTPS访问请求）的API对象，它可以提供负载均衡和基于域名的虚拟主机服务（实现nginx的功能）。&lt;br&gt;
在了解Ingress之前，我们需要先知道以下术语：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Node：k8s集群
      
    
    </summary>
    
      <category term="Kubernetes教程" scheme="http://www.whyvv.top/categories/Kubernetes%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Kubernetes" scheme="http://www.whyvv.top/tags/Kubernetes/"/>
    
      <category term="K8s" scheme="http://www.whyvv.top/tags/K8s/"/>
    
  </entry>
  
  <entry>
    <title>Roy学Kubernetes(16)：应用程序连接Service</title>
    <link href="http://www.whyvv.top/k8s16.html"/>
    <id>http://www.whyvv.top/k8s16.html</id>
    <published>2019-08-13T01:30:00.000Z</published>
    <updated>2019-08-14T05:42:30.219Z</updated>
    
    <content type="html"><![CDATA[<p>本章我们将讨论kubernetes中连接到serivce容器的方法，首先我们来看它和docker容器网络工作模式的对比：</p><ul><li>Docker默认使用主机私有网络通信，因此同一主机的容器之间可以互通。为了实现不同主机之间的容器访问，必须通过绑定本机端口来将请求转发或代理到其他节点容器。这就意味着容器必须协调好它们使用的端口，或者必须动态分配使用主机端口。当项目有多个开发人员时，协调端口及网络安全方面需要消耗更多的时间和人力成本。</li><li>kubernetes通过创建私有Pod子网，为每个pod提供了唯一的集群私有IP地址，无论Pod在哪个节点，均可互通。</li></ul><p>下面我们来用演示如何配置访问kubernetes的Pod。</p><h3 id="将pod暴露给k8s集群"><a class="header-anchor" href="#将pod暴露给k8s集群"></a>将Pod暴露给k8s集群</h3><p>创建一个nginx的Deployment，配置<code>containerPort</code>端口，即可实现从k8s群集中的任何节点访问。</p><p>nginx.yml</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">apps/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Deployment</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">my-nginx</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  selector:</span></span><br><span class="line"><span class="attr">    matchLabels:</span></span><br><span class="line"><span class="attr">      run:</span> <span class="string">my-nginx</span></span><br><span class="line"><span class="attr">  replicas:</span> <span class="number">2</span></span><br><span class="line"><span class="attr">  template:</span></span><br><span class="line"><span class="attr">    metadata:</span></span><br><span class="line"><span class="attr">      labels:</span></span><br><span class="line"><span class="attr">        run:</span> <span class="string">my-nginx</span></span><br><span class="line"><span class="attr">    spec:</span></span><br><span class="line"><span class="attr">      containers:</span></span><br><span class="line"><span class="attr">      - name:</span> <span class="string">my-nginx</span></span><br><span class="line"><span class="attr">        image:</span> <span class="string">nginx</span></span><br><span class="line"><span class="attr">        ports:</span></span><br><span class="line"><span class="attr">        - containerPort:</span> <span class="number">80</span>     <span class="comment"># 指定containerPort端口暴露</span></span><br></pre></td></tr></table></figure><p>创建Deployment</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">kubectl apply -f nginx.yaml</span><br></pre></td></tr></table></figure><p>检查Pod正在运行的节点和Pod IP</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></pre></td><td class="code"><pre><span class="line">kubectl get pods -l run=my-nginx -o wide</span><br><span class="line"></span><br><span class="line">NAME                        READY     STATUS    RESTARTS   AGE       IP            NODE</span><br><span class="line">my-nginx-3800858182-jr4a2   1/1       Running   0          13s       10.244.3.4    kubernetes-minion-905m</span><br><span class="line">my-nginx-3800858182-kna2y   1/1       Running   0          13s       10.244.2.5    kubernetes-minion-ljyd</span><br></pre></td></tr></table></figure><p>我们可以在k8s任何节点上通过Pod IP和containerPort访问到Pod的运行在80端口上的nginxService，且一个节点可以同时跑多个containerPort端口相同的Service而不会冲突。同样，我们仍然可以将Pod的端口映射到主机节点上，但由于k8s的上述特性，现在很少这么做。</p><h3 id="创建service"><a class="header-anchor" href="#创建service"></a>创建Service</h3><p>由上可知，我们通过部署Deployment就可以直接与这些pod进行通信，但是当节点挂掉时，pod会随之消亡，Deployment将会创建具有不同IP的新节点；nginx的访问IP也随之变更了，怎么样才能让访问方式保持不变？这就要用到Service。</p><p>Kubernetes Service是一种抽象资源，它定义了在k8s集群中运行的相同逻辑Pod集合，它们都提供相同的功能。当Service创建时，k8s会为每个Service分配一个唯一的IP地址（也称为clusterIP）。 此地址与Service的生命周期相关，并且在Service处于活动状态时不会变更。可配置对Service的通信请求自动负载均衡到Service成员的pod上。</p><p>可以使用kubectl公开为2个nginx副本创建Service：</p><figure class="highlight shell"><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">kubectl expose deployment my-nginx</span><br><span class="line">service/my-nginx exposed</span><br></pre></td></tr></table></figure><p>但通常使用yaml配置文件通过kubectl apply创建</p><p>nginx-svc.yaml</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Service</span>   <span class="comment"># 创建Service</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">my-nginx</span></span><br><span class="line"><span class="attr">  labels:</span></span><br><span class="line"><span class="attr">    run:</span> <span class="string">my-nginx</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  ports:</span></span><br><span class="line"><span class="attr">  - port:</span> <span class="number">80</span>    <span class="comment"># 指定Service暴露端口</span></span><br><span class="line"><span class="attr">    protocol:</span> <span class="string">TCP</span>   <span class="comment"># 端口类型</span></span><br><span class="line"><span class="attr">  selector:</span>     <span class="comment"># Pod选择器</span></span><br><span class="line"><span class="attr">    run:</span> <span class="string">my-nginx</span></span><br></pre></td></tr></table></figure><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">kubectl apply -f nginx-svc.yaml</span><br></pre></td></tr></table></figure><p>此Service使用<code>run：my-nginx</code>标签匹配任何Pod上的TCP端口80，并在抽象的Service端口80上暴露给整个k8s集群（targetPort：是容器接受流量的端口，port：是抽象的Service端口 ，可以是其他pod用于访问Service的任何端口）。</p><p>查看创建的Service</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">kubectl get svc my-nginx</span><br><span class="line"></span><br><span class="line">NAME       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE</span><br><span class="line">my-nginx   ClusterIP   10.0.162.149   &lt;none&gt;        80/TCP    21s</span><br></pre></td></tr></table></figure><p>如前所述，Service由一组Pod支持。 这些Pod通过Endpoint端点（此处为Pod IP和containerPort）公开。集群将不停的检查Service的选择器，并将结果发布到名为my-nginx的端点对象。当Pod死亡时，它会自动从端点移除，与Service选择器匹配的新Pod将自动添加到端点。</p><p>查看Service详情</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><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">kubectl describe svc my-nginx</span><br><span class="line"></span><br><span class="line">Name:                my-nginx</span><br><span class="line">Namespace:           default</span><br><span class="line">Labels:              run=my-nginx</span><br><span class="line">Annotations:         &lt;none&gt;</span><br><span class="line">Selector:            run=my-nginx</span><br><span class="line">Type:                ClusterIP</span><br><span class="line">IP:                  10.0.162.149</span><br><span class="line">Port:                &lt;unset&gt; 80/TCP</span><br><span class="line">Endpoints:           10.244.2.5:80,10.244.3.4:80</span><br><span class="line">Session Affinity:    None</span><br><span class="line">Events:              &lt;none&gt;</span><br></pre></td></tr></table></figure><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">kubectl get ep my-nginx</span><br><span class="line"></span><br><span class="line">NAME       ENDPOINTS                     AGE</span><br><span class="line">my-nginx   10.244.2.5:80,10.244.3.4:80   1m</span><br></pre></td></tr></table></figure><p>现在可以从k8s群集中的任何节点通过的<cluster-ip>:<port>访问nginx服务。 请注意，Serivce IP是完全虚拟的。</port></cluster-ip></p><h3 id="访问service"><a class="header-anchor" href="#访问service"></a>访问Service</h3><p>Kubernetes支持2种查找Service的主要模式 - 环境变量和DNS。 前者内置在k8s中，而后者需要CoreDNS群集插件支持。详见<a href="https://www.whyvv.top/k8s8.html">Kubernetes之Service</a>。现在普遍使用DNS方式实现。</p><h3 id="service安全"><a class="header-anchor" href="#service安全"></a>Service安全</h3><p>到目前为止，我们只是从群集中访问到nginx服务。 在将服务暴露给互联网之前，需要确保Service通信渠道是安全的。因此，一般建议配置：</p><ul><li>https的自签名证书（除非您已拥有身份证书）</li><li>带证书的nginx服务</li><li>pod间访问证书的secret密钥</li></ul><p>例如：假设<a href="https://github.com/kubernetes/examples/tree/master/staging/https-nginx/" target="_blank" rel="noopener">证书创建</a></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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>create a public private key pair</span><br><span class="line">openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /d/tmp/nginx.key -out /d/tmp/nginx.crt -subj "/CN=my-nginx/O=my-nginx"</span><br><span class="line"><span class="meta">#</span>convert the keys to base64 encoding</span><br><span class="line">cat /d/tmp/nginx.crt | base64</span><br><span class="line">cat /d/tmp/nginx.key | base64</span><br></pre></td></tr></table></figure><p>使用上述输出配置文件nginxsecrets.yaml</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">"v1"</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">"Secret"</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">"nginxsecret"</span></span><br><span class="line"><span class="attr">  namespace:</span> <span class="string">"default"</span></span><br><span class="line"><span class="attr">data:</span></span><br><span class="line">  <span class="string">nginx.crt:</span> <span class="string">"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURIekNDQWdlZ0F3SUJBZ0lKQUp5M3lQK0pzMlpJTUEwR0NTcUdTSWIzRFFFQkJRVUFNQ1l4RVRBUEJnTlYKQkFNVENHNW5hVzU0YzNaak1SRXdEd1lEVlFRS0V3aHVaMmx1ZUhOMll6QWVGdzB4TnpFd01qWXdOekEzTVRKYQpGdzB4T0RFd01qWXdOekEzTVRKYU1DWXhFVEFQQmdOVkJBTVRDRzVuYVc1NGMzWmpNUkV3RHdZRFZRUUtFd2h1CloybHVlSE4yWXpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSjFxSU1SOVdWM0IKMlZIQlRMRmtobDRONXljMEJxYUhIQktMSnJMcy8vdzZhU3hRS29GbHlJSU94NGUrMlN5ajBFcndCLzlYTnBwbQppeW1CL3JkRldkOXg5UWhBQUxCZkVaTmNiV3NsTVFVcnhBZW50VWt1dk1vLzgvMHRpbGhjc3paenJEYVJ4NEo5Ci82UVRtVVI3a0ZTWUpOWTVQZkR3cGc3dlVvaDZmZ1Voam92VG42eHNVR0M2QURVODBpNXFlZWhNeVI1N2lmU2YKNHZpaXdIY3hnL3lZR1JBRS9mRTRqakxCdmdONjc2SU90S01rZXV3R0ljNDFhd05tNnNTSzRqYUNGeGpYSnZaZQp2by9kTlEybHhHWCtKT2l3SEhXbXNhdGp4WTRaNVk3R1ZoK0QrWnYvcW1mMFgvbVY0Rmo1NzV3ajFMWVBocWtsCmdhSXZYRyt4U1FVQ0F3RUFBYU5RTUU0d0hRWURWUjBPQkJZRUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjcKTUI4R0ExVWRJd1FZTUJhQUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjdNQXdHQTFVZEV3UUZNQU1CQWY4dwpEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBRVhTMW9FU0lFaXdyMDhWcVA0K2NwTHI3TW5FMTducDBvMm14alFvCjRGb0RvRjdRZnZqeE04Tzd2TjB0clcxb2pGSW0vWDE4ZnZaL3k4ZzVaWG40Vm8zc3hKVmRBcStNZC9jTStzUGEKNmJjTkNUekZqeFpUV0UrKzE5NS9zb2dmOUZ3VDVDK3U2Q3B5N0M3MTZvUXRUakViV05VdEt4cXI0Nk1OZWNCMApwRFhWZmdWQTRadkR4NFo3S2RiZDY5eXM3OVFHYmg5ZW1PZ05NZFlsSUswSGt0ejF5WU4vbVpmK3FqTkJqbWZjCkNnMnlwbGQ0Wi8rUUNQZjl3SkoybFIrY2FnT0R4elBWcGxNSEcybzgvTHFDdnh6elZPUDUxeXdLZEtxaUMwSVEKQ0I5T2wwWW5scE9UNEh1b2hSUzBPOStlMm9KdFZsNUIyczRpbDlhZ3RTVXFxUlU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"</span></span><br><span class="line">  <span class="string">nginx.key:</span> <span class="string">"LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2RhaURFZlZsZHdkbFIKd1V5eFpJWmVEZWNuTkFhbWh4d1NpeWF5N1AvOE9ta3NVQ3FCWmNpQ0RzZUh2dGtzbzlCSzhBZi9WemFhWm9zcApnZjYzUlZuZmNmVUlRQUN3WHhHVFhHMXJKVEVGSzhRSHA3VkpMcnpLUC9QOUxZcFlYTE0yYzZ3MmtjZUNmZitrCkU1bEVlNUJVbUNUV09UM3c4S1lPNzFLSWVuNEZJWTZMMDUrc2JGQmd1Z0ExUE5JdWFubm9UTWtlZTRuMG4rTDQKb3NCM01ZUDhtQmtRQlAzeE9JNHl3YjREZXUraURyU2pKSHJzQmlIT05Xc0RadXJFaXVJMmdoY1kxeWIyWHI2UAozVFVOcGNSbC9pVG9zQngxcHJHclk4V09HZVdPeGxZZmcvbWIvNnBuOUYvNWxlQlkrZStjSTlTMkQ0YXBKWUdpCkwxeHZzVWtGQWdNQkFBRUNnZ0VBZFhCK0xkbk8ySElOTGo5bWRsb25IUGlHWWVzZ294RGQwci9hQ1Zkank4dlEKTjIwL3FQWkUxek1yall6Ry9kVGhTMmMwc0QxaTBXSjdwR1lGb0xtdXlWTjltY0FXUTM5SjM0VHZaU2FFSWZWNgo5TE1jUHhNTmFsNjRLMFRVbUFQZytGam9QSFlhUUxLOERLOUtnNXNrSE5pOWNzMlY5ckd6VWlVZWtBL0RBUlBTClI3L2ZjUFBacDRuRWVBZmI3WTk1R1llb1p5V21SU3VKdlNyblBESGtUdW1vVlVWdkxMRHRzaG9reUxiTWVtN3oKMmJzVmpwSW1GTHJqbGtmQXlpNHg0WjJrV3YyMFRrdWtsZU1jaVlMbjk4QWxiRi9DSmRLM3QraTRoMTVlR2ZQegpoTnh3bk9QdlVTaDR2Q0o3c2Q5TmtEUGJvS2JneVVHOXBYamZhRGR2UVFLQmdRRFFLM01nUkhkQ1pKNVFqZWFKClFGdXF4cHdnNzhZTjQyL1NwenlUYmtGcVFoQWtyczJxWGx1MDZBRzhrZzIzQkswaHkzaE9zSGgxcXRVK3NHZVAKOWRERHBsUWV0ODZsY2FlR3hoc0V0L1R6cEdtNGFKSm5oNzVVaTVGZk9QTDhPTm1FZ3MxMVRhUldhNzZxelRyMgphRlpjQ2pWV1g0YnRSTHVwSkgrMjZnY0FhUUtCZ1FEQmxVSUUzTnNVOFBBZEYvL25sQVB5VWs1T3lDdWc3dmVyClUycXlrdXFzYnBkSi9hODViT1JhM05IVmpVM25uRGpHVHBWaE9JeXg5TEFrc2RwZEFjVmxvcG9HODhXYk9lMTAKMUdqbnkySmdDK3JVWUZiRGtpUGx1K09IYnRnOXFYcGJMSHBzUVpsMGhucDBYSFNYVm9CMUliQndnMGEyOFVadApCbFBtWmc2d1BRS0JnRHVIUVV2SDZHYTNDVUsxNFdmOFhIcFFnMU16M2VvWTBPQm5iSDRvZUZKZmcraEppSXlnCm9RN3hqWldVR3BIc3AyblRtcHErQWlSNzdyRVhsdlhtOElVU2FsbkNiRGlKY01Pc29RdFBZNS9NczJMRm5LQTQKaENmL0pWb2FtZm1nZEN0ZGtFMXNINE9MR2lJVHdEbTRpb0dWZGIwMllnbzFyb2htNUpLMUI3MkpBb0dBUW01UQpHNDhXOTVhL0w1eSt5dCsyZ3YvUHM2VnBvMjZlTzRNQ3lJazJVem9ZWE9IYnNkODJkaC8xT2sybGdHZlI2K3VuCnc1YytZUXRSTHlhQmd3MUtpbGhFZDBKTWU3cGpUSVpnQWJ0LzVPbnlDak9OVXN2aDJjS2lrQ1Z2dTZsZlBjNkQKckliT2ZIaHhxV0RZK2Q1TGN1YSt2NzJ0RkxhenJsSlBsRzlOZHhrQ2dZRUF5elIzT3UyMDNRVVV6bUlCRkwzZAp4Wm5XZ0JLSEo3TnNxcGFWb2RjL0d5aGVycjFDZzE2MmJaSjJDV2RsZkI0VEdtUjZZdmxTZEFOOFRwUWhFbUtKCnFBLzVzdHdxNWd0WGVLOVJmMWxXK29xNThRNTBxMmk1NVdUTThoSDZhTjlaMTltZ0FGdE5VdGNqQUx2dFYxdEYKWSs4WFJkSHJaRnBIWll2NWkwVW1VbGc9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K"</span></span><br></pre></td></tr></table></figure><p>创建secret证书和密钥</p><figure class="highlight shell"><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">kubectl apply -f nginxsecrets.yaml</span><br><span class="line">secret/nginxsecret created</span><br></pre></td></tr></table></figure><p>查看secret</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></pre></td><td class="code"><pre><span class="line">kubectl get secrets</span><br><span class="line"></span><br><span class="line">NAME                  TYPE                                  DATA      AGE</span><br><span class="line">default-token-il9rc   kubernetes.io/service-account-token   1         1d</span><br><span class="line">nginxsecret           Opaque                                2         1m</span><br></pre></td></tr></table></figure><p>修改nginx服务，使用secret中的证书启动https服务，暴露两个端口（80和443）：</p><p>nginx-secure-app.yaml</p><figure class="highlight yml"><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></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Service</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">my-nginx</span></span><br><span class="line"><span class="attr">  labels:</span></span><br><span class="line"><span class="attr">    run:</span> <span class="string">my-nginx</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  type:</span> <span class="string">NodePort</span>    <span class="comment"># 配置NodePort节点端口映射</span></span><br><span class="line"><span class="attr">  ports:</span></span><br><span class="line"><span class="attr">  - port:</span> <span class="number">8080</span></span><br><span class="line"><span class="attr">    targetPort:</span> <span class="number">80</span></span><br><span class="line"><span class="attr">    protocol:</span> <span class="string">TCP</span></span><br><span class="line"><span class="attr">    name:</span> <span class="string">http</span></span><br><span class="line"><span class="attr">  - port:</span> <span class="number">443</span></span><br><span class="line"><span class="attr">    protocol:</span> <span class="string">TCP</span></span><br><span class="line"><span class="attr">    name:</span> <span class="string">https</span></span><br><span class="line"><span class="attr">  selector:</span></span><br><span class="line"><span class="attr">    run:</span> <span class="string">my-nginx</span></span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">apps/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Deployment</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">my-nginx</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  selector:</span></span><br><span class="line"><span class="attr">    matchLabels:</span></span><br><span class="line"><span class="attr">      run:</span> <span class="string">my-nginx</span></span><br><span class="line"><span class="attr">  replicas:</span> <span class="number">1</span></span><br><span class="line"><span class="attr">  template:</span></span><br><span class="line"><span class="attr">    metadata:</span></span><br><span class="line"><span class="attr">      labels:</span></span><br><span class="line"><span class="attr">        run:</span> <span class="string">my-nginx</span></span><br><span class="line"><span class="attr">    spec:</span></span><br><span class="line"><span class="attr">      volumes:</span>  <span class="comment"># 指定挂载卷</span></span><br><span class="line"><span class="attr">      - name:</span> <span class="string">secret-volume</span> <span class="comment"># 卷名</span></span><br><span class="line"><span class="attr">        secret:</span></span><br><span class="line"><span class="attr">          secretName:</span> <span class="string">nginxsecret</span></span><br><span class="line"><span class="attr">      containers:</span></span><br><span class="line"><span class="attr">      - name:</span> <span class="string">nginxhttps</span></span><br><span class="line"><span class="attr">        image:</span> <span class="string">bprashanth/nginxhttps:1.0</span></span><br><span class="line"><span class="attr">        ports:</span></span><br><span class="line"><span class="attr">        - containerPort:</span> <span class="number">443</span></span><br><span class="line"><span class="attr">        - containerPort:</span> <span class="number">80</span></span><br><span class="line"><span class="attr">        volumeMounts:</span></span><br><span class="line"><span class="attr">        - mountPath:</span> <span class="string">/etc/nginx/ssl</span> <span class="comment"># 此处挂载secret</span></span><br><span class="line"><span class="attr">          name:</span> <span class="string">secret-volume</span>       <span class="comment"># 卷名</span></span><br></pre></td></tr></table></figure><p>上述重要配置信息：</p><ul><li>创建Deployment和Service</li><li>nginx Service同时监听80和443</li><li>nginx每个容器都通过/etc/nginx/ssl挂载创建的密钥和证书secret卷</li></ul><p>然后你可以通过Pod或ClusterIP访问到nginx服务</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></pre></td><td class="code"><pre><span class="line">kubectl get pods -o yaml | grep -i podip</span><br><span class="line">    podIP: 10.244.3.5</span><br><span class="line">node $ curl -k https://10.244.3.5</span><br><span class="line">...</span><br><span class="line">&lt;h1&gt;Welcome to nginx!&lt;/h1&gt;</span><br></pre></td></tr></table></figure><h3 id="暴露service服务"><a class="header-anchor" href="#暴露service服务"></a>暴露Service服务</h3><p>经常你需要将应用程序公开到外部IP地址，方便业务流量接入访问。 为此，Kubernetes支持两种方式：<code>NodePorts</code>和<code>LoadBalancers</code>。 在上一节中创建的Service服务已使用NodePort，因此如果你的节点具有公网IP，则你的nginx HTTPS副本已经可以通过Internet访问。</p><p><strong>NodePorts</strong></p><p>获取ClusterIP和nodePort端口</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><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">kubectl get svc my-nginx -o yaml | grep nodePort -C 5</span><br><span class="line">  uid: 07191fb3-f61a-11e5-8ae5-42010af00002</span><br><span class="line">spec:</span><br><span class="line">  clusterIP: 10.0.162.149</span><br><span class="line">  ports:</span><br><span class="line">  - name: http</span><br><span class="line">    nodePort: 31704</span><br><span class="line">    port: 8080</span><br><span class="line">    protocol: TCP</span><br><span class="line">    targetPort: 80</span><br><span class="line">  - name: https</span><br><span class="line">    nodePort: 32453</span><br><span class="line">    port: 443</span><br><span class="line">    protocol: TCP</span><br><span class="line">    targetPort: 443</span><br><span class="line">  selector:</span><br><span class="line">    run: my-nginx</span><br></pre></td></tr></table></figure><p>测试你的nginx服务</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><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">kubectl get nodes -o yaml | grep ExternalIP -C 1</span><br><span class="line">    - address: 104.197.41.11</span><br><span class="line">      type: ExternalIP</span><br><span class="line">    allocatable:</span><br><span class="line">--</span><br><span class="line">    - address: 23.251.152.56</span><br><span class="line">      type: ExternalIP</span><br><span class="line">    allocatable:</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="meta">$</span> curl https://&lt;EXTERNAL-IP&gt;:&lt;NODE-PORT&gt; -k</span><br><span class="line">...</span><br><span class="line">&lt;h1&gt;Welcome to nginx!&lt;/h1&gt;</span><br></pre></td></tr></table></figure><p><strong>LoadBalancer</strong></p><p>现在我们使用LoadBalancer方式重新创建服务，只需将my-nginx服务的类型从NodePort更改为LoadBalancer即可</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></pre></td><td class="code"><pre><span class="line">kubectl edit svc my-nginx</span><br><span class="line">kubectl get svc my-nginx</span><br><span class="line"></span><br><span class="line">NAME       TYPE        CLUSTER-IP     EXTERNAL-IP        PORT(S)               AGE</span><br><span class="line">my-nginx   ClusterIP   10.0.162.149   162.222.184.144    80/TCP,81/TCP,82/TCP  21s</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line">curl https://&lt;EXTERNAL-IP&gt; -k</span><br><span class="line">...</span><br><span class="line">&lt;title&gt;Welcome to nginx!&lt;/title&gt;</span><br></pre></td></tr></table></figure><p>EXTERNAL-IP列中的IP地址是公共互联网上可用的IP地址。 CLUSTER-IP仅在您的群集/私有云网络中可用。</p><p>请注意，在AWS上，键入LoadBalancer会创建一个ELB，它使用（长）主机名，而不是IP。实际上，要适应标准的kubectl获取svc输出太长了，所以你需要做kubectl描述服务my-nginx才能看到它。你会看到这样的事情：</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">kubectl describe service my-nginx</span><br><span class="line">...</span><br><span class="line">LoadBalancer Ingress:   a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.elb.amazonaws.com</span><br><span class="line">...</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;本章我们将讨论kubernetes中连接到serivce容器的方法，首先我们来看它和docker容器网络工作模式的对比：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Docker默认使用主机私有网络通信，因此同一主机的容器之间可以互通。为了实现不同主机之间的容器访问，必须通过绑定本机端口来将
      
    
    </summary>
    
      <category term="Kubernetes教程" scheme="http://www.whyvv.top/categories/Kubernetes%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Kubernetes" scheme="http://www.whyvv.top/tags/Kubernetes/"/>
    
      <category term="K8s" scheme="http://www.whyvv.top/tags/K8s/"/>
    
  </entry>
  
  <entry>
    <title>linux磁盘IO查看命令iotop</title>
    <link href="http://www.whyvv.top/iotop.html"/>
    <id>http://www.whyvv.top/iotop.html</id>
    <published>2019-08-12T03:00:00.000Z</published>
    <updated>2019-08-12T09:55:37.881Z</updated>
    
    <content type="html"><![CDATA[<p>linux服务器如果磁盘性能不佳，或者进程操作IO量超过磁盘负荷，都会导致磁盘IO响应缓慢，甚至出现宕机的情况。很多人会说，我有iostat命令啊。但是如果需要找到哪个进程对磁盘IO操作压力最大，iostat是不能帮我们直接呈现的，这时候，另一个利器iotop就派上用场了。</p><h3 id="iotop命令"><a class="header-anchor" href="#iotop命令"></a>iotop命令</h3><p>iotop命令是一个用来监视磁盘I/O使用状况的top类工具。iotop具有与top相似的UI，其中包括PID、用户、I/O、进程等相关信息。如果你想知道每个进程是如何使用IO的就比较麻烦，使用iotop命令可以很方便的查看。</p><h3 id="iotop安装"><a class="header-anchor" href="#iotop安装"></a>iotop安装</h3><p>一般iotop默认是没有安装的，iotop安装也很简单，你需要如下操作(其它linux版本可自行搜索安装方法)：</p><p>CentOS/Redhat：yum install iotop<br>Debian/Ubuntu：apt-get install iotop</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">wget http://guichaz.free.fr/iotop/files/iotop-0.6.tar.gz</span><br><span class="line">tar zxf iotop-0.4.4.tar.gz</span><br><span class="line">python setup.py build</span><br><span class="line">python setup.py install</span><br></pre></td></tr></table></figure><h3 id="iotop输出"><a class="header-anchor" href="#iotop输出"></a>iotop输出</h3><p>iotop输出很容易看懂：</p><p>第一行：Read和Write速率总计</p><p>第二：实际的Read和Write速率</p><p>第三行：参数如下：</p><ul><li>线程ID（按p切换为进程ID）</li><li>优先级</li><li>用户</li><li>磁盘读速率</li><li>磁盘写速率</li><li>swap交换百分比</li><li>IO等待所占的百分比</li><li>线程/进程命令</li></ul><h3 id="常用参数"><a class="header-anchor" href="#常用参数"></a>常用参数</h3><ul><li>-o, --only只显示正在产生I/O的进程或线程。除了传参，可以在运行过程中按o生效。</li><li>-b, --batch非交互模式，一般用来记录日志。</li><li>-n NUM, --iter=NUM设置监测的次数，默认无限。在非交互模式下很有用。</li><li>-d SEC, --delay=SEC设置每次监测的间隔，默认1秒，接受非整形数据例如1.1。</li><li>-p PID, --pid=PID指定监测的进程/线程。</li><li>-u USER, --user=USER指定监测某个用户产生的I/O。</li><li>-P, --processes仅显示进程，默认iotop显示所有线程。</li><li>-a, --accumulated显示累积的I/O，而不是带宽。</li><li>-k, --kilobytes使用kB单位，而不是对人友好的单位。在非交互模式下，脚本编程有用。</li><li>-t, --time 加上时间戳，非交互非模式。</li><li>-q, --quiet 禁止头几行，非交互模式。有三种指定方式。<ul><li>-q 只在第一次监测时显示列名</li><li>-qq 永远不显示列名。</li><li>-qqq 永远不显示I/O汇总。</li></ul></li></ul><h3 id="交互按键"><a class="header-anchor" href="#交互按键"></a>交互按键</h3><p>和top命令类似，iotop也支持以下几个交互按键。</p><ul><li>left和right方向键：改变排序。</li><li>r：反向排序。</li><li>o：切换至选项–only。</li><li>p：切换至–processes选项。</li><li>a：切换至–accumulated选项。</li><li>q：退出。</li><li>i：改变线程的优先级。</li></ul><h3 id="写在最后"><a class="header-anchor" href="#写在最后"></a>写在最后</h3><p>itop通过方向键选择按哪一列来排序，基本上我们会以此来判断当前哪些线程/进程对磁盘有IO操作，以及操作的IO速率，但是要判断磁盘IO负载是否已饱和，还需要结合top命令，当前磁盘最大性能等指标综合判断。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;linux服务器如果磁盘性能不佳，或者进程操作IO量超过磁盘负荷，都会导致磁盘IO响应缓慢，甚至出现宕机的情况。很多人会说，我有iostat命令啊。但是如果需要找到哪个进程对磁盘IO操作压力最大，iostat是不能帮我们直接呈现的，这时候，另一个利器iotop就派上用场了。
      
    
    </summary>
    
      <category term="技术" scheme="http://www.whyvv.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="linux" scheme="http://www.whyvv.top/tags/linux/"/>
    
      <category term="磁盘IO" scheme="http://www.whyvv.top/tags/%E7%A3%81%E7%9B%98IO/"/>
    
  </entry>
  
  <entry>
    <title>linux磁盘IO测试工具hdparm</title>
    <link href="http://www.whyvv.top/hdparm.html"/>
    <id>http://www.whyvv.top/hdparm.html</id>
    <published>2019-08-09T03:00:00.000Z</published>
    <updated>2019-08-09T03:36:03.663Z</updated>
    
    <content type="html"><![CDATA[<p><strong>磁盘IO性能</strong></p><p>服务器磁盘IO是最可能影响服务器性能发挥的指标之一，在很多情况下，服务器负载异常都可能与磁盘IO性能不足有关。所以很多时候我们需要做磁盘测试，hdparm就是一个很好的磁盘测试工具。</p><p>命令语法</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hdparm [-CfghiIqtTvyYZ][-a &lt;快取分区&gt;][-A &lt;0或1&gt;][-c &lt;I/O模式&gt;][-d &lt;0或1&gt;][-k &lt;0或1&gt;][-K &lt;0或1&gt;][-m &lt;分区数&gt;][-n &lt;0或1&gt;][-p &lt;PIO模式&gt;][-P &lt;分区数&gt;][-r &lt;0或1&gt;][-S &lt;时间&gt;][-u &lt;0或1&gt;][-W &lt;0或1&gt;][-X &lt;传输模式&gt;][设备]</span><br></pre></td></tr></table></figure><p>补充说明：hdparm可检测，显示与设定IDE或SCSI硬盘的参数。</p><p>参数解析:</p><ul><li>-a&lt;快取分区&gt;：设定读取文件时，预先存入块区的分区数，若不加上&lt;快取分区&gt;选项，则显示目前的设定。</li><li>-A&lt;0或1&gt;：启动或关闭读取文件时的快取功能。</li><li>-c&lt;I/O模式&gt;：设定IDE32位I/O模式。</li><li>-C：检测IDE硬盘的电源管理模式。</li><li>-d&lt;0或1&gt;：设定磁盘的DMA模式。</li><li>-f：将内存缓冲区的数据写入硬盘，并清楚缓冲区。</li><li>-g：显示硬盘的磁轨，磁头，磁区等参数。</li><li>-h：显示帮助。</li><li>-i：显示硬盘的硬件规格信息，这些信息是在开机时由硬盘本身所提供。</li><li>-I：直接读取硬盘所提供的硬件规格信息。</li><li>-k&lt;0或1&gt;：重设硬盘时，保留-dmu参数的设定。</li><li>-K&lt;0或1&gt;：重设硬盘时，保留-APSWXZ参数的设定。</li><li>-m&lt;磁区数&gt;：设定硬盘多重分区存取的分区数。</li><li>-n&lt;0或1&gt;：忽略硬盘写入时所发生的错误。</li><li>-p&lt;PIO模式&gt;：设定硬盘的PIO模式。</li><li>-P&lt;磁区数&gt;：设定硬盘内部快取的分区数。</li><li>-q：在执行后续的参数时，不在屏幕上显示任何信息。</li><li>-r&lt;0或1&gt;：设定硬盘的读写模式。</li><li>-S&lt;时间&gt;：设定硬盘进入省电模式前的等待时间。</li><li>-t：评估硬盘的读取效率。</li><li>-T：评估硬盘快取的读取效率。</li><li>-u&lt;0或1&gt;：在硬盘存取时，允许其他中断要求同时执行。</li><li>-v：显示硬盘的相关设定。</li><li>-W&lt;0或1&gt;：设定硬盘的写入快取。</li><li>-X&lt;传输模式&gt;：设定硬盘的传输模式。</li><li>-y：使IDE硬盘进入省电模式。</li><li>-Y：使IDE硬盘进入睡眠模式。</li><li>-Z：关闭某些Seagate硬盘的自动省电功能。</li></ul><p><strong>用法举例</strong></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><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> hdparm -t /dev/sda</span><br><span class="line">/dev/sda:</span><br><span class="line">Timing buffered disk reads: 316 MB in 3.02 seconds = 104.71 MB/sec</span><br><span class="line"><span class="meta">#</span> hdparm -T /dev/sda</span><br><span class="line">/dev/sda:</span><br><span class="line">Timing cached reads: 19328 MB in 1.99 seconds = 9691.24 MB/sec</span><br></pre></td></tr></table></figure><p>RAID0测试(两块盘)</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> hdparm -t /dev/sdb</span><br><span class="line">/dev/sdb:</span><br><span class="line">Timing buffered disk reads: 622 MB in 3.01 seconds = 206.89 MB/sec</span><br><span class="line"><span class="meta">#</span> hdparm -T /dev/sdb1</span><br><span class="line">/dev/sdb1:</span><br><span class="line">Timing cached reads: 19632 MB in 1.99 seconds = 9844.20 MB/sec</span><br></pre></td></tr></table></figure><p>RAID0测试(三块盘)</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> hdparm -t /dev/sdb</span><br><span class="line">/dev/sdb:</span><br><span class="line">Timing buffered disk reads: 846 MB in 3.00 seconds = 281.54 MB/sec</span><br><span class="line"><span class="meta">#</span> hdparm -T /dev/sdb</span><br><span class="line">/dev/sdb:</span><br><span class="line">Timing cached reads: 18412 MB in 1.99 seconds = 9229.67 MB/sec</span><br></pre></td></tr></table></figure><p>RAID0测试(四块盘)</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></pre></td><td class="code"><pre><span class="line">/dev/sdb:</span><br><span class="line">Timing cached reads: 19608 MB in 1.99 seconds = 9832.76 MB/sec</span><br><span class="line">Timing buffered disk reads: 860 MB in 3.00 seconds = 286.35 MB/sec</span><br></pre></td></tr></table></figure><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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">hdparm /dev/sda</span><br><span class="line">/dev/sda: IO_support = 0 (default 16-bit)</span><br><span class="line">readonly = 0 (off)</span><br><span class="line">readahead = 256 (on)</span><br><span class="line">geometry = 19457［柱面数］/255［磁头数］/63［扇区数］, sectors = 312581808［总扇区数］, start = 0［起始扇区数］</span><br></pre></td></tr></table></figure><p>显示硬盘的柱面、磁头、扇区数</p><figure class="highlight shell"><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">hdparm -g /dev/sda</span><br><span class="line">/dev/sda: geometry = 19457［柱面数］/255［磁头数］/63［扇区数］, sectors = 312581808［总扇区数］, start = 0［起始扇区数］</span><br></pre></td></tr></table></figure><p>测试硬盘缓存的读取速度</p><figure class="highlight shell"><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">hdparm -T /dev/xvda</span><br><span class="line">/dev/xvda: Timing cached reads: 11154 MB in 1.98 seconds = 5633.44 MB/sec</span><br></pre></td></tr></table></figure><p>检测硬盘的电源管理模式</p><figure class="highlight shell"><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">hdparm -C /dev/sda</span><br><span class="line">/dev/sda: drive state is: standby [省电模式]</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;&lt;strong&gt;磁盘IO性能&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;服务器磁盘IO是最可能影响服务器性能发挥的指标之一，在很多情况下，服务器负载异常都可能与磁盘IO性能不足有关。所以很多时候我们需要做磁盘测试，hdparm就是一个很好的磁盘测试工具。&lt;/p&gt;
&lt;p&gt;命令语法&lt;/p
      
    
    </summary>
    
      <category term="技术" scheme="http://www.whyvv.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="linux" scheme="http://www.whyvv.top/tags/linux/"/>
    
      <category term="磁盘IO" scheme="http://www.whyvv.top/tags/%E7%A3%81%E7%9B%98IO/"/>
    
  </entry>
  
  <entry>
    <title>yum通过squid代理连接外网</title>
    <link href="http://www.whyvv.top/yum_proxy.html"/>
    <id>http://www.whyvv.top/yum_proxy.html</id>
    <published>2019-08-09T02:00:00.000Z</published>
    <updated>2019-08-09T03:05:13.573Z</updated>
    
    <content type="html"><![CDATA[<p>平时大家在部署环境或项目时，肯定有碰到类似的网络环境：私有网络中，有一台机器（一般是跳板机或代理机）可访问外网，其它机器无外网访问权限。这时除这台以外的其他机器，yum无法正常安装软件。解决方案是：在有外网权限的机器上配置squid代理到公网，然后为内网其他机器配置yum代理，使用公网的yum源(<a href="http://xn--mirrors-ff6kt45e.aliyun.com" target="_blank" rel="noopener">例如mirrors.aliyun.com</a>)安装软件包。</p><p>此次实验环境：CentOS7.3_x64</p><h1>配置squid</h1><p>在有外网权限的机器上（假设这台主机名为manage01）squid代理使用默认配置，只需要修改下面配置重启即可：</p><p>/etc/sqiud/squid.conf</p><figure class="highlight plain"><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">#http_access deny all</span><br><span class="line">http_access allow all</span><br></pre></td></tr></table></figure><p>重启squid</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">systemctl restart squid</span><br></pre></td></tr></table></figure><p>squid默认监听3128端口</p><h1>配置yum代理</h1><p>在/etc/yum.conf添加一行即可</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">proxy=http://manage01:3128</span><br></pre></td></tr></table></figure><h1>配置aliyun仓库</h1><p>/etc/yum.repos.d/aliyun.repo</p><figure class="highlight plain"><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]</span><br><span class="line">name=CentOS-$releasever - Base</span><br><span class="line">baseurl=http://mirrors.aliyun.com/centos/7/os/$basearch/</span><br><span class="line">enabled=1</span><br><span class="line">gpgcheck=0</span><br><span class="line">gpgkey=http://mirrors.aliyun.com/centos/7/os/x86_64/RPM-GPG-KEY-CentOS-7</span><br><span class="line"></span><br><span class="line">#released updates</span><br><span class="line">[updates]</span><br><span class="line">name=CentOS-$releasever - Updates</span><br><span class="line">baseurl=http://mirrors.aliyun.com/centos/7/updates/$basearch/</span><br><span class="line">enabled=1</span><br><span class="line">gpgcheck=0</span><br><span class="line">gpgkey=http://mirrors.aliyun.com/centos/7/os/x86_64/RPM-GPG-KEY-CentOS-7</span><br><span class="line"></span><br><span class="line">[extras]</span><br><span class="line">name=CentOS-$releasever - Extras</span><br><span class="line">baseurl=http://mirrors.aliyun.com/centos/7/extras//$basearch/</span><br><span class="line">enabled=1</span><br><span class="line">gpgcheck=0</span><br><span class="line">gpgkey=http://mirrors.aliyun.com/centos/7/os/x86_64/RPM-GPG-KEY-CentOS-7</span><br><span class="line"></span><br><span class="line">[centosplus]</span><br><span class="line">name=CentOS-$releasever - Plus</span><br><span class="line">baseurl=http://mirrors.aliyun.com/centos/7/centosplus//$basearch/</span><br><span class="line">enabled=1</span><br><span class="line">gpgcheck=0</span><br></pre></td></tr></table></figure><p>验证</p><figure class="highlight shell"><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">yum cleann all</span><br><span class="line">yum repolist</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;平时大家在部署环境或项目时，肯定有碰到类似的网络环境：私有网络中，有一台机器（一般是跳板机或代理机）可访问外网，其它机器无外网访问权限。这时除这台以外的其他机器，yum无法正常安装软件。解决方案是：在有外网权限的机器上配置squid代理到公网，然后为内网其他机器配置yum代
      
    
    </summary>
    
      <category term="技术" scheme="http://www.whyvv.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="linux" scheme="http://www.whyvv.top/tags/linux/"/>
    
      <category term="代理" scheme="http://www.whyvv.top/tags/%E4%BB%A3%E7%90%86/"/>
    
      <category term="yum" scheme="http://www.whyvv.top/tags/yum/"/>
    
  </entry>
  
  <entry>
    <title>使用Docker swarm mode创建多节点容器集群</title>
    <link href="http://www.whyvv.top/docker_swarm_mode.html"/>
    <id>http://www.whyvv.top/docker_swarm_mode.html</id>
    <published>2019-08-08T03:00:00.000Z</published>
    <updated>2019-08-09T03:53:05.045Z</updated>
    
    <content type="html"><![CDATA[<p><strong>1.初始化创建swarm</strong></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">docker swarm init --advertise-addr &lt;MANAGER-IP&gt;</span><br></pre></td></tr></table></figure><ul><li>–listen-addr：指定swarm节点监听的地址/网络接口及端口，默认端口为0.0.0.0:2377</li><li>–advertise-addr：指定为其它swarm节点提供API access和overlay networking的监听地址和端口，若不指出，会使用–listen-addr指定的端口；若系统有多个IP地址，这个参数必须指定监听到哪个网络地址</li></ul><p><strong>2.查看swarm信息</strong></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">docker info</span><br></pre></td></tr></table></figure><p>有相关swarm信息（示例如下）</p><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">Swarm: active</span><br><span class="line">NodeID: os0l8xe87o0nz0sc04vrrpppl</span><br><span class="line">Is Manager: true</span><br><span class="line">ClusterID: o1c3g9ockktlagwpqirgb49no</span><br><span class="line">Managers: 1</span><br><span class="line">Nodes: 2</span><br><span class="line">Orchestration:</span><br><span class="line">Task History Retention Limit: 5</span><br><span class="line">Raft:</span><br><span class="line">Snapshot Interval: 10000</span><br><span class="line">Number of Old Snapshots to Retain: 0</span><br><span class="line">Heartbeat Tick: 1</span><br><span class="line">Election Tick: 3</span><br><span class="line">Dispatcher:</span><br><span class="line">Heartbeat Period: 5 seconds</span><br><span class="line">CA Configuration:</span><br><span class="line">Expiry Duration: 3 months</span><br><span class="line">Node Address: 192.168.1.146</span><br><span class="line">Manager Addresses:</span><br><span class="line">192.168.1.146:2377</span><br></pre></td></tr></table></figure><p><strong>3.增加swarm节点</strong></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">docker swarm join --token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c 192.168.99.100:2377</span><br></pre></td></tr></table></figure><p><strong>4.查看主节点供连接信息</strong></p><figure class="highlight shell"><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">docker swarm join-token worker</span><br><span class="line">docker swarm join-token manager</span><br></pre></td></tr></table></figure><p>重新生成token</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">swarm join-token --rotate</span><br></pre></td></tr></table></figure><p>强烈建议manager节点为奇数个，方便在某节点故障时选举出leader，以下为manager节点规划和可FT(Fault Tolerance)数，以此类推，即swarm cluster允许(N-1)/2个节点故障。</p><p><img src="/images/swarm_mode.png" alt="docker swarm mode cluster节点建议"></p><p>分布式manager节点配置：不同节点上配置的manager节点数，保证更好的容错性</p><p><img src="/images/swarm_mode2.png" alt="swarm manager nodes"></p><p>运行manager-only节点（默认manager节点也是worker节点），即将节点状态变为drain状态</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">docker node update --availability drain &lt;NODE-ID&gt;</span><br></pre></td></tr></table></figure><p>节点从故障中恢复</p><figure class="highlight shell"><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">docker swarm init --force-new-cluster --listen-addr node01:2377</span><br><span class="line">The --force-new-cluster flag puts the Docker Engine into swarm mode as a manager node of a single-node cluster. It discards cluster membership information that existed before the loss of the quorum but it retains data necessary to the Swarm cluster such as services, tasks and the list of worker nodes.This flag forces an existing node that was part of a quorum that was lost to restart as a single node Manager without losing its data</span><br></pre></td></tr></table></figure><p><strong>5.在主节点上查看所有节点信息</strong></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">docker node ls</span><br></pre></td></tr></table></figure><p><strong>6.创建（发布）服务</strong></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">docker service create --replicas 1 --name helloworld alpine ping docker.com</span><br></pre></td></tr></table></figure><p>参数解析：</p><ul><li>–replicas：服务实例数</li><li>–name：服务名称</li><li>alpine：镜像名称</li><li>ping <a href="http://docker.com" target="_blank" rel="noopener">docker.com</a>：执行的命令等参数</li></ul><p>还有其它常用参数如：</p><ul><li>–publish：设置映射到外面的端口</li><li>–env：设置环境变量</li><li>–workdir：设置运行目录</li><li>–user：设置运行用户</li><li>–mode：设置任务模式</li><li>–network：创建overlay网络</li><li>–update-delay：设置更新时间间隔</li><li>–update-parallelism：设置同时更新的任务数，默认是1</li><li>–update-failure-action：设置更新失败后的行为，如continue</li></ul><p>具体查询–help或https://docs.docker.com/engine/reference/commandline/service_create/</p><p>配置挂载项：–mount</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></pre></td><td class="code"><pre><span class="line">docker service create --mount src=&lt;VOLUME-NAME&gt;,dst=&lt;CONTAINER-PATH&gt; --name myservice &lt;IMAGE&gt;</span><br><span class="line">docker service create --mount type=volume,src=&lt;VOLUME-NAME&gt;,dst=&lt;CONTAINER-PATH&gt;,volume-driver=&lt;DRIVER&gt;,volume-opt=&lt;KEY0&gt;=&lt;VALUE0&gt;,volume-opt=&lt;KEY1&gt;=&lt;VALUE1&gt; --name myservice &lt;IMAGE&gt;</span><br></pre></td></tr></table></figure><p>绑定挂载是指来自那些调度部署容器任务的主机文件系统路径，docker会挂载到容器内部的路径，这个文件系统路径必须在swarm初始化容器任务之前已存在,同时绑定挂载是有风险的，通常情况下不推荐使用，因为需要在每个机器上存在此挂载的文件系统路径，调度程序随时可能重新调度分配那些不健康或者无法连接的服务容器，并且此种挂载不能保证开发和生产一致。</p><figure class="highlight shell"><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">docker service create --mount type=bind,src=&lt;HOST-PATH&gt;,dst=&lt;CONTAINER-PATH&gt; --name myservice &lt;IMAGE&gt;</span><br><span class="line">docker service create --mount type=bind,src=&lt;HOST-PATH&gt;,dst=&lt;CONTAINER-PATH&gt;,readonly --name myservice &lt;IMAGE&gt;</span><br></pre></td></tr></table></figure><p><strong>7.查看服务状态</strong></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">docker service ls</span><br></pre></td></tr></table></figure><p><strong>8.查看服务详细信息</strong></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">docker service inspect --pretty helloworld</span><br></pre></td></tr></table></figure><ul><li>–pretty：以人性华(非json)方式显示，方便查看</li></ul><p><strong>9.查看有哪些节点运行此服务</strong></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">docker service ps helloworld</span><br></pre></td></tr></table></figure><p>也可在每个swarm节点上直接使用docker ps查看运行的容器</p><p><strong>10.变更服务任务数</strong>（只能在manager节点执行，可同时变更多个服务的任务数）</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">docker service scale &lt;SERVICE-ID&gt;=&lt;NUMBER-OF-TASKS&gt;</span><br></pre></td></tr></table></figure><p>例如：docker service scale helloworld=5表示实例数变更为5个</p><p><strong>11.删除服务</strong>（只能在manager节点执行）</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">docker service rm helloworld</span><br></pre></td></tr></table></figure><p>可通过docker service inspect helloworld确认是否删除</p><p><strong>12.滚动更新</strong></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">docker service update --image redis:3.0.7 redis</span><br></pre></td></tr></table></figure><p>默认更新步骤如下：<br>关闭第一个任务（实例）<br>开始在此关闭节点执行计划中的更新<br>更新完成后启动此任务<br>如果被更新的节点状态返回为RUNNING，等待指定的delay时间，然后停止下一个任务<br>如果，在更新的任意时间，任务返回FAILED，则暂停更新<br>更新完成后可以使用docker service inspect --pretty redis查看服务的images是否更新成功<br>若更新失败，使用docker service inspect --pretty <service-id>会显示失败，可重新使用docker service update <service-id>再次重启更新<br>使用docker service ps <service-id>可查看滚动更新</service-id></service-id></service-id></p><p><strong>13.停用节点</strong></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">docker node update --availability drain &lt;NODE-ID&gt;</span><br></pre></td></tr></table></figure><p>被信用的节点即不会再接受新的任务指派，也会停止节点上所有运行的任务，此节点上的服务状态会显示为Shutdown，且它的任务会被重新指派到新的可用节点上</p><p><strong>14.启用节点</strong></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">docker node update --availability active &lt;NODE-ID&gt;</span><br></pre></td></tr></table></figure><p>此时节点可以接受新的任务指派</p><p><strong>15.查看本地节点信息</strong></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">docker node inspect self --pretty</span><br></pre></td></tr></table></figure><p><strong>16.提升或者降职节点</strong></p><figure class="highlight shell"><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">docker node promote node-3 node-2</span><br><span class="line">docker node demote node-3 node-2</span><br></pre></td></tr></table></figure><p><strong>17.节点退出swarm</strong></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">docker swarm leave</span><br></pre></td></tr></table></figure><p>主管理节点退出时需要加–force<br>待节点退出后，可在任意管理节点从节点列表中删除掉此节点</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">docker node rm node-2</span><br></pre></td></tr></table></figure><p><strong>18.创建overlay网络</strong></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">docker network create --driver overlay my-network</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;&lt;strong&gt;1.初始化创建swarm&lt;/strong&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
      
    
    </summary>
    
      <category term="技术" scheme="http://www.whyvv.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="Docker" scheme="http://www.whyvv.top/tags/Docker/"/>
    
      <category term="swarm" scheme="http://www.whyvv.top/tags/swarm/"/>
    
      <category term="集群" scheme="http://www.whyvv.top/tags/%E9%9B%86%E7%BE%A4/"/>
    
  </entry>
  
  <entry>
    <title>Roy学Kubernetes(15)：Pod和Servicer的DNS</title>
    <link href="http://www.whyvv.top/k8s15.html"/>
    <id>http://www.whyvv.top/k8s15.html</id>
    <published>2019-08-07T01:30:00.000Z</published>
    <updated>2019-08-06T08:58:35.913Z</updated>
    
    <content type="html"><![CDATA[<p>Kubernetes为集群内的Pod和Service提供了DNS服务，它会自动配置kubelet以告知各个容器使用DNS服务的IP来解析集群内的DNS名称。集群中定义的每个Service服务（包括DNS服务器本身）都会分配一个DNS名称。 默认情况下，客户端Pod的DNS搜索列表将包含Pod自己的namespace和集群的默认域（默认是cluster.local）。所以同namespace内的Servie和Pod的DNS记录查询，可以省略namespace和默认域。</p><h1>Service</h1><p><strong>A记录</strong></p><ul><li>正常Service（非Headless Service）会以如下这种名字的形式被指派一个DNS A记录。此记录会解析成此Service的Cluster IP。</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">my-svc.my-namespace.svc.cluster.local</span><br></pre></td></tr></table></figure><ul><li><p>my-svc：你定义的Serive名</p></li><li><p>my-namespace：你定义的命名空间</p></li><li><p>Headless Service（没有Cluster IP）也会以如上相同命名的形式被指派一个DNS A记录。不同的是它会解析成该Service下所有Pod的IP组。如果客户端无法使用这一组IP，就会使用标准的round-robin策略从这一组IP中返回随机一个。</p></li></ul><p><strong>SRV记录</strong></p><p>可以为Service（包含Headless Service）命名（绑定）的端口需要创建SRV记录。对每个命名端口，SRV记录形式如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster.local</span><br></pre></td></tr></table></figure><ul><li>my-port-name：你命名（绑定）的port</li><li>my-port-protocol：port的协议，例如tcp/udp</li></ul><p>对于普通的Service，这会被解析成端口号和CNAME：my-svc.my-namespace.svc.cluster.local。 对于Headless Service，这会被解析成一组结果：Service对应的每个后端Pod各一个，包含auto-generated-name.my-svc.my-namespace.svc.cluster.local这种形式Pod的端口号和CNAME。</p><h1>Pod</h1><p><strong>A记录</strong></p><ul><li><p>当创建pod时，其主机名是Pod的metadata.name值。</p></li><li><p>Pod规范有一个可选的主机名字段，可用于指定Pod的主机名。指定后，它优先于Pod的名称作为pod的主机名。</p></li><li><p>Pod规范还有一个可选的子域字段，可用于指定其子域。例如，在命名空间“my-namespace”中，主机名设置为“foo”，子域设置为“bar”的Pod将具有完全限定的域名（FQDN）“foo.bar.my-namespace.svc。集群cluster.local”</p></li><li><p>如果在与pod相同的命名空间中存在无头服务且与子域名称相同，则集群的KubeDNS服务器还会返回Pod的完全限定主机名的A记录。 例如，给定主机名设置为“busybox-1”且子域设置为“default-subdomain”的Pod，以及同一名称空间中名为“default-subdomain”的无头服务，该pod将看到自己的FQDN为 “Busybox的1.default-subdomain.my-namespace.svc.cluster.local”。 DNS以该名称提供A记录，指向Pod的IP。pod“busybox1”和“busybox2”都可以拥有不同的A记录。</p></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Kubernetes为集群内的Pod和Service提供了DNS服务，它会自动配置kubelet以告知各个容器使用DNS服务的IP来解析集群内的DNS名称。集群中定义的每个Service服务（包括DNS服务器本身）都会分配一个DNS名称。 默认情况下，客户端Pod的DNS搜
      
    
    </summary>
    
      <category term="Kubernetes教程" scheme="http://www.whyvv.top/categories/Kubernetes%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Kubernetes" scheme="http://www.whyvv.top/tags/Kubernetes/"/>
    
      <category term="K8s" scheme="http://www.whyvv.top/tags/K8s/"/>
    
  </entry>
  
  <entry>
    <title>Roy学Kubernetes(14)：控制器之CronJob</title>
    <link href="http://www.whyvv.top/k8s14.html"/>
    <id>http://www.whyvv.top/k8s14.html</id>
    <published>2019-08-06T01:30:00.000Z</published>
    <updated>2019-08-06T02:28:58.136Z</updated>
    
    <content type="html"><![CDATA[<p>CronJob是基于时间的任务，和linux系统中的计划任务crontab同理。一个CronJob对象就像一行crontab（cron表）文件。 它以给定的时间表定期运行指定的任务，语法与crontab格式相同。（在Kubernetes1.4版本名为ScheduledJob，从1.5版本开始改成CronJob）</p><p>它的常用场景和crontab一样：</p><ul><li>在指定时间点执行Job</li><li>周期性执行Job</li></ul><h3 id="创建cronjob"><a class="header-anchor" href="#创建cronjob"></a>创建CronJob</h3><p>cronjob.yaml</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">batch/v1beta1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">CronJob</span>   <span class="comment"># 创建CronJob</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">hello</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  schedule:</span> <span class="string">"*/1 * * * *"</span></span><br><span class="line"><span class="attr">  concurrencyPolicy:</span> <span class="string">Allow</span>  <span class="comment"># 默认允许并发，可配置Forbid（禁止并发）、Replace（替换当前Job）并发策略</span></span><br><span class="line"><span class="attr">  jobTemplate:</span>  <span class="comment"># Job模板</span></span><br><span class="line"><span class="attr">    spec:</span></span><br><span class="line"><span class="attr">      template:</span></span><br><span class="line"><span class="attr">        spec:</span></span><br><span class="line"><span class="attr">          containers:</span></span><br><span class="line"><span class="attr">          - name:</span> <span class="string">hello</span></span><br><span class="line"><span class="attr">            image:</span> <span class="string">busybox</span></span><br><span class="line"><span class="attr">            args:</span></span><br><span class="line"><span class="bullet">            -</span> <span class="string">/bin/sh</span></span><br><span class="line"><span class="bullet">            -</span> <span class="bullet">-c</span></span><br><span class="line"><span class="bullet">            -</span> <span class="string">date;</span> <span class="string">echo</span> <span class="string">Hello</span> <span class="string">from</span> <span class="string">the</span> <span class="string">Kubernetes</span> <span class="string">cluster</span></span><br><span class="line"><span class="attr">          restartPolicy:</span> <span class="string">OnFailure</span></span><br></pre></td></tr></table></figure><p>创建</p><figure class="highlight shell"><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">[root@node1 ~]# kubectl create -f cronjob.yaml</span><br><span class="line">cronjob "hello" created</span><br></pre></td></tr></table></figure><p>也可以使用Kubectl run来创建一个CronJob，而不需要写yaml配置文件</p><figure class="highlight shell"><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">[root@node1 ~]# kubectl run hello --schedule="*/1 * * * *" --restart=OnFailure --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster"</span><br><span class="line">cronjob "hello" created</span><br></pre></td></tr></table></figure><p>创建后获取CronJob状态信息</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></pre></td><td class="code"><pre><span class="line">[root@node1 ~]# kubectl get cronjob hello</span><br><span class="line">NAME      SCHEDULE      SUSPEND   ACTIVE    LAST-SCHEDULE</span><br><span class="line">hello     */1 * * * *   False     0         &lt;none&gt;</span><br></pre></td></tr></table></figure><p>上述状态表示即没有active的Job，也没有被调度的Job。此时稍等约一分钟再看：</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></pre></td><td class="code"><pre><span class="line">[root@node1 ~]# kubectl get jobs --watch</span><br><span class="line">NAME               DESIRED   SUCCESSFUL   AGE</span><br><span class="line">hello-4111706356   1         1         2s</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line">[root@node1 ~]# kubectl get cronjob hello</span><br><span class="line">NAME      SCHEDULE      SUSPEND   ACTIVE    LAST-SCHEDULE</span><br><span class="line">hello     */1 * * * *   False     0         Mon, 29 Aug 2018 14:34:00 -0700</span><br></pre></td></tr></table></figure><p><code>LAST-SCHEDULE</code>表示此Job在指定的时间点已被调度。此时可查看最近一次调度的Pod执行的结果输出：</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></pre></td><td class="code"><pre><span class="line">[root@node1 ~]# pods=$(kubectl get pods --selector=job-name=hello-4111706356 --output=jsonpath=&#123;.items..metadata.name&#125;)</span><br><span class="line">[root@node1 ~]# echo $pods</span><br><span class="line">hello-4111706356-o9qcm</span><br><span class="line">[root@node1 ~]# kubectl logs $pods</span><br><span class="line">Mon Aug 29 21:34:09 UTC 2018</span><br><span class="line">Hello from the Kubernetes cluster</span><br></pre></td></tr></table></figure><h3 id="删除cronjob"><a class="header-anchor" href="#删除cronjob"></a>删除CronJob</h3><figure class="highlight shell"><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">[root@node1 ~]# kubectl delete cronjob hello</span><br><span class="line">cronjob "hello" deleted</span><br></pre></td></tr></table></figure><p>这将会终止正在创建的Job。但运行中的Job不会被终止，包括它的Pod。为了清理这些Job和Pod，需要列出该CronJob创建的全部Job并删除它们：</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></pre></td><td class="code"><pre><span class="line">[root@node1 ~]# kubectl get jobs</span><br><span class="line">NAME               DESIRED   SUCCESSFUL   AGE</span><br><span class="line">hello-1201907962   1         1            11m</span><br><span class="line">hello-1202039034   1         1            8m</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line">[root@node1 ~]# kubectl delete jobs hello-1201907962 hello-1202039034 ...</span><br><span class="line">job "hello-1201907962" deleted</span><br><span class="line">job "hello-1202039034" deleted</span><br><span class="line">...</span><br></pre></td></tr></table></figure><p>删除当前namespace下的所有job，可以使用<code>kubectl delete jobs --all</code>来操作。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;CronJob是基于时间的任务，和linux系统中的计划任务crontab同理。一个CronJob对象就像一行crontab（cron表）文件。 它以给定的时间表定期运行指定的任务，语法与crontab格式相同。（在Kubernetes1.4版本名为ScheduledJob
      
    
    </summary>
    
      <category term="Kubernetes教程" scheme="http://www.whyvv.top/categories/Kubernetes%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Kubernetes" scheme="http://www.whyvv.top/tags/Kubernetes/"/>
    
      <category term="K8s" scheme="http://www.whyvv.top/tags/K8s/"/>
    
  </entry>
  
  <entry>
    <title>Roy学Kubernetes(13)：控制器之Jobs</title>
    <link href="http://www.whyvv.top/k8s13.html"/>
    <id>http://www.whyvv.top/k8s13.html</id>
    <published>2019-08-05T01:30:00.000Z</published>
    <updated>2019-08-05T09:01:26.518Z</updated>
    
    <content type="html"><![CDATA[<p>Job创建一个或多个Pod并确保指定数量的Pod成功执行并终止。 当pod成功完成后，Job会跟踪任务完成情况。 达到指定数量的成功完成时，任务（即Job）完成。您还可以使用Job并行运行多个Pod。</p><p>一个简单的例子是创建一个Job任务对象，以便可靠地运行一个Pod来完成。 如果第一个Pod失败或被删除（例如由于节点硬件故障或节点重启），Job对象将启动一个新的Pod。</p><h3 id="job示例"><a class="header-anchor" href="#job示例"></a>Job示例</h3><p>job.yaml</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">batch/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Job</span>       <span class="comment"># 创建Job控制器</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">pi</span>      <span class="comment"># Job名</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  template:</span>     <span class="comment"># Pod模板</span></span><br><span class="line"><span class="attr">    spec:</span></span><br><span class="line"><span class="attr">      containers:</span>   <span class="comment"># 容器参数</span></span><br><span class="line"><span class="attr">      - name:</span> <span class="string">pi</span>    <span class="comment"># 容器名</span></span><br><span class="line"><span class="attr">        image:</span> <span class="string">perl</span> <span class="comment"># 镜像</span></span><br><span class="line"><span class="attr">        command:</span> <span class="string">["perl",</span>  <span class="string">"-Mbignum=bpi"</span><span class="string">,</span> <span class="string">"-wle"</span><span class="string">,</span> <span class="string">"print bpi(2000)"</span><span class="string">]</span>   <span class="comment"># 运行的Job任务命令</span></span><br><span class="line"><span class="attr">      restartPolicy:</span> <span class="string">Never</span>  <span class="comment"># 重启策略，仅支持Never和OnFailure</span></span><br><span class="line"><span class="attr">  backoffLimit:</span> <span class="number">4</span>   <span class="comment"># 决定失败之前的重试次数</span></span><br></pre></td></tr></table></figure><p>运行Job</p><figure class="highlight shell"><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">[root@node1 ~]# kubectl apply -f job.yaml</span><br><span class="line">job "pi" created</span><br></pre></td></tr></table></figure><p>查看job状态</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><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></pre></td><td class="code"><pre><span class="line">[root@node1 ~]# kubectl describe jobs/pi</span><br><span class="line">Name:             pi</span><br><span class="line">Namespace:        default</span><br><span class="line">Selector:         controller-uid=b1db589a-2c8d-11e6-b324-0209dc45a495</span><br><span class="line">Labels:           controller-uid=b1db589a-2c8d-11e6-b324-0209dc45a495</span><br><span class="line">                  job-name=pi</span><br><span class="line">Annotations:      &lt;none&gt;</span><br><span class="line">Parallelism:      1</span><br><span class="line">Completions:      1</span><br><span class="line">Start Time:       Tue, 07 Jun 2016 10:56:16 +0200</span><br><span class="line">Pods Statuses:    0 Running / 1 Succeeded / 0 Failed</span><br><span class="line">Pod Template:</span><br><span class="line">  Labels:       controller-uid=b1db589a-2c8d-11e6-b324-0209dc45a495</span><br><span class="line">                job-name=pi</span><br><span class="line">  Containers:</span><br><span class="line">   pi:</span><br><span class="line">    Image:      perl</span><br><span class="line">    Port:</span><br><span class="line">    Command:</span><br><span class="line">      perl</span><br><span class="line">      -Mbignum=bpi</span><br><span class="line">      -wle</span><br><span class="line">      print bpi(2000)</span><br><span class="line">    Environment:        &lt;none&gt;</span><br><span class="line">    Mounts:             &lt;none&gt;</span><br><span class="line">  Volumes:              &lt;none&gt;</span><br><span class="line">Events:</span><br><span class="line">  FirstSeen    LastSeen    Count    From            SubobjectPath    Type        Reason            Message</span><br><span class="line">  ---------    --------    -----    ----            -------------    --------    ------            -------</span><br><span class="line">  1m           1m          1        &#123;job-controller &#125;                Normal      SuccessfulCreate  Created pod: pi-dtn4q</span><br></pre></td></tr></table></figure><p>可通过kubectl get pods查看到成功完成Job的Pod。通过kubectl logs对应Pod名，可以获取此Pod的Job执行结果。</p><h3 id="并行jobs"><a class="header-anchor" href="#并行jobs"></a>并行Jobs</h3><p>Job有如下三类：</p><ol><li>非并行的任务</li></ol><ul><li>通常，只有一个Pod启动，除非Pod失败。</li><li>一旦Pod成功终止，任务就完成了。</li></ul><ol start="2"><li>指定完成数的并行任务：</li></ol><ul><li>为.spec.completions指定非零正值。</li><li>Job代表整体任务，当1到.spec.completions范围内的每个值都有一个成功的Pod时，它就完成了。</li></ul><ol start="3"><li>工作队列类的并行任务：</li></ol><ul><li>不要指定.spec.completions，默认为.spec.parallelism。</li><li>Pod必须在它们之间或外部服务之间进行协调，以确定每个应该工作的内容。</li><li>每个Pod能够独立地确定是否完成了所有对等操作，从而完成整个Job任务。</li><li>当Job中的任何Pod成功终止时，则不会创建新的Pod。</li><li>一旦至少一个Pod成功终止并且所有Pod终止，则任务成功完成。</li><li>一旦任何Pod退出成功，其他任何Pod都不会为此任务做任何工作或输出。因为他们都处于退出的过程中。</li></ul><p>对于非并行Job，您可以保留.spec.completions和.spec.parallelism。 当两者都未设置时，两者都默认为1</p><h3 id="job终止和清理"><a class="header-anchor" href="#job终止和清理"></a>Job终止和清理</h3><p>Job完成后，不会再创建Pod，但也不会删除Pod，保留Pod是为了完成后仍能查看它的日志。 Job对象在完成后也会保留，以便你可以查看其状态。删除 job可使用kubectl delete jobs（例如kubectl delete jobs pi或kubectl delete -f job.yaml），它创建的所有pod也将被删除。</p><p>默认情况下，除非Pod失败（restartPolicy = Never）或Container出错（restartPolicy = OnFailure），否则Job将不间断运行，此时Job一旦达到.spec.backoffLimit值，Job将被标记为失败，任何正在运行的Pod将被终止。</p><p>终止Job的另一种方法是设置活跃截止期。 通过将Job的.spec.activeDeadlineSeconds字段设置为秒数来执行此操作。 无论创建多少个Pod，<code>activeDeadlineSeconds</code>都应用于Job的持续时间。 一旦Job达到<code>activeDeadlineSeconds</code>，它的所有正在运行的Pod都将被终止，Job状态将变为type：Failed with reason：DeadlineExceeded。</p><p>请注意，Job的.spec.activeDeadlineSeconds优先于其.spec.backoffLimit。 因此，重试一个或多个失败的Pod的Job在达到<code>activeDeadlineSeconds</code>指定的时间限制后将不会部署其他Pod，即使尚未达到backoffLimit值也是如此。</p><p>配置示例：</p><figure class="highlight yml"><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"><span class="attr">apiVersion:</span> <span class="string">batch/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Job</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">pi-with-timeout</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  backoffLimit:</span> <span class="number">5</span></span><br><span class="line"><span class="attr">  activeDeadlineSeconds:</span> <span class="number">100</span></span><br><span class="line"><span class="attr">  template:</span></span><br><span class="line"><span class="attr">    spec:</span></span><br><span class="line"><span class="attr">      containers:</span></span><br><span class="line"><span class="attr">      - name:</span> <span class="string">pi</span></span><br><span class="line"><span class="attr">        image:</span> <span class="string">perl</span></span><br><span class="line"><span class="attr">        command:</span> <span class="string">["perl",</span>  <span class="string">"-Mbignum=bpi"</span><span class="string">,</span> <span class="string">"-wle"</span><span class="string">,</span> <span class="string">"print bpi(2000)"</span><span class="string">]</span></span><br><span class="line"><span class="attr">      restartPolicy:</span> <span class="string">Never</span></span><br></pre></td></tr></table></figure><p>系统中通常不再需要完成的Job。 将它们保留在系统中会给API服务器带来压力。 如果Job由更高级别的控制器（如CronJobs）直接管理，CronJobs可以根据指定的基于容量的清理策略清理Job。</p><p>可为Job指定成功后的TTL生命周期</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">batch/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Job</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr">  name:</span> <span class="string">pi-with-ttl</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr">  ttlSecondsAfterFinished:</span> <span class="number">100</span></span><br><span class="line"><span class="attr">  template:</span></span><br><span class="line"><span class="attr">    spec:</span></span><br><span class="line"><span class="attr">      containers:</span></span><br><span class="line"><span class="attr">      - name:</span> <span class="string">pi</span></span><br><span class="line"><span class="attr">        image:</span> <span class="string">perl</span></span><br><span class="line"><span class="attr">        command:</span> <span class="string">["perl",</span>  <span class="string">"-Mbignum=bpi"</span><span class="string">,</span> <span class="string">"-wle"</span><span class="string">,</span> <span class="string">"print bpi(2000)"</span><span class="string">]</span></span><br><span class="line"><span class="attr">      restartPolicy:</span> <span class="string">Never</span></span><br></pre></td></tr></table></figure><p>上述配置表示Job pi-with-ttl将在完成后100秒自动删除。如果该字段设置为0，则Job将在完成后立即自动删除。 如果未设置该字段，则TTL控制器完成后将不会清除此Job。</p><p>请注意，此TTL机制是alpha功能参数，在Kubernetes v1.12版本中才引入。</p><p>你可以使用CronJob创建一个将在指定时间/日期运行的Job，类似于Unix工具crontab，我会在后面篇章详细讲解CronJob。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Job创建一个或多个Pod并确保指定数量的Pod成功执行并终止。 当pod成功完成后，Job会跟踪任务完成情况。 达到指定数量的成功完成时，任务（即Job）完成。您还可以使用Job并行运行多个Pod。&lt;/p&gt;
&lt;p&gt;一个简单的例子是创建一个Job任务对象，以便可靠地运行一个
      
    
    </summary>
    
      <category term="Kubernetes教程" scheme="http://www.whyvv.top/categories/Kubernetes%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Kubernetes" scheme="http://www.whyvv.top/tags/Kubernetes/"/>
    
      <category term="K8s" scheme="http://www.whyvv.top/tags/K8s/"/>
    
  </entry>
  
  <entry>
    <title>EFK收集nginx日志并展示来源IP地图</title>
    <link href="http://www.whyvv.top/efk.html"/>
    <id>http://www.whyvv.top/efk.html</id>
    <published>2019-08-01T05:00:00.000Z</published>
    <updated>2019-08-01T07:52:50.837Z</updated>
    
    <content type="html"><![CDATA[<h3 id="格式化nginx日志"><a class="header-anchor" href="#格式化nginx日志"></a>格式化nginx日志</h3><p>首先，为了方便收集nginx日志，先格式化nginx日志为json，打开nginx.conf配置文件，在http{}中添加如下日志格式化参数</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">log_format logstash_json '&#123; "@fields": &#123; '</span><br><span class="line">                         '"@timestamp": "$time_iso8601", '</span><br><span class="line">                         '"remote_addr": "$remote_addr", '</span><br><span class="line">                         '"remote_user": "$remote_user", '</span><br><span class="line">                         '"body_bytes_sent": "$body_bytes_sent", '</span><br><span class="line">                         '"request_time": "$request_time", '</span><br><span class="line">                         '"http_device_id": "$http_device_id", '</span><br><span class="line">                         '"http_client_type": "$http_client_type",'</span><br><span class="line">                         '"http_device_name":"$http_device_name",'</span><br><span class="line">                         '"status": "$status", '</span><br><span class="line">                         '"request": "$request", '</span><br><span class="line">                         '"request_method": "$request_method", '</span><br><span class="line">                         '"host": "$host", '</span><br><span class="line">                         '"server_port": "$server_port", '</span><br><span class="line">                         '"http_referrer": "$http_referer", '</span><br><span class="line">                         '"body_bytes_sent":"$body_bytes_sent", '</span><br><span class="line">                         '"http_x_forwarded_for": "$http_x_forwarded_for", '</span><br><span class="line">                         '"http_user_agent": "$http_user_agent" &#125; &#125;';</span><br></pre></td></tr></table></figure><p>其次，在站点配置中引用，如下示例</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">access_log  logs/access.log logstash_json;</span><br></pre></td></tr></table></figure><h3 id="fluentd添加地图库插件fluent-plugin-geoip"><a class="header-anchor" href="#fluentd添加地图库插件fluent-plugin-geoip"></a>Fluentd添加地图库插件fluent-plugin-geoip</h3><p><a href="https://github.com/y-ken/fluent-plugin-geoip" target="_blank" rel="noopener">插件地址</a>，以下为CentOS7的安装</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></pre></td><td class="code"><pre><span class="line">yum groupinstall "Development Tools"</span><br><span class="line">yum install geoip-devel --enablerepo=epel</span><br><span class="line">td-agent-gem install fluent-plugin-geoip</span><br></pre></td></tr></table></figure><p>在<a href="https://dev.maxmind.com/geoip/legacy/geolite/" target="_blank" rel="noopener">GeoIP官网</a>下载免费地图数据库包(GeoLite City即可)，解压并放在路径/etc/td-agent/下，假设文件名为GeoLiteCity.dat</p><h3 id="fluentd添加geoip配置信息"><a class="header-anchor" href="#fluentd添加geoip配置信息"></a>Fluentd添加geoip配置信息</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><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> Parse IP to Geo</span><br><span class="line">&lt;filter nginx**&gt;</span><br><span class="line">  @type geoip</span><br><span class="line"></span><br><span class="line"><span class="meta">  #</span> Specify one or more geoip lookup field which has ip address (default: host)</span><br><span class="line"><span class="meta">  #</span> in the case of accessing nested value, delimit keys by dot like 'host.ip'.</span><br><span class="line">  geoip_lookup_keys @fields.remote_addr</span><br><span class="line"></span><br><span class="line"><span class="meta">  #</span> Specify optional geoip database (using bundled GeoLiteCity databse by default)</span><br><span class="line">  geoip_database    "/etc/td-agent/GeoLiteCity.dat"</span><br><span class="line"><span class="meta">  #</span> Specify optional geoip2 database</span><br><span class="line"><span class="meta">  #</span> geoip2_database   "/path/to/your/GeoLite2-City.mmdb" (using bundled GeoLite2-City.mmdb by default)</span><br><span class="line"><span class="meta">  #</span> Specify backend library (geoip2_c, geoip, geoip2_compat)</span><br><span class="line">  backend_library geoip2_c</span><br><span class="line"></span><br><span class="line"><span class="meta">  #</span> Set adding field with placeholder (more than one settings are required.)</span><br><span class="line">  &lt;record&gt;</span><br><span class="line">    city            $&#123;city.names.en["@fields.remote_addr"]&#125;</span><br><span class="line">    #latitude        $&#123;location.latitude["@fields.remote_addr"]&#125;</span><br><span class="line">    #longitude       $&#123;location.longitude["@fields.remote_addr"]&#125;</span><br><span class="line">    location       '[$&#123;location.longitude["@fields.remote_addr"]&#125;,$&#123;location.latitude["@fields.remote_addr"]&#125;]'</span><br><span class="line">    country         $&#123;country.iso_code["@fields.remote_addr"]&#125;</span><br><span class="line">    country_name    $&#123;country.names.en["@fields.remote_addr"]&#125;</span><br><span class="line">    #postal_code     $&#123;postal.code["@fields.remote_addr"]&#125;</span><br><span class="line">  &lt;/record&gt;</span><br><span class="line"></span><br><span class="line"><span class="meta">  #</span> To avoid get stacktrace error with `[null, null]` array for elasticsearch.</span><br><span class="line">  skip_adding_null_record  true</span><br><span class="line"></span><br><span class="line"><span class="meta">  #</span> Set @log_level (default: warn)</span><br><span class="line">  @log_level         info</span><br><span class="line">&lt;/filter&gt;</span><br></pre></td></tr></table></figure><h3 id="修改location字段默认类型为geo-point"><a class="header-anchor" href="#修改location字段默认类型为geo-point"></a>修改location字段默认类型为geo_point</h3><p>先不要启动fluentd，需要在elasticsearch未生成nginx的索引日志时，将location字段的默认类型个性为geo_point(若不修改，默认会是float，无法生成地图数据)；直接在kibana的Dev Tools中执行如下命令(索引根据实际情况)</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">PUT _template/logstash-nginx-*</span><br><span class="line">&#123;</span><br><span class="line">  "template": "logstash-nginx-*",</span><br><span class="line">  "mappings": &#123;</span><br><span class="line">    "_default_": &#123;</span><br><span class="line">      "properties" : &#123;</span><br><span class="line">        "location": &#123; "type": "geo_point"&#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后开启nginx的日志收集</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">service td-agent start/restart</span><br></pre></td></tr></table></figure><h3 id="然后在kibana中直接创建tile-map即可"><a class="header-anchor" href="#然后在kibana中直接创建tile-map即可"></a>然后在kibana中直接创建Tile Map即可</h3><p>默认地图全是英文名称，要添加高德中文名称地图支持，在kibana.yaml文件最后添加如下一行配置，并重启kibana即可</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">tilemap.url: 'http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&amp;size=1&amp;scale=1&amp;style=7&amp;x=&#123;x&#125;&amp;y=&#123;y&#125;&amp;z=&#123;z&#125;'</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;格式化nginx日志&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#格式化nginx日志&quot;&gt;&lt;/a&gt;格式化nginx日志&lt;/h3&gt;
&lt;p&gt;首先，为了方便收集nginx日志，先格式化nginx日志为json，打开nginx.conf配置文件，在h
      
    
    </summary>
    
      <category term="技术" scheme="http://www.whyvv.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="Fluentd" scheme="http://www.whyvv.top/tags/Fluentd/"/>
    
      <category term="ELK/EFK" scheme="http://www.whyvv.top/tags/ELK-EFK/"/>
    
      <category term="日志收集" scheme="http://www.whyvv.top/tags/%E6%97%A5%E5%BF%97%E6%94%B6%E9%9B%86/"/>
    
  </entry>
  
</feed>
