Ansible自动化运维工具 —— Playbook 剧本

playbooks 本身由以下各部分组成
(1)Tasks:任务,即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行
(2)Variables:变量
(3)Templates:模板
(4)Handlers:处理器,当changed状态条件满足时,(notify)触发执行的操作
(5)Roles:角色

playbook 剧本 总结

vim  XXX.yaml

- name:                      #指定play名称
  hosts:                     #指定主机组
  remote_user:               #执行用户 
  gather_facts: true|false   #是否收集远程主机facts信息
  vars:                      #定义变量
  tasks:                     #定义task任务列表
  - name:                 #定义task任务名称
    模块:                 #定义任务使用的模块和参数
    with_items:           #定义循环列表
    when:                 #定义判断条件(== != >= > <= <),true则执行任务,否则不执行任务
    ignore_errors: true   #忽略任务失败
    notify:               #定义task任务changed状态时触发的任务名
    tags:                 #指定标签,ansible-playbook --tags 仅执行拥有指定 tags 标签的任务(always标签总会执行)
  handlers:                  #定义notify触发的任务列表

task任务 模块语法格式

模块名: 参数选项1=值  参数选项2={{变量名}}  ...

模块名:
  参数选项1: 值
  参数选项2: "{{变量名}}"
  ...

with_items 和 变量 的语法格式

with_items: ["值1", "值2", "值3"]

with_items:
- 值1
- 值2
- 值3

值为对象(键值对字段)时:

with_items:
- {key1: value1, key2: value2, ...}
- {key1: value3, key2: value4, ...}


with_items:
- key1: value1
  key2: value2
- key1: value3
  key2: value4

template模板模块
1)先要准备一个 xxx.j2 模板文件,在文件中使用 {{变量名}} 引用主机变量 或者 vars 自定义的变量 及 facts 字段的值
2)在 playbook 中的 tasks 中定义 template 模板配置  template: src=xxx.j2  dest=xxx

roles 角色 的作用?【重中之重】

把playbook剧本里的各个play看作为角色,将各个角色的tasks任务、vars变量、templates模板、files文件等内容放置到角色的目录中统一管理,需要的时候可在playbook中直接使用roles调用,所以roles可以实现playbook代码的复用。

实验

架构

192.168.80.101 ansible

192.168.80.102 被控服务器

192.168.80.103 被控服务器

/etc/ansible/hosts配置如下

cat /etc/ansible/hosts

示例1 安装httpd服务

mkdir -p /etc/ansible/playbook/
cp /etc/httpd/conf/httpd.conf /etc/ansible/playbook/httpd.conf
#本机的httpd配置复制到ansible目录。可以自定义位置,在下面yaml更改对应位置即可。
vim /etc/ansible/playbook/test1.yaml

---     #yaml文件以---开头,以表明这是一个yaml文件,可省略。
        #若文件中存在多个--- 则代表有多个yaml配置文件存在于同一个文件中
- name: the first play for install apache     #定义一个play的名称,可省略
  gather_facts: false    #设置不进行facts信息收集,这可以加快执行速度,可省略
  hosts: webservers    #指定要执行任务的被管理主机组,如多个主机组用冒号分隔
  remote_user: root    #指定被管理主机上执行任务的用户
  tasks:     #定义任务列表,任务列表中的各任务按次序逐个在hosts中指定的主机上执行
   - name: test connection    #自定义任务名称
     ping:     #使用 module: [options] 格式来定义一个任务
   - name: disable selinux
     command: '/sbin/setenforce 0'    #command模块和shell模块无需使用key=value格式
     ignore_errors: True     #如执行命令的返回值不为0,就会报错,tasks停止,可使用ignore_errors忽略失败的任务。
			     #这里需要忽略是因为如果selinux已经关闭再次关闭会返回1
   - name: disable selinux forever
     replace: path=/etc/selinux/config  regexp="enforcing"  replace="disabled"
   - name: disable firewalld
     service: name=firewalld state=stopped enabled=no    #使用 module: options 格式来定义任务,option使用key=value格式
#======================================================================================================================
# 若想要挂载光盘使用本地yum源安装(需要在控制服务器存在/etc/yum.repos.d/repo.bak/local.repo配置文件)可以省略
   - name: mount cdrom
     mount: src=/dev/sr0 path=/mnt fstype=iso9660 state=mounted
   - name: copy local yum configuration file
     copy: src=/etc/yum.repos.d/repo.bak/local.repo  dest=/etc/yum.repos.d/local.repo
