天天看点

Absible——YAML语法介绍和Playbook介绍

YAML 语言

YAML 官方网站:

http://www.yaml.org

YAML语言特性

YAML的可读性好

YAML和脚本语言的交互性好

YAML使用实现语言的数据类型

YAML有一个一致的信息模型

YAML易于实现

YAML可以基于流来处理

YAML表达能力强,扩展性好

YAML语法简介

在单一文件第一行,用连续三个连字号“-” 开始,还有选择性的连续三个点号( … )用来表示文件的

结尾

次行开始正常写Playbook的内容,一般建议写明该Playbook的功能

使用#号注释代码

缩进必须是统一的,不能空格和tab混用

缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换

行来实现的 YAML文件内容是区别大小写的,key/value的值均需大小写敏感

多个k/v可同行写也可换行写,同行使用,分隔

v可是个字符串,也可是另一个列表

一个完整的代码块功能需最少元素需包括 name 和 task

一个name只能包括一个task

YAML文件扩展名通常为yml或yaml

YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构

(Structure)通过空格来展示,序列(Sequence)里的项用"-“来代表,Map里的键值对用”:"分隔,下

面介绍常见的数据结构。

List列表

列表由多个元素组成,且所有元素前均使用“-”打头 范例:

# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
#[Apple,Orange,Strawberry,Mango]
           

Dictionary字典

字典通常由多个key与value构成

# An employee record
name: Example Developer
job: Developer
skill: Elite
也可以将key:value放置于{}中进行表示,用,分隔多个key:value
# An employee record
{name: Example Developer, job: Developer, skill: Elite}
           

范例:

name: John Smith
  age: 41
  gender: Male
spouse:
  name: Jane Smith
  age: 37
  gender: Female
children:
  - name: Jimmy Smith
  age: 17
  gender: Male
  - name: Jenny Smith
  age 13
  gender: Female
           

Playbook核心元素

Hosts 执行的远程主机列表

Tasks ,任务集

Variables,内置变量或自定义变量在playbook中调用

Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件

Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行

tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此

会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地

长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断

hosts 组件

Hosts:playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts

用于指定要执行指定任务的主机,须事先定义在主机清单中

one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
Websrvs:dbsrvs             #或者,两个组的并集
Websrvs:&dbsrvs            #与,两个组的交集
webservers:!phoenix        #在websrvs组,但不在dbsrvs组
           

范例:

- hosts: websrvs:appsrvs
           

remote_user 组件

remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可

用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户

- hosts: websrvs
  remote_user: root
  tasks:
    - name: test connection
    ping:
    remote_user: magedu
    sudo: yes         #默认sudo为root
    sudo_user:kaivi    #sudo为kaivi
           

task列表和action组件

play的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主

机上执行,即在所有主机上完成第一个task后,再开始第二个task task的目的是使用指定的参数执行模

块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一

致 每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步

骤。如果未提供name,则action的结果将用于输出

task两种格式:

(1) action: module arguments

(2) module: arguments 建议使用

注意:shell和command模块后面跟命令,而非key=value

范例:

---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: install httpd
	  yum: name=httpd
	- name: start httpd
	  service: name=httpd state=started enabled=yes
           

其它组件

某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers 任务可以通过"tags“打标

签,可在ansible-playbook命令上使用-t指定进行调用

ShellScripts VS Playbook 案例

#SHELL脚本实现
#!/bin/bash
# 安装Apache
yum install --quiet -y httpd
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp/tmp/vhosts.conf /etc/httpd/conf.d/
# 启动Apache,并设置开机启动
systemctl enable --now httpd

#Playbook实现
---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: "安装Apache"
      yum: name=httpd
    - name: "复制配置文件"
      copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
    - name: "复制配置文件"
      copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
    - name: "启动Apache,并设置开机启动"
      service: name=httpd state=started enabled=yes
           

playbook 命令

格式

常见选项

--check -C #只检测可能会发生的改变,但不真正执行操作
--list-hosts #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的主机执行
-v -vv -vvv #显示过程
           

范例:

ansible-playbook file.yml --check #只检测
ansible-playbook file.yml
ansible-playbook file.yml --limit websrvs
           

实验一:二进制安装数据库

在centos8中,在主机centos8 192.168.32.8 中yum安装ansible,被控远程机器为192.168.32.18和192.168.32.28

[[email protected] ~]yum install ansible -y
[[email protected] ~]#ansible --version
ansible 2.8.5
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.6/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.6.8 (default, May 21 2019, 23:51:36) [GCC 8.2.1 20180905 (Red Hat 8.2.1-3)]

[[email protected] ~]#vi /etc/ansible/hosts 
[websrvs]
192.168.32.18
192.168.32.28

[appsrvs]
192.168.32.28

基于SSH key验证
[[email protected] ~]#ssh-keygen 
[[email protected] ~]#vim /etc/ssh/ssh_config
 StrictHostKeyChecking no
