Ansible playbook教程|如何编写playbook示例

时间:2020-01-09 10:34:04  来源:igfitidea点击:

这是一个Ansible Playbook教程,我们将通过一个例子从零开始学习编写Ansible Playbook。Ansible需要两个最重要的文件,即playbook和inventory文件。

在开始学习Ansible Playbook教程之前,我希望我们已经安装了Ansible环境,让我们通过一些示例了解YAML文件体系结构:

YAML是什么?

  • YAML不是标记语言(markuplanguage,YAML)通常被称为数据序列化语言。

  • 它的目的是让人可读,并将数据组织成结构化格式。

  • 编程语言可以理解YAML文件的内容(通常有.yml或者.YAML扩展名)并将它们映射到内置的数据类型。

  • 例如,当我们使用Python脚本中的.yaml文件时,它会自动将内容转换为字典{}或者列表[],这样我们就可以对其进行操作和迭代。

  • YAML规则有助于构造一个可读的文件,因此理解它们对于编写一个有效且格式良好的YAML文件非常重要。

YAML文件格式

在开发YAML文件时需要遵循一些规则。YAML使用缩进(如Python),它建立了项目之间的关系:

YAML文件中的键值对

下面我们以最简单的形式获取数据,例如YAML格式的"key-value-pair",其中"key和value用冒号分隔"。在y冒号后面加一个空格来区分键和值是很重要的

Fruit: Apple
Vegetable: Carrot
Liquid: Water
Meat: Chicken

这里的"键"是水果、蔬菜、液体、肉类,而相应的"值"是苹果、胡萝卜、水和鸡肉

YAML文件中的数组或者列表

这里我们列出一些水果和蔬菜。所以水果和蔬菜后跟冒号表示数组而数组的所有元素都以破折号(-)开头
所以橘子、苹果和香蕉是水果数组的元素, 胡萝卜、花椰菜和西红柿是蔬菜数组的元素

Fruits:
- Orange
- Apple
- Banana
Vegetables:
- Carrot
- Cauliflower
- Tomato

YAML文件中的字典或者地图

它是"一组属性组合在一个项下"。其中:我们试图表示两种水果的营养信息

每种食物的卡路里、脂肪和碳水化合物都不同。在单个项的属性之前必须有相等数量的空白,以便它们都对齐在一起

Banana:
	Calories: 105
	Fat: 0.4 g
	Carbs: 27 g
Grapes:
	Calories: 62
	Fat: 0.3 g
	Carbs: 16g

YAML文件中的空格和缩进

正确的缩进对YAML数据非常重要。建议使用高级文本编辑器,如Sublime text或者Notepad++,因为它们可以将选项卡转换为特定数量的空格。我们为单个属性提供了"相同的数字空间",这些属性表示这些键值对属于Banana"。但是如果我们给脂肪和碳水化合物留出额外的空间呢

Banana:
	Calories: 105
  	  Fat: 0.4 g
	  Carbs: 27 g

现在有了这些脂肪和碳水化合物就属于卡路里的范畴,因此它们将成为卡路里的属性,这毫无意义,因此会导致语法错误。该错误将告诉我们,这里不允许映射值,因为卡路里已经设置了一个值,即105. 我们可以设置直接值或者hashmapo,但不能同时设置两者。

所以"每个属性前面的空格数是YAML中的键"。"缩进并不重要",也就是说,你可以给5个空格或者6个空格,但要确保间距一致。

提示:

不建议在YAML文件中使用TAB,因此请始终使用空格键来指定空格。

YAML文件中的键值或者字典或者列表

可以有"包含词典的列表"和"包含列表"。在本例中,我们有"水果列表"和"列表中的元素是香蕉和葡萄",但"每个元素都是包含营养信息的进一步词典"

Fruits:
	- Banana:
		Calories: 105
		Fat: 0.4 g
		Carbs: 27 g
		
	- Grape:
		Calories: 62
		Fat: 0.3 g
		Carbs: 16g

词典vs列表vs词典列表

理解所有数据结构(如XML、JSON或者YAML)都是用来表示数据的,这一点很重要。这些数据可以是关于一个组织及其所有员工及其个人信息,也可以是关于学校及其所有学生及其成绩的数据

让我们以一辆汽车为例,汽车是一个单一的物体,它具有诸如颜色、型号、过渡和价格等属性'。为了存储单个对象的不同信息或者属性,我们使用字典

这里,我们使用键值格式创建一个简单的字典。

Color: Blue
Model: Corvette
Transition: Manual
Price: ,000

现在我们还可以将模型进一步分为"模型名称"和"年份",这样我们就可以在另一个字典中使用一个字典

Color: Blue
Model: 
	Name: Corvette
	Year: 1995
Transition: Manual
Price: ,000

假设我们要存储6辆不同汽车的名称。为了存储它,我们将使用"List or Array",因为它是同一类型或者对象的多个项。因为我们只存储一个名称,所以我们有一个简单的字符串列表`

- Blue Corvette
- Grey Corvette
- Red Corvette
- Green Corvette

现在,如果我们想存储有关每辆车的所有信息,如颜色、型号、过渡和价格,该怎么办。因此,我们将把"字符串列表"修改为"词典列表"`

- Color: Blue
  Model: 
	Name: Corvette
	Year: 1995
  Transition: Manual
  Price: ,000
- Color: Grey
  Model: 
	Name: Corvette
	Year: 1995
  Transition: Manual
  Price: ,000