#======================================================================================================================
   - name: install httpd
     yum: name=httpd state=latest
   - name: prepare httpd configuration file
     copy: src=/etc/ansible/playbook/httpd.conf dest=/etc/httpd/conf/httpd.conf #这里需要一个事先准备好的/opt/httpd.conf文件
     notify: "restart httpd" ##如以上操作后为changed的状态时,会通过notify指定的名称触发对应名称的handlers操作
   - name: start apache httpd
     service: name=httpd state=started enabled=yes
  handlers:     #handlers中定义由notify触发的任务
   - name: restart httpd    #notify和handlers中任务的名称必须一致。注意reload不能让httpd重新加载配置文件中端口等配置,只能restart
     service: name=httpd state=restarted

##Ansible在执行完某个任务之后并不会立即去执行对应的handler,而是在当前play中所有普通任务都执行完后再去执行handler
##这样的好处是可以多次触发notify,但最后只执行一次对应的handler,从而避免多次重启。


//运行playbook

ansible-playbook test1.yaml

//补充参数:
-k(–ask-pass):用来交互输入ssh密码
-K(-ask-become-pass):用来交互输入sudo密码
-u:指定用户

ansible-playbook test1.yaml --syntax-check    #检查yaml文件的语法是否正确
ansible-playbook test1.yaml --list-task       #检查tasks任务
ansible-playbook test1.yaml --list-hosts      #检查生效的主机
ansible-playbook test1.yaml --start-at-task='install httpd'     #指定从某个task开始运行

 

定义、引用变量

vim /etc/ansible/playbook/test2.yaml

- name: second play
  hosts: dbservers
  remote_user: root
  #remote_user: zhangsan
  #become: yes #这三行代表 远程控制时 使用的普通用户zhangsan提升权限使用root用户
  #become_user: root #需要先修改sudo配置/etc/sudoers使zhangsan用户可以使用sudo提权
  vars:                 #定义变量
   - groupname: mysql   #格式为 key: value
   - username: nginx
   - filename: /opt/123.txt
  gather_facts: true #可以不写 默认开启
  tasks:
   - name: create group
     group: name={{groupname}} system=yes gid=2800    #使用 {{key}} 引用变量的值 system为默认项可以省略不写不影>响
   - name: create user
     user: name={{username}} uid={{uid}} group={{groupname}} #uid并未写在var中,由外部命令执行时传参
   - name: copy file
     #copy: content="{{ansible_default_ipv4}}" dest={{filename}}     #在setup模块中可以获取facts变量信息 这里获>取ipv4块所有信息
     copy: content="{{ansible_default_ipv4.address}}" dest={{filename}}     #在setup模块中可以获取facts变量信息 这里获取ipv4块中address一项信息
   - name: modify username and groupname of file
     file: path={{filename}} owner={{username}}  group={{groupname}}
ansible-playbook test2.yaml -e "username=nginx2" -e "uid=1234"
#在命令行里定义变量 命令行内指定的参数优先级更高可以覆盖playbook var内写的变量

可看到命令行的传参username覆盖了playbook中定义的变量,并且uid也传参进去,其余参数都从playbook中已经定义的var变量中取 



指定远程主机sudo切换用户

在上面的脚本做修改

额外注意在 /etc/ansible/hosts 组变量中是否已经指定了 用户等参数!优先级:命令行传参>host组定义>playbook中定义变量

若host组中已经规定了用户,playbook中的用户设置,become提权等可能被覆盖不会生效!

---
- hosts: dbservers
  remote_user: zhangsan            
  become: yes                    #2.6版本以后的参数,之前是sudo,意思为切换用户运行
  become_user: root              #指定sudo用户为root

运行前需要先在被控制的远程主机上创建zhangsan用户,并修改sudo配置使zhangsan用户可以使用sudo提权,才能在playbook中使用become 使用root用户

adduser zhangsan
passwd zhangsan

vim /etc/sudoers
    zhangsan ALL=ALL

执行playbook,原先命令上附加上 -k -K参数

ansible-playbook test2.yaml  -e "username=nginx3" -e "uid=1357" -k -K
 -k -K
-k(–ask-pass):用来交互输入ssh密码
-K(-ask-become-pass):用来交互输入sudo密码 都输入zhangsan密码即可
-u:指定用户

 

