这里是网易云课堂·IT技术快速入门学院演示视频中使用的文档,8元小课系列,可以在系列教程中找到该系列所有文章。
QQ交流群(ansible实践互助):955105412。
这篇文档是会不停的更新,这其实是我的个人笔记,工作中每掌握一个ansible的功能,就会在这里记录一点。
ansible-playbook -u root -i inventories/demo/hosts site.yml --limit @/Users/lijiao/Work/Docker/GOPATH/src/github.com/lijiaocn/kubefromscratch-ansible/site.retry
通过ansible管理的机器默认记录在/etc/ansible/hosts
文件中,可以用-i
指定另外的hosts文件。
hosts文件记录了所有的目标机器,以及它们的分组信息,例如:
mail.example.com <--- 机器列表
[webservers] <--- group名称
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com
badwolf.example.com:5309 <--可以指定ssh端口,默认是22
jumper ansible_port=5555 ansible_host=192.0.2.50 <--可以设置别名
hosts文件可以是上面所示的ini格式,也可以是yaml格式:
all:
hosts:
mail.example.com
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
使用yaml设置别名的格式如下:
hosts:
jumper:
ansible_port: 5555
ansible_host: 192.0.2.50
如果host名称类似,可以使用下面的模式:
[webservers]
www[01:50].example.com
[databases]
db-[a:f].example.com
还可以分别指定连接类型和用户名:
[targets]
localhost ansible_connection=local
other1.example.com ansible_connection=ssh ansible_user=mpdehaan
other2.example.com ansible_connection=ssh ansible_user=mdehaan
可以为每个host设置变量:
[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909
默认有all
和ungrouped
两个group,all包括所有的host,ungrouped
是只在all
中的host。
可以将group再打包成一个group,使用:children
后缀:
[atlanta]
host1
host2
[raleigh]
host2
host3
[southeast:children]
atlanta
raleigh
也可以为整个group设置变量,使用后缀:vars
:
[atlanta]
host1
host2
[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
可以将host变量和group变量拆分到group_vars
目录和host_vars
目录中,与group或者host同名的文件中:
/etc/ansible/group_vars/raleigh
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball
如果不使用默认路径,group_vars
和host_vars
应当与hosts文件位于同一个目录中。
变量文件使用yaml格式,如下:
---
ntp_server: acme.example.org
database_server: storage.example.org
也可以在与group和host同名的目录中,创建多个变量文件,需要1.4及以上版本:
/etc/ansible/group_vars/raleigh/db_settings
/etc/ansible/group_vars/raleigh/cluster_settings
可以用下面的方式获取每个host的变量:
""
ansible定义以下这些有特殊含义的变量:
ansible_connection //可以是local、docker、smart、ssh、paramiko
ansible_host
ansible_port
ansible_user
ansible_ssh_pass
ansible_ssh_private_key_file
ansible_ssh_common_args
ansible_sftp_extra_args
ansible_scp_extra_args
ansible_ssh_extra_args
ansible_ssh_pipelining
ansible_ssh_executable (added in version 2.2)
ansible_become
ansible_become_method
ansible_become_user
ansible_become_pass
ansible_become_exe
ansible_become_flags
ansible_shell_type
ansible_python_interpreter
ansible_*_interpreter
ansible_shell_executable
变量使用下面方式引用,具体参考ansible Jinja2 templating:
My amp goes to
template: src=foo.cfg.j2 dest=/foo.cfg
host和group信息还可以从其它系统中动态的获取,ansible Dynamic Inventory。
ansible可以根据playbook文件中的描述,对一组机器进行一系列的操作。
playbook文件是yaml格式的,由每个group的task和handler组成。
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: name=httpd state=latest
- name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:
- restart apache -->触发handlers
- name: ensure apache is running (and enable it at boot)
service: name=httpd state=started enabled=yes
handlers:
- name: restart apache
service: name=httpd state=restarted
task被按照顺序执行,task可以通过notify
触发handlers。被触发的handler是按照它们在文件中的顺序执行的!
上面的task是通过handler的名字触发handler,还可以通过handler中的listen topic进行触发:
handlers:
- name: restart memcached
service: name=memcached state=restarted
listen: "restart web services"
- name: restart apache
service: name=apache state=restarted
listen: "restart web services"
tasks:
- name: restart everything
command: echo "this task will restart the web services"
notify: "restart web services"
handler的名字和listen topic都是全局的,如果重名,只有一个会被执行。
ansible给出了一套实践建议ansible playbook Best Practices。
实践建议1:
production # inventory file for production servers
demo # inventory file for demo environment
group_vars/
group1 # here we assign variables to particular groups
group2 # ""
host_vars/
hostname1 # if systems need specific variables, put them here
hostname2 # ""
library/ # if any custom modules, put them here (optional)
module_utils/ # if any custom module_utils to support modules, put them here (optional)
filter_plugins/ # if any custom filter plugins, put them here (optional)
site.yml # master playbook
webservers.yml # playbook for webserver tier
dbservers.yml # playbook for dbserver tier
roles/
common/ # this hierarchy represents a "role"
tasks/ #
main.yml # <-- tasks file can include smaller files if warranted
handlers/ #
main.yml # <-- handlers file
templates/ # <-- files for use with the template resource
ntp.conf.j2 # <------- templates end in .j2
files/ #
bar.txt # <-- files for use with the copy resource
foo.sh # <-- script files for use with the script resource
vars/ #
main.yml # <-- variables associated with this role
defaults/ #
main.yml # <-- default lower priority variables for this role
meta/ #
main.yml # <-- role dependencies
library/ # roles can also include custom modules
module_utils/ # roles can also include custom module_utils
lookup_plugins/ # or other types of plugins, like lookup in this case
webtier/ # same kind of structure as "common" was above, done for the webtier role
monitoring/ # ""
fooapp/ # ""
或者用下面的方式,将预发布环境和生产环境更好地区分开:
inventories/
production/
hosts # inventory file for production servers
group_vars/
group1 # here we assign variables to particular groups
group2 # ""
host_vars/
hostname1 # if systems need specific variables, put them here
hostname2 # ""
demo/
hosts # inventory file for demo environment
group_vars/
group1 # here we assign variables to particular groups
group2 # ""
host_vars/
stagehost1 # if systems need specific variables, put them here
stagehost2 # ""
library/
module_utils/
filter_plugins/
site.yml
webservers.yml
dbservers.yml
roles/
common/
webtier/
monitoring/
fooapp/
目标机器可以按照地理位置和角色做两级分组:
[atlanta-webservers] <-- 按照角色和地理位置分组
www-atl-1.example.com
www-atl-2.example.com
[boston-webservers]
www-bos-1.example.com
www-bos-2.example.com
[atlanta-dbservers]
db-atl-1.example.com
db-atl-2.example.com
[boston-dbservers]
db-bos-1.example.com
# webservers in all geos <-- 按照角色进行分组
[webservers:children]
atlanta-webservers
boston-webservers
# dbservers in all geos
[dbservers:children]
atlanta-dbservers
boston-dbservers
# everything in the atlanta geo <-- 按照地理位置进行分组
[atlanta:children]
atlanta-webservers
atlanta-dbservers
# everything in the boston geo
[boston:children]
boston-webservers
boston-dbservers
顶层的playbook引入细分的playbook文件:
# file: site.yml
- import_playbook: webservers.yml
- import_playbook: dbservers.yml
细分的playbook中,为host设置role:
# file: webservers.yml
- hosts: webservers
roles:
- common
- webtier
task和handler被拆分到单独的role中,在与role同名的目录下分别有tasks目录和handler目录:
# file: roles/common/tasks/main.yml
- name: be sure ntp is installed
yum: name=ntp state=installed
tags: ntp
- name: be sure ntp is configured
template: src=ntp.conf.j2 dest=/etc/ntp.conf
notify:
- restart ntpd
tags: ntp
- name: be sure ntpd is running and enabled
service: name=ntpd state=started enabled=yes
tags: ntp
# file: roles/common/handlers/main.yml
- name: restart ntpd
service: name=ntpd state=restarted
可以用下面的方式执行指定的playbook:
//重新配置所有的设置
ansible-playbook -i production site.yml
//重新配置所有的NTP
ansible-playbook -i production site.yml --tags ntp
//重新配置所有的webserver机器
ansible-playbook -i production webservers.yml
//重新配置位于波士顿的所有webserver
ansible-playbook -i production webservers.yml --limit boston
//分批重新配置位于波士顿的所有webserver
ansible-playbook -i production webservers.yml --limit boston[1:10]
ansible-playbook -i production webservers.yml --limit boston[11:20]
操作失败的机器列表会存放在一个*.retry文件中,可以用limit指定该文件,从而只在操作失败的机器上进行重试:
ansible-playbook -u root -i inventories/demo/hosts all.yml --limit @all.retry
//注意文件前面需要有@
还可以用serial
控制每次更新的机器数量:
- name: test play
hosts: webservers
serial: 3
- name: test play
hosts: webservers
serial: "30%"
- name: test play
hosts: webservers
serial:
- "10%"
- "20%"
- "100%"
具体参考ansible Delegation, Rolling Updates, and Local Actions
ansible2.5中用loop替代了with_list。
- name: with_list
debug:
msg: ""
with_list:
- one
- two
- name: with_list -> loop
debug:
msg: ""
loop:
- one
- two
Ansible Conditionals,关键字when
tasks:
- shell: echo "I've got '' and am not afraid to use it!"
when: foo is defined
- fail: msg="Bailing out. this play requires 'bar'"
when: bar is undefined
tasks:
- shell: echo "only on Red Hat 6, derivatives, and later"
when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6
ansible提供了大量的module,在task和handler中可以引用这些module。
也可以用下面方式只是使用特定module:
ansible boston -i production -m ping
ansible boston -i production -m command -a '/sbin/reboot'
每个模块有不同的用法,可以参考ansible all modules
- file:
path: /etc/foo.conf
owner: foo
group: foo
mode: 0644
- file:
src: /file/to/link/to
dest: /path/to/symlink
owner: foo
group: foo
state: link
- file:
src: '/tmp/'
dest: ''
state: link
with_items:
- { src: 'x', dest: 'y' }
- { src: 'z', dest: 'k' }
# touch a file, using symbolic modes to set the permissions (equivalent to 0644)
- file:
path: /etc/foo.conf
state: touch
mode: "u=rw,g=r,o=r"
# touch the same file, but add/remove some permissions
- file:
path: /etc/foo.conf
state: touch
mode: "u+rw,g-wx,o-rwx"
# create a directory if it doesn't exist
- file:
path: /etc/some_directory
state: directory
mode: 0755