六、Ansible Role:

1、Role简介:

role:角色,用于层次性、结构化地组织playbook,以便多次复用。role能够根据层次型结构自动装载变量文件、task以及handler等。

2、Role以特定的层级目录结构进行组织,包括:

Ø  tasks目录:角色需要执行的主任务文件放置在此目录中,默认的主任务文件名为main.yml。当调用角色时,默认会执行main.yml文件中的任务,也可以将其它需要执行的任务文件通过include的方式包含在tasks/main.yml文件中。

Ø  handlers目录:当角色需要调用handler时,默认会在此目录中的main.yml文件中查找对应的handler

Ø  defaults目录:角色会使用到的变量可以写入到此目录中的main.yml文件中,通常defaults/main.yml文件中的变量都用于设置变量的默认值,以便在没有设置对应变量时,变量有默认的值可以使用,定义在defaults/main.yml文件中的变量优先级是最低的。

Ø  vars目录:角色会使用到的变量可以写入到此目录中的main.yml文件中,vars/main.yml文件中的变量优先级非常高(除了比“-e”传入的变量优先级低),而defaults/main.yml文件中的变量优先级是最低的。如果只是想提供一个默认的配置,那么可以把对应的变量定义在defaults/main.yml文件中,如果想要确保别人在调用角色时,使用的值就是指定的值,则可以将变量定义在vars/main.yml文件中,因为定义在vars/main.yml文件中的变量优先级非常高,所以其值比较难以被覆盖。

Ø  meta目录:如果想要赋予角色一些元数据,则可以将元数据写入到meta/main.yml文件中,这些元数据用于描述角色的相关属性,比如:作者信息、角色主要作用等,也可以在meta/main.yml文件中定义此角色依赖于哪些其它角色,或者改变角色的默认调用设定。

Ø  templates目录:角色相关的模板文件(默认以.j2为后缀)可以放置在此目录中。当使用角色相关的模板时,如果没有指定路径,会默认从此目录中查找对应名称的模板文件。

Ø  files目录:角色可能会用到的一些其它文件可以放置在此目录中,比如:当定义nginx角色时,需要配置https,那么相关的证书文件就可放置在此目录中。

备注:上述目录并不是都必需的,如果角色中并没有相关的模板文件,那么角色目录中并不用包含templates目录,同理其它目录也一样,一般情况下,至少会有一个tasks目录。

3、实战案例:

(1)nginx节点反代用户请求至2tomcat节点,实现负载均衡

a、演示环境:

IP

操作系统

主机名

安装软件

软件版本

服务器角色

192.168.1.143

CentOS   7.6 x86_64

ansible

epel-releaseansible

2.7.10

Ansible主机

192.168.1.144

CentOS   7.6 x86_64

nginx

epel-releasenginx

1.12.2

被管控主机

192.168.1.145

CentOS   7.6 x86_64

tomcat1

jdktomcat

jdk-8u212-linux-x64.rpm

apache-tomcat-8.5.40.tar.gz

被管控主机

192.168.1.220

CentOS   6.10 x86_64

tomcat2

jdktomcat

jdk-8u212-linux-x64.rpm

apache-tomcat-8.5.40.tar.gz

被管控主机

备注:python版本为2.7.5

b、Ansible主机关闭firewalldSELinux

c、Ansible主机修改/etc/hosts文件:

# vim /etc/hosts

192.168.1.143 ansible

192.168.1.144 nginx

192.168.1.145 tomcat1

192.168.1.220 tomcat2

d、Ansible主机安装ansible# yum -y install epel-release  # yum -y install ansible

e、Ansible主机配置主机清单文件:

# vim /etc/ansible/hosts,末尾新增如下代码:

[ansrv]

ansible ansible_host=192.168.1.143

[ngxsrv]

nginx ansible_host=192.168.1.144

[tcsrvs]

tomcat1 ansible_host=192.168.1.145

tomcat2 ansible_host=192.168.1.220

f、Ansible主机生成密钥对,基于密钥认证:# ssh-keygen -t rsa -P ""

g、Ansible主机复制公钥至所有被管控主机:

# ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

# ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

# ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

# ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

h、Ansible主机测试连通性:# ansible all -m ping

i、Ansible主机创建roles相关目录结构:

# cd /etc/ansible/roles

# mkdir -pv {chrony,nginx,jdk,tomcat}/{files,templates,tasks,handlers,vars,meta,defaults}

j、配置chrony role

# vim chrony/tasks/main.yml

- name: stop iptables on centos 6

service: name=iptables state=stopped enabled=no

when: ansible_distribution=="CentOS" and ansible_distribution_major_version=="6"

- name: stop firewalld on centos 7

