Ansible

ansible是一款基于ssh管理服务器的工具

这儿是 中文文档 English Docs

简介

  • ansible是个什么东西呢?官方的title是“Ansible is Simple IT Automation”——简单的自动化IT工具。这个工具的目标有这么几项:自动化部署APP;自动化管理配置项;自动化的持续交互;自动化的(AWS)云服务管理。所有的这几个目标从本质上来说都是在一个台或者几台服务器上,执行一系列的命令而已。通俗的说就是批量的在远程服务器上执行命令 。当然,最主要的是它是基于 paramiko 开发的。这个paramiko是什么呢?它是一个纯Python实现的ssh协议库。因此fabric和ansible还有一个共同点就是不需要在远程主机上安装client/agents,因为它们是基于ssh来和远程主机通讯的。简单归纳一下:
  • Ansible:—基于 Python paramiko 开发,分布式,无需客户端,轻量级,配置语法使用 YMAL 及 Jinja2模板语言,更强的远程命令执行操作
  • 类似的自动化运维工具有很多常用的还有:
    • Puppet(基于 Ruby 开发,采用 C/S 架构,扩展性强,基于 SSL,远程命令执行相对较弱)

安装

  • mac

    1
    2
    3
    4
    5
    6
    brew install ansible
    ```

    - linux
    ```bash
    yum -y install ansible
  • 安装好之后,需要编辑被管理机器的host

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #编辑添加ansible的hosts配置文件
    vim /etc/ansible/hosts
    [group1]
    192.168.18.91

    [group2]
    192.168.18.92

    [group3]
    192.168.18.93

    [all:vars]
    ansible_ssh_user=root
  • 测试是否可通

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    ansible all -m ping
    192.168.18.91 | SUCCESS => {
    "ansible_facts": {
    "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
    }
    192.168.18.92 | SUCCESS => {
    "ansible_facts": {
    "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
    }
    192.168.18.93 | SUCCESS => {
    "ansible_facts": {
    "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
    }

一些简单的ansible命令

1
2
3
4
5
6
7
8
# as bruce
ansible all -m ping -u bruce
# as bruce, sudoing to root
ansible all -m ping -u bruce --sudo
# as bruce, sudoing to batman
ansible all -m ping -u bruce --sudo --sudo-user batman
# 所有的目标节点运行命令(俗称ad-hoc命令)
ansible all -a "/bin/echo hello"

Inventory文件

  • Ansible 可同时操作属于一个组的多台主机,组和主机之间的关系通过 inventory 文件配置. 默认的文件路径为 /etc/ansible/hosts
  • 除默认文件外,你还可以同时使用多个 inventory 文件

主机与组

  • /etc/ansible/hosts 文件的格式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    mail.example.com

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

    [dbservers]
    one.example.com
    two.example.com
    three.example.com
  • 方括号[]中是组名

  • 一个系统可以属于不同的组,比如一台服务器可以同时属于 webserver组 和 dbserver组.这时属于两个组的变量都可以为这台主机所用,至于变量的优先级关系将于以后的章节中讨论.

  • 如果有主机的SSH端口不是标准的22端口,可在主机名之后加上端口号

    1
    badwolf.example.com:5309
  • 给IP设置别名

    1
    jumper ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50
  • 一组相似的 hostname , 可简写如下:

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

主机变量

  • 前面已经提到过,分配变量给主机很容易做到,这些变量定义后可在 playbooks 中使用:
    1
    2
    3
    [atlanta]
    host1 http_port=80 maxRequestsPerChild=808
    host2 http_port=303 maxRequestsPerChild=909

组的变量

  • 也可以定义属于整个组的变量:
    1
    2
    3
    4
    5
    6
    7
    [atlanta]
    host1
    host2

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

把一个组作为另一个组的子成员

  • 可以把一个组作为另一个组的子成员,以及分配变量给整个组使用. 这些变量可以给 /usr/bin/ansible-playbook 使用,但不能给 /usr/bin/ansible 使用:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    [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

分文件定义 Host 和 Group 变量

  • 在 inventory 主文件中保存所有的变量并不是最佳的方式.还可以保存在独立的文件中,这些独立文件与 inventory 文件保持关联. 不同于 inventory 文件(INI 格式),这些独立文件的格式为 YAML.

  • 假设 inventory 文件的路径为:

    1
    /etc/ansible/hosts
  • 假设有一个主机名为 ‘foosball’, 主机同时属于两个组,一个是 ‘raleigh’, 另一个是 ‘webservers’. 那么以下配置文件(YAML 格式)中的变量可以为 ‘foosball’ 主机所用.依次为 ‘raleigh’ 的组变量,’webservers’ 的组变量,’foosball’ 的主机变量:

    1
    2
    3
    /etc/ansible/group_vars/raleigh
    /etc/ansible/group_vars/webservers
    /etc/ansible/host_vars/foosball

Inventory 参数的说明

  • 如同前面提到的,通过设置下面的参数,可以控制 ansible 与远程主机的交互方式,其中一些我们已经讲到过:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    ansible_ssh_host
    将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.

    ansible_ssh_port
    ssh端口号.如果不是默认的端口号,通过此变量设置.

    ansible_ssh_user
    默认的 ssh 用户名

    ansible_ssh_pass
    ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)

    ansible_sudo_pass
    sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)

    ansible_sudo_exe (new in version 1.8)
    sudo 命令路径(适用于1.8及以上版本)

    ansible_connection
    与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行.

    ansible_ssh_private_key_file
    ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.

    ansible_shell_type
    目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh''fish'.

    ansible_python_interpreter
    目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 \*BSD, 或者 /usr/bin/python
    不是 2.X 版本的 Python.我们不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).

    与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....
  • 一个主机文件的例子:

    1
    2
    3
    4
    some_host         ansible_ssh_port=2222     ansible_ssh_user=manager
    aws_host ansible_ssh_private_key_file=/home/example/.ssh/aws.pem
    freebsd_host ansible_python_interpreter=/usr/local/bin/python
    ruby_module_host ansible_ruby_interpreter=/usr/bin/ruby.1.9.3

Ansible的配置文件

  • ansible配置文件,ansible.cfg

  • Ansible 的配置文件的查找顺序如下:

    • 环境变量 ANSIBLE_CONFIG
    • 当前目录下的 ansible.cfg (这个比较重要,一般用这个比较多)
    • home 目录下的 ~/.ansible.cfg
    • /etc/ansible/ansible.cfg
  • Ansible 使用找到的第一个文件,忽略其余的。

  • 配置文件的几个组成部分:

    • [defaults] —>通用默认配置
    • [privilege_escalation] —> 提权配置
    • [paramiko_connection]
    • [ssh_connection]
    • [accelerate]
  • 例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    [defaults]   --->通用默认配置
    # some basic default values...
    inventory = /etc/ansible/hosts 这个是默认库文件位置,脚本,或者存放可通信主机的目录
    #library = /usr/share/my_modules/ Ansible默认搜寻模块的位置
    remote_tmp = $HOME/.ansible/tmp Ansible 通过远程传输模块到远程主机,然后远程执行,执行后在清理现场.在有些场景下,你也许想使用默认路径希望像更换补丁一样使用
    pattern = * 如果没有提供“hosts”节点,这是playbook要通信的默认主机组.默认值是对所有主机通信
    forks = 5 在与主机通信时的默认并行进程数 ,默认是5d
    poll_interval = 15 当具体的poll interval 没有定义时,多少时间回查一下这些任务的状态, 默认值是5秒
    sudo_user = root sudo使用的默认用户 ,默认是root
    #ask_sudo_pass = True 用来控制Ansible playbook 在执行sudo之前是否询问sudo密码.默认为no
    #ask_pass = True 控制Ansible playbook 是否会自动默认弹出密码
    transport = smart 通信机制.默认 值为’smart’。如果本地系统支持 ControlPersist技术的话,将会使用(基于OpenSSH)‘ssh’,如果不支持讲使用‘paramiko’.其他传输选项包括‘local’, ‘chroot’,’jail’等等
    #remote_port = 22 远程SSH端口。 默认是22
    module_lang = C 模块和系统之间通信的计算机语言,默认是C语言
    # plays will gather facts by default, which contain information about
    # the remote system.
    #
    # smart - gather by default, but don't regather if already gathered# implicit - gather by default, turn off with gather_facts: False
    # explicit - do not gather by default, must say gather_facts: True
    gathering = implicit 控制默认facts收集(远程系统变量). 默认值为’implicit’, 每一次play,facts都会被收集
    # additional paths to search for roles in, colon separated
    #roles_path = /etc/ansible/roles roles 路径指的是’roles/’下的额外目录,用于playbook搜索Ansible roles
    # uncomment this to disable SSH key host checking
    #host_key_checking = False 检查主机密钥
    # change this for alternative sudo implementations
    sudo_exe = sudo 如果在其他远程主机上使用另一种方式执sudu操作.可以使用该参数进行更换
    # what flags to pass to sudo 传递sudo之外的参数
    #sudo_flags = -H
    # SSH timeout SSH超时时间
    timeout = 10# default user to use for playbooks if user is not specified
    # (/usr/bin/ansible will use current user as default)
    #remote_user = root 使用/usr/bin/ansible-playbook链接的默认用户名,如果不指定,会使用当前登录的用户名
    # logging is off by default unless this path is defined
    # if so defined, consider logrotate
    #log_path = /var/log/ansible.log 日志文件存放路径
    # default module name for /usr/bin/ansible
    #module_name = command ansible命令执行默认的模块
    # use this shell for commands executed under sudo
    # you may need to change this to bin/bash in rare instances
    # if sudo is constrained
    #executable = /bin/sh 在sudo环境下产生一个shell交互接口. 用户只在/bin/bash的或者sudo限制的一些场景中需要修改
    # if inventory variables overlap, does the higher precedence one win
    # or are hash values merged together? The default is 'replace' but
    # this can also be set to 'merge'.
    #hash_behaviour = replace 特定的优先级覆盖变量
    # list any Jinja2 extensions to enable here:
    #jinja2_extensions = jinja2.ext.do,jinja2.ext.i18n 允许开启Jinja2拓展模块
    # if set, always use this private key file for authentication, same as # if passing --private-key to ansible or ansible-playbook
    #private_key_file = /path/to/file 私钥文件存储位置
    # format of string {{ ansible_managed }} available within Jinja2
    # templates indicates to users editing templates files will be replaced.
    # replacing {file}, {host} and {uid} and strftime codes with proper values.
    ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host} 这个设置可以告知用户,Ansible修改了一个文件,并且手动写入的内容可能已经被覆盖.
    # by default, ansible-playbook will display "Skipping [host]" if it determines a task
    # should not be run on a host. Set this to "False" if you don't want to see these "Skipping" # messages. NOTE: the task header will still be shown regardless of whether or not the
    # task is skipped.
    #display_skipped_hosts = True 显示任何跳过任务的状态 ,默认是显示
    # by default (as of 1.3), Ansible will raise errors when attempting to dereference
    # Jinja2 variables that are not set in templates or action lines. Uncomment this line
    # to revert the behavior to pre-1.3.
    #error_on_undefined_vars = False 如果所引用的变量名称错误的话, 将会导致ansible在执行步骤上失败
    # by default (as of 1.6), Ansible may display warnings based on the configuration of the
    # system running ansible itself. This may include warnings about 3rd party packages or
    # other conditions that should be resolved if possible.
    # to disable these warnings, set the following value to False:
    #system_warnings = True 允许禁用系统运行ansible相关的潜在问题警告
    # by default (as of 1.4), Ansible may display deprecation warnings for language
    # features that should no longer be used and will be removed in future versions.
    # to disable these warnings, set the following value to False:
    #deprecation_warnings = True 允许在ansible-playbook输出结果中禁用“不建议使用”警告
    # (as of 1.8), Ansible can optionally warn when usage of the shell and
    # command module appear to be simplified by using a default Ansible module
    # instead. These warnings can be silenced by adjusting the following
    # setting or adding warn=yes or warn=no to the end of the command line
    # parameter string. This will for example suggest using the git module
    # instead of shelling out to the git command.
    # command_warnings = False 当shell和命令行模块被默认模块简化的时,Ansible 将默认发出警告
    # set plugin path directories here, separate with colons
    action_plugins = /usr/share/ansible_plugins/action_plugins
    callback_plugins = /usr/share/ansible_plugins/callback_plugins
    connection_plugins = /usr/share/ansible_plugins/connection_plugins
    lookup_plugins = /usr/share/ansible_plugins/lookup_plugins
    vars_plugins = /usr/share/ansible_plugins/vars_plugins
    filter_plugins = /usr/share/ansible_plugins/filter_plugins
    # by default callbacks are not loaded for /bin/ansible, enable this if you
    # want, for example, a notification or logging callback to also apply to
    # /bin/ansible runs
    #bin_ansible_callbacks = False 用来控制callback插件是否在运行 /usr/bin/ansible 的时候被加载. 这个模块将用于命令行的日志系统,发出通知等特性
    # don't like cows? that's unfortunate.
    # set to 1 if you don't want cowsay support or export ANSIBLE_NOCOWS=1 #nocows = 1 默认ansible可以调用一些cowsay的特性 开启/禁用:0/1# don't like colors either?# set to 1 if you don't want colors, or export ANSIBLE_NOCOLOR=1#nocolor = 1 输出带上颜色区别, 开启/关闭:0/1# the CA certificate path used for validating SSL certs. This path
    # should exist on the controlling node, not the target nodes
    # common locations:
    # RHEL/CentOS: /etc/pki/tls/certs/ca-bundle.crt
    # Fedora : /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
    # Ubuntu : /usr/share/ca-certificates/cacert.org/cacert.org.crt
    #ca_file_path = # the http user-agent string to use when fetching urls. Some web server
    # operators block the default urllib user agent as it is frequently used
    # by malicious attacks/scripts, so we set it to something unique to
    # avoid issues.
    #http_user_agent = ansible-agent
    # if set to a persistent type (not 'memory', for example 'redis') fact values
    # from previous runs in Ansible will be stored. This may be useful when
    # wanting to use, for example, IP information from one group of servers
    # without having to talk to them in the same playbook run to get their
    # current IP information.
    fact_caching = memory
    # retry files
    #retry_files_enabled = False
    #retry_files_save_path = ~/.ansible-retry
    [privilege_escalation]
    #become=True
    #become_method=sudo
    #become_user=root
    #become_ask_pass=False
    [paramiko_connection]
    # uncomment this line to cause the paramiko connection plugin to not record new host
    # keys encountered. Increases performance on new host additions. Setting works independently of the
    # host key checking setting above.
    #record_host_keys=False
    # by default, Ansible requests a pseudo-terminal for commands executed under sudo. Uncomment this# line to disable this behaviour.
    #pty=False
    [ssh_connection]
    # ssh arguments to use
    # Leaving off ControlPersist will result in poor performance, so use
    # paramiko on older platforms rather than removing it
    #ssh_args = -o ControlMaster=auto -o ControlPersist=60s
    # The path to use for the ControlPath sockets. This defaults to
    # "%(directory)s/ansible-ssh-%%h-%%p-%%r", however on some systems with
    # very long hostnames or very long path names (caused by long user names or
    # deeply nested home directories) this can exceed the character limit on
    # file socket names (108 characters for most platforms). In that case, you
    # may wish to shorten the string below.
    #
    # Example:
    # control_path = %(directory)s/%%h-%%r
    #control_path = %(directory)s/ansible-ssh-%%h-%%p-%%r
    # Enabling pipelining reduces the number of SSH operations required to
    # execute a module on the remote server. This can result in a significant
    # performance improvement when enabled, however when using "sudo:" you must
    # first disable 'requiretty' in /etc/sudoers
    #
    # By default, this option is disabled to preserve compatibility with
    # sudoers configurations that have requiretty (the default on many distros).
    #
    #pipelining = False
    # if True, make ansible use scp if the connection type is ssh
    # (default is sftp)
    #scp_if_ssh = True
    [accelerate]
    accelerate_port = 5099accelerate_timeout = 30accelerate_connect_timeout = 5.0# The daemon timeout is measured in minutes. This time is measured
    # from the last activity to the accelerate daemon.
    accelerate_daemon_timeout = 30 # If set to yes, accelerate_multi_key will allow multiple
    # private keys to be uploaded to it, though each user must
    # have access to the system via SSH to add a new key. The default# is "no".
    #accelerate_multi_key = yes
    [selinux]
    # file systems that require special treatment when dealing with security context
    # the default behaviour that copies the existing context or uses the user default# needs to be changed to use the file system dependant context.
    #special_context_filesystems=nfs,vboxsf,fuse

