27、配置管理系统与代码即配置(CaC)工具详解

配置管理系统与代码即配置(CaC)工具详解

1. 引言

在系统管理领域,配置管理(CM)和代码即配置(CaC)是至关重要的概念与工具。它们能够帮助系统管理员高效地部署、配置和维护 IT 系统。本文将详细介绍几种常见的 CM 系统,如 Puppet、CFEngine,并重点介绍 Ansible 这一强大的 CaC 工具。

2. Puppet 系统

Puppet 是一种广泛使用的 CM 系统,通过编写清单(manifest)来定义系统的配置。以下是一个简单的 Puppet 配置示例,用于配置 Nginx:

require => File['/etc/nginx/sites-available/yourdomain.tld.conf'],
}
# Restart Nginx when the configuration changes
service { 'nginx':
  ensure     => running,
  enable     => true,
  subscribe  => File['/etc/nginx/sites-enabled/yourdomain.tld.conf'],
}

当你创建好清单并将其放置在 Puppet 服务器上后,安装在服务器上的 Puppet 代理会自动获取并执行这些配置。通信通过 TLS 协议进行加密,保障了数据的安全性。

Puppet 代理节点会运行一个 Puppet 代理进程,通过 TCP 端口 8140 连接到主服务器。代理会向服务器发送证书签名请求(CSR),管理员必须批准该请求。一旦 CSR 被批准,代理就可以访问服务器的 Puppet 配置。

代理运行时,会向主服务器请求其配置,服务器会返回一个资源目录,代理会根据该目录对节点进行配置,如安装软件包、更新配置文件或启动/停止服务。配置完成后,代理会向服务器发送报告,用于监控和审计。

3. CFEngine 系统

CFEngine 是一个开源的 CM 系统,由 Mark Burgess 于 1993 年创建。它以其强大而灵活的语言来描述系统配置和执行策略,适用于复杂的 IT 环境。CFEngine 的第一个版本于 1994 年发布,是现存最古老的 CM 工具之一。

CFEngine 不断更新和改进,以适应不断变化的 IT 环境和新兴技术。最新版本 3.18 具有改进的加密、增强的监控功能和更好的云基础设施支持。

以下是一个简单的 CFEngine 配置示例:

##############################################################
# cf.main - for master infrastructure server
##################################################################
###
# BEGIN cf.main
###
control:
    access     = ( root )      # Only root should run this
    site       = ( main )
    domain     = ( example.com )
    sysadm     = ( admin@example.com )
    repository = ( /var/spool/cfengine )
    netmask    = ( 255.255.255.0 )
    timezone   = ( CET )
#################################################################
files:
    Prepare::
        /etc/motd              m=0644 r=0 o=root act=touch
4. Ansible 工具

Ansible 是我们选择的 CaC 工具,它用 Python 编写,源代码可自由下载和修改(遵循 Apache License 2.0)。Ansible 具有以下特点:
- 模块化 :Ansible 不是一个单一的工具,而是一个核心程序,每个任务都作为一个单独的模块编写,形成一个库。这种设计产生了一个清晰的 API,任何人都可以使用它来编写自己的模块。
- 幂等性 :无论执行多少次配置,结果始终相同。这是 Ansible 最重要的基本特性之一,你无需知道哪些操作已经执行,当扩展配置并再次运行工具时,它会自动检测系统状态并只应用新的操作。
- 无代理 :Ansible 不会在被配置的系统上安装代理。但要执行 Ansible 脚本,目标系统需要有连接方式(通常是运行 SSH 服务器)和安装 Python 语言。这种模式带来了以下优点:
- Ansible 不关心通信协议,使用 SSH 但不实现它,将细节留给操作系统、SSH 服务器和客户端。你可以自由更换 SSH 解决方案,Ansible 剧本应能按预期工作。
- Ansible 项目无需为管理节点开发和维护单独的程序,这不仅减轻了开发者的负担,还降低了安全漏洞被发现和利用的可能性。
- 在使用代理的解决方案中,如果代理程序因任何原因停止工作,就无法向系统交付新的配置。而 SSH 服务器通常广泛使用,故障概率可忽略不计。
- 使用 SSH 作为通信协议降低了防火墙阻止 CM 系统通信端口的风险。
- 声明式 :编写 Ansible 剧本的人无需过多关注具体的操作方式,只需指定 Ansible 完成后系统的期望状态。例如,要确保 Nginx 安装,配置条目如下:

- name: install nginx
  package:
    name: nginx
    state: present
5. Ansible 的使用基础
5.1 安装 Ansible

在不同的操作系统上安装 Ansible 的方法不同:
- Debian 系发行版

