Ansible剧本与角色

Ansible

文中具体主机组与ip在上一篇中已解析

[webgrp1]
ansible-web1
[webgrp2]
ansible-web2

核心元素:
variables #变量元素,可传递给tasks/templates使用。
tasks #任务元素,由模块定义的操作的列表,即调用模块完成任务。
templates #模板元素,使用了模板语法的文本文件。
handlers #处理器元素,通常指在某事件满足时触发的操作。
roles #角色元素。

ansible剧本(playbook)

简单的剧本

playbook格式:playbook由YMAL语言编写,YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。

一个剧本里面可以有多个play,每个play只能有一个tasks,每个tasks可以有多个name

playbool的基础组件

  1. name:定义playbook或者task的名称(描述信息),每一个play都可以完成一个任务。
  2. hosts:hosts用于指定要执行指定任务的主机。
  3. user:remote_user则用于指定远程主机上的执行任务的用户。
  4. tasks:任务列表play的主体部分是task list,task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。
  5. vars:定义变量(如果不使用内部变量需要提前定义)。
  6. vars_files:调用定义变量文件。
  7. notify:任务执行结果如果是发生更改了的则触发定义在handler的任务执行。
  8. handlers:用于当前关注的资源发生变化时采取一定指定的操作。

先创建一个YMAL格式的文件,结尾以 .yml 或 .ymal 都可以

[root@ansible-server] cd /etc/ansible/
[root@ansible-server] vim test.yml

在文件中按格式写入想要执行的操作

---
 - hosts: webgrp1
   user: root
   tasks:
   - name: playbook_test
     file: state=touch path=/tmp/playbook.txt

#参数解释
    hosts: 参数指定了对哪些主机进行操作
    user: 参数指定了使用什么用户登录远程主机操作
    tasks: 指定了一个任务
    name: 参数同样是对任务的描述,在执行过程中会打印出来

写好后检测语法

[root@ansible-server] ansible-playbook --syntax-check test.yml
playbook: test.yml   #这个反馈就是没有问题
#在当前目录下敲的是相对路径

[root@ansible-server] ansible-playbook test.yml   #执行该剧本
'PLAY [webgrp1] *****************************************************************
......
ansible-web1               : ok=2    changed=1    unreachable=0    failed=0   '

#我们到web1机器上查看一下/tmp/下是否有playbook.txt文件
[root@ansible-web1] ll /tmp/playbook.txt 
-rw-r--r--. 1 root root 0 Mar 25 17:30 /tmp/playbook.txt

触发器

上面是一个简单的剧本,下面我们来了解一下触发器

#参数详解
handlers:由特定条件触发的tasks
handlers:处理器
notify:触发器

[root@ansible-server] cd /etc/ansible/
[root@ansible-server] vim handlers.yml

触发器可以实现多级操作,剧本中开头的—也可以不写

- hosts: webgrp2
  user: root
  tasks:
  - name: test copy
    copy: src=/root/b.txt dest=/mnt
    notify: test handlers
  handlers:
  - name: test handlers
    shell: echo "abcd" >> /mnt/b.txt

#注意notify里的名字一定要和handlers里的name一样
#只有 copy 模块真正执行后,才会去调用下面的 handlers 相关的操作,追加内容。所以这种比较适合配置文件发生更改后,需要重启服务的操作。

保存并退出测试一下剧本

[root@ansible-server] ansible-playbook --syntax-check handlers.yml
playbook: handlers.yml

[root@ansible-server] ansible-playbook handlers.yml
ok: [ansible-web2]
TASK [test copy] ********************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AnsibleFileNotFound: Could not find or access '/root/b.txt'
fatal: [ansible-web2]: FAILED! => {"changed": false, "msg": "Could not find or access '/root/b.txt'"}
	to retry, use: --limit @/etc/ansible/handlers.retry
PLAY RECAP **************************************************************************
ansible-web2               : ok=1    changed=0    unreachable=0    failed=1   

#这次反馈不是绿色的了,星号中间的是报错信息,我们来看一下

在这里插入图片描述
执行剧本之前一定要确定有我们要发的文件,没有的话就创建一个

[root@ansible-server] touch /root/b.txt
[root@ansible-server] ansible-playbook handlers.yml
'PLAY [webgrp2] **********************************************************************
......
ansible-web2               : ok=3    changed=2    unreachable=0    failed=0   '

#执行成功,我们到web2上查看
[root@ansible-web2] ll /mnt/b.txt 
-rw-r--r--. 1 root root 5 Mar 25 17:49 /mnt/b.txt
[root@ansible-web2] cat /mnt/b.txt 
abcd
#我们可以看到不仅文件拷贝了过去,还触发了我们的第二个指令,将abcd重定向到b.txt里

循环迭代

对迭代项的引用,固定变量名为”item”,使用with_item属性给定要迭代的元素,需要重复执行的任务。

#我们在web2上确定一下有没有安装httpd php php-mysql php-mbstring php-gd软件
[root@ansible-web2] rpm -q httpd php php-mysql php-mbstring php-gd
package httpd is not installed
package php is not installed
package php-mysql is not installed
package php-mbstring is not installed
package php-gd is not installed

