ansible

2019-10-27 0 条评论 611 次阅读 0 人点赞

Ansible是一款非常优秀的自动化运维工具使用Python语言编写的一个自动化运维工具,是基于模块化开发的,支持自定义模块,可以使用任何语言对其进行扩展,其本身利用了ssh服务,不需要安装客户端,但是效率可能会略差一些,因此可以更加适用于一些中小型的场合,对于一些大型的项目,目前还是有点不太够用的,该软件发布于2012年,在2015年的时候被RedHat收购,在centos系统中可以从epel源中安装它,其源码也维护在了GitHub上面

介绍

工作方式

单一模块:这种方式,就是传统的命令方式,通过命令调用模块,执行相应的操作,这个就像我们编程时使用到的一条条语句

playbook方式:使用yaml语言把要执行的多个操作编写到同一个文件中,以此来处理一些较复杂的场景,这个就好像组织成了一个函数

role角色方式:如果遇到一些比较大且复杂的场景,可以使用ansible提供的角色机制,将任务,变量等操作分门别类的存放到不同的目录下的不同的文件中,最后使用一个playbook文件调用他们,这个就好像最终的一个程序

工作原理

介绍中说到他是基于ssh协议的,因此在使用前最好做好基于key的认证,在主控端根据用户输入的ansible命令,或者playbook生成一个临时的Python脚本,然后将这个脚本传给被控端在被控端执行完成后还会将这个脚本删除,因此,我们的主控端和被控端都必须有Python的执行环境

安装

安装方式

  1. yum安装:yum install ansible
  2. 编译安装:
  3. git方式安装
  4. pip安装:

配置文件

/etc/ansible/ansible.cfg:主配置文件

配置文件格式为:
    [names]
    key=value
常用配置项项
    remote_tmp:         远程存放要执行的Python脚本的位置
    local_tmp:          在本地存放临时生成的脚本位置
    forks:              并发执行主机的个数
    remote_port:        远程主机sshd服务的端口号
    host_key_checking:   是否检查known_hosts文件,可选值为true,false,建议设置为false
    log_path:           日志文件的位置

/etc/ansible/hosts: 主机清单文件,将需要管理的主机,只有将主机放在这个文件中才能被ansible管理,可以对主机进行分组,用[]包含分组名,其下面的主机都属于该组,直到文件结尾,或者下一个中括号,主机的表示方式可以是单个IP也可以是192.168.1.[1:10],表示192.168.1.1至192.168.1.10,还可以在此处指定被控端sshd服务的端口可以使用ip:port格式

可执行程序:

ansible: ansible [host-pattern] [option] [-m module] [-a args],ansible主程序,可以按单一模块方式执行命令

host-patten:要操作的主机列表,,必须是在主机清单中的主机

​ all:所有主机
​ group_name:某一个组,可以使用*进行通配
​ group_name1:group_name2:本身为或者的关系,表示组1和组2中的所有的主机
​ 'group_name1:&group_name2':并且的关系,既出现在组1中又出现在组2中的主机
​ 'group_name1:!group_name2':出现在组1中但是没有出现在组2中的主机
​ '~pattern':使用正则表达式

option

​ --version:版本信息
​ -v:显示程序执行过程,-vv,-vvv依次递增详细度
​ -m:指定使用的模块
​ -k:输入用户名对应的密码
​ group_name --list:列出主机清单中定义的该组的所有主机
​ -u user_name:指定连接被控端的用户名
​ -K:输入sudo口令
​ -a 'arguments...':指定执行模块的参数
​ --list-host:查看都会执行哪些主机

ansible-doc [option] [modules]:查看模块文档,相当于man帮助

​ -l:列出所有可用模块,即简单说明
​ -a:列出所有可用模块和详细文档
​ -s:列出模块的简介文档

ansible-galaxy:管理roles角色,该命令可以从https://galaxy.ansible.com这个网站上下载大神共享的role角色

​ install role_name:安装某个角色,role_name可以从上面的网站上找到
​ remove role_name:删除某个角色
​ list:列出本机中所有的角色

ansible-playbook:用于执行playbook,这个命令有一个常用的选项就是-C,这个选项是测试,并不会实际的执行,在写完playbook后可以先用这个命令检查一下

ansible-vault:对playbook进行加密

​ encrypt yml_file:加密playbook文件
​ decrypt yml_file:解密某个playbook文件
​ view yml_file:查看某个加密的playbook文件
​ rekey yml_file:修改playbook文件

ansible-console:ansible的交互式命令执行工具

常用模块

模块的参数大多数是key=value格式,并且,很多参数是在其他模块中也是可以用的,这里只是列举了常用的模块及常用的选项,如果遇到其他的需求可以查文件ansible-doc

ping:用于探测主机是否存活,其本本身并不是使用的ICMP协议,而是使用了ssh协议,会发出一个ping包然后对方存活会回复一个pong包,这个模块也没有什么参数

示例:

1527758568418.png

command:执行shell命令,是ansible的默认模块,这个模块不支持变量,管道,重定向等,因此也不太建议使用

