Ansible简介

我是在学习部署okd与ansible相遇的,我从来没有特地去学习这么一款工具,只是需要的时候查阅一下官方文档,ansible真的足够简单,可以想使用命令行一样使用ansible,当然ansible也可以做一些不简单的事情。
Ansible是一种IT自动化工具。它可以配置系统,部署软件以及协调更高级的IT任务,例如连续部署或零停机滚动更新。Ansible的主要目标是简单和易用。它还非常关注安全性和可靠性,其特点是活动部件最少,使用OpenSSH进行运输(使用其他运输方式和拉动模式作为替代方案)以及一种围绕人员(即使是不熟悉的人)可审核性设计的语言。

Ansible概念

控制节点(Control node)

任何装有Ansible的机器。可以从任何控制节点调用/usr/bin/ansible或来运行命令和运行playbook /usr/bin/ansible-playbook。可以将任何安装了Python的计算机用作控制节点-笔记本电脑,共享台式机和服务器都可以运行Ansible。但是,不能将Windows计算机用作控制节点。您可以有多个控制节点。

受控节点(Managed nodes)

使用Ansible管理的网络设备(和/或服务器)。受管节点有时也称为“主机”。未在受管节点上安装Ansible。

管理清单(Inventory)

受控节点的列表。清单文件有时也称为“主机文件”。您的清单可以为每个受管节点指定信息,例如IP地址。库存还可以组织受管节点,创建和嵌套组以便于扩展。默认是使用/etc/ansible/hosts 文件作为管理清单文件。在运行时可以通过-i 自定义hosts地址。详细请参考:管理清单

模块(Modules)

将执行代码单元Ansible。从管理特定类型的数据库上的用户到管理特定类型的网络设备上的VLAN接口,每个模块都有特定的用途。您可以通过ansible命令调用单个模块,也可以在playbook中调用多个不同的模块。详细请参考:所有模块

任务(Tasks)

Ansible中的行动单位。您可以使用临时命令一次执行一个任务。

PlayBook

已保存任务的有序列表,因此您可以按此顺序重复运行这些任务。剧本可以包括变量以及任务。剧本采用YAML编写,易于阅读,编写,共享和理解。要了解有关剧本的更多信息,请参阅关于Playbook

安装Ansible

ansible的安装非常简单,CentOS下安装:yum install -y ansible,Ubantu下安装: sudo apt update && sudo apt install software-properties-common && sudo apt-add-repository --yes --update ppa:ansible/ansible && sudo apt install ansible 更多系统安装ansible请参考Installing Ansible

配置文件

ansible配置文件有两个ansible.cfghosts,前者为ansible软件配置,如常见的第一次访问host_key_checking,连接超时时间。后者为批量执行的受控机配置和变量设置。

ansible.cfg

ansible.cfg 配置文件优先级:

  1. ANSIBLE_CONFIG (环境变量配置)
  2. ansible.cfg(当前目录,存在风险,不会主动加载)
  3. ~/.ansible.cfg(当前用户主目录)
  4. /etc/ansible/ansible.cfg

ansible会安装以上列表并使用第一个找到的配置文件,可以通过ansible-config listansible-config dump --only-changed查看ansible配置情况

常用的ansible.cfg文件内容如下:

[defaults]
log_path = /var/log/ansible.log

forks = 20
host_key_checking = False
retry_files_enabled = False
deprecation_warnings = False
nocows = True
remote_user = root
roles_path = roles/
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /etc/ansible/facts
fact_caching_timeout = 600
callback_whitelist = profile_tasks
inventory_ignore_extensions = secrets.py, .pyc, .cfg, .crt, .ini
timeout = 30

[inventory]
unparsed_is_failed=true

