User Tools

Site Tools


сервис_ansible

This is an old revision of the document!


Сервис Ansible

Установка на управляющей системе

Из репозитория дистрибутива

node1# apt install ansible

node1# ansible --version

Из репозитория производителя

Установка на управляемых системах

nodeN# apt install python python-apt

debian11/ubuntu20# apt install python python3-apt

Настройка групп управляемых систем

debian11# mkdir /etc/ansible/

node1# cat /etc/ansible/hosts
[all:vars]
#ansible_python_interpreter="/usr/bin/python3"

#[corp]
#server.corp13.un
#server.corp[1:12].un ansible_ssh_user=root ansible_ssh_pass=strongpassword
#mail.corp[1:12].un ansible_ssh_user=root ansible_ssh_pass=strongpassword
#192.168.[1:25].10

[corpX]
node[1:2]

[addnodes]
192.168.X.[3:9] ansible_ssh_user=root ansible_ssh_pass=strongpassword

[sws]
switch[1:3] ansible_ssh_user=root ansible_ssh_pass=cisco

[nodes]
192.168.13.[210:230:10]

[nodes:vars]
ansible_ssh_user=vagrant
ansible_ssh_pass=strongpassword
ansible_become=yes

Настройка транспорта ssh

  • Для автоматизации подключения к новым системам может потребоваться отключение проверки их публичного ключа и Парольная аутентификация в ssh
# cat /etc/ansible/ansible.cfg
[defaults]
...
host_key_checking = False
...
node1# ssh-keygen

node1# ssh-copy-id node1
node1# ssh-copy-id node2

Использование модулей

$ ansible-doc -l
$ ansible-doc ping

node1# ansible corpX -m ping
node1# ansible localhost -m ping
node1# ansible all -m ping
node1# ansible all -m ping -i inv_file.ini
node1# ansible all -m ping -i node2:2222, -e "ansible_python_interpreter=/usr/bin/python3"

node1# ansible corpX -m command -a 'uname -a'
node1# ansible corpX -a 'uname -a'

node1# ansible corpX -f 2 -m apt -a 'pkg=apache2 state=present update_cache=true'

node1# ansible addnodes -vv -f 5 -m apt -a 'pkg=ceph,tgt-rbd state=present update_cache=true'

ubuntu20# apt install python3-paramiko

server# ansible sws -m ios_command -a "commands='show cdp nei'" -c local

server# ansible sws -m ios_command -a "commands='show cdp nei'" -c network_cli -e "ansible_network_os=ios"

Использование playbook

Пример 1

# cat provision_docker.yml

  или

λ npp provision_docker.yml &
- hosts: "{{ variable_host | default('all') }}"
  become: yes
  user: vagrant
  tasks:
    - name: Install Docker's prequirement
      apt:
        pkg:
          - apt-transport-https
          - ca-certificates
          - curl
          - gnupg2
          - software-properties-common
        state: present 
        update_cache: true
    - name: Add Docker's official GPG key
      apt_key:
#        url: https://download.docker.com/linux/debian/gpg
#        url: https://download.docker.com/linux/ubuntu/gpg
        state: present
    - name: Add Docker's repository into sources list
      apt_repository:
#        repo: deb [arch=amd64] https://download.docker.com/linux/debian bullseye stable
#        repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable
        state: present
    - name: Install Docker
      apt: 
        pkg:
          - docker-ce
          - docker-ce-cli
          - containerd.io
          - docker-compose-plugin
        state: present 
        update_cache: true
gate# ansible-playbook provision_docker.yml

gate# ansible-playbook provision_docker.yml -i inv_file.ini

gate# ansible-playbook provision_docker.yml -e "ansible_python_interpreter=/usr/bin/python3" -i 192.168.X.1:2222,

gate# ansible-playbook provision_docker.yml --extra-vars "variable_host=corp"

gate# ansible-playbook provision_docker.yml --extra-vars "variable_host=localhost"

Пример 2

  • Ansible module user - Manage user accounts
    node1# cat addusers.yml
    - hosts: corpX
      tasks:
        - name: Add user1
          user:
            name: user1
            uid: 10001
            shell: /bin/bash
            comment: "Ivan Ivanovitch Ivanov,RA1,401,499-239-45-23"
            password: $6$3Gz1ZuH3yHckA$wQNZbfU/9G6bYx08owpn7CoFP//2WbB4cmDDOgwDYBbwEyHxB0QQyCuMrOiPOLv3JF5RFtIv/r/kxoPPYFCsx1
    
        - name: Add user2
          user:
            name: user2
            uid: 10002
            shell: /bin/bash
            comment: "Petr Petrovitch Petrov,RA7,402,499-323-55-53"
            password: $6$x/AU/p9Dgi/ZiNF$6Xb8J4fsGuTi5IR0LaZe5pSgRX8vp54sfQGWJZZwKX.KFVpUL9m2PJNDh/d/l0rocueIvVjdQTzEAYPMmTm991
    
    
    node1# ansible-playbook addusers.yml