- Color: Red
  Model: 
	Name: Corvette
	Year: 1995
  Transition: Manual
  Price: ,000
- Color: Green
  Model: 
	Name: Corvette
	Year: 1995
  Transition: Manual
  Price: ,000

Dictionary是一个未排序的集合,其中List是一个排序的集合

例如这里我们有两本字典。

在第一个例子中,脂肪是在碳水化合物之前定义的

Banana:
	Calories: 105
	Fat: 0.4 g
	Carbs: 27 g

在这个例子中,碳水化合物是在脂肪之前定义的,但这并不重要。"属性可以按任何顺序定义",但只要每个属性的值匹配,这两个词典仍将是相同的。对于列表或者数组,这是不同的。数组是有序集合,因此项的顺序很重要。

Banana:
	Calories: 105
	Fat: 0.4 g
	Carbs: 27 g

在本例中,我们定义了"按顺序排列的列表"Orange→Apple→Banana

Fruits:
- Orange
- Apple
- Banana

但是如果我们按下面的顺序写相同的数组/列表,那么两个数组就不一样了。在使用数据结构时,我们应该记住这一点

Fruits:
- Orange
- Banana
- Apple

现在让我们继续我们的Ansible Playbook教程的基本问题,什么是Ansible playbooks?

什么是易变剧本?

  • Ansible playbooks是以称为YAML的特定格式编写的文本文件或者配置文件。

  • 它们以YAML格式表示,并且具有最少的语法,这不是编程语言或者脚本,而是配置的模型。

  • 每个剧本都在一个列表中包含一个或者多个"剧本"。

  • 戏剧的目标是将一组主持人映射到一些定义明确的角色和任务。

  • 任务只不过是一个调用或者操作,适用于一组主机。

以下是剧本.yaml文件:

--
- hosts: webserver
  sudo: yes
  remote_user: ec2-user
  tasks: 
      - name: Updating System
         yum: name=* state=latest

在这个剧本中,有两个指令很重要,第一个是hosts,第二个是tasks。任务将应用于主机。

Ansible剧本教程

Ansible剧本是Ansible编排语言,在剧本中我们定义了我们想要Ansible做什么。这是你提供的一套指令,它是神奇的。既然我们知道所有的剧本都是用YAML格式写的。下面的示例分解了YAML文件。

Playbook - A single YAML file
	Play - Defines a set of activities (tasks) to be run on a single or group of hosts
		Task - An action to be performed on the host, below are some examples:
			Execute command
			Run a script
			Install a package
			Shutdown/restart

简单的Ansible剧本示例

例如,它可以简单到按顺序在不同的服务器上运行一系列命令,然后按特定顺序重新启动这些服务器。下面是一个简单的ansible剧本示例:

# Simple Ansible Playbook Example
- Run command1 on server1
- Run command2 on server2
- Run command3 on server3
- Run command4 on server4
- Run command5 on server5
- Run command6 on server6
- Run command7 on server7
- restarting server1
- restarting server2
- restarting server3
- restarting server4
- restarting server5
- restarting server6
- restarting server7

复杂Ansible剧本示例

下面是一个更复杂的Ansible剧本示例:

# Complex Ansible playbook Example
- Deploy 50 VMs on Public Cloud
- Deploy 50 VMs on Private Cloud
- Provision Storage to all VMs
- Setup Network Configuration on Private VMs
- Setup Cluster configuration
- Configure Web server on 20 Public VMs
- Configure DB server on 20 private VMs
- Setup LoadBalancing between web server VMs
- Setup Monitoring components
- Install and Configure backup clients on VMs
- Update CMDB database with new VM information

安装Apache的Ansible Playbook示例

我已经创建了我的Ansible环境,所以我不会其中解释这些部分。

这里我们有一个简单的剧本'安装_httpd.yml包含单个播放,即"播放1"。这个playbook的目标是在一个托管主机server2上一个接一个地运行一组活动。example.com` .

# Simple Ansible Playbook.yml
--
- name: Play 1
  # Here the host is defined at the play level. This can be anything from your inventory file.
  hosts: server2.example.com
  # All tasks under this will be executed on all nodes mentioned under "hosts" which here is "localhost"
  tasks:
    - name: Execute command 'date'
	  # Execute date command
      command: date
    - name: Execute script on server
	  # Execute test_script.sh, this must exist in your project directory
      script: test_script.sh
	  # Install httpd service
    - name: Install httpd service
	  # Using yum
      yum:
        name: httpd
        state: present
    - name: Start web server
	  # Start the httpd service using service module
      service:
        name: httpd
        state: started

因此,playbook是一个字典列表,它有一组名为name、hosts和tasks的属性。因为这些是字典中的条目,所以顺序无关紧要,但这不是任务的价值所在。

如我们所见,任务是一个由破折号表示的列表,因此条目的位置很重要。

# Sample Inventory File
localhost
server1.example.com
server2.example.com

接下来我们执行剧本

[ansible@controller base]$ ansible-playbook install_httpd.yml
PLAY [Play 1] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
TASK [Gathering Facts] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
ok: [server2.example.com]
TASK [Execute command 'date'] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *****
changed: [server2.example.com]
TASK [Execute script on server] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
changed: [server2.example.com]
TASK [Install httpd service] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **
changed: [server2.example.com]
TASK [Start web server] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
changed: [server2.example.com]
PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
server2.example.com        : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0