Skip to content

Commit

Permalink
Ansible (#2)
Browse files Browse the repository at this point in the history
* Move to tezedge-ci-builder repo

* Fix typo
  • Loading branch information
adonagy authored Jul 2, 2021
1 parent 0f41552 commit f654504
Show file tree
Hide file tree
Showing 16 changed files with 508 additions and 0 deletions.
235 changes: 235 additions & 0 deletions drone_ci_deployment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
# Tezegde CI - Drone - Continuous Integration platform

Our CI of choice was [drone](https://www.drone.io/). The following readme was designed to apply to Ubuntu 18.04 and above.

## Prerequisites

- Be able to ssh into the desired target hosts with public key authentication with the **SAME** username and public key used on all the hosts
- For the real time runner, we restrict the hardware for a one of hetzner dedicated servers, specifically to [PX-93](https://www.hetzner.com/dedicated-rootserver/px93?country=by) to be able to install our custom compiled kernel with PREEMTP_RT patch

## Deploying a drone ci for tezedge repository

### 1. Creating an OAuth Application on github
- GitHub's documentation has a [step by step guide](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app)

- The most important is to set the:
- `Application name`: A descriptive name of the Application (E.g.: Tezege Fork CI)
- `Homepage URL`: The url of the `drone_server` with an empty path component (E.g.: http://ci.tezedgem.com)
- `Authorization callback URL`: The url of the `drone_server` with a `login` path component (E.g.: http://ci.tezedgem.com/login)

- After we have created the OAuth app, we will be redirected to the configuration page.

- Create a client secret and copy it. Be careful! You can only see the secret once.

- Copy out the client id.

The whole process is captured on the following gif:

![alt text](images/github_oauth_app.gif)

### 2. Create a shared secret

The shared secret is used to authenticate communication between runners and our `drone_server`.

- To create a shared secret, run the following command in a terminal
```
$ openssl rand -hex 16
bea26a2221fd8090ea38720fc445eca6
```

### 3. Install ansible

For comfortable automation, we have created ansible playbooks to deploy a drone ci setup with just a few commands

```
$ sudo apt update
$ sudo apt install software-properties-common
$ sudo add-apt-repository --yes --update ppa:ansible/ansible
$ sudo apt install ansible
```

### 4. Fork the tezedge repository.

Fork is important if we want to run our own CI environment as the drone CI runs builds via github webhooks.

![alt text](images/github_repo_forking.gif)

### 5. Clone the two repositories

You will need this repository to set up the CI environment and the forked tezedge repository to execute new builds inside the CI

```
$ git clone https://github.com/tezedge/tezedge-ci-builder.git
$ git clone https://github.com/tezedgeUser/tezedge.git
```

Please, change the username `tezedgeUser` for the username you forked the repository with.

### 6. Edit variables and hosts

Now change directory into the tezedge-ci-builder

```
$ cd tezedge-ci-builder/drone_ci_deployment
```

Before we run the playbooks, we need to set a few variables that are used in the configuration. In the vars directory, we need to
edit the [variables.yml](vars/variables.yml)

There are 6 variables we need to set before continuing

```
drone_server: The ip/hostname of the machine we wish to set as a server
# User with the ssh connects to the target machines
target_hosts_user: The username with sudo permissions on the target hosts
# The github username you wish to add as an admin for the drone CI
admin_user: The github username of the desired administrator
# Variables for drone server configuration
github_client_id: The client id of the OAuth app
github_client_secret: The client secret of the OAuth app
rpc_secret: The generated shared secret for RPC communication
```

Example of a fully edited variables.yml file:

```
---
# The drone server
drone_server: 65.21.165.82
# User with the ssh connects to the target machines
target_hosts_user: dev
# The github username you wish to add as an admin for the drone CI
admin_user: tezedgeUser
# Variables for drone server configuration
github_client_id: a3e1b143f5cf193c3ef2
github_client_secret: a4421f712e07eca2ea0fd3f78934a5a5351f3a5e
rpc_secret: 96cac97a56ebe9419709cbffc0849292
# ** DO NOT EDIT THE VARIABLES BELOW THIS LINE **
# Path to the tezedge-ci data that needs to be acquired before running the ci
ci_data_path: "/home/{{ target_hosts_user }}"
# SSH configuration
ssh_strict_host_keys: 'no'
ssh_config_file: "/home/{{ target_hosts_user }}/.ssh/config"
...
```

The next file we should edit is the [hosts](inventory/hosts) file. This file is in ini format and contains all the hosts we wish to connect to.

Example of a fully edit host file:
```
[drone_server]
65.21.165.82
[drone_runners]
65.21.165.82
65.21.165.83
[real_time_runners]
65.21.165.84
```

You can add as many *drone_runners* or *real_time_runners* as we wish. Please be aware of the *real_time_runners* hardware prerequisites talked about earlier in this readme. Note that the `drone_server` can also run a drone_runner

### 7. Run the ansible playbooks

**Please keep in mind that we have to run these playbooks in this exact order**

Once all the variables and hosts are set we can proceed to execute the ansible playbooks. Please double check that we can connect to the target hosts with public key authentication.

We use the `ansible-playbook` command to execute the playbooks. Here we provide a description for an example `ansible-playbook` command. Use the same user as the `target_hosts_user` we set in the variables.yml.
```
$ ansible-playbook ./playbooks/docker_setup.yml --user dev --ask-become-pass -i ./inventory/hosts
| | | |
| | | -------> inventory file
| | -------> sudo password for the user
| -------> the user we want to connect to the host
-------> the specific playbook we are running
```

After we run the command, ansible will ask for the `BECOME` password. You must enter the user's password, so ansible can execute sudo commands on the host.

- The first one we run is [docker_setup](playbooks/docker_setup.yml). This playbook prepares the hosts for the docker containers that drone runs in. It installs all the prerequisite packages for docker and docker itself.

```
$ ansible-playbook ./playbooks/docker_setup.yml --user dev --ask-become-pass -i ./inventory/hosts
```

- As the next step, we run the [real_time_node_setup](playbooks/real_time_node_setup.yml). This playbook downloads and installs the required kernel for the real time environment. It ends in the reboot of the target host. Ansible will wait for the host to come online again. Again, please be aware of the *real_time_runners* hardware prerequisites talked about earlier in this readme.

```
$ ansible-playbook ./playbooks/real_time_node_setup.yml --user dev --ask-become-pass -i ./inventory/hosts
```

- The next one to run is the [drone_server_setup](playbooks/drone_server_setup.yml). With this we set up and start the drone server.

```
$ ansible-playbook ./playbooks/drone_server_setup.yml --user dev --ask-become-pass -i ./inventory/hosts
```

- As the final touch, we set up and run all the drone runners. These playbooks will also download all the data needed to run all of our tests in the CI.

```
$ ansible-playbook ./playbooks/normal_drone_runner_setup.yml --user dev --ask-become-pass -i ./inventory/hosts
$ ansible-playbook ./playbooks/real_time_drone_runner_setup.yml --user dev --ask-become-pass -i ./inventory/hosts
```
Please note that both playbooks will stay on `Download data` task quite a long time as they are downloading approximately 29 GB of data for each host.

### 8. Enable and setup the tezedge repository

After we ran all the playbooks above we can navigate to the `drone_server` url to enable the repository

Follow this gif to set up the CI:

![alt text](images/drone_ui_config.gif)

With these few steps we enable the repository to send webhooks to our `drone_server`. We also enable the `Trusted` setting and set the pipeline timeouts to 4 hours.

### 8. Add the drone runner ips/hosts to the synchronize_ci.sh script

The CI environment is now properly set up! Now all we have to do is to edit the `synchronize_ci.sh`.

Change directory into tezedge

```
$ cd ../tezedge
```

This script handles the distribution of the build data across all the runners and can be found in the root of the repository [here](../synchronize_ci.sh) . We need to edit the `CI_HOSTS` array in the script to have all the `drone_runners` and `real_time_runners` included.

## Run a build

Done! We now have a fully configured drone CI with all the data required to run the test pipelines.

To run a build:

- Create a custom branch
```
$ git checkout -b ci/testing
```

- Commit all of the changes
```
$ git add . && git commit -m "Our new CI setup"
```

- Push the changes to the remote forked github repository

```
$ git push origin ci/testing
```

Now all we have to do is to create a pull request to the develop branch. After the pull request creation, we will notice a new build in our `drone_server` webpage.
Binary file added drone_ci_deployment/images/drone_ui_config.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added drone_ci_deployment/images/github_oauth_app.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions drone_ci_deployment/inventory/hosts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[drone_server]
<edit>

[drone_runners]
<edit>

[real_time_runners]
<edit>
44 changes: 44 additions & 0 deletions drone_ci_deployment/playbooks/docker_setup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
- hosts: "*"
become: yes
vars_files:
- ../vars/variables.yml

tasks:
- name: Install aptitude using apt
apt: name=aptitude state=latest update_cache=yes force_apt_get=yes

- name: Install required system packages
apt: name={{ item }} state=latest update_cache=yes
loop: [ 'apt-transport-https', 'ca-certificates', 'curl', 'software-properties-common', 'python3-pip', 'virtualenv', 'python3-setuptools']

- name: Add Docker GPG apt Key
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present

- name: Add Docker Repository
apt_repository:
repo: deb https://download.docker.com/linux/ubuntu bionic stable
state: present

- name: Update apt and install docker-ce
apt: update_cache=yes name=docker-ce state=latest

- name: Install Docker Module for Python
pip:
name: docker

- name: Add user to docker group
user:
name: "{{ target_hosts_user }}"
shell: /bin/bash
groups: docker
append: yes

- name: Deploy {{ ssh_config_file }}
template:
src : ../templates/ssh_config.j2
dest : "{{ ssh_config_file }}"
owner : root
group : root
mode : 0600
25 changes: 25 additions & 0 deletions drone_ci_deployment/playbooks/drone_server_setup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
- hosts: "drone_server"
become: yes
vars_files:
- ../vars/variables.yml
tasks:

- name: Pull drone server image
docker_image:
name: "drone/drone:2"
source: pull

- name: Deploy environment file
template:
src: ../templates/ci.env.j2
dest: /home/dev/ci.env

- name: Deploy starting script
template:
src: ../templates/drone_server.sh.j2
dest: /home/dev/drone_server.sh
mode : 0755

- name: Start the drone server
command:
cmd: '/bin/bash /home/dev/drone_server.sh'
61 changes: 61 additions & 0 deletions drone_ci_deployment/playbooks/normal_drone_runner_setup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
- hosts: "drone_runners"
# become: yes
vars_files:
- ../vars/variables.yml
tasks:

- name: Pull drone runner image
docker_image:
name: "drone/drone-runner-docker:1"
source: pull

- name: Deploy environment file
template:
src: ../templates/ci.env.j2
dest: "/home/{{ target_hosts_user }}/ci.env"

- name: Deploy starting script
template:
src: ../templates/drone_runner.sh.j2
dest: /home/{{ target_hosts_user }}/drone_runner.sh
mode : 0755

- name: Download data
shell: "wget -q -m -np -nH -R 'index.html*' http://65.21.165.81:8080/tezedge-ci/ -P {{ ci_data_path }}"

- name: Move data to the desired location
become: yes
command: mv {{ ci_data_path }}/tezedge-ci /usr/local/etc/tezedge-ci

- name: SSH KeyGen command
shell: >
ssh-keygen -q -b 2048 -t rsa -N "" -C "creating SSH" -f ~/.ssh/id_rsa
creates="~/.ssh/id_rsa"
- name: Fetch the keyfile from the node to master
fetch:
src: "~/.ssh/id_rsa.pub"
dest: "buffer/{{ inventory_hostname }}-id_rsa.pub"
flat: yes

- name: Copy the key add to authorized_keys using Ansible module
become: yes
authorized_key:
user: "{{ target_hosts_user }}"
state: present
key: "{{ lookup('file','buffer/{{item}}-id_rsa.pub')}}"
when: "{{ item != inventory_hostname }}"
with_items:
- "{{ groups['drone_runners'] }}"

- name: Copy id to tezedge-ci dir
command: cp ~/.ssh/id_rsa /usr/local/etc/tezedge-ci/id/id_rsa

- name: Change outpu-filter permissons
file:
path: /usr/local/etc/tezedge-ci/tools/output-filter
mode: "0775"

- name: Start the drone runner
command:
cmd: '/bin/bash /home/{{ target_hosts_user }}/drone_runner.sh'
Loading

0 comments on commit f654504

Please sign in to comment.