ansible 学习笔记

是什么

自动化工具。用来自动化安装,部署,测试。

为什么

让人专注于做什么,而不是怎么做。(不太关心怎么连接,连接多少太机器,怎么验证)

类似的工具还有puppet。ansible 最大的优势就是不用安装客户端,只要ssh 能够连接进去,就能工作了。

安装

简单的方式

For RHEL

$ yum install ansible

For CentOS

 $ yum install -y epel-release 
 $ yum install -y ansible

For ubuntu

# apt-get update
# apt-get install -y software-properties-common
# apt-add-repository ppa:ansible/ansible
# apt-get update
# apt-get install -y ansible

通过pip安装 [推荐]

这种方式可以获取ansible 最新的版本。

For CentOS

$ sudo yum -y install https://centos7.iuscommunity.org/ius-release.rpm
$ sudo yum -y install python36u
$ sudo python3.6 -m ensurepip
$ pip3 install ansible

For ubuntu

# apt update
# apt install python3-pip
# pip3 install ansible

配置文件

Changes can be made and used in a configuration file which will be searched for in the following order:

  • ANSIBLE_CONFIG (environment variable if set)
  • ansible.cfg (in the current directory)
  • ~/.ansible.cfg (in the home directory)
  • /etc/ansible/ansible.cfg

Ansible will process the above list and use the first file found, all others are ignored.

使用(Ad-hoc)

$ ansible web –m ping
$ ansible web -b –m yum –a "name=httpd state=present"
$ ansible web -m command -a 'echo "hello world"'

使用(playbook)

Playbook (who, where, what)

File test.yml

- hosts: localhost
  tasks:
    - name: check login user
      shell: whoami > /tmp/login_user

运行

$ ansible-playbook test.yml

变量

命令行方式

key=value format:

ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"
ansible localhost -m package -a "name=git state=present" -b -e 'ansible_python_interpreter=/usr/bin/python'

JSON string format:

ansible-playbook release.yml --extra-vars '{"version":"1.23.45","other_variable":"foo"}'
ansible-playbook arcade.yml -e '{"pacman":"mrs","ghosts":["inky","pinky","clyde","sue"]}'

YAML string format:

ansible-playbook release.yml --extra-vars '
version: "1.23.45"
other_variable: foo'

ansible-playbook arcade.yml --extra-vars '
pacman: mrs
ghosts:
 - inky
 - pinky
 - clyde
 - sue'

vars from a JSON or YAML file:

ansible-playbook release.yml --extra-vars "@some_file.json"

其它参数:

Specifying a user:

ansible-playbook playbooks/atmo_playbook.yml --user atmouser

Using a specific SSH private key:

ansible -m ping hosts --private-key=~/.ssh/keys/id_rsa -u centos

Inventory vars

[ambari-nodes]
my-vm-hdp-1
my-vm-hdp-2

[ambari-nodes:vars]
ansible_ssh_user=dcpuser
ansible_ssh_private_key_file=group_vars/iot_rsa

Play vars

In a playbook, it’s possible to define variables directly inline like so:

- hosts: webservers
  vars:
    http_port: 80

Role vars

---
- hosts: webservers
  roles:
    - role: foo
      vars:
        message: "first"
    - { role: foo, vars: { message: "second" } }

Jinja2

For instance, in a simple template, you can do something like:

My amp goes to {{ max_amp_value }}

This is also valid directly in playbooks, and you’ll occasionally want to do things like:

template: src=foo.cfg.j2 dest={{ remote_install_path }}/foo.cfg

注册变量

- hosts: web_servers
  tasks:
     - shell: /usr/bin/foo
       register: foo_result
       ignore_errors: True

     - shell: /usr/bin/bar
       when: foo_result.rc == 5

动态输入变量

- hosts: ambari-server
  vars_prompt:
    - name: "ambari"
      prompt: "Enter password for [admin]"
      confirm: yes

内置变量

Special Variable

变量名称 说明 使用
hostvars 包含主机得fcats信息 {{ hostvars['db.example.com'].ansible_eth0.ipv4.address }}
inventory_hostname 当前主机的名称 {{ hostvars[inventory_hostname] }} , {{ inventory_hostname }}
group_names 当前主机所在组的主机列表 {% if 'webserver' in group_names %}# some part of a configuration file that only applies to webservers{% endif %}
groups 包含设备清单组内的所有主机 {% for host in groups[‘db_servers’] %} {{ host }}{% endfor %}
play_hosts 在当前playbook中处于活动状态的主机名列表 {{play_hosts}}
playbook_dir The path to the directory of the playbook that was passed to the ansible-playbook command line. {{ playbook_dir }}
role_path The path to the dir of the currently running role {{ role_path }}

获取主机IP

- hosts: localhost
  connection: local
  tasks:
    - debug: var=ansible_all_ipv4_addresses
    - debug: var=ansible_default_ipv4.address
    - debug: var=ansible_eth0.ipv4.address

环境变量

You can use the environment keyword at the play, block, or task level to set an environment variable for an action on a remote host.

https://docs.ansible.com/ansible/latest/user_guide/playbooks_environment.html

- hosts: dev
  tasks:
    - name: Echo my_env_var
      shell: "echo $MY_ENV_VARIABLE"
      environment:
        MY_ENV_VARIABLE: whatever_value

    - name: Echo my_env_var again
      shell: "echo $MY_ENV_VARIABLE"

变量优先级

官网

Ansible does apply variable precedence, and you might have a use for it. Here is the order of precedence from least to greatest (the last listed variables override all other variables):

