Ansible Cookbooks-Highly-Available Infrastructure with Ansible(一)

chapter 1:Highly-Available Infrastructure with Ansible
In the following example, we’ll use Ansible to configure a complex infrastructure on servers provisioned.

Varnish acts as a load balancer and reverse proxy, fronting web requests and routing them to the application servers. We could just as easily use something like Nginx or HAProxy, or even a proprietary cloud-based solution like an Amazon’s Elastic Load Balancer or Linode’s NodeBalancer, but for simplicity’s sake and for flexibility in deployment, we’ll use Varnish.

Apache and mod_php run a PHP-based application that displays the entire stack’s current status and outputs the current server’s IP address for load balancing verification.

A Memcached server provides a caching layer that can be used to store and retrieve frequently- accessed objects in lieu of slower database storage.

Two MySQL servers, configured as a master and slave, offer redundant and performant database access; all data will be replicated from the master to the slave, and in addition, the slave can be used as a secondary server for read-only queries to take some load off the master.

.
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── roles
│   ├── db
│   ├── memcached
│   ├── varnish
│   └── www
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

Varnish

---
- hosts: lamp-varnish
  sudo: yes

  vars_files:
    - vars.yml

  roles:
    - geerlingguy.firewall
    - geerlingguy.repo-epel
    - geerlingguy.varnish

  tasks:
    - name: Copy Varnish default.vcl.
    template:
      src: "templates/default.vcl.j2"
      dest: "/etc/varnish/default.vcl"
    notify: restart varnish

• geerlingguy.firewall configures a simple iptables-based firewall using a couple variables defined in vars.yml .
• geerlingguy.repo-epel adds the EPEL repository (a prerequisite for varnish).
• geerlingguy.varnish installs and configures Varnish.

vars.yml

---
firewall_allowned_tcp_ports:
  - "20"
  - "80"
varnish_use_default_vcl: false

default.vcl.j2

vcl 4.0;

import directors;

{% for host in groups['lamp-www'] %}
backend www{{ loop.index }} {
.host = "{{ host }}";
.port = "80";
}
 {% endfor %}

 sub vcl_init {
 new vdir = directors.random();
 {% for host in groups['lamp-www'] %}
 vdir.add_backend(www{{ loop.index }}, 1);
 {% endfor %}
 }

 sub vcl_recv {
 set req.backend_hint = vdir.backend();

 # For testing ONLY; makes sure load balancing is working correctly.
 return (pass);
 }

Apache/PHP
www/main.yml

--- 
- hosts: lamp-www
  sudo: yes

  vars_files:
    - vars.yml

  roles:
    - geerlingguy.firewall
    - geerlingguy.repo-epel
    - geerlingguy.apache
    - geerlingguy.php
    - geerlingguy.php-mysql
    - geerlingguy.php-memcached

  tasks:
    - name: Remove the Apache test page.
      file:
        path: /var/www/html/index.html
        state: absent

    - name: Copy our fancy server-specific home page.
      template:
        src: template/index.php.j2
        dest: /var/www/html/index.php




• geerlingguy.apache installs and configures the latest available version of the Apache web server.
• geerlingguy.php installs and configures PHP to run through Apache.
• geerlingguy.php-mysql adds MySQL support to PHP.
• geerlingguy.php-memcached adds Memcached support to PHP.

vars.yml


---
firewall_allowed_tcp_ports:
  - "22"
  - "80"

index.php.j2

<?php
/**
* @file
* Infrastructure test page.
*
* DO NOT use this in production. It is simply a PoC.
*/