when条件判断

在Ansible中,提供的唯一一个通用的条件判断是when指令,当when指令的值为true时,则该任务执行,否则不执行该任务。

when一个比较常见的应用场景是实现跳过某个主机不执行任务或者只有满足条件的主机执行任务

vim /etc/ansible/playbook/test3.yaml

---
- name: third play
  hosts: all
  remote_user: root
  tasks:
   - name: touch file
     file: path=/opt/1.txt state=touch #创建文件
     #command: /sbin/shutdown/ -r now  #重启指令
     when: inventory_hostname == "192.168.80.102"
       #写法1 inventory_hostname为主机清单 /etc/ansible/hosts的主机名
     #when: ansible_default_ipv4.address != "192.168.80.103" 
       #写法2 ansible_default_ipv4.address为gather_facts获取的主机信息    != 含义为除了103主机
     #when指令中的变量名不需要手动加上 {{}} 
ansible-playbook test3.yaml

迭代(循环) with_items

Ansible提供了很多种循环结构,一般都命名为with_items,作用等同于 loop 循环。

with_items普通取值  写法演示

vim /etc/ansible/playbook/test4.yaml

#😊with_items普通取值
---
- name: fouth play
  hosts: dbservers
  remote_user: root
##############################################################################
  vars:
    myfile:
    - /opt/a
    - /opt/b
    - /opt/c
    - /opt/d
  tasks:
  - name: touch directory #✨方法1 预先编写var变量,随后赋值给with_items
    with_items: "{{myfile}}"
    file: path={{item}} state=directory #🧯模组 横向写法
##############################################################################
  - name: touch file 1    #✨方法2 直接在with_items中定义
    file:                               #🧯模组 纵向写法
      path: "{{item}}"
      state: touch
    with_items:                                        #🔥with_items纵向写法
    - /root/a
    - /root/b
    - /root/c
    - /root/d

  - name: touch file 2
    file:                               #🧯模组 纵向写法
      path: "{{item}}"
      state: touch
    with_items: [ /opt/aa, /opt/bb, /opt/cc, /opt/dd ] #🔥with_items横向写法

with_items——值为对象(键值对字段) 写法演示

vim /etc/ansible/playbook/test5.yaml

#😊with_items——值为对象(键值对字段)
---
- name: fifth play
  hosts: dbservers
  remote_user: root
  tasks:
  - name: touch file
    with_items: #✨with_items(键值对字段对象)横向写法
    - {filename: /opt/afile, username: xue, groupname: xue}
    - {filename: /opt/bfile, username: zhangsan, groupname: zhangsan}
        #当值为对象(键值对字段)引用值需要像item.filename指定对象中的某个字段
    file: path={{item.filename}}  owner={{item.username}} group={{item.groupname}} state=touch #模块 横向写法

  - name: create dir
    with_items: #✨with_items(键值对字段对象)纵向写法
    - filename: /opt/cfile
      username: xue
      groupname: xue
    - filename: /opt/dfile
      username: zhangsan
      groupname: zhangsan
    file: #模块 纵向写法
      path: "{{item.filename}}"
      owner: "{{item.username}}"
      group: "{{item.groupname}}"
      state: directory

  


执行playbook test4

ansible-playbook test4.yaml


 执行playbook test5

由于playbook中指定了用户与组,需要在被控制的远程主机创建
adduser xue
adduser zhangsan

 查看用户 与 组 信息(playbook中指定的{filename: /opt/afile, username: xue, groupname: xue}一定要与系统中的用户—组对应关系相匹配!不然报错)

 

在ansible服务器运行
ansible-playbook test5.yaml

Templates 模块

Jinja是基于Python的模板引擎。Template类是Jinja的一个重要组件,可以看作是一个编译过的模板文件,用来产生目标文本,传递Python的变量给模板去替换模板中的标记。

1)先要准备一个 xxx.j2 模板文件,在文件中使用 {{变量名}} 引用主机变量 或者 vars 自定义的变量 及 facts 字段的值
2)在 playbook 中的 tasks 中定义 template 模板配置  template: src=xxx.j2  dest=xxx

1.先准备一个以 .j2 为后缀的 template 模板文件,设置引用的变量

cp /etc/httpd/conf/httpd.conf /etc/ansible/playbook/httpd.conf.j2
vim /etc/ansible/playbook/httpd.conf.j2

