配置Inventory
Ansible把主机与主机分组信息的配置称为Inventory,默认路径为/etc/ansible/hosts
。
如果在ssh配置文件(~/.ssh/config
)有如下配置
Host dev-server
HostName 111.223.19.18
Port 1212
User someone
Host test-server
HostName 111.223.19.10
User someone
那么可以在ansible的hosts
文件中直接使用这些主机名,例如
dev-server:1212
test-server
注意需要在这里显示地指定ssh端口。
也可以通过以下方式为主机定义别名:
host_alias ansible_ssh_host=192.168.0.73 ansible_ssh_port=2121 ansible_ssh_user=username
Ansible模块
Ansible包含了众多模块,用于完成常见的运维任务。可通过ansible-doc
命令查看模块文档。
ansible-doc file
Ansible playbook
ansible playbook使用的是YAML格式
列出playerbook里的任务
ansible-playbook mezzanine.yml --list-tasks
使用标签(tags)
若想有选择地执行playbook里的部分任务应该怎么办呢?这个时候就要用到标签(tags)。
- name: build bell.api
shell: "{{ home }}//bin/my_program my_args"
tags:
- java
args:
executable: /bin/bash
下面的命令执行带有java
或run
标签的所有任务:
ansible-playbook -i hosts --ask-become-pass centos-web.yml --tags "java,run"
下面的命令执行java
标签外的所有任务
ansible-playbook -i hosts --ask-become-pass centos-web.yml --skip-tags "java"
引用变量文件
可将变量集中定义在某一文件里,通过vars_files
指令引入,其后可以像使用本地变量那样使用这些变量。
vars_files:
- secrets.yml
复杂参数
同一任务的参数较多时,可能造成难以阅读,将字符串参数转换为字典格式,以上面的检出git仓库的代码为例:
- name: checkout a git repo
git:
repo: "{{ repo_url }}"
dest: "{{ proj_path }}"
accept_hostkey: True
关闭facts采集
可在playbook中声明gather_facts: False
,这样做可能是因为
- 运行playbook的时候,服务器可能还没有开始运行,facts采集会失败;或
- 关闭facts采集,减少ansible执行任务的等待时间
但需要注意,关闭facts采集后,主机信息相关的参数也变得不可用。
逐台运行,不允许失败
如果全部并行执行,负载均衡后的服务器可能在某段时间全部失败。为避免此类情况,可让任务串行执行:
serial: 1
max_fail_percentage: 0
只执行一次
让任务在多台服务器上只执行一次,也就是说对于同一个任务,在任意一台主机上执行成功后将不会在其它主机上再执行。 应用场景如数据库迁移或依赖库代码初始化
run_once: true
使用条件判断(conditionals )
见conditionals文档, 比如when
修改任务状态的判断条件
这里的状态是指任务执行结束时,ansible判定的changed
或failed
状态。可通过changed_when
或failed_when
修改自定义判断方法。
启用pipeline
需要关闭/etc/sudoers/
里的requiretty
[ssh_connection]
pipelining = True
fact缓存
[defaults]
# smart - gather by default, but don't regather if already gathered
# implicit - gather by default, turn off with gather_facts: False
# explicit - do not gather by default, must say gather_facts: True
gathering = smart
fact_caching_timeout=86400
fact_caching=jsonfile
fact_caching_connection=/tmp/ansible_fact_cache
一些常见任务
ping - 测试与服务器的连接
ansible -i hosts all -m ping
上传文件
- name: copy file/directory
synchronize:
src: /local-path/
dest: /remote-path/
删除远程文件
- name: delete remote file/path
file:
state: absent
path: "/remote/path/"
执行远程shell命令
ansible dev-server -m shell -a "ps aux |grep java"
如果用ansible-playbook,则用如下配置
- name: restart docker
shell: docker restart $(docker ps -aqf 'name=mydocker-image-name)
这个例子通过镜像名查找正在运行的docker容器ID,并重启这个容器。注意这里要使用shell
而非command
模块,因为后者会解析命令行参数,导致错误
本地命令
使用local_action
模块。例如检查本地文件是否存在:
- name: Check for {{ dump_root }}
local_action: stat path="{{ dump_root }}"
register: stat_path_dump_root
从源码安装nginx
参考https://github.com/nickjj/ansible-nginx或https://github.com/ANXS/nginx
定义安装软件包的任务
下面的代码片断在远程主机使用Debian 系统的apt
命令安装aptitude, python3-pip
等软件包。
- hosts: my_web_servers
gather_facts: no
become: yes
become_method: sudo
tasks:
- name: install pip3
apt:
name: "{{pkg}}"
state: latest
vars:
pkg:
- aptitude
- python3-pip
检出git仓库的代码
- name: checkout a git repo
git: repo={{ repo_url }} dest={{ proj_path }} accept_hostkey=yes
在控制主机上打开Agent Forwarding
,编辑ansible配置文件,如/etc/ansible/ansible.cfg
,
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ForwardAgent=yes
通过pip安装python软件包
可使用requirements.txt文件安装软件包,注意调用前必须先将此文件上传到远程服务器:
- name: install python packages
pip:
requirements: requirements.txt
extra_args: --user
executable: pip3
state: present
MySQL数据库初始化
数据库初始化包含自动创建数据库与数据库用户,对于MySQL数据库,可以参考以下文档
常见问题
sudo的问题
使用远程sudo时,
ansible all -m ping --sudo
如果没有在远程主机上配置sudo免密,则会出现错误"module_stdout": "sudo: a password is required\r\n"
。这时候有两种选择,要么为远程sudo用户设置免密sudo权限,要么在执行ansible命令时输入远程sudo密码。
设置免密sudo权限
需要通过sudo visudo
(或sudo visudo -f /etc/sudoers
)命令编辑/etc/sudoers
文件,将其中的your_username
改为远程主机的用户名。
your_username ALL=(ALL) NOPASSWD:ALL
也可以对整个sudo用户组免密,例如对Centos系统,添加下面一行
%wheel ALL=(ALL) NOPASSWD: ALL
在执行ansible命令时输入远程sudo密码
添加-ask-sudo-pass
选项,如
ansible -i hosts --sudo -ask-sudo-pass playhost -m ping
在新版ansible里,用--ask-become-pass
,如
ansible-playbook -i hosts --ask-become-pass centos-web.yml
执行远程脚本错误
远程脚本如果没有开头的#!/bin/bash
,使用ansible的command
模块则可能报错: [Errno 8] Exec format error
sudo: sorry, you must have a tty to run sudo
编辑sudo visudo /etc/sudoers
, 注释Defaults requiretty
使用synchronize模块与delegate_to同步文件时很慢
- 首先确保两台过程主机间
rsync
是正常的 - 在
/etc/ansible/ansible.cfg
中配置ssh连接选项(ssh_connection
),即在默认配置上添加-o ForwardAgent=yes
- 配置
ControlPersist
为保持SSH连接的时长[ssh_connection] ssh_args=-o ControlMaster=auto -o ControlPersist=60s -o ControlPath=/tmp/ansible-ssh-%h-%p-%r -o ForwardAgent=yes
一个完整示例
下面的示例演示了如何在远程准备python3执行环境,上传脚本并执行的操作。
---
- hosts: example
gather_facts: no
become: yes
become_method: sudo
tasks:
- name: install pip3
apt:
name: "{{pkg}}"
state: latest
vars:
pkg:
- aptitude
- python3-pip
- name: feedly
hosts: "example"
gather_facts: False
vars:
path: /home/user/fd
home: /home/user
token: "my_fd_token"
tasks:
- name: Synchronization files
synchronize:
src: ./
dest: "{{ path }}"
- name: install python packages
pip:
requirements: "{{ path }}/requirements.txt"
extra_args: --user
executable: pip3
state: present
- name: run feedly
shell: FEEDLY_TOKEN="{{ token }}" python3 feedly_to_epub.py
args:
chdir: "{{ path }}"
executable: /bin/bash
参考
- Ansible中文文档与英文文档
- Ansible模块列表
- 安装Ansible