ansible

Posted by Mr.Cai on August 2, 2018

0x01 概念

ansible是自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。 ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:

  • 连接插件connection plugins:负责和被监控端实现通信;
  • host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
  • 各种模块核心模块、command模块、自定义模块;
  • 借助于插件完成记录日志邮件等功能;
  • playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。

0x02 目的

调研目的,服务的自动化部署、批量环境配置、线上热加载、热修复功能。

0x03 安装

    yum install python-pip
    pip install ansible

0x04 inventory配置

默认的inventory配置/etc/ansible/hosts的模板

# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
# ...
#
# Ex 1: 未分组的机器,要在分组的定义前面来定义.

## green.example.com 
## blue.example.com caijiahe_zuishuai= # 占位符,变量值handsome从vars目录的main.yml中读取
## 192.168.100.1
## 192.168.100.10

# Ex 2: 定义'webservers'组的host

## [webservers]
## alpha.example.org ansible_connection=local
## beta.example.org http_port=80 maxRequestsPerChild=808 # 定义主机变量
## 192.168.1.100 ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50 # 定义主机ssh连接端口和连接地址
## 192.168.1.110

# 这是多个host的简写模式
## www[001:006].example.com # 定义1-6范围内的主机

# 定义webservers组的变量
[webservers:vars]
ntp_server=ntp.example.com
proxy=proxy.example.com

# Ex 3: 定义'dbservers'组的host

## [dbservers]
## 
## db01.intranet.mydomain.net ansible_python_interpreter=/usr/local/bin/python #定义python执行文件
## db02.intranet.mydomain.net  ruby_module_host  ansible_ruby_interpreter=/usr/bin/ruby.1.9.3 # 定义ruby执行文件
## 10.25.1.56
## 10.25.1.57

主机连接:

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

ssh连接参数:

  • ansible_ssh_host:将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
  • ansible_ssh_port:ssh端口号.如果不是默认的端口号,通过此变量设置.
  • ansible_ssh_user:默认的 ssh 用户名
  • ansible_ssh_pass:ssh 密码(这种方式并不安全,我们强烈建议使用 –ask-pass 或 SSH 密钥)
  • ansible_ssh_private_key_file:ssh使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.
  • ansible_ssh_common_args:此设置附加到sftp,scp和ssh的缺省命令行
  • ansible_sftp_extra_args:此设置附加到默认sftp命令行。
  • ansible_scp_extra_args:此设置附加到默认scp命令行。
  • ansible_ssh_extra_args:此设置附加到默认ssh命令行。
  • ansible_ssh_pipelining:确定是否使用SSH管道。 这可以覆盖ansible.cfg中得设置。

远程主机环境参数:

  • ansible_shell_type:目标系统的shell类型.默认情况下,命令的执行使用 ‘sh’ 语法,可设置为 ‘csh’ 或 ‘fish’.
  • ansible_python_interpreter:目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是”/usr/bin/python”,比如 *BSD, 或者 /usr/bin/python
  • _ansible_interpreter__:这里的”“可以是ruby 或perl 或其他语言的解释器,作用和ansible_python_interpreter 类似
  • ansible_shell_executable:这将设置ansible控制器将在目标机器上使用的shell,覆盖ansible.cfg中的配置,默认为/bin/sh。

如果修改默认的配置路径,可以在/etc/ansible/ansible.cfg中修改inventory项。

