ansible笔记

ansible

ansible是一个用于集群自动化部署的工具。

ansible工作的架构很简单,分为一个主控结点(control node)和多个被控结点(managed node),主控节点和被控结点之间通过SSH和python来协作。inventory是被控机器的列表文件,用来管理分类被控机器。

安装ansible

在主控结点上需要安装ansible,python,ssh。在被控结点只需要python,ssh。

ssh一般都自带了,然后需要考虑ansible版本对应需要的python版本。

ansible版本 控制结点python 被控结点python
2.11 Python 2.7, Python 3.5 - 3.9 Python 2.6 - 2.7, Python 3.5 - 3.9
2.12 Python 3.8 - 3.10 Python 2.6 - 2.7, Python 3.5 - 3.10
2.13 Python 3.8 - 3.10 Python 2.7, Python 3.5 - 3.10
2.14 Python 3.9 - 3.11 Python 2.7, Python 3.5 - 3.11

在centos7中自带了python2.7,再直接通过yum下载ansible就行。

sudo yum install -y epel-release
sudo yum install -y ansible

inventory文件

inventory文件用来记录被控结点主机信息,并对其进行分组管理。可以在ansible命令行通过-i设置inventory文件路径,也可以写在配置文件ansible.cfg中,都没有那默认就是/etc/ansible/hosts文件。

inventory中按照group划分主机,示例如下

# 保存在./hosts文件中
mail.example.com

[webservers]
foo.example.com
bar.example.com
one.example.com

[dbservers]
one.example.com
two.example.com
three.example.com

查看分组包含哪些主机

可以通过ansible xx --list-hosts命令查看当前选中的xx组都包含哪些主机:

[rc@cos201 hello-ansible]$ ansible webservers -i ./hosts --list-hosts
  hosts (3):
    foo.example.com
    bar.example.com
    one.example.com

all分组

有一个特殊的all分组,包含所有的出现在inventory中的主机,重复的主机名只会出现一次:

[rc@cos201 hello-ansible]$ ansible all -i ./hosts --list-hosts
  hosts (6):
    mail.example.com
    foo.example.com
    bar.example.com
    one.example.com
    two.example.com
    three.example.com

分组嵌套

分组group是可以嵌套的,可以用[xx:children]语法来指定属于xx分组的子分组,示例如下:

# 保存在./hosts文件中
mail.example.com

[webservers]
foo.example.com
bar.example.com
one.example.com

[dbservers]
one.example.com
two.example.com
three.example.com

[servers]
four.example.com

[servers:children]
webservers
dbservers

这个时候查询servers分组,就是自己本身的主机再加上webservers和dbservers之和:

[rc@cos201 hello-ansible]$ ansible servers -i ./hosts --list-hosts
  hosts (6):
    four.example.com
    foo.example.com
    bar.example.com
    one.example.com
    two.example.com
    three.example.com

生成范围主机

自动生成某个范围的主机,示例语法[0:10:1][a:z]

[servers]
# 从01生成到10,步长为1
www[01:10:1].example.com

这个时候查询就有10个主机信息了:

[rc@cos201 hello-ansible]$ ansible servers -i ./hosts --list-hosts
  hosts (10):
    www01.example.com
    www02.example.com
    www03.example.com
    www04.example.com
    www05.example.com
    www06.example.com
    www07.example.com
    www08.example.com
    www09.example.com
    www10.example.com

设置变量

还可以为主机或者分组设置变量,常用变量如下

变量名 说明
ansible_host 主机名
ansible_port 连接端口
ansible_user 执行远程登录用户
ansible_password 登录密码
ansible_ssh_private_key_file ssh密钥登陆对应的密钥文件(连接的时候不需要密码了)
ansible_become 连接后是否自动在受管主机上切换用户
ansible_become_user 要在受管主机上切换到的用户
ansible_become_password 切换用户的密码

给主机设置变量:

[dbservers]
one.example.com ansible_host=192.168.135.202 ansible_user=rc ansible_password=123456

给分组设置变量

[all:vars]
ansible_user=rc
ansible_password=123456

ansible.cfg配置文件

在运行ansible命令时,会加载ansible.cfg配置文件,查找顺序如下:

  1. ANSIBLE_CFG:首先,ansible命令会先检查环境变量,及这个环境变量将指向的配置文件。
  2. ./ansible.cfg:其次,将会检查当前目录下的ansible.cfg配置文件。
  3. ~/.ansible.cfg:再次,将会检查当前用户home目录下的ansible.cfg配置文件。
  4. /etc/ansible/ansible.cfg:最后,将会检查在安装ansible时自动生产的配置文件。

