When working with CentOS 7, we encounter several architectural changes from previous versions that impact network configuration:
- NetworkManager as the default network configuration daemon
- Consistent network device naming via udev
- Systemd integration replacing traditional init scripts
The most maintainable method is to use Ansible's template
module to manage interface configuration files while keeping NetworkManager operational. Here's why:
- Maintains consistency with CentOS 7's default architecture
- Allows for both GUI and CLI management when needed
- Provides better integration with modern networking features
Here's a complete Ansible playbook example that configures a static IP address:
---
- name: Configure static network interface
hosts: centos_servers
become: yes
vars:
interface_name: "{{ ansible_default_ipv4.interface }}"
static_ip: 192.168.1.100
netmask: 255.255.255.0
gateway: 192.168.1.1
dns_servers:
- 8.8.8.8
- 8.8.4.4
tasks:
- name: Create interface configuration file
template:
src: templates/ifcfg-static.j2
dest: /etc/sysconfig/network-scripts/ifcfg-{{ interface_name }}
owner: root
group: root
mode: 0644
notify: restart network
- name: Ensure NetworkManager is running
service:
name: NetworkManager
state: started
enabled: yes
handlers:
- name: restart network
service:
name: network
state: restarted
Create this Jinja2 template at templates/ifcfg-static.j2
:
DEVICE={{ interface_name }}
BOOTPROTO=static
IPADDR={{ static_ip }}
NETMASK={{ netmask }}
GATEWAY={{ gateway }}
DNS1={{ dns_servers[0] }}
DNS2={{ dns_servers[1] }}
ONBOOT=yes
NM_CONTROLLED=yes
TYPE=Ethernet
For environments where you prefer direct NetworkManager control:
- name: Configure static IP via nmcli
command: |
nmcli con add con-name static-{{ interface_name }} ifname {{ interface_name }} type ethernet \
ip4 {{ static_ip }}/{{ netmask|replace('255.255.255.','') }} gw4 {{ gateway }}
args:
creates: /etc/sysconfig/network-scripts/ifcfg-static-{{ interface_name }}
For servers with multiple NICs, extend the playbook with interface-specific variables:
vars:
network_interfaces:
- name: enp0s3
ip: 192.168.1.100
gateway: 192.168.1.1
- name: enp0s8
ip: 10.0.0.100
gateway: 10.0.0.1
Modern CentOS 7 systems present unique challenges for network configuration compared to their RHEL 6 predecessors. With NetworkManager enabled by default and predictable network interface naming, traditional approaches to static IP assignment need reconsideration. The key components affecting our configuration approach include:
- NetworkManager service (default enabled)
- systemd-networkd (alternative)
- Consistent device naming (enpXsY format)
- ifcfg files legacy location (/etc/sysconfig/network-scripts/)
Ansible offers several approaches to handle network configuration on CentOS 7:
# Main modules to consider:
- nmcli (for NetworkManager configurations)
- template (for ifcfg file generation)
- ini_file (for direct file modifications)
- lineinfile (for quick edits)
- systemd (for service management)
Here's a complete Ansible playbook example that handles static IP configuration while maintaining compatibility with NetworkManager:
- name: Configure static network interface
hosts: centos_servers
become: yes
vars:
interface_name: "{{ ansible_default_ipv4.interface }}"
static_ip: 192.168.1.100
netmask: 255.255.255.0
gateway: 192.168.1.1
dns_servers:
- 8.8.8.8
- 8.8.4.4
tasks:
- name: Ensure NetworkManager is running
service:
name: NetworkManager
state: started
enabled: yes
- name: Create static connection profile
nmcli:
conn_name: "static-{{ interface_name }}"
ifname: "{{ interface_name }}"
type: ethernet
ip4: "{{ static_ip }}/24"
gw4: "{{ gateway }}"
dns4: "{{ dns_servers | join(',') }}"
state: present
- name: Set the connection as default
nmcli:
conn_name: "static-{{ interface_name }}"
autoconnect: yes
state: up
For environments where NetworkManager is not desired, here's how to implement static configuration via ifcfg files:
- name: Configure network using ifcfg files
template:
src: templates/ifcfg-eth0.j2
dest: /etc/sysconfig/network-scripts/ifcfg-{{ interface_name }}
owner: root
group: root
mode: 0644
notify: restart network
- name: Ensure NetworkManager is disabled
service:
name: NetworkManager
state: stopped
enabled: no
- name: Ensure network service is enabled
service:
name: network
state: started
enabled: yes
handlers:
- name: restart network
service:
name: network
state: restarted
DEVICE={{ interface_name }}
BOOTPROTO=static
IPADDR={{ static_ip }}
NETMASK={{ netmask }}
GATEWAY={{ gateway }}
DNS1={{ dns_servers[0] }}
DNS2={{ dns_servers[1] }}
ONBOOT=yes
TYPE=Ethernet
Always include validation steps in your playbook:
- name: Verify network configuration
assert:
that:
- ansible_default_ipv4.address == static_ip
- ansible_default_ipv4.gateway == gateway
success_msg: "Network configuration verified successfully"
fail_msg: "Network configuration verification failed"
- Always test network changes in a staging environment first
- Consider using host_vars for interface-specific configurations
- Implement proper error handling for network changes
- Document all network configuration standards
- Use ansible_facts to make playbooks more dynamic