Ansible简要笔记
参考http://www.ansible.com.cn/docs
一、安装:
系统要求:Linux ssh
安装方法:通过系统自带的源进行安装(yum install ansible)
Python:python2.6或python2.7
selinux:如果启用,需要安装libselinux-python
二、使用前配置(可选)
配置客户端无密码登陆:
[root@localhost ~]# ssh-keygen
[root@localhost ~]# ssh-copy-id [email protected]
#########################################################################
三基本配置文件:
(一)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 的路径....
#########################################################################
(二)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
3.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还有很多不常见的用法,具体参考官方文档
在/etc/ansible/hosts中添加客户端主机IP/域名
四、文件目录
目录结构
目录结构 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/ # ""