自学内容网 自学内容网

ansible基础教程(下)

一、playbook

简介:

playbook 是 ansible 用于配置,部署,和管理被控节点的剧本。

通过 playbook 的详细描述,执行其中的一系列 tasks ,可以让远端主机达到预期的状态。

使用场景:

像执行shell命令与写shell脚本一样,可以理解为批处理任务,不过playbook有自己的语法格式。

使用playbook可以方便重用这些代码,可以移植到不同的机器上面,像函数一样,最大化的利用代码。之后管理服务器会变得十分简单。

格式:

playbook由YMAL语言编写。

YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。以下为playbook常用到的YMAL格式:

1、文件的第一行应该以 "---" (三个连字符)开始,表明YMAL文件的开始。

2、在同一行中,#之后的内容表示注释,类似于shell,python和ruby。

3、YMAL中的列表元素以”-”开头然后紧跟着一个空格,后面为元素内容。

4、同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。

5、play中hosts,variables,roles,tasks等对象的表示方法都是键值中间以":"分隔表示,":"后面还要增加一个空格。

以下是一个简单的playbook:

---
#安装与运行mysql服务
- hosts: test
  remote_user: root
  tasks:
  - name: install mysql-server package
    yum: name=mariadb-server state=present
  - name: starting mysqld service
    service: name=mariadb state=started

host部分:使用 hosts 指示使用哪个主机或主机组来运行下面的 tasks ,每个 playbook 都必须指定 hosts ,hosts也可以使用通配符格式。主机或主机组在 inventory 清单中指定,可以使用系统默认的/etc/ansible/hosts,也可以自己编辑,在运行的时候加上-i选项,指定清单的位置即可。在运行清单文件的时候,–list-hosts选项会显示那些主机将会参与执行 task 的过程中。

remote_user:指定远端主机中的哪个用户来登录远端系统,在远端系统执行 task 的用户,可以任意指定,也可以使用 sudo,但是用户必须要有执行相应 task 的权限。

tasks:指定远端主机将要执行的一系列动作。tasks 的核心为 ansible 的模块,前面已经提到模块的用法。tasks 包含 name 和要执行的模块,name 是可选的,只是为了便于用户阅读,不过还是建议加上去,模块是必须的,同时也要给予模块相应的参数。

使用ansible-playbook运行playbook文件,得到如下输出信息,输出内容为JSON格式。并且由不同颜色组成,便于识别。一般而言

绿色代表执行成功,系统保持原样

黄色代表系统代表系统状态发生改变

红色代表执行失败,显示错误输出

执行有三个步骤:1、收集facts 2、执行tasks 3、报告结果

核心元素:

Hosts:主机组;
Tasks:任务列表;
Variables:变量,设置方式有四种;
Templates:包含了模板语法的文本文件;
Handlers:由特定条件触发的任务;
remoute_user:在远程主机上执行任务的用户;
  Tasks格式:
    tasks:
      – name: TASK_NAME
       module: arguments
       notify: HANDLER_NAME
       handlers:   #在特定条件下触发;接收到其它任务的通知时被触发;
      – name: HANDLER_NAME
       module: arguments
模块参数:
  格式:
    (1) action: module arguments
    (2) module: arguments
标签的用法:
---
- hosts: test
  remote_user: root
  tasks:
    - name: install mariadb
      yum:
        name: mariadb
        state: present

    - name: start mariadb service
      service:
        name: mariadb
        state: started
      tags: startmariadb  # 打标签

  handlers:  # 注意缩进格式,这里相对于hosts那一层缩进两个空格
    - name: reload
      service:
        name: mariadb
        state: restarted  # 为了在进程中能看出来

 执行命令

ansible-playbook 3.yml    #执行playbook

可以看到执行完成,此时我们已经打了一个标签,可以直接调用,现在把服务关闭,直接调用标签,看看可不可以运行

ansible test -m shell -a 'systemctl stop mariadb'   #关闭服务
ansible-playbook 3.yml -t startmariadb   #调用标签

可以看到这里的标签被成功的调用了。

二、var变量

Ansible 中的变量用于存储值,这些值可以在 Playbook、任务或模板中重复使用。

1.在playbook中定义变量