Playbooks

  • Playbooks 是 Ansible的配置,部署,编排语言.他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组IT程序运行的命令集合.

  • playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表.

  • 在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible 模块的调用

  • demo 如下所示,其中仅包含一个 play:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ---
    - hosts: webservers
    vars:
    http_port: 80
    max_clients: 200
    remote_user: root
    tasks:
    - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
    - name: write the apache config file
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache
    - name: ensure apache is running
    service: name=httpd state=started
    handlers:
    - name: restart apache
    service: name=httpd state=restarted

Playbook基础

主机与用户

  • 你可以为 playbook 中的每一个 play,个别地选择操作的目标机器是哪些,以哪个用户身份去完成要执行的步骤(called tasks).

  • hosts 行的内容是一个或多个组或主机的 patterns,以逗号为分隔符,remote_user 就是账户名:

    1
    2
    3
    ---
    - hosts: webservers
    remote_user: root
  • 再者,在每一个 task 中,可以定义自己的远程用户:

    1
    2
    3
    4
    5
    6
    7
    ---
    - hosts: webservers
    remote_user: root
    tasks:
    - name: test connection
    ping:
    remote_user: yourname
  • 也支持从 sudo 执行命令:

    1
    2
    3
    4
    ---
    - hosts: webservers
    remote_user: yourname
    sudo: yes
  • 同样的,你可以仅在一个 task 中,使用 sudo 执行命令,而不是在整个 play 中使用 sudo:

    1
    2
    3
    4
    5
    6
    ---
    - hosts: webservers
    remote_user: yourname
    tasks:
    - service: name=nginx state=started
    sudo: yes
  • 你也可以登陆后,sudo 到不同的用户身份,而不是使用 root:

    1
    2
    3
    4
    5
    ---
    - hosts: webservers
    remote_user: yourname
    sudo: yes
    sudo_user: postgres

