ANSIBLE

本文最后更新于:2023年12月5日 晚上

ansible 介绍和架构

ansible 特性

  • 基于 python 实现
  • 模块化:支持自定义模块,可以使用任何语言编写模块
  • 安全:基于 OpenSSH
  • 部署简单:被控端不需要配置环境
  • 幂等性:一个任何执行一遍和执行 n 遍效果一样,不因重复执行带来意外情况,此特性非绝对
  • 支持 playbook 编排任务,YAML 格式,编排任务,支持丰富的数据结构
  • 较强大的多层解决方案 role

ansible 架构

  • INVENTORY:Ansible 管理主机的清单/etc/anaible/hosts
  • MODULES:Ansible 执行命令的功能模块,多数为内置核心模块,也可自定义
  • PLUGINS:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
  • API:供第三方程序调用的应用程序编程接口

ansible 命令执行来源

  • USER:普通用户,即 SYSTEM ADMINISTRATOR
  • PLAYBOOKS:任务剧本(任务集),编排定义 Ansible 任务集的配置文件,由 Ansible 顺序依次执行,通常是 JSON 格式的 YML 文件
  • CMDB(配置管理数据库) API 调用
  • PUBLIC/PRIVATE CLOUD API 调用
  • USER-> Ansible Playbook -> Ansibile

注意事项

  • 执行 ansible 的主机一般称为管理端, 主控端,中控,master 或堡垒机
  • 主控端 Python 版本需要 2.6 或以上
  • 如果被控端 Python 版本小于 2.4,则需要安装 python-simplejson
  • 被控端如开启 SELinux 需要安装 libselinux-python
  • windows 不能做为主控端

ansible 安装和入门

pip安装

$ mkdir -p /usr/local/ansible
$ cd /usr/local/ansible
$ apt install python3.10-venv
$ python3 -m venv venv
$ . venv/bin/activate
(venv) $ pip install ansible

pip 安装后没有配置文件,需要手动创建,有以下四种方式:

  1. ANSIBLE_CONFIG (environment variable if set)
  2. ansible.cfg (in the current directory)
  3. ~/.ansible.cfg (in the home directory)
  4. /etc/ansible/ansible.cfg

ansible 相关文件

  • /etc/ansible/ansible.cfg 主配置文件,配置 ansible 工作特性

  • /etc/ansible/hosts 主机清单

  • /etc/ansible/roles/ 存放角色的目录

ansible 主配置文件

默认为:/etc/ansible/ansible.cfg

参考文档:

https://github.com/ansible/ansible/blob/stable-2.9/examples/ansible.cfg

http://www.ansible.com.cn/docs/intro_configuration.html

# config file for ansible -- https://ansible.com/
# ===============================================

# nearly all parameters can be overridden in ansible-playbook
# or with command line flags. ansible will read ANSIBLE_CONFIG,
# ansible.cfg in the current working directory, .ansible.cfg in
# the home directory or /etc/ansible/ansible.cfg, whichever it
# finds first

[defaults]

# some basic default values...

#inventory      = /etc/ansible/hosts     # 主机列表配置文件
#library        = /usr/share/my_modules/    # 库文件存放目录
#module_utils   = /usr/share/my_module_utils/   # 自定义模块
#remote_tmp     = ~/.ansible/tmp      # 临时py命令文件存放在远程主机目录
#local_tmp      = ~/.ansible/tmp      # 本机的临时命令执行目录
#plugin_filters_cfg = /etc/ansible/plugin_filters.yml # 将不想要的模块列入黑名单
#forks          = 5          # 默认并发数
#poll_interval  = 15         # 异步操作的轮询频率
#sudo_user      = root         # 默认sudo用户
#ask_sudo_pass = True         # 每次执行ansible命令是否询问ssh密码
#ask_pass      = True
#transport      = smart
#remote_port    = 22
#module_lang    = C
#module_set_locale = False

# 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

# This only affects the gathering done by a play's gather_facts directive,
# by default gathering retrieves all facts subsets
# all - gather all subsets
# network - gather min and network facts
# hardware - gather hardware facts (longest facts to retrieve)
# virtual - gather min and virtual facts
# facter - import facts from facter
# ohai - import facts from ohai
# You can combine them using comma (ex: network,virtual)
# You can negate them using ! (ex: !hardware,!facter,!ohai)
# A minimal set of facts is always gathered.
#gather_subset = all

# some hardware related facts are collected
# with a maximum timeout of 10 seconds. This
# option lets you increase or decrease that
# timeout to something more suitable for the
# environment.
# gather_timeout = 10

# Ansible facts are available inside the ansible_facts.* dictionary
# namespace. This setting maintains the behaviour which was the default prior
# to 2.5, duplicating these variables into the main namespace, each with a
# prefix of 'ansible_'.
# This variable is set to True by default for backwards compatibility. It
# will be changed to a default of 'False' in a future release.
# ansible_facts.
# inject_facts_as_vars = True

# additional paths to search for roles in, colon separated
#roles_path    = /etc/ansible/roles

# uncomment this to disable SSH key host checking
#host_key_checking = False

# change the default callback, you can only have one 'stdout' type  enabled at a time.
#stdout_callback = skippy


## Ansible ships with some plugins that require whitelisting,
## this is done to avoid running all of a type by default.
## These setting lists those that you want enabled for your system.
## Custom plugins should not need this unless plugin author specifies it.

# enable callback plugins, they can output to stdout but cannot be 'stdout' type.
#callback_whitelist = timer, mail

# Determine whether includes in tasks and handlers are "static" by
# default. As of 2.0, includes are dynamic by default. Setting these
# values to True will make includes behave more like they did in the
# 1.x versions.
#task_includes_static = False
#handler_includes_static = False

# Controls if a missing handler for a notification event is an error or a warning
#error_on_missing_handler = True

# change this for alternative sudo implementations
#sudo_exe = sudo

# What flags to pass to sudo
# WARNING: leaving out the defaults might create unexpected behaviours
#sudo_flags = -H -S -n

# SSH timeout
#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

# 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

# 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

# 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

# by default, variables from roles will be visible in the global variable
# scope. To prevent this, the following option can be enabled, and only
# tasks and handlers within the role will see the variables there
#private_role_vars = yes

# list any Jinja2 extensions to enable here:
#jinja2_extensions = jinja2.ext.do,jinja2.ext.i18n

# 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

