Ansible playbook教程|如何编写playbook示例
这是一个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