#确定都没有后回到server端,有就卸载
[root@ansible-server] cd /etc/ansible/
[root@ansible-server] vim list.yml

接下来我们就用with_item属性
item相当于for循环里面的i
with_items取值,但不支持通配符

- hosts: webgrp2
  remote_user: root
  tasks:
  - name: install packages
    yum: name={{ item }} state=latest
    with_items:  
     - httpd
     - php
     - php-mysql
     - php-mbstring
     - php-gd 

检测

[root@ansible-server] ansible-playbook --syntax-check list.yml
playbook: list.yml
[root@ansible-server] ansible-playbook list.yml   #这次时间会长一点
'PLAY [webgrp2] **********************************************************************
......
ansible-web2               : ok=2    changed=1    unreachable=0    failed=0   '

#我们到web2主机上
[root@ansible-web2] rpm -q httpd php php-mysql php-mbstring php-gd
httpd-2.4.6-90.el7.centos.x86_64
php-5.4.16-46.1.el7_7.x86_64
php-mysql-5.4.16-46.1.el7_7.x86_64
php-mbstring-5.4.16-46.1.el7_7.x86_64
php-gd-5.4.16-46.1.el7_7.x86_64
#可以看到都下载好了

自定义vars_files变量

变量调用语法: {{ var_name }}

我们要先创建变量目录

[root@ansible-server] mkdir /etc/ansible/vars
[root@ansible-server] cd /etc/ansible/vars/
[root@ansible-server] vim file.yml

在这个变量文件中写入

src_path: /root/test/b.txt
dest_path: /opt/test/

在server端创建/root/test/目录和/root/test/b.txt文件

[root@ansible-server] cd /etc/ansible/
[root@ansible-server] vim vars.yml

在文件中写入

- hosts: ansible-web1
  user: root
  vars_files:
   - /etc/ansible/vars/file.yml
  tasks:
   - name: create directory
     file: path={{ dest_path }} mode=755 state=directory
   - name: copy file
     copy: src={{ src_path }} dest={{ dest_path }}

#ansible-web1就是webgrp1主机组内的主机,不要忘记哦

检测

[root@ansible-server] ansible-playbook --syntax-check vars.yml
playbook: vars.yml
[root@ansible-server] ansible-playbook vars.yml
'PLAY [ansible-web1] *****************************************************************
......
ansible-web1               : ok=3    changed=1    unreachable=0    failed=0   '

#我们换到web1上查看
[root@ansible-web1] ll -d /opt/test/
drwxr-xr-x. 2 root root 19 Mar 25 18:30 /opt/test/
[root@ansible-web1] ls /opt/test/
b.txt

#我们可以看到不仅创建好了目录,文件也拷贝了过去,所以引用变量也是可以的

剧本多个play

在web1上创建一个名为mygrp的系统组,gid为2003,并且创建一个bai用户为系统用户,用户组为mygrp
在web2上下载apache并启动apache

#web1主机
[root@ansible-web1] id bai
id: bai: no such user
[root@ansible-web1] cat /etc/group |grep mygrp

#web2主机
[root@ansible-web2] rpm -q httpd
httpd-2.4.6-90.el7.centos.x86_64
[root@ansible-web2] yum -y remove httpd

#server主机
[root@ansible-server] cd /etc/ansible/
[root@ansible-server] vim play.yml

创建多个play

- hosts: webgrp1
  user: root
  tasks:
  - name: create a group
    group: name=mygrp gid=2003 system=true
  - name: create a user
    user: name=bai group=mygrp system=true

- hosts: webgrp2
  user: root
  tasks:
  - name: install apache
    yum: name=httpd state=latest
  - name: start httpd service
    service: name=httpd state=started

#group模块参数
#name参数:必须参数,用于指定组名称。
#state参数:用于指定组的状态,两个值可选,present,absent,默认为 present,设置为absent 表示删除组。
#gid参数:用于指定组的gid,不指定为随机。
#system参数:true为系统组,可选。

测试

[root@ansible-server] ansible-playbook --syntax-check play.yml
playbook: play.yml
[root@ansible-server] ansible-playbook play.yml
'PLAY [webgrp1] **********************************************************************
......
ansible-web1               : ok=3    changed=2    unreachable=0    failed=0   
ansible-web2               : ok=3    changed=2    unreachable=0    failed=0   '

#web1主机
[root@ansible-web1] id bai
uid=998(bai) gid=2003(mygrp) groups=2003(mygrp)
[root@ansible-web1] cat /etc/group |grep mygrp
mygrp:x:2003:

#web2主机
[root@ansible-web2] rpm -q httpd
httpd-2.4.6-90.el7.centos.x86_64
[root@ansible-web2] systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: 'active (running)' since Thu 2020-03-26 03:20:26 CST; 13min ago

when模块

先判断when条件是否成立,如果成立则继续执行当前模块的命令

[root@ansible-server] cd /etc/ansible/
[root@ansible-server] vim when.yml
- hosts: webgrp1
  user: root
  tasks:
  - name: use when
    file: state=touch path=/tmp/when.txt
  - name: insert data
    shell: echo 123 >> /tmp/when.txt
    when: ansible_hostname == "ansible-web1"   #when可以在shell上也可以在shell下

