ansible学习笔记02(最佳实践)

时间:2022-10-04 07:24:29

1、 编写yaml格式inventory文件

1.1 ansible支持的inventory文件格式

从ansible2.4版本以后,ansible开始支持YAML格式的inventory文件,只需要在配置文件中打开inventory插件,就能支持YAML格式inventory,ansible配置文件默认支持一些其他格式的inventory文件。

可以通过ansible.cfg中在inventory选项加入enable_plugins支持一些格式的inventory文件,默认支持host_list, script, auto, yaml, ini, toml

[student@workstation ~]$ vim /etc/ansible/ansible.cfg
[inventory]
# enable inventory plugins, default: 'host_list', 'script', 'auto', 'yaml', 'ini', 'toml'
# enable_plugins = host_list, virtualbox, yaml, constructed

# ignore these extensions when parsing a directory as inventory source
#ignore_extensions = .pyc, .pyo, .swp, .bak, ~, .rpm, .md, .txt, ~, .orig, .ini, .cfg, .retry

# ignore files matching these patterns when parsing a directory as inventory source
#ignore_patterns=

# If 'true' unparsed inventory sources become fatal errors, they are warnings otherwise.
#unparsed_is_failed=False

1.2 列出主机清单

ansible-inventory --graph #图标方式列出来

[student@workstation development-practices]$ ansible-inventory --graph
@all:
  |--@lb_servers:
  |  |--servera.lab.example.com
  |--@region_eu:
  |  |--serverc.lab.example.com
  |--@ungrouped:
  |--@web_servers:
  |  |--serverb.lab.example.com
  |  |--serverc.lab.example.com

1.3 INI格式inventory文件

[lb_servers]
servera.lab.example.com

[web_servers]
serverb.lab.example.com
serverc.lab.example.com

[web_servers:vars]
alternate_server=serverd.lab.example.com

[backend_server_pool]
server[b:f].lab.example.com
[student@workstation development-practices]$ ansible-inventory -i origin_inventory --graph
@all:
  |--@backend_server_pool:
  |  |--serverb.lab.example.com
  |  |--serverc.lab.example.com
  |  |--serverd.lab.example.com
  |  |--servere.lab.example.com
  |  |--serverf.lab.example.com
  |--@lb_servers:
  |  |--servera.lab.example.com
  |--@ungrouped:
  |--@web_servers:
  |  |--serverb.lab.example.com
  |  |--serverc.lab.example.com

1.4 YAML格式inventory文件

YAML格式的inventory文件符合ansible最佳实践的原则,同时yaml格式文件的可读性和效率也比ini格式的inventory文件好一些

lb_servers:
  hosts:
    servera.lab.example.com:
web_servers:
  hosts:
    serverb.lab.example.com:
    serverc.lab.example.com:
backend_server_pool:
  hosts:
    server[b:f].lab.example.com:
# 使用-i参数列出yaml格式的inventory文件
[student@workstation development-practices]$ ansible-inventory -i yaml_inventory.yml --graph
@all:
  |--@backend_server_pool:
  |  |--serverb.lab.example.com
  |  |--serverc.lab.example.com
  |  |--serverd.lab.example.com
  |  |--servere.lab.example.com
  |  |--serverf.lab.example.com
  |--@lb_servers:
  |  |--servera.lab.example.com
  |--@ungrouped:
  |--@web_servers:
  |  |--serverb.lab.example.com
  |  |--serverc.lab.example.com

1.5 YAML格式inventory文件说明

  1. 每一行以冒号(:)结尾

  2. 拥有层级关系(组名--hosts--主机)

  3. 也可以使用关键字children表示子组

  4. 默认情况all参数包含所有主机,但是all关键字要和children关键字一起使用

all:
  children:
    lb_servers:
      hosts:
        servera.lab.example.com:
    web_servers:
      hosts:
        serverb.lab.example.com:
[student@workstation development-practices]$ ansible-inventory -i yaml_children.yml --graph
@all:
  |--@lb_servers:
  |  |--servera.lab.example.com
  |--@ungrouped:
  |--@web_servers:
  |  |--serverb.lab.example.com

