<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>DevOps技术分享 &#187; Ansible</title>
	<atom:link href="http://www.showerlee.com/archives/category/ci-cd/ansible/feed" rel="self" type="application/rss+xml" />
	<link>http://www.showerlee.com</link>
	<description>与你共同学习运维开发</description>
	<lastBuildDate>Mon, 19 Oct 2020 05:51:41 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.6</generator>
		<item>
		<title>Mac+Docker+Ansible部署WordPress Application</title>
		<link>http://www.showerlee.com/archives/1938</link>
		<comments>http://www.showerlee.com/archives/1938#comments</comments>
		<pubDate>Tue, 06 Dec 2016 09:42:37 +0000</pubDate>
		<dc:creator>showerlee</dc:creator>
				<category><![CDATA[Ansible]]></category>
		<category><![CDATA[Docker]]></category>

		<guid isPermaLink="false">http://www.showerlee.com/?p=1938</guid>
		<description><![CDATA[很久没有更新了，今天给大家在这里推荐使用Docker部署Wordpress Application Docke [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>
	很久没有更新了，今天给大家在这里推荐使用<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>部署Wordpress Application
</p>
<p>
	<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>就不多介绍了，大家可以理解为是他是一个虚拟集装箱，将原来以服务器为基础单元的集群，细化到以每个服务进程为单元。这样的优点在于：
</p>
<p>
	1. 隔离开发环境和具体可执行进程，可跨平台跨主机使用，统一开发环境
</p>
<p>
	2. 节约时间成本，硬件成本，秒级别快速部署启动
</p>
<p>
	3. 支持持续集成，可利用相关部署工具(<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>, saltstack)进行快速部署
</p>
<p>
	4. 可作为轻量级别主机或节点部署应用
</p>
<p>
	5. 未来可能代替虚拟机的虚拟容器
</p>
<p>
	
</p>
<p>
	最后利用<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>去对<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>容器进行具体服务的部署，最大限度的体现轻量级，统一开发部署环境的好处。
</p>
<p>
	
</p>
<p>
	在部署之前首先给大家介绍一下我的部署结构:
</p>
<p>
	<span style="color:#E53333;">dockerfiles</span><br />
<span style="color:#E53333;"> ├── mariadb</span><br />
<span style="color:#E53333;"> │ &nbsp; ├── <a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>file</span><br />
<span style="color:#E53333;"> │ &nbsp; ├── ansible</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; ├── mariadb-install-container.yml</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; ├── mariadb.sh</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; ├── mariadb.sql</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; └── my.cnf</span><br />
<span style="color:#E53333;"> │ &nbsp; └── run.sh</span><br />
<span style="color:#E53333;"> ├── nginx</span><br />
<span style="color:#E53333;"> │ &nbsp; ├── <a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>file</span><br />
<span style="color:#E53333;"> │ &nbsp; ├── ansible</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; ├── default.conf</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; ├── nginx-container.yml</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; └── nginx.conf</span><br />
<span style="color:#E53333;"> │ &nbsp; └── run.sh</span><br />
<span style="color:#E53333;"> └── php</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; ├── Dockerfile</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; ├── ansible</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; │ &nbsp; ├── info.php</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; │ &nbsp; ├── php-container.yml</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; │ &nbsp; ├── test-db-conn.php</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; │ &nbsp; ├── wp-config.php</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; │ &nbsp; └── <a href="http://www.conf" rel="nofollow">http://www.conf</a></span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; └── run.sh</span>
</p>
<p>
	Dockerfiles主目录下面分别是3个服务所对应的目录，每个目录大致分为Dockerfile配置文件, ansible目录，以及run.sh
</p>
<p>
	Dockerfile这个大家都清楚，用来Build容器镜像的配置脚本。
</p>
<p>
	ansible目录下保存需要在容器内使用到的ansible playbook相应配置文件。
</p>
<p>
	run.sh则是创建和运行容器的启动脚本，我们分别去执行对应目录的执行脚本用来构建Docker容器所对应的服务。
</p>
<p>
	
</p>
<p>
	这里给大家提供一个我的gitlab私人仓库的链接，方便大家去下载这个部署脚本：
</p>
<p>
	<a href="https://git.showerlee.com/showerlee/ansible-docker-wp" target="_blank">https://git.showerlee.com/showerlee/ansible-docker-wp</a>
</p>
<p>
	
</p>
<p>
	大家如果想对Docker和<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>有不太明白的地方可以先阅读我之前写的文章。
</p>
<p>
	Docker:&nbsp;<a href="http://www.showerlee.com/archives/1758" target="_blank">http://www.showerlee.com/archives/1758</a>
</p>
<p>
	Ansible: <a href="http://www.showerlee.com/archives/1649" target="_blank">http://www.showerlee.com/archives/1649</a>
</p>
<p>
	
</p>
<p>
	<strong><span style="color:#337FE5;font-size:16px;">一.环境部署</span></strong>
</p>
<p>
	<span style="color:#337FE5;">Local system: &nbsp;MAC OS X 10.12.1</span><br />
<span style="color:#337FE5;">Docker: &nbsp; Docker 1.12.3</span>
</p>
<p>
	<span style="color:#E53333;">Tip: 这里说明一下，较早版本的Docker若在非Linux内核下去安装需要去配合安装virtualbox虚拟机才能正常使用，这里我们使用的最新版本Docker配合MAC OS 10.12.1最新开放出来的内核接口，可无需调用额外虚拟机直接安装使用即可。</span>
</p>
<p>
	
</p>
<p>
	<strong><span style="color:#337FE5;font-size:16px;">二.Docker部署</span></strong>
</p>
<p>
	<span style="font-size:14px;color:#337FE5;"><strong>Mariadb container</strong></span>
</p>
<p>
	Mariadb是Mysql在CentOS7上的一个开源分支, 大家可以理解就是一个mysql. 这里首先我们为什么先去部署并启动Mariadb, 是因为我们后面启动Docker时会用到它的一个Link参数，这个参数不仅保证两台容器会安全的利用这个Link去传输数据，而且还会在被Link主机内创建一个host记录，方便我们直接用FQDN名去访问相应主机。
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">Dockerfile</span>
</p>
<pre class="prettyprint lang-bsh">FROM ansible/centos7-ansible/:stable

ADD ansible /data/ansible

WORKDIR /data/ansible

RUN ansible-playbook mariadb-install-container.yml -c local

# Initialize and start mariadb
RUN chmod +x mariadb.sh

CMD ["./mariadb.sh"]

EXPOSE 3306</pre>
<p>这里简单来说就是下载集成Ansible的CentOS7容器镜像，并将ansible playbook及相应配置文件复制到容器内去部署MariaDB初始环境，最终启动服务，并开启3306DB端口.</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/mariadb-install-container.yml</span>
</p>
<pre class="prettyprint">- name: Install Mariadb container
  hosts: local
  vars:
    conf_path: /etc/my.cnf
    src_socket: /data/mariadb_data/mysql.sock
    link_socket: /var/lib/mysql/mysql.sock
    user: mysql
  tasks:
  - name: Install epel-release package
    yum: name=epel-release state=latest

  - name: Install required packages
    yum: name={{ item }} state=latest
    with_items:
      - net-tools
      - lsof 
      - nmap
      - mariadb-server
      - MySQL-python

  - name: Copy mariadb conf
    copy: src=my.cnf dest={{ conf_path }} mode=0644

  - name: Link mysql socket
    file: 
      src={{ src_socket }} dest={{ link_socket }} state=link force=yes</pre>
<p>这里是ansible playbook, 基本上就是利用ansible本地安装Epel源以及Mariadb相应的安装包，然后进行DB的相关配置。</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/mariadb.sh</span>
</p>
<pre class="prettyprint lang-bsh">#!/bin/sh
 chown -R mysql:mysql /var/lib/mysql

 mysql_install_db --user=mysql --datadir=/data/mariadb_data &gt; /dev/null

 mysqld_safe &amp;

 sleep 5s

 mysql -v &lt; mariadb.sql

 sleep 5s

 ps -wef | grep mysql | grep -v grep | awk '{print $2}' | xargs kill -9

 mysqld_safe --user mysql</pre>
<p>这里是对Mariadb进行初始化安装，并使用sql脚本更改root密码及相应权限和创建Wordpress数据库，最终重启DB服务。</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/Mariadb.sql</span>
</p>
<pre class="prettyprint">USE mysql;
 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
 FLUSH PRIVILEGES;
 UPDATE user SET password=PASSWORD("123456") WHERE user='root';
 FLUSH PRIVILEGES;
 CREATE DATABASE wordpress;
 FLUSH PRIVILEGES;</pre>
<p><span style="color:#337FE5;">ansible/my.cnf</span> </p>
<pre class="prettyprint">[mysqld]
datadir=/data/mariadb_data
socket=/data/mariadb_data/mysql.sock
port=3306
bind-address = 0.0.0.0

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in <a href="http://fedoraproject.org/wiki/Systemd" rel="nofollow">http://fedoraproject.org/wiki/Systemd</a>

[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid

#
# include all files from the config directory
#
!includedir /etc/my.cnf.d</pre>
<p>Mariadb的DB配置.</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">run.sh</span>
</p>
<pre class="prettyprint lang-bsh">#/bin/bash

IMAGE="leon/mariadb"
Container="mariadb"

docker build -t ${IMAGE} .

docker run -d -p 3306:3306 --name ${Container} ${IMAGE}</pre>
<p>最终我们使用docker build去创建一个基于Dockerfile配置的MariaDB容器镜像，并用docker run去启动这个容器镜像。</p>
<p>
	<span style="color:#E53333;">Tip: -d为后台启动容器，-p为打开端口，--name 为创建容器名，-t为打一个镜像标签。</span>
</p>
<p>
	
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:14px;"><strong>PHP container</strong></span>
</p>
<p>
	接下来我们会部署启动php-fpm服务，作为解析Wordpress网站的php服务, 它会开启9000端口，方便后面的nginx container去进行反向连接。
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">Dockerfile</span>
</p>
<pre class="prettyprint lang-bsh">FROM ansible/centos7-ansible:stable

ADD ansible /data/ansible

WORKDIR /data/ansible

RUN ansible-playbook php-container.yml -c local

# Add the volume to php application
VOLUME ["/data/app"]

# CMD ["php-fpm", "--nodaemonize"]
ENTRYPOINT ["/usr/sbin/php-fpm", "-F"]

EXPOSE 9000</pre>
<p>
	这里的配置基本上和MariaDB类似，区别在于我们会在这里去创建一个与nginx共同使用的共享网站目录，里面会保存Wordpress源代码和相关php测试文件。
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/php-container.yml</span>
</p>
<pre class="prettyprint">- name: Create PHP container
  hosts: local
  vars:
    app_dir: /data/app
    src_dir: /data/src
    phpfpm_path: /etc/php-fpm.d/www.conf
    info_path: /data/app/info.php
    test_path: /data/app/test-db-conn.php
    wp_url: <a href="https://cn.wordpress.org/wordpress-4.5.3-zh_CN.tar.gz" rel="nofollow">https://cn.wordpress.org/wordpress-4.5.3-zh_CN.tar.gz</a>
    wp_config: /data/app/wp-config.php
  tasks:
  - name: Install epel-release packages
    yum: name=epel-release state=latest 

  - name: Install required packages
    yum: name={{ item }} state=latest
    with_items:
      - net-tools
      - lsof
      - nmap
      - unzip
      - mariadb

  - name: Install php packages
    yum: name={{ item }} state=latest
    with_items:
      - php
      - php-mysql
      - php-fpm
      - php-gd
      - php-mbstring

  - name: Create dir
    file: path={{ item }} state=directory mode=0755
    with_items:
      - "{{ app_dir }}"
      - "{{ src_dir }}"

  - name: Unpack WP package
    unarchive: src={{ wp_url }} dest={{ src_dir }} remote_src=yes

  - name: Move WP source code to app_dir
    shell: "shopt -s dotglob &amp;&amp; mv {{ src_dir }}/wordpress/* {{ app_dir }}" 

  - name: Copy wp configuration
    copy: src=wp-config.php dest={{ wp_config }}

  - name: Copy php info page
    copy: src=info.php dest={{ info_path }} mode=0755

  - name: Copy test-db-conn page
    copy: src=test-db-conn.php dest={{ test_path }} mode=0755

  - name: Copy nginx configuration
    copy: src=www.conf dest={{ phpfpm_path }} mode=0755</pre>
<p>
	这里playbook配置内容较多，不过基本上就是安装php-fpm以及相应安装包，配置php-fpm配置项，并下载Wordpress源代码并将DB信息写入WP配置文件，复制php测试脚本等。
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/info.php</span>
</p>
<pre class="prettyprint">&lt;?php
phpinfo();
?&gt;
</pre>
<p><span style="color:#337FE5;">ansible/test-db-conn.php</span> </p>
<pre class="prettyprint">&lt;html&gt;&lt;body&gt;&lt;h1&gt;The page to test Mariadb connection.&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;
&lt;?php
 $conn=mysql_connect('mariadb','root','123456');
 if ($conn)
   echo "&lt;h2&gt;Success...&lt;/h2&gt;";
 else
   echo "&lt;h2&gt;Failure...&lt;/h2&gt;";
 
?&gt;
</pre>
<p><span style="color:#337FE5;">ansible/wp-config.php</span> </p>
<pre class="prettyprint lang-php">&lt;?php
/**
 * WordPress基础配置文件。
 *
 * 这个文件被安装程序用于自动生成wp-config.php配置文件，
 * 您可以不使用网站，您需要手动复制这个文件，
 * 并重命名为“wp-config.php”，然后填入相关信息。
 *
 * 本文件包含以下配置选项：
 *
 * * MySQL设置
 * * 密钥
 * * 数据库表名前缀
 * * ABSPATH
 *
 * @link <a href="https://codex.wordpress.org/zh-cn:%E7%BC%96%E8%BE%91_wp-config.php" rel="nofollow">https://codex.wordpress.org/zh-cn:%E7%BC%96%E8%BE%91_wp-config.php</a>
 *
 * @package WordPress
 */

// ** MySQL 设置 - 具体信息来自您正在使用的主机 ** //
/** WordPress数据库的名称 */
define('DB_NAME', 'wordpress');

/** MySQL数据库用户名 */
define('DB_USER', 'root');

/** MySQL数据库密码 */
define('DB_PASSWORD', '123456');

/** MySQL主机 */
define('DB_HOST', 'mariadb');

/** 创建数据表时默认的文字编码 */
define('DB_CHARSET', 'utf8');

/** 数据库整理类型。如不确定请勿更改 */
define('DB_COLLATE', '');

/**#@+
 * 身份认证密钥与盐。
 *
 * 修改为任意独一无二的字串！
 * 或者直接访问{@link <a href="https://api.wordpress.org/secret-key/1.1/salt/" rel="nofollow">https://api.wordpress.org/secret-key/1.1/salt/</a>
 * WordPress.org密钥生成服务}
 * 任何修改都会导致所有cookies失效，所有用户将必须重新登录。
 *
 * @since 2.6.0
 */
define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');

/**#@-*/

/**
 * WordPress数据表前缀。
 *
 * 如果您有在同一数据库内安装多个WordPress的需求，请为每个WordPress设置
 * 不同的数据表前缀。前缀名只能为数字、字母加下划线。
 */
$table_prefix  = 'wp_';

/**
 * 开发者专用：WordPress调试模式。
 *
 * 将这个值改为true，WordPress将显示所有用于开发的提示。
 * 强烈建议插件开发者在开发环境中启用WP_DEBUG。
 *
 * 要获取其他能用于调试的信息，请访问Codex。
 *
 * @link <a href="https://codex.wordpress.org/Debugging_in_WordPress" rel="nofollow">https://codex.wordpress.org/Debugging_in_WordPress</a>
 */
define('WP_DEBUG', false);

/**
 * zh_CN本地化设置：启用ICP备案号显示
 *
 * 可在设置→常规中修改。
 * 如需禁用，请移除或注释掉本行。
 */
define('WP_ZH_CN_ICP_NUM', true);

/* 好了！请不要再继续编辑。请保存本文件。使用愉快！ */

/** WordPress目录的绝对路径。 */
if ( !defined('ABSPATH') )
	define('ABSPATH', dirname(__FILE__) . '/');

/** 设置WordPress变量和包含文件。 */
require_once(ABSPATH . 'wp-settings.php');</pre>
<p><span style="color:#337FE5;">ansible/www.conf</span> </p>
<pre class="prettyprint">; Start a new pool named 'www'.
[www]

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses on a
;                            specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = 0.0.0.0:9000

; Set listen(2) backlog. A value of '-1' means unlimited.
; Default Value: -1
;listen.backlog = -1
 
; List of ipv4 addresses of FastCGI clients which are allowed to connect.
; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
; must be separated by a comma. If this value is left blank, connections will be
; accepted from any ip address.
; Default Value: any
;listen.allowed_clients = any

; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions. 
; Default Values: user and group are set as the running user
;                 mode is set to 0666
listen.owner = nobody
listen.group = nobody
listen.mode = 0666

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
; RPM: apache Choosed to be able to access some dir as httpd
user = nobody
; RPM: Keep a group allowed to write in log dir.
group = nobody

; Choose how the process manager will control the number of child processes.
; Possible Values:
;   static  - a fixed number (pm.max_children) of child processes;
;   dynamic - the number of child processes are set dynamically based on the
;             following directives:
;             pm.max_children      - the maximum number of children that can
;                                    be alive at the same time.
;             pm.start_servers     - the number of children created on startup.
;             pm.min_spare_servers - the minimum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is less than this
;                                    number then some children will be created.
;             pm.max_spare_servers - the maximum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is greater than this
;                                    number then some children will be killed.
; Note: This value is mandatory.
pm = dynamic

; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes to be created when pm is set to 'dynamic'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
; CGI.
; Note: Used when pm is set to either 'static' or 'dynamic'
; Note: This value is mandatory.
pm.max_children = 5

; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
pm.start_servers = 2

; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.min_spare_servers = 1

; The desired maximum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.max_spare_servers = 3
 
; The number of requests each child process should execute before respawning.
; This can be useful to work around memory leaks in 3rd party libraries. For
; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
; Default Value: 0
;pm.max_requests = 500

; The URI to view the FPM status page. If this value is not set, no URI will be
; recognized as a status page. By default, the status page shows the following
; information:
;   accepted conn    - the number of request accepted by the pool;
;   pool             - the name of the pool;
;   process manager  - static or dynamic;
;   idle processes   - the number of idle processes;
;   active processes - the number of active processes;
;   total processes  - the number of idle + active processes.
; The values of 'idle processes', 'active processes' and 'total processes' are
; updated each second. The value of 'accepted conn' is updated in real time.
; Example output:
;   accepted conn:   12073
;   pool:             www
;   process manager:  static
;   idle processes:   35
;   active processes: 65
;   total processes:  100
; By default the status page output is formatted as text/plain. Passing either
; 'html' or 'json' as a query string will return the corresponding output
; syntax. Example:
;   <a href="http://www.foo.bar/status" rel="nofollow">http://www.foo.bar/status</a>
;   <a href="http://www.foo.bar/status?json" rel="nofollow">http://www.foo.bar/status?json</a>
;   <a href="http://www.foo.bar/status?html" rel="nofollow">http://www.foo.bar/status?html</a>
; Note: The value must start with a leading slash (/). The value can be
;       anything, but it may not be a good idea to use the .php extension or it
;       may conflict with a real PHP file.
; Default Value: not set 
;pm.status_path = /status
 
; The ping URI to call the monitoring page of FPM. If this value is not set, no
; URI will be recognized as a ping page. This could be used to test from outside
; that FPM is alive and responding, or to
; - create a graph of FPM availability (rrd or such);
; - remove a server from a group if it is not responding (load balancing);
; - trigger alerts for the operating team (24/7).
; Note: The value must start with a leading slash (/). The value can be
;       anything, but it may not be a good idea to use the .php extension or it
;       may conflict with a real PHP file.
; Default Value: not set
;ping.path = /ping

; This directive may be used to customize the response of a ping request. The
; response is formatted as text/plain with a 200 response code.
; Default Value: pong
;ping.response = pong
 
; The timeout for serving a single request after which the worker process will
; be killed. This option should be used when the 'max_execution_time' ini option
; does not stop script execution for some reason. A value of '0' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_terminate_timeout = 0
 
; The timeout for serving a single request after which a PHP backtrace will be
; dumped to the 'slowlog' file. A value of '0s' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_slowlog_timeout = 0
 
; The log file for slow requests
; Default Value: not set
; Note: slowlog is mandatory if request_slowlog_timeout is set
slowlog = /var/log/php-fpm/www-slow.log
 
; Set open file descriptor rlimit.
; Default Value: system defined value
;rlimit_files = 1024
 
; Set max core size rlimit.
; Possible Values: 'unlimited' or an integer greater or equal to 0
; Default Value: system defined value
;rlimit_core = 0
 
; Chroot to this directory at the start. This value must be defined as an
; absolute path. When this value is not set, chroot is not used.
; Note: chrooting is a great security feature and should be used whenever 
;       possible. However, all PHP paths will be relative to the chroot
;       (error_log, sessions.save_path, ...).
; Default Value: not set
;chroot = 
 
; Chdir to this directory at the start. This value must be an absolute path.
; Default Value: current directory or / when chroot
;chdir = /var/www
 
; Redirect worker stdout and stderr into main error log. If not set, stdout and
; stderr will be redirected to /dev/null according to FastCGI specs.
; Default Value: no
;catch_workers_output = yes
 
; Limits the extensions of the main script FPM will allow to parse. This can
; prevent configuration mistakes on the web server side. You should only limit
; FPM to .php extensions to prevent malicious users to use other extensions to
; exectute php code.
; Note: set an empty value to allow all extensions.
; Default Value: .php
;security.limit_extensions = .php .php3 .php4 .php5

; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
; Default Value: clean env
;env[HOSTNAME] = $HOSTNAME
;env[PATH] = /usr/local/bin:/usr/bin:/bin
;env[TMP] = /tmp
;env[TMPDIR] = /tmp
;env[TEMP] = /tmp

; Additional php.ini defines, specific to this pool of workers. These settings
; overwrite the values previously defined in the php.ini. The directives are the
; same as the PHP SAPI:
;   php_value/php_flag             - you can set classic ini defines which can
;                                    be overwritten from PHP call 'ini_set'. 
;   php_admin_value/php_admin_flag - these directives won't be overwritten by
;                                     PHP call 'ini_set'
; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.

; Defining 'extension' will load the corresponding shared extension from
; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
; overwrite previously defined php.ini values, but will append the new value
; instead.

; Default Value: nothing is defined by default except the values in php.ini and
;                specified at startup with the -d argument
;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f <a href="mailto:www@my.domain.com">www@my.domain.com</a>
;php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
;php_admin_value[memory_limit] = 128M

; Set session path to a directory owned by process user
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session</pre>
<p>
	<span style="color:#337FE5;">run.sh</span>
</p>
<pre class="prettyprint lang-bsh">#/bin/bash

IMAGE="leon/php"
Container="php"
Link="mariadb"

docker build -t ${IMAGE} .

docker run -d -p 9000:9000 --name ${Container} --link ${Link}:${Link} ${IMAGE}</pre>
<p>
	这里去创建PHP并启动镜像，需要提到这里的link就是文章开头说到的需要与DB进行安全传输，并在php容器内创建一个DB的host记录。
</p>
<p>
	我们可以使用这个命令去进入容器，查看该记录。
</p>
<pre class="prettyprint lang-bsh"># docker exec -it php bash
[root@7e6188415cb2 ansible]# cat /etc/hosts
127.0.0.1      	localhost
::1    	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.2     mariadb 29ae9593fbfc
172.17.0.3     7e6188415cb2</pre>
<p><span style="color:#E53333;">Tip: 这里可以看到mariadb的内网ip为172.17.0.2, php-fpm的为172.17.0.3, 我们MAC本机作为Docker主机与容器间会进行DNAT通信，容器因为在同一内网，可自由通信，前提是需要在创建和启动镜像前打开相应服务端口。</span> </p>
<p>
	
</p>
<p>
	<span style="color:#E53333;"><br />
</span>
</p>
<p>
	<span style="color:#337FE5;font-size:14px;"><strong>Nginx container</strong></span>
</p>
<p>
	这里最终我们会利用Nginx作为一个反向代理，配置www.example.com去访问我们的PHP容器下的Wordpress页面.
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">Dockerfile</span>
</p>
<pre class="prettyprint lang-bsh">FROM ansible/centos7-ansible/epel:stable

ADD ansible /data/ansible

WORKDIR /data/ansible

RUN ansible-playbook nginx-container.yml -c local

VOLUME ["/data/app"]

# CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT [ "/usr/sbin/nginx" ]

EXPOSE 80
EXPOSE 443</pre>
<p>
	这里基本与PHP的容器配置类似，执行playbook，共享网站目录，启动nginx服务并打开80，443端口。
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/nginx-container.yml</span>
</p>
<pre class="prettyprint lang-bsh">- name: Create Nginx container
  hosts: local
  vars:
    global_conf_path: /etc/nginx/nginx.conf
    server_conf_path: /etc/nginx/conf.d/default.conf
  tasks:
  - name: Install epel-release package
    yum: name=epel-release state=latest

  - name: Install required packages
    yum: name={{ item }} state=latest
    with_items:
      - net-tools
      - lsof
      - nmap
      - nginx

  - name: Copy nginx global conf
    copy: src=nginx.conf dest={{ global_conf_path }} mode=0644

  - name: Copy nginx server conf
    copy: src=default.conf dest={{ server_conf_path }} mode=0644</pre>
<p>
	这里安装nginx，并将配置文件复制到对应nginx目录.
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/defalut.conf</span>
</p>
<pre class="prettyprint"># The default server
#

upstream backend {
    server php:9000;
}

server {
    listen 80;
    server_name <a href="http://www.example.com" rel="nofollow">http://www.example.com</a>;
    root /data/app;
    index index.php index.html index.htm;

    location / {
          try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        fastcgi_pass backend;
        fastcgi_index index.php;
        include fastcgi.conf;
    }

}</pre>
<p>
	<span style="color:#337FE5;">ansible/nginx.conf</span>
</p>
<pre class="prettyprint"># For more information on configuration, see:
#   * Official English Documentation: <a href="http://nginx.org/en/docs/" rel="nofollow">http://nginx.org/en/docs/</a>
#   * Official Russian Documentation: <a href="http://nginx.org/ru/docs/" rel="nofollow">http://nginx.org/ru/docs/</a>

user nobody;
worker_processes 1;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
daemon off;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 768;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See <a href="http://nginx.org/en/docs/ngx_core_module.html#include" rel="nofollow">http://nginx.org/en/docs/ngx_core_module.html#include</a>
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2 default_server;
#        listen       [::]:443 ssl http2 default_server;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}</pre>
<p><span style="color:#337FE5;">run.sh</span> </p>
<pre class="prettyprint lang-bsh">#/bin/bash

IMAGE="leon/nginx"
Container="nginx"
Link="php"
Volume="php"

docker build -t ${IMAGE} .

docker run -d -p 80:80 -p 443:443 --name ${Container} --link ${Link}:${Link} --volumes-from ${Volume} ${IMAGE}</pre>
<p>这里需要注意的是我们添加了一个--volumes-from参数用来调用PHP share出来的网站目录。</p>
<p>
	
</p>
<p>
	这里我们分别执行3个目录下的执行脚本(run.sh)后，效果如下:
</p>
<p>
	#&nbsp;docker ps
</p>
<pre class="prettyprint lang-bsh">CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                      NAMES
7e6188415cb2        leon/php            "/usr/sbin/php-fpm -F"   2 hours ago         Up About an hour    0.0.0.0:9000-&gt;9000/tcp                     php
29ae9593fbfc        leon/mariadb        "./mariadb.sh"           2 hours ago         Up About an hour    0.0.0.0:3306-&gt;3306/tcp                     mariadb
d07bb4aea5c1        leon/nginx          "/usr/sbin/nginx"        3 days ago          Up 4 hours          0.0.0.0:80-&gt;80/tcp, 0.0.0.0:443-&gt;443/tcp   nginx</pre>
<p>
	
</p>
<p>
	#&nbsp;docker images
</p>
<pre class="prettyprint lang-bsh">REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
leon/php                       latest              f243f43c99a2        3 hours ago         883 MB
leon/mariadb                   latest              7046c76b434a        3 hours ago         1.694 GB
leon/nginx                     latest              d588d0a73eee        7 days ago          737.6 MB
ansible/centos7-ansible        stable              5108f665e079        3 weeks ago         433.3 MB</pre>
<p>
	
</p>
<p>
	
</p>
<p>
	到这里我们就成功创建并启动了我们Wordpress所需要的三个基础服务。
</p>
<p>
	我们可以利用<strong>Docker start "容器名"</strong>或者<strong>Docker stop "容器名" </strong>去启动或者关闭这个包含具体服务的容器，可以作为我们在Docker服务器下重启服务的命令。
</p>
<p>
	如果需要进入容器进行调测，我们也可以使用<strong>Docker exec -it </strong><strong>"容器名" bash</strong>
</p>
<p>
	<strong><br />
</strong>
</p>
<p>
	测试结果
</p>
<p>
	我们给MAC主机添加一个host记录
</p>
<p>
	# cat /etc/hosts
</p>
<pre class="prettyprint lang-bsh">127.0.0.1 <a href="http://www.example.com" rel="nofollow">http://www.example.com</a></pre>
<p>
	
</p>
<p>
	
</p>
<p>
	然后使用PHP测试文件分别测试PHP是否部署成功以及PHP与MariaDB是否联通
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/12/test-db-conn.jpg"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/12/test-db-conn-1024x279.jpg" alt="test-db-conn" width="1024" height="279" class="alignnone size-large wp-image-1940" /></a> <a href="http://www.showerlee.com/wp-content/uploads/2016/12/phpinfo.jpg"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/12/phpinfo-1024x720.jpg" alt="phpinfo" width="1024" height="720" class="alignnone size-large wp-image-1941" /></a>
</p>
<p>
	
</p>
<p>
	
</p>
<p>
	最终我们访问www.example.com查看wordpress是否部署成功。
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/12/wp-install.jpg"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/12/wp-install-1024x797.jpg" alt="wp-install" width="1024" height="797" class="alignnone size-large wp-image-1942" /></a>
</p>
<p>
	
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/12/admin.jpg"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/12/admin-1024x567.jpg" alt="admin" width="1024" height="567" class="alignnone size-large wp-image-1957" /></a> <a href="http://www.showerlee.com/wp-content/uploads/2016/12/index.jpg"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/12/index-1024x553.jpg" alt="index" width="1024" height="553" class="alignnone size-large wp-image-1958" /></a>
</p>
<p>
	
</p>
<p>
	<span>至此使用Docker+Ansible部署Wordpress大功告成。。。&nbsp;</span></p>
<div>声明: 本文采用 <a rel="external" href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" title="署名-非商业性使用-相同方式共享 3.0 Unported">CC BY-NC-SA 3.0</a> 协议进行授权</div><div>转载请注明来源：<a rel="external" title="DevOps技术分享" href="http://www.showerlee.com/archives/1938">DevOps技术分享</a></div><div>本文链接地址：<a rel="external" title="Mac+Docker+Ansible部署WordPress Application" href="http://www.showerlee.com/archives/1938">http://www.showerlee.com/archives/1938</a></div>]]></content:encoded>
			<wfw:commentRss>http://www.showerlee.com/archives/1938/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Jenkins+Ansible+Gitlab自动化部署三剑客</title>
		<link>http://www.showerlee.com/archives/1880</link>
		<comments>http://www.showerlee.com/archives/1880#comments</comments>
		<pubDate>Fri, 11 Mar 2016 05:00:47 +0000</pubDate>
		<dc:creator>showerlee</dc:creator>
				<category><![CDATA[Ansible]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Jenkins]]></category>
		<category><![CDATA[gitlab]]></category>

		<guid isPermaLink="false">http://www.showerlee.com/?p=1880</guid>
		<description><![CDATA[最近一直在学习Ansible的一些playbook的写法, 所以一直没有怎么更新, 想到目前大家对诸如salt [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>
	
</p>
<p>
	最近一直在学习<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>的一些playbook的写法, 所以一直没有怎么更新, 想到目前大家对诸如saltstack, docker, <a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>等自动化部署相关的工具很感兴趣, 但又苦于没有可学习的中文实例, 这里我就把我这几个月所接触到目前国外比较流行的部署经验给大家分享一下.
</p>
<p>
	<span style="line-height:1.5;">首先给大家介绍的是<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>, 恩, 重要的问题说三遍, 不是Saltstack, <a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>作为一个python写的自动化部署工具, 确实较之前我所接触的Chef, saltstack, puppet更有自己的一些优势, 首先就是agentless, 无需在Linux client安装任何服务即可无缝连接Linux default ssh端口进行部署(windows需要安装winrm 开启ssh服务), 这点其实我觉得非常重要, 可以想象很多公司本身是对network管理非常严格的, 在部署一个产品的同时你需要考虑很多时间成本, 使用其他部署工具本身非常棘手的问题就是去申请开端口, client量少的话, 我们可以去等, 多的话本身你去request, waiting, unblock port等等long long process.... 最后会耗费很长时间. 这个对很多产品本身就是很致命的. 不推荐Saltstack的原因也是因为其需要在每台agent逐一去安装client service并测试, 这本身就会耗费一些时间成本.</span>
</p>
<p>
	<span style="line-height:1.5;">其他呢? 其实我觉得就是容易上手, 语法简单, 有现成模板让你去学习, 加之是我们非常喜爱的python语法, why not?</span>
</p>
<p>
	<span style="line-height:1.5;">Jenkins不用我多说, 估计懂行的人都在用它, 开源, 轻量级, 兼容性和扩展性强, 直观的GUI管理这都是它的优势, 配合<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>我觉得用起来会非常easy going.</span>
</p>
<p>
	<span style="line-height:1.5;">最后提一下Gitlab, 为什么要用Gitlab? 他作为一个代码版本控制系统和部署有什么关系呢? 其实这里就涉及一个我们<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a> playbook管理问题, 试想我们需要维护一个公司庞大的server集群, 我们所有需要部署的机器或者产品会对应我们相对的部署脚本, 我们使用的<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a> playbook如果只是保存在Ansible Server的具体某个目录, 这本身就不便于我们进行编写维护更新(想想每次都跑到远程去编写playbook或者每次在本地编写好后再upload到远程我都会脑补数以万计的草泥马从我眼前呼啸而来).</span>
</p>
<p>
	<span style="line-height:1.5;">这里Gitlab就给我们提供一个非常方便以及直观的Playbook management. 我们需要做的其实就是在Gitlab去建立一个对应产品或者server的playbook仓库, 然后我们在本地写好后直接commit到这个仓库, 最后在部署的时候, 去让Jenkins pull这个playbook到其workspace, 并作为一个Job去run这个playbook, 这样是不是很规范, 而且便于管理?</span>
</p>
<p>
	<span style="line-height:1.5;">当然Ansible本身企业版Tower也会提供一个类似管理并维护playbook以及监控ansible本身running process的GUI管理系统, 用起来也很不错, 但作为收费版本, 我们在这里就不做过多阐述了.</span>
</p>
<p>
	<span style="line-height:1.5;"><br />
</span>
</p>
<p>
	<span style="line-height:1.5;">这里我推荐Jenkins和Ansible可以安装到同一个环境作为部署server, Gitlab作为版本控制系统可单独部署在另一台server.</span>
</p>
<p>
	<span style="color:#E53333;">总结:</span>
</p>
<p>
	<span style="color:#E53333;">Jenkins首先从Gitlab去抓取我们写好的具体产品的playbook, 并使用virtualenv下的Ansible相关命令, 保证我们在一个clean的环境下使用stable version去批量部署我们的产品到远程client.</span>
</p>
<p>
	
</p>
<p>
	<span style="color:#E53333;font-size:16px;">Let's go.....</span>
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:16px;">一. 安装环境</span>
</p>
<p>
	System: CentOS 6.7 x64 (deploy.example.com)
</p>
<p>
	Jenkins:&nbsp;Jenkins ver. 1.650
</p>
<p>
	Ansible: Ansible 2.1.0
</p>
<p>
	Gitlab:&nbsp;GitLab 7.14.3
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:16px;">二. Jenkins配置</span>
</p>
<p>
	我们创建deploy用户作为jenkins_user, workspace为deploy家目录下的jenkins目录.
</p>
<p>
	# su - root
</p>
<p>
	# adduser deploy
</p>
<p>
	# wget -O /etc/yum.repos.d/jenkins.repo <a href="http://pkg.jenkins-ci.org/redhat/jenkins.repo" rel="nofollow">http://pkg.jenkins-ci.org/redhat/jenkins.repo</a>
</p>
<p>
	<span style="line-height:1.5;"># rpm --import <a href="https://jenkins-ci.org/redhat/jenkins-ci.org.key" rel="nofollow">https://jenkins-ci.org/redhat/jenkins-ci.org.key</a></span>
</p>
<p>
	<span style="line-height:1.5;"># yum install jenkins -y</span>
</p>
<p>
	<span style="line-height:1.5;"># vi&nbsp;/etc/sysconfig/jenkins</span>
</p>
<p>
	<span style="line-height:1.5;"> </span>
</p>
<pre class="prettyprint lang-bsh">...
JENKINS_HOME="/home/deploy/jenkins"
JENKINS_USER="deploy"
...</pre>
<p>
	# service jenkins start
</p>
<p>
	浏览器访问Jenkins页面
</p>
<p><a href="http://deploy.example.com:8080" rel="nofollow">http://deploy.example.com:8080</a></p>
<p>
	安装完成, 以下是我已经配置好的一些Jenkins&nbsp;Job.
</p>
<p>
	<span style="line-height:1.5;"></span>
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-0.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-0-1024x338.png" alt="QQ20160311-0" width="1024" height="338" class="alignnone size-large wp-image-1884" /></a>
</p>
<p>
	这里我们使用一个国内PHP网站模板phpcms作为我们需要部署的产品进行本次范例演示, 在进行最终的Build前我们需要做一些准备工作, 稍后我们会回到这个界面.
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:16px;">三. Ansible配置</span>
</p>
<p>
	这里我们需要配置virtualenv去隔离我们ansible的发行版本为最新版本2.1.0, 默认pip或者yum安装的1.9版本因为BUG以及对windows不兼容的原因, 这里不推荐使用.
</p>
<p>
	配置步骤传送门:&nbsp;<a href="http://www.showerlee.com/archives/1862" target="_blank">http://www.showerlee.com/archives/1862</a>
</p>
<p>
	Ansible-playbook范例传送门:&nbsp;<a href="http://www.showerlee.com/archives/1649" target="_blank">http://www.showerlee.com/archives/1649</a>
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:16px;">四. Gitlab配置</span>
</p>
<p>
	部署并使用传送门:&nbsp;<a href="http://www.showerlee.com/archives/1285" target="_blank">http://www.showerlee.com/archives/1285</a>
</p>
<p>
	我们最终会创建一个ansible playbook仓库&nbsp;git@git.example.cn:showerlee/Ansible-showerlee.git, 并在本地编写好我们的规则, 最终commit到这个仓库, 以便Jenkins去调用我们的部署<span style="line-height:1.5;">规则.</span>
</p>
<p>
	<span style="color:#E53333;">这里博主单独clone出来一份部署phpcms的playbook仓库</span><span style="color:#E53333;">, 算是给大家的福利:</span>
</p>
<p>
	<a href="https://git.showerlee.com/showerlee/leon-playbook-phpcms1.1" target="_blank"><span style="color:#E53333;"><a href="https://git.showerlee.com/showerlee/leon-playbook-phpcms1.1" rel="nofollow">https://git.showerlee.com/showerlee/leon-playbook-phpcms1.1</a></span><span style="color:#E53333;"></span></a>
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-2.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-2-1024x500.png" alt="" width="800" height="391" class="alignnone size-large wp-image-1885" title="" align="" /></a>
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-3.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-3-1024x250.png" alt="" width="800" height="195" class="alignnone size-large wp-image-1886" title="" align="" /></a>
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-4.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-4-1024x274.png" alt="" width="800" height="214" class="alignnone size-large wp-image-1887" title="" align="" /></a>
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:16px;">五.最终部署</span>
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">准备工作完毕, 我们接下来给大家介绍Jenkins Job配置.</span>
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">1.创建一个new item</span>
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-5.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-5.png" alt="QQ20160311-5" width="354" height="313" class="alignnone size-full wp-image-1888" /></a>
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">2. 创建一个freestyle Job, 命名规则"产品名-环境", 这里我们为Phpcms-Dev</span>
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-6.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-6-1024x306.png" alt="" width="800" height="239" class="alignnone size-large wp-image-1889" title="" align="" /></a>
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">3. Job配置</span>
</p>
<p>
	<span style="color:#337FE5;">1). 定制Build参数.</span>
</p>
<p>
	这里Dynamic Choice Parameter用来通过Groovy脚本来抓取这个git仓库的所有branch, 并作为一个多选项, 方便我们在最终Build前去选择我们需要的这个产品Branch分支.
</p>
<p>
	Groovy抓取Git branch代码:
</p>
<p>
	
</p>
<pre class="prettyprint lang-bsh">def gettags = ("git ls-remote -h <a href="mailto:git@git.showerlee.com">git@git.showerlee.com</a>:showerlee/phpcms.git").execute()  
gettags.text.readLines().collect { it.split()[1].replaceAll('refs/heads/', '')  }.unique() </pre>
<p>
	
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-11.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-11-1024x425.png" alt="" width="800" height="332" class="alignnone size-large wp-image-1895" title="" align="" /></a>
</p>
<p>
	Choice Parameter也是用来给我们Job定制Build前的可选参数, 不过这里的参数可以直接写死
</p>
<p>
	deploy_environment为我们的参数名, 定义我们的部署环境名,&nbsp;prod, qa为我们具体的可选项, 定义我们产品的两个环境.
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-8.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-8-1024x427.png" alt="" width="800" height="334" class="alignnone size-large wp-image-1892" title="" align="" /></a><span style="color:#337FE5;">2). 源代码管理</span>
</p>
<p>
	我们可以利用Jenkins内置的Source Code Management工具去抓取远程Git或者SVN仓库的代码到本地, 这里我们抓取存放在我们Gitlab上的Playbook到Jenkins的workspace目录, 用来进行后续部署工作, 这个仓库如需认证,&nbsp;我们可以在Credentials add这个仓库的用户账号密码, 其余均保持默认即可(默认Jenkins default不支持Git, 需要到其后台安装Git插件)
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-9.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-9-1024x557.png" alt="" width="800" height="435" class="alignnone size-large wp-image-1894" title="" align="" /></a>
</p>
<p>
	<span style="color:#337FE5;">3). Execute shell进行最终的CLI部署.</span>
</p>
<p>
	这个Build模块下的Execute shell方法是Jenkins比较常用并非常核心的功能, 用来执行我们部署过程中核心的命令.
</p>
<p>
	开头和结尾的set +x,&nbsp;set&nbsp;-x用来关闭和打开该部分的扩展参数及命令
</p>
<p>
	<span>开启virtualenv和加载ansible环境变量</span>
</p>
<pre class="prettyprint"># source /home/deploy/.virtualenv/bin/activate
# . /home/deploy/.virtualenv/ansible/hacking/env-setup -q</pre>
<p>
	<span>进入该Job的workspace目录下保存该playbook的仓库子目录下, 检查ansible版本, 并执行最终的部署命令.</span>
</p>
<pre class="prettyprint lang-bsh">cd $WORKSPACE/leon-playbook-phpcms1.1
ansible --version
ansible-playbook -i inventory/$deploy_environment ./deploy.yml -e project=phpcms -e branch=$branch_selector -e env=$deploy_environment</pre>
<p><span style="color:#E53333;">注: -i&nbsp;用来自定义ansible host文件路径, ./deploy.yml为ansible-playbook入口文件, -e 后可跟给当前session添加的环境变量.</span> </p>
<p>
	<span style="color:#E53333;">这里</span><span style="color:#E53333;">$deploy_environment</span> <span style="color:#E53333;">$branch_selector 为该Job定义好的可选参数, 详见3-1)</span>
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-10.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-10-1024x266.png" alt="" width="800" height="208" class="alignnone size-large wp-image-1891" title="" align="" /></a>
</p>
<p>
	
</p>
<p>
	配置完毕后, save保存.
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">4. 执行Job.</span>
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-12.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-12-1024x336.png" alt="" width="800" height="263" class="alignnone size-large wp-image-1897" title="" align="" /></a>
</p>
<p>
	选择master分支和prod环境
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-13.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-13.png" alt="QQ20160311-13" width="859" height="302" class="alignnone size-full wp-image-1898" /></a>
</p>
<p>
	
</p>
<p>
	查看该Job最终的console output, 也就是显示我们实际在CLI下的输出结果.
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-14.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/03/QQ20160311-14.png" alt="QQ20160311-14" width="347" height="684" class="alignnone size-full wp-image-1899" /></a>
</p>
<p>
	
</p>
<h1 class="build-caption page-headline" style="color:#333333;font-family:Helvetica, Arial, sans-serif;">
	Console Output<br />
</h1>
<pre class="prettyprint lang-bsh">Started by user Leon Li
Building in workspace /home/deploy/jenkins/workspace/Phpcms-Dev
 &gt; git rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 &gt; git config remote.origin.url <a href="mailto:git@git.showerlee.com">git@git.showerlee.com</a>:showerlee/Ansible-showerlee.git # timeout=10
Fetching upstream changes from <a href="mailto:git@git.showerlee.com">git@git.showerlee.com</a>:showerlee/Ansible-showerlee.git
 &gt; git --version # timeout=10
 &gt; git fetch --tags --progress <a href="mailto:git@git.showerlee.com">git@git.showerlee.com</a>:showerlee/Ansible-showerlee.git +refs/heads/*:refs/remotes/origin/*
 &gt; git rev-parse refs/remotes/origin/master^{commit} # timeout=10
 &gt; git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10
Checking out Revision 6bf787dcad68219d8eee09cecb83cbca36edbef1 (refs/remotes/origin/master)
 &gt; git config core.sparsecheckout # timeout=10
 &gt; git checkout -f 6bf787dcad68219d8eee09cecb83cbca36edbef1
 &gt; git rev-list 6bf787dcad68219d8eee09cecb83cbca36edbef1 # timeout=10
[Phpcms-Dev] $ /bin/sh -xe /tmp/hudson7452069223867148990.sh
+ set +x
ansible 2.1.0 (devel 6ddea3e915) last updated 2016/02/16 16:13:32 (GMT +800)
  lib/ansible/modules/core: (detached HEAD 8d126bd877) last updated 2016/02/16 16:19:09 (GMT +800)
  lib/ansible/modules/extras: (detached HEAD f6c5ed987f) last updated 2016/02/16 16:19:40 (GMT +800)
  config file = /home/deploy/jenkins/workspace/Phpcms-Dev/leon-playbook-phpcms1.1/ansible.cfg
  configured module search path = /home/deploy/active-ansible-modules/

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [127.0.0.1]

TASK [deploy : Backup current source code] *************************************
changed: [127.0.0.1]

cmd: mv /data/deploy_dir/phpcms /data/deploy_dir/phpcms_master_1457681152

start: 2016-03-11 15:25:54.774716

end: 2016-03-11 15:25:54.927415

delta: 0:00:00.152699

TASK [deploy : Get new source code] ********************************************
changed: [127.0.0.1]

TASK [deploy : Check if caches/configs/database.php exists] ********************
ok: [127.0.0.1]

TASK [deploy : Check if test_dir exists] ***************************************
ok: [127.0.0.1]

TASK [deploy : debug] **********************************************************
ok: [127.0.0.1] =&gt; {
    "msg": "/data/deploy_dir/phpcms_master_1457681152/caches/configs/database.php exists"
}

msg: /data/deploy_dir/phpcms_master_1457681152/caches/configs/database.php exists

TASK [deploy : debug] **********************************************************
ok: [127.0.0.1] =&gt; {
    "msg": "/data/deploy_dir/phpcms_master_1457681152/test_dir exists"
}

msg: /data/deploy_dir/phpcms_master_1457681152/test_dir exists

TASK [deploy : Copy remote necessary original config to new release when Product env] ***
changed: [127.0.0.1] =&gt; (item={u'name': u'db_config', u'dir': u'caches/configs/database.php'})
changed: [127.0.0.1] =&gt; (item={u'name': u'version_config', u'dir': u'caches/configs/version.php'})

msg: All items completed

results: [
  {
    "src": "/data/deploy_dir/phpcms_master_1457681152/caches/configs/database.php", 
    "changed": true, 
    "group": "deploy", 
    "uid": 606, 
    "dest": "/data/deploy_dir/phpcms/caches/configs/database.php", 
    "checksum": "91869c2faa244f8c5de8a586636c6b4f3c0a2817", 
    "md5sum": "fd88a78a4629bca012a79d22fdcecadd", 
    "owner": "deploy", 
    "_ansible_no_log": false, 
    "item": {
      "name": "db_config", 
      "dir": "caches/configs/database.php"
    }, 
    "state": "file", 
    "gid": 608, 
    "mode": "0644", 
    "invocation": {
      "module_args": {
        "src": "/data/deploy_dir/phpcms_master_1457681152/caches/configs/database.php", 
        "directory_mode": null, 
        "force": true, 
        "remote_src": true, 
        "dest": "/data/deploy_dir/phpcms/caches/configs/database.php", 
        "selevel": null, 
        "seuser": null, 
        "setype": null, 
        "group": null, 
        "content": null, 
        "serole": null, 
        "original_basename": null, 
        "delimiter": null, 
        "mode": "0644", 
        "regexp": null, 
        "owner": null, 
        "follow": false, 
        "validate": null, 
        "backup": false
      }
    }, 
    "size": 302
  }, 
  {
    "src": "/data/deploy_dir/phpcms_master_1457681152/caches/configs/version.php", 
    "changed": true, 
    "group": "deploy", 
    "uid": 606, 
    "dest": "/data/deploy_dir/phpcms/caches/configs/version.php", 
    "checksum": "d0eaedb46a36303eb3f3e2a77cc2a623062eff3c", 
    "md5sum": "7917d8199b7c6d5bc87ff3035a72670e", 
    "owner": "deploy", 
    "_ansible_no_log": false, 
    "item": {
      "name": "version_config", 
      "dir": "caches/configs/version.php"
    }, 
    "state": "file", 
    "gid": 608, 
    "mode": "0644", 
    "invocation": {
      "module_args": {
        "src": "/data/deploy_dir/phpcms_master_1457681152/caches/configs/version.php", 
        "directory_mode": null, 
        "force": true, 
        "remote_src": true, 
        "dest": "/data/deploy_dir/phpcms/caches/configs/version.php", 
        "selevel": null, 
        "seuser": null, 
        "setype": null, 
        "group": null, 
        "content": null, 
        "serole": null, 
        "original_basename": null, 
        "delimiter": null, 
        "mode": "0644", 
        "regexp": null, 
        "owner": null, 
        "follow": false, 
        "validate": null, 
        "backup": false
      }
    }, 
    "size": 127
  }
]

TASK [deploy : Copy dir test_dir to new release when Product env] **************
changed: [127.0.0.1]

cmd: cp -a /data/deploy_dir/phpcms_master_1457681152/test_dir /data/deploy_dir/phpcms/

start: 2016-03-11 15:26:16.966237

end: 2016-03-11 15:26:17.069705

delta: 0:00:00.103468

TASK [deploy : Get php version] ************************************************
changed: [127.0.0.1 -&gt; localhost]

cmd: python /home/deploy/jenkins/workspace/Phpcms-Dev/leon-playbook-phpcms1.1/roles/deploy/files/get_php_version.py <a href="http://www.showerlee.com" rel="nofollow">http://www.showerlee.com</a>

start: 2016-03-11 15:26:17.468311

end: 2016-03-11 15:26:51.560313

delta: 0:00:34.092002

stdout: PHP/5.4.13

TASK [deploy : debug] **********************************************************
ok: [127.0.0.1] =&gt; {
    "msg": {
        "changed": true, 
        "cmd": "python /home/deploy/jenkins/workspace/Phpcms-Dev/leon-playbook-phpcms1.1/roles/deploy/files/get_php_version.py <a href="http://www.showerlee.com" rel="nofollow">http://www.showerlee.com</a>", 
        "delta": "0:00:34.092002", 
        "end": "2016-03-11 15:26:51.560313", 
        "rc": 0, 
        "start": "2016-03-11 15:26:17.468311", 
        "stderr": "", 
        "stdout": "PHP/5.4.13", 
        "stdout_lines": [
            "PHP/5.4.13"
        ], 
        "warnings": []
    }
}

msg: {
  "changed": true, 
  "end": "2016-03-11 15:26:51.560313", 
  "stdout": "PHP/5.4.13", 
  "cmd": "python /home/deploy/jenkins/workspace/Phpcms-Dev/leon-playbook-phpcms1.1/roles/deploy/files/get_php_version.py <a href="http://www.showerlee.com" rel="nofollow">http://www.showerlee.com</a>", 
  "start": "2016-03-11 15:26:17.468311", 
  "delta": "0:00:34.092002", 
  "stderr": "", 
  "rc": 0, 
  "stdout_lines": [
    "PHP/5.4.13"
  ], 
  "warnings": []
}

TASK [deploy : debug] **********************************************************
ok: [127.0.0.1] =&gt; {
    "msg": "PHP/5.4.13"
}

msg: PHP/5.4.13

PLAY RECAP *********************************************************************
127.0.0.1                  : ok=12   changed=5    unreachable=0    failed=0   

Finished: SUCCESS</pre>
<p>
	
</p>
<p>
	这样我们就利用Jenkins+Ansible+Gitlab, 成功部署phpcms到远程Client.</p>
<div>声明: 本文采用 <a rel="external" href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" title="署名-非商业性使用-相同方式共享 3.0 Unported">CC BY-NC-SA 3.0</a> 协议进行授权</div><div>转载请注明来源：<a rel="external" title="DevOps技术分享" href="http://www.showerlee.com/archives/1880">DevOps技术分享</a></div><div>本文链接地址：<a rel="external" title="Jenkins+Ansible+Gitlab自动化部署三剑客" href="http://www.showerlee.com/archives/1880">http://www.showerlee.com/archives/1880</a></div>]]></content:encoded>
			<wfw:commentRss>http://www.showerlee.com/archives/1880/feed</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>CentOS6.7下Ansible部署</title>
		<link>http://www.showerlee.com/archives/1649</link>
		<comments>http://www.showerlee.com/archives/1649#comments</comments>
		<pubDate>Thu, 22 Oct 2015 05:54:48 +0000</pubDate>
		<dc:creator>showerlee</dc:creator>
				<category><![CDATA[Ansible]]></category>

		<guid isPermaLink="false">http://www.showerlee.com/?p=1649</guid>
		<description><![CDATA[Ansible是一种集成IT系统的配置管理, 应用部署, 执行特定任务的开源平台. 它基于Python语言实现 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2015/10/QQ20151022-0@2x.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2015/10/QQ20151022-0@2x.png" alt="QQ20151022-0@2x" width="376" height="322" class="alignnone size-full wp-image-1676" /></a>
</p>
<p>
	<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>是一种集成IT系统的配置管理, 应用部署, 执行特定任务的开源平台. 它基于Python语言实现, 部署只需在主控端部署<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>环境, 被控端无需安装代理工具, 只需打开SSH, 让主控端通过SSH秘钥认证对其进行所有的管理监控操作. 相对于SaltStack, 它除了利用SSH安全传输, 无需在客户端进行任何配置, 而且它有一个很庞大的用户群体以及丰富的API, 相对适合部署到数量比较大且对系统软件安装要求比较严格的集群中.
</p>
<p>
	更多配置参考:&nbsp;<a href="https://github.com/ansible/" target="_blank">https://github.com/ansible</a>&nbsp;
</p>
<p>
	官方文档:&nbsp;<a href="http://docs.ansible.com/ansible/" target="_blank">http://docs.ansible.com/ansible</a>
</p>
<p>
	
</p>
<p>
	本文将帮助大家如何快速部署一个<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>平台.
</p>
<p>
	
</p>
<p>
	安装环境:
</p>
<p>
	System: Centos 6.7 x64
</p>
<p>
	Master: master.example.com<span style="line-height:1.5;">&nbsp;</span>
</p>
<p>
	Minion: client01.example.com
</p>
<p>
	<span>Minion: client02.example.com</span>
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:16px;"><strong>一. 环境部署及安装</strong></span>
</p>
<p>
	<span style="color:#337FE5;">1. 关闭iptables和SELINUX</span>
</p>
<p>
	# service iptables stop
</p>
<p>
	# setenforce 0
</p>
<p>
	# vi /etc/sysconfig/selinux
</p>
<pre class="prettyprint lang-bsh">...
SELINUX=disabled
...</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">2. Master端安装EPEL第三方yum源</span>
</p>
<p>
	# rpm -Uvh <a href="http://ftp.linux.ncsu.edu/pub/epel/6/i386/epel-release-6-8.noarch.rpm" rel="nofollow">http://ftp.linux.ncsu.edu/pub/epel/6/i386/epel-release-6-8.noarch.rpm</a>
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">3.安装<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a></span>
</p>
<p>
	# yum install ansible -y
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">4.添加环境变量以便vi能正常显示中文注释.</span>
</p>
<p>
	# vi /etc/profile
</p>
<p>
	添加:
</p>
<p>
	
</p>
<pre class="prettyprint lang-bsh">export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8</pre>
<p>#&nbsp;source /etc/profile</p>
<p>
	
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:16px;"><strong>二. 初始配置</strong></span>
</p>
<p>
	<span style="color:#337FE5;">1. 修改主机及组配置</span>
</p>
<p>
	<span style="color:#000000;"># cd /etc/ansible</span>
</p>
<p>
	<span style="color:#000000;"># cp hosts hosts.bak</span>
</p>
<p>
	# cat /dev/null &gt; hosts
</p>
<p>
	# vi /etc/ansible/hosts
</p>
<pre class="prettyprint lang-bsh">[webservers]
client01.example.com
client02.example.com
[nginx01]
client01.example.com
[nginx02]
client02.example.com</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">2.配置SSH秘钥认证</span>
</p>
<p>
	# yum install ssh* -y
</p>
<p>
	#&nbsp;ssh-keygen -t rsa
</p>
<pre class="prettyprint lang-bsh">Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
24:13:34:e9:71:2b:20:0b:48:a6:86:9a:1d:1b:1d:26 <a href="mailto:root@master.example.com">root@master.example.com</a>
The key's randomart image is:
+--[ RSA 2048]----+
|ooE o.+.         |
|* .+..oo.        |
|oooo.ooo..       |
|oo.+  o+.        |
|o o    .S        |
|                 |
|                 |
|                 |
|                 |
+-----------------+</pre>
<p>同步公钥文件id_rsa.pub到目标主机</p>
<p>
	#&nbsp;ssh-copy-id -i /root/.ssh/id_rsa.pub <a href="mailto:root@client01.example.com">root@client01.example.com</a>
</p>
<p>
	#&nbsp;ssh-copy-id -i /root/.ssh/id_rsa.pub <a href="mailto:root@client02.example.com">root@client02.example.com</a>
</p>
<p>
	校验SSH免密码配置是否成功.
</p>
<p>
	# ssh <a href="mailto:root@client02.example.com">root@client02.example.com</a>
</p>
<p>
	如直接进入则配置完成.
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">3.定义主机与组</span>
</p>
<p>
	所有定义的主机与组规则都在/etc/<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>/hosts下.
</p>
<p>
	常见的写法:
</p>
<p>
	192.168.1.21:2135 定义一个IP为192.168.1.21, SSH端口为2135的主机.
</p>
<p>
	jumper ansible_ssh_port=22 ansible_ssh_host=192.168.1.50 定义一个别名为jumper, SSH端口为22, IP为192.168.1.50的主机.&nbsp;
</p>
<p>
	组成员主机名称范例:
</p>
<pre class="prettyprint lang-bsh">[webservers]
www[001:006].example.com
[dbservers]
db-[a:f].example.com</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">4.定义主机变量</span>
</p>
<p>
	主机可以指定变量, 后面可以供Playbooks调用
</p>
<pre class="prettyprint lang-bsh">[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=8080 maxRequestsPerChild=909</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">5.定义组变量</span>
</p>
<pre class="prettyprint lang-bsh">[atlanta]
host1
host2

[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">6.匹配目标</span>
</p>
<p>
	重启webservers组所有SSH服务.
</p>
<p>
	# ansible webservers -m service -a "name=sshd state=restarted"
</p>
<pre class="prettyprint lang-bsh">client01.example.com | success &gt;&gt; {
    "changed": true, 
    "name": "sshd", 
    "state": "started"
}

client02.example.com | success &gt;&gt; {
    "changed": true, 
    "name": "sshd", 
    "state": "started"
}</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:14px;"><strong>三. <a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>常用模块及API</strong></span>
</p>
<p>
	<span style="color:#337FE5;">1.远程命令模块</span>
</p>
<p>
	command: 执行远程主机SHELL命令:
</p>
<p>
	# ansible webservers -m command -a "free -m"
</p>
<pre class="prettyprint lang-bsh">client01.example.com | success | rc=0 &gt;&gt;
             total       used       free     shared    buffers     cached
Mem:           996        108        887          0          7         41
-/+ buffers/cache:         58        937 
Swap:         1023          0       1023 

client02.example.com | success | rc=0 &gt;&gt;
             total       used       free     shared    buffers     cached
Mem:           996        108        888          0          7         41
-/+ buffers/cache:         58        937 
Swap:         1023          0       1023 </pre>
<p>script: 远程执行MASTER本地SHELL脚本.(类似scp+shell)</p>
<p>
	# echo "df -h" &gt; ~/test.sh
</p>
<p>
	# ansible webservers -m script -a "~/test.sh"
</p>
<pre class="prettyprint lang-bsh">client01.example.com | success &gt;&gt; {
    "changed": true, 
    "rc": 0, 
    "stderr": "OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug1: mux_client_request_session: master session id: 2\r\ndebug1: mux_client_request_session: master session id: 2\r\nShared connection to client01.example.com closed.\r\n", 
    "stdout": "Filesystem      Size  Used Avail Use% Mounted on\r\n/dev/sda3       6.6G  815M  5.5G  13% /\r\ntmpfs           499M     0  499M   0% /dev/shm\r\n/dev/sda1       190M   27M  154M  15% /boot\r\n"
}

client02.example.com | success &gt;&gt; {
    "changed": true, 
    "rc": 0, 
    "stderr": "OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug1: mux_client_request_session: master session id: 2\r\ndebug1: mux_client_request_session: master session id: 2\r\nShared connection to client02.example.com closed.\r\n", 
    "stdout": "Filesystem      Size  Used Avail Use% Mounted on\r\n/dev/sda3       6.6G  815M  5.5G  13% /\r\ntmpfs           499M     0  499M   0% /dev/shm\r\n/dev/sda1       190M   27M  154M  15% /boot\r\n"
}</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">2. copy模块</span>
</p>
<p>
	实现主控端向目标主机拷贝文件, 类似scp功能.
</p>
<p>
	该实例实现~/test.sh文件至webservers组目标主机/tmp下, 并更新文件owner和group
</p>
<p>
	# ansible webservers -m copy -a "src=~/test.sh dest=/tmp/ owner=root group=root mode=0755"
</p>
<pre class="prettyprint lang-bsh"># ansible webservers -m copy -a "src=~/test.sh dest=/tmp/ owner=root group=root mode=0755"
client01.example.com | success &gt;&gt; {
    "changed": true, 
    "checksum": "c989bd551bfa8c755f6cacacb90c5c509432110e", 
    "dest": "/tmp/test.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "69a238d8cb3c5f979252010b3299e524", 
    "mode": "0755", 
    "owner": "root", 
    "size": 6, 
    "src": "/root/.ansible/tmp/ansible-tmp-1445322165.21-234077402845688/source", 
    "state": "file", 
    "uid": 0
}

client02.example.com | success &gt;&gt; {
    "changed": true, 
    "checksum": "c989bd551bfa8c755f6cacacb90c5c509432110e", 
    "dest": "/tmp/test.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "69a238d8cb3c5f979252010b3299e524", 
    "mode": "0755", 
    "owner": "root", 
    "size": 6, 
    "src": "/root/.ansible/tmp/ansible-tmp-1445322165.2-164402895387597/source", 
    "state": "file", 
    "uid": 0
}</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">3.stat模块</span>
</p>
<p>
	获取远程文件状态信息, 包括atime, ctime, mtime, md5, uid, gid等信息.
</p>
<p>
	# ansible webservers -m stat -a "path=/etc/sysctl.conf"
</p>
<pre class="prettyprint lang-bsh">client02.example.com | success &gt;&gt; {
    "changed": false, 
    "stat": {
        "atime": 1445312213.9599864, 
        "checksum": "704d7d26321b453d973939ee41aaf9861e238a78", 
        "ctime": 1444969315.401, 
        "dev": 2051, 
        "exists": true, 
        "gid": 0, 
        "gr_name": "root", 
        "inode": 130328, 
        "isblk": false, 
        "ischr": false, 
        "isdir": false, 
        "isfifo": false, 
        "isgid": false, 
        "islnk": false, 
        "isreg": true, 
        "issock": false, 
        "isuid": false, 
        "md5": "9ce78fbee91a542ca29d3e7945486e27", 
        "mode": "0644", 
        "mtime": 1437725687.0, 
        "nlink": 1, 
        "path": "/etc/sysctl.conf", 
        "pw_name": "root", 
        "rgrp": true, 
        "roth": true, 
        "rusr": true, 
        "size": 998, 
        "uid": 0, 
        "wgrp": false, 
        "woth": false, 
        "wusr": true, 
        "xgrp": false, 
        "xoth": false, 
        "xusr": false
    }
}

client01.example.com | success &gt;&gt; {
    "changed": false, 
    "stat": {
        "atime": 1445312212.9747968, 
        "checksum": "704d7d26321b453d973939ee41aaf9861e238a78", 
        "ctime": 1444969315.401, 
        "dev": 2051, 
        "exists": true, 
        "gid": 0, 
        "gr_name": "root", 
        "inode": 130328, 
        "isblk": false, 
        "ischr": false, 
        "isdir": false, 
        "isfifo": false, 
        "isgid": false, 
        "islnk": false, 
        "isreg": true, 
        "issock": false, 
        "isuid": false, 
        "md5": "9ce78fbee91a542ca29d3e7945486e27", 
        "mode": "0644", 
        "mtime": 1437725687.0, 
        "nlink": 1, 
        "path": "/etc/sysctl.conf", 
        "pw_name": "root", 
        "rgrp": true, 
        "roth": true, 
        "rusr": true, 
        "size": 998, 
        "uid": 0, 
        "wgrp": false, 
        "woth": false, 
        "wusr": true, 
        "xgrp": false, 
        "xoth": false, 
        "xusr": false
    }
}</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">4.get_url模块</span>
</p>
<p>
	实现在远程主机下载指定URL到本地.
</p>
<p>
	# ansible webservers -m get_url -a "url=http://www.showerlee.com dest=/tmp/index.html mode=0400 force=yes"
</p>
<pre class="prettyprint lang-bsh">client02.example.com | success &gt;&gt; {
    "changed": true, 
    "checksum": "470d6ab960810153bb8149c3754b0e8a2d89209d", 
    "dest": "/tmp/index.html", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "009949f770f35a4ea82105e5e923abcb", 
    "mode": "0400", 
    "msg": "OK (unknown bytes)", 
    "owner": "root", 
    "sha256sum": "", 
    "size": 81635, 
    "src": "/tmp/tmpa44PoE", 
    "state": "file", 
    "uid": 0, 
    "url": "http://www.showerlee.com"
}

client01.example.com | success &gt;&gt; {
    "changed": true, 
    "checksum": "9b1afd16f97c07638965ba0c5cf01037af00a38a", 
    "dest": "/tmp/index.html", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "5a935e77927286dfcb7a0190e8af461b", 
    "mode": "0400", 
    "msg": "OK (unknown bytes)", 
    "owner": "root", 
    "sha256sum": "", 
    "size": 81679, 
    "src": "/tmp/tmp5WHuj0", 
    "state": "file", 
    "uid": 0, 
    "url": "http://www.showerlee.com"
}</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">5.yum模块</span>
</p>
<p>
	Linux包管理平台操作, &nbsp;常见都会有yum和apt,&nbsp;此处会调用yum管理模式
</p>
<p>
	# ansible servers -m yum -a "name=curl state=latest"
</p>
<pre class="prettyprint lang-bsh">client01.example.com | success &gt;&gt; {
    "changed": false, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "All packages providing curl are up to date"
    ]
}

client02.example.com | success &gt;&gt; {
    "changed": false, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "All packages providing curl are up to date"
    ]
}</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">6. cron模块</span>
</p>
<p>
	远程主机crontab配置
</p>
<p>
	# ansible webservers -m cron -a "name='check dir' hour='5,2' job='ls -alh &gt; /dev/null'"
</p>
<pre class="prettyprint lang-bsh">client02.example.com | success &gt;&gt; {
    "changed": true, 
    "jobs": [
        "check dir"
    ]
}

client01.example.com | success &gt;&gt; {
    "changed": true, 
    "jobs": [
        "check dir"
    ]
}</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">7.service模块</span>
</p>
<p>
	远程主机系统服务管理
</p>
<p>
	# ansible webservers -m service -a "name=crond state=stopped"
</p>
<p>
	#&nbsp;<span>ansible webservers -m service -a "name=crond state=restarted"</span>
</p>
<p>
	#&nbsp;<span>ansible webservers -m service -a "name=crond state=reloaded"</span>
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">8.user服务模块</span>
</p>
<p>
	远程主机系统用户管理
</p>
<p>
	添加用户:
</p>
<p>
	# ansible webservers -m user -a "name=johnd comment='John Doe'"
</p>
<p>
	删除用户:
</p>
<p>
	#&nbsp;<span>ansible webservers -m user -a "name=johnd state=absent remove=yes"</span>
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:16px;"><strong>四. playbook介绍</strong></span>
</p>
<p>
	playbook是一个不同于使用<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>命令行执行方式的模式, 其功能是将大量命令行配置集成到一起形成一个可定制的<span>多主机</span>配置管理部署工具.
</p>
<p>
	它通过YAML格式定义, 可以实现向多台主机的分发应用部署.
</p>
<p>
	
</p>
<p>
	以下给大家详细介绍一个针对nginx嵌套复用结构的playbook部署实例:
</p>
<p>
	<span style="color:#337FE5;">1. 构建目录结构</span>
</p>
<p>
	# cd /etc/ansible/
</p>
<p>
	# mkdir&nbsp;group_vars
</p>
<p>
	# mkdir roles
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">2.定义host</span>
</p>
<p>
	# vi /etc/ansible/hosts
</p>
<pre class="prettyprint lang-bsh">[webservers]
client01.example.com
client02.example.com
[nginx01]
client01.example.com
[nginx02]
client02.example.com</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">3.定义变量</span>
</p>
<p>
	# vi&nbsp;/etc/ansible/group_vars/nginx01
</p>
<pre class="prettyprint lang-bsh">worker_processes: 4
num_cpus: 4
max_open_file: 65506
root: /data
remote_user: root</pre>
<p>
	# vi&nbsp;/etc/ansible/group_vars/nginx02
</p>
<pre class="prettyprint lang-bsh">worker_processes: 2
num_cpus: 2
max_open_file: 35506
root: /www
remote_user: root</pre>
<p>
	<span><span style="color:#E53333;">Tips:这里在group_vars下定义的文件名必须对应hosts文件下的group标签, 通过这里定义的不同参数从而部署不同类型的主机配置.</span></span>
</p>
<p>
	<span><br />
</span>
</p>
<p>
	<span style="color:#337FE5;">4.创建roles入口文件</span>
</p>
<p>
	# vi&nbsp;<span>/etc/ansible/site.yml</span>
</p>
<pre class="prettyprint lang-bsh">- hosts: webservers
  roles:
  - base_env
- hosts: nginx01
  roles:
  - nginx01
- hosts: nginx02
  roles:
  - nginx02</pre>
<p>
	<span style="color:#E53333;">Tips: 这里的<strong>roles:</strong>下的字符串需对应roles目录下的目录名.</span>
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">5.定义全局role base_env</span>
</p>
<p>
	<span style="color:#000000;">创建目录结构</span>
</p>
<p>
	# mkdir<span>&nbsp;-p&nbsp;</span><span>/etc/ansible/roles/</span>base_env/tasks&nbsp;
</p>
<p>
	# vi&nbsp;<span>/etc/ansible/roles/</span><span>base_env/tasks/main.yml</span>
</p>
<p>
	<span> </span>
</p>
<pre class="prettyprint lang-bsh"># 将EPEL的yum源配置文件传送到客户端
- name: Create the contains common plays that will run on all nodes 
  copy: src=epel.repo dest=/etc/yum.repos.d/epel.repo
- name: Create the GPG key for EPEL
  copy: src=RPM-GPG-KEY-EPEL-6 dest=/etc/pki/rpm-gpg
  
# 关闭SELINUX
- name: test to see if selling is running
  command: getenforce
  register: sestatus
  changed_when: false

# 删除iptables默认规则并保存
- name: remove the default iptables rules
  command: iptables -F
- name: save iptables rules
  command: service iptables save</pre>
<p>
	
</p>
<p>
	将对应需要拷贝到远程的文件复制到base_env/files目录下
</p>
<p>
	# mkdir -p&nbsp;&nbsp;/etc/ansible/roles/base_env/files
</p>
<p>
	# cp&nbsp;/etc/yum.repos.d/epel.repo&nbsp;/etc/ansible/roles/base_env/files
</p>
<p>
	# cp&nbsp;/etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6&nbsp;/etc/ansible/roles/base_env/files
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">6. 定义nginx01和ngnix02 role</span>
</p>
<p>
	创建目录结构
</p>
<p>
	<span># mkdir -p&nbsp;<span>/etc/ansible/roles/nginx{01,02}</span></span>
</p>
<p>
	<span><span># mkdir -p&nbsp;/etc/ansible/roles/nginx01/tasks</span></span>
</p>
<p>
	<span><span># mkdir -p</span><span>&nbsp;/etc/ansible/roles/nginx02/tasks</span><span></span><br />
</span>
</p>
<p>
	<span># vi&nbsp;<span>/etc/ansible/roles/nginx01/tasks/main.yml</span></span>
</p>
<p>
	<span><span> </span></span>
</p>
<pre class="prettyprint lang-bsh"># 安装nginx最新版本
- name: ensure nginx is at the latest version
  yum: pkg=nginx state=latest

# 将nginx配置文件传送到远程目录
- name: write the nginx config file
  template: src=nginx.conf dest=/etc/nginx/nginx.conf
  notify: restart nginx # 重启nginx

# 创建nginx根目录
- name: Create Web Root
  file: dest={{ root }} mode=775 state=directory owner=nginx group=nginx
  notify: reload nginx
- name: ensure nginx is running
  service: name=nginx state=restarted</pre>
<p>
	
</p>
<p>
	<span></span>
</p>
<p>
	# cp /home/ansible/roles/nginx01/tasks/main.yml&nbsp;<span>/home/ansible/roles/nginx02/tasks/main.yml</span>
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">7.定义files</span>
</p>
<p>
	# mkdir -p /etc/ansible/roles/nginx01/templates
</p>
<p>
	<span># mkdir -p&nbsp;</span><span>/etc/ansible/roles/nginx02/<span>templates</span></span>
</p>
<p>
	# vi&nbsp;<span>/etc/ansible/roles/nginx01/<span>templates</span>/</span>nginx.conf
</p>
<pre class="prettyprint lang-bsh"># For more information on configuration, see: 

user              nginx;  
worker_processes  {{ worker_processes }};  
{% if num_cpus == 2 %}  
worker_cpu_affinity 01 10;  
{% elif num_cpus == 4 %}  
worker_cpu_affinity 1000 0100 0010 0001;  
{% elif num_cpus &gt;= 8 %}  
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;  
{% else %}  
worker_cpu_affinity 1000 0100 0010 0001;  
{% endif %}  
worker_rlimit_nofile {{ max_open_file }};  
  
error_log  /var/log/nginx/error.log;  
#error_log  /var/log/nginx/error.log  notice;  
#error_log  /var/log/nginx/error.log  info;  
  
pid        /var/run/nginx.pid;  
  
events {  
    worker_connections  {{ max_open_file }};  
}  
  
  
http {  
    include       /etc/nginx/mime.types;  
    default_type  application/octet-stream;  
  
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '  
                      '$status $body_bytes_sent "$http_referer" '  
                      '"$http_user_agent" "$http_x_forwarded_for"';  
  
    access_log  /var/log/nginx/access.log  main;  
  
    sendfile        on;  
    #tcp_nopush     on;  
  
    #keepalive_timeout  0;  
    keepalive_timeout  65;  
  
    #gzip  on;  
      
    # Load config files from the /etc/nginx/conf.d directory  
    # The default server is in conf.d/default.conf  
    #include /etc/nginx/conf.d/*.conf;  
    server {  
        listen       80 default_server;  
        server_name  _;  
  
        #charset koi8-r;  
  
        #access_log  logs/host.access.log  main;  
  
        location / {  
            root   {{ root }};  
            index  index.html index.htm;  
        }  
  
        error_page  404              /404.html;  
        location = /404.html {  
            root   /usr/share/nginx/html;  
        }  
  
        # redirect server error pages to the static page /50x.html  
        #  
        error_page   500 502 503 504  /50x.html;  
        location = /50x.html {  
            root   /usr/share/nginx/html;  
        }  
  
    }  
  
} </pre>
<p>
	<span style="color:#E53333;">Tip:&nbsp;</span><span style="color:#E53333;">worker_processes, num_cpus, max_open_file, root等</span><span style="color:#E53333;">参数会调用group_vars目录下配置文件中相应的变量</span><span style="color:#E53333;">值</span>
</p>
<p>
	# cp&nbsp;<span>/etc/ansible/roles/nginx01/<span>templates</span>/</span><span>nginx.conf&nbsp;<span>&nbsp;</span><span>/etc/ansible/roles/nginx02/<span>templates</span>/</span><span>nginx.conf</span></span>
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">8.执行playbook</span>
</p>
<p>
	# ansible-playbook -i&nbsp;<span>/etc/ansible/hosts&nbsp;</span><span>/etc/ansible/site.yml -f 10</span>
</p>
<p>
	<span style="color:#E53333;">Tips: -f 为启动10个并行进程执行playbook, -i 定义inventory host文件, site.yml 为入口文件&nbsp;</span>
</p>
<p>
	<span> </span>
</p>
<pre class="prettyprint lang-js">PLAY [webservers] ************************************************************* 

GATHERING FACTS *************************************************************** 
ok: [client02.example.com]
ok: [client01.example.com]

TASK: [base_env | Create the contains common plays that will run on all nodes] *** 
ok: [client01.example.com]
ok: [client02.example.com]

TASK: [base_env | Create the GPG key for EPEL] ******************************** 
ok: [client02.example.com]
ok: [client01.example.com]

TASK: [base_env | test to see if selling is running] ************************** 
ok: [client01.example.com]
ok: [client02.example.com]

TASK: [base_env | remove the default iptables rules] ************************** 
changed: [client02.example.com]
changed: [client01.example.com]

TASK: [base_env | save iptables rules] **************************************** 
changed: [client01.example.com]
changed: [client02.example.com]

PLAY [nginx01] **************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [client01.example.com]

TASK: [nginx01 | ensure nginx is at the latest version] *********************** 
ok: [client01.example.com]

TASK: [nginx01 | write the nginx config file] ********************************* 
ok: [client01.example.com]

TASK: [nginx01 | Create Web Root] ********************************************* 
ok: [client01.example.com]

TASK: [nginx01 | ensure nginx is running] ************************************* 
changed: [client01.example.com]

PLAY [nginx02] **************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [client02.example.com]

TASK: [nginx02 | ensure nginx is at the latest version] *********************** 
ok: [client02.example.com]

TASK: [nginx02 | write the nginx config file] ********************************* 
ok: [client02.example.com]

TASK: [nginx02 | Create Web Root] ********************************************* 
ok: [client02.example.com]

TASK: [nginx02 | ensure nginx is running] ************************************* 
changed: [client02.example.com]

PLAY RECAP ******************************************************************** 
client01.example.com       : ok=11   changed=3    unreachable=0    failed=0   
client02.example.com       : ok=11   changed=3    unreachable=0    failed=0 </pre>
<p>
	
</p>
<p>
	最终部署目录结构如下
</p>
<p>
	# tree /etc/ansible/
</p>
<pre class="prettyprint lang-bsh">/etc/ansible/
├── ansible.cfg
├── group_vars
│   ├── nginx01
│   └── nginx02
├── hosts
├── hosts.bak
├── roles
│   ├── base_env
│   │   ├── files
│   │   │   ├── epel.repo
│   │   │   └── RPM-GPG-KEY-EPEL-6
│   │   └── tasks
│   │       └── main.yml
│   ├── nginx01
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── templates
│   │       └── nginx.conf
│   └── nginx02
│       ├── tasks
│       │   └── main.yml
│       └── templates
│           └── nginx.conf
└── site.yml

11 directories, 13 files</pre>
<p>
	
</p>
<p>
	
</p>
<p>
	到此, 部署nignx到两台远程webserver服务器全部完成.
</p>
<p>
	
</p>
<p>
	</p>
<div>声明: 本文采用 <a rel="external" href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" title="署名-非商业性使用-相同方式共享 3.0 Unported">CC BY-NC-SA 3.0</a> 协议进行授权</div><div>转载请注明来源：<a rel="external" title="DevOps技术分享" href="http://www.showerlee.com/archives/1649">DevOps技术分享</a></div><div>本文链接地址：<a rel="external" title="CentOS6.7下Ansible部署" href="http://www.showerlee.com/archives/1649">http://www.showerlee.com/archives/1649</a></div>]]></content:encoded>
			<wfw:commentRss>http://www.showerlee.com/archives/1649/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