$ sudo apt-get install ansible
  • Fedora Linux 发行版
$ sudo dnf install ansible
  • 使用 Python 虚拟环境和 pip 安装最新版本
$ python3 -m venv venv
$ source venv/bin/activate
$ pip install -U pip
$ pip install ansible
5.2 简单命令示例:ad hoc ping
$ ansible all -m ping -i inventory

这个命令尝试连接指定主机并打印连接结果。其中, -m ping 表示使用 ping 模块, -i inventory 表示使用名为 inventory 的库存文件。如果不指定库存文件,Ansible 将尝试使用 /etc/ansible/hosts ,这通常不是一个好主意。

5.3 库存文件

库存文件是一个简单而强大的工具,用于列出、分组和为管理节点提供变量。以下是一个示例库存文件:

[www]
hostone ansible_host=192.168.1.2 ansible_ssh_private_key_file=~/.ssh/hostone.pem ansible_user=admin

这个文件定义了一个名为 www 的节点组,其中包含一个名为 hostone 的节点,并指定了其 IP 地址、SSH 私钥文件和登录用户名。

6. Ansible 的核心概念
6.1 任务(Tasks)

任务是 Ansible 配置的核心,是要在管理节点上运行的操作。任务包含在剧本(plays)中,可以直接放在剧本中,也可以通过角色(roles)间接包含。

6.2 角色(Roles)

角色是可重用的 Ansible 内容的有限分发,用于在剧本中组织任务、处理程序、变量、插件、模板和文件。通过将剧本分解为角色,可以更轻松高效地管理单独的任务,并且使包含这些任务的文件更易读。

角色在 Ansible 中有预定的目录结构,常见的子目录包括 tasks templates files vars handlers 。以下是一个角色目录结构的示例:

roles/
    common/          # this hierarchy represents a "role"
        tasks/
            main.yml  # <-- tasks file can include smaller files if warranted
        handlers/
            main.yml  # <-- handlers file
        templates/
            ntp.conf.j2  # <------- templates end in .j2
        files/
            bar.txt  # <-- files for use with the copy resource
            foo.sh   # <-- script files for use with the script resource
        vars/
            main.yml  # <-- variables associated with this role
        defaults/
            main.yml  # <-- default lower priority variables for this role
        meta/
            main.yml  # <-- role dependencies
        library/     # roles can also include custom modules
        module_utils/  # roles can also include custom module_utils
        lookup_plugins/  # or other types of plugins, like lookup in this case
6.3 剧本(Playbooks)

剧本是 Ansible 的入口点,是定义剧本的 YAML 文件。以下是一个简单的剧本示例,用于在管理节点上安装 Nginx 和 PHP 包:

---
- name: Install nginx and php
  hosts: www
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.package:
        name: nginx
        state: present
    - name: Install php
      ansible.builtin.package:
        name: php8
        state: present
    - name: Start nginx
      ansible.builtin.service:
        name: nginx
        state: started

在运行剧本之前,建议使用 ansible-lint 工具检查剧本的语法错误和最佳实践:

$ ansible-lint install.yaml
7. 总结

使用 CaC 工具具有许多优点,如配置可以通过自动化工具进行语法检查、可以无限次应用且结果相同、可以在多个系统上并行运行、可以保存在版本控制系统中以便查看更改历史和注释,还可以由自动化工具运行,减少了人工干预。

Ansible 作为一种强大的 CaC 工具,通过其模块化、幂等性、无代理和声明式的特点,为系统管理员提供了一种高效、灵活的方式来管理系统配置。通过合理使用角色和剧本,可以更好地组织和管理复杂的配置任务。

流程图:Puppet 工作流程

graph LR
    A[创建 Puppet 清单] --> B[放置在 Puppet 服务器]
    B --> C[Puppet 代理获取清单]
    C --> D[代理发送 CSR 请求]
    D --> E{管理员批准 CSR}
    E -- 是 --> F[代理访问配置]
    F --> G[代理请求配置]
    G --> H[服务器返回资源目录]
    H --> I[代理应用配置]
    I --> J[代理发送报告]
    E -- 否 --> K[等待批准]

表格:Ansible 安装方法对比

操作系统 安装命令
Debian 系发行版 sudo apt-get install ansible
Fedora Linux 发行版 sudo dnf install ansible
使用 Python 虚拟环境和 pip python3 -m venv venv; source venv/bin/activate; pip install -U pip; pip install ansible

8. Ansible 剧本的实际操作与优化

8.1 剧本的调试与修正

当我们编写好一个 Ansible 剧本后,使用 ansible-lint 工具可以检查剧本中的语法错误和不符合最佳实践的地方。例如,对于之前的 install.yaml 剧本,运行 ansible-lint install.yaml 后可能会得到如下输出:

WARNING: PATH altered to expand ~ in it. Read https://stackoverflow.com/a/44704799/99834 and correct your system configuration.
WARNING  Listing 9 violation(s) that are fatal
yaml[trailing-spaces]: Trailing spaces
install.yaml:1
yaml[truthy]: Truthy value should be one of [false, true]
install.yaml:4
fqcn[action-core]: Use FQCN for builtin module actions (package).
install.yaml:6 Use `ansible.builtin.package` or `ansible.legacy.package` instead.
[...]
yaml[empty-lines]: Too many blank lines (1 > 0)
install.yaml:18
Read documentation for instructions on how to ignore specific rule violations.
        Rule Violation Summary
 count tag               profile    rule associated tags
     1 yaml[empty-lines] basic      formatting, yaml
     1 yaml[indentation] basic      formatting, yaml
     3 yaml[trailing-spaces] basic  formatting, yaml
     1 yaml[truthy]            basic  formatting, yaml
     3 fqcn[action-core]       production formatting
Failed after min profile: 9 failure(s), 0 warning(s) on 1 files.

根据这些提示,我们可以对剧本进行修正。修正后的剧本如下:

---
- name: Install nginx and php
  hosts: www
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.package:
        name: nginx
        state: present
    - name: Install php
      ansible.builtin.package:
        name: php8
        state: present
    - name: Start nginx
      ansible.builtin.service:
        name: nginx
        state: started
8.2 剧本的运行与结果分析

使用 ansible-playbook 命令来运行剧本:

$ ansible-playbook -i inventory install.yaml

运行结果可能如下:

PLAY [Install nginx and php] ***************************************************
TASK [Gathering Facts] *********************************************************
ok: [hostone]
TASK [Install nginx] ***********************************************************
changed: [hostone]
TASK [Install php] *************************************************************
fatal: [hostone]: FAILED! => {"changed": false, "msg": "No package matching 'php8' is available"}
PLAY RECAP *********************************************************************
hostone         : ok=2    changed=1    reachable=0    failed=1    skipped=0    rescued=0    ignored=0

从结果中可以看出, nginx 安装成功,但 php8 安装失败,原因是目标系统中没有 php8 包。经过检查,发现实际可用的是 php7.4 包,修改剧本后再次运行:

$ ansible-playbook -i inventory install.yaml

新的运行结果如下:

PLAY [Install nginx and php] ***************************************************
TASK [Gathering Facts] *********************************************************
ok: [hostone]
TASK [Install nginx] ***********************************************************
ok: [hostone]
TASK [Install php] *************************************************************
changed: [hostone]
TASK [Start nginx] *************************************************************
ok: [hostone]
PLAY RECAP *********************************************************************
hostone         : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

此时, nginx 已安装, php7.4 也安装成功,并且 nginx 已启动。

8.3 剧本的优化:循环任务

为了避免为每个要安装的包都编写一个单独的任务,我们可以使用循环。修改后的剧本如下:

---
- name: Install nginx and php
  hosts: www
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.package:
        name: '{{ item }}'
        state: present
      with_items:
        - nginx
        - php7.4
        - gcc
        - g++ 
    - name: Start nginx
      ansible.builtin.service:
        name: nginx
        state: started

在运行这个剧本之前,先使用 ansible-lint 检查:

$ ansible-lint install.yaml

如果检查通过,再运行剧本:

$ ansible-playbook -i inventory install.yaml

运行结果会显示每个包的安装情况。

8.4 剧本的优化:使用通知和处理程序

假设我们要安装一个 Nginx 的页面配置,并在服务设置完成后只重启一次 Nginx。可以使用 notify handlers 来实现。完整的剧本如下:

---
- name: Install nginx and php
  hosts: www
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.package:
        name: '{{ item }}'
        state: present
      with_items:
        - nginx
        - php7.4
        - gcc
        - g++
      notify:
        - Start nginx
    - name: Copy service configuration
      ansible.builtin.copy:
        src: "files/service.cfg"
        dest: "/etc/nginx/sites-available/service.cfg"
        owner: root
        group: root
        mode: '0640'
    - name: Enable site
      ansible.builtin.file:
        src: "/etc/nginx/sites-available/service.cfg"
        dest: "/etc/nginx/sites-enabled/default"
        state: link
      notify:
        - Restart nginx
  handlers:
    - name: Start nginx
      ansible.builtin.service:
        name: nginx
        state: started
    - name: Restart nginx
      ansible.builtin.service:
        name: nginx
        state: restarted

运行这个剧本后,Ansible 会根据任务的执行情况触发相应的处理程序。

