<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Jay Chang&#39;s Blog</title>
  
  <subtitle>我的技术博客</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://jaychang.cn/"/>
  <updated>2023-04-17T13:26:23.243Z</updated>
  <id>http://jaychang.cn/</id>
  
  <author>
    <name>Jay Chang</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Ubuntu20.04 源码安装APISIX-2.15.x Dashboard</title>
    <link href="http://jaychang.cn/2023/04/17/buntu20-04-%E6%BA%90%E7%A0%81%E5%AE%89%E8%A3%85APISIX-2-15-x-Dashboard/"/>
    <id>http://jaychang.cn/2023/04/17/buntu20-04-源码安装APISIX-2-15-x-Dashboard/</id>
    <published>2023-04-17T13:26:18.000Z</published>
    <updated>2023-04-17T13:26:23.243Z</updated>
    
    <content type="html"><![CDATA[<p>[TOC]</p><h1 id="nodejs及go环境准备"><a href="#nodejs及go环境准备" class="headerlink" title="nodejs及go环境准备"></a>nodejs及go环境准备</h1><h2 id="安装nodejs"><a href="#安装nodejs" class="headerlink" title="安装nodejs"></a>安装nodejs</h2><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">wget https://nodejs.org/download/release/v14.21.3/node-v14.21.3-linux-x64.tar.gz</span><br><span class="line">tar xzvf node-v14.21.3-linux-x64.tar.gz -C /opt</span><br><span class="line">mv /opt/node-v14.21.3-linux-x64/ /opt/node/</span><br></pre></td></tr></table></figure><blockquote><p>注意nodejs版本不能过高，试过node18构建会报错，建议版本node14~node16</p></blockquote><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">tee -a /etc/profile &lt;&lt; EOF</span><br><span class="line">export NODE_HOME=/opt/node</span><br><span class="line">export PATH=$PATH:$NODE_HOME/bin</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><p>使环境变量生效<br><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">source /etc/profile</span><br></pre></td></tr></table></figure></p><p>安装yarn<br><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">npm install -g yarn</span><br></pre></td></tr></table></figure></p><h2 id="安装go"><a href="#安装go" class="headerlink" title="安装go"></a>安装go</h2><p><a href="https://mirrors.aliyun.com/golang/可以找需要的版本" target="_blank" rel="noopener">https://mirrors.aliyun.com/golang/可以找需要的版本</a><br><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://mirrors.aliyun.com/golang/go1.20.3.linux-amd64.tar.gz</span><br><span class="line">tar xzvf go1.20.3.linux-amd64.tar.gz -C /opt/</span><br></pre></td></tr></table></figure></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">tee -a /etc/profile &lt;&lt; EOF</span><br><span class="line">export GO_HOME=/opt/go</span><br><span class="line">export PATH=$PATH:$GO_HOME/bin</span><br><span class="line">go env -w GO111MODULE=on</span><br><span class="line">go env -w GOPROXY=https://goproxy.cn,direct</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><p>使环境变量生效<br><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">source /etc/profile</span><br></pre></td></tr></table></figure></p><h1 id="安装APISIX-Dashboard"><a href="#安装APISIX-Dashboard" class="headerlink" title="安装APISIX Dashboard"></a>安装APISIX Dashboard</h1><h2 id="下载源码"><a href="#下载源码" class="headerlink" title="下载源码"></a>下载源码</h2><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">wget https://github.com/apache/apisix-dashboard/archive/refs/tags/v2.15.1.tar.gz</span><br></pre></td></tr></table></figure><h2 id="解压源码"><a href="#解压源码" class="headerlink" title="解压源码"></a>解压源码</h2><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">tar xzvf v2.15.1.tar.gz</span><br><span class="line"></span><br><span class="line">cd apisix-dashboard-2.15.1</span><br></pre></td></tr></table></figure><h2 id="构建"><a href="#构建" class="headerlink" title="构建"></a>构建</h2><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">make build</span><br></pre></td></tr></table></figure><p>构建完成会打印以下内容，估计要7分钟左右<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">其他省略...</span><br><span class="line"></span><br><span class="line">The bundle size is significantly larger than recommended.</span><br><span class="line">Consider reducing it with code splitting: https://umijs.org/docs/load-on-demand</span><br><span class="line">You can also analyze the project dependencies using ANALYZE=1</span><br><span class="line"></span><br><span class="line">Done in 433.32s.</span><br></pre></td></tr></table></figure></p><p>编译完将output拷贝到/opt/apisix-dashboard<br><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">mkdir -p mkdir -p /usr/local/apisix/dashboard &amp;&amp; cp -r ./output/* /usr/local/apisix/dashboard</span><br></pre></td></tr></table></figure></p><h2 id="修改配置"><a href="#修改配置" class="headerlink" title="修改配置"></a>修改配置</h2><p>如果是http访问etcd仅需配置ectd的访问地址即可</p><p>如果是https访问etcd则需要相关证书</p><p>将根证书，etcd-server-key证书，etcd-server证书拷贝到apisix目录下</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">mkdir -p /usr/local/apisix/ssl</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 根据具体情况即可</span><br><span class="line">cp /opt/etcd3/ssl/&#123;etcd-ca.pem,etcd-server-key.pem,etcd-server.pem&#125; /usr/local/apisix/ssl/</span><br></pre></td></tr></table></figure><p>修改vi /usr/local/apisix/dashboard/conf/conf.yaml</p><figure class="highlight yaml"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 其余省略...</span></span><br><span class="line"><span class="attr">  etcd:</span></span><br><span class="line"><span class="attr">    endpoints:</span>            <span class="comment"># supports defining multiple etcd host addresses for an etcd cluster</span></span><br><span class="line"><span class="bullet">      -</span> <span class="number">10.1</span><span class="number">.80</span><span class="number">.91</span><span class="string">:2379</span></span><br><span class="line"><span class="bullet">      -</span> <span class="number">10.1</span><span class="number">.80</span><span class="number">.92</span><span class="string">:2379</span></span><br><span class="line"><span class="bullet">      -</span> <span class="number">10.1</span><span class="number">.80</span><span class="number">.93</span><span class="string">:2379</span></span><br><span class="line">                          <span class="comment"># yamllint disable rule:comments-indentation</span></span><br><span class="line">                          <span class="comment"># etcd basic auth info</span></span><br><span class="line">    <span class="comment"># username: "root"    # ignore etcd username if not enable etcd auth</span></span><br><span class="line">    <span class="comment"># password: "123456"  # ignore etcd password if not enable etcd auth</span></span><br><span class="line"><span class="attr">    mtls:</span></span><br><span class="line"><span class="attr">      key_file:</span> <span class="string">"/usr/local/apisix/ssl/etcd-server-key.pem"</span>  <span class="comment"># Path of your self-signed client side key</span></span><br><span class="line"><span class="attr">      cert_file:</span> <span class="string">"/usr/local/apisix/ssl/etcd-server.pem"</span>     <span class="comment"># Path of your self-signed client side cert</span></span><br><span class="line"><span class="attr">      ca_file:</span> <span class="string">"/usr/local/apisix/ssl/etcd-ca.pem"</span>           <span class="comment"># Path of your self-signed ca cert, the CA is used to sign callers' certificates</span></span><br><span class="line">    <span class="comment"># prefix: /apisix       # apisix config's prefix in etcd, /apisix by default</span></span><br><span class="line"><span class="comment"># 其余省略...</span></span><br></pre></td></tr></table></figure><h1 id="运行APISIX-DASHBOARD"><a href="#运行APISIX-DASHBOARD" class="headerlink" title="运行APISIX DASHBOARD"></a>运行APISIX DASHBOARD</h1><p>frontend方式运行apisix-dashboard(不推荐)<br><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">cd /usr/local/apisix/dashboard</span><br><span class="line">./manager-api</span><br></pre></td></tr></table></figure></p><p>安装为系统服务(推荐)<br><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">tee /usr/lib/systemd/system/apisix-dashboard.service &lt;&lt; EOF</span><br><span class="line">[Unit]</span><br><span class="line">Description=apisix-dashboard</span><br><span class="line">Conflicts=apisix-dashboard.service</span><br><span class="line">After=network-online.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">WorkingDirectory=/usr/local/apisix/dashboard</span><br><span class="line">ExecStart=/usr/local/apisix/dashboard/manager-api -c /usr/local/apisix/dashboard/conf/conf.yaml</span><br><span class="line"></span><br><span class="line">EOF</span><br></pre></td></tr></table></figure></p><p>服务管理<br><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> reload下</span><br><span class="line">systemctl daemon-reload</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> enable apisix-dashboard</span><br><span class="line">systemctl enable apisix-dashboard</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> start apisix-dashboard</span><br><span class="line">systemctl start apisix-dashboard</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> stop apisix-dashboard</span><br><span class="line">systemctl stop apisix-dashboard</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> check apisix-dashboard status</span><br><span class="line">systemctl status apisix-dashboard</span><br></pre></td></tr></table></figure></p><p>访问<a href="http://10.1.80.91:9000/" target="_blank" rel="noopener">http://10.1.80.91:9000/</a></p><p>若出现以下错误，需要将您的机器IP加入白名单，修改conf.yaml将IP地址或IP网段加入到allow_list内即可<br><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">&#123;</span><br><span class="line">    Code: 20002,</span><br><span class="line">    Message: "IP address not allowed",</span><br><span class="line">    Data: null,</span><br><span class="line">    SourceSrv: ""</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>修改vi /usr/local/apisix/dashboard/conf/conf.yaml，加入允许访问的网段即可<br><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 其余省略...</span></span><br><span class="line"><span class="attr">  allow_list:</span>             <span class="comment"># If we don't set any IP list, then any IP access is allowed by default.</span></span><br><span class="line"><span class="bullet">    -</span> <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>           <span class="comment"># The rules are checked in sequence until the first match is found.</span></span><br><span class="line"><span class="bullet">    -</span> <span class="number">10.1</span><span class="number">.80</span><span class="number">.0</span><span class="string">/24</span>        <span class="comment"># The rules are checked in sequence until the first match is found.</span></span><br><span class="line"><span class="bullet">    -</span> <span class="string">::1</span>                 <span class="comment"># In this example, access is allowed only for IPv4 network 127.0.0.1, and for IPv6 network ::1.</span></span><br><span class="line">                          <span class="comment"># It also support CIDR like 192.168.1.0/24 and 2001:0db8::/32</span></span><br><span class="line"><span class="comment"># 其余省略...</span></span><br></pre></td></tr></table></figure></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;[TOC]&lt;/p&gt;
&lt;h1 id=&quot;nodejs及go环境准备&quot;&gt;&lt;a href=&quot;#nodejs及go环境准备&quot; class=&quot;headerlink&quot; title=&quot;nodejs及go环境准备&quot;&gt;&lt;/a&gt;nodejs及go环境准备&lt;/h1&gt;&lt;h2 id=&quot;安装nodejs
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Ubuntu20.04 源码安装APISIX-2.15.3</title>
    <link href="http://jaychang.cn/2023/04/17/buntu20-04-%E6%BA%90%E7%A0%81%E5%AE%89%E8%A3%85APISIX-2-15-3/"/>
    <id>http://jaychang.cn/2023/04/17/buntu20-04-源码安装APISIX-2-15-3/</id>
    <published>2023-04-17T13:25:39.000Z</published>
    <updated>2023-04-17T13:25:43.854Z</updated>
    
    <content type="html"><![CDATA[<p>[TOC]</p><h1 id="OpenResty源码安装"><a href="#OpenResty源码安装" class="headerlink" title="OpenResty源码安装"></a>OpenResty源码安装</h1><h2 id="安装前准备"><a href="#安装前准备" class="headerlink" title="安装前准备"></a>安装前准备</h2><p>您必须将这些库 perl 5.6.1+, libpcre, libssl安装在您的电脑之中。 对于 Linux来说, 您需要确认使用 ldconfig 命令，让其在您的系统环境路径中能找到它们。</p><p>以下安装的内容就是取自<a href="https://raw.githubusercontent.com/apache/apisix/master/utils/linux-install-luarocks.sh(master可以替换为具体版本号" target="_blank" rel="noopener">https://raw.githubusercontent.com/apache/apisix/master/utils/linux-install-luarocks.sh(master可以替换为具体版本号</a>)<br><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">sudo apt-get install make gcc g++ build-essential curl unzip</span><br><span class="line">sudo apt-get install -y libssl-dev perl zlib1g-dev libpcre3 libpcre3-dev libldap2-dev libpq-dev</span><br></pre></td></tr></table></figure></p><h2 id="编译安装OpenResty"><a href="#编译安装OpenResty" class="headerlink" title="编译安装OpenResty"></a>编译安装OpenResty</h2><p>下载，解压openresty-$VERSION.tar.gz<br><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">mkdir -p /opt/src &amp;&amp; cd /opt/src</span><br><span class="line">curl -O https://openresty.org/download/openresty-1.21.4.1.tar.gz</span><br><span class="line">tar xzvf openresty-1.21.4.1.tar.gz -C /opt/src</span><br><span class="line">cd /opt/src/openresty-1.21.4.1</span><br></pre></td></tr></table></figure></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></pre></td><td class="code"><pre><span class="line">./configure --prefix=/usr/local/openresty \</span><br><span class="line">    --with-poll_module \</span><br><span class="line">    --with-pcre-jit \</span><br><span class="line">    --without-http_rds_json_module \</span><br><span class="line">    --without-http_rds_csv_module \</span><br><span class="line">    --without-lua_rds_parser \</span><br><span class="line">    --with-stream \</span><br><span class="line">    --with-stream_ssl_module \</span><br><span class="line">    --with-stream_ssl_preread_module \</span><br><span class="line">    --with-http_v2_module \</span><br><span class="line">    --without-mail_pop3_module \</span><br><span class="line">    --without-mail_imap_module \</span><br><span class="line">    --without-mail_smtp_module \</span><br><span class="line">    --with-http_stub_status_module \</span><br><span class="line">    --with-http_realip_module \</span><br><span class="line">    --with-http_addition_module \</span><br><span class="line">    --with-http_auth_request_module \</span><br><span class="line">    --with-http_secure_link_module \</span><br><span class="line">    --with-http_random_index_module \</span><br><span class="line">    --with-http_gzip_static_module \</span><br><span class="line">    --with-http_sub_module \</span><br><span class="line">    --with-http_dav_module \</span><br><span class="line">    --with-http_flv_module \</span><br><span class="line">    --with-http_mp4_module \</span><br><span class="line">    --with-http_gunzip_module \</span><br><span class="line">    --with-threads \</span><br><span class="line">    --with-compat \</span><br><span class="line">    -j`nproc`</span><br></pre></td></tr></table></figure><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">make -j`nproc` &amp;&amp; make install</span><br></pre></td></tr></table></figure><h2 id="安装OpenResty的相关组件"><a href="#安装OpenResty的相关组件" class="headerlink" title="安装OpenResty的相关组件"></a>安装OpenResty的相关组件</h2><p>openresty-openssl111-dev openresty-pcre-dev openresty-zlib-dev</p><p>我们应该通过添加 GPG 公钥来安装一些需要的组件。这些可以在之后删除</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">sudo apt-get -y install --no-install-recommends wget gnupg ca-certificates</span><br></pre></td></tr></table></figure><p>然后导入openresty的 GPG 密钥<br><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">wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -</span><br></pre></td></tr></table></figure></p><p>接着添加 openresty 的官方 APT 库</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">echo "deb https://openresty.org/package/ubuntu $(lsb_release -sc) main" &gt; openresty.list</span><br><span class="line">sudo cp openresty.list /etc/apt/sources.list.d/</span><br></pre></td></tr></table></figure><p>请注意，这是针对 x86_64 或 amd64 系统的</p><p>对于 Aarch64 或 ARM64 系统，你应该使用这个 URL 来代替</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">echo "deb https://openresty.org/package/arm64/ubuntu $(lsb_release -sc) main"</span><br></pre></td></tr></table></figure><p>现在更新 APT 索引<br><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">sudo apt-get update</span><br></pre></td></tr></table></figure></p><p>安装 Openrety 相关组件<br><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">sudo apt-get -y install openresty-openssl111-dev openresty-pcre-dev openresty-zlib-dev</span><br></pre></td></tr></table></figure></p><blockquote><p>安装完会生成/usr/local/openresty目录，且/usr/local/openresty/openssl111,/usr/local/openresty/pcre,/usr/local/openresty/zlib这子目录会在该目录下。</p></blockquote><h2 id="安装luarocks"><a href="#安装luarocks" class="headerlink" title="安装luarocks"></a>安装luarocks</h2><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">wget https://luarocks.org/releases/luarocks-3.8.0.tar.gz</span><br><span class="line">tar -xzvf luarocks-3.8.0.tar.gz</span><br><span class="line">cd luarocks-3.8.0</span><br><span class="line"></span><br><span class="line">./configure --prefix=/usr/local/openresty/luajit \</span><br><span class="line">--with-lua=/usr/local/openresty/luajit/ \</span><br><span class="line">--lua-suffix=jit \</span><br><span class="line">--with-lua-include=/usr/local/openresty/luajit/include/luajit-2.1</span><br><span class="line"></span><br><span class="line">make &amp;&amp; make install</span><br></pre></td></tr></table></figure><p>结果如下<br><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></pre></td><td class="code"><pre><span class="line">root@s91:/opt/src/apisix-3.2.0/utils/luarocks-3.8.0# ./configure --prefix=/usr/local/openresty/luajit \</span><br><span class="line"><span class="meta">&gt;</span> --with-lua=/usr/local/openresty/luajit/ \</span><br><span class="line"><span class="meta">&gt;</span> --lua-suffix=jit \</span><br><span class="line"><span class="meta">&gt;</span> --with-lua-include=/usr/local/openresty/luajit/include/luajit-2.1</span><br><span class="line">--lua-suffix is no longer necessary.</span><br><span class="line">The suffix is automatically detected.</span><br><span class="line"></span><br><span class="line">Configuring LuaRocks version 3.8.0...</span><br><span class="line"></span><br><span class="line">Lua version detected: 5.1</span><br><span class="line">Lua interpreter found: /usr/local/openresty/luajit/bin/luajit</span><br><span class="line">lua.h found: /usr/local/openresty/luajit/include/luajit-2.1/lua.h</span><br><span class="line">unzip found in PATH: /usr/bin</span><br><span class="line"></span><br><span class="line">Done configuring.</span><br><span class="line"></span><br><span class="line">LuaRocks will be installed at......: /usr/local/openresty/luajit</span><br><span class="line">LuaRocks will install rocks at.....: /usr/local/openresty/luajit</span><br><span class="line">LuaRocks configuration directory...: /usr/local/openresty/luajit/etc/luarocks</span><br><span class="line">Using Lua from.....................: /usr/local/openresty/luajit</span><br><span class="line">Lua include directory..............: /usr/local/openresty/luajit/include/luajit-2.1</span><br><span class="line"></span><br><span class="line">* Type make and make install:</span><br><span class="line">  to install to /usr/local/openresty/luajit as usual.</span><br><span class="line">* Type make bootstrap:</span><br><span class="line">  to install LuaRocks into /usr/local/openresty/luajit as a rock.</span><br></pre></td></tr></table></figure></p><p>设置环境变量<br><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">vi /etc/profile</span><br></pre></td></tr></table></figure></p><p>/etc/profile文件最后添加如下代码<br><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">export OPENRESTY_HOME=/usr/local/openresty</span><br><span class="line">export PATH=$PATH:$OPENRESTY_HOME/bin:$OPENRESTY_HOME/luajit/bin</span><br></pre></td></tr></table></figure></p><p>使得环境变量生效<br><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">source /etc/profile</span><br></pre></td></tr></table></figure></p><h2 id="重构Openresty"><a href="#重构Openresty" class="headerlink" title="重构Openresty"></a>重构Openresty</h2><p>主要是为了加一些apisix所需的模块</p><pre><code>To enable etcd client certificate you need to build APISIX-Base, seehttps://apisix.apache.org/docs/apisix/FAQ#how-do-i-build-the-apisix-base-environment</code></pre><p><a href="https://raw.githubusercontent.com/api7/apisix-build-tools/apisix/2.5.13/build-apisix-base.sh" target="_blank" rel="noopener">apisix提供的openresty构建脚本</a><br>我将版本改为2.5.13，即version=${version:-0.0.0}改为了version=2.5.13。<br>由于git clone经常出问题(github不稳定，翻墙会好一些)，我改了下脚本，可以先将需要的包都下载下来(所需的源码包百度网盘下载)[<a href="https://pan.baidu.com/s/1X8U4_pIL86QH3wJuhrv6LQ?pwd=k8sl" target="_blank" rel="noopener">https://pan.baidu.com/s/1X8U4_pIL86QH3wJuhrv6LQ?pwd=k8sl</a>]</p><p>可以提前将下载好的安装包放到构建脚本同目录下，构建脚本内容如下,我处理了下：1.有些解压出来不带v，但是文件名带v 2.解压出来是大写的。这两种情况<br><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><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>!/usr/bin/env bash</span><br><span class="line">set -euo pipefail</span><br><span class="line">set -x</span><br><span class="line"></span><br><span class="line">version=$&#123;version:-2.15.3&#125;</span><br><span class="line"></span><br><span class="line">if ([ $# -gt 0 ] &amp;&amp; [ "$1" == "latest" ]) || [ "$version" == "latest" ]; then</span><br><span class="line">    ngx_multi_upstream_module_ver="master"</span><br><span class="line">    mod_dubbo_ver="master"</span><br><span class="line">    apisix_nginx_module_ver="main"</span><br><span class="line">    wasm_nginx_module_ver="main"</span><br><span class="line">    lua_var_nginx_module_ver="master"</span><br><span class="line">    grpc_client_nginx_module_ver="main"</span><br><span class="line">    amesh_ver="main"</span><br><span class="line">    debug_args="--with-debug"</span><br><span class="line">    OR_PREFIX=$&#123;OR_PREFIX:="/usr/local/openresty-debug"&#125;</span><br><span class="line">else</span><br><span class="line">    ngx_multi_upstream_module_ver="1.1.1"</span><br><span class="line">    mod_dubbo_ver="1.0.2"</span><br><span class="line">    apisix_nginx_module_ver="1.12.0"</span><br><span class="line">    wasm_nginx_module_ver="0.6.4"</span><br><span class="line">    lua_var_nginx_module_ver="v0.5.3"</span><br><span class="line">    grpc_client_nginx_module_ver="v0.4.2"</span><br><span class="line">    amesh_ver="main"</span><br><span class="line">    debug_args=$&#123;debug_args:-&#125;</span><br><span class="line">    OR_PREFIX=$&#123;OR_PREFIX:="/usr/local/openresty"&#125;</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">prev_workdir="$PWD"</span><br><span class="line">repo=$(basename "$prev_workdir")</span><br><span class="line">workdir=$(mktemp -d)</span><br><span class="line">cd "$workdir" || exit 1</span><br><span class="line"></span><br><span class="line">or_ver="1.21.4.1"</span><br><span class="line">wget --no-check-certificate https://openresty.org/download/openresty-$&#123;or_ver&#125;.tar.gz</span><br><span class="line">tar -zxvpf openresty-$&#123;or_ver&#125;.tar.gz &gt; /dev/null</span><br><span class="line"></span><br><span class="line">if [ "$repo" == ngx_multi_upstream_module ]; then</span><br><span class="line">    cp -r "$prev_workdir" ./ngx_multi_upstream_module-$&#123;ngx_multi_upstream_module_ver&#125;</span><br><span class="line">else</span><br><span class="line">    unzip $&#123;prev_workdir&#125;/ngx_multi_upstream_module-$&#123;ngx_multi_upstream_module_ver&#125;.zip</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">if [ "$repo" == mod_dubbo ]; then</span><br><span class="line">    cp -r "$prev_workdir" ./mod_dubbo-$&#123;mod_dubbo_ver&#125;</span><br><span class="line">else</span><br><span class="line">     unzip $&#123;prev_workdir&#125;/mod_dubbo-$&#123;mod_dubbo_ver&#125;.zip</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">if [ "$repo" == apisix-nginx-module ]; then</span><br><span class="line">    cp -r "$prev_workdir" ./apisix-nginx-module-$&#123;apisix_nginx_module_ver&#125;</span><br><span class="line">else</span><br><span class="line">    unzip $&#123;prev_workdir&#125;/apisix-nginx-module-$&#123;apisix_nginx_module_ver&#125;.zip</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">if [ "$repo" == wasm-nginx-module ]; then</span><br><span class="line">    cp -r "$prev_workdir" ./wasm-nginx-module-$&#123;wasm_nginx_module_ver&#125;</span><br><span class="line">else</span><br><span class="line">    unzip $&#123;prev_workdir&#125;/wasm-nginx-module-$&#123;wasm_nginx_module_ver&#125;.zip</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">if [ "$repo" == lua-var-nginx-module ]; then</span><br><span class="line">    cp -r "$prev_workdir" ./lua-var-nginx-module-$&#123;lua_var_nginx_module_ver&#125;</span><br><span class="line">else</span><br><span class="line">    unzip $&#123;prev_workdir&#125;/lua-var-nginx-module-$&#123;lua_var_nginx_module_ver#*v&#125;.zip</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">if [ "$repo" == grpc-client-nginx-module ]; then</span><br><span class="line">    cp -r "$prev_workdir" ./grpc-client-nginx-module-$&#123;grpc_client_nginx_module_ver&#125;</span><br><span class="line">else</span><br><span class="line">    unzip $&#123;prev_workdir&#125;/grpc-client-nginx-module-$&#123;grpc_client_nginx_module_ver#*v&#125;.zip</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">if [ "$repo" == amesh ]; then</span><br><span class="line">    cp -r "$prev_workdir" ./amesh-$&#123;amesh_ver&#125;</span><br><span class="line">else</span><br><span class="line">    unzip $&#123;prev_workdir&#125;/Amesh-$&#123;amesh_ver&#125;.zip</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">cd ngx_multi_upstream_module-$&#123;ngx_multi_upstream_module_ver&#125; || exit 1</span><br><span class="line">./patch.sh ../openresty-$&#123;or_ver&#125;</span><br><span class="line">cd ..</span><br><span class="line"></span><br><span class="line">cd apisix-nginx-module-$&#123;apisix_nginx_module_ver&#125;/patch || exit 1</span><br><span class="line">./patch.sh ../../openresty-$&#123;or_ver&#125;</span><br><span class="line">cd ../..</span><br><span class="line"></span><br><span class="line">cd wasm-nginx-module-$&#123;wasm_nginx_module_ver&#125; || exit 1</span><br><span class="line">./install-wasmtime.sh</span><br><span class="line">cd ..</span><br><span class="line"></span><br><span class="line">cc_opt=$&#123;cc_opt:-&#125;</span><br><span class="line">ld_opt=$&#123;ld_opt:-&#125;</span><br><span class="line">luajit_xcflags=$&#123;luajit_xcflags:="-DLUAJIT_NUMMODE=2 -DLUAJIT_ENABLE_LUA52COMPAT"&#125;</span><br><span class="line">no_pool_patch=$&#123;no_pool_patch:-&#125;</span><br><span class="line"><span class="meta">#</span> TODO: remove old NGX_HTTP_GRPC_CLI_ENGINE_PATH once we have released a new</span><br><span class="line"><span class="meta">#</span> version of grpc-client-nginx-module</span><br><span class="line">grpc_engine_path="-DNGX_GRPC_CLI_ENGINE_PATH=$OR_PREFIX/libgrpc_engine.so -DNGX_HTTP_GRPC_CLI_ENGINE_PATH=$OR_PREFIX/libgrpc_engine.so"</span><br><span class="line"></span><br><span class="line">cd openresty-$&#123;or_ver&#125; || exit 1</span><br><span class="line"><span class="meta">#</span> FIXME: remove this once 1.21.4.2 is released</span><br><span class="line">rm -rf bundle/LuaJIT-2.1-20220411</span><br><span class="line">lj_ver=2.1-20230119</span><br><span class="line">wget "https://github.com/openresty/luajit2/archive/v$lj_ver.tar.gz" -O "LuaJIT-$lj_ver.tar.gz"</span><br><span class="line">tar -xzf LuaJIT-$lj_ver.tar.gz</span><br><span class="line">mv luajit2-* bundle/LuaJIT-2.1-20220411</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> $&#123;lua_var_nginx_module_ver#*v&#125;是为了去掉v</span><br><span class="line"></span><br><span class="line">./configure --prefix="$OR_PREFIX" \</span><br><span class="line">    --with-cc-opt="-DAPISIX_BASE_VER=$version $grpc_engine_path $cc_opt" \</span><br><span class="line">    --with-ld-opt="-Wl,-rpath,$OR_PREFIX/wasmtime-c-api/lib $ld_opt" \</span><br><span class="line">    $debug_args \</span><br><span class="line">    --add-module=../mod_dubbo-$&#123;mod_dubbo_ver&#125; \</span><br><span class="line">    --add-module=../ngx_multi_upstream_module-$&#123;ngx_multi_upstream_module_ver&#125; \</span><br><span class="line">    --add-module=../apisix-nginx-module-$&#123;apisix_nginx_module_ver&#125; \</span><br><span class="line">    --add-module=../apisix-nginx-module-$&#123;apisix_nginx_module_ver&#125;/src/stream \</span><br><span class="line">    --add-module=../apisix-nginx-module-$&#123;apisix_nginx_module_ver&#125;/src/meta \</span><br><span class="line">    --add-module=../wasm-nginx-module-$&#123;wasm_nginx_module_ver&#125; \</span><br><span class="line">    --add-module=../lua-var-nginx-module-$&#123;lua_var_nginx_module_ver#*v&#125; \</span><br><span class="line">    --add-module=../grpc-client-nginx-module-$&#123;grpc_client_nginx_module_ver#*v&#125; \</span><br><span class="line">    --with-poll_module \</span><br><span class="line">    --with-pcre-jit \</span><br><span class="line">    --without-http_rds_json_module \</span><br><span class="line">    --without-http_rds_csv_module \</span><br><span class="line">    --without-lua_rds_parser \</span><br><span class="line">    --with-stream \</span><br><span class="line">    --with-stream_ssl_module \</span><br><span class="line">    --with-stream_ssl_preread_module \</span><br><span class="line">    --with-http_v2_module \</span><br><span class="line">    --without-mail_pop3_module \</span><br><span class="line">    --without-mail_imap_module \</span><br><span class="line">    --without-mail_smtp_module \</span><br><span class="line">    --with-http_stub_status_module \</span><br><span class="line">    --with-http_realip_module \</span><br><span class="line">    --with-http_addition_module \</span><br><span class="line">    --with-http_auth_request_module \</span><br><span class="line">    --with-http_secure_link_module \</span><br><span class="line">    --with-http_random_index_module \</span><br><span class="line">    --with-http_gzip_static_module \</span><br><span class="line">    --with-http_sub_module \</span><br><span class="line">    --with-http_dav_module \</span><br><span class="line">    --with-http_flv_module \</span><br><span class="line">    --with-http_mp4_module \</span><br><span class="line">    --with-http_gunzip_module \</span><br><span class="line">    --with-threads \</span><br><span class="line">    --with-compat \</span><br><span class="line">    --with-luajit-xcflags="$luajit_xcflags" \</span><br><span class="line">    $no_pool_patch \</span><br><span class="line">    -j`nproc`</span><br><span class="line"></span><br><span class="line">make -j`nproc`</span><br><span class="line">sudo make install</span><br><span class="line">cd ..</span><br><span class="line"></span><br><span class="line">cd apisix-nginx-module-$&#123;apisix_nginx_module_ver&#125; || exit 1</span><br><span class="line">sudo OPENRESTY_PREFIX="$OR_PREFIX" make install</span><br><span class="line">cd ..</span><br><span class="line"></span><br><span class="line">cd wasm-nginx-module-$&#123;wasm_nginx_module_ver&#125; || exit 1</span><br><span class="line">sudo OPENRESTY_PREFIX="$OR_PREFIX" make install</span><br><span class="line">cd ..</span><br><span class="line"></span><br><span class="line">cd grpc-client-nginx-module-$&#123;grpc_client_nginx_module_ver#*v&#125; || exit 1</span><br><span class="line">sudo sed -i s#https://go.dev/dl/#https://golang.google.cn/dl/#g install-util.sh</span><br><span class="line">sudo /usr/local/go/bin/go env -w GO111MODULE=on</span><br><span class="line">sudo /usr/local/go/bin/go env -w GOPROXY=https://goproxy.cn,direct</span><br><span class="line">sudo OPENRESTY_PREFIX="$OR_PREFIX" make install</span><br><span class="line">cd ..</span><br><span class="line"></span><br><span class="line">cd Amesh-$&#123;amesh_ver&#125; || exit 1</span><br><span class="line">sudo OPENRESTY_PREFIX="$OR_PREFIX" sh -c 'PATH="$&#123;PATH&#125;:/usr/local/go/bin" make install'</span><br><span class="line">cd ..</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> package etcdctl</span><br><span class="line">ETCD_ARCH="amd64"</span><br><span class="line">ETCD_VERSION=$&#123;ETCD_VERSION:-'3.5.4'&#125;</span><br><span class="line">ARCH=$&#123;ARCH:-$(uname -m | tr '[:upper:]' '[:lower:]')&#125;</span><br><span class="line"></span><br><span class="line">if [[ $ARCH == "arm64" ]] || [[ $ARCH == "aarch64" ]]; then</span><br><span class="line">    ETCD_ARCH="arm64"</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">wget -q https://github.com/etcd-io/etcd/releases/download/v$&#123;ETCD_VERSION&#125;/etcd-v$&#123;ETCD_VERSION&#125;-linux-$&#123;ETCD_ARCH&#125;.tar.gz</span><br><span class="line">tar xf etcd-v$&#123;ETCD_VERSION&#125;-linux-$&#123;ETCD_ARCH&#125;.tar.gz</span><br><span class="line"><span class="meta">#</span> ship etcdctl under the same bin dir of openresty so we can package it easily</span><br><span class="line">sudo cp etcd-v$&#123;ETCD_VERSION&#125;-linux-$&#123;ETCD_ARCH&#125;/etcdctl "$OR_PREFIX"/bin/</span><br><span class="line">rm -rf etcd-v$&#123;ETCD_VERSION&#125;-linux-$&#123;ETCD_ARCH&#125;</span><br></pre></td></tr></table></figure></p><p>设置环境变量<br><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">vi /etc/profile</span><br></pre></td></tr></table></figure></p><p>添加以下内容<br><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></pre></td><td class="code"><pre><span class="line">cat &gt;&gt; /etc/profile &lt;&lt; EOF</span><br><span class="line">export $OPENRESTY_HOME=/usr/local/openresty</span><br><span class="line">export PATH=$PATH:$OPENRESTY_HOME/bin</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure></p><p>然后执行<br><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">souce /etc/profile</span><br></pre></td></tr></table></figure></p><h1 id="APISIX安装"><a href="#APISIX安装" class="headerlink" title="APISIX安装"></a>APISIX安装</h1><p>进入APISIX源码目录</p><p>设置APISIX版本，并创建目录</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">APISIX_VERSION=2.15.3</span><br><span class="line">mkdir apisix-$&#123;APISIX_VERSION&#125;</span><br></pre></td></tr></table></figure><p>下载源码包<br><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 -O https://downloads.apache.org/apisix/$&#123;APISIX_VERSION&#125;/apache-apisix-$&#123;APISIX_VERSION&#125;-src.tgz</span><br></pre></td></tr></table></figure></p><p>解压源码包<br><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">mkdir -p /opt/src/apisix-$&#123;APISIX_VERSION&#125; &amp;&amp; tar xzvf apache-apisix-$&#123;APISIX_VERSION&#125;-src.tgz -C /opt/src/apisix-$&#123;APISIX_VERSION&#125;</span><br></pre></td></tr></table></figure></p><p>修改luarocks源,添加以下配置<br><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></pre></td><td class="code"><pre><span class="line">mkdir -p ~/.luarocks</span><br><span class="line">cat &gt;&gt; ~/.luarocks/config-5.1.lua &lt;&lt; EOF</span><br><span class="line">rocks_servers = &#123;</span><br><span class="line">   &#123;</span><br><span class="line">      "https://luarocks.cn",</span><br><span class="line">      "https://luarocks.org",</span><br><span class="line">      "https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/",</span><br><span class="line">      "https://luafr.org/luarocks/",</span><br><span class="line">      "http://luarocks.logiceditor.com/rocks"</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line">variables = &#123;</span><br><span class="line">   OPENSSL_INCDIR = "/usr/local/openresty/openssl111/include",</span><br><span class="line">   OPENSSL_LIBDIR = "/usr/local/openresty/openssl111/lib"</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure></p><p>构建<br><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"><span class="meta">#</span> Switch to the apisix-$&#123;APISIX_VERSION&#125; directory</span><br><span class="line">cd apisix-$&#123;APISIX_VERSION&#125;</span><br><span class="line"><span class="meta">#</span> Create dependencies</span><br><span class="line">make deps</span><br></pre></td></tr></table></figure></p><p>或指定源地址<br><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">make deps ENV_LUAROCKS_SERVER=https://luarocks.cn</span><br></pre></td></tr></table></figure></p><blockquote><p>构建的话由于网络问题，可能需要多试几次</p></blockquote><p>最后安装<br><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> Install apisix command</span><br><span class="line">make install</span><br></pre></td></tr></table></figure></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></pre></td><td class="code"><pre><span class="line">sudo tee -a /etc/security/limits.conf &lt;&lt; EOF</span><br><span class="line"><span class="meta">#</span> </span><br><span class="line">* soft nofile 65536</span><br><span class="line">* hard nofile 65536</span><br><span class="line">* soft nproc 65536</span><br><span class="line">* hard nproc 65536</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><p>设置luarocks<br><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">OPENSSL_PREFIX=/usr/local/openresty/openssl111</span><br><span class="line">luarocks config variables.OPENSSL_LIBDIR $&#123;OPENSSL_PREFIX&#125;/lib</span><br><span class="line">luarocks config variables.OPENSSL_INCDIR $&#123;OPENSSL_PREFIX&#125;/include</span><br></pre></td></tr></table></figure></p><p>拷贝源码构建目录下的apisix目录以及deps目录到 /usr/local/apisix<br><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">cp -r /opt/src/apisix-$&#123;APISIX_VERSION&#125;/apisix/ /opt/src/apisix-$&#123;APISIX_VERSION&#125;/deps/ /usr/local/apisix/</span><br></pre></td></tr></table></figure></p><p>测试apisix<br><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">/usr/bin/apisix test</span><br><span class="line">/usr/bin/apisix init</span><br></pre></td></tr></table></figure></p><h1 id="APISIX连接etcd"><a href="#APISIX连接etcd" class="headerlink" title="APISIX连接etcd"></a>APISIX连接etcd</h1><h2 id="无证书方式"><a href="#无证书方式" class="headerlink" title="无证书方式"></a>无证书方式</h2><p>分别在三个节点上起etcd服务<br><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">/opt/etcd3/etcd \</span><br><span class="line">--name s1 \</span><br><span class="line">--data-dir /tmp/etcd-data \</span><br><span class="line">--listen-client-urls http://0.0.0.0:2379 \</span><br><span class="line">--advertise-client-urls http://0.0.0.0:2379 \</span><br><span class="line">--listen-peer-urls http://0.0.0.0:2380 \</span><br><span class="line">--initial-advertise-peer-urls http://0.0.0.0:2380 \</span><br><span class="line">--initial-cluster s1=http://0.0.0.0:2380 \</span><br><span class="line">--initial-cluster-token tkn \</span><br><span class="line">--initial-cluster-state new \</span><br><span class="line">--log-level info \</span><br><span class="line">--logger zap \</span><br><span class="line">--log-outputs stderr</span><br></pre></td></tr></table></figure></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">/opt/etcd3/etcd \</span><br><span class="line">--name s2 \</span><br><span class="line">--data-dir /tmp/etcd-data \</span><br><span class="line">--listen-client-urls http://0.0.0.0:2379 \</span><br><span class="line">--advertise-client-urls http://0.0.0.0:2379 \</span><br><span class="line">--listen-peer-urls http://0.0.0.0:2380 \</span><br><span class="line">--initial-advertise-peer-urls http://0.0.0.0:2380 \</span><br><span class="line">--initial-cluster s1=http://0.0.0.0:2380 \</span><br><span class="line">--initial-cluster-token tkn \</span><br><span class="line">--initial-cluster-state new \</span><br><span class="line">--log-level info \</span><br><span class="line">--logger zap \</span><br><span class="line">--log-outputs stderr</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><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">/opt/etcd3/etcd \</span><br><span class="line">--name s3 \</span><br><span class="line">--data-dir /tmp/etcd-data \</span><br><span class="line">--listen-client-urls http://0.0.0.0:2379 \</span><br><span class="line">--advertise-client-urls http://0.0.0.0:2379 \</span><br><span class="line">--listen-peer-urls http://0.0.0.0:2380 \</span><br><span class="line">--initial-advertise-peer-urls http://0.0.0.0:2380 \</span><br><span class="line">--initial-cluster s1=http://0.0.0.0:2380 \</span><br><span class="line">--initial-cluster-token tkn \</span><br><span class="line">--initial-cluster-state new \</span><br><span class="line">--log-level info \</span><br><span class="line">--logger zap \</span><br><span class="line">--log-outputs stderr</span><br></pre></td></tr></table></figure><p>如果是使用http的话，就配置下host就行了<br><figure class="highlight yaml"><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="comment"># 其他配置省略...</span></span><br><span class="line"></span><br><span class="line"><span class="attr">etcd:</span></span><br><span class="line"><span class="attr">  host:</span>                           </span><br><span class="line"><span class="bullet">    -</span> <span class="string">"http://10.1.80.91:2379"</span></span><br><span class="line"><span class="bullet">    -</span> <span class="string">"http://10.1.80.92:2379"</span></span><br><span class="line"><span class="bullet">    -</span> <span class="string">"http://10.1.80.93:2379"</span></span><br><span class="line">    </span><br><span class="line"><span class="comment"># 其他配置省略...</span></span><br></pre></td></tr></table></figure></p><h2 id="有证书方式"><a href="#有证书方式" class="headerlink" title="有证书方式"></a>有证书方式</h2><p>如果是使用https的话，需要配置下etcd证书</p><p>创建放etcd证书的目录，并将证书拷贝过去，由于我是将etcd和apisix安装在一台上了，请根据具体情况来操作<br><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">sudo mkdir -p /usr/local/apisix/ssl</span><br><span class="line">sudo cp /opt/etcd3/ssl/&#123;etcd-ca.pem,etcd-server-key.pem,etcd-server.pem&#125; /usr/local/apisix/ssl</span><br><span class="line">sudo chmod a+r /usr/local/apisix/ssl/etcd-server-key.pem</span><br></pre></td></tr></table></figure></p><blockquote><p>chmod 666 /usr/local/apisix/ssl/etcd-server-key.pem 为什么加写权限，见常见问题</p></blockquote><p>修改APISIX配置文件，可以先备份下，然后用config-default.yaml这个模板<br><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">cp /usr/local/apisix/conf/config.yaml /usr/local/apisix/conf/config.yaml.bak</span><br><span class="line">cp /usr/local/apisix/conf/config-default.yaml /usr/local/apisix/conf/config.yaml</span><br><span class="line">vi /usr/local/apisix/conf/config.yaml</span><br></pre></td></tr></table></figure></p><p>修改内容如下<br><figure class="highlight yaml"><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 class="comment"># 其余省略...</span></span><br><span class="line"><span class="attr">ssl:</span></span><br><span class="line"><span class="attr">  enable:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr">  listen:</span>                       <span class="comment"># APISIX listening port in https.</span></span><br><span class="line"><span class="attr">    - port:</span> <span class="number">9443</span></span><br><span class="line"><span class="attr">      enable_http2:</span> <span class="literal">true</span></span><br><span class="line">  <span class="comment">#   - ip: 127.0.0.3           # Specific IP, If not set, the default value is `0.0.0.0`.</span></span><br><span class="line">  <span class="comment">#     port: 9445</span></span><br><span class="line">  <span class="comment">#     enable_http2: true</span></span><br><span class="line"><span class="attr">  ssl_trusted_certificate:</span> <span class="string">/usr/local/apisix/ssl/etcd-ca.pem</span> <span class="comment"># Specifies a file path with trusted CA certificates in the PEM format  </span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 其余省略...</span></span><br><span class="line"><span class="attr">etcd:</span></span><br><span class="line"><span class="attr">  host:</span>                           <span class="comment"># it's possible to define multiple etcd hosts addresses of the same etcd cluster.</span></span><br><span class="line"><span class="bullet">    -</span> <span class="string">"https://10.1.80.91:2379"</span>   <span class="comment"># multiple etcd address, if your etcd cluster enables TLS, please use https scheme,</span></span><br><span class="line"><span class="bullet">    -</span> <span class="string">"https://10.1.80.92:2379"</span>   <span class="comment"># multiple etcd address, if your etcd cluster enables TLS, please use https scheme,</span></span><br><span class="line"><span class="bullet">    -</span> <span class="string">"https://10.1.80.93:2379"</span>   <span class="comment"># multiple etcd address, if your etcd cluster enables TLS, please use https scheme,</span></span><br><span class="line">                                  <span class="comment"># e.g. https://127.0.0.1:2379.</span></span><br><span class="line"><span class="attr">  prefix:</span> <span class="string">/apisix</span>                 <span class="comment"># configuration prefix in etcd</span></span><br><span class="line"><span class="attr">  use_grpc:</span> <span class="literal">false</span>                 <span class="comment"># enable the experimental configuration sync via gRPC</span></span><br><span class="line"><span class="attr">  timeout:</span> <span class="number">30</span>                     <span class="comment"># 30 seconds. Use a much higher timeout (like an hour) if the `use_grpc` is true.</span></span><br><span class="line">  <span class="comment">#resync_delay: 5                # when sync failed and a rest is needed, resync after the configured seconds plus 50% random jitter</span></span><br><span class="line">  <span class="comment">#health_check_timeout: 10       # etcd retry the unhealthy nodes after the configured seconds</span></span><br><span class="line"><span class="attr">  startup_retry:</span> <span class="number">2</span>                <span class="comment"># the number of retry to etcd during the startup, default to 2</span></span><br><span class="line">  <span class="comment">#user: root                     # root username for etcd</span></span><br><span class="line">  <span class="comment">#password: 5tHkHhYkjr6cQY       # root password for etcd</span></span><br><span class="line"><span class="attr">  tls:</span></span><br><span class="line">    <span class="comment"># To enable etcd client certificate you need to build APISIX-Base, see</span></span><br><span class="line">    <span class="comment"># https://apisix.apache.org/docs/apisix/FAQ#how-do-i-build-the-apisix-base-environment</span></span><br><span class="line"><span class="attr">    cert:</span> <span class="string">/usr/local/apisix/ssl/etcd-server.pem</span>          <span class="comment"># path of certificate used by the etcd client</span></span><br><span class="line"><span class="attr">    key:</span> <span class="string">/usr/local/apisix/ssl/etcd-server-key.pem</span>       <span class="comment"># path of key used by the etcd client</span></span><br><span class="line"></span><br><span class="line"><span class="attr">    verify:</span> <span class="literal">true</span>                  <span class="comment"># whether to verify the etcd endpoint certificate when setup a TLS connection to etcd,</span></span><br></pre></td></tr></table></figure></p><h1 id="初始化启动APISIX"><a href="#初始化启动APISIX" class="headerlink" title="初始化启动APISIX"></a>初始化启动APISIX</h1><p>启动apisix<br><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">/usr/bin/apisix test</span><br><span class="line">/usr/bin/apisix init</span><br><span class="line">/usr/bin/apisix start</span><br></pre></td></tr></table></figure></p><p>如果以这种方式启动了，当使用systemd服务方式启动时，别忘了关掉之前的apisix进程</p><p>为APISIX添加systemd服务<br><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></pre></td><td class="code"><pre><span class="line">sudo tee -a /usr/lib/systemd/system/apisix.service &lt;&lt; EOF  </span><br><span class="line"><span class="meta">#</span> apisix systemd service</span><br><span class="line"><span class="meta">#</span> https://github.com/api7/apisix-build-tools/blob/master/usr/lib/systemd/system/apisix.service</span><br><span class="line">[Unit]</span><br><span class="line">Description=apisix</span><br><span class="line"><span class="meta">#</span>Conflicts=apisix.service</span><br><span class="line">After=network-online.target</span><br><span class="line">Wants=network-online.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=forking</span><br><span class="line">Restart=on-failure</span><br><span class="line">WorkingDirectory=/usr/local/apisix</span><br><span class="line">ExecStart=/usr/bin/apisix start</span><br><span class="line">ExecStop=/usr/bin/apisix stop</span><br><span class="line">ExecReload=/usr/bin/apisix reload</span><br><span class="line">LimitNOFILE=65536</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure></p><p>启用apisix服务<br><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 daemon-reload</span><br><span class="line">systemctl enable apisix</span><br></pre></td></tr></table></figure></p><h1 id="常见错误"><a href="#常见错误" class="headerlink" title="常见错误"></a>常见错误</h1><h2 id="Could-not-find-header-file-for-OPENSSL"><a href="#Could-not-find-header-file-for-OPENSSL" class="headerlink" title="Could not find header file for OPENSSL"></a>Could not find header file for OPENSSL</h2><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></pre></td><td class="code"><pre><span class="line">Installing https://luarocks.org/luasec-0.9-1.src.rock</span><br><span class="line"></span><br><span class="line">Error: Failed installing dependency: https://luarocks.org/luasec-0.9-1.src.rock - Could not find header file for OPENSSL</span><br><span class="line">  No file openssl/ssl.h in /usr/local/openresty/openssl/include</span><br><span class="line">You may have to install OPENSSL in your system and/or pass OPENSSL_DIR or OPENSSL_INCDIR to the luarocks command.</span><br><span class="line">Example: luarocks install luasec OPENSSL_DIR=/usr/local</span><br><span class="line">make: *** [Makefile:152: deps] Error 1</span><br><span class="line">root@exp:/tmp/src/apisix-2.15# ll /usr/local/openresty/op^C</span><br><span class="line">root@exp:/tmp/src/apisix-2.15# apt install libssl-dev</span><br><span class="line">Reading package lists... Done</span><br><span class="line">Building dependency tree</span><br><span class="line">Reading state information... Done</span><br><span class="line">libssl-dev is already the newest version (1.1.1f-1ubuntu2.16).</span><br><span class="line">0 upgraded, 0 newly installed, 0 to remove and 9 not upgraded.</span><br></pre></td></tr></table></figure><p>需要安装openresty-openssl111-dev</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">sudo apt install -y openresty-openssl111-dev</span><br></pre></td></tr></table></figure><h2 id="gzip-module-requires-the-zlib-library"><a href="#gzip-module-requires-the-zlib-library" class="headerlink" title="gzip module requires the zlib library"></a>gzip module requires the zlib library</h2><p>在进行./configure编译Nginx提示gzip module requires the zlib library<br>执行sudo apt install zlib1g-dev可解决</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">sudo apt install zlib1g-dev</span><br></pre></td></tr></table></figure><h2 id="ngx-postgres-addon-was-unable-to-detect-version-of-the-libpq-library"><a href="#ngx-postgres-addon-was-unable-to-detect-version-of-the-libpq-library" class="headerlink" title="ngx_postgres addon was unable to detect version of the libpq library"></a>ngx_postgres addon was unable to detect version of the libpq library</h2><p>在进行./configure编译Nginx提示ngx_postgres addon was unable to detect version of the libpq library<br>执行sudo apt-get install libpq-dev可解决</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">sudo apt-get install libpq-dev</span><br></pre></td></tr></table></figure><p>安装apixsix make deps时报如下错误，说明没有安装libldap2-dev<br><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">Error: Failed installing dependency: https://luarocks.cn/lualdap-1.2.6-1.src.rock - Could not find header file for LDAP</span><br><span class="line">  No file ldap.h in /usr/local/include</span><br><span class="line">  No file ldap.h in /usr/include</span><br><span class="line">  No file ldap.h in /include</span><br></pre></td></tr></table></figure></p><h2 id="APISIX相关文件缺失"><a href="#APISIX相关文件缺失" class="headerlink" title="APISIX相关文件缺失"></a>APISIX相关文件缺失</h2><p>遇如下错误，只需将源码apisix-$VERSION/apisix目录拷贝到 /usr/local/apisix安装目录下 cp -r /opt/src/apisix-3.2.0/apisix/ /usr/local/apisix/<br><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@s91:/usr/local/apisix# apisix init</span><br><span class="line">/usr/local/openresty//luajit/bin/luajit /usr/local/apisix/apisix/cli/apisix.lua init</span><br><span class="line">/usr/local/openresty//luajit/bin/luajit: cannot open /usr/local/apisix/apisix/cli/apisix.lua: No such file or directory</span><br><span class="line">root@s91:/usr/local/apisix# apisix test</span><br><span class="line">/usr/local/openresty//luajit/bin/luajit /usr/local/apisix/apisix/cli/apisix.lua test</span><br><span class="line">/usr/local/openresty//luajit/bin/luajit: cannot open /usr/local/apisix/apisix/cli/apisix.lua: No such file or directory</span><br></pre></td></tr></table></figure></p><h2 id="缺少主机名的解析"><a href="#缺少主机名的解析" class="headerlink" title="缺少主机名的解析"></a>缺少主机名的解析</h2><p>遇到如下错误，只需要在/etc/hosts里加一条记录 127.0.0.1 s92.idc3.meeleet.com 即可<br><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">sudo: unable to resolve host s92.idc3.meeleet.com: Temporary failure in name resolution</span><br></pre></td></tr></table></figure></p><h2 id="默认luarocks源下载慢，很容易下载失败的问题"><a href="#默认luarocks源下载慢，很容易下载失败的问题" class="headerlink" title="默认luarocks源下载慢，很容易下载失败的问题"></a>默认luarocks源下载慢，很容易下载失败的问题</h2><p>APISIX make deps构建，如果出现以下错误,需要配置下luarcoks国内源优先,因为默认的源luarocks.org比较慢，使用<a href="https://luarocks.cn的源，成功率会高很多，但是可能还有偶尔失败，多试几次就可以了" target="_blank" rel="noopener">https://luarocks.cn的源，成功率会高很多，但是可能还有偶尔失败，多试几次就可以了</a><br><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></pre></td><td class="code"><pre><span class="line">Installing https://luarocks.org/lua-resty-radixtree-2.8.2-0.src.rock</span><br><span class="line">Missing dependencies for lua-resty-radixtree 2.8.2-0:</span><br><span class="line">   lua-resty-expr 1.3.0 (not installed)</span><br><span class="line"></span><br><span class="line">lua-resty-radixtree 2.8.2-0 depends on lua-resty-ipmatcher (0.6.1-0 installed)</span><br><span class="line">lua-resty-radixtree 2.8.2-0 depends on lua-resty-expr 1.3.0 (not installed)</span><br><span class="line">Installing https://luarocks.org/lua-resty-expr-1.3.0-0.rockspec</span><br><span class="line">Cloning into 'lua-resty-expr'...</span><br><span class="line">fatal: unable to access 'https://github.com/api7/lua-resty-expr/': GnuTLS recv error (-110): The TLS connection was non-properly terminated.</span><br><span class="line"></span><br><span class="line">Error: Failed installing dependency: https://luarocks.org/lua-resty-radixtree-2.8.2-0.src.rock - Failed installing dependency: https://luarocks.org/lua-resty-expr-1.3.0-0.rockspec - Failed cloning git repository.</span><br><span class="line">make: *** [Makefile:152: deps] Error 1</span><br></pre></td></tr></table></figure></p><h2 id="etcd-server-key-pem-Permission-denied"><a href="#etcd-server-key-pem-Permission-denied" class="headerlink" title="etcd-server-key.pem:Permission denied"></a>etcd-server-key.pem:Permission denied</h2><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">2023/04/17 04:28:11 [warn] 110028#110028: *44161 [lua] v3.lua:716: request_chunk(): https://10.1.80.93:2379: /usr/local/apisix/ssl/etcd-server-key.pem: Permission denied. Retrying, context: ngx.timer</span><br><span class="line">2023/04/17 04:28:11 [warn] 110028#110028: *44161 [lua] v3.lua:716: request_chunk(): https://10.1.80.91:2379: /usr/local/apisix/ssl/etcd-server-key.pem: Permission denied. Retrying, context: ngx.timer</span><br><span class="line">2023/04/17 04:28:11 [warn] 110028#110028: *44161 [lua] v3.lua:716: request_chunk(): https://10.1.80.92:2379: /usr/local/apisix/ssl/etcd-server-key.pem: Permission denied. Retrying, context: ngx.timer</span><br></pre></td></tr></table></figure><p>需要给证书文件所有用户以读权限<br><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">sudo chmod a+r /usr/local/apisix/ssl/etcd-server-key.pem</span><br></pre></td></tr></table></figure></p><h1 id="FAQ"><a href="#FAQ" class="headerlink" title="FAQ"></a>FAQ</h1><h2 id="需要安装Lua吗？"><a href="#需要安装Lua吗？" class="headerlink" title="需要安装Lua吗？"></a>需要安装Lua吗？</h2><p>不需要，因为这里OpenResty用的LuaJIT来运行</p><h2 id="怎么卸载APISIX"><a href="#怎么卸载APISIX" class="headerlink" title="怎么卸载APISIX"></a>怎么卸载APISIX</h2><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"><span class="meta">#</span> To uninstall the APISIX runtime, run:</span><br><span class="line">make uninstall</span><br><span class="line">make undeps</span><br></pre></td></tr></table></figure><h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><p><a href="https://openresty.org/cn/linux-packages.html" target="_blank" rel="noopener">OpenResty® Linux 包</a></p><p><a href="https://www.digitalocean.com/community/tutorials/how-to-use-the-openresty-web-framework-for-nginx-on-ubuntu-16-04" target="_blank" rel="noopener">How to Use the OpenResty Web Framework for Nginx on Ubuntu 16.04</a></p><p><a href="https://apisix.apache.org/zh/docs/apisix/install-dependencies/" target="_blank" rel="noopener">APISIX安装依赖</a></p><p><a href="https://blog.51cto.com/rongfengliang/5289951" target="_blank" rel="noopener">luarocks 简单使用&amp;openresty 离线集成说明 原创</a></p><p><a href="https://www.cnblogs.com/wangguishe/p/16165880.html" target="_blank" rel="noopener">ubuntu 20.04安装 Apache APISIX</a></p><p><a href="https://github.com/apache/apisix/issues/7098" target="_blank" rel="noopener">help request: please check the version of OpenResty and lua, OpenResty 1.19 + LuaJIT or OpenResty before 1.19 + Lua 5.1 is required for Apache APISIX</a></p><p><a href="https://cmjava.ltd:8090/archives/apisix%E9%85%8D%E7%BD%AE%E9%9C%80%E8%A6%81%E8%AF%81%E4%B9%A6%E7%9A%84etcd%E9%9B%86%E7%BE%A4" target="_blank" rel="noopener">apisix配置需要证书的etcd集群</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;[TOC]&lt;/p&gt;
&lt;h1 id=&quot;OpenResty源码安装&quot;&gt;&lt;a href=&quot;#OpenResty源码安装&quot; class=&quot;headerlink&quot; title=&quot;OpenResty源码安装&quot;&gt;&lt;/a&gt;OpenResty源码安装&lt;/h1&gt;&lt;h2 id=&quot;安装前准备&quot;&gt;&lt;
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>安装部署3节点Etcd高可用集群(3节点同一套证书)【APISIX用的etcd集群】</title>
    <link href="http://jaychang.cn/2023/04/17/%E5%AE%89%E8%A3%85%E9%83%A8%E7%BD%B23%E8%8A%82%E7%82%B9Etcd%E9%AB%98%E5%8F%AF%E7%94%A8%E9%9B%86%E7%BE%A4-3%E8%8A%82%E7%82%B9%E5%90%8C%E4%B8%80%E5%A5%97%E8%AF%81%E4%B9%A6-%E3%80%90APISIX%E7%94%A8%E7%9A%84etcd%E9%9B%86%E7%BE%A4%E3%80%91/"/>
    <id>http://jaychang.cn/2023/04/17/安装部署3节点Etcd高可用集群-3节点同一套证书-【APISIX用的etcd集群】/</id>
    <published>2023-04-17T13:24:30.000Z</published>
    <updated>2023-04-17T13:24:46.862Z</updated>
    
    <content type="html"><![CDATA[<p>[toc]</p><h1 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h1><table><thead><tr><th>IP</th><th>主机名</th></tr></thead><tbody><tr><td>10.1.80.91</td><td>s1</td></tr><tr><td>10.1.80.92</td><td>s2</td></tr><tr><td>10.1.80.93</td><td>s3</td></tr></tbody></table><h1 id="安装cfssl"><a href="#安装cfssl" class="headerlink" title="安装cfssl"></a>安装cfssl</h1><table><thead><tr><th>cfssl版本</th><th>可执行文件存放目录</th><th>证书存放目录</th></tr></thead><tbody><tr><td>1.6.2</td><td>/usr/local/bin</td><td>/tmp/certs</td></tr></tbody></table><blockquote><p>下载地址<br><a href="https://github.com/cloudflare/cfssl/releases" target="_blank" rel="noopener">https://github.com/cloudflare/cfssl/releases</a></p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.2/cfssl_1.6.2_linux_amd64 -o /tmp/cfssl</span><br><span class="line">chmod +x /tmp/cfssl</span><br><span class="line">mv /tmp/cfssl /usr/bin/cfssl</span><br><span class="line"></span><br><span class="line">curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.2/cfssljson_1.6.2_linux_amd64 -o /tmp/cfssljson</span><br><span class="line">chmod +x /tmp/cfssljson</span><br><span class="line">mv /tmp/cfssljson /usr/bin/cfssljson</span><br></pre></td></tr></table></figure><p>打印默认证书配置<br><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">cfssl print-defaults csr</span><br><span class="line">cfssl print-defaults config</span><br></pre></td></tr></table></figure></p><h1 id="生成CA根证书"><a href="#生成CA根证书" class="headerlink" title="生成CA根证书"></a>生成CA根证书</h1><h2 id="ca-config配置"><a href="#ca-config配置" class="headerlink" title="ca-config配置"></a>ca-config配置</h2><p>需要注意的是，etcd-ca-config.json里面server的配置一定要加上”client auth”，因为APISIX新建集群时候，会默认做一次节点间健康检查，此时并没有像etcdctl那样提供client的证书和私钥，所以节点会用server的证书和私钥来进行通信，此时server证书就互为服务端和客户端了。<br>并且apisix和etcd集群通信时，etcd由于grpc-gateway的原因，也会把server证书当成客户端证书来验证。</p><p>profiles(ca证书不同配置的作用)里面的内容就是CA可以用来发挥作用的功能，一共预置了三种配置，分别对应Server、Peer和Client的证书密钥。</p><p>signing即签名证书，key encipherment即加密，server auth即服务器认证，client auth即客户端认证</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></pre></td><td class="code"><pre><span class="line">mkdir -p /tmp/certs</span><br><span class="line"></span><br><span class="line">cat &gt; /tmp/certs/etcd-ca-config.json &lt;&lt;EOF</span><br><span class="line">&#123;</span><br><span class="line">    &quot;signing&quot;: &#123;</span><br><span class="line">        &quot;default&quot;: &#123;</span><br><span class="line">            &quot;expiry&quot;: &quot;876000h&quot;</span><br><span class="line">        &#125;,</span><br><span class="line">        &quot;profiles&quot;: &#123;</span><br><span class="line">            &quot;server&quot;: &#123;</span><br><span class="line">                &quot;expiry&quot;: &quot;876000h&quot;,</span><br><span class="line">                &quot;usages&quot;: [</span><br><span class="line">                    &quot;signing&quot;,</span><br><span class="line">                    &quot;key encipherment&quot;,</span><br><span class="line">                    &quot;server auth&quot;,</span><br><span class="line">                    &quot;client auth&quot;</span><br><span class="line">                ]</span><br><span class="line">            &#125;,</span><br><span class="line">            &quot;client&quot;: &#123;</span><br><span class="line">                &quot;expiry&quot;: &quot;876000h&quot;,</span><br><span class="line">                &quot;usages&quot;: [</span><br><span class="line">                    &quot;signing&quot;,</span><br><span class="line">                    &quot;key encipherment&quot;,</span><br><span class="line">                    &quot;client auth&quot;</span><br><span class="line">                ]</span><br><span class="line">            &#125;,</span><br><span class="line">            &quot;peer&quot;: &#123;</span><br><span class="line">                &quot;expiry&quot;: &quot;876000h&quot;,</span><br><span class="line">                &quot;usages&quot;: [</span><br><span class="line">                &quot;signing&quot;,</span><br><span class="line">                &quot;key encipherment&quot;,</span><br><span class="line">                &quot;server auth&quot;,</span><br><span class="line">                &quot;client auth&quot;</span><br><span class="line">                ]</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h2 id="ca-csr配置"><a href="#ca-csr配置" class="headerlink" title="ca-csr配置"></a>ca-csr配置</h2><p>hosts里写所有etcd节点的ip，所有etcd节点的ip和对应的<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><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">cat &gt; /tmp/certs/etcd-ca-csr.json &lt;&lt;EOF</span><br><span class="line">&#123;</span><br><span class="line">    "CN": "etcd-ca",</span><br><span class="line">    "hosts": [</span><br><span class="line">        "127.0.0.1",</span><br><span class="line">        "localhost",</span><br><span class="line">        "10.1.80.91",</span><br><span class="line">        "10.1.80.92",</span><br><span class="line">        "10.1.80.93"</span><br><span class="line">    ],</span><br><span class="line">    "key": &#123;</span><br><span class="line">        "algo": "ecdsa",</span><br><span class="line">        "size": 256</span><br><span class="line">    &#125;,</span><br><span class="line">    "names": [</span><br><span class="line">        &#123;</span><br><span class="line">          "L": "Hangzhou",</span><br><span class="line">          "ST": "Zhejiang",</span><br><span class="line">          "C": "CN"</span><br><span class="line">        &#125;</span><br><span class="line">    ]</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h2 id="生成CA证书和CA证书的私钥"><a href="#生成CA证书和CA证书的私钥" class="headerlink" title="生成CA证书和CA证书的私钥"></a>生成CA证书和CA证书的私钥</h2><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">cd /tmp/certs</span><br><span class="line">cfssl gencert -initca etcd-ca-csr.json | cfssljson -bare etcd-ca -</span><br></pre></td></tr></table></figure><p>会生成以下文件</p><ul><li>etcd-ca.csr </li><li>etcd-ca-key.pem  </li><li>etcd-ca.pem</li></ul><p>etcd-ca-key.pem为CA的私钥，请妥善保管<br>etcd-ca.csr文件为证书请求文件，可以删除</p><h1 id="生成Server和Peer证书"><a href="#生成Server和Peer证书" class="headerlink" title="生成Server和Peer证书"></a>生成Server和Peer证书</h1><h2 id="Server和Peer配置"><a href="#Server和Peer配置" class="headerlink" title="Server和Peer配置"></a>Server和Peer配置</h2><p>Server用来服务端客户端通信的，Peer用来节点间通信的，它们共用同一套配置</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></pre></td><td class="code"><pre><span class="line">mkdir -p /tmp/certs</span><br><span class="line"></span><br><span class="line">cat &gt; /tmp/certs/etcd-csr.json &lt;&lt;EOF</span><br><span class="line">&#123;</span><br><span class="line">  "CN": "etcd",</span><br><span class="line">  "hosts": [</span><br><span class="line">    "127.0.0.1",</span><br><span class="line">    "localhost",</span><br><span class="line">    "10.1.80.91",</span><br><span class="line">    "10.1.80.92",</span><br><span class="line">    "10.1.80.93"</span><br><span class="line">  ],</span><br><span class="line">  "key": &#123;</span><br><span class="line">    "algo": "ecdsa",</span><br><span class="line">    "size": 256</span><br><span class="line">  &#125;,</span><br><span class="line">  "names": [</span><br><span class="line">    &#123;</span><br><span class="line">      "L": "Hangzhou",</span><br><span class="line">      "ST": "Zhejiang",</span><br><span class="line">      "C": "CN"</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h2 id="生成Server和Peer证书-1"><a href="#生成Server和Peer证书-1" class="headerlink" title="生成Server和Peer证书"></a>生成Server和Peer证书</h2><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">cfssl gencert -ca=etcd-ca.pem -ca-key=etcd-ca-key.pem -config=etcd-ca-config.json -profile=server etcd-csr.json | cfssljson -bare etcd-server</span><br><span class="line"></span><br><span class="line">cfssl gencert -ca=etcd-ca.pem -ca-key=etcd-ca-key.pem -config=etcd-ca-config.json -profile=peer etcd-csr.json | cfssljson -bare etcd-peer</span><br></pre></td></tr></table></figure><p>生成以下文件</p><ul><li>etcd-server.csr</li><li>etcd-server-key.pem</li><li>etcd-server.pem</li><li>etcd-peer.csr</li><li>etcd-peer-key.pem</li><li>etcd-peer.pem</li></ul><h1 id="生成Client证书"><a href="#生成Client证书" class="headerlink" title="生成Client证书"></a>生成Client证书</h1><h2 id="Client配置"><a href="#Client配置" class="headerlink" title="Client配置"></a>Client配置</h2><p>客户端证书不需要hosts字段，只需要CN字段设置为client</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">mkdir -p /tmp/certs</span><br><span class="line"></span><br><span class="line">cat &gt; /tmp/certs/etcd-client-csr.json &lt;&lt;EOF</span><br><span class="line">&#123;</span><br><span class="line">  "CN": "etcd-client",</span><br><span class="line">  "key": &#123;</span><br><span class="line">    "algo": "ecdsa",</span><br><span class="line">    "size": 256</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><h2 id="生成Client证书-1"><a href="#生成Client证书-1" class="headerlink" title="生成Client证书"></a>生成Client证书</h2><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">cfssl gencert -ca=etcd-ca.pem -ca-key=etcd-ca-key.pem -config=etcd-ca-config.json -profile=client etcd-client-csr.json  | cfssljson -bare etcd-client</span><br></pre></td></tr></table></figure><p>生成以下文件</p><ul><li>etcd-client.csr</li><li>etcd-client-key.pem</li><li>etcd-client.pem</li></ul><h1 id="创建3节点集群"><a href="#创建3节点集群" class="headerlink" title="创建3节点集群"></a>创建3节点集群</h1><h2 id="安装etcd"><a href="#安装etcd" class="headerlink" title="安装etcd"></a>安装etcd</h2><p>s91,s92,s93上安装etcd</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></pre></td><td class="code"><pre><span class="line">ETCD_VER=v3.5.4</span><br><span class="line">ETCD_INSTALL_PATH=/opt/etcd3</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> choose either URL</span><br><span class="line"><span class="meta">#</span> GOOGLE_URL=https://storage.googleapis.com/etcd</span><br><span class="line">GITHUB_URL=https://github.com/etcd-io/etcd/releases/download</span><br><span class="line">DOWNLOAD_URL=$&#123;GITHUB_URL&#125;</span><br><span class="line"></span><br><span class="line">mkdir -p $&#123;ETCD_INSTALL_PATH&#125;</span><br><span class="line">curl -L $&#123;DOWNLOAD_URL&#125;/$&#123;ETCD_VER&#125;/etcd-$&#123;ETCD_VER&#125;-linux-amd64.tar.gz -o $&#123;ETCD_INSTALL_PATH&#125;/etcd-$&#123;ETCD_VER&#125;-linux-amd64.tar.gz</span><br><span class="line">tar xzvf $&#123;ETCD_INSTALL_PATH&#125;/etcd-$&#123;ETCD_VER&#125;-linux-amd64.tar.gz -C /opt/etcd3 --strip-components=1</span><br><span class="line">rm -f $&#123;ETCD_INSTALL_PATH&#125;/etcd-$&#123;ETCD_VER&#125;-linux-amd64.tar.gz</span><br><span class="line"></span><br><span class="line"><span class="meta">$</span>&#123;ETCD_INSTALL_PATH&#125;/etcd --version</span><br><span class="line"><span class="meta">$</span>&#123;ETCD_INSTALL_PATH&#125;/etcdctl version</span><br></pre></td></tr></table></figure><h2 id="创建证书存放目录"><a href="#创建证书存放目录" class="headerlink" title="创建证书存放目录"></a>创建证书存放目录</h2><p>每个节点创建证书存放目录<br><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">mkdir -p /opt/etcd3/ssl</span><br></pre></td></tr></table></figure></p><h2 id="将证书传到s91-s92-s93"><a href="#将证书传到s91-s92-s93" class="headerlink" title="将证书传到s91, s92, s93"></a>将证书传到s91, s92, s93</h2><p>方便起见，就把所有文件都传了<br><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">scp -r /tmp/certs/etcd-*.pem root@10.1.80.91:/opt/etcd3/ssl</span><br><span class="line">scp -r /tmp/certs/etcd-*.pem root@10.1.80.92:/opt/etcd3/ssl</span><br><span class="line">scp -r /tmp/certs/etcd-*.pem root@10.1.80.93:/opt/etcd3/ssl</span><br></pre></td></tr></table></figure></p><h2 id="frontend-运行etcd-不推荐"><a href="#frontend-运行etcd-不推荐" class="headerlink" title="frontend 运行etcd(不推荐)"></a>frontend 运行etcd(不推荐)</h2><h3 id="运行etcd的模板"><a href="#运行etcd的模板" class="headerlink" title="运行etcd的模板"></a>运行etcd的模板</h3><p>–initial-cluster-token etcd-cluster-tkn  “etcd-cluster-tkn”可以替换成你自己需要的值</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></pre></td><td class="code"><pre><span class="line">./etcd -name etcd1 \</span><br><span class="line">  --data-dir /tmp/etcd/s1 \</span><br><span class="line">  --auto-tls \</span><br><span class="line">  --client-cert-auth \ # 要求客户端验证</span><br><span class="line">  --cert-file=/opt/etcd3/ssl/etcd-server.pem \ # 服务端证书</span><br><span class="line">  --key-file=/opt/etcd3/ssl/etcd-server-key.pem \ # 服务端私钥</span><br><span class="line">  --trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \ # 服务端CA根证书</span><br><span class="line">  --peer-auto-tls \</span><br><span class="line">  --peer-cert-file=/opt/etcd3/ssl/etcd-peer.pem \ # 节点通信证书</span><br><span class="line">  --peer-key-file=/opt/etcd3/ssl/etcd-peer-key.pem \ # 节点通信私钥</span><br><span class="line">  --peer-client-cert-auth \ # 要求节点通信验证</span><br><span class="line">  --peer-trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \ #节点通信CA根证书</span><br><span class="line">  --advertise-client-urls https://10.1.80.91:2379 \ # 所有url都变成https协议</span><br><span class="line">  --listen-client-urls https://10.1.80.91:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.91:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.91:2380 \</span><br><span class="line">  --initial-cluster-token etcd-cluster-tkn \</span><br><span class="line">  --initial-cluster "s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380" \</span><br><span class="line">  --initial-cluster-state new</span><br></pre></td></tr></table></figure><h3 id="分别在s91-s92-s93上运行etcd"><a href="#分别在s91-s92-s93上运行etcd" class="headerlink" title="分别在s91,s92,s93上运行etcd"></a>分别在s91,s92,s93上运行etcd</h3><ul><li><p>节点1</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> make sure etcd process has write access to this directory</span><br><span class="line"><span class="meta">#</span> remove this directory if the cluster is new; keep if restarting etcd</span><br><span class="line"><span class="meta">#</span> rm -rf /tmp/etcd</span><br><span class="line"></span><br><span class="line">./etcd -name s1 \</span><br><span class="line">  --data-dir /tmp/etcd-data \</span><br><span class="line">  --auto-tls \</span><br><span class="line">  --client-cert-auth \</span><br><span class="line">  --cert-file=/opt/etcd3/ssl/etcd-server.pem \</span><br><span class="line">  --key-file=/opt/etcd3/ssl/etcd-server-key.pem \</span><br><span class="line">  --trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --peer-auto-tls \</span><br><span class="line">  --peer-cert-file=/opt/etcd3/ssl/etcd-peer.pem \</span><br><span class="line">  --peer-key-file=/opt/etcd3/ssl/etcd-peer-key.pem \</span><br><span class="line">  --peer-client-cert-auth \</span><br><span class="line">  --peer-trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --advertise-client-urls https://10.1.80.91:2379 \</span><br><span class="line">  --listen-client-urls https://10.1.80.91:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.91:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.91:2380 \</span><br><span class="line">  --initial-cluster-token etcd-cluster-tkn \</span><br><span class="line">  --initial-cluster "s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380" \</span><br><span class="line">  --initial-cluster-state new</span><br></pre></td></tr></table></figure></li><li><p>节点2</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> make sure etcd process has write access to this directory</span><br><span class="line"><span class="meta">#</span> remove this directory if the cluster is new; keep if restarting etcd</span><br><span class="line"><span class="meta">#</span> rm -rf /tmp/etcd</span><br><span class="line"></span><br><span class="line">./etcd -name s2 \</span><br><span class="line">  --data-dir /tmp/etcd-data \</span><br><span class="line">  --auto-tls \</span><br><span class="line">  --client-cert-auth \</span><br><span class="line">  --cert-file=/opt/etcd3/ssl/etcd-server.pem \</span><br><span class="line">  --key-file=/opt/etcd3/ssl/etcd-server-key.pem \</span><br><span class="line">  --trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --peer-auto-tls \</span><br><span class="line">  --peer-cert-file=/opt/etcd3/ssl/etcd-peer.pem \</span><br><span class="line">  --peer-key-file=/opt/etcd3/ssl/etcd-peer-key.pem \</span><br><span class="line">  --peer-client-cert-auth \</span><br><span class="line">  --peer-trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --advertise-client-urls https://10.1.80.92:2379 \</span><br><span class="line">  --listen-client-urls https://10.1.80.92:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.92:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.92:2380 \</span><br><span class="line">  --initial-cluster-token etcd-cluster-tkn \</span><br><span class="line">  --initial-cluster "s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380" \</span><br><span class="line">  --initial-cluster-state new</span><br></pre></td></tr></table></figure></li><li><p>节点3</p></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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> make sure etcd process has write access to this directory</span><br><span class="line"><span class="meta">#</span> remove this directory if the cluster is new; keep if restarting etcd</span><br><span class="line"><span class="meta">#</span> rm -rf /tmp/etcd</span><br><span class="line"></span><br><span class="line">./etcd -name s3 \</span><br><span class="line">  --data-dir /tmp/etcd-data \</span><br><span class="line">  --auto-tls \</span><br><span class="line">  --client-cert-auth \</span><br><span class="line">  --cert-file=/opt/etcd3/ssl/etcd-server.pem \</span><br><span class="line">  --key-file=/opt/etcd3/ssl/etcd-server-key.pem \</span><br><span class="line">  --trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --peer-auto-tls \</span><br><span class="line">  --peer-cert-file=/opt/etcd3/ssl/etcd-peer.pem \</span><br><span class="line">  --peer-key-file=/opt/etcd3/ssl/etcd-peer-key.pem \</span><br><span class="line">  --peer-client-cert-auth \</span><br><span class="line">  --peer-trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --advertise-client-urls https://10.1.80.93:2379 \</span><br><span class="line">  --listen-client-urls https://10.1.80.93:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.93:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.93:2380 \</span><br><span class="line">  --initial-cluster-token etcd-cluster-tkn \</span><br><span class="line">  --initial-cluster "s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380" \</span><br><span class="line">  --initial-cluster-state new</span><br></pre></td></tr></table></figure><p>检查etcd集群状态</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></pre></td><td class="code"><pre><span class="line">ETCDCTL_API=3 </span><br><span class="line">/opt/etcd3/etcdctl \</span><br><span class="line">  --endpoints 10.1.80.91:2379,10.1.80.92:2379,10.1.80.93:2379 \</span><br><span class="line">  --cacert /opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --cert  /opt/etcd3/ssl/etcd-server.pem \</span><br><span class="line">  --key  /opt/etcd3/ssl/etcd-server-key.pem \</span><br><span class="line">  endpoint health</span><br></pre></td></tr></table></figure><h2 id="systemd运行方式-强烈推荐"><a href="#systemd运行方式-强烈推荐" class="headerlink" title="systemd运行方式(强烈推荐)"></a>systemd运行方式(强烈推荐)</h2><p>如果之前通过frontend方式运行过apisix,记得要停掉之前的apisix进程。</p><p>证书先拷贝到/opt/etcd3/ssl目录<br><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> make sure etcd process has write access to this directory</span><br><span class="line"><span class="meta">#</span> remove this directory if the cluster is new; keep if restarting etcd</span><br><span class="line"><span class="meta">#</span> rm -rf /tmp/etcd/s1</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> to write service file for etcd</span><br></pre></td></tr></table></figure></p><h3 id="s1"><a href="#s1" class="headerlink" title="s1"></a>s1</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><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></pre></td><td class="code"><pre><span class="line">cat &gt; /tmp/s1.service &lt;&lt;EOF</span><br><span class="line">[Unit]</span><br><span class="line">Description=etcd</span><br><span class="line">Documentation=https://github.com/coreos/etcd</span><br><span class="line">Conflicts=etcd.service</span><br><span class="line">Conflicts=etcd2.service</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=notify</span><br><span class="line">Restart=always</span><br><span class="line">RestartSec=5s</span><br><span class="line">LimitNOFILE=40000</span><br><span class="line">TimeoutStartSec=0</span><br><span class="line"></span><br><span class="line">ExecStart=/opt/etcd3/etcd -name s1 \</span><br><span class="line">  --data-dir /tmp/etcd-data \</span><br><span class="line">  --auto-tls \</span><br><span class="line">  --client-cert-auth \</span><br><span class="line">  --cert-file=/opt/etcd3/ssl/etcd-server.pem \</span><br><span class="line">  --key-file=/opt/etcd3/ssl/etcd-server-key.pem \</span><br><span class="line">  --trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --peer-auto-tls \</span><br><span class="line">  --peer-cert-file=/opt/etcd3/ssl/etcd-peer.pem \</span><br><span class="line">  --peer-key-file=/opt/etcd3/ssl/etcd-peer-key.pem \</span><br><span class="line">  --peer-client-cert-auth \</span><br><span class="line">  --peer-trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --advertise-client-urls https://10.1.80.91:2379 \</span><br><span class="line">  --listen-client-urls https://10.1.80.91:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.91:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.91:2380 \</span><br><span class="line">  --initial-cluster-token etcd-cluster-tkn \</span><br><span class="line">  --initial-cluster "s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380" \</span><br><span class="line">  --initial-cluster-state new</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">sudo mv /tmp/s1.service /etc/systemd/system/s1.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> to start service</span><br><span class="line">sudo systemctl daemon-reload</span><br><span class="line">sudo systemctl enable s1.service</span><br><span class="line">sudo systemctl start s1.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> cat s1.service</span><br><span class="line">sudo systemctl cat s1.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> to get logs from service</span><br><span class="line">sudo systemctl status s1.service -l --no-pager</span><br><span class="line">sudo journalctl -u s1.service -l --no-pager|less</span><br><span class="line">sudo journalctl -f -u s1.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> to stop service</span><br><span class="line">sudo systemctl stop s1.service</span><br><span class="line">sudo systemctl disable s1.service</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"><span class="meta">#</span> to start service</span><br></pre></td></tr></table></figure><h3 id="s2"><a href="#s2" class="headerlink" title="s2"></a>s2</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><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></pre></td><td class="code"><pre><span class="line">cat &gt; /tmp/s2.service &lt;&lt;EOF</span><br><span class="line">[Unit]</span><br><span class="line">Description=etcd</span><br><span class="line">Documentation=https://github.com/coreos/etcd</span><br><span class="line">Conflicts=etcd.service</span><br><span class="line">Conflicts=etcd2.service</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=notify</span><br><span class="line">Restart=always</span><br><span class="line">RestartSec=5s</span><br><span class="line">LimitNOFILE=40000</span><br><span class="line">TimeoutStartSec=0</span><br><span class="line"></span><br><span class="line">ExecStart=/opt/etcd3/etcd -name s2 \</span><br><span class="line">  --data-dir /tmp/etcd-data \</span><br><span class="line">  --auto-tls \</span><br><span class="line">  --client-cert-auth \</span><br><span class="line">  --cert-file=/opt/etcd3/ssl/etcd-server.pem \</span><br><span class="line">  --key-file=/opt/etcd3/ssl/etcd-server-key.pem \</span><br><span class="line">  --trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --peer-auto-tls \</span><br><span class="line">  --peer-cert-file=/opt/etcd3/ssl/etcd-peer.pem \</span><br><span class="line">  --peer-key-file=/opt/etcd3/ssl/etcd-peer-key.pem \</span><br><span class="line">  --peer-client-cert-auth \</span><br><span class="line">  --peer-trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --advertise-client-urls https://10.1.80.92:2379 \</span><br><span class="line">  --listen-client-urls https://10.1.80.92:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.92:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.92:2380 \</span><br><span class="line">  --initial-cluster-token etcd-cluster-tkn \</span><br><span class="line">  --initial-cluster "s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380" \</span><br><span class="line">  --initial-cluster-state new</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">sudo mv /tmp/s2.service /etc/systemd/system/s2.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> to start service</span><br><span class="line">sudo systemctl daemon-reload</span><br><span class="line">sudo systemctl enable s2.service</span><br><span class="line">sudo systemctl start s2.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> cat s2.service</span><br><span class="line">sudo systemctl cat s2.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> to get logs from service</span><br><span class="line">sudo systemctl status s2.service -l --no-pager</span><br><span class="line">sudo journalctl -u s2.service -l --no-pager|less</span><br><span class="line">sudo journalctl -f -u s2.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> to stop service</span><br><span class="line">sudo systemctl stop s2.service</span><br><span class="line">sudo systemctl disable s2.service</span><br></pre></td></tr></table></figure><h3 id="s3"><a href="#s3" class="headerlink" title="s3"></a>s3</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><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></pre></td><td class="code"><pre><span class="line">cat &gt; /tmp/s3.service &lt;&lt;EOF</span><br><span class="line">[Unit]</span><br><span class="line">Description=etcd</span><br><span class="line">Documentation=https://github.com/coreos/etcd</span><br><span class="line">Conflicts=etcd.service</span><br><span class="line">Conflicts=etcd2.service</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=notify</span><br><span class="line">Restart=always</span><br><span class="line">RestartSec=5s</span><br><span class="line">LimitNOFILE=40000</span><br><span class="line">TimeoutStartSec=0</span><br><span class="line"></span><br><span class="line">ExecStart=/opt/etcd3/etcd -name s3 \</span><br><span class="line">  --data-dir /tmp/etcd-data \</span><br><span class="line">  --auto-tls \</span><br><span class="line">  --client-cert-auth \</span><br><span class="line">  --cert-file=/opt/etcd3/ssl/etcd-server.pem \</span><br><span class="line">  --key-file=/opt/etcd3/ssl/etcd-server-key.pem \</span><br><span class="line">  --trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --peer-auto-tls \</span><br><span class="line">  --peer-cert-file=/opt/etcd3/ssl/etcd-peer.pem \</span><br><span class="line">  --peer-key-file=/opt/etcd3/ssl/etcd-peer-key.pem \</span><br><span class="line">  --peer-client-cert-auth \</span><br><span class="line">  --peer-trusted-ca-file=/opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">  --advertise-client-urls https://10.1.80.93:2379 \</span><br><span class="line">  --listen-client-urls https://10.1.80.93:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.93:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.93:2380 \</span><br><span class="line">  --initial-cluster-token etcd-cluster-tkn \</span><br><span class="line">  --initial-cluster "s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380" \</span><br><span class="line">  --initial-cluster-state new</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">sudo mv /tmp/s3.service /etc/systemd/system/s3.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> to start service</span><br><span class="line">sudo systemctl daemon-reload</span><br><span class="line">sudo systemctl enable s3.service</span><br><span class="line">sudo systemctl start s3.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> cat s3.service</span><br><span class="line">sudo systemctl cat s3.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> to get logs from service</span><br><span class="line">sudo systemctl status s3.service -l --no-pager</span><br><span class="line">sudo journalctl -u s3.service -l --no-pager|less</span><br><span class="line">sudo journalctl -f -u s3.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> to stop service</span><br><span class="line">sudo systemctl stop s3.service</span><br><span class="line">sudo systemctl disable s3.service</span><br></pre></td></tr></table></figure><p>Check status:</p><p>etcdctl检查<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">ETCDCTL_API=3 </span><br><span class="line">/opt/etcd3/etcdctl \</span><br><span class="line">--cacert /opt/etcd3/ssl/etcd-ca.pem \</span><br><span class="line">--cert /opt/etcd3/ssl/etcd-server.pem \</span><br><span class="line">--key /opt/etcd3/ssl/etcd-server-key.pem \</span><br><span class="line">--endpoints 10.1.80.91:2379,10.1.80.92:2379,10.1.80.93:2379 \</span><br><span class="line">endpoint health</span><br></pre></td></tr></table></figure></p><p>curl检查<br><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> curl查看健康状态</span><br><span class="line">curl --cacert /opt/etcd3/ssl/etcd-ca.pem --cert /opt/etcd3/ssl/etcd-server.pem --key /opt/etcd3/ssl/etcd-server-key.pem  https://10.1.80.91:2379/health</span><br></pre></td></tr></table></figure></p><p>注意切换到指定用户</p><p>若结果如下，表示集群状态正常<br><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">10.1.80.93:2379 is healthy: successfully committed proposal: took = 6.506639ms</span><br><span class="line">10.1.80.91:2379 is healthy: successfully committed proposal: took = 6.427877ms</span><br><span class="line">10.1.80.92:2379 is healthy: successfully committed proposal: took = 7.161322ms</span><br></pre></td></tr></table></figure></p><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><p><a href="http://play.etcd.io/install" target="_blank" rel="noopener">etcd Labs</a></p><p><a href="https://www.cnblogs.com/LiuChang-blog/p/15916998.html" target="_blank" rel="noopener">cfssl ca证书有效期修改</a></p><p><a href="https://cmjava.ltd:8090/archives/apisix%E9%85%8D%E7%BD%AE%E9%9C%80%E8%A6%81%E8%AF%81%E4%B9%A6%E7%9A%84etcd%E9%9B%86%E7%BE%A4" target="_blank" rel="noopener">apisix配置需要证书的etcd集群</a></p><p><a href="https://cmjava.ltd:8090/archives/%E4%B8%BAetcd%E9%9B%86%E7%BE%A4%E9%85%8D%E7%BD%AE%E8%AF%81%E4%B9%A6" target="_blank" rel="noopener">为etcd集群配置证书</a></p><p><a href="https://blog.csdn.net/xiaozhiit/article/details/108304488" target="_blank" rel="noopener">ETCD集群搭建和TLS证书访问</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;[toc]&lt;/p&gt;
&lt;h1 id=&quot;环境&quot;&gt;&lt;a href=&quot;#环境&quot; class=&quot;headerlink&quot; title=&quot;环境&quot;&gt;&lt;/a&gt;环境&lt;/h1&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;IP&lt;/th&gt;
&lt;th&gt;主机名&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>安装部署3节点Etcd高可用集群(3节点同一套证书)</title>
    <link href="http://jaychang.cn/2022/10/10/%E5%AE%89%E8%A3%85%E9%83%A8%E7%BD%B23%E8%8A%82%E7%82%B9Etcd%E9%AB%98%E5%8F%AF%E7%94%A8%E9%9B%86%E7%BE%A4-3%E8%8A%82%E7%82%B9%E5%90%8C%E4%B8%80%E5%A5%97%E8%AF%81%E4%B9%A6/"/>
    <id>http://jaychang.cn/2022/10/10/安装部署3节点Etcd高可用集群-3节点同一套证书/</id>
    <published>2022-10-10T14:19:46.000Z</published>
    <updated>2022-10-10T14:19:54.672Z</updated>
    
    <content type="html"><![CDATA[<h1 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h1><table><thead><tr><th>IP</th><th>主机名</th></tr></thead><tbody><tr><td>10.1.80.91</td><td>s1</td></tr><tr><td>10.1.80.92</td><td>s2</td></tr><tr><td>10.1.80.93</td><td>s3</td></tr></tbody></table><h1 id="安装cfssl"><a href="#安装cfssl" class="headerlink" title="安装cfssl"></a>安装cfssl</h1><table><thead><tr><th>cfssl版本</th><th>可执行文件存放目录</th><th>证书存放目录</th></tr></thead><tbody><tr><td>1.6.2</td><td>/usr/local/bin</td><td>/tmp/certs</td></tr></tbody></table><blockquote><p>下载地址<br><a href="https://github.com/cloudflare/cfssl/releases" target="_blank" rel="noopener">https://github.com/cloudflare/cfssl/releases</a></p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.2/cfssl_1.6.2_linux_amd64 -o /tmp/cfssl</span><br><span class="line">chmod +x /tmp/cfssl</span><br><span class="line">mv /tmp/cfssl /usr/bin/cfssl</span><br><span class="line"></span><br><span class="line">curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.2/cfssljson_1.6.2_linux_amd64 -o /tmp/cfssljson</span><br><span class="line">chmod +x /tmp/cfssljson</span><br><span class="line">mv /tmp/cfssljson /usr/bin/cfssljson</span><br></pre></td></tr></table></figure><h1 id="生成自签名CA证书"><a href="#生成自签名CA证书" class="headerlink" title="生成自签名CA证书"></a>生成自签名CA证书</h1><blockquote><p>可通过<a href="http://play.etcd.io/install生成配置" target="_blank" rel="noopener">http://play.etcd.io/install生成配置</a></p></blockquote><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></pre></td><td class="code"><pre><span class="line">mkdir -p /tmp/certs</span><br><span class="line"></span><br><span class="line">cat &gt; /tmp/certs/root-ca-csr.json &lt;&lt;EOF</span><br><span class="line">&#123;</span><br><span class="line">  &quot;key&quot;: &#123;</span><br><span class="line">    &quot;algo&quot;: &quot;rsa&quot;,</span><br><span class="line">    &quot;size&quot;: 2048</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;names&quot;: [</span><br><span class="line">    &#123;</span><br><span class="line">      &quot;O&quot;: &quot;Meeleet&quot;,</span><br><span class="line">      &quot;OU&quot;: &quot;Meeleet Security&quot;,</span><br><span class="line">      &quot;L&quot;: &quot;Hangzhou&quot;,</span><br><span class="line">      &quot;ST&quot;: &quot;Zhejiang&quot;,</span><br><span class="line">      &quot;C&quot;: &quot;CN&quot;</span><br><span class="line">    &#125;</span><br><span class="line">  ],</span><br><span class="line">  &quot;CN&quot;: &quot;root-ca&quot;</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br><span class="line">cfssl gencert --initca=true /tmp/certs/root-ca-csr.json | cfssljson --bare /tmp/certs/root-ca</span><br><span class="line"></span><br><span class="line"># verify</span><br><span class="line">openssl x509 -in /tmp/certs/root-ca.pem -text -noout</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># cert-generation configuration</span><br><span class="line">cat &gt; /tmp/certs/gencert.json &lt;&lt;EOF</span><br><span class="line">&#123;</span><br><span class="line">  &quot;signing&quot;: &#123;</span><br><span class="line">    &quot;default&quot;: &#123;</span><br><span class="line">        &quot;usages&quot;: [</span><br><span class="line">          &quot;signing&quot;,</span><br><span class="line">          &quot;key encipherment&quot;,</span><br><span class="line">          &quot;server auth&quot;,</span><br><span class="line">          &quot;client auth&quot;</span><br><span class="line">        ],</span><br><span class="line">        &quot;expiry&quot;: &quot;876000h&quot;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><p>结果<br><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> CSR configuration</span></span><br><span class="line">/tmp/certs/root-ca-csr.json</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> CSR</span></span><br><span class="line">/tmp/certs/root-ca.csr</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> self-signed root CA public key</span></span><br><span class="line">/tmp/certs/root-ca.pem</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> self-signed root CA private key</span></span><br><span class="line">/tmp/certs/root-ca-key.pem</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> cert-generation configuration <span class="keyword">for</span> other TLS assets</span></span><br><span class="line">/tmp/certs/gencert.json</span><br></pre></td></tr></table></figure></p><h1 id="生成本地颁发的带有私钥的证书"><a href="#生成本地颁发的带有私钥的证书" class="headerlink" title="生成本地颁发的带有私钥的证书"></a>生成本地颁发的带有私钥的证书</h1><h2 id="证书相关操作"><a href="#证书相关操作" class="headerlink" title="证书相关操作"></a>证书相关操作</h2><p>由于3个节点用同一套证书，所以只需生成一套即可</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></pre></td><td class="code"><pre><span class="line">mkdir -p /tmp/certs</span><br><span class="line"></span><br><span class="line">cat &gt; /tmp/certs/etcd-ca-csr.json &lt;&lt;EOF</span><br><span class="line">&#123;</span><br><span class="line">  "key": &#123;</span><br><span class="line">    "algo": "rsa",</span><br><span class="line">    "size": 2048</span><br><span class="line">  &#125;,</span><br><span class="line">  "names": [</span><br><span class="line">    &#123;</span><br><span class="line">      "O": "Meeleet",</span><br><span class="line">      "OU": "Meeleet Security",</span><br><span class="line">      "L": "Hangzhou",</span><br><span class="line">      "ST": "Zhejiang",</span><br><span class="line">      "C": "CN"</span><br><span class="line">    &#125;</span><br><span class="line">  ],</span><br><span class="line">  "CN": "etcd",</span><br><span class="line">  "hosts": [</span><br><span class="line">    "127.0.0.1",</span><br><span class="line">    "localhost",</span><br><span class="line">    "10.1.80.91",</span><br><span class="line">    "10.1.80.92",</span><br><span class="line">    "10.1.80.93"</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br><span class="line">cfssl gencert \</span><br><span class="line">  --ca /tmp/certs/root-ca.pem \</span><br><span class="line">  --ca-key /tmp/certs/root-ca-key.pem \</span><br><span class="line">  --config /tmp/certs/gencert.json \</span><br><span class="line">  /tmp/certs/etcd-ca-csr.json | cfssljson --bare /tmp/certs/etcd</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> verify</span></span><br><span class="line">openssl x509 -in /tmp/certs/etcd.pem -text -noout</span><br></pre></td></tr></table></figure><p>结果<br><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">-rw-r--r--  1 root root  323 Sep 30 05:28 etcd-ca-csr.json</span><br><span class="line">-rw-r--r--  1 root root 1098 Sep 30 05:28 etcd.csr</span><br><span class="line">-rw-------  1 root root 1679 Sep 30 05:28 etcd-key.pem</span><br><span class="line">-rw-r--r--  1 root root 1493 Sep 30 05:28 etcd.pem</span><br><span class="line">-rw-r--r--  1 root root  205 Sep 30 05:25 gencert.json</span><br><span class="line">-rw-r--r--  1 root root 1017 Sep 30 05:25 root-ca.csr</span><br><span class="line">-rw-r--r--  1 root root  221 Sep 30 05:25 root-ca-csr.json</span><br><span class="line">-rw-------  1 root root 1679 Sep 30 05:25 root-ca-key.pem</span><br><span class="line">-rw-r--r--  1 root root 1346 Sep 30 05:25 root-ca.pem</span><br></pre></td></tr></table></figure></p><p>将证书传到s91, s92, s93,方便起见，就把所有文件都传了<br><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">scp -r /tmp/certs/ root@10.1.80.91:/root/</span><br><span class="line">scp -r /tmp/certs/ root@10.1.80.92:/root/</span><br><span class="line">scp -r /tmp/certs/ root@10.1.80.93:/root/</span><br></pre></td></tr></table></figure></p><p>这里请更改成您自己所用的系统用户名</p><h1 id="安装etcd"><a href="#安装etcd" class="headerlink" title="安装etcd"></a>安装etcd</h1><p>s91,s92,s93上安装etcd</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></pre></td><td class="code"><pre><span class="line">ETCD_VER=v3.4.21</span><br><span class="line">ETCD_INSTALL_PATH=/opt/etcd3</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> choose either URL</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> GOOGLE_URL=https://storage.googleapis.com/etcd</span></span><br><span class="line">GITHUB_URL=https://github.com/etcd-io/etcd/releases/download</span><br><span class="line">DOWNLOAD_URL=$&#123;GITHUB_URL&#125;</span><br><span class="line"></span><br><span class="line">mkdir -p $&#123;ETCD_INSTALL_PATH&#125;</span><br><span class="line">curl -L $&#123;DOWNLOAD_URL&#125;/$&#123;ETCD_VER&#125;/etcd-$&#123;ETCD_VER&#125;-linux-amd64.tar.gz -o $&#123;ETCD_INSTALL_PATH&#125;/etcd-$&#123;ETCD_VER&#125;-linux-amd64.tar.gz</span><br><span class="line">tar xzvf $&#123;ETCD_INSTALL_PATH&#125;/etcd-$&#123;ETCD_VER&#125;-linux-amd64.tar.gz -C /opt/etcd3 --strip-components=1</span><br><span class="line">rm -f $&#123;ETCD_INSTALL_PATH&#125;/etcd-$&#123;ETCD_VER&#125;-linux-amd64.tar.gz</span><br><span class="line"></span><br><span class="line"><span class="meta">$</span><span class="bash">&#123;ETCD_INSTALL_PATH&#125;/etcd --version</span></span><br><span class="line"><span class="meta">$</span><span class="bash">&#123;ETCD_INSTALL_PATH&#125;/etcdctl version</span></span><br></pre></td></tr></table></figure><h1 id="frontend-运行etcd-不推荐，只用于测试功能用"><a href="#frontend-运行etcd-不推荐，只用于测试功能用" class="headerlink" title="frontend 运行etcd(不推荐，只用于测试功能用)"></a>frontend 运行etcd(不推荐，只用于测试功能用)</h1><p>分别在s91,s92,s93上运行etcd</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> make sure etcd process has write access to this directory</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> remove this directory <span class="keyword">if</span> the cluster is new; keep <span class="keyword">if</span> restarting etcd</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> rm -rf /tmp/etcd</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">/opt/etcd3/etcd --name s1 \</span><br><span class="line">  --data-dir /tmp/etcd/s1 \</span><br><span class="line">  --listen-client-urls https://10.1.80.91:2379 \</span><br><span class="line">  --advertise-client-urls https://10.1.80.91:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.91:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.91:2380 \</span><br><span class="line">  --initial-cluster s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380 \</span><br><span class="line">  --initial-cluster-token tkn \</span><br><span class="line">  --initial-cluster-state new \</span><br><span class="line">  --client-cert-auth \</span><br><span class="line">  --trusted-ca-file $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --cert-file $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --key-file $&#123;HOME&#125;/certs/etcd-key.pem \</span><br><span class="line">  --peer-client-cert-auth \</span><br><span class="line">  --peer-trusted-ca-file $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --peer-cert-file $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --peer-key-file $&#123;HOME&#125;/certs/etcd-key.pem</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><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">/opt/etcd3/etcd --name s2 \</span><br><span class="line">  --data-dir /tmp/etcd/s2 \</span><br><span class="line">  --listen-client-urls https://10.1.80.92:2379 \</span><br><span class="line">  --advertise-client-urls https://10.1.80.92:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.92:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.92:2380 \</span><br><span class="line">  --initial-cluster s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380 \</span><br><span class="line">  --initial-cluster-token tkn \</span><br><span class="line">  --initial-cluster-state new \</span><br><span class="line">  --client-cert-auth \</span><br><span class="line">  --trusted-ca-file $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --cert-file $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --key-file $&#123;HOME&#125;/certs/etcd-key.pem \</span><br><span class="line">  --peer-client-cert-auth \</span><br><span class="line">  --peer-trusted-ca-file $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --peer-cert-file $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --peer-key-file $&#123;HOME&#125;/certs/etcd-key.pem</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><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">/opt/etcd3/etcd --name s3 \</span><br><span class="line">  --data-dir /tmp/etcd/s3 \</span><br><span class="line">  --listen-client-urls https://10.1.80.93:2379 \</span><br><span class="line">  --advertise-client-urls https://10.1.80.93:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.93:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.93:2380 \</span><br><span class="line">  --initial-cluster s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380 \</span><br><span class="line">  --initial-cluster-token tkn \</span><br><span class="line">  --initial-cluster-state new \</span><br><span class="line">  --client-cert-auth \</span><br><span class="line">  --trusted-ca-file $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --cert-file $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --key-file $&#123;HOME&#125;/certs/etcd-key.pem \</span><br><span class="line">  --peer-client-cert-auth \</span><br><span class="line">  --peer-trusted-ca-file $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --peer-cert-file $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --peer-key-file $&#123;HOME&#125;/certs/etcd-key.pem</span><br></pre></td></tr></table></figure><p>–initial-cluster-token tkn  “tkn”可以替换成你自己需要的值</p><p>检查etcd集群状态</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">ETCDCTL_API=3 /opt/etcd3/etcdctl \</span><br><span class="line">  --endpoints 10.1.80.91:2379,10.1.80.92:2379,10.1.80.93:2379 \</span><br><span class="line">  --cacert $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --cert $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --key $&#123;HOME&#125;/certs/etcd-key.pem \</span><br><span class="line">  endpoint health</span><br></pre></td></tr></table></figure><h1 id="systemd运行方式-推荐"><a href="#systemd运行方式-推荐" class="headerlink" title="systemd运行方式(推荐)"></a>systemd运行方式(推荐)</h1><h2 id="s1"><a href="#s1" class="headerlink" title="s1"></a>s1</h2><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><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> after transferring certs to remote machines</span></span><br><span class="line">mkdir -p $&#123;HOME&#125;/certs</span><br><span class="line">cp /tmp/certs/* $&#123;HOME&#125;/certs</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> make sure etcd process has write access to this directory</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> remove this directory <span class="keyword">if</span> the cluster is new; keep <span class="keyword">if</span> restarting etcd</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> rm -rf /tmp/etcd/s1</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> to write service file <span class="keyword">for</span> etcd</span></span><br><span class="line">cat &gt; /tmp/s1.service &lt;&lt;EOF</span><br><span class="line">[Unit]</span><br><span class="line">Description=etcd</span><br><span class="line">Documentation=https://github.com/coreos/etcd</span><br><span class="line">Conflicts=etcd.service</span><br><span class="line">Conflicts=etcd2.service</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=notify</span><br><span class="line">Restart=always</span><br><span class="line">RestartSec=5s</span><br><span class="line">LimitNOFILE=40000</span><br><span class="line">TimeoutStartSec=0</span><br><span class="line"></span><br><span class="line">ExecStart=/opt/etcd3/etcd --name s1 \</span><br><span class="line">  --data-dir /tmp/etcd/s1 \</span><br><span class="line">  --listen-client-urls https://10.1.80.91:2379 \</span><br><span class="line">  --advertise-client-urls https://10.1.80.91:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.91:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.91:2380 \</span><br><span class="line">  --initial-cluster s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380 \</span><br><span class="line">  --initial-cluster-token tkn \</span><br><span class="line">  --initial-cluster-state new \</span><br><span class="line">  --client-cert-auth \</span><br><span class="line">  --trusted-ca-file $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --cert-file $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --key-file $&#123;HOME&#125;/certs/etcd-key.pem \</span><br><span class="line">  --peer-client-cert-auth \</span><br><span class="line">  --peer-trusted-ca-file $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --peer-cert-file $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --peer-key-file $&#123;HOME&#125;/certs/etcd-key.pem</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br><span class="line">EOF</span><br><span class="line">sudo mv /tmp/s1.service /etc/systemd/system/s1.service</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> to start service</span></span><br><span class="line">sudo systemctl daemon-reload</span><br><span class="line">sudo systemctl enable s1.service</span><br><span class="line">sudo systemctl start s1.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> cat s1.service</span></span><br><span class="line">sudo systemctl cat s1.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> to get logs from service</span></span><br><span class="line">sudo systemctl status s1.service -l --no-pager</span><br><span class="line">sudo journalctl -u s1.service -l --no-pager|less</span><br><span class="line">sudo journalctl -f -u s1.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> to stop service</span></span><br><span class="line">sudo systemctl stop s1.service</span><br><span class="line">sudo systemctl disable s1.service</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"><span class="meta">#</span><span class="bash"> to start service</span></span><br></pre></td></tr></table></figure><h2 id="s2"><a href="#s2" class="headerlink" title="s2"></a>s2</h2><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><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> after transferring certs to remote machines</span></span><br><span class="line">mkdir -p $&#123;HOME&#125;/certs</span><br><span class="line">cp /tmp/certs/* $&#123;HOME&#125;/certs</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> make sure etcd process has write access to this directory</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> remove this directory <span class="keyword">if</span> the cluster is new; keep <span class="keyword">if</span> restarting etcd</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> rm -rf /tmp/etcd/s2</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> to write service file <span class="keyword">for</span> etcd</span></span><br><span class="line">cat &gt; /tmp/s2.service &lt;&lt;EOF</span><br><span class="line">[Unit]</span><br><span class="line">Description=etcd</span><br><span class="line">Documentation=https://github.com/coreos/etcd</span><br><span class="line">Conflicts=etcd.service</span><br><span class="line">Conflicts=etcd2.service</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=notify</span><br><span class="line">Restart=always</span><br><span class="line">RestartSec=5s</span><br><span class="line">LimitNOFILE=40000</span><br><span class="line">TimeoutStartSec=0</span><br><span class="line"></span><br><span class="line">ExecStart=/opt/etcd3/etcd --name s2 \</span><br><span class="line">  --data-dir /tmp/etcd/s2 \</span><br><span class="line">  --listen-client-urls https://10.1.80.92:2379 \</span><br><span class="line">  --advertise-client-urls https://10.1.80.92:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.92:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.92:2380 \</span><br><span class="line">  --initial-cluster s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380 \</span><br><span class="line">  --initial-cluster-token tkn \</span><br><span class="line">  --initial-cluster-state new \</span><br><span class="line">  --client-cert-auth \</span><br><span class="line">  --trusted-ca-file $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --cert-file $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --key-file $&#123;HOME&#125;/certs/etcd-key.pem \</span><br><span class="line">  --peer-client-cert-auth \</span><br><span class="line">  --peer-trusted-ca-file $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --peer-cert-file $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --peer-key-file $&#123;HOME&#125;/certs/etcd-key.pem</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br><span class="line">EOF</span><br><span class="line">sudo mv /tmp/s2.service /etc/systemd/system/s2.service</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> to start service</span></span><br><span class="line">sudo systemctl daemon-reload</span><br><span class="line">sudo systemctl enable s2.service</span><br><span class="line">sudo systemctl start s2.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> cat s2.service</span></span><br><span class="line">sudo systemctl cat s2.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> to get logs from service</span></span><br><span class="line">sudo systemctl status s2.service -l --no-pager</span><br><span class="line">sudo journalctl -u s2.service -l --no-pager|less</span><br><span class="line">sudo journalctl -f -u s2.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> to stop service</span></span><br><span class="line">sudo systemctl stop s2.service</span><br><span class="line">sudo systemctl disable s2.service</span><br></pre></td></tr></table></figure><h2 id="s3"><a href="#s3" class="headerlink" title="s3"></a>s3</h2><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><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> after transferring certs to remote machines</span></span><br><span class="line">mkdir -p $&#123;HOME&#125;/certs</span><br><span class="line">cp /tmp/certs/* $&#123;HOME&#125;/certs</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> make sure etcd process has write access to this directory</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> remove this directory <span class="keyword">if</span> the cluster is new; keep <span class="keyword">if</span> restarting etcd</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> rm -rf /tmp/etcd/s3</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> to write service file <span class="keyword">for</span> etcd</span></span><br><span class="line">cat &gt; /tmp/s3.service &lt;&lt;EOF</span><br><span class="line">[Unit]</span><br><span class="line">Description=etcd</span><br><span class="line">Documentation=https://github.com/coreos/etcd</span><br><span class="line">Conflicts=etcd.service</span><br><span class="line">Conflicts=etcd2.service</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=notify</span><br><span class="line">Restart=always</span><br><span class="line">RestartSec=5s</span><br><span class="line">LimitNOFILE=40000</span><br><span class="line">TimeoutStartSec=0</span><br><span class="line"></span><br><span class="line">ExecStart=/opt/etcd3/etcd --name s3 \</span><br><span class="line">  --data-dir /tmp/etcd/s3 \</span><br><span class="line">  --listen-client-urls https://10.1.80.93:2379 \</span><br><span class="line">  --advertise-client-urls https://10.1.80.93:2379 \</span><br><span class="line">  --listen-peer-urls https://10.1.80.93:2380 \</span><br><span class="line">  --initial-advertise-peer-urls https://10.1.80.93:2380 \</span><br><span class="line">  --initial-cluster s1=https://10.1.80.91:2380,s2=https://10.1.80.92:2380,s3=https://10.1.80.93:2380 \</span><br><span class="line">  --initial-cluster-token tkn \</span><br><span class="line">  --initial-cluster-state new \</span><br><span class="line">  --client-cert-auth \</span><br><span class="line">  --trusted-ca-file $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --cert-file $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --key-file $&#123;HOME&#125;/certs/etcd-key.pem \</span><br><span class="line">  --peer-client-cert-auth \</span><br><span class="line">  --peer-trusted-ca-file $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --peer-cert-file $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --peer-key-file $&#123;HOME&#125;/certs/etcd-key.pem</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br><span class="line">EOF</span><br><span class="line">sudo mv /tmp/s3.service /etc/systemd/system/s3.service</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> to start service</span></span><br><span class="line">sudo systemctl daemon-reload</span><br><span class="line">sudo systemctl enable s3.service</span><br><span class="line">sudo systemctl start s3.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> cat s3.service</span></span><br><span class="line">sudo systemctl cat s3.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> to get logs from service</span></span><br><span class="line">sudo systemctl status s3.service -l --no-pager</span><br><span class="line">sudo journalctl -u s3.service -l --no-pager|less</span><br><span class="line">sudo journalctl -f -u s3.service</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> to stop service</span></span><br><span class="line">sudo systemctl stop s3.service</span><br><span class="line">sudo systemctl disable s3.service</span><br></pre></td></tr></table></figure><p>Check status:</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">ETCDCTL_API=3 /opt/etcd3/etcdctl \</span><br><span class="line">  --endpoints 10.1.80.91:2379,10.1.80.92:2379,10.1.80.93:2379 \</span><br><span class="line">  --cacert $&#123;HOME&#125;/certs/root-ca.pem \</span><br><span class="line">  --cert $&#123;HOME&#125;/certs/etcd.pem \</span><br><span class="line">  --key $&#123;HOME&#125;/certs/etcd-key.pem \</span><br><span class="line">  endpoint health</span><br></pre></td></tr></table></figure><p>注意切换到指定用户</p><p>若结果如下，表示集群状态正常<br><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">10.1.80.92:2379 is healthy: successfully committed proposal: took = 9.184858ms</span><br><span class="line">10.1.80.93:2379 is healthy: successfully committed proposal: took = 8.681243ms</span><br><span class="line">10.1.80.91:2379 is healthy: successfully committed proposal: took = 11.855811ms</span><br></pre></td></tr></table></figure></p><h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><p><a href="http://play.etcd.io/install" target="_blank" rel="noopener">etcd Labs</a></p><p><a href="https://www.cnblogs.com/LiuChang-blog/p/15916998.html" target="_blank" rel="noopener">cfssl ca证书有效期修改</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;环境&quot;&gt;&lt;a href=&quot;#环境&quot; class=&quot;headerlink&quot; title=&quot;环境&quot;&gt;&lt;/a&gt;环境&lt;/h1&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;IP&lt;/th&gt;
&lt;th&gt;主机名&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Ubuntu 20.04上配置BIND作为私有网络DNS服务器</title>
    <link href="http://jaychang.cn/2022/10/10/ubuntu20.04-bind9/"/>
    <id>http://jaychang.cn/2022/10/10/ubuntu20.04-bind9/</id>
    <published>2022-10-10T12:03:42.000Z</published>
    <updated>2022-10-10T14:13:08.535Z</updated>
    
    <content type="html"><![CDATA[<h1 id="准备及说明"><a href="#准备及说明" class="headerlink" title="准备及说明"></a>准备及说明</h1><p>假设某公司有多个数据中心，数据中心1以内部使用idc1.meeleet.com,数据中心2使用idc2.meeleet.com,数据中心3使用idc3.meeleet.com。我们这里以数据中心3内部需要搭建私网DNS服务器为例来讲，idc3.meeleet.com(具体实施过程中，按读者实际情况进行修改)</p><ul><li>DNS服务器</li></ul><table><thead><tr><th>私网IP地址</th><th>简称</th><th>是否为主DNS服务器</th></tr></thead><tbody><tr><td>10.1.80.220</td><td>ns1</td><td>是(主DNS服务器)</td></tr><tr><td>10.1.80.221</td><td>ns2</td><td>否(备DNS服务器)</td></tr></tbody></table><ul><li>DNS客户端</li></ul><table><thead><tr><th>私网IP地址</th><th>简称</th></tr></thead><tbody><tr><td>10.1.80.91</td><td>s91</td><td></td></tr><tr><td>10.1.80.92</td><td>s92</td><td></td></tr></tbody></table><h1 id="步骤1-在DNS服务器上安装Bind"><a href="#步骤1-在DNS服务器上安装Bind" class="headerlink" title="步骤1 在DNS服务器上安装Bind"></a>步骤1 在DNS服务器上安装Bind</h1><p>在主DNS服务器及备DNS服务器上安装BIND</p><p><strong>ON ns1 ns2</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">sudo apt install bind9 bind9utils bind9-doc</span><br></pre></td></tr></table></figure><p>修改启动参数<br><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">sudo vi /etc/default/named</span><br></pre></td></tr></table></figure></p><p>OPTIONS参数最后添加-4,使用Ipv4模式<br><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><span class="bash"></span></span><br><span class="line"><span class="meta">#</span><span class="bash"> run resolvconf?</span></span><br><span class="line">RESOLVCONF=no</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> startup options <span class="keyword">for</span> the server</span></span><br><span class="line">OPTIONS="-u bind -4"</span><br></pre></td></tr></table></figure></p><p>重启bind</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">sudo systemctl restart bind9</span><br></pre></td></tr></table></figure><h1 id="步骤2-配置主DNS服务器"><a href="#步骤2-配置主DNS服务器" class="headerlink" title="步骤2 配置主DNS服务器"></a>步骤2 配置主DNS服务器</h1><p><strong>on ns1</strong> </p><h2 id="配置Options文件"><a href="#配置Options文件" class="headerlink" title="配置Options文件"></a>配置Options文件</h2><p>打开named.conf.options并修改</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">sudo vi /etc/bind/named.conf.options</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><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">acl "trusted" &#123;</span><br><span class="line">  10.1.80.220;    # ns1</span><br><span class="line">  10.1.80.221;    # ns2</span><br><span class="line">  10.1.80.0/24;   # trusted DNS clients network</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">options &#123;</span><br><span class="line">        directory "/var/cache/bind";</span><br><span class="line"></span><br><span class="line">        recursion yes;                 # enables recursive queries</span><br><span class="line">        allow-recursion &#123; trusted; &#125;;  # allows recursive queries from "trusted" clients</span><br><span class="line">        allow-query &#123; trusted; &#125;;      # allows queries from "trusted" clients</span><br><span class="line">        listen-on &#123; 10.1.80.220; &#125;;    # ns1 private IP address - listen on private network only</span><br><span class="line">        allow-transfer &#123; none; &#125;;      # disable zone transfers by default</span><br><span class="line"></span><br><span class="line">        forwarders &#123;</span><br><span class="line">          223.5.5.5;</span><br><span class="line">          223.6.6.6;</span><br><span class="line">          114.114.114.114;</span><br><span class="line">        &#125;;</span><br><span class="line"></span><br><span class="line">        dnssec-validation auto;</span><br><span class="line"></span><br><span class="line">        listen-on-v6 &#123; any; &#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>注意<em>forwards</em>配置块，有三个ip地址，其中223.5.5.5,223.6.6.6是阿里云公共DNS，114.114.114.114是电信提供公共的DNS。forwards可以为无法直接连接到外网的机器提供域名解析服务。</p><p>完成之后，保存并关闭named.conf.options文件。上面的配置指定只有您自己的服务器(受信任”trusted”的服务器)能够查询您的DNS服务器的外部域。</p><h2 id="配置named-conf-local"><a href="#配置named-conf-local" class="headerlink" title="配置named.conf.local"></a>配置named.conf.local</h2><p><strong>on ns1</strong> </p><p>打开named.conf.local，用vi来编辑</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">sudo vi /etc/bind/named.conf.local</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><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><br><span class="line">zone "idc3.meeleet.com" &#123;</span><br><span class="line">    type primary;</span><br><span class="line">    file "/etc/bind/zones/db.idc3.meeleet.com"; # zone file path</span><br><span class="line">    allow-transfer &#123; 10.1.80.221; &#125;;            # ns2 private IP address - secondary</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">zone "80.1.10.in-addr.arpa" &#123;</span><br><span class="line">    type primary;</span><br><span class="line">    file "/etc/bind/zones/db.10.1.80"; # 10.1.80.0/24 subnet</span><br><span class="line">    allow-transfer &#123; 10.1.80.221; &#125;;   # ns2 private IP address - secondary</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><h2 id="创建正向zone文件"><a href="#创建正向zone文件" class="headerlink" title="创建正向zone文件"></a>创建正向zone文件</h2><p><strong>on ns1</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">mkdir -p /etc/bind/zones</span><br></pre></td></tr></table></figure><p>复制db.local并修改</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">sudo cp /etc/bind/db.local /etc/bind/zones/db.idc3.meeleet.com</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><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><br><span class="line">; BIND data file for local loopback interface</span><br><span class="line">;</span><br><span class="line"><span class="meta">$</span><span class="bash">TTL    604800</span></span><br><span class="line">@       IN      SOA     localhost. root.localhost. (</span><br><span class="line">                              2         ; Serial</span><br><span class="line">                         604800         ; Refresh</span><br><span class="line">                          86400         ; Retry</span><br><span class="line">                        2419200         ; Expire</span><br><span class="line">                         604800 )       ; Negative Cache TTL</span><br><span class="line">;</span><br><span class="line">@       IN      NS      localhost. ; delete this line</span><br><span class="line">@       IN      A       127.0.0.1  ; delete this line</span><br><span class="line">@       IN      AAAA    ::1        ; delete this line</span><br></pre></td></tr></table></figure><p>将<em>localhost</em>替换为<em>idc3.meeleet.com</em>,删除含<em>delete this line</em>标记的行</p><p>文件最后添加上DNS服务器NS记录</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><br><span class="line">...</span><br><span class="line"></span><br><span class="line">; name servers - NS records</span><br><span class="line">    IN      NS      ns1.idc3.meeleet.com.</span><br><span class="line">    IN      NS      ns2.idc3.meeleet.com.</span><br></pre></td></tr></table></figure><p>给这个域内的主机添加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><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><br><span class="line"></span><br><span class="line">; name servers - A records</span><br><span class="line">ns1.idc3.meeleet.com.          IN      A       10.1.80.220</span><br><span class="line">ns2.idc3.meeleet.com.          IN      A       10.1.80.221</span><br><span class="line"></span><br><span class="line">; 10.1.80.0/24 - A records</span><br><span class="line">s91.idc3.meeleet.com.          IN      A       10.1.80.91</span><br><span class="line">s92.idc3.meeleet.com.          IN      A       10.1.80.92</span><br></pre></td></tr></table></figure><p>每次编辑区域文件时，需要在重新启动命名进程之前增加<strong>Serial</strong>值。在这里，将其增加为3,注意增加<strong>Serial</strong>值非常重要！非常重要！非常重要！最终zone配置文件内容如下<br><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">; BIND data file for local loopback interface</span><br><span class="line">;</span><br><span class="line"><span class="meta">$</span><span class="bash">TTL    604800</span></span><br><span class="line">@       IN      SOA     idc3.meeleet.com. root.idc3.meeleet.com. (</span><br><span class="line">                              3         ; Serial</span><br><span class="line">                         604800         ; Refresh</span><br><span class="line">                          86400         ; Retry</span><br><span class="line">                        2419200         ; Expire</span><br><span class="line">                         604800 )       ; Negative Cache TTL</span><br><span class="line">;</span><br><span class="line"></span><br><span class="line">; name servers - NS records</span><br><span class="line">    IN      NS      ns1.idc3.meeleet.com.</span><br><span class="line">    IN      NS      ns2.idc3.meeleet.com.</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">; name servers - A records</span><br><span class="line">ns1.idc3.meeleet.com.          IN      A       10.1.80.220</span><br><span class="line">ns2.idc3.meeleet.com.          IN      A       10.1.80.221</span><br><span class="line"></span><br><span class="line">; 10.1.80.0/24 - A records</span><br><span class="line">s91.idc3.meeleet.com.          IN      A       10.1.80.91</span><br><span class="line">s92.idc3.meeleet.com.          IN      A       10.1.80.92</span><br></pre></td></tr></table></figure></p><p>保存/etc/bind/zones/db.idc3.meeleet.com</p><h2 id="创建反向zone文件"><a href="#创建反向zone文件" class="headerlink" title="创建反向zone文件"></a>创建反向zone文件</h2><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">sudo cp /etc/bind/db.127 /etc/bind/zones/db.10.1.80</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><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="meta">$</span><span class="bash">TTL    604800</span></span><br><span class="line">@       IN      SOA     localhost. root.localhost. (</span><br><span class="line">                              1         ; Serial</span><br><span class="line">                         604800         ; Refresh</span><br><span class="line">                          86400         ; Retry</span><br><span class="line">                        2419200         ; Expire</span><br><span class="line">                         604800 )       ; Negative Cache TTL</span><br><span class="line">;</span><br><span class="line">@       IN      NS      localhost.      ; delete this line</span><br><span class="line">1.0.0   IN      PTR     localhost.      ; delete this line</span><br></pre></td></tr></table></figure><p>删除含<em>delete this line</em>标记的行</p><p>最终<br><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></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash">TTL    604800</span></span><br><span class="line">@       IN      SOA     ns1.idc3.meeleet.com. root.idc3.meeleet.com. (</span><br><span class="line">                              3         ; Serial</span><br><span class="line">                         604800         ; Refresh</span><br><span class="line">                          86400         ; Retry</span><br><span class="line">                        2419200         ; Expire</span><br><span class="line">                         604800 )       ; Negative Cache TTL</span><br><span class="line">;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">; name servers - NS records</span><br><span class="line">      IN      NS      ns1.idc3.meeleet.com.</span><br><span class="line">      IN      NS      ns2.idc3.meeleet.com.</span><br><span class="line"></span><br><span class="line">; PTR Records</span><br><span class="line">220   IN      PTR     ns1.idc3.meeleet.com.    ; 10.1.80.220</span><br><span class="line">221   IN      PTR     ns2.idc3.meeleet.com.    ; 10.1.80.221</span><br><span class="line">91    IN      PTR     s91.idc3.meeleet.com.    ; 10.1.80.91</span><br><span class="line">92    IN      PTR     s92.idc3.meeleet.com.    ; 10.1.80.92</span><br></pre></td></tr></table></figure></p><h2 id="检查配置文件是否正确"><a href="#检查配置文件是否正确" class="headerlink" title="检查配置文件是否正确"></a>检查配置文件是否正确</h2><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">sudo named-checkzone idc3.meeleet.com /etc/bind/zones/db.idc3.meeleet.com</span><br><span class="line"></span><br><span class="line">zone idc3.meeleet.com/IN: loaded serial 2</span><br><span class="line">OK</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">sudo named-checkzone 80.1.10.in-addr.arpa /etc/bind/zones/db.10.1.80</span><br><span class="line">zone 80.1.10.in-addr.arpa/IN: loaded serial 2</span><br><span class="line">OK</span><br></pre></td></tr></table></figure><p>检查没问题，可以重启bind9</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">sudo systemctl restart bind9</span><br></pre></td></tr></table></figure><p>如果有使用ufw,则需要让ufw允许bind9(如果有启用ufw的话)</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">sudo ufw allow Bind9</span><br></pre></td></tr></table></figure><h1 id="步骤3-配置备DNS服务器"><a href="#步骤3-配置备DNS服务器" class="headerlink" title="步骤3 配置备DNS服务器"></a>步骤3 配置备DNS服务器</h1><p>多数情况下搞一套主备DNS服务器还是很有必要的，这样的话当主备DNS服务器不可用时，备DNS服务器也可以接受DNS查询请求并作出响应。幸运的是，配置一个备DNS服务器比配置主DNS服务器简单多了。</p><p><strong>on ns2</strong></p><p>编辑named.conf.options文件</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">sudo vi /etc/bind/named.conf.options</span><br></pre></td></tr></table></figure><p>在文件的顶部，添加包含所有受信任服务器的私有IP地址的ACL。(也支持添加单独的ip,这里我为了方便，直接用网段来表示，这样就不用一个个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><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">acl "trusted" &#123;</span><br><span class="line">  10.1.80.220;    # ns1</span><br><span class="line">  10.1.80.221;    # ns2</span><br><span class="line">  10.1.80.0/24;   # trusted DNS clients network</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">options &#123;</span><br><span class="line"></span><br><span class="line">        . . .</span><br></pre></td></tr></table></figure><p>directory指令下方，添加如下行</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></pre></td><td class="code"><pre><span class="line">. . .</span><br><span class="line"></span><br><span class="line">     recursion yes;                     # enables recursive queries</span><br><span class="line">     allow-recursion &#123; trusted; &#125;;      # allows recursive queries from "trusted" clients</span><br><span class="line">     allow-query &#123; trusted; &#125;;          # allows queries from "trusted" clients</span><br><span class="line">     listen-on &#123; 10.1.80.221; &#125;;        # ns2 private IP address</span><br><span class="line">     allow-transfer &#123; none; &#125;;          # disable zone transfers by default</span><br><span class="line"></span><br><span class="line">     forwarders &#123;</span><br><span class="line">             223.5.5.5;</span><br><span class="line">             223.6.6.6;</span><br><span class="line">             114.114.114.114;</span><br><span class="line">     &#125;;</span><br><span class="line"></span><br><span class="line"> . . .</span><br></pre></td></tr></table></figure><p>保存并关闭named.conf.options文件。这个文件应该与ns1的named.conf.options文件相同，只是它应该被配置为监听ns2的私有IP地址。</p><p>最终named.conf.options文件内容如下<br><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></pre></td><td class="code"><pre><span class="line">acl "trusted" &#123;</span><br><span class="line">  10.1.80.220;    # ns1</span><br><span class="line">  10.1.80.221;    # ns2</span><br><span class="line">  10.1.80.0/24;   # trusted DNS clients network</span><br><span class="line">&#125;;</span><br><span class="line">options &#123;</span><br><span class="line">        directory "/var/cache/bind";</span><br><span class="line"></span><br><span class="line">        recursion yes;                     # enables recursive queries</span><br><span class="line">        allow-recursion &#123; trusted; &#125;;      # allows recursive queries from "trusted" clients</span><br><span class="line">        allow-query &#123; trusted; &#125;;          # allows queries from "trusted" clients</span><br><span class="line">        listen-on &#123; 10.1.80.221; &#125;;        # ns2 private IP address</span><br><span class="line">        allow-transfer &#123; none; &#125;;          # disable zone transfers by default</span><br><span class="line"></span><br><span class="line">        forwarders &#123;</span><br><span class="line">                223.5.5.5;</span><br><span class="line">                223.6.6.6;</span><br><span class="line">                114.114.114.114;</span><br><span class="line">        &#125;;</span><br><span class="line"></span><br><span class="line">        dnssec-validation auto;</span><br><span class="line"></span><br><span class="line">        listen-on-v6 &#123; any; &#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p><p>现在编辑named.conf.loca文件<br><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">sudo vi /etc/bind/named.conf.local</span><br></pre></td></tr></table></figure></p><p>在主DNS服务器上定义与主DNS服务器对应的辅助区域。注意，该类型是slave，文件不包含路径，并且有一个master指令，该指令应该设置为主DNS服务器的私有IP地址。如果您在主DNS服务器中定义了多个反向区域，请确保将它们全部添加到这里:</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"></span><br><span class="line"></span><br><span class="line">zone "idc3.meeleet.com" &#123;</span><br><span class="line">    type slave;</span><br><span class="line">    file "db.idc3.meeleet.com";</span><br><span class="line">    masters &#123; 10.1.80.220; &#125;;   # ns1 private IP</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">zone "80.1.10.in-addr.arpa" &#123;</span><br><span class="line">    type slave;</span><br><span class="line">    file "db.10.1.80";</span><br><span class="line">    masters &#123; 10.1.80.220; &#125;;   # ns1 private IP</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>注意:考虑到它们的负面含义，DigitalOcean倾向于尽可能避免使用“主人”和“奴隶”等术语。在Bind的最新版本中，可以使用primaries而不是masters，并将备服务器的类型定义为secondary服务器而不是slave服务器。然而，从默认的Ubuntu 20.04存储库中安装的BIND版本(如步骤1中所述)将无法识别这些选项，这意味着除非升级，否则您将不得不使用包含较少的术语。</p><p>保存并关闭named.conf.local文件<br>运行以下命令检查配置文件有效性<br><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">sudo named-checkconf</span><br></pre></td></tr></table></figure></p><p>如果命令执行反回没有任何错误，那么就可以重启bind</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">sudo systemctl restart bind9</span><br></pre></td></tr></table></figure><p>然后通过修改防火墙规则使得允许DNS客户端的连接到此DNS服务器</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">sudo ufw allow Bind9</span><br></pre></td></tr></table></figure><p>到现在为止，DNS主备服务器就搭建好了</p><p>从ns1传输到ns2的区域文件放在 ns2的/var/cache/bind/目录</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">ls /var/cache/bind/</span><br><span class="line">db.10.1.80             db.idc3.meeleet.com    managed-keys.bind      managed-keys.bind.jnl</span><br></pre></td></tr></table></figure><h1 id="步骤4-配置DNS客户端"><a href="#步骤4-配置DNS客户端" class="headerlink" title="步骤4 配置DNS客户端"></a>步骤4 配置DNS客户端</h1><p>在受信任ACL中的所有服务器都可以查询您的DNS服务器之前，必须将每个服务器配置为使用ns1和ns2作为DNS服务器。</p><p>假设您的客户端服务器运行Ubuntu，您需要找到与您的专用网络相关联的设备。可以使用ip address命令查询私有子网。在每台客户机上运行以下命令，将突出显示的子网替换为您自己的子网。</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">ip address show to 10.1.80.0/24</span><br><span class="line"></span><br><span class="line">2: enp0s3: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc fq_codel state UP group default qlen 1000</span><br><span class="line">    inet 10.1.80.91/24 brd 10.1.80.255 scope global enp0s3</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br></pre></td></tr></table></figure><p>本例中私网网卡名为enp0s3。本节中的示例将把enp0s3作为私有网络(10.1.80.0/24网段)网卡，不过您应该根据您的实际情况更改这些示例，以反映您自己的服务器的私有网卡。</p><p>修改/etc/netplan/00-installer-config.yaml给s91,s92的相应网卡设置ns1和ns2 DNS服务器的地址，以及search域</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">vi /etc/netplan/00-installer-config.yaml</span><br></pre></td></tr></table></figure><p>s91<br><figure class="highlight yaml"><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">network:</span></span><br><span class="line"><span class="attr">  ethernets:</span></span><br><span class="line"><span class="attr">    enp0s3:</span></span><br><span class="line"><span class="attr">      addresses:</span></span><br><span class="line"><span class="bullet">      -</span> <span class="number">10.1</span><span class="number">.80</span><span class="number">.91</span><span class="string">/24</span></span><br><span class="line"><span class="attr">      gateway4:</span> <span class="number">10.1</span><span class="number">.80</span><span class="number">.254</span></span><br><span class="line"><span class="attr">      nameservers:</span></span><br><span class="line"><span class="attr">        addresses:</span> <span class="string">[10.1.80.220,10.1.80.221]</span></span><br><span class="line"><span class="attr">        search:</span> <span class="string">[idc3.meeleet.com]</span></span><br><span class="line"><span class="attr">    enp0s8:</span></span><br><span class="line"><span class="attr">      dhcp4:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr">  version:</span> <span class="number">2</span></span><br></pre></td></tr></table></figure></p><p>s92<br><figure class="highlight yaml"><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">network:</span></span><br><span class="line"><span class="attr">  ethernets:</span></span><br><span class="line"><span class="attr">    enp0s3:</span></span><br><span class="line"><span class="attr">      addresses:</span></span><br><span class="line"><span class="bullet">      -</span> <span class="number">10.1</span><span class="number">.80</span><span class="number">.92</span><span class="string">/24</span></span><br><span class="line"><span class="attr">      gateway4:</span> <span class="number">10.1</span><span class="number">.80</span><span class="number">.254</span></span><br><span class="line"><span class="attr">      nameservers:</span></span><br><span class="line"><span class="attr">        addresses:</span></span><br><span class="line"><span class="bullet">          -</span> <span class="number">10.1</span><span class="number">.80</span><span class="number">.220</span></span><br><span class="line"><span class="bullet">          -</span> <span class="number">10.1</span><span class="number">.80</span><span class="number">.221</span></span><br><span class="line"><span class="attr">        search:</span> <span class="string">[idc3.meeleet.com]</span></span><br><span class="line"><span class="attr">    enp0s8:</span></span><br><span class="line"><span class="attr">      dhcp4:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr">  version:</span> <span class="number">2</span></span><br></pre></td></tr></table></figure></p><p>DNS服务器列表network-&gt;ethernets-&gt;enp0s3-&gt;nameservers-&gt;addresses两种配置方式都可以。search的作用就是就去ping s91时，原来当访问的域名(s91)不能被DNS解析时，resolver会将该域名加上search指定的参数，也就是s91.idc3.meeleet.com，重新请求DNS，直到被正确解析或试完search指定的列表为止。</p><p>保存并关闭</p><p>使用netplan try尝试新配置，如果有问netplay会在倒计时后自动回滚配置。</p><p>现在，检查系统的DNS解析器，以确定您的DNS配置是否已应用:<br><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">sudo systemd-resolve --status</span><br></pre></td></tr></table></figure></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><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line">Global</span><br><span class="line">       LLMNR setting: no</span><br><span class="line">MulticastDNS setting: no</span><br><span class="line">  DNSOverTLS setting: no</span><br><span class="line">      DNSSEC setting: no</span><br><span class="line">    DNSSEC supported: no</span><br><span class="line">          DNSSEC NTA: 10.in-addr.arpa</span><br><span class="line">                      16.172.in-addr.arpa</span><br><span class="line">                      168.192.in-addr.arpa</span><br><span class="line">                      17.172.in-addr.arpa</span><br><span class="line">                      18.172.in-addr.arpa</span><br><span class="line">                      19.172.in-addr.arpa</span><br><span class="line">                      20.172.in-addr.arpa</span><br><span class="line">                      21.172.in-addr.arpa</span><br><span class="line">                      22.172.in-addr.arpa</span><br><span class="line">                      23.172.in-addr.arpa</span><br><span class="line">                      24.172.in-addr.arpa</span><br><span class="line">                      25.172.in-addr.arpa</span><br><span class="line">                      26.172.in-addr.arpa</span><br><span class="line">                      27.172.in-addr.arpa</span><br><span class="line">                      28.172.in-addr.arpa</span><br><span class="line">                      29.172.in-addr.arpa</span><br><span class="line">                      30.172.in-addr.arpa</span><br><span class="line">                      31.172.in-addr.arpa</span><br><span class="line">                      corp</span><br><span class="line">                      d.f.ip6.arpa</span><br><span class="line">                      home</span><br><span class="line">                      internal</span><br><span class="line">                      intranet</span><br><span class="line">                      lan</span><br><span class="line">                      local</span><br><span class="line">                      private</span><br><span class="line">                      test</span><br><span class="line"></span><br><span class="line">Link 3 (enp0s8)</span><br><span class="line">      Current Scopes: DNS</span><br><span class="line">DefaultRoute setting: yes</span><br><span class="line">       LLMNR setting: yes</span><br><span class="line">MulticastDNS setting: no</span><br><span class="line">  DNSOverTLS setting: no</span><br><span class="line">      DNSSEC setting: no</span><br><span class="line">    DNSSEC supported: no</span><br><span class="line">  Current DNS Server: 223.5.5.5</span><br><span class="line">         DNS Servers: 223.5.5.5</span><br><span class="line">                      223.6.6.6</span><br><span class="line"></span><br><span class="line">Link 2 (enp0s3)</span><br><span class="line">      Current Scopes: DNS</span><br><span class="line">DefaultRoute setting: yes</span><br><span class="line">       LLMNR setting: yes</span><br><span class="line">MulticastDNS setting: no</span><br><span class="line">  DNSOverTLS setting: no</span><br><span class="line">      DNSSEC setting: no</span><br><span class="line">    DNSSEC supported: no</span><br><span class="line">  Current DNS Server: 223.5.5.5</span><br><span class="line">         DNS Servers: 223.5.5.5</span><br><span class="line">                      223.6.6.6</span><br><span class="line">                      10.1.80.200</span><br><span class="line">                      10.1.80.201</span><br><span class="line">          DNS Domain: idc3.meeleet.com</span><br></pre></td></tr></table></figure><h1 id="步骤5-测试客户端"><a href="#步骤5-测试客户端" class="headerlink" title="步骤5 测试客户端"></a>步骤5 测试客户端</h1><h1 id="步骤6-维护DNS记录"><a href="#步骤6-维护DNS记录" class="headerlink" title="步骤6 维护DNS记录"></a>步骤6 维护DNS记录</h1><p>现在你已拥有了工作在内网的DNS服务器，你需要维护DNS记录以便支持你的服务器环境。</p><h2 id="添加新主机DNS记录"><a href="#添加新主机DNS记录" class="headerlink" title="添加新主机DNS记录"></a>添加新主机DNS记录</h2><p>任何时候你要添加新主机到你的服务器环境(在同一个数据中心)，添加一个新主机的DNS记录，需要以下步骤：</p><h3 id="主域名服务器"><a href="#主域名服务器" class="headerlink" title="主域名服务器"></a>主域名服务器</h3><ul><li><p>正向区域文件：为新主机添加A记录，并增加Serial值</p></li><li><p>反向区域文件：为新主机增加PTR记录，并增加Serial值</p></li><li><p>添加新的主机私网IP地址到受信任的ACL列表(named.conf.options)</p></li></ul><p>测试配置文件：<br><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">sudo named-checkconf</span><br><span class="line">sudo named-checkzone idc3.meeleet.com /etc/bind/zones/db.idc3.meeleet.com</span><br><span class="line">sudo named-checkzone 80.1.10.in-addr.arpa /etc/bind/zones/db.10.1.80</span><br></pre></td></tr></table></figure></p><h3 id="辅域名服务器"><a href="#辅域名服务器" class="headerlink" title="辅域名服务器"></a>辅域名服务器</h3><ul><li>添加新的主机私网IP地址到受信任的ACL列表(named.conf.options)</li></ul><p>检查配置文件语法是否正确<br><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">sudo named-checkconf</span><br></pre></td></tr></table></figure></p><p>然后重载bind:<br><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">sudo systemctl reload bind9</span><br></pre></td></tr></table></figure></p><h2 id="删除主机DNS记录"><a href="#删除主机DNS记录" class="headerlink" title="删除主机DNS记录"></a>删除主机DNS记录</h2><p>如果你要删除某个主机的DNS记录，只需要删除之前添加的该主机的DNS记录信息(就是与之前添加主机DNS记录的步骤相反)</p><h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><p><a href="https://www.digitalocean.com/community/tutorials/how-to-configure-bind-as-a-private-network-dns-server-on-ubuntu-20-04" target="_blank" rel="noopener">How To Configure BIND as a Private Network DNS Server on Ubuntu 20.04</a></p><p><a href="https://lnsyyj.github.io/2019/01/06/%E5%A6%82%E4%BD%95%E5%9C%A8CentOS-7%E4%B8%8A%E5%B0%86BIND%E9%85%8D%E7%BD%AE%E4%B8%BA%E4%B8%93%E7%94%A8%E7%BD%91%E7%BB%9CDNS%E6%9C%8D%E5%8A%A1%E5%99%A8/" target="_blank" rel="noopener">如何在CentOS-7上将BIND配置为专用网络DNS服务器</a></p><p><a href="https://www.cnblogs.com/doherasyang/p/14464999.html?ivk_sa=1024320u" target="_blank" rel="noopener">ISC BIND9 - 最详细、最认真的从零开始的 BIND 9 - DNS服务搭建及其原理讲解</a></p><p><a href="https://wiki.ubuntu.org.cn/Bind9%E5%AE%89%E8%A3%85%E8%AE%BE%E7%BD%AE%E6%8C%87%E5%8D%97#HOWTO_Setup_BIND9_DNS_Server_.EF.BC.88.E5.A6.82.E4.BD.95.E5.AE.89.E8.A3.85.E8.AE.BE.E7.BD.AEBind9_DNS.E6.9C.8D.E5.8A.A1.E5.99.A8.EF.BC.89" target="_blank" rel="noopener">Bind9安装设置指南</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;准备及说明&quot;&gt;&lt;a href=&quot;#准备及说明&quot; class=&quot;headerlink&quot; title=&quot;准备及说明&quot;&gt;&lt;/a&gt;准备及说明&lt;/h1&gt;&lt;p&gt;假设某公司有多个数据中心，数据中心1以内部使用idc1.meeleet.com,数据中心2使用idc2.meelee
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>LVS高可用实战之DR模式(CentOS 7)</title>
    <link href="http://jaychang.cn/2022/10/09/VS%E9%AB%98%E5%8F%AF%E7%94%A8%E5%AE%9E%E6%88%98%E4%B9%8BDR%E6%A8%A1%E5%BC%8F-CentOS-7/"/>
    <id>http://jaychang.cn/2022/10/09/VS高可用实战之DR模式-CentOS-7/</id>
    <published>2022-10-09T08:18:50.000Z</published>
    <updated>2022-10-10T11:59:27.745Z</updated>
    
    <content type="html"><![CDATA[<h1 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h1><p>VirtualBox虚拟机3台，使用的网络有桥接网卡、网络地址转换(NAT)</p><p>桥接网卡网段是10.1.80.0/24，网络地址转换(NAT)是为了能访问internet以便安装软件</p><table><thead><tr><th>节点</th><th>IP</th><th>VIP</th></tr></thead><tbody><tr><td>ds1</td><td>10.1.80.91</td><td>enp0s3</td><td></td></tr><tr><td>ds2</td><td>10.1.80.92</td><td>enp0s3</td><td></td></tr><tr><td>rs1</td><td>10.1.80.93</td><td>lo:0</td><td></td></tr><tr><td>rs2</td><td>10.1.80.95</td><td>lo:0</td><td></td></tr></tbody></table><p>VIP地址为10.1.80.90</p><p>RS的RIP可以使用私网或公网IP， 文中DS与RS用的是同一网段。实际场景，一般情况下RS的RIP与VIP是不同网段的。</p><h1 id="LVS常用名词"><a href="#LVS常用名词" class="headerlink" title="LVS常用名词"></a>LVS常用名词</h1><ul><li>Load Balancer：负载均衡器，运行LVS负责负载均衡的服务器</li><li>DS：Director Server，指的是前端负载均衡器节点，也就是运行LVS的服务器；</li><li>RS：Real Server，后端真实的工作服务器；</li><li>VIP：Virtual Server IP，向外部直接面向用户请求，作为用户请求的目标的IP地址，一般也是DS的外部IP地址；</li><li>DIP：Director Server IP，主要用于和内部主机通讯的IP地址，一般也是DS的内部IP地址；</li><li>RIP：Real Server IP，后端服务器的IP地址；</li><li>CIP：Client IP，访问客户端的IP地址；</li></ul><h1 id="Director-Server"><a href="#Director-Server" class="headerlink" title="Director Server"></a>Director Server</h1><h2 id="ds1"><a href="#ds1" class="headerlink" title="ds1"></a>ds1</h2><p>安装ipvsadm<br><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">sudo yum install -y ipvsadm</span><br></pre></td></tr></table></figure></p><p>安装keepalived<br><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">sudo yum install -y keepalived</span><br></pre></td></tr></table></figure></p><p>备份keepalived.conf配置文件<br><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">sudo cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak</span><br></pre></td></tr></table></figure></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">sudo vi /etc/keepalived/keepalived.conf</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">global_defs &#123;</span><br><span class="line">   router_id LVS_DEVEL</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">vrrp_instance VI_1 &#123;</span><br><span class="line">    state MASTER</span><br><span class="line">    interface enp0s3</span><br><span class="line">    virtual_router_id 51</span><br><span class="line">    priority 101</span><br><span class="line">    advert_int 1</span><br><span class="line">    </span><br><span class="line">    # 如果两节点的上联交换机禁用了组播，则采用 vrrp 单播通告的方式</span><br><span class="line">    # unicast_src_ip 10.1.80.91</span><br><span class="line">    # unicast_peer &#123;</span><br><span class="line">    #    10.1.80.92</span><br><span class="line">    # &#125;</span><br><span class="line">    </span><br><span class="line">    authentication &#123;</span><br><span class="line">        auth_type PASS</span><br><span class="line">        auth_pass 1111</span><br><span class="line">    &#125;</span><br><span class="line">    virtual_ipaddress &#123;</span><br><span class="line">        10.1.80.90</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">virtual_server 10.1.80.90 80 &#123;</span><br><span class="line">    delay_loop 6</span><br><span class="line">    lb_algo wrr</span><br><span class="line">    lb_kind DR</span><br><span class="line">    persistence_timeout 5</span><br><span class="line">    protocol TCP</span><br><span class="line"></span><br><span class="line">    real_server 10.1.80.93 80 &#123;</span><br><span class="line">        weight 100</span><br><span class="line">        TCP_CHECK &#123;</span><br><span class="line">           connect_timeout 3</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    real_server 10.1.80.95 80 &#123;</span><br><span class="line">        weight 100</span><br><span class="line">        TCP_CHECK &#123;</span><br><span class="line">           connect_timeout 3</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>ds1作为MASTER优先级比ds2高，ds1设置priority 101，ds2设置priority 100</p></blockquote><p>重启keepalived<br><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">sudo systemctl restart keepalived</span><br></pre></td></tr></table></figure></p><p>防火墙开放80端口<br><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">sudo firewall-cmd --zone=public --add-port=80/tcp --permanent</span><br></pre></td></tr></table></figure></p><p>防火墙允许vrrp的组播</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">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface enp0s3 --destination 224.0.0.18 --protocol vrrp -j ACCEPT</span><br><span class="line"></span><br><span class="line">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --out-interface enp0s3 --destination 224.0.0.18 --protocol vrrp -j ACCEPT</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">sudo firewall-cmd --reload</span><br></pre></td></tr></table></figure><h2 id="ds2"><a href="#ds2" class="headerlink" title="ds2"></a>ds2</h2><p>安装ipvsadm<br><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">sudo yum install -y ipvsadm</span><br></pre></td></tr></table></figure></p><p>安装keepalived<br><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">sudo yum install -y keepalived</span><br></pre></td></tr></table></figure></p><p>备份keepalived.conf配置文件<br><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">sudo cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak</span><br></pre></td></tr></table></figure></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">sudo vi /etc/keepalived/keepalived.conf</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">global_defs &#123;</span><br><span class="line">   router_id LVS_DEVEL</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">vrrp_instance VI_1 &#123;</span><br><span class="line">    state BACKUP</span><br><span class="line">    interface enp0s3</span><br><span class="line">    virtual_router_id 51</span><br><span class="line">    priority 100</span><br><span class="line">    advert_int 1</span><br><span class="line">    </span><br><span class="line">    # 如果两节点的上联交换机禁用了组播，则采用 vrrp 单播通告的方式</span><br><span class="line">    # unicast_src_ip 10.1.80.92</span><br><span class="line">    # unicast_peer &#123;</span><br><span class="line">    #    10.1.80.91</span><br><span class="line">    # &#125;</span><br><span class="line">    </span><br><span class="line">    authentication &#123;</span><br><span class="line">        auth_type PASS</span><br><span class="line">        auth_pass 1111</span><br><span class="line">    &#125;</span><br><span class="line">    virtual_ipaddress &#123;</span><br><span class="line">        10.1.80.90</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">virtual_server 10.1.80.90 80 &#123;</span><br><span class="line">    delay_loop 6</span><br><span class="line">    lb_algo wrr</span><br><span class="line">    lb_kind DR</span><br><span class="line">    persistence_timeout 5</span><br><span class="line">    protocol TCP</span><br><span class="line"></span><br><span class="line">    real_server 10.1.80.93 80 &#123;</span><br><span class="line">        weight 100</span><br><span class="line">        TCP_CHECK &#123;</span><br><span class="line">           connect_timeout 3</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    real_server 10.1.80.95 80 &#123;</span><br><span class="line">        weight 100</span><br><span class="line">        TCP_CHECK &#123;</span><br><span class="line">           connect_timeout 3</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>重启keepalived<br><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">sudo systemctl restart keepalived</span><br></pre></td></tr></table></figure></p><p>防火墙开放80端口<br><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">sudo firewall-cmd --zone=public --add-port=80/tcp --permanent</span><br></pre></td></tr></table></figure></p><p>防火墙允许vrrp的组播</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">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface enp0s3 --destination 224.0.0.18 --protocol vrrp -j ACCEPT</span><br><span class="line"></span><br><span class="line">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --out-interface enp0s3 --destination 224.0.0.18 --protocol vrrp -j ACCEPT</span><br></pre></td></tr></table></figure><p>防火墙重新加载<br><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">sudo firewall-cmd --reload</span><br></pre></td></tr></table></figure></p><h1 id="Real-Server"><a href="#Real-Server" class="headerlink" title="Real Server"></a>Real Server</h1><h2 id="rs1"><a href="#rs1" class="headerlink" title="rs1"></a>rs1</h2><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">sudo mkdir -p /opt/scripts</span><br></pre></td></tr></table></figure><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">sudo vi /opt/scripts/lvs_rs.sh</span><br></pre></td></tr></table></figure><p>脚本如下<br><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>!/bin/bash </span><br><span class="line">VIP=10.1.80.90</span><br><span class="line">case "$1" in</span><br><span class="line">start)</span><br><span class="line">       ifconfig lo:0 $VIP netmask 255.255.255.255 broadcast $VIP</span><br><span class="line">       /sbin/route add -host $VIP dev lo:0</span><br><span class="line">       echo "1" &gt;/proc/sys/net/ipv4/conf/lo/arp_ignore</span><br><span class="line">       echo "2" &gt;/proc/sys/net/ipv4/conf/lo/arp_announce</span><br><span class="line">       echo "1" &gt;/proc/sys/net/ipv4/conf/all/arp_ignore</span><br><span class="line">       echo "2" &gt;/proc/sys/net/ipv4/conf/all/arp_announce</span><br><span class="line">       sysctl -p &gt;/dev/null 2&gt;&amp;1</span><br><span class="line">       echo "RealServer Start OK"</span><br><span class="line">       ;;</span><br><span class="line">stop)</span><br><span class="line">       ifconfig lo:0 down</span><br><span class="line">       route del $VIP &gt;/dev/null 2&gt;&amp;1</span><br><span class="line">       echo "0" &gt;/proc/sys/net/ipv4/conf/lo/arp_ignore</span><br><span class="line">       echo "0" &gt;/proc/sys/net/ipv4/conf/lo/arp_announce</span><br><span class="line">       echo "0" &gt;/proc/sys/net/ipv4/conf/all/arp_ignore</span><br><span class="line">       echo "0" &gt;/proc/sys/net/ipv4/conf/all/arp_announce</span><br><span class="line">       echo "RealServer Stoped"</span><br><span class="line">       ;;</span><br><span class="line">*)</span><br><span class="line">       echo "Usage: $0 &#123;start|stop&#125;"</span><br><span class="line">       exit 1</span><br><span class="line">esac</span><br><span class="line">exit 0</span><br></pre></td></tr></table></figure></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">sudo chmod +x /opt/scripts/lvs_rs.sh </span><br><span class="line">sudo /opt/scripts/lvs_rs.sh start</span><br></pre></td></tr></table></figure><p>安装tengine<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">sudo mkdir -p /tmp/software</span><br><span class="line">sudo cd /tmp/software</span><br><span class="line">sudo curl -O https://tengine.taobao.org/download/tengine-2.3.3.tar.gz</span><br><span class="line">sudo tar -xzvf tengine-2.3.3.tar.gz</span><br><span class="line">sudo cd tengine-2.3.3</span><br><span class="line">sudo yum install -y gcc make pcre-devel openssl-devel</span><br><span class="line">sudo ./configure --prefix=/usr/local/tengine</span><br></pre></td></tr></table></figure></p><p>修改index.html<br><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">sudo vi /usr/local/tengine/html/index.html</span><br></pre></td></tr></table></figure></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">其余省略...</span><br><span class="line"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>Welcome to tengine! I'm rs1<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">其余省略...</span><br></pre></td></tr></table></figure><p>启动tengine<br><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">sudo /usr/local/tengine/sbin/nginx</span><br></pre></td></tr></table></figure></p><p>防火墙设置开放80端口<br><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 --zone=public --add-port=80/tcp --permanent</span><br><span class="line">firewall-cmd --reload</span><br></pre></td></tr></table></figure></p><h2 id="rs2"><a href="#rs2" class="headerlink" title="rs2"></a>rs2</h2><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">sudo mkdir -p /opt/scripts</span><br></pre></td></tr></table></figure><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">sudo vi /opt/scripts/lvs_rs.sh</span><br></pre></td></tr></table></figure><p>脚本如下<br><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>!/bin/bash </span><br><span class="line">VIP=10.1.80.90</span><br><span class="line">case "$1" in</span><br><span class="line">start)</span><br><span class="line">       ifconfig lo:0 $VIP netmask 255.255.255.255 broadcast $VIP</span><br><span class="line">       /sbin/route add -host $VIP dev lo:0</span><br><span class="line">       echo "1" &gt;/proc/sys/net/ipv4/conf/lo/arp_ignore</span><br><span class="line">       echo "2" &gt;/proc/sys/net/ipv4/conf/lo/arp_announce</span><br><span class="line">       echo "1" &gt;/proc/sys/net/ipv4/conf/all/arp_ignore</span><br><span class="line">       echo "2" &gt;/proc/sys/net/ipv4/conf/all/arp_announce</span><br><span class="line">       sysctl -p &gt;/dev/null 2&gt;&amp;1</span><br><span class="line">       echo "RealServer Start OK"</span><br><span class="line">       ;;</span><br><span class="line">stop)</span><br><span class="line">       ifconfig lo:0 down</span><br><span class="line">       route del $VIP &gt;/dev/null 2&gt;&amp;1</span><br><span class="line">       echo "0" &gt;/proc/sys/net/ipv4/conf/lo/arp_ignore</span><br><span class="line">       echo "0" &gt;/proc/sys/net/ipv4/conf/lo/arp_announce</span><br><span class="line">       echo "0" &gt;/proc/sys/net/ipv4/conf/all/arp_ignore</span><br><span class="line">       echo "0" &gt;/proc/sys/net/ipv4/conf/all/arp_announce</span><br><span class="line">       echo "RealServer Stoped"</span><br><span class="line">       ;;</span><br><span class="line">*)</span><br><span class="line">       echo "Usage: $0 &#123;start|stop&#125;"</span><br><span class="line">       exit 1</span><br><span class="line">esac</span><br><span class="line">exit 0</span><br></pre></td></tr></table></figure></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">sudo chmod +x /opt/scripts/lvs_rs.sh </span><br><span class="line">sudo /opt/scripts/lvs_rs.sh start</span><br></pre></td></tr></table></figure><p>安装tengine<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">sudo mkdir -p /tmp/software</span><br><span class="line">sudo cd /tmp/software</span><br><span class="line">sudo curl -O https://tengine.taobao.org/download/tengine-2.3.3.tar.gz</span><br><span class="line">sudo tar -xzvf tengine-2.3.3.tar.gz</span><br><span class="line">sudo cd tengine-2.3.3</span><br><span class="line">sudo yum install -y gcc make pcre-devel openssl-devel</span><br><span class="line">sudo ./configure --prefix=/usr/local/tengine</span><br></pre></td></tr></table></figure></p><p>修改index.html<br><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">sudo vi /usr/local/tengine/html/index.html</span><br></pre></td></tr></table></figure></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">其余省略...</span><br><span class="line"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>Welcome to tengine! I'm rs2<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">其余省略...</span><br></pre></td></tr></table></figure><p>启动tengine<br><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">sudo /usr/local/tengine/sbin/nginx</span><br></pre></td></tr></table></figure></p><p>防火墙设置开放80端口<br><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 --zone=public --add-port=80/tcp --permanent</span><br><span class="line">firewall-cmd --reload</span><br></pre></td></tr></table></figure></p><h1 id="测试keepalived-vrrp报文"><a href="#测试keepalived-vrrp报文" class="headerlink" title="测试keepalived vrrp报文"></a>测试keepalived vrrp报文</h1><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">sudo tcpdump -vvv -n -i enp0s3 host 224.0.0.18</span><br></pre></td></tr></table></figure><p>在ds1上执行(ds2,rs1,rs2都可以的)<br><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">14:43:04.752665 IP (tos 0xc0, ttl 255, id 130, offset 0, flags [none], proto VRRP (112), length 40)</span><br><span class="line">    10.1.80.91 &gt; 224.0.0.18: vrrp 10.1.80.91 &gt; 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 101, authtype simple, intvl 1s, length 20, addrs: 10.1.80.90 auth "1111^@^@^@^@"</span><br><span class="line">14:43:05.753059 IP (tos 0xc0, ttl 255, id 131, offset 0, flags [none], proto VRRP (112), length 40)</span><br><span class="line">    10.1.80.91 &gt; 224.0.0.18: vrrp 10.1.80.91 &gt; 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 101, authtype simple, intvl 1s, length 20, addrs: 10.1.80.90 auth "1111^@^@^@^@"</span><br></pre></td></tr></table></figure></p><p>可以看到10.1.80.91在发组播消息，10.1.80.91证明我是MASTER，vip(10.1.80.90)在ds1的enp0s3上。<br>然后把ds1的keepalived关了,sudo systemctl stop keepalived</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">14:45:08.488190 IP (tos 0xc0, ttl 255, id 253, offset 0, flags [none], proto VRRP (112), length 40)</span><br><span class="line">    10.1.80.91 &gt; 224.0.0.18: vrrp 10.1.80.91 &gt; 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 0, authtype simple, intvl 1s, length 20, addrs: 10.1.80.90 auth "1111^@^@^@^@"</span><br><span class="line">14:45:09.120876 IP (tos 0xc0, ttl 255, id 8772, offset 0, flags [none], proto VRRP (112), length 40)</span><br><span class="line">    10.1.80.92 &gt; 224.0.0.18: vrrp 10.1.80.92 &gt; 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20, addrs: 10.1.80.90 auth "1111^@^@^@^@"</span><br></pre></td></tr></table></figure><p>发现已经由10.1.80.91改为10.1.80.92发组播消息,vip(10.1.80.90)飘到了ds2的enp0s3上。</p><p>重新启动ds1上的keepalived,再次观察报文</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">14:46:59.177236 IP (tos 0xc0, ttl 255, id 8880, offset 0, flags [none], proto VRRP (112), length 40)</span><br><span class="line">    10.1.80.92 &gt; 224.0.0.18: vrrp 10.1.80.92 &gt; 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20, addrs: 10.1.80.90 auth "1111^@^@^@^@"</span><br><span class="line">14:46:59.177350 IP (tos 0xc0, ttl 255, id 1, offset 0, flags [none], proto VRRP (112), length 40)</span><br><span class="line">    10.1.80.91 &gt; 224.0.0.18: vrrp 10.1.80.91 &gt; 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 101, authtype simple, intvl 1s, length 20, addrs: 10.1.80.90 auth "1111^@^@^@^@"</span><br></pre></td></tr></table></figure><p>发现由10.1.80.92改为了10.1.80.91发组播消息了，vip(10.1.80.90)飘回了ds1的enp0s3上。</p><h1 id="验证"><a href="#验证" class="headerlink" title="验证"></a>验证</h1><ul><li>打开浏览器，访问<a href="http://10.1.80.90" target="_blank" rel="noopener">http://10.1.80.90</a></li></ul><p>页面展示 Welcome to tengine! I’m rs1</p><p>ds1上查看sudo ipvsadm -ln</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></pre></td><td class="code"><pre><span class="line">[jaychang@ds01 ~]# sudo ipvsadm -ln</span><br><span class="line">IP Virtual Server version 1.2.1 (size=4096)</span><br><span class="line">Prot LocalAddress:Port Scheduler Flags</span><br><span class="line"><span class="meta">  -&gt;</span> RemoteAddress:Port           Forward Weight ActiveConn InActConn</span><br><span class="line">TCP  10.1.80.90:80 wrr persistent 50</span><br><span class="line"><span class="meta">  -&gt;</span> 10.1.80.93:80              Route   100    0          0</span><br><span class="line"><span class="meta">  -&gt;</span> 10.1.80.95:80              Route   100    2          0</span><br></pre></td></tr></table></figure><ul><li>停掉rs1的nginx后</li></ul><p>ds1上查看/var/log/keepalived.log(如果未设置过，默认是在/var/log/message)</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></pre></td><td class="code"><pre><span class="line">Oct  8 15:50:14 ds01 Keepalived_healthcheckers[15444]: TCP connection to [10.1.80.93]:80 failed.</span><br><span class="line">Oct  8 15:50:15 ds01 Keepalived_healthcheckers[15444]: TCP connection to [10.1.80.93]:80 failed.</span><br><span class="line">Oct  8 15:50:15 ds01 Keepalived_healthcheckers[15444]: Check on service [10.1.80.93]:80 failed after 1 retry.</span><br><span class="line">Oct  8 15:50:15 ds01 Keepalived_healthcheckers[15444]: Removing service [10.1.80.93]:80 from VS [10.1.80.90]:80</span><br></pre></td></tr></table></figure><p>从日志内容可以看到10.1.80.93已被剔除了</p><p>ds1上查看sudo ipvsadm -ln</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">[jaychang@ds01 ~]$ sudo ipvsadm -ln</span><br><span class="line">IP Virtual Server version 1.2.1 (size=4096)</span><br><span class="line">Prot LocalAddress:Port Scheduler Flags</span><br><span class="line"><span class="meta">  -&gt;</span> RemoteAddress:Port           Forward Weight ActiveConn InActConn</span><br><span class="line">TCP  10.1.80.90:80 wrr persistent 50</span><br><span class="line"><span class="meta">  -&gt;</span> 10.1.80.95:80              Route   100    4          0</span><br></pre></td></tr></table></figure><p>刷新浏览器页面显示Welcome to tengine! I’m rs2</p><ul><li>重新开启rs1的nginx</li></ul><p>观察/var/log/keepalived.log(如果未设置过，默认是在/var/log/message)</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">Oct  8 16:11:41 ds01 Keepalived_healthcheckers[15444]: TCP connection to [10.1.80.93]:80 success.</span><br><span class="line">Oct  8 16:11:41 ds01 Keepalived_healthcheckers[15444]: Adding service [10.1.80.93]:80 to VS [10.1.80.90]:80</span><br></pre></td></tr></table></figure><p>ds1上查看sudo ipvsadm -ln</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">IP Virtual Server version 1.2.1 (size=4096)</span><br><span class="line">Prot LocalAddress:Port Scheduler Flags</span><br><span class="line"><span class="meta">  -&gt;</span> RemoteAddress:Port           Forward Weight ActiveConn InActConn</span><br><span class="line">TCP  10.1.80.90:80 wrr persistent 50</span><br><span class="line"><span class="meta">  -&gt;</span> 10.1.80.93:80              Route   100    0          0</span><br><span class="line"><span class="meta">  -&gt;</span> 10.1.80.95:80              Route   100    2          0</span><br></pre></td></tr></table></figure><p>发现10.1.80.93已经重新被加入到服务列表中了</p><h1 id="Q-amp-A"><a href="#Q-amp-A" class="headerlink" title="Q&amp;A"></a>Q&amp;A</h1><ul><li>ds1,ds2上的LVS规则如何删除？</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">sudo ipvsadm --clear</span><br></pre></td></tr></table></figure><ul><li>如何删掉ds1,ds2上的VIP？</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">sudo ifconfig enp0s3:0 down</span><br></pre></td></tr></table></figure><ul><li>如何查看LVS统计信息？</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">sudo ipvsadm -ln --stats</span><br></pre></td></tr></table></figure><ul><li>如何查看LVS连接条目？</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">sudo ipvsadm -lnc</span><br></pre></td></tr></table></figure><ul><li>ds1,ds2上用tcpdump抓包观察组播消息？</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">sudo tcpdump -vvv -n -i enp0s3 host 224.0.0.18</span><br></pre></td></tr></table></figure><p>或<br><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">sudo tcpdump -vvv -n -i enp0s3 vrrp</span><br></pre></td></tr></table></figure></p><ul><li>指定访问来源主机，指定抓包端口号，网卡名称<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">sudo tcpdump -i enp0s3 tcp port 80 and host 10.1.80.62</span><br></pre></td></tr></table></figure></li></ul><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">sudo tcpdump -vvv -n -i enp0s3 tcp port 80 and host 10.1.80.62</span><br></pre></td></tr></table></figure><ul><li>用iptables如何允许组播?</li></ul><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">sudo iptables -I INPUT -i enp0s3 -d 224.0.0.18 -p vrrp -j ACCEPT</span><br><span class="line">sudo iptables -I OUTPUT -o enp0s3 -d 224.0.0.18 -p vrrp -j ACCEPT</span><br></pre></td></tr></table></figure><ul><li>firewall防火墙如何开放端口，关闭端口？</li></ul><p>开放80端口访问<br><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">sudo firewall-cmd --zone=public --add-port=80/tcp --permanent</span><br></pre></td></tr></table></figure></p><p>关闭80端口访问<br><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">sudo firewall-cmd --zone=public --remove-port=80/tcp --permanent</span><br></pre></td></tr></table></figure></p><p>记得要reload或restart下，防火墙才会生效<br><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">sudo firewall-cmd --reload</span><br></pre></td></tr></table></figure></p><p>或<br><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">sudo systemctl reload firewalld</span><br></pre></td></tr></table></figure></p><p>或<br><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">sudo systemctl restart firewalld</span><br></pre></td></tr></table></figure></p><blockquote><p>推荐使用第一种方式重新加载防火墙</p></blockquote><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">sudo firewall-cmd --list-port</span><br></pre></td></tr></table></figure><ul><li>脑裂的原因有哪些？</li></ul><ol><li>主备的virtual_router_id 不一致</li><li>交换机不允许组播(可以改成单播方式)</li><li>防火墙未允许组播</li></ol><h1 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h1><ul><li>注意要使得rs1,rs2上的配置重启生效的话，可以将/opt/scripts/lvs_rs.sh作为启动脚本（推荐）</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">sudo echo "/opt/scripts/lvs_rs.sh start" &gt;&gt; /etc/rc.d/rc.local</span><br></pre></td></tr></table></figure><p>在centos7中，/etc/rc.d/rc.local文件的权限被降低了<br><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">sudo chmod +x /etc/rc.d/rc.local</span><br></pre></td></tr></table></figure></p><ul><li>或使用以下方法</li></ul><p>要使得rs1,rs2上的lo:0重启后仍生效的话，要创建一个ifcfg-lo:0文件</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">sudo cp /etc/sysconfig/network-scripts/ifcfg-lo /etc/sysconfig/network-scripts/ifcfg-lo:0</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">sudo vi /etc/sysconfig/network-scripts/ifcfg-lo:0</span><br></pre></td></tr></table></figure><p>内容如下<br><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">DEVICE=lo:0</span><br><span class="line">IPADDR=10.1.80.90</span><br><span class="line">NETMASK=255.255.255.255</span><br><span class="line">BROADCAST=10.1.80.90</span><br><span class="line">ONBOOT=yes</span><br></pre></td></tr></table></figure></p><p>重启网络<br><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">sudo service network restart</span><br></pre></td></tr></table></figure></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">sudo vi /etc/sysctl.conf</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></pre></td><td class="code"><pre><span class="line">net.ipv4.conf.all.arp_ignore = 1</span><br><span class="line">net.ipv4.conf.default.arp_ignore = 1</span><br><span class="line">net.ipv4.conf.lo.arp_ignore = 1</span><br><span class="line">net.ipv4.conf.all.arp_announce = 2</span><br><span class="line">net.ipv4.conf.default.arp_announce = 2</span><br><span class="line">net.ipv4.conf.lo.arp_announce = 2</span><br></pre></td></tr></table></figure><p>刷新文件<br><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">sudo sysctl -p</span><br></pre></td></tr></table></figure></p><p>路由设置添加开启自启动<br>echo “route add -host 10.1.80.90 dev lo:0” &gt;&gt; /etc/rc.local</p><h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><p><a href="https://tinychen.com/20200427-lvs-principle-introduction/" target="_blank" rel="noopener">LVS三种模式的工作原理</a></p><p><a href="https://ynotes.cn/blog/article_detail/194" target="_blank" rel="noopener">CentOS7搭建LVS负载均衡器</a></p><p><a href="http://www.linuxvirtualserver.org/docs/ha/keepalived.html" target="_blank" rel="noopener">LVS High Availability - The Keepalived Solution</a></p><p><a href="https://blog.51cto.com/qujunorz/1861541" target="_blank" rel="noopener">keepalived组播故障排查</a></p><p><a href="https://blog.csdn.net/u010943765/article/details/59574764" target="_blank" rel="noopener">centos7 keepalived 主备通信 防火墙vrrp 协议</a></p><p><a href="https://qizhanming.com/blog/2018/05/17/how-to-config-keepalived-on-centos-7" target="_blank" rel="noopener">CentOS 7 配置 Keepalived 实现双机热备</a></p><p><a href="https://blog.csdn.net/tushanpeipei/article/details/112448165" target="_blank" rel="noopener">VRRP技术原理与注意点</a></p><p><a href="http://blog.itpub.net/70000438/viewspace-2782269/" target="_blank" rel="noopener">LVS+Keepalived+Nginx高可用实现</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;环境&quot;&gt;&lt;a href=&quot;#环境&quot; class=&quot;headerlink&quot; title=&quot;环境&quot;&gt;&lt;/a&gt;环境&lt;/h1&gt;&lt;p&gt;VirtualBox虚拟机3台，使用的网络有桥接网卡、网络地址转换(NAT)&lt;/p&gt;
&lt;p&gt;桥接网卡网段是10.1.80.0/24，网络地址
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>CentOS7安装kubernetes单master节点(v1.19.x)</title>
    <link href="http://jaychang.cn/2020/12/26/bernetes%E5%8D%95%E8%8A%82%E7%82%B9%E5%AE%89%E8%A3%85/"/>
    <id>http://jaychang.cn/2020/12/26/bernetes单节点安装/</id>
    <published>2020-12-26T03:01:24.000Z</published>
    <updated>2021-02-25T06:02:15.006Z</updated>
    
    <content type="html"><![CDATA[<h1 id="配置要求"><a href="#配置要求" class="headerlink" title="配置要求"></a>配置要求</h1><p>对于 Kubernetes 初学者，在搭建K8S集群时，推荐在阿里云或腾讯云采购如下配置：（您也可以使用自己的虚拟机、私有云等您最容易获得的 Linux 环境）</p><ul><li>至少2台 2核4G 的服务器</li><li>Cent OS 7.6 / 7.7 / 7.8</li></ul><h2 id="安装后软件版本"><a href="#安装后软件版本" class="headerlink" title="安装后软件版本"></a>安装后软件版本</h2><ul><li><p>Kubernetes v1.19.x</p><ul><li><p>calico 3.13.1</p></li><li><p>nginx-ingress 1.5.5</p></li></ul></li><li>Docker 19.03.14</li></ul><blockquote><p><strong>关于二进制安装</strong></p><p>kubeadm 是 Kubernetes 官方支持的安装方式，“二进制” 不是。本文档采用 kubernetes.io 官方推荐的 kubeadm 工具安装 kubernetes 集群。</p></blockquote><h1 id="检查CentOS-hostname"><a href="#检查CentOS-hostname" class="headerlink" title="检查CentOS / hostname"></a>检查CentOS / hostname</h1><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></pre></td><td class="code"><pre><span class="line"># 在 master 节点和 worker 节点都要执行</span><br><span class="line">cat /etc/redhat-release</span><br><span class="line"></span><br><span class="line"># 此处 hostname 的输出将会是该机器在 Kubernetes 集群中的节点名字</span><br><span class="line"># 不能使用 localhost 作为节点的名字</span><br><span class="line">hostname</span><br><span class="line"></span><br><span class="line"># 请使用 lscpu 命令，核对 CPU 信息</span><br><span class="line"># Architecture: x86_64    本安装文档不支持 arm 架构</span><br><span class="line"># CPU(s):       2         CPU 内核数量不能低于 2</span><br><span class="line">lscpu</span><br></pre></td></tr></table></figure><p><strong>操作系统兼容性</strong></p><table><thead><tr><th>CentOS版本</th><th>本文档是否兼容</th><th>备注</th></tr></thead><tbody><tr><td>7.8</td><td>是</td><td>已验证</td></tr><tr><td>7.7</td><td>是</td><td>已验证</td></tr><tr><td>7.6</td><td>是</td><td>已验证</td></tr><tr><td>7.5</td><td>否</td><td>已证实会出现 kubelet 无法启动的问题</td></tr><tr><td>7.4</td><td>否</td><td>已证实会出现 kubelet 无法启动的问题</td></tr><tr><td>7.3</td><td>否</td><td>已证实会出现 kubelet 无法启动的问题</td></tr><tr><td>7.2</td><td>否</td><td>已证实会出现 kubelet 无法启动的问题</td></tr></tbody></table><blockquote><p>修改 hostname</p><p>如果您需要修改 hostname，可执行如下指令：</p></blockquote><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> 修改 hostname</span><br><span class="line">hostnamectl set-hostname your-new-host-name</span><br><span class="line"><span class="meta">#</span> 查看修改结果</span><br><span class="line">hostnamectl status</span><br><span class="line"><span class="meta">#</span> 设置 hostname 解析</span><br><span class="line">echo "127.0.0.1   $(hostname)" &gt;&gt; /etc/hosts</span><br></pre></td></tr></table></figure><h1 id="检查网络"><a href="#检查网络" class="headerlink" title="检查网络"></a>检查网络</h1><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><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">[root@demo-master-a-1 ~]$ ip route show</span><br><span class="line">default via 172.21.0.1 dev eth0 </span><br><span class="line">169.254.0.0/16 dev eth0 scope link metric 1002 </span><br><span class="line">172.21.0.0/20 dev eth0 proto kernel scope link src 172.21.0.12 </span><br><span class="line"></span><br><span class="line">[root@demo-master-a-1 ~]$ ip address</span><br><span class="line">1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000</span><br><span class="line">    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00</span><br><span class="line">    inet 127.0.0.1/8 scope host lo</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000</span><br><span class="line">    link/ether 00:16:3e:12:a4:1b brd ff:ff:ff:ff:ff:ff</span><br><span class="line">    inet 172.17.216.80/20 brd 172.17.223.255 scope global dynamic eth0</span><br><span class="line">       valid_lft 305741654sec preferred_lft 305741654sec</span><br></pre></td></tr></table></figure><h1 id="安装docker及kubelet"><a href="#安装docker及kubelet" class="headerlink" title="安装docker及kubelet"></a>安装docker及kubelet</h1><p>使用 root 身份在所有节点执行如下代码，以安装软件：</p><ul><li>docker</li><li>nfs-utils</li><li>kubectl / kubeadm / kubelet</li></ul><h2 id="快速安装"><a href="#快速安装" class="headerlink" title="快速安装"></a>快速安装</h2><p><strong>请将脚本最后的 1.19.6 替换成您需要的版本号</strong>， 脚本中间的 v1.19.x 不要替换</p><p>docker hub 镜像请根据自己网络的情况任选一个</p><ul><li>第四行为腾讯云 docker hub 镜像</li><li>第六行为DaoCloud docker hub 镜像</li><li>第八行为华为云 docker hub 镜像</li><li>第十行为阿里云 docker hub 镜像</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> 在 master 节点和 worker 节点都要执行</span><br><span class="line"><span class="meta">#</span> 最后一个参数 1.19.5 用于指定 kubenetes 版本，支持所有 1.19.x 版本的安装</span><br><span class="line"><span class="meta">#</span> 腾讯云 docker hub 镜像</span><br><span class="line"><span class="meta">#</span> export REGISTRY_MIRROR="https://mirror.ccs.tencentyun.com"</span><br><span class="line"><span class="meta">#</span> DaoCloud 镜像</span><br><span class="line"><span class="meta">#</span> export REGISTRY_MIRROR="http://f1361db2.m.daocloud.io"</span><br><span class="line"><span class="meta">#</span> 华为云镜像</span><br><span class="line"><span class="meta">#</span> export REGISTRY_MIRROR="https://05f073ad3c0010ea0f4bc00b7105ec20.mirror.swr.myhuaweicloud.com"</span><br><span class="line"><span class="meta">#</span> 阿里云 docker hub 镜像</span><br><span class="line">export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com</span><br><span class="line">curl -sSL https://kuboard.cn/install-script/v1.19.x/install_kubelet.sh | sh -s 1.19.6</span><br></pre></td></tr></table></figure><h2 id="手动安装"><a href="#手动安装" class="headerlink" title="手动安装"></a>手动安装</h2><blockquote><p>手动执行以下代码，结果与快速安装相同。<strong>请将脚本第79行（已高亮）的 ${1} 替换成您需要的版本号，例如 1.19.6</strong></p></blockquote><p>docker hub 镜像请根据自己网络的情况任选一个</p><ul><li>第四行为腾讯云 docker hub 镜像</li><li>第六行为DaoCloud docker hub 镜像</li><li>第八行为阿里云 docker hub 镜像</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> 在 master 节点和 worker 节点都要执行</span><br><span class="line"><span class="meta">#</span> 最后一个参数 1.19.5 用于指定 kubenetes 版本，支持所有 1.19.x 版本的安装</span><br><span class="line"><span class="meta">#</span> 腾讯云 docker hub 镜像</span><br><span class="line"><span class="meta">#</span> export REGISTRY_MIRROR="https://mirror.ccs.tencentyun.com"</span><br><span class="line"><span class="meta">#</span> DaoCloud 镜像</span><br><span class="line"><span class="meta">#</span> export REGISTRY_MIRROR="http://f1361db2.m.daocloud.io"</span><br><span class="line"><span class="meta">#</span> 阿里云 docker hub 镜像</span><br><span class="line">export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com</span><br></pre></td></tr></table></figure><blockquote><p>可以指定安装docker-ce的版本，用<strong>yum list docker-ce –showduplicates|sort -r</strong> 查看所有版本</p></blockquote><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><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>!/bin/bash</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 在 master 节点和 worker 节点都要执行</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 安装 docker</span><br><span class="line"><span class="meta">#</span> 参考文档如下</span><br><span class="line"><span class="meta">#</span> https://docs.docker.com/install/linux/docker-ce/centos/ </span><br><span class="line"><span class="meta">#</span> https://docs.docker.com/install/linux/linux-postinstall/</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 卸载旧版本</span><br><span class="line">yum remove -y docker \</span><br><span class="line">docker-client \</span><br><span class="line">docker-client-latest \</span><br><span class="line">docker-ce-cli \</span><br><span class="line">docker-common \</span><br><span class="line">docker-latest \</span><br><span class="line">docker-latest-logrotate \</span><br><span class="line">docker-logrotate \</span><br><span class="line">docker-selinux \</span><br><span class="line">docker-engine-selinux \</span><br><span class="line">docker-engine</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 设置 yum repository</span><br><span class="line">yum install -y yum-utils \</span><br><span class="line">device-mapper-persistent-data \</span><br><span class="line">lvm2</span><br><span class="line">yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 安装并启动 docker</span><br><span class="line">yum install -y docker-ce-19.03.14 docker-ce-cli-19.03.14</span><br><span class="line"></span><br><span class="line">mkdir /etc/docker || true</span><br><span class="line"></span><br><span class="line">cat &gt; /etc/docker/daemon.json &lt;&lt;EOF</span><br><span class="line">&#123;</span><br><span class="line">  "registry-mirrors": ["$&#123;REGISTRY_MIRROR&#125;"],</span><br><span class="line">  "exec-opts": ["native.cgroupdriver=systemd"],</span><br><span class="line">  "log-driver": "json-file",</span><br><span class="line">  "log-opts": &#123;</span><br><span class="line">    "max-size": "100m"</span><br><span class="line">  &#125;,</span><br><span class="line">  "storage-driver": "overlay2",</span><br><span class="line">  "storage-opts": [</span><br><span class="line">    "overlay2.override_kernel_check=true"</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">mkdir -p /etc/systemd/system/docker.service.d</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> Restart Docker</span><br><span class="line">systemctl daemon-reload</span><br><span class="line">systemctl enable docker</span><br><span class="line">systemctl restart docker</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 安装 nfs-utils</span><br><span class="line"><span class="meta">#</span> 必须先安装 nfs-utils 才能挂载 nfs 网络存储</span><br><span class="line">yum install -y nfs-utils</span><br><span class="line">yum install -y wget</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 关闭 防火墙</span><br><span class="line">systemctl stop firewalld</span><br><span class="line">systemctl disable firewalld</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 关闭 SeLinux</span><br><span class="line">setenforce 0</span><br><span class="line">sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 关闭 swap</span><br><span class="line">swapoff -a</span><br><span class="line">yes | cp /etc/fstab /etc/fstab_bak</span><br><span class="line">cat /etc/fstab_bak |grep -v swap &gt; /etc/fstab</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 修改 /etc/sysctl.conf</span><br><span class="line"><span class="meta">#</span> 如果有配置，则修改</span><br><span class="line">sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g"  /etc/sysctl.conf</span><br><span class="line">sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g"  /etc/sysctl.conf</span><br><span class="line">sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g"  /etc/sysctl.conf</span><br><span class="line">sed -i "s#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g"  /etc/sysctl.conf</span><br><span class="line">sed -i "s#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g"  /etc/sysctl.conf</span><br><span class="line">sed -i "s#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g"  /etc/sysctl.conf</span><br><span class="line">sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=1#g"  /etc/sysctl.conf</span><br><span class="line"><span class="meta">#</span> 可能没有，追加</span><br><span class="line">echo "net.ipv4.ip_forward = 1" &gt;&gt; /etc/sysctl.conf</span><br><span class="line">echo "net.bridge.bridge-nf-call-ip6tables = 1" &gt;&gt; /etc/sysctl.conf</span><br><span class="line">echo "net.bridge.bridge-nf-call-iptables = 1" &gt;&gt; /etc/sysctl.conf</span><br><span class="line">echo "net.ipv6.conf.all.disable_ipv6 = 1" &gt;&gt; /etc/sysctl.conf</span><br><span class="line">echo "net.ipv6.conf.default.disable_ipv6 = 1" &gt;&gt; /etc/sysctl.conf</span><br><span class="line">echo "net.ipv6.conf.lo.disable_ipv6 = 1" &gt;&gt; /etc/sysctl.conf</span><br><span class="line">echo "net.ipv6.conf.all.forwarding = 1"  &gt;&gt; /etc/sysctl.conf</span><br><span class="line"><span class="meta">#</span> 执行命令以应用</span><br><span class="line">sysctl -p</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 配置K8S的yum源</span><br><span class="line">cat &lt;&lt;EOF &gt; /etc/yum.repos.d/kubernetes.repo</span><br><span class="line">[kubernetes]</span><br><span class="line">name=Kubernetes</span><br><span class="line">baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64</span><br><span class="line">enabled=1</span><br><span class="line">gpgcheck=0</span><br><span class="line">repo_gpgcheck=0</span><br><span class="line">gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg</span><br><span class="line">       http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 卸载旧版本</span><br><span class="line">yum remove -y kubelet kubeadm kubectl</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 安装kubelet、kubeadm、kubectl</span><br><span class="line"><span class="meta">#</span> 将 $&#123;1&#125; 替换为 kubernetes 版本号，例如 1.19.6</span><br><span class="line">yum install -y kubelet-$&#123;1&#125; kubeadm-$&#123;1&#125; kubectl-$&#123;1&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 重启 docker，并启动 kubelet</span><br><span class="line">systemctl daemon-reload</span><br><span class="line">systemctl restart docker</span><br><span class="line">systemctl enable kubelet &amp;&amp; systemctl start kubelet</span><br><span class="line"></span><br><span class="line">docker version</span><br></pre></td></tr></table></figure><blockquote><p>WARNING</p><p>如果此时执行 systemctl status kubelet 命令，将得到 kubelet 启动失败的错误提示，请忽略此错误，因为必须完成后续步骤中 kubeadm init 的操作，kubelet 才能正常启动</p></blockquote><h1 id="初始化master节点"><a href="#初始化master节点" class="headerlink" title="初始化master节点"></a>初始化master节点</h1><blockquote><p>关于初始化时用到的环境变量</p></blockquote><ul><li>APISERVER_NAME 不能是 master 的 hostname</li><li>APISERVER_NAME 必须全为小写字母、数字、小数点，不能包含减号</li><li>POD_SUBNET 所使用的网段不能与 master节点/worker节点 所在的网段重叠。该字段的取值为一个 CIDR 值，如果您对 CIDR 这个概念还不熟悉，请仍然执行 export POD_SUBNET=10.100.0.1/16 命令，不做修改</li></ul><h2 id="快速初始化"><a href="#快速初始化" class="headerlink" title="快速初始化"></a>快速初始化</h2><p><strong>请将脚本最后的 1.19.6 替换成您需要的版本号</strong>， 脚本中间的 v1.19.x 不要替换</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"><span class="meta">#</span> 只在 master 节点执行</span><br><span class="line"><span class="meta">#</span> 替换 x.x.x.x 为 master 节点实际 IP（请使用内网 IP）</span><br><span class="line"><span class="meta">#</span> export 命令只在当前 shell 会话中有效，开启新的 shell 窗口后，如果要继续安装过程，请重新执行此处的 export 命令</span><br><span class="line">export MASTER_IP=x.x.x.x</span><br><span class="line"><span class="meta">#</span> 替换 apiserver.demo 为 您想要的 dnsName</span><br><span class="line">export APISERVER_NAME=apiserver.demo</span><br><span class="line"><span class="meta">#</span> Kubernetes 容器组所在的网段，该网段安装完成后，由 kubernetes 创建，事先并不存在于您的物理网络中</span><br><span class="line">export POD_SUBNET=10.100.0.1/16</span><br><span class="line">echo "$&#123;MASTER_IP&#125;    $&#123;APISERVER_NAME&#125;" &gt;&gt; /etc/hosts</span><br><span class="line">curl -sSL https://kuboard.cn/install-script/v1.19.x/init_master.sh | sh -s 1.19.6</span><br></pre></td></tr></table></figure><h2 id="手动初始化"><a href="#手动初始化" class="headerlink" title="手动初始化"></a>手动初始化</h2><blockquote><p>手动执行以下代码，结果与快速初始化相同。<strong>请将脚本第21行（已高亮）的 ${1} 替换成您需要的版本号，例如 1.19.6</strong></p></blockquote><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"><span class="meta">#</span> 只在 master 节点执行</span><br><span class="line"><span class="meta">#</span> 替换 x.x.x.x 为 master 节点的内网IP</span><br><span class="line"><span class="meta">#</span> export 命令只在当前 shell 会话中有效，开启新的 shell 窗口后，如果要继续安装过程，请重新执行此处的 export 命令</span><br><span class="line">export MASTER_IP=x.x.x.x</span><br><span class="line"><span class="meta">#</span> 替换 apiserver.demo 为 您想要的 dnsName</span><br><span class="line">export APISERVER_NAME=apiserver.demo</span><br><span class="line"><span class="meta">#</span> Kubernetes 容器组所在的网段，该网段安装完成后，由 kubernetes 创建，事先并不存在于您的物理网络中</span><br><span class="line">export POD_SUBNET=10.100.0.1/16</span><br><span class="line">echo "$&#123;MASTER_IP&#125;    $&#123;APISERVER_NAME&#125;" &gt;&gt; /etc/hosts</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><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>!/bin/bash</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 只在 master 节点执行</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 脚本出错时终止执行</span><br><span class="line">set -e</span><br><span class="line"></span><br><span class="line">if [ $&#123;#POD_SUBNET&#125; -eq 0 ] || [ $&#123;#APISERVER_NAME&#125; -eq 0 ]; then</span><br><span class="line">  echo -e "\033[31;1m请确保您已经设置了环境变量 POD_SUBNET 和 APISERVER_NAME \033[0m"</span><br><span class="line">  echo 当前POD_SUBNET=$POD_SUBNET</span><br><span class="line">  echo 当前APISERVER_NAME=$APISERVER_NAME</span><br><span class="line">  exit 1</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 查看完整配置选项 https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2</span><br><span class="line">rm -f ./kubeadm-config.yaml</span><br><span class="line">cat &lt;&lt;EOF &gt; ./kubeadm-config.yaml</span><br><span class="line">apiVersion: kubeadm.k8s.io/v1beta2</span><br><span class="line">kind: ClusterConfiguration</span><br><span class="line">kubernetesVersion: v$&#123;1&#125;</span><br><span class="line">imageRepository: registry.aliyuncs.com/k8sxio</span><br><span class="line">controlPlaneEndpoint: "$&#123;APISERVER_NAME&#125;:6443"</span><br><span class="line">networking:</span><br><span class="line">  serviceSubnet: "10.96.0.0/16"</span><br><span class="line">  podSubnet: "$&#123;POD_SUBNET&#125;"</span><br><span class="line">  dnsDomain: "cluster.local"</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> kubeadm init</span><br><span class="line"><span class="meta">#</span> 根据您服务器网速的情况，您需要等候 3 - 10 分钟</span><br><span class="line">kubeadm config images pull --config=kubeadm-config.yaml</span><br><span class="line">kubeadm init --config=kubeadm-config.yaml --upload-certs</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 配置 kubectl</span><br><span class="line">rm -rf /root/.kube/</span><br><span class="line">mkdir /root/.kube/</span><br><span class="line">cp -i /etc/kubernetes/admin.conf /root/.kube/config</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 安装 calico 网络插件</span><br><span class="line"><span class="meta">#</span> 参考文档 https://docs.projectcalico.org/v3.13/getting-started/kubernetes/self-managed-onprem/onpremises</span><br><span class="line">echo "安装calico-3.13.1"</span><br><span class="line">rm -f calico-3.13.1.yaml</span><br><span class="line">wget https://kuboard.cn/install-script/calico/calico-3.13.1.yaml</span><br><span class="line">kubectl apply -f calico-3.13.1.yaml</span><br></pre></td></tr></table></figure><blockquote><p>感谢 <a href="https://github.com/zhangguanzhang/google_containers" target="_blank" rel="noopener">https://github.com/zhangguanzhang/google_containers</a> (opens new window)提供最新的 google_containers 国内镜像</p></blockquote><h2 id="初始化如果出错请看"><a href="#初始化如果出错请看" class="headerlink" title="初始化如果出错请看"></a>初始化如果出错请看</h2><ul><li><p>请确保您的环境符合 <a href="https://kuboard.cn/install/install-k8s.html#安装docker及kubelet" target="_blank" rel="noopener">安装docker及kubelet</a> 中所有勾选框的要求</p></li><li><p>请确保您使用 root 用户执行初始化命令</p></li><li><p>不能下载 kubernetes 的 docker 镜像</p><ul><li><p>安装文档中，默认使用阿里云的 docker 镜像仓库，然而，有时候，该镜像会罢工</p></li><li><p>如碰到不能下载 docker 镜像的情况，请尝试手工初始化，并修改手工初始化脚本里的第22行（文档中已高亮）为：</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">imageRepository: gcr.azk8s.cn/google-containers</span><br></pre></td></tr></table></figure></li></ul></li><li><p>检查环境变量，执行如下命令</p></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">echo MASTER_IP=$&#123;MASTER_IP&#125; &amp;&amp; echo APISERVER_NAME=$&#123;APISERVER_NAME&#125; &amp;&amp; echo POD_SUBNET=$&#123;POD_SUBNET&#125;</span><br></pre></td></tr></table></figure><ul><li>请验证如下几点：<ul><li>环境变量 <strong><em>MASTER_IP</em></strong> 的值应该为 master 节点的 <strong>内网IP</strong>，如果不是，请重新 export</li><li><strong>APISERVER_NAME</strong> 不能是 master 的 hostname</li><li><strong>APISERVER_NAME</strong> 必须全为小写字母、数字、小数点，不能包含减号</li><li><strong>POD_SUBNET</strong> 所使用的网段不能与 <strong><em>master节点/worker节点</em></strong> 所在的网段重叠。该字段的取值为一个 <a href="https://kuboard.cn/glossary/cidr.html" target="_blank" rel="noopener">CIDR</a> 值，如果您对 CIDR 这个概念还不熟悉，请仍然执行 export POD_SUBNET=10.100.0.1/16 命令，不做修改</li></ul></li><li>重新初始化 master 节点前，请先执行 <code>kubeadm reset -f</code> 操作</li></ul><ul><li><p>ImagePullBackoff / Pending</p></li><li><p>如果 kubectl get pod -n kube-system -o wide 的输出结果中出现 ImagePullBackoff 或者长时间处于 Pending 的情况，请参考 查看镜像抓取进度</p></li><li><p>ContainerCreating</p></li><li><p>如果 kubectl get pod -n kube-system -o wide 的输出结果中某个 Pod 长期处于 ContainerCreating、PodInitializing 或 Init:0/3 的状态，可以尝试：</p><ul><li>查看该 Pod 的状态，例如：</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">kubectl describe pod kube-flannel-ds-amd64-8l25c -n kube-system</span><br></pre></td></tr></table></figure><p>如果输出结果中，最后一行显示的是 Pulling image，请耐心等待，或者参考 查看镜像抓取进度</p></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">Normal  Pulling    44s   kubelet, k8s-worker-02  Pulling image "quay.io/coreos/flannel:v0.12.0-amd64"</span><br></pre></td></tr></table></figure><ul><li>将该 Pod 删除，系统会自动重建一个新的 Pod，例如：</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">kubectl delete pod kube-flannel-ds-amd64-8l25c -n kube-system</span><br></pre></td></tr></table></figure><h2 id="检查master初始化结果"><a href="#检查master初始化结果" class="headerlink" title="检查master初始化结果"></a>检查master初始化结果</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> 只在 master 节点执行</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 执行如下命令，等待 3-10 分钟，直到所有的容器组处于 Running 状态</span><br><span class="line">watch kubectl get pod -n kube-system -o wide</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 查看 master 节点初始化结果</span><br><span class="line">kubectl get nodes -o wide</span><br></pre></td></tr></table></figure><blockquote><p>如果出错请看</p></blockquote><ul><li><p>ImagePullBackoff / Pending</p><ul><li>如果 kubectl get pod -n kube-system -o wide的输出结果中出现 ImagePullBackoff 或者长时间处于 Pending 的情况，请参考 <a href="https://kuboard.cn/learning/faq/image-pull-backoff.html" target="_blank" rel="noopener">查看镜像抓取进度</a></li></ul></li><li><p>ContainerCreating</p><ul><li><p>如果kubectl get pod -n kube-system -o wide的输出结果中某个 Pod 长期处于 ContainerCreating、PodInitializing 或 Init:0/3 的状态，可以尝试：</p><ul><li><p>查看该 Pod 的状态，例如：</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">kubectl describe pod kube-flannel-ds-amd64-8l25c -n kube-system</span><br></pre></td></tr></table></figure><p>如果输出结果中，最后一行显示的是 Pulling image，请耐心等待，或者参考查看镜像抓取进度</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">      Normal  Pulling    44s   kubelet, k8s-worker-02  Pulling image <span class="string">"quay.io/coreos/flannel:v0.12.0-amd64"</span></span><br></pre></td></tr></table></figure></li><li><p>将该 Pod 删除，系统会自动重建一个新的 Pod，例如：</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">kubectl delete pod kube-flannel-ds-amd64-8l25c -n kube-system</span><br></pre></td></tr></table></figure></li></ul></li></ul></li></ul><h1 id="初始化worker节点"><a href="#初始化worker节点" class="headerlink" title="初始化worker节点"></a>初始化worker节点</h1><h2 id="获得join参数"><a href="#获得join参数" class="headerlink" title="获得join参数"></a>获得join参数</h2><p>在master节点上执行</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><span class="bash"> 只在 master 节点执行</span></span><br><span class="line">kubeadm token create --print-join-command</span><br></pre></td></tr></table></figure><p>可获取kubeadm join 命令及参数，如下所示</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><span class="bash"> kubeadm token create 命令的输出</span></span><br><span class="line">kubeadm join apiserver.demo:6443 --token mpfjma.4vjjg8flqihor4vt     --discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303</span><br></pre></td></tr></table></figure><blockquote><p>有效时间</p></blockquote><p>该 token 的有效时间为 2 个小时，2小时内，您可以使用此 token 初始化任意数量的 worker 节点。</p><h2 id="worker节点执行初始化"><a href="#worker节点执行初始化" class="headerlink" title="worker节点执行初始化"></a>worker节点执行初始化</h2><p>针对所有的 worker 节点执行</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"><span class="meta">#</span><span class="bash"> 只在 worker 节点执行</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> 替换 x.x.x.x 为 master 节点的内网 IP</span></span><br><span class="line">export MASTER_IP=x.x.x.x</span><br><span class="line"><span class="meta">#</span><span class="bash"> 替换 apiserver.demo 为初始化 master 节点时所使用的 APISERVER_NAME</span></span><br><span class="line">export APISERVER_NAME=apiserver.demo</span><br><span class="line">echo "$&#123;MASTER_IP&#125;    $&#123;APISERVER_NAME&#125;" &gt;&gt; /etc/hosts</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 替换为 master 节点上 kubeadm token create 命令的输出</span></span><br><span class="line">kubeadm join apiserver.demo:6443 --token mpfjma.4vjjg8flqihor4vt     --discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303</span><br></pre></td></tr></table></figure><h2 id="检查初始化结果"><a href="#检查初始化结果" class="headerlink" title="检查初始化结果"></a>检查初始化结果</h2><p>在master节点上执行<br><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><span class="bash"> 只在 master 节点执行</span></span><br><span class="line">kubectl get nodes -o wide</span><br></pre></td></tr></table></figure></p><p>输出结果如下所示：<br><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@demo-master-a-1 ~]# kubectl get nodes</span><br><span class="line">NAME     STATUS   ROLES    AGE     VERSION</span><br><span class="line">demo-master-a-1   Ready    master   5m3s    v1.19.x</span><br><span class="line">demo-worker-a-1   Ready    &lt;none&gt;   2m26s   v1.19.x</span><br><span class="line">demo-worker-a-2   Ready    &lt;none&gt;   3m56s   v1.19.x</span><br></pre></td></tr></table></figure></p><h2 id="常见错误原因"><a href="#常见错误原因" class="headerlink" title="常见错误原因"></a>常见错误原因</h2><p>经常在群里提问为什么 join 不成功的情况大致有这几种：</p><h3 id="worker-节点不能访问-apiserver"><a href="#worker-节点不能访问-apiserver" class="headerlink" title="worker 节点不能访问 apiserver"></a><strong>worker 节点不能访问 apiserver</strong></h3><p>在worker节点执行以下语句可验证worker节点是否能访问 apiserver</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 -ik https://apiserver.demo:6443</span><br></pre></td></tr></table></figure><p>如果不能，请在 master 节点上验证</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -ik https://localhost:6443</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><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">HTTP/1.1 403 Forbidden</span><br><span class="line">Cache-Control: no-cache, private</span><br><span class="line">Content-Type: application/json</span><br><span class="line">X-Content-Type-Options: nosniff</span><br><span class="line">Date: Fri, 15 Nov 2019 04:34:40 GMT</span><br><span class="line">Content-Length: 233</span><br><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">  "kind": "Status",</span><br><span class="line">  "apiVersion": "v1",</span><br><span class="line">  "metadata": &#123;</span><br><span class="line">...</span><br></pre></td></tr></table></figure><blockquote><p> 可能原因</p><ul><li>如果 master 节点能够访问 apiserver、而 worker 节点不能，则请检查自己的网络设置<ul><li>/etc/hosts 是否正确设置？</li><li>是否有安全组或防火墙的限制？</li></ul></li></ul></blockquote><h3 id="worker-节点默认网卡"><a href="#worker-节点默认网卡" class="headerlink" title="worker 节点默认网卡"></a>worker 节点默认网卡</h3><p>   Kubelet使用的 IP 地址与 master 节点可互通（无需 NAT 映射），且没有防火墙、安全组隔离</p><p>如果你使用 vmware 或 virtualbox 创建虚拟机用于 K8S 学习，可以尝试 NAT 模式的网络，而不是桥接模式的网络</p><h2 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h2><h3 id="移除worker节点并重试"><a href="#移除worker节点并重试" class="headerlink" title="移除worker节点并重试"></a>移除worker节点并重试</h3><blockquote><p>WARNING</p><p>正常情况下，您无需移除 worker 节点，如果添加到集群出错，您可以移除 worker 节点，再重新尝试添加  </p></blockquote><p>在准备移除的 worker 节点上执行</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><span class="bash"> 只在 worker 节点执行</span></span><br><span class="line">kubeadm reset -f</span><br></pre></td></tr></table></figure><p>在 master 节点 demo-master-a-1 上执行</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><span class="bash"> 只在 master 节点执行</span></span><br><span class="line">kubectl get nodes -o wide</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></pre></td><td class="code"><pre><span class="line"># 只在 master 节点执行</span><br><span class="line">kubectl delete node demo-worker-x-x</span><br></pre></td></tr></table></figure><blockquote><p>TIP</p><ul><li>将 demo-worker-x-x 替换为要移除的 worker 节点的名字</li><li>worker 节点的名字可以通过在节点 demo-master-a-1 上执行 kubectl get nodes 命令获得</li></ul></blockquote><h1 id="安装Ingress-Controller"><a href="#安装Ingress-Controller" class="headerlink" title="安装Ingress Controller"></a>安装Ingress Controller</h1><h2 id="快速初始化-1"><a href="#快速初始化-1" class="headerlink" title="快速初始化"></a>快速初始化</h2><p><strong>在master节点上执行</strong><br><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><span class="bash"> 只在 master 节点执行</span></span><br><span class="line">kubectl apply -f https://kuboard.cn/install-script/v1.19.x/nginx-ingress.yaml</span><br></pre></td></tr></table></figure></p><p><strong>nginx-ingress.yaml内容</strong><br><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><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br></pre></td><td class="code"><pre><span class="line"># 如果打算用于生产环境，请参考 https://github.com/nginxinc/kubernetes-ingress/blob/v1.5.5/docs/installation.md 并根据您自己的情况做进一步定制</span><br><span class="line"></span><br><span class="line">apiVersion: v1</span><br><span class="line">kind: Namespace</span><br><span class="line">metadata:</span><br><span class="line">  name: nginx-ingress</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">apiVersion: v1</span><br><span class="line">kind: ServiceAccount</span><br><span class="line">metadata:</span><br><span class="line">  name: nginx-ingress </span><br><span class="line">  namespace: nginx-ingress</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">apiVersion: v1</span><br><span class="line">kind: Secret</span><br><span class="line">metadata:</span><br><span class="line">  name: default-server-secret</span><br><span class="line">  namespace: nginx-ingress</span><br><span class="line">type: Opaque</span><br><span class="line">data:</span><br><span class="line">  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN2akNDQWFZQ0NRREFPRjl0THNhWFhEQU5CZ2txaGtpRzl3MEJBUXNGQURBaE1SOHdIUVlEVlFRRERCWk8KUjBsT1dFbHVaM0psYzNORGIyNTBjbTlzYkdWeU1CNFhEVEU0TURreE1qRTRNRE16TlZvWERUSXpNRGt4TVRFNApNRE16TlZvd0lURWZNQjBHQTFVRUF3d1dUa2RKVGxoSmJtZHlaWE56UTI5dWRISnZiR3hsY2pDQ0FTSXdEUVlKCktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUwvN2hIUEtFWGRMdjNyaUM3QlBrMTNpWkt5eTlyQ08KR2xZUXYyK2EzUDF0azIrS3YwVGF5aGRCbDRrcnNUcTZzZm8vWUk1Y2Vhbkw4WGM3U1pyQkVRYm9EN2REbWs1Qgo4eDZLS2xHWU5IWlg0Rm5UZ0VPaStlM2ptTFFxRlBSY1kzVnNPazFFeUZBL0JnWlJVbkNHZUtGeERSN0tQdGhyCmtqSXVuektURXUyaDU4Tlp0S21ScUJHdDEwcTNRYzhZT3ExM2FnbmovUWRjc0ZYYTJnMjB1K1lYZDdoZ3krZksKWk4vVUkxQUQ0YzZyM1lma1ZWUmVHd1lxQVp1WXN2V0RKbW1GNWRwdEMzN011cDBPRUxVTExSakZJOTZXNXIwSAo1TmdPc25NWFJNV1hYVlpiNWRxT3R0SmRtS3FhZ25TZ1JQQVpQN2MwQjFQU2FqYzZjNGZRVXpNQ0F3RUFBVEFOCkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWpLb2tRdGRPcEsrTzhibWVPc3lySmdJSXJycVFVY2ZOUitjb0hZVUoKdGhrYnhITFMzR3VBTWI5dm15VExPY2xxeC9aYzJPblEwMEJCLzlTb0swcitFZ1U2UlVrRWtWcitTTFA3NTdUWgozZWI4dmdPdEduMS9ienM3bzNBaS9kclkrcUI5Q2k1S3lPc3FHTG1US2xFaUtOYkcyR1ZyTWxjS0ZYQU80YTY3Cklnc1hzYktNbTQwV1U3cG9mcGltU1ZmaXFSdkV5YmN3N0NYODF6cFErUyt1eHRYK2VBZ3V0NHh3VlI5d2IyVXYKelhuZk9HbWhWNThDd1dIQnNKa0kxNXhaa2VUWXdSN0diaEFMSkZUUkk3dkhvQXprTWIzbjAxQjQyWjNrN3RXNQpJUDFmTlpIOFUvOWxiUHNoT21FRFZkdjF5ZytVRVJxbStGSis2R0oxeFJGcGZnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=</span><br><span class="line">  tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdi91RWM4b1JkMHUvZXVJTHNFK1RYZUprckxMMnNJNGFWaEMvYjVyYy9XMlRiNHEvClJOcktGMEdYaVN1eE9ycXgrajlnamx4NXFjdnhkenRKbXNFUkJ1Z1B0ME9hVGtIekhvb3FVWmcwZGxmZ1dkT0EKUTZMNTdlT1l0Q29VOUZ4amRXdzZUVVRJVUQ4R0JsRlNjSVo0b1hFTkhzbysyR3VTTWk2Zk1wTVM3YUhudzFtMApxWkdvRWEzWFNyZEJ6eGc2clhkcUNlUDlCMXl3VmRyYURiUzc1aGQzdUdETDU4cGszOVFqVUFQaHpxdmRoK1JWClZGNGJCaW9CbTVpeTlZTW1hWVhsMm0wTGZzeTZuUTRRdFFzdEdNVWozcGJtdlFmazJBNnljeGRFeFpkZFZsdmwKMm82MjBsMllxcHFDZEtCRThCay90elFIVTlKcU56cHpoOUJUTXdJREFRQUJBb0lCQVFDZklHbXowOHhRVmorNwpLZnZJUXQwQ0YzR2MxNld6eDhVNml4MHg4Mm15d1kxUUNlL3BzWE9LZlRxT1h1SENyUlp5TnUvZ2IvUUQ4bUFOCmxOMjRZTWl0TWRJODg5TEZoTkp3QU5OODJDeTczckM5bzVvUDlkazAvYzRIbjAzSkVYNzZ5QjgzQm9rR1FvYksKMjhMNk0rdHUzUmFqNjd6Vmc2d2szaEhrU0pXSzBwV1YrSjdrUkRWYmhDYUZhNk5nMUZNRWxhTlozVDhhUUtyQgpDUDNDeEFTdjYxWTk5TEI4KzNXWVFIK3NYaTVGM01pYVNBZ1BkQUk3WEh1dXFET1lvMU5PL0JoSGt1aVg2QnRtCnorNTZud2pZMy8yUytSRmNBc3JMTnIwMDJZZi9oY0IraVlDNzVWYmcydVd6WTY3TWdOTGQ5VW9RU3BDRkYrVm4KM0cyUnhybnhBb0dCQU40U3M0ZVlPU2huMVpQQjdhTUZsY0k2RHR2S2ErTGZTTXFyY2pOZjJlSEpZNnhubmxKdgpGenpGL2RiVWVTbWxSekR0WkdlcXZXaHFISy9iTjIyeWJhOU1WMDlRQ0JFTk5jNmtWajJTVHpUWkJVbEx4QzYrCk93Z0wyZHhKendWelU0VC84ajdHalRUN05BZVpFS2FvRHFyRG5BYWkyaW5oZU1JVWZHRXFGKzJyQW9HQkFOMVAKK0tZL0lsS3RWRzRKSklQNzBjUis3RmpyeXJpY05iWCtQVzUvOXFHaWxnY2grZ3l4b25BWlBpd2NpeDN3QVpGdwpaZC96ZFB2aTBkWEppc1BSZjRMazg5b2pCUmpiRmRmc2l5UmJYbyt3TFU4NUhRU2NGMnN5aUFPaTVBRHdVU0FkCm45YWFweUNweEFkREtERHdObit3ZFhtaTZ0OHRpSFRkK3RoVDhkaVpBb0dCQUt6Wis1bG9OOTBtYlF4VVh5YUwKMjFSUm9tMGJjcndsTmVCaWNFSmlzaEhYa2xpSVVxZ3hSZklNM2hhUVRUcklKZENFaHFsV01aV0xPb2I2NTNyZgo3aFlMSXM1ZUtka3o0aFRVdnpldm9TMHVXcm9CV2xOVHlGanIrSWhKZnZUc0hpOGdsU3FkbXgySkJhZUFVWUNXCndNdlQ4NmNLclNyNkQrZG8wS05FZzFsL0FvR0FlMkFVdHVFbFNqLzBmRzgrV3hHc1RFV1JqclRNUzRSUjhRWXQKeXdjdFA4aDZxTGxKUTRCWGxQU05rMXZLTmtOUkxIb2pZT2pCQTViYjhibXNVU1BlV09NNENoaFJ4QnlHbmR2eAphYkJDRkFwY0IvbEg4d1R0alVZYlN5T294ZGt5OEp0ek90ajJhS0FiZHd6NlArWDZDODhjZmxYVFo5MWpYL3RMCjF3TmRKS2tDZ1lCbyt0UzB5TzJ2SWFmK2UwSkN5TGhzVDQ5cTN3Zis2QWVqWGx2WDJ1VnRYejN5QTZnbXo5aCsKcDNlK2JMRUxwb3B0WFhNdUFRR0xhUkcrYlNNcjR5dERYbE5ZSndUeThXczNKY3dlSTdqZVp2b0ZpbmNvVlVIMwphdmxoTUVCRGYxSjltSDB5cDBwWUNaS2ROdHNvZEZtQktzVEtQMjJhTmtsVVhCS3gyZzR6cFE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">kind: ConfigMap</span><br><span class="line">apiVersion: v1</span><br><span class="line">metadata:</span><br><span class="line">  name: nginx-config</span><br><span class="line">  namespace: nginx-ingress</span><br><span class="line">data:</span><br><span class="line">  server-names-hash-bucket-size: &quot;1024&quot;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">kind: ClusterRole</span><br><span class="line">apiVersion: rbac.authorization.k8s.io/v1</span><br><span class="line">metadata:</span><br><span class="line">  name: nginx-ingress</span><br><span class="line">rules:</span><br><span class="line">- apiGroups:</span><br><span class="line">  - &quot;&quot;</span><br><span class="line">  resources:</span><br><span class="line">  - services</span><br><span class="line">  - endpoints</span><br><span class="line">  verbs:</span><br><span class="line">  - get</span><br><span class="line">  - list</span><br><span class="line">  - watch</span><br><span class="line">- apiGroups:</span><br><span class="line">  - &quot;&quot;</span><br><span class="line">  resources:</span><br><span class="line">  - secrets</span><br><span class="line">  verbs:</span><br><span class="line">  - get</span><br><span class="line">  - list</span><br><span class="line">  - watch</span><br><span class="line">- apiGroups:</span><br><span class="line">  - &quot;&quot;</span><br><span class="line">  resources:</span><br><span class="line">  - configmaps</span><br><span class="line">  verbs:</span><br><span class="line">  - get</span><br><span class="line">  - list</span><br><span class="line">  - watch</span><br><span class="line">  - update</span><br><span class="line">  - create</span><br><span class="line">- apiGroups:</span><br><span class="line">  - &quot;&quot;</span><br><span class="line">  resources:</span><br><span class="line">  - pods</span><br><span class="line">  verbs:</span><br><span class="line">  - list</span><br><span class="line">- apiGroups:</span><br><span class="line">  - &quot;&quot;</span><br><span class="line">  resources:</span><br><span class="line">  - events</span><br><span class="line">  verbs:</span><br><span class="line">  - create</span><br><span class="line">  - patch</span><br><span class="line">- apiGroups:</span><br><span class="line">  - extensions</span><br><span class="line">  resources:</span><br><span class="line">  - ingresses</span><br><span class="line">  verbs:</span><br><span class="line">  - list</span><br><span class="line">  - watch</span><br><span class="line">  - get</span><br><span class="line">- apiGroups:</span><br><span class="line">  - &quot;extensions&quot;</span><br><span class="line">  resources:</span><br><span class="line">  - ingresses/status</span><br><span class="line">  verbs:</span><br><span class="line">  - update</span><br><span class="line">- apiGroups:</span><br><span class="line">  - k8s.nginx.org</span><br><span class="line">  resources:</span><br><span class="line">  - virtualservers</span><br><span class="line">  - virtualserverroutes</span><br><span class="line">  verbs:</span><br><span class="line">  - list</span><br><span class="line">  - watch</span><br><span class="line">  - get</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">kind: ClusterRoleBinding</span><br><span class="line">apiVersion: rbac.authorization.k8s.io/v1</span><br><span class="line">metadata:</span><br><span class="line">  name: nginx-ingress</span><br><span class="line">subjects:</span><br><span class="line">- kind: ServiceAccount</span><br><span class="line">  name: nginx-ingress</span><br><span class="line">  namespace: nginx-ingress</span><br><span class="line">roleRef:</span><br><span class="line">  kind: ClusterRole</span><br><span class="line">  name: nginx-ingress</span><br><span class="line">  apiGroup: rbac.authorization.k8s.io</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">apiVersion: apps/v1</span><br><span class="line">kind: DaemonSet</span><br><span class="line">metadata:</span><br><span class="line">  name: nginx-ingress</span><br><span class="line">  namespace: nginx-ingress</span><br><span class="line">  annotations:</span><br><span class="line">    prometheus.io/scrape: &quot;true&quot;</span><br><span class="line">    prometheus.io/port: &quot;9113&quot;</span><br><span class="line">spec:</span><br><span class="line">  selector:</span><br><span class="line">    matchLabels:</span><br><span class="line">      app: nginx-ingress</span><br><span class="line">  template:</span><br><span class="line">    metadata:</span><br><span class="line">      labels:</span><br><span class="line">        app: nginx-ingress</span><br><span class="line">    spec:</span><br><span class="line">      serviceAccountName: nginx-ingress</span><br><span class="line">      containers:</span><br><span class="line">      - image: nginx/nginx-ingress:1.5.5</span><br><span class="line">        name: nginx-ingress</span><br><span class="line">        ports:</span><br><span class="line">        - name: http</span><br><span class="line">          containerPort: 80</span><br><span class="line">          hostPort: 80</span><br><span class="line">        - name: https</span><br><span class="line">          containerPort: 443</span><br><span class="line">          hostPort: 443</span><br><span class="line">        - name: prometheus</span><br><span class="line">          containerPort: 9113</span><br><span class="line">        env:</span><br><span class="line">        - name: POD_NAMESPACE</span><br><span class="line">          valueFrom:</span><br><span class="line">            fieldRef:</span><br><span class="line">              fieldPath: metadata.namespace</span><br><span class="line">        - name: POD_NAME</span><br><span class="line">          valueFrom:</span><br><span class="line">            fieldRef:</span><br><span class="line">              fieldPath: metadata.name</span><br><span class="line">        args:</span><br><span class="line">          - -nginx-configmaps=$(POD_NAMESPACE)/nginx-config</span><br><span class="line">          - -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret</span><br><span class="line">         #- -v=3 # Enables extensive logging. Useful for troubleshooting.</span><br><span class="line">         #- -report-ingress-status</span><br><span class="line">         #- -external-service=nginx-ingress</span><br><span class="line">         #- -enable-leader-election</span><br><span class="line">          - -enable-prometheus-metrics</span><br><span class="line">         #- -enable-custom-resources</span><br></pre></td></tr></table></figure></p><p><strong>卸载ingress congroller</strong></p><p>在master节点上执行</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">#只在 master 节点执行</span><br><span class="line">kubectl delete -f https://kuboard.cn/install-script/v1.19.x/nginx-ingress.yaml</span><br></pre></td></tr></table></figure><p><strong>配置域名解析</strong></p><p>将域名 *.demo.yourdomain.com 解析到 demo-worker-a-2 的 IP 地址 z.z.z.z （也可以是 demo-worker-a-1 的地址 y.y.y.y）</p><p><strong>验证配置</strong></p><p>在浏览器访问 a.demo.yourdomain.com，将得到 404 NotFound 错误页面</p><blockquote><p>提示</p></blockquote><p>许多初学者在安装 Ingress Controller 时会碰到问题，请不要灰心，可暂时跳过 安装 Ingress Controller 这个部分，等您学完 www.kuboard.cn 上 Kubernetes 入门 以及 通过互联网访问您的应用程序 这两部分内容后，再来回顾 Ingress Controller 的安装。</p><p>也可以参考 Install Nginx Ingress</p><h1 id="问题及注意"><a href="#问题及注意" class="headerlink" title="问题及注意"></a>问题及注意</h1><h2 id="重启Kubenetes集群后遇到的问题"><a href="#重启Kubenetes集群后遇到的问题" class="headerlink" title="重启Kubenetes集群后遇到的问题"></a>重启Kubenetes集群后遇到的问题</h2><p>Kubernetes集群的设计目标是setup-and-run-forever，然而许多学习者使用自己笔记本上的虚拟机安装K8S集群用于学习，这就必然会出现反复重启集群所在虚拟机的情况。本文针对重启后会出现一些的一些令人困惑的问题做了解释。</p><ul><li><p>Worker节点不能启动<br>Master 节点的 IP 地址变化，导致 worker 节点不能启动。请重装集群，并确保所有节点都有固定内网 IP 地址。</p></li><li><p>许多Pod一直Crash或不能正常访问</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">kubectl get pods --all-namespaces</span><br></pre></td></tr></table></figure></li></ul><p>重启后会发现许多 Pod 不在 Running 状态，此时，请使用如下命令删除这些状态不正常的 Pod。通常，您的 Pod 如果是使用 Deployment、StatefulSet 等控制器创建的，kubernetes 将创建新的 Pod 作为替代，重新启动的 Pod 通常能够正常工作。</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">kubectl delete pod &lt;pod-name&gt; -n &lt;pod-namespece&gt;</span><br></pre></td></tr></table></figure><h2 id="安装过程中的问题"><a href="#安装过程中的问题" class="headerlink" title="安装过程中的问题"></a>安装过程中的问题</h2><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">sysctl -p</span><br><span class="line">net.ipv4.ip_forward = 1</span><br><span class="line">sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: No such file or directory</span><br><span class="line">sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory</span><br><span class="line">net.ipv6.conf.all.disable_ipv6 = 1</span><br><span class="line">net.ipv6.conf.default.disable_ipv6 = 1</span><br><span class="line">net.ipv6.conf.lo.disable_ipv6 = 1</span><br><span class="line">net.ipv6.conf.all.forwarding = 1</span><br></pre></td></tr></table></figure><p>解决办法<br><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">modprobe br_netfilter</span><br></pre></td></tr></table></figure></p><p>查看版本<br><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">kubectl version</span><br></pre></td></tr></table></figure></p><h1 id="QA"><a href="#QA" class="headerlink" title="QA"></a>QA</h1><p>怎么查看可安装的docker版本<br><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 list docker-ce --showduplicates|sort -r</span><br></pre></td></tr></table></figure></p><h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><p><a href="https://kuboard.cn/install/install-k8s.html#%E6%A3%80%E6%9F%A5-centos-hostname" target="_blank" rel="noopener">https://kuboard.cn/install/install-k8s.html#%E6%A3%80%E6%9F%A5-centos-hostname</a><br><a href="https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm/" target="_blank" rel="noopener">https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm/</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;配置要求&quot;&gt;&lt;a href=&quot;#配置要求&quot; class=&quot;headerlink&quot; title=&quot;配置要求&quot;&gt;&lt;/a&gt;配置要求&lt;/h1&gt;&lt;p&gt;对于 Kubernetes 初学者，在搭建K8S集群时，推荐在阿里云或腾讯云采购如下配置：（您也可以使用自己的虚拟机、私有云
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Kafka安装及入门</title>
    <link href="http://jaychang.cn/2020/03/15/afka%E5%AE%89%E8%A3%85%E5%8F%8A%E5%85%A5%E9%97%A8/"/>
    <id>http://jaychang.cn/2020/03/15/afka安装及入门/</id>
    <published>2020-03-15T04:38:24.000Z</published>
    <updated>2020-03-15T07:01:15.380Z</updated>
    
    <content type="html"><![CDATA[<h1 id="下载kafka-cmak"><a href="#下载kafka-cmak" class="headerlink" title="下载kafka,cmak"></a>下载kafka,cmak</h1><p>下载好后，分别解压到/opt目录下</p><p>这里如果是单机kafka，可以直接用kafka自带的,启动方式为<br><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">./$KAFKA_HOME/bin/zookeeper-server-start.sh -daemon config/zookeeper.properties</span><br></pre></td></tr></table></figure></p><h1 id="配置kafka"><a href="#配置kafka" class="headerlink" title="配置kafka"></a>配置kafka</h1><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">broker.id=0</span><br><span class="line">log.dirs=/tmp/kafka-logs</span><br><span class="line">zookeeper.connect=localhost:2181</span><br></pre></td></tr></table></figure><blockquote><p>大多数情况下，可能会改动的估计就是上述3个配置，由于kafka需要做持久化消息，故这里有一个log.dirs的配置项</p></blockquote><h1 id="启动kafka"><a href="#启动kafka" class="headerlink" title="启动kafka"></a>启动kafka</h1><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"><span class="meta">$</span> ./bin/kafka-server-start.sh -daemon config/server.properties</span><br></pre></td></tr></table></figure><blockquote><p>不加-daemon则是前台启动，若是在docker中启动，就不用加-daemon</p></blockquote><h1 id="cmak-kafka-manager"><a href="#cmak-kafka-manager" class="headerlink" title="cmak(kafka manager)"></a>cmak(kafka manager)</h1><p><strong>依赖的组件说明</strong></p><p>cmak 3.x需要依赖jdk 11+ 且zookeeper需要3.5.x版本,我直接用了es 7.x的自带jdk13</p><p>所以修改了cmak启动脚本get_java_cmd函数:<br><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> Detect if we should use JAVA_HOME or just try PATH.</span><br><span class="line">get_java_cmd() &#123;</span><br><span class="line"><span class="meta">  #</span> High-priority override for Jlink images</span><br><span class="line"><span class="meta">  #</span>if [[ -n "$bundled_jvm" ]];  then</span><br><span class="line"><span class="meta">  #</span>  echo "$bundled_jvm/bin/java"</span><br><span class="line"><span class="meta">  #</span>elif [[ -n "$JAVA_HOME" ]] &amp;&amp; [[ -x "$JAVA_HOME/bin/java" ]];  then</span><br><span class="line"><span class="meta">  #</span>  echo "$JAVA_HOME/bin/java"</span><br><span class="line"><span class="meta">  #</span>else</span><br><span class="line"><span class="meta">  #</span>  echo "java"</span><br><span class="line"><span class="meta">  #</span>fi</span><br><span class="line">  echo "/opt/elasticsearch-7.6.1/jdk/bin/java"</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p><strong>修改配置</strong><br>修改conf/application.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></pre></td><td class="code"><pre><span class="line">kafka-manager.zkhosts=&quot;localhost:2181&quot;</span><br><span class="line">kafka-manager.zkhosts=$&#123;?ZK_HOSTS&#125;</span><br><span class="line">cmak.zkhosts=&quot;localhost:2181&quot;</span><br><span class="line">cmak.zkhosts=$&#123;?ZK_HOSTS&#125;</span><br></pre></td></tr></table></figure><blockquote><p>当然也可以不修改application.conf文件，而是提供环境变量ZK_HOSTS</p></blockquote><p><strong>启动cmak</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">./bin/cmak &gt; cmak.out 2&gt;&amp;1 &amp;</span><br></pre></td></tr></table></figure><p><strong>添加集群</strong></p><p>点添加集群（Add Cluster）<br><img src="/images/pasted-36.png" alt="upload successful"></p><p>填写集群名称与zookeeper地址<br><img src="/images/pasted-37.png" alt="upload successful"></p><p>添加完成查看集群信息，包括zookeepers连接地址，kafka版本，topic数量，broker数量<br><img src="/images/pasted-38.png" alt="upload successful"></p><p><strong>查看broker信息</strong></p><p><img src="/images/pasted-42.png" alt="upload successful"></p><p><strong>查看、操作topic</strong></p><p>之前已经创建过first-topic，topics列表就可以看到了<br><img src="/images/pasted-39.png" alt="upload successful"></p><p>给topic增加分区</p><p><img src="/images/pasted-40.png" alt="upload successful"></p><p>创建topic<br><img src="/images/pasted-41.png" alt="upload successful"></p><p>PS:更多cmak的功能有待实践</p><p><strong>常见错误</strong><br><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">This application is already running (Or delete /opt/kafka-cmak-3.0.0.4/RUNNING_PID file).</span><br></pre></td></tr></table></figure></p><p>删掉RUNNING_PID重新启动</p><h1 id="Kafka入门"><a href="#Kafka入门" class="headerlink" title="Kafka入门"></a>Kafka入门</h1><p><strong>创建Topic</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">root@ubuntu:/opt/kafka_2.12-2.4.0# ./bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic first-topic</span><br><span class="line">Created topic first-topic.</span><br></pre></td></tr></table></figure><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><p><a href="https://segmentfault.com/a/1190000012730949" target="_blank" rel="noopener">https://segmentfault.com/a/1190000012730949</a><br><a href="https://blog.wolfogre.com/posts/kafka-manager-download/" target="_blank" rel="noopener">https://blog.wolfogre.com/posts/kafka-manager-download/</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;下载kafka-cmak&quot;&gt;&lt;a href=&quot;#下载kafka-cmak&quot; class=&quot;headerlink&quot; title=&quot;下载kafka,cmak&quot;&gt;&lt;/a&gt;下载kafka,cmak&lt;/h1&gt;&lt;p&gt;下载好后，分别解压到/opt目录下&lt;/p&gt;
&lt;p&gt;这里如果是
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>ElasticSearch7.x集群安装部署</title>
    <link href="http://jaychang.cn/2020/03/07/ElasticSearch7-x%E9%9B%86%E7%BE%A4%E5%AE%89%E8%A3%85%E9%83%A8%E7%BD%B2/"/>
    <id>http://jaychang.cn/2020/03/07/ElasticSearch7-x集群安装部署/</id>
    <published>2020-03-07T12:46:29.000Z</published>
    <updated>2020-03-15T04:21:42.094Z</updated>
    
    <content type="html"><![CDATA[<h1 id="创建用户"><a href="#创建用户" class="headerlink" title="创建用户"></a>创建用户</h1><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">groupadd es &amp;&amp; useradd es -g es -M -s /bin/bash</span><br><span class="line">chown -R es:es /opt/$ES_HOME</span><br></pre></td></tr></table></figure><h1 id="系统参数修改"><a href="#系统参数修改" class="headerlink" title="系统参数修改"></a>系统参数修改</h1><ul><li>vi /etc/sysctl.conf添加如下配置</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">vm.max_map_count=262144</span><br></pre></td></tr></table></figure><blockquote><p>使得重启之后也生效，即永久生效</p></blockquote><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">sysctl –p</span><br></pre></td></tr></table></figure><ul><li><p>修改/etc/security/limits.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">es hard nofile 65535</span><br><span class="line">es soft nofile 65535</span><br></pre></td></tr></table></figure></li><li><p>/etc/systemd/user.conf和/etc/systemd/system.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">DefaultLimitNOFILE=65535</span><br></pre></td></tr></table></figure></li></ul><blockquote><p>systemd启动elasticsearch，需要设置这两个文件，否则启动会报如下错误<br>[1] bootstrap checks failed<br>[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65535]</p></blockquote><h1 id="解压"><a href="#解压" class="headerlink" title="解压"></a>解压</h1><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">tar xzvf elasticsearch-7.6.1-linux-x86_64.tar.gz -C /opt/</span><br></pre></td></tr></table></figure><h1 id="配置ES"><a href="#配置ES" class="headerlink" title="配置ES"></a>配置ES</h1><p>1主2从的配置</p><ul><li>node-1</li></ul><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">cluster.name:</span> <span class="string">my-es</span></span><br><span class="line"></span><br><span class="line"><span class="string">node.name:</span> <span class="string">node-1</span></span><br><span class="line"><span class="string">node.master:</span> <span class="literal">true</span></span><br><span class="line"><span class="string">node.data:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="string">network.host:</span> <span class="number">0.0</span><span class="number">.0</span><span class="number">.0</span></span><br><span class="line"><span class="string">network.publish_host:</span> <span class="number">192.168</span><span class="number">.56</span><span class="number">.131</span></span><br><span class="line"></span><br><span class="line"><span class="string">discovery.seed_hosts:</span> <span class="string">[</span> <span class="string">"192.168.56.132"</span><span class="string">,"192.168.56.133"]</span></span><br><span class="line"><span class="string">cluster.initial_master_nodes:</span> <span class="string">["node-1"]</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 允许跨域，elastic header需要</span></span><br><span class="line"><span class="string">http.cors.enabled:</span> <span class="literal">true</span></span><br><span class="line"><span class="string">http.cors.allow-origin:</span> <span class="string">"*"</span></span><br></pre></td></tr></table></figure><ul><li>node-2</li></ul><figure class="highlight yaml"><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></pre></td><td class="code"><pre><span class="line"><span class="string">cluster.name:</span> <span class="string">my-es</span></span><br><span class="line"></span><br><span class="line"><span class="string">node.name:</span> <span class="string">node-2</span></span><br><span class="line"><span class="string">node.master:</span> <span class="literal">false</span></span><br><span class="line"><span class="string">node.data:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="string">network.host:</span> <span class="number">0.0</span><span class="number">.0</span><span class="number">.0</span></span><br><span class="line"><span class="string">network.publish_host:</span> <span class="number">192.168</span><span class="number">.56</span><span class="number">.132</span></span><br><span class="line"></span><br><span class="line"><span class="string">discovery.seed_hosts:</span> <span class="string">["192.168.56.131","192.168.56.133"]</span></span><br><span class="line"></span><br><span class="line"><span class="string">cluster.initial_master_nodes:</span> <span class="string">["node-1"]</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 允许跨域，elastic header需要</span></span><br><span class="line"><span class="string">http.cors.enabled:</span> <span class="literal">true</span></span><br><span class="line"><span class="string">http.cors.allow-origin:</span> <span class="string">"*"</span></span><br></pre></td></tr></table></figure><ul><li>node-3</li></ul><figure class="highlight yaml"><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></pre></td><td class="code"><pre><span class="line"><span class="string">cluster.name:</span> <span class="string">my-es</span></span><br><span class="line"></span><br><span class="line"><span class="string">node.name:</span> <span class="string">node-3</span></span><br><span class="line"><span class="string">node.master:</span> <span class="literal">false</span></span><br><span class="line"><span class="string">node.data:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="string">network.host:</span> <span class="number">0.0</span><span class="number">.0</span><span class="number">.0</span></span><br><span class="line"><span class="string">network.publish_host:</span> <span class="number">192.168</span><span class="number">.56</span><span class="number">.133</span></span><br><span class="line"></span><br><span class="line"><span class="string">discovery.seed_hosts:</span> <span class="string">["192.168.56.131",</span> <span class="string">"192.168.56.132"</span><span class="string">]</span></span><br><span class="line"></span><br><span class="line"><span class="string">cluster.initial_master_nodes:</span> <span class="string">["node-1"]</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 允许跨域，elastic header需要</span></span><br><span class="line"><span class="string">http.cors.enabled:</span> <span class="literal">true</span></span><br><span class="line"><span class="string">http.cors.allow-origin:</span> <span class="string">"*"</span></span><br></pre></td></tr></table></figure><blockquote><p>生产环境建议network.host: 指定IP</p></blockquote><h1 id="检查集群状态"><a href="#检查集群状态" class="headerlink" title="检查集群状态"></a>检查集群状态</h1><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></pre></td><td class="code"><pre><span class="line">curl -XGET http://192.168.56.131:9200/_cluster/health?pretty</span><br><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">cluster_name: "my-es",</span><br><span class="line">status: "green",</span><br><span class="line">timed_out: false,</span><br><span class="line">number_of_nodes: 3,</span><br><span class="line">number_of_data_nodes: 3,</span><br><span class="line">active_primary_shards: 0,</span><br><span class="line">active_shards: 0,</span><br><span class="line">relocating_shards: 0,</span><br><span class="line">initializing_shards: 0,</span><br><span class="line">unassigned_shards: 0,</span><br><span class="line">delayed_unassigned_shards: 0,</span><br><span class="line">number_of_pending_tasks: 0,</span><br><span class="line">number_of_in_flight_fetch: 0,</span><br><span class="line">task_max_waiting_in_queue_millis: 0,</span><br><span class="line">active_shards_percent_as_number: 100</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="开机启动ElasticSearch"><a href="#开机启动ElasticSearch" class="headerlink" title="开机启动ElasticSearch"></a>开机启动ElasticSearch</h1><p><strong>方案一 在/etc/init.d目录下</strong></p><p>创建名为elasticsearch的文件，内容如下</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>!/bin/sh</span><br><span class="line"><span class="meta">#</span>description: elasticsearch</span><br><span class="line"><span class="meta">#</span>## BEGIN INIT INFO</span><br><span class="line"><span class="meta">#</span> Provides:          elasticsearch</span><br><span class="line"><span class="meta">#</span> Required-Start:    $all</span><br><span class="line"><span class="meta">#</span> Required-Stop:</span><br><span class="line"><span class="meta">#</span> Default-Start:     2 3 4 5</span><br><span class="line"><span class="meta">#</span> Default-Stop:</span><br><span class="line"><span class="meta">#</span> Short-Description: start elasticsearch</span><br><span class="line"><span class="meta">#</span>## END INIT INFO</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">case "$1" in</span><br><span class="line">start)</span><br><span class="line">    cd /opt/elasticsearch-7.6.1</span><br><span class="line">    ./bin/elasticsearch -d</span><br><span class="line">!</span><br><span class="line">    echo "elasticsearch startup"</span><br><span class="line">    ;;</span><br><span class="line">stop)</span><br><span class="line">    es_pid=`ps aux|grep elasticsearch | grep -v 'grep elasticsearch' | awk '&#123;print $2&#125;'`</span><br><span class="line">    kill -9 $es_pid</span><br><span class="line">    echo "elasticsearch stopped"</span><br><span class="line">    ;;</span><br><span class="line">restart)</span><br><span class="line">    es_pid=`ps aux|grep elasticsearch | grep -v 'grep elasticsearch' | awk '&#123;print $2&#125;'`</span><br><span class="line">    kill -9 $es_pid</span><br><span class="line">    echo "elasticsearch stopped"</span><br><span class="line">    cd /opt/elasticsearch-7.6.1</span><br><span class="line">    ./bin/elasticsearch -d</span><br><span class="line">!</span><br><span class="line">    echo "elasticsearch startup"</span><br><span class="line">    ;;</span><br><span class="line">*)</span><br><span class="line">    echo "start|stop|restart"</span><br><span class="line">    ;;</span><br><span class="line">esac</span><br><span class="line"></span><br><span class="line">exit $?</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"><span class="meta">$</span> chmod a+x elasticsearch.sh</span><br></pre></td></tr></table></figure><p><strong>方案二 在/lib/systemd/system目录下</strong></p><p>创建名为elasticsearch.service的文件，内容如下<br><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></pre></td><td class="code"><pre><span class="line">[Unit]</span><br><span class="line">Description=elasticsearch</span><br><span class="line">After=network.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=simple</span><br><span class="line">ExecStart=/bin/bash /opt/elasticsearch-7.6.1/bin/elasticsearch</span><br><span class="line">Restart=always</span><br><span class="line">User=es</span><br><span class="line">Group=es</span><br><span class="line">WorkingDirectory=/opt/elasticsearch-7.6.1</span><br><span class="line">[Install]</span><br><span class="line">WantedBy=mutil-user.target</span><br></pre></td></tr></table></figure></p><p>重载配置文件<br><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"><span class="meta">$</span> sudo systemctl daemon-reload</span><br></pre></td></tr></table></figure></p><p>启用服务<br><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"><span class="meta">$</span> sudo systemctl enable elasticsearch</span><br></pre></td></tr></table></figure></p><p>启动服务<br><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"><span class="meta">$</span> sudo systemctl start elasticsearch</span><br></pre></td></tr></table></figure></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><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> 查看状态</span><br><span class="line"><span class="meta">$</span> sudo systemctl status elasticsearch</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 查看日志</span><br><span class="line"><span class="meta">$</span> sudo journalctl -u elasticsearch</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 实时输出最新日志</span><br><span class="line"><span class="meta">$</span> sudo journalctl --follow -u elasticsearch</span><br></pre></td></tr></table></figure><p>通过systemctl 启动服务报如下错误<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Mar 15 10:08:51 ubuntu bash[1308]: ERROR: [1] bootstrap checks failed</span><br><span class="line">Mar 15 10:08:51 ubuntu bash[1308]: [1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65535]</span><br><span class="line">Mar 15 10:08:51 ubuntu bash[1308]: ERROR: Elasticsearch did not exit normally - check the logs at /opt/elasticsearch-7.6.1/logs/my-es.log</span><br><span class="line">Mar 15 10:08:51 ubuntu bash[1308]: [2020-03-15T02:08:51,352][INFO ][o.e.n.Node               ] [node-1] stopping ...</span><br><span class="line">Mar 15 10:08:51 ubuntu bash[1308]: [2020-03-15T02:08:51,462][INFO ][o.e.n.Node               ] [node-1] stopped</span><br><span class="line">Mar 15 10:08:51 ubuntu bash[1308]: [2020-03-15T02:08:51,463][INFO ][o.e.n.Node               ] [node-1] closing ...</span><br><span class="line">Mar 15 10:08:51 ubuntu bash[1308]: [2020-03-15T02:08:51,535][INFO ][o.e.n.Node               ] [node-1] closed</span><br></pre></td></tr></table></figure></p><p><em>划重点：通过systemctrl自建elasticsearch系统服务的形式来启动的es,则需要修改/etc/systemd/user.conf,/etc/systemd/system.conf这两个文件，添加以下配置</em><br><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">DefaultLimitNOFILE=65536</span><br></pre></td></tr></table></figure></p><h1 id="常见错误"><a href="#常见错误" class="headerlink" title="常见错误"></a>常见错误</h1><figure class="highlight java"><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">org.elasticsearch.bootstrap.StartupException: java.lang.RuntimeException: can not run elasticsearch as root</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:<span class="number">174</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:<span class="number">161</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:<span class="number">86</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:<span class="number">125</span>) ~[elasticsearch-cli-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.cli.Command.main(Command.java:<span class="number">90</span>) ~[elasticsearch-cli-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:<span class="number">126</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:<span class="number">92</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">Caused by: java.lang.RuntimeException: can not run elasticsearch as root</span><br><span class="line">at org.elasticsearch.bootstrap.Bootstrap.initializeNatives(Bootstrap.java:<span class="number">105</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:<span class="number">172</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:<span class="number">349</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:<span class="number">170</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br></pre></td></tr></table></figure><p>这个是最常见的了，不能用root用户来启动elasticsearch</p><figure class="highlight java"><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">Exception in thread <span class="string">"main"</span> org.elasticsearch.bootstrap.BootstrapException: java.nio.file.AccessDeniedException: /opt/elasticsearch-<span class="number">7.6</span>.1/config/elasticsearch.keystore</span><br><span class="line">Likely root cause: java.nio.file.AccessDeniedException: /opt/elasticsearch-<span class="number">7.6</span>.1/config/elasticsearch.keystore</span><br><span class="line">at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:<span class="number">90</span>)</span><br><span class="line">at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:<span class="number">111</span>)</span><br><span class="line">at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:<span class="number">116</span>)</span><br><span class="line">at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:<span class="number">219</span>)</span><br><span class="line">at java.base/java.nio.file.Files.newByteChannel(Files.java:<span class="number">374</span>)</span><br><span class="line">at java.base/java.nio.file.Files.newByteChannel(Files.java:<span class="number">425</span>)</span><br><span class="line">at org.apache.lucene.store.SimpleFSDirectory.openInput(SimpleFSDirectory.java:<span class="number">77</span>)</span><br><span class="line">at org.elasticsearch.common.settings.KeyStoreWrapper.load(KeyStoreWrapper.java:<span class="number">219</span>)</span><br><span class="line">at org.elasticsearch.bootstrap.Bootstrap.loadSecureSettings(Bootstrap.java:<span class="number">234</span>)</span><br><span class="line">at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:<span class="number">305</span>)</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:<span class="number">170</span>)</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:<span class="number">161</span>)</span><br><span class="line">at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:<span class="number">86</span>)</span><br><span class="line">at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:<span class="number">125</span>)</span><br><span class="line">at org.elasticsearch.cli.Command.main(Command.java:<span class="number">90</span>)</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:<span class="number">126</span>)</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:<span class="number">92</span>)</span><br></pre></td></tr></table></figure><p>处理方法 chown -R es:es $ES_HOME/conf</p><figure class="highlight java"><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></pre></td><td class="code"><pre><span class="line">2020-03-07 14:50:20,774 main ERROR Unable to invoke factory method in class org.apache.logging.log4j.core.appender.RollingFileAppender for element RollingFile: java.lang.IllegalStateException: No factory method found for class org.apache.logging.log4j.core.appender.RollingFileAppender java.lang.IllegalStateException: No factory method found for class org.apache.logging.log4j.core.appender.RollingFileAppender</span><br><span class="line">at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.findFactoryMethod(PluginBuilder.java:<span class="number">235</span>)</span><br><span class="line">at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:<span class="number">135</span>)</span><br><span class="line">at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:<span class="number">959</span>)</span><br><span class="line">at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:<span class="number">899</span>)</span><br><span class="line">at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:<span class="number">891</span>)</span><br><span class="line">at org.apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:<span class="number">514</span>)</span><br><span class="line">at org.apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:<span class="number">238</span>)</span><br><span class="line">at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:<span class="number">250</span>)</span><br><span class="line">at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:<span class="number">547</span>)</span><br><span class="line">at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:<span class="number">263</span>)</span><br><span class="line">at org.elasticsearch.common.logging.LogConfigurator.configure(LogConfigurator.java:<span class="number">234</span>)</span><br><span class="line">at org.elasticsearch.common.logging.LogConfigurator.configure(LogConfigurator.java:<span class="number">127</span>)</span><br><span class="line">at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:<span class="number">310</span>)</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:<span class="number">170</span>)</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:<span class="number">161</span>)</span><br><span class="line">at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:<span class="number">86</span>)</span><br><span class="line">at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:<span class="number">125</span>)</span><br><span class="line">at org.elasticsearch.cli.Command.main(Command.java:<span class="number">90</span>)</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:<span class="number">126</span>)</span><br><span class="line">at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:<span class="number">92</span>)</span><br></pre></td></tr></table></figure><p>处理方法 chown -R es:es $ES_HOME/logs</p><figure class="highlight java"><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="number">2020</span>-<span class="number">03</span>-<span class="number">07</span>T14:<span class="number">11</span>:<span class="number">03</span>,<span class="number">119</span>][WARN ][o.e.c.c.Coordinator      ] [node-<span class="number">1</span>] failed to validate incoming join request from node [&#123;node-<span class="number">2</span>&#125;&#123;OTFjHR3wRuyQBMbb9PdGoQ&#125;&#123;GH_dXyYZQIuyjnnBTsELRw&#125;&#123;<span class="number">192.168</span>.56.132&#125;&#123;<span class="number">192.168</span>.56.132:<span class="number">9300</span>&#125;&#123;dil&#125;&#123;ml.machine_memory=<span class="number">3665874944</span>, ml.max_open_jobs=<span class="number">20</span>, xpack.installed=<span class="keyword">true</span>&#125;]</span><br><span class="line">org.elasticsearch.transport.RemoteTransportException: [node-<span class="number">2</span>][<span class="number">192.168</span>.56.132:<span class="number">9300</span>][internal:cluster/coordination/join/validate]</span><br><span class="line">Caused by: org.elasticsearch.cluster.coordination.CoordinationStateRejectedException: join validation on cluster state with a different cluster uuid of6I6UasSd209Y_5-YdZ2A than local cluster uuid <span class="number">4</span>jifFlHcR9K7wQflerzo3g, rejecting</span><br><span class="line">at org.elasticsearch.cluster.coordination.JoinHelper.lambda$<span class="keyword">new</span>$<span class="number">4</span>(JoinHelper.java:<span class="number">148</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.xpack.security.transport.SecurityServerTransportInterceptor$ProfileSecuredRequestHandler$<span class="number">1</span>.doRun(SecurityServerTransportInterceptor.java:<span class="number">257</span>) ~[?:?]</span><br><span class="line">at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:<span class="number">37</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.xpack.security.transport.SecurityServerTransportInterceptor$ProfileSecuredRequestHandler.messageReceived(SecurityServerTransportInterceptor.java:<span class="number">315</span>) ~[?:?]</span><br><span class="line">at org.elasticsearch.transport.RequestHandlerRegistry.processMessageReceived(RequestHandlerRegistry.java:<span class="number">63</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.transport.InboundHandler$RequestHandler.doRun(InboundHandler.java:<span class="number">264</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:<span class="number">692</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:<span class="number">37</span>) ~[elasticsearch-<span class="number">7.6</span>.1.jar:<span class="number">7.6</span>.1]</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:<span class="number">1128</span>) [?:?]</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:<span class="number">628</span>) [?:?]</span><br><span class="line">at java.lang.Thread.run(Thread.java:<span class="number">830</span>) [?:?]</span><br></pre></td></tr></table></figure><p>如果集群所有节点cluster.name设置都一样的，但还是报以上错误，可以将集群内的节点的data目录删掉后重启</p><h1 id="附加"><a href="#附加" class="headerlink" title="附加"></a>附加</h1><p>目前es没有桌面客户端，不过elasticsearch-head算是比较方便的，用于快速查询下数据。<br>这里我就给出elastic-head，systemd服务的脚本</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></pre></td><td class="code"><pre><span class="line">[Unit]</span><br><span class="line">Description=elasticsearch head</span><br><span class="line">After=network.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=simple</span><br><span class="line">Environment=PATH=/opt/node-v12.16.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin</span><br><span class="line">ExecStart=/opt/node-v12.16.1/bin/npm run start</span><br><span class="line">Restart=always</span><br><span class="line">User=es</span><br><span class="line">Group=es</span><br><span class="line">WorkingDirectory=/opt/elasticsearch-head</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=mutil-user.target</span><br></pre></td></tr></table></figure><blockquote><p>请事先安装好node环境，并在/opt/elasticsearch-head目录，执行好npm i -V安装好相关module</p></blockquote><p>执行如下命令，下次就能开机启动了<br><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> systemctl daemon-reload</span><br><span class="line"><span class="meta">$</span> systemctl enable elasticsearch-head</span><br></pre></td></tr></table></figure></p><h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-network.html" target="_blank" rel="noopener">https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-network.html</a><br><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/targz.html" target="_blank" rel="noopener">https://www.elastic.co/guide/en/elasticsearch/reference/current/targz.html</a><br><a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.6/docker.html" target="_blank" rel="noopener">https://www.elastic.co/guide/en/elasticsearch/reference/7.6/docker.html</a><br><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/settings.html" target="_blank" rel="noopener">https://www.elastic.co/guide/en/elasticsearch/reference/current/settings.html</a><br><a href="https://www.linuxtechi.com/set-ulimit-file-descriptors-limit-linux-servers/" target="_blank" rel="noopener">https://www.linuxtechi.com/set-ulimit-file-descriptors-limit-linux-servers/</a><br><a href="https://askubuntu.com/questions/1102512/set-ulimit-for-non-root-user" target="_blank" rel="noopener">https://askubuntu.com/questions/1102512/set-ulimit-for-non-root-user</a><br><a href="https://superuser.com/questions/1200539/cannot-increase-open-file-limit-past-4096-ubuntu/1200818#1200818" target="_blank" rel="noopener">https://superuser.com/questions/1200539/cannot-increase-open-file-limit-past-4096-ubuntu/1200818#1200818</a><br><a href="http://www.ruanyifeng.com/blog/2018/03/systemd-timer.html" target="_blank" rel="noopener">http://www.ruanyifeng.com/blog/2018/03/systemd-timer.html</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;创建用户&quot;&gt;&lt;a href=&quot;#创建用户&quot; class=&quot;headerlink&quot; title=&quot;创建用户&quot;&gt;&lt;/a&gt;创建用户&lt;/h1&gt;&lt;figure class=&quot;highlight shell&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pr
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>如何构建SpringBoot应用的Docker镜像</title>
    <link href="http://jaychang.cn/2019/12/02/%E4%BD%95%E6%9E%84%E5%BB%BASpringBoot%E5%BA%94%E7%94%A8%E7%9A%84Docker%E9%95%9C%E5%83%8F/"/>
    <id>http://jaychang.cn/2019/12/02/何构建SpringBoot应用的Docker镜像/</id>
    <published>2019-12-02T12:57:36.000Z</published>
    <updated>2019-12-04T14:29:02.617Z</updated>
    
    <content type="html"><![CDATA[<hr><p>title: 如何构建SpringBoot应用的Docker镜像<br>date: 2019-12-04 22:17:54<br>categories: </p><ul><li>SpringBoot<br>tags:</li><li>Docker</li><li>SpringBoot</li></ul><hr><h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>SpringBoot大道其行，微服务也是大道其行，越来越多的SpringBoot应用使用Docker容器来运行。既然要用Docker容器运行，那首先得把SpringBoot应用打包成Docker镜像。</p><h1 id="构建方法"><a href="#构建方法" class="headerlink" title="构建方法"></a>构建方法</h1><p>目前主要的方法有三种：</p><ul><li>1.使用dockerfile-maven-plugin插件构建</li><li>2.使用Google Jib插件构建</li><li>3.手动构建</li></ul><p>下面我们一一来介绍，首先来介绍</p><h2 id="使用dockerfile-maven-plugin插件构建"><a href="#使用dockerfile-maven-plugin插件构建" class="headerlink" title="使用dockerfile-maven-plugin插件构建"></a>使用dockerfile-maven-plugin插件构建</h2><p>项目地址：<a href="https://github.com/spotify/dockerfile-maven" target="_blank" rel="noopener">https://github.com/spotify/dockerfile-maven</a></p><h3 id="项目根目录下创建Dockerfile"><a href="#项目根目录下创建Dockerfile" class="headerlink" title="项目根目录下创建Dockerfile"></a>项目根目录下创建Dockerfile</h3><blockquote><blockquote><p>以下给出了多个Dockerfile，根据实际情况选择</p></blockquote></blockquote><ol><li><p>简洁版</p><figure class="highlight dockerfile"><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="keyword">FROM</span> openjdk:<span class="number">8</span>-jdk-alpine</span><br><span class="line"><span class="keyword">MAINTAINER</span> jaychang &lt;jaychang1987@gmail.com&gt;</span><br><span class="line"><span class="keyword">VOLUME</span><span class="bash"> /tmp</span></span><br><span class="line"><span class="bash">ARG FILE</span></span><br><span class="line"><span class="bash">ARG APP_NAME</span></span><br><span class="line"><span class="bash">ADD <span class="variable">$&#123;FILE&#125;</span> /app.jar</span></span><br><span class="line"><span class="bash">ENV JAVA_OPTS=<span class="string">"-XX:MaxRAMFraction=2"</span></span></span><br><span class="line"><span class="bash"><span class="comment"># Configure ustc alpine software source and timezone</span></span></span><br><span class="line"><span class="bash">RUN sed -i <span class="string">"s#http://dl-cdn.alpinelinux.org#https://mirrors.aliyun.com#g"</span> /etc/apk/repositories \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk update \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk --no-cache add tzdata curl tini \</span></span><br><span class="line"><span class="bash">    &amp;&amp; cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \</span></span><br><span class="line"><span class="bash">    &amp;&amp; <span class="built_in">echo</span> <span class="string">"Asia/Shanghai"</span> &gt;  /etc/timezone \</span></span><br><span class="line"><span class="bash">    &amp;&amp; rm -rf /var/cache/apk/*</span></span><br><span class="line"><span class="bash"><span class="comment"># To reduce Tomcat startup time we added a system property pointing to "/dev/urandom" as a source of entropy.</span></span></span><br><span class="line"><span class="bash">ENTRYPOINT [<span class="string">"/sbin/tini"</span>, <span class="string">"--"</span>]</span></span><br><span class="line"><span class="bash">CMD [<span class="string">"sh"</span>,<span class="string">"-c"</span>,<span class="string">"java <span class="variable">$JAVA_OPTS</span> -Djava.security.egd=file:/dev/./urandom -jar app.jar"</span>]</span></span><br></pre></td></tr></table></figure></li><li><p>有带-D的参数</p></li></ol><figure class="highlight dockerfile"><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="keyword">FROM</span> openjdk:<span class="number">8</span>-jdk-alpine</span><br><span class="line"><span class="keyword">MAINTAINER</span> jaychang &lt;jaychang1987@gmail.com&gt;</span><br><span class="line"><span class="keyword">VOLUME</span><span class="bash"> /tmp</span></span><br><span class="line"><span class="bash">ARG FILE</span></span><br><span class="line"><span class="bash">ARG APP_NAME</span></span><br><span class="line"><span class="bash">ADD <span class="variable">$&#123;FILE&#125;</span> /app.jar</span></span><br><span class="line"><span class="bash"><span class="comment"># PINPOINT_VERSION Default 1.6.2 it can be replaced at docker run use -e or docker service -e or environment in docker-compose.yml</span></span></span><br><span class="line"><span class="bash">ENV PINPOINT_VERSION=1.6.2</span></span><br><span class="line"><span class="bash">ENV JAVA_OPTS=<span class="string">"-XX:MaxRAMFraction=2"</span></span></span><br><span class="line"><span class="bash">ENV PINPOINT_OPTS=<span class="string">"-Dpinpoint.agentId=<span class="variable">$&#123;APP_NAME&#125;</span> -Dpinpoint.applicationName=<span class="variable">$APP_NAME</span>"</span></span></span><br><span class="line"><span class="bash"><span class="comment"># Configure ustc alpine software source and timezone</span></span></span><br><span class="line"><span class="bash">RUN sed -i <span class="string">"s/http:\/\/dl-cdn.alpinelinux.org/https:\/\/mirrors.aliyun.com/g"</span> /etc/apk/repositories \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk update \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk --no-cache add tzdata curl tini \</span></span><br><span class="line"><span class="bash">    &amp;&amp; cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \</span></span><br><span class="line"><span class="bash">    &amp;&amp; <span class="built_in">echo</span> <span class="string">"Asia/Shanghai"</span> &gt;  /etc/timezone \</span></span><br><span class="line"><span class="bash">    &amp;&amp; rm -rf /var/cache/apk/*</span></span><br><span class="line"><span class="bash"><span class="comment"># To reduce Tomcat startup time we added a system property pointing to "/dev/urandom" as a source of entropy.</span></span></span><br><span class="line"><span class="bash">ENTRYPOINT [<span class="string">"/sbin/tini"</span>, <span class="string">"--"</span>]</span></span><br><span class="line"><span class="bash">CMD [<span class="string">"sh"</span>,<span class="string">"-c"</span>,<span class="string">"java <span class="variable">$JAVA_OPTS</span> -javaagent:/pinpoint_data/pinpoint-agent-<span class="variable">$&#123;PINPOINT_VERSION&#125;</span>/pinpoint-bootstrap-<span class="variable">$PINPOINT_VERSION</span>.jar <span class="variable">$PINPOINT_OPTS</span> -Djava.security.egd=file:/dev/./urandom -jar app.jar"</span>]</span></span><br></pre></td></tr></table></figure><ol><li>带字体版<blockquote><p>常见的场景如excel导出，验证码</p></blockquote></li></ol><figure class="highlight dockerfile"><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="keyword">FROM</span> openjdk:<span class="number">8</span>-jdk-alpine</span><br><span class="line"><span class="keyword">MAINTAINER</span> jaychang &lt;jaychang1987@gmail.com&gt;</span><br><span class="line"><span class="keyword">VOLUME</span><span class="bash"> /tmp</span></span><br><span class="line"><span class="bash">ARG FILE</span></span><br><span class="line"><span class="bash">ARG APP_NAME</span></span><br><span class="line"><span class="bash">ADD <span class="variable">$&#123;FILE&#125;</span> /app.jar</span></span><br><span class="line"><span class="bash">ENV JAVA_OPTS=<span class="string">"-XX:MaxRAMFraction=2"</span></span></span><br><span class="line"><span class="bash"><span class="comment"># Configure ustc alpine software source and timezone</span></span></span><br><span class="line"><span class="bash">RUN sed -i <span class="string">"s/http:\/\/dl-cdn.alpinelinux.org/https:\/\/mirrors.aliyun.com/g"</span> /etc/apk/repositories \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk update \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk --no-cache add tzdata curl tini \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk --no-cahce add font-adobe-100dpi ttf-dejavu fontconfig \</span></span><br><span class="line"><span class="bash">    &amp;&amp; cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \</span></span><br><span class="line"><span class="bash">    &amp;&amp; <span class="built_in">echo</span> <span class="string">"Asia/Shanghai"</span> &gt;  /etc/timezone \</span></span><br><span class="line"><span class="bash">    &amp;&amp; rm -rf /var/cache/apk/*</span></span><br><span class="line"><span class="bash"><span class="comment"># To reduce Tomcat startup time we added a system property pointing to "/dev/urandom" as a source of entropy.</span></span></span><br><span class="line"><span class="bash">ENTRYPOINT [<span class="string">"/sbin/tini"</span>, <span class="string">"--"</span>]</span></span><br><span class="line"><span class="bash">CMD [<span class="string">"sh"</span>,<span class="string">"-c"</span>,<span class="string">"java <span class="variable">$JAVA_OPTS</span> -Djava.security.egd=file:/dev/./urandom -jar app.jar"</span>]</span></span><br></pre></td></tr></table></figure><h3 id="在pom-xml中配置maven插件"><a href="#在pom-xml中配置maven插件" class="headerlink" title="在pom.xml中配置maven插件"></a>在pom.xml中配置maven插件</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1.6.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">executions</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goals</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goal</span>&gt;</span>repackage<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">executions</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.spotify<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>dockerfile-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">version</span>&gt;</span>1.4.12<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">executions</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">id</span>&gt;</span>build-image<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">phase</span>&gt;</span>package<span class="tag">&lt;/<span class="name">phase</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goals</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goal</span>&gt;</span>build<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">id</span>&gt;</span>tag-image-version<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">phase</span>&gt;</span>package<span class="tag">&lt;/<span class="name">phase</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goals</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goal</span>&gt;</span>tag<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goal</span>&gt;</span>push<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tag</span>&gt;</span>$&#123;project.version&#125;<span class="tag">&lt;/<span class="name">tag</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">id</span>&gt;</span>tag-image-latest<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">phase</span>&gt;</span>package<span class="tag">&lt;/<span class="name">phase</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goals</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goal</span>&gt;</span>tag<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goal</span>&gt;</span>push<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tag</span>&gt;</span>latest<span class="tag">&lt;/<span class="name">tag</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">executions</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tag</span>&gt;</span>$&#123;project.version&#125;<span class="tag">&lt;/<span class="name">tag</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">repository</span>&gt;</span>$&#123;docker.image.prefix&#125;/$&#123;project.artifactId&#125;<span class="tag">&lt;/<span class="name">repository</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">buildArgs</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">FILE</span>&gt;</span>target/$&#123;project.build.finalName&#125;.jar<span class="tag">&lt;/<span class="name">FILE</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">APP_NAME</span>&gt;</span>$&#123;project.artifactId&#125;<span class="tag">&lt;/<span class="name">APP_NAME</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">buildArgs</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br></pre></td></tr></table></figure><blockquote><p>docker.image.prefix可以预先在properties标签中定义好，如果要区分不同环境传到不同的镜像中心可使用profiles标签来定义不同环境的docker.image.prefix</p></blockquote><h3 id="开始构建镜像"><a href="#开始构建镜像" class="headerlink" title="开始构建镜像"></a>开始构建镜像</h3><p>前提是要先安装好docker服务</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">mvn clean package -Dmaven.test.skip=true -U</span><br></pre></td></tr></table></figure><h2 id="使用Google-Jib插件构建"><a href="#使用Google-Jib插件构建" class="headerlink" title="使用Google Jib插件构建"></a>使用Google Jib插件构建</h2><p>项目地址：<a href="https://github.com/GoogleContainerTools/jib" target="_blank" rel="noopener">https://github.com/GoogleContainerTools/jib</a></p><p>Google Jib的优势是无需事先安装docker，无需定义Dockerfile文件，而且Google Jib可以分层,依赖的jar构成一层，resource构成一层，然后项目本身的classes构建一层。这样如果只是改变项目本身代码，那么构建是非常快的。且推送的镜像也是非常小的，可以大大节省网络流量。</p><h3 id="在pom-xml中配置maven插件-1"><a href="#在pom-xml中配置maven插件-1" class="headerlink" title="在pom.xml中配置maven插件"></a>在pom.xml中配置maven插件</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>maven-compiler-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">version</span>&gt;</span>3.8.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">source</span>&gt;</span>$&#123;java.version&#125;<span class="tag">&lt;/<span class="name">source</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">target</span>&gt;</span>$&#123;java.version&#125;<span class="tag">&lt;/<span class="name">target</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">encoding</span>&gt;</span>$&#123;project.build.sourceEncoding&#125;<span class="tag">&lt;/<span class="name">encoding</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">annotationProcessorPaths</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">path</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;lombok.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">path</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">path</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mapstruct<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mapstruct-processor<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;mapstruct.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">path</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- other annotation processors --&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">annotationProcessorPaths</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">compilerArgs</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">compilerArg</span>&gt;</span>-Amapstruct.defaultComponentModel=default<span class="tag">&lt;/<span class="name">compilerArg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">compilerArg</span>&gt;</span>-Amapstruct.unmappedTargetPolicy=WARN<span class="tag">&lt;/<span class="name">compilerArg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">compilerArgs</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.google.cloud.tools<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jib-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">version</span>&gt;</span>1.7.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">from</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">image</span>&gt;</span>harbor.chaomeifan.com/library/openjdk:8-jdk-alpine-v1<span class="tag">&lt;/<span class="name">image</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">from</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">allowInsecureRegistries</span>&gt;</span>true<span class="tag">&lt;/<span class="name">allowInsecureRegistries</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">to</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">image</span>&gt;</span>$&#123;docker.image.prefix&#125;/$&#123;project.artifactId&#125;<span class="tag">&lt;/<span class="name">image</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tags</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tag</span>&gt;</span>$&#123;project.version&#125;<span class="tag">&lt;/<span class="name">tag</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tag</span>&gt;</span>latest<span class="tag">&lt;/<span class="name">tag</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">tags</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">to</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">container</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">creationTime</span>&gt;</span>USE_CURRENT_TIMESTAMP<span class="tag">&lt;/<span class="name">creationTime</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">environment</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">PINPOINT_VERSION</span>&gt;</span>1.8.4<span class="tag">&lt;/<span class="name">PINPOINT_VERSION</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">PINPOINT_OPTS</span>&gt;</span>-Dpinpoint.agentId=$&#123;project.artifactId&#125; -Dpinpoint.applicationName=$&#123;project.artifactId&#125;<span class="tag">&lt;/<span class="name">PINPOINT_OPTS</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">NACOS_OPTS</span>&gt;</span>-Dregistry.nacos.namespace=bbae7e8e-29cb-48e3-8c36-c8a9759975a9<span class="tag">&lt;/<span class="name">NACOS_OPTS</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">environment</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">user</span>&gt;</span>zcckj:zcckj<span class="tag">&lt;/<span class="name">user</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">entrypoint</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">arg</span>&gt;</span>/sbin/tini<span class="tag">&lt;/<span class="name">arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">arg</span>&gt;</span>--<span class="tag">&lt;/<span class="name">arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">arg</span>&gt;</span>/bin/sh<span class="tag">&lt;/<span class="name">arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">arg</span>&gt;</span>-c<span class="tag">&lt;/<span class="name">arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">arg</span>&gt;</span>java $&#123;JAVA_OPTS&#125; -javaagent:/pinpoint_data/pinpoint-agent-$&#123;PINPOINT_VERSION&#125;/pinpoint-bootstrap-$PINPOINT_VERSION.jar $PINPOINT_OPTS $NACOS_OPTS -Djava.security.egd=file:/dev/./urandom -cp /app/resources/:/app/classes/:/app/libs/* com.zcckj.jingtian.biz.server.JingtianBizApplication<span class="tag">&lt;/<span class="name">arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">entrypoint</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">container</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">executions</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">phase</span>&gt;</span>package<span class="tag">&lt;/<span class="name">phase</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goals</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goal</span>&gt;</span>build<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">executions</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li><p>lombok.version为1.18.8</p></li><li><p>mapstruct.version为1.3.0.Final</p></li></ul><blockquote><blockquote><p>如果您的项目没有用到Pinpoint,Nacos可以完全精简为如下</p></blockquote></blockquote><figure class="highlight xml"><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></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">plugin</span>&gt;</span>编译插件省略(同上)...<span class="tag">&lt;/<span class="name">plugin</span>&gt;</span> </span><br><span class="line"> <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.google.cloud.tools<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jib-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">version</span>&gt;</span>1.7.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">from</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">image</span>&gt;</span>harbor.chaomeifan.com/library/openjdk:8-jdk-alpine-v1<span class="tag">&lt;/<span class="name">image</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">from</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">allowInsecureRegistries</span>&gt;</span>true<span class="tag">&lt;/<span class="name">allowInsecureRegistries</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">to</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">image</span>&gt;</span>$&#123;docker.image.prefix&#125;/$&#123;project.artifactId&#125;<span class="tag">&lt;/<span class="name">image</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tags</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tag</span>&gt;</span>$&#123;project.version&#125;<span class="tag">&lt;/<span class="name">tag</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tag</span>&gt;</span>latest<span class="tag">&lt;/<span class="name">tag</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">tags</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">to</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">container</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">creationTime</span>&gt;</span>USE_CURRENT_TIMESTAMP<span class="tag">&lt;/<span class="name">creationTime</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">user</span>&gt;</span>zcckj:zcckj<span class="tag">&lt;/<span class="name">user</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">entrypoint</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">arg</span>&gt;</span>/sbin/tini<span class="tag">&lt;/<span class="name">arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">arg</span>&gt;</span>--<span class="tag">&lt;/<span class="name">arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">arg</span>&gt;</span>/bin/sh<span class="tag">&lt;/<span class="name">arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">arg</span>&gt;</span>-c<span class="tag">&lt;/<span class="name">arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">arg</span>&gt;</span>java -cp /app/resources/:/app/classes/:/app/libs/* com.zcckj.jingtian.biz.server.JingtianBizApplication<span class="tag">&lt;/<span class="name">arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">entrypoint</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">container</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">executions</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">phase</span>&gt;</span>package<span class="tag">&lt;/<span class="name">phase</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goals</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">goal</span>&gt;</span>build<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">executions</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br></pre></td></tr></table></figure><blockquote><p>这里我们构建了一个基镜像harbor.chaomeifan.com/library/openjdk:8-jdk-alpine-v1，以下给出基镜像的Dockerfile</p></blockquote><figure class="highlight dockerfile"><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="keyword">FROM</span> openjdk:<span class="number">8</span>-jdk-alpine</span><br><span class="line"><span class="keyword">MAINTAINER</span> zhangjie &lt;jaychang1987@gmail.com&gt;</span><br><span class="line"></span><br><span class="line"><span class="keyword">ARG</span> <span class="keyword">user</span>=zcckj</span><br><span class="line"><span class="keyword">ARG</span> group=zcckj</span><br><span class="line"><span class="keyword">ARG</span> uid=<span class="number">1739</span></span><br><span class="line"><span class="keyword">ARG</span> gid=<span class="number">1739</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">ENV</span> JAVA_OPTS=<span class="string">"-Xmx1024M -Xms1024M -Xmn192M -XX:MaxMetaspaceSize=256M -XX:MetaspaceSize=256M -XX:+UseParallelGC -XX:+UseAdaptiveSizePolicy -XX:MaxGCPauseMillis=100 -XX:ErrorFile=/tmp/hs_err_pid%p.log   -Xloggc:/tmp/gc.log -XX:HeapDumpPath=/tmp -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+HeapDumpOnOutOfMemoryError"</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Configure aliyun alpine software source and timezone</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> <span class="built_in">set</span> -x \</span></span><br><span class="line"><span class="bash">    &amp;&amp; sed -i <span class="string">"s/http:\/\/dl-cdn.alpinelinux.org/https:\/\/mirrors.aliyun.com/g"</span> /etc/apk/repositories \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk update \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk --no-cache add bash bash-completion bash-doc \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk --no-cache add tzdata curl tini \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk --no-cahce add font-adobe-100dpi ttf-dejavu fontconfig \</span></span><br><span class="line"><span class="bash">    &amp;&amp; cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \</span></span><br><span class="line"><span class="bash">    &amp;&amp; <span class="built_in">echo</span> <span class="string">"Asia/Shanghai"</span> &gt;  /etc/timezone \</span></span><br><span class="line"><span class="bash">    &amp;&amp; rm -rf /var/cache/apk/* \</span></span><br><span class="line"><span class="bash">    &amp;&amp; addgroup --gid <span class="variable">$&#123;gid&#125;</span> <span class="variable">$&#123;group&#125;</span> \</span></span><br><span class="line"><span class="bash">    &amp;&amp; adduser --uid <span class="variable">$&#123;uid&#125;</span> -G <span class="variable">$&#123;group&#125;</span> <span class="variable">$&#123;user&#125;</span> -s /bin/bash -D</span></span><br></pre></td></tr></table></figure><blockquote><blockquote><p>由于基镜像用了非root用户启动进程，故如果有映射到容器的目录需要将目录所有者所属组改为Dockerfile中定义的用户id,组id，chown -R 1739:1739 /path/directory</p><p>如果觉得嫌麻烦，可以在基镜像中直接用root</p></blockquote></blockquote><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> openjdk:<span class="number">8</span>-jdk-alpine</span><br><span class="line"><span class="keyword">MAINTAINER</span> zhangjie &lt;jaychang1987@gmail.com&gt;</span><br><span class="line"></span><br><span class="line"><span class="keyword">ENV</span> JAVA_OPTS=<span class="string">"-Xmx1024M -Xms1024M -Xmn192M -XX:MaxMetaspaceSize=256M -XX:MetaspaceSize=256M -XX:+UseParallelGC -XX:+UseAdaptiveSizePolicy -XX:MaxGCPauseMillis=100 -XX:ErrorFile=/tmp/hs_err_pid%p.log   -Xloggc:/tmp/gc.log -XX:HeapDumpPath=/tmp -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+HeapDumpOnOutOfMemoryError"</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Configure aliyun alpine software source and timezone</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> <span class="built_in">set</span> -x \</span></span><br><span class="line"><span class="bash">    &amp;&amp; sed -i <span class="string">"s/http:\/\/dl-cdn.alpinelinux.org/https:\/\/mirrors.aliyun.com/g"</span> /etc/apk/repositories \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk update \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk --no-cache add bash bash-completion bash-doc \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk --no-cache add tzdata curl tini \</span></span><br><span class="line"><span class="bash">    &amp;&amp; apk --no-cahce add font-adobe-100dpi ttf-dejavu fontconfig \</span></span><br><span class="line"><span class="bash">    &amp;&amp; cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \</span></span><br><span class="line"><span class="bash">    &amp;&amp; <span class="built_in">echo</span> <span class="string">"Asia/Shanghai"</span> &gt;  /etc/timezone \</span></span><br><span class="line"><span class="bash">    &amp;&amp; rm -rf /var/cache/apk/*</span></span><br></pre></td></tr></table></figure><blockquote><blockquote><p>这样就无需在jib插件配置中设置<user>zcckj:zcckj</user></p></blockquote></blockquote><h3 id="开始构建镜像-1"><a href="#开始构建镜像-1" class="headerlink" title="开始构建镜像"></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">mvn clean compile jib:build -Dmaven.test.skip=true -DsendCredentialsOverHttp=true -U</span><br></pre></td></tr></table></figure><h2 id="手工构建"><a href="#手工构建" class="headerlink" title="手工构建"></a>手工构建</h2>]]></content>
    
    <summary type="html">
    
      
      
        &lt;hr&gt;
&lt;p&gt;title: 如何构建SpringBoot应用的Docker镜像&lt;br&gt;date: 2019-12-04 22:17:54&lt;br&gt;categories: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SpringBoot&lt;br&gt;tags:&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;

      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Ubuntu Linux下安装MySQL5.7</title>
    <link href="http://jaychang.cn/2019/07/27/buntu18-04%E5%AE%89%E8%A3%85MySQL5-7/"/>
    <id>http://jaychang.cn/2019/07/27/buntu18-04安装MySQL5-7/</id>
    <published>2019-07-27T14:40:34.000Z</published>
    <updated>2020-04-12T15:27:47.375Z</updated>
    
    <content type="html"><![CDATA[<p>MySQL通用Linux二进制安装包用于在Linux系统上安装MySQL。可以根据我们的需求，定制安装MySQL,比如可以设置数据存储目录，日志存储目录等。</p><h1 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h1><p>如果系统之前安装过mysql，版本可能是比较旧的，需要在安装之前确认下。可以使用如apt,yum包管理工具，将mysql卸载。并注意/etc/my.cnf，mysql数据存放目录，将数据备份好，然后再删除这些文件或目录。</p><p>mysql需要依赖libaio库，在安装mysql前确认已经安装好libaio库</p><ul><li><p>centos:</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 search libaio  # search for info</span><br><span class="line">yum install libaio # install library</span><br></pre></td></tr></table></figure></li><li><p>ubuntu:</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">apt-cache search libaio # search for info</span><br><span class="line">apt-get install libaio1 # install library</span><br></pre></td></tr></table></figure></li></ul><h1 id="下载MySQL二进制安装包"><a href="#下载MySQL二进制安装包" class="headerlink" title="下载MySQL二进制安装包"></a>下载MySQL二进制安装包</h1><p>下载64位mysql5.7.27 linux通用二进制安装包<br><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">wget --no-check-certificate https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.27-linux-glibc2.12-x86_64.tar.gz</span><br></pre></td></tr></table></figure></p><p>二进制安装包清单</p><table><thead><tr><th>目录</th><th>目录中的文件</th></tr></thead><tbody><tr><td>bin</td><td>mysqld服务端程序,mysql客户端程序，等其他工具程序</td></tr><tr><td>docs</td><td>mysql文档</td></tr><tr><td>man</td><td>man手册</td></tr><tr><td>include</td><td>header头文件</td></tr><tr><td>share</td><td>用于数据库安装的错误消息、字典和SQ</td></tr><tr><td>support-files</td><td>各种支持文件</td></tr></tbody></table><h1 id="创建用户组、用户"><a href="#创建用户组、用户" class="headerlink" title="创建用户组、用户"></a>创建用户组、用户</h1><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">groupadd mysql</span><br><span class="line">useradd -r -g mysql -s /bin/false mysql</span><br></pre></td></tr></table></figure><blockquote><p>此用户仅仅用于mysql服务，而不用于系统登录，所以使用useradd -r和-s /bin/false命令选项来创建没有登录权限的用户。</p></blockquote><h1 id="解压MySQL安装包"><a href="#解压MySQL安装包" class="headerlink" title="解压MySQL安装包"></a>解压MySQL安装包</h1><p>解压mysql安装包到/user/local目录下，并设置软连接，使得mysql的basedir为/usr/local/mysql<br><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">tar zxvf /path/to/mysql-5.7.27-linux-glibc2.12-x86_64.tar.gz -C /usr/local</span><br><span class="line">cd /usr/local</span><br><span class="line">ln -s mysql-5.7.26-linux-glibc2.12-x86_64 mysql</span><br></pre></td></tr></table></figure></p><blockquote><p>/path/to改为mysql安装包所在目录</p></blockquote><p>将bin目录添加到PATH环境变量中</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">export PATH=$PATH:/usr/local/mysql/bin</span><br><span class="line">echo "export PATH=$PATH:/usr/local/mysql/bin" &gt;&gt; ~/.bashrc</span><br><span class="line">echo "export PATH=$PATH:/usr/local/mysql/bin" &gt;&gt; /etc/profile</span><br><span class="line">source /etc/profile</span><br></pre></td></tr></table></figure><h1 id="mysql目录、文件规划"><a href="#mysql目录、文件规划" class="headerlink" title="mysql目录、文件规划"></a>mysql目录、文件规划</h1><table><thead><tr><th>名称</th><th>目录或文件</th><th>软链</th><th>实际目录</th></tr></thead><tbody><tr><td>数据目录datadir</td><td>/data/mysql/data</td><td>否</td><td></td></tr><tr><td>参数配置my.cnf</td><td>/usr/local/mysql/etc/my.cnf</td><td>否</td><td></td></tr><tr><td>日志log目录</td><td>/usr/local/mysql/log</td><td>是</td><td>/data/mysql/log</td></tr><tr><td>错误日志log-error</td><td>/usr/local/mysql/log/mysql_error.log</td><td>否</td><td></td></tr><tr><td>慢查询日志slow_query_log_file</td><td>/usr/local/mysql/log/mysql_slow_query.log</td><td>否</td><td></td></tr><tr><td>二进制日志log-bin</td><td>/usr/local/mysql/binlogs/mysql-bin</td><td>是</td><td>/data/mysql/binlogs/mysql-bin</td></tr><tr><td>套接字socket文件</td><td>/usr/local/mysql/run/mysql.sock</td><td>否</td><td></td></tr><tr><td>pid文件(进程id)</td><td>/usr/local/mysql/run/mysql.pid</td><td>否</td></tr></tbody></table><blockquote><p>默认情况下socket文件， pid文件是存在datadir的，建议还是分开一个目录，取名run目录好一点</p></blockquote><h1 id="创建所需目录并设置权限"><a href="#创建所需目录并设置权限" class="headerlink" title="创建所需目录并设置权限"></a>创建所需目录并设置权限</h1><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">mkdir -p /usr/local/mysql/&#123;etc,run&#125;</span><br><span class="line">mkdir -p /data/mysql/&#123;data,binlogs,log&#125;</span><br><span class="line">chown -R mysql.mysql /data/mysql</span><br><span class="line">chown -R mysql.mysql /usr/local/mysql/&#123;etc,run&#125;</span><br></pre></td></tr></table></figure><h2 id="配置my-cnf"><a href="#配置my-cnf" class="headerlink" title="配置my.cnf"></a>配置my.cnf</h2><p>文件放在/usr/local/mysql/etc/my.cnf，放此目录，会自动加载该配置文件的<br><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><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">[client]</span><br><span class="line">port = 3306</span><br><span class="line">socket = /usr/local/mysql/run/mysql.sock</span><br><span class="line"></span><br><span class="line">[mysqld]</span><br><span class="line"></span><br><span class="line">##########################</span><br><span class="line">#GENERAL</span><br><span class="line">##########################</span><br><span class="line">user = mysql</span><br><span class="line">port = 3306</span><br><span class="line">server_id = 1</span><br><span class="line">skip-name-resolve</span><br><span class="line">bind-address= 0.0.0.0</span><br><span class="line">default_storage_engine = InnoDB</span><br><span class="line">socket = /usr/local/mysql/run/mysql.sock</span><br><span class="line">pid-file = /usr/local/mysql/run/mysqld.pid</span><br><span class="line">max_allowed_packet=32M</span><br><span class="line">max_connections = 1024</span><br><span class="line">open_files_limit = 65535</span><br><span class="line">#default-time-zone=&apos;+08:00&apos;</span><br><span class="line">explicit_defaults_for_timestamp=true</span><br><span class="line"></span><br><span class="line">##########################</span><br><span class="line"># character set</span><br><span class="line">##########################</span><br><span class="line">character_set_server = utf8mb4</span><br><span class="line">collation-server = utf8mb4_general_ci</span><br><span class="line">init_connect=&apos;SET NAMES utf8mb4&apos;</span><br><span class="line"></span><br><span class="line">##########################</span><br><span class="line"># DATA STORAGE </span><br><span class="line">##########################</span><br><span class="line">basedir= /usr/local/mysql</span><br><span class="line">datadir = /data/mysql/data</span><br><span class="line"></span><br><span class="line">##########################</span><br><span class="line"># INNODB</span><br><span class="line">##########################</span><br><span class="line">innodb_file_per_table = 1</span><br><span class="line">innodb_buffer_pool_size = 512M</span><br><span class="line">innodb_log_buffer_size = 16M</span><br><span class="line">innodb_log_file_size = 128M</span><br><span class="line">innodb_tmpdir= /data/mysql/tmp</span><br><span class="line"></span><br><span class="line">##########################</span><br><span class="line"># MyISAM</span><br><span class="line">##########################</span><br><span class="line">key_buffer_size = 64M</span><br><span class="line"></span><br><span class="line">##########################</span><br><span class="line"># Logging</span><br><span class="line">##########################</span><br><span class="line"># mysql log timezone use system timezone</span><br><span class="line">log_timestamps=SYSTEM</span><br><span class="line">log_error = /data/mysql/log/mysql_error.log</span><br><span class="line"></span><br><span class="line">##########################</span><br><span class="line"># log bin</span><br><span class="line">##########################</span><br><span class="line">log-bin = /data/mysql/binlogs/mysql-bin</span><br><span class="line">sync-binlog = 1</span><br><span class="line">binlog_format = row</span><br><span class="line">binlog_row_image = FULL</span><br><span class="line">expire_logs_days = 15</span><br><span class="line">master_info_repository = TABLE</span><br><span class="line">relay_log_info_repository = TABLE</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">##########################</span><br><span class="line"># log relay</span><br><span class="line">##########################</span><br><span class="line">relay-log = /data/mysql/binlogs/relay-bin</span><br><span class="line">relay_log_recovery = on</span><br><span class="line">max_relay_log_size = 1G</span><br><span class="line">log_slave_updates = 1</span><br><span class="line"></span><br><span class="line">##########################</span><br><span class="line"># gtid</span><br><span class="line">##########################</span><br><span class="line">gtid_mode = on</span><br><span class="line">enforce_gtid_consistency = on</span><br><span class="line">replicate_ignore_db=mysql</span><br><span class="line">replicate_ignore_db=information_schema</span><br><span class="line">replicate_ignore_db=performation_schema</span><br><span class="line">replicate_ignore_db=sys</span><br><span class="line"></span><br><span class="line">##########################</span><br><span class="line"># General logs (only enable for debugging – it use too much I/O)</span><br><span class="line">##########################</span><br><span class="line">#general-log = on</span><br><span class="line">#general-log-file = /data/mysql/log/general-query.log</span><br><span class="line"></span><br><span class="line">##########################</span><br><span class="line"># Slow query logs (optional)</span><br><span class="line">##########################</span><br><span class="line">slow_query_log = on</span><br><span class="line">long_query_time= 3</span><br><span class="line">slow_query_log_file = /data/mysql/log/slow-query.log</span><br></pre></td></tr></table></figure></p><h2 id="初始化mysql-server"><a href="#初始化mysql-server" class="headerlink" title="初始化mysql server"></a>初始化mysql server</h2><p>查看初始化参数<br><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">mysqld --verbose --help |more</span><br></pre></td></tr></table></figure></p><ul><li>初始化数据库<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">cd /user/local/mysql</span><br><span class="line">mkdir mysql-files</span><br><span class="line">chown mysql:mysql mysql-files</span><br><span class="line">chmod 750 mysql-files</span><br><span class="line">bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql/data</span><br></pre></td></tr></table></figure></li></ul><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">grep 'temporary password' /data/mysql/log/mysql_error.log</span><br></pre></td></tr></table></figure><p><img src="\images\pasted-34.png" alt="upload successful"></p><ul><li>生成ssl</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">mysql_ssl_rsa_setup --basedir=/usr/local/mysql --datadir=/data/mysql/data</span><br></pre></td></tr></table></figure><h2 id="启动mysql服务"><a href="#启动mysql服务" class="headerlink" title="启动mysql服务"></a>启动mysql服务</h2><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">mysqld_safe --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql/data --defaults-file=/usr/local/mysql/etc/my.cnf &amp;</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">mysqld_safe --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql/data &amp;</span><br></pre></td></tr></table></figure><blockquote><p>可以不用指定–defaults-file，会加载到$MYSQL_HOME/etc/my.cnf这个配置文件</p></blockquote><h2 id="修改密码"><a href="#修改密码" class="headerlink" title="修改密码"></a>修改密码</h2><p>mysql -uroot -p<br>输入上一步查到的临时密码</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">set password=password('123456');</span><br><span class="line">grant all privileges on *.* to root@'%' identified by '123456' with grant option;</span><br><span class="line">flush privileges;</span><br></pre></td></tr></table></figure><h1 id="mysql作为系统服务"><a href="#mysql作为系统服务" class="headerlink" title="mysql作为系统服务"></a>mysql作为系统服务</h1><h2 id="非systemctrl管理（不推荐）"><a href="#非systemctrl管理（不推荐）" class="headerlink" title="非systemctrl管理（不推荐）"></a>非systemctrl管理（不推荐）</h2><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><span class="bash">Next <span class="built_in">command</span> is optional</span></span><br><span class="line">cp support-files/mysql.server /etc/init.d/mysqld</span><br></pre></td></tr></table></figure><p>修改/etc/init.d/mysqld的basedir,datadir等配置<br>chomod 755 /etc/init.d/mysqld</p><p>下面介绍使用 systemctrl来管理mysql服务</p><h2 id="systemctl管理（强烈推荐）"><a href="#systemctl管理（强烈推荐）" class="headerlink" title="systemctl管理（强烈推荐）"></a>systemctl管理（强烈推荐）</h2><p>创建 /etc/systemd/system/mysqld.service<br><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></pre></td><td class="code"><pre><span class="line">[Unit]</span><br><span class="line">Description=MySQL Server</span><br><span class="line">Documentation=man:mysqld(5.7)</span><br><span class="line">Documentation=https://dev.mysql.com/doc/refman/5.7/en/using-systemd.html</span><br><span class="line">After=network.target</span><br><span class="line">After=syslog.target</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">User=mysql</span><br><span class="line">Group=mysql</span><br><span class="line">#PIDFile=/usr/local/mysql/run/mysqld.pid</span><br><span class="line">#ExecStart=</span><br><span class="line">ExecStart=/usr/local/mysql/bin/mysqld_safe --defaults-file=/usr/local/mysql/etc/my.cnf</span><br><span class="line">LimitNOFILE=65535</span><br></pre></td></tr></table></figure></p><p>设置开机启动<br><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 daemon-reload</span><br><span class="line">systemctl enable mysqld</span><br></pre></td></tr></table></figure></p><p>启动、停止、查看日志<br><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">systemctrl start mysqld</span><br><span class="line">systemctrl stop mysqld</span><br><span class="line">journalctl -u mysqld</span><br></pre></td></tr></table></figure></p><h1 id="附录"><a href="#附录" class="headerlink" title="附录"></a>附录</h1><p>单机多实例的安装配置见<a href="https://www.jb51.net/article/103843.htm，需要注意版本差异" target="_blank" rel="noopener">https://www.jb51.net/article/103843.htm，需要注意版本差异</a></p><h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><p><a href="https://lalitvc.wordpress.com/2019/03/04/mysql-5-7-binary-install-on-linux/" target="_blank" rel="noopener">https://lalitvc.wordpress.com/2019/03/04/mysql-5-7-binary-install-on-linux/</a><br><a href="https://dev.mysql.com/doc/refman/5.7/en/binary-installation.html" target="_blank" rel="noopener">https://dev.mysql.com/doc/refman/5.7/en/binary-installation.html</a><br><a href="https://dev.mysql.com/doc/refman/5.7/en/postinstallation.html" target="_blank" rel="noopener">https://dev.mysql.com/doc/refman/5.7/en/postinstallation.html</a><br><a href="https://dev.mysql.com/doc/refman/5.7/en/using-systemd.html#systemd-mysql-configuration" target="_blank" rel="noopener">https://dev.mysql.com/doc/refman/5.7/en/using-systemd.html#systemd-mysql-configuration</a><br><a href="https://dev.mysql.com/doc/refman/5.7/en/mysqld-safe.html#option_mysqld_safe_malloc-lib" target="_blank" rel="noopener">https://dev.mysql.com/doc/refman/5.7/en/mysqld-safe.html#option_mysqld_safe_malloc-lib</a><br><a href="https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html" target="_blank" rel="noopener">https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html</a><br><a href="https://blog.csdn.net/zml3721/article/details/79090983" target="_blank" rel="noopener">https://blog.csdn.net/zml3721/article/details/79090983</a><br><a href="https://www.jianshu.com/p/0d628b2f7476" target="_blank" rel="noopener">https://www.jianshu.com/p/0d628b2f7476</a><br><a href="https://www.jb51.net/article/103843.htm" target="_blank" rel="noopener">https://www.jb51.net/article/103843.htm</a><br><a href="https://blog.pythian.com/manage-multiple-mysql-binary-installations-with-systemd/" target="_blank" rel="noopener">https://blog.pythian.com/manage-multiple-mysql-binary-installations-with-systemd/</a><br><a href="https://www.linuxidc.com/Linux/2017-10/147829.htm" target="_blank" rel="noopener">https://www.linuxidc.com/Linux/2017-10/147829.htm</a><br><a href="https://blog.csdn.net/l1028386804/article/details/87996449" target="_blank" rel="noopener">https://blog.csdn.net/l1028386804/article/details/87996449</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;MySQL通用Linux二进制安装包用于在Linux系统上安装MySQL。可以根据我们的需求，定制安装MySQL,比如可以设置数据存储目录，日志存储目录等。&lt;/p&gt;
&lt;h1 id=&quot;准备&quot;&gt;&lt;a href=&quot;#准备&quot; class=&quot;headerlink&quot; title=&quot;准备
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Ubuntu18.04 Nginx+Lua+GraphicsMagick图片缩放</title>
    <link href="http://jaychang.cn/2019/07/07/buntu18-04-Nginx-Lua-GraphicsMagick%E5%9B%BE%E7%89%87%E7%BC%A9%E6%94%BE/"/>
    <id>http://jaychang.cn/2019/07/07/buntu18-04-Nginx-Lua-GraphicsMagick图片缩放/</id>
    <published>2019-07-07T13:18:00.000Z</published>
    <updated>2019-07-14T12:53:33.548Z</updated>
    
    <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>自己搭建的图片服务器，有图片缩放的需求，大致思路是可以使用nginx调用lua，使用GraphicMagick的命令来做图片缩放</p><h1 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h1><h2 id="文件夹规划"><a href="#文件夹规划" class="headerlink" title="文件夹规划"></a>文件夹规划</h2><p>lua.jaychang.cn(如/var/filebase)</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></pre></td><td class="code"><pre><span class="line">jaychang@nginx:~$ tree /var/filebase/</span><br><span class="line">/var/filebase/</span><br><span class="line">├── avatar.png</span><br><span class="line">├── cache</span><br><span class="line">│   └── thumb</span><br><span class="line">│       ├── avatar.png_100x100.png</span><br><span class="line">│       └── upload</span><br><span class="line">│           ├── 1.png_100x100.png #固定高和宽</span><br><span class="line">│           ├── 1.png_400-.png # 定高</span><br><span class="line">│           └── 1.png_800-.png # 定宽</span><br><span class="line">└── upload</span><br><span class="line">    ├── 1.png</span><br><span class="line">4 directories, 8 files</span><br></pre></td></tr></table></figure><p>其中img.xyz.com为图片站点根目录<br>cache/thumb为缩略图存放目录<br>upload目录存放上传的图片</p><h2 id="链接地址对应关系"><a href="#链接地址对应关系" class="headerlink" title="链接地址对应关系"></a>链接地址对应关系</h2><p>原图访问地址：<a href="http://img.xyz.com/upload/1.png" target="_blank" rel="noopener">http://img.xyz.com/upload/1.png</a><br>缩略图访问地址：<a href="http://img.xyz.com/upload/1.png_100x100.png" target="_blank" rel="noopener">http://img.xyz.com/upload/1.png_100x100.png</a> 即为宽100,高100<br>自动宽地址: <a href="http://img.xyz.com/upload/1.png_-400.png" target="_blank" rel="noopener">http://img.xyz.com/upload/1.png_-400.png</a> 用”-“表示自动,即为高400,宽自动<br>自动高地址: <a href="http://img.xyz.com/upload/1.png_800-.jpg" target="_blank" rel="noopener">http://img.xyz.com/upload/1.png_800-.jpg</a> 用”-“表示自动,即为宽800,高自动</p><h2 id="访问流程"><a href="#访问流程" class="headerlink" title="访问流程"></a>访问流程</h2><p>首先判断缩略图是否存在，如存在则直接显示缩略图；<br>缩略图不存在,则判断原图是否存在，如原图存在则拼接graphicsmagick(gm)命令,生成并显示缩略图,否则返回404</p><h1 id="所需软件"><a href="#所需软件" class="headerlink" title="所需软件"></a>所需软件</h1><ul><li>lua-5.3.5.tar.gz</li><li>LuaJIT-2.0.5.tar.gz</li><li>nginx-1.14.2.tar.gz</li><li>nginx模块：lua-nginx-module-0.10.15.tar.gz<blockquote><p>lua-nginx-module 依赖于 LuaJIT 和 ngx_devel_kit。LuaJIT 需要安装，ngx_devel_kit 只需下载源码包，在 Nginx 编译时指定 ngx_devel_kit 目录</p></blockquote></li><li>nginx模块：nginx-http-concat</li><li>nginx模块：ngx_devel_kit</li><li>nginx模块：nginx-http-concat</li></ul><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">curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz</span><br><span class="line">curl -R -O http://luajit.org/download/LuaJIT-2.0.5.tar.gz</span><br><span class="line">curl -R -O http://nginx.org/download/nginx-1.14.2.tar.gz</span><br><span class="line">curl -R -O https://github.com/openresty/lua-nginx-module/archive/v0.10.15.tar.gz</span><br><span class="line">curl -R -O https://github.com/openresty/lua-resty-core/archive/v0.1.17.tar.gz</span><br><span class="line">curl -R -O https://github.com/simpl/ngx_devel_kit/archive/v0.3.0.tar.gz</span><br><span class="line">git clone git@github.com:alibaba/nginx-http-concat.git</span><br></pre></td></tr></table></figure><h1 id="安装依赖"><a href="#安装依赖" class="headerlink" title="安装依赖"></a>安装依赖</h1><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">apt-get install -y gcc g++ make</span><br><span class="line"></span><br><span class="line">apt-get install libreadline-dev libpcre3 libpcre3-dev openssl libssl-dev zlib1g zlib1g-dev libgeoip-dev -y</span><br></pre></td></tr></table></figure><h1 id="编译安装Lua-LuaJIT"><a href="#编译安装Lua-LuaJIT" class="headerlink" title="编译安装Lua LuaJIT"></a>编译安装Lua LuaJIT</h1><h2 id="编译安装Lua"><a href="#编译安装Lua" class="headerlink" title="编译安装Lua"></a>编译安装Lua</h2><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></pre></td><td class="code"><pre><span class="line">curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz</span><br><span class="line">tar zxf lua-5.3.5.tar.gz</span><br><span class="line">cd lua-5.3.5</span><br><span class="line">make linux test</span><br></pre></td></tr></table></figure><h2 id="编译安装LuaJIT"><a href="#编译安装LuaJIT" class="headerlink" title="编译安装LuaJIT"></a>编译安装LuaJIT</h2><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">curl -R -O http://luajit.org/download/LuaJIT-2.0.5.tar.gz</span><br><span class="line">tar -zxvf LuaJIT-2.0.5.tar.gz</span><br><span class="line">cd LuaJIT-2.0.5</span><br><span class="line">make -j2 &amp;&amp; make install</span><br><span class="line">export LUAJIT_LIB=/usr/local/lib</span><br><span class="line">export LUAJIT_INC=/usr/local/include/luajit-2.0</span><br><span class="line">echo &quot;/usr/local/lib&quot; &gt; /etc/ld.so.conf.d/usr_local_lib.conf</span><br><span class="line">ldconfig</span><br></pre></td></tr></table></figure><h1 id="安装GraphicsMagick"><a href="#安装GraphicsMagick" class="headerlink" title="安装GraphicsMagick"></a>安装GraphicsMagick</h1><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">apt install -y graphicsmagick</span><br></pre></td></tr></table></figure><blockquote><p>直接用apt来安装的话，可以免去安装 jpg,png 等图片库依赖</p></blockquote><h1 id="创建用户及相应目录"><a href="#创建用户及相应目录" class="headerlink" title="创建用户及相应目录"></a>创建用户及相应目录</h1><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></pre></td><td class="code"><pre><span class="line">groupadd nginx &amp;&amp; useradd nginx -g nginx -s /sbin/nologin -M</span><br><span class="line"></span><br><span class="line">mkdir -p /var/tmp/nginx/client_body_temp</span><br><span class="line">mkdir -p /var/tmp/nginx/uwsgi_temp</span><br></pre></td></tr></table></figure><p>创建用户也可以用以下命令：<br><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">groupadd nginx &amp;&amp; useradd nginx -g nginx -s /bin/false -M</span><br></pre></td></tr></table></figure></p><h1 id="编译安装nginx"><a href="#编译安装nginx" class="headerlink" title="编译安装nginx"></a>编译安装nginx</h1><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></pre></td><td class="code"><pre><span class="line">./configure --prefix=/usr/local/nginx \</span><br><span class="line">--user=nginx --group=nginx \</span><br><span class="line">--sbin-path=/usr/sbin/nginx \</span><br><span class="line">--with-pcre \</span><br><span class="line">--with-http_realip_module \</span><br><span class="line">--with-http_gzip_static_module \</span><br><span class="line">--with-http_stub_status_module \</span><br><span class="line">--with-http_v2_module \</span><br><span class="line">--with-http_flv_module \</span><br><span class="line">--with-http_ssl_module \</span><br><span class="line">--with-http_addition_module \</span><br><span class="line">--with-http_geoip_module \</span><br><span class="line">--add-module=/usr/local/src/lua-nginx-module-0.10.15 \</span><br><span class="line">--add-module=/usr/local/src/ngx_devel_kit-0.3.0 \</span><br><span class="line">--add-module=/usr/local/src/nginx-http-concat \</span><br><span class="line">--http-scgi-temp-path=/var/tmp/nginx/cgi_temp \</span><br><span class="line">--http-client-body-temp-path=/var/tmp/nginx/client_body_temp \</span><br><span class="line">--http-proxy-temp-path=/var/tmp/nginx/proxy_temp \</span><br><span class="line">--http-uwsgi-temp-path=/var/tmp/nginx/uwsgi_temp \</span><br><span class="line">--http-fastcgi-temp-path=/var/tmp/nginx/fastcgi_temp \</span><br><span class="line">--http-log-path=/var/log/nginx/access.log \</span><br><span class="line">--error-log-path=/var/log/nginx/error.log</span><br></pre></td></tr></table></figure><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">make -j 2 &amp;&amp; make install</span><br></pre></td></tr></table></figure><p> 注意：动态加载模块，Nginx官方的load_module指令,详细文档<a href="http://nginx.org/en/docs/ngx_core_module.html#load_module" target="_blank" rel="noopener">参考1</a><br>和 <a href="https://www.nginx.com/resources/wiki/extending/converting/#compiling-dynamic" target="_blank" rel="noopener">参考2</a><br>还有–with-http_spdy_module 已经改为–with-http_v2_module了<br>,如果不用geo的话，编译的时候可以不加–with-http_geoip_module，可以不安装libgeoip-dev</p><h1 id="测试nginx"><a href="#测试nginx" class="headerlink" title="测试nginx"></a>测试nginx</h1><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">nginx -t</span><br></pre></td></tr></table></figure><p>如果出现以下错误(没有报错就不用做以下操作了)<br><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">root@ubuntu:/usr/local/src/nginx-1.14.2# nginx -t</span><br><span class="line">nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory</span><br></pre></td></tr></table></figure></p><p>执行以下命令即可<br><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">echo &quot;/usr/local/lib&quot; &gt; /etc/ld.so.conf.d/usr_local_lib.conf</span><br><span class="line">ldconfig</span><br></pre></td></tr></table></figure></p><h1 id="修改nginx-conf配置文件"><a href="#修改nginx-conf配置文件" class="headerlink" title="修改nginx.conf配置文件"></a>修改nginx.conf配置文件</h1><p>将nginx.conf配置文件中的<strong>server{}段</strong>配置注释掉</p><p>加一行配置，以便读取/usr/local/tengine/conf.d目录下所有后缀为.conf的配置文件<br><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">include ../conf.d/*.conf;</span><br></pre></td></tr></table></figure></p><p>可以参考如下配置<br><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></pre></td><td class="code"><pre><span class="line">user nginx;</span><br><span class="line">worker_processes 4;</span><br><span class="line">worker_cpu_affinity 1000 0100 0010 0001;</span><br><span class="line">error_log /var/log/nginx/error.log error;</span><br><span class="line">pid /usr/local/nginx/logs/nginx.pid;</span><br><span class="line">worker_rlimit_nofile 65535;</span><br><span class="line">events</span><br><span class="line">&#123;</span><br><span class="line">use epoll;</span><br><span class="line">worker_connections 65535;</span><br><span class="line">&#125;</span><br><span class="line">http</span><br><span class="line">&#123;</span><br><span class="line">   lua_load_resty_core off;</span><br><span class="line">   limit_conn_zone $binary_remote_addr zone=one:10m;</span><br><span class="line">   limit_conn_zone $server_name zone=perserver:10m;</span><br><span class="line">include mime.types;</span><br><span class="line">include fastcgi.conf;</span><br><span class="line">default_type application/octet-stream;</span><br><span class="line">charset utf-8;</span><br><span class="line">server_names_hash_bucket_size 128;</span><br><span class="line">client_header_buffer_size 32k;</span><br><span class="line">large_client_header_buffers 4 64k;</span><br><span class="line">sendfile on;</span><br><span class="line">autoindex off;</span><br><span class="line">tcp_nopush on;</span><br><span class="line">tcp_nodelay on;</span><br><span class="line">keepalive_timeout 120;</span><br><span class="line">    </span><br><span class="line">fastcgi_connect_timeout 60;</span><br><span class="line">fastcgi_send_timeout 60;</span><br><span class="line">fastcgi_read_timeout 60;</span><br><span class="line">fastcgi_buffer_size 128k;</span><br><span class="line">fastcgi_buffers 8 128k;</span><br><span class="line">fastcgi_busy_buffers_size 128k;</span><br><span class="line">fastcgi_temp_file_write_size 128k;</span><br><span class="line">    </span><br><span class="line">gzip on;</span><br><span class="line">gzip_min_length 1k;</span><br><span class="line">gzip_buffers 4 16k;</span><br><span class="line">gzip_http_version 1.0;</span><br><span class="line">gzip_comp_level 2;</span><br><span class="line">gzip_types text/plain application/x-javascript text/css application/xml;</span><br><span class="line">gzip_vary on;</span><br><span class="line"></span><br><span class="line">log_format main &apos;$remote_addr - $remote_user [$time_local] &quot;$request&quot; &apos;</span><br><span class="line">&apos;$status $body_bytes_sent &quot;$http_referer&quot; &apos;</span><br><span class="line">&apos;&quot;$http_user_agent&quot; $http_x_forwarded_for&apos;;</span><br><span class="line"></span><br><span class="line">client_max_body_size 10m;</span><br><span class="line"></span><br><span class="line">include ../conf.d/*.conf;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><blockquote><p>注意：lua_load_resty_core off;如果不加会有以下错误</p></blockquote><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></pre></td><td class="code"><pre><span class="line">nginx: [alert] detected a LuaJIT version which is not OpenResty&apos;s; many optimizations will be disabled and performance will be compromised (see https://github.com/openresty/luajit2 for OpenResty&apos;s LuaJIT or, even better, consider using the OpenResty releases from https://openresty.org/en/download.html)</span><br><span class="line">nginx: [error] lua_load_resty_core failed to load the resty.core module from https://github.com/openresty/lua-resty-core; ensure you are using an OpenResty release from https://openresty.org/en/download.html (rc: 2, reason: module &apos;resty.core&apos; not found:</span><br><span class="line">        no field package.preload[&apos;resty.core&apos;]</span><br><span class="line">        no file &apos; /usr/local/lib/lua-resty-core-0.1.17/lib/resty/core.lua&apos;</span><br><span class="line">        no file &apos;./resty/core.lua&apos;</span><br><span class="line">        no file &apos;/usr/local/share/luajit-2.0.5/resty/core.lua&apos;</span><br><span class="line">        no file &apos;/usr/local/share/lua/5.1/resty/core.lua&apos;</span><br><span class="line">        no file &apos;/usr/local/share/lua/5.1/resty/core/init.lua&apos;</span><br><span class="line">        no file &apos;./resty/core.so&apos;</span><br><span class="line">        no file &apos;/usr/local/lib/lua/5.1/resty/core.so&apos;</span><br><span class="line">        no file &apos;/usr/local/lib/lua/5.1/loadall.so&apos;</span><br><span class="line">        no file &apos;./resty.so&apos;</span><br><span class="line">        no file &apos;/usr/local/lib/lua/5.1/resty.so&apos;</span><br><span class="line">        no file &apos;/usr/local/lib/lua/5.1/loadall.so&apos;)</span><br></pre></td></tr></table></figure><h1 id="创建放图片的目录"><a href="#创建放图片的目录" class="headerlink" title="创建放图片的目录"></a>创建放图片的目录</h1><p>目录规划</p><ul><li>/var/www 放网页,css,js等资源</li><li>/var/fielbase 放图片</li><li>/var/filebase/upload 上传的图片放这里</li></ul><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">mkdir -p /var/filebase/upload </span><br><span class="line">mkdir -p /var/filebase/cache/thumb</span><br><span class="line">chown -R nginx:nginx /var/filebase</span><br></pre></td></tr></table></figure><h1 id="配置站点配置文件"><a href="#配置站点配置文件" class="headerlink" title="配置站点配置文件"></a>配置站点配置文件</h1><p>在/usr/local/tengine/conf.d目录下创建demo.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><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br></pre></td><td class="code"><pre><span class="line"># 定义lua缩略图支持的图片尺寸及开关</span><br><span class="line">init_by_lua &apos;</span><br><span class="line">    image_sizes_check = true</span><br><span class="line">    image_sizes = &#123;&quot;800x800&quot;, &quot;400x400&quot;,&quot;200x200&quot;,&quot;100x100&quot;, &quot;-800&quot;, &quot;-400&quot;, &quot;-200&quot;,&quot;-100&quot;, &quot;800-&quot;, &quot;400-&quot;, &quot;200-&quot;,&quot;100-&quot;&#125;</span><br><span class="line">&apos;;</span><br><span class="line"></span><br><span class="line">server &#123;</span><br><span class="line">    listen   80;</span><br><span class="line">    servername img.xyz.com;</span><br><span class="line">    index index.php index.html index.htm;</span><br><span class="line"></span><br><span class="line">    set $root_path &apos;/var/www&apos;;</span><br><span class="line">    root $root_path;</span><br><span class="line"></span><br><span class="line">   # /lua仅用于测试，可去掉</span><br><span class="line"> location /lua &#123;</span><br><span class="line">default_type &apos;text/plain&apos;;</span><br><span class="line">        content_by_lua &apos;ngx.say(&quot;hello, ttlsa lua&quot;)&apos;;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    # 这里也是需要根据实际情况修改的，这里的是用了rewrite</span><br><span class="line">    location / &#123;</span><br><span class="line">        try_files $uri $uri/ /index.php?$args;</span><br><span class="line"></span><br><span class="line">        # add support for img which has query params,</span><br><span class="line">        # like:  xxx.jpg?a=b&amp;c=d_750x750.jpg</span><br><span class="line">        if ($args ~* &quot;^([^_]+)_(\d+)+x(\d+)+\.(jpg|jpeg|gif|png)$&quot;) &#123;</span><br><span class="line">            set $w $2;</span><br><span class="line">            set $h $3;</span><br><span class="line">            set $img_ext $4;</span><br><span class="line"></span><br><span class="line">            # rewrite ^\?(.*)$ _$&#123;w&#125;x$&#123;h&#125;.$img_ext? last;</span><br><span class="line">            rewrite ([^.]*).(jpg|jpeg|png|gif)$  $1.$2_$&#123;w&#125;x$&#123;h&#125;.$img_ext? permanent;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    # set var for thumb pic</span><br><span class="line">    set $upload_path /var/filebase;</span><br><span class="line">    set $img_original_root  $upload_path;# original root;</span><br><span class="line">    set $img_thumbnail_root $upload_path/cache/thumb;</span><br><span class="line">    set $img_file $img_thumbnail_root$uri;</span><br><span class="line"></span><br><span class="line">    # like：/xx/xx/xx.jpg_100-.jpg or /xx/xx/xx.jpg_-100.jpg</span><br><span class="line">    location ~* ^(.+\.(jpg|jpeg|gif|png))_((\d+\-)|(\-\d+))\.(jpg|jpeg|gif|png)$ &#123;</span><br><span class="line">            root $img_thumbnail_root;    # root path for croped img</span><br><span class="line">            set $img_size $3;</span><br><span class="line"></span><br><span class="line">            if (!-f $img_file) &#123;    # if file not exists</span><br><span class="line">                    add_header X-Powered-By &apos;Nginx+Lua+GraphicsMagick By Botao&apos;;  #  header for test</span><br><span class="line">                    add_header file-path $request_filename;    #  header for test</span><br><span class="line">                    set $request_filepath $img_original_root$1;    # origin_img full path：/document_root/1.gif</span><br><span class="line">                    set $img_size $3;    # img width or height size depends on uri</span><br><span class="line">                    set $img_ext $2;    # file ext</span><br><span class="line">                    content_by_lua_file /usr/local/nginx/lua/autoSize.lua;    # load lua</span><br><span class="line">            &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    # like: /xx/xx/xx.jpg_100x100.jpg</span><br><span class="line">    location ~* ^(.+\.(jpg|jpeg|gif|png))_(\d+)+x(\d+)+\.(jpg|jpeg|gif|png)$ &#123;</span><br><span class="line">            root $img_thumbnail_root;    # root path for croped img</span><br><span class="line"></span><br><span class="line">            if (!-f $img_file) &#123;    # if file not exists</span><br><span class="line">                    add_header X-Powered-By &apos;Nginx+Lua+GraphicsMagick By Botao&apos;;  #  header for test</span><br><span class="line">                    add_header file-path $request_filename;    #  header for test</span><br><span class="line">                    set $request_filepath $img_original_root$1;    # origin_img file path</span><br><span class="line">                    set $img_width $3;    # img width</span><br><span class="line">                    set $img_height $4;    # height</span><br><span class="line">                    set $img_ext $5;    # file ext</span><br><span class="line">                    content_by_lua_file /usr/local/nginx/lua/cropSize.lua;    # load lua</span><br><span class="line">            &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    # if need (all go there)</span><br><span class="line">    location ~* /upload &#123;</span><br><span class="line">            root $img_original_root;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    location ~ /\.ht &#123;</span><br><span class="line">        deny all;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="lua脚本"><a href="#lua脚本" class="headerlink" title="lua脚本"></a>lua脚本</h1><ul><li>/usr/local/tengine/lua/autoSize.lua</li></ul><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><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br></pre></td><td class="code"><pre><span class="line">-- 根据输入长或宽的尺寸自动裁切图片大小</span><br><span class="line"></span><br><span class="line">-- 检测路径是否目录</span><br><span class="line">local function is_dir(sPath)</span><br><span class="line">    if type(sPath) ~= &quot;string&quot; then return false end</span><br><span class="line"></span><br><span class="line">    local response = os.execute(&quot;cd &quot; .. sPath)</span><br><span class="line">    if response == 0 then</span><br><span class="line">        return true</span><br><span class="line">    end</span><br><span class="line">    return false</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 文件是否存在</span><br><span class="line">function file_exists(name)</span><br><span class="line">    local f = io.open(name, &quot;r&quot;)</span><br><span class="line">    if f ~= nil then io.close(f) return true else return false end</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 获取文件路径</span><br><span class="line">function getFileDir(filename)</span><br><span class="line">    return string.match(filename, &quot;(.+)/[^/]*%.%w+$&quot;) --*nix system</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 获取文件名</span><br><span class="line">function strippath(filename)</span><br><span class="line">    return string.match(filename, &quot;.+/([^/]*%.%w+)$&quot;) -- *nix system</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">--去除扩展名</span><br><span class="line">function stripextension(filename)</span><br><span class="line">    local idx = filename:match(&quot;.+()%.%w+$&quot;)</span><br><span class="line">    if (idx) then</span><br><span class="line">        return filename:sub(1, idx - 1)</span><br><span class="line">    else</span><br><span class="line">        return filename</span><br><span class="line">    end</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">--获取扩展名</span><br><span class="line">function getExtension(filename)</span><br><span class="line">    return filename:match(&quot;.+%.(%w+)$&quot;)</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">function getImgSize(img)</span><br><span class="line"></span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 判断尺寸是否合法</span><br><span class="line">-- check image size</span><br><span class="line">function table.contains(table, element)</span><br><span class="line">   for _, value in pairs(table) do</span><br><span class="line">      if value == element then</span><br><span class="line">         return true</span><br><span class="line">      end</span><br><span class="line">   end</span><br><span class="line">   return false</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">if image_sizes_check</span><br><span class="line">then</span><br><span class="line">    if not table.contains(image_sizes, ngx.var.img_size)</span><br><span class="line">    then</span><br><span class="line">        ngx.exit(404);</span><br><span class="line">    end</span><br><span class="line">end</span><br><span class="line">-- check image end</span><br><span class="line"></span><br><span class="line">-- 开始执行</span><br><span class="line">-- ngx.log(ngx.ERR, getFileDir(ngx.var.img_file));</span><br><span class="line"></span><br><span class="line">local gm_path = &apos;gm&apos;</span><br><span class="line"></span><br><span class="line">-- check image dir</span><br><span class="line">if not is_dir(getFileDir(ngx.var.img_file)) then</span><br><span class="line">    os.execute(&quot;mkdir -p &quot; .. getFileDir(ngx.var.img_file))</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 获取高宽 100!或!100模式</span><br><span class="line">local uri = ngx.var.img_size</span><br><span class="line">local width = string.sub(uri,1,1)</span><br><span class="line">local height = 0</span><br><span class="line"></span><br><span class="line">if width == &quot;-&quot; then</span><br><span class="line">  width = 0</span><br><span class="line">  height = string.sub(uri,2,string.len(uri))</span><br><span class="line">else</span><br><span class="line">  width = string.sub(uri,1,string.len(uri)-1)</span><br><span class="line">  height = 0</span><br><span class="line">end</span><br><span class="line">-- ngx.log(ngx.ERR,uri)</span><br><span class="line">-- ngx.log(ngx.ERR,width)</span><br><span class="line">-- ngx.log(ngx.ERR,height)</span><br><span class="line">-- ngx.log(ngx.ERR,ngx.var.img_file);</span><br><span class="line">-- ngx.log(ngx.ERR,ngx.var.request_filepath);</span><br><span class="line">-- 裁剪后保证等比缩图 （缺点：裁剪了图片的一部分）</span><br><span class="line">-- 如: gm convert autoSize.jpg -resize x200 -quality 100 +profile &quot;*&quot; autoSize.jpg_-200.jpg</span><br><span class="line">if (file_exists(ngx.var.request_filepath)) then</span><br><span class="line">    local cmd = gm_path .. &apos; convert -auto-orient &apos; .. ngx.var.request_filepath</span><br><span class="line">    if height == 0 then</span><br><span class="line">        cmd = cmd .. &quot; -resize &quot; .. width .. &quot;x&quot; ..  &quot;&quot;</span><br><span class="line">    else</span><br><span class="line">        cmd = cmd .. &quot; -resize &quot; .. &quot;x&quot; .. height .. &quot;&quot;</span><br><span class="line">    end</span><br><span class="line"></span><br><span class="line">-- 由于压缩后比较模糊,默认图片质量为100,请根据自己情况修改quality</span><br><span class="line">    cmd = cmd .. &quot; -quality 100&quot;</span><br><span class="line">    cmd = cmd .. &quot; +profile \&quot;*\&quot; &quot; .. ngx.var.img_file;</span><br><span class="line">    ngx.log(ngx.ERR, cmd);</span><br><span class="line">    os.execute(cmd);</span><br><span class="line">    ngx.exec(ngx.var.uri);</span><br><span class="line">else</span><br><span class="line">    ngx.exit(ngx.HTTP_NOT_FOUND);</span><br><span class="line">end</span><br></pre></td></tr></table></figure><ul><li>/usr/local/tengine/lua/cropSize.lua</li></ul><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><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre></td><td class="code"><pre><span class="line">-- 根据输入长和宽的尺寸裁切图片</span><br><span class="line"></span><br><span class="line">-- 检测路径是否目录</span><br><span class="line">local function is_dir(sPath)</span><br><span class="line">    if type(sPath) ~= &quot;string&quot; then return false end</span><br><span class="line"></span><br><span class="line">    local response = os.execute(&quot;cd &quot; .. sPath)</span><br><span class="line">    if response == 0 then</span><br><span class="line">        return true</span><br><span class="line">    end</span><br><span class="line">    return false</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 文件是否存在</span><br><span class="line">function file_exists(name)</span><br><span class="line">    local f = io.open(name, &quot;r&quot;)</span><br><span class="line">    if f ~= nil then io.close(f) return true else return false end</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 获取文件路径</span><br><span class="line">function getFileDir(filename)</span><br><span class="line">    return string.match(filename, &quot;(.+)/[^/]*%.%w+$&quot;) --*nix system</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 获取文件名</span><br><span class="line">function strippath(filename)</span><br><span class="line">    return string.match(filename, &quot;.+/([^/]*%.%w+)$&quot;) -- *nix system</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">--去除扩展名</span><br><span class="line">function stripextension(filename)</span><br><span class="line">    local idx = filename:match(&quot;.+()%.%w+$&quot;)</span><br><span class="line">    if (idx) then</span><br><span class="line">        return filename:sub(1, idx - 1)</span><br><span class="line">    else</span><br><span class="line">        return filename</span><br><span class="line">    end</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">--获取扩展名</span><br><span class="line">function getExtension(filename)</span><br><span class="line">    return filename:match(&quot;.+%.(%w+)$&quot;)</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 判断尺寸是否合法</span><br><span class="line">-- 待切割的图片尺寸</span><br><span class="line">local img_width_height = ngx.var.img_width .. &quot;x&quot; .. ngx.var.img_height;</span><br><span class="line">-- check image size</span><br><span class="line">function table.contains(table, element)</span><br><span class="line">   for _, value in pairs(table) do</span><br><span class="line">      if value == element then</span><br><span class="line">         return true</span><br><span class="line">      end</span><br><span class="line">   end</span><br><span class="line">   return false</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">if image_sizes_check</span><br><span class="line">then</span><br><span class="line">    if not table.contains(image_sizes, img_width_height)</span><br><span class="line">    then</span><br><span class="line">        ngx.exit(404);</span><br><span class="line">    end</span><br><span class="line">end</span><br><span class="line">-- check image end</span><br><span class="line"></span><br><span class="line">-- 开始执行</span><br><span class="line">-- ngx.log(ngx.ERR, getFileDir(ngx.var.img_file));</span><br><span class="line"></span><br><span class="line">local gm_path = &apos;gm&apos;</span><br><span class="line"></span><br><span class="line">-- check image dir</span><br><span class="line">if not is_dir(getFileDir(ngx.var.img_file)) then</span><br><span class="line">    os.execute(&quot;mkdir -p &quot; .. getFileDir(ngx.var.img_file))</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">--  ngx.log(ngx.ERR,ngx.var.img_file);</span><br><span class="line">--  ngx.log(ngx.ERR,ngx.var.request_filepath);</span><br><span class="line"></span><br><span class="line">-- 裁剪后保证等比缩图 （缺点：裁剪了图片的一部分）</span><br><span class="line">-- gm convert cropSize.jpg -thumbnail 300x300^ -gravity center -extent 300x300 -quality 100 +profile &quot;*&quot; cropSize.jpg_300x300.jpg</span><br><span class="line">if (file_exists(ngx.var.request_filepath)) then</span><br><span class="line">    local cmd = gm_path .. &apos; convert -auto-orient &apos; .. ngx.var.request_filepath</span><br><span class="line">    cmd = cmd .. &quot; -thumbnail &quot; .. ngx.var.img_width .. &quot;x&quot; .. ngx.var.img_height .. &quot;^&quot;</span><br><span class="line">    cmd = cmd .. &quot; -gravity center -extent &quot; .. ngx.var.img_width .. &quot;x&quot; .. ngx.var.img_height</span><br><span class="line"></span><br><span class="line">    -- 由于压缩后比较模糊,默认图片质量为100,请根据自己情况修改quality</span><br><span class="line">    cmd = cmd .. &quot; -quality 100&quot;</span><br><span class="line">    cmd = cmd .. &quot; +profile \&quot;*\&quot; &quot; .. ngx.var.img_file;</span><br><span class="line">--  ngx.log(ngx.ERR, cmd);</span><br><span class="line">    os.execute(cmd);</span><br><span class="line">    ngx.exec(ngx.var.uri);</span><br><span class="line">else</span><br><span class="line">    ngx.exit(ngx.HTTP_NOT_FOUND);</span><br><span class="line">end</span><br></pre></td></tr></table></figure><p>然后 nginx -s reload下</p><h1 id="测试效果"><a href="#测试效果" class="headerlink" title="测试效果"></a>测试效果</h1><p>在/var/filebase/upload目录，放1张图片</p><p><img src="\images\pasted-21.png" alt="upload successful"><br>原图</p><p><img src="\images\pasted-22.png" alt="upload successful"><br>100x100</p><p><img src="\images\pasted-23.png" alt="upload successful"><br>由于我们开启了image_sizes_check，不支持的尺寸会返回404</p><p><img src="\images\pasted-24.png" alt="upload successful"><br>固定定宽高自适应</p><p><img src="\images\pasted-25.png" alt="upload successful"><br>查看服务器上生成的文件</p><p>PS:这里有个问题，就是图片缩放后，图片的方向跟原先不一致的问题，后来笔者查了下GraphicsMagick资料，关于图片缩放后改变图片方向的问题，可以用-auto-orient参数可以来解决的,可以写成”gm convert -auto-orient “</p><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><p><a href="https://github.com/botaozhao/nginx-lua-GraphicsMagick" target="_blank" rel="noopener">https://github.com/botaozhao/nginx-lua-GraphicsMagick</a><br><a href="https://www.fanhaobai.com/2017/09/lua-in-nginx.html" target="_blank" rel="noopener">https://www.fanhaobai.com/2017/09/lua-in-nginx.html</a><br><a href="https://github.com/openresty/lua-nginx-module/issues/1533" target="_blank" rel="noopener">https://github.com/openresty/lua-nginx-module/issues/1533</a><br><a href="https://github.com/openresty/lua-nginx-module/pull/1501#issuecomment-486123650" target="_blank" rel="noopener">https://github.com/openresty/lua-nginx-module/pull/1501#issuecomment-486123650</a><br><a href="https://github.com/openresty/lua-resty-core/issues/248" target="_blank" rel="noopener">https://github.com/openresty/lua-resty-core/issues/248</a><br><a href="https://segmentfault.com/a/1190000011093243" target="_blank" rel="noopener">https://segmentfault.com/a/1190000011093243</a><br><a href="https://github.com/yanue/nginx-lua-GraphicsMagick/blob/master/nginx-install.md" target="_blank" rel="noopener">https://github.com/yanue/nginx-lua-GraphicsMagick/blob/master/nginx-install.md</a><br><a href="http://www.icode9.com/content-3-77987.html" target="_blank" rel="noopener">http://www.icode9.com/content-3-77987.html</a><br><a href="https://my.oschina.net/ranhai/blog/1797454" target="_blank" rel="noopener">https://my.oschina.net/ranhai/blog/1797454</a><br><a href="https://www.twblogs.net/a/5bafdb372b7177781a0f64d7/zh-cn" target="_blank" rel="noopener">https://www.twblogs.net/a/5bafdb372b7177781a0f64d7/zh-cn</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;自己搭建的图片服务器，有图片缩放的需求，大致思路是可以使用nginx调用lua，使用GraphicMagick的命令来做图片缩放&lt;/p&gt;
&lt;
      
    
    </summary>
    
      <category term="Linux Server" scheme="http://jaychang.cn/categories/Linux-Server/"/>
    
    
  </entry>
  
  <entry>
    <title>Ubuntu18.04 Tengine+Lua+GraphicsMagick图片缩放</title>
    <link href="http://jaychang.cn/2019/06/10/Ubuntu18-04-%E5%AE%89%E8%A3%85tengine/"/>
    <id>http://jaychang.cn/2019/06/10/Ubuntu18-04-安装tengine/</id>
    <published>2019-06-10T13:36:00.000Z</published>
    <updated>2019-07-14T09:39:04.654Z</updated>
    
    <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>自己搭建的图片服务器，有图片缩放的需求，大致思路是可以使用nginx调用lua，使用GraphicMagick的命令来做图片缩放</p><h1 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h1><h2 id="文件夹规划"><a href="#文件夹规划" class="headerlink" title="文件夹规划"></a>文件夹规划</h2><p>lua.jaychang.cn(如/var/filebase)</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></pre></td><td class="code"><pre><span class="line">jaychang@tengine:~$ tree /var/filebase/</span><br><span class="line">/var/filebase/</span><br><span class="line">├── avatar.png</span><br><span class="line">├── cache</span><br><span class="line">│   └── thumb</span><br><span class="line">│       ├── avatar.png_100x100.png</span><br><span class="line">│       └── upload</span><br><span class="line">│           ├── 1.png_100x100.png #固定高和宽</span><br><span class="line">│           ├── 1.png_400-.png # 定高</span><br><span class="line">│           └── 1.png_800-.png # 定宽</span><br><span class="line">└── upload</span><br><span class="line">    ├── 1.png</span><br><span class="line">4 directories, 8 files</span><br></pre></td></tr></table></figure><p>其中img.xyz.com为图片站点根目录<br>cache/thumb为缩略图存放目录<br>upload目录存放上传的图片</p><h2 id="链接地址对应关系"><a href="#链接地址对应关系" class="headerlink" title="链接地址对应关系"></a>链接地址对应关系</h2><p>原图访问地址：<a href="http://img.xyz.com/upload/1.png" target="_blank" rel="noopener">http://img.xyz.com/upload/1.png</a><br>缩略图访问地址：<a href="http://img.xyz.com/upload/1.png_100x100.png" target="_blank" rel="noopener">http://img.xyz.com/upload/1.png_100x100.png</a> 即为宽100,高100<br>自动宽地址: <a href="http://img.xyz.com/upload/1.png_-400.png" target="_blank" rel="noopener">http://img.xyz.com/upload/1.png_-400.png</a> 用”-“表示自动,即为高400,宽自动<br>自动高地址: <a href="http://img.xyz.com/upload/1.png_800-.jpg" target="_blank" rel="noopener">http://img.xyz.com/upload/1.png_800-.jpg</a> 用”-“表示自动,即为宽800,高自动</p><h2 id="访问流程"><a href="#访问流程" class="headerlink" title="访问流程"></a>访问流程</h2><p>首先判断缩略图是否存在，如存在则直接显示缩略图；<br>缩略图不存在,则判断原图是否存在，如原图存在则拼接graphicsmagick(gm)命令,生成并显示缩略图,否则返回404</p><h1 id="所需软件"><a href="#所需软件" class="headerlink" title="所需软件"></a>所需软件</h1><ul><li>lua-5.3.5.tar.gz</li><li>LuaJIT-2.0.5.tar.gz</li><li>tengine-2.3.0.tar.gz</li></ul><h1 id="安装依赖"><a href="#安装依赖" class="headerlink" title="安装依赖"></a>安装依赖</h1><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">apt-get install -y gcc g++ make</span><br><span class="line"></span><br><span class="line">apt-get install libreadline-dev libpcre3 libpcre3-dev openssl libssl-dev zlib1g zlib1g-dev libgeoip-dev -y</span><br></pre></td></tr></table></figure><h1 id="编译安装Lua-LuaJIT"><a href="#编译安装Lua-LuaJIT" class="headerlink" title="编译安装Lua LuaJIT"></a>编译安装Lua LuaJIT</h1><h2 id="编译安装Lua"><a href="#编译安装Lua" class="headerlink" title="编译安装Lua"></a>编译安装Lua</h2><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></pre></td><td class="code"><pre><span class="line">curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz</span><br><span class="line">tar zxf lua-5.3.5.tar.gz</span><br><span class="line">cd lua-5.3.5</span><br><span class="line">make linux test</span><br></pre></td></tr></table></figure><h2 id="编译安装LuaJIT"><a href="#编译安装LuaJIT" class="headerlink" title="编译安装LuaJIT"></a>编译安装LuaJIT</h2><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">curl -R -O http://luajit.org/download/LuaJIT-2.0.5.tar.gz</span><br><span class="line">tar -zxvf LuaJIT-2.0.5.tar.gz</span><br><span class="line">cd LuaJIT-2.0.5</span><br><span class="line">make -j2</span><br><span class="line">export LUAJIT_LIB=/usr/local/lib</span><br><span class="line">export LUAJIT_INC=/usr/local/include/luajit-2.0</span><br><span class="line">ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2</span><br></pre></td></tr></table></figure><h1 id="安装GraphicsMagick"><a href="#安装GraphicsMagick" class="headerlink" title="安装GraphicsMagick"></a>安装GraphicsMagick</h1><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></pre></td><td class="code"><pre><span class="line">wget ftp://ftp.graphicsmagick.org/pub/GraphicsMagick/1.3/GraphicsMagick-1.3.31.tar.gz</span><br><span class="line">tar xzvf GraphicsMagick-1.3.31.tar.gz</span><br><span class="line">cd GraphicsMagick-1.3.31</span><br><span class="line">./configure --prefix=/usr/local/GraphicsMagick --enable-shared</span><br><span class="line">make &amp;&amp; make install</span><br></pre></td></tr></table></figure><h1 id="创建用户及相应目录"><a href="#创建用户及相应目录" class="headerlink" title="创建用户及相应目录"></a>创建用户及相应目录</h1><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></pre></td><td class="code"><pre><span class="line">groupadd nginx &amp;&amp; useradd nginx -g nginx -s /sbin/nologin -M</span><br><span class="line"></span><br><span class="line">mkdir -p /var/tmp/tengine/client_body_temp</span><br><span class="line">mkdir -p /var/tmp/tengine/uwsgi_temp</span><br></pre></td></tr></table></figure><p>创建用户也可以用以下命令：<br><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">groupadd nginx &amp;&amp; useradd nginx -g nginx -s /bin/false -M</span><br></pre></td></tr></table></figure></p><h1 id="编译安装tengine"><a href="#编译安装tengine" class="headerlink" title="编译安装tengine"></a>编译安装tengine</h1><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">./configure --prefix=/usr/local/tengine \</span><br><span class="line">--user=nginx --group=nginx \</span><br><span class="line">--sbin-path=/usr/sbin/nginx \</span><br><span class="line">--with-pcre \</span><br><span class="line">--with-http_realip_module \</span><br><span class="line">--with-http_gzip_static_module \</span><br><span class="line">--with-http_stub_status_module \</span><br><span class="line">--with-http_v2_module \</span><br><span class="line">--with-http_lua_module \</span><br><span class="line">--with-http_flv_module \</span><br><span class="line">--with-http_ssl_module \</span><br><span class="line">--with-http_addition_module \</span><br><span class="line">--with-http_geoip_module \</span><br><span class="line">--http-scgi-temp-path=/var/tmp/tengine/cgi_temp \</span><br><span class="line">--http-client-body-temp-path=/var/tmp/tengine/client_body_temp \</span><br><span class="line">--http-proxy-temp-path=/var/tmp/tengine/proxy_temp \</span><br><span class="line">--http-uwsgi-temp-path=/var/tmp/tengine/uwsgi_temp \</span><br><span class="line">--http-fastcgi-temp-path=/var/tmp/tengine/fastcgi_temp \</span><br><span class="line">--http-log-path=/var/log/tengine/access.log \</span><br><span class="line">--error-log-path=/var/log/tengine/error.log</span><br></pre></td></tr></table></figure><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">make -j 2 &amp;&amp; make install</span><br></pre></td></tr></table></figure><p> 注意：在Tengine-2.3.0版本后废弃Tengine的dso_tool工具以及dso配置指令，若之前有使用Tengine的dso功能、则可以切换到Nginx官方的load_module指令,详细文档<a href="http://nginx.org/en/docs/ngx_core_module.html#load_module" target="_blank" rel="noopener">参考1</a><br>和 <a href="https://www.nginx.com/resources/wiki/extending/converting/#compiling-dynamic" target="_blank" rel="noopener">参考2</a><br>还有–with-http_spdy_module 已经改为–with-http_v2_module了<br>,如果不用geo的话，编译的时候可以不加–with-http_geoip_module，可以不安装libgeoip-dev</p><h1 id="测试tengine"><a href="#测试tengine" class="headerlink" title="测试tengine"></a>测试tengine</h1><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">cd /usr/local/tengine</span><br><span class="line">./sbin/nginx -t</span><br></pre></td></tr></table></figure><p>如果出现以下错误(没有报错就不用做以下操作了)<br><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">jaychang@tengine:/usr/local/tengine/sbin$ ./nginx -t</span><br><span class="line">./nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory</span><br></pre></td></tr></table></figure></p><p>查找下位置<br><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"></span><br><span class="line">jaychang@tengine:/usr/local/tengine/sbin$ sudo whereis libluajit-5.1.so.2</span><br><span class="line">libluajit-5.1.so: /usr/local/lib/libluajit-5.1.so /usr/local/lib/libluajit-5.1.so.2</span><br></pre></td></tr></table></figure></p><p>修改/etc/ld.so.conf,添加“/usr/local/lib”<br>vi /etc/ld.so.conf<br><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">include /etc/ld.so.conf.d/*.conf</span><br><span class="line">/usr/local/lib</span><br></pre></td></tr></table></figure></p><p>然后执行下ldconfig<br><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">ldconfig</span><br></pre></td></tr></table></figure></p><h1 id="修改nginx-conf配置文件"><a href="#修改nginx-conf配置文件" class="headerlink" title="修改nginx.conf配置文件"></a>修改nginx.conf配置文件</h1><p>将nginx.conf配置文件中的<strong>server{}段</strong>配置注释掉</p><p>加一行配置，以便读取/usr/local/tengine/conf.d目录下所有后缀为.conf的配置文件<br><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">include ../conf.d/*.conf;</span><br></pre></td></tr></table></figure></p><p>可以参考如下配置<br><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></pre></td><td class="code"><pre><span class="line">user nginx;</span><br><span class="line">worker_processes 4;</span><br><span class="line">worker_cpu_affinity 1000 0100 0010 0001;</span><br><span class="line">error_log /var/log/tengine/error.log error;</span><br><span class="line">pid /usr/local/tengine/logs/nginx.pid;</span><br><span class="line">worker_rlimit_nofile 65535;</span><br><span class="line">events</span><br><span class="line">&#123;</span><br><span class="line">use epoll;</span><br><span class="line">worker_connections 65535;</span><br><span class="line">&#125;</span><br><span class="line">http</span><br><span class="line">&#123;</span><br><span class="line">   limit_conn_zone $binary_remote_addr zone=one:10m;</span><br><span class="line">   limit_conn_zone $server_name zone=perserver:10m;</span><br><span class="line">include mime.types;</span><br><span class="line">include fastcgi.conf;</span><br><span class="line">default_type application/octet-stream;</span><br><span class="line">charset utf-8;</span><br><span class="line">server_names_hash_bucket_size 128;</span><br><span class="line">client_header_buffer_size 32k;</span><br><span class="line">large_client_header_buffers 4 64k;</span><br><span class="line">sendfile on;</span><br><span class="line">autoindex off;</span><br><span class="line">tcp_nopush on;</span><br><span class="line">tcp_nodelay on;</span><br><span class="line">keepalive_timeout 120;</span><br><span class="line">    </span><br><span class="line">fastcgi_connect_timeout 60;</span><br><span class="line">fastcgi_send_timeout 60;</span><br><span class="line">fastcgi_read_timeout 60;</span><br><span class="line">fastcgi_buffer_size 128k;</span><br><span class="line">fastcgi_buffers 8 128k;</span><br><span class="line">fastcgi_busy_buffers_size 128k;</span><br><span class="line">fastcgi_temp_file_write_size 128k;</span><br><span class="line">    </span><br><span class="line">gzip on;</span><br><span class="line">gzip_min_length 1k;</span><br><span class="line">gzip_buffers 4 16k;</span><br><span class="line">gzip_http_version 1.0;</span><br><span class="line">gzip_comp_level 2;</span><br><span class="line">gzip_types text/plain application/x-javascript text/css application/xml;</span><br><span class="line">gzip_vary on;</span><br><span class="line"></span><br><span class="line">log_format main &apos;$remote_addr - $remote_user [$time_local] &quot;$request&quot; &apos;</span><br><span class="line">&apos;$status $body_bytes_sent &quot;$http_referer&quot; &apos;</span><br><span class="line">&apos;&quot;$http_user_agent&quot; $http_x_forwarded_for&apos;;</span><br><span class="line"></span><br><span class="line">client_max_body_size 10m;</span><br><span class="line"></span><br><span class="line">include ../conf.d/*.conf;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><h1 id="创建放图片的目录"><a href="#创建放图片的目录" class="headerlink" title="创建放图片的目录"></a>创建放图片的目录</h1><p>目录规划</p><ul><li>/var/www 放网页,css,js等资源</li><li>/var/fielbase 放图片</li><li>/var/filebase/upload 上传的图片放这里</li></ul><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">mkdir -p /var/filebase/upload </span><br><span class="line">mkdir -p /var/filebase/cache/thumb</span><br><span class="line">chown -R nginx:nginx /var/filebase</span><br></pre></td></tr></table></figure><h1 id="配置站点配置文件"><a href="#配置站点配置文件" class="headerlink" title="配置站点配置文件"></a>配置站点配置文件</h1><p>在/usr/local/tengine/conf.d目录下创建demo.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><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br></pre></td><td class="code"><pre><span class="line"># 定义lua缩略图支持的图片尺寸及开关</span><br><span class="line">init_by_lua &apos;</span><br><span class="line">    image_sizes_check = true</span><br><span class="line">    image_sizes = &#123;&quot;800x800&quot;, &quot;400x400&quot;,&quot;200x200&quot;,&quot;100x100&quot;, &quot;-800&quot;, &quot;-400&quot;, &quot;-200&quot;,&quot;-100&quot;, &quot;800-&quot;, &quot;400-&quot;, &quot;200-&quot;,&quot;100-&quot;&#125;</span><br><span class="line">&apos;;</span><br><span class="line"></span><br><span class="line">server &#123;</span><br><span class="line">    listen   80;</span><br><span class="line">    servername img.xyz.com;</span><br><span class="line">    index index.php index.html index.htm;</span><br><span class="line"></span><br><span class="line">    set $root_path &apos;/var/www&apos;;</span><br><span class="line">    root $root_path;</span><br><span class="line"></span><br><span class="line">   # /lua仅用于测试，可去掉</span><br><span class="line"> location /lua &#123;</span><br><span class="line">default_type &apos;text/plain&apos;;</span><br><span class="line">        content_by_lua &apos;ngx.say(&quot;hello, ttlsa lua&quot;)&apos;;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    # 这里也是需要根据实际情况修改的，这里的是用了rewrite</span><br><span class="line">    location / &#123;</span><br><span class="line">        try_files $uri $uri/ /index.php?$args;</span><br><span class="line"></span><br><span class="line">        # add support for img which has query params,</span><br><span class="line">        # like:  xxx.jpg?a=b&amp;c=d_750x750.jpg</span><br><span class="line">        if ($args ~* &quot;^([^_]+)_(\d+)+x(\d+)+\.(jpg|jpeg|gif|png)$&quot;) &#123;</span><br><span class="line">            set $w $2;</span><br><span class="line">            set $h $3;</span><br><span class="line">            set $img_ext $4;</span><br><span class="line"></span><br><span class="line">            # rewrite ^\?(.*)$ _$&#123;w&#125;x$&#123;h&#125;.$img_ext? last;</span><br><span class="line">            rewrite ([^.]*).(jpg|jpeg|png|gif)$  $1.$2_$&#123;w&#125;x$&#123;h&#125;.$img_ext? permanent;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    # set var for thumb pic</span><br><span class="line">    set $upload_path /var/filebase;</span><br><span class="line">    set $img_original_root  $upload_path;# original root;</span><br><span class="line">    set $img_thumbnail_root $upload_path/cache/thumb;</span><br><span class="line">    set $img_file $img_thumbnail_root$uri;</span><br><span class="line"></span><br><span class="line">    # like：/xx/xx/xx.jpg_100-.jpg or /xx/xx/xx.jpg_-100.jpg</span><br><span class="line">    location ~* ^(.+\.(jpg|jpeg|gif|png))_((\d+\-)|(\-\d+))\.(jpg|jpeg|gif|png)$ &#123;</span><br><span class="line">            root $img_thumbnail_root;    # root path for croped img</span><br><span class="line">            set $img_size $3;</span><br><span class="line"></span><br><span class="line">            if (!-f $img_file) &#123;    # if file not exists</span><br><span class="line">                    add_header X-Powered-By &apos;Nginx+Lua+GraphicsMagick By Botao&apos;;  #  header for test</span><br><span class="line">                    add_header file-path $request_filename;    #  header for test</span><br><span class="line">                    set $request_filepath $img_original_root$1;    # origin_img full path：/document_root/1.gif</span><br><span class="line">                    set $img_size $3;    # img width or height size depends on uri</span><br><span class="line">                    set $img_ext $2;    # file ext</span><br><span class="line">                    content_by_lua_file /usr/local/tengine/lua/autoSize.lua;    # load lua</span><br><span class="line">            &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    # like: /xx/xx/xx.jpg_100x100.jpg</span><br><span class="line">    location ~* ^(.+\.(jpg|jpeg|gif|png))_(\d+)+x(\d+)+\.(jpg|jpeg|gif|png)$ &#123;</span><br><span class="line">            root $img_thumbnail_root;    # root path for croped img</span><br><span class="line"></span><br><span class="line">            if (!-f $img_file) &#123;    # if file not exists</span><br><span class="line">                    add_header X-Powered-By &apos;Nginx+Lua+GraphicsMagick By Botao&apos;;  #  header for test</span><br><span class="line">                    add_header file-path $request_filename;    #  header for test</span><br><span class="line">                    set $request_filepath $img_original_root$1;    # origin_img file path</span><br><span class="line">                    set $img_width $3;    # img width</span><br><span class="line">                    set $img_height $4;    # height</span><br><span class="line">                    set $img_ext $5;    # file ext</span><br><span class="line">                    content_by_lua_file /usr/local/tengine/lua/cropSize.lua;    # load lua</span><br><span class="line">            &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    # if need (all go there)</span><br><span class="line">    location ~* /upload &#123;</span><br><span class="line">            root $img_original_root;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    location ~ /\.ht &#123;</span><br><span class="line">        deny all;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="lua脚本"><a href="#lua脚本" class="headerlink" title="lua脚本"></a>lua脚本</h1><ul><li>/usr/local/tengine/lua/autoSize.lua</li></ul><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><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br></pre></td><td class="code"><pre><span class="line">-- 根据输入长或宽的尺寸自动裁切图片大小</span><br><span class="line"></span><br><span class="line">-- 检测路径是否目录</span><br><span class="line">local function is_dir(sPath)</span><br><span class="line">    if type(sPath) ~= &quot;string&quot; then return false end</span><br><span class="line"></span><br><span class="line">    local response = os.execute(&quot;cd &quot; .. sPath)</span><br><span class="line">    if response == 0 then</span><br><span class="line">        return true</span><br><span class="line">    end</span><br><span class="line">    return false</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 文件是否存在</span><br><span class="line">function file_exists(name)</span><br><span class="line">    local f = io.open(name, &quot;r&quot;)</span><br><span class="line">    if f ~= nil then io.close(f) return true else return false end</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 获取文件路径</span><br><span class="line">function getFileDir(filename)</span><br><span class="line">    return string.match(filename, &quot;(.+)/[^/]*%.%w+$&quot;) --*nix system</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 获取文件名</span><br><span class="line">function strippath(filename)</span><br><span class="line">    return string.match(filename, &quot;.+/([^/]*%.%w+)$&quot;) -- *nix system</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">--去除扩展名</span><br><span class="line">function stripextension(filename)</span><br><span class="line">    local idx = filename:match(&quot;.+()%.%w+$&quot;)</span><br><span class="line">    if (idx) then</span><br><span class="line">        return filename:sub(1, idx - 1)</span><br><span class="line">    else</span><br><span class="line">        return filename</span><br><span class="line">    end</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">--获取扩展名</span><br><span class="line">function getExtension(filename)</span><br><span class="line">    return filename:match(&quot;.+%.(%w+)$&quot;)</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">function getImgSize(img)</span><br><span class="line"></span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 判断尺寸是否合法</span><br><span class="line">-- check image size</span><br><span class="line">function table.contains(table, element)</span><br><span class="line">   for _, value in pairs(table) do</span><br><span class="line">      if value == element then</span><br><span class="line">         return true</span><br><span class="line">      end</span><br><span class="line">   end</span><br><span class="line">   return false</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">if image_sizes_check</span><br><span class="line">then</span><br><span class="line">    if not table.contains(image_sizes, ngx.var.img_size)</span><br><span class="line">    then</span><br><span class="line">        ngx.exit(404);</span><br><span class="line">    end</span><br><span class="line">end</span><br><span class="line">-- check image end</span><br><span class="line"></span><br><span class="line">-- 开始执行</span><br><span class="line">-- ngx.log(ngx.ERR, getFileDir(ngx.var.img_file));</span><br><span class="line"></span><br><span class="line">local gm_path = &apos;gm&apos;</span><br><span class="line"></span><br><span class="line">-- check image dir</span><br><span class="line">if not is_dir(getFileDir(ngx.var.img_file)) then</span><br><span class="line">    os.execute(&quot;mkdir -p &quot; .. getFileDir(ngx.var.img_file))</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 获取高宽 100!或!100模式</span><br><span class="line">local uri = ngx.var.img_size</span><br><span class="line">local width = string.sub(uri,1,1)</span><br><span class="line">local height = 0</span><br><span class="line"></span><br><span class="line">if width == &quot;-&quot; then</span><br><span class="line">  width = 0</span><br><span class="line">  height = string.sub(uri,2,string.len(uri))</span><br><span class="line">else</span><br><span class="line">  width = string.sub(uri,1,string.len(uri)-1)</span><br><span class="line">  height = 0</span><br><span class="line">end</span><br><span class="line">-- ngx.log(ngx.ERR,uri)</span><br><span class="line">-- ngx.log(ngx.ERR,width)</span><br><span class="line">-- ngx.log(ngx.ERR,height)</span><br><span class="line">-- ngx.log(ngx.ERR,ngx.var.img_file);</span><br><span class="line">-- ngx.log(ngx.ERR,ngx.var.request_filepath);</span><br><span class="line">-- 裁剪后保证等比缩图 （缺点：裁剪了图片的一部分）</span><br><span class="line">-- 如: gm convert autoSize.jpg -resize x200 -quality 100 +profile &quot;*&quot; autoSize.jpg_-200.jpg</span><br><span class="line">if (file_exists(ngx.var.request_filepath)) then</span><br><span class="line">    local cmd = gm_path .. &apos; convert -auto-orient &apos; .. ngx.var.request_filepath</span><br><span class="line">    if height == 0 then</span><br><span class="line">        cmd = cmd .. &quot; -resize &quot; .. width .. &quot;x&quot; ..  &quot;&quot;</span><br><span class="line">    else</span><br><span class="line">        cmd = cmd .. &quot; -resize &quot; .. &quot;x&quot; .. height .. &quot;&quot;</span><br><span class="line">    end</span><br><span class="line"></span><br><span class="line">-- 由于压缩后比较模糊,默认图片质量为100,请根据自己情况修改quality</span><br><span class="line">    cmd = cmd .. &quot; -quality 100&quot;</span><br><span class="line">    cmd = cmd .. &quot; +profile \&quot;*\&quot; &quot; .. ngx.var.img_file;</span><br><span class="line">    ngx.log(ngx.ERR, cmd);</span><br><span class="line">    os.execute(cmd);</span><br><span class="line">    ngx.exec(ngx.var.uri);</span><br><span class="line">else</span><br><span class="line">    ngx.exit(ngx.HTTP_NOT_FOUND);</span><br><span class="line">end</span><br></pre></td></tr></table></figure><ul><li>/usr/local/tengine/lua/cropSize.lua</li></ul><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><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre></td><td class="code"><pre><span class="line">-- 根据输入长和宽的尺寸裁切图片</span><br><span class="line"></span><br><span class="line">-- 检测路径是否目录</span><br><span class="line">local function is_dir(sPath)</span><br><span class="line">    if type(sPath) ~= &quot;string&quot; then return false end</span><br><span class="line"></span><br><span class="line">    local response = os.execute(&quot;cd &quot; .. sPath)</span><br><span class="line">    if response == 0 then</span><br><span class="line">        return true</span><br><span class="line">    end</span><br><span class="line">    return false</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 文件是否存在</span><br><span class="line">function file_exists(name)</span><br><span class="line">    local f = io.open(name, &quot;r&quot;)</span><br><span class="line">    if f ~= nil then io.close(f) return true else return false end</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 获取文件路径</span><br><span class="line">function getFileDir(filename)</span><br><span class="line">    return string.match(filename, &quot;(.+)/[^/]*%.%w+$&quot;) --*nix system</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 获取文件名</span><br><span class="line">function strippath(filename)</span><br><span class="line">    return string.match(filename, &quot;.+/([^/]*%.%w+)$&quot;) -- *nix system</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">--去除扩展名</span><br><span class="line">function stripextension(filename)</span><br><span class="line">    local idx = filename:match(&quot;.+()%.%w+$&quot;)</span><br><span class="line">    if (idx) then</span><br><span class="line">        return filename:sub(1, idx - 1)</span><br><span class="line">    else</span><br><span class="line">        return filename</span><br><span class="line">    end</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">--获取扩展名</span><br><span class="line">function getExtension(filename)</span><br><span class="line">    return filename:match(&quot;.+%.(%w+)$&quot;)</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">-- 判断尺寸是否合法</span><br><span class="line">-- 待切割的图片尺寸</span><br><span class="line">local img_width_height = ngx.var.img_width .. &quot;x&quot; .. ngx.var.img_height;</span><br><span class="line">-- check image size</span><br><span class="line">function table.contains(table, element)</span><br><span class="line">   for _, value in pairs(table) do</span><br><span class="line">      if value == element then</span><br><span class="line">         return true</span><br><span class="line">      end</span><br><span class="line">   end</span><br><span class="line">   return false</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">if image_sizes_check</span><br><span class="line">then</span><br><span class="line">    if not table.contains(image_sizes, img_width_height)</span><br><span class="line">    then</span><br><span class="line">        ngx.exit(404);</span><br><span class="line">    end</span><br><span class="line">end</span><br><span class="line">-- check image end</span><br><span class="line"></span><br><span class="line">-- 开始执行</span><br><span class="line">-- ngx.log(ngx.ERR, getFileDir(ngx.var.img_file));</span><br><span class="line"></span><br><span class="line">local gm_path = &apos;gm&apos;</span><br><span class="line"></span><br><span class="line">-- check image dir</span><br><span class="line">if not is_dir(getFileDir(ngx.var.img_file)) then</span><br><span class="line">    os.execute(&quot;mkdir -p &quot; .. getFileDir(ngx.var.img_file))</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">--  ngx.log(ngx.ERR,ngx.var.img_file);</span><br><span class="line">--  ngx.log(ngx.ERR,ngx.var.request_filepath);</span><br><span class="line"></span><br><span class="line">-- 裁剪后保证等比缩图 （缺点：裁剪了图片的一部分）</span><br><span class="line">-- gm convert cropSize.jpg -thumbnail 300x300^ -gravity center -extent 300x300 -quality 100 +profile &quot;*&quot; cropSize.jpg_300x300.jpg</span><br><span class="line">if (file_exists(ngx.var.request_filepath)) then</span><br><span class="line">    local cmd = gm_path .. &apos; convert -auto-orient &apos; .. ngx.var.request_filepath</span><br><span class="line">    cmd = cmd .. &quot; -thumbnail &quot; .. ngx.var.img_width .. &quot;x&quot; .. ngx.var.img_height .. &quot;^&quot;</span><br><span class="line">    cmd = cmd .. &quot; -gravity center -extent &quot; .. ngx.var.img_width .. &quot;x&quot; .. ngx.var.img_height</span><br><span class="line"></span><br><span class="line">    -- 由于压缩后比较模糊,默认图片质量为100,请根据自己情况修改quality</span><br><span class="line">    cmd = cmd .. &quot; -quality 100&quot;</span><br><span class="line">    cmd = cmd .. &quot; +profile \&quot;*\&quot; &quot; .. ngx.var.img_file;</span><br><span class="line">--  ngx.log(ngx.ERR, cmd);</span><br><span class="line">    os.execute(cmd);</span><br><span class="line">    ngx.exec(ngx.var.uri);</span><br><span class="line">else</span><br><span class="line">    ngx.exit(ngx.HTTP_NOT_FOUND);</span><br><span class="line">end</span><br></pre></td></tr></table></figure><p>然后 nginx -s reload下</p><h1 id="测试效果"><a href="#测试效果" class="headerlink" title="测试效果"></a>测试效果</h1><p>在/var/filebase/upload目录，放1张图片</p><p><img src="\images\pasted-21.png" alt="upload successful"><br>原图</p><p><img src="\images\pasted-22.png" alt="upload successful"><br>100x100</p><p><img src="\images\pasted-23.png" alt="upload successful"><br>由于我们开启了image_sizes_check，不支持的尺寸会返回404</p><p><img src="\images\pasted-24.png" alt="upload successful"><br>固定定宽高自适应</p><p><img src="\images\pasted-25.png" alt="upload successful"><br>查看服务器上生成的文件</p><p>PS:这里有个问题，就是图片缩放后，图片的方向跟原先不一致的问题，后来笔者查了下GraphicsMagick资料，关于图片缩放后改变图片方向的问题，可以用-auto-orient参数可以来解决的,可以写成”gm convert -auto-orient “</p><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><p><a href="https://github.com/botaozhao/nginx-lua-GraphicsMagick" target="_blank" rel="noopener">https://github.com/botaozhao/nginx-lua-GraphicsMagick</a><br><a href="https://github.com/yanue/nginx-lua-GraphicsMagick/blob/master/nginx-install.md" target="_blank" rel="noopener">https://github.com/yanue/nginx-lua-GraphicsMagick/blob/master/nginx-install.md</a><br><a href="http://www.icode9.com/content-3-77987.html" target="_blank" rel="noopener">http://www.icode9.com/content-3-77987.html</a><br><a href="https://my.oschina.net/ranhai/blog/1797454" target="_blank" rel="noopener">https://my.oschina.net/ranhai/blog/1797454</a><br><a href="https://www.twblogs.net/a/5bafdb372b7177781a0f64d7/zh-cn" target="_blank" rel="noopener">https://www.twblogs.net/a/5bafdb372b7177781a0f64d7/zh-cn</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;自己搭建的图片服务器，有图片缩放的需求，大致思路是可以使用nginx调用lua，使用GraphicMagick的命令来做图片缩放&lt;/p&gt;
&lt;
      
    
    </summary>
    
      <category term="Linux Server" scheme="http://jaychang.cn/categories/Linux-Server/"/>
    
    
  </entry>
  
  <entry>
    <title>Ubuntu18.04 Swarm集群搭建</title>
    <link href="http://jaychang.cn/2019/05/15/Ubuntu%2018.04%20Docker%20Swarm%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA/"/>
    <id>http://jaychang.cn/2019/05/15/Ubuntu 18.04 Docker Swarm集群搭建/</id>
    <published>2019-05-15T14:56:00.000Z</published>
    <updated>2019-07-07T12:06:09.108Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Swarm简介"><a href="#Swarm简介" class="headerlink" title="Swarm简介"></a>Swarm简介</h1><p>Swarm 是 Docker 官方提供的一款集群管理工具，用来管理 Docker 集群，它将若干台 Docker 主机抽象为一个整体，并且通过一个入口统一管理这些 Docker 主机上的各种 Docker 资源。</p><p>Swarm 只是一个调度器（Scheduler）加路由器 (Router)，Swarm 自己不运行容器，它只是接受 Docker 客户端发送过来的请求，调度适合的节点来运行容器，这意味着，即使 Swarm 由于某些原因挂掉了，集群中的节点也会照常运行，当 Swarm 重新恢复运行之后，它会收集重建集群信息。</p><p>Docker Engine 从 V1.12.0 版本开始，原生集成了 Docker Swarm，所以只要在每台机器上安装 Docker，就可以直接使用 Docker Swarm。</p><p>Swarm 和 Kubernetes 比较类似，但是更加轻，具有的功能也较 Kubernetes 更少一些。</p><p>Swarm会提供网络管理、负载均衡、基于DNS容器发现、集群状态管理、扩容缩容等功能，在DevOps流程层面，可以组合成发布、回滚应用、查看服务的状态、日志、终端，更改发布配置（例如环境变量、默认副本数等）等功能。这个层面Portainer这个开源项目，提供了更好用集群管理的UI界面和类似Kubernetes Apiserver设计的Docker集群API接口服务。</p><p><img src="\images\pasted-18.png" alt="upload successful"></p><p>Docker Swarm的资源抽象比较简单，在没有容器编排的情况下，我们主要使用Services，这个和Kubernetes上的Services有些不一样，可以理解为Services和Deployment的合体，用来管理和定义容器的调度和扩容等，也可以直接做端口映射，在容器集群里任意IP都可以访问。</p><h1 id="集群规划"><a href="#集群规划" class="headerlink" title="集群规划"></a>集群规划</h1><p>因为Manager节点只负责调度集群的Task，配置要求不高，可用3台低配置机器作为Manager节点，根据Raft算法，3台可以容许1台机器出问题，5台可以允许2台机器出问题，大家可以按需求部署。Worker节点的作用是运行业务容器。同时，在Manager和Worker节点上，会以容器方式部署机器监控和日志收集，上面还需要运行网络和存储插件。</p><table><thead><tr><th>IP地址</th><th>Swarm节点类型</th><th>主机名</th></tr></thead><tbody><tr><td>192.168.56.111</td><td>manager</td><td>m01</td></tr><tr><td>192.168.56.112</td><td>manager</td><td>m02</td></tr><tr><td>192.168.56.113</td><td>manager</td><td>m03</td></tr><tr><td>192.168.56.114</td><td>worker</td><td>n01</td></tr><tr><td>192.168.56.115</td><td>worker</td><td>n02</td></tr></tbody></table><h2 id="集群节点配置"><a href="#集群节点配置" class="headerlink" title="集群节点配置"></a>集群节点配置</h2><p>笔者是用VirtualBox虚拟5台机器,作为运行Docker的宿主机。本节以下内容均是在m01上操作的。其他节点配置不再赘述，参考此m01节点的配置即可。</p><h3 id="网络配置"><a href="#网络配置" class="headerlink" title="网络配置"></a>网络配置</h3><p>每台宿主机需要启用仅主机(Host-Only)网络及网络地址转换(NAT)两张网卡</p><p>以m01为例,/etc/netplan/01-netcfg.yaml网络配置如下：<br><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></pre></td><td class="code"><pre><span class="line">network:</span><br><span class="line">  version: 2</span><br><span class="line">  renderer: networkd</span><br><span class="line">  ethernets:</span><br><span class="line">    enp0s3:</span><br><span class="line">      dhcp4: no</span><br><span class="line">      dhcp6: no</span><br><span class="line">      addresses: [192.168.56.111/24]</span><br><span class="line">    enp0s8:</span><br><span class="line">      dhcp4: yes</span><br><span class="line">      dhcp6: no</span><br></pre></td></tr></table></figure></p><blockquote><p>注意这里enp0s3就是仅主机(Host-Only)网络这个网卡，此网卡用于ssh连接我们的虚拟机，由于这里是virtualbox虚拟机无需配置网关，enp0s8就是网络地址转换(NAT)这个网卡，此网卡用于访问外网。</p></blockquote><h3 id="主机名及hosts"><a href="#主机名及hosts" class="headerlink" title="主机名及hosts"></a>主机名及hosts</h3><p>设置主机名 sudo vi /etc/hostname<br><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">m01</span><br></pre></td></tr></table></figure></p><blockquote><p>如果遇到重启机器后主机名被重置，可以再用<strong><em>sudo hostnamectl set-hostname xxx</em></strong> 设置</p></blockquote><p> 通过sudo vi /etc/host以添加以下内容</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></pre></td><td class="code"><pre><span class="line">192.168.56.111 m01</span><br><span class="line">192.168.56.112 m02</span><br><span class="line">192.168.56.113 m03</span><br><span class="line">192.168.56.114 n01</span><br><span class="line">192.168.56.115 n02</span><br></pre></td></tr></table></figure><h3 id="设置国内软件源"><a href="#设置国内软件源" class="headerlink" title="设置国内软件源"></a>设置国内软件源</h3><p> 备份sources.list,sudo cp /etc/apt/sources.list /etc/apt/sources.list.default</p><p>批量修改sources.list<br><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">sudo sed -i &quot;s#us.archive.ubuntu.com/#mirrors.aliyun.com/#g&quot; /etc/apt/sources.list</span><br><span class="line"></span><br><span class="line">sudo sed -i &quot;s#security.ubuntu.com/#mirrors.aliyun.com/#g&quot; /etc/apt/sources.list</span><br></pre></td></tr></table></figure></p><h3 id="安装Docker"><a href="#安装Docker" class="headerlink" title="安装Docker"></a>安装Docker</h3><h4 id="安装GPG证书"><a href="#安装GPG证书" class="headerlink" title="安装GPG证书"></a>安装GPG证书</h4><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">curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -</span><br></pre></td></tr></table></figure><h4 id="写入软件源信息"><a href="#写入软件源信息" class="headerlink" title="写入软件源信息"></a>写入软件源信息</h4><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">sudo add-apt-repository &quot;deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable&quot;</span><br></pre></td></tr></table></figure><h4 id="更新并安装Docker-CE"><a href="#更新并安装Docker-CE" class="headerlink" title="更新并安装Docker-CE"></a>更新并安装Docker-CE</h4><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">sudo apt-get -y update</span><br><span class="line">sudo apt-get -y install docker-ce</span><br></pre></td></tr></table></figure><p>若想要安装指定版本Docker，参照如下操作：</p><ul><li>Step 1: 查找Docker-CE的版本:</li></ul><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"></span><br><span class="line">sudo apt-cache madison docker-ce</span><br></pre></td></tr></table></figure><ul><li>Step 2: 安装指定版本的Docker-CE</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">sudo apt-get -y install docker-ce=[VERSION]</span><br></pre></td></tr></table></figure><blockquote><p>注意上面命令中的[VERSION]需要替换成你想要安装的docker版本，<br>比如这里我将[VERSION]替换为5:18.09.4~3-0~ubuntu-bionic，所以最终的安装命令是<strong>sudo apt-get -y install docker-ce=5:18.09.6~3-0~ubuntu-bionic</strong></p><p>其他可选的Docker软件源还有<a href="https://mirror.tuna.tsinghua.edu.cn/help/docker-ce/" title="清华大学Docker软件源" target="_blank" rel="noopener">清华大学Docker软件源</a></p></blockquote><h4 id="配置Docker镜像加速"><a href="#配置Docker镜像加速" class="headerlink" title="配置Docker镜像加速"></a>配置Docker镜像加速</h4><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></pre></td><td class="code"><pre><span class="line">sudo vi /etc/docker/daemon.json</span><br><span class="line">&#123;</span><br><span class="line">  &quot;registry-mirrors&quot;: [&quot;https://docker.mirrors.ustc.edu.cn&quot;]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>注意 insecure-registries是配置非https的镜像中心，比如我们自己搭建的一个docker私有镜像中心，是用http的话，就可以用insecure-registries指定。</p></blockquote><h4 id="修改docker-service配置"><a href="#修改docker-service配置" class="headerlink" title="修改docker.service配置"></a>修改docker.service配置</h4><p>如果碰到Unable to proxy the request via the Docker socket,这个错误，建议可以在任意worker节点，docker服务配置，<br><img src="\images\pasted-20.png" alt="upload successful"></p><p>这里只要改集群中一个节点就可以了(如果是用portainer agent方式添加的endpoint)主要是要改ExecStart,暴露2375,笔者改的是n01节点上的/lib/systemd/system/docker.service</p><p>sudo vi /lib/systemd/system/docker.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><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></pre></td><td class="code"><pre><span class="line">[Unit]</span><br><span class="line">Description=Docker Application Container Engine</span><br><span class="line">Documentation=https://docs.docker.com</span><br><span class="line">BindsTo=containerd.service</span><br><span class="line">After=network-online.target firewalld.service containerd.service</span><br><span class="line">Wants=network-online.target</span><br><span class="line">Requires=docker.socket</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=notify</span><br><span class="line"># the default is not to use systemd for cgroups because the delegate issues still</span><br><span class="line"># exists and systemd currently does not support the cgroup feature set required</span><br><span class="line"># for containers run by docker</span><br><span class="line">ExecStart=/usr/bin/dockerd -H fd:// -H 0.0.0.0:2375 --containerd=/run/containerd/containerd.sock</span><br><span class="line">ExecReload=/bin/kill -s HUP $MAINPID</span><br><span class="line">TimeoutSec=0</span><br><span class="line">RestartSec=2</span><br><span class="line">Restart=always</span><br><span class="line"></span><br><span class="line"># Note that StartLimit* options were moved from &quot;Service&quot; to &quot;Unit&quot; in systemd 229.</span><br><span class="line"># Both the old, and new location are accepted by systemd 229 and up, so using the old location</span><br><span class="line"># to make them work for either version of systemd.</span><br><span class="line">StartLimitBurst=3</span><br><span class="line"></span><br><span class="line"># Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.</span><br><span class="line"># Both the old, and new name are accepted by systemd 230 and up, so using the old name to make</span><br><span class="line"># this option work for either version of systemd.</span><br><span class="line">StartLimitInterval=60s</span><br><span class="line"></span><br><span class="line"># Having non-zero Limit*s causes performance problems due to accounting overhead</span><br><span class="line"># in the kernel. We recommend using cgroups to do container-local accounting.</span><br><span class="line">LimitNOFILE=infinity</span><br><span class="line">LimitNPROC=infinity</span><br><span class="line">LimitCORE=infinity</span><br><span class="line"></span><br><span class="line"># Comment TasksMax if your systemd version does not supports it.</span><br><span class="line"># Only systemd 226 and above support this option.</span><br><span class="line">TasksMax=infinity</span><br><span class="line"></span><br><span class="line"># set delegate yes so that systemd does not reset the cgroups of docker containers</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">内容过多省略...</span><br></pre></td></tr></table></figure><p>还可以改成<br><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"># for containers run by docker</span><br><span class="line">ExecStart=/usr/bin/dockerd -H unix:// -H 0.0.0.0:2375 --containerd=/run/containerd/containerd.sock</span><br></pre></td></tr></table></figure></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></pre></td><td class="code"><pre><span class="line"># for containers run by docker</span><br><span class="line">ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375 --containerd=/run/containerd/containerd.sock</span><br></pre></td></tr></table></figure><p>sudo systemctl daemon-reload<br>sudo systemctl restart docker</p><h4 id="重启docker服务"><a href="#重启docker服务" class="headerlink" title="重启docker服务"></a>重启docker服务</h4><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">sudo systemctl restart docker</span><br></pre></td></tr></table></figure><h1 id="开始搭建Swarm集群"><a href="#开始搭建Swarm集群" class="headerlink" title="开始搭建Swarm集群"></a>开始搭建Swarm集群</h1><p>上述都是在做准备工作，接下来就正式开始搭建Swarm集群。</p><h2 id="初始化Swarm集群"><a href="#初始化Swarm集群" class="headerlink" title="初始化Swarm集群"></a>初始化Swarm集群</h2><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">sudo docker swarm init --advertise-addr 192.168.56.111</span><br></pre></td></tr></table></figure><p><img src="/images/pasted-0.png" alt="初始化swarm集群"></p><blockquote><p>注意：上图显示的token仅作参考，具体需看实际情况，也请记下来</p><p>如果遗失可以通过下面两个命令，分别找回manager、worker的join token</p></blockquote><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">sudo docker swarm join-token manager</span><br><span class="line"></span><br><span class="line">sudo docker swarm join-token worker</span><br></pre></td></tr></table></figure><h2 id="集群添加manager节点"><a href="#集群添加manager节点" class="headerlink" title="集群添加manager节点"></a>集群添加manager节点</h2><h3 id="获取manager的join-token"><a href="#获取manager的join-token" class="headerlink" title="获取manager的join token"></a>获取manager的join token</h3><p>根据上一节给出的提示，在192.168.56.111(m01)上执行<br><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">sudo docker swarm join-token manager</span><br></pre></td></tr></table></figure></p><p><img src="\images\pasted-1.png" alt="集群添加manager节点"></p><p>根据提示，若要将节点作为manager节点加入swarm集群，需执行如下命令:<br><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">docker swarm join --token SWMTKN-1-65q3om1lmrjrsvnbqug0qccf00ertneorskvmv86g05qzicc8w-1kuf57afgawuuz24h7gx4hycb 192.168.56.111:2377</span><br></pre></td></tr></table></figure></p><h3 id="添加manager节点到集群"><a href="#添加manager节点到集群" class="headerlink" title="添加manager节点到集群"></a>添加manager节点到集群</h3><p>根据我们的规划，我们要将m02、m03作为manager节点加入到swarm集群，所以我们在m02,m03上执行：</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">sudo docker swarm join --token SWMTKN-1-65q3om1lmrjrsvnbqug0qccf00ertneorskvmv86g05qzicc8w-1kuf57afgawuuz24h7gx4hycb 192.168.56.111:2377</span><br></pre></td></tr></table></figure><blockquote><p>注意：请根据实际情况进行修改，不要一模一样复制！</p></blockquote><p><img src="\images\pasted-2.png" alt="upload successful"></p><p><img src="\images\pasted-3.png" alt="upload successful"></p><h2 id="添加worker节点到集群"><a href="#添加worker节点到集群" class="headerlink" title="添加worker节点到集群"></a>添加worker节点到集群</h2><p>分别在n01,n02上执行如下命令：</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">docker swarm join --token SWMTKN-1-65q3om1lmrjrsvnbqug0qccf00ertneorskvmv86g05qzicc8w-978befgfbbuqzqzv2zbvcg8fk 192.168.56.111:2377</span><br></pre></td></tr></table></figure><blockquote><p>注意：请根据实际情况进行修改，不要一模一样复制！</p></blockquote><p><img src="\images\pasted-4.png" alt="upload successful"></p><p><img src="\images\pasted-5.png" alt="upload successful"></p><h2 id="查看节点状态"><a href="#查看节点状态" class="headerlink" title="查看节点状态"></a>查看节点状态</h2><p>在任意manager节点上执行<br><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">sudo docker node ls</span><br></pre></td></tr></table></figure></p><p><img src="\images\pasted-7.png" alt="upload successful"></p><p>从上图可以看到集群中有3个manager节点，2个worker</p><h1 id="Swarm集群管理UI"><a href="#Swarm集群管理UI" class="headerlink" title="Swarm集群管理UI"></a>Swarm集群管理UI</h1><p>建议每次都在固定的节点上运行,所以这里指定了node.hostname == m01<br><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">sudo docker service create --name portainer --publish 9000:9000 --replicas=1 --constraint &apos;node.hostname == m01&apos; --mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock --mount type=volume,src=portainer_data,dst=/data portainer/portainer</span><br></pre></td></tr></table></figure></p><p><img src="\images\pasted-9.png" alt="upload successful"></p><h2 id="Add-Endpoints"><a href="#Add-Endpoints" class="headerlink" title="Add Endpoints"></a>Add Endpoints</h2><p>添加一个Local Endpoint，由于portainer是运行在m01上的，所以就是添加m01</p><p><img src="\images\pasted-10.png" alt="upload successful"></p><p><img src="\images\pasted-11.png" alt="upload successful"></p><h2 id="部署Portainer-Agent"><a href="#部署Portainer-Agent" class="headerlink" title="部署Portainer Agent"></a>部署Portainer Agent</h2><p>打开App Template，点击Poirtainer Agent<br><img src="\images\pasted-12.png" alt="upload successful"></p><p>给stack取个名字，然后单击deploy</p><p><img src="\images\pasted-14.png" alt="upload successful"></p><p>部署完成后，每个节点会起一个</p><p><img src="\images\pasted-15.png" alt="upload successful"></p><blockquote><p>部署Portainer Agent的另外一个途径是在任意manager节点上，执行<br>以下命令</p></blockquote><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">curl -L https://downloads.portainer.io/agent-stack.yml -o agent-stack.yml &amp;&amp; docker stack deploy --compose-file=agent-stack.yml portainer-agent</span><br></pre></td></tr></table></figure><h2 id="添加其他Endpoint"><a href="#添加其他Endpoint" class="headerlink" title="添加其他Endpoint"></a>添加其他Endpoint</h2><p>这里以添加m02为例，Endpoint的名称我们就填m02这个主机名好了，然后就是要填写Endpoint URL，就填m02节点的IP地址以及Portainer Agent的端口号，即192.168.56.112:9001</p><p><img src="\images\pasted-16.png" alt="upload successful"></p><p>所有Endpoint添加完毕</p><p><img src="\images\pasted-17.png" alt="upload successful"></p><blockquote><p>这里的m01也可以删掉后，用Agent来添加</p></blockquote><h2 id="镜像中心设置"><a href="#镜像中心设置" class="headerlink" title="镜像中心设置"></a>镜像中心设置</h2><p>当镜像中心是需要身份认证的，那么可以在registries里添加一个镜像中心，输入镜像中心的用户名，密码即可，这样集群中的所有节点都能从该镜像中心拉取镜像了。由于篇幅，这里不再赘述跟截图了，读者可以自行尝试。</p><h1 id="测试集群"><a href="#测试集群" class="headerlink" title="测试集群"></a>测试集群</h1><ul><li>部署一个nginx service</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">sudo docker service create --name mynginx --replicas 3 -p 8088:80 nginx:alpine</span><br></pre></td></tr></table></figure><p><img src="\images\pasted-19.png" alt="upload successful"></p><blockquote><p>我们发现通过任意节点的8088端口都能访问，那是因为Ingress的特性使得请求可以转发到任何一台Worker或者Manager节点上，然后通过内置的routing mesh的Load Balancer通过LVS转发请求到Service的其中一个副本，一个值得注意的点是，就算这台Node上没有运行这个Service的容器。Load Balancer也会找到其他机器上存在的副本，这个主要是通过内置的DNS加LVS转发实现。</p></blockquote><ul><li>扩容、缩容</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">sudo docker service scale mynginx=2</span><br></pre></td></tr></table></figure><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">sudo docker service scale mynginx=3</span><br></pre></td></tr></table></figure><h1 id="附录"><a href="#附录" class="headerlink" title="附录"></a>附录</h1><h2 id="删除节点"><a href="#删除节点" class="headerlink" title="删除节点"></a>删除节点</h2><h3 id="删除manager节点"><a href="#删除manager节点" class="headerlink" title="删除manager节点"></a>删除manager节点</h3><p>manager节点不能直接删除，需要先降级到worker节点再删除。</p><p>比如，这里我误把n02作为manager加入到集群，我想把n02改成worker节点。</p><p><img src="\images\pasted-6.png" alt="upload successful"></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">sudo docker node demote cu8f</span><br><span class="line">sudo docker node rm cu8f</span><br></pre></td></tr></table></figure><blockquote><p>cu8f为节点ID的前缀</p></blockquote><h3 id="删除worker节点"><a href="#删除worker节点" class="headerlink" title="删除worker节点"></a>删除worker节点</h3><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">sudo docker node rm [ID或HOSTNAME]</span><br></pre></td></tr></table></figure><h3 id="工作节点离开集群"><a href="#工作节点离开集群" class="headerlink" title="工作节点离开集群"></a>工作节点离开集群</h3><p>在工作节点上执行<br><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">sudo docker swarm leave</span><br></pre></td></tr></table></figure></p><p>工作节点离开集群后，节点状态就会变为Down,这样此节点就可以加入到另外一个swarm集群了。（原先的swarm集群manager节点上记得用sudo docker node rm xxx删除此节点）</p><h2 id="创建overlay网络"><a href="#创建overlay网络" class="headerlink" title="创建overlay网络"></a>创建overlay网络</h2><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">docker network create --subnet=192.168.10.0/24 --attachable -d overlay my-net</span><br></pre></td></tr></table></figure><h2 id="QA"><a href="#QA" class="headerlink" title="QA"></a>QA</h2><h3 id="如何删除docker"><a href="#如何删除docker" class="headerlink" title="如何删除docker"></a>如何删除docker</h3><p>通过sudo apt-get purge docker-ce,然后将/var/lib/docker目录删掉</p><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><p><a href="http://dockone.io/article/8808" target="_blank" rel="noopener">http://dockone.io/article/8808</a> 房多多容器化和容器云实践<br><a href="https://www.cnblogs.com/bigberg/p/8656963.html" target="_blank" rel="noopener">https://www.cnblogs.com/bigberg/p/8656963.html</a> Docker Macvlan<br><a href="https://cizixs.com/2017/02/14/network-virtualization-macvlan/" target="_blank" rel="noopener">https://cizixs.com/2017/02/14/network-virtualization-macvlan/</a> linux 网络虚拟化： macvlan<br><a href="https://opsx.alibaba.com/guide?lang=zh-CN&amp;document=69a2341e-801e-11e8-8b5a-00163e04cdbb" target="_blank" rel="noopener">https://opsx.alibaba.com/guide?lang=zh-CN&amp;document=69a2341e-801e-11e8-8b5a-00163e04cdbb</a> ubuntu 18.04 (bionic) 配置 opsx 安装源</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;Swarm简介&quot;&gt;&lt;a href=&quot;#Swarm简介&quot; class=&quot;headerlink&quot; title=&quot;Swarm简介&quot;&gt;&lt;/a&gt;Swarm简介&lt;/h1&gt;&lt;p&gt;Swarm 是 Docker 官方提供的一款集群管理工具，用来管理 Docker 集群，它将若干台 
      
    
    </summary>
    
      <category term="Docker&amp;Kubernetes" scheme="http://jaychang.cn/categories/Docker-Kubernetes/"/>
    
    
      <category term="docker" scheme="http://jaychang.cn/tags/docker/"/>
    
      <category term="swarm" scheme="http://jaychang.cn/tags/swarm/"/>
    
  </entry>
  
  <entry>
    <title>CentOS6.6内核升级,安装docker17.06.2-ce</title>
    <link href="http://jaychang.cn/2018/05/24/CentOS6-x%E5%86%85%E6%A0%B8%E5%8D%87%E7%BA%A7-%E5%AE%89%E8%A3%85docker17-06-2-ce/"/>
    <id>http://jaychang.cn/2018/05/24/CentOS6-x内核升级-安装docker17-06-2-ce/</id>
    <published>2018-05-24T14:05:00.000Z</published>
    <updated>2019-07-07T12:04:16.721Z</updated>
    
    <content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><hr><p>由于笔者所在公司无论是开发、测试环境，还是准生产环境、生产环境，使用的都是CentOS6.6。要想按照新版本的Docker就必须升级Linux内核。因此，此文讲解如何升级Linux内核，以及在升级完内核后，如何安装Docker17.06.2-ce。其他版本的docker笔者没有尝试，应该也是可行的。毕竟内核升级到4.4.132-1了</p><a id="more"></a><h1 id="安装方式一"><a href="#安装方式一" class="headerlink" title="安装方式一"></a>安装方式一</h1><p>第一种安装方式，需要联网，因此请确保机器可以连接到互联网</p><h2 id="升级Linux内核"><a href="#升级Linux内核" class="headerlink" title="升级Linux内核"></a>升级Linux内核</h2><ul><li>查看当前linux内核版本,查看CentOS版本</li></ul><blockquote><p>uname -a</p><p>cat /etc/centos-release </p></blockquote><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">[root@localhost ~]# uname -a</span><br><span class="line">Linux localhost.localdomain 2.6.32-504.el6.x86_64 #1 SMP Wed Oct 15 04:27:16 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux</span><br><span class="line">[root@localhost ~]# cat /etc/centos-release </span><br><span class="line">CentOS release 6.6 (Final)</span><br></pre></td></tr></table></figure><ul><li>导入存储库的GPG密钥</li></ul><blockquote><p>rpm –import <a href="https://www.elrepo.org/RPM-GPG-KEY-elrepo.org" target="_blank" rel="noopener">https://www.elrepo.org/RPM-GPG-KEY-elrepo.org</a></p></blockquote><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@localhost ~]# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org</span><br><span class="line">curl: (35) SSL connect error</span><br><span class="line">error: https://www.elrepo.org/RPM-GPG-KEY-elrepo.org: import read failed(2).</span><br></pre></td></tr></table></figure><ul><li>若你也遇到以上错误，可执行下yum -y update nss</li></ul><blockquote><p>yum -y update nss</p></blockquote><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><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br></pre></td><td class="code"><pre><span class="line">[root@localhost ~]# yum -y update nss</span><br><span class="line">Loaded plugins: fastestmirror</span><br><span class="line">Setting up Update Process</span><br><span class="line">base                                                                                                                                                                    | 3.7 kB     00:00     </span><br><span class="line">base/primary_db                                                                                                                                                         | 4.7 MB     00:01     </span><br><span class="line">extras                                                                                                                                                                  | 3.4 kB     00:00     </span><br><span class="line">extras/primary_db                                                                                                                                                       |  30 kB     00:00     </span><br><span class="line">updates                                                                                                                                                                 | 3.4 kB     00:00     </span><br><span class="line">updates/primary_db                                                                                                                                                      | 8.1 MB     00:03     </span><br><span class="line">Resolving Dependencies</span><br><span class="line"><span class="meta">--&gt;</span> Running transaction check</span><br><span class="line"><span class="meta">---&gt;</span> Package nss.x86_64 0:3.16.1-14.el6 will be updated</span><br><span class="line"><span class="meta">--&gt;</span> Processing Dependency: nss = 3.16.1-14.el6 for package: nss-sysinit-3.16.1-14.el6.x86_64</span><br><span class="line"><span class="meta">--&gt;</span> Processing Dependency: nss(x86-64) = 3.16.1-14.el6 for package: nss-tools-3.16.1-14.el6.x86_64</span><br><span class="line"><span class="meta">---&gt;</span> Package nss.x86_64 0:3.28.4-4.el6_9 will be an update</span><br><span class="line"><span class="meta">--&gt;</span> Processing Dependency: nss-util &gt;= 3.28.3 for package: nss-3.28.4-4.el6_9.x86_64</span><br><span class="line"><span class="meta">--&gt;</span> Processing Dependency: nss-softokn(x86-64) &gt;= 3.14.3-22 for package: nss-3.28.4-4.el6_9.x86_64</span><br><span class="line"><span class="meta">--&gt;</span> Processing Dependency: nspr &gt;= 4.13.0 for package: nss-3.28.4-4.el6_9.x86_64</span><br><span class="line"><span class="meta">--&gt;</span> Processing Dependency: libnssutil3.so(NSSUTIL_3.24)(64bit) for package: nss-3.28.4-4.el6_9.x86_64</span><br><span class="line"><span class="meta">--&gt;</span> Processing Dependency: libnssutil3.so(NSSUTIL_3.21)(64bit) for package: nss-3.28.4-4.el6_9.x86_64</span><br><span class="line"><span class="meta">--&gt;</span> Running transaction check</span><br><span class="line"><span class="meta">---&gt;</span> Package nspr.x86_64 0:4.10.6-1.el6_5 will be updated</span><br><span class="line"><span class="meta">---&gt;</span> Package nspr.x86_64 0:4.13.1-1.el6 will be an update</span><br><span class="line"><span class="meta">---&gt;</span> Package nss-softokn.x86_64 0:3.14.3-17.el6 will be updated</span><br><span class="line"><span class="meta">---&gt;</span> Package nss-softokn.x86_64 0:3.14.3-23.3.el6_8 will be an update</span><br><span class="line"><span class="meta">--&gt;</span> Processing Dependency: nss-softokn-freebl(x86-64) &gt;= 3.14.3-23.3.el6_8 for package: nss-softokn-3.14.3-23.3.el6_8.x86_64</span><br><span class="line"><span class="meta">---&gt;</span> Package nss-sysinit.x86_64 0:3.16.1-14.el6 will be updated</span><br><span class="line"><span class="meta">---&gt;</span> Package nss-sysinit.x86_64 0:3.28.4-4.el6_9 will be an update</span><br><span class="line"><span class="meta">---&gt;</span> Package nss-tools.x86_64 0:3.16.1-14.el6 will be updated</span><br><span class="line"><span class="meta">---&gt;</span> Package nss-tools.x86_64 0:3.28.4-4.el6_9 will be an update</span><br><span class="line"><span class="meta">---&gt;</span> Package nss-util.x86_64 0:3.16.1-3.el6 will be updated</span><br><span class="line"><span class="meta">---&gt;</span> Package nss-util.x86_64 0:3.28.4-1.el6_9 will be an update</span><br><span class="line"><span class="meta">--&gt;</span> Running transaction check</span><br><span class="line"><span class="meta">---&gt;</span> Package nss-softokn-freebl.x86_64 0:3.14.3-17.el6 will be updated</span><br><span class="line"><span class="meta">---&gt;</span> Package nss-softokn-freebl.x86_64 0:3.14.3-23.3.el6_8 will be an update</span><br><span class="line"><span class="meta">--&gt;</span> Finished Dependency Resolution</span><br><span class="line"></span><br><span class="line">Dependencies Resolved</span><br><span class="line"></span><br><span class="line">===============================================================================================================================================================================================</span><br><span class="line"> Package                                             Arch                                    Version                                            Repository                                Size</span><br><span class="line">===============================================================================================================================================================================================</span><br><span class="line">Updating:</span><br><span class="line"> nss                                                 x86_64                                  3.28.4-4.el6_9                                     updates                                  879 k</span><br><span class="line">Updating for dependencies:</span><br><span class="line"> nspr                                                x86_64                                  4.13.1-1.el6                                       base                                     114 k</span><br><span class="line"> nss-softokn                                         x86_64                                  3.14.3-23.3.el6_8                                  base                                     262 k</span><br><span class="line"> nss-softokn-freebl                                  x86_64                                  3.14.3-23.3.el6_8                                  base                                     168 k</span><br><span class="line"> nss-sysinit                                         x86_64                                  3.28.4-4.el6_9                                     updates                                   51 k</span><br><span class="line"> nss-tools                                           x86_64                                  3.28.4-4.el6_9                                     updates                                  447 k</span><br><span class="line"> nss-util                                            x86_64                                  3.28.4-1.el6_9                                     updates                                   68 k</span><br><span class="line"></span><br><span class="line">Transaction Summary</span><br><span class="line">===============================================================================================================================================================================================</span><br><span class="line">Upgrade       7 Package(s)</span><br><span class="line"></span><br><span class="line">Total download size: 1.9 M</span><br><span class="line">Downloading Packages:</span><br><span class="line">(1/7): nspr-4.13.1-1.el6.x86_64.rpm                                                                                                                                     | 114 kB     00:00     </span><br><span class="line">(2/7): nss-3.28.4-4.el6_9.x86_64.rpm                                                                                                                                    | 879 kB     00:00     </span><br><span class="line">(3/7): nss-softokn-3.14.3-23.3.el6_8.x86_64.rpm                                                                                                                         | 262 kB     00:00     </span><br><span class="line">(4/7): nss-softokn-freebl-3.14.3-23.3.el6_8.x86_64.rpm                                                                                                                  | 168 kB     00:00     </span><br><span class="line">(5/7): nss-sysinit-3.28.4-4.el6_9.x86_64.rpm                                                                                                                            |  51 kB     00:00     </span><br><span class="line">(6/7): nss-tools-3.28.4-4.el6_9.x86_64.rpm                                                                                                                              | 447 kB     00:00     </span><br><span class="line">(7/7): nss-util-3.28.4-1.el6_9.x86_64.rpm                                                                                                                               |  68 kB     00:00     </span><br><span class="line">-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------</span><br><span class="line">Total                                                                                                                                                          986 kB/s | 1.9 MB     00:02     </span><br><span class="line">warning: rpmts_HdrFromFdno: Header V3 RSA/SHA1 Signature, key ID c105b9de: NOKEY</span><br><span class="line">Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6</span><br><span class="line">Importing GPG key 0xC105B9DE:</span><br><span class="line"> Userid : CentOS-6 Key (CentOS 6 Official Signing Key) &lt;centos-6-key@centos.org&gt;</span><br><span class="line"> Package: centos-release-6-6.el6.centos.12.2.x86_64 (@anaconda-CentOS-201410241409.x86_64/6.6)</span><br><span class="line"> From   : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6</span><br><span class="line">Running rpm_check_debug</span><br><span class="line">Running Transaction Test</span><br><span class="line">Transaction Test Succeeded</span><br><span class="line">Running Transaction</span><br><span class="line">  Updating   : nspr-4.13.1-1.el6.x86_64                                                                                                                                                   1/14 </span><br><span class="line">  Updating   : nss-util-3.28.4-1.el6_9.x86_64                                                                                                                                             2/14 </span><br><span class="line">  Updating   : nss-softokn-freebl-3.14.3-23.3.el6_8.x86_64                                                                                                                                3/14 </span><br><span class="line">  Updating   : nss-softokn-3.14.3-23.3.el6_8.x86_64                                                                                                                                       4/14 </span><br><span class="line">  Updating   : nss-sysinit-3.28.4-4.el6_9.x86_64                                                                                                                                          5/14 </span><br><span class="line">  Updating   : nss-3.28.4-4.el6_9.x86_64                                                                                                                                                  6/14 </span><br><span class="line">  Updating   : nss-tools-3.28.4-4.el6_9.x86_64                                                                                                                                            7/14 </span><br><span class="line">  Cleanup    : nss-tools-3.16.1-14.el6.x86_64                                                                                                                                             8/14 </span><br><span class="line">  Cleanup    : nss-sysinit-3.16.1-14.el6.x86_64                                                                                                                                           9/14 </span><br><span class="line">  Cleanup    : nss-3.16.1-14.el6.x86_64                                                                                                                                                  10/14 </span><br><span class="line">  Cleanup    : nss-softokn-3.14.3-17.el6.x86_64                                                                                                                                          11/14 </span><br><span class="line">  Cleanup    : nss-util-3.16.1-3.el6.x86_64                                                                                                                                              12/14 </span><br><span class="line">  Cleanup    : nspr-4.10.6-1.el6_5.x86_64                                                                                                                                                13/14 </span><br><span class="line">  Cleanup    : nss-softokn-freebl-3.14.3-17.el6.x86_64                                                                                                                                   14/14 </span><br><span class="line">  Verifying  : nss-tools-3.28.4-4.el6_9.x86_64                                                                                                                                            1/14 </span><br><span class="line">  Verifying  : nss-3.28.4-4.el6_9.x86_64                                                                                                                                                  2/14 </span><br><span class="line">  Verifying  : nss-softokn-3.14.3-23.3.el6_8.x86_64                                                                                                                                       3/14 </span><br><span class="line">  Verifying  : nss-softokn-freebl-3.14.3-23.3.el6_8.x86_64                                                                                                                                4/14 </span><br><span class="line">  Verifying  : nspr-4.13.1-1.el6.x86_64                                                                                                                                                   5/14 </span><br><span class="line">  Verifying  : nss-util-3.28.4-1.el6_9.x86_64                                                                                                                                             6/14 </span><br><span class="line">  Verifying  : nss-sysinit-3.28.4-4.el6_9.x86_64                                                                                                                                          7/14 </span><br><span class="line">  Verifying  : nss-sysinit-3.16.1-14.el6.x86_64                                                                                                                                           8/14 </span><br><span class="line">  Verifying  : nspr-4.10.6-1.el6_5.x86_64                                                                                                                                                 9/14 </span><br><span class="line">  Verifying  : nss-softokn-3.14.3-17.el6.x86_64                                                                                                                                          10/14 </span><br><span class="line">  Verifying  : nss-util-3.16.1-3.el6.x86_64                                                                                                                                              11/14 </span><br><span class="line">  Verifying  : nss-3.16.1-14.el6.x86_64                                                                                                                                                  12/14 </span><br><span class="line">  Verifying  : nss-softokn-freebl-3.14.3-17.el6.x86_64                                                                                                                                   13/14 </span><br><span class="line">  Verifying  : nss-tools-3.16.1-14.el6.x86_64                                                                                                                                            14/14 </span><br><span class="line"></span><br><span class="line">Updated:</span><br><span class="line">  nss.x86_64 0:3.28.4-4.el6_9                                                                                                                                                                  </span><br><span class="line"></span><br><span class="line">Dependency Updated:</span><br><span class="line">  nspr.x86_64 0:4.13.1-1.el6       nss-softokn.x86_64 0:3.14.3-23.3.el6_8 nss-softokn-freebl.x86_64 0:3.14.3-23.3.el6_8 nss-sysinit.x86_64 0:3.28.4-4.el6_9 nss-tools.x86_64 0:3.28.4-4.el6_9</span><br><span class="line">  nss-util.x86_64 0:3.28.4-1.el6_9</span><br><span class="line"></span><br><span class="line">Complete!</span><br></pre></td></tr></table></figure><ul><li>再次尝试导入GPG密钥就OK了</li></ul><blockquote><p>rpm –import <a href="https://www.elrepo.org/RPM-GPG-KEY-elrepo.org" target="_blank" rel="noopener">https://www.elrepo.org/RPM-GPG-KEY-elrepo.org</a></p></blockquote><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@localhost ~]# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org</span><br><span class="line">[root@localhost ~]#</span><br></pre></td></tr></table></figure><ul><li>安装ELRepo</li></ul><blockquote><p>rpm -Uvh <a href="http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm" target="_blank" rel="noopener">http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm</a></p></blockquote><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">[root@localhost ~]# rpm -Uvh http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm</span><br><span class="line">Retrieving http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm</span><br><span class="line">Preparing...                ########################################### [100%]</span><br><span class="line">   1:elrepo-release         ########################################### [100%]</span><br></pre></td></tr></table></figure><ul><li>安装新内核</li></ul><blockquote><p>yum –enablerepo=elrepo-kernel install kernel-lt -y</p><p>不建议 <del>yum –enablerepo=elrepo-kernel install -y kernel-ml（ ml=mainline）</del></p></blockquote><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><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">[root@localhost ~]# yum --enablerepo=elrepo-kernel install kernel-lt -y</span><br><span class="line">Loaded plugins: fastestmirror</span><br><span class="line">Setting up Install Process</span><br><span class="line">Determining fastest mirrors</span><br><span class="line"> * base: mirrors.aliyun.com</span><br><span class="line"> * elrepo: mirrors.tuna.tsinghua.edu.cn</span><br><span class="line"> * elrepo-kernel: mirrors.tuna.tsinghua.edu.cn</span><br><span class="line"> * extras: mirrors.aliyun.com</span><br><span class="line"> * updates: centos.ustc.edu.cn</span><br><span class="line">elrepo                                                                                                                                                                  | 2.9 kB     00:00     </span><br><span class="line">elrepo/primary_db                                                                                                                                                       | 718 kB     00:00     </span><br><span class="line">elrepo-kernel                                                                                                                                                           | 2.9 kB     00:00     </span><br><span class="line">elrepo-kernel/primary_db                                                                                                                                                |  22 kB     00:00     </span><br><span class="line">Resolving Dependencies</span><br><span class="line"><span class="meta">--&gt;</span> Running transaction check</span><br><span class="line"><span class="meta">---&gt;</span> Package kernel-lt.x86_64 0:4.4.132-1.el6.elrepo will be installed</span><br><span class="line"><span class="meta">--&gt;</span> Finished Dependency Resolution</span><br><span class="line"></span><br><span class="line">Dependencies Resolved</span><br><span class="line"></span><br><span class="line">===============================================================================================================================================================================================</span><br><span class="line"> Package                                    Arch                                    Version                                               Repository                                      Size</span><br><span class="line">===============================================================================================================================================================================================</span><br><span class="line">Installing:</span><br><span class="line"> kernel-lt                                  x86_64                                  4.4.132-1.el6.elrepo                                  elrepo-kernel                                   39 M</span><br><span class="line"></span><br><span class="line">Transaction Summary</span><br><span class="line">===============================================================================================================================================================================================</span><br><span class="line">Install       1 Package(s)</span><br><span class="line"></span><br><span class="line">Total download size: 39 M</span><br><span class="line">Installed size: 178 M</span><br><span class="line">Downloading Packages:</span><br><span class="line">kernel-lt-4.4.132-1.el6.elrepo.x86_64.rpm                                                                                                                               |  39 MB     00:11     </span><br><span class="line">Running rpm_check_debug</span><br><span class="line">Running Transaction Test</span><br><span class="line">Transaction Test Succeeded</span><br><span class="line">Running Transaction</span><br><span class="line">Warning: RPMDB altered outside of yum.</span><br><span class="line">  Installing : kernel-lt-4.4.132-1.el6.elrepo.x86_64                                                                                                                                       1/1 </span><br><span class="line">  Verifying  : kernel-lt-4.4.132-1.el6.elrepo.x86_64                                                                                                                                       1/1 </span><br><span class="line"></span><br><span class="line">Installed:</span><br><span class="line">  kernel-lt.x86_64 0:4.4.132-1.el6.elrepo                                                                                                                                                      </span><br><span class="line"></span><br><span class="line">Complete!</span><br></pre></td></tr></table></figure><ul><li>编辑grub.conf文件，修改Grub引导顺序</li></ul><blockquote><p>vi /etc/grub.conf (这里踩了个坑，我改了/etc/grub.conf文件，但是貌似一直没有生效，后来发现原来用的是/boot/grub/grub.conf，这个得事先观察下是否存在这个/boot/grub/grub.conf)，一般情况应该都是使用/etc/grub.conf。但无论如何安装内核都是去操作/etc/grub.conf文件的，如果grub启动用的是/boot/grub/grub.conf，那么请将/etc/grub.conf文件内新安装的内核的启动引导配置复制到/boot/grub/grub.conf文件内。</p></blockquote><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></pre></td><td class="code"><pre><span class="line"># grub.conf generated by anaconda</span><br><span class="line">#</span><br><span class="line"># Note that you do not have to rerun grub after making changes to this file</span><br><span class="line"># NOTICE:  You have a /boot partition.  This means that</span><br><span class="line">#          all kernel and initrd paths are relative to /boot/, eg.</span><br><span class="line">#          root (hd0,0)</span><br><span class="line">#          kernel /vmlinuz-version ro root=/dev/mapper/VolGroup-LogVol00</span><br><span class="line">#          initrd /initrd-[generic-]version.img</span><br><span class="line">#boot=/dev/sda</span><br><span class="line">default=0</span><br><span class="line">timeout=5</span><br><span class="line">splashimage=(hd0,0)/grub/splash.xpm.gz</span><br><span class="line">hiddenmenu</span><br><span class="line">title CentOS (4.4.132-1.el6.elrepo.x86_64)</span><br><span class="line">        root (hd0,0)</span><br><span class="line">        kernel /vmlinuz-4.4.132-1.el6.elrepo.x86_64 ro root=/dev/mapper/VolGroup-LogVol00 rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto  KEYBOARDTYPE=pc KEYTABLE=us rd_LVM_LV=VolGroup/LogVol00 rd_NO_DM rhgb quiet</span><br><span class="line">        initrd /initramfs-4.4.132-1.el6.elrepo.x86_64.img</span><br><span class="line">title CentOS 6 (2.6.32-504.el6.x86_64)</span><br><span class="line">        root (hd0,0)</span><br><span class="line">        kernel /vmlinuz-2.6.32-504.el6.x86_64 ro root=/dev/mapper/VolGroup-LogVol00 rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto  KEYBOARDTYPE=pc KEYTABLE=us rd_LVM_LV=VolGroup/LogVol00 rd_NO_DM rhgb quiet</span><br><span class="line">        initrd /initramfs-2.6.32-504.el6.x86_64.img</span><br></pre></td></tr></table></figure><p>将default=1改为default=0,确保默认启动新的内核。一般新安装的内核会在第一个位置(从0开始)，所以设置<strong>default=0</strong></p><h2 id="安装Docker"><a href="#安装Docker" class="headerlink" title="安装Docker"></a>安装Docker</h2><p>笔者这里用的是二进制安装包来安装</p><ul><li>下载安装，配置国内中科大docker镜像源</li></ul><p>下面给出中科大与阿里云的docker二进制安装包</p><blockquote><p>curl -O <a href="http://mirrors.ustc.edu.cn/docker-ce/linux/static/stable/x86_64/docker-17.06.2-ce.tgz" target="_blank" rel="noopener">http://mirrors.ustc.edu.cn/docker-ce/linux/static/stable/x86_64/docker-17.06.2-ce.tgz</a></p><p>tar -xzvf docker-17.06.2-ce.tgz &amp;&amp; cp docker/* /usr/bin &amp;&amp; rm -rf docker</p><p>mkdir -p /etc/docker &amp;&amp; echo “{\”registry-mirrors\”: [\”<a href="https://docker.mirrors.ustc.edu.cn/" target="_blank" rel="noopener">https://docker.mirrors.ustc.edu.cn</a>\”]}” &gt; /etc/docker/daemon.json</p></blockquote><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></pre></td><td class="code"><pre><span class="line">[root@localhost ~]# curl -O http://mirrors.ustc.edu.cn/docker-ce/linux/static/stable/x86_64/docker-17.06.2-ce.tgz</span><br><span class="line"><span class="meta">  %</span> Total    % Received % Xferd  Average Speed   Time    Time     Time  Current</span><br><span class="line">                                 Dload  Upload   Total   Spent    Left  Speed</span><br><span class="line">100 28.3M  100 28.3M    0     0  3618k      0  0:00:08  0:00:08 --:--:-- 3726k</span><br><span class="line">[root@localhost ~]# ll</span><br><span class="line">total 29032</span><br><span class="line">-rw-------. 1 root root     1038 May 22 20:46 anaconda-ks.cfg</span><br><span class="line">-rw-r--r--. 1 root root 29704322 May 24 23:46 docker-17.06.2-ce.tgz</span><br><span class="line">-rw-r--r--. 1 root root     8823 May 22 20:46 install.log</span><br><span class="line">-rw-r--r--. 1 root root     3384 May 22 20:45 install.log.syslog</span><br><span class="line">[root@localhost ~]# tar -xzvf docker-17.06.2-ce.tgz &amp;&amp; cp docker/* /usr/bin &amp;&amp; rm -rf docker</span><br><span class="line">docker/</span><br><span class="line">docker/docker-runc</span><br><span class="line">docker/docker</span><br><span class="line">docker/docker-containerd-ctr</span><br><span class="line">docker/docker-containerd</span><br><span class="line">docker/docker-proxy</span><br><span class="line">docker/docker-containerd-shim</span><br><span class="line">docker/dockerd</span><br><span class="line">docker/docker-init</span><br><span class="line"></span><br><span class="line">[root@localhost ~]# mkdir -p /etc/docker &amp;&amp; echo "&#123;\"registry-mirrors\": [\"https://docker.mirrors.ustc.edu.cn\"]&#125;" &gt; /etc/docker/daemon.json</span><br><span class="line">[root@localhost ~]# ls /etc/docker/</span><br><span class="line">daemon.json  key.json</span><br></pre></td></tr></table></figure><ul><li>如果我们此时启动dockerd，提示我们升级到3.10.0内核版本或升级到更新的内核版本，这个重启下就好了，不用担心</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></pre></td><td class="code"><pre><span class="line">[root@localhost ~]# dockerd </span><br><span class="line">WARN[0000] could not change group /var/run/docker.sock to docker: group docker not found </span><br><span class="line">WARN[0000] libcontainerd: makeUpgradeProof could not open /var/run/docker/libcontainerd/containerd </span><br><span class="line">INFO[0000] libcontainerd: new containerd process, pid: 13659 </span><br><span class="line">WARN[0000] containerd: low RLIMIT_NOFILE changing to max  current=1024 max=4096</span><br><span class="line">FATA[0001] Your Linux kernel version 2.6.32-504.el6.x86_64 is not supported for running docker. Please upgrade your kernel to 3.10.0 or newer.</span><br></pre></td></tr></table></figure><ul><li>给dockerd设置自动启动</li></ul><blockquote><p>echo “nohup dockerd &gt; /var/log/dockerd.log &amp; 2&gt;&amp;1” &gt;&gt; /etc/rc.local</p></blockquote><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@localhost ~]# echo "nohup dockerd &gt; /var/log/dockerd.log 2&gt;&amp;1 &amp;" &gt;&gt; /etc/rc.local</span><br><span class="line">[root@localhost ~]#</span><br></pre></td></tr></table></figure><ul><li>重启查看内核版本</li></ul><blockquote><p>如果看到内核版本已经是4.4.132啦，那说明grub确实已经引导了新的内核了</p></blockquote><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">[root@localhost ~]# uname -a</span><br><span class="line">Linux localhost.localdomain 4.4.132-1.el6.elrepo.x86_64 #1 SMP Wed May 16 14:20:29 EDT 2018 x86_64 x86_64 x86_64 GNU/Linux</span><br></pre></td></tr></table></figure><ul><li>查看docker info但提示docker没启动成功</li></ul><blockquote><p>此时我们也可以查看docker的日志，我们把日志放在了/var/log/dockerd.log。或者你可以直接运行dockerd。</p><p>提示我们cgroup的东东，看来得安装cgroup</p></blockquote><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></pre></td><td class="code"><pre><span class="line">[root@localhost ~]# docker info</span><br><span class="line">Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?</span><br><span class="line"></span><br><span class="line">[root@localhost ~]# dockerd </span><br><span class="line">WARN[0000] could not change group /var/run/docker.sock to docker: group docker not found </span><br><span class="line">INFO[0000] libcontainerd: new containerd process, pid: 1293 </span><br><span class="line">WARN[0000] containerd: low RLIMIT_NOFILE changing to max  current=1024 max=4096</span><br><span class="line">INFO[0001] [graphdriver] using prior storage driver: overlay2 </span><br><span class="line">INFO[0001] Graph migration to content-addressability took 0.00 seconds </span><br><span class="line">WARN[0001] Your kernel does not support cgroup memory limit </span><br><span class="line">WARN[0001] Unable to find cpu cgroup in mounts          </span><br><span class="line">WARN[0001] Unable to find blkio cgroup in mounts        </span><br><span class="line">WARN[0001] Unable to find cpuset cgroup in mounts       </span><br><span class="line">WARN[0001] mountpoint for pids not found                </span><br><span class="line">Error starting daemon: Devices cgroup isn't mounted</span><br></pre></td></tr></table></figure><ul><li>安装cgroup,并配置挂载cgroup，需要重启系统(当然这一步可以在之前重启前就做好，这样系统只要重启一次就好了，我这里只是想分享我的踩坑经历哈，就按我踩坑的顺序写下去了)</li></ul><blockquote><p>yum install -y libcgroup</p><p>echo “none                    /sys/fs/cgroup         cgroup   defaults        0 0” &gt;&gt; /etc/fstab</p></blockquote><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><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">[root@localhost ~]# yum install -y libcgroup</span><br><span class="line">Loaded plugins: fastestmirror</span><br><span class="line">Setting up Install Process</span><br><span class="line">Loading mirror speeds from cached hostfile</span><br><span class="line"> * base: mirrors.aliyun.com</span><br><span class="line"> * elrepo: mirrors.tuna.tsinghua.edu.cn</span><br><span class="line"> * extras: mirrors.aliyun.com</span><br><span class="line"> * updates: centos.ustc.edu.cn</span><br><span class="line">Resolving Dependencies</span><br><span class="line"><span class="meta">--&gt;</span> Running transaction check</span><br><span class="line"><span class="meta">---&gt;</span> Package libcgroup.x86_64 0:0.40.rc1-24.el6_9 will be installed</span><br><span class="line"><span class="meta">--&gt;</span> Finished Dependency Resolution</span><br><span class="line"></span><br><span class="line">Dependencies Resolved</span><br><span class="line"></span><br><span class="line">===============================================================================================================================================================================================</span><br><span class="line"> Package                                      Arch                                      Version                                               Repository                                  Size</span><br><span class="line">===============================================================================================================================================================================================</span><br><span class="line">Installing:</span><br><span class="line"> libcgroup                                    x86_64                                    0.40.rc1-24.el6_9                                     updates                                    131 k</span><br><span class="line"></span><br><span class="line">Transaction Summary</span><br><span class="line">===============================================================================================================================================================================================</span><br><span class="line">Install       1 Package(s)</span><br><span class="line"></span><br><span class="line">Total download size: 131 k</span><br><span class="line">Installed size: 331 k</span><br><span class="line">Downloading Packages:</span><br><span class="line">libcgroup-0.40.rc1-24.el6_9.x86_64.rpm                                                                                                                                  | 131 kB     00:00     </span><br><span class="line">Running rpm_check_debug</span><br><span class="line">Running Transaction Test</span><br><span class="line">Transaction Test Succeeded</span><br><span class="line">Running Transaction</span><br><span class="line">  Installing : libcgroup-0.40.rc1-24.el6_9.x86_64                                                                                                                                          1/1 </span><br><span class="line">  Verifying  : libcgroup-0.40.rc1-24.el6_9.x86_64                                                                                                                                          1/1 </span><br><span class="line"></span><br><span class="line">Installed:</span><br><span class="line">  libcgroup.x86_64 0:0.40.rc1-24.el6_9                                                                                                                                                         </span><br><span class="line"></span><br><span class="line">Complete!</span><br><span class="line"></span><br><span class="line">[root@localhost ~]# echo "none                    /sys/fs/cgroup         cgroup   defaults        0 0" &gt;&gt; /etc/fstab</span><br><span class="line">[root@localhost ~]#</span><br></pre></td></tr></table></figure><h2 id="一键安装shell脚本"><a href="#一键安装shell脚本" class="headerlink" title="一键安装shell脚本"></a>一键安装shell脚本</h2><p>上述一步步比较多，可以整合在一起搞一个shell进行统一处理，因此有了下面的一键安装脚本</p><blockquote><p>笔者希望在别的机器上能一键处理，自己写了个一键安装内核及docker的脚本。这里仅供给大家参考，但由于笔者水平有限，不可能写出非常完美的安装脚本，并不保证在每台机器上都能完美运行。也希望大家多多提建议，我可以改进这个脚本。</p><p>curl也可以用来下载如curl -O <a href="http://mirrors.ustc.edu.cn/docker-ce/linux/static/stable/x86_64/docker-17.06.2-ce.tgz" target="_blank" rel="noopener">http://mirrors.ustc.edu.cn/docker-ce/linux/static/stable/x86_64/docker-17.06.2-ce.tgz</a></p></blockquote><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><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>!/bin/sh</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 必须要以root帐号或sudo来运行</span><br><span class="line">wget_bin=`which wget`</span><br><span class="line">if [ -z "$wget_bin" ];then</span><br><span class="line">  echo "please install wget" &gt;&amp;2</span><br><span class="line">  exit 1</span><br><span class="line">fi</span><br><span class="line"><span class="meta">#</span> 禁用 fastestmirror 插件</span><br><span class="line">sed -i.backup 's/^enabled=1/enabled=0/' /etc/yum/pluginconf.d/fastestmirror.conf</span><br><span class="line"><span class="meta">#</span> 备份</span><br><span class="line">mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup</span><br><span class="line"><span class="meta">#</span> 使用阿里云镜像</span><br><span class="line">wget -O /etc/yum.repos.d/CentOS-Base-aliyun.repo http://mirrors.aliyun.com/repo/Centos-6.repo</span><br><span class="line"><span class="meta">#</span> 安装 EPEL 源(用于更新内核)</span><br><span class="line">elrepo="/etc/yum.repos.d/elrepo.repo"</span><br><span class="line">if [ ! -f $elrepo ]; then</span><br><span class="line">  yum -y update nss</span><br><span class="line">  rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org</span><br><span class="line">  rpm -Uvh http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 使用阿里云镜像</span><br><span class="line">if [[ ! -f /etc/yum.repos.d/epel.repo.backup ]]; then</span><br><span class="line">  mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup 2&gt;/dev/null || :</span><br><span class="line">fi</span><br><span class="line">if [[ ! -f /etc/yum.repos.d/epel-testing.repo.backup ]]; then</span><br><span class="line">  mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup 2&gt;/dev/null || :</span><br><span class="line">fi</span><br><span class="line">wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel.repo</span><br><span class="line">wget -O /etc/yum.repos.d/epel-testing.repo http://mirrors.aliyun.com/repo/epel-testing.repo</span><br><span class="line">yum clean all</span><br><span class="line">yum makecache</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 安装cgroup，docker依赖它</span><br><span class="line">if [ ! -d "/sys/fs/cgroup" ]; then</span><br><span class="line">  yum install -y libcgroup</span><br><span class="line">fi</span><br><span class="line">count=`cat /etc/fstab |grep "/sys/fs/cgroup"|grep -v grep |wc -l`</span><br><span class="line">if [ $count -eq 0 ]; then</span><br><span class="line">   echo "none                    /sys/fs/cgroup         cgroup   defaults        0 0" &gt;&gt; /etc/fstab</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 找出4.4内核的启动顺序，并自动修改/etc/grub.conf(这里有坑如果是grub配置文件用的是/boot/grub/grub.conf请自行修改)</span><br><span class="line">count=`cat /etc/grub.conf |grep "/vmlinuz-4.4.*" |grep -v grep |wc -l`</span><br><span class="line">if [ $count -eq 0 ]; then</span><br><span class="line">  yum --enablerepo=elrepo-kernel install kernel-lt -y</span><br><span class="line"> content=`cat /etc/grub.conf |grep title`</span><br><span class="line"> target_kernel=4.4</span><br><span class="line"> num=0</span><br><span class="line"> target=0</span><br><span class="line"> while read line</span><br><span class="line">   do</span><br><span class="line">        echo $line</span><br><span class="line">        if [[ "$line" == *"$target_kernel"* ]]; then</span><br><span class="line">          target=$num</span><br><span class="line">        fi</span><br><span class="line">        let num=num+1</span><br><span class="line">  done &lt;&lt;&lt; "$content"</span><br><span class="line">  sed -i 's/^default\s*=\s*[0-9]/default=$target/g' /etc/grub.conf</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">sed -i 's/^net\.ipv4\.ip_forward\s*=\s*[0-1]/net\.ipv4\.ip_forward = 1/g' /etc/sysctl.conf</span><br><span class="line"><span class="meta">#</span> 仅仅是为了消除dockerd启动时的警告日志</span><br><span class="line">echo "CentOS release 6.x (Final)" &gt; /usr/lib/os-release</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> 压轴了，安装docker</span><br><span class="line">dockerd_bin=`which dockerd`</span><br><span class="line">if [ -z "$dockerd_bin" ]; then</span><br><span class="line">  if [ ! -f "docker-17.06.2-ce.tgz" ]; then</span><br><span class="line">    wget http://mirrors.ustc.edu.cn/docker-ce/linux/static/stable/x86_64/docker-17.06.2-ce.tgz</span><br><span class="line">    tar -xzvf docker-17.06.2-ce.tgz &amp;&amp; cp docker/* /usr/bin &amp;&amp; rm -rf docker</span><br><span class="line">    count=`cat /etc/rc.local |grep dockerd | grep -v grep | wc -l`</span><br><span class="line">    if [ $count -eq 0 ]; then</span><br><span class="line">       echo "nohup dockerd &gt; /var/log/dockerd.log 2&gt;&amp;1 &amp;" &gt;&gt; /etc/rc.local</span><br><span class="line">    fi</span><br><span class="line">  fi</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">if [ ! -d "/etc/docker" ]; then</span><br><span class="line">  mkdir -p /etc/docker</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">docker_daemon_file="/etc/docker/daemon.json"</span><br><span class="line">if [ ! -f $docker_daemon_file ]; then</span><br><span class="line">  echo "&#123;\"registry-mirrors\": [\"https://docker.mirrors.ustc.edu.cn\"]&#125;" &gt; /etc/docker/daemon.json</span><br><span class="line">fi</span><br></pre></td></tr></table></figure><p>执行完记得要重启机器</p><h1 id="安装方式二"><a href="#安装方式二" class="headerlink" title="安装方式二"></a>安装方式二</h1><hr><p>为什么有安装方式二？这个说来话长，公司内部有几台服务器无法连接外网，只能先下载好安装包。这个我就写简单点了哈。<br>| 安装包名                 | 下载地址                                                     |<br>| ———————— | ———————————————————— |<br>| linux4.4.132-1内核安装包 | <a href="http://elrepo.org/linux/kernel/el6/x86_64/RPMS/kernel-lt-4.4.132-1.el6.elrepo.x86_64.rpm" target="_blank" rel="noopener">http://elrepo.org/linux/kernel/el6/x86_64/RPMS/kernel-lt-4.4.132-1.el6.elrepo.x86_64.rpm</a> |<br>| cgroup安装包             | <a href="http://mirror.centos.org/centos/6/updates/x86_64/Packages/libcgroup-0.40.rc1-24.el6_9.x86_64.rpm" target="_blank" rel="noopener">http://mirror.centos.org/centos/6/updates/x86_64/Packages/libcgroup-0.40.rc1-24.el6_9.x86_64.rpm</a> |<br>| docker安装包             | <a href="http://mirrors.ustc.edu.cn/docker-ce/linux/static/stable/x86_64/docker-17.06.2-ce.tgz" target="_blank" rel="noopener">http://mirrors.ustc.edu.cn/docker-ce/linux/static/stable/x86_64/docker-17.06.2-ce.tgz</a> |</p><ul><li>离线安装内核及cgroup</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></pre></td><td class="code"><pre><span class="line">rpm -ivh kernel-lt-4.4.132-1.el6.elrepo.x86_64.rpm</span><br><span class="line"></span><br><span class="line">rpm -ivh libcgroup-0.40.rc1-24.el6_9.x86_64.rpm</span><br></pre></td></tr></table></figure><ul><li>挂载cgroup文件系统</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">echo "none                    /sys/fs/cgroup         cgroup   defaults        0 0" &gt;&gt; /etc/fstab</span><br></pre></td></tr></table></figure><ul><li>修改grub内核启动顺序</li></ul><blockquote><p>vi /etc/grub.conf(这里有坑，可能会用/boot/grub/grub.conf)</p></blockquote><p>得确定下是否存在 /boot/grub/grub.conf如果存在那么 grub启动用的是这个文件如果不存在用的是/etc/grub.conf安装完内核后，默认会在/etc/grub.conf下添加一条记录把/etc/grub.conf下的添加的新内核的启动记录复制到/boot/grub/grub.conf文件末尾，然后把/boot/grub/grub.conf的 default=0改为default=1</p><ul><li>安装docker</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">tar -xzvf  docker-17.06.2-ce.tgz &amp;&amp; cp docker/* /usr/bin &amp;&amp; rm -rf docker</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><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mkdir -p /etc/docker </span><br><span class="line">echo -e "&#123;\n\t\"registry-mirrors\": [\"https://docker.mirrors.ustc.edu.cn\"]\n&#125;" &gt; /etc/docker/daemon.json</span><br></pre></td></tr></table></figure><ul><li>设置dockerd自动启动</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">echo &quot;nohup dockerd &gt; /var/log/dockerd.log 2&gt;&amp;1 &amp;&quot; &gt;&gt; /etc/rc.local</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><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">reboot </span><br><span class="line"></span><br><span class="line">或</span><br><span class="line"></span><br><span class="line">shutdown -r now</span><br></pre></td></tr></table></figure><h1 id="附加注意点"><a href="#附加注意点" class="headerlink" title="附加注意点"></a>附加注意点</h1><hr><h2 id="几个常见警告的解决"><a href="#几个常见警告的解决" class="headerlink" title="几个常见警告的解决"></a>几个常见警告的解决</h2><ul><li>IPv4 forwarding is disabled的警告</li></ul><blockquote><p>vi /etc/sysctl.conf</p></blockquote><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"># Controls IP packet forwarding</span><br><span class="line">net.ipv4.ip_forward = 1</span><br><span class="line">其他配置省略...</span><br></pre></td></tr></table></figure><ul><li>Could not get operating system name: Error opening /usr/lib/os-release: open /usr/lib/os-release: no such file or directory</li></ul><blockquote><p>echo “CentOS release 6.x (Final)” | tee  /usr/lib/os-release</p></blockquote><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@localhost ~]# echo "CentOS release 6.x (Final)" | tee  /usr/lib/os-release</span><br><span class="line">CentOS release 6.x (Final)</span><br></pre></td></tr></table></figure><h2 id="docker-exec-it-报错的问题"><a href="#docker-exec-it-报错的问题" class="headerlink" title="docker exec -it 报错的问题"></a>docker exec -it 报错的问题</h2><p>报的错误是rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:262: starting container process caused “open /dev/ptmx: no such file or directory “，我看了下宿主机上是有这个文件，那么应该是容器里没有的原因，目前还没查到原因。不过可以通过启动容器时指定  -v /dev:/dev 映射宿主机/dev来解决</p><p>此问题可以在启动容器的时候时候，通过<strong>-v /dev:/dev</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 run -it -d --name mynginx -p 80:80  -v /dev:/dev nginx:alpine</span><br><span class="line">docker run -it -d --name myjdk -v /dev:/dev openjdk:8-jdk-alpine</span><br></pre></td></tr></table></figure><h2 id="如果报以下错误则可以执行下yum-update"><a href="#如果报以下错误则可以执行下yum-update" class="headerlink" title="如果报以下错误则可以执行下yum update"></a>如果报以下错误则可以执行下yum update</h2><p>[root@centos ~]# docker run -it alpine:3.7 /bin/sh<br>Unable to find image ‘alpine:3.7’ locally<br>3.7: Pulling from library/alpine<br>ff3a5c916c92: Pull complete<br>Digest: sha256:e1871801d30885a610511c867de0d6baca7ed4e6a2573d506bbec7fd3b03873f<br>Status: Downloaded newer image for alpine:3.7<br>docker: Error response from daemon: mkdir /var/lib/docker/overlay2/3520bc6c5dcc7ba4dc5e2ba1419cd6250c4b6d61797da7487f20d991179ddd05-init/merged/dev/shm: permission denied.<br>See ‘docker run –help’.</p><p>那么请yum update下，注意/etc/grub.conf的内核启动顺序，要改下</p><h1 id="提供一个service脚本"><a href="#提供一个service脚本" class="headerlink" title="提供一个service脚本"></a>提供一个service脚本</h1><blockquote><p>可以方便的实现 service dockerd start,service dockerd stop，service dockerd restart</p></blockquote><p>创建一个dockerd文件，赋予可执行权限,并将该文件放到/etc/init.d即可</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><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>!/bin/sh</span><br><span class="line"><span class="meta">#</span>set -x</span><br><span class="line">BASE_HOME=/var/run</span><br><span class="line">PID_FILE=$BASE_HOME/docker.pid</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span> dockerd父进程的id,如果docker.pid文件不存在则PID值就为-1</span><br><span class="line">PID=-1</span><br><span class="line">if [ -f $PID_FILE ];then</span><br><span class="line">  PID=`cat $PID_FILE`</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">status()&#123;</span><br><span class="line">    if [ $PID -gt -1 ]; then</span><br><span class="line">       echo "dockerd is running"        </span><br><span class="line">    else</span><br><span class="line">       echo "dockerd is not running"        </span><br><span class="line">    fi</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">start() &#123;</span><br><span class="line">    if [ $PID -gt -1 ]; then</span><br><span class="line">       echo "dockerd has started,the pid is $PID"</span><br><span class="line">       return</span><br><span class="line">    fi</span><br><span class="line">    nohup dockerd &gt; /var/log/dockerd.log 2&gt;&amp;1 &amp;</span><br><span class="line">    COUNT=0</span><br><span class="line">    NUMBER=0</span><br><span class="line">    echo -e "starting...\c"</span><br><span class="line">    while [ $COUNT -lt 2 ]; do</span><br><span class="line">      echo -e ".\c"</span><br><span class="line">      sleep 0.25</span><br><span class="line">      if [ -f $PID_FILE ];then</span><br><span class="line">         PID=`cat $PID_FILE`</span><br><span class="line">      fi</span><br><span class="line">      COUNT=`ps -ef |grep $PID|grep -v grep|wc -l`</span><br><span class="line">      # dockerd父进程与docker-containerd子进程都启动</span><br><span class="line">      if [ $COUNT -ge 2 ]; then</span><br><span class="line">         echo -e "\ndockerd has started,the pid is $PID"</span><br><span class="line">         return</span><br><span class="line">      fi</span><br><span class="line">      if [ $NUMBER -gt 20 ]; then</span><br><span class="line">         break</span><br><span class="line">      fi</span><br><span class="line">      NUMBER=$NUMBER+1</span><br><span class="line">    done</span><br><span class="line">    </span><br><span class="line">    echo -e "\ndockerd start failed"        </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">stop() &#123;</span><br><span class="line">   if [ $PID -eq -1 ]; then</span><br><span class="line">    echo "dockerd is not running"</span><br><span class="line">    return</span><br><span class="line">   fi</span><br><span class="line">   </span><br><span class="line"><span class="meta">   #</span> PIDS得到的是dockerd父进程及docker-containerd子进程号</span><br><span class="line"><span class="meta">   #</span> sort -r是为了先杀子进程，再杀父进程</span><br><span class="line">   PIDS=`ps -ef|grep $PID|grep -v grep|awk '&#123;print $2&#125;'|sort -r`</span><br><span class="line"></span><br><span class="line">   for VAR_PID in $PIDS ; do</span><br><span class="line">      kill $VAR_PID &gt; /dev/null 2&gt;&amp;1</span><br><span class="line">   done</span><br><span class="line">   </span><br><span class="line"><span class="meta">   #</span> 因为有dockerd父进程和docker-containerd子进程，因此预先设置COUNT=2</span><br><span class="line">   COUNT=2</span><br><span class="line">   echo -e "stoping...\c"</span><br><span class="line">   while [ $COUNT -gt 0 ]; do</span><br><span class="line">      echo -e ".\c"</span><br><span class="line">      sleep 0.05</span><br><span class="line">      COUNT=`ps -ef |grep $PID |grep -v grep |wc -l`</span><br><span class="line">      if [ $COUNT -eq 0 ]; then</span><br><span class="line">        echo -e "\ndockerd has been stoped"</span><br><span class="line">        break</span><br><span class="line">      fi</span><br><span class="line">   done</span><br><span class="line"><span class="meta">   #</span> restart的时候会存在无法启动dockerd进程的问题。(因为PID值还是原先停掉的dockerd进程id)</span><br><span class="line">   PID=-1</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">restart() &#123;</span><br><span class="line">   stop</span><br><span class="line">   start</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">case "$1" in</span><br><span class="line">    'start')</span><br><span class="line">        start</span><br><span class="line">        ;;</span><br><span class="line">    'stop')</span><br><span class="line">        stop</span><br><span class="line">        ;;</span><br><span class="line">    'status')</span><br><span class="line">        status</span><br><span class="line">        ;;</span><br><span class="line">    'restart')</span><br><span class="line">        restart</span><br><span class="line">        ;;</span><br><span class="line">    *)</span><br><span class="line">    echo "usage: $0 &#123;start|stop|restart|status&#125;"</span><br><span class="line">    exit 1</span><br><span class="line">    ;;</span><br><span class="line">esac</span><br></pre></td></tr></table></figure><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>踩了好多坑，还是一点点解决了，有点抓狂，有点惊喜；还是得多多总结，多多把遇到的坑，怎么解决的经历整理成文，分享出来，以免更多人踩同样的坑。希望此文对有需要在CentOS6.6或CentOS6.x上安装docker的读者有一些帮助。</p><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><ul><li>Get Docker CE for CentOS <a href="https://docs.docker.com/install/linux/docker-ce/centos/" target="_blank" rel="noopener">https://docs.docker.com/install/linux/docker-ce/centos/</a></li><li>Install Docker CE from binaries <a href="https://docs.docker.com/install/linux/docker-ce/binaries/" target="_blank" rel="noopener">https://docs.docker.com/install/linux/docker-ce/binaries/</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h1&gt;&lt;hr&gt;
&lt;p&gt;由于笔者所在公司无论是开发、测试环境，还是准生产环境、生产环境，使用的都是CentOS6.6。要想按照新版本的Docker就必须升级Linux内核。因此，此文讲解如何升级Linux内核，以及在升级完内核后，如何安装Docker17.06.2-ce。其他版本的docker笔者没有尝试，应该也是可行的。毕竟内核升级到4.4.132-1了&lt;/p&gt;
    
    </summary>
    
      <category term="Docker&amp;Kubernetes" scheme="http://jaychang.cn/categories/Docker-Kubernetes/"/>
    
    
      <category term="Docker" scheme="http://jaychang.cn/tags/Docker/"/>
    
      <category term="Linux" scheme="http://jaychang.cn/tags/Linux/"/>
    
      <category term="CentOS" scheme="http://jaychang.cn/tags/CentOS/"/>
    
  </entry>
  
  <entry>
    <title>Docker下Zookeeper集群搭建</title>
    <link href="http://jaychang.cn/2018/05/05/Docker%E4%B8%8BZookeeper%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA/"/>
    <id>http://jaychang.cn/2018/05/05/Docker下Zookeeper集群搭建/</id>
    <published>2018-05-05T09:32:00.000Z</published>
    <updated>2019-07-07T12:05:44.071Z</updated>
    
    <content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>自己了解一些Docker容器技术，想在自己机器上搭建一个zookeeper集群，以前在虚拟机上有过实践经验，这次就想着在Docker下也搞一个Zookeeper集群。Docker的相关介绍这里就不多讲了，大家可以通过搜索引擎查阅相关资料。</p><img src="/2018/05/05/Docker下Zookeeper集群搭建/00.jpg"><a id="more"></a><h1 id="zookeeper简介"><a href="#zookeeper简介" class="headerlink" title="zookeeper简介"></a>zookeeper简介</h1><p>Apache ZooKeeper是Apache的一个软件项目，它提供了一个开放源码的分布式配置服务、同步服务和大型分布式系统的命名注册服务。ZooKeeper是Hadoop的一个子项目，但目前是它本身就是一个顶级项目。</p><h1 id="安装包下载、镜像下载"><a href="#安装包下载、镜像下载" class="headerlink" title="安装包下载、镜像下载"></a>安装包下载、镜像下载</h1><p><a href="http://archive.apache.org/dist/zookeeper/zookeeper-3.4.11/zookeeper-3.4.11.tar.gz" target="_blank" rel="noopener">http://archive.apache.org/dist/zookeeper/zookeeper-3.4.11/zookeeper-3.4.11.tar.gz</a></p><p>docker pull zookeeper</p><p>到写文章时，pull下来zookeeper的版本也是3.4.11，后续pull下来可能不是3.4.11了，需注意，后续新版本有配置变更也请留意</p><h1 id="Zookeeper集群及容灾"><a href="#Zookeeper集群及容灾" class="headerlink" title="Zookeeper集群及容灾"></a>Zookeeper集群及容灾</h1><h2 id="集群"><a href="#集群" class="headerlink" title="集群"></a>集群</h2><p>Zookeeper集群部署并非一定需要奇数台服务器，任意台Zookeeper服务器都能部署且能够正常运行。</p><p>一个Zookeeper集群如果要对外提供可用的服务，那么集群中必须要有过半的机器正常工作并且彼此之间能够正常通信。基于这个特性，如果想搭建一个能够允许N台机器挂掉的集群，那么就需要部署一个由2XN+1台服务器构成的Zookeeper集群。因此，一个由5台机器构成的Zookeeper集群，能够在挂掉2台机器后依然正常工作，而如果是一个由6台服务器构成的Zookeeper集群，同样只能够挂掉2台机器，因为如果挂掉3台，剩下的机器就无法实现过半了。</p><p>因此，从上面的讲解中，我们可以看出，对于一个由6台服务器组成的Zookeeper集群来说，和一个由5台服务器构成的Zookeeper集群相比，其在容灾能力上没有任何明显的提升。基于这个原因，Zookeeper集群通常设计部署成奇数台服务器即可。</p><h2 id="容灾"><a href="#容灾" class="headerlink" title="容灾"></a>容灾</h2><p>容灾主要是两个个方面，一个是单点问题，Zookeeper的单点问题可以通过搭建集群来解决。二是Zookeeper需要保证集群内服务器过半存活问题，可以考虑三机房部署(N1=N总/3,N2=N总/3, N3=N总-N1-N2,其中N代表机器数量)。对于双机房部署，可以将过半的Zookeeper部署在主机房。</p><h1 id="Zookeeper官方镜像提供的环境变量"><a href="#Zookeeper官方镜像提供的环境变量" class="headerlink" title="Zookeeper官方镜像提供的环境变量"></a>Zookeeper官方镜像提供的环境变量</h1><p>注意跟系统属性配置方式区分开来，这个启动容器时可制定的环境变量与系统属性配置没有关系</p><table><thead><tr><th>启动容器时可指定的环境变量名</th><th>默认值</th></tr></thead><tbody><tr><td>ZOO_TICK_TIME</td><td>2000</td></tr><tr><td>ZOO_INIT_LIMIT</td><td>5</td></tr><tr><td>ZOO_SYNC_LIMIT</td><td>2</td></tr><tr><td>ZOO_MAX_CLIENT_CNXNS</td><td>60</td></tr><tr><td>ZOO_STANDALONE_ENABLED</td><td>false</td></tr><tr><td>ZOO_MY_ID</td><td>如果是在复制模式下该参数是必须的，要么在启动容器时，指定此环境变量。要么在数据目录的myid文件里指定</td></tr><tr><td>ZOO_SERVERS</td><td>如果是在复制模式下该参数是必须的，要么在启动容器时，指定此环境变量。要么在zoo.cfg配置文件里指定 。This variable allows you to specify a list of machines of the Zookeeper ensemble. Each entry has the form of <code>server.id=host:port:port</code>. Entries are separated with space. Do note that this variable will not have any effect if you start the container with a <code>/conf</code> directory that already contains the <code>zoo.cfg</code> file.</td></tr></tbody></table><h1 id="Zookeeper简单部署之使用Docker方式"><a href="#Zookeeper简单部署之使用Docker方式" class="headerlink" title="Zookeeper简单部署之使用Docker方式"></a>Zookeeper简单部署之使用Docker方式</h1><p>zookeeper官方镜像，数据目录是/data,日志目录是/datalog，配置目录是/conf。这里官方文档里给出了解释，如果你映射了配置目录/conf</p><p>如果没有映射配置文件目录或映射配置文件也没关系，zookeeper官方镜像提供了以下启动容器时的环境变量参数</p><p>启动一个zookeeper容器</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"><span class="meta">$</span> docker run --name some-zookeeper --restart always -d zookeeper</span><br></pre></td></tr></table></figure><p>启动一个应用的容器，这个应用是需要用到zookeeper的，可以通过–link some-zookeeper:zookeeper连接到上一步启动的zookeeper容器。some-zookeeper冒号后的zookeeper是别名</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"><span class="meta">$</span> docker run --name some-app --link some-zookeeper:zookeeper -d application-that-uses-zookeeper</span><br></pre></td></tr></table></figure><p>通过命令行客户端连接zookeeper，由于这里加了–rm参数，使得退出容器，容器马上会被删掉</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> docker run -it --rm --link some-zookeeper:zookeeper zookeeper zkCli.sh -server zookeeper</span><br><span class="line"><span class="meta">#</span> 可以直接指定ip:port</span><br><span class="line"><span class="meta">$</span> docker run -it --rm --link some-zookeeper:zookeeper zookeeper zkCli.sh -server 192.168.56.101:2181</span><br><span class="line"><span class="meta">#</span> 连接集群</span><br><span class="line"><span class="meta">$</span> docker run -it --rm --link some-zookeeper:zookeeper zookeeper zkCli.sh -server 192.168.56.101:2181,192.168.56.101:2182,192.168.56.101:2183</span><br></pre></td></tr></table></figure><h1 id="Zookeeper集群部署之Use-Docker-Compose"><a href="#Zookeeper集群部署之Use-Docker-Compose" class="headerlink" title="Zookeeper集群部署之Use Docker Compose"></a>Zookeeper集群部署之Use Docker Compose</h1><p>stack.yml定义如下：</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></pre></td><td class="code"><pre><span class="line">version: &apos;3.1&apos;</span><br><span class="line"></span><br><span class="line">services:</span><br><span class="line">  zoo1:</span><br><span class="line">    image: zookeeper</span><br><span class="line">    restart: always</span><br><span class="line">    hostname: zoo1</span><br><span class="line">    ports:</span><br><span class="line">      - 2181:2181</span><br><span class="line">    environment:</span><br><span class="line">      ZOO_MY_ID: 1</span><br><span class="line">      ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888</span><br><span class="line"></span><br><span class="line">  zoo2:</span><br><span class="line">    image: zookeeper</span><br><span class="line">    restart: always</span><br><span class="line">    hostname: zoo2</span><br><span class="line">    ports:</span><br><span class="line">      - 2182:2181</span><br><span class="line">    environment:</span><br><span class="line">      ZOO_MY_ID: 2</span><br><span class="line">      ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=0.0.0.0:2888:3888 server.3=zoo3:2888:3888</span><br><span class="line"></span><br><span class="line">  zoo3:</span><br><span class="line">    image: zookeeper</span><br><span class="line">    restart: always</span><br><span class="line">    hostname: zoo3</span><br><span class="line">    ports:</span><br><span class="line">      - 2183:2181</span><br><span class="line">    environment:</span><br><span class="line">      ZOO_MY_ID: 3</span><br><span class="line">      ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=0.0.0.0:2888:3888</span><br></pre></td></tr></table></figure><p>端口2181、2182、2183将会暴露出来</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">docker-compose -f stack.yml up</span><br></pre></td></tr></table></figure><p>这种方式是一种伪集群方式，只适合在开发、测试环境中部署；生产环境是强烈不建议的，生产环境建议每个zookeeper实例部署在不同的物理机上。如果zookeeper实例部署在在同一物理机上的不同虚拟机，仍然不是严格意义的完全冗余。</p><h1 id="Zookeeper集群部署之普通Docker部署方式"><a href="#Zookeeper集群部署之普通Docker部署方式" class="headerlink" title="Zookeeper集群部署之普通Docker部署方式"></a>Zookeeper集群部署之普通Docker部署方式</h1><h2 id="zk容器规划"><a href="#zk容器规划" class="headerlink" title="zk容器规划"></a>zk容器规划</h2><p>通过表格形式来规划下各个zookeeper实例所需的myid，端口号，以及需要在宿主机上的对应的配置文件</p><table><thead><tr><th>容器名称</th><th>ip</th><th>myid</th><th>端口1</th><th>端口2</th><th>端口3</th><th>宿主机配置文件</th><th>宿主机上的data目录</th></tr></thead><tbody><tr><td>zk1</td><td>ip1</td><td>1</td><td>2181</td><td>2881</td><td>3881</td><td>/opt/data/zk1/conf/zoo.cfg</td><td>/opt/data/zk1/data</td></tr><tr><td>zk2</td><td>ip2</td><td>2</td><td>2182</td><td>2882</td><td>3882</td><td>/opt/data/zk2/conf/zoo.cfg</td><td>/opt/data/zk2/data</td></tr><tr><td>zk3</td><td>ip3</td><td>3</td><td>2183</td><td>2883</td><td>3883</td><td>/opt/data/zk3/conf/zoo.cfg</td><td>/opt/data/zk3/data</td></tr></tbody></table><p>上面表格显示有点问题，还是提供一张图片清楚一些，那么看图吧</p><img src="/2018/05/05/Docker下Zookeeper集群搭建/01.png"><p>端口1用于对client端提供服务，端口2用于选举leader，端口3用于集群内通讯使用(Leader会监听此端口),zk实例数应为大于等于3的奇数，如3、5、7。。。不宜太多。由于我是在同一台机器上启动的Zookeeper容器，所以ip1,ip2,ip3都是一样的。在同一台机器上启的话，是伪集群。</p><h2 id="宿主机上创建相应目录"><a href="#宿主机上创建相应目录" class="headerlink" title="宿主机上创建相应目录"></a>宿主机上创建相应目录</h2><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">mkdir -p /opt/data/zk1/data</span><br><span class="line">mkdir -p /opt/data/zk2/data</span><br><span class="line">mkdir -p /opt/data/zk3/data</span><br><span class="line"></span><br><span class="line">mkdir -p /opt/data/zk1/conf</span><br><span class="line">mkdir -p /opt/data/zk2/conf</span><br><span class="line">mkdir -p /opt/data/zk3/conf</span><br><span class="line"></span><br><span class="line">将zookeeper-3.4.11.tar.gz，解压出zoo_sample.cfg,并重命名为zoo.cfg</span><br><span class="line">将zoo.cfg传到/opt/data/zk1/conf,/opt/data/zk1/conf,/opt/data/zk1/conf目录下</span><br></pre></td></tr></table></figure><p>我实验的时候，是在同一台机器上操作的，如果是在不同的机器上，请分别在不同机器上创建目录</p><h2 id="创建myid文件"><a href="#创建myid文件" class="headerlink" title="创建myid文件"></a>创建myid文件</h2><p>分别在/opt/data/zk1/data,/opt/data/zk2/data,/opt/data/zk3/data目录下创建myid文件，并写入相应的id</p><table><thead><tr><th>name</th><th style="text-align:left">myid file</th><th>server id</th></tr></thead><tbody><tr><td>zk1</td><td style="text-align:left">/opt/data/zk1/data/myid</td><td>1</td></tr><tr><td>zk2</td><td style="text-align:left">/opt/data/zk2/data/myid</td><td>2</td></tr><tr><td>zk3</td><td style="text-align:left">/opt/data/zk3/data/myid</td><td>3</td></tr></tbody></table><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></pre></td><td class="code"><pre><span class="line">cd /opt/data/zk1/data/ &amp;&amp; echo 1 |tee myid</span><br><span class="line"></span><br><span class="line">cd /opt/data/zk2/data/ &amp;&amp; echo 2 |tee myid</span><br><span class="line"></span><br><span class="line">cd /opt/data/zk3/data/ &amp;&amp; echo 3 |tee myid</span><br></pre></td></tr></table></figure><h2 id="zoo-cfg配置"><a href="#zoo-cfg配置" class="headerlink" title="zoo.cfg配置"></a>zoo.cfg配置</h2><p>以下配置只有clientPort是不同的，因为我是在同一台机器上跑的容器，端口一样会有冲突；如果在不同机器上跑，那clientPort可以是一样的。生产环境建议是在不同的机器上跑。分别修改/opt/data/zk1/conf/zoo.cfg，/opt/data/zk2/conf/zoo.cfg，/opt/data/zk3/conf/zoo.cfg</p><h3 id="zk1的配置zoo-cfg"><a href="#zk1的配置zoo-cfg" class="headerlink" title="zk1的配置zoo.cfg"></a>zk1的配置zoo.cfg</h3><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"># The number of milliseconds of each tick</span><br><span class="line">tickTime=2000</span><br><span class="line"># The number of ticks that the initial</span><br><span class="line"># synchronization phase can take</span><br><span class="line">initLimit=10</span><br><span class="line"># The number of ticks that can pass between</span><br><span class="line"># sending a request and getting an acknowledgement</span><br><span class="line">syncLimit=5</span><br><span class="line"># the directory where the snapshot is stored.</span><br><span class="line"># do not use /tmp for storage, /tmp here is just</span><br><span class="line"># example sakes.</span><br><span class="line">dataDir=/data</span><br><span class="line">dataLogDir=/datalog</span><br><span class="line"># the port at which the clients will connect</span><br><span class="line">clientPort=2181</span><br><span class="line"># the maximum number of client connections.</span><br><span class="line"># increase this if you need to handle more clients</span><br><span class="line">#maxClientCnxns=60</span><br><span class="line">#</span><br><span class="line"># Be sure to read the maintenance section of the</span><br><span class="line"># administrator guide before turning on autopurge.</span><br><span class="line">#</span><br><span class="line"># http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance</span><br><span class="line">#</span><br><span class="line"># The number of snapshots to retain in dataDir</span><br><span class="line">#autopurge.snapRetainCount=3</span><br><span class="line"># Purge task interval in hours</span><br><span class="line"># Set to &quot;0&quot; to disable auto purge feature</span><br><span class="line">#autopurge.purgeInterval=1</span><br><span class="line"></span><br><span class="line">server.1=192.168.56.101:2881:3881</span><br><span class="line">server.2=192.168.56.101:2882:3882</span><br><span class="line">server.3=192.168.56.101:2883:3883</span><br></pre></td></tr></table></figure><h3 id="zk2的配置zoo-cfg"><a href="#zk2的配置zoo-cfg" class="headerlink" title="zk2的配置zoo.cfg"></a>zk2的配置zoo.cfg</h3><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></pre></td><td class="code"><pre><span class="line"># The number of milliseconds of each tick</span><br><span class="line">tickTime=2000</span><br><span class="line"># The number of ticks that the initial </span><br><span class="line"># synchronization phase can take</span><br><span class="line">initLimit=10</span><br><span class="line"># The number of ticks that can pass between </span><br><span class="line"># sending a request and getting an acknowledgement</span><br><span class="line">syncLimit=5</span><br><span class="line"># the directory where the snapshot is stored.</span><br><span class="line"># do not use /tmp for storage, /tmp here is just </span><br><span class="line"># example sakes.</span><br><span class="line">dataDir=/data         </span><br><span class="line">dataLogDir=/datalog</span><br><span class="line"># the port at which the clients will connect</span><br><span class="line">clientPort=2182</span><br><span class="line"># the maximum number of client connections.</span><br><span class="line"># increase this if you need to handle more clients</span><br><span class="line">#maxClientCnxns=60</span><br><span class="line">#</span><br><span class="line"># Be sure to read the maintenance section of the </span><br><span class="line"># administrator guide before turning on autopurge.</span><br><span class="line">#</span><br><span class="line"># http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance</span><br><span class="line">#</span><br><span class="line"># The number of snapshots to retain in dataDir</span><br><span class="line">#autopurge.snapRetainCount=3</span><br><span class="line"># Purge task interval in hours</span><br><span class="line"># Set to &quot;0&quot; to disable auto purge feature</span><br><span class="line">#autopurge.purgeInterval=1</span><br><span class="line">server.1=192.168.56.101:2881:3881</span><br><span class="line">server.2=192.168.56.101:2882:3882</span><br><span class="line">server.3=192.168.56.101:2883:3883</span><br></pre></td></tr></table></figure><h3 id="zk3的配置zoo-cfg"><a href="#zk3的配置zoo-cfg" class="headerlink" title="zk3的配置zoo.cfg"></a>zk3的配置zoo.cfg</h3><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></pre></td><td class="code"><pre><span class="line"># The number of milliseconds of each tick</span><br><span class="line">tickTime=2000</span><br><span class="line"># The number of ticks that the initial </span><br><span class="line"># synchronization phase can take</span><br><span class="line">initLimit=10</span><br><span class="line"># The number of ticks that can pass between </span><br><span class="line"># sending a request and getting an acknowledgement</span><br><span class="line">syncLimit=5</span><br><span class="line"># the directory where the snapshot is stored.</span><br><span class="line"># do not use /tmp for storage, /tmp here is just </span><br><span class="line"># example sakes.</span><br><span class="line">dataDir=/data         </span><br><span class="line">dataLogDir=/datalog</span><br><span class="line"># the port at which the clients will connect</span><br><span class="line">clientPort=2183</span><br><span class="line"># the maximum number of client connections.</span><br><span class="line"># increase this if you need to handle more clients</span><br><span class="line">#maxClientCnxns=60</span><br><span class="line">#</span><br><span class="line"># Be sure to read the maintenance section of the </span><br><span class="line"># administrator guide before turning on autopurge.</span><br><span class="line">#</span><br><span class="line"># http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance</span><br><span class="line">#</span><br><span class="line"># The number of snapshots to retain in dataDir</span><br><span class="line">#autopurge.snapRetainCount=3</span><br><span class="line"># Purge task interval in hours</span><br><span class="line"># Set to &quot;0&quot; to disable auto purge feature</span><br><span class="line">#autopurge.purgeInterval=1</span><br><span class="line">server.1=192.168.56.101:2881:3881</span><br><span class="line">server.2=192.168.56.101:2882:3882</span><br><span class="line">server.3=192.168.56.101:2883:3883</span><br></pre></td></tr></table></figure><h2 id="启动容器"><a href="#启动容器" class="headerlink" title="启动容器"></a>启动容器</h2><p>接下来就可以启动容器了，我是在同一台机器上启动的，用的docker的host网络。生产环境建议在不同的机器上启动zookeeper容器。</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></pre></td><td class="code"><pre><span class="line">docker run --name zk1 --net host --restart always -d -v/opt/data/zk1/data:/data -v /opt/data/zk1/conf/zoo.cfg:/conf/zoo.cfg -p 2181:2181 -p 2881:2881 -p 3881:3881 zookeeper</span><br><span class="line"></span><br><span class="line">docker run --name zk2 --net host --restart always -d -v/opt/data/zk2/data:/data -v /opt/data/zk2/conf/zoo.cfg:/conf/zoo.cfg -p 2182:2182 -p 2882:2882 -p 3882:3882 zookeeper</span><br><span class="line"></span><br><span class="line">docker run --name zk3 --net host --restart always -d -v/opt/data/zk3/data:/data -v /opt/data/zk3/conf/zoo.cfg:/conf/zoo.cfg -p 2183:2183 -p 2883:2883 -p 3883:3883 zookeeper</span><br></pre></td></tr></table></figure><h1 id="Zookeeper配置详解"><a href="#Zookeeper配置详解" class="headerlink" title="Zookeeper配置详解"></a>Zookeeper配置详解</h1><p>以下有些默认值在新版本中可能已经改成其他值了，这个是需要注意的。这里还未去验证确切的默认值</p><h2 id="基础配置"><a href="#基础配置" class="headerlink" title="基础配置"></a>基础配置</h2><table><thead><tr><th>配置项</th><th>解释</th></tr></thead><tbody><tr><td>clientPort</td><td>该参数无默认值，必须配置，不支持系统属性方式配置。参数clientPort用于配置当前服务器对外的服务器端口，客户端会通过该端口和Zookeeper服务器创建连接，一般设置为2181。每台Zookeeper服务器都可以配置任意可用的端口，同时，集群中的所有服务器不需要保持clientPort端口一致。</td></tr><tr><td>dataDir</td><td>该参数无默认值，必须配置，不支持系统属性方式配置。参数dataDir用于配置Zookeeper服务器存储快照文件的目录。默认情况下，如果没有配置参数dataLogDir,那么事务日志也会存储在这个目录中。考虑到事务日志的写性能直接影响Zookeeper整体的服务能力，因此建议同时通过参数dataLogDir来配置Zookeeper事务日志的存储目录。</td></tr><tr><td>tickTime</td><td>该参数有默认值:3000，单位是毫秒(ms)，可以不配置，不支持系统属性方式配置。参数tickTime用于配置Zookeeper中最小事件单元的长度，很多运行时的时间间隔都是使用tickTime的倍数来表示的。例如，Zookeeper中会话的最小超时时间默认是2*tickTime.</td></tr></tbody></table><h2 id="高级配置"><a href="#高级配置" class="headerlink" title="高级配置"></a>高级配置</h2><p>系统属性方式配置：即在Java中，可以通过在启动的命令行参数中添加-D参数来达到配置系统属性的目的</p><p>例如 -Djava.library.path=/home/admin/jdk/lib， 就是通过系统属性来配置java.library.path的。</p><table><thead><tr><th>配置项</th><th>解释</th></tr></thead><tbody><tr><td>dataLogDir</td><td>该参数有默认值:dataDir,可以不配置，不支持系统属性方式配置。参数dataLogDir用于配置Zookeeper服务器存储事务日志文件的目录。默认情况下，Zookeeper会将事务日志文件和快照数据存储在同一个目录中，使用者应尽量将这两者的目录区分开来。另外，如果条件允许，可以将事务日志的存储配置在一个单独的磁盘上。事务日志记录对于磁盘的性能要求非常高，为了保证数据的一致性，Zookeeper在返回客户端事务请求响应之前，必须将本次请求对应的事务日志写入到磁盘中。因此事务日志写入的性能直接决定了Zookeeper在处理事务请求时的吞吐。针对同一块磁盘的其他并发读写操作(例如Zookeeper运行时日志输出和操作系统自身的读写等)，尤其是数据快照操作，会极大的影响事务日志的写性能。因此尽量给事务日志的输出配置一个单独的磁盘或是挂载点，将极大地提升Zookeeper的整体性能</td></tr><tr><td>initLimit</td><td>该参数有默认值：10，即表示是参数tickTime值的10倍，必须配置，且需要配置一个正整数，不支持系统属性方式配置。该参数用于配置Leader服务器等待Follower启动，并完成数据同步的时间。Follower服务器在启动过程中，会与Leader建立连接并完成对数据的同步，从而确定自己对外提供服务的起始状态。通常情况下，运维人员不用太在意这个参数的配置，使用期默认值即可。但如果随着Zookeeper集群管理的数据量增大，Follower服务器在启动的时候，从Leader上进行同步数据的时间也会相应变长，于是无法在较短的时间完成数据同步。因此，在这种情况下，有必要适当调大这个参数。</td></tr><tr><td>syncLimit</td><td>该参数有默认值：5，即表示是参数tickTime值的5倍，必须配置，且需要配置一个正整数，不支持系统属性当时配置。该参数用于配置Leader服务器和Follower之间进行心跳检测的最大延时事件。在Zookeeper集群运行过程中，Leader服务器会与所有的Follower进行心跳检测来确定该服务器是否存活。如果Leader服务器在syncLimit时间内无法获取到Follower的心跳检测响应，那么Leader就会认为该Follower已经脱离了和自己的同步。通常情况下，运维人员使用该参数的默认值即可，但如果部署Zookeeper集群的网络环境质量较低(例如网络延时较大或丢包严重)，那么可以适当调大这个参数。</td></tr><tr><td>snapCount</td><td>该参数有默认值:100000,可以不配置，仅支持系统属性方式配置：zookeeper.snapCount。参数snapCount用于配置相邻两次数据快照之间的事务操作次数，即Zookeeper会在snapCount次事务操作之后进行一次数据快照。</td></tr><tr><td>preAllocSize</td><td>该参数有默认值：65536，单位是KB，即64MB，可以不配置，仅支持系统属性方式配置：zookeeper.preAllocSize。参数preAlloSize用于配置Zookeeper事务日志文件预分配的磁盘空间大小。通常情况下，我们使用Zookeeper的默认配置65536KB即可，但是如果我们将参数snapCount设置得比默认值更小或更大，那么preAllocSize参数也要随之做出变更。举例来说：如果我们将snapCount的值设置为500，同时预估每次事务操作的数据量大小至多1KB，那么参数preAllocSize设置为500就足够了。</td></tr><tr><td>minSessionTimeout/maxSessionTimeout</td><td>这两个参数有默认值，分别是参数tickTime值的2倍和20倍，即默认的会话超时时间在2<em>tickTime~20</em>tickTime范围内，单位毫秒，可以不配置，不支持系统属性方式配置。这两个参数用于服务端对客户端会话的超时时间进行限制，如果客户端设置的超时时间不在该范围内，那么会被服务端强制设置为最大或最小超时时间。</td></tr><tr><td>maxClientCnxns</td><td>该参数有默认值：60，可以不配置，不支持系统属性方式配置。从Socket层面限制单个客户端与单台服务器之间的并发连接数，即以IP地址粒度来进行连接数的限制。如果将该参数设置为0，则表示对连接数不做任何限制。需要注意该连接数限制选项的适用范围，其仅仅是对单台客户端机器与单台Zookeeper服务器之间的连接数限制，并不能控制所有客户端的连接数总和。另外，在3.4.0版本以前该参数的默认值都是10，从3.4.0版本开始变成了60，因此运维人员尤其需要注意这个变化，以防Zookeeper版本变化带来服务器连接数限制变化的隐患。</td></tr><tr><td>jute.maxbuffer</td><td>该参数有默认值：1048575，单位是字节，可以不配置，仅支持系统属性方式配置：jute.maxbuffer。该参数用于配置单个数据节点(ZNode)上可以存储的最大数据量大小。通常情况下，运维人员不需要改动该参数，同时考虑到Zookeeper上不适宜存储太多的数据，往往还需要将该参数设置得更小。需要注意的是，在变更该参数的时候，需要在Zookeeper集群的所有机器以及所有的客户端上均设置才能生效。</td></tr><tr><td>clientPortAddress</td><td>该参数没有默认值：可以不配置，不支持系统属性方式配置。针对那些多网卡的机器，该参数允许为每个IP地址制定不同的监听端口。</td></tr><tr><td>server.id=host:port:port</td><td>该参数没有默认值，在单机模式下可以不配置，不支持系统属性方式配置。该参数用于配置组成Zookeeper集群的及其列表，其中id即为ServerID，与每台服务器myid文件中的数字相对应。同时，在该参数中，会配置两个端口：第一个端口用于指定Follower服务器与Leader进行运行时通信和数据同步时所使用的端口，第二个端口则专门用于进行Leader选举过程中的投票通信。在Zookeeper服务器启动的时候，其会根据myid文件中配置的ServerID来确定自己是哪台服务器，并使用对应配置的端口来进行启动。如果在实际使用过程中，需要在同一台服务器上部署多个Zookeeper实例来构成伪集群的话，那么这些端口都需要配置成不同。例如 <code>server.1=192.168.0.1:2777:3777</code>, <code>server.1=192.168.0.1:2888:3888</code>, <code>server.1=192.168.0.1:2999:3999</code> 不过这个参数在3.5.0版本开始，有所改变了，具体查看zookeeper官方文档</td></tr><tr><td>autopurge.snapRetainCount</td><td>该参数有默认值：3，可以不配置，不支持系统属性方式配置。从3.4.0版本开始，Zookeeper提供了对历史事务日志和快照数据自动清理的支持。参数autopurge.snapRetainCount用于配置Zookeeper在自动清理的时候需要保留的快照数据文件数量和对应的事务日志万能键。需要注意的是，并不是磁盘上的所有事务日志和快照数据文件都可以被清理掉–那样的话将无法恢复数据。因此参数autopurge.snapRetainCount的最小值是3，如果配置的autopurge.snapRetainCount值小于3的话，那么会被自动调整到3，即至少需要保留3个快照数据文件和对应的事务日志文件</td></tr><tr><td>autopurge.purgeInteval</td><td>该参数有默认值：0，单位是小时，可以不配置，不支持系统属性方式配置。参数autopurge.purgeInterval和参数autopurge.snapRetainCount配套使用，用于配置Zookeeper进行历史文件自动清理的频率。如果配置该值为0或者负数，那么就表明不需要开启定时清理功能。Zookeeper默认不开启这项功能。</td></tr><tr><td>fsync.warningthresholdms</td><td>该参数有默认值：1000，单位是毫秒，可以不配置，仅支持系统属性方式配置：fsync.warningthresholdms。参数fsync.warningthresholdms用于配置Zookeeper进行事务日志fsync操作时消耗时间的报警阈值。一旦进行一个fsync操作消耗的事件大于参数fsync.warningthresholdms指定的值，那么就在日志中打印出报警日志。</td></tr><tr><td>forceSync</td><td>该参数有默认值：yes，可以不配置，可选配置项为<code>yes</code>和<code>no</code>，仅支持系统属性方式配置：zookeeper.forceSync。该参数用于配置Zookeeper服务器是否在事务提交的时候，将日志写入操作强制刷入磁盘(即调用java.nio.channels.FileChannel.force接口)，默认情况下是<code>yes</code>，即每次事务日志写入操作都会实时刷入磁盘。如果将其设置为<code>no</code>。则能一定程度的提高Zookeeper的写性能，但同时也会存在类似于机器断电这样的安全风险。</td></tr><tr><td>globalOutstandingLimit</td><td>该参数有默认值：1000，可以不配置，仅支持系统属性方式配置：zookeeper.globalOutstandingLimit。参数globalOutstandingLimit用于配置Zookeeper服务器最大请求堆积数量。在Zookeeper服务器运行的过程中，客户端会源源不断的将请求发送到服务端，为了防止服务端资源(包括CPU,内存和网络等)耗尽，服务端必须限制同时处理的请求数，即最大请求堆积数量。</td></tr><tr><td>leaderServes</td><td>该参数有默认值：yes，可以不配置，可选配置项为<code>yes</code>和<code>no</code>，仅支持系统属性方式配置：zookeeper.leaderServes。该参数用于配置Leader服务器是否能够接受客户端的连接，即是否允许Leader向客户端提供服务，默认情况下，Leader服务器能够接受并处理客户端的所有读写请求。在Zookeeper的架构设计中，Leader服务器主要用来进行对事务更新请求的协调以及集群本身的运行时协调，因此，可以设置让Leader服务器不接受客户端的连接，以使其专注于进行分布式协调。</td></tr><tr><td>skipAcl</td><td>该参数有默认值：no，可以不配置，可选配置项为<code>yes</code>和<code>no</code>，仅支持系统属性方式配置：zookeeper.skipACL。该参数用于配置Zookeeper服务器是否跳过ACL权限检查，默认情况下是<code>no</code>，即会对每一个客户端请求进行权限检查。如果将其设置为<code>yes</code>，则能一定程度的提高Zookeeper的读写性能，但同时也会向所有客户端开放Zookeeper的数据，包括那些之前设置过ACL权限的数据节点，也将不再接收权限控制。</td></tr><tr><td>xncTimeout</td><td>该参数有默认值：5000，单位是毫秒，可以不配置，仅支持系统属性方式配置：zookeeper.cnxTimeout。该参数用于配置在Leader选举过程中，各服务器之间进行TCP连接创建的超时时间。</td></tr><tr><td>electionAlg</td><td>在之前的版本中，可以使用该参数来配置选择Zookeeper进行Leader选举时所使用的算法，但从3.4.0版本开始，Zookeeper废弃了其他选举算法，只留下了FastLeaderElection算法，因此该参数目前看来没有用了。</td></tr></tbody></table><h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><p><a href="https://hub.docker.com/_/zookeeper/" target="_blank" rel="noopener">https://hub.docker.com/_/zookeeper/</a></p><p><a href="http://zookeeper.apache.org/doc/r3.4.11/zookeeperAdmin.html" target="_blank" rel="noopener">http://zookeeper.apache.org/doc/r3.4.11/zookeeperAdmin.html</a></p><p><a href="https://www.hifreud.com/2017/01/09/zookeeper-06-common-configurations/" target="_blank" rel="noopener">https://www.hifreud.com/2017/01/09/zookeeper-06-common-configurations/</a></p><p><a href="http://www.cnblogs.com/sunddenly/articles/4071730.html" target="_blank" rel="noopener">http://www.cnblogs.com/sunddenly/articles/4071730.html</a></p><p><a href="https://my.oschina.net/xiaotian120/blog/194820" target="_blank" rel="noopener">https://my.oschina.net/xiaotian120/blog/194820</a></p><p><a href="https://yq.aliyun.com/articles/30328" target="_blank" rel="noopener">https://yq.aliyun.com/articles/30328</a></p>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h1&gt;&lt;p&gt;自己了解一些Docker容器技术，想在自己机器上搭建一个zookeeper集群，以前在虚拟机上有过实践经验，这次就想着在Docker下也搞一个Zookeeper集群。Docker的相关介绍这里就不多讲了，大家可以通过搜索引擎查阅相关资料。&lt;/p&gt;
&lt;img src=&quot;/2018/05/05/Docker下Zookeeper集群搭建/00.jpg&quot;&gt;
    
    </summary>
    
      <category term="Docker&amp;Kubernetes" scheme="http://jaychang.cn/categories/Docker-Kubernetes/"/>
    
    
      <category term="Docker" scheme="http://jaychang.cn/tags/Docker/"/>
    
      <category term="Zookeeper" scheme="http://jaychang.cn/tags/Zookeeper/"/>
    
      <category term="容器" scheme="http://jaychang.cn/tags/%E5%AE%B9%E5%99%A8/"/>
    
  </entry>
  
  <entry>
    <title>数据结构-线性表的链式表示与实现</title>
    <link href="http://jaychang.cn/2018/02/06/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E7%BA%BF%E6%80%A7%E8%A1%A8%E7%9A%84%E9%93%BE%E5%BC%8F%E8%A1%A8%E7%A4%BA%E4%B8%8E%E5%AE%9E%E7%8E%B0/"/>
    <id>http://jaychang.cn/2018/02/06/数据结构-线性表的链式表示与实现/</id>
    <published>2018-02-06T15:11:40.000Z</published>
    <updated>2018-04-29T22:53:28.882Z</updated>
    
    <content type="html"><![CDATA[<h1 id="线性表链式存储结构定义"><a href="#线性表链式存储结构定义" class="headerlink" title="线性表链式存储结构定义"></a>线性表链式存储结构定义</h1><p>线性表的链式存储结构的特点是用一组任务的存储单元存储线性表的数据元素，这组存储单元可以是连续的，也可以是非连续的。这就意味着，这些数据元素可以存储在内存未被占用的任意位置。</p><a id="more"></a><p>线性表的顺序存储结构中，每个数据元素只需要存储数据元素信息就可以了。现在链式结构中，除了要存储数据元素外，还要存储它的后继元素的存储地址。</p><p>为了表示每个数据元素ai与其直接后继元素的ai+1之间的逻辑关系，对数据元素ai来说，除了存储其本身的信息之外，还需存储一个指示其后继的信息(即直接后继的存储位置)。我们把存储数据元素的域称为数据域，把存储直接后继位置的域成为指针域。指针域中存储的信息称作指针或链。这两部分信息组成数据元素ai的存储映像，成为结点(Node)。</p><p>n个结点链结成一个链表，即为线性表(a1,a2,…ai，ai+1，…，an)的链式存储结构，因为此链表的每个结点中只包含一个指针域，所以叫做单链表。</p><img src="/2018/02/06/数据结构-线性表的链式表示与实现/linkedlist.jpg"><h1 id="线性表链式存储结构"><a href="#线性表链式存储结构" class="headerlink" title="线性表链式存储结构"></a>线性表链式存储结构</h1><figure class="highlight c"><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="keyword">typedef</span> <span class="keyword">int</span> ElementType;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">Node</span> &#123;</span></span><br><span class="line">ElementType data;</span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">Node</span>* <span class="title">next</span>;</span></span><br><span class="line">&#125; Node;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">Node</span> *<span class="title">LinkedList</span>;</span></span><br></pre></td></tr></table></figure><p>data为数据域，next为指针域</p><h1 id="线性表链式存储结构的插入"><a href="#线性表链式存储结构的插入" class="headerlink" title="线性表链式存储结构的插入"></a>线性表链式存储结构的插入</h1><p><strong>插入操作算法描述</strong></p><ul><li>p初始指向链表头结点，迭代p,最终使得p指向第i-1个结点</li><li>如果p为NULL，表示第i-1个结点不存在，返回FAILURE</li><li>创建新结点，令p的后继是新结点，返回SUCCESS</li></ul><img src="/2018/02/06/数据结构-线性表的链式表示与实现/list_insert.jpg"><figure class="highlight c"><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="function">Status <span class="title">listInsert</span><span class="params">(LinkedList linkedList, <span class="keyword">int</span> i, ElementType e)</span> </span>&#123;</span><br><span class="line">Node *p = linkedList;</span><br><span class="line"><span class="comment">// j=0表示从头结点开始</span></span><br><span class="line"><span class="keyword">int</span> j = <span class="number">0</span>;</span><br><span class="line"><span class="comment">// j &lt; i - 1条件表示循环完成后（j == i - 1结束循环），p指向第i-1个结点</span></span><br><span class="line"><span class="keyword">while</span> (p &amp;&amp; j &lt; i - <span class="number">1</span>) &#123;</span><br><span class="line">p = p-&gt;next;</span><br><span class="line">j++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (!p || j &gt; i - <span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line">Node *newNode = (Node*) <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(Node));</span><br><span class="line">newNode-&gt;data = e;</span><br><span class="line">newNode-&gt;next = p-&gt;next;</span><br><span class="line">p-&gt;next = newNode;</span><br><span class="line">    linkedList-&gt;data++;</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="线性表链式存储结构的删除"><a href="#线性表链式存储结构的删除" class="headerlink" title="线性表链式存储结构的删除"></a>线性表链式存储结构的删除</h1><p><strong>删除操作算法描述</strong></p><ul><li>p初始指向链表头结点，迭代p,最终使得p指向第i-1个结点</li><li>如果p为NULL，则返回FAILURE</li><li>tmp指向第i个结点，p的后继为第i个结点的后继</li><li>释放掉tmp指向的结点所占内存，返回SUCCESS</li></ul><img src="/2018/02/06/数据结构-线性表的链式表示与实现/list_delete.jpg"><figure class="highlight c"><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="function">Status <span class="title">listDelete</span><span class="params">(LinkedList linkedList, <span class="keyword">int</span> i, ElementType *e)</span> </span>&#123;</span><br><span class="line">Node *p = linkedList;</span><br><span class="line"><span class="keyword">int</span> j = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">while</span> (p &amp;&amp; j &lt; i - <span class="number">1</span>) &#123;</span><br><span class="line">p = p-&gt;next;</span><br><span class="line">j++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (!p || j &gt; i - <span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line">Node *tmp = p-&gt;next;</span><br><span class="line">p-&gt;next = tmp-&gt;next;</span><br><span class="line">*e = tmp-&gt;data;</span><br><span class="line"><span class="built_in">free</span>(tmp);</span><br><span class="line">    linkedList-&gt;data--;</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="线性表链式存储结构的逆转"><a href="#线性表链式存储结构的逆转" class="headerlink" title="线性表链式存储结构的逆转"></a>线性表链式存储结构的逆转</h1><p><strong>反转算法描述</strong></p><p>设置3个指针，cur指向当前要操作的元素(操作当前元素的指针域)，pre指向前驱元素，next指向后继元素，next用于保存暂存后继元素的位置信息</p><ul><li>使得next指向cur的后继元素，因为下一步要修改cur元素的指针域，如果没有这一步，将找不到cur的后继元素</li><li>将cur指向的当前元素的指针域修改为指向pre指向的元素</li><li>使得pre指向cur指向的元素</li><li>令cur与next的指向相同</li><li>循环结束后，创建新的头结点（当然用之前的头节点也可以，只要修改指针域令其指向pre指向的结点），令头结点的指针域指向pre指向的结点</li><li>释放原来头结点占用的内存空间</li></ul><img src="/2018/02/06/数据结构-线性表的链式表示与实现/list_reverse.jpg"><figure class="highlight c"><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="function">LinkedList <span class="title">listReverse</span><span class="params">(LinkedList <span class="built_in">list</span>)</span> </span>&#123;</span><br><span class="line">Node *cur = <span class="built_in">list</span>-&gt;next;</span><br><span class="line"><span class="keyword">if</span> (!cur || !cur-&gt;next) &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">list</span>;</span><br><span class="line">&#125;</span><br><span class="line">Node *pre = <span class="literal">NULL</span>;</span><br><span class="line">Node *next = <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> (cur) &#123;</span><br><span class="line">next = cur-&gt;next;</span><br><span class="line">cur-&gt;next = pre;</span><br><span class="line">pre = cur;</span><br><span class="line">cur = next;</span><br><span class="line">&#125;</span><br><span class="line">LinkedList reverseList = (LinkedList) <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(Node));</span><br><span class="line"><span class="comment">// 拷贝链表长度数据</span></span><br><span class="line">reverseList-&gt;data = <span class="built_in">list</span>-&gt;data;</span><br><span class="line">reverseList-&gt;next = pre;</span><br><span class="line"><span class="built_in">free</span>(<span class="built_in">list</span>);</span><br><span class="line"><span class="keyword">return</span> reverseList;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="线性表链式存储结构的查找"><a href="#线性表链式存储结构的查找" class="headerlink" title="线性表链式存储结构的查找"></a>线性表链式存储结构的查找</h1><p><strong>算法描述</strong></p><ul><li>p指向第一个结点，j=1</li><li>迭代直到j=i，退出循环</li><li>如果p为NULL则返回FAILURE</li><li>用e来返回第i个元素的数据</li></ul><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">Status <span class="title">listSearch</span><span class="params">(LinkedList <span class="built_in">list</span>, <span class="keyword">int</span> i, ElementType *e)</span> </span>&#123;</span><br><span class="line">Node *p = <span class="built_in">list</span>-&gt;next;</span><br><span class="line"><span class="comment">// j=1表示从第1个结点开始</span></span><br><span class="line"><span class="keyword">int</span> j = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">while</span> (p &amp;&amp; j &lt; i) &#123;</span><br><span class="line">p = p-&gt;next;</span><br><span class="line">++j;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"i=%d,j=%d\n"</span>, i, j);</span><br><span class="line"><span class="keyword">if</span> (!p || j &gt; i) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line">*e = p-&gt;data;</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="线性表链式存储结构查找倒数第k个结点"><a href="#线性表链式存储结构查找倒数第k个结点" class="headerlink" title="线性表链式存储结构查找倒数第k个结点"></a>线性表链式存储结构查找倒数第k个结点</h1><p><strong>算法描述</strong></p><ul><li>设置两个指针p1,p2初始都指向第1个结点</li><li>p2向右移动k个位置</li><li>p1,p2一起向右移动，直至p2移动到末尾</li><li>返回p1,即倒数第k个结点</li></ul><img src="/2018/02/06/数据结构-线性表的链式表示与实现/list_baak_kth_node.jpg"><figure class="highlight c"><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="function">Node* <span class="title">listTheBackKthNode</span><span class="params">(LinkedList <span class="built_in">list</span>, <span class="keyword">int</span> k)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (!<span class="built_in">list</span>-&gt;next || k &lt;= <span class="number">0</span> || k &gt; <span class="built_in">list</span>-&gt;data) &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 设置两个指针p1,p2初始都指向第1个结点，p2向右移动k个位置,然后p1,p2同时向右移动，直至p2移动到末尾</span></span><br><span class="line">Node *p1 = <span class="built_in">list</span>-&gt;next;</span><br><span class="line">Node *p2 = p1;</span><br><span class="line"><span class="keyword">int</span> j = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">while</span> (p2-&gt;next &amp;&amp; j &lt; k) &#123;</span><br><span class="line">p2 = p2-&gt;next;</span><br><span class="line">j++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span> (p2-&gt;next) &#123;</span><br><span class="line">p2 = p2-&gt;next;</span><br><span class="line">p1 = p1-&gt;next;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> p1;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="线性表链式存储结构查中间结点"><a href="#线性表链式存储结构查中间结点" class="headerlink" title="线性表链式存储结构查中间结点"></a>线性表链式存储结构查中间结点</h1><p><strong>算法描述</strong></p><p>与上述查找倒数第k个结点的算法一样，只不过倒数第几个，要根据链表长度计算一下而已，不再赘述</p><figure class="highlight c"><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="function">Node* <span class="title">listTheMiddleNode</span><span class="params">(LinkedList <span class="built_in">list</span>)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (!<span class="built_in">list</span>-&gt;next) &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取链表的长度（头结点数据域存储了链表的长度）</span></span><br><span class="line"><span class="keyword">int</span> len = <span class="built_in">list</span>-&gt;data;</span><br><span class="line"><span class="keyword">int</span> mid = len / <span class="number">2</span>;</span><br><span class="line">Node *p1 = <span class="built_in">list</span>-&gt;next;</span><br><span class="line">Node *p2 = p1;</span><br><span class="line"><span class="keyword">int</span> j = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">while</span> (p2 &amp;&amp; j &lt; mid + <span class="number">1</span>) &#123;</span><br><span class="line">p2 = p2-&gt;next;</span><br><span class="line">j++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span> (p2-&gt;next) &#123;</span><br><span class="line">p2 = p2-&gt;next;</span><br><span class="line">p1 = p1-&gt;next;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> p1;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="线性表链式存储完整代码"><a href="#线性表链式存储完整代码" class="headerlink" title="线性表链式存储完整代码"></a>线性表链式存储完整代码</h1><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> SUCCESS 1</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> FAILURE 0</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">int</span> Status;</span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">int</span> ElementType;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">Node</span> &#123;</span></span><br><span class="line">ElementType data;</span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">Node</span>* <span class="title">next</span>;</span></span><br><span class="line">&#125; Node;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">Node</span> *<span class="title">LinkedList</span>;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">listInit</span><span class="params">(LinkedList *<span class="built_in">list</span>)</span> </span>&#123;</span><br><span class="line"><span class="comment">// 头结点数据域存储链表长度</span></span><br><span class="line">(*<span class="built_in">list</span>)-&gt;data = <span class="number">0</span>;</span><br><span class="line">(*<span class="built_in">list</span>)-&gt;next = <span class="literal">NULL</span>;</span><br><span class="line"><span class="comment">// list的值是linkedList的地址，所以跟&amp;linkedList是一样的</span></span><br><span class="line"><span class="comment">//printf("init method list's address = %p\n", list);</span></span><br><span class="line"><span class="comment">// &amp;list是指向linkedList指针的地址</span></span><br><span class="line"><span class="comment">//printf("init method &amp;list's address = %p\n", &amp;list);</span></span><br><span class="line"><span class="comment">// 是头结点的地址</span></span><br><span class="line"><span class="comment">//printf("init method *list's address = %p\n", *list);</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 若在这里初始化n个结点，则参数必须是LinkedList *list,不能是LinkedList list。需要用到指向指针的指针，因为main函数中的linkedList与listInit的形参list指向的内存地址不一样。</span></span><br><span class="line">    <span class="comment">// 以下代码还是注释掉吧，初始化只需要把data值置为0，next指针域置为NULL</span></span><br><span class="line"><span class="comment">//Node *p = (*list);</span></span><br><span class="line"><span class="comment">//for (int i = 0; i &lt; n; i++) &#123;</span></span><br><span class="line"><span class="comment">//p-&gt;next = (Node*) malloc(sizeof(Node));</span></span><br><span class="line"><span class="comment">//p-&gt;next-&gt;data = i;</span></span><br><span class="line"><span class="comment">//p-&gt;next-&gt;next = NULL;</span></span><br><span class="line"><span class="comment">//p = p-&gt;next;</span></span><br><span class="line"><span class="comment">//&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">Status <span class="title">listSearch</span><span class="params">(LinkedList <span class="built_in">list</span>, <span class="keyword">int</span> i, ElementType *e)</span> </span>&#123;</span><br><span class="line">Node *p = <span class="built_in">list</span>-&gt;next;</span><br><span class="line"><span class="comment">// j=1表示从第1个结点开始</span></span><br><span class="line"><span class="keyword">int</span> j = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">while</span> (p &amp;&amp; j &lt; i) &#123;</span><br><span class="line">p = p-&gt;next;</span><br><span class="line">++j;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"i=%d,j=%d\n"</span>, i, j);</span><br><span class="line"><span class="keyword">if</span> (!p || j &gt; i) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line">*e = p-&gt;data;</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">Status <span class="title">listInsert</span><span class="params">(LinkedList linkedList, <span class="keyword">int</span> i, ElementType e)</span> </span>&#123;</span><br><span class="line">Node *p = linkedList;</span><br><span class="line"><span class="comment">// j=0表示从头结点开始</span></span><br><span class="line"><span class="keyword">int</span> j = <span class="number">0</span>;</span><br><span class="line"><span class="comment">// j &lt; i - 1条件表示循环完成后（j == i - 1结束循环），p指向第i-1个结点</span></span><br><span class="line"><span class="keyword">while</span> (p &amp;&amp; j &lt; i - <span class="number">1</span>) &#123;</span><br><span class="line">p = p-&gt;next;</span><br><span class="line">j++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (!p || j &gt; i - <span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line">Node *newNode = (Node*) <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(Node));</span><br><span class="line">newNode-&gt;data = e;</span><br><span class="line">newNode-&gt;next = p-&gt;next;</span><br><span class="line">p-&gt;next = newNode;</span><br><span class="line">linkedList-&gt;data++;</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">Status <span class="title">listDelete</span><span class="params">(LinkedList linkedList, <span class="keyword">int</span> i, ElementType *e)</span> </span>&#123;</span><br><span class="line">Node *p = linkedList;</span><br><span class="line"><span class="keyword">int</span> j = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">while</span> (p &amp;&amp; j &lt; i - <span class="number">1</span>) &#123;</span><br><span class="line">p = p-&gt;next;</span><br><span class="line">j++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (!p || j &gt; i - <span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line">Node *tmp = p-&gt;next;</span><br><span class="line">p-&gt;next = tmp-&gt;next;</span><br><span class="line">*e = tmp-&gt;data;</span><br><span class="line"><span class="built_in">free</span>(tmp);</span><br><span class="line">linkedList-&gt;data--;</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">LinkedList <span class="title">listReverse</span><span class="params">(LinkedList <span class="built_in">list</span>)</span> </span>&#123;</span><br><span class="line">Node *cur = <span class="built_in">list</span>-&gt;next;</span><br><span class="line"><span class="keyword">if</span> (!cur || !cur-&gt;next) &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">list</span>;</span><br><span class="line">&#125;</span><br><span class="line">Node *pre = <span class="literal">NULL</span>;</span><br><span class="line">Node *next = <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> (cur) &#123;</span><br><span class="line">next = cur-&gt;next;</span><br><span class="line">cur-&gt;next = pre;</span><br><span class="line">pre = cur;</span><br><span class="line">cur = next;</span><br><span class="line">&#125;</span><br><span class="line">LinkedList reverseList = (LinkedList) <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(Node));</span><br><span class="line"><span class="comment">// 拷贝链表长度数据</span></span><br><span class="line">reverseList-&gt;data = <span class="built_in">list</span>-&gt;data;</span><br><span class="line">reverseList-&gt;next = pre;</span><br><span class="line"><span class="built_in">free</span>(<span class="built_in">list</span>);</span><br><span class="line"><span class="keyword">return</span> reverseList;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 找倒数第k个结点</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function">Node* <span class="title">listTheBackKthNode</span><span class="params">(LinkedList <span class="built_in">list</span>, <span class="keyword">int</span> k)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (!<span class="built_in">list</span>-&gt;next || k &lt;= <span class="number">0</span> || k &gt; <span class="built_in">list</span>-&gt;data) &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 设置两个指针p1,p2初始都指向第1个结点，p2向右移动k个位置,然后p1,p2同时向右移动，直至p2移动到末尾</span></span><br><span class="line">Node *p1 = <span class="built_in">list</span>-&gt;next;</span><br><span class="line">Node *p2 = p1;</span><br><span class="line"><span class="keyword">int</span> j = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">while</span> (p2-&gt;next &amp;&amp; j &lt; k) &#123;</span><br><span class="line">p2 = p2-&gt;next;</span><br><span class="line">j++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span> (p2-&gt;next) &#123;</span><br><span class="line">p2 = p2-&gt;next;</span><br><span class="line">p1 = p1-&gt;next;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> p1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 找到中间结点</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function">Node* <span class="title">listTheMiddleNode</span><span class="params">(LinkedList <span class="built_in">list</span>)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (!<span class="built_in">list</span>-&gt;next) &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取链表的长度（头结点数据域存储了链表的长度）</span></span><br><span class="line"><span class="keyword">int</span> len = <span class="built_in">list</span>-&gt;data;</span><br><span class="line"><span class="keyword">int</span> mid = len / <span class="number">2</span>;</span><br><span class="line">Node *p1 = <span class="built_in">list</span>-&gt;next;</span><br><span class="line">Node *p2 = p1;</span><br><span class="line"><span class="keyword">int</span> j = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">while</span> (p2 &amp;&amp; j &lt; mid + <span class="number">1</span>) &#123;</span><br><span class="line">p2 = p2-&gt;next;</span><br><span class="line">j++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span> (p2-&gt;next) &#123;</span><br><span class="line">p2 = p2-&gt;next;</span><br><span class="line">p1 = p1-&gt;next;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> p1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">listPrint</span><span class="params">(LinkedList <span class="built_in">list</span>)</span> </span>&#123;</span><br><span class="line">Node *p = <span class="built_in">list</span>-&gt;next;</span><br><span class="line"><span class="keyword">while</span> (p) &#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%d "</span>, p-&gt;data);</span><br><span class="line">p = p-&gt;next;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"\n"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line"><span class="comment">// 初始化一个单项链表的头结点</span></span><br><span class="line"><span class="comment">// LinkedList linkedList = (Node*)malloc(sizeof(Node));</span></span><br><span class="line">LinkedList linkedList = (LinkedList) <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(Node));</span><br><span class="line"><span class="comment">// 头结点的地址</span></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"main method linkedList's address = %p\n"</span>, linkedList);</span><br><span class="line"><span class="comment">// 指向头结点的指针的地址</span></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"main method &amp;linkedList's address = %p\n"</span>, &amp;linkedList);</span><br><span class="line">listInit(&amp;linkedList);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= <span class="number">10</span>; i++) &#123;</span><br><span class="line">ElementType data = i;</span><br><span class="line">listInsert(linkedList, i, data);</span><br><span class="line">&#125;</span><br><span class="line">ElementType searchElement = <span class="number">-1</span>;</span><br><span class="line">Status searchResult = listSearch(linkedList, <span class="number">3</span>, &amp;searchElement);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"search result:%d,the element is %d\n"</span>, searchResult, searchElement);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"insert %d\n"</span>, listInsert(linkedList, <span class="number">10</span>, <span class="number">33</span>));</span><br><span class="line">listPrint(linkedList);</span><br><span class="line">ElementType deletedElement = <span class="number">-1</span>;</span><br><span class="line">Status deleteResult = listDelete(linkedList, <span class="number">2</span>, &amp;deletedElement);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"delete result:%d,deleted element:%d\n"</span>, deleteResult,</span><br><span class="line">deletedElement);</span><br><span class="line">listPrint(linkedList);</span><br><span class="line">LinkedList reverseList = listReverse(linkedList);</span><br><span class="line">listPrint(reverseList);</span><br><span class="line"><span class="keyword">int</span> k = <span class="number">2</span>;</span><br><span class="line">Node *theBackKthNode = listTheBackKthNode(reverseList, k);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"the back %dth node is %d\n"</span>, k,</span><br><span class="line">theBackKthNode ? theBackKthNode-&gt;data : <span class="number">-1</span>);</span><br><span class="line"></span><br><span class="line">Node *theMiddleNode = listTheMiddleNode(reverseList);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"the middle node is %d\n"</span>, theMiddleNode-&gt;data);</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;线性表链式存储结构定义&quot;&gt;&lt;a href=&quot;#线性表链式存储结构定义&quot; class=&quot;headerlink&quot; title=&quot;线性表链式存储结构定义&quot;&gt;&lt;/a&gt;线性表链式存储结构定义&lt;/h1&gt;&lt;p&gt;线性表的链式存储结构的特点是用一组任务的存储单元存储线性表的数据元素，这组存储单元可以是连续的，也可以是非连续的。这就意味着，这些数据元素可以存储在内存未被占用的任意位置。&lt;/p&gt;
    
    </summary>
    
      <category term="数据结构与算法" scheme="http://jaychang.cn/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/"/>
    
    
      <category term="线性表" scheme="http://jaychang.cn/tags/%E7%BA%BF%E6%80%A7%E8%A1%A8/"/>
    
  </entry>
  
  <entry>
    <title>数据结构-线性表的顺序表示与实现</title>
    <link href="http://jaychang.cn/2018/01/22/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E7%BA%BF%E6%80%A7%E8%A1%A8%E7%9A%84%E9%A1%BA%E5%BA%8F%E8%A1%A8%E7%A4%BA%E4%B8%8E%E5%AE%9E%E7%8E%B0/"/>
    <id>http://jaychang.cn/2018/01/22/数据结构-线性表的顺序表示与实现/</id>
    <published>2018-01-22T15:41:57.000Z</published>
    <updated>2018-05-05T14:24:41.886Z</updated>
    
    <content type="html"><![CDATA[<h1 id="线性表的抽象数据类型定义"><a href="#线性表的抽象数据类型定义" class="headerlink" title="线性表的抽象数据类型定义"></a>线性表的抽象数据类型定义</h1><p>ADT 线性表(List)</p><p>Data </p><p>​    线性表的数据对象集合为{a1,a2,…,ai,ai+1,…,an-1,an}，每个元素的类型为DataType。其中，除第一个元素a1外，每个元素都有一个直接前驱元素，除最后一个元素an外，每个元素都有一个直接后继元素，数据元素之间的关系是一对一的</p><a id="more"></a><p>Operation:</p><p>​    initList(List *list): 初始化操作，建立一个空的线性表list</p><p>​    listEmpty(List list):若线性表为空，则返回true,否则返回false</p><p>​    clearList(List *list):将线性表清空</p><p>​    getElement(List list,int i,ElementType *e):获取线性表第i个元素的值，该值赋值给e</p><p>​    locateElement(List list,ElementType e):在线性表中查找与给定e值相等的元素，如果查找成功则返回元素在线性表中的序号，否则返回0</p><p>​    listInsert(List *list,int i,ElementType e):在线性表序号为i处，新建并插入值为e的新元素，插入成功返回TRUE,否则返回FALSE</p><p>​    listDelete(List <em>list,int i,ElementType </em>e):删除线性表中序号为i的元素，并用e来存储元素值返回给调用方，如果删除成功返回TRUE,否则返回FALSE</p><p>注：这个定义对于线性表的顺序存储与链式存储都是适用的</p><h1 id="线性表顺序存储定义"><a href="#线性表顺序存储定义" class="headerlink" title="线性表顺序存储定义"></a>线性表顺序存储定义</h1><p>线性表的顺序存储结构，指的是用一段地址连续的存储单元依次存储线性表的数据元素。</p><p>若存在线性表{a1,a2,…,ai,ai+1,…,an-1,an},LOC表示求地址操作，每个数据元素需要m存储空间，则有LOC(ai+1)=LOC(ai)+m, LOC(ai)=LOC(a1)+(i-1)*m</p><h1 id="线性表顺序存储结构"><a href="#线性表顺序存储结构" class="headerlink" title="线性表顺序存储结构"></a>线性表顺序存储结构</h1><figure class="highlight c"><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 class="meta-keyword">define</span> MAXSIZE 20</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">int</span> ElementType;</span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">ElementType data[MAXSIZE];</span><br><span class="line"><span class="keyword">int</span> length;</span><br><span class="line">&#125; SqList;</span><br></pre></td></tr></table></figure><p>这里，我们就发现线性表顺序存储结构的三个特点</p><ul><li>线性表的最大存储容量：数组长度MAXSIZE</li><li>length当前存储的数据元素的个数，即当前线性表的长度</li><li>存储空间的起始位置：数组data,它的存储位置就是存储空间的存储位置</li></ul><h1 id="线性表顺序存储结构的插入、删除操作"><a href="#线性表顺序存储结构的插入、删除操作" class="headerlink" title="线性表顺序存储结构的插入、删除操作"></a>线性表顺序存储结构的插入、删除操作</h1><p><strong>插入操作算法描述</strong></p><ul><li>检查当前线性表的长度是否等于线性表的最大存储容量，若是则返回FAILURE，然后检查插入位置是否在1至线性表长度+1，若不是则返回FAILURE</li><li>若i &lt;= 线性表长度，意味着需要移动元素，从线性表最后那个元素开始，到第i个元素，每个元素往后移动一个位置</li><li>将要插入的元素填入位置e</li><li>线性表的长度+1</li></ul><p>注意：这里第i个元素，在C语言数组的序号表示为i-1</p><img src="/2018/01/22/数据结构-线性表的顺序表示与实现/01.jpg"><figure class="highlight c"><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></pre></td><td class="code"><pre><span class="line"><span class="function">Status <span class="title">listInsert</span><span class="params">(SqList *sqList, <span class="keyword">int</span> i, ElementType e)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (sqList-&gt;length &gt;= MAXSIZE || i &lt; <span class="number">1</span> || i &gt; sqList-&gt;length + <span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (i &lt;= sqList-&gt;length) &#123;</span><br><span class="line"><span class="comment">// 从最后那个元素到第i个元素每个元素都往后移动一个位置</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = sqList-&gt;length - <span class="number">1</span>; j &gt;= i - <span class="number">1</span>; j--) &#123;</span><br><span class="line">sqList-&gt;data[j + <span class="number">1</span>] = sqList-&gt;data[j];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 将原先第i个元素值替换为e</span></span><br><span class="line">sqList-&gt;data[i - <span class="number">1</span>] = e;</span><br><span class="line"><span class="comment">// 线性表长度+1</span></span><br><span class="line">sqList-&gt;length = sqList-&gt;length + <span class="number">1</span>;</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>插入操作时间复杂度为O(n)</p><p><strong>删除操作算法描述</strong></p><ul><li>如果删除元素位置不合理，则返回FAILURE</li><li>用e存储要被删除的元素</li><li>如果删除的元素位置不在表尾，则需要移动元素，从第i+1元素开始至第length个元素，每个元素向前移动一个位置</li><li>线性表长度-1</li></ul><img src="/2018/01/22/数据结构-线性表的顺序表示与实现/02.jpg"><figure class="highlight c"><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"><span class="function">Status <span class="title">listDelete</span><span class="params">(SqList *sqList, <span class="keyword">int</span> i, ElementType *e)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (i &lt;= <span class="number">0</span> || i &gt;= sqList-&gt;length + <span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line">*e = sqList-&gt;data[i - <span class="number">1</span>];</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = i - <span class="number">1</span>; j &lt; sqList-&gt;length - <span class="number">1</span>; j++) &#123;</span><br><span class="line">sqList-&gt;data[j] = sqList-&gt;data[j + <span class="number">1</span>];</span><br><span class="line">&#125;</span><br><span class="line">sqList-&gt;length = sqList-&gt;length - <span class="number">1</span>;</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>删除操作时间复杂度为O(n)</p><h1 id="线性表顺序存储实现的完整代码"><a href="#线性表顺序存储实现的完整代码" class="headerlink" title="线性表顺序存储实现的完整代码"></a>线性表顺序存储实现的完整代码</h1><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> SUCCESS 1</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> FAILURE 0</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> TRUE 1</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> FALSE 0</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MAXSIZE 20</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">int</span> Status;</span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">int</span> Boolean;</span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">int</span> ElementType;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">ElementType data[MAXSIZE];</span><br><span class="line"><span class="keyword">int</span> length;</span><br><span class="line">&#125; SqList;</span><br><span class="line"></span><br><span class="line"><span class="function">Status <span class="title">initList</span><span class="params">(SqList *sqList)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (!sqList) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line">sqList-&gt;length = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">Boolean <span class="title">listEmpty</span><span class="params">(SqList *sqList)</span> </span>&#123;</span><br><span class="line"><span class="keyword">return</span> sqList-&gt;length &gt; <span class="number">0</span> ? FALSE : TRUE;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">Status <span class="title">clearList</span><span class="params">(SqList *sqList)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (!sqList) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line">sqList-&gt;length = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">Status <span class="title">getElement</span><span class="params">(SqList sqList, <span class="keyword">int</span> i, ElementType *e)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (i &lt; <span class="number">1</span> || i &gt; sqList.length) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line">*e = sqList.data[i];</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">locateElement</span><span class="params">(SqList sqList, ElementType e)</span> </span>&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; sqList.length; i++) &#123;</span><br><span class="line"><span class="keyword">if</span> (sqList.data[i] == e) &#123;</span><br><span class="line"><span class="keyword">return</span> i + <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">Status <span class="title">listInsert</span><span class="params">(SqList *sqList, <span class="keyword">int</span> i, ElementType e)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (sqList-&gt;length &gt;= MAXSIZE || i &lt; <span class="number">1</span> || i &gt; sqList-&gt;length + <span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (i &lt;= sqList-&gt;length) &#123;</span><br><span class="line"><span class="comment">// 从最后那个元素到第i个元素每个元素都往后移动一个位置</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = sqList-&gt;length - <span class="number">1</span>; j &gt;= i - <span class="number">1</span>; j--) &#123;</span><br><span class="line">sqList-&gt;data[j + <span class="number">1</span>] = sqList-&gt;data[j];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 将原先第i个元素值替换为e</span></span><br><span class="line">sqList-&gt;data[i - <span class="number">1</span>] = e;</span><br><span class="line"><span class="comment">// 线性表长度+1</span></span><br><span class="line">sqList-&gt;length = sqList-&gt;length + <span class="number">1</span>;</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">Status <span class="title">listDelete</span><span class="params">(SqList *sqList, <span class="keyword">int</span> i, ElementType *e)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (i &lt;= <span class="number">0</span> || i &gt;= sqList-&gt;length + <span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">return</span> FAILURE;</span><br><span class="line">&#125;</span><br><span class="line">*e = sqList-&gt;data[i - <span class="number">1</span>];</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = i - <span class="number">1</span>; j &lt; sqList-&gt;length - <span class="number">1</span>; j++) &#123;</span><br><span class="line">sqList-&gt;data[j] = sqList-&gt;data[j + <span class="number">1</span>];</span><br><span class="line">&#125;</span><br><span class="line">sqList-&gt;length = sqList-&gt;length - <span class="number">1</span>;</span><br><span class="line"><span class="keyword">return</span> SUCCESS;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">listPrint</span><span class="params">(SqList *sqList)</span> </span>&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; sqList-&gt;length; i++) &#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%d\n"</span>, sqList-&gt;data[i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"length=%d\n"</span>, sqList-&gt;length);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">SqList sqList;</span><br><span class="line">initList(&amp;sqList);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= <span class="number">10</span>; i++) &#123;</span><br><span class="line">listInsert(&amp;sqList, i, (ElementType) i);</span><br><span class="line">&#125;</span><br><span class="line">listPrint(&amp;sqList);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"locate the element 3's index = %d"</span>, locateElement(sqList, <span class="number">3</span>));</span><br><span class="line">ElementType deletedElement;</span><br><span class="line">listDelete(&amp;sqList, <span class="number">4</span>, &amp;deletedElement);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"deleted element is %d"</span>, deletedElement);</span><br><span class="line">listPrint(&amp;sqList);</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="线性表顺序存储的优缺点"><a href="#线性表顺序存储的优缺点" class="headerlink" title="线性表顺序存储的优缺点"></a>线性表顺序存储的优缺点</h1><p><strong>优点</strong></p><ul><li>无需为表示表中的元素之间的逻辑关系，而额外增加存储空间</li><li>可以快速存取表中任一位置的元素，存取元素时间复杂度为O(1)</li></ul><p><strong>缺点</strong></p><ul><li>插入、删除元素时，需要移动大量元素</li><li>当线性表长度变化比较大的时候，难以估计线性表的存储容量</li><li>容易造成存储空间的“碎片”</li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;线性表的抽象数据类型定义&quot;&gt;&lt;a href=&quot;#线性表的抽象数据类型定义&quot; class=&quot;headerlink&quot; title=&quot;线性表的抽象数据类型定义&quot;&gt;&lt;/a&gt;线性表的抽象数据类型定义&lt;/h1&gt;&lt;p&gt;ADT 线性表(List)&lt;/p&gt;
&lt;p&gt;Data &lt;/p&gt;
&lt;p&gt;​    线性表的数据对象集合为{a1,a2,…,ai,ai+1,…,an-1,an}，每个元素的类型为DataType。其中，除第一个元素a1外，每个元素都有一个直接前驱元素，除最后一个元素an外，每个元素都有一个直接后继元素，数据元素之间的关系是一对一的&lt;/p&gt;
    
    </summary>
    
      <category term="数据结构与算法" scheme="http://jaychang.cn/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/"/>
    
    
      <category term="线性表" scheme="http://jaychang.cn/tags/%E7%BA%BF%E6%80%A7%E8%A1%A8/"/>
    
  </entry>
  
  <entry>
    <title>【Spring Cloud微服务全家桶】03之Eureka控制台的General Info(unavailable-replicas available-replicas显示不正确问题)</title>
    <link href="http://jaychang.cn/2017/09/01/%E3%80%90Spring-Cloud%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%85%A8%E5%AE%B6%E6%A1%B6%E3%80%9103%E4%B9%8BEureka%E6%8E%A7%E5%88%B6%E5%8F%B0%E7%9A%84General-Info-unavailable-replicas-available-replicas%E6%98%BE%E7%A4%BA%E4%B8%8D%E6%AD%A3%E7%A1%AE%E9%97%AE%E9%A2%98/"/>
    <id>http://jaychang.cn/2017/09/01/【Spring-Cloud微服务全家桶】03之Eureka控制台的General-Info-unavailable-replicas-available-replicas显示不正确问题/</id>
    <published>2017-09-01T09:36:30.000Z</published>
    <updated>2018-04-29T22:51:01.177Z</updated>
    
    <content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>之前【Spring Cloud微服务全家桶】之高可用服务注册中心 文章介绍了Eureka Server高可用</p><a id="more"></a><h1 id="问题描述"><a href="#问题描述" class="headerlink" title="问题描述"></a>问题描述</h1><img src="/2017/09/01/【Spring-Cloud微服务全家桶】03之Eureka控制台的General-Info-unavailable-replicas-available-replicas显示不正确问题/01.png"><p>观察eureka-peer1，发现unavailable-replicas与available-replicas显示信息不正确，按理说所有eureka节点都启动后，eureka-peer3,eureka-peer2应该出现在available-replicas列表</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】03之Eureka控制台的General-Info-unavailable-replicas-available-replicas显示不正确问题/02.png"><h1 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h1><p>修改下每个eureka节点的配置，把自身注册到注册中心</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">eureka.client.fetch-registry=true</span><br><span class="line">eureka.client.register-with-eureka=true</span><br><span class="line">eureka.instance.prefer-ip-address=false</span><br></pre></td></tr></table></figure><ul><li>eureka-peer1节点的application.properties配置</li></ul><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></pre></td><td class="code"><pre><span class="line">server.port=1011</span><br><span class="line">spring.application.name=registry-ha-ms</span><br><span class="line"></span><br><span class="line">eureka.instance.hostname=eureka-peer1</span><br><span class="line">eureka.client.serviceUrl.defaultZone=http://eureka-peer2:1012/eureka,http://eureka-peer3:1013/eureka</span><br><span class="line"></span><br><span class="line">eureka.client.fetch-registry=true</span><br><span class="line">eureka.client.register-with-eureka=true</span><br><span class="line">eureka.instance.prefer-ip-address=false</span><br></pre></td></tr></table></figure><ul><li>eureka-peer2节点的application.properties配置</li></ul><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></pre></td><td class="code"><pre><span class="line">server.port=1012</span><br><span class="line">spring.application.name=registry-ha-ms</span><br><span class="line"></span><br><span class="line">eureka.instance.hostname=eureka-peer2</span><br><span class="line">eureka.client.serviceUrl.defaultZone=http://eureka-peer1:1011/eureka,http://eureka-peer3:1013/eureka</span><br><span class="line"></span><br><span class="line">eureka.client.fetch-registry=true</span><br><span class="line">eureka.client.register-with-eureka=true</span><br><span class="line">eureka.instance.prefer-ip-address=false</span><br></pre></td></tr></table></figure><ul><li>eureka-peer3节点的application.properties配置</li></ul><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></pre></td><td class="code"><pre><span class="line">server.port=1013</span><br><span class="line">spring.application.name=registry-ha-ms</span><br><span class="line"></span><br><span class="line">eureka.instance.hostname=eureka-peer3</span><br><span class="line">eureka.client.serviceUrl.defaultZone=http://eureka-peer1:1011/eureka,http://eureka-peer2:1012/eureka</span><br><span class="line"></span><br><span class="line">eureka.client.fetch-registry=true</span><br><span class="line">eureka.client.register-with-eureka=true</span><br><span class="line">eureka.instance.prefer-ip-address=false</span><br></pre></td></tr></table></figure><p>重启每个eureka节点<br>发现available-replicas栏可以出现了</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】03之Eureka控制台的General-Info-unavailable-replicas-available-replicas显示不正确问题/03.png"><img src="/2017/09/01/【Spring-Cloud微服务全家桶】03之Eureka控制台的General-Info-unavailable-replicas-available-replicas显示不正确问题/04.png"><img src="/2017/09/01/【Spring-Cloud微服务全家桶】03之Eureka控制台的General-Info-unavailable-replicas-available-replicas显示不正确问题/05.png">]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h1&gt;&lt;p&gt;之前【Spring Cloud微服务全家桶】之高可用服务注册中心 文章介绍了Eureka Server高可用&lt;/p&gt;
    
    </summary>
    
      <category term="Spring Cloud" scheme="http://jaychang.cn/categories/Spring-Cloud/"/>
    
    
      <category term="微服务" scheme="http://jaychang.cn/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/"/>
    
      <category term="Spring Cloud" scheme="http://jaychang.cn/tags/Spring-Cloud/"/>
    
  </entry>
  
  <entry>
    <title>【Spring Cloud微服务全家桶】02之高可用服务注册中心</title>
    <link href="http://jaychang.cn/2017/09/01/%E3%80%90Spring-Cloud%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%85%A8%E5%AE%B6%E6%A1%B6%E3%80%9102%E4%B9%8B%E9%AB%98%E5%8F%AF%E7%94%A8%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83/"/>
    <id>http://jaychang.cn/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/</id>
    <published>2017-09-01T06:03:59.000Z</published>
    <updated>2018-04-29T22:29:24.391Z</updated>
    
    <content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>在Spring Cloud微服务全家桶之服务注册、服务发现(Eureka、Consul作为服务注册中心)文中，使用的是单点eureka注册中心。在开发测试环境是可以的，但生产环境强烈不建议用单点eureka注册中心。</p><a id="more"></a><h1 id="双eureka高可用"><a href="#双eureka高可用" class="headerlink" title="双eureka高可用"></a>双eureka高可用</h1><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/01.png"><p>思路就是每个eureka server通过eureka.client.serviceUrl.defaultZone配置，将自己注册到对方的注册中心。<br>新建一个module项目，建的过程这里省略，名为registry-ha-ms,建完后pom.xml</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">  <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.choosefine<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>registry-ha-ms<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">version</span>&gt;</span>0.0.1-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">packaging</span>&gt;</span>jar<span class="tag">&lt;/<span class="name">packaging</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">name</span>&gt;</span>registry-ha-ms<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">description</span>&gt;</span>Demo project for Spring Boot<span class="tag">&lt;/<span class="name">description</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.5.6.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">relativePath</span>/&gt;</span> <span class="comment">&lt;!-- lookup parent from repository --&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">properties</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">project.build.sourceEncoding</span>&gt;</span>UTF-8<span class="tag">&lt;/<span class="name">project.build.sourceEncoding</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">project.reporting.outputEncoding</span>&gt;</span>UTF-8<span class="tag">&lt;/<span class="name">project.reporting.outputEncoding</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">java.version</span>&gt;</span>1.8<span class="tag">&lt;/<span class="name">java.version</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">spring-cloud.version</span>&gt;</span>Dalston.SR2<span class="tag">&lt;/<span class="name">spring-cloud.version</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">properties</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-eureka-server<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">dependencyManagement</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-dependencies<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;spring-cloud.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">type</span>&gt;</span>pom<span class="tag">&lt;/<span class="name">type</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>import<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">dependencyManagement</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure><p>使用@EnableEurekaServer注解启用Eureka注册中心</p><figure class="highlight java"><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="meta">@EnableEurekaServer</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RegistryHaApplication</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">      SpringApplication.run(RegistryHaApplication.class, args);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>建两个properties配置文件，分别为application-peer1.properties，application-peer2.properties</p><ul><li>application-peer1.properties</li></ul><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></pre></td><td class="code"><pre><span class="line">server.port=1011</span><br><span class="line">spring.application.name=registry-ha-ms</span><br><span class="line"></span><br><span class="line">eureka.instance.hostname=eureka-peer1</span><br><span class="line">eureka.client.serviceUrl.defaultZone=http://eureka-peer2:1012/eureka</span><br></pre></td></tr></table></figure><ul><li>application-peer2.properties</li></ul><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></pre></td><td class="code"><pre><span class="line">server.port=1012</span><br><span class="line">spring.application.name=registry-ha-ms</span><br><span class="line"></span><br><span class="line">eureka.instance.hostname=eureka-peer2</span><br><span class="line">eureka.client.serviceUrl.defaultZone=http://eureka-peer1:1011/eureka</span><br></pre></td></tr></table></figure><p>配置本地Hosts域名解析</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">127.0.0.1 eureka-peer1</span><br><span class="line">127.0.0.1 eureka-peer2</span><br></pre></td></tr></table></figure><p>在项目目录下使用maven clean package -DskipTests打包，进入target目录，开启两个命令行窗口分别执行</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">java -jar registry-ha-ms-0.0.1-SNAPSHOT --spring.profiles.active=peer1</span><br><span class="line"></span><br><span class="line">java -jar registry-ha-ms-0.0.1-SNAPSHOT --spring.profiles.active=peer2</span><br></pre></td></tr></table></figure><p>或者在idea里建两个执行配置</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/02.png"><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/03.png"><p>这样就开启了两个eureka server。</p><p>我们在上一篇文章的基础上，将provider-ms的application.properties修改下</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></pre></td><td class="code"><pre><span class="line">server.port=2103</span><br><span class="line">spring.application.name=provider-ms</span><br><span class="line">#eureka.client.serviceUrl.defaultZone=http://registry-ms.pay-inner.com:1001/eureka</span><br><span class="line">eureka.client.serviceUrl.defaultZone=http://eureka-peer1:1011/eureka,http://eureka-peer2:1012/eureka</span><br></pre></td></tr></table></figure><p>然后再启动ProviderApplication，可以看到PROVIDER-MS 已经注册到eureka-peer1与eureka-peer2上了。且eureka-peer1的replicas节点列表里有eureka-peer2，eureka-peer2的replicas节点列表里有eureka-peer1</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/04.png"><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/05.png"><p>新建一个服务消费项目，名为consumer-ms建完后pom.xml</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">  <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.choosefine<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>consumer-ms<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">version</span>&gt;</span>0.0.1-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">packaging</span>&gt;</span>jar<span class="tag">&lt;/<span class="name">packaging</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">name</span>&gt;</span>consumer-ms<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">description</span>&gt;</span>Demo project for Spring Boot<span class="tag">&lt;/<span class="name">description</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.5.6.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">relativePath</span>/&gt;</span> <span class="comment">&lt;!-- lookup parent from repository --&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">properties</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">project.build.sourceEncoding</span>&gt;</span>UTF-8<span class="tag">&lt;/<span class="name">project.build.sourceEncoding</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">project.reporting.outputEncoding</span>&gt;</span>UTF-8<span class="tag">&lt;/<span class="name">project.reporting.outputEncoding</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">java.version</span>&gt;</span>1.8<span class="tag">&lt;/<span class="name">java.version</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">spring-cloud.version</span>&gt;</span>Dalston.SR2<span class="tag">&lt;/<span class="name">spring-cloud.version</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">properties</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-eureka<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">dependencyManagement</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-dependencies<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;spring-cloud.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">type</span>&gt;</span>pom<span class="tag">&lt;/<span class="name">type</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>import<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">dependencyManagement</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure><p>修改properties资源文件</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></pre></td><td class="code"><pre><span class="line">server.port=2104</span><br><span class="line">spring.application.name=consumer-ms</span><br><span class="line"></span><br><span class="line">eureka.client.serviceUrl.defaultZone=http://eureka-peer1:1011/eureka,http://eureka-peer2:1012/eureka</span><br></pre></td></tr></table></figure><p>@EnableDiscoveryClient启用服务发现客户端</p><figure class="highlight java"><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="meta">@EnableDiscoveryClient</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ConsumerMsApplication</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">  <span class="meta">@Bean</span></span><br><span class="line">  <span class="function"><span class="keyword">public</span> RestTemplate <span class="title">restTemplate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="keyword">new</span> RestTemplate();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">      SpringApplication.run(ConsumerMsApplication.class, args);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>写一个Controller消费provider-ms提供的服务</p><figure class="highlight java"><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="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ConsumerDemoController</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> LoadBalancerClient loadBalancerClient;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> RestTemplate restTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping</span>(<span class="string">"consume"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">consumeService</span><span class="params">()</span></span>&#123;</span><br><span class="line">        ServiceInstance serviceInstance = loadBalancerClient.choose(<span class="string">"provider-ms"</span>);</span><br><span class="line">        String url = <span class="string">"http://"</span>+serviceInstance.getHost()+<span class="string">":"</span>+serviceInstance.getPort()+<span class="string">"/"</span>+<span class="string">"services"</span>;</span><br><span class="line">        System.out.println(serviceInstance.getUri().toString());</span><br><span class="line">        String result = restTemplate.getForObject(url, String.class);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里引入了LoadBalancerClient，通过choose方法负载均衡选择一个“provider-ms”的服务实例，再通过restTemplate调用，服务实例的信息存储在ServiceInstance对象中，可以获取到主机名，端口号等信<br>启动ConsumerMsApplication，观察eureka-peer1,eureka-peer2，consumer-ms已经注册了<br><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/06.png"></p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/07.png"><p>此时调用刚才写的consume接口，发现已经能够将注册中心的两个服务实例展示出来了，说明服务间调用成功了</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/08.png"><h1 id="三eureka高可用"><a href="#三eureka高可用" class="headerlink" title="三eureka高可用"></a>三eureka高可用</h1><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/09.png"><p>虽然上面我们以双节点作为例子，但是实际上因负载等原因，我们往往可能需要在生产环境构建多于两个的Eureka Server节点。那么对于如何配置serviceUrl来让集群中的服务进行同步，需要我们更深入的理解节点间的同步机制来做出决策。Eureka Server的同步遵循着一个非常简单的原则：只要有一条边将节点连接，就可以进行信息传播与同步。什么意思呢？不妨我们通过下面的实验来看看会发生什么。场景一：假设我们有3个注册中心，我们将eureka-peer1、eureka-peer2、eureka-peer3各自都将eureka.client.serviceUrl.defaultZone指向另外两个节点。换言之，peer1、peer2、peer3是两两互相注册的。启动三个服务注册中心，并将provider-ms的serviceUrl指向eureka-peer1并启动，可以获得如下图所示的集群效果。</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/10.png"><p>我们在上述双eureka节点高可用的基础上，增加一个application-peer3.properties,并修改3个properties配置文件，内容如下：</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></pre></td><td class="code"><pre><span class="line">application-peer1.properties</span><br><span class="line"></span><br><span class="line">server.port=1011spring.application.name=registry-ha-ms</span><br><span class="line"></span><br><span class="line">eureka.instance.hostname=eureka-peer1eureka.client.serviceUrl.defaultZone=http://eureka-peer2:1012/eureka,http://eureka-peer3:1013/eureka</span><br></pre></td></tr></table></figure><p>application-peer2.properties</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">server.port=1012spring.application.name=registry-ha-ms</span><br><span class="line"></span><br><span class="line">eureka.instance.hostname=eureka-peer2eureka.client.serviceUrl.defaultZone=http://eureka-peer1:1011/eureka,http://eureka-peer3:1013/eureka</span><br></pre></td></tr></table></figure><p>application-peer3.properties</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">server.port=1013spring.application.name=registry-ha-ms</span><br><span class="line"></span><br><span class="line">eureka.instance.hostname=eureka-peer3eureka.client.serviceUrl.defaultZone=http://eureka-peer1:1011/eureka,http://eureka-peer2:1012/eureka</span><br></pre></td></tr></table></figure><p>复制一个，改名RegistryHaApplication-peer3 ，其中Program arguments: –spring.profiles.active=peer3</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/11.png"><p>配置本地Hosts域名解析</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">127.0.0.1 eureka-peer1127.0.0.1 eureka-peer2127.0.0.1 eureka-peer3</span><br></pre></td></tr></table></figure><p>分别启动RegistryHaApplication-peer1,RegistryHaApplication-peer2,RegistryHaApplication-peer3</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/11.png"><p>观察eureka-peer1,eureka-peer2,eureka-peer3,每个eureka都已经两两互相注册，且目前没有服务实例注册在注册中心（Instances currently registered with Eureka,No instance available）<br><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/12.png"></p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/13.png"><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/14.png"><p>试验下单边注册一个服务实例，即provider-ms的serviceUrl指向eureka-peer1修改provider-ms项目的application.properties配置，仅仅配置将provider-ms注册到eureka-peer1,然后启动ProviderApplication<br>server.port=2103spring.application.name=provider-ms#eureka.client.serviceUrl.defaultZone=<a href="http://registry-ms.pay-inner.com:1001/eurekaeureka.client.serviceUrl.defaultZone=http://eureka-peer1:1011/eureka" target="_blank" rel="noopener">http://registry-ms.pay-inner.com:1001/eurekaeureka.client.serviceUrl.defaultZone=http://eureka-peer1:1011/eureka</a><br>观察eureka-peer1,eureka-peer2,eureka-peer3发现provider-ms服务，已经通过eureka-peer1将服务实例信息同步给了eureka-peer2,eureka-peer3</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/15.png"><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/16.png"><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/17.png"><p>进一步，我们再将consumer-ms进行eureka-peer2单边注册</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/18.png"><p>观察eureka-peer1,eureka-peer2,eureka-peer3,此时eureka-peer2同步consumer-ms的服务实例信息到eureka-perr1,eureka-peer3<br><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/19.png"></p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/20.png"><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/21.png"><p>然后我们调用下consumer-ms的consume接口，没有问题</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/22.png"><p>将eureka-peer1 shutdownprovider-ms开始报错，访问不到eureka-peer1</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/23.png"><p>但这并不影响，consumer-ms调用provider-ms</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/24.png"><p>将eureka-peer2 shutdownconsumer-ms开始报错，访问不到eureka-peer2</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/25.png"><p>但丝毫不影响,consumer-ms调用provider-ms,做到了服务注册中心的高可用！（这里有点不严谨，因为即使把所有eureka节点都shutdown，还是可以调用的，服务消费方都会本地缓存服务提供方的地址的，但是如果eureka节点全部shutdown，那么新加入的服务实例就无法感知了）</p><img src="/2017/09/01/【Spring-Cloud微服务全家桶】02之高可用服务注册中心/26.png"><p>不过，不建议每个服务配置单边注册到某个eureka节点，强烈建议，每个服务配置所有eureka节点即provider-ms,consumer-ms的application.properties中的<em>eureka.client.serviceUrl.defaultZone</em>配成所有eureka节点</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">eureka.client.serviceUrl.defaultZone=http://eureka-peer1:1011/eureka,http://eureka-peer2:1012/eureka,http://eureka-peer3:1013/eureka</span><br></pre></td></tr></table></figure><p>这个配置的试验就不再赘述，可以自行尝试</p><p>示例代码：<a href="https://git.oschina.net/jaychang/spring-cloud-demo.git" target="_blank" rel="noopener">https://git.oschina.net/jaychang/spring-cloud-demo.git</a></p>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h1&gt;&lt;p&gt;在Spring Cloud微服务全家桶之服务注册、服务发现(Eureka、Consul作为服务注册中心)文中，使用的是单点eureka注册中心。在开发测试环境是可以的，但生产环境强烈不建议用单点eureka注册中心。&lt;/p&gt;
    
    </summary>
    
      <category term="Spring Cloud" scheme="http://jaychang.cn/categories/Spring-Cloud/"/>
    
    
      <category term="微服务" scheme="http://jaychang.cn/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/"/>
    
      <category term="Spring Cloud" scheme="http://jaychang.cn/tags/Spring-Cloud/"/>
    
  </entry>
  
</feed>
