Ansible学习笔记

∥☆過路亽.° 提交于 2021-01-02 11:23:53

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/               # ""

 五 常用命令

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!