systemd: name=firewalld.service state=stopped enabled=no

when: ansible_distribution=="CentOS" and ansible_distribution_major_version=="7"

- name: install libselinux-python

yum: name=libselinux-python state=latest

- name: stop selinux

selinux: state=disabled

- name: set hostname

hostname: name={{inventory_hostname}}

- name: edit hosts file

lineinfile: path=/etc/hosts line="{{ansible_host}} {{inventory_hostname}}" state=present backup=yes

- name: install chrony

yum: name=chrony state=latest

- name: install configuration file

copy: src=chrony.conf dest=/etc/ owner=root group=root mode=0644 backup=yes

notify: restart chrony service

tags: chrony configuration file

- name: start chrony service

service: name=chronyd state=started enabled=yes

# vim chrony/files/chrony.conf

server 192.168.1.142 iburst

driftfile /var/lib/chrony/drift

makestep 10 3

rtcsync

local stratum 10

keyfile /etc/chrony.keys

logdir /var/log/chrony

stratumweight 0

noclientlog

logchange 0.5

备注:192.168.1.142为内网NTP服务器

# vim chrony/handlers/main.yml

- name: restart chrony service

service: name=chronyd state=restarted

k、配置nginx role

# vim nginx/tasks/main.yml

- name: install {{item}}

yum: name={{item}} state=latest

loop:

- epel-release

- nginx

- name: install configuration file

copy: src=nginx.conf dest=/etc/nginx/ owner=root group=root mode=0644 validate="nginx -t -c %s" backup=yes

notify: reload nginx service

tags: nginx configuration file

- name: start nginx service

service: name=nginx state=started enabled=yes

# vim nginx/files/nginx.conf

Ø  删除listen [::]:80 default_server;

Ø  修改listen 80 default_server;listen 80;

Ø  http配置段内、server配置段外新增如下代码:

upstream tcsrvs {

server 192.168.1.145:8080;

server 192.168.1.220:8080;

}

Ø  serverlocation /配置段内新增如下代码:

server {

location / {

proxy_pass http://tcsrvs;

}

}

备注:

Ø  由于nginx.conf文件中没有使用到任何变量,所以简单地使用了copy模块,而没有使用template模块

Ø  nginx.conf文件从其它CentOS 7.6主机中提取而来

# vim nginx/handlers/main.yml

- name: reload nginx service

service: name=nginx state=reloaded

l、配置jdk role

# vim jdk/tasks/main.yml

- name: copy jdk

copy: src=jdk-{{version}}-linux-x64.rpm dest=/tmp/ owner=root group=root mode=0644

- name: install jdk

yum: name=/tmp/jdk-{{version}}-linux-x64.rpm state=present

- name: set jdk environment variable

copy: src=jdk.sh dest=/etc/profile.d/ owner=root group=root mode=0644

- name: effect jdk environment variable

shell: source /etc/profile.d/jdk.sh

# vim jdk/files/jdk.sh

export JAVA_HOME=/usr/java/latest

export PATH=$JAVA_HOME/bin:$PATH

备注:软件包jdk-8u212-linux-x64.rpm需要放在jdk/files目录中,使用copy模块复制至被管控节点后再安装

# vim jdk/vars/main.yml

version: 8u212

m、配置tomcat role

# vim tomcat/tasks/main.yml

- name: unarchive tomcat

unarchive: src=apache-tomcat-{{version}}.tar.gz dest=/usr/local/

- name: create soft link

file: src=/usr/local/apache-tomcat-{{version}} path=/usr/local/tomcat state=link

- name: set tomcat environment variable

copy: src=tomcat.sh dest=/etc/profile.d/ owner=root group=root mode=0644

- name: effect tomcat environment variable

shell: source /etc/profile.d/tomcat.sh

- name: install jsp test page

template: src=test.jsp.j2 dest=/usr/local/tomcat/webapps/ROOT/test.jsp owner=root group=root mode=0640

- name: optimize JVM

blockinfile: path=/usr/local/tomcat/bin/catalina.sh block="JAVA_OPTS='-server -Xms2048m -Xmx2048m'" marker="#{mark} JAVA_OPTS" insertafter="^#!/bin/sh" state=present backup=yes

- name: start tomcat

shell: chdir=/usr/local/tomcat/bin/ nohup ./catalina.sh start &

# vim tomcat/files/tomcat.sh

export CATALINA_HOME=/usr/local/tomcat

export PATH=$CATALINA_HOME/bin:$PATH

备注:软件包apache-tomcat-8.5.40.tar.gz需要放在tomcat/files目录中

# vim tomcat/vars/main.yml

version: 8.5.40

# vim tomcat/templates/test.jsp.j2

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