Tasks 列表

  • 每一个 play 包含了一个 task 列表(任务列表).

  • 每一个 task 必须有一个名称 name, 一个 task 在其所对应的所有主机上(通过 host pattern 匹配的所有主机)执行完毕之后,下一个 task 才会执行.

  • 有一点需要明白的是(很重要),在一个 play 之中,所有 hosts 会获取相同的任务指令,这是 play 的一个目的所在,也就是将一组选出的 hosts 映射到 task.

  • 在运行 playbook 时(从上到下执行),如果一个 host 执行 task 失败,这个 host 将会从整个 playbook 的 rotation 中移除. 如果发生执行失败的情况,请修正 playbook 中的错误,然后重新执行即可.

执行一个Playbook

  • 这里的示例是并行的运行 playbook,并行的级别 是10 :
    1
    ansible-playbook playbook.yml -f 10

Playbook 角色(Roles) 和 Include 语句

  • 为了避免将playbook写成一个超大的文件

Include 导入 task

  • 一个 task include file 由一个普通的 task 列表所组成,像这样:

    1
    2
    3
    4
    5
    6
    7
    8
    ---
    # possibly saved as tasks/foo.yml

    - name: placeholder foo
    command: /bin/foo

    - name: placeholder bar
    command: /bin/bar
  • Include 指令看起来像下面这样,在一个 playbook 中,Include 指令可以跟普通的 task 混合在一起使用:

    1
    2
    3
    tasks:

    - include: tasks/foo.yml
  • 举个例子,如果我们要部署多个 wordpress 实例,我们可将所有的 wordpress task 写在一个 wordpress.yml 文件中, 然后像下面这样使用 wordpress.yml 文件:

    1
    2
    3
    4
    tasks:
    - include: wordpress.yml wp_user=timmy
    - include: wordpress.yml wp_user=alice
    - include: wordpress.yml wp_user=bob
  • 如果你运行的是 Ansible 1.4 及以后的版本,include 语法可更为精简,这种写法同样允许传递列表和字典参数:

    1
    2
    tasks:
    - { include: wordpress.yml, wp_user: timmy, ssh_keys: [ 'keys/one.txt', 'keys/two.txt' ] }

