Ansible简要笔记
参考http://www.ansible.com.cn/docs
主流的自动化运维工具:Puppet、saltstack、ansible chef
Ansible:用Python编写,采用paramiko协议库
Ansible的组成:
1.核心引擎:Ansible
2.核心模块:
3.自定义模块
4.插件:实现日志记录、邮件等功能
5.playbook:记录执行的任务
6.连接插件:现在主要是ssh,还支持其他(ZeroMQ等)
7.主机清单:记录需要配置的节点信息(文件hosts)
Ansible的优点:
1.语法简单
2.不要安装客户端
3.大量内置模块 用 ansible-doc -l | wc -l 统计可用模块
[root@localhost ~]# ansible-doc -l | wc -l
1652
ansible的配置文件:/etc/ansible/ansible.cfg
CentOS7.4的安装:
[root@localhost ~]#yum install -y ansible
[root@localhost ~]# ansible --version
ansible 2.5.0
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, Aug 4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
修改配置文件:/etc/ansible/ansible.cfg
#开启日志 log_path = /var/log/ansible.log #如果ansible没有和被管理节点配置无密码登录时,会提示没有在known_hosts中初始化,如果不想出现这样的提示,可以在配置文件中设置 host_key_checking = False 其他配置基本不用改
基本命令使用:
#查看版本
[root@localhost ~]# ansible --version
#查看所有可用的内置模块
[root@localhost ~]#
ansible-doc -l #查看模式使用帮助
[root@localhost ~]# ansible-doc -s yum
一、安装:
系统要求:Linux ssh
安装方法:通过系统自带的源进行安装(yum install ansible)
Python:python2.6或python2.7
selinux:如果启用,需要安装libselinux-python
二、使用前配置(可选)
配置客户端无密码登陆:
[root@localhost ~]# ssh-keygen
[root@localhost ~]# ssh-copy-id root@10.100.14.102
#########################################################################
三基本配置文件:
(一)inventory文件(客户端主机的IP/域名)
默认文件位置:/etc/ansible/hosts
几种常见的格式:
#1.直接写IP地址 192.168.1.10 #2.把IP分组 [webserver] 192.168.1.11 192.168.1.12 #3.对于不是以22端口连接的主机,可以指定IP地址 [sql] 192.168.1.20:2222 #4.主机别名设置 [jumper] jumper ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50 #5.对于有规律的一组IP地址可以简写 [dbserver] 192.168.1.[100:102] db[1:3].example.com #6.对用非root用户登录或不同登录方式的主机可以指定连接的用户名 [targets] localhost ansible_connection=local other1.example.com ansible_connection=ssh ansible_ssh_user=user1 other2.example.com ansible_connection=ssh ansible_ssh_user=user1 #7.给主机定义变量 [apache] host1 http_port=80 maxRequestsPerChild=808 host2 http_port=303 maxRequestsPerChild=909 #8.给一组主机定义变量 [atlanta] host1 host2 [atlanta:vars] ntp_server=ntp.atlanta.example.com proxy=proxy.atlanta.example.com #9.把一个组作为另一个组的子成员 [group1] host1 host2 [group2] host3 host3 [group:children] group1 group2
此外,inventory还有很多参数
ansible_ssh_host 将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_ssh_port ssh端口号.如果不是默认的端口号,通过此变量设置.
ansible_ssh_user 默认的 ssh 用户名
ansible_ssh_pass ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)
ansible_sudo_pass sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)
ansible_sudo_exe (new in version 1.8) sudo 命令路径(适用于1.8及以上版本)
ansible_connection 与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行.
ansible_ssh_private_key_file ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.
ansible_shell_type 目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'.
ansible_python_interpreter 目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 *BSD, 或者 /usr/bin/python
不是 2.X 版本的 Python.我们不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).
与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....
inventory的升级用法:
/etc/ansible/hosts是ansible中默认的被管理节点的IP存放的文件路径,如果想自己定义,或者想把不同类型的主机存在不同的文件中,可以在/etc/ansible/ansible.cfg中更改配置文件即可。比如:
[root@localhost ~]# vim /etc/ansible/ansible.cfg inventory = /root/myhosts/ [root@localhost ~]# tree /root/myhosts/ /root/myhosts/ ├── dbserver └── httpd 0 directories, 2 files [root@localhost ~]# ansible all --list-hosts hosts (2): 10.100.14.102 192.168.1.2
以上的inventory都是静态hosts配置,对于大量的主机在后期添加起来比较麻烦,ansible还支持动态的inventory
即通过外部拉取主机的IP,inventory的脚本需要支持两个参数,--list(-l),--host(-H)然后返回json格式的主机信息。
#########################################################################
(二)playbook配置文件
hosts 中记录的是客户机的IP地址
playbook 中记录的是客户机要进行的操作
Playbooks 的格式是YAML
palybook的简单实例:
--- - hosts: webservers vars: http_port: 80 max_clients: 200 remote_user: root #定义连接的用户名 tasks: - name: ensure apache is at the latest version yum: pkg=httpd state=latest - name: write the apache config file template: src=/srv/httpd.j2 dest=/etc/httpd.conf notify: - restart apache - name: ensure apache is running service: name=httpd state=started handlers: - name: restart apache service: name=httpd state=restarted
详细解释:
1.主机与用户:
1.2在任务开始之前定义用户
- hosts: webservers #指定操作对象,webserver是在hosts文件中农定义的一组主机的名字
remote_user: root #定义连接的用户名
1.2在每一个任务中定义远程用户
- hosts: webservers
remote_user: root
tasks:
- name: test connection
ping:
remote_user: username
1.3使用sudo切换用户
---
- hosts: webservers
remote_user: yourname
sudo: yes
或者在任务中使用sudo
---
- hosts: webservers
remote_user: username
tasks:
- service: name=nginx state=started
sudo: yes
或者使用sudo切换到其他用户
- hosts: webservers
remote_user: yourname
sudo: yes
sudo_user: postgres
2.任务(tasks)
tasks的格式;
tasks:
- name: 注释部分
模块名称和执行内容
2.1command模块和shell模块格式
tasks:
- name: disable selinux
command: /sbin/setenforce 0
异常的处理:
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
或者使用ignore_errors: True
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
2.2其他模块的格式:
tasks:
- name: make sure apache is running
service: name=httpd state=running
3.Handlers的用法:主要用来重启服务
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted
playbook的执行
ansible-playbook playbook.yml
4.playbook中变量
4.1变量的命名和其他语言一致
4.2在playbook中定义变量
- hosts: webservers
vars:
http_port: 80
4.3变量的引用:注意需要加双引号
- hosts: app_servers
vars:
app_path: "{{ base_path }}/22"
5.条件选择
5.1when语句(jinja2)
用法1:
tasks: - name: "shutdown Debian flavored systems" command: /sbin/shutdown -t now when: ansible_os_family == "Debian" tasks: - shell: echo "only on Red Hat 6, derivatives, and later" when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6
用法2:如果变量不存在,可以使用defined跳过
tasks: - shell: echo "I've got '{{ foo }}' and am not afraid to use it!" when: foo is defined - fail: msg="Bailing out. this play requires 'bar'" when: bar is not defined
用法3:在roles 和 includes 上面应用’when’语句
- include: tasks/sometasks.yml when: "'reticulating splines' in output" - hosts: webservers roles: - { role: debian_stock_config, when: ansible_os_family == 'Debian' }
ansible中的when
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
5.2变量注册:返回结果保存到一个变量中,比如
- name: test play hosts: all tasks: - shell: cat /etc/motd register: motd_contents - shell: echo "motd contains the word hi" when: motd_contents.stdout.find('hi') != -1
6.循环
6.1标准循环
- name: add several users user: name={{ item }} state=present groups=wheel with_items: - testuser1 - testuser2 或者: - name: add several users user: name={{ item }} state=present groups=wheel with_items:"{{somelist}}" 或者: - name: add several users user: name={{ item.name }} state=present groups={{ item.groups }} with_items: - { name: 'testuser1', groups: 'wheel' } - { name: 'testuser2', groups: 'root' }
6.2循环嵌套
- name: give users access to multiple databases mysql_user: name={{ item[0] }} priv={{ item[1] }}.*:ALL append_privs=yes password=foo with_nested: - [ 'alice', 'bob' ] - [ 'clientdb', 'employeedb', 'providerdb' ] 或者: - name: here, 'users' contains the above list of employees mysql_user: name={{ item[0] }} priv={{ item[1] }}.*:ALL append_privs=yes password=foo with_nested: - "{{users}}" - [ 'clientdb', 'employeedb', 'providerdb' ]
6.3对哈希表使用循环
--- users: alice: name: Alice Appleworth telephone: 123-456-7890 bob: name: Bob Bananarama telephone: 987-654-3210 tasks: - name: Print phone records debug: msg="User {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})" with_dict: "{{users}}"
6.4对文件列表使用循环
--- - hosts: all tasks: # first ensure our target directory exists - file: dest=/etc/fooapp state=directory # copy each file over that matches the given pattern - copy: src={{ item }} dest=/etc/fooapp/ owner=root mode=600 with_fileglob: - /playbooks/files/fooapp/*
6.5对并行数据集使用循环(不常用)
--- alpha: [ 'a', 'b', 'c', 'd' ] numbers: [ 1, 2, 3, 4 ] tasks: - debug: msg="{{ item.0 }} and {{ item.1 }}" with_together: - "{{alpha}}" - "{{numbers}}"
6.6对子元素使用循环
--- users: - name: alice authorized: - /tmp/alice/onekey.pub - /tmp/alice/twokey.pub mysql: password: mysql-password hosts: - "%" - "127.0.0.1" - "::1" - "localhost" privs: - "*.*:SELECT" - "DB1.*:ALL" - name: bob authorized: - /tmp/bob/id_rsa.pub mysql: password: other-mysql-password hosts: - "db1" privs: - "*.*:SELECT" - "DB2.*:ALL" - user: name={{ item.name }} state=present generate_ssh_key=yes with_items: "{{users}}" - authorized_key: "user={{ item.0.name }} key='{{ lookup('file', item.1) }}'" with_subelements: - users - authorized - name: Setup MySQL users mysql_user: name={{ item.0.user }} password={{ item.0.mysql.password }} host={{ item.1 }} priv={{ item.0.mysql.privs | join('/') }} with_subelements: - users - mysql.hosts
6.7对整数序列循环(不常用)
--- - hosts: all tasks: # create groups - group: name=evens state=present - group: name=odds state=present # create some test users - user: name={{ item }} state=present groups=evens with_sequence: start=0 end=32 format=testuser%02x # create a series of directories with even numbers for some reason - file: dest=/var/stuff/{{ item }} state=directory with_sequence: start=4 end=16 stride=2 # a simpler way to use the sequence plugin # create 4 groups - group: name=group{{ item }} state=present with_sequence: count=4
6.8随机选择(不常用)
- debug: msg={{ item }} with_random_choice: - "go through the door" - "drink from the goblet" - "press the red button" - "do nothing"
6.9Do-Until循环
- action: shell /usr/bin/foo register: result until: result.stdout.find("all systems go") != -1 retries: 5 delay: 10
6.10还有很多不常见的用法,具体参考官方文档
四、文件目录
目录结构
production # 关于生产环境服务器的清单文件 stage # 关于 stage 环境的清单文件 group_vars/ group1 # 这里我们给特定的组赋值 group2 # "" host_vars/ hostname1 # 如果系统需要特定的变量,把它们放置在这里. hostname2 # "" library/ # 如果有自定义的模块,放在这里(可选) filter_plugins/ # 如果有自定义的过滤插件,放在这里(可选) site.yml # 主 playbook webservers.yml # 服务器的 playbook dbservers.yml # 数据库服务器的 playbook roles/ common/ # 这里的结构代表了一个 "role" tasks/ # main.yml # tasks file can include smaller files if warranted handlers/ # main.yml # handlers file templates/ # files for use with the template resource ntp.conf.j2 # templates end in .j2 files/ # bar.txt # files for use with the copy resource foo.sh # script files for use with the script resource vars/ # main.yml # variables associated with this role defaults/ # main.yml # default lower priority variables for this role meta/ # main.yml # role dependencies webtier/ # same kind of structure as "common" was above, done for the webtier role monitoring/ # "" fooapp/ # ""
五 常用命令