python -- 自动化运维工具ansible(大全)_python ansible

southeast
northeast
southwest
northwest


**3.5、给每个主机选择连接类型和连接用户名**



[targets]
localhost ansible_connection=local
other.example.com other.example.com=ssh ansible_ssh_user=test
other2.example.com other2.example.com=ssh ansible_ssh_user=test2


**3.6、设置inventory参数**  
 通过设置inventory参数,可以控制Ansible与远程主机的交互方式



ansible_ssh_host # 如果将要连接的远程主机名与你想要设定的主机的别名不同的话,可以通过此变量来控制

ansible_ssh_port # ssh的端口号,如果不是默认端口号,就通过此变量来设置

ansible_ssh_user # 默认ssh的用户名

ansible_pass # ssh的密码(这种方式不建议,很不安全,建议使用秘钥)

ansible_sudo_pass # sudo的密码(建议使用 --ask-sudo-pass)

ansible_sudo_exe # sudo的命令路径

ansible_connection # 与主机连接的类型。比如:local,ssh 或者 parmaiko

ansible_ssh_private_key_file # ssh 使用的私钥文件,适用于有多个密钥,而你不想使用ssh代理的情况下

ansible_shell_type # 目标系统的shell类型,默认情况下使用“sh”,也可以设置成"csh"或"fish"

ansible_python_interpreter # 目标主机python的路径,使用情况:系统中有多个python,或者路径不是/usr/bin/python等

-------------------------以下是一个主机文件示例-----------------------

some_host absible_ssh_port=2222 ansible_ssh_user=test1
one_host absible_ssh_port=2222 ansible_ssh_user=test2


## 三、上传秘钥


**秘钥上传前**


* 返回的信息是false,ping测试不成功



[root@localhost ~]# ansible master -m ping
192.168.10.10 | UNREACHABLE! => {
“changed”: false,
“msg”: “Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).”,
“unreachable”: true
}


**可以加上–ask-pass来手动输入密码**


* 这时候ping成功了,但是这样很麻烦



[root@localhost ~]# ansible master -m “ping” --ask-pass
SSH password: # 输入密码
192.168.10.10 | SUCCESS => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: false,
“ping”: “pong”
}


**上传秘钥**



生成秘钥

[root@localhost ~]# ssh-keygen -t rsa
……省略部分
±–[RSA 2048]----+
| ++=Eo |
|oo…= |
| o… . . |
| o * = . |
| = + * S |
| . * . |
|. +.*… . |
| =*=+= o. o |
| .=@=o=…o |
±—[SHA256]-----+

查看公钥文件

[root@localhost ~]# ls -ltr /root/.ssh/
总用量 12
-rw-r–r–. 1 root root 396 5月 23 19:23 id_rsa.pub
-rw-------. 1 root root 1679 5月 23 19:23 id_rsa
-rw-r–r–. 1 root root 175 5月 23 19:24 known_hosts

上传公钥

[root@localhost ~]# ansible all -m authorized_key -a “user=root key=‘{{lookup(‘file’, ‘/root/.ssh/id_rsa.pub’)}}’ path=/root/.ssh/id_rsa.pub manage_dir=yes” --ask-pass
SSH password:
192.168.10.10 | CHANGED => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: true,
“comment”: null,
“exclusive”: false,
“follow”: false,
“gid”: 0,
“group”: “root”,
“key”: “ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDmZ3VmXIZRL2W2INKz8iZV/DBLcfyoPhciAQKJJKLNdpKDcHwsT33WgDioVunk1qgwPVi79PZZtl/4sSmo1ZJt1sQ4W37Y9a8ad4jMuQW2JhD/TWfYFKsQgisgSE9YgdTkEZv7T5/Fuqpa0RgblLnqZ0pv3Kb/OweHZIWsieVGZ9pom+MQ3f06mngPRpQIxCDiUHdoAvCRCvk3TXMbggOhg2R8BpZLmPzbu8rR9UOEezT03+nS3gQGuhtJvz3iOBEqLgN80FtsLBm812Vbxjj97ZCu+Dc8kMhtwaOs/GZtH3IMACmAd5chj4ZJomV1EY22eWPslRuceIGOv9QovALT root@localhost”,
“key_options”: null,
“keyfile”: “/root/.ssh/id_rsa.pub”,
“manage_dir”: true,
“mode”: “0600”,
“owner”: “root”,
“path”: “/root/.ssh/id_rsa.pub”,
“size”: 396,
“state”: “file”,
“uid”: 0,
“user”: “root”,
“validate_certs”: true
}

测试是否已实现免密

[root@localhost ~]# ansible all -m ping
192.168.10.10 | SUCCESS => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: false,
“ping”: “pong”
}


## 四、ansible ad-hoc模式


### 1. 查看分组主机列表



[root@localhost ~]# ansible 分组名 --list-hosts ##查看分组中的主机列表
[root@localhost ~]# ansible work --list-host
hosts (40):
192.168.2.115
192.168.2.116
192.168.2.202
192.168.2.204
192.168.2.207
……


### 2. 生成秘钥代理



[root@localhost ~]# ssh-keygen -t rsa ##生成秘钥
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): ##直接回车
Enter passphrase (empty for no passphrase): ##输入密码123123
Enter same passphrase again: ##再次输入密码
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.

[root@localhost ~]# ssh-copy-id root@192.168.10.30

[root@localhost ~]# ssh-copy-id root@192.168.10.170 //配置密钥对验证
------------免交互代理--------------(设置代理可以让主机不要再输入密码)
ssh-agent bash ## 开启代理功能
ssh-add ## 添加秘钥给代理


### 3. ansible 命令模板



ansible-doc -l # 列出所有已安装的模块 注:按q退出
ansible-doc -s yum #-s列出yum模块描述信息和操作动作

-m:指定模块;-a:指定参数(如-m command:指定命令模块;-a date:命令模块参数为date,相当于在对方执行了date命令)

------------------ ansible指定ip执行命令 ----------------
方法1:
[root@localhost ~]# ansible all -i “IP地址,” -m shell -a “free -m”

方法2:
[root@localhost ~]# ansible ip地址 -m command -a ‘date’

----------------- ansible指定分组批量执行命令 -----------
[root@localhost ~]# ansible 分组名 -m command -a ‘date’


#### 3.1 、command模块 (执行命令,是默认模块)



> 
> 命令格式:ansible [主机] [-m 模块] [-a args]
> 
> 
> 



ansible mysql -m command -a ‘date’
ansible all -m command -a ‘date’ //所有hosts主机执行date命令
ansible all -a ‘ls /’ ##如果不加-m模块,则默认运行command模块,all:表示所有的分类

报错信息:“changed”: false,

[root@localhost ~]# ansible all -a ‘ls /’
192.168.10.30 | UNREACHABLE! => {
“changed”: false,
“msg”: “Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).”,
“unreachable”: true
}
192.168.10.170 | UNREACHABLE! => {
“changed”: false,
“msg”: “Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).”,
“unreachable”: true
}
报错原因:ssh秘钥错误
ssh-keygen -t rsa ##生成秘钥
ssh-copy-id root@192.168.10.30
ssh-copy-id root@192.168.10.170 //配置密钥对验证
ssh-agent bash ##开启代理功能
ssh-add ##添加秘钥给代理
########################################################################


#### 3.2、cron模块(设置计划任务)



两种状态(state):present表示添加(可以省略),absent表示移除
[root@localhost ~]# ansible-doc -s cron # 查看cron模块信息,帮助文档

[root@localhost ~]# ansible webserver -m cron -a ‘minute=“*/1” job=“/usr/bin/echo heihei” name=“test cron job”’

选项解释:

-m:指定模块;

-a:指定参数;minute=“*/1”:表示每分钟执行计划任务;

job=“/bin/echo heihei”:表示执行echo的动作;

最后name表示定义的计划任务的名称(自定义)

[root@localhost ~]# ansible webserver -a ‘crontab -l’ # 查看设置的计划任务
192.168.10.30 | CHANGED | rc=0 >>
#Ansible: test cron job
*/1 * * * * /usr/bin/echo heihei

[root@localhost ~]# crontab -l # 去192.168.10.30(即webserver)上查看计划任务
#Ansible: test cron job
*/1 * * * * /usr/bin/echo heihei # 可以查看到计划任务
You have new mail in /var/spool/mail/root # 执行的结果生成在/var/spool/mail/root文件内

[root@localhost ~]# ansible webserver -m cron -a ‘name=“test cron job” state=absent’ //指定计划任务名称,结合state=absent参数,移除计划任务

[root@localhost ~]# ansible webserver -a ‘crontab -l’ # 再次查看,计划任务消失了
192.168.10.30 | CHANGED | rc=0 >>


#### 3.3、user模块(用户操作)



user模块是请求的是useradd,userdel,usermod三个指令

[root@localhost ~]# ansible-doc -s user # 查看user模块参数说明
[root@localhost ~]# ansible mysql -m user -a ‘name=“test01”’ # 创建用户test01

[root@localhost ~]# id test01 # 到192.168.10.170(即mysql上)查看用户是否建立
uid=1001(test01) gid=1001(test01) 组=1001(test01)

[root@localhost ~]# ansible mysql -m command -a ‘tail -1 /etc/passwd’ # 同样可以查看到新用户test01
192.168.10.170 | CHANGED | rc=0 >>
test01❌1001:1001::/home/test01:/bin/bash

[root@localhost ~]# ansible mysql -m user -a ‘name=“test01” state=absent’ # 删除用户test01,state=absent参数用于删除


#### 3.4、group模块(用户组操作)



group模块请求的是groupadd,groupdel,groupmod 三个指令。

[root@localhost ~]# ansible-doc -s group # 查看group模块参数说明

[root@localhost ~]# ansible mysql -m group -a ‘name=mysql gid=306 system=yes’ # 创建用户组mysql,指定uid,system=yes代表创建的是系统组

[root@localhost ~]# ansible mysql -a ‘tail -1 /etc/group’ # 查看到新建的用户组
192.168.10.170 | CHANGED | rc=0 >>
mysql❌306:

[root@localhost ~]# ansible mysql -m user -a ‘name=test01 uid=306 system=yes group=mysql’ # 创建test01用户,指定uid,和ground组名,添加到mysql组

[root@localhost ~]# ansible mysql -a ‘tail -1 /etc/passwd’ # 查看,mysql组中多了test01用户成员
192.168.10.170 | CHANGED | rc=0 >>
test01❌306:306::/home/test01:/bin/bash

[root@localhost ~]# ansible mysql -a ‘id test01’ # 查看test01用户,标明了所在组
192.168.10.170 | CHANGED | rc=0 >>
uid=306(test01) gid=306(mysql) groups=306(mysql)


#### 3.5、copy模块(复制目录或文件)



[root@localhost ~]# ansible-doc -s copy # 查看copy模块参数说明

[root@localhost ~]# ansible mysql -m copy -a ‘src=/etc/fstab dest=/opt/fstab.back owner=root mode=640’

参数解释:

src:源文件(被copy的文件);

dest:目标文件;

owner:属主属性;

mode:文件权限属性

[root@localhost ~]# ansible mysql -a ‘ls -l /opt’ # 查看copy过去的文件,属主root,权限640
192.168.10.170 | CHANGED | rc=0 >>
total 4
-rw-r-----. 1 root root 465 Nov 29 22:34 fstab.back

[root@localhost ~]# ansible mysql -a ’ cat /opt/fstab.back’ # 查看内容

[root@localhost ~]# ansible mysql -m copy -a ‘content=“hello heihei !” dest=/opt/fstab.back’ # 将hello heihei!写入/opt/fstab.back

[root@localhost ~]# ansible mysql -a ‘cat /opt/fstab.back’ # 查看到写入的内容
192.168.10.170 | CHANGED | rc=0 >>
hello heihei !


#### 3.6、file模块(修改文件属性)



> 
> 1、修改文件属性, ansible all -m file -a “path=/root/test.sh owner=test group=test mode=0644”  
>  2、生成链接文件:ansible all -m file -a “src=/root/test.sh dest=/root/testlink.sh owner=root group=root state=link”  
>  3、创建空文件:ansible all -m file -a “path=/root/testtouch.sh state=touch mode=0644”  
>  4、创建空目录: ansible all -m file -a “path=/root/testdirectory state=directory mode=0644”  
>  5、删除目录或文件,强制执行:ansible all -m file -a “path=/root/testdirectory state=absent force=yes”
> 
> 
> 



[root@localhost ~]# ansible-doc -s file # 查看file模块参数说明

[root@localhost ~]# ansible mysql -m user -a ’ name=mysql system=yes’

[root@localhost ~]# ansible mysql -m group -a ’ name=mysql system=yes’

[root@localhost ~]# ansible mysql -m file -a ‘owner=mysql group=mysql mode=644 path=/opt/fstab.back’ # 修改文件属主、属组、权限

[root@localhost ~]# ansible mysql -m file -a ’ src=/opt/fstab.back path=/opt/fstab.link state=link’ # 给原文件/opt/fstab.back建立软连接,利用state=link参数

[root@localhost ~]# ansible mysql -m file -a “path=/opt/fstab.back state=absent” # 删除一个文件或目录

[root@localhost ~]# ansible mysql -m file -a “path=/opt/test state=touch” # 创建一个空文件

[root@localhost ltp]# ansible 192.168.2.100 -m file -a “name=/abc state=directory” # 创建一个目录


#### 3.7、ping模块(测试被管理主机是否在线)



[root@localhost ~]# ansible all -m ping ## ping所有分类
192.168.10.30 | SUCCESS => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: false,
“ping”: “pong” ## “pong” 表示能ping通
}
192.168.10.170 | SUCCESS => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: false,
“ping”: “pong”
}


#### 3.8、yum模块



[root@localhost ~]# ansible-doc -s yum # 查看模块帮助文档
[root@localhost ~]# ansible webserver -m yum -a ‘name=“httpd”’ //yum安装httpd服务

[root@localhost ~]# rpm -q httpd ##到192.168.10.20上查看,安装成功了
httpd-2.4.6-97.el7.centos.x86_64

[root@localhost ~]# ansible webserver -m yum -a ‘name=httpd state=absent’ //卸载httpd

[root@localhost ~]# rpm -q httpd ##再到192.168.10.20上查看,被卸载了
package httpd is not installed


#### 3.9、service模块(用于启动服务)



[root@localhost ~]# ansible-doc -s service

[root@localhost ~]# ansible webserver -m yum -a ‘name=“httpd”’

[root@localhost ~]# ansible webserver -a ‘systemctl status httpd’ // 查看web服务器httpd运行状态
192.168.10.30 | FAILED | rc=3 >>
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: man:httpd(8)
man:apachectl(8)non-zero return code

[root@localhost ~]# ansible webserver -m service -a ‘enabled=true name=httpd state=started’ //启动httpd服务,并且开机自启

[root@localhost ~]# ansible webserver -a ‘systemctl status httpd’ //查看是否开启,成功开启了
192.168.10.30 | CHANGED | rc=0 >>
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2020-11-29 23:30:11 CST; 8s ago
Docs: man:httpd(8)
man:apachectl(8)


#### 3.10、shell模块(执行shell命令)



[root@localhost ~]# ansible-doc -s shell

[root@localhost ~]# ansible webserver -m user -a ‘name=jack’ ##创建一个用户

[root@localhost ~]# ansible webserver -m shell -a ‘echo abc123 | passwd --stdin jack’ ##使用无交互模式给用户设置密码
192.168.10.30 | CHANGED | rc=0 >>
Changing password for user jack.
passwd: all authentication tokens updated successfully. ##免密设置成功


#### 3.11、script模块(本地先写脚本,利用ansible在控制主机上执行)



ansible-doc -s script

[root@localhost ~]# vim /opt/test.sh ##写一个脚本
#!/bin/bash
echo “hello ansible from script”> /opt/script.txt

[root@localhost ~]# chmod +x test.sh ##给执行权限

[root@localhost ~]# ansible mysql -m script -a ‘/opt/test.sh’ ##指定script模块和脚本位置,执行脚本

[root@localhost ~]# cat /opt/script.txt ##到192.168.10.170上查看,脚本是否执行成功
hello ansible from script


#### 3.12、setup模块 ( 获取主机信息 )



ansible-doc -s setup

ansible mysql -m setup //获取mysql组主机的facts信息(包含ip信息、版本信息等等)


## 五、Ansible playbooks 模式


* ansible-playbook剧本,可以更加灵活的配置部署不同的主机


#### 1. 查看ansible-playbook的帮助文档



[root@localhost ~]# ansible-playbook -h

usage: ansible-playbook [-h] [–version] [-v] [-k]
[–private-key PRIVATE_KEY_FILE] [-u REMOTE_USER]
[-c CONNECTION] [-T TIMEOUT]
[–ssh-common-args SSH_COMMON_ARGS]
[–sftp-extra-args SFTP_EXTRA_ARGS]
[–scp-extra-args SCP_EXTRA_ARGS]
[–ssh-extra-args SSH_EXTRA_ARGS] [–force-handlers]
[–flush-cache] [-b] [–become-method BECOME_METHOD]
[–become-user BECOME_USER] [-K] [-t TAGS]
[–skip-tags SKIP_TAGS] [-C] [–syntax-check] [-D]
[-i INVENTORY] [–list-hosts] [-l SUBSET]
[-e EXTRA_VARS] [–vault-id VAULT_IDS]
[–ask-vault-pass | --vault-password-file VAULT_PASSWORD_FILES]
[-f FORKS] [-M MODULE_PATH] [–list-tasks]
[–list-tags] [–step] [–start-at-task START_AT_TASK]
playbook [playbook …]

……


#### 2. 讲解playbook的yaml


* playbook是根据yaml语法格式的文件进行编写的
* 对于ansible来说,每一个yaml文件都是从一个列表开始,列表中的每一项都是一个键值对,通常被称为一个"哈希"或"字典"。
* 所有的yaml文件开始行都应该是"—",这是yaml格式的一部分,表明一个文件的开始。
* 列表中的所有成员都开始于相同的缩进级别了,并且使用一个"-“作为开头(一个横杠”-“和一个空格” ")




---


YAML支持的数据结构:



1.对象:键值对的集合,又称为映射(mapping)/哈希(hashes)/字
例如:
name: Example Developer
键 值

2.数组:一组按次序排列的值,又称为序列(sequence)/列表(list)
例如:

  • Apple
  • Orange

3.纯量:单个的、不可再分的值
例如:
number: 12.30
sure: true




---


yaml示例:




一个美味的水果列表

  • Apple
  • Oranage
  • Strawebrry
  • Mango

一个字典是由一个简单的 键: 值 的形式组成(注意:这个":"冒号后面必须是一个空格)




一个职工的记录

name: Example Developer
job: Developer
skill: Elite


字典也可以使用缩进形式来表示(这种格式在ansible中不经常使用)




一个职工记录

{name: Example Developer, job: Developer, skill: Elite}


可以通过下面格式指定一个布尔值




create_key: yes
need_agent: no
knows_oop: True
likes_emacs: TRUE
uses_cvs: False


示例:将上面的示例整合到一个yaml中




一个职工记录

name: Example Developer
job: Developer
skill: Elite
employed: True
foods:

  • Apple
  • Orange
  • Strawberry
  • Mango

相当于{foods:[Apple, Orange, Strawberry, Mango]}

languages:
ruby: Elite
python: Elite
dotnet: Lame

相当于{languages:{ruby: Elite, python: Elite, dotnet: Lame}}


#### 3. 尝试编写playbook.yaml


**playbooks本身由以下各部分组成**


* (1) Tasks:任务,即调用模块完成的某操作,执行了tasks,相当于执行了事务,一旦有一条失败,则进行回滚 ;
* (2) Variables:变量
* (3) Templates:模板
* (4) Handlers:处理器,当某条件满足时,触发执行的操作;
* (5) Roles:角色。




---


**示例1:**



[root@localhost ~]# cat /etc/ansible/hosts |grep -Ev “$|#”
[work]
master
node
[master]
192.168.10.10
[node]
192.168.10.20

[root@localhost ~]# vim MyPlaybook.yaml

  • shosts: master
    remote_user: root
    task:
    • name: read sys time
      shell: echo “$(date +‘%Y-%m-%d %T’)” > time.txt
  • hosts: slave
    remote_user: root
    task:
    • name: list file
      shell: ls -ltr > list.txt

执行结果:



[root@localhost ~]# ansible-playbook MyPlaybook.yaml --ask-pass
SSH password:

PLAY [master] ********************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [192.168.10.10]

TASK [read sys time] *************************************************************************************************
changed: [192.168.10.10]

PLAY [node] **********************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [192.168.10.20]

TASK [list file] *****************************************************************************************************
changed: [192.168.10.20]

PLAY RECAP ***********************************************************************************************************
192.168.10.10 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.10.20 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

查看执行后生成的文件

[root@localhost ~]# ansible all -m shell -a “ls -ltr |tail -1”
192.168.10.10 | CHANGED | rc=0 >>
-rw-r–r-- 1 root root 20 5月 23 21:14 time.txt
192.168.10.20 | CHANGED | rc=0 >>
-rw-r–r-- 1 root root 1051 5月 23 21:14 list.txt



> 
> -f :可以指定并发进程数  
>  例如:ansible-playbook MyPlaybook.yaml --ask-pass -f 3 # 表示由3个并发进程来执行
> 
> 
> 


**示例2**  
 下面是一个playbook的示例:



查看模板内容,模板中用{{变量名}}来调用playbook.yaml中的变量值,如下

[root@localhost temp]# vim httpd-temp.conf
Listen {{http_port}}
MaxClients {{max_clients}}
[root@localhost temp]# vim HttpPlaybook.yaml

  • hosts: node # 定义的主机组,即应用的主机,前面的(- hosts:)不能更改,指明在/etc/ansible/hsots中声明的组
    vars: # 定义变量
    http_port: 80
    max_clients: 200
    user: root # 在远程执行时建议使用remote_user远程用户
    tasks: # 执行的任务
    • name: ensure apache is at the latest version # 指定任务名称,会在执行任务时显示出来的内容(自定义),有利于定位错误发生位置
      yum: pkg=httpd state=latest # yum是模块,pkg指定检测软件包,state=latest是否为最新的
    • name: write the apache config file
      template: src=httpd-temp.conf dest=/etc/httpd/conf/httpd.conf # 定义配置文件模板
      notify: # 调用下面自定义的restart apache(restart apache在handlers中定义了具体内容)
      • restart apache
    • name: ensure apache is running
      service: name=httpd state=started
      handlers: # 处理器,当某条件满足时,触发执行的操作,和notify结合使用,被notify调用;
      • name: restart apache
        service: name=httpd state=restarted

执行结果:



[root@localhost temp]# ansible-playbook HttpPlaybook.yaml

PLAY [node] **********************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [192.168.10.20]

TASK [ensure apache is at the latest version] ************************************************************************
ok: [192.168.10.20]

TASK [write the apache config file] **********************************************************************************
ok: [192.168.10.20]

TASK [ensure apache is running] **************************************************************************************
changed: [192.168.10.20]

PLAY RECAP ***********************************************************************************************************
192.168.10.20 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

[root@localhost temp]# ansible node -m shell -a “systemctl status httpd”
192.168.10.20 | CHANGED | rc=0 >>
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: active (running) since 日 2021-05-23 21:30:07 CST; 21s ago
Docs: man:httpd(8)
man:apachectl(8)
Main PID: 7544 (httpd)
Status: “Total requests: 0; Current requests/sec: 0; Current traffic: 0 B/sec”
Memory: 3.3M
CGroup: /system.slice/httpd.service
├─7544 /usr/sbin/httpd -DFOREGROUND
├─7545 /usr/sbin/httpd -DFOREGROUND
├─7546 /usr/sbin/httpd -DFOREGROUND
├─7547 /usr/sbin/httpd -DFOREGROUND
├─7548 /usr/sbin/httpd -DFOREGROUND
└─7549 /usr/sbin/httpd -DFOREGROUND

5月 23 21:30:07 node01 systemd[1]: Starting The Apache HTTP Server…
5月 23 21:30:07 node01 httpd[7544]: AH00558: httpd: Could not reliably determine the server’s fully qualified domain name, using fe80::20c:29ff:fe47:c5d7. Set the ‘ServerName’ directive globally to suppress this message
5月 23 21:30:07 node01 systemd[1]: Started The Apache HTTP Server.


#### 4. ansible-playbook相关命令


执行一个playbook



> 
> 语法:ansible-playbook [yaml文件名]  
>  例如: ansible-playbook ping.yml  
>  参数:-k(-ask-pass):用来交互输入ssh密码  
>  -K(-ask-become-pass):用来交互输入sudo密码(提权)…  
>  -u:指定用户
> 
> 
> 


补充命令:



> 
> `# 检查yaml文件的语法`  
>  ansible-playbook nginx.yaml --syntax-check  
>  `# 检查tasks任务`  
>  ansible-playbook nginx. yaml --list-task  
>  `# 检查生效的主机`  
>  ansible-playbook nginx. yaml --list-hosts  
>  `# 指定playbook中的task执行,检查效果`  
>  ansible-playbook nginx.yaml --start-at-task=‘Copy Nginx.conf’  
>  `# 指定执行playbook的并行线程数`  
>  ansible-playbook nginx.yaml -f 线程数
> 
> 
> 


#### 5. hosts和users介绍



  • hosts: webserver # 指定主机组,可以是一个或多个组。
    remote_user: root # 指定远程主机执行的用户名,注意,用户一定要有执行权限



---


还可以为每个任务定义远程执行用户:



  • hosts: mysql
    remote_user: root
    tasks:
    -name: test connection
    ping:
    remote_user: mysql # 指定远程主机执行tasks的运行用远程指定的用户

执行playbook时: ansible-playbook ping. yml -k




---


指定远程主机sudo切换用户:



-hosts: mysql
remote_user: root
become: yes ## 2.6版本以后的参数,之前是sudo,意思相同
become_user: mysql ## 指定sudo用户为mysql,之后执行任务的用户就变为mysql了


执行playbook时 : ansible-playbook ping. yml -K




---


#### 6. tasks列表和action


1、Play的主体部分是task列表,task列表中的各任务按次序逐个在hosts中指定的主机上执行


* 在hosts中扌在运行playbook时(从上到下执行),如果一个host执行task失败,整个tasks都将回滚,请求修正playbook中的错误
* Task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量,模


2、每一个task必须有一个名称name,这样在运行playbook时,从其输出的任务执行信息中可以很好的辨别出是属于那一部分的任务


3、定义一个task,常见的格式:”module: options”是"模块对应参数"的形式,例如: yum: name=htttpd


4、ansible的自带模块中,command模块和shel1模块无需使用key=value格式




---


示例:



  • hosts: 192.168.10.20
    remote_user: root
    tasks:
    • name: disable selinux
      command: ‘/sbin/setenforce o’
    • name: make sure apache is running
      service: name=httpd state=started



---


playbook中只要执行命令的返回值不为0,就会报错,tasks停止  
 要想报错不停止执行tasks,修改如下 ignore\_errors: True



  • hosts: webserver
    remote_user: root
    tasks:
    • name: disable selinux
      command: ‘/sbin/setenforce 0’
      ignore_errors: True #忽略错误,强制返回成功,继续执行,true这个布尔值不区分大小写的
    • name: make sure apache is running
      service: name=httpd state=started

以下是另外一个示例,可以读一读



  • hosts: webserver
    remote_user: root
    tasks:
    • name: create nginx group
      group: name=nginx system=yes gid=208
    • name: create nginx user
      user: name=nginx uid=208 group=nginx system=yes
  • hosts: mysql
    remote_user: root
    tasks:
    • name: copy file to mysql
      copy : src=/etc/inittab dest=/opt/inittab.back

#### 7. Handlers介绍


* Handlers也是一些task的列表,和一般的task并没有什么区别。
* 是由通知者进行的notify,如果没有被notify,则Handlers不会执行,假如不管有多少个通知者进行了notify,等到play中的所有task执行完成之后,
* 只有当一个task中的动作action执行了,这个task中的notify才会生效,才会通知执行handler中的action




---


**示例1**



  • hosts: webserver
    remote_user: root
    tasks:
    • name: install httpd package
      yum: name=httpd state=latest
    • name: install configuration file for httpd
      copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf
      notify:
      • restart httpd
    • name: start httpd service
      service: enabled=true name=httpd state=started
      handlers:
    • name: restart httpd
      service: name=httpd state=restarted

**示例2:测试notify所在task执行失败,是否会继续执行notify**



[root@localhost temp]# vim testvarPlaybook.yaml

  • hosts: node
    remote_user: root
    vars: # 定义变量
    • path: /root/
    • filename: test.txt
      tasks:
    • name: delete file
      file: path=/root/test.txt state=absent
      ignore_errors: True
      notify:
      • modify file
        handlers:
    • name: modify file
      shell: echo “123” >{{path}}{{filename}}

* 若目标及其的root目录下不存在test.txt文件,"delete file"的任务无法执行成功。发现notify不会调用handler



目标及其没有test.txt文件

[root@localhost temp]# ansible node -m shell -a “cat test.txt”
192.168.10.20 | FAILED | rc=1 >>
cat: test.txt: 没有那个文件或目录non-zero return code

执行playbook

[root@localhost temp]# ansible-playbook testvarPlaybook.yaml
PLAY [node] **********************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [192.168.10.20]

TASK [delete file] ***************************************************************************************************
ok: [192.168.10.20]

PLAY RECAP ***********************************************************************************************************
192.168.10.20 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

再次查看,依旧没有test.txt文件

[root@localhost temp]# ansible node -m shell -a “cat test.txt”
192.168.10.20 | FAILED | rc=1 >>
cat: test.txt: 没有那个文件或目录non-zero return code


* 若目标机器的root目录下存在test.txt文件,"delete file"的任务能成功执行。发现notify调用的handler也执行了,修改了test.txt中内容



首先在目标机器上创建test.txt文件

[root@localhost temp]# ansible node -m file -a “path=/root/test.txt state=touch”
192.168.10.20 | CHANGED => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: true,
“dest”: “/root/test.txt”,
“gid”: 0,
“group”: “root”,
“mode”: “0644”,
“owner”: “root”,
“size”: 0,
“state”: “file”,
“uid”: 0
}

查看文件内容为空

[root@localhost temp]# ansible node -m shell -a “cat test.txt”
192.168.10.20 | CHANGED | rc=0 >>

执行playbook

[root@localhost temp]# ansible-playbook testvarPlaybook.yaml
PLAY [node] **********************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [192.168.10.20]

TASK [delete file] ***************************************************************************************************
changed: [192.168.10.20]

RUNNING HANDLER [modify file] ****************************************************************************************
changed: [192.168.10.20]

PLAY RECAP ***********************************************************************************************************
192.168.10.20 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

查看test.txt文件,handler的action被调用执行

[root@localhost temp]# ansible node -m shell -a “cat test.txt”
192.168.10.20 | CHANGED | rc=0 >>
123


#### 8.playbook引入变量


playbook使用变量的方法:  
 1、在yml文件中使用vars来设置变量  
 2、在/etc/ansible/hosts文件中主机名后面声明变量(如:变量username=lisi)  
 3、在执行ansible-playbook时,后面加上 -e 变量名=值 的方式给变量赋值;如 ansible-playbook test.yml -e “service=httpd”




---


示例1



  • hosts: webserver
    remote_user: root
    vars:
    • package: httpd
    • service: httpd
      tasks:
    • name: install httpd package
      yum: name={{package}} state=latest
    • name: install configuration file for httpd
      copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf
      notify:
      • restart httpd
    • name: start httpd service
      service: enabled=true name={{service}} state=started
      handlers:
    • name: restart httpd
      service: name={{service}} state=restarted

#### 9. 引用ansible的固定变量


示例



[root@localhost temp]# vi test.yml

  • hosts: node
    remote_user: root
    tasks:
    • name: copy filel

      {{ansible_all_ipv4_addresses}}是引用ip的固定变量

      copy: content=“{{ansible_all_ipv4_addresses}},” dest=/opt/iplist.txt

执行结果



[root@localhost temp]# ansible-playbook test.yaml

PLAY [node] **********************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [192.168.10.20]

TASK [copy filel] ****************************************************************************************************
changed: [192.168.10.20]

PLAY RECAP ***********************************************************************************************************
192.168.10.20 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

[root@localhost temp]# ansible node -m shell -a “cat /opt/iplist.txt”
192.168.10.20 | CHANGED | rc=0 >>
([u’192.168.122.1’, u’192.168.10.20’],)

查看目标机器ip,确实有192.168.122.1 和 192.168.10.20两个ip

[root@localhost temp]# ansible node -m shell -a “ip a”
192.168.10.20 | CHANGED | rc=0 >>
……
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:47:c5:d7 brd ff:ff:ff:ff:ff:ff
inet 192.168.10.20/24 brd 192.168.10.255 scope global ens33
……
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN qlen 1000
link/ether 52:54:00:13:da:e3 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
……


#### 10. 条件测试,条件判断


* 如果需要根据变量facts (setup)或此前任务的执行结果来作为某task执行依据,  
 可以在task后添加when子句,即可使用条件测试: when子句支持jinjia2表达式或


##### 10.1、单条件判断



[root@localhost temp]# vim test.yaml

  • hosts: node
    remote_user: root
    tasks:
    • name: “look os”
      shell: echo {{ansible_distribution}} >os.txt
      when: ansible_distribution == “CentOS”

执行结果



[root@localhost temp]# ansible-playbook test.yaml

PLAY [node] **********************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [192.168.10.20]

TASK [look os] *******************************************************************************************************
changed: [192.168.10.20]

PLAY RECAP ***********************************************************************************************************
192.168.10.20 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

查看os.txt文件

[root@localhost temp]# ansible node -m shell -a “cat os.txt”
192.168.10.20 | CHANGED | rc=0 >>
CentOS


##### 10.2、多条件判断



[root@localhost temp]# cat test.yaml

  • hosts: node
    remote_user: root
    tasks:
    • name: “look os”
      shell: echo “{{ansible_distribution}}.{{ansible_distribution_major_version}}” >os.txt
      when:
      • ansible_distribution == “CentOS”
      • ansible_distribution_major_version == “7”

执行结果



[root@localhost temp]# ansible-playbook test.yaml
PLAY [node] **********************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [192.168.10.20]

TASK [look os] *******************************************************************************************************
changed: [192.168.10.20]

PLAY RECAP ***********************************************************************************************************
192.168.10.20 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

[root@localhost temp]# ansible node -m shell -a “cat os.txt”
192.168.10.20 | CHANGED | rc=0 >>
CentOS.7


##### 10.3、组条件判断



[root@localhost temp]# cat test.yaml

  • hosts: node
    remote_user: root
    tasks:
    • name: “look os”
      shell: echo “{{ansible_distribution}}.{{ansible_distribution_major_version}}” >os.txt
      when: (ansible_distribution == “CentOS” and ansible_distribution_major_version == “7”) or (ansible_distribution == “CentOS” and ansible_distribution_major_version == “6”)

满足系统为centos且为6版本,或者系统文centos且是6版本,则执行命令


执行结果



[root@localhost temp]# ansible-playbook test.yaml

PLAY [node] **********************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [192.168.10.20]

TASK [look os] *******************************************************************************************************
changed: [192.168.10.20]

PLAY RECAP ***********************************************************************************************************
192.168.10.20 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

[root@localhost temp]# ansible node -m shell -a “cat os.txt”
192.168.10.20 | CHANGED | rc=0 >>
CentOS.7


##### 10.4、自定义变量进行条件测试



[root@localhost temp]# vi test.yaml

  • hosts: node
    remote_user: root
    vars:
    msg: ‘hellow world’
    exist: True
    flag: None
    tasks:
    • name: “existed file”
      shell: rm -rf os.txt
      when:
      • exist == False
    • name: ‘look file’
      shell: echo “{{msg}}” >os.txt
      when: flag == “None”

执行结果



[root@localhost temp]# ansible-playbook test.yaml

PLAY [node] **********************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [192.168.10.20]

TASK [existed file] **************************************************************************************************
skipping: [192.168.10.20]

TASK [look file] *****************************************************************************************************
changed: [192.168.10.20]

PLAY RECAP ***********************************************************************************************************
192.168.10.20 : ok=2 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

[root@localhost temp]# ansible node -m shell -a “cat os.txt”
192.168.10.20 | CHANGED | rc=0 >>
hellow world


#### 11、迭代


* 当有需要重复性执行的任务时,可以使用迭代机制。
* 迭代器,类似于for循环,依次执行


##### 11.1、直接调用item迭代器



[root@localhost temp]# vim test.yaml

  • hosts: node
    remote_user: root
    vars:
    path: /ltp/
    msg: “hellow world”
    tasks:
    • name: “Save Msg”
      shell: echo {{msg}} > {{path}}{{item}} # 固定变量item,值为下面with_items:下的参数,遍历执行
      with_items: # 定义了item的值
      • first.txt
      • second.txt
      • third.txt
        register: shell_result # registe用于储存执行结果,调试阶段使用,利用下面的debug返回结果
    • debug: var=shell_result.stdout verbosity=0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值