Ansible是一种自动化管理工具,相较于其他管理工具,ansible的最大优点就是不需要安装客户端,但需要ssh道路畅通。基于Python开发,可以实现批量系统配置,批量程序部署,批量运行命令等。
一、Ansible安装
1.Epel源安装
[root@node ~]#curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
[root@node ~]#yum install ansible
2.编译安装
[root@node ~]#yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
[root@node ~]#tar xf ansible-1.5.4.tar.gz
[root@node ~]#cd ansible-1.5.4
[root@node ~]#python setup.py build
[root@node ~]#python setup.py install
[root@node ~]#mkdir /etc/ansible
[root@node ~]#cp -r examples/* /etc/ansible
3.Git方式安装
[root@node ~]#git clone git://github.com/ansible/ansible.git --recursive
[root@node ~]#cd ./ansible
[root@node ~]#source ./hacking/env-setup
4.pip安装
[root@node ~]#yum install python-pip python-devel
[root@node ~]#yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel
[root@node ~]#pip install --upgrade pip
[root@node ~]#pip install ansible --upgrade
确认安装
[root@node ~]#ansible --version
ansible 2.9.5
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.6/site-packages/ansible
executable location = /usr/bin/ansible
python version = 3.6.8 (default, Nov 21 2019, 19:31:34) [GCC 8.3.1 20190507 (Red Hat 8.3.1-4)]
二、Ansible相关工具
- /usr/bin/ansible 主程序,临时命令执行工具
- /usr/bin/ansible-doc 查看配置文档,模块功能查看工具
- /usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台
- /usr/bin/ansible-playbook 定制自动化任务,编排剧本工具
- /usr/bin/ansible-pull 远程执行命令的工具
- /usr/bin/ansible-vault 文件加密工具
- /usr/bin/ansible-console 基于Console界面与用户交互的执行工具
使用ansible实现管理的主要方式:
- Ad-Hoc 即使用ansible命令
- Ansible-playbook
Ansible程序结构(yum安装):
配置文件目录:/etc/ansible/
执行文件目录:/usr/bin/
Lib库依赖目录:/usr/lib/pythonX.X/site-packages/ansible/
Help文档目录:/usr/share/doc/ansible-X.X.X/
Man文档目录:/usr/share/man/man1/
ansible-doc
#列出所有模块
ansible-doc -l
#查看指定模块的帮助用法
ansible-doc ping
ansible-doc -s ping
ansible
通过ssh协议,实现对远程主机的配置管理、应用部署、任务执行等功能
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
--version #显示版本
-m module #指定模块,默认为command
-a #指定模块的参数
-i INVENTORY #指定主机清单的路径,默认为/etc/ansible/hosts
-v #详细过程 –vv -vvv更详细
-C, --check #检查,并不执行
--list-hosts #显示主机列表,可简写 --list
-k, --ask-pass #提示输入ssh连接密码,默认Key验证
-T, --timeout=TIMEOUT #执行命令的超时时间,默认10s
-u, --user=REMOTE_USER #执行远程执行的用户
-b, --become #代替旧版的sudo 切换
--become-user=USERNAME #指定sudo的runas用户,默认为root
-K, --ask-become-pass #提示输入sudo时的口令
ansible主机清单
/etc/ansible/hosts 默认主机清单
ansible_host
ansible_port 用于配置对应主机上的sshd服务端口号
ansible_user 用于配置连接到对应主机时所使用的用户名称
ansible_ssh_pass 用于配置对应用户的连接密码
三、Ansible常用模块
1.ping模块
用来进行主机连通性测试
[root@node ~]# ansible all -m ping
192.168.157.130 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.157.129 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
2.command模块
默认模块,可忽略-m选项,在远程主机上执行命令,但不支持$VARNAME < > | ; & 等
[root@node ~]# ansible all -m command -a 'chdir=/etc/yum.repos.d/ ls'
192.168.157.129 | CHANGED | rc=0 >>
CentOS-Base.repo
epel.repo
192.168.157.130 | CHANGED | rc=0 >>
CentOS-Base.repo
epel.repo
[root@node ~]# ansible all -a 'creates=/etc/yum.repos.d/epel.repo ls' #如果文件存在,不执行ls
192.168.157.129 | SUCCESS | rc=0 >>
skipped, since /etc/yum.repos.d/epel.repo exists
192.168.157.130 | SUCCESS | rc=0 >>
skipped, since /etc/yum.repos.d/epel.repo exists
[root@node ~]# ansible all -a 'removes=/etc/yum.repos.d/epel.repo ls' #如果文件存在,执行ls
192.168.157.130 | CHANGED | rc=0 >>
test.txt
192.168.157.129 | CHANGED | rc=0 >>
test.txt
3.shell模块
和command相似,用shell执行命令
[root@node ~]# ansible all -m shell -a "ls |grep txt"
192.168.157.130 | CHANGED | rc=0 >>
test.txt
192.168.157.129 | CHANGED | rc=0 >>
k8s.txt
工作中可将shell模块代替command模块
[root@node ~]# vim /etc/ansible/ansible.cfg
module_name = shell
4.script模块
在远程主机上运行ansible服务器的脚本
[root@node data]# ansible all -m script -a "chdir=/root /data/test.sh"
192.168.157.130 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.157.130 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.157.130 closed."
],
"stdout": "/root\r\n",
"stdout_lines": [
"/root"
]
}
5.copy模块
将文件复制到远程主机
常用选项:
src #源文件,如果路径是目录,会递归复制
content #用于替换src,表示文件的值
dest #复制到的远程主机的绝对路径
backup #当文件发生改变时,覆盖之前备份原文件
directory_mode #递归设置目录的权限
owner
group
mode
force
用法
[root@node data]# ansible all -m copy -a "src=/data/test.sh dest=/data/test.sh owner=root mode=644 backup=yes"
[root@node data]# ansible all -m copy -a 'content="This is test" dest=/data/test2.txt mode=666'
6.fetch模块
从远程主机提取文件到ansible主机,与copy相反,目前不支持目录
[root@node ~]# ansible all -m fetch -a 'src=/etc/hostname dest=/data'
192.168.157.129 | CHANGED => {
"changed": true,
"checksum": "62343d9fe31e6f9b93f4507094248c44aaf32ac7",
"dest": "/data/192.168.157.129/etc/hostname",
"md5sum": "221a057e91928a3651f31d376b907d60",
"remote_checksum": "62343d9fe31e6f9b93f4507094248c44aaf32ac7",
"remote_md5sum": null
}
192.168.157.130 | CHANGED => {
"changed": true,
"checksum": "471de9b108f7f57e58c240a4ca3bfe24b7b69bfc",
"dest": "/data/192.168.157.130/etc/hostname",
"md5sum": "21d192a7f99b9d042621777150ea8a5f",
"remote_checksum": "471de9b108f7f57e58c240a4ca3bfe24b7b69bfc",
"remote_md5sum": null
}
[root@node ~]# tree /data/
/data/
├── 192.168.157.129
│ └── etc
│ └── hostname
└── 192.168.157.130
└── etc
└── hostname
4 directories, 2 files
---
- hosts: all
tasks:
- name: tar packages
shell: chdir=/var/ warn=false tar zcvf log.tar.gz log
- name: fetch logs
fetch: src=/var/log.tar.gz dest=/data/log
7.file模块
用于设置文件的属性,比如创建文件或目录、创建链接文件、删除文件、修改权限等
path #必须项,指定操作的对象,为了兼容旧版本,用dest或name也可以
state #directory:创建目录,touch:创建文件,link:创建软连接,hard:创建硬连接,absent:删除
src #指定连接源
force
owner
group
mode
recurse #当操作目录时,recurse=yes,可以递归修改属性
#创建目录
[root@node ~]# ansible all -m file -a 'path=/data/testdir state=directory'
#创建文件
[root@node ~]# ansible all -m file -a 'path=/data/testfile state=touch'
[root@node ~]# ansible all -m file -a 'path=/data/testfile owner=root mode=755'
#创建软链接
[root@node ~]# ansible all -m file -a 'src=/data/testfile dest=/date/testfile-link state=link'
#删除文件
[root@node ~]# ansible all -m file -a 'path=/data/testfile-link state=absent'
8.archive和unarchive
archive用于打包压缩
[root@node ~]# ansible all -m archive -a 'path=/var/log/ dest=/var/log.tar.gz'
unarchive用于解包解压缩,有两种方式:
1.将ansible主机上的压缩包传到远程主机后解压缩至特定的目录,copy=yes(默认)
2.将远程主机的某个压缩文件解压缩到指定路径,copy=no
#将远程主机的压缩文件解压
[root@node ~]# ansible all -m unarchive -a 'src=/var/log.tar.gz dest=/data copy=no mode=700'
#将ansible主机的压缩文件解压到远程主机
[root@node ~]# ansible all -m unarchive -a 'src=/root/nginx-1.10.3.tar.gz dest=/data mode=700'
9.cron模块
用于管理cron计划任务
选项:
minute、hour、day、month、weekday
name #定时任务的描述
job #指明运行的命令
user #以哪个用户
state #present 添加,默认设置;absent删除
#新建定时任务
[root@node ~]# ansible all -m cron -a 'name="test cron" minute=*/5 job="/sbin/ntpdate ntp.aliyun.com &> /dev/null"'
[root@node ~]# ansible all -a "crontab -l"
192.168.157.130 | CHANGED | rc=0 >>
#Ansible: test cron
*/5 * * * * /sbin/ntpdate ntp.aliyun.com &> /dev/null
192.168.157.129 | CHANGED | rc=0 >>
#Ansible: test cron
*/5 * * * * /sbin/ntpdate ntp.aliyun.com &> /dev/null
#删除定时任务
[root@node ~]# ansible all -m cron -a 'name="test cron" state=absent'
192.168.157.129 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": []
}
192.168.157.130 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": []
}
[root@node ~]# ansible all -a "crontab -l"
192.168.157.130 | CHANGED | rc=0 >>
192.168.157.129 | CHANGED | rc=0 >>
10.yum模块
软件包管理,只支持RHEL,CentOS,fedora,不支持Ubuntu其它版本
state
present 确保已经安装,但不升级
installed 确认已经安装
latest 确保安装,且升级为最新
absent和removed确认已移除
[root@node ~]# ansible all -m yum -a "name=lrzsz state=present"
[root@node ~]# ansible all -m yum -a "name=lrzsz state=absent"
11.service和systemd
用于服务程序的管理
name
state:
started,stopped,restarted,reloaded
enabled:
yes,no
[root@node ~]# ansible all -m service -a 'daemon_reload=yes'
[root@node ~]# ansible all -m service -a 'daemon_reload=yes'
[root@node ~]# ansible all -m service -a "name=network state=started enabled=yes"
12.user和group
#创建组
[root@node ~]# ansible all -m group -a 'name=user gid=88 system=yes'
#删除组
[root@node ~]# ansible all -m group -a 'name=user state=absent'
#创建用户
[root@node ~]# ansible all -m user -a 'name=user1 comment="test user" uid=2048 home=/data/user1 group=root'
[root@node ~]# ansible all -m user -a 'name=nginx comment=nginx uid=88 group=nginx group=root shell=/sbin/nologin system=yes create_home=no home=/data/nginx non_unique=yes'
#删除目录及家目录等数据
[root@node ~]# ansible all -m user -a 'name=nginx state=absent remove=yes'
13.Setup模块
setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影响执行速度,可以使用gather_facts: no
来禁止 Ansible 收集 facts 信息
[root@node ~]# ansible all -m setup -a 'filter=ansible_nodename' --tree /data
[root@node ~]# tree /data/
/data/
├── 192.168.157.129
└── 192.168.157.130
0 directories, 2 files
四、Ansible-playbook
核心元素
- hosts 执行远程主机的列表
- tasks 任务集
- variables 变量在playbook中调用
- templates 模板
- handlers 和notify结合使用
- tags 标签
实例
[root@node ~]# vim first.yml
- hosts: all
remote_user: root
vars: httpd_port=80
gather_facts: no
tasks:
- name: install httpd
yum: name=httpd state=present
- name: install php
yum: name=php state=present
- name: start httpd
service: name=httpd state=start enabled=ture
说明:
hosts定义单个主机或组,vars定义变量,remote_user定义执行命令的远程用户,tasks定义执行哪些步骤
ansible-playbook filename.yml [options]
常见选项
-C --check #只检测可能会发生的改变,但不真正执行操作
--syntax-check #语法检查
--list-hosts #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的主机执行
-v -vv -vvv #显示过程
tags标签
给playbook中task指定标签,当在执行playbook时,可以只执行特定的tags的task,而非整个playbook文件
[root@node ~]# vim httpd.yaml
- hosts: all
remote_user: root
gather_facts: no
tasks:
- name: install httpd
yum: name=httpd state=present
tags: httpd
- name: install php
yum: name=php state=present
- name: start httpd
service: name=httpd state=start enabled=ture
tags: service
##
语法一:
tags:
- testtag
- t1
语法二:
tags: tag1,t1
语法三:
tags: ['tagtest','t2']
##
[root@node ~]# ansible-playbook --list-tag httpd.yaml #列出tags
playbook: httpd.yaml
play #1 (all): all TAGS: []
TASK TAGS: [httpd, service]
[root@node ~]# ansible-playbook -t httpd,service httpd.yaml #指定tags执行
[root@node ~]# ansible-playbook --skip-tags httpd,service httpd.yaml #跳过tags执行
变量
由字母数字下划线组成,只能以字母开头
种类:
-
facts(内置变量)
有远程主机发回ansible主机的属性信息
ansible 192.168.157.129 -m setup可获取,filter指定过滤项,在ansible-playbook中如果不需要,可禁止:[root@129 ~]#ansible all -m setup -a 'filter=ansible_memory_mb' ### - hosts: all remote_user: root gater_fact: no
- 命令行传递
[root@129 ~]# ansible-playbook -h -e EXTRA_VARS, --extra-vars EXTRA_VARS [root@129 ~]# ansible-playbook test.yml –e httpd_port=80
- yaml文件中定义
--- - hosts: all remote_user: root vars: - username: user1 - groupname: group1 tasks: - name: create group group: name={{ groupname }} state=present - name: create user user: name={{ username }} state=present ... ### vars: nginx: conf80: /etc/nginx/conf.d/80.conf conf8080: /etc/nginx/conf.d/8080.conf 引用 "{{nginx.conf80}}"
- 变量文件定义
[root@node ~]# vi vars.yaml username: user2 groupname: group2 [root@node ~]# vim test.yaml - hosts: all remote_user: root vars_files: - vars.yaml tasks: - name: create group group: name={{ groupname }} state=present - name: create user user: name={{ username }} state=present
- 通过主机或组变量
[web1] 192.168.1.1 name=haha [group_name:vars] foo=bar
handlers和notify
[root@node ~]# vim first.yml
- hosts: all
remote_user: root
gather_facts: no
tasks:
- name: install httpd
yum: name=httpd state=present
- name: config file
copy: src=file/httpd.conf dest=/etc/httpd/conf/
notify: restart httpd
- name: start httpd
service: name=httpd state=start enabled=ture
handlers:
- name: restart httpd
service: name=httpd state=restarted
template模板
命名以j2结尾
模板中可嵌套jinja2语言
#范例1
#temnginx1.yml
---
- host: websrvs
remote_user: root
vars:
nginx_vhosts:
- 81
- 82
- 83
tasks:
- name: config file
template: src=nginx2.conf.j2 dest=/data/nginx2.conf
#templates/nginx.conf1.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost }}
}
{% endfor %}
#生成结果:
server {
listen 81
}
server {
listen 82
}
server {
listen 83
}
#范例2
#temnginx1.yml
---
- host: websrvs
remote_user: root
vars:
nginx_vhosts:
- listen: 81
server_name: "www.web1.com"
root: "/var/www/html/web1"
- listen: 82
server_name: "www.web2.com"
root: "/var/www/html/web2"
- {listen: 83, server_name: "www.web3com", root: "/var/www/html/web3"}
tasks:
- name: config file
template: src=nginx2.conf.j2 dest=/data/nginx2.conf
#templates/nginx.conf1.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
server_name {{ vhost.server_name }}
root {{ vhost.root }}
}
{% endfor %}
#生成结果:
server {
listen 81
server_name www.web1.com
root /var/www/html/web1
}
server {
listen 82
server_name www.web1.com
root /var/www/html/web2
}
server {
listen 83
server_name www.web1.com
root /var/www/html/web3
}
when
when语句可以实现条件判断,然后决定是否执行task。
- hosts: all
remote_user: root
tasks:
- name: install httpd
yum: name=httpd state=present
when: ansible_distribution_major_version == "7"
- name: install php
yum: name=php state=present
when: ansible_distribution_major_version == "7"
- name: start httpd
service: name=httpd state=start enabled=ture
when: ansible_distribution_major_version == "7"
#通过判断ansible_distribution_major_version是否等于7来决定是否执行tasks
with_items
迭代,重复执行task
#简单使用
---
- hosts: all
remote_user: root
tasks:
- name: add users
user: name={{ item }} state=present
with_items:
- testuser1
- testuser2
#上面的语句等同于
- name: add users1
user: name=testuser1 state=present
- name: add users2
user: name=testuser2 state=present
...
#迭代嵌套子变量:在迭代中还可以嵌套子变量,关联多个变量在一起使用
---
- hosts: all
remote_user: root
tasks:
- name: add group
user: name={{ item }} state=present
with_items:
- nginx
- mysql
- apache
- name: add user
user: name={{ item.name }} state=present group={{ item.group }}
with_items:
- { name: 'nginx', group: 'nginx' }
- { name: 'mysql', group: 'mysql' }
- { name: 'apache', group: 'apache' }
五、roles角色
用于层次性、结构化地组织playbook。roles能够根据层次型结构自动化装载变量文件、tasks以及handlers等。多个角色的集合,可以将多个的role,分别放到roles目录下的独立子目录中
roles/
├── httpd
│ ├── files
│ │ ├── httpd.conf
│ │ └── index.html
│ ├── handlers
│ │ └── main.yaml
│ └── tasks
│ ├── config.yml
│ ├── index.yml
│ ├── install.yml
│ ├── main.yml
│ └── service.yml
└── nginx
├── handlers
├── tasks
├── templates
└── vars
---
- hosts: all
remote_user: root
tasks:
- name: 关闭firewalld
service: name:firewalld state=stopped enabled=no
- name: 关闭selinux1
shell: "setenforce 0"
failed_when: false
- name: 关闭selinux2
lineinfile: dest=/etc/selinux/config regexp="^SELINUX=" line="DELINUX=disabled"
- name: 安装常用的软件
yum: name=vim,lrzsz,net-tools,wget,curl,bash-completion,unzip state=latest