自动化运维Ansible

文章目录


一、自动化运维工具

1、不止ansible

自动化运维工具有很多

  • 1、Puppet:基于 Ruby 开发,采用 C/S 架构,扩展性强,基于 SSL,远程命令执行相对较弱。
  • 2、SaltStack:基于 Python 开发,采用 C/S 架构,相对 puppet 更轻量级,配置语法使用 YAML,使配置脚本更简单,需要配置客户端以及服务器端。每台被控制节点需要安装agent。
  • 3、Ansible:基于 Python开发,分布式,无需客户端,轻量级,配置语法使用YAML语言,更强的远程命令执行操作。

2、凭什么是ansible

Ansible简介
ansible是新出现的自动化运维工具,基于Python开发,分布式,无需客户端,轻量级,实现了批量系统配置、批量程序部署、批量运行命令等功能,ansible是基于模块工作的,本身并没有批量部署的能力,真正具有批量部署的是ansible上所运行的模块,ansible只是提供一种框架。

Ansible特性

  1. 、no agents:不需要在被管控主机上安装任何客户端,更新时只需在操作机上进行一次更新即可(不用安装客户端,分布式的)。
  2. 、no server:无服务器端,使用时直接运行命令即可。
  3. 、modules in any languages:基于模块工作,可使用任意语言开发模块。
  4. 、yaml,not code:使用yaml语言定制剧本playbook。
  5. 、ssh by default:基于SSH工作。
  6. 、strong multi-tier solution:可实现多级指挥。

connection plugins:连接插件,负责和被监控端实现通信,默认使用SSH连接。
host inventory:主机清单,是一个配置文件里面定义监控的主机。
modules:模块,核心模块、command模块、自定义模块等。
plugins:modules功能的补充,包括连接插件,邮件插件等。
playbook:编排,定义 Ansible 多任务配置文件,非必需。

二、安装部署ansible

1、安装配置ansible主机组

在这里我们准备三台机器,分别是server(控制节点),web1(被控节点),web2(被控节点)
主机清单文件配置

#三台服务器的/etc/hosts文件中配置解析
[root@ansible-server] vim /etc/hosts
192.168.202.131   ansible-server
192.168.202.132   ansible-web1
192.168.202.133   ansible-web2

#配置秘钥对,采用公钥认证方式:控制节点需要发送ssh公钥给所有被控制节点
[root@ansible-server] ssh-keygen
[root@ansible-server] ssh-copy-id -i 192.168.202.132
#也可以把ip换成解析的ansible-web1(两台机器都要发)

除了ssh公钥认证的方式外,也可以用密码认证

[root@ansible-server] yum -y install ansible
#如果没有的话就先安装epel-release源

[root@ansible-server] ansible --version   #查看版本及信息,如果报红则环境有问题安装失败

[root@ansible-server] rpm -qc ansible   #查看配置文件
/etc/ansible/ansible.cfg   #主配置文件
/etc/ansible/hosts   #主机清单文件

自动化运维Ansible
/etc/ansible/ansible.cfg 主配置文件,主要设置一些ansible初始化的信息,比如日志存放路径、模块、等配置信息。
/etc/ansible/hosts 默认主机清单文件,定义管理的主机及主机组,默认路径。

[root@ansible-server] vim /etc/ansible/hosts
#单独定义主机的
ansible-web1   #单独定义一个主机
192.168.202.133   #如果未解析也可以写ip

#定义主机组批量管理的
#每个组内可以有一个到多个主机
#定义主机组用[]
[webgrp1]   #组1
ansible-web1
[webgrp2]   #组2
ansible-web2

#主机组内也可以包含其它组
[weball:children]   #后跟children表示子组
webgrp1
webgrp2

#主机组指定变量
[weball:vars]   #后跟vars设置变量
ansible_ssh_port=22     
ansible_ssh_user=root   
ansible_ssh_private_key_file=/root/.ssh/id_rsa  
#ansible_ssh_pass=xiaobai123      
#如果没有互传秘钥可以使用密码,使用密码就将ansible_ssh_private_key_file=/root/.ssh/id_rsa注释掉

#也可以自定义主机清单文件
#自定义的可以写在任意目录下
[root@ansible-server] vim /tmp/hostlist
[all]
ansible-web1
ansible-web2
[all:vars]
ansible_ssh_port=22     
ansible_ssh_user=root   
ansible_ssh_private_key_file=/root/.ssh/id_rsa

2、ansible内置参数

ansible常见的内置参数

参数 用途
ansible_ssh_host 定义hosts ssh地址
ansible_ssh_port 定义hosts ssh端口
ansible_ssh_user 定义hosts ssh认证用户
ansible_ssh_pass 定义hosts ssh认证密码
ansible_sudo 定义hosts sudo用户
ansible_sudo_pass 定义hosts sudo密码
ansible_sudo_exe 定义hosts sudo路径
ansible_connection 定义hosts连接方式
anshible_ssh_private_key_file 定义hosts私钥
ansible_ssh_shell_type 定义hosts shell类型
ansible_python_interpreter 定义hosts任务执行python路径
ansible_*_interpreter 定义hosts其它语言解析路径

查看主机组内的主机

#列出weball组里所有的主机
#如果不加参数,指定是默认主机清单文件
[root@ansible-server] ansible weball --list-hosts
  hosts (2):
    ansible-web1
    ansible-web2

#加上-i参数后跟路径就会读取路径中配置的主机清单文件
[root@ansible-server] ansible -i /tmp/hostlist all --list-hosts
  hosts (2):
    ansible-web1
    ansible-web2

三、Ansible的简单操作

1、基本语法

ansible的基本语法
ansible 主机名或主机组或ip或别名等 -m 模块 -a ‘命令’
-m:指定模块
-a:传递给后面的命令
注:最后可以跟-o
-o:友好显示,显示一行

[root@ansible-server] ansible weball -m ping -o   #检测能否ping通
ansible-web1 | SUCCESS => {"changed": false, "ping": "pong"}
ansible-web2 | SUCCESS => {"changed": false, "ping": "pong"}

#我们在server端用ansible对ansible-web1执行的操作
[root@ansible-server] ansible ansible-web1 -m shell -a 'uptime'
ansible-web1 | SUCCESS | rc=0 >>
 18:37:01 up  9:17,  3 users,  load average: 0.00, 0.01, 0.05
#现在我们切换到ansible-web1上执行uptime命令
[root@ansible-web1] uptime
 18:39:56 up  9:20,  2 users,  load average: 0.00, 0.01, 0.05
#可以看到执行的效果是一样的,由于数据实时更新所以数据会不同

指定多台机器时用逗号分割,或者将之定义到一个主机组内

重定向输入到本地文件中

[root@ansible-server] ansible ansible-web1 -m shell -a 'df -Th' > /opt/a.txt   #敲回车后不会有任何输出

#执行后我们换到ansible-web1上查看一下
[root@ansible-web1] cat /opt/a.txt
cat: /opt/a.txt: No such file or directory
#ansible-web1上并没有a.txt

#我们换回到server端
[root@ansible-server] cat /opt/a.txt
ansible-web1 | SUCCESS | rc=0 >>
Filesystem              Type      Size  Used Avail Use% Mounted on
/dev/mapper/centos-root xfs        17G  1.2G   16G   7% /
devtmpfs                devtmpfs  475M     0  475M   0% /dev
tmpfs                   tmpfs     487M     0  487M   0% /dev/shm
tmpfs                   tmpfs     487M  7.7M  479M   2% /run
tmpfs                   tmpfs     487M     0  487M   0% /sys/fs/cgroup
/dev/sda1               xfs      1014M  133M  882M  14% /boot
tmpfs                   tmpfs      98M     0   98M   0% /run/user/0

自动化运维Ansible
自动化运维Ansible

2、ansible里的常用模块

ansible是基于模块工作的,它上面有很多模块

[root@ansible-server] ansible-doc -l   #查看所有模块
[root@ansible-server] ansible-doc -s yum   #查看yum模块的使用信息

2.1、copy模块

#远程复制备份模块:copy
参数详解
src=:指定源文件路径
dest=:目标地址
owner=:指定属主
group=:指定属组
mode=:指定权限
backup=:如果目标地址已存在这个文件则会查看文件,文件有变化将原文件备份,无变化不做备份,备份文件包含时间信息,选项为yes|no

[root@ansible-server] vim /root/a.txt   #在server端创建a.txt
xiaobai   #在文件中写入xiaobai

#切换到web1上查看/opt/下有没有a.txt文件
[root@ansible-web1] cat /opt/a.txt
cat: /opt/a.txt: No such file or directory
#可以看到web1的/opt/下是没有a.txt的

[root@ansible-server] ansible webgrp1 -m copy -a 'src=/root/a.txt dest=/opt/ owner=root group=root mode='644' backup=yes' -o
ansible-web1 | SUCCESS => {"changed": true ...... "state": "file", "uid": 0}
#此时我们再切换到web1上查看
[root@ansible-web1] ll /opt/
total 4
-rw-r--r--. 1 root root 8 Mar 24 16:23 a.txt
[root@ansible-web1] cat /opt/a.txt 
xiaobai
#这时候web1下已经有了a.txt文件,文件内容就是我们输入的xiaobai,属主属组为root,权限为644
#由于之前的/opt/下没有a.txt文件,所以备份开启也不备份

#我们再回到server端执行刚才的命令
[root@ansible-server] ansible webgrp1 -m copy -a 'src=/root/a.txt dest=/opt/ owner=root group=root mode='644' backup=yes' -o
ansible-web1 | SUCCESS => {"changed": false ...... "state": "file", "uid": 0}
#再次回到web1上查看有无备份文件
[root@ansible-web1] ls /opt/
a.txt
#这里我们可以看到,由于文件内容相同不进行备份

#我们先在web2的/opt/下创建一个a.txt文件
[root@ansible-web2] vim /opt/a.txt
little   #在这个文件中写入little

#我们换回到server端执行命令
[root@ansible-server] ansible webgrp2 -m copy -a 'src=/root/a.txt dest=/opt/ owner=root group=root mode='644' backup=yes' -o
ansible-web2 | SUCCESS => {"backup_file": "/opt/a.txt.8548.2020-03-24@16:38:46~" ...... "state": "file", "uid": 0}

#此时我们回到web2查看
[root@ansible-web2] ls /opt/
a.txt    a.txt.8548.2020-03-24@16:38:46~
#可以看到这里有两个文件,分别查看
[root@ansible-web2] cat /opt/a.txt.8548.2020-03-24\@16\:38\:46~ 
little
[root@ansible-web2] cat /opt/a.txt
xiaobai
#长的为原文件,原文件被备份并加上了日期时间

2.2、yum模块

#软件包管理模块:yum
参数详解
name=:安装包名
state=absent:用于卸载安装包
state=latest:表示安装最新的
state=removed:表示卸载
#state=absent和state=removed都是卸载,用哪个都可以

#先切换到web1查看有没有下载httpd服务
[root@ansible-web1] rpm -qa |grep httpd
#没有任何反馈就是没下载

#回到server端
[root@ansible-server] ansible webgrp1 -m yum -a 'name=httpd state=latest'   #要等一定时间
ansible-web1 | SUCCESS => {"changed": true, "msg": "", "rc": 0, "results": ["Loaded plugins: fastestmirror
--> Running transaction check

......


Dependency Installed:
  apr.x86_64 0:1.4.8-5.el7                     apr-util.x86_64 0:1.5.2-6.el7    
  httpd-tools.x86_64 0:2.4.6-90.el7.centos     mailcap.noarch 0:2.1.41-2.el7    
Complete!
"]}

#安装成功,我们到web1上查看一下
[root@ansible-web1] rpm -qa |grep httpd
httpd-tools-2.4.6-90.el7.centos.x86_64
httpd-2.4.6-90.el7.centos.x86_64
#此时已经有了httpd,卸载的话用remove和absent都可以

2.3、service模块

#服务管理模块:service
参数详解
state=stopped:停止服务
state=restarted:重启服务
state=started:启动服务
enabled=yes:开机自启
enabled=no:开机关闭

[root@ansible-server] ansible webgrp1 -m service -a 'name=httpd state=started enabled=yes' -o
ansible-web1 | SUCCESS => {"changed": false, "enabled": true, "name": "httpd"
                            ......
"WatchdogTimestampMonotonic": "32583844837", "WatchdogUSec": "0"}}


#我们切换到web1上查看
[root@ansible-web1] systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2020-03-24 18:15:11 CST; 57s ago

自动化运维Ansible

2.4、file模块

#文件模块:file
参数详解
owner:修改属主
group:修改属组
mode:修改权限
path:修改文件的路径
recurse:递归设置的文件,只对目录有效,yes表示使用递归参数
state=touch:创建一个新的空文件
state=directory:创建一个新的目录,当目录存在时不会进行修改

#我们创建一个文件bai.txt属主为xiaobai
#先切换到web1
[root@xiaobai-web1] useradd xiaobai
[root@xiaobai-web1] id xiaobai
uid=1000(xiaobai) gid=1000(xiaobai) groups=1000(xiaobai)

#我们回到server端
[root@xiaobai-server] ansible webgrp1 -m file -a 'path=/tmp/bai.txt mode=777 owner=xiaobai state=touch' -o   #不写属主属组的话默认为root
ansible-web1 | SUCCESS => {"changed": true ..... "state": "file", "uid": 1000}

#到web1上查看这个文件
[root@xiaobai-web1] ll /tmp
total 4
-rwxrwxrwx. 1 xiaobai root   0 Mar 24 18:36 bai.txt


#下面我们在web2上用递归修改目录属主属组
#首先我们先在web2上创建一个目录及文件查看一下
[root@xiaobai-web2] ll /xb
total 0
-rw-r--r--. 1 root root 0 Mar 24 18:43 little.txt
-rw-r--r--. 1 root root 0 Mar 24 18:43 xiaobai.txt
[root@xiaobai-web2] ll -d /xb
drwxr-xr-x. 2 root root 43 Mar 24 18:43 /xb
[root@xiaobai-web2] useradd bai
[root@xiaobai-web2] groupadd little

#创建好后我们到server端
[root@xiaobai-server] ansible webgrp2 -m file -a 'path=/xb owner=bai group=little state=directory recurse=yes' -o
ansible-web2 | SUCCESS => {"changed": true, "gid": 1001, "group": "little", "mode": "0755", "owner": "bai", "path": "/xb", "secontext": "unconfined_u:object_r:default_t:s0", "size": 43, "state": "directory", "uid": 1000}

#我们到web2上查看
[root@xiaobai-web2] ll /xb
total 0
-rw-r--r--. 1 bai little 0 Mar 24 18:43 little.txt
-rw-r--r--. 1 bai little 0 Mar 24 18:43 xiaobai.txt
[root@xiaobai-web2] ll -d /xb
drwxr-xr-x. 2 bai little 43 Mar 24 18:43 /xb

2.5、setup模块

#收集信息模块:setup
#只查询ipv4的地址
[root@xiaobai-server] ansible webgrp1 -m setup -a 'filter=ansible_all_ipv4_addresses'   #只查询ipv4的地址
ansible-web1 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.202.132"
        ]
    }, 
    "changed": false
}


#收集webgrp1主机组里主机的所有信息
[root@xiaobai-server] ansible webgrp1 -m setup   #收集所有信息
ansible-web1 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.202.132"
            
                    ......
                    
        "module_setup": true
    }, 
    "changed": false
}

四、ansible剧本(playbook)

前面已经定义了ansible的主机组

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

接下来来了解ansible中最重要的playbok吧

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

1、简单的剧本

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

1.1、触发器

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

#参数详解
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   

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

自动化运维Ansible
执行剧本之前一定要确定有我们要发的文件,没有的话就创建一个

[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里

1.2、循环迭代

对迭代项的引用,固定变量名为”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
#可以看到都下载好了

1.3、自定义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

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

1.4、剧本多个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

1.5、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
#可以看到我们执行成功了

1.6、剧本中定义变量

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

在文件中
自动化运维Ansible

五、roles角色

1、roles又是什么

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

  • 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:定义哪个主机应用哪个角色。

2、用roles创建一个nginx吧

[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目录下还没有创建文件,先不着急

自动化运维Ansible

#创建nginx的测试文件
[root@ansible-server] echo 1234 > nginx/files/index.html
#安装nginx并配置模板,下载不了的先下载epel-release源
[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结尾可以引用变量,

修改成如下内容,自定义变量
自动化运维Ansible
把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了
上一篇:jsp页面List迭代


下一篇:failed to run Kubelet: misconfiguration: kubelet cgroup driver: \"systemd\" 问题解决