[[email protected] ~]#ET=192.168.32; for i in 18 28;do sshpass -p centos ssh-copy-id $NET.$i ;done
           

把下好的安装数据库二进制包上传到新建的文件夹中

[[email protected] ~]#cd /data/ansible/
[[email protected] ansible]#cd /data/ansible/
[[email protected] ansible]#ls
mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz

           

编写planbook

---
#install mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
- hosts: websrvs
  remote_user: root

  tasks:
    - name: install packages
      yum: name=libaio,perl-Data-Dumper,perl-Getopt-Long
    - name: create mysql group
      group: name=mysql gid=306
    - name: create mysql user
      user: name=mysql uid=306 group=mysql shell=/sbin/nologin system=yes create_home=no home=/data/mysql
    - name: copy tar to remote host and modifity file mode
      unarchive: src=/data/ansible/mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz dest=/usr/local/ owner=root group=root
    - name: mkdir /usr/local/mysql
      file: src=/usr/local/mysql-5.6.46-linux-glibc2.12-x86_64 dest=/usr/local/mysql state=link
    - name: data dir
      shell: chdir=/usr/local/mysql ./scripts/mysql_install_db --datadir=/data/mysql --user=mysql
      tags: data
    - name: config my.cnf
      copy: src=/data/ansible/my.cnf dest=/etc/my.cnf
    - name: service script
      shell: /bin/cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
    - name: enable serbice
      shell: /etc/init.d/mysqld start;chkconfig --add mysqld;chkconfig mysqld on
      tags: service
    - name: PATH variable
      copy: content='PATH=/usr/local/mysql/bin:$PATH' dest=/etc/profile.d/mysql.sh
#   - name: copy script
#      script: /data/ansible/secure_mysql.sh
#      tags: script

           

编辑配置文件:

[[email protected] ansible]#vim my.cnf 

[mysqld]
socket=/tmp/mysql.sock
user=mysql
symbolic-links=0
datadir=/data/mysql
innodb_file_per_table=1
log-bin
pid-file=/tmp/mysql.pid

[client]
port=3306
socket=/tmp/mysql.sock