1.6 设置inventory变量

可以在YAML中设置inventory变量,就像你在INI格式文件中那样配置变量。

大多数情况下,最佳实践要求尽可能避免将变量信息存放在inventory静态文件中。变量信息可以存放在inventory中,inventory文件目录下hosts_vars或则group_vars文件中。也可以使用ansible_port或ansible_connection这类ansible变量中,尽量不要要将变量文件放在多个位置,后期维护的时候将很难找到它们的存放位置,不利于维护。

在group block中,可以使用vars关键字在YAML文件中设置变量

# ini格式
[monitoring]
watcher.lab.example.com

[monitoring:vars]
smtp_relay: smtp.lab.example.com
# YAML格式
monitoring:
  hosts:
    watcher.lab.example.com
  vars:
  	smtp_relay: smtp.lab.example.com

在变量文件中设置变量

[workstations]
workstation.lab.example.com
localhost ansible_connection=local
host.lab.example.com
workstations:
  hosts:
    worktstation.lab.example.com:
    localhost:
      ansible_connection: local
    host.lab.exampel.com:

1.7 INI格式转为YAML格式

可以通过命令快速将INI格式的inventory文件转为YAML格式的inventory文件,虽然转换的时候可能有一些问题,不过不影响使用,可以很大程度节省手动将大量INI转成YAML的时间。

ansible-inventory --yaml -i INI格式 --list --output YAML格式

[student@workstation development-practices]$ cat inventory
[lb_servers]
servera.lab.example.com

[web_servers]
server[b:c].lab.example.com

[region_eu]
serverc.lab.example.com
[student@workstation development-practices]$ ansible-inventory --yaml -i inventory --list --output inventory_new.yml
[student@workstation development-practices]$ cat inventory_new.yml
all:
  children:
    lb_servers:
      hosts:
        servera.lab.example.com:
          haproxy_appservers:
          - ip: 172.25.250.11
            name: serverb.lab.example.com
          - ip: 172.25.250.12
            name: serverc.lab.example.com
    region_eu:
      hosts:
        serverc.lab.example.com:
          webapp_message: Hello from Europe. This is
    ungrouped: {}
    web_servers:
      hosts:
        serverb.lab.example.com: {}
        serverc.lab.example.com: {}

该YAML格式inventory文件手写如下

