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,从而避免多次重启。
//运行playbookansible-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=xxx1.先准备一个以 .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服务器的文件夹,导致出错