ansible技巧——使用ansible修改网络

ansible技巧——使用ansible修改网络

ansible是现在使用最广泛的的自动化运维工具之一,它有着强大的能力以及丰富的特性。不过并非在所有方面它都能面面俱到,在修改网络方面,ansible所能获取的资料甚少,而在问答社区中更是有人回答ansible适合在平稳的网络条件下运行,不适合用来修改网络。那么,如果我真的需要为某些节点修改网络ip,怎么才能办到呢?接下来本篇文章介绍一些可行的办法。

问题还原

如下是一个简单的playbook,负责将新的ip写入到配置文件中,随后清空ip并重启network服务。

# playbooks/test.yml
- hosts: nodes[0]
  gather_facts: false
  tasks:
  - name: Apply new network
    shell: |
      cat > /etc/sysconfig/network-scripts/ifcfg-{{ device }} << EOF
      DEVICE={{ device }}
      TYPE=Ethernet
      ONBOOT=yes
      BOOTPROTO=static
      IPADDR={{ ipaddr }}
      GATEWAY={{ gateway }}
      NETMASK={{ netmask }}
      EOF
      ip address flush scope global
      systemctl restart network

这个playbook乍一看没有什么问题, 但执行的时候却会发现进程一直卡在修改网络的步骤,直到ssh超时(约半小时)。

# ansible-playbook -i inventory/hosts.ini playbooks/test.yml -e device=eth0 -e ipaddr=192.168.0.10 -e gateway=192.168.0.254 -e netmask=255.255.255.0

PLAY [nodes[0]] ****************************************************************************************

TASK [Apply new network] *******************************************************************************
# hang on...

这是由于ssh远程执行命令的中途网络发生变化所导致的,ansible使用ssh连接各个托管节点,倘若ssh连接中途网络环境发生变化,那么ssh命令的执行就会一直卡住,等待托管节点返回响应,虽然这个响应可能永远也等不到了。

解决方法

一个显而易见的方法是,既然ansible内置的ssh方法是同步连接,那么不用ansible连接托管节点,改为自己手动异步ssh不就好了么?如下所示,临时将task运行的节点通过delegate_to修改为控制节点自身,随后使用ssh执行命令。异步的方法有两种,一个是通过nohup的方式,另一个是给ssh加上-f参数,这两种方式均能试ssh转入后台运行。

- name: Apply new network
  shell: |
    # nohup ssh -p{{ ansible_ssh_port|default(55555) }} {{ item }} 'ip address flush scope global && systemctl restart network' &
    ssh -f -p{{ ansible_ssh_port|default(55555) }} {{ item }} 'ip address flush scope global && systemctl restart network'
  loop: "{{ groups.nodes|reject('eq', groups.nodes.0) }}"
  delegate_to: localhost

也可以使用ansible自身的异步特性做到这一点,ansible提供了async和poll两个关键词,当poll的值为0时,可以将一个task转入后台执行(poll值非0时用以设置一个任务的执行超时时间,和异步没有关系)。如下所示,该task也能正常的修改托管节点的网络,且实现较为优雅。

- name: Apply new network
  shell: |
    ip address flush scope global
    systemctl restart network
  async: 60
  poll: 0

综合案例

接下来介绍一个ansible网络修改的综合案例。假设现在要部署一个三节点k8s集群,其中每个节点都包含管理外网和管理内网两个ip地址,在通过管理外网pxe安装操作系统之后,ansible会为每个节点配置管理内网的ip,但仅为master1节点配置管理外网,其余节点均不再需要管理外网的ip,为之后部署k8s服务做准备。

现在需要写一份playbook,通过管理外网ip连接到三个节点上,应用新的网络配置文件并重启网络,playbook目录结构如下:

# tree
.
├── inventory
│   ├── group_vars
│   │   └── all.yml
│   ├── hosts.ini
│   └── host_vars
│       ├── 1.1.1.1.yml
│       ├── 2.2.2.2.yml
│       └── 3.3.3.3.yml
└── playbooks
    ├── roles
    │   └── test
    │       ├── tasks
    │       │   └── main.yml
    │       └── templates
    │           ├── ifcfg_mgm_ex.j2
    │           └── ifcfg_mgm_in.j2
    └── setup.yml

8 directories, 9 files

inventory/hosts.ini文件记录被控节点的清单:

localhost
# BEGIN NODES BLOCK
[nodes]
1.1.1.1 ansible_ssh_port=22
2.2.2.2 ansible_ssh_port=22
3.3.3.3 ansible_ssh_port=22
# END NODES BLOCK

playbook/setup.yml文件描述在nodes主机组中运行test role:

---
- hosts: nodes
  gather_facts: false
  roles:
  - { role: test }

playbooks/roles/test/tasks/main.yml文件:

- name: prepare_network | delete all /etc/sysconfig/network-scripts/ifcfg-* file
  shell: rm -rf /etc/sysconfig/network-scripts/ifcfg-*

- name: prepare_network | template management internal interface to /etc/sysconfig/network-scripts
  vars:
    device: "{{ ifaceRoles.mgm }}"
    ipaddr: "{{ intMgmIpaddr }}"
  template:
    src: ifcfg_mgm_in.j2
    dest: /etc/sysconfig/network-scripts/ifcfg-{{ device }}

- name: prepare_network | template management external interface to /etc/sysconfig/network-scripts
  vars:
    device: "{{ ifaceRoles.ext }}"
    ipaddr: "{{ extMgmIpaddr }}"
  template:
    src: ifcfg_mgm_ex.j2
    dest: /etc/sysconfig/network-scripts/ifcfg-{{ device }}
  when: inventory_hostname == groups.nodes.0

- name: prepare_network | restart network service on nodes, synchronous on master1 and asynchronous on the other nodes
  shell: |
    ip address flush scope global
    systemctl restart network
  async: 60
  poll: "{{ inventory_hostname == groups.nodes.0 and 3 or 0 }}"

- name: prepare_network | later tasks
  debug:
    msg: "Later tasks can't run on nodes except master1 on account of no network connectivity."

管理外网和管理内网网卡配置文件的模板:

# playbooks/roles/test/templates/ifcfg_mgm_ex.j2
DEVICE={{ device }}
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=static
IPADDR={{ ipaddr }}
GATEWAY={{ gateway }}
NETMASK={{ netMask }}

# playbooks/roles/test/templates/ifcfg_mgm_in.j2
DEVICE={{ device }}
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=static
IPADDR={{ ipaddr }}
GATEWAY=
NETMASK={{ netMask }}

小结

综上,使用ansible修改网络并不是一件推荐的事,不过依然有办法能做到这一点。除此之外,网络ip的变化意味着ansible控制节点无法继续访问被控节点,如果在修改ip后依然需要访问被控节点,ansible提供了add_host模块用以动态添加被控节点,这样便能够继续访问。

posted @ 2023-04-19 11:55  frankming  阅读(513)  评论(0编辑  收藏  举报