all:
  children:
    lb_servers:
      hosts:
        servera.lab.example.com:
          haproxy_appservers:`
          - ip: 172.25.250.11
            name: serverb.lab.example.com
          - ip: 172.25.250.12
            name: serverc.lab.example.com
    region_eu:
      hosts:
        serverc.lab.example.com:
          webapp_message: Hello from Europe. This is
    ungrouped: {}
    web_servers:
      hosts:
        server[b:c ].lab.example.com: {}

使用yaml格式inventory文件查看主机

[student@workstation development-practices]$ ansible-inventory -i inventory_new.yml --graph
@all:
  |--@lb_servers:
  |  |--servera.lab.example.com
  |--@region_eu:
  |  |--serverc.lab.example.com
  |--@ungrouped:
  |--@web_servers:
  |  |--serverb.lab.example.com
  |  |--serverc.lab.example.com

1.8 YAML格式排障

冒号后跟了空格

(x) 一行多个冒号 title: hello: xiaoming

(√) 冒号后没有空格 title: hello:xiaoming

(√) 使用引号括起来 simple: 'hello xiaoming : good'

(√) 使用双引号括起来 simple: "hello xiaoming : good"

使用{{ 变量 }},表示变量

(x) 单引号会被解释成字典 { good }

(√)双引号会被解释称变量 {{ good }}

(√)一段话使用变量用双引号括起来 "hello {{ xiaoming }}"

了解ansible识别字符串、布尔值、浮点数

default_answer: yes # 布尔值

default_float: 1.5 # 浮点数

default_name: "xiaoming" #字符串

1.9 编写YAML格式inventory文件练习

1.9.1 实验要求

  1. 开启实验
  2. 将inventory文件复制inventory.yml
  3. 编辑inventory.yml文件,转化成YAML格式
  4. 通过ad hoc命令,ping测试all servers组
  5. 实验结束

1.9.2 实验

[student@workstation ~]$ lab inventory-yaml start

Setting up workstation for the Guided Exercise: Writing inventory files in YAML

 · Downloading starter project.................................  SUCCESS
 · Downloading solution project................................  SUCCESS

Setup successful. Please proceed with the exercise.
[student@workstation inventory-yaml]$ cat inventory
[active_web_servers]
server[b:c].lab.example.com

[inactive_web_servers]
server[d:f].lab.example.com

[region_eu]
serverc.lab.example.com
serverf.lab.example.com

[web_servers:children]
active_web_servers
inactive_web_servers

[all_servers]
servera.lab.example.com

[all_servers:children]
web_servers
[student@workstation inventory-yaml]$ cat inventory.yml
all_servers:
  hosts:
    servera.lab.example.com:
  children:
    web_servers:
      children:
        active_web_servers:
          hosts:
            server[b:c].lab.example.com:
        inactive_web_servers:
          hosts:
            server[d:f].lab.example.com:
region_eu:
  hosts:
    serverc.lab.example.com:
    serverf.lab.example.com:
[student@workstation inventory-yaml]$ ansible-inventory -i inventory.yml --graph
@all:
  |--@all_servers:
  |  |--@web_servers:
  |  |  |--@active_web_servers:
  |  |  |  |--serverb.lab.example.com
  |  |  |  |--serverc.lab.example.com
  |  |  |--@inactive_web_servers:
  |  |  |  |--serverd.lab.example.com
  |  |  |  |--servere.lab.example.com
  |  |  |  |--serverf.lab.example.com
  |  |--servera.lab.example.com
  |--@region_eu:
  |  |--serverc.lab.example.com
  |  |--serverf.lab.example.com
  |--@ungrouped:
[student@workstation inventory-yaml]$ ansible -i inventory.yml all_servers -m ping
servera.lab.example.com | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
serverb.lab.example.com | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
serverc.lab.example.com | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
servere.lab.example.com | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
serverd.lab.example.com | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
serverf.lab.example.com | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
[student@workstation inventory-yaml]$ lab inventory-yaml finish

Cleaning up the lab for Guided Exercise: Writing inventory files in YAML

 · Cleaning lab files..........................................  SUCCESS
 · Cleaning solutions files....................................  SUCCESS

2、 管理INVENTORY变量

2.1 变量最佳实践

变量可以在tasks、roles和playbook中,它允许你在不同的操作系统下进行不同的配置,变量可以设置在如下几个位置:

  1. roles下default和vars目录
  2. 在inventory文件编辑host和group变量
  3. 在group_vars和host_vars目录下
  4. 在play、role、task中
变量定义最佳实践 说明
keep it simple 保持简单
don't repeat yourself 不要做重复的事情
organize variables in small, readable file 打散保证易读性

2.2 变量合并和优先级

尽管变量可以放置在多个位置,不过还是建议将变量放置在一处,如果变量放在多个位置,它们的优先级将会不同。

一般情况下,限定范围越小,变量的优先级越高

优先级从低到高:

  1. 命令行参数(除了-e以外,优先级是最低的)
  2. Role中的default目录
  3. host和group变量
    1. inventory文件中
    2. inventory中group_vars/all下
    3. playbook中group_vars/all下
    4. inventory中group_vars下
    5. playbook中group_vars下
    6. 动态inventory文件
    7. inventory中host_vars下
    8. playbook中host_vars下
    9. fact变量
  4. playbook文件中定义变量
    1. 设置var选项
    2. 设置vars_prompt选项
    3. 设置role下/vars/
    4. block块下
    5. task下的vars选项
    6. include_var模块加载变量
    7. set_fact模块 或 register关键字
    8. include_role模块加载role
    9. include_tasks加载tasks
  5. 命令行参数-e,指定变量

2.3 从inventory分离变量

静态inventory中定义变量如果把变量集中一处,后期难以维护,如果在inventory目录下定义一个个装有变量的文件,并且根据使用环境给出名字,将可以很好的解决后期维护的问题。

变量的最佳实践:将一个大的变量文件,分成若干个小的文件。

  1. 项目较小可以分离成如下形式
[student@workstation ~]$ tree group_vars/
group_vars/
├── db_servers.yml
├── lb_servers.yml
└── web_servers.yml

0 directories, 3 files
  1. 项目较大可以写成如下形式
[student@workstation ~]$ tree group_vars/
group_vars/
├── all
│?? └── common.yml
├── db_servers
│?? ├── firewall.yml
│?? └── mysql.yml
├── lb_servers
│?? ├── firewall.yml
│?? ├── haproxy.yml
│?? └── ssl.yml
└── web_servers
    ├── apache.yml
    ├── firewall.yml
    └── webapp.yml

4 directories, 9 files

2.4 特殊的inventory变量

变量名 说明
ansible_connection 连接方式(使用ssh、local或其他方式)
ansible_host 使用指定IP或域名连接
ansible_port 使用指定端口连接
ansible_user 连接到XX用户
ansible_become_user 提权到XX用户
ansible_python_interpreter 指定python版本

2.5 指定易读的inventory名称

主机名如果是server100、server200、server300这样定义的,阅读起来非常不便,可以通过指定主机名,提高可读性,利于后期维护。

# 不清楚主机是干啥的
web_servers:
  hosts:
    server100.example.com
    server101.example.com
    server102.example.com
lb_servers:
  hosts:
    server103.example.com
# 指定主机名称
web_servers:
  hosts:
    web_server1:
      ansible_host: server100.example.com:
    web_server2:
      ansible_host: server101.example.com:
    web_server3:
      ansible_host: server102.example.com:
lb_servers:
  hosts:
    loadbalancer:
      ansible_hosts: server103.example.com:

2.6 使用变量识别主机

运行play的时候,可以使用一些变量识别托管的主机

变量名 说明
inventory_hostname inventory清单中主机名
ansible_host 主机IP地址或主机名
ansible_facts['hostname'] 主机名
ansible_facts['fqdn'] 完全限定域名

2.7 管理inventory变量练习

2.7.1 实验要求

  1. 开启实验
  2. 创建git-repo目录
    1. 克隆http://git.lab.example.com:8081/git/inventory-variables.git
    2. 进入inventory-variables目录
      1. 创建group_vars目录,进入目录创建lb_servers和web_servers目录
      2. 阅读deploy_haproxy.yml文件
        1. 将firewall规则加入gruop_vars/lb_servers/firewall.yml
        2. 将haproxy_appservers变量加入gruop_vars/lb_servers/deploy_haproxy.yml
        3. 编辑deploy_haproxy.yml移除变量
      3. 阅读deploy_apache.yml文件
        1. 将firewall变量放入gruop_vars/web_servers/firewall.yml
        2. 移除deploy_apache.yml中firewall变量
      4. 编辑inventory.yml文件
        1. 给主机servera起名:load_balancer
      5. 使用ansible-playbook运行site.yml
      6. 使用git追踪+提交+上传
  3. 结束实验

2.7.2 实验

# 开启实验环境
[student@workstation ~]$ lab inventory-variables start

Setting up the lab for the Guided Exercise: Managing Inventory Variables

 · Checking python on remote hosts.............................  SUCCESS
 · Installing git..............................................  SUCCESS
 · Installing tree.............................................  SUCCESS
 · Configuring Git.............................................  SUCCESS
 · Configuring Git credentials.................................  SUCCESS
 · Adding content to git repo..................................  SUCCESS
# 创建目录,克隆git
[student@workstation ~]# mkdir -p git-repos
[student@workstation ~]# ls
gitrc  git-repos
[student@workstation ~]# cd git-repos/
[student@workstation git-repos]# git clone http://git.lab.example.com:8081/git/inventory-variables.git
Cloning into 'inventory-variables'...
remote: Enumerating objects: 53, done.
remote: Counting objects: 100% (53/53), done.
remote: Compressing objects: 100% (37/37), done.
remote: Total 53 (delta 6), reused 0 (delta 0)
Unpacking objects: 100% (53/53), done.
[student@workstation git-repos]# ls
inventory-variables
[student@workstation git-repos]# cd inventory-variables/
[student@workstation inventory-variables (master)]# ls
ansible.cfg  deploy_apache.yml  deploy_haproxy.yml  deploy_webapp.yml  inventory.yml  roles  site.yml
[student@workstation inventory-variables (master)]# mkdir group_vars
[student@workstation inventory-variables (master)]# cd group_vars/
[student@workstation group_vars (master)]# ls
[student@workstation group_vars (master)]# mkdir {lb,web}_server
[student@workstation group_vars (master)]# ls
lb_server  web_server
# 查看文件内容
[student@workstation inventory-variables (master)]# cat deploy_haproxy.yml
- name: Ensure HAProxy is deployed
  hosts: lb_servers
  force_handlers: True

  roles:
    # The "haproxy" role has a dependency on the "firewall" role.
    # The "firewall" role requires a "firewall_rules" variable be defined.
    - role: haproxy
      firewall_rules:
        # Allow 80/tcp connections
        - port: 80/tcp

      haproxy_appservers:
      - name: serverb.lab.example.com
        ip: 172.25.250.11
        backend_port: 80
      - name: serverc.lab.example.com
        ip: 172.25.250.12
        backend_port: 80
# 将变量信息移动到firewall.yml中
[student@workstation inventory-variables (master)]# cat  group_vars/lb_server/firewall.yml
firewall_rules:
  # Allow 80/tcp connections
  - port: 80/tcp
# 将变量信息移动到deploy_haproxy.yml中
[student@workstation inventory-variables (master)]# cat group_vars/lb_server/deploy_haproxy.yml
haproxy_appservers:
  - name: serverb.lab.example.com
    ip: 172.25.250.11
    backend_port: 80
  - name: serverc.lab.example.com
    ip: 172.25.250.12
    backend_port: 80
# 删除变量信息,留下role信息
[student@workstation inventory-variables (master *)]# cat deploy_haproxy.yml
- name: Ensure HAProxy is deployed
  hosts: lb_servers
  force_handlers: True

  roles:
    # The "haproxy" role has a dependency on the "firewall" role.
    # The "firewall" role requires a "firewall_rules" variable be defined.
    - role: haproxy
# 将变量信息写入firewall.yml文件
[student@workstation inventory-variables (master *)]# touch group_vars/web_server/firewall.yml
[student@workstation inventory-variables (master *)]# cat > group_vars/web_server/firewall.yml <<END
> firewall_rules:
>         # Allow http requests from the load_balancer.
>         - zone: internal
>           service: http
>           source: "172.25.250.10"
> END
[student@workstation inventory-variables (master *)]# cat group_vars/web_server/firewall.yml
firewall_rules:
        # Allow http requests from the load_balancer.
        - zone: internal
          service: http
          source: "172.25.250.10"
# 删除变量信息,留下role
[student@workstation inventory-variables (master *)]# cat deploy_apache.yml
- name: Ensure Apache is deployed
  hosts: web_servers
  force_handlers: True

  roles:
    # The "apache" role has a dependency on the "firewall" role.
    # The "firewall" role requires a "firewall_rules" variable be defined.
    - role: apache
# 给inventory文件中主机添加名称
[student@workstation inventory-variables (master *)]# cat inventory.yml
lb_servers:
  hosts:
    load_balancer:
      ansible_host: servera.lab.example.com

web_servers:
  hosts:
    web_server1:
      ansible_host: serverb.lab.example.com
    web_server2:
      ansible_host: serverc.lab.example.com
# 测试连通性
[student@workstation inventory-variables (master *)]# ansible all -i inventory.yml -m ping
web_server2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
load_balancer | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
web_server1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
[student@workstation inventory-variables (master *)]# ansible-inventory --graph
@all:
  |--@lb_servers:
  |  |--load_balancer
  |--@ungrouped:
  |--@web_servers:
  |  |--web_server1
  |  |--web_server2
# 查看并运行site.yml
[student@workstation inventory-variables (master)]# cat site.yml

- name: Deploy HAProxy
  import_playbook: deploy_haproxy.yml

- name: Deploy Web Server
  import_playbook: deploy_apache.yml

- name: Deploy Web App
  import_playbook: deploy_webapp.yml

[student@workstation inventory-variables (master *)]# ansible-playbook site.yml

PLAY [Ensure HAProxy is deployed] ****************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [load_balancer]

TASK [firewall : Ensure Firewall Sources Configuration] ******************************************************************************

TASK [haproxy : Ensure haproxy packages are present] *********************************************************************************
changed: [load_balancer]

TASK [haproxy : Ensure haproxy is started and enabled] *******************************************************************************
changed: [load_balancer]

TASK [haproxy : Ensure haproxy configuration is set] *********************************************************************************
changed: [load_balancer]

RUNNING HANDLER [haproxy : reload haproxy] *******************************************************************************************
changed: [load_balancer]

PLAY [Ensure Apache is deployed] *****************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [web_server1]
ok: [web_server2]

TASK [firewall : Ensure Firewall Sources Configuration] ******************************************************************************

TASK [apache : Install http] *********************************************************************************************************
changed: [web_server1]
changed: [web_server2]

TASK [apache : Configure SELinux to allow httpd to connect to remote database] *******************************************************
changed: [web_server2]
changed: [web_server1]

TASK [apache : http service state] ***************************************************************************************************
changed: [web_server1]
changed: [web_server2]

PLAY [Ensure Web App is deployed] ****************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [web_server1]
ok: [web_server2]

TASK [webapp : Copy a stub file.] ****************************************************************************************************
changed: [web_server1]
changed: [web_server2]

PLAY RECAP ***************************************************************************************************************************
load_balancer              : ok=5    changed=4    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
web_server1                : ok=6    changed=4    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
web_server2                : ok=6    changed=4    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
# git上传
[student@workstation inventory-variables (master *)]# git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   deploy_apache.yml
        modified:   deploy_haproxy.yml
        modified:   inventory.yml

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        group_vars/

no changes added to commit (use "git add" and/or "git commit -a")
[student@workstation inventory-variables (master *)]# git add -A
[student@workstation inventory-variables (master +)]# git commit -m "Use group vars for author mmx"
[master 1203eb6] Use group vars for author mmx
 6 files changed, 21 insertions(+), 22 deletions(-)
 create mode 100644 group_vars/lb_server/deploy_haproxy.yml
 create mode 100644 group_vars/lb_server/firewall.yml
 create mode 100644 group_vars/web_server/firewall.yml
[student@workstation inventory-variables (master)]# git push
Enumerating objects: 15, done.
Counting objects: 100% (15/15), done.
Delta compression using up to 4 threads.
Compressing objects: 100% (10/10), done.
Writing objects: 100% (11/11), 1.10 KiB | 564.00 KiB/s, done.
Total 11 (delta 3), reused 0 (delta 0)
To http://git.lab.example.com:8081/git/inventory-variables.git
   b1d72e9..1203eb6  master -> master
[student@workstation inventory-variables (master)]# git log
commit 1203eb6bc3a8570209b2a56d6550a0febe858079 (HEAD -> master, origin/master, origin/HEAD)
Author: Git Lab <git@lab.example.com>
Date:   Mon Oct 3 23:22:24 2022 +0800

    Use group vars for author mmx

commit b1d72e956e9802737f6490a3ce3ca3c7a1a30813
Author: Root User <root@localhost>
Date:   Mon Oct 3 17:50:18 2022 +0800

    Adding files
# 实验结束
[student@workstation inventory-variables (master)]# lab inventory-variables finish

Cleaning up the lab for the Guided Exercise: Managing Inventory Variables

 · Cleaning lab files..........................................  SUCCESS
 · Cleaning solutions files....................................  SUCCESS
 · Cloning the inventory-variables repository..................  SUCCESS
 · Retrieving cleanup playbook.................................  SUCCESS
 · Executing cleanup playbook..................................  SUCCESS
 · Removing temporary repository clone.........................  SUCCESS

3、 综合实验

3.1 实验要求

3.2 实验