Пример 3

server# cat cisco_change_conf.yml
- hosts: sws
  connection: local
  tasks:
    - name: configure top level configuration
      ios_config:
        lines:
          - ip host server 192.168.X.10

          - snmp-server host server writetrap
          - snmp-server community write RW

#          - snmp-server enable traps config
#          - snmp-server enable traps config-copy
#          - snmp-server enable traps snmp linkdown linkup
#          - ip scp server enable

#          - logging facility local0
##          - logging host server
#          - logging host server transport udp port 8514

#          - ntp server server
#          - clock timezone MSK 3
#          - service timestamps log datetime localtime year

#          - aaa new-model
#          - aaa authentication login CONSOLE none
#          - aaa authorization exec CONSOLE none
#          - enable secret cisco
#          - aaa authorization console
#          - aaa authentication login default local
#          - aaa authorization exec default local
#          - username root privilege 15 secret cisco

#          - radius-server host server auth-port 1812 acct-port 1813
#          - radius-server key testing123
#          - aaa authentication login default group radius enable
#          - aaa authorization exec default group radius none

#          - tacacs-server host server
#          - tacacs-server key tackey123
#          - aaa authentication login default group tacacs+ enable
#          - aaa authorization exec default group tacacs+ none
#          - aaa accounting commands 15 default start-stop group tacacs+

#          - aaa authentication dot1x default group radius
##          - aaa accounting dot1x default start-stop group radius


#    - name: configure line con 0
#      ios_config:
#        lines:
#          - login authentication CONSOLE
#          - authorization exec CONSOLE
#          - privilege level 15
#        parents: line con 0
server# ansible-playbook cisco_change_conf.yml

server# ansible-playbook cisco_change_conf.yml --limit @/root/cisco_change_conf.retry

Использование шаблонов

node1# ansible -m setup corpX

node1# ansible -m setup corpX | grep ansible_fqdn

node1# cat index.html.j2
<html>
<body>
<h1>
{{ ansible_fqdn }}
</h1>
</body>
</html>
node1# cat inst_apache.yml
- hosts: corpX
  tasks:
    - name: Installs apache web server
      apt: pkg=apache2 state=present update_cache=true

    - name: Create index.html file
      template: src=index.html.j2 dest=/var/www/html/index.html
node1# ansible-playbook inst_apache.yml
# cat iax.conf.j2
[general]
disallow=all
allow=alaw

{% for Y in YS %}
[corp{{Y}}]
type=user
host=dynamic
secret=apassword{{Y}}
auth=md5

[corp{{Y}}]
type=peer
host=server.corp{{Y}}.un
username=corp{{X}}
secret=apassword{{X}}
auth=md5

{% endfor %}
# cat ast_iax_corps.yml
- hosts: corp
  tasks:
    - name: Create iax.conf file
      template: src=iax.conf.j2 dest=/etc/asterisk/iax.conf

    - name: Reload asterisk confs
      service: name=asterisk state=reloaded
# ansible-playbook ast_iax_corps.yml --extra-vars '{"X":"{{ ansible_eth0.ipv4.address.split(\".\")[3] }}","YS":[1,2,3,4,5,6,7,8,9,10,11,12,13]}'

Использование handlers

node1# cat conf_apache.yml
- hosts: corpX
  tasks:
    - name: Add userdir to apache
      apache2_module:
        state: present
#        state: absent
        name: userdir
      notify:
        - restart apache

  handlers:
    - name: restart apache
      service: name=apache2 state=restarted
node1# ansible-playbook conf_apache.yml

Использование ролей

Роль настроенного через ifupdown узла сети

# cat nodes.yml
- name: Network config for nodes
  hosts: addnodes
  roles:
    - node
# ansible-galaxy init node  # не обязательно

# cat node/vars/main.yml
name_prefix: node
X: "{{ ansible_eth0.ipv4.address.split('.')[2] }}"
N: "{{ ansible_eth0.ipv4.address.split('.')[3] }}"
# cat node/tasks/main.yml
- name: Create hosts file
  template: src=hosts.j2 dest=/etc/hosts

- name: Create resolv.conf file
  template: src=resolv.conf.j2 dest=/etc/resolv.conf

- name: Create hostname file
  template: src=hostname.j2 dest=/etc/hostname
  notify:
    - restart system

- name: Create interfaces file
  template: src=interfaces.j2 dest=/etc/network/interfaces
  notify:
    - restart system

- name: Set timezone to Europe/Moscow
  timezone:
    name: Europe/Moscow
# cat node/handlers/main.yml
- name: restart system
  reboot:
debian11# mkdir node/templates

# cat node/templates/hostname.j2
{{ name_prefix }}{{ N }}.corp{{ X }}.un
# cat node/templates/hosts.j2
127.0.0.1 localhost