Include 导入 handlers

  • 重启 apache 的 handler

    1
    2
    3
    4
    ---
    # this might be in a file like handlers/handlers.yml
    - name: restart apache
    service: name=apache state=restarted
  • 然后在你的主 playbook 文件中,在一个 play 的最后使用 include 包含 handlers.yml:

    1
    2
    handlers:
    - include: handlers/handlers.yml

Roles

  • 你现在已经学过 tasks 和 handlers,那怎样组织 playbook 才是最好的方式呢?简单的回答就是:使用 roles ! Roles 基于一个已知的文件结构,去自动的加载某些 vars_files,tasks 以及 handlers。基于 roles 对内容进行分组,使得我们可以容易地与其他用户分享 roles 。

  • 一个项目的结构如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    site.yml
    webservers.yml
    fooservers.yml
    roles/
    common/
    files/
    templates/
    tasks/
    handlers/
    vars/
    defaults/
    meta/
    webservers/
    files/
    templates/
    tasks/
    handlers/
    vars/
    defaults/
    meta/
  • 一个 playbook 如下:

    1
    2
    3
    4
    5
    ---
    - hosts: webservers
    roles:
    - common
    - webservers
  • 这个 playbook 为一个角色 ‘x’ 指定了如下的行为:

    • 如果 roles/x/tasks/main.yml 存在, 其中列出的 tasks 将被添加到 play 中
    • 如果 roles/x/handlers/main.yml 存在, 其中列出的 handlers 将被添加到 play 中
    • 如果 roles/x/vars/main.yml 存在, 其中列出的 variables 将被添加到 play 中
    • 如果 roles/x/meta/main.yml 存在, 其中列出的 “角色依赖” 将被添加到 roles 列表中 (1.3 and later)
    • 所有 copy tasks 可以引用 roles/x/files/ 中的文件,不需要指明文件的路径。
    • 所有 script tasks 可以引用 roles/x/files/ 中的脚本,不需要指明文件的路径。
    • 所有 template tasks 可以引用 roles/x/templates/ 中的文件,不需要指明文件的路径。
    • 所有 include tasks 可以引用 roles/x/tasks/ 中的文件,不需要指明文件的路径。
  • 如果 roles 目录下有文件不存在,这些文件将被忽略。比如 roles 目录下面缺少了 ‘vars/’ 目录,这也没关系。

  • 而且,如果你愿意,也可以使用参数化的 roles,这种方式通过添加变量来实现,比如:

    1
    2
    3
    4
    5
    6
    7
    ---

    - hosts: webservers
    roles:
    - common
    - { role: foo_app_instance, dir: '/opt/a', port: 5000 }
    - { role: foo_app_instance, dir: '/opt/b', port: 5001 }
  • 当一些事情不需要频繁去做时,你也可以为 roles 设置触发条件,像这样:

    1
    2
    3
    4
    5
    ---

    - hosts: webservers
    roles:
    - { role: some_role, when: "ansible_os_family == 'RedHat'" }
  • 最后,你可能希望给 roles 分配指定的 tags。比如:

    1
    2
    3
    4
    5
    ---

    - hosts: webservers
    roles:
    - { role: foo, tags: ["bar", "baz"] }
  • 如果 play 仍然包含有 ‘tasks’ section,这些 tasks 将在所有 roles 应用完成之后才被执行。

  • 如果你希望定义一些 tasks,让它们在 roles 之前以及之后执行,你可以这样做:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ---

    - hosts: webservers

    pre_tasks:
    - shell: echo 'hello'

    roles:
    - { role: some_role }

    tasks:
    - shell: echo 'still busy'

    post_tasks:
    - shell: echo 'goodbye'

角色默认变量(Role Default Variables)

  • 角色默认变量允许你为 included roles 或者 dependent roles(见下) 设置默认变量。要创建默认变量,只需在 roles 目录下添加 defaults/main.yml 文件。这些变量在所有可用变量中拥有最低优先级,可能被其他地方定义的变量(包括 inventory 中的变量)所覆盖。

角色依赖(Role Dependencies)

  • “角色依赖” 使你可以自动地将其他 roles 拉取到现在使用的 role 中。”角色依赖” 保存在 roles 目录下的 meta/main.yml 文件中。这个文件应包含一列 roles 和 为之指定的参数,下面是在 roles/myapp/meta/main.yml 文件中的示例:
    1
    2
    3
    4
    5
    ---
    dependencies:
    - { role: common, some_parameter: 3 }
    - { role: apache, port: 80 }
    - { role: postgres, dbname: blarg, other_parameter: 12 }

Variables

  • To be continued

条件选择

  • To be continued

循环

  • To be continued

欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 qinhan_shu@163.com

文章标题:Ansible

本文作者:QinHan

发布时间:2019-10-22, 06:46:49

最后更新:2020-02-20, 05:42:12

原始链接:https://qinhan.site/2019/10/22/ansible/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