自动化运维工具ansible
ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能
ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:
- 连接插件connection plugins:负责和被监控端实现通信;
- host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
- 各种模块核心模块、command模块、自定义模块;
- 借助于插件完成记录日志邮件等功能;
- playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。
ansible并不需要启动服务,直接使用即可,就像使用ssh一样
ansible安装
ansible的安装
1.配置安装软件所需要的软件仓库,这里使用的是阿里云的源
cd /etc/yum.repo.d
vim epel.repo
[epel]
name=epel
baseurl=https://mirrors.aliyun.com/epel/7/x86_64/
gpgcheck=0
需要注意的是这个软件源是需要虚拟机联网才能访问到的,
2.yum命令下载安装,检查配置文件
yum install -y ansible
cd /etc/ansible
ll
Ansible任务执行模式分为以下两种:
ad-hoc模式(点对点模块)
使用单个模块,支持批量执行单条命令,相当与在bash中执行一句shell命令
playbook模式(剧本模式)
ansible主要的管理方式,通过多个task的集合完成一类功能,可以理解为多个ad-hoc的配置文件
ac-hoc及其常用模块
Ansible的参数配置文件
Ansible 配置是以ini格式存储数据的,在Ansible中,几乎所有配置都可以通过Ansible的Playbook或环境变量来重新赋值。在运行Ansible命令时,命令将会按照预先设定的顺序查找配置文件
1)ANSIBLE_CONFIG:首先,Ansible命令会检查环境变量,及这个环境变量将指向的配置文件
2)./ansible.cfg:其次,将会检查当前目录下的ansible.cfg配置文件
3)~/.ansible.cfg:再次,将会检查当前用户home目录下的.ansible.cfg配置文件
4)/etc/ansible/ansible.cfg:最后,将会检查在用软件包管理工具安装Ansible时自动产生的配置文件
引用自博客:https://blog.csdn.net/cx881020/article/details/86618937
Ansible 可同时操作属于一个组的多台主机,组和主机之间的关系通过 inventory 文件配置. 默认的文件路径为 /etc/ansible/hosts
也可以使用配置文件中的参数inventory指定该文件的位置
使用ansible
1.在inventory文件(默认路径/etc/ansible/hosts)中加入主机,以及所属的组
不指定主机所属的组的话,会被加入到默认的组ungroup中
cd /etc/ansible
ll
vim hosts
[test] # 组名test,组内两台主机61,62
172.25.60.61
172.25.60.62
2.测试主机是否添加成功
ansible test -m ping -k
# 参数-m匹配指定模块ping,参数-k询问远程登陆的用户身份的密码
# 由于当前默认以root身份ssh远程连接,且未配置免密SSH连接,如果不加-k参数,则会报错
对于执行ansible命令后显示的返回结果,红色——报错,黄色——更改了原配置,绿色——未改变原配置
3.使用copy模块,将文件复制到资源主机
ansible test -m copy -a "src=test.sh dest=/tmp/test.sh mode=755" -k
# 参数-a,指定模块的参数
# 参数src文件源位置,参数dest指定文件目标位置,参数mode指定复制到目标上的文件权限
4.使用shell模块,相当于在目标主机执行了一条shell命令
ansible test -m shell -a "/tmp/test.sh" -k
# 不使用-m参数指定模块的话,默认匹配shell模块
ansible-doc 类似于help命令,用于模块功能及使用的查询
ansible-doc -l 显示所有的可用模块
ansible-doc yum 获取指定模块yum的帮助
为ansible创建用于远程连接并部署服务的用户身份,并配置免密SSH连接资源主机,以及用户授权
由于我们在实际应用时,不可能直接使用root用户身份进行SSH连接(不使用-u参数,默认以当前用户身份进行远程连接,因此也要保证所有主机上的用户信息一致,如,相同的用户名也要保证相同的UID,GID等),那样的权限过大,并不安全。我们需要专门创建一个用户身份,用于ansible的SSH连接通信。同时要为该用户授予一定的权限。上面我们每次都要加-k参数,并输入密码,不但麻烦,而且降低了效率,因此要使用免密连接的方式。
1.在三台主机上建立devops用户,用于ansible的ssh远程连接使用
useradd devops
id devops # 确保在三台主机上,这个用户信息都一致
passwd devops # 设置devops用户密码
2.生成密钥并加密,从而完成免密SSH远程连接访问
su - devops # 切换到devops用户
ssh-keygen # 生成密钥,在~/.ssh中
ssh-copy-id 172.25.60.61 # 对两台机器分别使用生成的免密的密钥进行加密
ssh-copy-id 172.25.60.62
3.测试能否免密远程登陆
ssh 172.25.60.61
ssh 172.25.60.62
4.锁定两台资源主机上的用户密码,并对devops用户授权
passwd -l devops # 不允许使用密码登陆devops用户,只是用于该用户完成免密连接,确保安全性
visudo # 用户授权
5.为了方便,在devops用户家目录下创建目录ansible用于存放该身份的配置文件,而不是使用默认配置文件
cd
ls
mkdir ansible
cd ansible/
ls
vim ansible.cfg # ansible配置文件
[defaults]
inventory=./hosts # 该参数指定了inventory文件的位置
cp /etc/ansible/hosts . # 即上面配置文件inventory参数中指定的文件
vim hosts # 删除原来的内容,指定管理的主机及所属组
[test]
172.25.60.61
[db]
172.25.60.62
ansible test -m ping # 两条命令分别测试上面的配置文件是否编辑成功
ansible db -m ping
pwd # 显示当前位置的绝对路径,注意的是,我们自己写的这个配置文件必须要在这个路径下才有效;在该路径外,我们自己编辑的配置文件无效,只有全局配置文件/etc/ansible/ansible.cfg文件生效
6.测试对devops用户的授权是否成功
ansible test -m copy -a "src=hosts dest=/mnt/hosts" -b
# 在未授权以前,将文件复制到目标主机的/mnt下是会报错的,提示不可写入
# 参数-b相当于在目标主机sudo执行命令,即以被授权的身份执行;不加该参数也是会报错的
7.更改配置文件,使ansible命令简化
vim ansible.cfg
[defaults]
inventory=./hosts
remote_user=devops
[privilege_escalation] # 这些参数是从/etc/ansible/ansible.cfg文件中复制得到
become=True
become_method=sudo
become_user=root
become_ask_pass=False
编辑后的配置文件下,默认使用其内的参数设定,我们就不必再加上-b,-u参数了
8.测试上一步对于配置文件的更改是否生效了
ansible test -m copy -a "src=hosts dest=/mnt/hosts"
# 不加-b参数,仍然执行成功了
playbook
playbook是由一个或多个“play”组成的列表。play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联同起来按事先编排的机制同唱一台大戏。
playbooks的组成部分
Target section: 定义要运行playbook的远程主机组
hosts: hosts用于指定要执行指定任务的主机,其可以是一个或多个由冒号分隔主机组
user: 指定远程主机上的执行任务的用户,还可以指定sudo用户等
Variable section: 定义playbook运行时使用的变量
Task section: 定义要在远程主机上运行的任务列表
name: 每个任务都有name,建议描述任务执行步骤,未通过name会用执行结果作为name
'module:options': 调用的module和传入的参数args
Handler section: 定义task完成后需要调用的任务
notify: 在Task Section在每个play的最后触发,调用在hendler中定义的操作
handler: 也是task的列表
以上说明引用自博客 https://www.jianshu.com/p/c82737b5485c
我的理解就是:
简单的讲,之前的ac-hoc相当于shell命令,是单条指令执行的方式
而playbook则相当于shell脚本,是由多个模块调用的命令(task)的多个主机(play)组成的
示例:推送zabbix服务
准备:
三台虚拟机
处理-服务器 server 172.25.60.60
存储-数据库 db 172.25.60.61
前端-页面 web 172.25.60.62
执行下面的playbook自动推送部署zabbix的前提:
三台主机免密SSH
用户devops均授权
mariadb手动安全初始化(第一次执行deploy.yml后,手动在数据库主机上执行mysql_secure_installation命令)
在ansible文件目录下,执行命令ansible-playbook zabbix/deploy.yml
即可自动部署zabbix服务
接下来访问web前端页面的主机172.25.60.62:/zabbix,即可进行zabbix的初始化,再创建自动注册动作,即可发现server外的另外两台主机61,62
vim deploy.yml
---
- hosts: db
tasks:
- name: install mariadb
yum:
name: mariadb-server,MySQL-python
state: present
- name: config mariadb
copy:
src: my.cnf
dest: /etc/my.cnf
notify: restart mariadb
- name: start mariadb
service:
name: '{{ item }}'
state: started
enabled: yes
loop:
- mariadb
- firewalld
- name: create database zabbix
mysql_db:
login_user: root
login_password: westos
name: zabbix
state: present
notify: import create.sql
- name: create server
mysql_user:
login_user: root
login_password: westos
name: zabbix
password: zabbix
host: '%'
priv: 'zabbix.*:ALL'
- name: copy create.sql
copy:
src: create.sql.gz
dest: /tmp/create.sql.gz
- name: config firewalld
firewalld:
service: mysql
permanent: yes
immediate: yes
state: enabled
handlers:
- name: restart mariadb
service:
name: mariadb
state: restarted
- name: import create.sql
mysql_db:
login_user: root
login_password: westos
name: zabbix
state: import
target: /tmp/create.sql.gz
- hosts: server
tasks:
- name: add zabbix repo
yum_repository:
name: zabbix
description: zabbix 4.0
baseurl: https://mirrors.aliyun.com/zabbix/zabbix/4.0/rhel/7/x86_64/
gpgcheck: no
- name: add update repo
yum_repository:
name: update
description: non-supported
baseurl: https://mirrors.aliyun.com/zabbix/non-supported/rhel/7/x86_64/
gpgcheck: no
- name: install zabbix-server
yum:
name: zabbix-server-mysql,zabbix-agent
state: present
- name: config zabbix-server
copy:
src: /home/devops/ansible/zabbix/zabbix_server.conf
dest: /etc/zabbix/zabbix_server.conf
owner: root
group: zabbix
mode: 640
notify: restart zabbix-server
- name: start zabbix-server
service:
name: "{{ item }}"
state: started
loop:
- zabbix-server
- zabbix-agent
- firewalld
- name: config firewalld
firewalld:
port: 10051/tcp
permanent: yes
immediate: yes
state: enabled
handlers:
- name: restart zabbix-server
service:
name: zabbix-server
state: restarted
- hosts: web
tasks:
- name: add zabbix repo
yum_repository:
name: zabbix
description: zabbix 4.0
baseurl: https://mirrors.aliyun.com/zabbix/zabbix/4.0/rhel/7/x86_64/
gpgcheck: no
- name: add update repo
yum_repository:
name: update
description: non-supported
baseurl: https://mirrors.aliyun.com/zabbix/non-supported/rhel/7/x86_64/
gpgcheck: no
- name: add centos repo
yum_repository:
name: centos
description: centos 7
baseurl: https://mirrors.aliyun.com/centos/7/os/x86_64/
gpgcheck: no
- name: install zabbix-web
yum:
name: zabbix-web-mysql
state: present
- name: config zabbix-web
copy:
src: zabbix.conf
dest: /etc/httpd/conf.d/zabbix.conf
notify: restart httpd
- name: start httpd
service:
name: "{{ item }}"
state: started
loop:
- httpd
- firewalld
- name: config firewalld
firewalld:
service: http
permanent: yes
immediate: yes
state: enabled
handlers:
- name: restart httpd
service:
name: httpd
state: restarted
- hosts: agent
tasks:
- name: add zabbix repo
yum_repository:
name: zabbix
description: zabbix 4.0
baseurl: https://mirrors.aliyun.com/zabbix/zabbix/4.0/rhel/7/x86_64/
gpgcheck: no
- name: install zabbix-agent
yum:
name: zabbix-agent
state: present
- name: config zabbix-agent
template:
src: zabbix_agentd.conf.j2
dest: /etc/zabbix/zabbix_agentd.conf
owner: root
group: root
mode: 644
notify: restart zabbix-agent
- name: start zabbix-agent
service:
name: "{{ item }}"
state: started
loop:
- zabbix-agent
- firewalld
- name: config firewalld
firewalld:
port: 10050/tcp
permanent: yes
immediate: yes
state: enabled
handlers:
- name: restart zabbix-agent
service:
name: zabbix-agent
state: restarted