defaults配置(查看配置可以用ansible-config list命令):

配置项 说明 默认值
inventory ansible inventory文件路径 /etc/ansible/hosts
remote_user ansible执行远程登录用户 当前用户
ask_pass 是否提示输入SSH密码 false
become 连接后是否自动在受管主机上切换用户(通常切换为root) false
become_method 如何切换用户 sudo
become_user 要在受管主机上切换到的用户 root
become_ask_pass 是否需要为become_method提示输入密码 false
roles_path ansible role存放路径 /etc/ansible/roles
host_key_checking ansible第一次连接客户端时是否要检查ssh密钥 true

配置文件示例:

[defaults]
inventory=./hosts
remote_user=rc
ask_pass=true
host_key_checking=false

命令行模式操作(ad-hoc模式)

直接使用ansible命令来执行简单的部署命令。官方把这种模式叫做ad-hoc命令模式。也就是临时命令模式。

命令行模式的语法如下,-m表示要用的模块名,如果模块需要参数需要用-a传进参数:

ansible [pattern] -m [module] -a "[module options]"

示例:ansible all -m ping,使用ping模块来测试被控主机是否能连通。

-e "ansible_user=rc ansible_password=123456"可以设置变量,通过命令行设置的变量优先级最高。

常用模块

可以用ansible-doc -s ping命令查看具体模块的详细说明。

ping模块

ping一下被控主机,如果可以通过ansible成功连接,那么返回pong

[rc@cos201 hello-ansible]$ ansible all -m ping
SSH password:
192.168.135.202 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

setup模块

用于收集被控主机的信息。setup的参数如下:

  • filter:对返回的主机信息进行过滤,支持shell通配符,仅展示匹配到的信息。
    • ansible_architecture:显示机器架构,比如x86,x86_64。
    • ansible_distribution:显示是什么发行版,例如centos,ubuntu。
    • ansible_distribution_major_version:发行版主版本号。
    • ansible_hostname:主机名。
    • ansible_kernel:内核信息。
    • ansible_memory_mb:显示内存数据。
[rc@cos201 hello-ansible]$ ansible all -m setup -a "filter=ansible_distribution"
SSH password:
192.168.135.203 | SUCCESS => {
    "ansible_facts": {
        "ansible_distribution": "CentOS",
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}

copy

从本地拷贝文件到远程节点,如果目的文件内容和要拷贝的一样那么不做改变。copy的参数如下:

  • src:本地文件路径。
  • dest:要拷贝到的被控主机的路径。
  • owner:文件属主。
  • group:文件属组。
  • mode:读写权限。
  • backup:当受控主机中存在文件时备份原文件,默认yes。
  • content:指定文本内容直接在受控主机中生成文件。
[rc@cos201 hello-ansible]$ ansible all -m copy -a 'dest=/home/rc/text.txt content="hello ansible"'
SSH password:
192.168.135.202 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "7b320b1dc0c867516cf00728df488daa3532bc1f",
    "dest": "/home/rc/text.txt",
    "gid": 1000,
    "group": "rc",
    "md5sum": "37bc018071eae9a0e879c31b2f9aa554",
    "mode": "0664",
    "owner": "rc",
    "secontext": "unconfined_u:object_r:user_home_t:s0",
    "size": 13,
    "src": "/home/rc/.ansible/tmp/ansible-tmp-1677258597.47-19058-13947958580310/source",
    "state": "file",
    "uid": 1000
}

fetch

从受控主机把文件复制到ansible主机,但不支持目录。fetch的参数如下:

  • src:受控主机的源文件。
  • dest:本机目录。
  • flat:为yes那么直接复制文件过来,为no那么嵌套源文件原本的目录路径。

flat为yes,且受控主机有多个,有多个同名文件要获取的时候,那么文件会覆盖。

[rc@cos201 hello-ansible]$ ansible all -m fetch -a "src=/home/rc/text.txt dest=./ flat=yes"
SSH password:
192.168.135.202 | CHANGED => {
    "changed": true,
    "checksum": "7b320b1dc0c867516cf00728df488daa3532bc1f",
    "dest": "/home/rc/work/hello-ansible/text.txt",
    "md5sum": "37bc018071eae9a0e879c31b2f9aa554",
    "remote_checksum": "7b320b1dc0c867516cf00728df488daa3532bc1f",
    "remote_md5sum": null
}

file