JSP Test Page

{{ansible_host}}

n、编写playbook并执行:

# mkdir -pv /playbooks

# vim /playbooks/lb.yml

- hosts: all

remote_user: root

roles:

- chrony


- hosts: ngxsrv

remote_user: root

roles:

- nginx


- hosts: tcsrvs

remote_user: root

roles:

- jdk

- tomcat

# ansible-playbook --syntax-check /playbooks/lb.yml

# ansible-playbook -C /playbooks/lb.yml

# ansible-playbook /playbooks/lb.yml

o、浏览器测试:

192.168.1.144

192.168.1.144/test.jsp,刷新页面,实现负载均衡:


(2)搭建LNMP环境

a、演示环境:

IP

操作系统

主机名

安装软件

软件版本

服务器角色

192.168.1.144

CentOS   7.6 x86_64

ansible

epel-releaseansible

2.7.10

Ansible主机

192.168.1.145

CentOS   7.6 x86_64

nginx

epel-releasenginxphpphp-fpm

1.12.2

被管控主机

192.168.1.146

CentOS   7.6 x86_64

mariadb

mariadbexpect

10.3.14

被管控主机

备注:ansible使用的python版本为2.7.5

b、ansible主机关闭firewalldSELinux

c、ansible主机修改/etc/hosts文件:

# vim /etc/hosts

192.168.1.144 ansible

192.168.1.145 nginx

192.168.1.146 mariadb

d、ansible主机安装ansible# yum -y install epel-release  # yum -y install ansible

e、ansible主机配置主机清单文件:

# vim /etc/ansible/hosts,末尾新增如下代码:

[ansrv]

ansible ansible_host=192.168.1.144

[ngxsrv]

nginx ansible_host=192.168.1.145

[madbsrv]

mariadb ansible_host=192.168.1.146

f、ansible主机生成密钥对,基于密钥认证:# ssh-keygen -t rsa -P ""

g、ansible主机复制公钥至所有被管控主机:

# ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

# ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

# ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

h、ansible主机测试连通性:# ansible all -m ping

i、ansible主机创建roles相关目录结构:

# cd /etc/ansible/roles

# mkdir -pv {chrony,nginx,php,mariadb}/{files,templates,tasks,handlers,vars,meta,defaults}

j、配置chrony role

# vim chrony/tasks/main.yml

- name: stop firewalld

systemd: name=firewalld.service state=stopped enabled=no

- name: install libselinux-python

yum: name=libselinux-python state=latest

- name: stop selinux

selinux: state=disabled

- name: set hostname

hostname: name={{inventory_hostname}}

- name: edit hosts file

lineinfile: path=/etc/hosts line="{{ansible_host}} {{inventory_hostname}}" state=present backup=yes

- name: install chrony

yum: name=chrony state=latest

- name: install configuration file

copy: src=chrony.conf dest=/etc/ owner=root group=root mode=0644 backup=yes

notify: restart chrony service

tags: chrony configuration file

- name: start chrony service

service: name=chronyd state=started enabled=yes

# vim chrony/files/chrony.conf

server 192.168.1.142 iburst

driftfile /var/lib/chrony/drift

makestep 10 3

rtcsync

local stratum 10

keyfile /etc/chrony.keys

logdir /var/log/chrony

stratumweight 0

noclientlog

logchange 0.5

备注:192.168.1.142为内网NTP服务器

# vim chrony/handlers/main.yml

- name: restart chrony service

service: name=chronyd state=restarted

k、配置nginx role

# vim nginx/tasks/main.yml

- name: install {{item}}

yum: name={{item}} state=latest

loop:

- epel-release

- nginx

- name: install configuration file

copy: src=nginx.conf dest=/etc/nginx/ owner=root group=root mode=0644 backup=yes

notify: reload nginx service

tags: nginx configuration file

- name: install php test page

copy: src=index.php dest=/usr/share/nginx/html/ owner=root group=root mode=0644

- name: start nginx service

service: name=nginx state=started enabled=yes

# vim nginx/files/nginx.conf

Ø  删除listen [::]:80 default_server;

Ø  修改listen 80 default_server;listen 80;

Ø  server配置段内新增如下代码:

location / {

index index.html index.htm;

}


location ~ \.php$ {

fastcgi_pass   192.168.1.145:9000;

fastcgi_index  index.php;

fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

include       fastcgi.conf;

}

备注:

Ø  由于nginx.conf文件中没有使用到任何变量,所以简单地使用了copy模块,而没有使用template模块

Ø  nginx.conf文件从其它CentOS 7.6主机中提取而来

# vim nginx/files/index.php

$conn = mysqli_connect("192.168.1.146","testuser","654321");