9. Ansible 角色的使用与管理

9.1 角色的概念与作用

随着剧本的复杂度增加,将任务分割成角色可以使管理更加清晰。角色可以根据管理节点的功能进行分组,例如 HTTP 服务器、数据库服务器、文件服务器等。一个管理节点可以有多个角色。

9.2 角色的目录结构

Ansible 角色有预定的目录结构,常见的子目录包括 tasks templates files vars handlers 。以下是一个角色目录结构的示例:

roles/
    common/          # this hierarchy represents a "role"
        tasks/
            main.yml  # <-- tasks file can include smaller files if warranted
        handlers/
            main.yml  # <-- handlers file
        templates/
            ntp.conf.j2  # <------- templates end in .j2
        files/
            bar.txt  # <-- files for use with the copy resource
            foo.sh   # <-- script files for use with the script resource
        vars/
            main.yml  # <-- variables associated with this role
        defaults/
            main.yml  # <-- default lower priority variables for this role
        meta/
            main.yml  # <-- role dependencies
        library/     # roles can also include custom modules
        module_utils/  # roles can also include custom module_utils
        lookup_plugins/  # or other types of plugins, like lookup in this case
9.3 实际创建角色

假设我们有一个 install.yaml 剧本,为了更好地管理任务,我们创建 www development 两个角色。
首先,修改库存文件:

[www]
hostone ansible_host=192.168.1.2 ansible_ssh_private_key_file=~/.ssh/hostone.pem ansible_user=admin
[development]
hostone ansible_host=192.168.1.3 ansible_ssh_private_key_file=~/.ssh/hostone.pem ansible_user=admin

然后,修改 install.yaml 剧本:

---
- name: Install nginx and php
  hosts: www
  roles:
    - www
  become: true
- name: Install development packages
  hosts: development
  roles:
    - development
  become: true

www 角色的 tasks/main.yaml 文件内容如下:

---
- name: Install nginx
  ansible.builtin.package:
    name: '{{ item }}'
    state: present
  with_items:
    - nginx
    - php7.4
  notify:
    - Start nginx
- name: Copy service configuration
  ansible.builtin.copy:
    src: "files/service.cfg"
    dest: "/etc/nginx/sites-available/service.cfg"
    owner: root
    group: root
    mode: '0640'
- name: Enable site
  ansible.builtin.file:
    src: "/etc/nginx/sites-available/service.cfg"
    dest: "/etc/nginx/sites-enabled/default"
    state: link
  notify:
    - Restart nginx

www 角色的 handlers/main.yaml 文件内容如下:

---
- name: Start nginx
  ansible.builtin.service:
    name: nginx
    state: started
  listen: "Start nginx"
- name: Restart nginx
  ansible.builtin.service:
    name: nginx
    state: restarted
  listen: "Restart nginx"

development 角色的 tasks/main.yaml 文件内容如下:

---
- name: Install compilers
  ansible.builtin.package:
    name: '{{ item }}'
    state: present
  with_items:
    - gcc
    - g++

10. 总结与展望

10.1 使用 CaC 工具的优势总结

使用代码即配置(CaC)工具具有诸多优势:
- 语法检查 :配置可以通过自动化工具进行语法检查,确保配置的正确性。
- 幂等性 :可以无限次应用且结果相同,避免了重复操作带来的问题。
- 并行运行 :可以在多个系统上并行运行,提高了配置效率。
- 版本控制 :可以保存在版本控制系统中,方便查看更改历史和注释。
- 自动化执行 :可以由自动化工具运行,减少了人工干预。

10.2 Ansible 的优势与应用前景

Ansible 作为一种强大的 CaC 工具,通过其模块化、幂等性、无代理和声明式的特点,为系统管理员提供了一种高效、灵活的方式来管理系统配置。在未来,随着 IT 系统的不断发展和复杂化,Ansible 的应用前景将更加广阔。通过合理使用角色和剧本,可以更好地组织和管理复杂的配置任务,满足不同场景的需求。

流程图:Ansible 剧本运行流程

graph LR
    A[编写 Ansible 剧本] --> B[使用 ansible-lint 检查]
    B -- 通过 --> C[使用 ansible-playbook 运行]
    B -- 未通过 --> D[修正剧本]
    D --> B
    C --> E{任务执行情况}
    E -- 成功 --> F[结束]
    E -- 失败 --> G[分析失败原因]
    G --> D

表格:Ansible 角色与任务管理对比

管理方式 优点 缺点
单一剧本 简单直接,适合简单配置 复杂配置时难以管理
角色管理 清晰组织任务,提高可维护性 需要了解角色目录结构
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值