文件操作。file的参数如下:

  • path:文件路径。
  • state:指定操作状态
    • file:获取文件信息。
    • touch:文件不存在创建文件,文件存在更新时间。
    • absent:删除文件或目录。
    • directory 递归创建文件夹。
    • link:建立软链接。
    • hard:建立硬链接。
  • src:对于linkhard生效,指定要链接的源文件。
  • mode:文件读写权限。
  • owner:文件属主。
  • group:文件属组。
  • recurse:为yes时,且statedirectory,那么递归设置文件属性。默认为yes。

unarchive

将文件解压缩到受控主机。unarchive的参数如下:

  • remote_src:要解压的源文件是否在受控主机上,为yes表示在受控主机上,为no表示在控制主机上。
  • src:要解压的源文件路径,如果路径带://还将自动从这个url下载文件来解压。
  • dest:解压目的路径。
  • mode:文件读写权限。
  • owner:文件属主。
  • group:文件属组。

archive

压缩文件。archive参数如下:

  • path:要压缩文件的路径。
  • dest:压缩目的路径。
  • remove:压缩完之后,删除之前的源文件。
  • mode:文件读写权限。
  • owner:文件属主。
  • group:文件属组。

cron

给受控主机设置定时任务。cron参数如下:

  • minute:分钟。
  • hour:小时。
  • day:天。
  • month:月。
  • weekday:周。
  • name:任务名称。
  • job:任务脚本或命令。
  • disabled:yes禁用计划任务。

service

后台服务管理。service参数如下:

  • name:指定服务名称。
  • state:指定对服务的操作。
    • started:开启服务。
    • stopped:停止服务。
    • restarted:重启服务。
    • reload:重新加载服务。
  • enabled:yes开机自启动,no开机不启动。

yum

yum安装软件。yum参数如下:

  • name:软件包名。
  • state:指定对软件包的操作。
    • present:安装。
    • latest:更新。
    • absent:卸载。

脚本操作模式(playbook模式)

只有脚本才可以重用,避免总敲重复的代码。ansible脚本的名字叫playbook,使用的是yaml的格式。

ansible提供了一个单独的命令:ansible-playbook命令,我们可以通过这个命令来执行yaml脚本:

ansible-playbook demo.yaml

最基本的playbook脚本分为三个部分:

  1. 在哪些机器上以什么身份执行。
  2. 执行的任务有哪些。
  3. 善后任务有哪些。

比如下面的playbook(在单一playbook文件中,可以用“---”区分多个play。还有“...”用来表示play的结尾,也可省略):

---
- name: reload apache
  hosts: server1
  remote_user: root
  vars:
    http_port: 80
    max_clients: 200

  tasks:
    - name: Write apache config file
      template: src=/home/test1/httpd.j2 dest=/home/test2/httpd.conf
      notify:
        - restart apache
    - name: Ensure apache is running
      service: name=httpd state=started

  handlers:
    - name: restart apache
      service: name=httpd state=restarted
  • 主机和用户
key 含义
hosts 为主机的IP,或者主机组名,或者关键字all
remote_user 以哪个身份登录远端
become 切换成其他用户身份执行,值为yes或者no
become_method 与become一起使用,值可以为sudo/su等
become_user 要切换成的用户身份,默认为root

为了安全一般是不允许用root登录ssh的,所以一般是先用普通用户登录ssh,然后再切换为root用户(sudo)。

  • Tasks任务列表

tasks是从上到下顺序执行,如果中间发生错误,那么整个playbook会中止。你可以改修文件后,再重新执行。每一个任务都是对模块的一次调用,只是使用不同的参数和变量而已。每一个任务最好有一个name属性,这样在执行yaml脚本时,可以看到执行进度信息。

task中每个action会调用一个module,在module中会去检查当前系统状态是否需要重新执行。

  • 响应事件Handler

Handlers里面的每一个handler,也是对module的一次调用。而handlers与tasks不同,tasks会默认的按定义顺序执行每一个task,handlers则不会,它需要在tasks中被调用,才有可能被执行。

Tasks中的任务都是有状态的,changed或者ok。 在Ansible中,只在task的执行状态为changed的时候,才会执行该task调用的handler,这也是handler与普通的event机制不同的地方。
在所有的任务里表执行之后执行,如果有多个task notify同一个handler,那么只执行一次。

handlers是按照在handlers中定义个顺序执行的,而不是安装notify的顺序执行的。
下面的例子定义的顺序是1>2>3,notify的顺序是3>2>1,实际执行顺序:1>2>3:

---
- hosts: lb
  remote_user: root
  gather_facts: no
  vars:
      random_number1: "{{ 10000 | random }}"
      random_number2: "{{ 10000000000 | random }}"
  tasks:
  - name: Copy the /etc/hosts to /tmp/hosts.{{ random_number1 }}
    copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number1 }}
    notify:
      - define the 3nd handler
  - name: Copy the /etc/hosts to /tmp/hosts.{{ random_number2 }}
    copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number2 }}
    notify:
      - define the 2nd handler
      - define the 1nd handler
  handlers:
  - name: define the 1nd handler
    debug: msg="define the 1nd handler"
  - name: define the 2nd handler
    debug: msg="define the 2nd handler"
  - name: define the 3nd handler
    debug: msg="define the 3nd handler"

常用语法

ignore_errors:ansible的playbook在执行任务出现错误的时候会停止运行,如果需要忽略错误继续运行可以用该语法:

# 当没有docker服务的时候也不报错
- name: stop docker service
  systemd:
    name: docker
    daemon_reload: yes
    state: stopped
    enabled: yes
  ignore_errors: true

connection: local:如果希望在控制主机本地运行一个特定的任务,可以使用local_action语句:

# 等待被控端sshd端口开启
- name: wait for ssh server to be running
  wait_for
      port: 22 
      host: "{{ inventory_hostname }}" 
      search_regex: OpenSSH
  connection: local

delegate_to:可以使用delegate_to语句来在另一台主机上运行task,注意这里delegate_to不是只在指定的机器上执行一次任务,而是在指定机器上执行所有任务,比如上面的connection: local等价于delegate_to: 127.0.0.1

- name: enable alerts for web servers
  hosts: webservers
  tasks:
    - name: enable alerts
      nagios: action=enable_alerts service=web host="{{ inventory_hostname }}"
      delegate_to: nagios.example.com

run_once:当有多台主机要执行任务时,那么只有一台机器会执行任务,可以和delegate_to搭配指定在哪台机器上执行任务:

- name: run the task locally, only once
  command: /opt/my-custom-command
  run_once: true
  delegate_to: app.a1-61-105.dev.unp

roles

roles 用于层次性、结构化地组织playbook。
在ansible中,通过遵循特定的目录结构,就可以实现对role的定义:

site.yml
roles/
├── myrole
    ├── tasks
    │   └── main.yml
    ├── handlers
    │   └── main.yml
    ├── defaults
    │   └── main.yml
    ├── vars
    │   └── main.yml
    ├── files
    ├── templates
    ├── README.md
    ├── meta
    │   └── main.yml
    └── tests
        ├── inventory
        └── test.yml

ansible并不要求role包含上述所有的目录及文件,根据role的功能需要加入对应的目录和文件。下面是每个目录和文件的功能:

  • 如果roles/x/tasks/main.yml存在, 其中列出的 tasks 将被添加到 play 中,所以这个文件也可以视作role的入口文件,想看role做了什么操作,可以从此文件看起。
  • 如果roles/x/handlers/main.yml存在, 其中列出的 handlers 将被添加到 play 中
  • 如果roles/x/vars/main.yml存在, 其中列出的 variables 将被添加到 play 中
  • 如果roles/x/meta/main.yml存在, 其中列出的 “角色依赖” 将被添加到 roles 列表中
  • roles/x/tasks/main.yml中所有tasks,可以引用roles/x/{files,templates,tasks}中的文件,不需要指明文件的路径。

roles和tasks的执行顺序:

  • pre_tasks > role > tasks > post_tasks

变量优先级

下面是变量的优先级,由高到低:

  • extra vars:通过命令行穿进去的变量,例如-e "user=my_user"
  • include params
  • role (and include_role) params
  • set_facts / registered vars
  • include_vars
  • task vars (only for the task):在task中定义的变量。
  • block vars (only for tasks in block)
  • role vars (defined in role/vars/main.yml)
  • play vars_files
  • play vars_prompt
  • play vars
  • host facts / cached set_facts
  • playbook host_vars/*playbook group_vars/all
  • inventory host_vars/*
  • inventory file or script host vars
  • playbook group_vars/*
  • inventory group_vars/*
  • playbook group_vars/all
  • inventory group_vars/all
  • inventory file or script group vars
  • role defaults (defined in role/defaults/main.yml)
  • command line values (for example, -u my_user, these are not variables)

group_vars 存放的是组变量,group_vars/all.yml 表示所有主机有效,等同于[all:vars],grous_vars/etcd.yml 表示etcd组主机有效,等同于[etcd:vars]。

参考资料

posted @   HachikoT  阅读(77)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示