Factor frr role from debian, ceph and proxmox
Consolidate base system and networking setup into debian role and BGP configuration into frr role. Add facts role to collect data from NetBox once to avoid many slow lookups. Also many other tweaks and cleanups.
This commit is contained in:
parent
256dae2955
commit
25bcddede1
31 changed files with 167 additions and 312 deletions
|
@ -1,16 +0,0 @@
|
|||
[Unit]
|
||||
Description=OpenBSD Secure Shell server (management VRF)
|
||||
After=network.target auditd.service
|
||||
|
||||
[Service]
|
||||
ExecStartPre=/usr/sbin/sshd -t
|
||||
ExecStart=ip vrf exec mgmt /usr/sbin/sshd -f /etc/ssh/sshd_config.mgmt
|
||||
ExecReload=/usr/sbin/sshd -t
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
KillMode=process
|
||||
Restart=on-failure
|
||||
RestartPreventExitStatus=255
|
||||
Type=notify
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1,15 +0,0 @@
|
|||
# This is for sshd in management VRF, for ansible and other not-really-OOB stuff.
|
||||
|
||||
PidFile none
|
||||
UsePAM no
|
||||
Subsystem sftp /usr/lib/openssh/sftp-server
|
||||
|
||||
# Only allow pubkey auth.
|
||||
KbdInteractiveAuthentication no
|
||||
PasswordAuthentication no
|
||||
PermitRootLogin prohibit-password
|
||||
|
||||
# Disable what we can.
|
||||
AllowTcpForwarding no
|
||||
GatewayPorts no
|
||||
X11Forwarding no
|
|
@ -1,8 +1,3 @@
|
|||
- name: reboot
|
||||
reboot:
|
||||
|
||||
- name: reload interfaces
|
||||
command: ifreload -a
|
||||
|
||||
- name: reload frr
|
||||
command: /usr/lib/frr/frr-reload.py --reload /etc/frr/frr.conf
|
||||
when: "'handler' not in ansible_skip_tags"
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
mode: 0640
|
||||
owner: root
|
||||
group: www-data
|
||||
when: inventory_hostname == primary
|
||||
when: is_primary
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
- name: Install FRR
|
||||
package:
|
||||
name: frr
|
||||
|
||||
- name: Configure FRR
|
||||
template:
|
||||
dest: /etc/frr/frr.conf
|
||||
src: frr.conf.j2
|
||||
mode: 0644
|
||||
notify: reload frr
|
||||
|
||||
- name: Set datacenter defaults for FRR
|
||||
lineinfile:
|
||||
path: /etc/frr/daemons
|
||||
line: 'frr_profile="datacenter"'
|
||||
regexp: '#?frr_profile="datacenter"'
|
||||
|
||||
- name: Enable FRR
|
||||
service:
|
||||
name: frr
|
||||
enabled: yes
|
||||
state: started
|
|
@ -1,11 +1,7 @@
|
|||
- name: Get all nodes in my cluster
|
||||
set_fact:
|
||||
nodes: "{{ groups['cluster_'+cluster] | map('extract', hostvars) }}"
|
||||
|
||||
# choose a node for tasks that should only run on (any) one node, e.g. when writing to /etc/pve
|
||||
- name: Select primary node
|
||||
- name: Select the primary node
|
||||
set_fact:
|
||||
primary: '{{ nodes | map(attribute="inventory_hostname") | sort | first }}'
|
||||
is_primary: '{{ inventory_hostname == (nodes | map(attribute="inventory_hostname") | sort | first) }}'
|
||||
|
||||
- name: Disable enterprise repositories
|
||||
apt_repository:
|
||||
|
@ -22,27 +18,15 @@
|
|||
apt_repository:
|
||||
repo: 'deb http://download.proxmox.com/debian/pve {{ ansible_distribution_release }} pve-no-subscription'
|
||||
|
||||
- name: Set hostname
|
||||
hostname:
|
||||
name: '{{ inventory_hostname }}'
|
||||
|
||||
- name: Add rules to rename network interfaces
|
||||
template:
|
||||
dest: /etc/udev/rules.d/10-network.rules
|
||||
src: 10-network.rules.j2
|
||||
mode: 0644
|
||||
notify: reboot
|
||||
|
||||
- name: Set up sysctls
|
||||
copy:
|
||||
dest: /etc/sysctl.d/local.conf
|
||||
src: sysctl.conf
|
||||
|
||||
- name: Set up interfaces
|
||||
- name: Set VXLAN local tunnel IP
|
||||
template:
|
||||
dest: /etc/network/interfaces.d/real.intf
|
||||
src: real.intf.j2
|
||||
mode: 0644
|
||||
dest: /etc/network/interfaces.d/loopback.intf
|
||||
src: loopback.intf.j2
|
||||
notify: reload interfaces
|
||||
|
||||
- name: Set up bridges
|
||||
|
@ -52,10 +36,6 @@
|
|||
mode: 0644
|
||||
notify: reload interfaces
|
||||
|
||||
- include_tasks: mgmt.yml
|
||||
|
||||
- include_tasks: firewall.yml
|
||||
|
||||
- include_tasks: frr.yml
|
||||
|
||||
- include_tasks: user.yml
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
# We could probably avoid rebooting in some cases, but those should never happen
|
||||
# in normal operation anyway. This way all setup is done before rebooting once.
|
||||
|
||||
- name: Configure SSH instance in management VRF
|
||||
copy:
|
||||
dest: /etc/ssh/
|
||||
src: sshd_config.mgmt
|
||||
mode: 0644
|
||||
notify: reboot
|
||||
|
||||
- name: Set up a SSH instance in management VRF
|
||||
copy:
|
||||
dest: /etc/systemd/system/
|
||||
src: sshd@mgmt.service
|
||||
mode: 0644
|
||||
notify: reboot
|
||||
|
||||
- name: Enable management SSH
|
||||
service:
|
||||
name: sshd@mgmt
|
||||
enabled: yes
|
||||
notify: reboot
|
||||
|
||||
- meta: flush_handlers
|
|
@ -1,17 +1,19 @@
|
|||
# synchronize user and group data from LDAP when sync-ldap context key is set to a realm
|
||||
- block:
|
||||
- name: Set up LDAP user synchronization
|
||||
when: '"sync-ldap" in hostvars[inventory_hostname]'
|
||||
block:
|
||||
- name: Install LDAP sync script
|
||||
template:
|
||||
dest: /usr/local/bin/sync-ldap.py
|
||||
src: sync-ldap.py.j2
|
||||
mode: 0700
|
||||
when: primary == inventory_hostname
|
||||
when: is_primary
|
||||
|
||||
- name: Remove LDAP sync script
|
||||
file:
|
||||
path: /usr/local/bin/sync-ldap.py
|
||||
state: absent
|
||||
when: primary != inventory_hostname
|
||||
when: not is_primary
|
||||
|
||||
- name: Configure cronjob
|
||||
cron:
|
||||
|
@ -21,5 +23,4 @@
|
|||
cron_file: sync-ldap
|
||||
hour: "2"
|
||||
minute: "51"
|
||||
state: '{{ "present" if inventory_hostname == primary else "absent" }}'
|
||||
when: '"sync-ldap" in hostvars[inventory_hostname]'
|
||||
state: '{{ "present" if is_primary else "absent" }}'
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
{% set services = query('netbox.netbox.nb_lookup', 'clusters', raw_data=true, api_filter='name='+cluster)
|
||||
| map(attribute='custom_fields.services') | flatten -%}
|
||||
[OPTIONS]
|
||||
|
||||
enable: 1
|
||||
|
@ -10,7 +8,7 @@ IN Ping(ACCEPT) -log nolog # don’t be rude
|
|||
IN SSH(ACCEPT) -i mgmt # for ansible etc.
|
||||
IN ACCEPT -source {{ nodes | map('device_address') | flatten | selectattr('family.value', '==', 4) | map(attribute='address') | join(',') }} # my cluster
|
||||
IN ACCEPT -source {{ nodes | map('device_address') | flatten | selectattr('family.value', '==', 6) | map(attribute='address') | join(',') }} # my cluster
|
||||
{% for service in services %}
|
||||
{% for service in cluster.custom_fields.services %}
|
||||
{% set prefixes = service | allowed_prefixes %}
|
||||
{% set prefixes4 = prefixes | selectattr('family.value', '==', 4) | map('string') %}
|
||||
{% set prefixes6 = prefixes | selectattr('family.value', '==', 6) | map('string') %}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
frr defaults datacenter
|
||||
service integrated-vtysh-config
|
||||
log syslog
|
||||
|
||||
# We only have the default route, so allow talking to BGP peers over it.
|
||||
ip nht resolve-via-default
|
||||
|
||||
router bgp {{ asn.asn }}
|
||||
bgp bestpath as-path multipath-relax
|
||||
|
||||
neighbor fabric peer-group
|
||||
neighbor fabric remote-as external
|
||||
neighbor fabric capability extended-nexthop
|
||||
|
||||
{% for iface in interfaces | rejectattr('name', '==', 'lo') | rejectattr('mgmt_only') | rejectattr('vrf') %}
|
||||
neighbor {{ iface.name }} interface peer-group fabric
|
||||
neighbor {{ iface.name }} bfd
|
||||
{% endfor %}
|
||||
|
||||
address-family ipv4 unicast
|
||||
redistribute connected route-map loopback
|
||||
neighbor fabric activate
|
||||
neighbor fabric route-map local out
|
||||
exit-address-family
|
||||
|
||||
address-family ipv6 unicast
|
||||
redistribute connected route-map loopback
|
||||
neighbor fabric activate
|
||||
neighbor fabric route-map local out
|
||||
exit-address-family
|
||||
|
||||
address-family l2vpn evpn
|
||||
neighbor fabric activate
|
||||
neighbor fabric route-map local out
|
||||
advertise-all-vni
|
||||
exit-address-family
|
||||
|
||||
bgp as-path access-list local permit ^$
|
||||
|
||||
route-map loopback permit 1
|
||||
match interface lo
|
||||
|
||||
route-map local permit 1
|
||||
match as-path local
|
|
@ -1,8 +1,6 @@
|
|||
{% set my_cluster = query('netbox.netbox.nb_lookup', 'clusters', raw_data=true,
|
||||
api_filter='name='~cluster) | first -%}
|
||||
|
||||
# bridges must be named vmbrN for proxmox to care
|
||||
{% for vlan in my_cluster.custom_fields.vlans | default([], true) | sort(attribute='vid') %}
|
||||
{# bridges must be named vmbrN for proxmox to care #}
|
||||
{% for vlan in cluster.custom_fields.vlans | default([], true) | sort(attribute='vid') %}
|
||||
# bridge and VNI for {{ vlan.name }}
|
||||
auto vmbr{{ vlan.vid }}
|
||||
iface vmbr{{ vlan.vid }}
|
||||
# {{ vlan.name }}
|
||||
|
|
7
roles/proxmox/templates/loopback.intf.j2
Normal file
7
roles/proxmox/templates/loopback.intf.j2
Normal file
|
@ -0,0 +1,7 @@
|
|||
{% set lo = hostvars[inventory_hostname].interfaces | selectattr('name', '==', 'lo') | first %}
|
||||
{% set vxlan_ip = lo.ip_addresses | selectattr('family.value', '==', 4)
|
||||
| map(attribute='address') | first
|
||||
| ipaddr('address') %}
|
||||
iface lo
|
||||
# without this the local tunnel IP is sometimes advertised as 0.0.0.0 on boot
|
||||
vxlan-local-tunnelip {{ vxlan_ip }}
|
|
@ -1,27 +0,0 @@
|
|||
# Management VRF.
|
||||
auto mgmt
|
||||
iface mgmt
|
||||
address 127.0.0.1/8
|
||||
address ::1/128
|
||||
vrf-table auto
|
||||
|
||||
{% for iface in interfaces | rejectattr('mgmt_only') %}
|
||||
auto {{ iface.name }}
|
||||
iface {{ iface.name }} inet {% if iface.name == 'lo' %}loopback{% else %}static{% endif +%}
|
||||
{% if iface.mtu %}
|
||||
mtu {{ iface.mtu }}
|
||||
{% endif %}
|
||||
{% if iface.vrf %}
|
||||
vrf {{ iface.vrf.name }}
|
||||
{% endif %}
|
||||
{% for ip in iface.ip_addresses %}
|
||||
address {{ ip.address }}
|
||||
{% endfor %}
|
||||
{% if iface.custom_fields.gateway %}
|
||||
gateway {{ iface.custom_fields.gateway.address | ipaddr('address') }}
|
||||
{% endif %}
|
||||
{% if iface.name == 'lo' %}
|
||||
vxlan-local-tunnelip {{ iface.ip_addresses | selectattr('family.value', '==', 4) | map(attribute='address') | sort | first | ipaddr('address') }}
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
|
@ -6,7 +6,7 @@ import re
|
|||
|
||||
import ldap3
|
||||
|
||||
{% set password = lookup('passwordstore', "cluster/"+cluster, returnall=true) | from_yaml %}
|
||||
{% set password = lookup('passwordstore', "cluster/"+cluster.name, returnall=true) | from_yaml %}
|
||||
realm = '{{ hostvars[inventory_hostname]["sync-ldap"] }}'
|
||||
ldap_host = '{{ domain }}'
|
||||
ldap_user = '{{ password.ldap_user }}'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue