作用:用户复杂的任务处理,以及要管理经常要完成的任务。
playbook也是通过模块和它的参数,在特定主机上执行任务
playbook是一个文件,该文件中需要通过yaml格式进行书写
yaml语法规范
- yaml文件的文件名,一般以yml或yaml作为扩展名
- 文件一般以---作为第一行,不是必须的,但是常用
- 键值对使用冒号:表示,冒号后面必须有空格。
- 数组使用-表示,-后面必须有空格。
- 相同的层级必须有相同的缩进。如果缩进不对,则有语法错误。每一级缩进,建议2个空格。
- 全文不能使用tab,必须使用空格。
环境准备:
1.配置vim适应yaml语法
vim ~/.vimrc
set ai #设置自动缩进
set ts=2 #设置按tab键为两个空格
ser et #将tab转换成相应个数的空格
set cursorcolumn #能看到对齐
:wq
编写playbook使用方式
1.一个剧本可以有多个play
2.每个play用于指定主机上,通过模块和参数执行相应的任务
3.每个play可以包含多个任务
4.任务由模块和参数构成
#编写用于测试连通性的playbook,相当于执行ansible all -m ping
vim test01.yml
---
- name: test network # play的名字,可选项
host: all # 作用于所有的主机
task: # 任务
- name: test ping # 第1个任务的名字,可选项
ping: # 第1个任务使用的模块
ansible-playbook test01.yml
# 在dbs组的主机和web1上创建/tmp/demo目录,权限是0755。将控制端/etc/hosts拷贝到目标主机的/tmp/demo中
vim test02.yml
---
- name: cteate directory and copy file
hosts: dbs,web1 # 这里的名称,必须出现在主机清单文件中
tasks:
- name: create dir
file:
path: /tmp/demo
mode:0755
state: directory
- name: copy file
copy:
src: /etc/hosts
dest: /tmp/demo/hosts
ansible-playbook test02.yml
# 在webservers组中的主机上,创建用户bob,附加组是adm;在db1主机上,创建/tmp/hi.txt,其内容为Hello World.
vim test03.yml
---
- name: create user
hosts: webservers
tasks:
- name: create bob
user:
name: bob
groups: adm
- name: create file
hosts: db1
- name: make file
copy:
dest: /tmp/hi.txt
content: "Hello World"
ansible-playbook test03.yml
补充知识:
| 保留换行符
> 把多行合并成一行
# 通过copy模块创建/tmp/1.txt,文件中有两行内容,分别是Hello World和ni hao
vim test04.yml
---
- name: play1
hosts: webservers
tasks:
- name: mkfile
copy:
dest: /tmp/1.txt
content: |
Hello World
ni hao
执行成功后,在webservers组的主机中查看结果
# 在webservers组中的主机上创建john用户,它的uid是1040,主组是daemon,密码为123
vim test04.txt
---
- name: create user
hosts: websevers
tasks:
- name: create user jhon
user:
name: jhon
uid: 1040
group: daemon
passwoed: "{{'123' | password_hash('sha512')}}"
# 在webservers组中的主机上创建john用户,它的uid是1040,主组是daemon,密码为123
[root@pubserver ansible]# vim user_john.yml
---
- name: create user
hosts: webservers
tasks:
- name: create user john
user:
name: john
uid: 1040
group: daemon
password: "{{'123'|password_hash('sha512')}}"
[root@pubserver ansible]# ansible-playbook user_john.yml
# 在webservers组中的主机上删除用户john
[root@pubserver ansible]# vim del_john.yml
---
- name: delete user
hosts: webservers
tasks:
- name: delete user john
user:
name: john
state: absent
[root@pubserver ansible]# ansible-playbook del_john.yml
硬盘管理
常用的分区表类型有:MBR(主引导记录)、GPT(GUID分区表)
MBR最多支持4个主分区,或3个主分区加1个扩展分区。最大支持2.2TB左右的硬盘
GPT最多支持128个主分区。支持大硬盘
parted模块:
用于硬盘分区管理
常用选项:
- device:待分区的设备
- number:分区编号
- state:present表示创建,absent表示删除
- part_start:分区的起始位置,不写表示从开头
- part_end:表示分区的结束位置,不写表示到结尾
# 在web1主机上,对/dev/vdc进行分区,创建1个1GB的主分区
---
- name: disk mange
hosts: web1
tasks:
- name: create a partition
parted:
device: /dev/vdc
number: 1
state: present
part_end: 1GiB
执行成功后进web1主机通过 lsblk 查看结果
# 继续编辑disk.yml,对/dev/vdc进行分区,创建1个新的5GB的主分区
....
- name: create a new
parted:
device: /dev/vdc
number: 2
state: present
part_start: 1GiB
parted_end: 6GiB
执行成功后进web1主机通过 lsblk 查看结果
容量的大是结束位置减去起始位置的结果
继续编辑disk.yml,创建名为my_vg的卷组,它由上面创建的vdc1和vdc2构成
继续编辑disk.yml,在my_vg卷组上创建名为my_lv的逻辑卷,大小1G
继续编辑disk.yml,格式化my_lv为ext4
继续编辑disk.yml,将my_lv挂载到/data
---
- name: disk manage
hosts: web1
tasks:
- name: create a partition
parted:
device: /dev/vdc
number: 1
state: present
part_end: 1GiB
- name: add a new partition
parted:
device: /dev/vdc
number: 2
state: present
part_start: 1GiB
part_end: 6GiB
- name: create my_vg
lvg:
vg: my_vg
pvs: /dev/vdc1,/dev/vdc2
- name: create my_lv
lvol:
vg: my_vg
lv: my_lv
size: 1G
- name: mkfs my_lv
filesystem:
dev: /dev/my_vg/my_lv
fstype: ext4
- name: mount my_lv
mount:
path: /data
src: /dev/my_vg/my_lv
fstype: ext4
state: mounted
根据功能等,可以将一系列软件放到一个组中,安装软件包组,将会把很多软件一起安装上。比如gcc、java等都是开发工具,安装开发工具包组,将会把它们一起安装。
yum grouplist # 列出所有的软件包组
yum groupinstall "Development Tools"
# 如果列出的组名为中文,可以这样进行:
LANG=C yum grouplist
---
- name: install pkgs
hosts: webservers
tasks:
- name: install web pkgs # 此任务通过yum安装三个包
yum:
name:
- httpd
- php
- php-mysqlnd
state: present
- name: install dev group # 此任务通过yum安装一组包
yum:
name: "@Development Tools" # @表示后面的名字是组名
state: present
- name: update system # 相当于yum update命令
yum:
name: "*" # 表示系统已经安装的所有包
state: latest
facts变量
facts变量是ansible自带的预定义变量,用于描述被控端软硬件信息。
facts变量通过setup模块获得。
通过setup模块查看所有facts变量
ansible webservers -m setup
- acts变量是一个大的由{}构成的键值对字典。在{}中,有很多层级的嵌套。可以通过参数过滤出第一个层级的内容。
ansible webservers -m setup -a "filter=ansible_all_ipv4_addresses"
查看所有的IPV4地址,filter是过滤的意思
ansible webservers -m setup -a "filter=ansible_memfree_mb"
# 查看可用内存
常用的facts变量
ansible_all_ipv4_addresses:所有的IPV4地址
ansible_bios_version:BIOS版本信息
ansible_memtotal_mb:总内存大小
ansible_hostname:主机名
在playbook中使用变量 debug模块用于输出信息,常用的参数是msg,用于输出指定内容
# 显示远程主机的主机名和内存大小。在ansible中,变量使用{{}}表示
# debug模块用于输出信息,常用的参数是msg,用于输出指定内容
---
- name: display host info
hosts: webservers
tasks:
- name: display hostname and memory
debug: # debug是模块,它的选项msg可以输出指定信息
msg: "hostname: {{ansible_hostname}}; mem: {{ansible_memtotal_mb}} MB"
# 显示远程主机的主机名和内存大小。在ansible中,变量使用{{}}表示
# debug模块用于输出信息,常用的参数是msg,用于输出指定内容
[root@pubserver ansible]# vim debug.yml
---
- name: display host info
hosts: webservers
tasks:
- name: display hostname and memory
debug: # debug是模块,它的选项msg可以输出指定信息
msg: "hostname: {{ansible_hostname}}; mem: {{ansible_memtotal_mb}} MB"
[root@pubserver ansible]# ansible-playbook debug.yml
找对应数据的方法:
ansible web1 -m setup | less 搜寻对应的数据后,单词以ansible开头,找到对应的值后,往上找到最上一级的以ansible开头。语法:通过.调用子键,eg :ansible_eth0.ipv4.address
# 配置nginx服务
[root@pubserver ansible]# vim firewall.yml
---
- name: configure webservers
hosts: webservers
tasks:
- name: install nginx pkg # 这里通过yum模块装httpd
yum:
name: nginx
state: present
- name: start nginx service # 这里通过service模块启httpd服务
service:
name: nginx
state: started
enabled: yes
[root@pubserver ansible]# ansible-playbook firewall.yml
[root@pubserver ansible]# curl http://192.168.88.11/ # 可访问
# 安装并启动firewalld
[root@pubserver ansible]# vim firewall.yml
---
- name: configure webservers
hosts: webservers
tasks:
- name: install nginx pkg # 这里通过yum模块装httpd
yum:
name: nginx
state: present
- name: start nginx service # 这里通过service模块启httpd服务
service:
name: nginx
state: started
enabled: yes
- name: install firewalld pkg # 这里通过yum模块装firewalld
yum:
name: firewalld
state: present
- name: start firewalld service # 这里通过service模块启firewalld服务
service:
name: firewalld
state: started
enabled: yes
[root@pubserver ansible]# ansible-playbook firewall.yml
[root@pubserver ansible]# curl http://192.168.88.11/ # 被拒绝
curl: (7) Failed to connect to 192.168.88.11 port 80: 没有到主机的路由
# 配置防火墙规则,放行http协议
[root@pubserver ansible]# vim firewall.yml
---
- name: configure webservers
hosts: webservers
tasks:
- name: install nginx pkg # 这里通过yum模块装httpd
yum:
name: nginx
state: present
- name: start nginx service # 这里通过service模块启httpd服务
service:
name: nginx
state: started
enabled: yes
- name: install firewalld pkg # 这里通过yum模块安装firewalld
yum:
name: firewalld
state: present
- name: start firewalld service # 这里通过service模块启service服务
service:
name: firewalld
state: started
enabled: yes
- name: set firewalld rules # 通过firewalld模块开放80端口
firewalld:
port: 80/tcp
permanent: yes
immediate: yes
state: enabled
[root@pubserver ansible]# ansible-playbook firewall.yml
[root@pubserver ansible]# curl http://192.168.88.11/ # 可访问
template模块
- copy模块可以上传文件,但是文件内容固定
- template模块可以上传具有特定格式的文件(如文件中包含变量)
- 当远程主机接收到文件之后,文件中的变量将会变成具体的值
- template模块上传的文件,使用的语法叫Jinja2。
- 常用选项:
-
- src:要上传的文件
- dest:目标文件路径
# 使用template模块将含有变量的文件上传到webservers组中的主机
[root@pubserver ansible]# vim index.html
Welcome to {{ansible_hostname}} on {{ansible_eth0.ipv4.address}}
[root@pubserver ansible]# vim templ.yml
---
- name: upload index
hosts: webservers
tasks:
- name: create web index
template:
src: index.html
dest: /usr/share/nginx/html/index.html
[root@pubserver ansible]# ansible-playbook templ.yml
[root@pubserver ansible]# curl http://192.168.88.11/
Welcome to web1 on 192.168.88.11
[root@pubserver ansible]# curl http://192.168.88.12
Welcome to web2 on 192.168.88.12
[root@web1 ~]# cat /usr/share/nginx/html/index.html
Welcome to web1 on 192.168.88.11
[root@web2 ~]# cat /usr/share/nginx/html/index.html
Welcome to web2 on 192.168.88.12
进阶语法
错误处理
- 默认:当Playbook中包含很多任务时,没有由上而下执行,当某一个任务遇到错误,它将崩溃,终止执行后续任务
# 在webservers组中的主机上启动mysqld服务,然后创建/tmp/service.txt
# 因为目标主机上没有mysqld服务,所以它将崩溃,终止执行。即,不会创建/tmp/service.txt文件
[root@pubserver ansible]# vim myerr.yml
---
- name: my errors
hosts: webservers
tasks:
- name: start mysqld service # 通过service模块启动mysqld服务
service:
name: mysqld
state: started
enabled: yes
- name: touch a file # 通过file模块创建文件
file:
path: /tmp/service.txt
state: touch
# 执行playbook,第1个任务就会失败
[root@pubserver ansible]# ansible-playbook myerr.yml
# 到node1上查看,因为第2个任务没有执行,所以文件不会创建
[root@web1 ~]# ls /tmp/service.txt
ls: cannot access '/tmp/service.txt': No such file or directory
- 可以指定某一个任务如果出现错误,则忽略它
# 编辑myerr.yml,如果myslqd服务无法启动,则忽略它
[root@pubserver ansible]# vim myerr.yml
---
- name: my errors
hosts: webservers
tasks:
- name: start mysqld service
service:
name: mysqld
state: started
enabled: yes
ignore_errors: yes # 即使这个任务失败了,也要继续执行下去
- name: touch a file
file:
path: /tmp/service.txt
state: touch
[root@pubserver ansible]# ansible-playbook myerr.yml
[root@web1 ~]# ls /tmp/service.txt # 第2个任务已执行
/tmp/service.txt
- 通过全局设置,无论哪个任务出现问题,都要忽略
[root@pubserver ansible]# vim myerr.yml
---
- name: my errors
hosts: webservers
ignore_errors: yes
tasks:
- name: start mysqld service
service:
name: mysqld
state: started
enabled: yes
- name: touch a file
file:
path: /tmp/mysql.txt
state: touch
[root@pubserver ansible]# ansible-playbook myerr.yml
[root@web1 ~]# ls /tmp/mysql.txt
/tmp/mysql.txt
触发执行任务
- 通过handlers定义触发执行的任务
- handlers中定义的任务,不是一定会执行的
- 在tasks中定义的任务,通过notify关键通知handlers中的哪个任务要执行
- 只有tasks中的任务状态是changed才会进行通知。
# 下载web1上的/etc/nginx/nginx.conf
[root@pubserver ansible]# vim get_conf.yml
---
- name: download nginx.conf
hosts: web1
tasks:
- name: get nginx.conf
fetch:
src: /etc/nginx/nginx.conf
dest: ./
flat: yes # 直接下载文件,不要目录
[root@pubserver ansible]# ansible-playbook get_conf.yml
# 修改nginx.conf的端口为变量
[root@pubserver ansible]# vim +39 nginx.conf
... ...
server {
listen {{http_port}} default_server;
listen [::]:{{http_port}} default_server;
server_name _;
... ...
# 修改nginx服务的端口为8000,重启nginx
[root@pubserver ansible]# vim trigger.yml
---
- name: configure nginx
hosts: webservers
vars:
http_port: "8000" # 定义nginx.conf中的变量和值
tasks:
- name: upload nginx.conf # 上传nginx.conf
template:
src: ./nginx.conf
dest: /etc/nginx/nginx.conf
- name: restart nginx # 重启服务
service:
name: nginx
state: restarted
# 第一次执行trigger.yml,上传文件和重启服务两个任务的状态都是黄色changed
[root@pubserver ansible]# ansible-playbook trigger.yml
# 第二次执行trigger.yml,上传文件的任务状态是绿色的ok,重启服务任务的状态是黄色changed
[root@pubserver ansible]# ansible-playbook trigger.yml
# 既然配置文件没有改变,那么服务就不应该重启
# 修改Playbook,只有配置文件变化了,才重启服务
[root@pubserver ansible]# vim trigger.yml
---
- name: configure nginx
hosts: webservers
vars:
http_port: "80"
tasks:
- name: upload nginx.conf
template:
src: ./nginx.conf
dest: /etc/nginx/nginx.conf
notify: restart nginx # 通知restart httpd需要执行
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
# 第一次运行Playbook,因为第1个任务是黄色的changed,所以handlers中的任务也被触发执行
[root@pubserver ansible]# ansible-playbook trigger.yml
# 第二次运行Playbook,因为第1个任务是绿色的OK,也就不会再触发执行其他任务了
[root@pubserver ansible]# ansible-playbook trigger.yml
when条件
- 只有满足某一条件时,才执行任务
- 常用的操作符:
-
- ==:相等
- !=:不等
- >:大于
- <:小于
- <=:小于等于
- >=:大于等于
- 多个条件或以使用and或or进行连接
- when表达式中的变量,可以不使用{{}} ,
×××××××× 没有上下的执行顺序,都要先执行when语句
# 当dbs组中的主机内存大于2G的时候,才安装mysql-server
[root@pubserver ansible]# vim when1.yml
---
- name: install mysql-server
hosts: dbs
tasks:
- name: install mysql-server pkg
yum:
name: mysql-server
state: present
when: ansible_memtotal_mb>2048
# 如果目标主机没有2GB内存,则不会安装mysqld-server
[root@pubserver ansible]# ansible-playbook when1.yml
# 多条件。系统发行版是Rocky8才执行任务
# /etc/motd中的内容,将会在用户登陆时显示在屏幕上
取消可以卸载软件 yum remove cowsay
域名-有install cowsay cowsay -l cowsay -f kiss laalalal
[root@pubserver ansible]# vim motd
_____________
< hello world >
-------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
[root@pubserver ansible]# vim when2.yml
---
- name: when condition
hosts: webservers
tasks:
- name: modify /etc/motd
copy:
dest: /etc/motd
src: motd
when: > # 以下三行合并成一行
ansible_distribution == "Rocky"
and
ansible_distribution_major_version == "8"
[root@pubserver ansible]# ansible-playbook when2.yml
register注册变量
Ansible的“register”模块是用于捕获和保存任务执行结果的,它允许将其他任务的输出作为变量使用。register是一个关键字,可以将任务执行的结果赋值给指定的变量名称。这个变量可以在后续任务中使用。register模块可以捕获各种类型的输出,包括stdout、stderr、rc、changed等。它可以与其他模块一起使用,例如“when”条件、“loop”循环等。 存的是字典。键值对的方式,可以通过 字典名「“key”」或者 字典名.键调用值
# 在web1组的主机上执行任务,创建/tmp/regfile1.txt,并打印创建结果
[root@pubserver ansible]# vim reg1.yml
---
- name: create file /tmp/regfile1.txt
hosts: web1
tasks:
- name: create file
file:
path: /tmp/rgefile1.txt
state: touch
register: result
- name: display output
debug:
msg: "{{result}}"
# 在web1主机上执行任务,创建文件/tmp/ademo/abc。如果创建不成功,则通过debug输出create failed
[root@pubserver ansible]# vim reg2.yml
---
- name: create file /tmp/ademo/abc
hosts: web1
ignore_errors: yes
tasks:
- name: create file
file:
path: /tmp/ademo/abc
state: touch
register: result
- name: debug output
debug:
msg: "create failed"
when: result.failed
cowsay:
# cowsay是一个软件,可以在以下地址获得
# https://rpmfind.net/linux/epel/8/Everything/x86_64/Packages/c/cowsay-3.04-16.el8.noarch.rpm
# 使用方式如下:
[root@pubserver ansible]# yum install -y /root/cowsay-3.04-16.el8.noarch.rpm
[root@pubserver ansible]#
< ni hao a >
----------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
# 查看其他形象
[root@pubserver ansible]# cowsay -l
Cow files in /usr/share/cowsay:
beavis.zen blowfish bud-frogs bunny cheese cower default dragon
dragon-and-cow elephant elephant-in-snake eyes flaming-sheep fox
ghostbusters head-in hellokitty kiss kitty koala kosh luke-koala
mech-and-cow meow milk moofasa moose mutilated ren sheep skeleton small
stegosaurus stimpy supermilker surgery telebears three-eyes turkey turtle
tux udder vader vader-koala www
[root@pubserver ansible]# cowsay -f elephant are you ok?
_____________
< are you ok? >
-------------
\ /\ ___ /\
\ // \/ \/ \\
(( O O ))
\\ / \ //
\/ | | \/
| | | |
| | | |
| o |
| | | |
|m| |m|
# 如果执行playbook时也会出现奶牛,则可以使用以下方式取消
[root@pubserver ansible]# echo 'nocows = 1' >> ansible.cfg
# 在test组中的主机上创建5个目录/tmp/{aaa,bbb,ccc,ddd,eee}
[root@pubserver ansible]# vim loop1.yml
---
- name: use loop
hosts: webservers
tasks:
- name: create directory
file:
path: /tmp/{{item}}
state: directory
loop: [aaa,bbb,ccc,ddd,eee]
# 上面写法,也可以改为:
---
- name: use loop
hosts: webservers
tasks:
- name: create directory
file:
path: /tmp/{{item}}
state: directory
loop:
- aaa
- bbb
- ccc
- ddd
- eee
[root@pubserver ansible]# ansible-playbook loop1.yml
# 使用复杂变量。创建zhangsan用户,密码是123;创建lisi用户,密码是456
# item是固定的,用于表示循环中的变量
# 循环时,loop中每个-后面的内容作为一个整体赋值给item。
# loop中{}中的内容是自己定义的,写法为key: val 注意空格
# 取值时使用句点表示。如下例中取出用户名就是{{item.uname}}
[root@pubserver ansible]# vim loop_user.yml
---
- name: create users
hosts: webservers
tasks:
- name: create multiple users
user:
name: "{{item.uname}}"
password: "{{item.upass|password_hash('sha512')}}"
loop:
- {"uname": "zhangsan", "upass": "123"}
- {"uname": "lisi", "upass": "456"}
[root@pubserver ansible]# ansible-playbook loop_user.yml
role角色
- 为了实现playbook重用,可以使用role角色
- 角色role相当于把任务打散,放到不同的目录中,目录不需要全都有,可以删掉
- 再把一些固定的值,如用户名、软件包、服务等,用变量来表示
- role角色定义好之后,可以在其他playbook中直接调用
切换上一个目录 cd - 可以来回切
roles 和tasks没有顺序,roles先执行,tasks后执行,但里面的任务由上而下执行
# 使用常规playbook,修改/etc/motd的内容
# 1. 创建motd模板文件
[root@pubserver ansible]# vim motd
Hostname: {{ansible_hostname}} # facts变量,主机名
Date: {{ansible_date_time.date}} # facts变量,日期
Contact to: {{admin}} # 自定义变量
# 2. 编写playbook
[root@pubserver ansible]# vim motd.yml
---
- name: modifty /etc/motd
hosts: webservers
vars:
admin: root@tedu.cn # 自定义名为admin的变量
tasks:
- name: modify motd
template:
src: motd
dest: /etc/motd
[root@pubserver ansible]# ansible-playbook motd.yml
[root@web1 ~]# cat /etc/motd
Hostname: web1
Date: 2021-11-01
Contact to: root@tedu.cn
# 创建角色
# 1. 声明角色存放的位置
[root@pubserver ansible]# vim ansible.cfg
[defaults]
inventory = hosts
roles_path = roles # 定义角色存在当前目录的roles子目录中
# 2. 创建角色目录
[root@pubserver ansible]# mkdir roles
# 3. 创建名为motd的角色
[root@pubserver ansible]# ansible-galaxy init roles/motd 名字自定义
[root@pubserver ansible]# ls roles/
motd # 生成了motd角色目录
[root@pubserver ansible]# yum install -y tree
[root@pubserver ansible]# tree roles/motd/
roles/motd/
├── defaults # 定义变量的目录,优先级最低
│ └── main.yml
├── files # 保存上传的文件(如copy模块用到的文件)
├── handlers # handlers任务写到这个目录的main.yml中
│ └── main.yml
├── meta # 保存说明数据,如角色作者、版本等
│ └── main.yml
├── README.md # 保存角色如何使用之类的说明
├── tasks # 保存任务
│ └── main.yml
├── templates # 保存template模块上传的模板文件
├── tests # 保存测试用的playbook。可选
│ ├── inventory
│ └── test.yml
└── vars # 定义变量的位置,推荐使用的位置
└── main.yml
# 4. 将不同的内容分别写到对应目录的main.yml中
# 4.1 创建motd模板文件
[root@pubserver ansible]# vim roles/motd/templates/motd
Hostname: {{ansible_hostname}}
Date: {{ansible_date_time.date}}
Contact to: {{admin}}
# 4.2 创建变量
[root@pubserver ansible]# vim roles/motd/vars/main.yml # 追加一行
admin: zzg@tedu.cn
# 4.3 创建任务
[root@pubserver ansible]# vim roles/motd/tasks/main.yml # 追加
- name: modify motd
template:
src: motd # 这里的文件,自动到templates目录下查找
dest: /etc/motd
# 5. 创建playbook,调用motd角色
[root@pubserver ansible]# vim role_motd.yml
---
- name: modify motd with role
hosts: webservers
roles:
- motd
# 6. 执行playbook
[root@pubserver ansible]# ansible-playbook role_motd.yml
role练习
- 创建名为pkgs的角色。用于装包。包名使用变量pkg代表
- 创建inst_nginx.yml,调用pkgs角色,安装nginx
- 创建inst_mysql.yml,调用pkgs角色,安装mysql
# 1. 创建名为pkgs的角色。
# 1.1 创建角色目录
[root@pubserver ansible]# ansible-galaxy init roles/pkgs
# 1.2 创建装包的任务,包名使用变量pkg代表
[root@pubserver ansible]# vim roles/pkgs/tasks/main.yml
---
# tasks file for roles/pkgs
- name: install rpm pkg
yum:
name: "{{pkg}}"
state: present
# 1.3 定义变量
[root@pubserver ansible]# vim roles/pkgs/defaults/main.yml
---
# defaults file for roles/pkgs
pkg: nginx
# 2. 创建inst_nginx.yml,调用pkgs角色,安装nginx
[root@pubserver ansible]# vim inst_nginx.yml
---
- name: install nginx pkg
hosts: webservers
roles:
- pkgs
[root@pubserver ansible]# ansible-playbook inst_nginx.yml
# 3. 创建inst_mysql.yml,调用pkgs角色,安装mysql-server
[root@pubserver ansible]# vim inst_mysql.yml
---
- name: install mysql pkg
hosts: dbs
vars:
pkg: mysql-server
roles:
- pkgs
[root@pubserver ansible]# ansible-playbook inst_mysql.yml
- ansible的公共角色仓库:Ansible Galaxy
# 在公共仓库中搜索与nginx相关的角色
[root@myhost ~]# ansible-galaxy search nginx
# 如果找到相应的角色,如名字为mynginx,可以下载它到roles目录
[root@myhost ~]# ansible-galaxy install mynginx -p roles/
ansible加解密文件
- ansible加解密文件使用ansible-vault命令
[root@pubserver ansible]# echo "Hi ni hao" > hello.txt
[root@pubserver ansible]# cat hello.txt
Hi ni hao
# 加密文件
[root@pubserver ansible]# ansible-vault encrypt hello.txt
New Vault password: 123456
Confirm New Vault password: 123456
Encryption successful
[root@pubserver ansible]# cat hello.txt
$ANSIBLE_VAULT;1.1;AES256
37373366353566346235613731396566646533393361386131313632306563633336333963373465
6164323461356130303863633964393339363738653036310a666564313832316263393061616330
32373133323162353864316435366439386266616661373936363563373634356365326637336165
6336636230366564650a383239636230623633356565623461326431393634656666306330663533
6235
# 解密
[root@pubserver ansible]# ansible-vault decrypt hello.txt
Vault password: 123456
Decryption successful
[root@pubserver ansible]# cat hello.txt
Hi ni hao
# 加密后更改密码
[root@pubserver ansible]# ansible-vault encrypt hello.txt
New Vault password: 123456
Confirm New Vault password: 123456
Encryption successful
[root@pubserver ansible]# ansible-vault rekey hello.txt # 改密码
Vault password: 123456 # 旧密码
New Vault password: abcd # 新密码
Confirm New Vault password: abcd
Rekey successful
# 不解密文件,查看内容
[root@pubserver ansible]# ansible-vault view hello.txt
Vault password: abcd
Hi ni hao
# 使用密码文件进行加解密
# 1. 将密码写入文件
[root@pubserver ansible]# echo 'tedu.cn' > pass.txt
# 2. 创建明文文件
[root@pubserver ansible]# echo 'hello world' > data.txt
# 3. 使用pass.txt中的内容作为密码加密文件
[root@pubserver ansible]# ansible-vault encrypt --vault-id=pass.txt data.txt
Encryption successful
[root@pubserver ansible]# cat data.txt # 文件已加密
# 4. 使用pass.txt中的内容作为密码解密文件
[root@pubserver ansible]# ansible-vault decrypt --vault-id=pass.txt data.txt
Decryption successful
[root@pubserver ansible]# cat data.txt
hello world
- 使用ansible管理远程主机,存储敏感数据时(如,文件中包含密码),应该将其加密
- 执行playbook时,通过--ask-vault-password选项提示输入密码
# 1. 编写有密码的playbook
[root@pubserver ansible]# vim user_zhangsan.yml
---
- name: create a user
hosts: webservers
tasks:
- name: create user zhangsan
user:
name: zhangsan
password: "{{'123'|password_hash('sha512')}}"
# 2. 加密playbook
[root@pubserver ansible]# ansible-vault encrypt user_zhangsan.yml
New Vault password: 123456
Confirm New Vault password: 123456
Encryption successful
# 3. 直接执行playbook,报错
[root@pubserver ansible]# ansible-playbook user_zhangsan.yml
ERROR! Attempting to decrypt but no vault secrets found
# 4. 使用--ask-vault-password选项
[root@pubserver ansible]# ansible-playbook --ask-vault-password user_zhangsan.yml
Vault password: 123456
起
通过 ansible-playbook --help | less 查询
sudo命令
- 一般用于普通用户执行需要root权限的命令
- 在web1上配置zhangsan拥有sudo权限
# 如果没有zhangsan,手工创建
[root@web1 ~]# visudo # 将会打开vi,在尾部追加以下一行
zhangsan ALL=(ALL) ALL
# 中间的ALL=(ALL)在集中认证的域环境中才有效,单机忽略即可
# zhangsan是用户名,最后的ALL表示zhangsan可以以管理员的身份执行所有命令
# 切换成zhangsan用户,执行命令
[root@web1 ~]# su - zhangsan
[zhangsan@web1 ~]$ useradd wangwu # 失败,因为还是张三身份
[zhangsan@web1 ~]$ sudo useradd wangwu # 以管理员身份执行
... ...
[sudo] password for zhangsan: # 输入zhangsan的密码,不是root
# 配置lisi不输入密码可以直接运行sudo
[root@web1 ~]# visudo # 在最后追加一行
lisi ALL=(ALL) NOPASSWD: ALL
# 切换成lisi运行
[root@web1 ~]# su - lisi
[lisi@web1 ~]$ ls /root/ # 没权限
ls: cannot open directory '/root/': Permission denied
[lisi@web1 ~]$ sudo ls /root/ # 成功运行,无需输入密码
a3.txt anaconda-ks.cfg
特殊的主机清单变量
- 如果远程主机没有使用免密登陆,如果远程主机ssh不是标准的22端口,可以设置特殊的主机清单变量
- ansible_ssh_user:指定登陆远程主机的用户名
- ansible_ssh_pass:指定登陆远程主机的密码
- ansible_ssh_port:指定登陆远程主机的端口号
# 删除远程主机的/root/.ssh/authorized_keys,以便恢复通过密码登陆
[root@pubserver ansible]# ansible all -m file -a "path=/root/.ssh/authorized_keys state=absent"
# 创建新的工作目录
[root@pubserver ~]# mkdir myansible
[root@pubserver ~]# cd myansible
[root@pubserver myansible]# vim ansible.cfg
[defaults]
inventory = inventory
[root@pubserver myansible]# vim inventory
[group1]
web1
web2
db1
[root@pubserver myansible]# ansible all -m ping # 报错,因为无法免密执行
# 修改web1 ssh服务的端口为220
[root@web1 ~]# systemctl stop firewalld
[root@web1 ~]# echo 'Port 220' >> /etc/ssh/sshd_config
[root@web1 ~]# systemctl restart sshd
# 退出再登陆时,需要指定端口号
[root@myhost ~]# ssh -p220 192.168.88.11
# 配置ssh通过用户名、密码管理远程主机,通过220端口连接web1
[root@pubserver myansible]# vim inventory
[group1]
web1 ansible_ssh_user=root ansible_ssh_pass=a ansible_ssh_port=220
web2 ansible_ssh_user=root ansible_ssh_pass=a
db1 ansible_ssh_user=root ansible_ssh_pass=a
[root@pubserver myansible]# ansible all -m ping