一、概述
- ansible:python编写的自动化引擎,实现了批量系统配置、批量程序部署、批量运行命令等
- 优点:
- 安装简单:被控端无需安装任何软件
- 基于SSH配置:加密通信,安全
- 模块、playbook及role:模块话操作、分享平台、批量命令编辑
- 命令格式:
ansible 服务器匹配 -m 模块名 -a "参数"
二、 安装
2.1 控制端
- 代码示例
# centos yum install ansible -y
2.2 被控制端
- docker模拟被控制端
# 无操作服务权限:避免报错无法获取D总线连接,如果需要用host网络加参数--network host docker run -itd --name centos7 --privileged centos:7 init # 进入docker容器 docker exec -it centos7 bash # 安装systemctl yum install initscripts -y # 安装网络工具:如ping、ifconfig yum install net-tools -y # 安装ssh yum install openssh-server -y # 安装epel yum install epel-release
偷懒测试:被控制端为本机,域名为
localhost
或者IP127.0.0.1
,不用输入密码 - centos系统SSH设置
# /etc/ssh/sshd.conf # 允许ssh密码登陆:打开此两行 PasswordAuthentication yes PermitRootLogin yes >>> systemctl restart sshd # 修改root密码:两遍,不显示输入 >>> passwd
2.3 连接测试(控制端)
- /etc/ansible/hosts
# 控制主机列表 [test] # 密码包含特殊符号,需要使用双引号,第三节详解 172.17.0.4 ansible_user=root ansible_password="xxx"
官方配置文件夹:优先
/etc/ansible
、次优先/root/.ansible
- 命令
# 指定主机列表、指定模块(此处ping以ssh连接目标机测试) # become即权限提升,即Linux中的sudo >>> ansible test -m ping -become 172.17.0.4 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" }
报错:“msg”: "Failed to connect to the host via ssh
解决:删除/root/.ssh/known_host
三、Inventory管理
3.1 简介
- Inventory:管理的服务器集合
- hosts文件指定
- 默认:/etc/ansible/hosts
- 命令行指定:当前目录下查找
ansible test -i hosts -m ping
- 配置文件指定(常用):/etc/ansible/ansible.cfg中
[defaults]
标签
3.2 命令
- /etc/ansible/hosts修改如下
mail.doubi.com [test] 172.17.0.4 [webservers] api.doubi.com doubi.com [dbservers] one.doubi.com two.doubi.com [common:children] webservers dbservers
批量写法:
web[1:10].doubi.com
,代表 web1.doubi.com到web10.doubi.com - 代码示例
# 显示所有的服务器 >>> ansible all --list-hosts hosts (6): 172.17.0.4 mail.doubi.com api.doubi.com doubi.com one.doubi.com two.doubi.com # 显示指定组的服务器 >>> ansible webservers --list-hosts hosts (2): api.doubi.com doubi.com # 显示所有common写法组的服务器 >>> ansible common --list-hosts hosts (4): api.doubi.com doubi.com one.doubi.com two.doubi.com
3.3 服务器匹配
- 规则列表
规则 含义 192.168.0.1或web.doubi.com 单服务器匹配,若多个用冒号分隔 webservers 匹配组名,多个用冒号分隔 all或’*’ 匹配所有 webservers:!dbservers 在web组不在db组,&替换!表示又在…又在… 192.168.0.* 通配符法 webserver[1:2] 索引号匹配组中服务器 ~(web|db).*.doubi.com
以~开头的表示正则表达式匹配
3.4 Inventory行为参数
- 行为参数列表
名称 默认值 描述 ansible_host 主机的名称 SSH目的主机名或IP ansible_user 当前用户 SSH连接的用户名 ansible_port 22 SSH连接的端口号 ansible_ssh_private_key_file none 连接使用的私钥,也可以在ansible.cfg中指定 ansible_python_interpreter /usr/bin/python 使用哪个python解释器 - /etc/ansible/hosts
# 定义SSH登陆用户名、登陆密码 172.17.0.6 ansible_user=root ansible_password="xxx"
- 定义服务器变量
# 定义单个服务器变量,后续yaml引用 # 当前服务器也可以当作远程服务器来管理 127.0.0.1 mysql_port=3306 [db] one.doubi.com two.doubi.com # 定义组服务器变量 [db:vars] mysql_port=3306
四、ansible模块
4.1 基础功能
4.1.1 ping模块
- 功能:测试SSH服务器连通状况,非icmp的ping测试
- 代码示例
# 如下表示SSH连接服务器正常 >>> ansible localhost -m ping localhost | SUCCESS => { "changed": false, "ping": "pong" }
4.1.2 远程命令模块
- 功能:在远程Linux服务器上执行命令
- 代码示例
# command(默认模块):不可使用管道 >>> ansible test -a 'ls' 172.17.0.4 | CHANGED | rc=0 >> anaconda-ks.cfg # shell模块(一):可以使用管道,修改root密码 >>> ansible test -m shell -a "echo 123 | passwd --stdin root" 172.17.0.4 | CHANGED | rc=0 >> Changing password for user root. passwd: all authentication tokens updated successfully. # shell模块(二):运行服务器上的脚本(绝对路径) ansible test -m shell -a '/root/123.sh' 172.17.0.4 | CHANGED | rc=0 >> 123.sh anaconda-ks.cfg
docker:如果用docker-compose管理docker,可以用copy模块和shell模块进行操作
4.2 文件操作
4.2.3 file模块
- 功能:操作远程服务器上的文件和目录
- 参数列表
参数名 解释 path 文件、文件夹路径 recurse 递归设置文件属性,只对文件夹有效,开启 recurse=yes
src、dest 创建链接时使用,state=link/hard,源文件或者目录\目标文件或者目录 mode、owner、group、attributes 指定远程主机文件及文件夹的权限、所有者、所有组、特殊属性 state 状态包括:
file:文件,文件若不存在不会创建
link:软链接
directory:文件夹,文件夹不存在则创建
hard:硬链接
touch:创建文件,若存在则更新访问时间和修改时间
absent:删除文件、链接、文件夹force 强制创建软连接:开启 force=yes
使用场景:1、源文件不存在之后会建立;2、目标软连接已存在,会先取消旧的后创建新的 - 用法示例
# 创建软连接 >>> ansible test -m file -a 'src=/root/a.sh dest='/root/b.sh' state=link' 172.17.0.4 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "dest": "/root/b.sh", "gid": 0, "group": "root", "mode": "0777", "owner": "root", "size": 12, "src": "/root/a.sh", "state": "link", "uid": 0 } # 创建目录 >>> ansible 远程host -m file -a 'path=路径 state=directory' # 创建文件 >>> ansible 远程host -m file -a 'path=路径 state=touch' # 创建文件并指定owner,group,mode等 >>> ansible 远程host -m file -a 'path=目录 state=touch owner=拥有者 group=所属组 mode=权限' # 递归修改owner,group,mode >>> ansible 远程host -m file -a 'path=目录 recurse=yes owner=拥有者 group=所属组 mode=权限 recurse=yes' # 删除目录(强制删除其内文件) >>> ansible 远程host -m file -a 'path=目录 state=absent' # 删除文件 >>> ansible 远程host -m file -a 'path=路径 state=absent'
4.2.4 copy模块
- 功能:将管理端文件或目录拷贝到远程服务器上
- 参数列表
参数名 解释 src 管理端的文件或目录,目录可相对目录dir/test,目录末尾有/表示目录内文件,无/表示文件夹,一级目录若为空则不拷贝 dest 被管理端目标目录或者文件的绝对路径 force 默认yes:若文件md5值不同则强制覆盖被管理端文件或文件夹,no:只有在目标主机不存在此文件时才创建 backup 拷贝动作执行之前,先备份被管理端原始文件,原文件名.backup,默认no directory_mode 递归设置目录权限,默认为系统默认权限 其他 file模块里所有选项都可以
4.2.5 unarchive模块
- 功能:拷贝压缩包到远程,再解压缩
- 参数列表
参数名 解释 src tar源路径,可以是ansible主机上的路径,也可以是远程主机上的路径,如果是远程主机上的路径,则需设置copy=no dest 远程主机上的目标绝对路径 mode 设置解压缩后的文件权限 exec 列出需要排除的目录和文件 remote_src 设置remote_src=yes为解包目标上已经存在的档案 owner 解压后文件或目录的属主 group 解压后的目录或文件的属组 - 操作示例
# 在远程主机上解压文件并设置权限 ansible test -m unarchive -a 'src=/srv/tomcat8/apache-tomcat.tar.gz \ dest=/usr/local copy=no mode=0755' # 解压管理机上的压缩文件到远程主机并设置权限 ansible test -m unarchive -a "src=/tmp/install/zabbix.tar.gz \ dest=/tmp/ mode=0755 copy=yes"
4.2.6 stat模块
- 功能:获取远程服务器文件信息
- 参数列表
参数名 解释 path 必选项,文件或目录绝对路径 atime/ctime/mtime 访问时间、修改时间、属性修改时间 uid/gid 用户和组ID checksum 文件的校验和
4.3 系统服务
4.3.1 user/group模块
- 功能:管理远程服务器上的user和group
- 参数列表
参数名 解释 参数名 解释 name 操作的用户名或群组名 comment 用户描述信息 createhome 创建家目录,默认yes home 指定用户的家目录 group 创建用户主组 groups 指定用户组 或 附属组添加,覆盖式添加 system 默认创建普通用户no,系统用户yes append 添加一个新的组 uid 指定用户id gid 指定群组id password 指定用户的密码,此处需转换明文密码 update_password 修改用户密码,配合always使用 shell 设置用户的shell,非登陆用户 /sbin/nologin
expire 指定用户过期时间戳,Linux查询 date -d2020-12-31 +%s
state 增删用户或群组,默认为present新建,absent删除 force 强制删除 - 用法示例
# 创建用户 ansible 远程host -m user -a "user=test group=root" # 创建无登陆权限无home目录的用户 ansible 远程host -m user -a "user=test shell=/sbin/nologin createhome=no" # 删除用户:1 不删除home文件夹 2 删除文件夹 ansible 远程host -m user -a "name=test state=absent" ansible 远程host -m user -a 'name=test state=absent remove=yes' # 用户增组:test用户新增nginx组,默认组test,附加组nginx ansible 远程host -m user -a "name=test append=yes groups=nginx" # 修改默认组:默认组nginx,附加组也为nginx ansible 远程host -m user -a "name=test group=nginx" # 修改附加组:默认组nginx,附加组也为nginx ansible 远程host -m user -a "name=test groups=test" ################################################################# # 设置用户密码:ansible不认明文密码,需设置加密密码 pip3 install passlib # 将123加密:返回密文 python3 -c "from passlib.hash import sha512_crypt; \ print(sha512_crypt.encrypt('123'))" # 设置密码 ansible 远程host -m user -a "name=duke password=密文" # 变更密码 ansible 远程host -m user -a "name=duke password=密文 update_password=always" ################################################################# # 增组 ansible 远程host -m group -a "name=test" # 删组 ansible 远程host -m group -a "name=test state=absent"
4.3.2 cron模块
- 功能:管理远程服务器上的计划任务
- 参数列表
参数名 解释 name 计划任务名称,会以注释的方式写入文件 cron_file 替换客户端该用户的任务计划的文件 minute 分( 0-59 ,* ,*/5 ),(具体第几分,每分,每5分钟),计划任务的最小单位 hour 时( 0-23 ,* ,*/5 ) day 日( 1-31 ,* ,*/5 ) month 月( 1-12 ,* ,*/5 ) weekday 周( 0-6 或 1-7 ,* ) special_time reboot(重启后)、yearly(每年)、monthly(每月)、weekly(每周)、daily(每天)、hourly(每时),不写时间是每分 job 任务命令内容,要有state=present backup 修改删除之前先备份,默认 no,备份位置为 /temp user 指定操作哪一个用户的 cron state 指定创建或删除任务: present、absent
计划任务执行时机:crond 命令每分钟检查是否有要执行的工作,有则执行, 新建 cron 任务,不会马上执行,至少要过 2 分钟后才可以,可重启 cron 立即执行
- 操作示例
# 查看被管理机的计划任务列表 >>> ansible test -a "crontab -l" # 查看被管理机 >>> ansible test -a "systemctl status crond" # 管理机上操作如下命令设置计划任务 # 新增计划任务:每三天的1:05和1:15分执行一次 ansible test -m cron -a "name='check fix time' minute=5,15 hour=1 \ day=*/3 job='/root/test.sh'" # 特殊写法:每天的 ansible test -m cron -a "name='check daily' special_time=daily \ job='/root/test.sh'" # 删除计划任务 ansible test -m cron -a "name='check reboot' state=absent"
4.3.3 yum模块
- 功能:管理远程服务器上的软件的安装、升级、卸载,支持红帽.rpm软件的管理
- 参数列表
参数名 解释 conf_file 设定远程yum执行时所依赖的yum配置文件 disable_gpg_check 安装软件包之前是否坚持gpg key; name 需要安装的软件名称,支持软件组安装; update_cache 安装软件前更新缓存; enablerepo 指定repo源名称; skip_broken 跳过异常软件节点; state 软件包状态:安装present、最新latest、卸载absent - 代码示例
# 安装软件前先更新缓存 ansible test -m yum -a "name=nmap state=present update_cache=yes" # 安装rpm ansible test -m yum -a "name=http://nginx.org/.../na.rpm state=present" # 卸载软件 ansible test -m yum -a "name=nmap state=absent"
4.3.4 service模块
- 功能:管理远程服务器的服务
- 参数列表
参数名 解释 enabled 开机启动,默认no name 服务名称 state 服务状态:started, stopped, restarted, reloaded - 操作示例
# 开启crond服务,并设置开机启动 ansible test -m service -a "name=crond state=started enabled=yes" # 重新加载配置文件 ansible test -m service -a "name=crond daemon_reload=yes"
4.4 其他
4.4.1 get_url模块
- 功能:用于从http、ftp、https服务器上下载文件(类似于wget)
- 参数列表
参数名 解释 url 必选项,下载的URL, url=http://...
dest 必选项,文件绝对路径,若为目录,采用服务器提供的文件名 checksum 文件校验码, checksun=md5:...
backup 如果本地已存在,备份本地文件 timeout 下载超时时间,默认10s url_password、url_username 主要用于需要用户名密码进行验证的情况 headers 以格式“key:value,key:value”为请求添加自定义HTTP标头
五、剧本playbook
- yaml:JSON格式属于YAML的子格式,后端流行配置文件格式
- 语法特点: 缩进为两个空格,禁tab,大小写敏感,#为注释
5.1 yaml语法
- 数据类型
写法 注释 name:duke 字符串字典 male:yes 字典布尔值 age:18 字典数字 birthday:2020-01-01 字典日期 time:2018-02-17T15:02:31+08:00 +后面为时区 parent: ~ null写法 - list 列表,首元素为字符串[‘list’] - auth:yes 列表,首元素为字典[{‘auth’:True}]
5.2 playbook写法
5.2.1 常规演示
- python解析yaml
# pip3 install pyyaml import yaml with open('test.yml','r') as f: # 解析yaml文件为字典,loader指定默认加载器,否则报错TypeError config= yaml.load(f, Loader=yaml.FullLoader) # 输出如下 print(config)
- /root/test.yml
# yml文件以三个横杠开篇 --- # - 为列表标识,默认以map格式包住各个元素,即[{},{},{}] # 列表索引值为0 # hosts\tasks为必选项 - hosts: dbservers # yaml附加选项,此处为是否允许权限提升 become: yes tasks: # 经测试,-与name同行效果一样 - name: install nmap # 模块名称作为键,参数作为值 # 多参数换行写法 yum : # 使用变量的写法 # 针对5.2.2循环name: "{{ item }}" name: nmap state: present update_cache: yes # 列表索引值为1 - hosts: webservers tasks: # 以下为tasks[0] - name: change mode copy: src=/tmp/data.txt dest=/tmp/data.txt # 以下为tasks[1] - # 以下为tasks[1]['name']返回'make file' name: make file file: path=/root/data.txt state=touch
- python解析后输出
[ { 'hosts': 'dbservers', 'become': True, 'become_method': 'sudo', 'tasks': [ {'name': 'install nmap', 'yum': 'name=nmap state=present update_cache=True' } ] }, { 'hosts': 'webservers', 'tasks': [ {'name': 'change mode', 'copy': 'src=/tmp/data.txt dest=/tmp/data.txt'}, {'name': 'make file', 'file': 'path=/root/data.txt state=touch'} ] } ]
5.2.2 附加选项
- 权限
# 指定执行play的用户,默认用当前用户连接远程服务器 --- - hosts: webservers remote_user: duke ########################################### # 细分特定task用户 --- - hosts: dbservers tasks: - name: test connection ping: remote_user: duke ########################################### # 常用:全局采用一个用户,特定任务用管理员权限 --- - hosts:dbservers remote_user: duke tasks: - service: name=nginx state=started become: yes become_method: sudo
- 通知notify
--- - hosts: webservers tasks: - name: 确定apache已安装且是最新版 yum: name=httpd state=latest - name: 拷贝apache配置文件 copy: src=/root/httpd.conf dest=/etc/httpd.conf # 若当前task改变了服务器,则触发通知notify notify: # 匹配handler中的对应name - 重启apache - name: 确定apache已经运行 service: name=httpd state=started handlers: - name: 重启apache service: name=httpd state=restarted
handler触发时机:在playbook所有任务执行完成后再执行,多次触发仅执行一次
功能:官方推荐用来重启服务或服务器
- 变量var
--- - hosts: webservers # 变量写法一:变量较少 vars: mysql_port: 80 # 变量写法二:变量较多 vars_files: - /vars/external_vars.yml tasks: - name: 生成apache配置文件 # 模版模块:前者是jinja2模版,后者是目标服务器文件位置 # jinjia2模版可以直接使用vars中的变量 template: src=/root/httpd.j2 dest=/etc/httpd.conf
- external_vars.yml内容:
--- password: 123 somevar: somevar ...
- jinja2语法:详见Python运维(五)
- facts变量:自动获取远程服务器参数,不需设置直接可使用,可由
ansible all -m setup
查看,嵌套数据获取ansible_eth0.ipv4.address
- external_vars.yml内容:
- 循环
--- - hosts: webservers tasks: - name: 批量安装软件 # item会从下面的loop中依次读取 yum: name={{ item }} state=latest update_cache=yes loop: - python3 - net-tools
- 条件判断
--- - hosts: webservers tasks: - command: /usr/bin/ls # 将此task的返回值保存到result变量中 register: result # 如果遇到报错,忽略,继续执行后续task,否则直接跳出 ignore_errors: yes - ping: when: # 提取变量result中的返回码 - result.rc==0 # facts变量可直接使用,见上变量注释 - ansible_os_family=="RedHat" # debug模块:会在控制端终端打印变量 # 以下语句效果相同 # - debug: msg={{ result }} 或 # - debug: #. msg: "{{result}}" - debug: var=result
5.3 命令行运行playbook
- 命令写法及注释
# 执行yml文件,远程主机目录默认/etc/ansible/hosts # 参数随后添加,见下表 ansible-playbook test.yml # 每进行一个任务等待用户确认继续 ansible-playbook test.yml --step
- 参数列表
写法 注释 - T 或–timeout 设置建立SSH超时时间 –private-key 密钥路径 设置SSH连接的私钥文件 -i host文件路径 指定host文件位置,默认/etc/ansible/hosts –list-hosts 列出playbook的匹配服务器列表 –list-tasks 列出playbook的任务列表 –syntax-check 检查playbook语法 –check 检查当前playbook是否会修改远程服务器
5.4 role
- 概述:roles是将playbook各项进行拆分,并形成模块化目录组织结构,还可以从线上社区仓库下载最受欢迎的role
- 特点
- 专一性:一个role只包含一个单一、明确的操作
- 非必需性:role的每个文件夹都不是必须的,按需删除
- 简洁性:编写playbook时可以引用role大幅简化配置
- role管理命令
# 初始化一个roles的目录结构:默认在当前文件夹创建 ansible-galaxy init /root/.ansible/roles/websrvs # 安装线上nginx的roles:https://galaxy.ansible.com ansible-galaxy install geerlingguy.nginx # 列出已安装的roles ansible-galaxy list # 卸载roles ansible-galaxy remove geerlingguy.nginx
- 新建的role目录结构
# galayx默认下载到/root/.ansible/roles目录下 # 在此roles目录下运行init命令 /root/.ansible/roles/websrvs/ ├── defaults # 默认可被覆盖的变量 │ └── main.yml ├── files # 静态文件,可拷贝进目标服务器 ├── handlers # 所有handler │ └── main.yml ├── meta # role依赖 │ └── main.yml ├── README.md # 说明文件 ├── tasks # 任务列表 │ └── main.yml ├── templates # jinja2模版 ├── tests # 测试区域 │ ├── inventory │ └── test.yml └── vars # 不可被覆盖的变量
- 所有main.yml
# main将当前文件夹的a.yml和b.yml按顺序插入进来 --- - include: a.yml - include: b.yml
- playbook的role写法
# /root/.ansible/site.yml --- - hosts: webservers # 直接写文件夹名称 - roles: - geerlingguy.nginx - websrvs
- 运行:
ansible-playbook site.yml