​ chdir=/path/to/som_file:切换当前目录
​ creates=/path/to/som_file:如果文件存在则不执行
​ removes=/path/to/som_file:如果文件不存在就不执行

shell:也是执行shell命令,最好使用单引号,不能使用别名

​ executeable:指定使用的shell
​ chdir=/path/to/som_file:切换当前目录
​ creates=/path/to/som_file:如果文件存在则不执行
​ removes=/path/to/som_file:如果文件不存在就不执行

copy:文件复制

​ backup:复制文件到远程主机时,如果存在同名文件,是否备份
​ content:文件内容,结合dest使用,在被控端创建内容为其指定的文件
​ dest:远程主机上的位置
​ src:本机文件的位置
​ remote_src:源路径是主控端还是被控端,yes为被控端,no为主控端
​ mode:指定权限
​ owner:修改属主

fetch:从被控端复制文件到主控端,目前使用的版本是2.5.3只能复制单个文件,不支持复制目录,不支持通配符,可能会在以后的版本中支持

​ src=/src_dir/file_name:指定要从远程拷贝到本地的文件
​ dest=dir:复制到本地的哪个目录下,会在该目录下以远程主机名创建一个目录,然后会在这个目录下创建源路径的全路径

file:文件管理,不支持文件名通配

​ name:指定文件,目录名称,可以写全路径
src:指定源文件路径
dest:指定目标文件名
state:根据该值进行,创建文件,目录,链接等
touch:对文件进行操作
directory:对目录进行操作
link:对软链接进行操作
absent:删除操作
path:被管理的文件路径
force=yes:强制执行

scirpt:将本地脚本传到远程进行执行,参数直接写脚本的全路径就可以
cron:计划任务,对于时间,没有定义的默认为*

​ minute
hour
month
weekday
job="command":要执行的命令,注意命令最好写全路径
name:为计划任务定义个名字
​ state=absent:删除某个计划任务
​ disable=true:禁用某个计划任务,可以是true/false也可以是yes/no,底层其实就是将某个计划任务注释了禁用时必须写job和name,否则会新建一个job并将其禁用

yum:ansible的包管理工具,被控端必须提前配置好yum

name:指定包名,多个包用逗号隔开,这里可以写rpm包,安装包组要在包名前加@
state
present:默认是这个
installed
lasted安装
absent
removed:卸载
list=installed:查看所有已经装好的包
disable_gpg_check=yes:禁用gpgcheck
update_cache:更新缓存

service:服务管理

name:指定服务名
enabled:是否开机启动
state:启动关闭服务
started/stopped/restarted/reload

user:用户管理

group:指定主组
groups:指定附加组
remove:删除用户并删除家目录
system:指定系统账号
home:指定家目录
comment:指定描述信息
state=absent:删除用户

group:组管理

gid
name
state
system

setup:显示主机信息

filter:过滤信息

Playbook

playbook:翻译过来叫做剧本,在一个playbook中将多个模块组合起来,方便使用且条理清晰,比一条一条敲命令省事,playbook文件使用yaml语言编写的,因此文件后缀最后为.yml或者.yaml.这种语言也是一种标记语言,就像HTML,xml,他的格式比较像json,主要格式为key: value1 value2 ...,value可以写在同一行,也可以将每一个value写在一行,如果是写在同一行他的冒号后面必须有一个空格,使用-开头的表示是一个列表,严格区分大小写,使用#注释,还有就是他的缩进必须一致切记不要tab和空格混用,相同的缩进代表同一个级别,可以在同一个playbook文件中写多个任务任务之间使用---分隔

文件格式

---                         #固定格式,可写可不写
- hosts: hosts/group        #横杠后面有空格,冒号后面有空给
  remote_user: user_name    #指定被控端以哪个用户执行

  tasks:                    #作业集,在其下面定义要执行的模块
   - name: hello            #一个作业的名称,任务描述,一个name下只能写一个任务
     module: arguments,... #执行的模块

示例:
- hosts: all
  remote_usre: root

  tasks:
    - name: hello
      command: hostname
    - name: hi
      shell: echo $HOSTNAME

变量:

变量可以定义的位置
1.在playbook中定义

- vars:
  key1: value1
  key2: value2

2.在/etc/ansible/hosts文件中为主机或者主机组设置特有的变量,可以为每个主机定义单独的变量,在IP后面使用key=value使用空格分隔定义变量

192.168.0.1 http_port=80 ssh_port=22

3.可以为主机组定义单独的变量,

[group_name:vars]
    key1: value1
    key2: value2

4.在命令中使用-e "key=value"为playbook中的变量赋值,在playbook中使用变量

5.可以将变量单独定义到一个yml文件中,在playbook中使用var_file: var_filename.yml导入

变量的使用:在playbook中使用,格式为,使用两组大括号将变量名包起来,两边最好留一个空格,不是格式要求是为了美观:例如{{ key }},另外ansible的setup模块定义了关于被控端的信息相关的变量,可以在playbook中直接使用