注意:when判断中的ansible-web1指的是被控节点上真正的主机名称,不是解析的名,如果被控节点的主机名不是ansible-web1则不会执行insert data的命令

测试

[root@ansible-server] ansible-playbook --syntax-check when.yml
playbook: when.yml
[root@ansible-server] ansible-playbook when.yml
'PLAY [webgrp1] **********************************************************************
......
ansible-web1               : ok=3    changed=2    unreachable=0    failed=0   '


#web1主机
[root@ansible-web1] ll /tmp/when.txt 
-rw-r--r--. 1 root root 4 Mar 26 03:45 /tmp/when.txt
[root@ansible-web1] cat /tmp/when.txt 
123
#可以看到我们执行成功了

剧本中定义变量

使用变量并不显示搜集主机相关信息
gather_facts参数:指定了在任务部分执行前,是否先执行setup模块获取主机相关信息,默认值为true,改成false之后在执行过程中不会搜集主机相关信息。

在文件中
在这里插入图片描述

roles角色

roles是在ansible中playbooks的目录组织结构,模块化之后,成为roles的组织结构,易读,代码可重用,层次清晰

在这里插入图片描述
目录顺序

  • role_name/:角色名称=目录。
  • files/:存储一些可以用copy调用的静态文件。
  • tasks/: 存储任务的目录,此目录中至少应该有一个名为main.yml的文件,用于定义各task。其它的文件需要由main.yml进行“包含”调用。
  • handlers/:此目录中至少应该有一个名为main.yml的文件,用于定义各handler。其它的文件需要由(与notify:名字相同,方便notify通知执行下一条命令)通过main.yml进行“包含”调用。
  • vars/:此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用。
  • templates/:存储由template模块调用的模板文本。(也可以调用变量)
  • site.yml:定义哪个主机应用哪个角色。

编写内容

[root@ansible-server] cd /etc/ansible/roles/   #role为自带目录,如果不存在可以创建
[root@ansible-server] mkdir nginx/{files,handlers,tasks,templates,vars} -p   #递归创建
[root@ansible-server] touch site.yml nginx/{handlers,tasks,vars}/main.yml
[root@ansible-server] yum install -y tree   #下载tree命令,结构树
[root@ansible-server] tree /etc/ansible/roles/nginx/
/etc/ansible/roles/nginx/
├── files
├── handlers
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
└── vars
    └── main.yml

#files目录和templates目录下还没有创建文件,先不着急

在这里插入图片描述

#创建nginx的测试文件
[root@ansible-server] echo 1234 > nginx/files/index.html
#安装nginx并配置模板
[root@ansible-server] yum install -y nginx && cp /etc/nginx/nginx.conf nginx/templates/nginx.conf.j2
#一定要将nginx的主配置文件结尾改为.j2结尾

#编写任务
[root@ansible-server] vim nginx/tasks/main.yml

任务中写入

---
- name: install epel
  yum: name=epel-release state=latest
- name: install nginx
  yum: name=nginx state=latest
- name: copy nginx.conf templte
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: copy index.html
  copy: /etc/ansible/roles/nginx/files/index.html dest=/usr/share/nginx/html/index.html
  notify: start nginx

#注意这里的notify一定和nginx/handlers/main.yml的name一样

保存并退出,继续

[root@ansible-server] vim nginx/handlers/main.yml

文件中写入

---
- name: start nginx
  service: name=nginx state=started

#这里的name一定要和nginx/tasks/main.yml的notify的名字一样

保存并退出,继续

vim nginx/templates/nginx.conf.j2
#以.j2结尾可以引用变量,

修改成如下内容,自定义变量
在这里插入图片描述
把worker_processes 后改为变量名,变量还没有定义,继续

[root@ansible-server] vim nginx/vars/main.yml   #这个文件中写入变量的值

在文件中定义变量

worker_connections: 2

编写剧本

[root@ansible-server] vim site.yml

文件中写入

---
- hosts: webgrp2
  user: root
  roles:
   - nginx

保存并退出,检测

[root@ansible-server] ansible-playbook --syntax-check site.yml
playbook: site.yml
[root@ansible-server] ansible-playbook site.yml

#web2主机
[root@ansible-web2] netstat -lntp   #或者ss -lntp
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      3102/nginx: master  
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      926/sshd            
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1007/master         
tcp6       0      0 :::80                   :::*                    LISTEN      3102/nginx: master  
tcp6       0      0 :::22                   :::*                    LISTEN      926/sshd            
tcp6       0      0 ::1:25                  :::*                    LISTEN      1007/master   

[root@ansible-web2] cat /etc/nginx/nginx.conf | grep worker_processes   #查看一下我们的变量
#worker_processes auto;
worker_processes 2;

#这里看到已经为2了

文中内容适用于初学者 @小白

发布了17 篇原创文章 · 获赞 19 · 访问量 1103

猜你喜欢

转载自blog.csdn.net/little_baixb/article/details/105101927