<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[新运维]]></title>
  <link href="https://newops.cn/atom.xml" rel="self"/>
  <link href="https://newops.cn/"/>
  <updated>2018-11-21T19:29:52+08:00</updated>
  <id>https://newops.cn/</id>
  <author>
    <name><![CDATA[]]></name>
    
  </author>
  <generator uri="http://www.mweb.im">MWeb</generator>

  
  <entry>
    <title type="html"><![CDATA[letsencrypt auto renewal by dns challenge]]></title>
    <link href="https://newops.cn/15451920026292.html"/>
    <updated>2018-12-19T12:00:02+08:00</updated>
    <id>https://newops.cn/15451920026292.html</id>
    <content type="html"><![CDATA[
<p>源码: <a href="https://github.com/newopscn/autossl-alidns">autossl-alidns</a></p>

<p>使用条件:</p>

<ul>
<li>域名接入阿里云DNS</li>
<li>已经有解析记录存在</li>
</ul>

<h2 id="toc_0">env</h2>

<ul>
<li>ALI_SECRET_ID=</li>
<li>ALI_SECRET_KEY=</li>
</ul>

<h2 id="toc_1">create accounts and renewal config file</h2>

<ul>
<li>shell</li>
</ul>

<pre><code class="language-bash">$ certbot certonly --manual --preferred-challenges=dns --manual-auth-hook /usr/src/app/authenticator.sh -d hub.newops.cn
</code></pre>

<ul>
<li>docker</li>
</ul>

<pre><code class="language-bash">docker run -it --rm --name alidns -e ALI_SECRET_ID=xxx -e ALI_SECRET_KEY=xxx -v /data/ssl/:/etc/letsencrypt/ hub.newops.cn/base/alidns:1.0.0 update hub.newops.cn
</code></pre>

<h2 id="toc_2">renewal by force</h2>

<ul>
<li>shell</li>
</ul>

<pre><code class="language-bash">certbot renew --force-renewal
</code></pre>

<ul>
<li>docker</li>
</ul>

<pre><code class="language-bash">docker run -it --rm --name alidns -e ALI_SECRET_ID=xxx -e ALI_SECRET_KEY=xxx -v /data/ssl/:/etc/letsencrypt/ hub.newops.cn/base/alidns:1.0.0
</code></pre>

<h2 id="toc_3">renewal cron</h2>

<pre><code class="language-bash">$ crontab -l

00 09 01 * * /root/cron/update_cert_cron.sh # 每月定时重新签发一次证书
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[LVM 扩容 - 添加新硬盘]]></title>
    <link href="https://newops.cn/15391644260408.html"/>
    <updated>2018-10-10T17:40:26+08:00</updated>
    <id>https://newops.cn/15391644260408.html</id>
    <content type="html"><![CDATA[
<p>vmware虚拟机空间不足，进行扩容</p>

<h2 id="toc_0">VMware挂载硬盘</h2>

<p>挂载之后，默认不会被系统发现，需要执行命令添加</p>

<pre><code class="language-bash">ls /sys/class/scsi_host/
echo &quot;- - -&quot; &gt; /sys/class/scsi_host/host0/scan
echo &quot;- - -&quot; &gt; /sys/class/scsi_host/host1/scan
echo &quot;- - -&quot; &gt; /sys/class/scsi_host/host2/scan
</code></pre>

<h2 id="toc_1">查看当前状况</h2>

<ul>
<li>查看物理卷</li>
</ul>

<pre><code class="language-bash">$ pvs
  PV         VG     Fmt  Attr PSize  PFree 
  /dev/sda2  centos lvm2 a--  49.51g     0 
  /dev/sdb1  centos lvm2 a--  50.00g 40.00m
$ pvdisplay 
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               centos
  PV Size               49.51 GiB / not usable 3.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              12674
  Free PE               0
  Allocated PE          12674
  PV UUID               5ocR0z-ZfDF-sjE6-llnD-ilcJ-BNTE-G1MAhe
   
  --- Physical volume ---
  PV Name               /dev/sdb1
  VG Name               centos
  PV Size               50.00 GiB / not usable 3.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              12799
  Free PE               10
  Allocated PE          12789
  PV UUID               nCUaT0-IPJy-zeCK-ITj1-un2I-FQIc-aYmj3V
</code></pre>

<ul>
<li>查看逻辑卷组</li>
</ul>

<pre><code class="language-bash">$ vgs
  VG     #PV #LV #SN Attr   VSize  VFree 
  centos   2   2   0 wz--n- 99.50g 40.00m
$ vgdisplay 
  --- Volume group ---
  VG Name               centos
  System ID             
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  5
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               2
  Max PV                0
  Cur PV                2
  Act PV                2
  VG Size               99.50 GiB
  PE Size               4.00 MiB
  Total PE              25473
  Alloc PE / Size       25463 / 99.46 GiB
  Free  PE / Size       10 / 40.00 MiB
  VG UUID               v9I5Jd-OOFk-0VUV-Yhq4-eAnC-CHKO-DQ9mlx
</code></pre>

<ul>
<li>查看逻辑卷</li>
</ul>

<pre><code class="language-bash">$ lvs
  LV   VG     Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root centos -wi-ao---- 97.46g                                                    
  swap centos -wi-ao----  2.00g                                                    
$ lvdisplay 
  --- Logical volume ---
  LV Path                /dev/centos/swap
  LV Name                swap
  VG Name                centos
  LV UUID                QEWL0J-KDEi-A6uH-OgGl-65hZ-NZhh-dCO3YQ
  LV Write Access        read/write
  LV Creation host, time dragon.dsky, 2016-12-06 11:13:40 +0800
  LV Status              available
  # open                 2
  LV Size                2.00 GiB
  Current LE             512
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:1
   
  --- Logical volume ---
  LV Path                /dev/centos/root
  LV Name                root
  VG Name                centos
  LV UUID                dRtNvW-Tm7Q-gkzQ-2uhR-N6Gg-0I2V-6Bh9CM
  LV Write Access        read/write
  LV Creation host, time dragon.dsky, 2016-12-06 11:13:41 +0800
  LV Status              available
  # open                 1
  LV Size                97.46 GiB
  Current LE             24951
  Segments               2
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:0
</code></pre>

<h2 id="toc_2">创建新硬盘为物理卷</h2>

<pre><code class="language-bash">$ pvcreate /dev/sdb1
</code></pre>

<h2 id="toc_3">扩容逻辑卷组 - 加入新物理卷</h2>

<pre><code class="language-bash">$ vgextend centos /dev/sdb1
</code></pre>

<h2 id="toc_4">扩容逻辑卷</h2>

<pre><code class="language-bash">$ lvextend -L +50G /dev/mapper/centos-root
</code></pre>

<h2 id="toc_5">刷新逻辑卷大小</h2>

<ul>
<li>ext4 文件系统</li>
</ul>

<pre><code class="language-bash">$ resize2fs /dev/mapper/centos-root
</code></pre>

<ul>
<li>xfs 文件系统</li>
</ul>

<pre><code class="language-bash">$ xfs_growfs /dev/mapper/centos-root
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[open-falcon 从0.2.1升级到最新git commit版本(20180614)]]></title>
    <link href="https://newops.cn/15289802424278.html"/>
    <updated>2018-06-14T20:44:02+08:00</updated>
    <id>https://newops.cn/15289802424278.html</id>
    <content type="html"><![CDATA[
<h2 id="toc_0">编译最新代码</h2>

<blockquote>
<p>date: 20180614</p>

<p>commit: b399492</p>
</blockquote>

<ul>
<li>准备golang环境</li>
</ul>

<pre><code class="language-bash">$ docker run -it --rm --name golang -v /home/docker/gitbase/falcon-plus/:/opt golang bash

#(docker) apt-get update &amp;&amp; apt-get install -y git
</code></pre>

<ul>
<li>拉取最新代码</li>
</ul>

<pre><code class="language-bash">mkdir -p $GOPATH/src/github.com/open-falcon
cd $GOPATH/src/github.com/open-falcon
git clone https://github.com/open-falcon/falcon-plus.git
</code></pre>

<h2 id="toc_1">编译</h2>

<pre><code class="language-bash">Compilation
cd $GOPATH/src/github.com/open-falcon/falcon-plus/

# make all modules
make all

# make specified module
make agent

# pack all modules
make pack
after make pack you will got open-falcon-vx.x.x.tar.gz
if you want to edit configure file for each module, you can edit config/xxx.json before you do make pack
</code></pre>

<h2 id="toc_2">部署</h2>

<ul>
<li>db schema</li>
</ul>

<p>无需更新</p>

<ul>
<li>配置文件</li>
</ul>

<p>在graph/config/cfg.json中新增配置</p>

<blockquote>
<pre><code class="language-text">&quot;ioWorkerNum&quot;: 64,
</code></pre>
</blockquote>

<ul>
<li>启动</li>
</ul>

<pre><code class="language-bash">$ ./open-falcon start
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[freeipa server]]></title>
    <link href="https://newops.cn/15282719436136.html"/>
    <updated>2018-06-06T15:59:03+08:00</updated>
    <id>https://newops.cn/15282719436136.html</id>
    <content type="html"><![CDATA[
<ul>
<li><a href="https://www.freeipa.org/page/Docker">https://www.freeipa.org/page/Docker</a></li>
<li><a href="https://hub.docker.com/r/freeipa/freeipa-server/">https://hub.docker.com/r/freeipa/freeipa-server/</a></li>
</ul>

<h2 id="toc_0">prepare</h2>

<pre><code class="language-bash">net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 0
net.ipv6.conf.eth0.disable_ipv6 = 0

ping6 ::1
ping6 localhost
</code></pre>

<h2 id="toc_1">install</h2>

<pre><code class="language-bash">export NAME=ipa-master
export IMAGE=freeipa/freeipa-server:fedora-27

docker run -ti --rm --privileged \
  -v /:/host \
  -e HOST=/host \
  -e DATADIR=/data/${NAME} \
  -e NAME=${NAME} \
  -e IMAGE=${IMAGE} ${IMAGE} \
  /bin/install.sh --hostname ipa.newops.cn
</code></pre>

<h2 id="toc_2">run</h2>

<pre><code class="language-bash">docker run -it -d --privileged --restart=always --name ${NAME} \
    -h ipa.newops.cn \
    -e IPA_SERVER_IP=x.x.x.x \
    -p 80:80 \
    -p 443:443 \
    -p 389:389 \
    -p 636:636 \
    -p 88:88 \
    -p 464:464 \
    -p 88:88/udp \
    -p 464:464/udp \
    -v /data/${NAME}:/data:Z \
    -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
    --tmpfs /run --tmpfs /tmp \
    -v /dev/urandom:/dev/random:ro ${IMAGE}
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[caffe2 - Loading Pretrained Models]]></title>
    <link href="https://newops.cn/15275752075952.html"/>
    <updated>2018-05-29T14:26:47+08:00</updated>
    <id>https://newops.cn/15275752075952.html</id>
    <content type="html"><![CDATA[
<h2 id="toc_0">doc</h2>

<p><a href="https://github.com/caffe2/tutorials/blob/master/Loading_Pretrained_Models.ipynb">https://github.com/caffe2/tutorials/blob/master/Loading_Pretrained_Models.ipynb</a><br/>
<a href="https://github.com/caffe2/models/tree/master/squeezenet">https://github.com/caffe2/models/tree/master/squeezenet</a><br/>
<a href="https://caffe2.ai/docs/zoo">https://caffe2.ai/docs/zoo</a></p>

<h2 id="toc_1">point</h2>

<pre><code class="language-bash"># Run the net and return prediction
#results = p.run({&#39;data&#39;: img}) ---&gt; 这是的数据格式，官方例子中是dict，但根据报错提示，改成list就可以了(同时去除index: data)
results = p.run([img])
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GIT 分支模型 - 模拟]]></title>
    <link href="https://newops.cn/15265413252978.html"/>
    <updated>2018-05-17T15:15:25+08:00</updated>
    <id>https://newops.cn/15265413252978.html</id>
    <content type="html"><![CDATA[
<h2 id="toc_0">Git Flow分支模型</h2>

<blockquote>
<p>master[tag] + devlop + qa(常设分支) + feature-* + bugfix-*</p>
</blockquote>

<h2 id="toc_1">快速开发分支模型</h2>

<blockquote>
<p>master[tag] + qa + dev-* + bugfix-*</p>
</blockquote>

<h3 id="toc_2">功能开发</h3>

<h4 id="toc_3">开发新功能</h4>

<pre><code class="language-bash">$ git checkout -b dev-fed_register master
$ ./update-files.sh
$ git commit -a -m &#39;dev 注册功能&#39;
</code></pre>

<h4 id="toc_4">完成功能开发</h4>

<pre><code class="language-bash">$ git checkout master
$ git merge --no-ff dev-fed_register
$ git branch -d dev-fed_register
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[rancher install]]></title>
    <link href="https://newops.cn/15264592239484.html"/>
    <updated>2018-05-16T16:27:03+08:00</updated>
    <id>https://newops.cn/15264592239484.html</id>
    <content type="html"><![CDATA[
<pre><code class="language-bash">docker run --restart=always -it -d --name=rancher -p 80:80 -p 443:443 \
  -v /data/ssl/rancher.newops.cn/fullchain1.pem:/etc/rancher/ssl/cert.pem \
  -v /data/ssl/rancher.newops.cn/privkey1.pem:/etc/rancher/ssl/key.pem \
  -v /data/rancher:/var/lib/rancher \
  rancher/rancher
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[ansible-vault 实现普通用户在加密环境下非交互式地执行su/sudo命令]]></title>
    <link href="https://newops.cn/15257636092001.html"/>
    <updated>2018-05-08T15:13:29+08:00</updated>
    <id>https://newops.cn/15257636092001.html</id>
    <content type="html"><![CDATA[
<h2 id="toc_0">ansible-play 目录结构</h2>

<pre><code class="language-bash">$ tree 
.
├── ansible.cfg
├── test.yml
├── vars.yml
└── vault_password_file
</code></pre>

<pre><code class="language-bash">$ cat ansible.cfg 
[defaults]
remote_user = rokadmin
forks = 15
# inventory script
#inventory = /usr/local/inventory/get_host.py

# roles path
roles_path = ./roles

# temp files
remote_tmp = /tmp/ansible_tmp_$USER/
local_tmp = /tmp/ansible_tmp_$USER/

# ssh connect
remote_port = 4399
#remote_user = wd2admin
#private_key_file = roles/common/files/id_rsa-$USER
host_key_checking = False

# retry files
retry_files_enabled = False

# ansible log
log_path = /tmp/ansible_run_$USER.log

#ask_pass      = True

# if set, always use this private key file for authentication, same as
# if passing --private-key to ansible or ansible-playbook
#private_key_file = /path/to/file

# If set, configures the path to the Vault password file as an alternative to
# specifying --vault-password-file on the command line.
vault_password_file = ./vault_password_file

deprecation_warnings=False
allow_duplicates = True # if same role exists at diffrent position, run twice

[ssh_connection]
#ssh_args = &#39;-o ProxyCommand=&quot;ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no -p 4399 -W %h:%p -q rokadmin@103.14.33.233&quot;&#39;
#pipelining = True
</code></pre>

<pre><code class="language-bash">$ cat vars.yml 
ansible_become_pass: xxx
</code></pre>

<pre><code class="language-bash">$ cat test.yml 
- hosts: rok_global_ps.gm
  any_errors_fatal: &quot;{{ any_errors_fatal | default(true) }}&quot;
  gather_facts: false
  vars_files:
    - vars.yml
  tasks:
    - name: enable service rok-gm
      systemd:
        name: rok-gm
        daemon_reload: yes
        state: started
        enabled: True
      become: true
      become_method: su
</code></pre>

<h2 id="toc_1">执行</h2>

<pre><code class="language-bash">$ ansible-playbook test.yml
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Gitlab(ce)社区版备份和恢复]]></title>
    <link href="https://newops.cn/15120267877627.html"/>
    <updated>2017-11-30T15:26:27+08:00</updated>
    <id>https://newops.cn/15120267877627.html</id>
    <content type="html"><![CDATA[
<p><a href="https://docs.gitlab.com/ce/raketasks/backup_restore.html">官方参考</a></p>

<p>版本: gitlab-ce:9.5.5<br/>
运行环境: docker + gfs</p>

<h2 id="toc_0">备份 for Docker or Omnibus installations</h2>

<p>最佳实践</p>

<h3 id="toc_1">数据备份</h3>

<pre><code class="language-bash">$ gitlab-rake gitlab:backup:create STRATEGY=copy DIRECTORY=daily

# STRATEGY=copy 表示先进行拷贝，完成后再使用tar/gzip进行打包，避免出现因为频繁访问出来的`file changed as we read it`
# DIRECTORY=daily 将备份按天分组保存
</code></pre>

<ul>
<li>注意</li>
</ul>

<p>本例中使用了gfs作为gitlab的存储. 在进行备份时,若备份文件存储在gfs中会一直出现<code>tar: xxx: file changed as we read it</code>, 导致备份失败. 解决办法就是在<code>gitlab.rb</code>中将备份目录配置在本地存储</p>

<h3 id="toc_2">配置备份</h3>

<p>主要备份<code>gitlab.rb</code>和<code>gitlab-secrets.json</code></p>

<pre><code class="language-bash">$ tar czf /var/opt/gitlab/backups/`date +%s`_config_gitlab_backup.tar /etc/gitlab/gitlab.rb /etc/gitlab/gitlab-secrets.json /etc/gitlab/ssl

# /etc/gitlab/gitlab.rb 配置文件
# /etc/gitlab/gitlab-secrets.json CI的secrets文件
# 本例将域名证书挂载在/etc/gitlab/ssl/, 可移除
</code></pre>

<h3 id="toc_3">备份的配置参数</h3>

<p>配置文件位置<code>/etc/gitlab/gitlab.rb</code></p>

<p>备份存储位置</p>

<pre><code class="language-bash">gitlab_rails[&#39;backup_path&#39;] = /var/opt/gitlab/backups
</code></pre>

<p>备份保留时间，超过这个时间会被删除</p>

<pre><code class="language-bash"># limit backup lifetime to 7 days - 604800 seconds
gitlab_rails[&#39;backup_keep_time&#39;] = 604800
</code></pre>

<h2 id="toc_4">恢复 for Docker or Omnibus installations</h2>

<p>要求：</p>

<ul>
<li>使用相同版本</li>
</ul>

<p>恢复配置文件<code>gitlab.rb</code>到<code>/etc/gitlab/gitlab.rb</code>, 并重新配置</p>

<blockquote>
<p>gitlab-ctl reconfigure</p>
</blockquote>

<p>重启gitlab</p>

<blockquote>
<p>gitlab-ctl restart</p>
</blockquote>

<p>传输备份文件<code>1512026157_2017_11_30_9.5.5_gitlab_backup.tar</code>到gitlab.rb中配置的备份地址<code>gitlab_rails[&#39;backup_path&#39;]</code>, 默认为<code>/var/opt/gitlab/backups</code></p>

<p>停止有数据库连接的进程</p>

<pre><code class="language-bash">$ gitlab-ctl stop unicorn
$ gitlab-ctl stop sidekiq
# Verify
$ gitlab-ctl status
</code></pre>

<p>指定备份文件<code>TIMESTAMP</code>进行恢复，本例<code>TIMESTAMP</code>为<code>1512026157_2017_11_30_9.5.5</code></p>

<blockquote>
<p>gitlab-rake gitlab:backup:restore BACKUP=1512026157_2017_11_30_9.5.5</p>
</blockquote>

<p>然后恢复备份的secrets文件<code>gitlab-secrets.json</code>到<code>/etc/gitlab/gitlab-secrets.json</code></p>

<p>启动并测试</p>

<pre><code class="language-bash">$ gitlab-ctl restart
$ gitlab-rake gitlab:check SANITIZE=true
</code></pre>

<h2 id="toc_5">crontab 例行备份</h2>

<ul>
<li>容器中没有启用CRON调用，这里在宿主机上进行调用定时备份</li>
</ul>

<blockquote>
<p>0 4 * * * docker exec gitlabce_web_1 sh -c &quot;gitlab-rake gitlab:backup:create STRATEGY=copy DIRECTORY=daily&quot; CRON=1</p>
</blockquote>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[jenkins传递环境变量的方法 - slave ssh plugin]]></title>
    <link href="https://newops.cn/15113386629609.html"/>
    <updated>2017-11-22T16:17:42+08:00</updated>
    <id>https://newops.cn/15113386629609.html</id>
    <content type="html"><![CDATA[
<p><a href="https://wiki.jenkins.io/display/JENKINS/SSH+Slaves+plugin#SSHSlavesplugin-Loginprofilefiles">slave ssh plugin 参考</a></p>

<p>slave ssh plugin远程执行时，是non-interactive shell，同时也是login shell</p>

<h2 id="toc_0">让 SLAVE SSH PLUGIN 获取 SLAVE 机器环境变量的方法</h2>

<p>针对shell模式可以有以下几种方法. </p>

<p>注意：SHELL=bash</p>

<h3 id="toc_1">1.login shell 环境变量设置</h3>

<p>将export KEY=VALUE写入到 /etc/profile.d/xxx.sh</p>

<h3 id="toc_2">2.non-interactive shell 环境变量设置</h3>

<p>将export KEY=VALUE写入到 ~/.bashrc</p>

<h3 id="toc_3">3.non-interactive shell 特别方法 - 开启sshd变量传递参数</h3>

<p>有文章说需要设置UsePAM yes，实际测试并没有影响; 测试环境为centos7</p>

<p><a href="http://www.thinkplexx.com/learn/howto/security/ssh/setting-ssh-remote-host-environment-variables-interactive-shell">non-interactive 参考</a></p>

<ul>
<li>修改sshd参数</li>
</ul>

<pre><code class="language-bash">$ sed -i -e &#39;$aPermitUserEnvironment yes&#39; -e &#39;$aUseDNS no&#39; /etc/ssh/sshd_config
    
$ systemctl restart sshd
</code></pre>

<ul>
<li>添加变量到文件</li>
</ul>

<p>在/etc/environment或~/.ssh/environment中加入KEY=VALUE值</p>

<h2 id="toc_4">验证</h2>

<pre><code class="language-bash">$ ssh user@host env  #远程服务器上实际是以 bash -c env来执行的
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[使用gradle进行RPM打包 - Gradle buildRpm]]></title>
    <link href="https://newops.cn/15109027128968.html"/>
    <updated>2017-11-17T15:11:52+08:00</updated>
    <id>https://newops.cn/15109027128968.html</id>
    <content type="html"><![CDATA[
<p>此方法基于gradle-ospackage-plugin插件</p>

<h2 id="toc_0">参考文档</h2>

<p><a href="https://plugins.gradle.org/plugin/nebula.rpm">nebula:rpm</a><br/>
<a href="https://github.com/nebula-plugins/gradle-ospackage-plugin/wiki/RPM-Plugin">Gradle:RPM-Plugin wiki</a><br/>
<a href="https://docs.gradle.org/current/userguide/working_with_files.html#sec:copying_files">Gradle:copying_files</a></p>

<h2 id="toc_1">环境准备</h2>

<h3 id="toc_2">安装 Gradle</h3>

<p>可以使用构建好的<a href="hub.digi-sky.com/base/gradle:4.3.1">gradle镜像</a>, 参考<a href="https://code.digi-sky.com/base/gradle/blob/master/Dockerfile">Dockerfile</a></p>

<ul>
<li>依赖 java 1.8</li>
</ul>

<p>下载gradle二进制包，并设置环境变量</p>

<pre><code class="language-bash">$ VERSION=4.3.1

$ curl -O https://services.gradle.org/distributions/gradle-${VERSION}-bin.zip

$ export PATH=$PATH:/usr/local/gradle-${VERSION}/bin
</code></pre>

<p>验证是否安装成功</p>

<pre><code class="language-bash">$ gradle -v

------------------------------------------------------------
Gradle 4.3.1
------------------------------------------------------------

Build time:   2017-11-08 08:59:45 UTC
Revision:     e4f4804807ef7c2829da51877861ff06e07e006d

Groovy:       2.4.12
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_111 (Oracle Corporation 25.111-b14)
OS:           Linux 3.10.0-514.el7.x86_64 amd64
</code></pre>

<h2 id="toc_3">构建jre的rpm包</h2>

<p>这里使用Gradle 2.1开始支持的新写法，更加简洁；<a href="https://www.ccampo.me/java/spring/linux/2016/02/15/boot-service-package.html#fnref:1">老版本写法</a></p>

<p>需要创建构建文件build.gradle</p>

<h3 id="toc_4">Step 1: 引用依赖包 - Build script snippet</h3>

<pre><code class="language-groovy">plugins {
  id &quot;nebula.rpm&quot; version &quot;4.5.1&quot;
}
</code></pre>

<h3 id="toc_5">Step 2: 添加task</h3>

<pre><code class="language-groovy">task buildJRE(type: Rpm) {
    packageName = &#39;jre-8u111&#39;
    version = &#39;0.0.1&#39;
    release = &#39;dsky&#39;
    packageDescription = &#39;Digital sky - JRE Runtime Environment&#39;
    arch = X86_64
    os = LINUX
    
    ......
}
</code></pre>

<p>最终生成的build.gradle</p>

<pre><code class="language-bash">$ cat build.gradle
</code></pre>

<pre><code class="language-groovy">plugins {
  id &quot;nebula.ospackage&quot; version &quot;4.5.1&quot;
}

task buildJRE(type: Rpm) {
    packageName = &#39;jre-8u111&#39;
    version = &#39;0.0.1&#39;
    release = &#39;dsky&#39;
    packageDescription = &#39;Digital sky - JRE Runtime Environment&#39;
    arch = X86_64
    os = LINUX

    /*
    preInstall file(&#39;scripts/preInstall.sh&#39;)

    requires(&#39;epel-release&#39;)
    */

    FileTree jre_files = tarTree(&#39;jre-8u111-linux-x64.tar.gz&#39;)

    from(jre_files) {
        into &#39;/usr/local/&#39;
    }

    from(&#39;scripts/java.sh&#39;) {
        into &#39;/etc/profile.d/&#39;
    }

    link(&#39;/bin/java&#39;, &#39;/usr/local/jre1.8.0_111/bin/java&#39;)
}

println relativePath(buildJRE.archivePath)
</code></pre>

<h3 id="toc_6">开始构建</h3>

<ul>
<li>构建task: buildJRE</li>
</ul>

<pre><code class="language-bash">$ gradle clean buildJRE #buildJRE为task名称


&gt; Configure project : 
build/distributions/jre-8u111-0.0.1-dsky.x86_64.rpm


BUILD SUCCESSFUL in 26s
2 actionable tasks: 2 executed
</code></pre>

<ul>
<li>验证安装</li>
</ul>

<pre><code class="language-bash">$ rpm -ivh build/distributions/jre-8u111-0.0.1-dsky.x86_64.rpm
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[让容器在指定节点运行 - Assigning Pods to Nodes]]></title>
    <link href="https://newops.cn/15107386871938.html"/>
    <updated>2017-11-15T17:38:07+08:00</updated>
    <id>https://newops.cn/15107386871938.html</id>
    <content type="html"><![CDATA[
<p>官方参考：<a href="https://kubernetes.io/docs/concepts/configuration/assign-pod-node/">Assigning Pods to Nodes</a></p>

<p>容器组在运行时可以绑定或者优先使用某个节点。这样就可以指定有读写要求的应用部署到集群中有SSD硬盘的节点；还有需要在一个集群中进行构建任务时，就只需要指定到性能强劲的节点中去。</p>

<p>下面只讨论nodeSelector方式</p>

<h2 id="toc_0">nodeSelector</h2>

<p>使用时需要在PodSpec中增加nodeSelector配置，包含一个或一组key:value.</p>

<h3 id="toc_1">Step One: Attach label to the node</h3>

<ul>
<li>查询节点信息</li>
</ul>

<pre><code class="language-bash">$ kubectl get nodes --show-labels
</code></pre>

<p>可以返回当前所有节点信息，包括了系统默认标签.</p>

<ul>
<li>给节点打标签</li>
</ul>

<p><code>kubectl label nodes &lt;node-name&gt; &lt;label-key&gt;=&lt;label-value&gt;</code></p>

<pre><code class="language-bash">$ kubectl label nodes rose nodeName=rose
</code></pre>

<h3 id="toc_2">Step Two: Add a nodeSelector field to your pod configuration</h3>

<ul>
<li>原pod配置</li>
</ul>

<pre><code class="language-yaml">apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
</code></pre>

<ul>
<li>新pod配置-带指定标签</li>
</ul>

<pre><code class="language-yaml">apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    nodeName: rose
</code></pre>

<h2 id="toc_3">创建并查询结果</h2>

<pre><code class="language-bash">$ kubectl create -f pod.yaml
$ kubectl get pods -o wide

NAME                        READY     STATUS    RESTARTS   AGE       IP               NODE
nginx                        6/6       Running   0          3h        10.233.81.220        rose
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[解决 Mac OS 编译 python 时的ssl依赖问题]]></title>
    <link href="https://newops.cn/15081278426550.html"/>
    <updated>2017-10-16T12:24:02+08:00</updated>
    <id>https://newops.cn/15081278426550.html</id>
    <content type="html"><![CDATA[
<p>系统版本: 10.11.6</p>

<h2 id="toc_0">问题：</h2>

<p>直接编译安装python之后,使用时提示TLS/SSL不可用</p>

<pre><code class="language-bash">$ /usr/local/python3/bin/pip3 install requests

pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
Collecting requests

  Could not fetch URL https://pypi.python.org/simple/requests/: There was a problem confirming the ssl certificate: Can&#39;t connect to HTTPS URL because the SSL module is not available. - skipping
  Could not find a version that satisfies the requirement requests (from versions: )
No matching distribution found for requests
</code></pre>

<h2 id="toc_1">解决思路：</h2>

<p>查了config.log没有openssl模块依赖, 但是系统中是安装了openssl包的，which也能找到openssl命令，应该是编译python时没有检测到openssl</p>

<h2 id="toc_2">解决尝试</h2>

<h3 id="toc_3">Requires</h3>

<ul>
<li>涉及到编译需先安装 Xcode</li>
</ul>

<pre><code class="language-bash">$ brew install xcode
</code></pre>

<ul>
<li>openssl依赖, 在重新安装和更新时提示了编译时依赖ssl的使用方法</li>
</ul>

<pre><code class="language-bash">$ brew install openssl # 或者 brew update openssl

If you need to have this software first in your PATH run:
  echo &#39;export PATH=&quot;/usr/local/opt/openssl/bin:$PATH&quot;&#39; &gt;&gt; ~/.bash_profile

For compilers to find this software you may need to set:
    LDFLAGS:  -L/usr/local/opt/openssl/lib
    CPPFLAGS: -I/usr/local/opt/openssl/include
For pkg-config to find this software you may need to set:
    PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
</code></pre>

<h3 id="toc_4">安装 python3 时，加入CFLAGS/LDFLAGS重新编译</h3>

<pre><code class="language-bash">$ wget https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tar.xz

$ tar Jxvf Python-3.6.2.tar.xz

$ cd Python-3.6.2

$ CFLAGS=&quot;-I$(brew --prefix openssl)/include&quot; LDFLAGS=&quot;-L$(brew --prefix openssl)/lib&quot; ./configure --prefix=/usr/local/python3

$ make &amp;&amp; make install
</code></pre>

<p>按以上方法重新编译安装后，pip3已经可以正常下载其它软件包，问题解决</p>

<p>进一步python3虚拟空间环境的安装请看<a href="https://newops.cn/15047775881781.html">Centos7 中使用 virtualenv 管理 python3</a></p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How-to: 提交python软件到PyPI]]></title>
    <link href="https://newops.cn/15077893526985.html"/>
    <updated>2017-10-12T14:22:32+08:00</updated>
    <id>https://newops.cn/15077893526985.html</id>
    <content type="html"><![CDATA[
<p>PyPI -「Python Package Index」，官方介绍：</p>

<blockquote>
<p>The Python Package Index is a repository of software for the Python<br/>
programming language. There are currently 102159 packages here. </p>
</blockquote>

<p>使用python时，经常用到pip或easy_install安装软件包，因而一直对如何使用pip来管理自己的软件好奇.</p>

<p>刚好项目上有需要将腾讯公有云容器服务一些操作进行封装、简化，适合我们的部署方式. </p>

<p>下面就以该项目为例，将软件打包上传到PyPI, 然后通过pip安装使用.</p>

<h2 id="toc_0">软件包准备</h2>

<ol>
<li>qcloud_ccs的目录结构:</li>
</ol>

<pre><code class="language-bash">.
├── qcloud_ccs
│   └── __init__.py
├── README.md
└── setup.py
</code></pre>

<ol>
<li>qcloud_ccs代码内容:</li>
</ol>

<pre><code class="language-bash">$ cat qcloud_ccs/__init__.py 
#!/usr/bin/env python3
# encoding=utf-8

def test():
    print(u&#39;吃瓜群众&#39;)

def main():
    test()
</code></pre>

<ol>
<li>安装描述文件</li>
</ol>

<pre><code class="language-bash">$ cat setup.py 
#!/usr/bin/env python3
# coding: utf-8

from setuptools import setup

setup(
    name=&#39;qcloud_ccs&#39;,
    version=&#39;1.0.2&#39;,
    author=&#39;wanglin&#39;,
    author_email=&#39;wanglin@dbca.cn&#39;,
    url=&#39;https://newops.cn/qcloud_ccs&#39;,
    description=u&#39;以qcloud 容器服务sdk为基础. 1, 将机器创建/服务启停及更新等封装为接口;2.将机器和服务配置抽离为配置文件&#39;,
    packages=[&#39;qcloud_ccs&#39;],
    install_requires=[],
    entry_points={
        &#39;console_scripts&#39;: [
            &#39;qcloud_ccs=qcloud_ccs:test&#39;
        ]
    }
)
</code></pre>

<ul>
<li>name: 软件名</li>
<li>version: 版本号</li>
<li>&#39;qcloud_ccs=qcloud_ccs:test&#39;： 将qcloud_ccs:test封装为cmd命令，名称为qcloud_ccs</li>
</ul>

<h2 id="toc_1">PyPI 注册并上传</h2>

<h3 id="toc_2">帐号注册</h3>

<p>首先在<a href="https://pypi.python.org/pypi?%3Aaction=register_form">PyPI帐号注册地址</a>申请一个帐号</p>

<h3 id="toc_3">帐号配置</h3>

<pre><code class="language-bash">$ cat ~/.pypirc 
[distutils]
index-servers =
    pypi

[pypi]
repository=https://pypi.python.org/pypi
username=xxxx
password=xxxx
</code></pre>

<p>后面上传时如何出现：<em>403: Invalid or non-existent authentication information</em>, 请检查用户名、密码，注意密码不能用引号、百分号、注释符号等</p>

<h3 id="toc_4">软件打包、上传</h3>

<pre><code class="language-bash">$ python setup.py sdist upload         
running sdist
running egg_info
writing qcloud_ccs.egg-info/PKG-INFO
writing dependency_links to qcloud_ccs.egg-info/dependency_links.txt
writing entry points to qcloud_ccs.egg-info/entry_points.txt
writing top-level names to qcloud_ccs.egg-info/top_level.txt
reading manifest file &#39;qcloud_ccs.egg-info/SOURCES.txt&#39;
writing manifest file &#39;qcloud_ccs.egg-info/SOURCES.txt&#39;
running check
creating qcloud_ccs-1.0.2
creating qcloud_ccs-1.0.2/qcloud_ccs
creating qcloud_ccs-1.0.2/qcloud_ccs.egg-info
copying files to qcloud_ccs-1.0.2...
copying README.md -&gt; qcloud_ccs-1.0.2
copying setup.py -&gt; qcloud_ccs-1.0.2
copying qcloud_ccs/__init__.py -&gt; qcloud_ccs-1.0.2/qcloud_ccs
copying qcloud_ccs.egg-info/PKG-INFO -&gt; qcloud_ccs-1.0.2/qcloud_ccs.egg-info
copying qcloud_ccs.egg-info/SOURCES.txt -&gt; qcloud_ccs-1.0.2/qcloud_ccs.egg-info
copying qcloud_ccs.egg-info/dependency_links.txt -&gt; qcloud_ccs-1.0.2/qcloud_ccs.egg-info
copying qcloud_ccs.egg-info/entry_points.txt -&gt; qcloud_ccs-1.0.2/qcloud_ccs.egg-info
copying qcloud_ccs.egg-info/top_level.txt -&gt; qcloud_ccs-1.0.2/qcloud_ccs.egg-info
Writing qcloud_ccs-1.0.2/setup.cfg
creating dist
Creating tar archive
removing &#39;qcloud_ccs-1.0.2&#39; (and everything under it)
running upload
Submitting dist/qcloud_ccs-1.0.2.tar.gz to https://upload.pypi.org/legacy/
Server response (200): OK
</code></pre>

<h3 id="toc_5">安装使用</h3>

<pre><code class="language-bash">$ pip install qcloud_ccs
Collecting qcloud_ccs
  Downloading qcloud_ccs-1.0.2.tar.gz
Building wheels for collected packages: qcloud-ccs
  Running setup.py bdist_wheel for qcloud-ccs ... done
  Stored in directory: /home/k8s/.cache/pip/wheels/38/45/0d/435a007b7f6a47983ae16dd198e3864d515b42b79d31c490d6
Successfully built qcloud-ccs
Installing collected packages: qcloud-ccs
Successfully installed qcloud-ccs-1.0.2

$ qcloud_ccs
吃瓜群众
</code></pre>

<p>到这里，软件包已经可以在pip的软件仓库中找到并安装使用了 <sup>V^</sup></p>

<h3 id="toc_6">后台管理已上传的软件包</h3>

<p><img src="media/15077893526985/15077921792517.jpg" alt=""/></p>

<h3 id="toc_7">引用依赖</h3>

<p>如果软件依赖其它软件包，需在setup.py完善相关配置</p>

<pre><code class="language-bash">$ cat setup.py
...
    install_requires=[
        &#39;qcloudapi-sdk-python==2.0.7&#39;,
        &#39;requests==2.18.4&#39;
    ],
...
</code></pre>

<pre><code class="language-bash">$ pip install qcloud_ccs
Collecting qcloud_ccs
  Downloading qcloud_ccs-1.0.4.tar.gz
Collecting qcloudapi-sdk-python==2.0.7 (from qcloud_ccs)
  Downloading qcloudapi-sdk-python-2.0.7.tar.gz
Collecting requests==2.18.4 (from qcloud_ccs)
  Downloading requests-2.18.4-py2.py3-none-any.whl (88kB)
    100% |████████████████████████████████| 92kB 982kB/s 
Collecting certifi&gt;=2017.4.17 (from requests==2.18.4-&gt;qcloud_ccs)
  Downloading certifi-2017.7.27.1-py2.py3-none-any.whl (349kB)
    100% |████████████████████████████████| 358kB 783kB/s 
Collecting idna&lt;2.7,&gt;=2.5 (from requests==2.18.4-&gt;qcloud_ccs)
  Downloading idna-2.6-py2.py3-none-any.whl (56kB)
    100% |████████████████████████████████| 61kB 2.1MB/s 
Collecting urllib3&lt;1.23,&gt;=1.21.1 (from requests==2.18.4-&gt;qcloud_ccs)
  Downloading urllib3-1.22-py2.py3-none-any.whl (132kB)
    100% |████████████████████████████████| 133kB 1.2MB/s 
Collecting chardet&lt;3.1.0,&gt;=3.0.2 (from requests==2.18.4-&gt;qcloud_ccs)
  Downloading chardet-3.0.4-py2.py3-none-any.whl (133kB)
    100% |████████████████████████████████| 143kB 1.3MB/s 
Building wheels for collected packages: qcloud-ccs, qcloudapi-sdk-python
  Running setup.py bdist_wheel for qcloud-ccs ... done
  Stored in directory: /home/k8s/.cache/pip/wheels/cd/d8/d6/aac6a354d0fe4099b6837aceda25fc1f11de6629d4b1581cff
  Running setup.py bdist_wheel for qcloudapi-sdk-python ... done
  Stored in directory: /home/k8s/.cache/pip/wheels/55/5e/4e/e15deea2b7077e4e1838cbdbd512c4cf8e51eab3352ed8989a
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[在线试玩docker]]></title>
    <link href="https://newops.cn/15066659949551.html"/>
    <updated>2017-09-29T14:19:54+08:00</updated>
    <id>https://newops.cn/15066659949551.html</id>
    <content type="html"><![CDATA[
<p><a href="play-with-docker.com">PWD</a> 提供了一个免费、在线虚拟机, 目视配置不错，安装了docker相关环境</p>

<p>在这里可以编译、运行docker镜像，十分方便</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[安装 docker-compose]]></title>
    <link href="https://newops.cn/15059891419177.html"/>
    <updated>2017-09-21T18:19:01+08:00</updated>
    <id>https://newops.cn/15059891419177.html</id>
    <content type="html"><![CDATA[
<p><a href="https://docs.docker.com/compose/">Docker compose 官方文档</a></p>

<ul>
<li>install dependent python</li>
</ul>

<pre><code class="language-bash">$ yum install python-virtualenv

$ virtualenv -p /usr/bin/python2.7 --no-site-packages ~/pyenv/docker_py27/
</code></pre>

<ul>
<li>install docker compose</li>
</ul>

<pre><code class="language-bash">$ source ~/pyenv/docker_py27/bin/activate

$ pip install -U pip

$ pip install -U docker-compose #Note: pip version 6.0 or greater is required
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Harbor - 创建本地私有仓库 - LDAP管理用户]]></title>
    <link href="https://newops.cn/15059834250714.html"/>
    <updated>2017-09-21T16:43:45+08:00</updated>
    <id>https://newops.cn/15059834250714.html</id>
    <content type="html"><![CDATA[
<p><a href="https://github.com/vmware/harbor">Harbor</a>是一款企业级的docker私有仓库管理软件，由VMware创建。支持LDAP/多项目/多租户/镜像异地同步等对企业用户非常友好的功能.</p>

<p><a href="https://github.com/vmware/harbor/blob/master/docs/installation_guide.md">官方安装指南</a></p>

<p>本文主要实现以下方面：</p>

<ul>
<li>Docker-compose安装镜像并启动Harbor</li>
<li>LDAP 管理用户</li>
<li>ssl 认证</li>
<li>邮箱设置</li>
</ul>

<h3 id="toc_0">下载</h3>

<p><a href="http://harbor.orientsoft.cn/">国内下载源</a></p>

<pre><code class="language-bash">$ wget http://harbor.orientsoft.cn/harbor-1.2.0/harbor-offline-installer-v1.2.0.tgz
$ tar zxf harbor-offline-installer-v1.2.0.tgz 
$ cd harbor
</code></pre>

<h3 id="toc_1">配置harbor.cfg</h3>

<ul>
<li>访问域名</li>
</ul>

<pre><code class="language-yaml">#The IP address or hostname to access admin UI and registry service.
#DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.

hostname = hub.digi-sky.com
</code></pre>

<ul>
<li>访问方式 - 默认为http</li>
</ul>

<pre><code class="language-yaml">#The protocol for accessing the UI and token/notification service, by default it is http.
#It can be set to https if ssl is enabled on nginx.

ui_url_protocol = https
</code></pre>

<ul>
<li>LDAP</li>
</ul>

<pre><code class="language-yaml">#By default the auth mode is db_auth, i.e. the credentials are stored in a local database.
#Set it to ldap_auth if you want to verify a user&#39;s credentials against an LDAP server.
#auth_mode = db_auth

auth_mode = ldap_auth

ldap_url = ldap://ipa.digi-sky.com:389
ldap_searchdn = uid=ds_login,cn=users,cn=accounts,dc=digisky,dc=com
ldap_search_pwd = xxxx
ldap_basedn = cn=users,cn=accounts,dc=digisky,dc=com
ldap_uid = uid
ldap_scope = 3
ldap_timeout = 5
</code></pre>

<ul>
<li>email 设置</li>
</ul>

<pre><code class="language-yaml">email_identity = 

email_server = smtp.qiye.163.com
email_server_port = 994
email_username = devops@digisky.com
email_password = xxxx
email_from = dockerhub &lt;hub.digi-sky.com&gt;
email_ssl = true
</code></pre>

<ul>
<li>ssl证书</li>
</ul>

<p><a href="https://newops.cn/15059675768201.html">申请letsencrypt证书</a></p>

<pre><code class="language-yaml">#The path of cert and key files for nginx, they are applied only the protocol is set to https

ssl_cert = /data/ssl/archive/hub.digi-sky.com/fullchain1.pem
ssl_cert_key = /data/ssl/archive/hub.digi-sky.com/privkey1.pem
</code></pre>

<h3 id="toc_2">安装并启动</h3>

<p>Harbor采用docker-compose的方式管理容器, 依赖docker 1.13+ 及docker-compose 1.16+</p>

<ul>
<li><p><a href="https://newops.cn/15059891419177.html">安装 docker-compose</a></p></li>
<li><p>Default installation (without Notary/Clair)</p></li>
</ul>

<pre><code class="language-bash">$ sudo ./install.sh
</code></pre>

<h3 id="toc_3">Trouble</h3>

<ul>
<li>重新配置及管理</li>
</ul>

<p>如果有配置修改harbor.cfg, 先停止容器，使用prepare脚本重新生成</p>

<pre><code class="language-bash">$ cd harbor
$ docker-compose down
$ vim harbor.cfg
...
$ docker-compose up -d
</code></pre>

<ul>
<li>配置文件修改</li>
</ul>

<p><em>不支持双引号或单引号转义</em></p>

<pre><code class="language-text">  1.在给变量赋值的时候，不能带有引号
  
  2.变量值中不要带有#号等特殊字符
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[申请letsencrypt证书]]></title>
    <link href="https://newops.cn/15059675768201.html"/>
    <updated>2017-09-21T12:19:36+08:00</updated>
    <id>https://newops.cn/15059675768201.html</id>
    <content type="html"><![CDATA[
<h3 id="toc_0">docker 手动获取证书 - dns</h3>

<p>dns方式：申请验证时，会提示一个相关域名的txt记录，按提示进行解析后进行验证，验证通过后在本地目录生成证书</p>

<ul>
<li>docker certbot 用法帮助</li>
</ul>

<pre><code class="language-bash">docker run --rm -it certbot/certbot certbot --help all
</code></pre>

<ul>
<li>获取证书 - 域名: code.digi-sky.com</li>
</ul>

<pre><code class="language-bash">docker run --rm -it -v /data/ssl:/etc/letsencrypt certbot/certbot certonly --manual --preferred-challenges dns -d code.digi-sky.com

# 证书文件生成在/data/ssl/archive/目录下
# -d 指定域名，可跟多个
</code></pre>

<h3 id="toc_1">shell 自动验证并获取证书 - webroot</h3>

<p>webroot方式：先验证网站所有权，通过后发放证书</p>

<p>要实现自动验证需要有在网站根目录生成验证文件的脚本authenticator.sh及验证通过后清理文件的脚本cleanup.sh</p>

<ul>
<li>所需脚本</li>
</ul>

<pre><code class="language-bash"># cat authenticator.sh 
#!/bin/bash
echo $CERTBOT_VALIDATION &gt; /var/www/htdocs/newops/.well-known/acme-challenge/$CERTBOT_TOKEN
</code></pre>

<pre><code class="language-bash"># cat cleanup.sh 
#!/bin/bash
rm -f /var/www/htdocs/newops/.well-known/acme-challenge/$CERTBOT_TOKEN
</code></pre>

<ul>
<li>验证并获取证书</li>
</ul>

<pre><code class="language-bash">certbot certonly --manual --preferred-challenges=http --manual-auth-hook ./authenticator.sh --manual-cleanup-hook ./cleanup.sh -d newops.cn

# -d 指定域名，可跟多个
</code></pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Centos7 yum 安装 docker CE (Docker中国官网)]]></title>
    <link href="https://newops.cn/15059615198679.html"/>
    <updated>2017-09-21T10:38:39+08:00</updated>
    <id>https://newops.cn/15059615198679.html</id>
    <content type="html"><![CDATA[
<p>Docker已经在国内开通了官网，也有很多镜像站可用.现在安装docker已经完全不用担心网络的问题，之前采用阿里云脚本的安装方法没有优势了.</p>

<p><a href="https://www.docker-cn.com/get-docker">Docker 中国</a> 推荐了四种安装docker ce(社区版)的方法: centos extra源安装、docker ce源安装、rpm直接安装及shell脚本安装，本文采用第二种.</p>

<h3 id="toc_0">安装前准备</h3>

<ul>
<li>初始化服务器环境</li>
</ul>

<pre><code class="language-bash">curl -s https://gitlab.com/snippets/1674279/raw?inline=false |sh -
</code></pre>

<h3 id="toc_1">准备镜像源</h3>

<ul>
<li>CLEAN PACKAGES</li>
</ul>

<pre><code class="language-bash">yum remove docker \
                  docker-common \
                  docker-selinux \
                  docker-engine
</code></pre>

<ul>
<li><a href="https://docs.docker.com/engine/installation/linux/docker-ce/centos/#install-using-the-repository">SET UP THE DOCKER CE REPOSITORY</a></li>
</ul>

<pre><code class="language-bash">yum install -y device-mapper-persistent-data lvm2
curl -o /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
yum clean all
</code></pre>

<h3 id="toc_2">安装</h3>

<ul>
<li>查看可安装的docker ce版本</li>
</ul>

<pre><code class="language-bash">yum list docker-ce.x86_64  --showduplicates | sort -r
</code></pre>

<ul>
<li>安装</li>
</ul>

<pre><code class="language-bash"># 安装指定版本
yum install -y docker-ce-17.12.1.ce

# 或 安装最新版
yum install -y docker-ce
</code></pre>

<h3 id="toc_3">安装后设置</h3>

<p><a href="https://docs.docker.com/engine/installation/linux/linux-postinstall/">postinstall docker</a></p>

<ul>
<li>普通用户使用docker</li>
</ul>

<p>默认docker以root运行，普通用户需要使用docker时就必须加sudo命令.</p>

<p>增加用户组docker(本文方法安装时，已经创建). 普通用户在加入到docker组后，就可以直接调用docker了</p>

<pre><code class="language-bash"># 创建普通用户docker并加入到docker组
useradd docker -m -g docker

# 或者将新用户加入到docker组
usermod -aG docker $USER
</code></pre>

<ul>
<li>镜像加速</li>
</ul>

<p>国内使用还是用加速比较好，<a href="https://www.docker-cn.com/registry-mirror">registry-mirror</a> 是Docker 中国官方镜像加速站入口</p>

<pre><code class="language-bash"># cat /etc/docker/daemon.json

{
  &quot;registry-mirrors&quot;: [&quot;https://registry.docker-cn.com&quot;],
  &quot;graph&quot;: &quot;xxx&quot;
}
</code></pre>

<ul>
<li>开机自启动</li>
</ul>

<p>systemd</p>

<pre><code class="language-bash">$ sudo systemctl enable docker

# To disable this behavior, use disable instead.

$ sudo systemctl disable docker
</code></pre>

<ul>
<li>Specify DNS servers for Docker</li>
</ul>

<p>还可以设置成<a href="https://docs.docker.com/engine/installation/linux/linux-postinstall/#specify-dns-servers-for-docker">使用指定的DNS</a></p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[填坑记-ssl中间证书]]></title>
    <link href="https://newops.cn/15051223976628.html"/>
    <updated>2017-09-11T17:33:17+08:00</updated>
    <id>https://newops.cn/15051223976628.html</id>
    <content type="html"><![CDATA[
<h2 id="toc_0">欢快地申请证书并安装</h2>

<p>在申请域名证书的时候，需要提供组织信息，如公司名称等，然后用ssl工具，如openssl，使用这些信息生成公钥密钥对，其中的公钥就是证书申请文件(CSR - Cerificate Signing Request). 将CSR文件提交给证书服务商进行签发，返回证书文件(CERTIFICATE)（当然不同的格式会有不同的名称）</p>

<p>这样我们的域名就有了一个被外界认可的身份证明，然后在nginx/tomcat下进行配置对外, 再用浏览器访问，会发现锁标志那里是绿色的<img src="media/15051223976628/15051270551349.jpg" alt=""/>, yeah!</p>

<p><em>但是事情太顺利一般都没有好事！</em>陆续接到反馈，在windows系统下有些工具报证书错误...持续构建服务拉代码失败...浏览器有时清理缓存后报证书不可信...</p>

<p><strong><em>现在我知道了，这种情况一定是中了中间证书的坑</em></strong></p>

<h2 id="toc_1">填坑</h2>

<ul>
<li>什么是中间证书？</li>
</ul>

<p>普通用户的证书是由证书签发机构签发的，但他们很可能只是一个中间代理机构，也是需要有一个凭证的，这个就是中间证书. 中间证书是由上级或者根证书签发机构签发</p>

<ul>
<li>为什么浏览器访问正常？</li>
</ul>

<p>浏览器中内置了根证书，如Chrome/Firefox, 没有中间证书. 但是在访问时发现没有中间证书的话，会自动去下载或使用访问其他网站时缓存的相同证书(所以有时清理缓存会造成问题). 补齐证书后自然访问正常</p>

<ul>
<li>为什么服务器工具访问失败?</li>
</ul>

<p>因为不会自动下载中间证书...</p>

<h3 id="toc_2">检测证书状态</h3>

<ul>
<li>命令行(适合于高手，或者服务部署于内网的情况)</li>
</ul>

<pre><code class="language-bash">openssl s_client -connect app-git.ppgame.com:443
</code></pre>

<p><img src="media/15051223976628/15051298696419.jpg" alt=""/></p>

<p>首先看depth，如果都是0, 说明在认证链(Certificate chain)的第一条就没有通过</p>

<p><img src="media/15051223976628/15051300610073.jpg" alt=""/></p>

<p>可以看到从证书读出的信息中包含了两组认证: s表示认证对象，i表示认证机构</p>

<p><img src="media/15051223976628/15051303534276.jpg" alt=""/></p>

<p>不能认证第一条证书，说明中间证书有问题</p>

<ul>
<li>第三方工具</li>
</ul>

<p><a href="https://www.myssl.cn/tools/check-server-cert.html">SSL服务器证书安装检查器</a></p>

<p><img src="media/15051223976628/15051304614790.jpg" alt=""/></p>

<p>返回结果</p>

<p><img src="media/15051223976628/15051307153216.jpg" alt=""/></p>

<p><img src="media/15051223976628/15051307415355.jpg" alt=""/></p>

<p><img src="media/15051223976628/15051307599776.jpg" alt=""/></p>

<p>很明显，正在缺少中间证书导致的问题</p>

<h3 id="toc_3">获取中间证书</h3>

<ul>
<li><p>最直接的办法当然是找中间证书代理商要啊，谁让我们给钱了</p></li>
<li><p>既然浏览器能缓存证书，那一定还在电脑里，是可以导出来的. Mac系统可以用钥匙串工具来导入导出证书</p></li>
<li><p>使用第三方工具<a href="https://www.myssl.cn/tools/downloadchain.html">下载中间证书</a></p></li>
</ul>

<p><img src="media/15051223976628/15051310508987.jpg" alt=""/></p>

<p>将我们的域名证书填进去会生成中间证书的下载地址. 相同的如果你要获取根证书，只要把中间证书填在这里就可以了</p>

<h2 id="toc_4">Let’s Encrypt</h2>

<p>最方便的是使用Let’s Encrypt来进行证书申请及网站部署：免费！操作简单！<br/>
<a href="https://newops.cn/15059675768201.html">申请letsencrypt证书</a></p>

<ul>
<li>不需要提供组织信息 (能证明网站或域名归你操控就可以了)</li>
<li>不需要自已生成CSR证书申请文件</li>
<li>不需要自己生成私钥</li>
</ul>

<p>签发成功后会返还以下文件：</p>

<pre><code class="language-bash">`privkey.pem`  : the private key for your certificate.
`fullchain.pem`: the certificate file used in most server software.
`chain.pem`    : used for OCSP stapling in Nginx &gt;=1.3.7.
`cert.pem`     : will break many server configurations, and should not be used
                 without reading further documentation (see link below).

We recommend not moving these files. For more information, see the Certbot
User Guide at https://certbot.eff.org/docs/using.html#where-are-my-certificates.
</code></pre>

<p>部署的时候，使用privkey.pem/fullchain.pem</p>

]]></content>
  </entry>
  
</feed>
