Ansible
环境准备
主机名 | ip | 分组 |
---|---|---|
crontol | 192.168.88.1 | |
node1 | 192.168.88.11 | test |
node2 | 192.168.88.12 | proxy |
node3 | 192.168.88.13 | webservers |
node4 | 192.168.88.14 | webservers |
node5 | 192.168.88.15 | database |
所有操作只需在crontol
上操作即可
- 安装
ansible
# 依赖一般也会跟着一起装好
yum install -y ansible
- 配置域名解析
for i in {1..5}; do echo -e "192.168.88.1$i\tnode$i" >> /etc/hosts; done
- 配置免密登录
ssh-keygen # 回车即可
for i in node{1..5}; do ssh-copy-id $i ;done # 按要求输入密码即可
- 创建
ansible
工作目录
mkdir ansible && cd ansible
- 创建配置文件(可参考:
etc/ansible/ansible.cfg
),以下操作都必须在工作目录下执行
vim ansible.cfg
# ansible.cfg内容
[defaults]
inventory = hosts # 管理的主机,配置在当前目录的hosts文件中,hosts名是自定义的。=号两边空格可有可无
vim hosts
# hosts内容
[test]
node1
[proxy]
node2
[webservers]
node[3:4]
[database]
node5
[cluster:children]
webservers
database
# 测试是否成功
ansible all --list-hosts
# 输出下列结果表示成功
hosts (5):
node2
node1
node3
node4
node5
ansible管理分类
-
ansible
远程管理-
adhoc
临时命令,也就是在命令行执行管理命令 -
playbook
剧本,把管理任务用特定格式写到文件中
-
adhoc临时命令
- 语法格式
ansible 主机或组列表 -m 模块 -a "参数" # -a是可选的
- 测试主机连通性
ansible all -m ping
ansible模块
- 查看模块基本信息
# 查看所有模块
ansible-doc -l
# 查看指定模块
ansible-doc -l | grep file
# 查看模块使用文档,/EXAMPLE可以查看示例
ansible-doc file
command模块
-
ansible
默认模块,用于在远程主机上执行任意命令 -
command
不支持shell
特性,如管道、重定向。
# 在所有被管主机上创建目录/tmp/demo
ansible all -a "mkdir /tmp/demo"
# 查看node1的ip地址
ansible node1 -a "ifconfig" # ansible node1 -a "ifconfig | head -5"就会报错
shell模块
- 与
command
模块类似,但是支持shell
特性,如管道、重定向。
ansible node1 -m shell -a "ifconfig | grep inet"
script模块
- 用于在远程主机上执行脚本
# 控制端先创建一个安装vsftpd服务的脚本
vim install.sh
# install.sh内容
#!/bin/bash
yum install -y vsftpd
systemctl start vsftpd
# 在test组执行这个脚本
ansible test -m script -a "install.sh"
注意:
command
、shell
、script
这三个模块一般不用,因为它们没有幂特性
file模块
- 创建文件、目录、链接等,还可以修改权限,属主、属组等
- 常用选项
-
path
:指定文件路径 -
owner
:设置文件所有者 -
group
:设置文件所属组 -
state
:状态,touch
表示创建文件,directory
表示创建目录,link
表示创建超链接,absent
表示删除 -
mode
:设置权限 -
src
:源文件,设置超链接的时候会用到 -
dest
:目标文件,设置超链接的时候会用到
-
# 查看使用帮助
ansible-doc file
# 在test组的主机上创建/tmp/test.txt
ansible test -m file -a "path=/tmp/test.txt state=touch"
# 将test组的主机上的/tmp/test.txt属主和属组都修改为adm,权限修改为0777
ansible test -m file -a "path=/tmp/test.txt owner=adm group=adm mode='0777'"
# 在test组的主机上创建/tmp/demo,创建的同时设置该目录的属主和属组都修改为adm,权限修改为0777
ansible test -m file -a "path=/tmp/demo owner=adm group=adm mode='0777' state=directory"
# 在test组的主机上创建/etc/hosts的超链接,存放在/tmp/demo/hosts
ansible test -m file -a "src=/etc/hosts dest=/tmp/demo/hosts state=link"
# 删除test组的主机上的/tmp/test.txt和/tmp/demo
ansible test -m file -a "path=/tmp/demo state=absent"
ansible test -m file -a "path=/tmp/test.txt state=absent"
copy模块
- 用于将文件从控制端拷贝到被控端
- 常用选项
-
src
:源文件路径 -
dest
:目标路径 -
content
:内容 -
owner
:设置文件所有者 -
group
:设置文件所属组 -
mode
:设置文件权限
-
# 将本地的/etc/hostname拷贝到test组服务器的/root/下
ansible test -m copy -a "src=/etc/hostname dest=/root/"
# 在目标主机上创建/tmp/test.txt,内容是Hello bhlu
ansible test -m copy -a "content='Hello bhlu' dest=/tmp/test.txt"
fetch模块
- 从被控端下载文件到控制端
- 常用选项
-
src
:源文件路径 -
dest
:目标路径 -
flag
:yes
代表直接下载文件,不会递归下载目录
-
# 将test组的主机上的/etc/hostname下载到本地的/root/下
ansible test -m fetch -a "src=/etc/hostname dest=/root/"
cat /root/node1/etc/hostname
# node1
lineinfile模块
- 操作目标服务器文件中的文件,可以添加,替换整行
- 常用选项
-
path
:待修改的文件路径 -
line
:写入文件的一行内容 -
regexp
:正则表达式,用于查找文件中内容
-
# 检测test组的主机的/tmp/test.txt文件中,是否有aaa,如果有,则不操作,没有就添加aaa到文件结尾
ansible test -m lineinfile -a "path=/tmp/test.txt line='aaa'"
# 将test组的主机的/tmp/test.txt文件中的包含aaa的行替换成bbb,从下往上,只替换一次
ansible test -m lineinfile -a "path=/tmp/test.txt line='bbb' regexp='aaa'"
replace模块
-
lineinfile
会替换一行,replace
替换关键词 - 常用选项
-
path
:待修改的文件路径 -
replace
:替换成的内容 -
regexp
:正则表达式,需要替换的内容
-
# 将test组的主机上的/tmp/test.txt中bb全部替换成haha
ansible test -m replace -a "path=/tmp/test.txt replace='haha' regexp='bbb'"
user模块
- 实现linux用户管理
- 常用选项
-
name
:待创建的用户名 -
uid
:用户ID -
group
:设置主组 -
groups
:设置附加组 -
home
:设置家目录 -
password
:设置用户密码 -
state
:状态,present
表示创建,也是默认选项,absent
表示删除 -
remove
:删除家目录、邮箱等,yes
或者true
-
# 在test组的主机上,创建一个bhlu的用户,uid为1020,设置主组为adm,附加组为root,密码是123456
ansible test -m user -a "name=bhlu uid=1020 group=adm groups=root password=123456"
# 修改test组的主机上的bhlu的密码为666666,使用加密算法
ansible test -m user -a "name=bhlu password={{'666666'|password_hash('sha512')}}"
# 删除test组的主机上的bhlu的用户,不删除家目录
ansible test -m user -a "name=bhlu state=absent"
# 删除test组的主机上的tools的用户,删除家目录
ansible test -m user -a "name=bhlu state=absent remove=yes"
group模块
- 实现linux的组管理
- 常用选项
-
name
:待创建的组名 -
gid
:GID -
state
:状态,present
表示创建,也是默认选项,absent
表示删除
-
# 在test组的主机上创建一个uid为1030的组,名称为project
ansible test -m group -a "name=project gid=1030"
# 将test组的主机上的名为project的组删除
ansible test -m group -a "name=project state=absent"
yum_repository模块
- 用于配置yum
- 常用选项
-
file
:指定文件名 -
name
:指定仓库名称 -
description
:仓库描述 -
baseurl
:仓库地址 -
gpgcheck
:是否检查gpg
,填yes
|no
,0和1都行 -
enabled
:是否开启,填yes
|no
,0和1都行
-
# 在test组的主机上创建yum文件,文件为myrepo.repo,仓库名为myRepo,描述为My Repo,baseurl为ftp://yum-server/base/,开启状态,不检查gpg
ansible test -m yum_repository -a "file=myrepo name=myRepo description='My Repo' baseurl=ftp://yum-server/base/ enabled=yes gpgcheck=0"
# 被控主机
cat myrepo.repo
[myRepo]
baseurl = ftp://yum-server/base/
enabled = 1
gpgcheck = 0
name = My Repo
yum模块
- 用于
rpm
软件包管理,如安装、升级、卸载 - 常用选项
-
name
:包名 -
state
:状态,present
表示安装,如果安装则忽略;latest
表示安装或者升级到最新版本;absent
表示卸载
-
# 在test组的主机上安装tree
ansible test -m yum -a "name=tree"
# 在test组的主机上卸载tree
ansible test -m yum -a "name=tree state=absent"
service模块
- 用于控制服务。启动、关闭、重启、设置开机自启
- 常用选项
-
name
:控制的服务名 -
state
:状态,started
表示启动;stopped
表示关闭;restarted
表示重启 -
enabled
:yes
表示设置开机自启;no
表示设置开机不自启
-
# 在test组的主机上开启vsftpd,并设置开机自启
ansible test -m service -a "name=vsftpd state=started enabled=yes"
# 在test组的主机上关闭vsftpd
ansible test -m service -a "name=vsftpd state=stopped"
逻辑卷相关模块
parted模块
- 用于硬盘分区管理
- 常用选项
-
device
:待分区的设备 -
number
:分区编号 -
state
:状态,present
表示创建;absent
表示删除 -
part_start
:分区起始位置,不写表示从开头 -
part_end
:分区结束位置,不写表示结尾
-
# 在test组的主机上,对20G的/dev/nvme0n2进行操作,分两个分区,第一个5G,第二个15G
ansible test -m parted -a "device=/dev/nvme0n2 number=1 state=present part_end=5GiB"
ansible test -m parted -a "device=/dev/nvme0n2 number=2 state=present part_start=5GiB"
lvg模块
- 创建、删除卷组,修改卷组大小
- 常用选项
-
vg
:定义卷组名。vg:volume group -
pvs
:物理卷,分号隔开。pvs:physical volumes -
state
:状态,present
表示创建,默认状态;absent
表示删除
-
# 在test组的主机上创建一个myvg的卷组,是有/dev/nvme0n2p1和/dev/nvme0n2p2组成
ansible test -m lvg -a "vg=myvg pvs=/dev/nvme0n2p1,/dev/nvme0n2p2 state=present"
lvol模块
- 创建、删除逻辑卷,修改逻辑卷大小
- 常用选项
-
vg
:指定那个卷组 -
lv
:逻辑卷名。lv:logical volume -
size
:逻辑卷大小,不写单位的情况下,默认以M为单位 -
state
:状态,present
表示创建,默认状态;absent
表示删除
-
# 在test组的主机上创建一个逻辑卷,卷名mylv,大小为5G
ansible test -m lvol -a "vg=myvg lv=mylv size=5G"
# 修改mylv的大小为10G
ansible test -m lvol -a "vg=myvg lv=mylv size=10G"
filesystem模块
- 用于格式化,创建文件系统
- 常用选项
-
fstype
:指定文件系统类型 -
dev
:指定要格式化的设备,可以是分区,也可以是逻辑卷 -
force
:yes
,强制的意思,当格式化或者删除dev
的时候,如果dev
上有数据,需要添加这个
-
# 将test组的主机上的mylv格式化成xfs格式
ansible test -m filesystem -a "fstype=xfs dev=/dev/myvg/mylv"
mount模块
- 用于挂载系统
- 常用选项
-
path
:挂载点 -
src
:待挂载的设备 -
fstype
:文件系统类型 -
state
:状态,mounted
表示永久挂载;absent
表示卸载
-
# 将test组的主机上的/dev/myvg/mylv挂载到/data
ansible test -m mount -a "path=/data src=/dev/myvg/mylv fstype=xfs state=mounted"
# 将test组的主机上的/dev/myvg/mylv挂载到/data
ansible test -m mount -a "path=/data src=/dev/myvg/mylv fstype=xfs state=absent"
firewalld模块
- 用于配置防火墙的模块
- 常用选项
-
port
:端口 -
permanent
:是否永久生效,yes
|no
-
immediate
:立即生效,临时生效,默认为no
-
state
:放行enabled
,拒绝disabled
-
# 放行80端口,文件内容如下
---
- name: set firewalld
hosts: test
tasks:
- name: allow 80/tcp
firewalld:
port: 80/tcp
permanent: yes
immediate: yes
state: enabled
template模块
- 上传文件,支持
jinja2
语法,跟copy
模块不同 - 常用选项
-
src
:源文件路径 -
dest
:目标文件路径
-
vim test.j2
# 文件内容如下
Hello {{name}},server is {{ansible_hostname}}
vim temp.yml
# 文件内容如下
---
- name: test template module
hosts: test
vars:
name: "bhlu"
tasks:
- name: copy test.j2 to test
template:
src: test.j2
dest: /var/www/html/index.html
# 执行,会有个警告,关于name变量,不用管
ansible-playbook temp.yml
# 测试
curl node1 # Hello bhlu,server is node1
综合测试
所有操作均对test组中的主机生效
在目标主机上创建/tmp/mydemo目录,属主和属组都是adm,权限为0777
将控制端的/etc/hosts文件上传到目标主机的/tmp/mydemo目录中,属主和属组都是adm,权限为0600
替换目标主机/tmp/mydemo/hosts文件中的node5为server5
将目标主机/tmp/mydemo/hosts文件下载到控制端的当前目录
# 在目标主机上创建/tmp/mydemo目录,属主和属组都是adm,权限为0777
ansible test -m file -a "path=/tmp/mydemo owner=adm group=adm mode='0777' state=directory"
# 将控制端的/etc/hosts文件上传到目标主机的/tmp/mydemo目录中,属主和属组都是adm,权限为0600
ansible test -m copy -a "src=/etc/hosts dest=/tmp/mydemo owner=adm group=adm mode='0600'"
# 替换目标主机/tmp/mydemo/hosts文件中的node5为server5
ansible test -m replace -a "path=/tmp/mydemo/hosts replace='server5' regexp='node5'"
# 将目标主机/tmp/mydemo/hosts文件下载到控制端的当前目录
ansible test -m fetch -a "src=/tmp/mydemo/hosts dest=."
Playbook剧本
- 常用于复杂任务的管理,以及管理经常要完成的任务
-
playbook
也是通过模块和它的参数,在特定主机上执行任务 -
playbook
是一个文件,该文件中需要通过yaml
格式进行书写
YAML
- YAML Ain’t a Markup Language:YAML不是一个标记语言
yaml语法规范
-
yaml
文件的文件名,一般以yml
或yaml
作为扩展名 - 文件一般以
---
作为第一行,不是必须的,但是常用 - 键值对使用冒号
:
表示,冒号后面必须有空格 - 数组使用
-
表示,-
后面必须有空格 - 相同的层级必须有相同的缩进。如果缩进不对,则有语法错误。每一级缩进,建议2个空格
- 全文不能使用
tab
,必须使用空格
配置vim适应yaml语法
vim ~/.vimrc
set ai # 设置自动缩进
set ts=2 # 设置按tab键,缩进2个空格
set et # 将tab转换成相应的空格
yaml文件格式
- 一般不能出现中文,下面的中文只是帮助理解
---
- name: 简介
hosts: 主机或组,用分号隔开
tasks:
- name: 任务1介绍
file:
path: ...
state: ...
mode: ...
- name: 任务2介绍
copy:
src: ...
copy: ...
示例
- 在
test
组和node2
上创建/tmp/demo
目录,权限是0600,将控制端/etc/hosts
拷贝到被控主机的/tmp/demo
中
vim fileop.yml
---
- name: create directory and copy file
hosts: test,node2
tasks:
- name: create directory
file:
path: /tmp/demo
state: directory
mode: '0600'
- name:
copy:
src: /etc/hosts
dest: /tmp/demo/hosts
- 运行:
ansible-playbook fileop.yml
- 在test组中的主机上,创建用户bob,附加组是adm;在node2主机上,创建/tmp/test.txt,其内容为Hello bhlu
-
vim test.yml
(文件中的content的|可以保留换行符,如果是>那就是将多行合并成一行)
---
- name: create user and touch file
hosts: test
tasks:
- name: create user bob
user:
name: bob
groups: adm
- name: touch file
copy:
dest: /tmp/test.txt
content: |
Hello bhlu
- 运行:
ansible-playbook test.yml
- 在test组中的主机上创建bhlu用户,它的uid是1040,主组是daemon,密码为123
vim user.yml
---
- name: create user
hosts: test
tasks:
- name: create user bhlu
user:
name: bhlu
uid: 1040
group: daemon
password: "{{'123'|password_hash('sha512')}}"
- 运行:
ansible-playbook user.yml
- 磁盘管理
将test组的主机上/dev/nvme0n3,创建两个物理盘,第一个5G,第二个15G,/dev/nvme0n3一共是20G
将两个物理盘组成一个叫test-vg的卷组
在test-vg卷组上创建一个叫test-lv的逻辑卷,大小5G
将test-lv格式化成xfs
将test-lv永久挂载到/data
vim disk.yml
---
- name: disk manage
hosts: test
tasks:
- name: create pv1
parted:
device: /dev/nvme0n3
number: 1
state: present
part_end: 5GiB
- name: create pv2
parted:
device: /dev/nvme0n3
number: 2
state: present
part_start: 5GiB
- name: create vg
lvg:
vg: test-vg
pvs: /dev/nvme0n3p1,/dev/nvme0n3p2
- name: create lv
lvol:
vg: test-vg
lv: test-lv
size: 5G
- name: create filesystem
filesystem:
dev: /dev/test-vg/test-lv
fstype: xfs
- name: mount
mount:
path: /data
src: /dev/test-vg/test-lv
fstype: xfs
state: mounted
- 运行:
ansible-playbook disk.yml
- 安装多个软件包
---
- name: install pkg
hosts: test
tasks:
- name: install httpd,tree,tar
yum:
name: [httpd,tree,tar]
state: present
- 安装软件包组
# 查看软件包组
yum grouplist
# 如果显示是中文,可以加LANG=C yum grouplist
LANG=c yum grouplist
# 安装组
yum groupinstall "组名"
---
- name: install package groups
hosts: test
tasks:
- name: install Development Tools
yum:
name: "@Development Tools"
state: present
- 更新系统所有包,相当于
yum update
---
- name: update packages
hosts: test
tasks:
- name: update system
yum:
name: "*"
state: latest
变量
facts变量
-
facts
变量是ansible
自带的预定义变量,用于描述被控端软硬件信息 - 查看所有
facts
变量
ansible test -m setup
- 可以通过
filter
来过滤想要查看的信息
# 查看所有ipv4地址信息
ansible test -m setup -a "filter=ansible_all_ipv4_addresses"
# 查看可用内存
ansible test -m setup -a "filter=ansible_memfree_mb"
-
常用的
facts
变量-
ansible_all_ipv4_addresses
:所有的IPV4地址 -
ansible_bios_version
:BIOS版本信息 -
ansible_memtotal_mb
:总内存大小 -
ansible_hostname
:主机名
-
-
示例
---
- name: display host info
hosts: test
tasks:
- name: display hostname and memory
debug:
msg: "hostname: {{ansible_hostname}} mem: {{ansible_memtotal_mb}}MB"
自定义变量
-
引入变量,可以方便Playbook重用。比如装包的playbook,包名使用变量。多次执行playbook,只要改变变量名即可,不用编写新的playbook。
-
ansible支持10种以上的变量定义方式。常用的变量来源如下:
- inventory变量。变量来自于主机清单文件
- facts变量。
- playbook变量。变量在playbook中定义。
- 变量文件。专门创建用于保存变量的文件。推荐变量写入单独的文件
-
使用inventory变量示例,在node1主机上创建一个用户bhlu,在webservers组的主机上创建一个用户maomao
vim hosts
# hosts内容如下
[test]
node1 username="bhlu" # 这里定义test组的
[proxy]
node2
[webservers]
node[3:4]
[database]
node5
[cluster:children]
webservers
database
[webservers:vars] # 固定写法 :vars
username="maomao"
# 创建yml文件
vim var.yml
# var.yml内容如下
---
- name: create users
hosts: test,webservers
tasks:
- name: create user
user:
name: "{{username}}"
state: present
# 执行
ansible-playbook var.yml
- 在playbook中定义变量
---
- name: create user
hosts: test
vars: # 固定是vars
username: "bhlu"
passowrd: "123"
tasks:
- name: create bhlu
user:
name: "{{username}}"
password: "{{passowrd|password_hash('sha512')}}"
state: present
- 将变量定义在文件里
vim user_vars.yml
# 文件内容
---
user: "maomao"
pwd: "123"
vim user.yml
# 文件内容
---
- name: create
hosts: test
vars_files: user_vars.yml
tasks:
- name: create maomao
user:
name: "{{user}}"
password: "{{pwd|password_hash('sha512')}}"
state: present
# 执行
ansible-playbook user.yml
错误处理
- 解决当前面任务运行错误,后面任务就不执行的问题
# 默认是下面这样写的,但是当启动test服务失败时,会直接跳出,不会执行下面的任务了
---
- name: test error
hosts: test
tasks:
- name: start test service
service:
name: test
state: started
enabled: yes
- name: touch a file
file:
path: /tmp/test.txt
state: touch
# 优化后
cat test.yml
---
- name: test error
hosts: test
tasks:
- name: start test service
ignore_errors: yes # 忽略错误
service:
name: test
state: started
enabled: yes
- name: touch a file
file:
path: /tmp/test.txt
state: touch
# 全局优化
---
- name: test error
hosts: test
ignore_errors: yes # 不管哪个任务发生错误,都会忽略
tasks:
- name: start test service
service:
name: test
state: started
enabled: yes
- name: touch a file
file:
path: /tmp/test.txt
state: touch
触发执行任务
- 不管第一个任务是否执行,第二个任务都会执行,有些情况是不需要这样的
# 不管有没有修改配置文件,都会重启服务
---
- name: test trigger
hosts: test
vars:
http_port: "80"
tasks:
- name: upload httpd.conf
template:
src: httpd.conf
dest: /etc/httpd/conf/httpd.conf
- name: restart httpd
service:
name: httpd
state: restarted
# 优化后,只有第一个任务changed,才会执行第二个任务
---
- name: test trigger
hosts: test
vars:
http_port: "8080"
tasks:
- name: upload httpd.conf
template:
src: httpd.conf
dest: /etc/httpd/conf/httpd.conf
notify: restart httpd # 通知,后面的要对应上,空格也不能少
handlers:
- name: restart httpd
service:
name: httpd
state: restarted
when条件
-
只有满足条件时,才执行任务<