[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=600s
timeout = 10
control_path = %(directory)s/%%h-%%r

以上配置文件,主要配置了日志路径、远程用户信息、超时时间等。更多信息请参考:ansible.cfg exampleansible configuration

hosts

管理清单(host文件)默认在/etc/ansible/hosts,可以通过命令行 -i <path>参数进行指定,-i参数可以多次指定,也就是说,ansible支持多个hosts文件同时使用。host文件支持iniyaml两种格式。

ini文件:

mail.example.com

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

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

yaml格式:

all:
  hosts:
    mail.example.com:
  children:
    webservers:
      hosts:
        foo.example.com:
        bar.example.com:
        two.example.com:
    dbservers:
      hosts:
        one.example.com:
        two.example.com:
        three.example.com:

这两个文件的内容是等价的,当你需要多级结构时,推荐使用yaml,否则ini将更加方便。host文件中存在2个默认组allungrouped。前者包含了每一个主机,后者则是除了all没有分组的。如示例中的mail.expample.com,一个host可以存在于多个组里面,如two.example.com:

ansible 支持添加一个范围的host:

在INI文件中:

[webservers]
www[01:50].example.com

在yaml文件中:

webservers:
  hosts:
    www[01:50].example.com:

表示1-50的主机,此外host文件支持字符顺序如:


[databases]
db-[a:f].example.com

host文件支持添加变量,如:

在INI文件中:

[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909

在YAML文件中:

atlanta:
  host1:
    http_port: 80
    maxRequestsPerChild: 808
  host2:
    http_port: 303
    maxRequestsPerChild: 909

对于一些像非标准的ssh端口,可以在hostname后面添加port:

badwolf.example.com:5309

但是ansible可以通过openssh的连接去找到并使用这些端口。

连接的变量也可以通过host变量描述:


localhost              ansible_connection=local
other1.example.com     ansible_connection=ssh        ansible_user=myuser
other2.example.com     ansible_connection=ssh        ansible_user=myotheruser

host文件支持别名

INI文件:

jumper ansible_port=5555 ansible_host=192.0.2.50

yaml文件

hosts:
  jumper:
    ansible_port: 5555
    ansible_host: 192.0.2.50

在命令行或者playbook文件中可以通过别名使用对应的host,在上面的例子中指定了端口号。

host支持组变量,相当于每一个host都继承了组变量:

INI文件:

[atlanta]
host1
host2

[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com

YAML文件:

atlanta:
  hosts:
    host1:
    host2:
  vars:
    ntp_server: ntp.atlanta.example.com
    proxy: proxy.atlanta.example.com

不过这会导致一个问题:一个host在多个组,且多个组都设置同一个变量。这将引起冲突,ansible将按照字符顺序选择最后一个(尽量避免这种问题出现),ansible支持通过ansible_group_priority修改优先级,默认值为1。具体规则参考 rules for merging

此外,host文件支持多重组变量集成,通过:childrenchildren:分别在INI和YAML来使用:

INI文件:

[atlanta]
host1
host2

[raleigh]
host2
host3

[southeast:children]
atlanta
raleigh

[southeast:vars]
some_server=foo.southeast.example.com
halon_system_timeout=30
self_destruct_countdown=60
escape_pods=2

[usa:children]
southeast
northeast
southwest
northwest

YAML文件:

all:
  children:
    usa:
      children:
        southeast:
          children:
            atlanta:
              hosts:
                host1:
                host2:
            raleigh:
              hosts:
                host2:
                host3:
          vars:
            some_server: foo.southeast.example.com
            halon_system_timeout: 30
            self_destruct_countdown: 60
            escape_pods: 2
        northeast:
        northwest:
        southwest:

hosts文件支持变量文件的添加,分别对应host变量和group_vars,hosts的变量文件存放位置可以在/etc/ansible/group_vars//etc/ansible/host_vars/,如:

/etc/ansible/group_vars/raleigh # can optionally end in '.yml', '.yaml', or '.json'
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball

同样ansible支持以组名作为目录:

/etc/ansible/group_vars/raleigh/db_settings
/etc/ansible/group_vars/raleigh/cluster_settings

ansible也支持多个hosts文件在指定目录里:

inventory/
  openstack.yml          # configure inventory plugin to get hosts from Openstack cloud
  dynamic-inventory.py   # add additional hosts with dynamic inventory script
  static-inventory       # add static hosts and groups
  group_vars/
    all.yml              # assign variables to all hosts

然后运行:ansible-playbook example.yml -i inventory

ansible 有很多内置变量,如: ssh连接变量,docker,local,详见:inventory parameters

hosts文件支持很多插件:Inventory Plugins

hosts文件同样支持动态功能:dynamic inventory

控制模式

ansible 在运行相关任务的时候,即通过ansible或者在编写ansible-playbook的文件,指定哪些受控主机需要执行任务的时候。可以通过以下通用模式指定:

描述模式目标主机
所有主机all(*)
一个主机host1
多个主机host1:host2(host1,host2)
一个分组ins
分组并集ins:nodes所有在ins加上所有在nodes的主机
分组差集ins:!nodes所有在ins但不在nodes的主机
分组交集ins:&nodes所有在ins也在nodes的主机

可以像这样:ins:nodes:&infra:!master,表示ins和nodes并且都在infra且不是master的hosts
受控模式同样支持通配符:

192.0.\*
\*.example.com
\*.com

one*.com:dbservers

在模式中使用变量,可以在 ansible-playbook使用-e注入变量

webservers:!:&

在模式中使用数组角标,比如存在ins:

[ins]
master
infra
nodes

可以通过数组角标来指定host:

ins[0]       # master
ins[-1]      # nodes
ins[0:2]     # ini[0],ins[1]
ins[1:]      #  infra nodes
ins[:3]      # master,infra,nodes

在模式中使用正则匹配,以~开头

~(web|db).*\.example\.com

临时命令(命令行)

ansible拥有开箱即用的功能,只要配置好了上面两个文件运行命令行ansible all -m ping 即可以查看各受控主机的状态。

临时命令用于快速批量执行命令:

ansible [模式] -m [模块] -a "[模块参数]"

ansible在不使用-m 指定模块时,默认使用command模块,默认情况下ansible使用5个并发进程,当你想指定进程数时可以通过-f ,通过-u 指定执行用户,通过--become提升用户权限:


ansible atlanta -a "/sbin/reboot" -f 10 -u username --become 。

常见模块

管理文件

  1. 复制文件:ansible ins -m copy -a "src=/etc/hosts dest=/tmp/hosts`

  2. 创建文件: ansible ins -m file -a "dest=/srv/foo/b.txt mode=600 owner=bryce group=bryce"

  3. 创建目录:ansible ins -m file -a "dest=/path/to/c mode=755 owner=bryce group=bryce state=directory"

  4. 删除文件:ansible ins -m file -a "dest=/path/to/c state=absent"

管理包

  1. 安装包:ansible ins -m yum -a "name=java-1.8.0-openjdk state=present"
  2. 确保包为最新:ansible ins -m yum -a "name=java state=latest"
  3. 确保未安装包:ansible webservers -m yum -a "name=java state=absent"

管理用户和组

  1. 创建用户:ansible all -m user -a "name=bryce password=<crypted password here>"
  2. 删除用户:ansible all -m user -a "name=bryce state=absent"

管理服务

  1. 启动服务:ansible ins -m service -a "name=httpd state=started"
  2. 停止服务: ansible ins -m service -a "name=httpd state=stopped"

收集信息

ansible all -m setup

Playbooks

playbooks是ansible的配置,部署和编排语言。真正具有生产力的搬砖工具。

在介绍playbook之前,我们先来看看一个playbook的文档结构

这是我一个安装ElasticSearch的简单例子:

.
├── elasticsearch.yml
├── roles
│   ├── after_install
│   │   └── tasks
│   │       └── main.yml
│   ├── certs
│   │   └── tasks
│   │       └── main.yml
│   ├── elasticsearch
│   │   ├── tasks
│   │   │   ├── config_elasticsearch.yml
│   │   │   ├── install_elasticsearch.yml
│   │   │   ├── main.yml
│   │   │   └── redhat.yml
│   │   └── templates
│   │       ├── elasticsearch
│   │       ├── elasticsearch.yml
│   │       └── jvm.options
│   └── user
│       └── tasks
│           └── main.yml
└── vars
    └── elasticsearch.yml

包含了运行主文件elasticsearch.yml、roles文件夹、vars变量文件夹。roles文件包含了多个模块的任务,其中elasticsearch用到了模板。

基础

hosts和users

每一个playbook都需要声明hosts和user,用户可以在每一个task上指定也可以在全局指定。become用于提升权限

---
- hosts: webservers
  remote_user: root
  tasks:
    - name: test connection
      ping:
      remote_user: yourname
      become: yes

tasks列表

在上面的tasks:表示一系列需要执行的任务,如:

tasks:
  - name: enable selinux
    command: /sbin/setenforce 1

  - name: run this command and ignore the result
    shell: /usr/bin/somecommand
    ignore_errors: True

  - name: Copy ansible inventory file to client
    copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
            owner=root group=root mode=0644

  - name: create a foo.conf file
    template:
    src: templates/foo.j2
    dest: /etc/foo.conf

变量

在playbook任何地方都可以使用两个花括号{{}}注入变量,但是需要注意yaml语法陷阱,在yaml使用变量时,需要将变量所在位置连续字符用""包裹。

变量的定义

变量可以定义在hosts文件中定义在playbook中,也可以引用变量文件:

- hosts: ins
  vars:
    http_port: 80
  vars_files:
    - /vars/external_vars.yml

也可以在任务中注册变量:

- hosts: ins

  tasks:

     - shell: /usr/bin/foo
       register: foo_result
       ignore_errors: True

     - shell: /usr/bin/bar
       when: foo_result.rc == 5

ansible关键字不能定义为变量,关键字:

add, append, as_integer_ratio, bit_length, capitalize, center, clear, conjugate, copy, count, decode, denominator, difference, difference_update, discard, encode, endswith, expandtabs, extend, find, format, fromhex, fromkeys, get, has_key, hex, imag, index, insert, intersection, intersection_update, isalnum, isalpha, isdecimal, isdigit, isdisjoint, is_integer, islower, isnumeric, isspace, issubset, issuperset, istitle, isupper, items, iteritems, iterkeys, itervalues, join, keys, ljust, lower, lstrip, numerator, partition, pop, popitem, real, remove, replace, reverse, rfind, rindex, rjust, rpartition, rsplit, rstrip, setdefault, sort, split, splitlines, startswith, strip, swapcase, symmetric_difference, symmetric_difference_update, title, translate, union, update, upper, values, viewitems, viewkeys, viewvalues, zfill

系统变量

ansible有一些内置的变量

  1. ansible_facts可以通过ansible hostname -m setup 查看,引用{{ ansible_facts['devices']['xvda']['model'] }}

  2. hostvars 运行的主机变量

  3. groups 是hosts中所有组(和主机)的列表。这可用于枚举组中的所有主机。
  4. group_names 是当前主机所在的所有组的列表(数组)。
  5. inventory_hostname Ansible的hosts文件中配置的主机名的名称

模板

ansible的模板使用的是Jinja2,具体可以参考模板(Jinja2)

使用了模板即可以,在使用template模块时,渲染模板文件。使得模板文件符合自己的要求

常见的语法

循环:

[{% for host in groups[elasticsearch_hosts] %}'{{ host }}'{% if not loop.last %},{% endif %}{% endfor %}]

判断:


{% if  ip  == inventory_hostname %}
echo {{ loop.index - 1 }} > {{install_dir}}/{{data_dir}}/myid
{% endif %}

加减乘除:

{{(groups[elasticsearch_hosts] | length)//2+1  }} # 获取长度除2加1

条件执行

条件执行可以在tasks上使用when:

tasks:
 - name: "shut down CentOS 6 and Debian 7 systems"
   command: /sbin/shutdown -t now
   when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6") or
         (ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "7")

when 支持多个关键字in or == and is not defined !=

循环

用于多次重复执行任务

简单循环列表:

- name: add several users
  user:
    name: "{{ item.name }}"
    state: present
    groups: "{{ item.groups }}"
  loop:
    - { name: 'testuser1', groups: 'wheel' }
    - { name: 'testuser2', groups: 'root' }
  # 或者 loop: '{{vars}}'

任务重试:

- shell: /usr/bin/foo
  register: result
  until: result.stdout.find("all systems go") != -1
  retries: 5
  delay: 10

详情参考:loop

阻塞块

块允许对任务进行逻辑分组以及进行中的错误处理。您可以应用于单个任务的大多数内容(循环除外)都可以应用于块级,这也使设置任务通用的数据或指令变得更加容易。这并不意味着该指令会影响块本身,而是被块所包含的任务继承。即,何时将应用于任务,而不是块本身.

tasks:
  - name: Install, configure, and start Apache
    block:
      - name: install httpd and memcached
        yum:
          name:
          - httpd
          - memcached
          state: present

      - name: apply the foo config template
        template:
          src: templates/src.j2
          dest: /etc/foo.conf
      - name: start service bar and enable it
        service:
          name: bar
          state: started
          enabled: True
    when: ansible_facts['distribution'] == 'CentOS'
    become: true
    become_user: root
    ignore_errors: yes

常用技巧及模块

ansible-playbook的最佳实践

tasks支持很多模块如commandshellcopytemplate
tasks 还有一个简单的写法:action: template src=templates/foo.j2 dest=/etc/foo.conf

执行playbook:ansible-playbook site.yml --limit datacenter2

命令行工具

ansible 拥有多个命令行工具其中包括ansibleansible-playbook

ansible

ansible参数:

usage: ansible [-h] [--version] [-v] [-b] [--become-method BECOME_METHOD]
            [--become-user BECOME_USER] [-K] [-i INVENTORY] [--list-hosts]
            [-l SUBSET] [-P POLL_INTERVAL] [-B SECONDS] [-o] [-t TREE] [-k]
            [--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER]
            [-c CONNECTION] [-T TIMEOUT]
            [--ssh-common-args SSH_COMMON_ARGS]
            [--sftp-extra-args SFTP_EXTRA_ARGS]
            [--scp-extra-args SCP_EXTRA_ARGS]
            [--ssh-extra-args SSH_EXTRA_ARGS] [-C] [--syntax-check] [-D]
            [-e EXTRA_VARS] [--vault-id VAULT_IDS]
            [--ask-vault-pass | --vault-password-file VAULT_PASSWORD_FILES]
            [-f FORKS] [-M MODULE_PATH] [--playbook-dir BASEDIR]
            [-a MODULE_ARGS] [-m MODULE_NAME]
            pattern

详细信息:ansible 常用选项

ansible-config

详细信息:ansible-config

ansible-console

详细信息:ansible-console

ansible-doc

详细信息:ansible-doc

ansible-galaxy

用于管理共享库
详细信息:ansible-galaxy

ansible-inventory

用于管理hosts文件
详细信息:ansible-inventory

ansible-playbook

用于运行ansible-playbook相关文件

常用参数:

usage: ansible-playbook [-h] [--version] [-v] [-k]
                     [--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER]
                     [-c CONNECTION] [-T TIMEOUT]
                     [--ssh-common-args SSH_COMMON_ARGS]
                     [--sftp-extra-args SFTP_EXTRA_ARGS]
                     [--scp-extra-args SCP_EXTRA_ARGS]
                     [--ssh-extra-args SSH_EXTRA_ARGS] [--force-handlers]
                     [--flush-cache] [-b] [--become-method BECOME_METHOD]
                     [--become-user BECOME_USER] [-K] [-t TAGS]
                     [--skip-tags SKIP_TAGS] [-C] [--syntax-check] [-D]
                     [-i INVENTORY] [--list-hosts] [-l SUBSET]
                     [-e EXTRA_VARS] [--vault-id VAULT_IDS]
                     [--ask-vault-pass | --vault-password-file VAULT_PASSWORD_FILES]
                     [-f FORKS] [-M MODULE_PATH] [--list-tasks]
                     [--list-tags] [--step] [--start-at-task START_AT_TASK]
                     playbook [playbook ...]

详细信息:ansible-playbook

ansible-pull

建立远程副本
详细信息:ansible-pull

ansible-vault

加密ansible文件
详细信息:ansible-vault

总结

本文简单介绍了ansible的概念,使用方法以及相关注意事项。

参考文档:Ansible is an IT automation tool


本博客所有文章除特别声明外,均采用: 署名-非商业性使用-禁止演绎 4.0 国际协议,转载请保留原文链接及作者。

mysql基础知识 上一篇
kubernetes 安装 下一篇

 目录


买个卤蛋,吃根冰棒