变量优先级:命令行 < playbook < 主机清单,影响的范围越小越优先

触发器:

我们在写playbook的时候,有时候希望某一个步骤执行了之后就一定要执行另一步骤,比如说我们修改了服务的配置文件,就一定需要重启其服务,那么我们就可以使用触发器了,使用handlers定义触发后执行的动作,handlers是和tasks同一个级别的,然后可以在tasks中的某一个- name中使用notify模块来定义触发哪个handlers

示例:

---
- hosts: all
  remote_user: root
  tasks:
    - name: test1
      copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
      notify: demo01
  handlers:
    - name: demo01
      service: name=httpd state=restart

标签:

在使用playbook的时候我们希望只使用其中的一个或者几个动作,这时就可以使用标签了,可以在某一个作业中使用tags: tag_name,来为该作业创建一个标签,然后我们在使用playbook的时候就可以只执行这一个作业,使用 -t tag_name来使用

示例:

---
- hosts: all
  remote_user: root
  tasks:
    - name: test1
      copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
      tags: test1

在使用playbook时我们就可以:

ansible-playbook -t test1 demo.yml

条件测试:

主要用到的模块是when,其参数是一个条件表达式,当条件表达式的值为真时就执行当前name下与其同级的模块,否则不执行

示例:

- hosts: all
  remote_user: root

  tasks:
    - name: test_when
      service: named=httpd started
      when: ansible_distribution_major_version == "6"

迭代:

如果我们要创建三个用户,这样我们就得写三遍只有文件名不同的代码,对于计算机来说这样肯定是挺low的于是ansible提供了解决这类问题的一个方式,可以将文件名定义在with_items中,然后在需要调用的地方用item变量获取

示例

# 简单示例
- name: create file
  file: name=/data/{{ item }} state=touch
  with_items:
    - file1
    - file2
    - file3
# 迭代嵌套自变量
- name:create user
  user:name={{item.user}} group={{item.group}}
  with_items:
    - {user:'user1',group:'g1'}
    - {user:'user2',group:'g2'}
    - {user:'user3',group:'g3'}

此时ansible,会依次读取 file1,file2,file3,并将其放在item的位置处,然后执行,注意with_items只能作用于单个name中

模板

主要的功能是根据不同主机的系统状态,配置,生成文件,而不是相同的文件,这样我们就有了更强的灵活性,模板文件是一个文本文件,使用jinja2语言编写,文件名后缀最好为.j2该语言有下面的形式:

字符串:使用单引号或者双引号
数字:整数,浮点数
列表:[item1,item2,...]
元组:(item1,item2,...)
字典:{key1:value1,key2:value2,...}
布尔型:true/false
算术运算:+,-,*,/,//(整除),%,**(乘方)
逻辑运算:and,or,not
流表达式:for,if,when

建议在playbook所在目录创建一个templates目录,专门存放模板文件,这样在playbook文件中直接写文件名就可以了,模板中的变量和playbook使用方式一样

for循环:

{%for name in list %}
    ... {{ name }} ...
{%endfor%}

if判断:

{%if some is defined %}
    something...
{%endif%}

ROLES角色

使用:在系统内的任意目录下创建一个roles目录,然后再在roles目录中创建相应的角色目录,在roles同级目录中创建一个调用角色的文件该文件中写明,主机,使用的用户,然后使用roles: { role: role_name }来指定要执行的角色,role_name就是roles目录中的目录的名称,最后使用ansible-playbook 执行调用文件,以此来执行角色

角色调用文件示例:

- hosts: web
  remote_user: root

  roles:
    - role: httpd

角色目录中常见的目录及其作用

tasks: 存放的是按功能编写的playbook文件
main.yml
templates: 存放了该角色需要用到的模板文件
vars: 变量文件存放的目录
main.yml
files: 需要用到的文件存放的目录

目录结构示例:

1527773881771.png
注意,按上面的命名方式创建目录,在使用角色时,系统会自动的找到相应的目录下的文件,因此,在很多时候,比如说template就不用再写路径了,直接写文件名就可以了,调用角色时系统会自动的找到tasks目录下的main.yml并执行之,因此main文件中多数情况下写的是整个角色的执行流程,可以使用include关键字来将其他的作业文件引入以此来达到调用的效果,而且在对应的目录下写的yml文件,不用再写前面的hosts等内容了就连vars,tasks这些也不用写了,要执行什么就写什么就可以了比如说vars目录中的文件,直接写key=value就可以了,在tasks目录中的文件直接写 -name ... module: ...就可以了

角色的标签:可以有两种,一种是在角色调用文件中设置标签,另外一种是为某一个任务创建标签,可以写在- include的下面,以上两种方式仍可以使用-t选项调用

角色中设置标签:

- roles:
  - { role: roles/httpd/tasks/copyfile.yml,tags: copyfile }

在tasks文件中包含变量可以使用:include_vars: vars_file.yml

相关文档:

官方文档

中文文档

bighero

这个人太懒什么东西都没留下

文章评论(0)