{{ ansible_eth0.ipv4.address }} {{ name_prefix }}{{ N }}.corp{{ X }}.un {{ name_prefix }}{{ N }}
# cat node/templates/resolv.conf.j2
search corp{{ X }}.un
nameserver 192.168.{{ X }}.1
nameserver 192.168.{{ X }}.2
# cat node/templates/interfaces.j2
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
        address {{ ansible_eth0.ipv4.address }}
        netmask 255.255.255.0
        gateway 192.168.{{ X }}.254
# ansible-playbook -f 5 nodes.yml

  ИЛИ

# ansible-playbook -f 5 conf/ansible/roles/nodes.yml

Роль OpenVPN сервера

server:~# mkdir openvpn1 && cd openvpn1

server:~/openvpn1# ansible-galaxy init openvpn1

server:~/openvpn1# cd openvpn1/files/

server:~/openvpn1/openvpn1/files#
server:~/openvpn1/openvpn1/files# ls
dh2048.pem  server.crt  server.key
server:~/openvpn1# cat openvpn1/templates/openvpn1.conf.j2
dev tun
keepalive 10 120

server {{node_nets[ansible_hostname]}} 255.255.255.0

push "route 192.168.X.0 255.255.255.0"
status /var/log/openvpn1-status.log
dh /etc/openvpn/dh2048.pem
key /etc/ssl/private/server.key
ca /etc/ssl/certs/server.crt
cert /etc/ssl/certs/server.crt
plugin /usr/lib/x86_64-linux-gnu/openvpn/plugins/openvpn-plugin-auth-pam.so login
verify-client-cert none
username-as-common-name

#management 0.0.0.0 7505
server:~/openvpn1# cat openvpn1/tasks/main.yml
- name: Install OpenVPN
  apt: pkg=openvpn state=present update_cache=true
#  when: node_nets[ansible_hostname] is defined

- name: Create openvpn1.conf file
  template: src=openvpn1.conf.j2 dest=/etc/openvpn/openvpn1.conf
  notify:
    - restart openvpn1

- name: Copy file server.key
  copy:
    src: server.key
    dest: /etc/ssl/private/server.key
    mode: '0600'
  notify:
    - restart openvpn1

- name: Copy many files
  copy:
    src: '{{item.0}}'
    dest: '{{item.1}}'
  loop:
    - [ 'dh2048.pem', '/etc/openvpn/dh2048.pem' ]
    - [ 'server.crt', '/etc/ssl/certs/server.crt' ]
  notify:
    - restart openvpn1

- name: Enable service OpenVPN
  service:
    name: openvpn@openvpn1
    enabled: yes
    state: started
server:~/openvpn1# cat openvpn1/handlers/main.yml
- name: restart openvpn1
  service:
    name: openvpn@openvpn1
    state: restarted
server:~/openvpn1# cat inventory.yaml
all:
  vars:
    ansible_python_interpreter: "/usr/bin/python3"
    ansible_ssh_user: vagrant
    ansible_ssh_pass: vagrant
    ansible_become: yes
    node_nets:
      node1: 192.168.110.0
      node2: 192.168.120.0
      node3: 192.168.130.0

prod_nodes:
  hosts:
    node1:
    node2:

test_nodes:
  hosts:
    node3:
server:~/openvpn1# cat openvpn1.yaml
- name: Run openvpn1 on nodes
  hosts: "{{ variable_host | default('prod_nodes') }}"
  roles:
    - role: openvpn1
      when: node_nets[ansible_hostname] is defined
server:~/openvpn1# ansible-playbook openvpn1.yaml -i inventory.yaml -e "variable_host=test_nodes"

server:~/openvpn1# ansible-playbook openvpn1.yaml -i inventory.yaml

Фрагмент роли с условиями и отладкой

# cat conf/ansible/roles/host/vars/main.yml
...
octet4: "{{ ansible_eth0.ipv4.address.split('.')[3] }}"
...
# cat conf/ansible/roles/host/tasks/main.yml
- name: set vars for server
  set_fact:
    hostname: "mail"
    X: "{{ octet4 | int - 100 }}"
  when: octet4 | int >= 100

- name: set vars for mail
  set_fact:
    hostname: "server"
    X: "{{ octet4 }}"
  when: octet4 | int < 100

- name: echo variables
  debug:
    msg: octet4 is {{ octet4 }}, X is {{ X }}, hostname is {{hostname}}
...

Дополнительные материалы

выполнение команд на цисках через ансибл

1. добавить в /etc/ansible/group_vars/all.yml строки
ansible_connection: network_cli
ansible_network_os: ios
2. создать файл playbook формата
- name: Run show commands on routers
  hosts: cisco-routers

  tasks:

    - name: run show commands
      ios_command:
        commands: # перечисление команд
          - show ip int br
          - sh ip route
      register: show_result
сервис_ansible.1659005549.txt.gz · Last modified: 2022/07/28 13:52 by val