ansible的使用入门

作者: 李佶澳   转载请保留:原文地址   发布时间:2018/03/12 15:43:00

说明

ansible是一个常用的运维管理工具。ansible documents

重试

ansible-playbook -u root -i inventories/staging/hosts site.yml  --limit @/Users/lijiao/Work/Docker/GOPATH/src/github.com/lijiaocn/kubefromscratch-ansible/site.retry ## host管理

通过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

group管理

默认有allungrouped两个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_varshost_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

playbook

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
staging                   # inventory file for staging 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        # ""

   staging/
      hosts               # inventory file for staging 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/staging/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

语法

循环、遍历

Ansible Loops

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

常用模块

authorized_key

file

- 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

参考

  1. ansible documents
  2. ansible Dynamic Inventory
  3. ansible playbook Best Practices
  4. ansible Delegation, Rolling Updates, and Local Actions
  5. ansible Jinja2 templating
  6. ansible all modules
  7. how to access host variable of a different host with Ansible?
  8. Ansible Loops
  9. Ansible Conditionals
  10. ansible special variables

限时活动,每邀请一人即返回25元!

Copyright @2011-2018 All rights reserved. 转载请添加原文连接,合作请加微信lijiaocn或者发送邮件: lijiaocn@foxmail.com,备注网站合作 友情链接: lijiaocn github.com