Ansible – 快速指南
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 剧本和清单,一次性在所有机器上安装 WebLogic/WebSphere。您所要做的就是在清单中列出节点的 IP 地址并编写一个剧本来安装 WebLogic/WebSphere。从您的控制机器运行剧本,它将安装在您的所有节点上。
Ansible 如何工作?
下面给出的图片显示了 Ansible 的工作。
Ansible 的工作原理是连接到您的节点并向它们推送称为“ Ansible模块”的小程序。然后Ansible执行这些模块(默认通过 SSH),并在完成后删除它们。您的模块库可以驻留在任何机器上,并且不需要服务器、守护程序或数据库。
上图中的管理节点是控制节点(managing node),它控制着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 使用简单的键值对来表示数据。字典以键:值对表示。
注意– : 和 value 之间应该有空格。
示例:学生记录
--- #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’]
字典里面的列表
我们可以在字典中使用list,即key的值为list。
例子
--- 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 ”运行 Adhoc 命令。
这些临时命令不用于配置管理和部署,因为这些命令是一次性使用的。
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 命令。如果要更改此行为,则必须在 Ad-hoc 命令中传递用户名,如下所示 –
$ 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"
收集事实
Facts 可用于在 playbook 中实现条件语句。您可以通过以下 Ad-hoc 命令找到所有事实的临时信息 –
$ Ansible all -m setup
Ansible – 剧本
在本章中,我们将了解 Ansible 中的 Playbooks。
Playbooks 是编写 Ansible 代码的文件。Playbooks 以 YAML 格式编写。YAML 代表另一种标记语言。Playbooks是 Ansible 的核心功能之一,它告诉 Ansible 要执行什么。它们就像 Ansible 的待办事项列表,其中包含任务列表。
Playbooks 包含用户想要在特定机器上执行的步骤。剧本按顺序运行。Playbooks 是 Ansible 所有用例的基石。
剧本结构
每个剧本都是其中一个或多个剧本的集合。Playbooks 是使用 Plays 构建的。一本剧本中可以有多个剧本。
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>
上面是一个示例剧本,我们试图在其中涵盖剧本的基本语法。将上述内容保存为test.yml文件。YAML 语法需要遵循正确的缩进,并且在编写语法时需要小心一点。
不同的 YAML 标签
现在让我们来看看不同的 YAML 标签。不同的标签描述如下 –
名称
此标签指定 Ansible 剧本的名称。就像这本剧本将要做的那样。可以为剧本指定任何逻辑名称。
主机
该标签指定了我们要针对其运行任务的主机或主机组的列表。主机字段/标签是强制性的。它告诉 Ansible 在哪些主机上运行列出的任务。这些任务可以在同一台机器或远程机器上运行。一个可以在多台机器上运行任务,因此主机标签也可以有一组主机条目。
变量
Vars 标签可让您定义可在剧本中使用的变量。用法类似于任何编程语言中的变量。
任务
所有剧本都应该包含要执行的任务或任务列表。任务是需要执行的操作列表。任务字段包含任务的名称。这用作用户的帮助文本。这不是强制性的,但在调试剧本时证明是有用的。每个任务在内部链接到一段称为模块的代码。应该执行的模块,以及要执行的模块所需的参数。
Ansible – 角色
角色为变量、任务、文件、模板和模块的完全独立或相互依赖的集合提供了一个框架。
在 Ansible 中,角色是将剧本分成多个文件的主要机制。这简化了编写复杂剧本的过程,并使它们更易于重用。打破 playbook 允许您在逻辑上将 playbook 分解为可重用的组件。
每个角色基本上都限于特定的功能或所需的输出,所有必要的步骤都可以在该角色本身内或在列为依赖项的其他角色中提供该结果。
角色不是剧本。角色是可以独立使用但必须在剧本中使用的小功能。没有办法直接执行角色。角色没有明确设置角色将应用于哪个主机。
顶级 playbook 是将主机从清单文件连接到应应用于这些主机的角色的桥梁。
创建新角色
角色的目录结构对于创建新角色至关重要。
角色结构
角色在文件系统上具有结构化布局。默认结构可以更改,但现在让我们坚持使用默认值。
每个角色本身就是一个目录树。角色名称是 /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
部署的战争只有一个显示“Hello World”的 servlet。由于 ansible.cfg 文件中添加的条目,详细输出显示了每个任务所花费的时间 –
[defaults] callback_whitelist = profile_tasks
Ansible – 变量
剧本中的变量与在任何编程语言中使用变量非常相似。它可以帮助您使用变量并为其分配值,并在剧本中的任何地方使用它。可以在变量值周围放置条件,并相应地在剧本中使用它们。
例子
- hosts : <your hosts> vars: tomcat_port : 8080
在上面的示例中,我们定义了一个变量名称tomcat_port并将值 8080 分配给该变量,并且可以在您的剧本中任何需要的地方使用它。
现在从共享的示例中获取参考。以下代码来自其中一个角色 (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 关键字注册动作的输出,输出是保存动作输出的变量名称。
-
always – 同样是一个 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 块,并且始终类似于finally。
循环
下面是演示 Ansible 中 Loops 用法的示例。
任务是将一组所有战争文件从一个目录复制到 tomcat webapps 文件夹。
以下示例中使用的大多数命令之前已经涵盖。在这里,我们将专注于循环的使用。
最初在“shell”命令中我们已经完成了 ls *.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 命令,可以提供详细级别。您可以使用详细级别一 (-v) 或二 (-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 限定警告和错误中的错误。