- name: Example playbook with variables
  hosts: test
  vars:
    http_port: 80
    document_root: "/var/www/html"
  tasks:
    - name: Install httpd package
      yum:
        name: httpd
        state: present
    - name: Configure httpd service
      template:
        src: httpd.conf.j2
        dest: /etc/httpd/conf/httpd.conf
      notify:
        - Restart httpd
  handlers:
    - name: Restart httpd
      service:
        name: httpd
        state: restarted

在这个 Playbook 中,http_port和document_root是定义的变量。它们可以在任务(如配置httpd服务的任务)和模板(httpd.conf.j2)中使用。

2.在主机清单中定义变量

可以在 Ansible 的主机清单文件中定义变量

这里为test组中的192.168.119.134主机定义了http_port变量。这种方式适用于为特定主机或主机组设置不同的变量值。

3.通过命令行传递变量

将文件内容修改为如下

---
- hosts: test
  remote_user: root
  tasks:
  - name: install {{ rpmname }} package
    yum: name={{ rpmname }} state=present
  - name: starting {{ rpmname }} service
    service: name={{ rpmname }} state=started

在命令行输入

ansible-playbook 4.yml -e rpmname=keepalived

 这里的-e 表示在在命令行中传递变量

结果显示命令执行成功。

 4.变量的优先级

命令行传递的变量优先级最高,其次是主机清单中定义的主机变量,然后是 Playbook 中vars部分定义的变量,最后是任务中定义的局部变量(在没有被更高优先级变量覆盖的情况下)。这种优先级顺序可以让用户根据需要灵活地设置变量的值。

三、jinja2模板

Jinja2 是一个现代的、功能强大的模板引擎,用于 Python 编程语言。它广泛应用于 Web 开发、自动化配置管理(如 Ansible)等众多领域。其设计理念是简洁、灵活,能够高效地生成文本内容。例如,在网页开发中,它可以根据后端传递的数据动态地生成 HTML 页面;在 Ansible 中,它能依据变量和逻辑生成配置文件等。

示例:

自动化配置文件生成:

假设要在多台服务器上部署一个 Web 服务(如 Nginx),不同服务器可能有不同的域名、端口和其他配置参数。

创建一个nignx.conf.j2文件,用于生成nginx文件,内容为:

server {
    listen       {{ nginx_port }};
    server_name  {{ server_domain }};
    location / {
        root   {{ document_root }};
        index  index.html index.htm;
    }
}

Playbook设置变量并应用模板

- name: Configure Nginx servers
  hosts: test
  vars:
    nginx_port: 80
    server_domain: "example.com"
    document_root: "/var/www/html"
  tasks:
    - name: Generate Nginx configuration file
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf.default
    - name: Restart Nginx service
      service:
        name: nginx
        state: restarted

当执行这个 Ansible Playbook 时,它会根据vars部分定义的变量(nginx_port、server_domain和document_root)来渲染nginx.conf.j2模板,生成 Nginx 配置文件,并将其发送到目标主机的/etc/nginx/nginx.conf.default位置。然后重启 Nginx 服务,使新的配置生效。这样就可以轻松地在不同的服务器上根据具体的变量值部署定制化的 Nginx 配置。 

if语句的使用:

Jinja2 中的if语句用于条件判断,格式为{% if condition %}...{% elif condition %}...{% else %}...{% endif %}。条件可以是比较表达式、逻辑表达式或者对变量的检查。

示例:

假设在部署软件时,根据不同的操作系统类型,需要使用不同的软件包名称或者配置参数

在 Playbook 中定义变量来表示操作系统类型和软件相关的参数:

- name: Install software
  hosts: all
  vars:
    os_type: "CentOS"
    software_name: "{% if os_type == 'CentOS' %}httpd{% elif os_type == 'Ubuntu' %}apache2{% endif %}"
    config_param: "{% if os_type == 'CentOS' %}CentOS_config{% elif os_type == 'Ubuntu' %}Ubuntu_config{% endif %}"
  tasks:
    - name: Install software package
      yum:
        name: "{{ software_name }}"
        state: present
    - name: Generate configuration file from template
      template:
        src: software_config.j2
        dest: /etc/{{ software_name }}/config

