Commit 3e3f43b2 authored by Piotr Szlenk's avatar Piotr Szlenk

Initial working version

parent 5123adc5
.vagrant
cumulus-ip-fabric/VENV
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
# IP Fabric
config.vm.define("spine1") do |spine1|
spine1.vm.box = "CumulusCommunity/cumulus-vx"
spine1.vm.box_version = "3.7.3"
spine1.vm.network("forwarded_port", guest: 22, host: 2022, id: 'ssh', auto_correct: false)
# Fabric links (swp1 - swp4)
spine1.vm.network("private_network", virtualbox__intnet: "SPINE1_LEAF1", cumulus__intname: 'swp1', nic_type: "virtio", auto_config: false)
spine1.vm.network("private_network", virtualbox__intnet: "SPINE1_LEAF2", cumulus__intname: 'swp2', nic_type: "virtio", auto_config: false)
spine1.vm.network("private_network", virtualbox__intnet: "SPINE1_LEAF3", cumulus__intname: 'swp3', nic_type: "virtio", auto_config: false)
spine1.vm.network("private_network", virtualbox__intnet: "SPINE1_LEAF4", cumulus__intname: 'swp4', nic_type: "virtio", auto_config: false)
end
config.vm.define("spine2") do |spine2|
spine2.vm.box = "CumulusCommunity/cumulus-vx"
spine2.vm.box_version = "3.7.3"
spine2.vm.network("forwarded_port", guest: 22, host: 2023, id: 'ssh', auto_correct: false)
spine2.vm.network("private_network", virtualbox__intnet: "SPINE2_LEAF1", cumulus__intname: 'swp1', nic_type: "virtio", auto_config: false)
spine2.vm.network("private_network", virtualbox__intnet: "SPINE2_LEAF2", cumulus__intname: 'swp2', nic_type: "virtio", auto_config: false)
spine2.vm.network("private_network", virtualbox__intnet: "SPINE2_LEAF3", cumulus__intname: 'swp3', nic_type: "virtio", auto_config: false)
spine2.vm.network("private_network", virtualbox__intnet: "SPINE2_LEAF4", cumulus__intname: 'swp4', nic_type: "virtio", auto_config: false)
end
config.vm.define("leaf1") do |leaf1|
leaf1.vm.box = "CumulusCommunity/cumulus-vx"
leaf1.vm.box_version = "3.7.3"
leaf1.vm.network("forwarded_port", guest: 22, host: 2024, id: 'ssh', auto_correct: false)
leaf1.vm.network("private_network", virtualbox__intnet: "SPINE1_LEAF1", cumulus__intname: 'swp1', nic_type: "virtio", auto_config: false)
leaf1.vm.network("private_network", virtualbox__intnet: "SPINE2_LEAF1", cumulus__intname: 'swp2', nic_type: "virtio", auto_config: false)
leaf1.vm.network("private_network", virtualbox__intnet: "LEAF1_K8S_MASTER", cumulus__intname: 'swp3', nic_type: "virtio", auto_config: false)
leaf1.vm.network("private_network", virtualbox__intnet: "LEAF1_K8S_NODE1", cumulus__intname: 'swp4', nic_type: "virtio", auto_config: false)
end
config.vm.define("leaf2") do |leaf2|
leaf2.vm.box = "CumulusCommunity/cumulus-vx"
leaf2.vm.box_version = "3.7.3"
leaf2.vm.network("forwarded_port", guest: 22, host: 2025, id: 'ssh', auto_correct: false)
leaf2.vm.network("private_network", virtualbox__intnet: "SPINE1_LEAF2", cumulus__intname: 'swp1', nic_type: "virtio", auto_config: false)
leaf2.vm.network("private_network", virtualbox__intnet: "SPINE2_LEAF2", cumulus__intname: 'swp2', nic_type: "virtio", auto_config: false)
leaf2.vm.network("private_network", virtualbox__intnet: "LEAF2_K8S_NODE2", cumulus__intname: 'swp3', nic_type: "virtio", auto_config: false)
end
# Kubernetes
config.vm.define("k8s-master") do |k8smaster|
k8smaster.vm.box = "centos/7"
k8smaster.vm.hostname = "k8s-master"
k8smaster.vm.network("forwarded_port", guest: 22, host: 3001, id: 'ssh', auto_correct: false)
k8smaster.vm.network("private_network", virtualbox__intnet: "LEAF1_K8S_MASTER", nic_type: "virtio")
k8smaster.vm.provider "virtualbox" do |vb|
vb.cpus = 4
end
end
config.vm.define("k8s-node-1") do |k8snode1|
k8snode1.vm.box = "centos/7"
k8snode1.vm.hostname = "k8s-node-1"
k8snode1.vm.network("forwarded_port", guest: 22, host: 3002, id: 'ssh', auto_correct: false)
k8snode1.vm.network("private_network", virtualbox__intnet: "LEAF1_K8S_NODE1", nic_type: "virtio")
end
config.vm.define("k8s-node-2") do |k8snode2|
k8snode2.vm.box = "centos/7"
k8snode2.vm.hostname = "k8s-node-2"
k8snode2.vm.network("forwarded_port", guest: 22, host: 3003, id: 'ssh', auto_correct: false)
k8snode2.vm.network("private_network", virtualbox__intnet: "LEAF2_K8S_NODE2", nic_type: "virtio")
end
end
## Intro
This playbook builds an IP Fabric based on VX Cumulus. All the configuration should be stored in config/globals.yml
## Getting started
* VX Cumulus Virtualbox image: https://drive.google.com/drive/folders/1XxS0qn4oU3SXQUo955IZo_X0DwZ8CcwI?usp=sharing
* Ansible module: https://docs.ansible.com/ansible/2.7/modules/nclu_module.html#nclu-module
[defaults]
host_key_checking=False
stdout_callback = yaml
\ No newline at end of file
Vagrant.configure("2") do |config|
config.vm.box = "CumulusCommunity/cumulus-vx"
end
\ No newline at end of file
underlay_protocol: ospf
enable_mgmt_vrf: yes
ntpservers:
- 1.1.1.1
- 2.2.2.2
routes:
- target: 0.0.0.0/0
next-hop: 10.0.0.1
---
upstream_interfaces: ["swp1","swp2"]
---
downstream_interfaces: ["swp1","swp2"]
routerid: 172.16.255.101
hostname: leaf-sw1.lab.local
loopbacks:
- name: lo
ipv4: 172.16.255.101/32
ospf_area: 0.0.0.0
interfaces:
- name: swp1
ipv4: 172.16.0.1/31
ospf_area: 0.0.0.0
ospf_net_type: point-to-point
- name: swp2
ipv4: 172.16.1.1/31
ospf_area: 0.0.0.0
ospf_net_type: point-to-point
bridges:
- name: VLAN10
ipv4: 10.255.1.1/24
ospf_area: 0.0.0.10
ospf_passive: true
ports:
- swp3
- swp4
bgp:
as: 65101
routerid: 172.16.255.101
ipv4_unicast_peers:
- peer_ip: 172.16.255.1
peer_as: 65001
local_ip: 172.16.255.101
multihop: true
- peer_ip: 172.16.255.2
peer_as: 65002
local_ip: 172.16.255.101
multihop: true
ipv4_unicast_peer_groups:
- group_name: K8S-NODES
group_as: 65101
group_range: 10.255.1.0/24
\ No newline at end of file
routerid: 172.16.255.102
hostname: leaf-sw2.lab.local
loopbacks:
- name: lo
ipv4: 172.16.255.102/32
ospf_area: 0.0.0.0
interfaces:
- name: swp1
ipv4: 172.16.0.3/31
ospf_area: 0.0.0.0
ospf_net_type: point-to-point
- name: swp2
ipv4: 172.16.1.3/31
ospf_area: 0.0.0.0
ospf_net_type: point-to-point
bridges:
- name: VLAN10
ipv4: 10.255.2.1/24
ospf_area: 0.0.0.20
ospf_passive: true
ports:
- swp3
bgp:
as: 65102
routerid: 172.16.255.102
ipv4_unicast_peers:
- peer_ip: 172.16.255.1
peer_as: 65001
local_ip: 172.16.255.102
multihop: true
- peer_ip: 172.16.255.2
peer_as: 65002
local_ip: 172.16.255.102
multihop: true
ipv4_unicast_peer_groups:
- group_name: K8S-NODES
group_as: 65102
group_range: 10.255.2.0/24
\ No newline at end of file
routerid: 172.16.255.1
hostname: spine-sw1.lab.local
loopbacks:
- name: lo
ipv4: 172.16.255.1/32
ospf_area: 0.0.0.0
interfaces:
- name: swp1
ipv4: 172.16.0.0/31
ospf_area: 0.0.0.0
ospf_net_type: point-to-point
- name: swp2
ipv4: 172.16.0.2/31
ospf_area: 0.0.0.0
ospf_net_type: point-to-point
bgp:
as: 65001
routerid: 172.16.255.1
ipv4_unicast_peers:
- peer_ip: 172.16.255.101
peer_as: 65101
local_ip: 172.16.255.1
multihop: true
- peer_ip: 172.16.255.102
peer_as: 65102
local_ip: 172.16.255.1
multihop: true
routerid: 172.16.255.2
hostname: spine-sw2.lab.local
loopbacks:
- name: lo
ipv4: 172.16.255.2/32
ospf_area: 0.0.0.0
interfaces:
- name: swp1
ipv4: 172.16.1.0/31
ospf_area: 0.0.0.0
ospf_net_type: point-to-point
- name: swp2
ipv4: 172.16.1.2/31
ospf_area: 0.0.0.0
ospf_net_type: point-to-point
bgp:
as: 65002
routerid: 172.16.255.2
ipv4_unicast_peers:
- peer_ip: 172.16.255.101
peer_as: 65101
local_ip: 172.16.255.2
multihop: true
- peer_ip: 172.16.255.102
peer_as: 65102
local_ip: 172.16.255.2
multihop: true
[spine-switches]
spine-sw1 ansible_host=192.168.99.102 ansible_user=cumulus ansible_ssh_pass=CumulusLinux! ansible_become_pass=CumulusLinux!
spine-sw2 ansible_host=192.168.99.104 ansible_user=cumulus ansible_ssh_pass=CumulusLinux! ansible_become_pass=CumulusLinux!
[leaf-switches]
leaf-sw1 ansible_host=192.168.99.103 ansible_user=cumulus ansible_ssh_pass=CumulusLinux! ansible_become_pass=CumulusLinux!
leaf-sw2 ansible_host=192.168.99.105 ansible_user=cumulus ansible_ssh_pass=CumulusLinux! ansible_become_pass=CumulusLinux!
[ipfabric:children]
spine-switches
leaf-switches
\ No newline at end of file
[spine-switches]
spine-sw1 ansible_host=127.0.0.1 ansible_port=2022 ansible_user=cumulus ansible_ssh_pass=CumulusLinux! ansible_become_pass=CumulusLinux!
spine-sw2 ansible_host=127.0.0.1 ansible_port=2023 ansible_user=cumulus ansible_ssh_pass=CumulusLinux! ansible_become_pass=CumulusLinux!
[leaf-switches]
leaf-sw1 ansible_host=127.0.0.1 ansible_port=2024 ansible_user=cumulus ansible_ssh_pass=CumulusLinux! ansible_become_pass=CumulusLinux!
leaf-sw2 ansible_host=127.0.0.1 ansible_port=2025 ansible_user=cumulus ansible_ssh_pass=CumulusLinux! ansible_become_pass=CumulusLinux!
[ipfabric:children]
spine-switches
leaf-switches
\ No newline at end of file
ansible==2.7.8
asn1crypto==0.24.0
bcrypt==3.1.6
cffi==1.12.2
cryptography==2.6.1
enum34==1.1.6
ipaddr==2.2.0
ipaddress==1.0.22
Jinja2==2.10
MarkupSafe==1.1.1
netaddr==0.7.19
paramiko==2.4.2
pyasn1==0.4.5
pycparser==2.19
PyNaCl==1.3.0
PyYAML==3.13
six==1.12.0
- name: Set hostname
hostname:
name: '{{hostname}}'
notify: "Configuration was changed"
#- include_tasks: mgmt_vrf.yml
\ No newline at end of file
- name: Enable MGMT vrf
# @piotr.szlenk - when turning on mgmt vrf, Cumulus drops SSH connection which will mark this task as failed
retries: 2
delay: 5
nclu:
commands:
- add vrf mgmt
commit: true
notify: "Configuration was changed"
when: enable_mgmt_vrf
- name: Configure BGP
nclu:
template: |
add bgp autonomous-system {{bgp['as']}}
add bgp router-id {{bgp['routerid']}}
notify: "Configuration was changed"
\ No newline at end of file
- name: Configure BGP IPv4 unicast peers
nclu:
template: |
{% for peer in bgp['ipv4_unicast_peers'] %}
add bgp neighbor {{peer['peer_ip']}} remote-as {{peer['peer_as']}}
add bgp neighbor {{peer['peer_ip']}} update-source {{peer['local_ip']}}
add bgp ipv4 unicast neighbor {{peer['peer_ip']}} activate
{% if peer['multihop'] is defined and peer['multihop'] %}
add bgp neighbor {{peer['peer_ip']}} ebgp-multihop
{% endif %}
{% endfor %}
commit: false
notify: "Configuration was changed"
when: bgp['ipv4_unicast_peers'] is defined
- name: Configure BGP IPv4 unicast peers
nclu:
template: |
{% for group in bgp['ipv4_unicast_peer_groups'] %}
add bgp neighbor {{group['group_name']}} peer-group
add bgp listen range {{group['group_range']}} peer-group {{group['group_name']}}
add bgp neighbor {{group['group_name']}} remote-as {{group['group_as']}}
add bgp ipv4 unicast neighbor {{group['group_name']}} activate
{% if group['multihop'] is defined and group['multihop'] %}
add bgp neighbor {{group['group_name']}} ebgp-multihop
{% endif %}
{% endfor %}
commit: false
notify: "Configuration was changed"
when: bgp['ipv4_unicast_peer_groups'] is defined
\ No newline at end of file
- import_tasks: bgp.yml
when: bgp is defined
- import_tasks: bgp_peering.yml
when: bgp is defined
\ No newline at end of file
- name: Configure Bridge ports
nclu:
template: |
{% for bridge in bridges %}
{% for port in bridge['ports'] %}
add bridge {{bridge['name']}} port {{port}}
{% endfor %}
{% endfor %}
commit: false
notify: "Configuration was changed"
\ No newline at end of file
- name: Configure Bridge SVIs
nclu:
template: |
{% for bridge in bridges %}
add bridge {{bridge['name']}} ip address {{bridge['ipv4']}}
{% endfor %}
commit: false
notify: "Configuration was changed"
\ No newline at end of file
- import_tasks: bridge_svi.yml
when: bridges is defined
- import_tasks: bridge_ports.yml
when: bridges is defined
\ No newline at end of file
- name: "Configuration was changed"
set_fact:
config_was_changed: true
- name: Configure IPv4 interfaces
nclu:
template: |
{% for interface in interfaces %}
add interface {{interface['name']}} ip address {{interface['ipv4']}}
{% endfor %}
commit: false
notify: "Configuration was changed"
\ No newline at end of file
- name: Configure IPv4 loopbacks
nclu:
template: |
{% for loopback in loopbacks %}
add loopback {{loopback['name']}} ip address {{loopback['ipv4']}}
{% endfor %}
notify: "Configuration was changed"
\ No newline at end of file
- name: Configure NTP
nclu:
template: |
{% for ntpserver in ntpservers %}
add time ntp server {{ntpserver}}
{% endfor %}
commit: false
notify: "Configuration was changed"
\ No newline at end of file
- import_tasks: ospf_process.yml
- import_tasks: ospf_routerid.yml
- import_tasks: ospf_interfaces.yml
- import_tasks: ospf_loopbacks.yml
\ No newline at end of file
- name: Configure OSPF interfaces
nclu:
template: |
{% for interface in interfaces %}
{% if interface['ospf_area'] is defined %}
add ospf network {{ interface['ipv4'] }} area {{ interface['ospf_area'] }}
{% endif %}
{% endfor %}
commit: false
notify: "Configuration was changed"
when: interfaces is defined
- name: Configure OSPF interface type
nclu:
template: |
{% for interface in interfaces %}
{% if interface['ospf_net_type'] is defined %}
add interface {{ interface['name'] }} ospf network {{interface['ospf_net_type']}}
{% endif %}
{% endfor %}
commit: false
notify: "Configuration was changed"
when: interfaces is defined
- name: Configure OSPF for SVI
nclu:
template: |
{% for bridge in bridges %}
{% if bridge['ospf_area'] is defined %}
add ospf network {{ bridge['ipv4'] }} area {{ bridge['ospf_area'] }}
{% endif %}
{% endfor %}
commit: false
notify: "Configuration was changed"
when: bridges is defined
- name: Configure OSPF for SVI interface type
nclu:
template: |
{% for bridge in bridges %}
{% if bridge['ospf_net_type'] is defined %}
add bridge {{ bridge['name'] }} ospf network {{bridge['ospf_net_type']}}
{% endif %}
{% endfor %}
commit: false
notify: "Configuration was changed"
when: bridges is defined
- name: Configure passive OSPF interface for SVI
nclu:
template: |
{% for bridge in bridges %}
{% if bridge['ospf_passive'] %}
add ospf passive-interface {{ bridge['name'] }}
{% endif %}
{% endfor %}
commit: false
notify: "Configuration was changed"
when: bridges is defined
\ No newline at end of file
- name: Configure OSPF loopbacks
nclu:
template: |
{% for loopback in loopbacks %}
{% if loopback['ospf_area'] is defined %}
add ospf network {{ loopback['ipv4'] }} area {{ loopback['ospf_area'] }}
{% endif %}
{% endfor %}
commit: false
notify: "Configuration was changed"
\ No newline at end of file
- name: Enable OSPF process
lineinfile:
regexp: ^ospfd=
line: ospfd=yes
path: /etc/frr/daemons
notify: "Configuration was changed"
- name: Configure OSPF router-id
nclu:
commands:
- add ospf router-id {{routerid}}
notify: "Configuration was changed"
when: underlay_protocol == 'ospf'
---
- name: "Apply interfaces role"
hosts: ipfabric
gather_facts: no
become: yes
become_method: sudo
vars_files:
- config/globals.yml
tasks:
- import_role:
name: common
- import_role:
name: basic_config
- import_role:
name: interfaces
- import_role:
name: bridges
- import_role:
name: loopbacks
- import_role:
name: ospf
when: underlay_protocol == 'ospf'
- import_role:
name: bgp
post_tasks:
- name: "Commit pending configuration"
block:
- nclu:
commands:
- show hostname
commit: true
- set_fact:
config_was_changed: false
when: config_was_changed is defined and config_was_changed
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.define("spine1") do |spine1|
spine1.vm.box = "CumulusCommunity/cumulus-vx"
spine1.vm.box_version = "3.7.3"
spine1.vm.network("forwarded_port", guest: 22, host: 2022, id: 'ssh', auto_correct: false)
# Fabric links (swp1 - swp4)
spine1.vm.network("private_network", virtualbox__intnet: "SPINE1_LEAF1", cumulus__intname: 'swp1', nic_type: "virtio", auto_config: false)
spine1.vm.network("private_network", virtualbox__intnet: "SPINE1_LEAF2", cumulus__intname: 'swp2', nic_type: "virtio", auto_config: false)
spine1.vm.network("private_network", virtualbox__intnet: "SPINE1_LEAF3", cumulus__intname: 'swp3', nic_type: "virtio", auto_config: false)
spine1.vm.network("private_network", virtualbox__intnet: "SPINE1_LEAF4", cumulus__intname: 'swp4', nic_type: "virtio", auto_config: false)
end
config.vm.define("spine2") do |spine2|
spine2.vm.box = "CumulusCommunity/cumulus-vx"
spine2.vm.box_version = "3.7.3"
spine2.vm.network("forwarded_port", guest: 22, host: 2023, id: 'ssh', auto_correct: false)
spine2.vm.network("private_network", virtualbox__intnet: "SPINE2_LEAF1", cumulus__intname: 'swp1', nic_type: "virtio", auto_config: false)
spine2.vm.network("private_network", virtualbox__intnet: "SPINE2_LEAF2", cumulus__intname: 'swp2', nic_type: "virtio", auto_config: false)
spine2.vm.network("private_network", virtualbox__intnet: "SPINE2_LEAF3", cumulus__intname: 'swp3', nic_type: "virtio", auto_config: false)
spine2.vm.network("private_network", virtualbox__intnet: "SPINE2_LEAF4", cumulus__intname: 'swp4', nic_type: "virtio", auto_config: false)
end
config.vm.define("leaf1") do |leaf1|
leaf1.vm.box = "CumulusCommunity/cumulus-vx"
leaf1.vm.box_version = "3.7.3"
leaf1.vm.network("forwarded_port", guest: 22, host: 2024, id: 'ssh', auto_correct: false)
leaf1.vm.network("private_network", virtualbox__intnet: "SPINE1_LEAF1", cumulus__intname: 'swp1', nic_type: "virtio", auto_config: false)
leaf1.vm.network("private_network", virtualbox__intnet: "SPINE2_LEAF1", cumulus__intname: 'swp2', nic_type: "virtio", auto_config: false)
end
config.vm.define("leaf2") do |leaf2|
leaf2.vm.box = "CumulusCommunity/cumulus-vx"
leaf2.vm.box_version = "3.7.3"
leaf2.vm.network("forwarded_port", guest: 22, host: 2025, id: 'ssh', auto_correct: false)
leaf2.vm.network("private_network", virtualbox__intnet: "SPINE1_LEAF2", cumulus__intname: 'swp1', nic_type: "virtio", auto_config: false)
leaf2.vm.network("private_network", virtualbox__intnet: "SPINE2_LEAF2", cumulus__intname: 'swp2', nic_type: "virtio", auto_config: false)
end
end
#!/bin/sh
# Install Docker CE
## Set up the repository
### Install required packages.
yum install yum-utils device-mapper-per