自动化运维神器——Ansible

目录

一、Ansible

1、Ansible简介

2、自动化运维工具对比:

3、Ansible特性

4、Ansible执行流程

二、ansible安装

1、实验环境

2、安装

3、主配置文件

1、主配置文件

2、配置主机清单文件(inventory)

3、查看配置文件

4、添加主机或者主机组

5、ansible命令语法:

三、Ad-Hoc组件

常用模块

1、远程复制备份模块:copy

2、yum模块

3、服务管理service模块

4、文件模块file

5、用户管理user模块

6、收集信息模块setup

四、Ansible-playbook

1、Playbook介绍

2、playbook核心元素

3、playbook基础组件

4、playbook基础使用案例

5、ansible-playbook变量使用

五、ansible-role

六、ansible常用模块

批量部署JDK+Tomcat+Jenkins


一、Ansible

1、Ansible简介

Ansible是一款类Unix系统开发的自由开源的配置和自动化工具。

它用Python写成,类似于saltstack和Puppet,但是有一个不同的优点是我们不需要在节点中安装客户端。

他是用SSH来和节点进行通信。Ansible基于Python paramiko开发,分布式,无需客户端轻量级,配置语法使用YMAL及jinja2模板语言,更强的远程命令执行操作。

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

解决了容器不能免密的问题:sed -i -r 's/^(.*pam_nologin.so)/#\1/' /etc/pam.d/sshd

官方网站:https://www.ansible.com/

2、自动化运维工具对比:

1、Puppet:基于 Ruby 开发,采用 C/S 架构,扩展性强,基于 SSL,远程命令执行相对较弱

2、SaltStack:基于 Python 开发,采用 C/S 架构,相对 puppet 更轻量级,配置语法使用 YAML,使得配置脚本更简单.需要配置客户端以及服务器端。每台被控制节点需要安装agent

3、Ansible:基于Python开发,分布式,无需客户端,轻量级,配置语法使用YAML语言,更强的远程命令执行操作

3、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多任务配置文件,非必需

4、Ansible执行流程

  1. 读取ansible.cfg文件
  2. 通过规则过滤inventory中定义的主机列表
  3. 加载task对应的模块
  4. 通过ansible core将模块或命令打包成python脚本文件
  5. 将临时脚本文件传输到远程服务器
  6. 对应执行用户家目录的"ansible /tmp/xx/xxx.py"文件
  7. 给文件加执行权限
  8. 执行py文件并返回结果
  9. 删除临时文件并退出

二、ansible安装

1、实验环境

主机:4台 1个控制节点 3个被控制节点

所有机器全部互相解析

192.168.242.144 ansible

192.168.242.145 web-1

192.168.242.146 web-2

192.168.242.147 web-3

配置ssh公钥认证:控制节点需要发送ssh公钥给所有被控制节点
[root@ansible ~]# ssh-keygen
[root@ansible ~]# ssh-copy-id root@192.168.242.145
[root@ansible ~]# ssh-copy-id root@192.168.242.146
[root@ansible ~]# ssh-copy-id root@192.168.242.147

2、安装

安装:控制节点
配置epel网络yum源(有的话忽略)
[root@ansible ~]# yum install -y epel-release
[root@ansible ~]# yum install -y ansible
[root@ansible ~]# ansible --version
[root@ansible ~]# ansible --help

3、主配置文件

1、主配置文件

/etc/ansible/ansible.cfg

主要设置一些ansible初始化的信息,比如日志存放路径、模块、插件的配置信息

配置文件中常见参数:

inventory = /etc/ansible/hosts  #这个参数表示资源清单inventory文件的位置
library=/usr/share/ansible      #指向存放ansible模块的目录,支持多个目录方式,只要用冒号(:)隔开就可以
forks=5                         #并发连接数,默认为5
sudo_user=root                  #设置默认执行命令的用户
remote_port=22                  #指定连接被管节点的管理端口,默认为22端口,建议修改,能够更加安全
host_key_checking=False         #设置是否检查ssh主机的密匙,值为Ture/False。关闭后第一次连接不会提示配置实例
timeout=60                      #设置ssh连接的超时时间,单位为秒
log_pash=/var/log/ansible.log   #指定一个存储ansible日志的文件(默认不记录日志)
 

2、配置主机清单文件(inventory)

默认位置/etc/ansible/hosts,定义所管理的主机组及主机,可以在主配置文件中指定清单文件位置和名称

配置文件详解:
Ungrouped hosts, specify before any group headers. 未分组主机,在任何组头之前指定           blue.example.com
192.168.100.1

A collection of hosts belonging to the 'webservers' group.属于“webservers”组的主机集合[webservers]
alpha.example.org
beta.example.org
192.168.1.100
192.168.1.110

If you have multiple hosts following a pattern you can specify.如果有多个主机遵循一个模式,则可以指定
www[001:006].example.com

A collection of database servers in the 'dbservers' group.“dbservers”组中的数据库服务器集合
[dbservers]
db01.intranet.mydomain.net
db02.intranet.mydomain.net
10.25.1.56

3、查看配置文件

[root@ansible ~]# rpm  -qc ansible
/etc/ansible/ansible.cfg
/etc/ansible/hosts   #ansible主机清单文件

4、添加主机或者主机组

vim /etc/ansible/hosts     #在最后追加被管理端的机器
...
web-1    #单独添加主机,可以使用主机名称或ip地址

[web1]  组1 #添加主机组,使用[]标签指定主机组 ----标签自定义
web-1    被监控端的域名,如果未解析添加ip
web-2
up.example.com:5309              //指定 SSH 端口 5309
web5  ansible_ssh_host=web-2  //设置主机web-2的别名为 web5
web1 ansible_ssh_pass='123'  //设置ssh密码,使用-k参数之后提示的密码可以不写,直接回车
www[01:50].example.com         //支持通配符匹配www01,www02,...,www50
db-[a:f].example.com                //通配符匹配db-a,db-b,...,db-f    

[web2]  组2
web-3

#组可以包含其他组
[webzzz:children] #children-照写  #weball包括两个子组
web1
web2

#为一个组指定变量,组内每个主机都可以使用该变量:
[webzzz:vars]         #设置变量,vars--照写
ansible_ssh_port=22     
ansible_ssh_user=root   
ansible_ssh_private_key_file=/root/.ssh/id_rsa  
#ansible_ssh_pass=test      #也可以定义密码,如果没有互传秘钥可以使用密码。

ansible基于ssh连接inventory中指定的远程主机时,还可以通过参数指定其交互方式:
ansible_ssh_host # 远程主机
ansible_ssh_port # 指定远程主机ssh端口
ansible_ssh_user # ssh连接远程主机的用户,默认root
ansible_ssh_pass # 连接远程主机使用的密码,在文件中明文,建议使用--ask-pass或者使用SSH keys
ansible_sudo_pass # sudo密码, 建议使用--ask-sudo-pass
ansible_connection # 指定连接类型: local, ssh, paramiko
ansible_ssh_private_key_file # ssh 连接使用的私钥
ansible_shell_type # 指定连接对端的shell类型, 默认sh,支持csh,fish
ansible_python_interpreter # 指定对端使用的python编译器的路径

 Ansible Inventory 常见的内置参数:

 5、ansible命令语法:

ansible <pattern> -m <module_name> -a <argiments>
pattern:主机清单里定义的主机组名,主机名,ip,别名等,all表示所有的主机,支持通配符,正则
:  多个主机组,组名之间用冒号隔开
*web*:组名或主机名中含web的
webserver[0]:webserver组中的第一台主机
以~开头,匹配正则
-m module_name:模块名称,默认command
-a arguments:传递给模块的参数

查看组内主机列表:
语法:ansible  组名  --list-hosts
[root@ansible ~]# [root@ansible ~]# ansible web* --list-hosts
  hosts (3):
    web-3
    web-1
    web-2
====================================
扩展:自定义主机列表使用密码登录:(了解)
[root@ansible ~]# vim /opt/hostlist
[all:vars]
ansible_ssh_port=22
ansible_ssh_user=root
#ansible_ssh_private_key_file=/root/.ssh/id_rsa
ansible_ssh_pass=test

[all]
web-1
web-2
web-3
使用:
[root@ansible ~]# ansible -i /opt/hostlist all -m ping -o
小注释:如果不通,手动连接第一次,第一次需要手动输入密码。"第一次"
-i:指定清单文件
注意:这里的ping并不是真正意义上的ping而是探测远程主机ssh是否可以连接!判断ssh端口是否存活

基本使用示例:

执行shell命令:-a 是传给模块的参数
[root@ansible ~]# ansible web-1 -m shell -a 'uptime'
web-1 | CHANGED | rc=0 >>
 18:01:44 up 13:21,  3 users,  load average: 0.00, 0.01, 0.05
因为默认模块就是command,所以上面命令可以不加-m:
[root@ansible ~]# ansible web-2 -a 'uptime'
web-2 | CHANGED | rc=0 >>
 18:02:22 up 13:22,  3 users,  load average: 0.00, 0.01, 0.05
[root@ansible ~]# ansible web1 -a 'uptime' -u root -k
SSH password: 
web1 | SUCCESS | rc=0 >>
11:02:56 up 2 days, 15:07,  2 users,  load average: 0.00, 0.01, 0.05

使用ssh账户和密码:-u和-k
-u  用户    //指定ssh账户
-k             //指定使用ssh密码,注意:如果设置了公钥认证,这里写什么密码都可以

给节点增加用户
[root@ansible ~]# ansible web-3 -a "useradd tom"
web-3 | CHANGED | rc=0 >>
[root@ansible ~]# ansible web-3 -a "grep tom /etc/passwd"
web-3 | CHANGED | rc=0 >>
tom:x:1000:1000::/home/tom:/bin/bash

重定向输出到本地文件中:  
[root@ansible ~]# ansible web-1 -m shell -a "echo hello > /opt/a.txt"
web-1 | CHANGED | rc=0 >>

[root@ansible ~]# ansible web-1 -m shell -a "cat /opt/a.txt"
web-1 | CHANGED | rc=0 >>
hello

注意:一个典型的例子就是 shell 和 command 模块. 这两个模块在很多情况下都能完成同样的工作, 以下是两个模块之间的区别:
command 模块命令将不会使用 shell 执行. 因此, 像 $HOME 这样的变量是不可用的。还有像 |,& 都将不可用。
shell 模块通过shell程序执行, 默认是/bin/sh, <, >, |, ;, & 可用。

三、Ad-Hoc组件

ad hoc其实就是执行简单的命令——一条命令。对于复杂的命令则为 playbook。

帮助文档:

列出ansible支持的模块:

-l:获取列表

-s module_name:获取指定模块的使用信息

获取模块列表
[root@ansible ~]# ansible-doc -l
模块使用格式:
[root@ansible ~]# ansible-doc -s yum
参数:
-f 2 指定定要使用的并行进程数,默认为5个,临时指定,如果想要永久指定,修改主配置文件。

 也可以看官方手册:https://docs.ansible.com/ansible/2.9/modules/core_maintained.html#core-supported

常用模块

1、远程复制备份模块:copy

模块参数详解:  
src=:指定源文件路径
dest=:目标地址(拷贝到哪里)
owner:指定属主
group:指定属组
mode:指定权限,可以以数字指定比如0644
backup:在覆盖之前将原文件备份,备份文件包含时间信息。有两个选项:yes|no

[root@ansible ~]# echo 123 > a.txt
[root@ansible ~]# ansible web-1 -m copy -a 'src=/root/a.txt dest=/root owner=root group=root mode=644' -o 
....
[root@ansible ~]# echo 456 >> a.txt 
[root@ansible ~]# ansible web-1 -m copy -a 'src=/root/a.txt dest=/root owner=root group=root mode=644 backup=true' -o 
....
注释:如果文件没有变化,不会备份。只有文件内容不同,才会做备份。

在web-1上验证
[root@web-1 ~]# ls
anaconda-ks.cfg  a.txt        a.txt.4286.2022-05-22@18:28:53~
[root@web-1 ~]# cat a.txt
123
456
[root@web-1 ~]# cat a.txt.4286.2022-05-22@18\:28\:53~ 
123

copy模块:https://docs.ansible.com/ansible/2.9/modules/copy_module.html#copy-module

2、yum模块

state=     #状态是什么,干什么
state=absent       用于remove安装包
state=latest       表示最新的
state=removed      表示卸载
在用这个模块之前,可以不指定yum模块验证一下
安装:sl
[root@ansible ~]# ansible web-3 -a "yum -y install sl"
[WARNING]: Consider using the yum module rather than running 'yum'.  If you need to use command because yum is insufficient you can add
'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
([警告]:考虑使用yum模块,而不是运行“yum”。如果由于yum不足而需要使用命令,可以将“warn:false”添加到此命令任务,或在ansible中设置“command\u warnings=false”。cfg以删除此消息。)
...
完毕!
[root@ansible ~]# ansible web-1 -m yum -a "name=sl" -o
web-1 | CHANGED => {"ansible_facts": {"discovered_interpreter_py.....

卸载:
[root@ansible ~]# ansible web-1 -m yum -a "name=sl state=removed" -o
web-1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python......
或者
ansible web-1 -m yum -a "name=sl state=absent" -o

   yum模块:https://docs.ansible.com/ansible/2.9/modules/yum_module.html#yum-module

3、服务管理service模块

[root@ansible-server ~]# ansible web-1 -m service -a "name=httpd state=started" #启动
[root@ansible-server ~]# ansible web-1 -m service -a "name=httpd state=stopped" #停止
[root@ansible-server ~]# ansible web-1 -m service -a "name=httpd state=restarted" #重启
[root@ansible-server ~]# ansible web-1 -m service -a "name=httpd state=started enabled=yes" #开机启动
[root@ansible-server ~]# ansible web-1 -m service -a "name=httpd state=started enabled=no"  #开机关闭

4、文件模块file

模块参数详解:  
owner:修改属主
group:修改属组
mode:修改权限
path=:要修改文件的路径
recurse:递归的设置文件的属性,只对目录有效
yes:表示使用递归设置
state:
touch:创建一个新的空文件
directory:当目录存在时不会进行修改
[root@ansible ~]# ansible web-1 -m file -a 'path=/root/b.txt mode=777 state=touch'
web-1 | CHANGED => {
   ...
}
[root@ansible ~]# ansible web-1 -m file -a 'path=/root/c.txt mode=777 state=directory'
web-1 | CHANGED => {
  ....
}

5、用户管理user模块

添加用户并设置密码:使用命令需要用双引:
[root@ansible ~]# ansible web-1 -m user -a "name=liudehua password=`echo 1234 | openssl passwd -1 -stdin`" -o
"name=   "  #如:指定的用户名,要安装的软件
-1 MD5加密算法

删除用户:
[root@ansible ~]# ansible web-1 -m user -a "name=liudehua state=absent" -o
adsent #删除用户,但是不会删除家目录

也可以:ansible web-1 -a "userdel -r zzz"

6、收集信息模块setup

[root@ansible ~]# ansible web-1 -m setup  #收集所有信息
[root@ansible ~]# ansible web-1 -m setup -a 'filter=ansible_all_ipv4_addresses' #只查询ipv4的地址
filter:过滤
[root@ansible ~]# ansible web-1 -m setup -a 'filter=ansible_*_mb'
[root@ansible ~]# ansible -i /home/ansible/hostlist web1 -m setup -a 'filter=ansible_processor_cores'
[root@ansible ~]# ansible all -m setup --tree /tmp/facts  

扩展:

获取每台主机的IP地址:
ansible -i /opt/hostlist web-1 -m shell -a 'ip a |grep "scope global" |awk "{print $2}"'
获取每台主机的内存:
[root@xingdian ~]# ansible -i /opt/hostlist web-1 -m shell -a "free -m | awk 'NR==2'" > b.txt -o && cat b.txt | awk '{print $10}'

四、Ansible-playbook

1、Playbook介绍

playbook是ansible用于配置,部署。和管理被控节点的剧本。通过playbook的详细描述,执行其中的tasks,可以让远端主机达到预期的状态。playbook是由一个或多个"play"组成的列表。当对一台机器做环境初始化的时候往往需要布置做一件事情,这是使用playbook会更加适合。通过playbook你可以一次在多台机器执行指令。通过这种预先设计的的配置保持了机器的配置统一,并很简单的执行日常任务。

ansible通过不同的模块实现相应的管理,管理的方式通过定义的清单文件(hosts)所管理的主机包括认证的方式连接的端口等。所有的功能都是通过调用不同的模块(modules)来完成不同的功能的。不管是执行单条命令还是play-book都是基于清单文件。

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

2、playbook核心元素

Variables:变量元素,可传递给Tasks/Template使用;

Tasks:任务元素,有模块定义的操作的列表,即调用模块完成任务;

Templates:模块元素,使用了模块语法的文本文件,可根据变量动态生成配置文件;

Handlers:处理器元素,通常指在某事件满足时触发的操作;

Roles:角色元素

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

3、playbook基础组件

name:定义playbook或者tasks的名称(描述信息),每一个play都可以完成一个任务。

hosts:playbook中的每一个play的目的都是为了让某个或某些以某个指定用户的身份执行任务。hosts用于指定要执行指定任务的主机,其可以是一个或多个由冒号分隔主机组。与命令模式下的ansible匹配规则一样

user:remote_user则用于指定远程主机上的执行任务的用户,也可以使用user(基本都是root)

tasks:任务列表play的主题部分是task list,task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。

vars:定义变量(如果不使用内部变量需要提前定义)

vars_files:动用定义变量文件

notify:任务执行结果如果是发生更改了的则触发定义在handler的任务执行

handlers:用于当前关注的资源发生变化时采取的指定的操作

include:能包含的包括task,handler和playbook,可以在include的时候传递变量

4、playbook基础使用案例

案例一

[root@ansible ~]# cd /etc/ansible
[root@ansible ansible]# vim test.yml
- hosts: web-1     #-后面有空格,冒号后面有空格
  user: root
  tasks: 
  - name: test
    file: state=touch path=/root/test.txt
参数解释:
hosts: 参数指定了对哪些主机进行操作;
user: 参数指定了使用什么用户登录远程主机操作;
tasks: 指定了一个任务.
name:参数同样是对任务的描述,在执行过程中会打印出
[root@ansible ansible]# ansible-playbook --syntax-check test.yml  #检测是否有语法错误

playbook: Test.yml
[root@ansible ansible]# ansible-play-book test.yml    #运行playbook

案例二

handlers:由特定条件触发Tasks
语法:
tasks:
- name: TASK_NAME
  module: arguments              #1.上面任务执行成功,然后
  notify: HANDLER_NAME           #2.通知他
handlers:
- name: HANDLER_NAME             #3.一一对应,这里的描述与notify定义的必须一样
  module: arguments              #4.执行这个命令
[root@ansible ansible]# cat /root/a.txt 
123
[root@ansible ansible]# vim handlers.yml
- hosts: web-2
  user: root
  tasks:
  - name: test copy
    copy: src=/root/a.txt dest=/mnt
    notify: test handlers
  handlers:
  - name: test handlers
    shell: echo "1234" >>/mnt/a.txt
注意:只有 copy 模块真正执行后,才会去调用下面的 handlers 相关的操作,追加内容。所以这种比较适合配置文件发生更改后,需要重启服务的操作。
[root@ansible ansible]# ansible-playbook handlers.yml #运行playbook

在web-2上验证
[root@localhost ~]# cat /mnt/a.txt 
123
1234

案例三

安装nginx并启动服务
[root@ansible ansible]# vim yum.yml
- hosts: web-3
  user: root
  tasks:
  - name: nginx
    yum: name=nginx state=latest
  - name: index
    shell: echo "hello word" >/usr/share/nginx/html/index.html
    notify: test nginx
  handlers: test nginx
  - name: start nginx
    service: name=nginx state=started
[root@ansible ansible]# ansible-playbook --syntax-check yum.yml
playbook: handlers.yml
[root@ansible ansible]# ansible-playbook yum.yml
....


验证:
[root@ansible ansible]# curl web-3
hello word

案例四

自定义vars_file变量
变量调用语法:
{{ var_name }}
创建变量目录
[root@ansible ansible]# mkdir /etc/ansible/vars
[root@ansible ansible]# vim vars/file.yml      #创建变量文件
src_path: /root/a.txt
dest_path: /opt/
[root@ansible ansible]# echo "自定义变量" >/root/a.txt
创建playbook引用变量文件
[root@ansible ansible]# vim vars_file.yml
- hosts: web-1
  user: root
  vars_files: 
  - /etc/ansible/vars/file.yml
  tasks:
  - name: vars
    copy: src={{ src_path }} dest={{ dest_path }}
[root@ansible ansible]# ansible-playbook --syntax-check vars_file.yml 

playbook: vars_file.yml
[root@ansible ansible]# ansible-playbook vars_file.yml

在web-1验证
[root@web-1 ~]# cat /opt/a.txt 
自定义变量

案例五

循环:迭代,需要重复执行的任务;
对迭代项的引用,固定变量名为”item”,使用with_items属性给定要迭代的元素; 
元素:1.列表 2.字符串 3.字典
基于字符串列表元素实战
[root@ansible ansible]# vim list.yml
- hosts:
  user: root
  tasks:
  - name: a
    yum: name={{ item }} state=latest
    with_items:
    - httpd
    - php
    - php-mysql
[root@ansible ansible]# ansible-playbook --syntax-check list.yml 
[root@ansible ansible]# ansible-playbook  list.yml

基于字典列表元素实战
[root@ansible ansible]# vim item.yml
- hosts: web-1
  user: root
  tasks:
  - name: create group
    group: name={{ item }} state=present
    with_items:
    - hr1
    - hr2
    - hr3
  - name: create user
    user: name={{ item.name }} group={{ item.group }} state=present
    with_items:
    - {name: "zcg",group: "hr1"}
    - {name: "zcy",group: "hr2"}
    - {name: "hjf",group: "hr3"}
[root@ansible ansible]# ansible-playbook --syntax-check item.yml 
[root@ansible ansible]# ansible-playbook  item.yml

案例六

tags使用:
给指定任务定义一个调用标识,形式如下

只运行指定标记的任务:-t 标记名称
 ansible-playbook  -t z1 tags.yml

跳过某一个被标记的任务:--skip-tags=标记名称
 ansible-playbook  --skip-tags=z1 tags.yml 

从某一个任务开始往下运行:--start-at-task 任务名称
ansible-playbook  --start-at-task  tag2 tags.yml

[root@ansible ansible]# vim tags.yml
- hosts: web-1
  user: root
  tasks:
  - name: tag1
    file: state=touch path=/root/tag1
    tags: z1
  - name: tag2
    file: state=touch path=/root/tag2
    tags: z2
  - name: tag3
    file: state=touch path=/root/tag3.txt
    tags: z3
[root@ansible ansible]# ansible-playbook -t z1 tags.yml
[root@ansible ansible]# ansible-playbook --skip-tags=z1 tags.yml
[root@ansible ansible]# ansible-playbook --start-at-task tag3 tags.yml

批量安装apache服务,并用浏览器访问到对应的项目

[root@ansible ansible]# mkdir apache
[root@ansible ansible]# echo "hello word" > apache/index.html
[root@ansible ansible]# vim apache/apache.conf
<VirtualHost *:81>
        ServerName localhost
        DocumentRoot /apache
</VirtualHost>

<Directory "/apache">
        AllowOverride all
        Require all granted
</Directory>
[root@ansible ansible]# vim apache.yml
- hosts: web*
  user: root
  tasks:
  - name: a
    yum: name=httpd state=latest
  - name: b
    file: state=directory path=/apache mode=777
  - name: c
    copy: src=/etc/ansible/apache/index.html dest=/apache
  - name: d
    shell: echo "Listen 81" >>/etc/httpd/conf/httpd.conf
  - name: e
    copy: src=/etc/ansible/apache/apache.conf dest=etc/httpd/conf.d/
    notify: f
  - name: f
    service: name=httpd state=started
[root@ansible ansible]# ansible-playbook --syntax-check apache/apache.yml

playbook: apache/apache.yml
[root@ansible ansible]# ansible-playbook apache/apache.yml

验证:
[root@ansible ansible]# curl web-1
hello word

5、ansible-playbook变量使用

Variable类型:

内建变量

自定义变量

变量调用

{{ var_name }}

内建变量:由facts组件提供,可以使用setup模块查询

案例一

[root@ansible ansible]# ansible web-1 -m setup|grep mem
        "ansible_memfree_mb": 1175, 
        "ansible_memory_mb": {
        "ansible_memtotal_mb": 1823,
[root@ansible ansible]# vim var1.yml 
- hosts: web-3
  user: root
  tasks: 
  - name: vars
    shell: echo {{ ansible_memtotal_mb }} >> /root/mem.txt
[root@ansible ansible]# ansible-playbook var1.yml

案例二

自定义变量:
使用命令行传递参数
为了使Playbook更灵活、通用性更强,允许用户在执行的时候传入变量的值,这个时候就需要用到“额外变量”。
[root@ansible ansible]# vim var2.yml 
- hosts: '{{ hosts }}'
  user: '{{ user }}'
  tasks:
  - name: zzz
    file: state=touch path=/root/var1.txt
使用命令行变量
在命令行里面传值的方法: 
[root@ansible ansible]# ansible-playbook var2.yml --extra-vars "hosts=web-2 user=root"
还可以用json格式传递参数:  
[root@ansible ansible]# ansible-playbook var2.yml --extra-vars "{'hosts':'web-1','user':'root'}"

案例三

set_fact自定义facts变量

set_fact模块可以自定义facts,这些自定义的facts可以通过template或者变量的方式在playbook中使用。如果你想要获取一 个进程使用的内存的百分比,则必须通过set_fact来进行计算之后得出其值,并将其值在playbook中引用。

[root@ansible ansible]# mkdir templates
[root@ansible ansible]# vim template/my.conf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted
security risks
symbolic-links=0
 
# Configure the buffer pool
innodb_buffer_pool_size = {{ aaa|int }}M
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[root@ansible ansible]# vim var3.yml
- hosts: web*
  user: root
  tasks:
  - name: mycnf
    set_fact: aaa="{{ ansible_memtotal_mb / 2 }}"
  - name: ccc
    template: src=templates/my.cnf dest=/etc/my.cnf owner=root group=root mode=0644
[root@ansible ansible]# ansible-playbook var3.yml 

五、ansible-role

role 角色:roles是在ansible中,playbook的目录组织结构

每一个角色是有名字的,是一个目录,可以包含子目录。以特定的层级目录结构进行组织的tasks、variable、handlers、templates、files等

role_name/:这个是角色的名称

files/:存储有copy或script等模块调用的文件

tasks/:专门存储任务的目录,一个角色可以定义多个任务,此目录中至少应该有一个名为main.yml的文件,用于定义各task;其他的文件需要由main.yml进行“包含”调用

handlers/:条件,前一个任务执行成功去执行下面的,用于处理特定事物的文件。此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其他的文件需要由main.yml进行“包含”调用

vars/:变量,定义变量的文件。此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其他的文件需要由main.yml进行“包含”调用

templates/:模板,使用变量的文件存储由template模块调用的模板文本

meta/:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其以来关系

default/:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量

在playbook中调用角色的方法:

- hosts: HOSTS
  remote_user: USERNAME
  roles:
  - ROLE1
  - ROLE2
  - { role: ROLE3, VARIABLE: VALUE, ...}
  - { role: ROLE4, when: CONDITION }  

案例:批量部署nginx(做这个实验之前记得将apache关闭或者卸载)

 

目录结构准备
[root@ansible roles]# mkdir nginx/{files,handlers,tasks,templates,vars} -p
[root@ansible roles]# touch nginx/{handlers,tasks,vars}/main.yml site.yml
[root@ansible roles]# echo "hello word" >nginx/files/index.html
[root@ansible roles]# yum -y install nginx &&cp /etc/nginx/nginx.conf nginx/templates/nginx.conf.j2  这一步是为了准备nginx主配置文件的模板文件,如果已经有的话,直接拷贝到templates目录中即可
[root@ansible roles]# tree nginx
nginx/
├── files
│   └── index.html
├── handlers
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
│   └── nginx.conf.j2
└── vars
    └── main.yml

编写任务
[root@ansible roles]# vim nginx/tasks/main.yml
- name: a
  yum: name=nginx state=removed
- name: b
  yum: name=nginx state=latest
- name: c
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: d
  copy: src=index.html dest=/usr/share/nginx/html/index.html
  notify: start nginx
注意:这里面的src之所以不用写路径是因为roles使用的是特定的层级目录结构,会自动寻找nginx目录中对应的文件

templates模板:  用的是jinja2的语法
准备配置文件
[root@ansible roles]# vim nginx/templates/nginx.conf.j2
修改成如下内容。自定义变量
...
events {
    worker_connections  {{ worker_connections }};
}
...

编写变量
[root@ansible roles]# vim nginx/vars/main.yml
worker_connections: 65535

编写handlers
[root@ansible roles]# vim nginx/handlers/main.yml
- name: start nginx    #这里的名称描述要与tasks任务中的notify名称描述对应
  service: name=nginx state=started

编写剧本
[root@ansible roles]# vim site.yml
- hosts: web*
  user: root
  roles: 
  - nginx

语法检测
[root@ansible roles]# ansible-playbook --syntax-check site.yml
playbook: site.yml

执行剧本
[root@ansible roles]# ansible-playbook  site.yml

验证:
[root@ansible roles]# curl web-1
hello word
[root@ansible roles]# curl web-2
hello word
[root@ansible roles]# curl web-3
hello word

六、ansible常用模块

1. setup: 查看远程主机的基本信息
2. ping: 测试远程主机的运行状态
3. file: 设置文件属性
    相关选项如下:
    force:需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
    group:定义文件/目录的属组
    mode:定义文件/目录的权限
    owner:定义文件/目录的属主
    path:必选项,定义文件/目录的路径
    recurse:递归设置文件的属性,只对目录有效,有两个选项:yes|no
    src:被链接的源文件路径,只应用于state=link的情况
    dest:被链接到的路径,只应用于state=link的情况
    state:
           directory:如果目录不存在,就创建目录
           file:即使文件不存在,也不会被创建
           link:创建软链接
           hard:创建硬链接
           touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
           absent:删除目录、文件或者取消链接文件
    
   使用示例:
        ansible test -m file -a "src=/etc/fstab dest=/tmp/fstab state=link"
        ansible test -m file -a "path=/tmp/fstab state=absent"
        ansible test -m file -a "path=/tmp/test state=touch"

4. copy: 把主控端的文件复制到远程主机
    相关选项如下:
    backup:在覆盖之前,将源文件备份,备份文件包含时间信息。有两个选项:yes|no
    content:用于替代“src”,可以直接设定指定文件的值
    dest:必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录
    directory_mode:递归设定目录的权限,默认为系统默认权限
    force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes
    others:所有的file模块里的选项都可以在这里使用
    src:被复制到远程主机的本地文件,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用“/”来结尾,则只复制目录里的内容,如果没有使用“/”来结尾,则包含目录在内的整个内容全部复制,类似于rsync
   示例如下:
    ansible test -m copy -a "src=/srv/myfiles/foo.conf dest=/etc/foo.conf owner=foo group=foo mode=0644"
    ansible test -m copy -a "src=/mine/ntp.conf dest=/etc/ntp.conf owner=root group=root mode=644 backup=yes"

5.service模块:用于管理服务
该模块包含如下选项: 
arguments:给命令行提供一些选项 
enabled:是否开机启动 yes|no
name:必选项,服务名称 
pattern:定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行
runlevel:运行级别
sleep:如果执行了restarted,在则stop和start之间沉睡几秒钟
state:对当前服务执行启动,停止、重启、重新加载等操作(started,stopped,restarted,reloaded)

使用示例:
    ansible test -m service -a "name=httpd state=started enabled=yes"
    asnible test -m service -a "name=foo pattern=/usr/bin/foo state=started"
    ansible test -m service -a "name=network state=restarted args=eth0" 

6.cron模块:用于管理计划任务
包含如下选项: 
backup:对远程主机上的原任务计划内容修改之前做备份 
cron_file:如果指定该选项,则用该文件替换远程主机上的cron.d目录下的用户的任务计划 
day:日(1-31,*,*/2,……) 
hour:小时(0-23,*,*/2,……)  
minute:分钟(0-59,*,*/2,……) 
month:月(1-12,*,*/2,……) 
weekday:周(0-7,*,……)
job:要执行的任务,依赖于state=present 
name:该任务的描述 
special_time:指定什么时候执行,参数:reboot,yearly,annually,monthly,weekly,daily,hourly 
state:确认该任务计划是创建还是删除 
user:以哪个用户的身份执行

示例:
    ansible test -m cron -a 'name="a job for reboot" special_time=reboot job="/some/job.sh"'
    ansible test -m cron -a 'name="yum autoupdate" weekday="2" minute=0 hour=12 user="root
    ansible test -m cron  -a 'backup="True" name="test" minute="0" hour="5,2" job="ls -alh > /dev/null"'
    ansilbe test -m cron -a 'cron_file=ansible_yum-autoupdate state=absent'


7.yum模块:使用yum包管理器来管理软件包
其选项有: 
config_file:yum的配置文件 
disable_gpg_check:关闭gpg_check 
disablerepo:不启用某个源 
enablerepo:启用某个源
name:要进行操作的软件包的名字,也可以传递一个url或者一个本地的rpm包的路径 
state:状态(present,absent,latest)

示例如下:
    ansible test -m yum -a 'name=httpd state=latest'
    ansible test -m yum -a 'name="@Development tools" state=present'
    ansible test -m yum -a 'name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present'

8.user模块与group模块
user模块是请求的是useradd, userdel, usermod三个指令,goup模块请求的是groupadd, groupdel, groupmod 三个指令。

user模块
home:指定用户的家目录,需要与createhome配合使用
groups:指定用户的属组
uid:指定用的uid
password:指定用户的密码
name:指定用户名
createhome:是否创建家目录 yes|no
system:是否为系统用户
remove:当state=absent时,remove=yes则表示连同家目录一起删除,等价于userdel -r
state:是创建还是删除
shell:指定用户的shell环境

group示例
ansible all -m group -a 'name=somegroup state=present'

9. shell: shell命令
    ansible默认使用的模块是command,支持多数shell命令,但不支持shell变量及管道,如果要使用,用shell模块

批量部署JDK+Tomcat+Jenkins

将Jdk、Tomcat、Jenkins的安装包上传到ansbile控制节点的/usr/src下
[root@ansible ansible]# ls /usr/src/

[root@java-server ansible]# head -2 /usr/src/startup.sh 	//startup.sh是tomcat的启动脚本
#!/bin/sh
source /etc/profile    #加上此行,是为了启动加载到环境变量
变量文件
[root@ansible ansible]# cat /etc/ansible/vars/file.yml

下面是剧本

[root@ansible ansible]# cat jenkins.yml
- hosts: ansible-web1
  user: root
  vars_files:
  - /etc/ansible/vars/file.yml
  tasks:
##配置JDK,上传jdk、tomcat的安装包到/usr/src
  - name: configure JDK1.8
    copy: src={{ src_jdk_path }}  dest={{ dest_jdk_path }}
  - name: unzip JDK
    shell: tar -xvzf /usr/src/jdk-8u211-linux-x64.tar.gz -C /usr/local
  - name: rename to java
    shell: mv /usr/local/jdk1.8.0_211 /usr/local/java
  - name: configure JDK envirement1
    shell: echo "JAVA_HOME=/usr/local/java" >> /etc/profile
  - name: configure JDK envirement2
    shell: echo 'PATH=$JAVA_HOME/bin:$PATH' >> /etc/profile
##Tomcat
  - name: copy tomcat
    copy: src={{ src_tomcat_path }} dest={{ dest_tomcat_path }}
  - name: unzip tomcat
    shell: tar -xvzf /usr/src/apache-tomcat-8.5.45.tar.gz -C /usr/local
  - name: rename to tomcat
    shell: mv /usr/local/apache-tomcat-8.5.45 /usr/local/tomcat
  - name: copy startup file
    copy: src=/usr/src/startup.sh dest=/usr/local/tomcat/bin
##Jenkins
  - name: copy jenkins
    copy: src=/usr/src/jenkins.war  dest=/usr/local/tomcat/webapps/
    notify: start jenkins
  handlers:
  - name: start jenkins
    shell: nohup /usr/local/tomcat/bin/startup.sh &

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值