Listen {{http_port}}                 #42行
ServerName {{server_name}}           #95行
DocumentRoot "{{root_dir}}"          #119行

2.修改主机清单文件,定义变量,用于传参给模版

vim /etc/ansible/hosts

[webservers]
192.168.80.102 http_port=192.168.80.102:80 server_name=www.ws1.com:80 root_dir=/var/www/html/webserver1
192.168.80.103 http_port=192.168.80.103:80 server_name=www.ws2.com:80 root_dir=/var/www/html/webserver2

3.编写 playbook,在其中引用第一步定义的template模版。运行时host文件变量会传给playbook yaml配置文件再传参给模版。

根据不同host ip为不同的服务器生成指定的配置文件。

vim /etc/ansible/playbook/test6.yaml

- name: sixth play
  hosts: webservers
  remote_user: root
  vars:
  - pkgname: httpd

  tasks:
  - name: install apache
    yum: name=httpd state=latest

    #创建webserver1 webserver2文件夹(此处直接在每个主机上都创建这两个文件夹,可以指定when不同ip做更细分优化)
  - name: create root dir
    file: state=directory path={{item}}
    with_items:
    - /var/www/html/webserver1
    - /var/www/html/webserver2

    #根据不同ip生成不同页面
  - name: create index.html in www.ws1.com
    copy: content="<h1>this is web1</h1>" dest=/var/www/html/webserver1/index.html
    when: ansible_default_ipv4.address == "192.168.80.102"
  - name: create index.html in www.ws2.com
    copy: content="<h1>this is web2</h1>" dest=/var/www/html/webserver2/index.html
    when: inventory_hostname == "192.168.80.103"

    #引用template模板,生成配置后触发restart 
  - name: prepare configuration file
    template: src=/etc/ansible/playbook/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
    notify: "restart apache" 
    #本处可以为reload也可以为restart。虽然触发项最后才执行,会在start后reload。
    #但是实测可能是由于start需要时间,reload第一次运行会报错,第二次运行httpd完全启动后才正常。
    #所以直接使用restart,即使未启动restart也会直接执行start不报错。
         #后续补充:restart 似乎也需要执行两次,应该也与触发项或是启动时间有关

  - name: start apache
    service: name={{pkgname}} state=started enabled=yes

  handlers:
  - name: reload apache
    service: name={{pkgname}} state=reloaded
ansible-playbook test6.yaml

 

tags 模块

可以在一个playbook中为某个或某些任务定义“标签”,在执行此playbook时通过ansible-playbook命令使用--tags选项能实现仅运行指定的tasks。
playbook还提供了一个特殊的tags为always。作用就是当使用always作为tags的task时,无论执行哪一个tags时,定义有always的tags都会执行。

vim /etc/ansible/playbook/test7.yaml

- name: seventh play
  hosts: dbservers
  remote_user: root
  tasks:
  - name: create together-do.txt
    file: path=/opt/together-do.txt state=touch
    tags:
    - xiaoming_do_it
    - xiaohong_do_it

  - name: create always-do.txt
    file: path=/opt/always—do.txt state=touch
    tags:
    - always

  - name: create xiaohong-do.txt
    copy: content="0721" dest=/opt/xiaohong—do.txt
    tags:
    - xiaohong_do_it
ansible-playbook test7.yaml --tags="xiaoming_do_it"
#执行 tag:xiaoming与always

 

ansible-playbook test7.yaml --tags="xiaohong_do_it"
#执行 tag:xiaohong与always

Roles 模块

roles用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令引入即可。
简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷的include它们的一种机制。roles一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。主要使用场景代码复用度较高的情况下。

roles 角色 的作用?

把playbook剧本里的各个play看作为角色,将各个角色的tasks任务、vars变量、templates模板、files文件等内容放置到角色的目录中统一管理,需要的时候可在playbook中直接使用roles调用,所以roles可以实现playbook代码的复用。

roles 的目录结构

cd /etc/ansible/
tree roles/

