Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

All Feature branch updates #1

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
166 changes: 138 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,138 @@
# DevOps Engineer - Technical Test
We think infrastructure is best represented as code, and provisioning of resources should be automated as much as possible.

Your task is to create a CI build pipeline that deploys this web application to a load-balanced
environment. You are free to complete the test in a local environment (using tools like Vagrant and
Docker) or use any CI service, provisioning tool and cloud environment you feel comfortable with (we
recommend creating a free tier account so you don't incur any costs).

* Your CI job should:
* Run when a feature branch is pushed to Github (you should fork this repository to your Github account). If you are working locally feel free to use some other method for triggering your build.
* Deploy to a target environment when the job is successful.
* The target environment should consist of:
* A load-balancer accessible via HTTP on port 80.
* Two application servers (this repository) accessible via HTTP on port 3000.
* The load-balancer should use a round-robin strategy.
* The application server should return the response "Hi there! I'm being served from {hostname}!".

## Context
We are testing your ability to implement modern automated infrastructure, as well as general knowledge of system administration. In your solution you should emphasize readability, maintainability and DevOps methodologies.

## Submit your solution
Create a public Github repository and push your solution in it. Commit often - we would rather see a history of trial and error than a single monolithic push. When you're finished, send us the URL to the repository.

## Running this web application
This is a NodeJS application: This is a NodeJS application:

- `npm test` runs the application tests - `npm test` runs the application tests
- `npm start` starts the http server
# Devops-test

This page outlines the steps taken to implement a CI pipeline for the BuildIT Devops test - see [BuildIt DevOps Test](README_BUILDIT.md).
Any changes made to the _feature_ branch of this repository will trigger the pipeline resulting in deployment of the sample
web app to a HA environment on Digital Ocean.

### Pre-requsites
The following steps will assume that you have the following already setup
* GitHub account
* Digital Ocean account
* Codeship account
* Personal SSH key

## (1) Fork repository
This repository was created from a fork of the BuildIt DevOps Test repo at [https://github.com/buildit/devops-test](https://github.com/buildit/devops-test)

A local working copy of this repo can be created using the following command once forked to your GitHub account.
```
git clone https://github.com/dazoido/devops-test.git
```

## (2) Create a Droplet on Digital Ocean
Create a droplet capable of running the Node web app. Use the steps below:

1. Login to your Digital Ocean account
1. Create a Droplet using a standard Ubuntu distribution (Note: You can use their pre-baked 'Node on Ubuntu' image under the __Marketplace__ tab but for the purpose of being verbose we will use a standard image and install node on the droplet too)
1. Add your public SSH key to the droplet
1. Give you droplet and more friendly, identifiable name e.g. ws1-devops
1. You can skip over most of the other options (for the purpose of creating this demo/test)


## (3) Create 'deploy' user
Create a deploy user for managing deployments to droplet

1. SSH to droplet as root user - `ssh root@DROPLET_IP`
1. Add 'deploy' user - `useradd -s /bin/bash -m -d /home/deploy deploy`
1. Set password for 'deploy' user - `passwd deploy`
1. Give 'deploy user' sudo/root level access - `usermod -aG sudo deploy`
1. Create authorized_key file for ssh access to 'deploy' user -
```
cd /home/deploy
mkdir .ssh
chown deploy:deploy .ssh
chmod 700 .ssh
cd .ssh
touch authorized_keys
chown deploy:deploy authorized_keys
chmod 600 authorized_keys
```
Note: alternatively you can use `ssh-copy-id` command from your local machine to setup the necessary ssh directory, files and add your key.
1. Add your public SSH key to `/home/deploy/.ssh/authorized_keys`


## (4) Create SSH keys for deploy and connect to GitHub
Generate SSH keys for 'deploy' user and use these to connect the droplet to GitHub

1. SSH into your droplet as the 'deploy' user - `ssh deploy@DROPLET_IP`
```
ssh-keygen -t rsa -C "deploy"
```
When prompted save the key with an empty passphrase.
This will save the generated private/public pair to `/home/deploy/.ssh/id_rsa`.
1. Add the following ssh-agent startup script to `/home/deploy/.bashrc`. You will need to reboot the server for the `ssh-agent` to be started and the deploy key automatically added.
```
if [ ! -S ~/.ssh/ssh_auth_sock ]; then
eval `ssh-agent`
ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
ssh-add -l > /dev/null || ssh-add
```
1. Copy the contents of `id_rsa.pub` to your Github repo - Settings > Deploy Keys. (Do not allow write permissions).


## (5) Install Node and NPM on your Droplet
1. To install Node and NPM, SSH into to your newly created droplet and run the following commands:
```
curl -sL https://deb.nodesource.com/setup_10.x -o node_10_setup.sh
chmod 760 node_10_setup.sh
sudo bash node_10_setup.sh
sudo apt install nodejs
```
1. Verify successful installation using the following commands:
```
node -v
npm -v
```

## (6) Install Node app on Droplet
Clone the repo to a folder on the droplet.
1. Create folder where repo/app will reside
```
cd /var
mkdir www
sudo chown deploy:deploy -R www
cd www
```
1. Clone repo `git clone [email protected]:dazoido/devops-test.git`
1. Install app dependencies and start app
```
cd devops-test
npm install
npm start
```

## (7) Setup Codeship to manage CI
1. Create project and connect to repository
1. Set deployment script - Project > Project Settings > Deploy
```
# deploy to ws1-devops
ssh deploy@DROPLET_IP 'cd /var/www/devops-test && git checkout feature && git pull && npm install && pm2 restart all'
```
1. Set build triggers - Project > Project Settings > Build Triggers
* Select Behaviour - _Run builds for these branches only_ enter 'feature' for only the feature branch to trigger build
* Select Build Trigger - _Build on commit, merge, and tags_
1. Copy SSH key in - Project > Project Settings > General to `/home/deploy/.ssh/authorized_keys`

## (8) Create second Droplet for HA environment
1. Either repeat steps 2-6 __OR__ more convienently take a _snapshot_ of the first droplet and use this to create the second droplet.
1. SSH into the second droplet to start `ssh-agent` and the deploy key
1. Start the app/server `cd /var/www/devops-test && npm start`
1. Update the deploy script on Codeship to deploy to the second droplet
```
# deploy to ws1-devops
ssh deploy@DROPLET_IP 'cd /var/www/devops-test && git checkout feature && git pull && npm install && pm2 restart all'

# deploy to ws2-devops
ssh deploy@DROPLET_IP 'cd /var/www/devops-test && git checkout feature && git pull && npm install && pm2 restart all'
```
## (9) Setup Loadbalancer on DigitalOcean
1. Spin up a loadbalancer on Digital Ocean and add the droplets to its balancing group
1. Configure the settings as follows <img width="1218" alt="DigitalOcean_LB_settings" src="https://user-images.githubusercontent.com/22031811/58669926-44a9e100-8335-11e9-822a-29163d084e02.png">

## (10) Demo CI pipeline
* Droplet 1 - [http://ws1-devops.joelcalliste.me:3000](http://ws1-devops.joelcalliste.me:3000)
* Droplet 2 - [http://ws2-devops.joelcalliste.me:3000](http://ws2-devops.joelcalliste.me:3000)
* Loadbalancer - [http://ws-devops.joelcalliste.me](http://ws-devops.joelcalliste.me)

28 changes: 28 additions & 0 deletions README_BUILDIT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# DevOps Engineer - Technical Test
We think infrastructure is best represented as code, and provisioning of resources should be automated as much as possible.

Your task is to create a CI build pipeline that deploys this web application to a load-balanced
environment. You are free to complete the test in a local environment (using tools like Vagrant and
Docker) or use any CI service, provisioning tool and cloud environment you feel comfortable with (we
recommend creating a free tier account so you don't incur any costs).

* Your CI job should:
* Run when a feature branch is pushed to Github (you should fork this repository to your Github account). If you are working locally feel free to use some other method for triggering your build.
* Deploy to a target environment when the job is successful.
* The target environment should consist of:
* A load-balancer accessible via HTTP on port 80.
* Two application servers (this repository) accessible via HTTP on port 3000.
* The load-balancer should use a round-robin strategy.
* The application server should return the response "Hi there! I'm being served from {hostname}!".

## Context
We are testing your ability to implement modern automated infrastructure, as well as general knowledge of system administration. In your solution you should emphasize readability, maintainability and DevOps methodologies.

## Submit your solution
Create a public Github repository and push your solution in it. Commit often - we would rather see a history of trial and error than a single monolithic push. When you're finished, send us the URL to the repository.

## Running this web application
This is a NodeJS application: This is a NodeJS application:

- `npm test` runs the application tests - `npm test` runs the application tests
- `npm start` starts the http server
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ var os = require('os')
var http = require('http')

function handleRequest(req, res) {
res.write('Hi there! I\'m being served from ' + os.hostname())
res.write('Hi there! I\'m being served from ' + os.hostname() + ' using pm2. Tested and deployed using Codeship. v1')
res.end()
}

Expand Down
Loading