$mysql_servers = array(
 {% for host in groups['lamp-db'] %}
 '{{ host }}',
apter 8 - Ansible Cookbooks 148
 {% endfor %}
 );
 $mysql_results = array();
 foreach ($mysql_servers as $host) {
 if ($result = mysql_test_connection($host)) {
 $mysql_results[$host] = '<span style="color: green;">PASS</span>';
 $mysql_results[$host] .= ' (' . $result['status'] . ')';
 }
 else {
 $mysql_results[$host] = '<span style="color: red;">FAIL</span>';
 }
 }

 // Connect to Memcached.
 $memcached_result = '<span style="color: red;">FAIL</span>';
 if (class_exists('Memcached')) {
 $memcached = new Memcached;
 $memcached->addServer('{{ groups['lamp-memcached'][0] }}', 11211);

 // Test adding a value to memcached.
 if ($memcached->add('test', 'success', 1)) {
 $result = $memcached->get('test');
 if ($result == 'success') {
 $memcached_result = '<span style="color: green;">PASS</span>';
 $memcached->delete('test');
 }
 }
 }

 /**
 * Connect to a MySQL server and test the connection.
 *
 * @param string $host
 * IP Address or hostname of the server.
 *
 * @return array
 * Array with keys 'success' (bool) and 'status' ('slave' or 'master').
 * Empty if connection failure.
 */
 function mysql_test_connection($host) {
 $username = 'mycompany_user';
 $password = 'secret';
apter 8 - Ansible Cookbooks 149
 try {
 $db = new PDO(
 'mysql:host=' . $host . ';dbname=mycompany_database',
 $username,
 $password,
 array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));

 // Query to see if the server is configured as a master or slave.
 $statement = $db->prepare("SELECT variable_value
 FROM information_schema.global_variables
 WHERE variable_name = 'LOG_BIN';");
 $statement->execute();
 $result = $statement->fetch();

 return array(
 'success' => TRUE,
 'status' => ($result[0] == 'ON') ? 'master' : 'slave',
 );
 }
 catch (PDOException $e) {
 return array();
 }
 }
 ?>
 <!DOCTYPE html>
 <html>
 <head>
 <title>Host {{ inventory_hostname }}</title>
 <style>* { font-family: Helvetica, Arial, sans-serif }</style>
 </head>
 <body>
 <h1>Host {{ inventory_hostname }}</h1>
 <?php foreach ($mysql_results as $host => $result): ?>
 <p>MySQL Connection (<?php print $host; ?>): <?php print $result; ?></p>
 <?php endforeach; ?>
 <p>Memcached Connection: <?php print $memcached_result; ?></p>
 </body>
 </html>

Memcached
main.yml

---
- hosts: lamp-memcached
  sudo: yes

  vars_files:
    - vars.yml

  roles:
    - geerlingguy.firewall
    - geerlingguy.memcached

As with other servers, we need to ensure only the required TCP ports are open using the simple geeringguy.firewall role. Next we install Memcached using the geerlingguy.memcached rols. In our vars.yml
file

--- 
filewall_allowd_tcp_ports:
  - "22"

firewall_additional_rules:
  - "iptables -A INPUT -p tcp --dropt 11211 -s {{ groups['lamp-www'][0] }} -j ACCEPT"
  - "iptables -A INPUT -p tcp --dport 11211 -s {{ groups['lamp-www'][1] }} -j ACCEPT"
memcached_listen_ip: "{{ groups['lamp-memcached'][0] }}"

Mysql
db/main.yml

---
- hosts: lamp-db
sudo: yes

vars_files:
- vars.yml

pre_tasks:
- name: Create dynamic MySQL variables.
 set_fact:
 http://en.wikipedia.org/wiki/Principle_of_least_privilege
apter 8 - Ansible Cookbooks 152
 mysql_users:
 - {
 name: mycompany_user,
 host: "{{ groups['lamp-www'][0] }}",
 password: secret,
 priv: "*.*:SELECT"
 }
 - {
 name: mycompany_user,
 host: "{{ groups['lamp-www'][1] }}",
 password: secret,
 priv: "*.*:SELECT"
 }
 mysql_replication_master: "{{ groups['a4d.lamp.db.1'][0] }}"

 roles:
 - geerlingguy.firewall
 - geerlingguy.mysql

Getting the required roles
Ansible allows you to define all the required Ansible Galaxy roles for a given project in a requirements.yml file Instead of having to remember to run ansible-galaxy install -y [role1] [role2] [role3]

---
- src: geerlingguy.firewall
- src: geerlingguy.repo-epel
- src: geerlingguy.varnish
- src: geerlingguy.apache
- src: geerlingguy.php
- src: geerlingguy.php-mysql
- src: geerlingguy.php-memcached
- src: geerlingguy.mysql
- src: geerlingguy.memcached

To make sure all the required dependencies are installed, ansible-galaxy install -r from within the project’s root

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值