{"id":14975884,"url":"https://github.com/gmcadevops/sfia-devops-project-3","last_synced_at":"2025-07-17T06:35:15.204Z","repository":{"id":41498931,"uuid":"350397456","full_name":"GMCADevops/Sfia-DevOps-Project-3","owner":"GMCADevops","description":"This project was the final Project of GMCA Devops 2021, We team 1 are deploying an application using the technologies learned over the past 3 months: ANSIBLE, Kubernetes, Docker Compose, Terraform, Jenkins, Nginx.","archived":false,"fork":false,"pushed_at":"2021-03-26T09:38:54.000Z","size":5456,"stargazers_count":0,"open_issues_count":1,"forks_count":15,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-12T12:24:00.812Z","etag":null,"topics":["agile","ansible","aws","docker","dockercompose","ec2","eks","jenkins","kubernetes","rds","terraform"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GMCADevops.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-22T15:38:00.000Z","updated_at":"2022-01-15T17:39:40.000Z","dependencies_parsed_at":"2022-09-03T19:00:46.116Z","dependency_job_id":null,"html_url":"https://github.com/GMCADevops/Sfia-DevOps-Project-3","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GMCADevops%2FSfia-DevOps-Project-3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GMCADevops%2FSfia-DevOps-Project-3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GMCADevops%2FSfia-DevOps-Project-3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GMCADevops%2FSfia-DevOps-Project-3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GMCADevops","download_url":"https://codeload.github.com/GMCADevops/Sfia-DevOps-Project-3/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224225350,"owners_count":17276435,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agile","ansible","aws","docker","dockercompose","ec2","eks","jenkins","kubernetes","rds","terraform"],"created_at":"2024-09-24T13:52:48.865Z","updated_at":"2024-11-12T05:37:18.198Z","avatar_url":"https://github.com/GMCADevops.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DevOps-Project-3\r\n\r\nhttps://team-1616393125888.atlassian.net/jira/software/projects/DEV/boards/1\r\n\r\n## Tables of Contents\r\n\r\n1. [Scrum Roles](#ScrumRoles)\r\n2. [Scope](#Scope)\r\n3. [Workflows](#Workflows)\r\n4. [Requirements](#Requirements)\r\n5. [Project Planning](#ProjectPlanning)\r\n6. [Budget](#Budget)\r\n7. [Risk Assessment](#RiskAssessment)\r\n8. [Terraform](#Terraform)\r\n9. [Ansible](#Ansible)\r\n10. [Kubernetes](#Kubernetes)\r\n11. [Jenkins](#Jenkins)\r\n12. [Improvements](#Improvements)\r\n\r\n\r\n![TeamAlpha](https://github.com/GMCADevops/DevopsProject3/blob/Documentation/images/teamAlpha.png)\r\n\r\nThis is a group challenge to see what we can produce and how well we can apply the knowledge we have gained over the last 12 weeks, as well as gaining experience working to complete a deliverable as part of a team which will be invaluable experience for future roles.\r\n\r\n## Scrum Roles\r\n\r\n![ScrumRoles](https://github.com/GMCADevops/DevopsProject3/blob/Documentation/images/ScumTeam.png)\r\n\r\n## Scope\r\n\r\nIn short, we are expected to deploy the following applications:\r\n\r\nThis project was to deploy an application of our choosing we went with something one of us developed previous to the course, an unfinished but working API and frontend.\r\nthe frontend is using react and the backend is using python.\r\n\r\nThis project should demonstrate a deployment process thats not dependant on the application thats being deployed.\r\n\r\n## Workflows\r\n\r\nFor this project we all worked in an agile way assuming roles and having daily standup's, understanding the issues brought up in the standup was a major factor in us being able to succeed in this project. We also did a retrospective after this current sprint which was our only sprint, lasting 4 days with our project demo on the 5th day.\r\n\r\n## Requirements\r\n\r\nTo plan, design, and implement a solution for automating the development workflows and deployments of this application.\r\n\r\n![DevOpsTools](https://github.com/GMCADevops/DevopsProject3/blob/Documentation/images/DevOpsTools.png)\r\n\r\n## ProjectPlanning\r\n\r\nUsing an agile board on Jira to manage product backlogs and keep the whole team aware of progression.\r\n\r\n![Kanban](https://github.com/GMCADevops/DevopsProject3/blob/Documentation/images/ProjectPlanning.png)\r\n\r\n## Contributors\r\n\r\n[Jack Pendlebury](https://www.linkedin.com/in/jack-pendlebury-803736152/) - Project Manager\r\n\r\n[Andrea Torres](https://www.linkedin.com/in/andrea-torres-j/) - Development Team\r\n\r\n[Dale Walker](https://www.linkedin.com/in/dale-walker-b4b8b0209/) - Development Team\r\n\r\n[Bilal Shafiq](https://www.linkedin.com/in/bilal-shafiq-35202b201/) - Product Owner\r\n\r\n[Lee Ashworth](https://github.com/Leeroy2185) - Scrum Master\r\n\r\n### notable mentions\r\n\r\nFor support and help during during this project\r\n\r\n- The QA team\r\n\r\n## Budget\r\n\r\n![Budget](https://i.gyazo.com/45bb9d61541a4958f36589cc00875467.png)\r\n\r\nThe budget for this project was £20 for the week, this was easily met by maintaining all of our resources within terraform meaning at the end of the day we could pull them all down and at the start of the day we could quickly put them all back up.\r\n\r\n## RiskAssessment\r\n\r\n![RiskAssessment](https://i.gyazo.com/cf20af6596ddcf2c8f6d0adf81368048.png)\r\n\r\n## Terraform\r\n\r\n### What is terraform?\r\n\r\nTerraform is a tool for building and changing infrastructure efficiently.\r\nIt is probably the most common infrastructure as code tools, allowing you to describe using a high level configuration. All the infrastructure created can also be shared and reused.\r\n\r\n### Why did we use Terraform?\r\n\r\nFor this project, learning and using Terraform has been great, it's such an amazing tool, it makes creating and building infrastructure so much easier, this is one of the main reasons we decided to use it for this project.\r\n\r\nand this should apply all of the infrastructures and build it on AWS.\r\nthis takes about 15 minutes on average, but the great thing about Terraform is, it will save the current state, meaning you can change something and it will apply it without destroying all of the none affected files.\r\nFor this project terraform was the first thing we worked on, having the infrastructure from the start allowed us to easily put up and take down the infrastructure when it wasn't being used.\r\n\r\nFor Terraform, we wanted all of our infrastructure to be deployed with it, we wanted a k8 cluster with EKS and 2 instances with EC2 one for Jenkins and one for our bastion server.\r\n\r\nThis would be done from any machine when logged into the correct IAM user with env variables we also can set up the bastion server to connect to the cluster.\r\n\r\nFor the jenkins machine what we did was we using the current state of the machine with things installed and logged into the aws cli as an ami, meaning we could replicate it each time in a controlled manor\r\n\r\n``` sh\r\n$aws configure\r\n```\r\n\r\n```sh\r\n$terraform init\r\n```\r\n\r\n```sh\r\n$terraform apply\r\n```\r\n\r\n```sh\r\n$aws eks --region eu-west-2 update-kubeconfig --name my-cluster\r\n```\r\n\r\n### possible issues.\r\n\r\n```sh\r\n$rm ~/.kube/config\r\n```\r\n\r\n```sh\r\n$terraform state list | grep auth\r\n```\r\n\r\n```sh\r\n$terraform state rm \u003cthing\u003e\r\n```\r\n\r\napplying infrastructure changes is fast and simple when using terraform\r\n\r\n![Terraform image1](https://i.gyazo.com/e401c6dfcd8aab8aeac859c74fd7fcbd.png)\r\n\r\nAnother reason why we used terraform is the fact the it knows its own state, which means when applying new infrastructure it will replace and tear down the old infrastructure. this also means when you make changes you don't need to wait for the whole infrastructure to tear down you can just apply new infrastructure.\r\n\r\nWhen something isn't working you can also use the command:\r\n\r\n```sh\r\n$terraform taint\r\n```\r\n\r\nWhich then allows you to taint the resource that isn't working to tear it down and then apply it again, this as a whole saves a lot of time as you don't need to destroy everything each time.\r\n\r\n## What we did with Terraform\r\n\r\nsome of the notable things we used Terraform for is for our k8 cluster, our jenkins CI server and finally the bastion server.\r\n\r\n![k8 image](https://i.gyazo.com/cd794f159b6ec823c1bfa2ccdb6fcd92.png)\r\n\r\nFor the Jenkins server we also used custom images to allow us to retain the jenkins install as well as our pipeline and user accounts. The reason we did this is if the ec2 instance failed and we would need to re-deploy, this would be a quick simple fix. We also hope to automate this process by using snapshots of the instance and feeding them back into terraform with image versions.\r\n\r\n![Jenkins image](https://i.gyazo.com/640cdced80519b018b0b4195b6f06e66.png)\r\n\r\nThe final thing we did with Terraform was something we could have done with ansible, but we decided it would be best to do with terraform. This was install jenkins, docker and finally adding them to the jenkins user. This script is now not very useful as this allow us to save a snapshot and turn that into an image we are now using.\r\n\r\n## Ansible\r\n\r\n\r\n\u003cbr\u003e\r\n\r\nAnsible is an open-soruce agentless configureation management and application-deployment tool enabling infrastructure as code.\r\n\u003cbr\u003e\r\n\r\nIn this project we primary used ansible to configure all of our virtual machines by installing crucial packages, we achieved this by ssh proxying through our bastion server so ansible could security access all the virtual machines in the infrastructure network and configure them accordingly.  \r\n\u003cbr\u003e\r\nWe achieve the ssh proxy through the bastion server from our local machine by setting an ansible variable that specifies the location of the private ssh bastion key on our local machine, then by using the follow ansible command string:\r\n\u003cbr\u003e\r\n\u003cbr\u003e\r\n\r\n```sh\r\nProxyCommand=\"ssh -W %h:%p -q user@bastion ip address\"\r\n```\r\n\u003cbr\u003e\r\n\u003cbr\u003e\r\nThis command allows us to proxy ssh through the specified bastion ip address as the specified user on the condition that we have the correct path for the private key of the bastion server set as a variable.\r\n\u003cbr\u003e\r\n\u003cbr\u003e\r\n\r\n\u003ch2\u003e Ansible infrastructure diagram:\u003c/h2\u003e\r\n\r\n![](https://i.gyazo.com/71dc632d80a2600b0d27cbad32d82926.png)\r\n\r\nWe used ansible galaxy roles to define our configuration settings the roles used were:\r\n\r\n• Ping - The ping role is configured to ping the ansible host and check for the response \"pong\" and a hello from \"external ip address of host\" to display via ansible variable, This will confirm the successful exchange of packets and access to the virtual machine bash shell.\r\n\u003cbr\u003e\r\n\u003cbr\u003e\r\n• Kubectl - The kubectl role is configured to install the kubernetes kubectl package on each cluster node as well as the ci-cd server to allow infrastructure wide kubernetes cluster access management.\r\nIt will then display the installed version of kubectl as an ansible variable....\r\n\u003cbr\u003e\r\n\u003cbr\u003e\r\n• Aws-cli - The Aws-cli role is configured to install the amazon-web-services command line interface onto the ci-cd server to allow programmatic access via iam user to the virtual private cloud(vpc).\r\nIt will then display the installed version of Aws-cli as an ansible variable.\r\n\u003cbr\u003e\r\n\u003cbr\u003e\r\n• Jenkins - The jenkins role is configured to install the java openjdk dependency package then install, start and display the init admin password for jenkins as an ansible variable.\r\n\u003cbr\u003e\r\n\u003cbr\u003e\r\n\r\n### Pinging for packet exchange:\r\n\r\n![](https://i.gyazo.com/9dc5dd7675f59e7c74c8573402c2a362.png)\r\n\r\n### Checking bash shell access:\r\n\r\n![](https://i.gyazo.com/98536edf02041b8cfa018ff07a1dff0f.png)\r\n\r\n### Install kubectl package:\r\n\r\n![kube install](https://i.gyazo.com/f86737e01cd03cd7f01234928c8bac5d.png)\r\n\r\n### Checking installed kubectl package version:\r\n\r\n![kube version](https://i.gyazo.com/cb59342797904d3b35907acf238358f8.png)\r\n\r\n### Installing java openjdk dependency package:\r\n\r\n![install java](https://i.gyazo.com/508abbde02cf6e3b9625a3827644bab6.png)\r\n\r\n### Install, configure and start jenkins\r\n\r\n![install jenkins](https://i.gyazo.com/53be6f149a8c9739cb46e64290818a43.png)\r\n\r\n### Retrieve and display the jenkins init admin password:\r\n\r\n![](https://i.gyazo.com/c49ae6d3892903fa98dbf30ff610b4ad.png)\r\n\r\n### Install aws-cli package :\r\n\r\n![](https://i.gyazo.com/0717c68885d5346ad760c7127a86e3d5.png)\r\n\r\n### Checking  installed aws-cli package version\r\n\r\n![](https://i.gyazo.com/c44af90b2e7395afa26266251e4fa5df.png)\r\n\r\n## Kubernetes\r\n\r\nKubernetes is an open-source container orchestration platform that automates many of the manual processes involved in deploying, managing, and scaling containerized applications.\r\n\r\n### **Project**\r\n\r\nWe are going to deploy two applications using Kubernetes.\r\n \r\n1.**Frontend: React App**\r\n\r\n![enter image description here](https://trello-attachments.s3.amazonaws.com/605c6297d563636cdd8f5519/1132x856/2405866736f821220b365ebe88e5c21c/frontend.png)\r\n\r\n2.**Backend: FastAPI App**\r\n\r\n![enter image description here](https://trello-attachments.s3.amazonaws.com/605c6297d563636cdd8f5519/895x337/a9d28f506a7c638b7542faaeac37adc0/FastAPI.png)\r\n\r\n\u003e **How are we going to do it?**\r\n\r\n## **`Docker`** \r\n\r\n1) We will build the images of our two applications using Docker \u0026 Docker-Compose.\r\n\r\n- **Dockerfiles**\r\n\r\n![Backend_frontend.png](https://trello-attachments.s3.amazonaws.com/605c628b987ff1717da58164/605c6297d563636cdd8f5519/553e55064c6d78c9cbf80f9d88c01676/Backend_frontend.png)\r\n\r\n- **Docker-compose.yaml**\r\n\r\n![enter image description here](https://trello-attachments.s3.amazonaws.com/605c628b987ff1717da58164/605c6297d563636cdd8f5519/6447a2ef7bed4368ce778d63a52d90a9/docker_compose_yaml.png)\r\n\r\n## **`Kubernetes`**\r\n\r\n1) We will create a deployment/pod of the backend application:\r\n\r\n***Deployment / Pod - Backend***\r\n\r\n![enter image description here](https://trello-attachments.s3.amazonaws.com/605c6297d563636cdd8f5519/384x499/d7b7f65ed0c7e1ad3fb1b6c3940cbb72/backend_pod.png)\r\n\r\nIn order for this deployment to communicate continuously with the rest of the components of the cluster, we will create an internal service called backend-service.\r\n\r\n***Service - Backend***\r\n\r\n![enter image description here](https://trello-attachments.s3.amazonaws.com/605c6297d563636cdd8f5519/282x288/26e92c5efc71b5eff289982ca3ed66af/backend_service.png)\r\n\r\n\r\n2) We will do the same with our frontend application. Firstly, we will create a deployment/pod: \r\n\r\n***Deployment / Pod - Frontend***\r\n\r\n![enter image description here](https://trello-attachments.s3.amazonaws.com/605c6297d563636cdd8f5519/378x559/914654b19c4654b2b0477cce6db7f683/frontend_pod.png)\r\n\r\nSecondly, we will create an internal service (frontend - service). \r\n\r\n***Service - Frontend***\r\n\r\n![enter image description here](https://trello-attachments.s3.amazonaws.com/605c6297d563636cdd8f5519/280x289/de44732d84675ab93997f6f3f13bb6ea/frontend_service.png)\r\n\r\n3) The NGINX pod will be the component that joins the frontend application and the backend application.\r\n\r\n***Deployment / Pod - Nginx***\r\n\r\n![enter image description here](https://trello-attachments.s3.amazonaws.com/605c6297d563636cdd8f5519/421x643/8ae3bec2d4a745ecf674c8b77ca98061/nginx_pod.png)\r\n\r\nAll HTTP requests will go through the NGINX pod, but will then be sent to the correct service based on the requested URL.\r\n\r\nWe will keep the nginx configuration data separate from the application code, in a ConfigMap file.\r\n\r\n***ConfigMap - nginx-config*** \r\n\r\n![enter image description here](https://trello-attachments.s3.amazonaws.com/605c628b987ff1717da58164/605c6297d563636cdd8f5519/b4474b0488bdf156626d0fea76422671/configMap.png)\r\n\r\n4) Finally, we will need these two services that are deployed internally in Kubernetes, to be exposed to the outside world. To do this, we will create an external service (Load Balancer) that will allow our NGINX pod to receive external requests.\r\n\r\n***Service - Load Balancer***\r\n\r\n![enter image description here](https://trello-attachments.s3.amazonaws.com/605c6297d563636cdd8f5519/247x292/46f5f7785cfa214d0b3b68f05fc211ce/loadbalancer_service.png)\r\n\r\n![enter image description here](https://trello-attachments.s3.amazonaws.com/605c6297d563636cdd8f5519/1200x628/e98b5d0d820c4b10aa7d6814c6261f24/summary.jpeg.jpg)\r\n\r\n\r\n## **`Browser Request Flow through the Kubernetes Components`**\r\nThe request that will come from the browser, will go to the external service (Load Balancer) that will redirect it to the Nginx pod. The Nginx pod will send the request to the correct internal service (Frontend or Backend). From there, the request will be redirected to either the frontend or backend pod.\r\n\r\n![enter image description here](https://trello-attachments.s3.amazonaws.com/605c6297d563636cdd8f5519/1200x625/b5bc874c13ebd0bea60270d0ddcb35c9/requestworkflow.png)\r\n\r\nIn the event that the request goes to the backend application (backend pod), this pod will also communicate with a database that will be hosted on Amazon RDS.\r\n\r\n## Jenkins\r\n\r\nJenkins is a free and open source automation server. It helps automate the parts of software development related to building, testing, and deploying, facilitating continuous integration and continuous delivery. \r\n\r\nIt is a agent-based system that runs in servlet containers such as Apache Tomcat, it supports version control tools including AccuRev, CVS, Subversion and Git, jenkins can execute arbitrary shell scripts and Windows batch commands.\r\n\r\nIn this project jenkins was ultilised in an pipeline configuration with the use of github webhooks to orchestrate every step of automated product deployment, these stages were:\r\n\r\n\u003cbr\u003e\r\n\r\n![](https://github.com/GMCADevops/DevopsProject3/blob/Documentation/images/JenkinsPipeline.png)\r\n\r\n\u003cbr\u003e\r\n\r\n• Declarative Checkout SCM - The first stage triggered by a webhook is the source code management acquisition where jenkins will create a blank workspace and navigate to the github url repository clone it, switch into it and then checkout to the specified branch.\r\n\u003cbr\u003e\r\n\u003cbr\u003e\r\n• Testing - The second stage is the application testing stage where both the front-end and back-end will be testing using the specified bash testing script, test files and test tool.\r\n\u003cbr\u003e\r\n\u003cbr\u003e\r\n• Build Images - The third stage is the dockerization of the front-end and the back-end using the docker-compose.yaml to build the contents into a snapshop image with all the required dependencies to deploy the application as a container or pod.  \r\n\u003cbr\u003e\r\n• Push - The fourth stage push`s the docker images built in the previous stage to dockerhub. \r\n\u003cbr\u003e\r\n\u003cbr\u003e\r\n• Deployment - The fifth and final stage of the pipeline is to pulldown the previously built docker images from dockerhub, then deploy them in the terraform built kubernetes cluster using the bash deployment.sh script.\r\n\u003cbr\u003e\r\n\u003cbr\u003e\r\n\r\n\u003ch1\u003eSuccessful Pipeline build via github webhooks\u003c/h1\u003e\r\n\r\n![](https://i.gyazo.com/0d2d5c644fe89ca6b6370048fc9dabed.png)\r\n![](https://i.gyazo.com/b4c44f2fcf38bb4e09260fbd8cbb15a0.png)\r\n\r\n\u003ch1\u003eDeclarative Checkout SCM\u003c/h1\u003e\r\n\r\n![](https://i.gyazo.com/ec7fc30ab070a2d28611d52b48e7e5a7.png)\r\n\r\n\u003ch1\u003eTesting\u003c/h1\u003e\r\n\r\n![](https://i.gyazo.com/08875b0a04470758d4178e21ae3624ed.png)\r\n\r\n\u003ch1\u003eBuild Images\u003c/h1\u003e\r\n\r\n![](https://i.gyazo.com/7992a8948da0a7e8ddfc96539769477a.png)\r\n\r\n\u003ch1\u003ePush\u003c/h1\u003e\r\n\r\n![](https://i.gyazo.com/ec7ffb403425e1e7a5f9def2d4d8221e.png)\r\n\r\n\u003ch1\u003eDeployment\u003c/h1\u003e\r\n\r\n![](https://i.gyazo.com/1280f6c653d0ddf1563875cf4f95227e.png)\r\n\r\n## Improvements\r\n\r\nSome future things we could work on would be to introduce more tools, in hopes to lower complexity and achieve better security.\r\n\r\nWe were hoping to automated as much as possible within this project, one of the things we didn't manage because of time restraints were automating the snapshots of the jenkins ec2 instance, this was in hopes of saving its state.\r\n\r\nFor another future improvement we would liked to have tested the application before pushing the application but this was an external application with no tests for it, and with a very limited time frame testing wasn't an option we could do.\r\n\r\nFinally we would have liked to automate ansible for configuration, we decided later in the project that we wouldn't need ansible but we hoped we could still use it. The problem came when we realised the infrastructure in Terraform wouldn't support outputting private ip address' of an eks cluster by design.\r\n\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgmcadevops%2Fsfia-devops-project-3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgmcadevops%2Fsfia-devops-project-3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgmcadevops%2Fsfia-devops-project-3/lists"}