[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/tmp/mysql.pid

           

如果需要数据库安全加固的话。需要编写安装加固回答脚本:

[[email protected] ansible]#vim secure_mysql.sh 

#!/bin/bash
#
#********************************************************************
#Author:                KAIVI
#Date:                  2019-12-05
#FileName:             /data/ansible/secure_mysql.sh
#Description:           The test script
#Copyright (C):         2019 All rights reserved
#********************************************************************
/usr/local/mysql/bin/mysql_secure_installation <<EOF
                  #回车
centos
centos
y
y
y
y
EOF

           

运行ansible-playbook

[[email protected] ansible]#ansible-playbook install_mysql.yml

PLAY [websrvs] ****************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************
ok: [192.168.32.18]
ok: [192.168.32.28]

TASK [install packages] *******************************************************************************************
ok: [192.168.32.28]
ok: [192.168.32.18]

TASK [create mysql group] *****************************************************************************************
changed: [192.168.32.28]
changed: [192.168.32.18]

TASK [create mysql user] ******************************************************************************************
changed: [192.168.32.28]
changed: [192.168.32.18]

TASK [copy tar to remote host and modifity file mode] *************************************************************
changed: [192.168.32.28]
changed: [192.168.32.18]

TASK [mkdir /usr/local/mysql] *************************************************************************************
changed: [192.168.32.28]
changed: [192.168.32.18]

TASK [data dir] ***************************************************************************************************
changed: [192.168.32.28]
changed: [192.168.32.18]

TASK [config my.cnf] **********************************************************************************************
changed: [192.168.32.28]
changed: [192.168.32.18]

TASK [service script] *********************************************************************************************
changed: [192.168.32.18]
changed: [192.168.32.28]

TASK [enable serbice] *********************************************************************************************
changed: [192.168.32.28]
changed: [192.168.32.18]

TASK [PATH variable] **********************************************************************************************
changed: [192.168.32.18]
changed: [192.168.32.28]

PLAY RECAP ********************************************************************************************************
192.168.32.18              : ok=11   changed=9    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.32.28              : ok=11   changed=9    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

           

查看数据库端口3306是否起来:

[[email protected] ansible]#ansible all -m shell -a 'ss -ntl'
192.168.32.28 | CHANGED | rc=0 >>
State    Recv-Q    Send-Q        Local Address:Port        Peer Address:Port    
LISTEN   0         32            192.168.122.1:53               0.0.0.0:*       
LISTEN   0         128                 0.0.0.0:22               0.0.0.0:*       
LISTEN   0         5                 127.0.0.1:631              0.0.0.0:*       
LISTEN   0         128               127.0.0.1:6010             0.0.0.0:*       
LISTEN   0         128               127.0.0.1:6011             0.0.0.0:*       
LISTEN   0         128                 0.0.0.0:111              0.0.0.0:*       
LISTEN   0         128                 0.0.0.0:42707            0.0.0.0:*       
LISTEN   0         128                    [::]:22                  [::]:*       
LISTEN   0         5                     [::1]:631                 [::]:*       
LISTEN   0         128                   [::1]:6010                [::]:*       
LISTEN   0         128                   [::1]:6011                [::]:*       
LISTEN   0         80                        *:3306                   *:*       
LISTEN   0         128                    [::]:35053               [::]:*       
LISTEN   0         128                    [::]:111                 [::]:*       

192.168.32.18 | CHANGED | rc=0 >>
State    Recv-Q    Send-Q        Local Address:Port        Peer Address:Port    
LISTEN   0         32            192.168.122.1:53               0.0.0.0:*       
LISTEN   0         128                 0.0.0.0:22               0.0.0.0:*       
LISTEN   0         5                 127.0.0.1:631              0.0.0.0:*       
LISTEN   0         128               127.0.0.1:6010             0.0.0.0:*       
LISTEN   0         128               127.0.0.1:6011             0.0.0.0:*       
LISTEN   0         128                 0.0.0.0:47467            0.0.0.0:*       
LISTEN   0         128                 0.0.0.0:111              0.0.0.0:*       
LISTEN   0         128                    [::]:22                  [::]:*       
LISTEN   0         5                     [::1]:631                 [::]:*       
LISTEN   0         128                   [::1]:6010                [::]:*       
LISTEN   0         128                   [::1]:6011                [::]:*       
LISTEN   0         80                        *:3306                   *:*       
LISTEN   0         128                    [::]:35375               [::]:*       
LISTEN   0         128                    [::]:111                 [::]:*       

[[email protected] ansible]#

           

出现问题小结:

1.代码书写不规范

2.远程运行脚本时候的路径问题 可能需要先进入文件夹中然后才能执行

3.注意配置文件中数据库中PID的问题

4.安全加固脚本交互式回答问题

Playbook 初步小实验范例

范例:install_httpd.yml

---
#install httpd
- hosts: websrvs
  remote_user: root
  tasks:
    - name: Install httpd
      yum: name=httpd state=present
    - name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
    - name: start service
      service: name=httpd state=started enaled=yes
           

范例:remove_httpd.yml

#remove_httpd.yml
---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: remove httpd package
      yum: name=httpd state=absent
    - name: remove apache user
      user: name=apache state=absent
    - name: remove data file
      file: name=/etc/httpd state=absent
           

范例:mysql_user.yml

---
- hosts: dbsrvs
  remote_user: root
  tasks:
    - {name: create group, group: name=mysql system=yes gid=306}
    - name: create user
      user: name=mysql shell=/sbin/nologin system=yes group=mysql uid=306 home=/data/mysql create_home=no
           

范例:install_nginx.yml

---
# install nginx
- hosts: websrvs
  remote_user: root
  tasks:
    - name: add group nginx
      user: name=nginx state=present
    - name: add user nginx
      user: name=nginx state=present group=nginx
    - name: Install Nginx
      yum: name=nginx state=present
    - name: Start Nginx
      service: name=nginx state=started enabled=yes
           

Playbook中使用handlers和notify

Handlers本质是task list ,其中的task与前述的task并没有本质上的不同,用于当关注的资源发生变化

时,才会采取一定的操作.Notify对应的action可用于在每个play的最后被触发,这样可避免多次有改变

发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的

操作称为handler,也即notify中调用handler中定义的操作

案例:

---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: Install httpd
      yum: name=httpd state=present
    - name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      notify: restart httpd
    - name: ensure apache is running
      service: name=httpd state=started enabled=yes
      
  handlers:
    - name: restart httpd
      service: name=httpd state=restarted
           

案例:

---
- hosts: websrvs
  remote_user: root
  tasks:
	- name: add group nginx
	  user: name=nginx state=present
	- name: add user nginx
	  user: name=nginx state=present group=nginx
	- name: Install Nginx
	  yum: name=nginx state=present
	- name: config
	  copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
	  notify:
	    - Restart Nginx
		- Check Nginx Process
  handlers:
	- name: Restart Nginx
	  service: name=nginx state=restarted enabled=yes
	- name: Check Nginx process
	  shell: killall -0 nginx &> /tmp/nginx.log
           

Playbook中使用tags组件

在playbook文件中,可以利用tags组件,为特定 task 指定标签,当在执行playbook时,可以只执行特

定tags的task,而非整个playbook文件

范例:

vim httpd.yml
---
# tags example
- hosts: websrvs
  remote_user: root
  tasks:
	- name: Install httpd
	  yum: name=httpd state=present
	- name: Install configure file
  	  copy: src=files/httpd.conf dest=/etc/httpd/conf/
	  tags: conf
	- name: start httpd service
	  tags: service
	  service: name=httpd state=started enabled=yes


ansible-playbook –t conf,service httpd.yml      #可以同时执行多个tags
           

继续阅读