Ansible - 快速指南
Ansible - 简介
Ansible是简单的开源 IT 引擎,可自动执行应用程序部署、服务内编排、云配置和许多其他 IT 工具。
Ansible 易于部署,因为它不使用任何代理或自定义安全基础设施。
Ansible 使用 playbook 来描述自动化作业,而 playbook 使用非常简单的语言,即YAML(它是一种人类可读的数据序列化语言,通常用于配置文件,但可以在许多存储数据的应用程序中使用),这非常简单供人类理解、阅读和书写。因此,优点是即使是 IT 基础设施支持人员也可以阅读和理解剧本,并在需要时进行调试(YAML – 采用人类可读的形式)。
Ansible 专为多层部署而设计。Ansible 不会一次管理一个系统,它通过描述所有相互关联的系统来对 IT 基础设施进行建模。Ansible 是完全无代理的,这意味着 Ansible 通过 ssh 连接节点(默认情况下)来工作。但如果您想要其他连接方法(例如 Kerberos),Ansible 会为您提供该选项。
连接到节点后,Ansible 会推送称为“Ansible 模块”的小程序。Ansible 在您的节点上运行该模块并在完成后删除它们。Ansible 在简单的文本文件中管理您的库存(这些是主机文件)。Ansible 使用主机文件,可以在其中对主机进行分组,并可以控制剧本中特定组的操作。
示例主机文件
这是主机文件的内容 -
#File name: hosts #Description: Inventory file for your application. Defines machine type abc node to deploy specific artifacts # Defines machine type def node to upload metadata. [abc-node] #server1 ansible_host = <target machine for DU deployment> ansible_user = <Ansible user> ansible_connection = ssh server1 ansible_host = <your host name> ansible_user = <your unix user> ansible_connection = ssh [def-node] #server2 ansible_host = <target machine for artifact upload> ansible_user = <Ansible user> ansible_connection = ssh server2 ansible_host = <host> ansible_user = <user> ansible_connection = ssh
什么是配置管理
Ansible 中的配置管理意味着它通过记录和更新描述企业硬件和软件的详细信息来维护产品性能的配置。
此类信息通常包括已应用于已安装软件包的确切版本和更新以及硬件设备的位置和网络地址。例如,如果您想在企业中的所有机器上安装新版本的WebLogic/WebSphere服务器,则手动更新每台机器是不可行的。
您可以使用 Ansible playbook 和以最简单的方式编写的清单,在所有计算机上一次性安装 WebLogic/WebSphere。您所要做的就是在清单中列出节点的 IP 地址并编写剧本来安装 WebLogic/WebSphere。从您的控制机运行剧本,它将安装在您的所有节点上。
Ansible 是如何工作的?
下图展示了 Ansible 的工作原理。
Ansible 的工作原理是连接到您的节点并向其推送称为“ Ansible模块”的小程序。然后Ansible执行这些模块(默认通过 SSH),并在完成后删除它们。您的模块库可以驻留在任何计算机上,并且不需要服务器、守护程序或数据库。
上图中的管理节点是控制节点(管理节点),控制着playbook的整个执行。这是您运行安装的节点。库存文件提供需要运行 Ansible 模块的主机列表,管理节点进行 SSH 连接并在主机上执行小模块并安装产品/软件。
Ansible 的优点在于,一旦模块安装成功,它就会删除模块,它会连接到主机,执行指令,如果安装成功,则会删除在执行的主机上复制的代码。
Ansible - 环境设置
在本章中,我们将了解Ansible的环境设置。
安装过程
当我们谈论部署时,主要有两种类型的机器 -
控制机器- 我们可以管理其他机器的机器。
远程机器- 由控制机处理/控制的机器。
可以存在由一台控制机处理的多台远程机器。因此,为了管理远程机器,我们必须在控制机器上安装 Ansible。
控制机器要求
Ansible 可以在任何安装了 Python 2(版本 2.6 或 2.7)或 Python 3(版本 3.5 及更高版本)的计算机上运行。
注意- Windows 不支持控制机。
默认情况下,Ansible 使用ssh来管理远程计算机。
Ansible 不添加任何数据库。它不需要任何守护进程来启动或保持运行。在管理远程计算机时,Ansible不会在其上安装或运行任何软件。因此,不存在迁移到新版本时如何升级的问题。
Ansible 可以通过不同的方式安装在具有上述要求的控制机上。您可以通过 Apt、yum、pkg、pip、OpenCSW、pacman 等安装最新版本。
在 Ubuntu 机器上通过 apt 安装
要安装 Ansible,您必须在计算机上配置 PPA。为此,您必须运行以下代码行 -
$ sudo apt-get update $ sudo apt-get install software-properties-common $ sudo apt-add-repository ppa:ansible/ansible $ sudo apt-get update $ sudo apt-get install ansible
运行上面这行代码后,您就可以通过 Ansible 管理远程机器了。只需运行 Ansible –version 来检查版本并检查 Ansible 是否安装正确。
Ansible - YAML 基础知识
Ansible 使用 YAML 语法来表达 Ansible playbook。本章提供 YAML 的概述。Ansible 使用 YAML 是因为与 XML 和 JSON 等其他数据格式相比,它更容易让人理解、读取和编写。
每个YAML文件都可以选择以“---”开头并以“...”结尾。
了解 YAML
在本节中,我们将了解 YAML 数据表示的不同方式。
键值对
YAML 使用简单的键值对来表示数据。字典以键:值对的形式表示。
注意- : 和值之间应该有空格。
示例:学生记录
--- #Optional YAML start syntax james: name: james john rollNo: 34 div: B sex: male … #Optional YAML end syntax
缩写
您还可以使用缩写来表示词典。
例子
James: {name: james john, rollNo: 34, div: B, sex: male}
代表名单
我们还可以用 YAML 来表示 List。列表中的每个元素(成员)都应该写在一个新行中,并具有相同的缩进,以“-”(-和空格)开头。
例子
--- countries: - America - China - Canada - Iceland …
缩写
您还可以使用缩写来表示列表。
例子
Countries: [‘America’, ‘China’, ‘Canada’, ‘Iceland’]
字典内的列表
我们可以在字典中使用列表,即键的值是列表。
例子
--- james: name: james john rollNo: 34 div: B sex: male likes: - maths - physics - english …
词典列表
我们还可以制作字典列表。
例子
--- - james: name: james john rollNo: 34 div: B sex: male likes: - maths - physics - english - robert: name: robert richardson rollNo: 53 div: B sex: male likes: - biology - chemistry …
YAML 使用“|” 在显示多行时包含换行符,“>”在显示多行时抑制换行符。因此我们可以读取和编辑大行。在这两种情况下,意图都将被忽略。
我们还可以在 YAML 中表示布尔(真/假)值。其中布尔值可以不区分大小写。
例子
--- - james: name: james john rollNo: 34 div: B sex: male likes: - maths - physics - english result: maths: 87 chemistry: 45 biology: 56 physics: 70 english: 80 passed: TRUE messageIncludeNewLines: | Congratulation!! You passed with 79% messageExcludeNewLines: > Congratulation!! You passed with 79%
一些与 Ansible 相关的常用词。
服务/服务器- 提供服务的机器上的进程。
机器- 物理服务器、vm(虚拟机)或容器。
目标机器- 我们将使用 Ansible 配置的机器。
任务- 由 Ansible 管理的操作(运行这个、删除那个)等。
Playbook - 编写 Ansible 命令并在机器上执行 yml 的 yml 文件。
Ansible - 即席命令
即席命令是可以单独运行以执行快速功能的命令。稍后不需要执行这些命令。
例如,您必须重新启动公司的所有服务器。为此,您将从“ /usr/bin/ansible ”运行临时命令。
这些临时命令不用于配置管理和部署,因为这些命令是一次性的。
ansible-playbook 用于配置管理和部署。
并行性和 Shell 命令
一次以 12 个并行分支重新启动您的公司服务器。为此,我们需要设置 SSHagent 进行连接。
$ ssh-agent bash $ ssh-add ~/.ssh/id_rsa
要对 12 个并行分支中的“abc”组中的所有公司服务器运行重新启动 -
$ Ansible abc -a "/sbin/reboot" -f 12
默认情况下,Ansible 将从当前用户帐户运行上述 Ad-hoc 命令。如果您想更改此Behave,则必须在临时命令中传递用户名,如下所示 -
$ Ansible abc -a "/sbin/reboot" -f 12 -u username
文件传输
您可以使用 Ad-hoc 命令在多台计算机上并行执行SCP(安全复制协议)大量文件。
将文件传输到许多服务器/机器
$ Ansible abc -m copy -a "src = /etc/yum.conf dest = /tmp/yum.conf"
创建新目录
$ Ansible abc -m file -a "dest = /path/user1/new mode = 777 owner = user1 group = user1 state = directory"
删除整个目录和文件
$ Ansible abc -m file -a "dest = /path/user1/new state = absent"
管理包
Ad-hoc 命令可用于 yum 和 apt。以下是一些使用 yum 的临时命令。
以下命令检查 yum 软件包是否已安装,但不更新它。
$ Ansible abc -m yum -a "name = demo-tomcat-1 state = present"
以下命令检查软件包是否已安装。
$ Ansible abc -m yum -a "name = demo-tomcat-1 state = absent"
以下命令检查是否安装了最新版本的软件包。
$ Ansible abc -m yum -a "name = demo-tomcat-1 state = latest"
收集事实
事实可用于在剧本中实现条件语句。您可以通过以下临时命令找到所有事实的临时信息 -
$ Ansible all -m setup
Ansible - 剧本
在本章中,我们将学习 Ansible 中的 Playbook。
Playbook 是编写 Ansible 代码的文件。Playbook 以 YAML 格式编写。YAML 代表另一种标记语言。Playbook是 Ansible 的核心功能之一,它告诉 Ansible 要执行什么。它们就像 Ansible 的待办事项列表,其中包含任务列表。
Playbook 包含用户想要在特定计算机上执行的步骤。Playbook 按顺序运行。Playbook 是 Ansible 所有用例的构建块。
剧本结构
每个剧本都是其中一个或多个剧本的聚合。Playbook 是使用 Play 构建的。一本剧本中可以有多个剧本。
戏剧的功能是映射针对特定主机定义的一组指令。
YAML 是一种严格类型语言;因此,编写 YAML 文件时需要格外小心。有不同的 YAML 编辑器,但我们更喜欢使用像 notepad++ 这样的简单编辑器。只需打开记事本++并复制并粘贴以下yaml并将语言更改为YAML(语言→ YAML)。
YAML 以 --- 开头(3 个连字符)
创建剧本
让我们首先编写一个示例 YAML 文件。我们将逐步浏览以 yaml 文件编写的每个部分。
--- name: install and configure DB hosts: testServer become: yes vars: oracle_db_port_value : 1521 tasks: -name: Install the Oracle DB yum: <code to install the DB> -name: Ensure the installed service is enabled and running service: name: <your service name>
上面是一个示例 Playbook,我们试图在其中涵盖 Playbook 的基本语法。将以上内容保存在文件中,命名为test.yml。YAML 语法需要遵循正确的缩进,并且在编写语法时需要小心一些。
不同的 YAML 标签
现在让我们浏览一下不同的 YAML 标签。不同的标签描述如下 -
姓名
此标签指定 Ansible playbook 的名称。就像这本剧本将要做什么一样。可以为剧本指定任何逻辑名称。
主机
此标签指定我们要运行任务的主机或主机组的列表。主机字段/标签是强制性的。它告诉 Ansible 在哪些主机上运行列出的任务。这些任务可以在同一台计算机或远程计算机上运行。一个人可以在多台机器上运行任务,因此主机标签也可以有一组主机的条目。
变量
Vars 标签允许您定义可以在剧本中使用的变量。用法与任何编程语言中的变量类似。
任务
所有剧本都应包含要执行的任务或任务列表。任务是需要执行的一系列操作。任务字段包含任务的名称。这用作用户的帮助文本。它不是强制性的,但事实证明在调试剧本时很有用。每个任务在内部链接到一段称为模块的代码。应执行的模块以及要执行的模块所需的参数。
Ansible - 角色
角色为完全独立或相互依赖的变量、任务、文件、模板和模块集合提供了一个框架。
在 Ansible 中,角色是将剧本分解为多个文件的主要机制。这简化了复杂剧本的编写,并且使它们更容易重用。剧本的分解允许您从逻辑上将剧本分解为可重用的组件。
每个角色基本上仅限于特定功能或所需的输出,并在该角色本身或作为依赖项列出的其他角色中提供该结果的所有必要步骤。
角色不是剧本。角色是可以独立使用的小功能,但必须在剧本中使用。没有办法直接执行角色。角色没有明确设置角色将应用于哪个主机。
顶级剧本是将清单文件中的主机与应应用于这些主机的角色联系起来的桥梁。
创建新角色
角色的目录结构对于创建新角色至关重要。
角色结构
角色在文件系统上具有结构化布局。默认结构可以更改,但现在让我们坚持默认值。
每个角色本身就是一个目录树。角色名称是 /roles 目录中的目录名称。
$ ansible-galaxy -h
用法
ansible-galaxy [delete|import|info|init|install|list|login|remove|search|setup] [--help] [options] ...
选项
-h, --help - 显示此帮助消息并退出。
-v, --verbose - 详细模式(-vvv 用于更多,-vvvv 用于启用连接调试)
--version - 显示程序的版本号并退出。
创建角色目录
上面的命令已经创建了角色目录。
$ ansible-galaxy init vivekrole ERROR! The API server (https://galaxy.ansible.com/api/) is not responding, please try again later. $ ansible-galaxy init --force --offline vivekrole - vivekrole was created successfully $ tree vivekrole/ vivekrole/ ├── defaults │ └── main.yml ├── files ├── handlers │ └── main.yml ├── meta │ └── main.yml ├── README.md ├── tasks │ └── main.yml ├── templates ├── tests │ ├── inventory │ └── test.yml └── vars └── main.yml 8 directories, 8 files
并非所有目录都会在示例中使用,我们将在示例中展示其中一些目录的使用。
在 Playbook 中利用角色
这是我们为演示目的编写的剧本代码。此代码属于剧本 vivek_orchestrate.yml。我们定义了主机:tomcat-node并调用了两个角色 – install-tomcat和start-tomcat。
问题陈述是我们有一场战争需要通过 Ansible 部署在机器上。
--- - hosts: tomcat-node roles: - {role: install-tomcat} - {role: start-tomcat}
我们运行剧本的目录结构的内容。
$ ls ansible.cfg hosts roles vivek_orchestrate.retry vivek_orchestrate.yml
每个目录下都有一个tasks目录,其中包含一个main.yml。install-tomcat 的 main.yml 内容是 -
--- #Install vivek artifacts - block: - name: Install Tomcat artifacts action: > yum name = "demo-tomcat-1" state = present register: Output always: - debug: msg: - "Install Tomcat artifacts task ended with message: {{Output}}" - "Installed Tomcat artifacts - {{Output.changed}}"
启动 tomcat 的 main.yml 的内容是 -
#Start Tomcat - block: - name: Start Tomcat command: <path of tomcat>/bin/startup.sh" register: output become: true always: - debug: msg: - "Start Tomcat task ended with message: {{output}}" - "Tomcat started - {{output.changed}}"
将 playbook 分解为角色的优点是,任何想要使用 Install tomcat 功能的人都可以调用 Install Tomcat 角色。
将剧本分解为角色
如果不是角色,则可以将相应角色的 main.yml 内容复制到 playbook yml文件中。但为了实现模块化,创建了角色。
任何可以作为可重用功能重用的逻辑实体,该实体都可以移动到角色。上面显示了这个示例
运行命令来运行剧本。
-vvv option for verbose output – verbose output $ cd vivek-playbook/
这是运行剧本的命令
$ sudo ansible-playbook -i hosts vivek_orchestrate.yml –vvv ----------------------------------------------------------------- -----------------------------------------------------------------------
输出
生成的输出如屏幕上所示 -
使用/users/demo/vivek-playbook/ansible.cfg作为配置文件。
PLAYBOOK: vivek_orchestrate.yml ********************************************************* *********************************************************** 1 plays in vivek_orchestrate.yml PLAY [tomcat-node] ********************************************************************** ******** ************************************************* TASK [Gathering Facts] ************************************************* ****************************** ********************************************* Tuesday 21 November 2017 13:02:05 +0530 (0:00:00.056) 0:00:00.056 ****** Using module file /usr/lib/python2.7/sitepackages/ansible/modules/system/setup.py <localhost> ESTABLISH LOCAL CONNECTION FOR USER: root <localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' <localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1511249525.88-259535494116870 `" && echo ansible-tmp-1511249525.88-259535494116870="` echo /root/.ansible/tmp/ansibletmp-1511249525.88-259535494116870 `" ) && sleep 0' <localhost> PUT /tmp/tmpPEPrkd TO /root/.ansible/tmp/ansible-tmp-1511249525.88259535494116870/setup.py <localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp1511249525.88-259535494116870/ /root/.ansible/tmp/ansible-tmp-1511249525.88259535494116870/setup.py && sleep 0' <localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp1511249525.88-259535494116870/setup.py; rm -rf "/root/.ansible/tmp/ansible-tmp1511249525.88-259535494116870/" > /dev/null 2>&1 && sleep 0' ok: [server1] META: ran handlers TASK [install-tomcat : Install Tomcat artifacts] *********************************** *************************************************************** task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:5 Tuesday 21 November 2017 13:02:07 +0530 (0:00:01.515) 0:00:01.572 ****** Using module file /usr/lib/python2.7/sitepackages/ansible/modules/packaging/os/yum.py <localhost> ESTABLISH LOCAL CONNECTION FOR USER: root <localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' <localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1511249527.34-40247177825302 `" && echo ansibletmp-1511249527.34-40247177825302="` echo /root/.ansible/tmp/ansible-tmp1511249527.34-40247177825302 `" ) && sleep 0' <localhost> PUT /tmp/tmpu83chg TO /root/.ansible/tmp/ansible-tmp-1511249527.3440247177825302/yum.py <localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp1511249527.34-40247177825302/ /root/.ansible/tmp/ansible-tmp-1511249527.3440247177825302/yum.py && sleep 0' <localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp1511249527.34-40247177825302/yum.py; rm -rf "/root/.ansible/tmp/ansible-tmp1511249527.34-40247177825302/" > /dev/null 2> &1 && sleep 0' changed: [server1] => { "changed": true, "invocation": { "module_args": { "conf_file": null, "disable_gpg_check": false, "disablerepo": null, "enablerepo": null, "exclude": null, "install_repoquery": true, "installroot": "/", "list": null, "name": ["demo-tomcat-1"], "skip_broken": false, "state": "present", "update_cache": false, "validate_certs": true } }, "msg": "", "rc": 0, "results": [ "Loaded plugins: product-id, search-disabled-repos, subscriptionmanager\nThis system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.\nResolving Dependencies\n--> Running transaction check\n---> Package demo-tomcat-1.noarch 0:SNAPSHOT-1 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n \n================================================================================\n Package Arch Version Repository Size\n==================================================================\nInstalling:\n demo-tomcat-1 noarch SNAPSHOT-1 demo-repo1 7.1 M\n\nTransaction Summary\n==================================================================\nInstall 1 Package\n\nTotal download size: 7.1 M\nInstalled size: 7.9 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : demotomcat-1-SNAPSHOT-1.noarch 1/1 \n Verifying : demo-tomcat-1-SNAPSHOT-1.noarch 1/1 \n\nInstalled:\n demo-tomcat-1.noarch 0:SNAPSHOT-1 \n\nComplete!\n" ] } TASK [install-tomcat : debug] ********************************************************** *************************************************************************** task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:11 Tuesday 21 November 2017 13:02:13 +0530 (0:00:06.757) 0:00:08.329 ****** ok: [server1] => { "changed": false, "msg": [ "Install Tomcat artifacts task ended with message: { u'msg': u'', u'changed': True, u'results': [u'Loaded plugins: product-id, search-disabledrepos, subscription-manager\\nThis system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.\\nResolving Dependencies\\n--> Running transaction check\\n---> Package demo-tomcat-1.noarch 0:SNAPSHOT-1 will be installed\\n--> Finished Dependency Resolution\\n \\nDependencies Resolved\\n\\n==================================================================\\n Package Arch Version Repository Size\\n======================================================================== =====\\nInstalling:\\n demo-tomcat-1 noarch SNAPSHOT-1 demo-repo1 7.1 M\\n\\nTransaction Summary\\n=========================================================\\nInstall 1 Package\\n\\nTotal download size: 7.1 M\\nInstalled size: 7.9 M\\nDownloading packages:\\nRunning transaction check\\nRunning transaction test\\nTransaction test succeeded\\nRunning transaction\\n Installing : demo-tomcat-1-SNAPSHOT-1.noarch 1/1 \\n Verifying : demo-tomcat-1-SNAPSHOT-1.noarch 1/1 \\n\\nInstalled:\\n demo-tomcat-1.noarch 0:SNAPSHOT-1 \\n\\nComplete!\\n'], u'rc': 0 }", "Installed Tomcat artifacts - True" ] } TASK [install-tomcat : Clean DEMO environment] **************************************** ************************************************************ task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:19 Tuesday 21 November 2017 13:02:13 +0530 (0:00:00.057) 0:00:08.387 ****** [WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{installationOutput.changed}} Using module file /usr/lib/python2.7/sitepackages/ansible/modules/files/file.py <localhost> ESTABLISH LOCAL CONNECTION FOR USER: root <localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' <localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1511249534.13-128345805983963 `" && echo ansible-tmp-1511249534.13-128345805983963="` echo /root/.ansible/tmp/ansibletmp-1511249534.13-128345805983963 `" ) && sleep 0' <localhost> PUT /tmp/tmp0aXel7 TO /root/.ansible/tmp/ansible-tmp-1511249534.13128345805983963/file.py <localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp1511249534.13-128345805983963/ /root/.ansible/tmp/ansible-tmp-1511249534.13128345805983963/file.py && sleep 0' <localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp1511249534.13-128345805983963/file.py; rm -rf "/root/.ansible/tmp/ansible-tmp1511249534.13-128345805983963/" > /dev/null 2>&1 && sleep 0' changed: [server1] => { "changed": true, "diff": { "after": { "path": "/users/demo/DEMO", "state": "absent" }, "before": { "path": "/users/demo/DEMO", "state": "directory" } }, "invocation": { "module_args": { "attributes": null, "backup": null, "content": null, "delimiter": null, "diff_peek": null, "directory_mode": null, "follow": false, "force": false, "group": null, "mode": null, "original_basename": null, "owner": null, "path": "/users/demo/DEMO", "recurse": false, "regexp": null, "remote_src": null, "selevel": null, "serole": null, "setype": null, "seuser": null, "src": null, "state": "absent", "unsafe_writes": null, "validate": null } }, "path": "/users/demo/DEMO", "state": "absent" } TASK [install-tomcat : debug] ******************************************************** ************************************************************* task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:29 Tuesday 21 November 2017 13:02:14 +0530 (0:00:00.257) 0:00:08.645 ****** ok: [server1] => { "changed": false, "msg": [ "Clean DEMO environment task ended with message:{u'diff': {u'after': {u'path': u'/users/demo/DEMO', u'state': u'absent'}, u'before': {u'path': u'/users/demo/DEMO', u'state': u'directory'}}, u'state': u'absent', u'changed': True, u'path': u'/users/demo/DEMO'}", "check value :True" ] } TASK [install-tomcat : Copy Tomcat to user home] ************************************* ******************************************************** task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:37 Tuesday 21 November 2017 13:02:14 +0530 (0:00:00.055) 0:00:08.701 ****** [WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{installationOutput.changed}} Using module file /usr/lib/python2.7/sitepackages/ansible/modules/commands/command.py <localhost> ESTABLISH LOCAL CONNECTION FOR USER: root <localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' <localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1511249534.43-41077200718443 `" && echo ansibletmp-1511249534.43-41077200718443="` echo /root/.ansible/tmp/ansible-tmp1511249534.43-41077200718443 `" ) && sleep 0' <localhost> PUT /tmp/tmp25deWs TO /root/.ansible/tmp/ansible-tmp-1511249534.4341077200718443/command.py <localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp1511249534.43-41077200718443/ /root/.ansible/tmp/ansible-tmp-1511249534.4341077200718443/command.py && sleep 0' <localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp1511249534.43-41077200718443/command.py; rm -rf "/root/.ansible/tmp/ansibletmp-1511249534.43-41077200718443/" > /dev/null 2>&1 && sleep 0' changed: [server1] => { "changed": true, "cmd": [ "cp", "-r", "/opt/ansible/tomcat/demo", "/users/demo/DEMO/" ], "delta": "0:00:00.017923", "end": "2017-11-21 13:02:14.547633", "invocation": { "module_args": { "_raw_params": "cp -r /opt/ansible/tomcat/demo /users/demo/DEMO/", "_uses_shell": false, "chdir": null, "creates": null, "executable": null, "removes": null, "warn": true } }, "rc": 0, "start": "2017-11-21 13:02:14.529710", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": [] } TASK [install-tomcat : debug] ******************************************************** ********************************************************** task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:47 Tuesday 21 November 2017 13:02:14 +0530 (0:00:00.260) 0:00:08.961 ****** ok: [server1] => { "changed": false, "msg": "Copy Tomcat to user home task ended with message { 'stderr_lines': [], u'changed': True, u'end': u'2017-11-21 13:02:14.547633', u'stdout': u'', u'cmd': [u'cp', u'-r', u'/opt/ansible/tomcat/demo', u'/users/demo/DEMO/'], u'rc': 0, u'start': u'2017-11-21 13:02:14.529710', u'stderr': u'', u'delta': u'0:00:00.017923', 'stdout_lines': []}" } TASK [start-tomcat : Start Tomcat] ************************************************** ********************************************************** task path: /users/demo/vivek-playbook/roles/start-tomcat/tasks/main.yml:5 Tuesday 21 November 2017 13:02:14 +0530 (0:00:00.044) 0:00:09.006 ****** Using module file /usr/lib/python2.7/sitepackages/ansible/modules/commands/command.py <localhost> ESTABLISH LOCAL CONNECTION FOR USER: root <localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' <localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1511249534.63-46501211251197 `" && echo ansibletmp-1511249534.63-46501211251197="` echo /root/.ansible/tmp/ansible-tmp1511249534.63-46501211251197 `" ) && sleep 0' <localhost> PUT /tmp/tmp9f06MQ TO /root/.ansible/tmp/ansible-tmp-1511249534.6346501211251197/command.py <localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp1511249534.63-46501211251197/ /root/.ansible/tmp/ansible-tmp-1511249534.6346501211251197/command.py && sleep 0' <localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp1511249534.63-46501211251197/command.py; rm -rf "/root/.ansible/tmp/ansibletmp-1511249534.63-46501211251197/" > /dev/null 2>&1 && sleep 0' changed: [server1] => { "changed": true, "cmd": [ "/users/demo/DEMO/bin/startup.sh" ], "delta": "0:00:00.020024", "end": "2017-11-21 13:02:14.741649", "invocation": { "module_args": { "_raw_params": "/users/demo/DEMO/bin/startup.sh", "_uses_shell": false, "chdir": null, "creates": null, "executable": null, "removes": null, "warn": true } }, "rc": 0, "start": "2017-11-21 13:02:14.721625", "stderr": "", "stderr_lines": [], "stdout": "Tomcat started.", "stdout_lines": [ "Tomcat started." ] } TASK [start-tomcat : debug] ************************************************* ********************************************************************** task path: /users/demo/vivek-playbook/roles/start-tomcat/tasks/main.yml:10 Tuesday 21 November 2017 13:02:14 +0530 (0:00:00.150) 0:00:09.156 ****** ok: [server1] => { "changed": false, "msg": [ "Start Tomcat task ended with message: {' stderr_lines': [], u'changed': True, u'end': u'2017-11-21 13:02:14.741649', u'stdout': u'Tomcat started.', u'cmd': [u'/users/demo/DEMO/bin/startup.sh'], u'rc': 0, u'start': u'2017-11-21 13:02:14.721625', u'stderr': u'', u'delta': u'0:00:00.020024', 'stdout_lines': [u'Tomcat started.']}", "Tomcat started - True" ] } META: ran handlers META: ran handlers PLAY RECAP ******************************************************************************* ********************************************************* server1 : ok = 9 changed = 4 unreachable = 0 failed = 0 Tuesday 21 November 2017 13:02:14 +0530 (0:00:00.042) 0:00:09.198 ****** =============================================================================== install-tomcat : Install Tomcat artifacts ------------------------------- 6.76s /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:5 -------------- Gathering Facts --------------------------------------------------------- 1.52s ------------------------------------------------------------------------------ install-tomcat : Copy Tomcat to user home ------------------------------- 0.26s /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:37 ------------- install-tomcat : Clean DEMO environment --------------------------------- 0.26s /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:19 ------------- start-tomcat : Start Tomcat --------------------------------------------- 0.15s /users/demo/vivek-playbook/roles/start-tomcat/tasks/main.yml:5 ---------------- install-tomcat : debug -------------------------------------------------- 0.06s /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:11 ------------- install-tomcat : debug -------------------------------------------------- 0.06s /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:29 ------------- install-tomcat : debug -------------------------------------------------- 0.04s /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:47 ------------- start-tomcat : debug ---------------------------------------------------- 0.04s /users/demo/vivek-playbook/roles/start-tomcat/tasks/main.yml:10 ---------------
点击以下 URL,您将被定向到如下所示的页面 - http://10.76.0.134:11677/HelloWorld/HelloWorld
部署的 war 只有一个显示“Hello World”的 servlet。详细的输出显示了由于 ansible.cfg 文件中添加的条目而每个任务所花费的时间 -
[defaults] callback_whitelist = profile_tasks
Ansible - 变量
剧本中的变量与在任何编程语言中使用变量非常相似。它可以帮助您使用变量并将值分配给变量,并在剧本中的任何位置使用该变量。人们可以在变量值周围设置条件,并相应地在剧本中使用它们。
例子
- hosts : <your hosts> vars: tomcat_port : 8080
在上面的示例中,我们定义了一个变量名称tomcat_port并将值 8080 分配给该变量,并且可以在您的 playbook 中的任何需要的地方使用它。
现在参考共享的示例。以下代码来自角色之一 (install-tomcat) -
block: - name: Install Tomcat artifacts action: > yum name = "demo-tomcat-1" state = present register: Output always: - debug: msg: - "Install Tomcat artifacts task ended with message: {{Output}}" - "Installed Tomcat artifacts - {{Output.changed}}"
这里,输出是使用的变量。
让我们看一下上面代码中使用的所有关键字 -
block - 执行给定块的 Ansible 语法。
name - 块的相关名称 - 用于日志记录并有助于调试所有块已成功执行的内容。
action - 操作标签旁边的代码是要执行的任务。该操作又是 yaml 中使用的 Ansible 关键字。
register - 使用 register 关键字注册操作的输出,输出是保存操作输出的变量名称。
总是- 又是一个 Ansible 关键字,它声明下面的内容将始终被执行。
msg - 显示消息。
变量的使用 - {{Output}} -->
这将读取变量输出的值。此外,由于它在 msg 选项卡中使用,它将打印输出变量的值。
此外,您还可以使用变量的子属性。就像在检查 {{Output.changed}} 输出是否更改并相应地使用它的情况下一样。
Playbook 中的异常处理
Ansible 中的异常处理类似于任何编程语言中的异常处理。下面显示了 playbook 中异常处理的示例。
tasks: - name: Name of the task to be executed block: - debug: msg = 'Just a debug message , relevant for logging' - command: <the command to execute> rescue: - debug: msg = 'There was an exception.. ' - command: <Rescue mechanism for the above exception occurred) always: - debug: msg = "this will execute in all scenarios. Always will get logged"
以下是异常处理的语法。
rescue和always是特定于异常处理的关键字。
块是编写代码的地方(在 Unix 机器上执行的任何内容)。
如果块功能内写入的命令失败,则执行到达救援块并被执行。如果阻止功能下的命令没有错误,则不会执行救援。
在所有情况下总是被执行。
所以如果我们拿java来比较的话,那么它就类似于try、catch和finally块。
这里,Block类似于try块,你可以在其中编写要执行的代码,rescue类似于catch块,always类似于finally。
循环
下面的示例演示了 Ansible 中循环的用法。
任务是将所有 war 文件集从一个目录复制到 tomcat webapps 文件夹。
下面示例中使用的大部分命令之前已经介绍过。在这里,我们将重点关注循环的使用。
最初在“shell”命令中我们执行了 ls *.war。因此,它将列出该目录中的所有 war 文件。
该命令的输出保存在名为output 的变量中。
要循环,正在使用“with_items”语法。
with_items: "{{output.stdout_lines}}" --> output.stdout_lines 为我们提供逐行输出,然后我们使用 Ansible 的 with_items 命令循环输出。
附加示例输出只是为了让人们了解我们如何在 with_items 命令中使用 stdout_lines。
--- #Tsting - hosts: tomcat-node tasks: - name: Install Apache shell: "ls *.war" register: output args: chdir: /opt/ansible/tomcat/demo/webapps - file: src: '/opt/ansible/tomcat/demo/webapps/{{ item }}' dest: '/users/demo/vivek/{{ item }}' state: link with_items: "{{output.stdout_lines}}"
积木
整个剧本被分成几个块。要执行的最小步骤被写在块中。在块中编写特定指令有助于隔离功能并在需要时通过异常处理来处理它。
上面的变量使用、异常处理和循环中介绍了块的示例。
条件句
当需要根据条件运行特定步骤时使用条件。
--- #Tsting - hosts: all vars: test1: "Hello Vivek" tasks: - name: Testing Ansible variable debug: msg: "Equals" when: test1 == "Hello Vivek"
在这种情况下,将打印 Equals,因为 test1 变量与 when 条件中提到的相等。与所有编程语言一样, when可以与逻辑 OR 和逻辑 AND 条件一起使用。
只需将 test1 变量的值从 Hello Vivek 更改为 Hello World 并查看输出。
Ansible - 高级执行
在本章中,我们将学习什么是 Ansible 的高级执行。
如何限制任务执行
这是一种非常重要的执行策略,只需执行一次,而不是整个剧本。例如,假设您只想停止服务器(以防出现生产问题),然后在应用补丁后您只想启动服务器。
在原始剧本中,停止和开始是同一剧本中不同角色的一部分,但这可以通过使用标签来处理。我们可以为不同的角色(进而有任务)提供不同的标签,因此基于执行者提供的标签,仅执行指定的角色/任务。因此,对于上面提供的示例,我们可以添加如下标签 -
- {role: start-tomcat, tags: ['install']}}
以下命令有助于使用标签 -
ansible-playbook -i hosts <your yaml> --tags "install" -vvv
使用上面的命令,只会调用start-tomcat角色。提供的标签区分大小写。确保将精确匹配传递给命令。
如何限制主机执行
有两种方法可以实现在特定主机上执行特定步骤。对于特定角色,定义主机 - 即应运行该特定角色的特定主机。
例子
- hosts: <A> environment: "{{your env}}" pre_tasks: - debug: msg = "Started deployment. Current time is {{ansible_date_time.date}} {{ansible_date_time.time}} " roles: - {role: <your role>, tags: ['<respective tag>']} post_tasks: - debug: msg = "Completed deployment. Current time is {{ansible_date_time.date}} {{ansible_date_time.time}}" - hosts: <B> pre_tasks: - debug: msg = "started.... Current time is {{ansible_date_time.date}} {{ansible_date_time.time}} " roles: - {role: <your role>, tags: ['<respective tag>']} post_tasks: - debug: msg = "Completed the task.. Current time is {{ansible_date_time.date}} {{ansible_date_time.time}}"
根据上面的示例,根据提供的主机,只会调用相应的角色。现在我的主机 A 和 B 已在主机(库存文件)中定义。
替代解决方案
不同的解决方案可能是使用变量定义剧本的主机,然后通过--extra-vars传入特定的主机地址-
# file: user.yml (playbook) --- - hosts: '{{ target }}' user: ... playbook contd….
运行剧本
ansible-playbook user.yml --extra-vars "target = "<your host variable>"
如果未定义 {{ target }},则剧本不执行任何操作。如果需要,也可以传递主机文件中的组。如果不提供额外的变量,这不会造成损害。
针对单个主机的 Playbook
$ ansible-playbook user.yml --extra-vars "target = <your hosts variable>" --listhosts
Ansible - 故障排除
调试 Ansible playbook 的最常见策略是使用下面给出的模块 -
调试并注册
这两个是 Ansible 中可用的模块。出于调试目的,我们需要明智地使用这两个模块。下面举例说明。
使用冗长
使用 Ansible 命令,可以提供详细级别。您可以运行详细级别为 1 级 (-v) 或 2 级 (-vv) 的命令。
要点
在本节中,我们将通过几个示例来理解一些概念。
如果您没有引用以变量开头的参数。例如,
vars: age_path: {{vivek.name}}/demo/ {{vivek.name}}
这会引发错误。
解决方案
vars: age_path: "{{vivek.name}}/demo/" – marked in yellow is the fix. How to use register -> Copy this code into a yml file say test.yml and run it --- #Tsting - hosts: tomcat-node tasks: - shell: /usr/bin/uptime register: myvar - name: Just debugging usage debug: var = myvar
当我通过命令 Ansible-playbook -i Hosts test.yml 运行此代码时,我得到如下所示的输出。
如果您看到 yaml ,我们已将命令的输出注册到变量 - myvar中,并刚刚打印了输出。
标记为黄色的文本告诉我们变量 –myvar 的属性,可用于进一步的流量控制。通过这种方式,我们可以了解特定变量公开的属性。以下调试命令对此有所帮助。
$ ansible-playbook -i hosts test.yml PLAY [tomcat-node] *************************************************************** **************** **************************************************************** *************** ****************************** TASK [Gathering Facts] ***************************************************************** ************** ***************************************************************** ************** ************************** Monday 05 February 2018 17:33:14 +0530 (0:00:00.051) 0:00:00.051 ******* ok: [server1] TASK [command] ****************************************************************** ************* ****************************************************************** ************* ********************************** Monday 05 February 2018 17:33:16 +0530 (0:00:01.697) 0:00:01.748 ******* changed: [server1] TASK [Just debugging usage] ****************************************************************** ************* ****************************************************************** ************* ********************* Monday 05 February 2018 17:33:16 +0530 (0:00:00.226) 0:00:01.974 ******* ok: [server1] => { "myvar": { "changed": true, "cmd": "/usr/bin/uptime", "delta": "0:00:00.011306", "end": "2018-02-05 17:33:16.424647", "rc": 0, "start": "2018-02-05 17:33:16.413341", "stderr": "", "stderr_lines": [], "stdout": " 17:33:16 up 7 days, 35 min, 1 user, load average: 0.18, 0.15, 0.14", "stdout_lines": [ " 17:33:16 up 7 days, 35 min, 1 user, load average: 0.18, 0.15, 0.14" ] } } PLAY RECAP **************************************************************************** ********************************************************************************** ************************************** server1 : ok = 3 changed = 1 unreachable = 0 failed = 0
常见的剧本问题
在本节中,我们将了解一些常见的剧本问题。问题是 -
- 引用
- 缩进
Playbook是用yaml格式编写的,上面两个是yaml/playbook中最常见的问题。
Yaml 不支持基于制表符的缩进,但支持基于空格的缩进,因此需要小心。
注意- 编写完 yaml 后,打开此站点(https://editor.swagger.io/)并将 yaml 复制粘贴到左侧,以确保 yaml 正确编译。这只是一个提示。
Swagger 限定警告和错误中的错误。