越靠后,优先级越高

  1. command line values (for example, -u my_user, these are not variables)
  2. role defaults (defined in role/defaults/main.yml) 1
  3. inventory file or script group vars 2
  4. inventory group_vars/all 3
  5. playbook group_vars/all 3
  6. inventory group_vars/* 3
  7. playbook group_vars/* 3
  8. inventory file or script host vars 2
  9. inventory host_vars/* 3
  10. playbook host_vars/* 3
  11. host facts / cached set_facts 4
  12. play vars
  13. play vars_prompt
  14. play vars_files
  15. role vars (defined in role/vars/main.yml)
  16. block vars (only for tasks in block)
  17. task vars (only for the task)
  18. include_vars
  19. set_facts / registered vars
  20. role (and include_role) params
  21. include params
  22. extra vars (for example, -e "user=my_user")(always win precedence)

本地运行

delegate_to

- name: add back to load balancer pool
  command: /usr/bin/add_back_to_pool {{ inventory_hostname }}
  delegate_to: 127.0.0.1

local_action

  - name: recursively copy files from management server to target
    local_action: command rsync -a /path/to/files {{ inventory_hostname }}:/path/to/target/

connection

ansible-playbook playbook.yml --connection=local
...

- command: foo
  connection: local

tags

ansible-playbook offers five tag-related command-line options:

  • --tags all - run all tasks, ignore tags (default behavior)
  • --tags [tag1, tag2] - run only tasks with the tags tag1 and tag2
  • --skip-tags [tag3, tag4] - run all tasks except those with the tags tag3 and tag4
  • --tags tagged - run only tasks with at least one tag
  • --tags untagged - run only tasks with no tags

Adding tags to individual tasks

tasks:
- name: Install the servers
  ansible.builtin.yum:
    name:
    - httpd
    - memcached
    state: present
  tags:
  - packages
  - webservers

- name: Configure the service
  ansible.builtin.template:
    src: templates/src.j2
    dest: /etc/foo.conf
  tags:
  - configuration

Adding tags to plays

- hosts: all
  tags: ntp
  tasks:
  - name: Install ntp
    ansible.builtin.yum:
      name: ntp
      state: present

Adding tags to blocks

特殊替换

想把字符串 abc 替换成 {{ abc }} 默认办法做不到,比如:

 - name: change line - fail
   lineinfile:
     path: a.txt
     regexp: 'abc'
     line: '{{ abc }}'

它会认为要替换一个变量,而不是字符串。

可以使用 {% raw %} ... {% endraw %} tags 来解决问题。

- name: change line - succeed
  lineinfile:
    path: a.txt
    regexp: 'abc'
    line: '{% raw %} {{ abc }} {% endraw %}'

Tips

Retrieve public IP

方法一

- name: Get my public IP from ipify.org
  ipify_facts:
- debug: var=ipify_public_ip

方法二

use uri module:

- name: Find my public ip
  uri: 
    url: http://ifconfig.me/ip
    return_content: yes
  register: ip_response

Your IP will be in ip_response.content

refs: https://stackoverflow.com/questions/39819378/ansible-get-current-target-hosts-ip-address

跳板机设置

方法一:直接写入inventory

核心参数: ansible_ssh_common_args options

more ansible_*_args

Ansible 利用了 OpenSSH 的ProxyCommand来实现跳过Bastion(proxy/ jump)的功能。

用分组的方式

# file: tmp_hosts
[gatewayd]
hdp-slave-0
hdp-slave-1
hdp-master-0
hdp-master-1
hdp-master-2

[gatewayd:vars]
ansible_ssh_common_args=' -o ProxyCommand="ssh -W %h:%p -i /home/edaizen/.ssh/docomo-devops -o StrictHostKeyChecking=no [email protected]"'

[all:vars]
ansible_ssh_private_key_file='/home/edaizen/.ssh/docomo-hadoop'
ansible_user=centos

方法二:灵活性更强的配置方式

这是官方FAQ的例子。

定义一个组都要通过proxy 连接(相当于把上面例子中的 [gatewayd:vars] 部分单独拿出来)

# file: group_vars/gatewayed.yml
ansible_ssh_common_args: ' -o ProxyCommand="ssh -i group_vars/eea_rsa -W %h:%p -q [email protected]"'

定义这个组里有哪些机器

# file: hosts
[gatewayed]
foo ansible_host=192.168.3.5
small-test-01

方法三:在命令行中写入参数

参数:--ssh-common-args
e.g.

ansible-playbook  --ssh-common-args='-o ProxyCommand="ssh  -W %h:%p -q [email protected]"' site.yml

优点:不用关心配置文件关于bastion部分。
缺点:这么长的参数记不住,适合生成脚本再运行。

使用(galaxy)

通过galaxy 获取社区的ansible role,直接调用,不关心具体怎么实现的。

https://galaxy.ansible.com/

比如要对VM 加固,直接用社区的代码

$ ansible-galaxy install git+https://github.com/openstack/ansible-hardening
- extracting ansible-hardening to /home/edaizen/.ansible/roles/ansible-hardening
- ansible-hardening was installed successfully

检查自己安装了什么

$ ansible-galaxy list
# /home/edaizen/.ansible/roles
- ansible-hardening, (unknown version)

要调用这个role,跟其它playbook 一样

# test.yml
- name: Harden all systems
  hosts: all
  become: yes
  vars:
    security_enable_firewalld: no
    security_rhel7_initialize_aide: no
  roles:
    - ansible-hardening

你可能感兴趣的:(ansible 学习笔记)