Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • tfs/controller
1 result
Show changes
Commits on Source (6)
<!--
Copyright 2024 David Araújo
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
# TFS Cluster Auto-setup
The Ansible playbook and inventory in this directory are set up to configure Ubuntu 22.04 hosts, preparing them for a future TeraFlowSDN deployment.
## Host Environment
As a sandbox example, we create a network of three hosts using Vagrant and provision them with password-less SSH public keys.
In a production environment, various tools or platforms can be used to run these instances, such as a server with Proxmox or a cloud provider. Provisioning can be done manually or with tools like Terraform.
## Inventory
In the inventory, we list the hosts that will be part of the MicroK8s cluster and define their roles.
As of this writing, only three tags are required, with one being optional.
- **microk8s_master** - *boolean* - *mandatory* - Identifies the node that will serve as the master of the MicroK8s cluster.
- **tfs_branch** - *string* - *optional* - Specifies the branch to checkout when cloning the repository (defaults to `master`). This tag must be defined on the same host as the *microk8s_master* tag.
- **containerlab_host** - *boolean* - *mandatory* - Identifies the node where ContainerLab will be deployed. This tag enables Ansible to install ContainerLab on the correct host and set static routes on other hosts to reach nodes in the ContainerLab topology.
\ No newline at end of file
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.define "hub" do |hub|
hub.vm.box = "ubuntu/mantic64"
hub.vm.hostname = "hub"
hub.vm.network "private_network", ip: "192.168.56.10"
hub.vm.provider "virtualbox" do |v|
# This is high because in this scenarion, the hub will be responsible form running, both TFS and Containerlab
# Other configurations between the nodes can be used, but that will require to also change the playbook
v.memory = 8192
v.cpus = 4
end
hub.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "/home/vagrant/.ssh/host.pub"
hub.vm.provision "shell", inline: "cat /home/vagrant/.ssh/host.pub >> /home/vagrant/.ssh/authorized_keys"
end
config.vm.define "spoke1" do |spoke1|
spoke1.vm.box = "ubuntu/mantic64"
spoke1.vm.hostname = "spoke1"
spoke1.vm.network "private_network", ip: "192.168.56.11"
spoke1.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 1
end
spoke1.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "/home/vagrant/.ssh/host.pub"
spoke1.vm.provision "shell", inline: "cat /home/vagrant/.ssh/host.pub >> /home/vagrant/.ssh/authorized_keys"
end
config.vm.define "spoke2" do |spoke2|
spoke2.vm.box = "ubuntu/mantic64"
spoke2.vm.hostname = "spoke2"
spoke2.vm.network "private_network", ip: "192.168.56.12"
spoke2.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 1
end
spoke2.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "/home/vagrant/.ssh/host.pub"
spoke2.vm.provision "shell", inline: "cat /home/vagrant/.ssh/host.pub >> /home/vagrant/.ssh/authorized_keys"
end
end
---
# Copyright 2024 David Araújo
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
nodes:
hosts:
hub:
ansible_host: 192.168.56.10
containerlab_host: true # Mandatory
microk8s_master: true # Mandatory
tfs_branch: develop # Optional
spoke1:
ansible_host: 192.168.56.11
spoke2:
ansible_host: 192.168.56.12
vars:
ansible_user: vagrant
ansible_ssh_private_key_file: ~/.ssh/id_rsa
# Prevents from having to interact to approve a new remote host fingerprint
ansible_ssh_common_args: -o StrictHostKeyChecking=accept-new
---
# Copyright 2024 David Araújo
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
- name: TFS Cluster platform
hosts: nodes
become: true
remote_user: "{{ ansible_user }}"
tasks:
- name: Wait for /var/lib/dpkg/lock-frontend to be released
ansible.builtin.shell: while lsof /var/lib/dpkg/lock-frontend; do sleep 10; done
register: out
changed_when: out.rc != 0
- name: Configure all packages
ansible.builtin.command: dpkg --configure -a
register: out
changed_when: out.rc != 0
- name: Update repositories
ansible.builtin.apt:
update_cache: true
- name: Fix any broken packages
ansible.builtin.apt:
name: "*"
state: fixed
- name: Upgrade the OS (apt-get dist-upgrade)
ansible.builtin.apt:
upgrade: dist
- name: Install dependencies
ansible.builtin.apt:
pkg:
- ca-certificates
- curl
- gnupg
- lsb-release
- snapd
- jq
- docker.io
- docker-buildx
state: fixed
update_cache: true
- name: Update Docker daemon.json with insecure-registries
ansible.builtin.shell: |
if [ -s /etc/docker/daemon.json ]; then sudo cat /etc/docker/daemon.json; else echo '{}'; fi \
| jq 'if has("insecure-registries") then . else .+ {"insecure-registries": []} end' -- \
| jq '."insecure-registries" |= (.+ ["localhost:32000"] | unique)' -- \
| tee tmp.daemon.json
register: out
changed_when: out.rc != 0
- name: Copy tmp.daemon.json
ansible.builtin.copy:
remote_src: true
src: tmp.daemon.json
dest: /etc/docker/daemon.json
owner: root
group: root
mode: "600"
- name: Remove workdir tmp.daemon.json file
ansible.builtin.file:
path: tmp.daemon.json
state: absent
- name: Restart docker service
ansible.builtin.service:
name: docker
state: restarted
- name: Add address of all hosts to all hosts
ansible.builtin.lineinfile:
dest: /etc/hosts
regexp: .*{{ item }}$
line: "{{ hostvars[item].ansible_host }} {{ item }}"
state: present
when: hostvars[item].ansible_host is defined
with_items: "{{ groups.all }}"
- name: Find the Containerlab host IP
ansible.builtin.set_fact:
containerlab_host_address: "{{ hostvars[item].ansible_host }}"
when: hostvars[item].containerlab_host is defined
with_items: "{{ groups['all'] }}"
run_once: true
- name: Specify ip route to Containerlab network
ansible.builtin.shell: sudo ip route add 172.100.100.0/24 via {{ containerlab_host_address }}
when: hostvars[inventory_hostname].containerlab_host is not defined
register: out
changed_when: out.rc != 0
- name: Install Containerlab
ansible.builtin.shell: |
curl -sL https://containerlab.dev/setup \
| sudo bash -s "all"
register: out
changed_when: out.rc != 0
when: containerlab_host is defined
- name: Install gnmic
ansible.builtin.shell: |
curl -sL https://get-gnmic.kmrd.dev \
| sudo bash
register: out
changed_when: out.rc != 0
- name: Install MicroK8s
community.general.snap:
name: microk8s
classic: true
channel: 1.24/stable
- name: Create kubectl alias
community.general.snap_alias:
name: microk8s.kubectl
alias: kubectl
- name: Ensure group "microk8s" exists
ansible.builtin.group:
name: microk8s
state: present
- name: Ensure group "docker" exists
ansible.builtin.group:
name: docker
state: present
- name: Add user to docker and microk8s groups
ansible.builtin.user:
name: "{{ ansible_user }}"
groups: docker, microk8s
- name: Reboot for groups to take effect
ansible.builtin.reboot:
- name: Make sure docker daemon is running
ansible.builtin.systemd_service:
state: started
name: docker
enabled: true
- name: Create .kube directory
ansible.builtin.file:
path: /home/{{ ansible_user }}/.kube
state: directory
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: "0644"
- name: Create .kube/config file
ansible.builtin.file:
path: /home/{{ ansible_user }}/.kube/config
state: touch
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: "0644"
- name: Get microk8s config
ansible.builtin.command: sudo microk8s config
register: microk8s_config
changed_when: microk8s_config.rc != 0
- name: Keep microk8s config
ansible.builtin.copy:
remote_src: true
content: "{{ microk8s_config.stdout }}"
dest: /home/{{ ansible_user }}/.kube/config
mode: "0644"
register: out
- name: Add IP address to microk8s certificate template
ansible.builtin.lineinfile:
dest: /var/snap/microk8s/current/certs/csr.conf.template
search_string: "#MOREIPS"
line: IP.3 = {{ ansible_host }}
state: present
- name: Start MicroK8s
ansible.builtin.command: microk8s start
register: out
changed_when: out.rc != 0
- name: Forming MicroK8s cluster
hosts: all
become: true
remote_user: "{{ ansible_user }}"
serial: 1
tasks:
- name: MicroK8s add-node
ansible.builtin.shell: |
microk8s add-node \
| grep -m 1 "{{ hostvars[item].ansible_host }}"
register: master_output
delegate_to: "{{ item }}"
with_items: "{{ groups.all }}"
when: (microk8s_master is not defined) and (hostvars[item].microk8s_master is defined)
- name: Join command
ansible.builtin.set_fact:
join_command: "{{ (dict(master_output).results | selectattr('changed', 'true') | first).stdout }} --skip-verify"
when: microk8s_master is not defined
- name: MicroK8s join-node
ansible.builtin.command: "{{ join_command }}"
register: out
changed_when: out.rc != 0
when: microk8s_master is not defined
- name: Enabling MicroK8s
hosts: all
become: true
remote_user: "{{ ansible_user }}"
tasks:
- name: MicroK8s refresh certificate
ansible.builtin.command: microk8s refresh-certs -e ca.crt
register: out
changed_when: out.rc != 0
when: microk8s_master is not defined
- name: MicroK8s refresh config file
ansible.builtin.command: microk8s config > /home/$USER/.kube/config
register: out
changed_when: out.rc != 0
when: microk8s_master is not defined
- name: Enable add-ons
ansible.builtin.command: microk8s.enable {{ item }}
loop:
- community
- dns
- helm3
- hostpath-storage
- ingress
- registry
- prometheus
- metrics-server
- linkerd
register: out
changed_when: out.rc != 0
when: microk8s_master is defined
- name: Create kubectl helm3 alias
community.general.snap_alias:
name: microk8s.helm3
alias: helm3
when: microk8s_master is defined
- name: Create kubectl linkerd alias
community.general.snap_alias:
name: microk8s.linkerd
alias: linkerd
when: microk8s_master is defined
- name: Ensure MicroK8s started
ansible.builtin.command: microk8s start
register: out
changed_when: out.rc != 0
- name: Cloning TFS
hosts: all
remote_user: "{{ ansible_user }}"
tasks:
- name: Clone repository and switch to desired branch
ansible.builtin.git:
repo: 'https://labs.etsi.org/rep/tfs/controller.git'
dest: ./tfs-ctrl
version: "{{ tfs_branch | default('master') }}"
when: microk8s_master is defined
# Copyright 2024 David Araújo
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
echo "[!] Destroying existing Vagrant machines"
vagrant destroy -f --parallel
echo -e "\n[!] Removing destroyed hosts from known hosts"
ssh-keygen -f "/home/davidjosearaujo/.ssh/known_hosts" -R "192.168.56.10"
ssh-keygen -f "/home/davidjosearaujo/.ssh/known_hosts" -R "192.168.56.11"
ssh-keygen -f "/home/davidjosearaujo/.ssh/known_hosts" -R "192.168.56.12"
echo -e "\n[+] Creating new hosts"
vagrant up
AVAILABLE=1
while [ $AVAILABLE -ne 0 ]
do
ansible -o -i inventory.yml -m ping nodes 2>&1 >/dev/null
AVAILABLE=$?
done
echo -e "\n[!] Hosts ready, deploying configurations..."
ansible-playbook -i inventory.yml playbook.yml
\ No newline at end of file