0x05 常用配置

  • library:Ansible无论是本地或远程,都使用一小段代码来执行,这小段代码称为模块,这个library参数就是指向存放Ansible模块的目录 library = /usr/share/ansible
  • forks:设置默认情况下Ansible最多能有多少个进程同时工作,默认设置最多5个进程并行处理。具体需要设置多少个,可以根据控制主机的性能和被管理节点的数量来确定。 forks = 5
  • sudo_user:这是设置默认执行命令的用户,也可以在playbook中重新设置这个参数 sudo_user = root //ansible2.4.1下已经为default_sudo_user = root
  • remote_port:这是指定连接节点的管理端口,默认是22,除非设置了特殊的SSH端口,不然这个参数一般是不需要修改的 remote_port = 22
  • host_key_checking: 这是设置是否检查SSH主机的密钥。可以设置为True或False host_key_checking = False
  • timeout:这是设置SSH连接的超时间隔,单位是秒。 timeout = 20
  • log_path: Ansible系统默认是不记录日志的,如果想把Ansible系统的输出记录到人日志文件中,需要设置log_path来指定一个存储Ansible日志的文件 log_path = /var/log/ansible.log 另外需要注意,执行Ansible的用户需要有写入日志的权限,模块将会调用被管节点的syslog来记录,口令是不会出现的日志中的
  • private_key_file:在使用ssh公钥私钥登录系统时候,使用的密钥路径。 private_key_file=/path/to/file.pem
    !ansible更多配置

0x06 ansible-galaxy

ansible-galaxy是一个共享和下载Ansible角色,也可以是创建roles的命令行工具。

ansible-galaxy init rolename

执行上述命令后,会在当前目录下的roles目录下生成对应的角色目录,结构如下。

drwxr-xr-x. 2 root root   21 8月   2 14:23 defaults // 低优先级的变量,很容易被覆盖。
drwxr-xr-x. 2 root root    6 8月   2 14:23 files // 能被这个角色部署的文件
drwxr-xr-x. 2 root root   21 8月   2 14:23 handlers // handlers,可能被其他角色使用
drwxr-xr-x. 2 root root   21 8月   2 14:23 meta
-rw-r--r--. 1 root root 1328 8月   2 14:23 README.md
drwxr-xr-x. 2 root root   41 8月   2 14:45 tasks // 包含一个task的链表
drwxr-xr-x. 2 root root    6 8月   2 14:23 templates // 包含被这个角色部署的模板
drwxr-xr-x. 2 root root   37 8月   2 14:23 tests
drwxr-xr-x. 2 root root   21 8月   2 14:23 vars // 角色使用的变量

0x07 ansible-playbook

- hosts: webservers
  remote_user: root 最基本的playbook,包含一个在inventory配置里面定义的组名,和一个远程执行task的username。

- hosts: webservers
  remote_user: yourname
  tasks:
    - name: test connection
      ping:
      become: yes
      become_method: su 这个playbook增加了一个task,在执行ping的task的时候使用su切换到root用户。我们也可以在`roles/rolename/tasks/main.yml`中定义我们的task,或者在`roles/rolename/tasks`目录下新创建yml文件去定义task,但是一定要被main.yml `include_tasks`或者`import_tasks`进来。

handlers和执行失败的情况下handler的处理

---
# 打印当前的用户名,成功执行所有task后调用handler3
- name: name                                  
  shell: logname
  notify:
    - handler3

# 拷贝jar包到/root目录下
- name: copy                                  
  copy:
    src: /tmp/com.test-1.0-SNAPSHOT.jar
    dest: /root
  
# 执行一个不存在的命令,并且忽略错误,注册错误结果failResult
- name: fail task                             
  shell: ooo
  register: failResult
  ignore_errors: true
  notify:
    - handler2

# 如果failResult的stderr不为空,则输出`失败了`,成功执行所有task后调用handler1
- name: echo                                  
  shell: echo "失败了"
  register: result3
  when: failResult.stderr != ""
  notify:
    - handler1

# 如果failResult的stderr不为空,声明一个环境变量,然后启动jar包
- name: execute                               
  shell: java -cp /root/com.test-1.0-SNAPSHOT.jar Main
  environment: ""
  when: result3.stderr != ""

如果将上述的ignore_errors删掉,并且playbook的时候加上–force-handlers,那么即便handler2也会执行。但是目前并没有,于是我就在github上报了个bug

include_tasks和import_tasks

# tasks file for test
  - name: this is a task
    shell: echo "this is task" 
  - name: include task
    include_tasks: "task.yml"
  - name: import task
    import_tasks: "/etc/ansible/common/tasks/task.yml"

include_task是动态的,include_tasks是静态的。