自动化运维工具Ansible之Playbooks基础应用

记得自己当初最早使用Ansible的时候,网上搜到的中文资料的都是零零散散的,后来只能硬着头皮看官方的英文文档。发现好多事情都没有什么捷径可走,最好的资料还是官方的文档。最近又抽时间按照官方文档对Ansible做了一个较为系统的学习与研究,主要是为了整理一份较为完善的学习笔记供自己以后查阅,哎,年纪大了,记性不好了,写文档才能把有些细节记下来。


Playbooks可以称为是Ansible的配置,部署,编排语言。在Playbooks中,你可以定义远程节点要执行的某组动作。如:希望远程节点要先安装httpd,创建一个vhost,最后启动httpd。


Playbooks使用了YAML格式,具有较少的语法格式。其特意的避免将自己设计为一门语言或者脚本,而是一个纯粹的配置和过程模型。
每个playbooks都有一个或者多个play组成。
play简单来说就是一些主机节点要执行一些任务。最基本的,一个任务也就是调用一个Ansible模块。
通过为Playbooks编写多个play ,可以协调多主机的部署。如,按照一定的步骤在webservers组内的所有主机上执行操作,然后按照一定的步骤在databaseserver组内的主机上执行,然后再有其他更多的命令在webservers组内主机上执行,等等。


下边是个只包含一个play的playbooks:

[root@web1 ~]# cat /etc/ansible/http.yml
---
- hosts: webservers
vars:
 http_port: 80 #定义变量
 max_clients: 200 #定义变量
 remote_user: root
tasks:
 - name: ensure apache is at the latest version
   yum: pkg=httpd state=latest
 - name: write the apache config file
   template: src=/etc/ansible/httpd.j2 dest=/etc/httpd.conf
 notify:
  - restart apache
 - 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
[root@web1 ~]# ansible-playbook /etc/ansible/http.yml
PLAY [webservers] *************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.1.65]
TASK: [ensure apache is at the latest version] ********************************
changed: [192.168.1.65]
TASK: [write the apache config file] ******************************************
changed: [192.168.1.65]
TASK: [ensure apache is running (and enable it at boot)] **********************
changed: [192.168.1.65]
NOTIFIED: [restart apache] ****************************************************
changed: [192.168.1.65]
PLAY RECAP ********************************************************************
192.168.1.65 : ok=5 changed=4 unreachable=0 failed=0

上边的playbooks只定义了对webservers组内的主机所执行的一系列任务。

在模板httpd.j2中会引用上边定义的两个变量,如{{ max_clients }}

notify表示当配置文件发生变化时会触发restart apache动作 handlers定义一些要
被触发的动作。


playbooks也可以包含多个play ,如下边的示例,在同一个playbooks中既可以对web servers组操作,也可以对datavase servers组操作:

---
- hosts: webservers
  remote_user: root
  tasks:
    - name: ensure apache is at the latest version
      yum: pkg=httpd state=latest
    - name: write the apache config file
      template: src=/srv/httpd.j2 dest=/etc/httpd.conf
- hosts: databases
  remote_user: root
  tasks:
   - name: ensure postgresql is at the latest version
     yum: name=postgresql state=latest
   - name: ensure that postgresql is started
     service: name=postgresql state=running

play就像任务一样按照在playbooks中的定义顺序从上到下依次执行。


Playbooks中的主机和用户


Playbooks中的每个play ,都需要指定一个远程主机节点(或一组节点主机)和要以哪个远程用户执行任务。

hosts指定主机组的列表,或者是一个主机的匹配正则表达式。多个主机组或者多个匹配模式之间以冒号隔开,如,one*.com:dbserversremote_user指定一个用户账户。

---
- hosts: webservers
  remote_user: root

远程用户也可以在每个任务中指定:

---
- hosts: webservers
  remote_user: root
  tasks:
   - name: test connection
   ping:
   remote_user: yourname

也可以以其他用户的身份来执行任务(sudo):

---
- hosts: webservers
  remote_user: yourname
  sudo: yes