# If set, configures the path to the Vault password file as an alternative to
# specifying --vault-password-file on the command line.
#vault_password_file = /path/to/vault_password_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}
# {file}, {host}, {uid}, and the timestamp can all interfere with idempotence
# in some situations so the default is a static string:
#ansible_managed = Ansible managed

# 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, if a task in a playbook does not include a name: field then
# ansible-playbook will construct a header that includes the task's action but
# not the task's args.  This is a security feature because ansible cannot know
# if the *module* considers an argument to be no_log at the time that the
# header is printed.  If your environment doesn't have a problem securing
# stdout from ansible-playbook (or you have manually specified no_log in your
# playbook on all of the tasks where you have secret information) then you can
# safely set this to True to get more informative messages.
#display_args_to_stdout = False

# 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

# 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

# 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

# (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


# set plugin path directories here, separate with colons
#action_plugins     = /usr/share/ansible/plugins/action
#become_plugins     = /usr/share/ansible/plugins/become
#cache_plugins      = /usr/share/ansible/plugins/cache
#callback_plugins   = /usr/share/ansible/plugins/callback
#connection_plugins = /usr/share/ansible/plugins/connection
#lookup_plugins     = /usr/share/ansible/plugins/lookup
#inventory_plugins  = /usr/share/ansible/plugins/inventory
#vars_plugins       = /usr/share/ansible/plugins/vars
#filter_plugins     = /usr/share/ansible/plugins/filter
#test_plugins       = /usr/share/ansible/plugins/test
#terminal_plugins   = /usr/share/ansible/plugins/terminal
#strategy_plugins   = /usr/share/ansible/plugins/strategy


# by default, ansible will use the 'linear' strategy but you may want to try
# another one
#strategy = free

# 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


# don't like cows?  that's unfortunate.
# set to 1 if you don't want cowsay support or export ANSIBLE_NOCOWS=1
#nocows = 1

# set which cowsay stencil you'd like to use by default. When set to 'random',
# a random stencil will be selected for each task. The selection will be filtered
# against the `cow_whitelist` option below.
#cow_selection = default
#cow_selection = random

# when using the 'random' option for cowsay, stencils will be restricted to this list.
# it should be formatted as a comma-separated list with no spaces between names.
# NOTE: line continuations here are for formatting purposes only, as the INI parser
#       in python does not support them.
#cow_whitelist=bud-frogs,bunny,cheese,daemon,default,dragon,elephant-in-snake,elephant,eyes,\
#              hellokitty,kitty,luke-koala,meow,milk,moofasa,moose,ren,sheep,small,stegosaurus,\
#              stimpy,supermilker,three-eyes,turkey,turtle,tux,udder,vader-koala,vader,www

# don't like colors either?
# set to 1 if you don't want colors, or export ANSIBLE_NOCOLOR=1
#nocolor = 1

# 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

#This option tells Ansible where to cache facts. The value is plugin dependent.
#For the jsonfile plugin, it should be a path to a local directory.
#For the redis plugin, the value is a host:port:database triplet: fact_caching_connection = localhost:6379:0

#fact_caching_connection=/tmp



# retry files
# When a playbook fails a .retry file can be created that will be placed in ~/
# You can enable this feature by setting retry_files_enabled to True
# and you can change the location of the files by setting retry_files_save_path

#retry_files_enabled = False
#retry_files_save_path = ~/.ansible-retry

# squash actions
# Ansible can optimise actions that call modules with list parameters
# when looping. Instead of calling the module once per with_ item, the
# module is called once with all items at once. Currently this only works
# under limited circumstances, and only with parameters named 'name'.
#squash_actions = apk,apt,dnf,homebrew,pacman,pkgng,yum,zypper

# prevents logging of task data, off by default
#no_log = False

# prevents logging of tasks, but only on the targets, data is still logged on the master/controller
#no_target_syslog = False

# controls whether Ansible will raise an error or warning if a task has no
# choice but to create world readable temporary files to execute a module on
# the remote machine.  This option is False by default for security.  Users may
# turn this on to have behaviour more like Ansible prior to 2.1.x.  See
# https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user
# for more secure ways to fix this than enabling this option.
#allow_world_readable_tmpfiles = False

# controls the compression level of variables sent to
# worker processes. At the default of 0, no compression
# is used. This value must be an integer from 0 to 9.
#var_compression_level = 9

# controls what compression method is used for new-style ansible modules when
# they are sent to the remote system.  The compression types depend on having
# support compiled into both the controller's python and the client's python.
# The names should match with the python Zipfile compression types:
# * ZIP_STORED (no compression. available everywhere)
# * ZIP_DEFLATED (uses zlib, the default)
# These values may be set per host via the ansible_module_compression inventory
# variable
#module_compression = 'ZIP_DEFLATED'

# This controls the cutoff point (in bytes) on --diff for files
# set to 0 for unlimited (RAM may suffer!).
#max_diff_size = 1048576

# This controls how ansible handles multiple --tags and --skip-tags arguments
# on the CLI.  If this is True then multiple arguments are merged together.  If
# it is False, then the last specified argument is used and the others are ignored.
# This option will be removed in 2.8.
#merge_multiple_cli_flags = True

# Controls showing custom stats at the end, off by default
#show_custom_stats = True

# Controls which files to ignore when using a directory as inventory with
# possibly multiple sources (both static and dynamic)
#inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo

# This family of modules use an alternative execution path optimized for network appliances
# only update this setting if you know how this works, otherwise it can break module execution
#network_group_modules=eos, nxos, ios, iosxr, junos, vyos

# When enabled, this option allows lookups (via variables like {{lookup('foo')}} or when used as
# a loop with `with_foo`) to return data that is not marked "unsafe". This means the data may contain
# jinja2 templating language which will be run through the templating engine.
# ENABLING THIS COULD BE A SECURITY RISK
#allow_unsafe_lookups = False

# set default errors for all plays
#any_errors_fatal = False