if ($conn)

echo "Success";

else

echo "Failure";

mysqli_close();

phpinfo();

?>

# vim nginx/handlers/main.yml

- name: reload nginx service

service: name=nginx state=reloaded

l、配置php role

# vim php/tasks/main.yml

- name: install {{item}}

yum: name={{item}} state=latest

loop:

- php

- php-fpm

- php-mysql

- name: install www configuration file

template: src=www.conf.j2 dest=/etc/php-fpm.d/www.conf owner=root group=root mode=0644 backup=yes

notify: restart php-fpm service

tags: www configuration file

- name: start php-fpm service

service: name=php-fpm state=started enabled=yes

# vim php/templates/www.conf.j2,修改如下代码:

listen = 127.0.0.1:9000  -->  listen = {{ansible_host}}:9000

listen.allowed_clients = 127.0.0.1  -->  listen.allowed_clients = {{ansible_host}}

user = apache  -->  user = nginx

group = apache  -->  group = nginx

# vim php/handlers/main.yml

- name: restart php-fpm service

service: name=php-fpm state=restarted

备注:

Ø  www.conf文件从其它CentOS 7.6主机中提取而来

Ø  9000php-fpm监听的端口

Ø  listen.allowed_clients:允许连接的FastCGI客户端IP地址

m、配置mariadb role

# vim mariadb/tasks/main.yml

- name: create MariaDB-server repository

yum_repository: file=MariaDB name=mariadb description="MariaDB Repo" baseurl=http://mirrors.ustc.edu.cn/mariadb/yum/10.3/centos7-amd64/ gpgkey=http://mirrors.ustc.edu.cn/mariadb/yum/RPM-GPG-KEY-MariaDB gpgcheck=yes enabled=yes owner=root group=root mode=0644 state=present

- name: install {{item}}

yum: name={{item}} state=latest

loop:

- MariaDB-server

- MySQL-python

- expect

- name: install server configuration file

copy: src=server.cnf dest=/etc/my.cnf.d/ owner=root group=root mode=0644 backup=yes

notify: restart mariadb service

tags: server configuration file

- name: start mariadb service

service: name=mariadb state=started enabled=yes

- name: expect mysql_secure_installation

script: mysql_secure_installation.exp

- name: add testuser

mysql_user: login_host=localhost login_user=root login_password=123456 name=testuser host="%" password=654321 priv=*.*:all state=present

tags: add mariadb user

备注:被管控节点中新创建的yum源内容

# cat /etc/yum.repos.d/MariaDB.repo

[mariadb]

name=MariaDB Repo

baseurl=http://mirrors.ustc.edu.cn/mariadb/yum/10.3/centos7-amd64/

gpgkey=http://mirrors.ustc.edu.cn/mariadb/yum/RPM-GPG-KEY-MariaDB

gpgcheck=1

enabled=1

# vim mariadb/files/server.cnf,在[mysqld]配置段下新增如下代码:

[mysqld]

port=3306

socket=/var/lib/mysql/mysql.sock

datadir=/var/lib/mysql

log-error=/var/log/mariadb.log

lower_case_table_names=1

character-set-server=utf8mb4

collation-server=utf8mb4_unicode_ci

symbolic-links=0

# vim mariadb/files/mysql_secure_installation.exp

#!/usr/bin/expect -f

set timeout 5

set password 123456

spawn mysql_secure_installation

expect "Enter current password for root:"

send "\r"

expect "Set root password?"

send "y\r"

expect "New password:"

send "$password\r"

expect "Re-enter new password:"

send "$password\r"

expect "Remove anonymous users?"

send "y\r"

expect "Disallow root login remotely?"

send "n\r"

expect "Remove test database and access to it?"

send "y\r"

expect "Reload privilege tables now?"

send "y\r"

expect eof

# chmod +x mariadb/files/mysql_secure_installation.exp

备注:使用expect实现自动输入,脚本执行方式为# ./mysql_secure_installation.exp

# vim mariadb/handlers/main.yml

- name: restart mariadb service

service: name=mariadb state=restarted

n、编写playbook并执行:

# mkdir -pv /playbooks

# vim /playbooks/lnmp.yml

- hosts: all

remote_user: root

roles:

- chrony


- hosts: ngxsrv

remote_user: root

roles:

- nginx

- php


- hosts: madbsrv

remote_user: root

roles:

- mariadb

# ansible-playbook --syntax-check /playbooks/lnmp.yml

# ansible-playbook -C /playbooks/lnmp.yml

# ansible-playbook /playbooks/lnmp.yml

o、浏览器测试:

192.168.1.145

192.168.1.145/index.php

停止192.168.1.146中的mariadb,刷新页面: