diff --git a/ansible/inventory.yml b/ansible/inventory.yml new file mode 100644 index 0000000000000000000000000000000000000000..5f9038a74f88518dc4d3ce0bf4b521cbbfa944e6 --- /dev/null +++ b/ansible/inventory.yml @@ -0,0 +1,31 @@ +--- +# 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 diff --git a/ansible/playbook.yml b/ansible/playbook.yml new file mode 100644 index 0000000000000000000000000000000000000000..2c49a10bf362981edb784be146108c88349a08ed --- /dev/null +++ b/ansible/playbook.yml @@ -0,0 +1,279 @@ +--- +# 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: 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