roles/
├── httpd/                 #相当于 playbook 中的 每一个 play 主题,目录名即为角色名
│   ├── files/                  #存放copy 模块或 script 模块调用的文件
│   ├── templates/              #存放template 模块调用的jinjia2 模板文件
│   ├── tasks/main.yml          #定义此角色的任务列表
│   ├── handlers/main.yml       #定义此角色通过notity触发条件时执行的任务列表
│   ├── vars/main.yml           #定义此角色用到的自定义变量
│   ├── defaults/main.yml       #定义此角色用到的设定默认变量(一般不用)
│   └── meta/main.yml           #定义此角色的元数据信息
└── mysql/
    ├── files/
    ├── templates/
    ├── tasks/
    ├── handlers/
    ├── vars/
    ├── defaults/
    └── meta/

●files
用来存放由 copy 模块或 script 模块调用的文件。

●templates
用来存放 jinjia2 模板,template 模块会自动在此目录中寻找 jinjia2 模板文件。

●tasks
此目录应当包含一个 main.yml 文件,用于定义此角色的任务列表,此文件可以使用 include 包含其它的位于此目录的 task 文件。

●handlers
此目录应当包含一个 main.yml 文件,用于定义此角色中触发条件时执行的动作。

●vars
此目录应当包含一个 main.yml 文件,用于定义此角色用到的变量。

●defaults
此目录应当包含一个 main.yml 文件,用于为当前角色设定默认变量。 这些变量具有所有可用变量中最低的优先级,并且可以很容易地被任何其他变量覆盖。所以生产中我们一般不在这里定义变量

●meta
此目录应当包含一个 main.yml 文件,用于定义此角色的元数据信息及其依赖关系。

在一个 playbook 中使用 roles的步骤

(1)创建以 roles 命名的目录

mkdir /etc/ansible/roles/ -p
#yum装完默认就有

(2)创建全局变量目录(可选)

mkdir /etc/ansible/group_vars/ -p
touch /etc/ansible/group_vars/all
#文件名自己定义,引用的时候注意

(3)在 roles 目录中分别创建以各角色名称命名的目录,如 httpd、mysql

mkdir /etc/ansible/roles/httpd
mkdir /etc/ansible/roles/mysql

(4)在每个角色命名的目录中分别创建files、handlers、tasks、templates、meta、defaults和vars目录,用不到的目录可以创建为空目录,也可以不创建

mkdir /etc/ansible/roles/httpd/{files,templates,tasks,handlers,vars,defaults,meta}
mkdir /etc/ansible/roles/mysql/{files,templates,tasks,handlers,vars,defaults,meta}

(5)在每个角色的 handlers、tasks、meta、defaults、vars 目录下创建 main.yml 文件,千万不能自定义文件名

touch /etc/ansible/roles/httpd/{defaults,vars,tasks,meta,handlers}/main.yml
touch /etc/ansible/roles/mysql/{defaults,vars,tasks,meta,handlers}/main.yml

(6)修改 site.yml 文件,针对不同主机去调用不同的角色

vim /etc/ansible/site.yml
---
- hosts: webservers
  remote_user: root
  roles:
     - httpd
- hosts: dbservers
  remote_user: root
  roles:
     - mysql

(7)运行 ansible-playbook

cd /etc/ansible
ansible-playbook site.yml

示例:安装分布式LNMP架构web服务器
创建工作目录
mkdir /etc/ansible/roles/nginx/{files,templates,tasks,handlers,vars,defaults,meta} -p
mkdir /etc/ansible/roles/mysql/{files,templates,tasks,handlers,vars,defaults,meta} -p
mkdir /etc/ansible/roles/php/{files,templates,tasks,handlers,vars,defaults,meta} -p

touch /etc/ansible/roles/nginx/{defaults,vars,tasks,meta,handlers}/main.yaml
touch /etc/ansible/roles/mysql/{defaults,vars,tasks,meta,handlers}/main.yaml
touch /etc/ansible/roles/php/{defaults,vars,tasks,meta,handlers}/main.yaml
编辑主机列表
vim /etc/ansible/hosts

[webservers]
192.168.80.101

[mysqlservers]
192.168.80.102

[phpservers]
192.168.80.103
创建playbook,包含roles
vim /etc/ansible/playbook/lnmp.yaml

- name: nginx play
  hosts: webservers
  remote_user: root
  roles:
    - nginx

- name: php play
  hosts: phpservers
  remote_user: root
  roles:
    - php

- name: mysql play
  hosts: mysqlservers
  remote_user: root
  roles:
    - mysql

 

role:nginx

vars (变量)

vim /etc/ansible/roles/nginx/vars/main.yaml