[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

[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

# paramiko will default to looking for SSH keys initially when trying to
# authenticate to remote devices.  This is a problem for some network devices
# that close the connection after a key failure.  Uncomment this line to
# disable the Paramiko look for keys function
#look_for_keys = False

# When using persistent connections with Paramiko, the connection runs in a
# background process.  If the host doesn't already have a valid SSH key, by
# default Ansible will prompt to add the host key.  This will cause connections
# running in background processes to fail.  Uncomment this line to have
# Paramiko automatically add host keys.
#host_key_auto_add = True

[connection]

# ssh arguments to use
# Leaving off ControlPersist will result in poor performance, so use
# paramiko on older platforms rather than removing it, -C controls compression use
#ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s

# The base directory for the ControlPath sockets.
# This is the "%(directory)s" in the control_path option
#
# Example:
# control_path_dir = /tmp/.ansible/cp
#control_path_dir = ~/.ansible/cp

# The path to use for the ControlPath sockets. This defaults to a hashed string of the hostname,
# port and username (empty string in the config). The hash mitigates a common problem users
# found with long hostnames and the conventional %(directory)s/ansible-ssh-%%h-%%p-%%r format.
# In those cases, a "too long for Unix domain socket" ssh error would occur.
#
# Example:
# control_path = %(directory)s/%%h-%%r
#control_path =

# 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

# Control the mechanism for transferring files (old)
#   * smart = try sftp and then try scp [default]
#   * True = use scp only
#   * False = use sftp only
#scp_if_ssh = smart

# Control the mechanism for transferring files (new)
# If set, this will override the scp_if_ssh option
#   * sftp  = use sftp to transfer files
#   * scp   = use scp to transfer files
#   * piped = use 'dd' over SSH to transfer files
#   * smart = try sftp, scp, and piped, in that order [default]
#transfer_method = smart

# if False, sftp will not use batch mode to transfer files. This may cause some
# types of file transfer failures impossible to catch however, and should
# only be disabled if your sftp version has problems with batch mode
#sftp_batch_mode = False

# The -tt argument is passed to ssh when pipelining is not enabled because sudo 
# requires a tty by default. 
#usetty = True

# Number of times to retry an SSH connection to a host, in case of UNREACHABLE.
# For each retry attempt, there is an exponential backoff,
# so after the first attempt there is 1s wait, then 2s, 4s etc. up to 30s (max).
#retries = 3

[persistent_connection]

# Configures the persistent connection timeout value in seconds.  This value is
# how long the persistent connection will remain idle before it is destroyed.
# If the connection doesn't receive a request before the timeout value
# expires, the connection is shutdown. The default value is 30 seconds.
#connect_timeout = 30

# The command timeout value defines the amount of time to wait for a command
# or RPC call before timing out. The value for the command timeout must
# be less than the value of the persistent connection idle timeout (connect_timeout)
# The default value is 30 second.
#command_timeout = 30

[accelerate]
#accelerate_port = 5099
#accelerate_timeout = 30
#accelerate_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 dependent context.
#special_context_filesystems=nfs,vboxsf,fuse,ramfs,9p,vfat

# Set this to yes to allow libvirt_lxc connections to work without SELinux.
#libvirt_lxc_noseclabel = yes

[colors]
#highlight = white
#verbose = blue
#warn = bright purple
#error = red
#debug = dark gray
#deprecate = purple
#skip = cyan
#unreachable = red
#ok = green
#changed = yellow
#diff_add = green
#diff_remove = red
#diff_lines = cyan


[diff]
# Always print diff when running ( same as always running with -D/--diff )
# always = no

# Set how many context lines to show in diff
# context = 3

inventory 主机清单

ansible的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory file中将其分组命名。

默认:/etc/ansible/hosts

参考文档:

https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html

http://www.ansible.com.cn/docs/intro_inventory.html?highlight=hosts

格式

支持两种格式: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:
    dbservers:
      hosts:
        one.example.com:
        two.example.com:
        three.example.com:
默认组

即使inventory文件中没有定义任何组,ansible也会创建两个默认组:allungroupedall包含每个主机,ungrouped组包含除所有主机外没有其他组的all主机。每个主机都至少属于两个组(allungrouped 或者 all和其他一些组)。例如,在上面的示例中,主机mail.example.com属于allungrouped组;主机two.example.com属于alldbservers组。尽管allungrouped组始终存在,但他们是隐式的,不会出现在group_names等组列表中。

简写

如果您有很多具有类似模式的主机,您可以将它们添加为一个范围,而不是单独列出每个主机名:

[websrvs]
www[1:100].example.com
[dbsrvs]
db-[a:f].example.com

您可以在定义主机的数字范围时指定步幅(序列号之间的增量):

[webservers]
www[1:50:2].example.com
选择连接类型和连接用户名
[targets]
localhost              ansible_connection=local  #指定本地连接,无需ssh配置
#ansible_connection=ssh 需要StrictHostKeyChecking no
other1.example.com     ansible_connection=ssh        ansible_ssh_user=mpdehaan
other2.example.com     ansible_connection=ssh        ansible_ssh_user=mdehaan
主机变量

inventory中定义的变量, 在playbooks中使用。

分配变量给主机很容易做到:

[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909
组的变量

也可以定义属于整个组的变量:

[atlanta]
host1
host2

[atlanta:vars]     # 为atlanta主机组设置变量
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com

[all:vars]      # 为所有主机组设置变量
CONTAINER_RUNTIME="docker"
CLUSTER_NETWORK="calico"
PROXY_MODE="ipvs"
SERVICE_CIDR="192.168.0.0/16"
CLUSTER_CIDR="10.10.0.0/16"
NODE_PORT_RANGE="30000-60000"
CLUSTER_DNS_DOMAIN="ljk.local."
bin_dir="/usr/local/bin"
ca_dir="/etc/kubernetes/ssl"
base_dir="/etc/ansible"

或者:

all:
  vars:
    ansible_connection: ssh
    ansible_user: root
    ansible_ssh_pass: ljkk
    ansible_ssh_port: 22
  children:
    servers:
      hosts:
        10.0.0.11:
          ansible_connection: local
        10.0.0.12:
        10.0.0.13:
        10.0.0.14:
父/子组

您可以在组之间创建父/子关系。父组也称为嵌套组。例如,如果您的所有生产主机已经在atlanta_proddenver_prod等组中,您可以创建一个包含这些较小组的production组。

在INI格式中,使用 :children 后缀;在YAML格式中,使用 children: 条目:

all:
  hosts:
    mail.example.com:
  children:
    east:
      hosts:
        foo.example.com:
        one.example.com:
        two.example.com:
    west:
      hosts:
        bar.example.com:
        three.example.com:
    prod:
      children:
        east:
        west:
inventory 参数说明

ansible.builtin.ssh connection – connect via SSH client binary — Ansible Documentation

ansible 相关工具

  • ansible:主程序,临时命令执行工具
  • ansible-doc:查看配置文档,模块功能查看工具,相当于 man
  • ansible-playbook:定制自动化任务,剧本
  • ansible-pull:远程执行命令的工具
  • ansible-vault:文件加密工具
  • ansible-console:基于 Console 界面与用户交互的执行工具
  • ansible-galaxy:下载/上传优秀代码或 Roles 模块的官网平台

ansible

通过 ssh 协议,实现对远程主机的配置管理、应用部署、任务执行等功能

注意:使用 ansible 之前,需要配置各个被控端基于 key 的密钥认证

ansible <host-pattern> [option]...
  • host-pattern:匹配被控主机

    • all:inventory 中的所有主机
    • 支持通配符
    • 支持正则表达式:需要以 ‘~’ 开头
    • 使用:表示或关系
    • 使用:&表示与关系
    • 使用:!表示非关系

    示例:

    # all
    ansible all –m ping
    # 统配符
    ansible "*" -m ping
    ansible 192.168.1.* -m ping
    ansible "srvs" -m ping
    ansible "10.0.0.6 10.0.0.7" -m ping
    # 或
    ansible "websrvs:appsrvs" -m ping
    ansible "192.168.1.10:192.168.1.20" -m ping
    # 与
    ansible "websrvs:&dbsrvs" –m ping # 在websrvs组并且在dbsrvs组中的主机
    # 非 注意此处为单引号
    ansible 'websrvs:!dbsrvs' –m ping #在websrvs组,但不在dbsrvs组中的主机
    # 综合逻辑
    ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' –m ping
    # 正则表达式
    ansible "~(web|db).*\.magedu\.com" –m ping
  • 常用 option

    • –version:显示版本等信息
    • -m module:指定模块,默认为 command
    • -a | –args MODULE_ARGS:指定模块的参数
    • –list-hosts:显示主机列表,可简写 –lists
    • -C | –check:检查,并不执行
    • -T | –timeout=TIMEOUT:执行命令的超时时间,默认 10s
    • -k | –ask-pass:提示输入 ssh 连接密码,默认 Key 验证
    • -u | –user REMOTE_USER:指定远程执行的用户
    • -b | –become:代替旧版的 sudo 切换
    • –become-user=USERNAME:指定 sudo 的 runas 用户,默认为 root
    • -K | –ask-become-pass:提示输入 sudo 时的口令
ansible 命令执行顺序
  1. 加载配置文件,默认/etc/ansible/ansible.cfg
  2. 加载对应的模块文件,如:command
  3. 将模块或命令生成临时 py 文件,并将该文件传输至远程服务器远程服务器:$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY
  4. 给文件+x 权限
  5. 执行并返回结果
  6. 删除临时 py 文件,退出
ansible 执行状态

在 ansible.cfg 的[colors]配置项中设置:

  • 绿色:执行成功且没有对目标主机做更改
  • 黄色:执行成功且对目标主机做了更改
  • 红色:执行失败
ansible 使用示例
(venv) [root@c71 bin]$ansible all -m command -a 'ls ~'
10.0.0.72 | CHANGED | rc=0 >>
anaconda-ks.cfg
init.sh
original-ks.cfg
10.0.0.82 | CHANGED | rc=0 >>
anaconda-ks.cfg
init.sh
original-ks.cfg
10.0.0.81 | CHANGED | rc=0 >>
anaconda-ks.cfg
init.sh
original-ks.cfg
(venv) [root@c71 bin]$ansible all -m ping
10.0.0.72 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.81 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.82 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

ansible-doc

显示模块帮助,相当于 man

ansible-doc [options] [module...]

options:

  • -l|–list:列出可用模块
  • -s|–snippet:显示指定模块的 playbook 片段

示例:

#列出所有模块
ansible-doc -l
#查看指定模块帮助用法
ansible-doc ping
#查看指定模块帮助用法
ansible-doc -s ping

ansible-playbook

执行编写好的 playbook 任务

ansible-playbook <filename.yml> ... [options]
  • –syntax-check:语法检查
  • -C|–check:只检测可能会发生的改变,但不真正执行操作
  • –list-hosts:列出运行任务的主机
  • –list-tags:列出 tag
  • –list-tasks:列出 task
  • –limit 主机列表:只针对主机列表中的特定主机执行
  • -v -vv -vvv:显示过程

ansible-vault

加密解密 yml 文件

ansible-vault {create,decrypt,edit,view,encrypt,encrypt_string,rekey} ...
  • encrypt:加密
  • decrypt:解密
  • view:查看
  • edit:编辑加密文件
  • rekey:修改口令
  • create:创建新文件

ansible-console

交互执行命令,支持 tab,ansible 2.0+新增

执行用户@当前操作的主机组 (当前组的主机数量)[f:并发数]$

常用子命令:

  • 设置并发数: forks n 例如: forks 10
  • 切换组: cd 主机组 例如: cd web
  • 列出当前组主机列表: list
  • 列出所有的内置命令: ?help

示例:

(venv) [root@c71 bin]$ansible-console
Welcome to the ansible console.
Type help or ? to list commands.

root@all (3)[f:5]$ ping
10.0.0.72 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.82 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.81 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
root@all (3)[f:5]$ list
10.0.0.72
10.0.0.81
10.0.0.82
root@all (3)[f:5]$ ls ~
10.0.0.72 | CHANGED | rc=0 >>
anaconda-ks.cfg
init.sh
original-ks.cfg
10.0.0.82 | CHANGED | rc=0 >>
anaconda-ks.cfg
init.sh
original-ks.cfg
10.0.0.81 | CHANGED | rc=0 >>
anaconda-ks.cfg
init.sh
original-ks.cfg
root@all (3)[f:5]$ exit

(venv) [root@c71 bin]$

ansible-galaxy

连接 https://galaxy.ansible.com 下载相应的 roles

示例:

#列出所有已安装的galaxy
ansible-galaxy list
#安装galaxy
ansible-galaxy install geerlingguy.mysql
ansible-galaxy install geerlingguy.redis
#删除galaxy
ansible-galaxy remove geerlingguy.redis

ansible 常用 模块(module)和插件(plugin)

模块和插件的区别:

modules 是ansible的核心内容,它使playbook变得更加简单明了,一个task就是完成某一项功能。ansible模块是被传送到远程主机上运行的。所以它们可以用远程主机可以执行的任何语言编写modules。

plugins 是在 ansible控制节点 上执行的,用来辅助modules做一些操作。比如连接远程主机,拷贝文件到远程主机之类的。

  • 执行的位置:
    • 模块:文件被传送到 远端主机 并执行
    • 插件:在 ansible控制节点 上执行
  • 执行顺序:插件 先于 模块

本文以 ansible 2.10.5 为准

虽然模块众多,但最常用的模块也就 2,30 个而已,针对特定业务只用 10 几个模块

常用模块帮助文档参考:

# 官网
https://docs.ansible.com/ansible/latest/module_plugin_guide/index.html
https://docs.ansible.com/ansible/latest/collections/all_plugins.html
https://docs.ansible.com/ansible/latest/collections/index_module.html
# 中文文档
http://www.ansible.com.cn/docs/modules.html

使用 ansible-doc 可以查看每个模块的具体用法:

# 以 command 模块为例
ansible-doc -s command   # 查看模块的可用选项
ansible-doc command    # 查看模块的详细帮助信息

# ansible-doc module 的内容是包含 ansible-doc -s module 的

# 打印模块的选项
$ansible-doc -s shell | tail -n +3 | egrep '^[[:space:]]{6}[^[:space:]]+:' | cut -d ':' -f 1 | tr -d ' '
chdir
cmd
creates
executable
free_form
removes
stdin
stdin_add_newline
warn

command

ansible.builtin.command module – Execute commands on targets — Ansible Documentation

默认模块,可忽略 -m 选项
注意:此命令不支持 $VARNAME < > | ; & 等,可以用 shell 模块实现

# 以下两条命令是一样的,-m 可以省略,-a 不能省略
$ansible all -a 'hostname'
$ansible all -m command -a 'hostname'

$ansible all -a 'chdir=/etc pwd'
10.0.2.2 | CHANGED | rc=0 >>
/etc
10.0.2.3 | CHANGED | rc=0 >>
/etc
10.0.2.1 | CHANGED | rc=0 >>
/etc
# 选项:ansible-doc -s command
free_form  # 必须参数,指定需要远程执行的命令,free_form并不是一个"实际存在"的参数名,比如,当我们想要在远程主机上执行ls命令时,我们并不需要写成"free_form=ls" ,这样写反而是错误的,因为并没有任何参数的名字是free_form,当我们想要在远程主机中执行ls命令时,直接写成ls即可,这就是free_form参数的含义
chdir  # 指定一个目录,在执行对应的命令之前,会先进入到chdir参数指定的目录中
creates  # 当指定的文件存在时,就不执行对应命令
removes  # 与creates参数的作用正好相反,它的作用是当指定的文件不存在时,就不执行对应命令
stdin  #

shell

和 command 相似,但是功能更丰富,支持各种符号,比如 *、$、>

注意:类似 cat /tmp/test.md | awk -F'|' '{print $1,$2}' &> /tmp/example.txt
些复杂命令,即使使用 shell 也可能会失败,解决办法:写到脚本时,copy 到远程,执行,再把需要的
结果拉回执行命令的机器

建议将 shell 模块替换 command,设为默认模块

$vim /etc/ansible/ansible.cfg
module_name = shell
$ansible-doc -s shell | tail -n +3 | egrep '^[[:space:]]{6}[^[:space:]]+:' | cut -d ':' -f 1 | tr -d ' '
chdir
cmd
creates
executable  # 指定执行程序,默认是 /bin/bash
free_form
removes
stdin
stdin_add_newline
warn

script

在远程主机上运行 ansible 服务器上的脚本(无需执行权限)

$ansible-doc -s script | tail -n +3 | egrep '^[[:space:]]{6}[^[:space:]]+:' | cut -d ':' -f 1 | tr -d ' '
chdir
cmd
creates
decrypt
executable
free_form
removes

copy

从 ansible 服务器主控端复制文件到远程主机

src  # 需要copy的文件或目录
dest  # 文件将被拷贝到远程主机的哪个目录中,dest为必须参数
content  # 当不指定src时,可以使用content直接指定文件内容,src与content两个参数必有其一,否则会报错
force  # 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否强制覆盖,可选值有yes和no,默认值为yes,表示覆盖,如果设置为no,则不会执行覆盖拷贝操作,远程主机中的文件保持不变
backup  #  当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否对远程主机的文件进行备份,可选值有yes和no,当设置为yes时,会先备份远程主机中的文件,然后再将ansible主机中的文件拷贝到远程主机
owner  # 指定文件拷贝到远程主机后的属主,但是远程主机上必须有对应的用户,否则会报错
group  # 指定文件拷贝到远程主机后的属组,但是远程主机上必须有对应的组,否则会报错
mode  # 指定文件拷贝到远程主机后的权限,如果你想将权限设置为"rw-r--r--",则可以使用mode=0644表示,如果你想要在user对应的权限位上添加执行权限,则可以使用mode=u+x表示
attributes
checksum
decrypt
directory_mode
follow
local_follow
remote_src
selevel
serole
setype
seuser
unsafe_writes
validate

示例:

ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/"
ansible test70 -m copy -a 'content="aaa\nbbb\n" dest=/opt/test'
ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ force=no"
ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ backup=yes"
ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ owner=zsy"
ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ group=zsy"
ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ mode=0640"

fetch

从远程主机提取文件至 ansible 的主控端,和 copy 相反,目前不支持目录

$ansible-doc -s fetch | tail -n +3 | egrep '^[[:space:]]{6}[^[:space:]]+:' | cut -d ':' -f 1 | tr -d ' '
dest  # 保存文件的目录
fail_on_missing  # bool,当源文件不存在的时候,标识为失败
flat  # bool,文件覆盖
src  # 从远程主机上获取的文件,必须是文件,不能为目录
validate_checksum  # bool,文件fetch之后进行md5检查

file

file 模块可以帮助我们完成一些对文件的基本操作,比如,创建文件或目录、删除文件或目录、修改文件权限等

path  # 指定要操作的文件或目录,在之前版本的ansible中,使用dest或者name
state  # 此参数非常灵活,此参数对应的值需要根据情况设定,比如,当我们需要在远程主机中创建一个目录的时候,我们需要使用path参数指定对应的目录路径,假设,我想要在远程主机上创建/testdir/a/b目录,那么我则需要设置path=/testdir/a/b,但是,我们无法从"/testdir/a/b"这个路径看出b是一个文件还是一个目录,ansible也同样无法单单从一个字符串就知道你要创建文件还是目录,所以,我们需要通过state参数进行说明,当我们想要创建的/testdir/a/b是一个目录时,需要将state的值设置为directory,"directory"为目录之意,当它与path结合,ansible就能知道我们要操作的目标是一个目录,同理,当我们想要操作的/testdir/a/b是一个文件时,则需要将state的值设置为touch,当我们想要创建软链接文件时,需将state设置为link,想要创建硬链接文件时,需要将state设置为hard,当我们想要删除一个文件时(删除时不用区分目标是文件、目录、还是链接),则需要将state的值设置为absent,"absent"为缺席之意,当我们想让操作的目标"缺席"时,就表示我们想要删除目标
src  # 当state设置为link或者hard时,表示我们想要创建一个软链或者硬链,所以,我们必须指明软链或硬链链接的哪个文件,通过src参数即可指定链接源
force  # 当state=link的时候,可配合此参数强制创建链接文件,当force=yes时,表示强制创建链接文件,不过强制创建链接文件分为两种情况,情况一:当你要创建的链接文件指向的源文件并不存在时,使用此参数,可以先强制创建出链接文件。情况二:当你要创建链接文件的目录中已经存在与链接文件同名的文件时,将force设置为yes,回将同名文件覆盖为链接文件,相当于删除同名文件,创建链接文件。情况三:当你要创建链接文件的目录中已经存在与链接文件同名的文件,并且链接文件指向的源文件也不存在,这时会强制替换同名文件为链接文件
owner  # 用于指定被操作文件的属主,属主对应的用户必须在远程主机中存在,否则会报错
group  # 用于指定被操作文件的属组,属组对应的组必须在远程主机中存在,否则会报错
mode  # 用于指定被操作文件的权限,比如,如果想要将文件权限设置为"rw-r-x---",则可以使用mode=650进行设置,或者使用mode=0650,效果也是相同的,如果你想要设置特殊权限,比如为二进制文件设置suid,则可以使用mode=4700,很方便吧
recurse  # 当要操作的文件为目录,将recurse设置为yes,可以递归的修改目录中文件的属性
access_time
access_time_format
attributes
follow
modification_time
modification_time_format
selevel
serole
setype
seuser
unsafe_writes

示例:

#创建空文件
ansible all -m file -a 'path=/data/test.txt state=touch'
ansible all -m file -a 'path=/data/test.txt state=absent'
ansible all -m file -a "path=/root/test.sh owner=wang mode=755"
#创建目录
ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql"
#创建软链接
ansible all -m file -a 'src=/data/testfile path|dest|name=/data/testfile-link state=link'
#创建目录
ansible all -m file -a 'path=/data/testdir state=directory'
#递归修改目录属性
ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql recurse=yes"

# 在test70主机上创建一个名为testfile的文件,如果testfile文件已经存在,则会更新文件的时间戳,与touch命令的作用相同
ansible test70 -m file -a "path=/testdir/testfile state=touch"
# 在test70主机上创建一个名为testdir的目录,如果testdir目录已经存在,则不进行任何操作
ansible test70 -m file -a "path=/testdir/testdir state=directory"
# 在test70上为testfile文件创建软链接文件,软链接名为linkfile,执行下面命令的时候,testfile已经存在
ansible test70 -m file -a "path=/testdir/linkfile state=link src=/testdir/testfile"
# 在test70上为testfile文件创建硬链接文件,硬链接名为hardfile,执行下面命令的时候,testfile已经存在
ansible test70 -m file -a "path=/testdir/hardfile state=hard src=/testdir/testfile"
# 在创建链接文件时,如果源文件不存在,或者链接文件与其他文件同名时,强制覆盖同名文件或者创建链接文件,参考上述force参数的解释
ansible test70 -m file -a "path=/testdir/linkfile state=link src=sourcefile force=yes"
# 删除远程机器上的指定文件或目录
ansible test70 -m file -a "path=/testdir/testdir state=absent"
# 在创建文件或目录的时候指定属主,或者修改远程主机上的文件或目录的属主
ansible test70 -m file -a "path=/testdir/abc state=touch owner=zsy"
ansible test70 -m file -a "path=/testdir/abc owner=zsy"
ansible test70 -m file -a "path=/testdir/abc state=directory owner=zsy"
# 在创建文件或目录的时候指定属组,或者修改远程主机上的文件或目录的属组
ansible test70 -m file -a "path=/testdir/abb state=touch group=zsy"
ansible test70 -m file -a "path=/testdir/abb group=zsy"
ansible test70 -m file -a "path=/testdir/abb state=directory group=zsy"
# 在创建文件或目录的时候指定权限,或者修改远程主机上的文件或目录的权限
ansible test70 -m file -a "path=/testdir/abb state=touch mode=0644"
ansible test70 -m file -a "path=/testdir/abb mode=0644"
ansible test70 -m file -a "path=/testdir/binfile mode=4700"
ansible test70 -m file -a "path=/testdir/abb state=directory mode=0644"
# 当操作远程主机中的目录时,同时递归的将目录中的文件的属主属组都设置为zsy
ansible test70 -m file -a "path=/testdir/abd state=directory owner=zsy group=zsy recurse=yes"

unarchive

解包解压缩

copy  # 默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,如果设置为copy=no,会在远程主机上寻找src源文件
remote_src  # 和copy功能一样且互斥,yes表示在远程主机,不在ansible主机,no表示文件在ansible主机上
src  # 源路径,可以是ansible主机上的路径,也可以是远程主机(被管理端或者第三方主机)上的路径,如果是远程主机上的路径,则需要设置copy=no
dest  # 远程主机上的目标路径
mode  # 设置解压缩后的文件权限
attributes
creates
decrypt
exclude
extra_opts
group
keep_newer
list_files
owner
selevel
serole
setype
seuser
unsafe_writes
validate_certs

示例:

ansible all -m unarchive -a 'src=/data/foo.tgz dest=/var/lib/foo owner=wang group=bin'
ansible all -m unarchive -a 'src=/tmp/foo.zip dest=/data copy=no mode=0777'
ansible all -m unarchive -a 'src=https://example.com/example.zip dest=/data copy=no'
ansible websrvs -m unarchive -a 'src=https://releases.ansible.com/ansible/ansible-2.1.6.0-0.1.rc1.tar.gz dest=/data/ owner=mysql remote_src=yes'

archive

打包压缩保存在被管理节点

$ansible-doc -s archive | tail -n +3 | egrep '^[[:space:]]{6}[^[:space:]]+:' | cut -d ':' -f 1 | tr -d ' '
attributes
dest
exclude_path
force_archive
format
group
mode
owner
path
remove
selevel
serole
setype
seuser
unsafe_writes

示例:

ansible websrvs -m archive -a 'path=/var/log/ dest=/data/log.tar.bz2 format=bz2 owner=wang mode=0600'

hostname

管理主机名

示例:

ansible 10.0.0.18 -m hostname -a 'name=node18.magedu.com'

cron

计划任务,支持时间:minute,hour,day,month,weekday

# 示例1 每天的1点5分输出 test 字符
5 1 * * * echo test
# 示例2 每3天执行一次计划任务,于当天的1点1分执行,具体任务为输出 test 字符
1 1 */3 * * echo test
# 示例3 每次系统启动后需要执行一次计划任务,具体任务为输出 test 字符
@reboot echo test
# 示例4 每小时执行一次计划任务,具体任务为输出 test 字符
@hourly echo test
backup  # yes|no,当修改或者删除对应的计划任务时,是否先对计划任务进行备份,如果设置为yes,cron 模块会在远程主机的 /tmp 目录下创建备份文件
cron_file
disabled  # 当计划任务有名称时,我们可以根据名称使对应的任务”失效”(注释掉对应的任务)。注意,使用此参数时,除了需要指定任务的名称,还需要同时指定任务的job 以及任务的时间设定,而且任务的时间设定必须和对应任务完全相同,否则在注释任务的同时,任务的时间设定会被修改
env
minute  # 设置计划任务中分钟设定位的值,当不使用此参数时,分钟设定位的值默认为”*”
hour  # 设置计划任务中小时设定位的值,当不使用此参数时,小时设定位的值默认为”*”
day  # 设置计划任务中日设定位的值,当不使用此参数时,日设定位的值默认为”*”
month  # 设置计划任务中月设定位的值,当不使用此参数时,月设定位的值默认为”*”
weekday  # 设置计划任务中周几设定位的值,当不使用此参数时,周几设定位的值默认为”*”
insertafter
insertbefore
job  # 此参数用于指定计划的任务中需要实际执行的命令或者脚本,比如上例中的 “echo test” 命令
name  # 此参数用于设置计划任务的名称,计划任务的名称会在注释中显示,当不指定计划任务的名称时,ansible 会默认为计划任务加入注释,注释的内容为 #Ansible: None,假设指定计划任务的名称为 test,那么注释的内容为#Ansible: test,在一台机器中,计划任务的名称应该具有唯一性,方便我们以后根据名称修改或删除计划任务
reboot
special_time  # 在上述示例3与示例4中,计划任务的时间设定格式为 @reboot 或者@hourly。@reboot 表示重启时执行,@hourly 表示每小时执行一次,相当于设置成”0 0 * * *” ,这种@开头的时间设定格式则需要使用 special_time 参数进行设置,special_time 参数的可用值有 reboot(重启后)、yearly(每年)、annually(每年,与yearly相同)、monthly(每月)、weekly(每周)、daily(每天)、hourly(每时)
# 注意:当上述时间单位设定参数都未指定时,计划任务的时间设定默认会被设定为”* * * * *”,这样表示每秒都会执行一次计划任务,所以,在使用cron模块时,我们应该确定对应的时间参数设置正确
state  # 当计划任务有名称时,我们可以根据名称修改或删除对应的任务,当删除计划任务时,需要将 state 的值设置为 absent
user  # 此参数用于设置当前计划任务属于哪个用户,当不使用此参数时,默认为管理员用户

示例:

#备份数据库脚本
[root@centos8 ~]#cat /root/mysql_backup.sh
#!/bin/bash
mysqldump -A -F --single-transaction --master-data=2 -q -uroot |gzip > /data/mysql_`date +%F_%T`.sql.gz
#创建任务
ansible 10.0.0.8 -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh'
ansible websrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate ntp.aliyun.com &>/dev/null' name=Synctime"
#禁用计划任务
ansible websrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=yes"
#启用计划任务
ansible websrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=no"
#删除任务
ansible websrvs -m cron -a "name='backup mysql' state=absent"
ansible websrvs -m cron -a 'state=absent name=Synctime'

yum、apt

yum:管理软件包,只支持 RHEL,CentOS,fedora
apt:模块管理 Debian 相关版本的软件包

yum
allow_downgrade
autoremove
bugfix
conf_file
disable_excludes
disable_gpg_check
disable_plugin
disablerepo
download_dir
download_only
enable_plugin
enablerepo
exclude
install_repoquery
install_weak_deps
installroot
list
lock_timeout
name
releasever
security
skip_broken
state  # present|installed|latest|absent|removed,installed 和 present等效,表示安装;absent 和 removed 等效,表示卸载;latest 表示安装最新版本
update_cache
update_only
use_backend
validate_certs

示例:

ansible websrvs -m yum -a 'name=httpd state=present' #安装,state可以省略
ansible websrvs -m yum -a 'name=httpd state=absent' #删除
ansible websrvs -m yum -a 'name=sl,cowsay' # 安装
apt
allow_unauthenticated
autoclean
autoremove
cache_valid_time
deb
default_release
dpkg_options
force
force_apt_get
install_recommends
name
only_upgrade
policy_rc_d
purge
state
update_cache
update_cache_retries
update_cache_retry_max_delay
upgrade

示例:

ansible 10.0.0.100 -m apt -a 'name=bb,sl,cowsay,cmatrix,oneko,hollywood,boxes,libaa-bin,x11-apps'
ansible websrvs -m apt -a 'name=rsync,psmisc state=absent'

serivce

管理服务

arguments
enabled
name
pattern
runlevel
sleep
state
use

示例:

ansible all -m service -a 'name=httpd state=started enabled=yes'
ansible all -m service -a 'name=httpd state=stopped'
ansible all -m service -a 'name=httpd state=reloaded'
ansible all -m shell -a "sed -i 's/^Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf"
ansible all -m service -a 'name=httpd state=restarted'

user

管理用户

append
authorization
comment
create_home
expires
force
generate_ssh_key
group
groups
hidden
home
local
login_class
move_home
name
non_unique
password
password_lock
profile
remove
role
seuser
shell
skeleton
ssh_key_bits
ssh_key_comment
ssh_key_file
ssh_key_passphrase
ssh_key_type
state
system
uid
update_password
#创建用户
ansible all -m user -a 'name=user1 comment="test user" uid=2048 home=/app/user1 group=root'
ansible all -m user -a 'name=nginx comment=nginx uid=88 group=nginx groups="root,daemon" shell=/sbin/nologin system=yes create_home=no home=/data/nginx non_unique=yes'

#remove=yes表示删除用户及家目录等数据,默认remove=no
ansible all -m user -a 'name=nginx state=absent remove=yes'

group

管理组

gid
local
name
non_unique
state
system

示例:

#创建组
ansible websrvs -m group -a 'name=nginx gid=88 system=yes'
#删除组
ansible websrvs -m group -a 'name=nginx state=absent'

lineinfile

参考:http://www.zsythink.net/archives/2542

我们可以借助 lineinfile 模块,确保”某一行文本”存在于指定的文件中,或者确保从文件中删除指定的”文本”(即确保指定的文本不存在于文件中),还可以根据正则表达式,替换”某一行文本”

ansible 在使用 sed 进行替换时,经常会遇到需要转义的问题,而且 ansible 在遇到特殊符号进行替换时,存在问题,无法正常进行替换 。所以 ansible 提供了两个模块:lineinfile 模块和 replace 模块,可以方便的进行替换

一般在 ansible 当中去修改某个文件的单行进行替换的时候需要使用 lineinfile 模块

attributes
backrefs  # backrefs=yes 表示开启后向引用,并且当正则没有匹配到任何的行时,则不会对文件进行任何操作
backup  # 是否在修改文件之前对文件进行备份
create  # 当要操作的文件并不存在时,是否创建对应的文件
firstmatch
group
insertafter  # 将文本插入到“指定的行”之后
insertbefore  # 将文本插入到“指定的行”之前
line  # 使用此参数指定文本内容
mode
others
owner
path  # 必须参数,指定要操作的文件
regexp  # 使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配到的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,这么这些行都会被删除
selevel
serole
setype
seuser
state  # 默认值为present,absent表示删除
unsafe_writes
validate

示例:

# 查找内容为‘xxx’的行是否存在于文件/data/test/test.sh,如果不存在,则追加此行到此文件
ansible localhost -m lineinfile -a 'path=/data/test/test.sh line=xxx'

# 正则匹配,然后替换,如果匹配到多行,但是只能替换最后一行
ansible websrvs -m lineinfile -a "path=/etc/httpd/conf/httpd.conf regexp='^Listen' line='Listen 80'"
ansible all -m lineinfile -a "path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=disabled'"

# 正则匹配,然后删除,如果匹配到多行,就全部删除
ansible all -m lineinfile -a 'path=/etc/fstab state=absent regexp="^#"'

replace

lineinfile 模块的主要功能是操作 in file 的 line,只能替换单行文本,多行匹配进行替换需要使用 replace 模块

该模块有点类似于 sed 命令,主要也是基于正则进行匹配和替换,建议使用

after
attributes
backup
before
encoding
group
mode
others
owner
path
regexp
replace
selevel
serole
setype
seuser
unsafe_writes
validate

示例:

ansible all -m replace -a "path=/etc/fstab regexp='^(UUID.*)' replace='#\1'"
ansible all -m replace -a "path=/etc/fstab regexp='^#(UUID.*)' replace='\1'"

setup

setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影响执行速度,可以使用 gather_facts: no 来禁止 ansible 收集 facts 信息

playbook

  • playbook 是由一个或多个”play”组成的列表
  • play 的主要功能在于将预定义的一组主机,装扮成事先通过 ansible 中的 task 定义好的角色。Task 实际是调用 ansible 的一个 module,将多个 play 组织在一个 playbook 中,即可以让它们联合起来,按事先编排的机制执行预定义的动作
  • playbook 文件是采用 YAML 语言编写的

playbook 核心组件

  • hosts:执行的远程主机列表
  • tasks:任务集
  • variables:内置变量或自定义变量在 playbook 中调用
  • templates:模板,可替换模板文件中的变量并实现一些简单逻辑的文件
  • handlers 和 notify:两者结合使用,特定条件出发操作
  • tags:标签,指定某条任务执行,用于选择运行 playbook 中的部分代码。ansible 具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常长。此时,如果确信其没有变化,就可以通过 tags 跳过此些代码片断

hosts 组件

playbook 中的每一个 play 的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts 用于指定要执行指定任务的主机,须事先定义在 inventory 主机清单中

示例:

- hosts: websrvs:appsrvs

remote_user、sudo、sudo_user 组件

  • remote_usr:指定远程主机执行任务的用户
  • sudo:支持使用 sudo,默认切换到 root
  • sudo_user:指定使用 sudo 时切换的用户
- hosts: websrvs
  remote_user: root
  tasks:
    - name: test connection
      ping:
      remote_user: magedu
      sudo: yes
      sudo_user: lujinkai

tasks 和 action

tasks 是 task 列表,task是字典类型。

play 的主体部分是 tasks,所有 task依次在所有远程主机上执行,可以是同步也可以是异步;

task 的目的是使用指定的参数执行模块,

未完待续…

handlers 和 notify

tags 组件

Playbook 中使用变量

两类变量:

  1. ansible 内置变量 和 自定义变量,这些变量不仅可以在 playbook 中使用,在 ansible 中任何地方都可以使用

    # 使用debug模块可以格式化输出变量
    $ ansible localhost -m debug -a "msg={{hostvars}}"
  2. facts 信息,来自 setup 模块收集(允许自定义),可以禁止收集,这些变量只能在 playbook 中使用

    ansible localhost -m setup

内置变量 hostvars

在 playbook 中,自己主机的变量,无论是 ansible 内置、自定义还是 facts,都可以直接调用,其他主机的变量,可以通过 hostvars 间接调用,例如:

# 具体事例,待补充...

常用变量

  • groups:来自 ansible 内置,主机列表
  • group_names:来自 ansible 内置,当前主机在主机列表中的所属组

playbook 中使用 when

playbook 使用迭代 with_items(loop)

当有需要重复性执行的任务时,可以使用迭代机制

对迭代项的引用,固定内置变量名为”item”

要在 task 中使用 with_items 给定要迭代的元素列表

注意: ansible2.5 版本后,可以用 loop 代替 with_items

示例:

- name: 下载 kube-master 二进制
  copy: src={{ base_dir }}/bin/{{ item }} dest={{ bin_dir }}/{{ item }} mode=0755
  with_items:
  - kube-apiserver
  - kube-controller-manager
  - kube-scheduler
  - kubectl
  tags: upgrade_k8s

迭代嵌套子变量:在迭代中,还可以嵌套子变量,关联多个变量在一起使用

示例:

- name: add some users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'nginx', group: 'nginx' }
- { name: 'mysql', group: 'mysql' }
- { name: 'apache', group: 'apache' }

管理节点过多导致的超时问题解决方法

roles

roles 目录结构如下所示:


ANSIBLE
http://blog.lujinkai.cn/运维/运维自动化/ANSIBLE/ansible/
作者
像方便面一样的男子
发布于
2020年12月9日
更新于
2023年12月5日
许可协议