ansible基础

Ansible

安装部署ansible

### Centos7 安装EPEL源
$$ yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y

### 安装ansible
$$ yum install ansible -y

### 查看ansible版本
$$ ansible --version
ansible 2.9.23
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Nov 16 2020, 22:23:17) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]

### 修改主配置文件,取消某些选项注释
host_key_checking = False              
log_path=/var/log/ansible.log           
module_name   = shell 

ansible相关文件

/etc/ansible/ansible.cfg  主配置文件,配置ansible工作特性(一般无需修改)
/etc/ansible/hosts        主机清单(将被管理的主机放到此文件)
/etc/ansible/roles/       存放角色的目录

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

主配置文件

### /etc/ansible/ansible.cfg

$$ vim /etc/ansible/ansible.cfg
[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								# 远程主机临时命令文件存放目录
#local_tmp      = ~/.ansible/tmp								# 本地临时命令文件存放目录
#plugin_filters_cfg = /etc/ansible/plugin_filters.yml			
#forks          = 5												# 默认并发数
#poll_interval  = 15
#sudo_user      = root											# 默认root用户执行
#ask_sudo_pass = True											# 每次执行ansible命令是否询问ssh密码
#ask_pass      = True											# 每次执行ansible命令是否询问ssh口令
#transport      = smart
#remote_port    = 22											# 端口
#module_lang    = C
#module_set_locale = False					

建议优化项
host_key_checking = False               # 检查对应服务器的host_key,建议取消注释
log_path=/var/log/ansible.log           # 日志文件,建议取消注释
module_name   = command                 # 默认模块,建议修改成shell

inventory主机清单

### 主机清单中列举了需要批量操作的主机

主机清单格式:
1.未分组的主机,在任何组头之前指定
    green.example.com
    blue.example.com
    192.168.100.1
    192.168.100.10

2.对主机进行分组
    [webservers]
    alpha.example.org
    beta.example.org
    192.168.1.100
    192.168.1.110

如果某些主机之间有一定规律,可以使用以下的方法,例如主机www.aa1.com到主机www.aa10.com
	[webservers]
    www.aa[1:10].com

ansible相关工具

ansible-doc

### 用来显示模块帮助

### 格式
ansible-doc [-options] [-M MODULE_PATH]
-l --list		列出可用模块
-s --snippet	简单显示指定模块用法片段

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

ansible

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

### 建议配置ansible端能基于密钥认证的方式来访问管理节点
# 生成密钥对
$$ ssh-keygen -t rsa -P ''
# 分发公钥
$$ ssh-copy-id -i /root/.ssh/id_rsa.pub  [email protected]

### 格式
ansible <host-pattern> [-m module_name] [-a args]
ansible   主机列表           模块             参数
    --version              		显示版本
    -m module              		指定模块,默认为command
    -v                     		详细过程 –vv -vvv更详细
    --list-hosts           		显示主机列表,可简写 --list
    -k, --ask-pass         		提示输入ssh连接密码,默认Key验证
    -C, --check            		检查,并不执行
    -T, --timeout=TIMEOUT  		执行命令的超时时间,默认10s
    -u, --user=REMOTE_USER 		执行远程执行的用户
    -b, --become           		代替旧版的sudo切换
        --become-user=USERNAME 	指定sudo的runas用户,默认为root
    -K, --ask-become-pass  		提示输入sudo时的口令

### 示例
# 列出所有主机清单
$$  ansible all --list

# 列出web分组下的主机清单
$$  ansible web --list

# 使用ping模块检测主机状态
$$ ansible all -m ping

ansible的Host-pattern

### ansible的Host-pattern
All :表示所有Inventory中的所有主机
$$ ansible all –m ping

* :通配符
$$ ansible "*" -m ping  (*表示所有主机)
$$ ansible 192.168.236.* -m ping

 或关系 ":"
$$ ansible 'web:db' -m ping
$$ ansible “192.168.236.162:192.168.236.164” -m ping
    
逻辑与 ":&"
$$ ansible 'web:&db' –m ping
        
逻辑非 ":!"
$$ ansible 'websrvs:!dbsrvs' –m ping

也支持正则表达式
$$ ansible "~(web|db).*\.aaa\.com" –m ping

ansible命令执行过程

### ansible命令执行过程
1. 加载自己的配置文件 默认/etc/ansible/ansible.cfg
2. 加载自己对应的模块文件,如command
3. 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
4. 给文件+x执行
5. 执行并返回结果
6. 删除临时py文件,sleep 0退出

### 执行状态:
绿色:执行成功并且不需要做改变的操作
黄色:执行成功并且对目标主机做变更
红色:执行失败

### 执行状态的颜色修改:
$$  vim /etc/ansible/ansible.cfg 
[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

ansible-galaxy

### 该工具会连接 https://galaxy.ansible.com 去下载相应的roles

### 示例
# 安装
$$ ansible-galaxy  install geerlingguy.redis
# 卸载
$$ ansible-galaxy  remove geerlingguy.redis
# 列出
$$ ansible-galaxy  list

ansible-pull

### 该工具用来将ansible的命令推送至远程

ansible-playbook

### 用来执行编写好的playbook任务

### 示例
# 编写一个简单的playbook
$$ cat test.yaml 
# test yaml file
- hosts: web-test
  remote_user: root
  tasks:
    - name: hello world
      command: /usr/bin/wall  hello world

# 执行(部分输出未进行排版)
$$ ansible-playbook test.yaml 
192.168.236.162: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

ansible-vault

### 用于加密解密yaml文件

### 示例
# 加密  需要设置密码  加密后无法直接被运行
$$ ansible-vault encrypt test.yaml

# 解密
$$  ansible-vault decrypt test.yaml

# 查看
$$  ansible-vault view test.yaml

# 编辑
$$  ansible-vault edit test.yaml

# 修改密码
$$  ansible-vault rekey test.yaml

ansibel常用模块

command模块

### 在远程主机上执行命令,此为默认模块,可忽略-m选项
### 该模块不支持$VARNAME < > | ; &等,需要使用shell模块

### 格式参数
$$ ansible-doc -s command
- name: Execute commands on targets
  command:
      argv:                  # 以列表而不是字符串的形式传递命令。使用'argv'来避免引用会被错误解释的值(例如"user name")。
      						 # 只能提供字符串或列表形式,不能同时提供两者。必须提供其中一种。 
      chdir:                 # 在运行该命令之前,先切换到此目录。
      cmd:                   # 要运行的命令
      creates:               # 如果文件名或者glob已经存在,则不会运行该步骤
      free_form:             # 命令模块使用自由形式的命令运行
      removes:               # 如果文件名或者glob存在,则会运行该步骤
      stdin:                 # 设置命令的输入
      stdin_add_newline:     # 如果设置为' yes',则在stdin data后面附加一个换行符。
      strip_empty_ends:      # 删除输出末尾的空行
      warn:                  # 启用或禁用任务警告。
      
### 示例 (在前面已经修改了ansible配置文件,将默认模块修改为shell了,因此这里需要指定模块名)
$$ ansible all -m command -a "ls"
$$ ansible all -m command -a "creates=anaconda-ks.cfg ls"

shell模块

### 和command相似,支持$VARNAME < > | ; &等

### 格式参数
$$ ansible-doc -s shell
- name: Execute shell commands on targets
  shell:
      argv:                  # 以列表而不是字符串的形式传递命令。使用'argv'来避免引用会被错误解释的值(例如"user name")。
      						 # 只能提供字符串或列表形式,不能同时提供两者。必须提供其中一种。 
      chdir:                 # 在运行该命令之前,先切换到此目录。
      cmd:                   # 要运行的命令
      creates:               # 如果文件名或者glob已经存在,则不会运行该步骤
      free_form:             # 命令模块使用自由形式的命令运行
      removes:               # 如果文件名或者glob存在,则会运行该步骤
      stdin:                 # 设置命令的输入
      stdin_add_newline:     # 如果设置为' yes',则在stdin data后面附加一个换行符。
      strip_empty_ends:      # 删除输出末尾的空行
      warn:                  # 启用或禁用任务警告。

### 示例
$$ ansible all  -a "remove=anaconda-ks.cfg ls"
$$ ansible all  -a 'echo $HOSTNAME'


script模块

### 在远程主机上执行ansible端的脚本文件

### 格式参数
$$ ansible-doc -s script
- name: Runs a local script on a remote node after transferring it
  script:
      chdir:               	 # 在运行该脚本之前,先切换到此目录。
      cmd:                   # 本地脚本的路径,后面可接可选参数
      creates:               # 远程主机上若存在该文件,则不会运行该步骤
      decrypt:               # 对文件进行自动解密
      executable:            # 用来调用脚本的可执行文件的名称或路径。
      free_form:             # 本地脚本文件的路径,后面跟着可选参数。
      removes:               # 远程主机上若不存在该文件,则不会运行该步骤

### 示例
# 编写一个简单的脚本
$$ cat test.sh 
#! /bin/bash
# Desc: 测试ansible的script模块
# Time:2021-07-12

NAME=$HOSTNAME

echo "My hostname is ${NAME}"

# ansible端执行
$$  ansible all -m script -a test.sh

copy模块

### 从ansible端拷贝文件到远程主机

### 格式参数  
$$ ansible-doc -s copy
- name: Copy files to remote locations
  copy:
      attributes:		# 执行完后的文件或者目录应该具有的属性(lsattr查看权限),默认是=         
      backup:			# 创建一个包含时间戳信息的备份文件
      checksum:			# 传输文件的SHA1校验和。用于验证文件的副本是否成功。若没有提供,则使用src文件的本地计算校验和。
      content:          # 代替'src'使用,将文件的内容设置为指定的值。仅当'dest'是一个文件时工作。如果文件不存在,则创建文件。
      decrypt:          # 对源文件进行自动解密。
      dest:             # (必需)目的文件绝对路径。如果src是一个目录,那么它也必须是一个目录。如果目的是一个不存在的路径,并且以'/'结尾,或者'src'是一个目录,则dest被创建。如果src和dest是文件,则dest的父目录不会被创建,如果目录不存在,则任务会失败。
      directory_mode:   # 当执行递归复制时,设置目录的模式。如果没有设置,我们将使用系统默认值。该模式只设置在新创建的目录上,不会影响那些已经存在的目录。
      follow:           # 保留文件系统的链接
      force:            # 是否始终必须替换远程文件。如果是,当内容与源文件不同时,远程文件将被替换。否则只在目标不存在时传输文件。
      group:            # 设置文件/目录的所属组
      local_follow:     # 保留源代码树中的文件系统链接
      mode:             # 文件/目录的权限,可使用数字/符号模式(0644/"644"),也可以是特殊字符串'preserve'(与源文件相同权限)
      owner:            # 设置文件/目录的所属者
      remote_src:       # “src”是否需要转移或远程已经存在。如果no,它将在源机器上搜索'src'。如果yes,它将转到远程的'src'   
      selevel:          # selinux的级别
      serole:           # SELinux文件上下文的角色部分
      setype:           # SELinux文件上下文的类型部分
      seuser:           # SELinux文件上下文的用户部分。                   
      src:              # 源文件路径。目录会递归复制。如果以“/”结尾,则只复制目录的内容。否则,则目录本身也将被复制。
      unsafe_writes:    # 影响使用原子操作来防止数据损坏或从目标文件读取不一致。
      validate:         # 拷贝前需要执行的验证命令
  
### 示例
$$ ansible all -m copy -a "src=test.sh dest=/root/ mode=0644"
$$ ansible all -m copy -a "src=/tmp/ dest=/tmp/ mode=0644 owner=zabbix"

fetch模块

### 与copy相反,从远程主机拉取文件值ansible端,目前不支持目录操作

### 格式参数
$$ ansible-doc -s fetch
- name: Fetch files from remote nodes
  fetch:
      dest:                  # (必需)保存文件的目录,上级目录为主机名
      fail_on_missing:       # 当设置为“yes”时,如果远程文件由于任何原因无法读取,任务将失败
      flat:                  # 允许覆盖将主机名/路径/附加到/file到目标的默认行为。
      src:                   # (必需)远程系统上要获取的文件。目前只支持文件操作
      validate_checksum:     # 在获取文件之后,验证源和目标校验和是否匹配。

### 示例
# 拉取文件
$$ ansible all -m fetch -a "src=/etc/hostname dest=./tmp"
# 查看 可以发现ansible以主机名创建了相应的目录,避免了目录冲突
$$ tree tmp
tmp
├── 192.168.236.162
│   └── etc
│       └── hostname
└── 192.168.236.164
    └── etc
        └── hostname

file模块

### 用来设置文件属性

### 格式参数
$$ ansible-doc -s file
- name: Manage files and file properties
  file:
      access_time:           	# 设置文件的访问时间
      access_time_format:    	# 与'access_time'一起使用时,表示必须使用的时间格式。基于默认的Python格式
      attributes:            	# 文件或者目录应该具有的特权属性
      follow:                	# 保持文件系统链接
      force:                 	# 当源文件不存在(但稍后会出现)或者目标已经存在,并且是一个文件时创建软链接
      group:                 	# 文件或目录的所属组
      mode:                  	# 文件/目录的权限,可使用数字/符号模式(0644/"644")
      modification_time:     	# 设置文件的修改时间
      modification_time_format:	# 当与' modification_time'一起使用时,表示必须使用的时间格式。基于默认的Python格式
      owner:                 	# 设置文件或目录的所属者
      path:                  	# (必需)文件的路径
      recurse:               	# 递归地设置目录内容上的文件属性
      selevel:               	# SELinux文件上下文的级别部分
	  serole:                	# SELinux文件上下文的角色部分
      setype:               	# SELinux文件上下文的类型部分
      seuser:                	# SELinux文件上下文的用户部分
      src:                   	# 要链接到的文件的路径。这只适用于' state=link'和' state=hard','touch'创建文件
      state:                 	# 'absent'删除,'directory'递归创建中间子目录,'hard'/'link'链接文件
      unsafe_writes:         	# 使用原子操作来防止数据损坏或从目标文件读取不一致

### 示例
# 创建空文件
$$ ansible all -m file -a "state=touch path=/tmp/touch.txt"
# 删除文件
$$ ansible all -m file -a "state=absent path=/tmp/touch.txt"
# 创建目录
$$ ansible all -m file -a "state=directory path=/tmp/1/2/3 owner=zabbix group=zabbix"

archive模块

### 打包压缩

### 格式参数
$$ ansible-doc -s archive
- name: Creates a compressed archive of one or more files or trees
  archive:
      attributes:            # 执行完后的文件或者目录应该具有的属性(lsattr查看权限),默认是=
      dest:                  # 压缩文件名
      exclude_path:          # 排除文件列表路径
      force_archive:         # 强制打包不压缩
      format:                # 要使用的压缩类型
      group:                 # 所属组
      mode:                  # 权限设置
      owner:                 # 所属组
      path:                  # (必需)需要压缩的文件或目录的绝对路径
      remove:                # 删除任何添加到存档后的源文件和树。
      selevel:               # SELinux文件上下文的级别部分
	  serole:                # SELinux文件上下文的角色部分
      setype:                # SELinux文件上下文的类型部分
      seuser:                # SELinux文件上下文的用户部分
	  unsafe_writes:         # 使用原子操作来防止数据损坏或从目标文件读取不一致
                               
### 示例
$$ ansible all -m archive -a "path=""/root/ dest=/tmp/aaa.tar.gz"

unarchive模块

### 和archive作用相反,解包解压缩
有两种使用方法:
1 将ansible端的压缩文件传到远程主机后解压缩至特定目录,设置copy=yes.
2 将远程主机上的某个压缩文件解压缩到指定路径下,设置copy=no

### 格式参数
ansible-doc -s unarchive
- name: Unpacks an archive after (optionally) copying it from the local machine.
  unarchive:
      attributes:            # 执行完后的文件或者目录应该具有的属性(lsattr查看权限),默认是=                     
      copy:                  # 执行模式,yes/no
      creates:               # 如果指定的绝对路径(文件或目录)已经存在,则不会运行此步骤。
      decrypt:               # 对文件自动解密
      dest:                  # (必需)解压归档文件的远程绝对路径。
      exclude:               # 需要排除的文件列表
      extra_opts:            # 通过传入一个数组来指定其他选项
      group:                 # 所属组
      keep_newer:            # 不要替换比存档中的文件更新的现有文件。
      list_files:            # 如果设置为True,则返回tarball中包含的文件列表。
      mode:                  # 文件权限
      owner:                 # 所属者
      remote_src:            # 'yes'表示归档文件已经在远程系统上,而不是在Ansible端。这个选项与“copy”是互斥的
      selevel:               # SELinux文件上下文的级别部分
	  serole:                # SELinux文件上下文的角色部分
      setype:                # SELinux文件上下文的类型部分
      seuser:                # SELinux文件上下文的用户部分
      src:                   # (必需)归档文件复制到远程的本地路径,当remote_src设置为yes,表示要解压缩的现有存档文件的路径。
      unsafe_writes:         # 使用原子操作来防止数据损坏或从目标文件读取不一致
      validate_certs:        # 只适用于使用https URL作为文件源的情况,使用证书
      
### 示例
# 创建一个空目录
$$ ansible all -m file -a "state=directory path=/root/tmp/test"
# 将之前压缩的文件进行解压缩
$$ ansible all -m unarchive -a "src=/tmp/aaa.tar.gz dest=/root/tmp/ copy=no"

# 在ansible端创建一个压缩文件
$$ tar -cvzf  /tmp/test.tar.gz  /root/*
# 解压缩至远程主机
$$ ansible all -m unarchive -a "src=/tmp/test.tar.gz dest=/root/tmp/ mode=0644 owner=zabbix"

hostname模块

### 管理主机名

### 格式参数
$$ ansible-doc -s hostname
- name: Manage hostname
  hostname:
      name:                  # (必需)主机名
      use:                   # 使用哪个策略来更新主机名
      
### 示例
$$ ansible 192.168.236.162 -m hostname -a "name=agent01"

cron模块

### 设置定时任务

### 格式参数
$$ ansible-doc -s cron
- name: Manage cron.d and crontab entries
  cron:
      backup:                # 修改前备份crontab
      cron_file:             # 指定crontab的文件(通过该文件来设置crontab)
      disabled:              # disabled注释
      env:                   # 环境变量
      insertafter:           # 与'state=present'和env一起使用。如果指定,则在声明指定环境变量后插入该环境变量
      insertbefore:          # 与'state=present'和env一起使用。如果指定,则在声明指定环境变量前插入该环境变量
      job:                   # 任务
      name:                  # (必需)条目名
      reboot:                # 重新执行
      special_time:          # 特殊时间规范
      state:                 # 任务状态
      user:                  # 任务的所属者
	  minute:                # 分
      hour:                  # 时
      day:                   # 日
      month:                 # 月
      weekday:               # 周

### 示例
# 设置定时任务
$$ansible 192.168.236.162 -m cron -a "name=test-job minute=*/5 job='/usr/bin/bash echo hello'"
# 查看定时任务
$$ ansible 192.168.236.162 -a "crontab -l"
# 取消定时任务(注释)
$$ ansible 192.168.236.162 -m cron -a "name=test-job  job='/usr/bin/bash echo hello' disabled=yes"
# 取消定时任务(删除)
$$ ansible 192.168.236.162 -m cron -a "name=test-job  state=absent"

yum模块

### 管理rpm软件包 

### 格式参数
$$ ansible-doc -s yum
- name: Manages packages with the `yum' package manager
  yum:
      allow_downgrade:       # 是否允许降版本安装软件包
      autoremove:            # 自动卸载不必要软件
      bugfix:                # 如果设置为'yes',并且'state=latest',则只安装被标记为bug修复相关的更新。
      conf_file:             # 远程yum配置文件
      disable_excludes:      # 禁用yum配置文件中定义的排除
      disable_gpg_check:     # 是否关闭对正在安装包的签名进行GPG检查
      disable_plugin:        # 通过plugin名称禁用plugin
      disablerepo:           # 禁用存储库
      download_dir:          # 指定下载目录
      download_only:         # 只下载不安装
      enable_plugin:         # 通过plugin名称启用plugin
      enablerepo:            # 启用存储库
      exclude:               # 当state=present或latest时排除的包名
      install_weak_deps:     # 安装有弱依赖关系链接的所有包
      installroot:           # 指定一个替代的安装根,所有的包都将相对于它安装。
      list:                  # 列出软件包名
      lock_timeout:          # 等待lock被释放的时间
      name:                  # 软件包名
      releasever:            # 软件版本
      security:              # 只安装标记为安全相关的更新
      skip_broken:           # 跳过依赖关系损坏的包(devsolve)会导致的问题
      state:                 # 对软件包的操作状态,安装还是删除
      update_cache:          # 检查缓存是否过期,只有state为'latest'时才有效果
      update_only:           # 只更新,只有state为'latest'时才有效果
      use_backend:           # 默认情况下,该模块将基于' ansible_pkg_mgr'事实选择后端。
      validate_certs:        # 只适用于使用https URL作为文件源的情况,使用证书

### 示例
#安装
$$ ansible all -m yum -a "name=tree"
# 列出tree的信息
$$ ansible all -m yum -a "list=tree"
# 卸载
$$ ansible all -m yum -a "name=tree state=absent"

service模块

### 管理服务

### 格式参数
$$ ansible-doc -s service
- name: Manage services
  service:
      arguments:             # 其他参数
      enabled:               # 服务是否需要自启
      name:                  # (必需)服务名
      pattern:               # 如果服务不响应状态命令,则命名一个要子字符串作为状态结果的替代。找到该字符串则假定服务已启动。
      runlevel:              # 此服务所属的运行级别
      sleep:                 # 停止和启动命令之间休眠时间
      state:                 # 服务状态
      use:                   # 设置使用模块
      
### 示例
# 启动服务
$$ ansible all -m service -a "name=zabbix-agent.service state=started"
# 停止服务
$$ ansible all -m service -a "name=zabbix-agent.service state=stopped"

user模块

### 管理用户

### 格式参数
# ansible-doc -s user
- name: Manage user accounts
  user:
      append:				# yes则将用户添加到groups中指定的组,否则将只被添加到groups中指定的组,并从所有其他组中删除它们
      authorization:    	# 设置用户的授权
      comment:          	# 设置用户帐户的描述
      create_home:      	# 是否创建家目录,默认创建
      expires:          	# 过期时间
      force:            	# 当删除用户时,强制删除用户和相关目录
      generate_ssh_key: 	# 是否为用户生成SSH密钥
      group:            	# 设置用户的主组
      groups:           	# 设置用户需要加入的组列表
      home:             	# 设置家目录
      local:            	# 强制在实现它的平台上使用“本地”命令替代
      login_class:      	# 设置用户的登录方式
      move_home:       	 	# 尝试将用户的旧主目录移动到指定的目录
      name:             	# (必需)用户名
      non_unique:       	# 当与-u选项一起使用时,此选项允许将用户ID更改为非惟一值。
      password:         	# 密码
      password_lock:    	# 锁定密码
      profile:          	# 设置用户的配置文件
      remove:           	# 当state=absent时,它试图删除与用户关联的目录
      role:             	# 设置用户的角色
      seuser:           	# 启用selinux的系统上设置seuser类型
      shell:            	# 设置用户的shell
      skeleton:         	# 设置主骨架目录,需要“create_home”选项
      ssh_key_bits:     	# 指定SSH密钥中要创建的位数
      ssh_key_comment:  	# 定义SSH密钥的注释
      ssh_key_file:     	# SSH密钥文件
      ssh_key_passphrase: 	# 设置SSH密钥的密码
      ssh_key_type:         # 指定要生成的SSH密钥的类型
      state:                # 用户的状态
      system:               # 设置为系统用户
      uid:                  # 设置uid
      update_password:      # 总是更新密码

### 示例
# 创建用户
$$ ansible all -m user -a "name=test shell=/usr/bin/sh create_home=no"
# 删除用户
$$ ansible all -m user -a "name=test state=absent force=yes"

group模块

### 管理组

### 格式参数
$$ ansible-doc -s group
- name: Add or remove groups
  group:
      gid:                   # 设置组的gid
      local:                 # 强制在实现它的平台上使用“本地”命令替代
      name:                  # (必需)组名
      non_unique:            # 将组id设置为非唯一
      state:                 # 组状态
      system:                # 设置为系统组

### 示例
# 创建组
$$ ansible all -m group -a "name=test state=present"
# 删除组
$$ ansible all -m group -a "name=test state=absent"

lineinfile模块

### 文件替换,修改文件内容,相当于sed

### 格式参数
ansible-doc -s lineinfile
- name: Manage lines in text files
  lineinfile:
      attributes:            # 文件的特殊权限
      backup:                # 创建一个包含时间戳信息的备份文件
      backrefs:				 # yes时,如果没有匹配,则文件保持不变。如果匹配了,把匹配内容替被换为line内容。
      create:                # 如果文件不存在,将创建该文件
      firstmatch:            # 用于匹配给定正则表达式的第一行
      group:                 # 设置文件所属组
      line:                  # 要插入/替换到文件中的行
      mode:                  # 文件权限
      others:                # 其他参数列表
      owner:                 # 所属者
      path:                  # (必需)操作文件的路径名
      regexp:                # 正则表达式
      selevel:               # SELinux文件上下文的级别部分
	  serole:                # SELinux文件上下文的角色部分
      setype:                # SELinux文件上下文的类型部分
      seuser:                # SELinux文件上下文的用户部分
      state:                 # 文件状态
      unsafe_writes:         # 使用原子操作来防止数据损坏或从目标文件读取不一致
      validate:              # 复制之前需要执行的命令

### 示例
# 将/etc/selinux/config文件中的SELINUX=disabled替换成SELINUX=enforcing
$$  ansible all -m lineinfile -a "path=/etc/selinux/config regexp="SELINUX=disabled" line="SELINUX=enforcing""

replace模块

### 文件替换,修改文件内容,相当于sed

### 格式参数
ansible-doc -s replace
- name: Replace all instances of a particular string in a file using a back-referenced regular expression
  replace:
      after:                 # 如果指定,则只替换/删除匹配后的内容
      attributes:            # 文件特殊权限
      backup:                # 创建一个包含时间戳信息的备份文件
      before:                # 如果指定,则只替换/删除匹配项之前的内容
      encoding:              # 用于读写文件的字符编码
      group:                 # 所属组
      mode:                  # 文件权限
      others:                # 其他参数列表
      owner:                 # 所属者
      path:                  # (必需) 操作文件的路径名
	  regexp:                # (必需) 正则表达式
      replace:               # 要替换regexp匹配的字符串
      selevel:               # SELinux文件上下文的级别部分
	  serole:                # SELinux文件上下文的角色部分
      setype:                # SELinux文件上下文的类型部分
      seuser:                # SELinux文件上下文的用户部分
      unsafe_writes:         # 使用原子操作来防止数据损坏或从目标文件读取不一致
      validate:              # 复制之前需要执行的命令

### 示例
# 将/etc/fstab文件中以UUID开头的行替换成#开头
$$ ansible all -m replace -a "backup=yes path=/etc/fstab regexp='^(UUID)' replace='#\1'"

setup模块

### 用来手机主机的系统信息,facts信息直接以变量的形式使用,但主机过多会影响到性能,可以使用gather_facts:no来禁止收集facts信息

### 格式参数
$$ ansible-doc -s setup
- name: Gathers facts about remote hosts
  setup:
      fact_path:             # facts信息文件的路径
      filter:                # 如果提供,则只返回与shell风格(fnmatch)通配符匹配的信息
      gather_subset:         # 如果提供,则将收集到的其他信息限制到给定的子集。
      gather_timeout:        # 设置默认超时时间

### 示例
$$ ansible 192.168.236.164 -m setup
$$ ansible 192.168.236.164 -m setup -a "filter=ansible_user*"

playbook

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

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

 playbook采用YAML语言编写

playbook核心元素

hosts          		执行的远程主机列表(应用在哪些主机上)

tasks          		任务集
	两种格式:
        (1) action: module arguments
        (2) module: arguments 建议使用  模块: 参数
        注意:shell和command模块后面跟命令,而非key=value

variables      		内置变量或自定义变量在playbook中调用

templates			可替换模板文件中的变量并实现一些简单逻辑的文件

handlers和notify		由特定条件触发的操作,满足条件方才执行,否则不执行

tags标签       		指定某条任务执行,用于选择运行playbook中的部分代码。

ansible具有幂等性,因此会自动跳过没有变化的部分,此时,如果确信其没有变化,就可以通过tags跳过此些代码片断          

运行playbook

### 运行playbook的方式
    ansible-playbook <filename.yml> ... [options]

### 常见选项
    --check -C       只检测可能会发生的改变,但不真正执行操作 
                     (只检查语法,如果执行过程中出现问题,-C无法检测出来)
                     (执行playbook生成的文件不存在,后面的程序如果依赖这些文件,也会导致检测失败)
    --list-hosts     列出运行任务的主机
    --list-tags      列出tag  (列出标签)
    --list-tasks     列出task (列出任务)
    --limit 主机列表 只针对主机列表中的主机执行
    -v -vv -vvv      显示过程

### 示例
    ansible-playbook hello.yml --check 只检测
    ansible-playbook hello.yml --list-hosts  显示运行任务的主机
    ansible-playbook hello.yml --limit web  限制主机

playbook示例

1.创建相关用户和组

$$  vim create_user_group.yaml
# 编写playbook来创建用户和组
---
# 主机清单
- hosts: all
  # 执行任务的用户 
  remote_user: root
  # 不进行系统信息的收集 
  gather_facts: no

  # 任务集
  tasks:
    - name: create user
      user: name=yup shell=/usr/bin/bash
    - name: create group
      group: name=yup_group

### 检查playbook是否正确
$$ ansible-playbook create_user_group.yaml -C

### 执行
$$ ansible-playbook create_user_group.yaml

2.安装nginx

$$ vim install_nginx.yaml

# centos7安装nginx
---
- hosts: all
  remote_user: root
  gather_facts: no

  tasks:
  - name: install repo
    shell: cmd="rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm"
  - name: install nginx
    yum: name=nginx state=present
  - name: start nginx service
    service: name=nginx state=started

3.playbook中使用handlers和notify

Handlers(触发器)
  是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生变化时,才会采取一定的操作。

Notify(通知)
  此action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成最后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。
  
应用场景
	当我们修改了某些程序的配置文件以后,有可能需要重启应用程序,以便能够使新的配置生效

示例

### 将nginx的端口修改为6666,然后使得配置生效

# 修改centos7上面的nginx配置文件,并重启生效
---
- hosts: all
  remote_user: root
  gather_facts: no

  tasks:
  - name: modify conf
    replace: path=/etc/nginx/conf.d/default.conf regexp="(.*)listen(.*)80;" replace="\\1listen  6666;" backup=yes
    notify: restart nginx

  handlers:
  - name: restart nginx
    service: name=nginx state=restarted

playbook中使用tags

tags: 添加标签 
	可以指定某一个任务添加一个标签,添加标签以后,想执行某个动作可以做出挑选来执行
	多个动作可以使用同一个标签

示例

$$ vim test_tags.yaml
# 测试tags组件
---
- hosts: all
  remote_user: root
  gather_facts: no

  tasks:
  - name: test01
    yum: name=httpd state=present
    tags: install
  - name: test02
    yum: name=httpd state=absent
    tags: absent


### 只运行absent的任务
$$ ansible-playbook --tags "absent" test_tags.yaml

### 只运行absent之外的任务
$$ ansible-playbook --skip-tags "absent" test_tags.yaml

playbook中使用变量

# 变量名:由字母、数字和下划线组成,且只能以字母开头

# 变量定义:key=value
   
# 变量来源:
    1> setup模块返回系统变量
       ansible all -m setup -a 'filter="ansible_nodename"'     查询主机名
       ansible all -m setup -a 'filter="ansible_memtotal_mb"'  查询主机内存大小
       ansible all -m setup -a 'filter="ansible_distribution_major_version"'  查询系统版本
       ansible all -m setup -a 'filter="ansible_processor_vcpus"' 查询主机cpu个数
    
    2> 在/etc/ansible/hosts(主机清单)中定义变量
        普通变量:主机组中主机单独定义,优先级高于公共变量(单个主机 )
        公共()变量:针对主机组中所有主机定义统一变量(一组主机的同一类别)
    
    3> 通过命令行指定变量,优先级最高
       ansible-playbook –e varname=value
    
    4> 在playbook中定义
       vars:
        - var1: value1
        - var2: value2
    
    5> 在独立的变量YAML文件中定义
    
    6> 在role中定义


# 变量调用方式:
    1> 通过{{ variable_name }} 调用变量,且变量名前后必须有空格,有时用“{{ variable_name }}”才生效

    2> ansible-playbook –e 选项指定
       ansible-playbook test.yml -e "hosts=www"
       
# 变量优先级      
变量的默认加载顺序如下:
roles defaults目录下的变量
组变量:inventory 文件
组变量:inventory/group_vars/all
组变量:playbook/group_vars/all
组变量:inventory/group_vars/*
组变量:playbook/group_vars/*
主机变量:inventory 文件
主机变量:inventory/group_vars/*
主机变量:playbook/group_vars/*
facts变量
play变量:vars定义的
play变量:vars_prompt定义的
play变量:vars_files导入的
roles vars目录下的变量
block中task定义的变量
playbook中task定义的变量
include_vars导入的变量
set_facts/register注册的变量
使用roles/include_role/import_role语句时定义的变量
使用include语句(ansible旧版本)时定义的变量
命令行-e参数指定的额外变量(优先级最高)

1.使用setup模块设置变量

### 不能禁用ansible收集facts信息的功能
$$ vim setup_var.yaml

# setup设置变量
---
- hosts: all
  remote_user: root

  tasks:
  - name: test01
    file: path=/tmp/{{ ansible_nodename }} state=touch

2.在主机清单中定义变量

主机变量
可以在inventory中定义主机时为其添加主机变量以便于在playbook中使用
[websrvs]
192.168.236.162 port=80 
[dbsrvs]
192.168.236.164 port=3360

组变量
组变量是指赋予给指定组内所有主机上的在playbook中可用的变量
[websrvs]
192.168.236.162
192.168.236.163

[websrvs:vars]
server_name=nginx

示例

### 编写主机清单文件
$$ vim /etc/ansible/hosts
[web-test]
192.168.236.162 port=6666

[db-test]
192.168.236.164 port=3306

[web-test:vars]
server_name=nginx

### 命令行使用变量
$$ ansible all -m file -a "path=/tmp/{{ port }}.txt state=touch"

3.通过命令行指定变量

$$ vim cmd_var.yml
- hosts: all
  remote_user: root
  tasks:
    - name: install package
      yum: name={{ pkname }} state=present

### 命令行指定变量名
ansible-playbook –e pkname=httpd var.yml

4.在playbook中定义

$$ vim playbook_var.yml
- hosts: all
  remote_user: root
vars:
  - username: user1
  - groupname: group1
tasks:
  - name: create group
    group: name={{ groupname }} state=present
  - name: create user
    user: name={{ username }} state=present

### 执行
ansible-playbook var.yml
ansible-playbook -e "username=user2 groupname=group2” var2.yml

5.在YAML文件中定义

$$ cat vars.yml
var1: httpd
var2: nginx

$$ cat var.yml
- hosts: all
  remote_user: root
  vars_files:
    - vars.yml
  tasks:
    - name: create httpd log
      file: name=/app/{{ var1 }}.log state=touch
    - name: create nginx log
      file: name=/app/{{ var2 }}.log state=touch
      
hostname zabbix_agent01 hostname模块 不支持"_",认为"_"是非法字符
hostnamectl set-hostnamezabbix_agent01  可以更改主机名

6.在role中定义

见后续role

templates模板

一个文本文件,用来做为生成文件的模板,可以签到jinja语法

jinja语言

# 使用字面量,有下面形式
字符串:使用单引号或双引号
数字:整数,浮点数
列表:[item1, item2, ...]
元组:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布尔型:true/false
算术运算:+, -, *, /, //, %, **
比较操作:==, !=, >, >=, <, <=
逻辑运算:and,or,not
流表达式:for,if,when

jinja2文档

templates

template功能:根据模块文件动态生成对应的配置文件
	template文件必须存放于templates目录下,且命名为 .j2 结尾
	yaml/yml 文件需和templates目录平级,目录结构如下:
        ./
         ├── temnginx.yml
         └── templates
            └── xxxxx.j2

示例1

# 利用template 同步nginx配置文件

# 准备templates/nginx.conf.j2文件 在该文件中使用变量设置nginx的工作进程数
$$ grep "ansible_processor_vcpus" nginx.conf.j2
worker_processes  {{ ansible_processor_vcpus }};


$$ vim temnginx.yml
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

# 执行playbook
$$ ansible-playbook temnginx.yml

playbook使用when

条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,
通过when语句实现,在task中使用,jinja2的语法格式

when语句
    在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法
    
# 示例
tasks:
  - name: "shutdown RedHat flavored systems"
    command: /sbin/shutdown -h now
    when: ansible_os_family == "RedHat"  当系统属于红帽系列,执行command模块 
 
when语句中还可以使用Jinja2的大多"filter",
例如要忽略此前某语句的错误并基于其结果(failed或者success)运行后面指定的语句,
# 示例
tasks:
  - command: /bin/false
    register: result
    ignore_errors: True
  - command: /bin/something
    when: result|failed
  - command: /bin/something_else
    when: result|success
  - command: /bin/still/something_else
    when: result|skipped

此外,when语句中还可以使用facts或playbook中定义的变量

playbook使用迭代with_items

迭代:当有需要重复性执行的任务时,可以使用迭代机制,
对迭代项的引用,固定变量名为"item"
要在task中使用with_items给定要迭代的元素列表

列表格式:
    字符串
    字典

# 示例  创建用户
- name: add several users
  user: name={{ item }} state=present groups=wheel   # {{ item }} 系统自定义变量
  with_items:       # 定义{{ item }} 的值和个数
    - testuser1
    - testuser2

上面语句的功能等同于下面的语句:
- name: add user testuser1
  user: name=testuser1 state=present groups=wheel
- name: add user testuser2
  user: name=testuser2 state=present groups=wheel
  
with_items中可以使用元素还可为hashes
# 示例
- name: add several users
  user: name={{ item.name }} state=present groups={{ item.groups }}
  with_items:
    - { name: 'testuser1', groups: 'wheel' }
    - { name: 'testuser2', groups: 'root' }

role角色

roles
    ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。
    roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。
    要使用roles只需要在playbook中使用include指令即可。
    简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,
    并可以便捷地include它们的一种机制。
    角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中

复杂场景:建议使用roles,代码复用度高
    变更指定主机或主机组
    如命名不规范维护和传承成本大
    某些功能需多个Playbook,通过includes即可实现
    
# 目录结构
每个角色,以特定的层级目录结构进行组织
playbook.yml  调用角色
roles/
  project/ (角色名称)
    tasks/		# 定义task,role的基本元素,至少应该包含一个名为main.yml的文件,其它的文件需要在此文件中通过include进行包含
    files/		# 存放由copy或script模块等调用的文件
    vars/		# 定义变量,至少应该包含一个名为main.yml的文件,其它的文件需要在此文件中通过include进行包含
    templates/	# template模块查找所需要模板文件的目录
    handlers/	# 此目录中应当包含一个main.yml文件,用于定义此角色用到的各handler,在handler中使用include包含的其它的handler文件也应该位于此目录中;
    
# 创建role的步骤
(1) 创建以roles命名的目录
(2) 在roles目录中分别创建以各角色名称命名的目录,如webservers等
(3) 在每个角色命名的目录中分别创建files、handlers、tasks、templates和vars目录,用不到的目录可以创建为空目录,也可以不创建
(4) 在playbook文件中,调用各角色

你可能感兴趣的:(linux,linux,其他)