http_port: 192.168.80.101:80
http_hostname: www.xue.com
root_dir: /usr/share/nginx/html
php_remote: 192.168.80.103:9000
pkg: nginx
service: nginx

tasks (任务)

vim /etc/ansible/roles/nginx/tasks/init.yaml

- name: disable firewalld
  service: name=firewalld  state=stopped  enabled=no

- name: disable selinux
  shell: "/usr/sbin/setenforce 0"
  ignore_errors: true
vim /etc/ansible/roles/nginx/tasks/main.yaml

- include: "init.yaml"

- name: copy nginx yum repo file
  copy: src=nginx.repo  dest=/etc/yum.repos.d/

- name: install nginx
  yum: name={{pkg}}  state=latest

- name: copy index.php
  unarchive: src=/etc/ansible/roles/nginx/files/wordpress-4.9.4-zh_CN.tar.gz dest={{root_dir}} copy=yes

- name: copy nginx template configuration file
  template: src=default.conf.j2  dest=/etc/nginx/conf.d/default.conf
  notify: reload nginx

- name: start nginx
  service: name={{service}} state=started enabled=yes

handles (task中触发器)

vim /etc/ansible/roles/nginx/handlers/main.yaml

- name: reload nginx
  service: name={{service}}  state=reloaded

files (文件)

vim /etc/ansible/roles/nginx/files/nginx.repo

nginx.repo 用于yum下载nginx。
也可以不使用这个方法用不着准备这个文件,直接yum install epel 更新epel源

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
准备 WordPress论坛安装包 
(不一定要藏这么深的文件夹,只要脚本中对应上路径即可。为了显示file文件夹的作用,就放在这里)

/etc/ansible/roles/nginx/files/wordpress-4.9.4-zh_CN.tar.gz

templates(模版 用于给nginx服务器生成配置)

vim /etc/ansible/roles/nginx/templates/default.conf.j2

server {
    listen       {{http_port}};
    server_name  {{http_hostname}};

    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   {{root_dir}};
        index  index.php index.html index.htm;
    }

    #error_page  404              /404.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;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        root           {{root_dir}};
        fastcgi_pass   {{php_remote}};
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  {{root_dir}}$fastcgi_script_name;
        include        fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}
role:mysql

 vars (变量)

vim /etc/ansible/roles/mysql/vars/main.yaml

http_port: 192.168.80.101:80
http_hostname: www.xue.com
root_dir: /usr/share/nginx/html
php_remote: 192.168.80.103:9000
pkg: nginx
service: nginx

tasks (任务)

vim /etc/ansible/roles/mysql/tasks/init.yaml

- name: disable firewalld
  service: name=firewalld  state=stopped  enabled=no

- name: disable selinux
  shell: "/usr/sbin/setenforce 0"
  ignore_errors: true
vim /etc/ansible/roles/mysql/tasks/main.yaml

- name: yum uninstall mariadb*
  yum: name=mariadb* state=absent

- name: wget mysql
  shell: wget -i -c http://repo.mysql.com/mysql57-community-release-el7-11.noarch.rpm -P /etc/yum.repos.d

- name: rpm mysql57-community-release
  shell: rpm -ivh /etc/yum.repos.d/mysql57-community-release-el7-11.noarch.rpm
  ignore_errors: True

- name: turn off yum gpgcheck
  replace: path=/etc/yum.repos.d/mysql-community.repo regexp='gpgcheck=1' replace='gpgcheck=0'

- name: yum install mysql
  yum: name=mysql-server

- name: start and enable mysql
  service: enabled=true name=mysqld.service state=started

- name: get passwd from log
  shell: grep "password" /var/log/mysqld.log | awk 'NR==1{print $NF}'
  register: mysql_password   #将获取的密码导入到mysql_password的变量中
- name: echo passwd
  debug:    
   msg: "{{ mysql_password }}"           #输出变量mysql_password的值
#grep "password" /var/log/mysqld.log     #在日志文件中找出root用户的初始密码
#2021-07-31T07:55:00.366359Z 1 [Note] A temporary password is generated for root@localhost: ga7%<d<0*jD&
#grep "password" /var/log/mysqld.log | awk '{print $NF}'

#临时密码修改
- name: grant location
  shell:  mysql --connect-expired-password -uroot -p"{{ mysql_password['stdout'] }}" -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'Admin@123';"
  ignore_errors: True