创建一个software_config.j2模板文件,也可以在其中使用if语句来根据操作系统类型生成不同的配置内容:

{% if os_type == 'CentOS' %}
# CentOS specific configuration
Option1 = "{{ config_param }}"
{% elif os_type == 'Ubuntu' %}
# Ubuntu specific configuration
Option2 = "{{ config_param }}"
{% endif %}

当执行这个 Playbook 时,根据os_type变量的值,software_name和config_param变量会被正确地赋值。在安装软件包的任务中,会根据操作系统安装正确的软件包(如在 CentOS 上安装httpd,在 Ubuntu 上安装apache2)。在生成配置文件的任务中,template任务会根据操作系统类型在模板中生成相应的配置内容,使得软件配置符合操作系统的要求。

for语句的使用:

Jinja2 中的for语句用于循环遍历可迭代对象,如列表、元组、字典等。其基本格式是{% for item in iterable %}...{% endfor %}。

在 Ansible 的template任务中,for循环(通过 Jinja2 语法)用于动态生成配置文件内容。例如,要生成一个包含多个虚拟主机配置的 Nginx 配置文件:

- name: Configure Nginx virtual hosts
  hosts: test
  vars:
    virtual_hosts:
      - { domain: 'example1.com', root: '/var/www/html1' }
      - { domain: 'example2.com', root: '/var/www/html2' }
  tasks:
    - name: Generate Nginx config file
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf.default

对应的nginx.conf.j2的内容为:

{% for vhost in virtual_hosts %}
server {
    listen       80;
    server_name  {{ vhost.domain }};
    location / {
        root   {{ vhost.root }};
        index  index.html index.htm;
    }
}
{% endfor %}

在模板中,for循环遍历virtual_hosts变量中的每个元素(虚拟主机配置字典)。对于每个虚拟主机,生成一个server块,其中{{ vhost.domain }}和{{ vhost.root }}分别获取字典中的域名和文档根目录信息,用于生成完整的 Nginx 虚拟主机配置。

when语句的使用:

在ansible中,when语句用于条件判断,语法结构如下:

- name: 示例任务 
[模块名称]: [模块参数]
 when: [条件表达式]

 例如:

---
- hosts: test
  remote_user: root
  tasks:
  - name: install mysql-server package
    yum: name=mariadb-server state=present
    when: ansible_os_family == "RedHat" and ansible_distribution_major_version == "7"

该yml表示的是当系统为Redhat7时,执行上面的yum模块,执行该yml可以看到该playbook可以使用

将“7”改为“6”,再次执行该playboy,可以看到出现skipped=1,表示该任务被跳过了,因为并没有满足when的条件。

四、角色(roles)

 对于以上所有的方式有个弊端就是无法实现复用,假设在同时部署Web、db时或不同服务器组合不同的应用就需要写多个yml文件。很难实现灵活的调用。

roles 用于层次性、结构化地组织playbook。roles 能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量(vars)、文件(file)、任务(tasks)、模块(modules)及处理器(handlers)放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。

files/:存储由copy或script等模块调用的文件;
tasks/:此目录中至少应该有一个名为main.yml的文件,用于定义各task;其它的文件需要由main.yml进行“包含”调用;
handlers/:此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其它的文件需要由main.yml进行“包含”调用;
vars/:此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用;
templates/:存储由template模块调用的模板文本;
meta/:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由main.yml进行“包含”调用;
default/:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量;

在roles目录下生成相应的目录

用作示范,可以看到init的tasks下有个main.yml文件,内容为:

---
- name: 2.1同步网络时间
  shell: yum -y install ntp && ntpdate ntp.aliyun.com

- name: 2.2_install_yum_env
  yum:
    state: latest
    name:
      - wget
      - vim
      - tree

- name: 03_stop_firewalld
  service: name=firewalld state=stopped enabled=no

- name: 04_stop_selinux
  lineinfile:
    dest: /etc/selinux/config
    regexp: "^SELINUX=.*"
    line: "SELINUX=disabled"

此时在定义一个install_init.yml文件,即可使用

---
- name: 1初始化
  gather_facts: False
  hosts:
    - test
  roles:
    - init

剧本执行结果如下:


原文地址:https://blog.csdn.net/2401_82737195/article/details/144286046

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!