示例:

[root@web1 ~]# cat /etc/ansible/sudo.yml
---
- hosts: webservers
  remote_user: liuzhenwei
  sudo: yes
  tasks:
    - name: create file as root
      file: path=/tmp/testfile2 state=touch
[root@web1 ~]# ansible-playbook /etc/ansible/sudo.yml -K -k
SSH password:
SUDO password[defaults to SSH password]:
PLAY [webservers] *************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.1.65]
TASK: [create file as root] ***************************************************
changed: [192.168.1.65]
PLAY RECAP ********************************************************************
192.168.1.65 : ok=2 changed=1 unreachable=0 failed=0
#远程节点
[root@db2 ~]# ll /tmp/testfile2
-rw-r--r--. 1 root root 0 Jul 27 15:01 /tmp/testfile2

也可以为每个任务指定是否使用sudo,而不是应用于整个play中:

---
- hosts: webservers
  remote_user: yourname
  tasks:
    - service: name=nginx state=started
      become: yes
      become_method: sudo

也可以先以自己的账户登录,然后切换为其他非root用户:

---
- hosts: webservers
  remote_user: yourname
  become: yes
  become_user: postgres

示例:

[root@web1 ~]# cat /etc/ansible/become.yml
---
- hosts: webservers
  remote_user: liuzhenwei
  become: yes
  become_user: tom
  tasks:
   - name: touch file
     file: path=/tmp/sufile state=touch
[root@web1 ~]# ansible-playbook /etc/ansible/become.yml -k --ask-become-pass
SSH password:
SU password[defaults to SSH password]:
PLAY [webservers] *************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.1.65]
TASK: [touch file] ************************************************************
changed: [192.168.1.65]
PLAY RECAP ********************************************************************
192.168.1.65 : ok=2 changed=1 unreachable=0 failed=0
#远程节点
[root@db2 ~]# ll /tmp/sufile
-rw-r--r--. 1 tom tom 0 Jul 27 15:21 /tmp/sufile

-k,--ask-become-pass表示需要命令提示用户输入远程用户及su用户的密码。


也可以使用su来提升用户权限:

---
- hosts: webservers
  remote_user: yourname
  become: yes
  become_method: su

示例:

[root@web1 ~]# cat /etc/ansible/become.yml
---
- hosts: webservers
  remote_user: liuzhenwei
  become: yes
  become_method: su
  tasks:
   - name: touch file
     file: path=/tmp/sufiles state=touch
[root@web1 ~]# ansible-playbook /etc/ansible/become.yml -k --ask-su-pass
SSH password:
SU password[defaults to SSH password]:
PLAY [webservers] *************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.1.65]
TASK: [touch file] ************************************************************
changed: [192.168.1.65]
PLAY RECAP ********************************************************************
192.168.1.65 : ok=2 changed=1 unreachable=0 failed=0
#远程节点
[root@db2 ~]# ll /tmp/sufiles
-rw-rw-r--. 1 root root 0 Jul 27 15:23 /tmp/sufiles

注意-k,--ask-su-pass表示需要命令提示用户输入远程用户及su用户的密码。


任务列表


每个play都包含了一个任务列表,任务是按照顺序执行的,且每个任务会都在指定的所有远程节点上执行,然后再执行下一个任务。
playbooks从上到下执行,如果某个主机的某个任务执行失败则退出。
每个任务实际上都是执行了一个模块,并且为该模块指定了特定的参数。文件上边定义的变量,可以用在模块的参数内。
模块都是等幂的,意思就是当你再次运行的 时候,他们只做他们必须要做的操作(改变某些文件状态等),以使系统达到所需的状态。这样的话,当
你重复运行多次相同的playbooks时,也是非常安全的。
每个任务都应该有一个名称,这个名称会在运行playbook的时候输出,如果没有指定名称,那么对主机做的操作行为将会被用来输出到屏幕上。
任务可以以这种格式来定义: module:options


下边是一个简单的任务示例:

tasks:
- name: make sure apache is running
  service: name=httpd state=running

command和shell模块只需要一个参数列表既可:

tasks:
- name: disable selinux
  command: /sbin/setenforce 0

command和shell会关注它的返回码,如果有一个自定义的脚本或者命令,成功执行后的退出码为非0值,可以进行以下操作:

tasks:
- name: run this command and ignore the result
  shell: /usr/bin/somecommand || /bin/true

或者:

tasks:
- name: run this command and ignore the result
  shell: /usr/bin/somecommand
  ignore_errors: True

如果参数较多的话也可以将其换行书写:

tasks:
- name: Copy ansible inventory file to client
  copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
         owner=root group=root mode=0644

同样也可以在tasks中引用变量:

tasks:
- name: create a virtual host file for {{ vhost }}
  template: src=somefile.j2 dest=/etc/httpd/conf.d/{{ vhost }}

这些变量都会在vars中定义。关于变量和某些常用模块的使用方法后续也会介绍。


Handlers:当某些操作发生改变时触发执行的任务


正如前面提到的,Ansible模块都是幂等的,而且当在远程主机上做了改变之后也可以传递change这个事件。Playbooks有一个基本的事件系统来对‘改
变’做出响应。
notify中指定的行为会在每个任务的最后触发,如果在多个不同的任务里指定了相同的触发事件,那么只会触发一次。
例如,多个任务都表明需要重启Apache,因为他们都修改了配置文件。但是Apache只会重启一次,这样就避免了一些不必要的重启动作。

下边的例子,表名当文件内容发生变化的时候,重启两个服务:

- name: template configuration file
  template: src=template.j2 dest=/etc/foo.conf
  notify:
   - restart memcached
   - restart apache

notify中的任务称为handlers


handlers也是一个任务列表,与普通tasks不同的是hanlders下边的每个操作行为都需要指定一个全局唯一的名称。如果没有任务操作触发该
hanlders,那么它将不会运行。如论有多少个操作都触发了同一个handlers,在所有的任务执行完成后,也只会触发执行一次该handlders。

handlers定义格式如下:

handlers:
  - name: restart memcached
    service: name=memcached state=restarted
  - name: restart apache
     service: name=apache state=restarted

示例:

[root@web1 ~]# cat /etc/ansible/notify.yml
---
- hosts: webservers
  remote_user: root
  vars:
   http_port: 8083
   max_clients: 220
  tasks:
   - name: template config file
     template: src=/etc/ansible/httpd.j2 dest=/etc/httpd.conf
  notify:
   - restart apache
  handlers:
   - name: restart apache
   service: name=httpd state=restarted
[root@web1 ~]# ansible-playbook /etc/ansible/notify.yml
PLAY [webservers] *************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.1.65]
TASK: [template config file] **************************************************
changed: [192.168.1.65]
NOTIFIED: [restart apache] ****************************************************
changed: [192.168.1.65]
PLAY RECAP ********************************************************************
192.168.1.65 : ok=3 changed=2 unreachable=0 failed=0

vars是定义的变量内容,varname:value的形式,在该playbooks中和在template指定的模板文件中都可以引用变量,关于template模块和变量在其他文档中会详细说明。

notify hanlders都会按照书写的循序运行。
hanlders名称必须是全局唯一。
如果有两个handlers定义了相同的名称,只会有一个handlers会运行。


其实上边已经无形中说明了playbooks的执行方法,使用ansible-playbook命令:

ansible-playbook playbook.yml -f 10

-f|--forks 指定使用的并发进程数。

OK,关于playbooks的简单使用就介绍到这里,这基本上就可以做很多平时运维中的自动化工作了,playbooks高效的组织了ansible对远程节点所执行的操作。而且playbooks还有其他很多特性及语法可以更好地组织自动化操作,并且可以很方便的复用某些操作,不需要在不同的地方重复定义同一个操作行为,这些抽时间都会整理上来的。

你可能感兴趣的:(python,自动化运维,ansible,playbooks)