#授予root用户所有权限 
- name: grant option
  shell: mysql --connect-expired-password -uroot -pAdmin@123 -e "grant all privileges on *.* to 'root'@'%' identified by 'Admin@123456' with grant option;"
  ignore_errors: True
#创建wordpress数据库
- name: create database
  shell: mysql --connect-expired-password -uroot -pAdmin@123 -e "create database wordpress;"
  ignore_errors: True
#赋予mywordpress用户访问wordpress的权限(本地权限与远程权限)
- name: grant
  shell: mysql --connect-expired-password -uroot -pAdmin@123 -e "grant all on wordpress.* to 'admin'@'%' identified by 'mywordpress@123456';"
  ignore_errors: True
- name: grant
  shell: mysql --connect-expired-password -uroot -pAdmin@123 -e "grant all on wordpress.* to 'admin'@'localhost' identified by 'mywordpress@123456';"
  ignore_errors: True
#刷新权限
- name: flush privileges
  shell: mysql --connect-expired-password -uroot -pAdmin@123 -e 'flush privileges;'
  ignore_errors: True

- name: yum uninstall mariadb*
  yum: name=mysql57-community-release-el7-11.noarch.rpm state=absent
  #为了防止每次yum操作都会自动更新,卸载这个软件

role:php

vars (变量)

vim /etc/ansible/roles/php/vars/main.yaml

timezone: Asia/Shanghai
user_name: php
http_port: 192.168.80.103:9000
nginx_addr: 192.168.80.101
root_dir: /usr/share/nginx/html
service: php-fpm

tasks (任务)

vim /etc/ansible/roles/php/tasks/init.yaml

- name: disable firewalld
  service: name=firewalld  state=stopped  enabled=no

- name: disable selinux
  shell: "/usr/sbin/setenforce 0"
  ignore_errors: true
vim /etc/ansible/roles/php/tasks/main.yaml

- include: "init.yaml"

- name: install yum repo
  shell: "rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm && rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm"
  ignore_errors: True

- name: install php
  with_items:
  - php72w
  - php72w-cli
  - php72w-common
  - php72w-devel
  - php72w-embedded
  - php72w-gd
  - php72w-mbstring
  - php72w-pdo
  - php72w-xml
  - php72w-fpm
  - php72w-mysqlnd
  - php72w-opcache
  yum: name={{item}}

- name: create php user
  user: name={{user_name}}

- name: crate web root dir
  file: name={{root_dir}} state=directory

- name: copy index.php
  unarchive: src=/etc/ansible/roles/nginx/files/wordpress-4.9.4-zh_CN.tar.gz dest={{root_dir}} copy=yes

- name: modify php configuration file
  replace: path=/etc/php.ini  regexp=";date.timezone ="  replace="date.timezone = Asia/Shanghai"
  notify: reload php

- name: modify username and groupname in www.conf
  replace: path=/etc/php-fpm.d/www.conf  regexp="apache"  replace="{{user_name}}"
  notify: reload php

- name: modify listen addr in www.conf
  replace: path=/etc/php-fpm.d/www.conf  regexp="127.0.0.1:9000"  replace="{{http_port}}"
  notify: reload php

- name: modify allowed client in www.conf
  replace: path=/etc/php-fpm.d/www.conf  regexp="127.0.0.1"  replace="{{nginx_addr}}"
  notify: reload php

- name: start php
  service: name={{service}} state=started enabled=yes

handles (task中触发器)

vim /etc/ansible/roles/php/handlers/main.yaml

- name: reload php
  service: name={{service}} state=reloaded

配置密钥对验证 免交互登录

ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa

yum install -y sshpass
sshpass -p '密码' ssh-copy-id -o StrictHostKeyChecking=no root@192.168.80.102
sshpass -p '密码' ssh-copy-id -o StrictHostKeyChecking=no root@192.168.80.102
sshpass -p '密码' ssh-copy-id -o StrictHostKeyChecking=no root@192.168.80.103

执行 

ansible-playbook /etc/ansible/playbook/lnmp.yaml

 访问http://192.168.80.101/wordpress/index.php

故障处理

出现这种情况,由于是分布式部署lnmp,与单机不同,分布式部署必须在php服务器和nginx服务器上都存在相同的html目录以及其中的内容。

本次只在NGINX的html存放了WordPress论坛文件,而没有创建php服务器的文件夹,导致出错


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值