├── app ├── requirements.txt ├── static │ ├── logos │ │ ├── nti-logo.png │ │ └── ivolve-logo.png │ └── style.css ├── app.py ├── Dockerfile ├── README.md └── templates │ └── index.html ├── Ansible ├── roles │ ├── git │ │ ├── tests │ │ │ ├── inventory │ │ │ └── test.yml │ │ ├── vars │ │ │ └── main.yml │ │ ├── defaults │ │ │ └── main.yml │ │ ├── handlers │ │ │ └── main.yml │ │ ├── tasks │ │ │ └── main.yml │ │ ├── README.md │ │ └── meta │ │ │ └── main.yml │ ├── java │ │ ├── tests │ │ │ ├── inventory │ │ │ └── test.yml │ │ ├── vars │ │ │ └── main.yml │ │ ├── defaults │ │ │ └── main.yml │ │ ├── handlers │ │ │ └── main.yml │ │ ├── README.md │ │ ├── tasks │ │ │ └── main.yml │ │ └── meta │ │ │ └── main.yml │ ├── common │ │ ├── tests │ │ │ ├── inventory │ │ │ └── test.yml │ │ ├── vars │ │ │ └── main.yml │ │ ├── defaults │ │ │ └── main.yml │ │ ├── handlers │ │ │ └── main.yml │ │ ├── tasks │ │ │ └── main.yml │ │ ├── README.md │ │ └── meta │ │ │ └── main.yml │ ├── docker │ │ ├── tests │ │ │ ├── inventory │ │ │ └── test.yml │ │ ├── vars │ │ │ └── main.yml │ │ ├── defaults │ │ │ └── main.yml │ │ ├── handlers │ │ │ └── main.yml │ │ ├── tasks │ │ │ └── main.yml │ │ ├── README.md │ │ └── meta │ │ │ └── main.yml │ ├── jenkins │ │ ├── tests │ │ │ ├── inventory │ │ │ └── test.yml │ │ ├── defaults │ │ │ └── main.yml │ │ ├── vars │ │ │ └── main.yml │ │ ├── handlers │ │ │ └── main.yml │ │ ├── files │ │ │ └── jenkins.yaml │ │ ├── README.md │ │ ├── meta │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ └── kubeadm │ │ ├── tests │ │ ├── inventory │ │ └── test.yml │ │ ├── vars │ │ └── main.yml │ │ ├── defaults │ │ └── main.yml │ │ ├── handlers │ │ └── main.yml │ │ ├── tasks │ │ ├── main.yml │ │ ├── join_node.yml │ │ └── init_master.yml │ │ ├── README.md │ │ ├── meta │ │ └── main.yml │ │ └── files │ │ └── common-script.sh ├── assets │ ├── .DS_Store │ ├── pic1.png │ ├── pic11.png │ ├── pic2.png │ ├── pic5.png │ ├── pic6.png │ ├── pic7.png │ ├── pic8.png │ └── pic9.png ├── playbooks │ ├── jenkins-slave.yml │ ├── jenkins-master.yml │ ├── site.yaml │ └── kubeadm.yaml ├── inventory │ └── aws_ec2.yaml ├── ansible.cfg └── README.md ├── terraform ├── providers.tf ├── .gitignore ├── assets │ ├── .DS_Store │ ├── image.png │ ├── pic1.png │ ├── pic2.png │ ├── pic3.png │ ├── pic4.png │ ├── pic5.png │ └── pic6.png ├── backend.tf ├── terraform.tfvars ├── modules │ ├── network │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── main.tf │ └── compute │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── main.tf ├── variables.tf ├── outputs.tf ├── main.tf └── README.md ├── k8s-manifests ├── namespace.yaml ├── service.yaml └── deployment.yaml ├── ArgoCD ├── .DS_Store ├── assets │ ├── pic1.png │ ├── pic4.png │ ├── pic5.png │ ├── pic6.png │ ├── pic7.png │ ├── pic8.png │ ├── pic9.png │ ├── .DS_Store │ ├── image.png │ ├── pic10.png │ ├── pic11.png │ ├── pic12.png │ └── pic13.png └── README.md ├── Jenkins ├── .DS_Store ├── assets │ ├── .DS_Store │ ├── pic1.png │ ├── pic11.png │ ├── pic2.png │ ├── pic6.png │ ├── pic7.png │ └── pic8.png ├── jenkinsfile └── README.md └── README.md /app/requirements.txt: -------------------------------------------------------------------------------- 1 | flask -------------------------------------------------------------------------------- /Ansible/roles/git/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /Ansible/roles/java/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /Ansible/roles/common/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /Ansible/roles/docker/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /Ansible/roles/jenkins/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /Ansible/roles/kubeadm/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /Ansible/roles/git/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for roles/git 3 | -------------------------------------------------------------------------------- /Ansible/roles/java/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for roles/java 3 | -------------------------------------------------------------------------------- /Ansible/roles/common/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for roles/common 3 | -------------------------------------------------------------------------------- /Ansible/roles/docker/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for roles/docker 3 | -------------------------------------------------------------------------------- /Ansible/roles/git/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for roles/git 3 | -------------------------------------------------------------------------------- /Ansible/roles/git/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for roles/git 3 | -------------------------------------------------------------------------------- /Ansible/roles/kubeadm/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for roles/java 3 | -------------------------------------------------------------------------------- /Ansible/roles/common/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for roles/common 3 | -------------------------------------------------------------------------------- /Ansible/roles/common/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for roles/common 3 | -------------------------------------------------------------------------------- /Ansible/roles/docker/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for roles/docker 3 | -------------------------------------------------------------------------------- /Ansible/roles/docker/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for roles/docker 3 | -------------------------------------------------------------------------------- /Ansible/roles/java/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for roles/java 3 | -------------------------------------------------------------------------------- /Ansible/roles/java/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for roles/java 3 | -------------------------------------------------------------------------------- /Ansible/roles/kubeadm/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for roles/java 3 | -------------------------------------------------------------------------------- /Ansible/roles/kubeadm/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for roles/java 3 | -------------------------------------------------------------------------------- /terraform/providers.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.aws_region 3 | } 4 | -------------------------------------------------------------------------------- /Ansible/roles/jenkins/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for roles/jenkins 3 | -------------------------------------------------------------------------------- /Ansible/roles/jenkins/vars/main.yml: -------------------------------------------------------------------------------- 1 | jenkins_user: admin 2 | jenkins_password: admin123 3 | -------------------------------------------------------------------------------- /k8s-manifests/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: ivolve -------------------------------------------------------------------------------- /ArgoCD/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/.DS_Store -------------------------------------------------------------------------------- /Jenkins/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Jenkins/.DS_Store -------------------------------------------------------------------------------- /ArgoCD/assets/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/pic1.png -------------------------------------------------------------------------------- /ArgoCD/assets/pic4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/pic4.png -------------------------------------------------------------------------------- /ArgoCD/assets/pic5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/pic5.png -------------------------------------------------------------------------------- /ArgoCD/assets/pic6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/pic6.png -------------------------------------------------------------------------------- /ArgoCD/assets/pic7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/pic7.png -------------------------------------------------------------------------------- /ArgoCD/assets/pic8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/pic8.png -------------------------------------------------------------------------------- /ArgoCD/assets/pic9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/pic9.png -------------------------------------------------------------------------------- /terraform/.gitignore: -------------------------------------------------------------------------------- 1 | terraform.tfstate 2 | .terraform.lock.hcl 3 | .terraform/ 4 | terraform.tfstate.backup 5 | *.pem -------------------------------------------------------------------------------- /Ansible/assets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Ansible/assets/.DS_Store -------------------------------------------------------------------------------- /Ansible/assets/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Ansible/assets/pic1.png -------------------------------------------------------------------------------- /Ansible/assets/pic11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Ansible/assets/pic11.png -------------------------------------------------------------------------------- /Ansible/assets/pic2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Ansible/assets/pic2.png -------------------------------------------------------------------------------- /Ansible/assets/pic5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Ansible/assets/pic5.png -------------------------------------------------------------------------------- /Ansible/assets/pic6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Ansible/assets/pic6.png -------------------------------------------------------------------------------- /Ansible/assets/pic7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Ansible/assets/pic7.png -------------------------------------------------------------------------------- /Ansible/assets/pic8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Ansible/assets/pic8.png -------------------------------------------------------------------------------- /Ansible/assets/pic9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Ansible/assets/pic9.png -------------------------------------------------------------------------------- /Ansible/roles/git/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - roles/git 6 | -------------------------------------------------------------------------------- /Ansible/roles/java/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - roles/java 6 | -------------------------------------------------------------------------------- /ArgoCD/assets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/.DS_Store -------------------------------------------------------------------------------- /ArgoCD/assets/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/image.png -------------------------------------------------------------------------------- /ArgoCD/assets/pic10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/pic10.png -------------------------------------------------------------------------------- /ArgoCD/assets/pic11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/pic11.png -------------------------------------------------------------------------------- /ArgoCD/assets/pic12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/pic12.png -------------------------------------------------------------------------------- /ArgoCD/assets/pic13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/ArgoCD/assets/pic13.png -------------------------------------------------------------------------------- /Jenkins/assets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Jenkins/assets/.DS_Store -------------------------------------------------------------------------------- /Jenkins/assets/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Jenkins/assets/pic1.png -------------------------------------------------------------------------------- /Jenkins/assets/pic11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Jenkins/assets/pic11.png -------------------------------------------------------------------------------- /Jenkins/assets/pic2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Jenkins/assets/pic2.png -------------------------------------------------------------------------------- /Jenkins/assets/pic6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Jenkins/assets/pic6.png -------------------------------------------------------------------------------- /Jenkins/assets/pic7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Jenkins/assets/pic7.png -------------------------------------------------------------------------------- /Jenkins/assets/pic8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/Jenkins/assets/pic8.png -------------------------------------------------------------------------------- /Ansible/roles/common/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - roles/common 6 | -------------------------------------------------------------------------------- /Ansible/roles/docker/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - roles/docker 6 | -------------------------------------------------------------------------------- /Ansible/roles/jenkins/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - roles/jenkins 6 | -------------------------------------------------------------------------------- /Ansible/roles/kubeadm/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - roles/java 6 | -------------------------------------------------------------------------------- /terraform/assets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/terraform/assets/.DS_Store -------------------------------------------------------------------------------- /terraform/assets/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/terraform/assets/image.png -------------------------------------------------------------------------------- /terraform/assets/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/terraform/assets/pic1.png -------------------------------------------------------------------------------- /terraform/assets/pic2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/terraform/assets/pic2.png -------------------------------------------------------------------------------- /terraform/assets/pic3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/terraform/assets/pic3.png -------------------------------------------------------------------------------- /terraform/assets/pic4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/terraform/assets/pic4.png -------------------------------------------------------------------------------- /terraform/assets/pic5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/terraform/assets/pic5.png -------------------------------------------------------------------------------- /terraform/assets/pic6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/terraform/assets/pic6.png -------------------------------------------------------------------------------- /app/static/logos/nti-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/app/static/logos/nti-logo.png -------------------------------------------------------------------------------- /app/static/logos/ivolve-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahmoudAbdelnaser99/CloudDevOpsProject/HEAD/app/static/logos/ivolve-logo.png -------------------------------------------------------------------------------- /Ansible/roles/jenkins/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: restart jenkins 4 | service: 5 | name: jenkins 6 | state: restarted 7 | -------------------------------------------------------------------------------- /Ansible/playbooks/jenkins-slave.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Configure Jenkins Slave 3 | hosts: _jenkins_slave 4 | become: true 5 | roles: 6 | - common 7 | - git 8 | - java 9 | - docker 10 | -------------------------------------------------------------------------------- /Ansible/playbooks/jenkins-master.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Configure Jenkins Master 3 | hosts: _jenkins_master 4 | become: true 5 | roles: 6 | - common 7 | - git 8 | - java 9 | - docker 10 | - jenkins 11 | -------------------------------------------------------------------------------- /app/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | 3 | app = Flask(__name__) 4 | 5 | @app.route("/") 6 | def index(): 7 | return render_template("index.html") 8 | 9 | if __name__ == "__main__": 10 | app.run(host="0.0.0.0", port=5000) 11 | 12 | -------------------------------------------------------------------------------- /k8s-manifests/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: ivolve-service 5 | namespace: ivolve 6 | spec: 7 | selector: 8 | app: ivolve-app 9 | ports: 10 | - port: 80 11 | targetPort: 5000 12 | type: NodePort 13 | -------------------------------------------------------------------------------- /terraform/backend.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "jenkins12345-terraform-state" 4 | key = "cloud-devops/terraform.tfstate" 5 | region = "us-east-1" 6 | //dynamodb_table = "terraform-state-lock" 7 | } 8 | } 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Ansible/roles/kubeadm/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Upload common setup script 4 | copy: 5 | src: common-script.sh 6 | dest: /tmp/common-script.sh 7 | mode: 0755 8 | 9 | - name: Run common setup script 10 | command: bash /tmp/common-script.sh 11 | args: 12 | creates: /usr/bin/kubeadm 13 | -------------------------------------------------------------------------------- /Ansible/inventory/aws_ec2.yaml: -------------------------------------------------------------------------------- 1 | plugin: aws_ec2 2 | regions: 3 | - us-east-1 4 | 5 | keyed_groups: 6 | - key: tags.Name 7 | prefix: "" 8 | 9 | filters: 10 | tag:Name: 11 | - "jenkins-master" 12 | - "jenkins-slave" 13 | - "kubemaster" 14 | - "kubenode1" 15 | 16 | 17 | compose: 18 | ansible_host: public_ip_address 19 | 20 | -------------------------------------------------------------------------------- /Ansible/roles/kubeadm/tasks/join_node.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Set hostname 4 | command: hostnamectl set-hostname node1 5 | 6 | - name: Reboot the node gracefully 7 | reboot: 8 | reboot_timeout: 600 9 | 10 | - name: Join the node to the Kubernetes cluster 11 | shell: "{{ hostvars[groups['_kubemaster'][0]].kubeadm_join_cmd }} --ignore-preflight-errors=all" 12 | -------------------------------------------------------------------------------- /app/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use Python base image 2 | FROM python:3.10-slim 3 | 4 | # Set working directory 5 | WORKDIR /app 6 | 7 | # Copy requirements and install 8 | COPY requirements.txt . 9 | RUN pip install --no-cache-dir -r requirements.txt 10 | 11 | # Copy app code 12 | COPY . . 13 | 14 | # Expose the port 15 | EXPOSE 5000 16 | 17 | # Run the Flask app 18 | CMD ["python", "app.py"] 19 | -------------------------------------------------------------------------------- /terraform/terraform.tfvars: -------------------------------------------------------------------------------- 1 | aws_region = "us-east-1" 2 | project_name = "ivolve" 3 | vpc_cidr = "10.0.0.0/16" 4 | 5 | 6 | subnet_cidr = ["10.0.1.0/24", "10.0.2.0/24"] 7 | az = ["us-east-1a", "us-east-1b"] 8 | instance_type = "t3.medium" 9 | key_name = "jenkins-key" 10 | ami_id = "ami-0a7d80731ae1b2435" 11 | -------------------------------------------------------------------------------- /Ansible/playbooks/site.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Configure Jenkins Master 3 | hosts: _jenkins_master 4 | become: true 5 | roles: 6 | - common 7 | - git 8 | - java 9 | - docker 10 | - jenkins 11 | 12 | - name: Configure Jenkins Slave 13 | hosts: _jenkins_slave 14 | become: true 15 | roles: 16 | - common 17 | - git 18 | - java 19 | - docker 20 | 21 | -------------------------------------------------------------------------------- /Ansible/roles/jenkins/files/jenkins.yaml: -------------------------------------------------------------------------------- 1 | jenkins: 2 | systemMessage: "🚀 Configured by Ansible + JCasC" 3 | securityRealm: 4 | local: 5 | allowsSignup: false 6 | users: 7 | - id: "{{ jenkins_admin_user }}" 8 | password: "{{ jenkins_admin_password }}" 9 | authorizationStrategy: 10 | loggedInUsersCanDoAnything: 11 | allowAnonymousRead: false 12 | -------------------------------------------------------------------------------- /terraform/modules/network/outputs.tf: -------------------------------------------------------------------------------- 1 | 2 | output "vpc_id" { 3 | description = "ID of the VPC" 4 | value = aws_vpc.main.id 5 | } 6 | 7 | output "public_subnet_ids" { 8 | description = "IDs of public subnets" 9 | value = aws_subnet.public[*].id 10 | } 11 | 12 | output "internet_gateway_id" { 13 | description = "ID of the Internet Gateway" 14 | value = aws_internet_gateway.igw.id 15 | } -------------------------------------------------------------------------------- /Ansible/roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Update apt cache 3 | apt: 4 | update_cache: yes 5 | cache_valid_time: 3600 6 | 7 | - name: Install common packages 8 | apt: 9 | name: 10 | - wget 11 | - curl 12 | - unzip 13 | - ca-certificates 14 | - tar 15 | - python3 16 | - python3-pip 17 | state: present 18 | 19 | - name: Set timezone 20 | community.general.timezone: 21 | name: UTC 22 | -------------------------------------------------------------------------------- /Ansible/roles/git/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Git 3 | become: yes 4 | apt: 5 | name: git 6 | state: present 7 | update_cache: yes 8 | 9 | - name: Configure Git global settings 10 | become: yes 11 | git_config: 12 | name: "{{ item.name }}" 13 | value: "{{ item.value }}" 14 | scope: system 15 | loop: 16 | - { name: "credential.helper", value: "cache --timeout=3600" } 17 | - { name: "core.fileMode", value: "false" } 18 | 19 | -------------------------------------------------------------------------------- /Ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = ./inventory/aws_ec2.yaml 3 | remote_user = ubuntu 4 | private_key_file = ~/.ssh/jenkins-key.pem 5 | host_key_checking = False 6 | gathering = smart 7 | roles_path = roles 8 | retry_files_enabled = False 9 | allow_world_readable_tmpfiles = true 10 | 11 | 12 | [inventory] 13 | enable_plugins = aws_ec2 14 | 15 | [privilege_escalation] 16 | become = True 17 | become_method = sudo 18 | become_user = root 19 | become_ask_pass = False 20 | -------------------------------------------------------------------------------- /terraform/modules/network/variables.tf: -------------------------------------------------------------------------------- 1 | variable "project_name" { 2 | description = "Name of the project" 3 | type = string 4 | } 5 | 6 | variable "vpc_cidr" { 7 | description = "CIDR block for VPC" 8 | type = string 9 | } 10 | 11 | variable "subnet_cidr" { 12 | description = "CIDR blocks for public subnets" 13 | type = list(string) 14 | } 15 | 16 | variable "az" { 17 | description = "Availability zones" 18 | type = list(string) 19 | } 20 | -------------------------------------------------------------------------------- /k8s-manifests/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: ivolve-app 5 | namespace: ivolve 6 | spec: 7 | replicas: 2 8 | selector: 9 | matchLabels: 10 | app: ivolve-app 11 | template: 12 | metadata: 13 | labels: 14 | app: ivolve-app 15 | spec: 16 | containers: 17 | - name: app 18 | image: mahmoudabdelnaser99/ivolve-app:latest 19 | ports: 20 | - containerPort: 5000 21 | -------------------------------------------------------------------------------- /Ansible/playbooks/kubeadm.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Run common setup script on all EC2s 4 | hosts: 5 | - _kubemaster 6 | _kubenode1 7 | become: true 8 | roles: 9 | - role: kubeadm 10 | 11 | - name: Initialize Kubernetes master 12 | hosts: _kubemaster 13 | become: true 14 | tasks: 15 | - name: Import init_master tasks 16 | import_role: 17 | name: kubeadm 18 | tasks_from: init_master 19 | 20 | - name: Join worker nodes to cluster 21 | hosts: _kubenode1 22 | become: true 23 | tasks: 24 | - name: Import join_node tasks 25 | import_role: 26 | name: kubeadm 27 | tasks_from: join_node 28 | -------------------------------------------------------------------------------- /app/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |      4 | 5 |

6 | 7 |

8 | DevOps Graduation Project 9 |

10 | 11 |

12 | In Collaboration with iVolve Technologies 13 |

14 | 15 |

16 | This project represents the culmination of the DevOps training at the National Telecommunication Institute (NTI), 17 | in partnership with iVolve Technologies. 18 |

19 | 20 | --- 21 | 22 | -------------------------------------------------------------------------------- /terraform/modules/compute/outputs.tf: -------------------------------------------------------------------------------- 1 | 2 | 3 | output "security_group_id" { 4 | description = "ID of the EC2 security group" 5 | value = aws_security_group.app.id 6 | } 7 | 8 | output "instance_ids" { 9 | description = "IDs of EC2 instances" 10 | value = aws_instance.app[*].id 11 | } 12 | 13 | output "instance_public_ips" { 14 | description = "Public IPs of EC2 instances" 15 | value = aws_instance.app[*].public_ip 16 | } 17 | output "instance_private_ips" { 18 | description = "Public IPs of EC2 instances" 19 | value = aws_instance.app[*].private_ip 20 | } 21 | output "cloudwatch_alarm_arns" { 22 | description = "ARNs of CloudWatch alarms" 23 | value = aws_cloudwatch_metric_alarm.ec2_cpu[*].arn 24 | } 25 | 26 | output "sns_topic_arn" { 27 | description = "ARN of the SNS topic" 28 | value = aws_sns_topic.alerts.arn 29 | } -------------------------------------------------------------------------------- /terraform/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | description = "AWS region" 3 | type = string 4 | default = "us-east-1" 5 | } 6 | 7 | variable "project_name" { 8 | description = "Name of the project" 9 | type = string 10 | } 11 | 12 | variable "vpc_cidr" { 13 | description = "CIDR block for VPC" 14 | type = string 15 | } 16 | 17 | variable "subnet_cidr" { 18 | description = "CIDR blocks for public subnets" 19 | type = list(string) 20 | } 21 | 22 | variable "az" { 23 | description = "Availability zones" 24 | type = list(string) 25 | } 26 | 27 | 28 | 29 | variable "instance_type" { 30 | description = "EC2 instance type" 31 | type = string 32 | } 33 | 34 | variable "key_name" { 35 | description = "Name of the SSH key pair" 36 | type = string 37 | } 38 | variable "ami_id" { 39 | type = string 40 | default = "ami-084568db4383264d4" 41 | } 42 | -------------------------------------------------------------------------------- /terraform/modules/compute/variables.tf: -------------------------------------------------------------------------------- 1 | variable "project_name" { 2 | description = "Name of the project" 3 | type = string 4 | } 5 | 6 | variable "vpc_id" { 7 | description = "ID of the VPC" 8 | type = string 9 | } 10 | 11 | variable "instance_type" { 12 | description = "EC2 instance type" 13 | type = string 14 | } 15 | 16 | variable "subnet_id" { 17 | description = "IDs of subnets" 18 | type = list(string) 19 | } 20 | 21 | variable "ami_id" { 22 | description = "UBUNTU" 23 | type = string 24 | default = "ami-08a6efd148b1f7504" # Update for your region 25 | } 26 | 27 | variable "key_name" { 28 | description = "Name of the SSH key pair" 29 | type = string 30 | } 31 | 32 | variable "instance_count" { 33 | description = "Number of EC2 instances" 34 | type = number 35 | default = 4 36 | } 37 | 38 | variable "instance_names" { 39 | default = { 40 | 0 = "jenkins-master" 41 | 1 = "jenkins-slave" 42 | 2 = "kubemaster" 43 | 3 = "kubenode1" 44 | } 45 | } -------------------------------------------------------------------------------- /terraform/outputs.tf: -------------------------------------------------------------------------------- 1 | output "vpc_id" { 2 | description = "ID of the VPC" 3 | value = module.network.vpc_id 4 | } 5 | 6 | output "public_subnet_ids" { 7 | description = "IDs of public subnets" 8 | value = module.network.public_subnet_ids 9 | } 10 | 11 | output "security_group_id" { 12 | description = "ID of the EC2 security group" 13 | value = module.compute.security_group_id 14 | } 15 | 16 | output "instance_ids" { 17 | description = "IDs of EC2 instances" 18 | value = module.compute.instance_ids 19 | } 20 | 21 | output "instance_public_ips" { 22 | description = "Public IPs of EC2 instances" 23 | value = module.compute.instance_public_ips 24 | } 25 | output "instance_private_ips" { 26 | description = "Public IPs of EC2 instances" 27 | value = module.compute.instance_private_ips 28 | } 29 | output "cloudwatch_dashboard_url" { 30 | description = "URL of the CloudWatch dashboard" 31 | value = "https://${var.aws_region}.console.aws.amazon.com/cloudwatch/home?region=${var.aws_region}#dashboards:name=${aws_cloudwatch_dashboard.main.dashboard_name}" 32 | } -------------------------------------------------------------------------------- /Ansible/roles/docker/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install required packages 3 | become: yes 4 | apt: 5 | name: 6 | - apt-transport-https 7 | - ca-certificates 8 | - curl 9 | - software-properties-common 10 | state: present 11 | update_cache: yes 12 | 13 | - name: Add Docker GPG key 14 | become: yes 15 | apt_key: 16 | url: https://download.docker.com/linux/ubuntu/gpg 17 | state: present 18 | 19 | - name: Add Docker APT repository 20 | become: yes 21 | apt_repository: 22 | repo: deb https://download.docker.com/linux/ubuntu focal stable 23 | state: present 24 | 25 | - name: Install Docker and Docker Compose Plugin 26 | become: yes 27 | apt: 28 | name: 29 | - docker-ce 30 | - docker-ce-cli 31 | - containerd.io 32 | - docker-compose-plugin 33 | state: present 34 | update_cache: yes 35 | 36 | - name: Start and enable Docker service 37 | become: yes 38 | systemd: 39 | name: docker 40 | state: started 41 | enabled: yes 42 | 43 | - name: Create docker group 44 | become: yes 45 | group: 46 | name: docker 47 | state: present 48 | 49 | - name: Add ubuntu user to docker group 50 | become: yes 51 | user: 52 | name: ubuntu 53 | groups: docker 54 | append: yes 55 | 56 | -------------------------------------------------------------------------------- /app/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NTI x iVolve Graduation Project 6 | 7 | 8 | 9 | 10 |
11 |
12 |

DevOps Graduation Project

13 |

In Collaboration with iVolve Technologies

14 |
15 | 16 | 17 |
18 |

19 | This project represents the culmination of the DevOps training track at the National Telecommunication Institute (NTI), in partnership with iVolve Technologies. 20 |

21 |
22 | 25 |
26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Ansible/roles/git/README.md: -------------------------------------------------------------------------------- 1 | Role Name 2 | ========= 3 | 4 | A brief description of the role goes here. 5 | 6 | Requirements 7 | ------------ 8 | 9 | Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. 10 | 11 | Role Variables 12 | -------------- 13 | 14 | A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. 15 | 16 | Dependencies 17 | ------------ 18 | 19 | A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. 20 | 21 | Example Playbook 22 | ---------------- 23 | 24 | Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: 25 | 26 | - hosts: servers 27 | roles: 28 | - { role: username.rolename, x: 42 } 29 | 30 | License 31 | ------- 32 | 33 | BSD 34 | 35 | Author Information 36 | ------------------ 37 | 38 | An optional section for the role authors to include contact information, or a website (HTML is not allowed). 39 | -------------------------------------------------------------------------------- /Ansible/roles/java/README.md: -------------------------------------------------------------------------------- 1 | Role Name 2 | ========= 3 | 4 | A brief description of the role goes here. 5 | 6 | Requirements 7 | ------------ 8 | 9 | Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. 10 | 11 | Role Variables 12 | -------------- 13 | 14 | A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. 15 | 16 | Dependencies 17 | ------------ 18 | 19 | A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. 20 | 21 | Example Playbook 22 | ---------------- 23 | 24 | Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: 25 | 26 | - hosts: servers 27 | roles: 28 | - { role: username.rolename, x: 42 } 29 | 30 | License 31 | ------- 32 | 33 | BSD 34 | 35 | Author Information 36 | ------------------ 37 | 38 | An optional section for the role authors to include contact information, or a website (HTML is not allowed). 39 | -------------------------------------------------------------------------------- /Ansible/roles/common/README.md: -------------------------------------------------------------------------------- 1 | Role Name 2 | ========= 3 | 4 | A brief description of the role goes here. 5 | 6 | Requirements 7 | ------------ 8 | 9 | Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. 10 | 11 | Role Variables 12 | -------------- 13 | 14 | A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. 15 | 16 | Dependencies 17 | ------------ 18 | 19 | A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. 20 | 21 | Example Playbook 22 | ---------------- 23 | 24 | Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: 25 | 26 | - hosts: servers 27 | roles: 28 | - { role: username.rolename, x: 42 } 29 | 30 | License 31 | ------- 32 | 33 | BSD 34 | 35 | Author Information 36 | ------------------ 37 | 38 | An optional section for the role authors to include contact information, or a website (HTML is not allowed). 39 | -------------------------------------------------------------------------------- /Ansible/roles/docker/README.md: -------------------------------------------------------------------------------- 1 | Role Name 2 | ========= 3 | 4 | A brief description of the role goes here. 5 | 6 | Requirements 7 | ------------ 8 | 9 | Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. 10 | 11 | Role Variables 12 | -------------- 13 | 14 | A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. 15 | 16 | Dependencies 17 | ------------ 18 | 19 | A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. 20 | 21 | Example Playbook 22 | ---------------- 23 | 24 | Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: 25 | 26 | - hosts: servers 27 | roles: 28 | - { role: username.rolename, x: 42 } 29 | 30 | License 31 | ------- 32 | 33 | BSD 34 | 35 | Author Information 36 | ------------------ 37 | 38 | An optional section for the role authors to include contact information, or a website (HTML is not allowed). 39 | -------------------------------------------------------------------------------- /Ansible/roles/jenkins/README.md: -------------------------------------------------------------------------------- 1 | Role Name 2 | ========= 3 | 4 | A brief description of the role goes here. 5 | 6 | Requirements 7 | ------------ 8 | 9 | Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. 10 | 11 | Role Variables 12 | -------------- 13 | 14 | A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. 15 | 16 | Dependencies 17 | ------------ 18 | 19 | A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. 20 | 21 | Example Playbook 22 | ---------------- 23 | 24 | Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: 25 | 26 | - hosts: servers 27 | roles: 28 | - { role: username.rolename, x: 42 } 29 | 30 | License 31 | ------- 32 | 33 | BSD 34 | 35 | Author Information 36 | ------------------ 37 | 38 | An optional section for the role authors to include contact information, or a website (HTML is not allowed). 39 | -------------------------------------------------------------------------------- /Ansible/roles/kubeadm/README.md: -------------------------------------------------------------------------------- 1 | Role Name 2 | ========= 3 | 4 | A brief description of the role goes here. 5 | 6 | Requirements 7 | ------------ 8 | 9 | Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. 10 | 11 | Role Variables 12 | -------------- 13 | 14 | A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. 15 | 16 | Dependencies 17 | ------------ 18 | 19 | A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. 20 | 21 | Example Playbook 22 | ---------------- 23 | 24 | Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: 25 | 26 | - hosts: servers 27 | roles: 28 | - { role: username.rolename, x: 42 } 29 | 30 | License 31 | ------- 32 | 33 | BSD 34 | 35 | Author Information 36 | ------------------ 37 | 38 | An optional section for the role authors to include contact information, or a website (HTML is not allowed). 39 | -------------------------------------------------------------------------------- /terraform/modules/network/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_vpc" "main" { 2 | cidr_block = var.vpc_cidr 3 | enable_dns_support = true 4 | enable_dns_hostnames = true 5 | tags = { 6 | Name = "devops-vpc" 7 | Project = var.project_name 8 | } 9 | } 10 | 11 | resource "aws_internet_gateway" "igw" { 12 | vpc_id = aws_vpc.main.id 13 | 14 | tags = { 15 | Name = "${var.project_name}-igw" 16 | Project = var.project_name 17 | } 18 | } 19 | 20 | resource "aws_subnet" "public" { 21 | count = length(var.subnet_cidr) 22 | vpc_id = aws_vpc.main.id 23 | cidr_block = var.subnet_cidr[count.index] 24 | availability_zone = var.az[count.index] 25 | map_public_ip_on_launch = true 26 | 27 | tags = { 28 | Name = "${var.project_name}-public-subnet-${count.index + 1}" 29 | Project = var.project_name 30 | } 31 | } 32 | 33 | # resource "aws_network_acl" "public" { 34 | # vpc_id = aws_vpc.main.id 35 | # subnet_ids = [aws_subnet.public.id] 36 | 37 | # tags = { 38 | # Name = "${var.project_name}-public-acl" 39 | # } 40 | # } 41 | 42 | resource "aws_route_table" "public" { 43 | vpc_id = aws_vpc.main.id 44 | 45 | route { 46 | cidr_block = "0.0.0.0/0" 47 | gateway_id = aws_internet_gateway.igw.id 48 | } 49 | 50 | tags = { 51 | Name = "${var.project_name}-public-rt" 52 | Project = var.project_name 53 | } 54 | } 55 | 56 | resource "aws_route_table_association" "public_assoc" { 57 | count = length(var.subnet_cidr) 58 | subnet_id = aws_subnet.public[count.index].id 59 | route_table_id = aws_route_table.public.id 60 | } -------------------------------------------------------------------------------- /app/static/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: 'Poppins', sans-serif; 4 | background: linear-gradient(to right, #0f2027, #203a43, #2c5364); 5 | color: #fff; 6 | display: flex; 7 | justify-content: center; 8 | align-items: center; 9 | height: 100vh; 10 | overflow: hidden; 11 | } 12 | 13 | .container { 14 | text-align: center; 15 | max-width: 900px; 16 | padding: 20px; 17 | animation: fadeIn 2s ease-in-out; 18 | } 19 | 20 | .content { 21 | animation: zoomIn 1.5s ease; 22 | } 23 | 24 | .title { 25 | font-size: 3em; 26 | font-weight: 600; 27 | margin-bottom: 10px; 28 | color: #e0e0e0; 29 | } 30 | 31 | .subtitle { 32 | font-size: 1.5em; 33 | font-weight: 300; 34 | margin-bottom: 30px; 35 | color: #b0bec5; 36 | } 37 | 38 | .logos { 39 | display: flex; 40 | justify-content: center; 41 | gap: 60px; 42 | margin-bottom: 30px; 43 | } 44 | 45 | .logo { 46 | height: 100px; 47 | transition: transform 0.3s ease; 48 | } 49 | 50 | .logo:hover { 51 | transform: scale(1.1); 52 | } 53 | 54 | .description { 55 | font-size: 1.2em; 56 | color: #cfd8dc; 57 | margin-bottom: 40px; 58 | } 59 | 60 | footer { 61 | font-size: 0.9em; 62 | color: #90a4ae; 63 | margin-top: 20px; 64 | } 65 | 66 | /* Animations */ 67 | @keyframes fadeIn { 68 | 0% {opacity: 0;} 69 | 100% {opacity: 1;} 70 | } 71 | 72 | @keyframes zoomIn { 73 | 0% {transform: scale(0.9);} 74 | 100% {transform: scale(1);} 75 | } 76 | 77 | /* Responsive */ 78 | @media (max-width: 768px) { 79 | .logos { 80 | flex-direction: column; 81 | gap: 20px; 82 | } 83 | 84 | .logo { 85 | height: 80px; 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /Ansible/roles/java/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Java dependencies 3 | apt: 4 | name: 5 | - apt-transport-https 6 | - ca-certificates 7 | - wget 8 | - gnupg 9 | state: present 10 | 11 | - name: Check if Java is already installed 12 | command: java -version 13 | register: java_check 14 | failed_when: false 15 | changed_when: false 16 | ignore_errors: yes 17 | 18 | - name: Add Adoptium key 19 | apt_key: 20 | url: https://packages.adoptium.net/artifactory/api/gpg/key/public 21 | state: present 22 | when: java_check.rc != 0 23 | 24 | - name: Get Ubuntu version 25 | command: lsb_release -cs 26 | register: ubuntu_codename 27 | changed_when: false 28 | 29 | - name: Add Adoptium repository 30 | apt_repository: 31 | repo: "deb https://packages.adoptium.net/artifactory/deb {{ ubuntu_codename.stdout }} main" 32 | state: present 33 | filename: adoptium 34 | when: java_check.rc != 0 35 | 36 | - name: Update apt cache 37 | apt: 38 | update_cache: yes 39 | when: java_check.rc != 0 40 | 41 | - name: Install Java 17 42 | apt: 43 | name: temurin-17-jdk 44 | state: present 45 | when: java_check.rc != 0 46 | 47 | - name: Find Java home directory 48 | shell: update-alternatives --display java | grep 'link currently points to' | awk '{print $NF}' | sed 's/\/bin\/java$//' 49 | register: java_home_cmd 50 | changed_when: false 51 | 52 | - name: Set JAVA_HOME environment variable 53 | lineinfile: 54 | path: /etc/environment 55 | line: 'JAVA_HOME="{{ java_home_cmd.stdout }}"' 56 | state: present 57 | create: yes 58 | 59 | - name: Make JAVA_HOME available for current session 60 | shell: | 61 | export JAVA_HOME="{{ java_home_cmd.stdout }}" 62 | export PATH=$PATH:$JAVA_HOME/bin 63 | args: 64 | executable: /bin/bash 65 | -------------------------------------------------------------------------------- /Ansible/roles/git/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /Ansible/roles/java/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /Ansible/roles/common/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /Ansible/roles/docker/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /Ansible/roles/jenkins/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /Ansible/roles/kubeadm/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /Ansible/roles/kubeadm/tasks/init_master.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Initialize kubeadm on master 3 | command: kubeadm init --pod-network-cidr=10.244.0.0/16 4 | register: kubeadm_output 5 | changed_when: "'initialized' in kubeadm_output.stdout" 6 | args: 7 | creates: /etc/kubernetes/admin.conf 8 | 9 | 10 | - name: Set hostname to master 11 | hostname: 12 | name: master 13 | 14 | - name: Create .kube directory 15 | file: 16 | path: "{{ ansible_env.HOME }}/.kube" 17 | state: directory 18 | mode: '0755' 19 | 20 | - name: Copy admin.conf to user's kube config 21 | copy: 22 | src: /etc/kubernetes/admin.conf 23 | dest: "{{ ansible_env.HOME }}/.kube/config" 24 | remote_src: yes 25 | owner: "{{ ansible_user }}" 26 | group: "{{ ansible_user }}" 27 | 28 | - name: Apply Flannel CNI plugin 29 | shell: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml 30 | args: 31 | creates: /run/flannel/subnet.env # Only runs if flannel is not already installed 32 | 33 | - name: Ensure kubectl bash completion is in .bashrc 34 | lineinfile: 35 | path: ~/.bashrc 36 | line: "source <(kubectl completion bash)" 37 | state: present 38 | 39 | - name: Add kubectl alias to .bashrc 40 | lineinfile: 41 | path: ~/.bashrc 42 | line: "alias k=kubectl" 43 | state: present 44 | 45 | - name: Add kubectl completion alias 46 | lineinfile: 47 | path: ~/.bashrc 48 | line: "complete -F __start_kubectl k" 49 | state: present 50 | 51 | 52 | 53 | - name: Generate kubeadm join command 54 | command: kubeadm token create --print-join-command 55 | register: join_command_output 56 | delegate_to: "{{ groups['_kubemaster'][0] }}" 57 | 58 | - name: Set join command fact on master 59 | set_fact: 60 | kubeadm_join_cmd: "{{ join_command_output.stdout }}" 61 | delegate_to: "{{ groups['_kubemaster'][0] }}" 62 | -------------------------------------------------------------------------------- /terraform/main.tf: -------------------------------------------------------------------------------- 1 | module "network" { 2 | project_name = var.project_name 3 | source = "./modules/network" 4 | vpc_cidr = var.vpc_cidr 5 | subnet_cidr = var.subnet_cidr 6 | az = var.az 7 | } 8 | 9 | 10 | module "compute" { 11 | source = "./modules/compute" 12 | project_name = var.project_name 13 | subnet_id = module.network.public_subnet_ids 14 | vpc_id = module.network.vpc_id 15 | ami_id = var.ami_id 16 | instance_type = var.instance_type 17 | key_name = var.key_name 18 | instance_count = 4 19 | } 20 | 21 | 22 | 23 | 24 | # Create CloudWatch dashboard 25 | resource "aws_cloudwatch_dashboard" "main" { 26 | dashboard_name = "${var.project_name}-dashboard" 27 | 28 | dashboard_body = jsonencode({ 29 | widgets = [ 30 | { 31 | type = "metric" 32 | x = 0 33 | y = 0 34 | width = 12 35 | height = 6 36 | properties = { 37 | metrics = [ 38 | ["AWS/EC2", "CPUUtilization", "InstanceId", module.compute.instance_ids[0]], 39 | ["AWS/EC2", "CPUUtilization", "InstanceId", module.compute.instance_ids[1]] 40 | ] 41 | period = 300 42 | stat = "Average" 43 | region = var.aws_region 44 | title = "EC2 CPU Utilization" 45 | } 46 | }, 47 | { 48 | type = "metric" 49 | x = 12 50 | y = 0 51 | width = 12 52 | height = 6 53 | properties = { 54 | metrics = [ 55 | ["AWS/EC2", "NetworkIn", "InstanceId", module.compute.instance_ids[0]], 56 | ["AWS/EC2", "NetworkIn", "InstanceId", module.compute.instance_ids[1]] 57 | ] 58 | period = 300 59 | stat = "Average" 60 | region = var.aws_region 61 | title = "EC2 Network In" 62 | } 63 | } 64 | ] 65 | }) 66 | } 67 | 68 | -------------------------------------------------------------------------------- /Jenkins/jenkinsfile: -------------------------------------------------------------------------------- 1 | @Library('sharedlib') _ 2 | 3 | pipeline { 4 | agent { label 'slave' } 5 | 6 | environment { 7 | APP_NAME = 'ivolve-webapp' 8 | DOCKER_REGISTRY = 'docker.io' 9 | DOCKER_IMAGE = 'elkhawaga/ivolve-webapp' 10 | DOCKER_CREDENTIALS_ID = 'docker' 11 | GIT_CREDENTIALS_ID = 'github' 12 | MANIFEST_REPO = 'https://github.com/mahmoudAbdelnaser99/CloudDevOpsProject.git' 13 | IMAGE_TAG = "${BUILD_NUMBER}" 14 | REPO_NAME = 'CloudDevOpsProject' 15 | GIT_USERNAME = 'mahmoudAbdelnaser99' 16 | EMAIL = 'mahmoudabdelnaser309@gmail.com' 17 | DEPLOYMENT = 'ivolve-deployment' 18 | } 19 | 20 | stages { 21 | stage('Clone App') { 22 | steps { 23 | git url: "${MANIFEST_REPO}", branch: 'main' 24 | } 25 | } 26 | 27 | stage('Build Docker Image') { 28 | steps { 29 | buildApp('./app', "${DOCKER_IMAGE}:${IMAGE_TAG}") 30 | } 31 | } 32 | 33 | stage('Push to DockerHub') { 34 | steps { 35 | pushImage("${DOCKER_IMAGE}:${IMAGE_TAG}", "${DOCKER_IMAGE}:${IMAGE_TAG}", "${DOCKER_CREDENTIALS_ID}") 36 | } 37 | } 38 | 39 | stage('Scan Docker Image') { 40 | steps { 41 | scanImage("${DOCKER_IMAGE}:${IMAGE_TAG}") 42 | } 43 | } 44 | 45 | stage('Delete Local Docker Image') { 46 | steps { 47 | sh "docker rmi ${DOCKER_IMAGE}:${IMAGE_TAG} || true" 48 | } 49 | } 50 | 51 | stage('Update Kubernetes Manifest') { 52 | steps { 53 | updateManifest('k8s-manifests/deployment.yaml', "${DOCKER_IMAGE}:${IMAGE_TAG}") 54 | } 55 | } 56 | 57 | stage('Push Manifest to GitHub') { 58 | steps { 59 | pushManifest("${EMAIL}", "${GIT_USERNAME}", "${GIT_CREDENTIALS_ID}", "${REPO_NAME}", "${IMAGE_TAG}") 60 | } 61 | } 62 | } 63 | 64 | post { 65 | always { 66 | cleanWs() 67 | } 68 | success { 69 | echo "Pipeline completed successfully!" 70 | } 71 | failure { 72 | echo "Pipeline failed!" 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /terraform/modules/compute/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "app" { 2 | name = "${var.project_name}-app-sg" 3 | description = "Security group for application instances" 4 | vpc_id = var.vpc_id 5 | 6 | dynamic "ingress" { 7 | for_each = [22, 80, 443, 8080, 5000 ] 8 | content { 9 | from_port = ingress.value 10 | to_port = ingress.value 11 | protocol = "tcp" 12 | cidr_blocks = ["0.0.0.0/0"] 13 | } 14 | } 15 | 16 | egress { 17 | from_port = 0 18 | to_port = 0 19 | protocol = "-1" 20 | cidr_blocks = ["0.0.0.0/0"] 21 | } 22 | 23 | tags = { 24 | Name = "${var.project_name}-app-sg" 25 | Project = var.project_name 26 | } 27 | } 28 | 29 | 30 | 31 | data "aws_ami" "amazon_linux" { 32 | most_recent = true 33 | owners = ["amazon"] 34 | 35 | filter { 36 | name = "name" 37 | values = ["amzn2-ami-hvm-*-x86_64-gp2"] 38 | } 39 | 40 | filter { 41 | name = "virtualization-type" 42 | values = ["hvm"] 43 | } 44 | } 45 | 46 | resource "aws_instance" "app" { 47 | count = var.instance_count 48 | ami = var.ami_id 49 | instance_type = var.instance_type 50 | key_name = var.key_name 51 | subnet_id = var.subnet_id[count.index % length(var.subnet_id)] 52 | vpc_security_group_ids = [aws_security_group.app.id] 53 | associate_public_ip_address = true 54 | 55 | root_block_device { 56 | volume_size = 10 57 | volume_type = "gp2" 58 | } 59 | 60 | tags = { 61 | Name = lookup(var.instance_names, count.index, "default-name") 62 | Project = var.project_name 63 | } 64 | } 65 | 66 | # tags = { 67 | # Name = count.index == 0 ? "jenkins-master" : "jenkins-slave" 68 | # Project = var.project_name 69 | # } 70 | # } 71 | 72 | 73 | 74 | resource "aws_cloudwatch_metric_alarm" "ec2_cpu" { 75 | count = var.instance_count 76 | alarm_name = "${var.project_name}-cpu-alarm-${count.index + 1}" 77 | comparison_operator = "GreaterThanOrEqualToThreshold" 78 | evaluation_periods = "2" 79 | metric_name = "CPUUtilization" 80 | namespace = "AWS/EC2" 81 | period = "300" 82 | statistic = "Average" 83 | threshold = "80" 84 | alarm_description = "This metric monitors EC2 CPU utilization" 85 | dimensions = { 86 | InstanceId = aws_instance.app[count.index].id 87 | } 88 | alarm_actions = [aws_sns_topic.alerts.arn] 89 | } 90 | 91 | 92 | # SNS Topic for CloudWatch Alarms 93 | resource "aws_sns_topic" "alerts" { 94 | name = "${var.project_name}-alerts" 95 | } 96 | 97 | -------------------------------------------------------------------------------- /terraform/README.md: -------------------------------------------------------------------------------- 1 | # Jenkins Infrastructure Deployment 2 | 3 | ## Overview 4 | This document details the exact steps taken to deploy a Jenkins infrastructure on AWS using Terraform. The setup involves provisioning a VPC, configuring subnets, launching EC2 instances for Jenkins Master and Slave, setting up security groups, integrating CloudWatch monitoring, and configuring the Jenkins Master-Slave setup using Terraform modules. 5 | 6 | ## What I Created 7 | ## S3 Backend Configuration 8 | - Configured to store Terraform state in an S3 bucket 9 | - Includes DynamoDB table for state locking to prevent concurrent modifications 10 | 11 | ## Networking Module 12 | - Creates a VPC with specified CIDR block 13 | - Sets up public subnets across multiple availability zones 14 | - Configures Internet Gateway and routing for public internet access 15 | 16 | ## Compute Module 17 | - Provisions two EC2 instances across different availability zones 18 | - Creates a security group allowing SSH and application traffic 19 | - Uses Amazon Linux 2 AMI 20 | - Configures EBS volumes for each instance 21 | 22 | ## CloudWatch Integration 23 | - Sets up CloudWatch dashboard to monitor EC2 instances 24 | - Creates CloudWatch alarms for high CPU utilization 25 | - Configures SNS topic for alarm notifications 26 | 27 | 28 | ## Project Structure 29 | ``` 30 | jenkins-infrastructure/ 31 | ├── main.tf 32 | ├── variables.tf 33 | ├── outputs.tf 34 | ├── modules/ 35 | │ ├── network/ 36 | │ │ ├── main.tf 37 | │ │ ├── variables.tf 38 | │ │ └── outputs.tf 39 | │ └── compute/ 40 | │ ├── main.tf 41 | │ ├── variables.tf 42 | │ └── outputs.tf 43 | └── backend.tf 44 | ``` 45 | 46 | ## Steps I Took 47 | 48 | ### 1. Created Terraform Modules 49 | - **Network Module:** Provisions the VPC, subnet, and security group. 50 | - **Servers Module:** Launches Jenkins Master and Slave instances. 51 | 52 | ### 2. Configured Terraform Backend (S3) 53 | To store Terraform state remotely and enable team collaboration: 54 | ```bash 55 | aws s3api create-bucket --bucket jenkins12345-terraform-state --region us-east-1 56 | aws s3api put-bucket-versioning --bucket jenkins12345-terraform-state --versioning-configuration Status=Enabled 57 | ``` 58 | 59 | ### 3. Created an EC2 Key Pair 60 | To securely access Jenkins instances: 61 | ```bash 62 | aws ec2 create-key-pair --key-name jenkins-key --query 'KeyMaterial' --output text > jenkins-key.pem 63 | chmod 400 jenkins-key.pem 64 | ``` 65 | 66 | ### 4. Deployed Infrastructure Using Terraform 67 | ```bash 68 | terraform init 69 | terraform plan 70 | terraform apply -auto-approve 71 | ``` 72 | 73 | ### 5. Verified AWS Resources 74 | Checked the AWS Console to confirm: 75 | - VPC and subnet were created. 76 | 77 | ![Alt text](assets/pic1.png) 78 | 79 | - EC2 instances were running. 80 | 81 | ![Alt text](assets/pic2.png) 82 | 83 | - Security groups were correctly applied. 84 | 85 | ![Alt text](assets/pic3.png) 86 | 87 | - CloudWatch alarms were set up. 88 | 89 | ![Alt text](assets/pic4.png) 90 | 91 | ### 6. Tested SSH Access to Instances 92 | Retrieved public IPs: 93 | ```bash 94 | terraform output 95 | ``` 96 | ![Alt text](assets/pic6.png) 97 | 98 | Connected to instances: 99 | ```bash 100 | ssh -i jenkins-key.pem ec2-user@ 101 | ssh -i jenkins-key.pem ec2-user@ 102 | ``` 103 | ![Alt text](assets/pic5.png) 104 | 105 | 106 | -------------------------------------------------------------------------------- /ArgoCD/README.md: -------------------------------------------------------------------------------- 1 | # ArgoCD Deployment Configuration for iVolve Web Application 2 | 3 | ## Prerequisites 4 | - Kubernetes cluster with ArgoCD installed 5 | - Access to ArgoCD web UI (typically https://8080) 6 | - Existing Kubernetes manifests repository 7 | - Cluster admin permissions 8 | 9 | ## Step 1: Prepare Kubernetes Manifests Repository 10 | 1. Create new repository on GitHub: 11 | - Name: `kubernetes-manifests` 12 | 2. Add required manifest files: 13 | - `deployment.yaml` (with image placeholder) 14 | - `service.yaml` 15 | - `ingress.yaml` 16 | - `namespace.yaml` 17 | 18 | 19 | ## Step 2: Access ArgoCD Web UI 20 | 1. Open web browser and navigate to the ArgoCD URL 21 | 2. Log in using credentials (username/password) 22 | - to get the pass 23 | ```bash 24 | kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo 25 | ``` 26 | 3. Verify you see the default ArgoCD dashboard 27 | 28 | ![Alt text](assets/pic1.png) 29 | 30 | ## Step 3: Configure Repository in ArgoCD 31 | 2. **From settings Add New Repository**: 32 | - Click **+ Connect Repo** button 33 | - Choose your connection method: **VIA HTTPS** 34 | - Click **Connect** 35 | 36 | 3. **Verify Connection**: 37 | - Status should show "Successful" 38 | - Test connection by clicking **Refresh** button 39 | 40 | 41 | ## Step 4: Create New Application 42 | 1. Click "+ New App" button in top navigation 43 | 2. Configure application settings: 44 | 45 | **General Section:** 46 | - Application Name: `ivolve-webapp` 47 | - Project: `default` 48 | - Sync Policy: 49 | ✓ Automatic sync 50 | ✓ Self-Heal 51 | 52 | ![Alt text](assets/pic4.png) 53 | 54 | **Source Section:** 55 | - Repository URL: `https://github.com/mahmoudAbdelnaser99/CloudDevOpsProject/tree/main/k8s-manifests` 56 | - Revision: `main` 57 | - Path: `.` (root directory of repo) 58 | 59 | **Destination Section:** 60 | - Cluster: `in-cluster` 61 | - Namespace: `ivolve-app` 62 | 63 | 3. Click "Create" button 64 | 65 | ![Alt text](assets/pic5.png) 66 | 67 | ## Step 4: Verify Initial Deployment 68 | 1. In Applications list: 69 | - Locate `ivolve-webapp` 70 | - Verify status changes from "OutOfSync" → "Synced" 71 | - Health status should show "Healthy" 72 | 73 | ![Alt text](assets/pic6.png) 74 | 75 | 3. Verify resources: 76 | - Click application name 77 | - Check "Resources" tab for: 78 | - Deployment (1/1 available) 79 | - Service (ClusterIP created) 80 | - Pods (Running status) 81 | 82 | ![Alt text](assets/pic7.png) 83 | 84 | ## Step 6: Test Pipeline-Driven Deployment Flow 85 | 86 | ### 1. Manually Trigger Pipeline 87 | 1. **In Jenkins UI**: 88 | - Navigate to your `ivolve-webapp-pipeline` job 89 | - Click **Build Now** 90 | 91 | ### 2. Verify Automated Manifest Update 92 | 1. **Check Git commit** (within 1 minute of pipeline completion): 93 | 94 | ![Alt text](assets/pic2.png) 95 | 96 | ### 3. Observe ArgoCD Response (Within 3 Minutes) 97 | 1. **In ArgoCD UI**: 98 | - Application status will transition: 99 | ``` 100 | Synced → OutOfSync → Syncing → Synced 101 | ``` 102 | - Health status may briefly show **Progressing** during rollout 103 | 104 | ![Alt text](assets/pic8.png) 105 | 106 | 2. **Verify deployment update**: 107 | ```bash 108 | kubectl -n ivolve-app describe deployment ivolve-webapp | grep Image 109 | ``` 110 | Output should match the new BUILD_NUMBER from Jenkins 111 | 112 | ![Alt text](assets/pic9.png) 113 | ![Alt text](assets/pic10.png) 114 | 115 | ### 4. Validate Pod Rotation 116 | 1. **Check pod versions**: 117 | ```bash 118 | kubectl -n ivolve-app get pods 119 | ``` 120 | - Old pods will be terminating (if using rolling updates) 121 | - New pods will show the updated image tag 122 | 123 | ![Alt text](assets/pic11.png) 124 | 125 | - access the application 126 | with ip of node + svc port 127 | ![Alt text](assets/pic13.png) 128 | 129 | ![Alt text](assets/pic12.png) 130 | 131 | 132 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iVolve CI/CD Infrastructure 2 | 3 | A comprehensive end-to-end CI/CD infrastructure for containerized applications, featuring AWS infrastructure provisioning, automated configuration management, continuous integration, and GitOps-based deployment to Kubernetes. 4 | 5 | ## Project Archticture 6 | 7 | ![alt text]() 8 | ## 🚀 Architecture Overview 9 | 10 | This project implements a complete DevOps infrastructure with the following major components: 11 | 12 | ### 1. AWS Infrastructure (Terraform Provisioned) 13 | * **EC2 Instance 1 (Master)**: 14 | * Hosts Jenkins Master that controls the CI pipeline 15 | * Configured with Ansible playbooks 16 | * **EC2 Instance 2 (Slave)**: 17 | * Jenkins Slave node for executing build jobs 18 | * Handles resource-intensive pipeline tasks 19 | * Configured with Ansible playbooks 20 | * **Supporting Services**: 21 | * S3 Bucket for Terraform state backend 22 | * CloudWatch for monitoring and logging 23 | 24 | ### 2. Development Environment 25 | * **kubeadm Cluster**: 26 | * kubeadm Kubernetes implementation with master + node1 27 | * Contains dedicated "iVolve" namespace 28 | * Manages Deployments, Services, and Ingress resources 29 | 30 | ### 3. ArgoCD Implementation 31 | * **Core Components**: 32 | * Application Controller for state management 33 | * Repository Server for cached repositories 34 | * API Server for RESTful operations 35 | * GitOps Engine for synchronization logic 36 | * **Workflow**: 37 | * Monitors GitHub repository for manifest changes 38 | * Automatically syncs configurations to Kubernetes 39 | * Maintains desired state defined in Git 40 | 41 | ### 4. CI/CD Pipeline Flow 42 | 1. Code is pushed to GitHub repository 43 | 2. Jenkins Master detects changes and assigns build job to Slave 44 | 3. Jenkins Slave executes pipeline steps: 45 | * Runs unit tests 46 | * Creates Docker image 47 | * Pushes image to registry 48 | * Updates Kubernetes manifests 49 | * Commits changes back to Git repository 50 | 4. ArgoCD detects manifest changes in repository 51 | 5. ArgoCD syncs changes to Minikube cluster 52 | 6. Application is deployed/updated in the local environment 53 | 54 | ## 📋 Prerequisites 55 | 56 | - AWS account with appropriate permissions 57 | - Docker installed 58 | - Kubernetes cluster (kubeadm master + node1) 59 | - Git installed 60 | - Basic knowledge of Terraform, Ansible, Jenkins, and Kubernetes 61 | 62 | ## 🛠️ Project Components 63 | 64 | ### Terraform 65 | 66 | Contains Infrastructure as Code (IaC) configurations for AWS resources: 67 | - VPC and subnet configuration 68 | - EC2 instances for Jenkins Master and Slave 69 | - Security groups and networking 70 | - CloudWatch monitoring setup 71 | 72 | [Go to Terraform documentation →](./terraform/README.md) 73 | 74 | ### Ansible 75 | 76 | Contains configuration management scripts to set up: 77 | - Jenkins Master 78 | - Jenkins Slave configuration 79 | - k8s kubemaster and node1 80 | - All necessary dependencies and services 81 | 82 | [Go to Ansible documentation →](./Ansible/README.md) 83 | 84 | ### Jenkins 85 | 86 | Contains pipeline configurations for CI/CD: 87 | - Jenkinsfile with complete pipeline definition 88 | - Shared libraries for common operations 89 | 90 | [Go to Jenkins documentation →](./Jenkins/README.md) 91 | 92 | ### Docker 93 | 94 | Contains application Dockerfile and build context: 95 | - Multi-stage build process 96 | - Optimized container configuration 97 | - Spring Boot application containerization 98 | 99 | [Go to Docker documentation →](./app/README.md) 100 | 101 | ### Kubernetes 102 | 103 | Contains Kubernetes manifests for application deployment: 104 | - Deployment, Service, and Ingress configurations 105 | - Persistent storage setup 106 | - Namespace isolation 107 | 108 | [Go to Kubernetes documentation →](./k8s-manifests/README.md) 109 | 110 | ### ArgoCD 111 | 112 | Contains GitOps configuration for continuous deployment: 113 | - Application definition 114 | - Sync policies 115 | - Repository integration 116 | 117 | [Go to ArgoCD documentation →](./ArgoCD/README.md) 118 | 119 | ## 📝 Project Structure 120 | 121 | ``` 122 | ├── Ansible/ # Ansible playbooks and roles 123 | ├── ArgoCD/ # ArgoCD configuration files 124 | ├── app/ # Dockerfile and application source 125 | ├── Jenkins/ # Jenkinsfile and pipeline configs 126 | ├── k8s-manifests/ # Kubernetes manifest files 127 | ├── terraform/ # Terraform IaC configurations 128 | └── README.md # This file 129 | ``` 130 | 131 | -------------------------------------------------------------------------------- /Jenkins/README.md: -------------------------------------------------------------------------------- 1 | Here's a comprehensive README file with detailed steps for setting up the Jenkins CI/CD pipeline for the iVolve web application: 2 | 3 | --- 4 | 5 | # Jenkins CI/CD Pipeline Setup for iVolve Web Application 6 | 7 | ## Table of Contents 8 | 1. Prerequisites 9 | 2. Jenkins Slave Configuration 10 | 3. Shared Library Setup 11 | 5. Credentials Configuration 12 | 6. Pipeline Job Creation 13 | 7. Kubernetes Manifests Preparation 14 | 8. Running the Pipeline 15 | 9. Verification Steps 16 | 17 | ## 1. Prerequisites 18 | 19 | - Jenkins master and slave instances provisioned using **Ansible playbooks** 20 | - Java Development Kit (JDK) installed on both Jenkins **master and slave** 21 | - Git installed and configured on both instances 22 | - Docker installed and configured on the Jenkins slave 23 | - Kubernetes cluster accessible from the Jenkins slave 24 | - GitHub repository for the iVolve web application 25 | - Separate GitHub repository for **Kubernetes manifests** 26 | 27 | ## 2. Jenkins Slave Configuration 28 | 29 | Follow these steps to configure the Jenkins slave: 30 | 31 | 1. Log in to the Jenkins master web interface 32 | 2. Navigate to Manage Jenkins > Manage Nodes and Clouds 33 | 3. Click New Node to create a new agent 34 | 4. Enter "agent" as the node name and select Permanent Agent 35 | 5. Configure the node with these settings: 36 | - Remote root directory: /home/ubuntu 37 | - Labels: slave 38 | - Usage: Use this node as much as possible 39 | - Launch method: Launch agent via SSH 40 | 6. Enter the **Private IP address** of Jenkins slave instance 41 | 7. Add SSH credentials for the ubuntu user with the private key 42 | ```bash 43 | cat jenkins-key.pem 44 | ``` 45 | 8. Set Host Key Verification Strategy to Non verifying Verification Strategy 46 | 9. Click Save to create the node 47 | 10. Verify the slave connection appears online in the Nodes list 48 | 49 | ![Alt text](assets/pic1.png) 50 | 51 | ## 3. Shared Library Setup 52 | 53 | To create and configure the Jenkins shared library: 54 | 55 | 1. Create a new Git repository named "jenkins-shared-library" 56 | 2. Clone the repository to local machine 57 | 3. Create the following directory structure in the repository: 58 | - vars/ for global pipeline variables 59 | 4. Add the Groovy scripts for Docker operations and Git operations 60 | 5. Commit and push the initial implementation to the repository 61 | 6. In Jenkins, navigate to Manage Jenkins > Configure System 62 | 7. Scroll to trusted Global Pipeline Libraries section 63 | 8. Add a new library with name "jenkins-shared-library" 64 | 9. Configure the library with: 65 | - Default version: main 66 | - Retrieval method: Modern SCM 67 | - Source Code Management: Git 68 | - Repository URL of your shared library 69 | - Credentials if required 70 | 10. Click Save to apply the configuration 71 | 72 | ![Alt text](assets/pic2.png) 73 | 74 | 75 | ## 5. Credentials Configuration 76 | 77 | Set up the required credentials in Jenkins: 78 | 79 | 1. Docker Hub credentials: 80 | - Navigate to Manage Jenkins > Manage Credentials 81 | - Add new credentials with type Username with password 82 | - Enter your Docker Hub username and password 83 | - Set ID to "docker" 84 | 85 | 2. Git SSH credentials: 86 | - In the same credentials section 87 | - Add new credentials with type SSH Username with private key 88 | - Enter "git" as username 89 | - Paste your SSH private key 90 | - Set ID to "git-credentials" 91 | - Add description "Git SSH Credentials" 92 | 93 | ![Alt text](assets/pic6.png) 94 | 95 | ## 6. Pipeline Job Creation 96 | 97 | Create and configure the main pipeline job: 98 | 99 | 1. From Jenkins dashboard, click New Item 100 | 2. Enter "iVolve-WebApp" as name 101 | 3. Select Pipeline type and click OK 102 | 4. In the configuration page: 103 | - Under Pipeline section, select Pipeline script from SCM 104 | - Choose Git as SCM 105 | - Enter application repository URL 106 | - Add Git credentials 107 | - Specify branch (main) 108 | - Set Script Path to **jenkins/jenkinsfile** 109 | 5. Click Save to create the pipeline 110 | 111 | ## 7. Kubernetes Manifests Preparation 112 | 113 | Prepare your Kubernetes manifests repository: 114 | 115 | 1. Create a new Git repository for Kubernetes manifests 116 | 2. Add your existing Kubernetes YAML files: 117 | - deployment.yaml 118 | - service.yaml 119 | - ingress.yaml 120 | - persistent volume files 121 | 3. Organize the repository with clear structure 122 | 4. Modify deployment.yaml to use image placeholder: 123 | - Set image field to use Docker image name with :latest tag 124 | - This will be updated by the pipeline 125 | 126 | ![Alt text](assets/pic7.png) 127 | 128 | 129 | ## 9. Verification Steps 130 | 131 | After pipeline completion, verify all components: 132 | 133 | 1. Docker Image: 134 | - Log in to Docker Hub 135 | - Verify new image with build number tag exists 136 | 137 | ![Alt text](assets/pic8.png) 138 | 139 | 2. Kubernetes Manifests: 140 | - Check the Git repository commit history 141 | - Verify deployment.yaml was updated with new image tag 142 | 143 | ![Alt text](assets/pic12.png) 144 | 145 | 3. Application: 146 | - Check Kubernetes cluster for new deployment 147 | - Verify application pods are running with new image 148 | - Test application functionality 149 | 150 | 4. Review pipeline 151 | 152 | ![Alt text](assets/pic11.png) 153 | 154 | 155 | -------------------------------------------------------------------------------- /Ansible/roles/jenkins/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # _____________________________ Java 17 Installation _____________________________ 3 | - name: Install OpenJDK 17 4 | apt: 5 | name: openjdk-17-jdk 6 | state: present 7 | update_cache: yes 8 | become: yes 9 | 10 | - name: Set JAVA_HOME environment variable 11 | lineinfile: 12 | path: /etc/environment 13 | line: 'JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' 14 | create: yes 15 | 16 | # _____________________________ Jenkins Installation _____________________________ 17 | - name: Add Jenkins repository key 18 | apt_key: 19 | url: https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key 20 | state: present 21 | 22 | - name: Add Jenkins APT repository 23 | apt_repository: 24 | repo: "deb https://pkg.jenkins.io/debian-stable binary/" 25 | state: present 26 | 27 | - name: Install Jenkins 28 | apt: 29 | name: jenkins 30 | update_cache: yes 31 | become: true 32 | 33 | # _____________________________ Skip Setup Wizard Properly _____________________________ 34 | - name: Mark setup wizard as completed 35 | copy: 36 | dest: /var/lib/jenkins/jenkins.install.UpgradeWizard.state 37 | content: "2.440" 38 | owner: jenkins 39 | group: jenkins 40 | mode: '0644' 41 | 42 | - name: Mark last executed install version 43 | copy: 44 | dest: /var/lib/jenkins/jenkins.install.InstallUtil.lastExecVersion 45 | content: "2.440" 46 | owner: jenkins 47 | group: jenkins 48 | mode: '0644' 49 | 50 | # _____________________________ Create Admin User via Groovy _____________________________ 51 | - name: Ensure Jenkins init.groovy.d directory exists 52 | file: 53 | path: /var/lib/jenkins/init.groovy.d 54 | state: directory 55 | owner: jenkins 56 | group: jenkins 57 | mode: '0755' 58 | 59 | - name: Create Jenkins admin user via init Groovy script 60 | copy: 61 | dest: /var/lib/jenkins/init.groovy.d/basic-security.groovy 62 | content: | 63 | import jenkins.model.* 64 | import hudson.security.* 65 | 66 | def instance = Jenkins.getInstanceOrNull() 67 | if (instance != null) { 68 | def hudsonRealm = new HudsonPrivateSecurityRealm(false) 69 | hudsonRealm.createAccount("{{ jenkins_user }}", "{{ jenkins_password }}") 70 | instance.setSecurityRealm(hudsonRealm) 71 | def strategy = new FullControlOnceLoggedInAuthorizationStrategy() 72 | instance.setAuthorizationStrategy(strategy) 73 | instance.save() 74 | } 75 | notify: restart jenkins 76 | 77 | - name: Add Groovy script to install suggested plugins 78 | copy: 79 | dest: /var/lib/jenkins/init.groovy.d/plugins.groovy 80 | content: | 81 | import jenkins.model.* 82 | import hudson.model.* 83 | import java.util.logging.Logger 84 | 85 | def plugins = [ 86 | "git", 87 | "workflow-aggregator", 88 | "credentials-binding", 89 | "ssh-slaves", 90 | "matrix-auth", 91 | "pipeline-stage-view", 92 | "pipeline-github-lib", 93 | "github", 94 | "junit", 95 | "email-ext", 96 | "ant", 97 | "gradle", 98 | "blueocean", 99 | "docker-plugin", 100 | "pipeline-model-definition", 101 | "configuration-as-code", 102 | "ws-cleanup", 103 | "timestamper", 104 | "nodejs", 105 | "pipeline-utility-steps", 106 | "docker-workflow", 107 | "git-client", 108 | "github-branch-source", 109 | "command-launcher", 110 | "job-dsl", 111 | "build-timeout", 112 | "workflow-multibranch", 113 | "lockable-resources", 114 | "workflow-step-api", 115 | "scm-api", 116 | "pipeline-input-step", 117 | "ansicolor", 118 | "htmlpublisher", 119 | "pipeline-stage-step", 120 | "credentials" 121 | ] 122 | 123 | def instance = Jenkins.getInstance() 124 | def pluginManager = instance.getPluginManager() 125 | def updateCenter = instance.getUpdateCenter() 126 | Logger logger = Logger.getLogger("") 127 | 128 | plugins.each { pluginName -> 129 | if (!pluginManager.getPlugin(pluginName)) { 130 | def plugin = updateCenter.getPlugin(pluginName) 131 | if (plugin) { 132 | logger.info("Installing plugin: ${pluginName}") 133 | plugin.deploy() 134 | } 135 | } 136 | } 137 | 138 | instance.save() 139 | notify: restart jenkins 140 | - name: Install BlueOcean UI plugin separately 141 | copy: 142 | dest: /var/lib/jenkins/init.groovy.d/blueocean.groovy 143 | content: | 144 | import jenkins.model.* 145 | import java.util.logging.Logger 146 | 147 | def instance = Jenkins.getInstance() 148 | def pluginManager = instance.getPluginManager() 149 | def updateCenter = instance.getUpdateCenter() 150 | Logger logger = Logger.getLogger("") 151 | 152 | updateCenter.updateAllSites() 153 | 154 | def pluginName = "blueocean" 155 | def plugin = updateCenter.getPlugin(pluginName) 156 | if (!pluginManager.getPlugin(pluginName)) { 157 | if (plugin) { 158 | logger.info("Installing BlueOcean UI plugin") 159 | plugin.deploy() 160 | } 161 | } 162 | instance.save() 163 | notify: restart jenkins 164 | 165 | # _____________________________ Start Jenkins Service _____________________________ 166 | - name: Ensure Jenkins is started and enabled 167 | service: 168 | name: jenkins 169 | state: started 170 | enabled: yes 171 | -------------------------------------------------------------------------------- /Ansible/README.md: -------------------------------------------------------------------------------- 1 | # Jenkins Infrastructure Configuration with Ansible 2 | Jenkins Ansible Role - Automated Setup with Suggested Plugins and BlueOcean UI on AWS 3 | This repository provides a **complete Ansible-based solution** for **automated deployment** and **management** of a Jenkins CI/CD infrastructure on AWS EC2 instances. 4 | 5 | It uses a **dynamic inventory** to discover and manage EC2 instances based on their **tags**, grouping them automatically for **targeted playbook execution**. It can **fallback to a static inventory** if dynamic discovery fails. 6 | 7 | --- 8 | 9 | ## 🚀 Features 10 | 11 | - **Dynamic EC2 Inventory**: Automatically discovers instances based on AWS tags. 12 | - **Role-Based Configuration**: Modular and organized Ansible roles for components. 13 | - **Modular Playbooks**: Main and task-specific playbooks for flexibility. 14 | - **Environment Configuration**: Ensures environment readiness (system limits, permissions, etc.). 15 | - **Service Management**: Configures systemd services and dependencies. 16 | - **Complete CI/CD Setup**: Jenkins (with agents) 17 | - **Dockerized Environment**: Docker installed and configured across all nodes. 18 | - Creating an admin user via Groovy script 19 | - Automatic installation of all suggested Jenkins plugins (including BlueOcean) 20 | - Ensuring Jenkins is enabled and running 21 | 22 | --- 23 | 24 | ## 📋 Prerequisites 25 | 26 | - AWS CLI configured with valid credentials. 27 | - Terraform-deployed AWS Infrastructure (see [`Terraform/`](./terraform) directory). 28 | - Python 3.x installed with pip. 29 | - Ansible 2.9+ installed. 30 | - EC2 Key Pair (`jenkins-key.pem`) available and permissions set. 31 | 32 | Install required Python packages: 33 | 34 | ```bash 35 | pip install ansible boto3 botocore 36 | ``` 37 | create Roles 38 | ```bash 39 | ansible-galaxy init roles/common 40 | ansible-galaxy init roles/git 41 | ansible-galaxy init roles/java 42 | ansible-galaxy init roles/docker 43 | ansible-galaxy init roles/jenkins 44 | ``` 45 | 46 | Set key pair permissions: 47 | 48 | ```bash 49 | chmod 400 ~/jenkins-key.pem 50 | ``` 51 | 52 | --- 53 | 54 | ## 📂 Directory Structure 55 | 56 | ``` 57 | ├── ansible.cfg # Ansible configuration file 58 | ├── inventory/ # Dynamic inventory configuration for AWS 59 | │ └── ec2.yaml 60 | ├── playbooks/ # Playbooks for different node types 61 | │ ├── site.yml # Full infrastructure setup 62 | │ ├── jenkins-master.yml # Jenkins master setup 63 | │ ├── jenkins-slave.yml # Jenkins slave setup 64 | │ └── kubeadm.yaml # kubeadm setup 65 | ├── roles/ # Ansible roles 66 | ├── common/ # Common setup (packages, users, etc.) 67 | ├── java/ # Java installation 68 | ├── docker/ # Docker installation and configuration 69 | ├── jenkins_master/ # Jenkins master setup 70 | ├── jenkins_slave/ # Jenkins slave setup 71 | └── kubeadm/ # kubeadm master + node1 setup 72 | 73 | ``` 74 | 75 | --- 76 | 77 | ## ⚙️ Usage 78 | 79 | ### 1. Verifying Dynamic Inventory 80 | 81 | Check if instances are correctly grouped: 82 | 83 | ```bash 84 | ansible-inventory --graph 85 | ``` 86 | ![Alt text](assets/pic1.png) 87 | 88 | --- 89 | 90 | ### 2. Running Playbooks 91 | 92 | - Configure **all instances**: 93 | 94 | ```bash 95 | ansible-playbook playbooks/site.yml 96 | ansible-playbook playbooks/kubeadm.yaml 97 | ``` 98 | 99 | --- 100 | 101 | ## 🌐 Accessing Services 102 | 103 | After playbook execution: 104 | 105 | - **Jenkins**: 106 | http://:8080 107 | Username: `admin` 108 | Password: `admin123` (or as set in `group_vars`) 109 | 110 | ![Alt text](assets/pic2.png) 111 | 112 | --- 113 | 114 | ## 🔧 Components Installed 115 | 116 | ### Master Node 117 | 118 | - Java 17 119 | - Git, Docker, and essential packages 120 | - Jenkins (with pre-installed plugins) 121 | 122 | ### Slave Node 123 | 124 | - Java 17 125 | - Git, Docker, and essential packages 126 | - Jenkins agent (configured to connect to the master automatically) 127 | 128 | --- 129 | 130 | ## 📑 Role-Based Configuration Overview 131 | 132 | - **Common Role**: 133 | Sets up basic system packages, users, and permissions. 134 | 135 | ![Alt text](assets/pic7.png) 136 | 137 | - **Java Role**: 138 | Installs and configures Java 17. 139 | 140 | ![Alt text](assets/pic6.png) 141 | 142 | - **Docker Role**: 143 | Installs Docker, adds necessary users to the Docker group. 144 | 145 | ![Alt text](assets/pic5.png) 146 | 147 | - **Jenkins Master Role**: 148 | Installs Jenkins, configures plugins, sets admin credentials. 149 | 150 | - **Jenkins Slave Role**: 151 | Installs and configures Jenkins agent. 152 | 153 | - **kubeadm Role**: 154 | Initialize Kubernetes master , node1 through script 155 | copy admin.conf to user's kube config 156 | apply Flannel CNI plugin 157 | 158 | ![Alt text](assets/pic8.png) 159 | 160 | - **Join node1 to master**: 161 | generate kubeadm join 162 | Join the node to the Kubernetes cluster 163 | 164 | ![Alt text](assets/pic9.png) 165 | 166 | ![Alt text](assets/pic11.png) 167 | --- 168 | 169 | ## 🛠️ Service Management 170 | 171 | - Creates **systemd service files** for Jenkins. 172 | - Ensures services **start automatically on boot**. 173 | - Handles service **dependencies** properly. 174 | 175 | --- 176 | 177 | ## 🏷️ EC2 Tag Requirements 178 | 179 | Make sure your EC2 instances are tagged appropriately: 180 | 181 | - Tag key: `Project` 182 | - Tag value: `ivolve` 183 | 184 | 185 | --- 186 | 187 | ## 📈 Benefits 188 | 189 | ✅ Highly scalable and modular setup 190 | ✅ Automated CI/CD foundation ready for production 191 | ✅ Easy to extend and maintain 192 | ✅ Docker-ready for microservice deployments 193 | ✅ Automated Jenkins Setup with Suggested Plugins 194 | ✅ Setup Kubernetes Cluster on AWS 195 | 196 | 197 | 198 | 199 | -------------------------------------------------------------------------------- /Ansible/roles/kubeadm/files/common-script.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | sudo apt update -y 4 | 5 | sudo apt-get install -y apt-transport-https ca-certificates curl gpg 6 | 7 | sudo install -m 0755 -d /etc/apt/keyrings 8 | 9 | sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc 10 | 11 | sudo chmod a+r /etc/apt/keyrings/docker.asc 12 | 13 | echo \ 14 | "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ 15 | $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ 16 | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null 17 | 18 | sudo apt-get update -y 19 | 20 | sudo apt install -y containerd.io docker-ce docker-ce-cli 21 | 22 | sudo systemctl daemon-reload 23 | 24 | sudo systemctl enable docker 25 | 26 | sudo systemctl enable --now containerd 27 | 28 | sudo usermod -aG docker ubuntu 29 | 30 | 31 | wget https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz 32 | sudo mkdir -p /opt/cni/bin 33 | sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.4.0.tgz 34 | 35 | 36 | sudo mkdir -p /etc/containerd 37 | sudo containerd config default | tee /etc/containerd/config.toml 38 | 39 | sudo tee /etc/containerd/config.toml <> /etc/sysctl.conf" 272 | sudo sysctl -p 273 | 274 | cat /proc/sys/net/ipv4/ip_forward 275 | 276 | 277 | 278 | 279 | 280 | # change Hostname 281 | 282 | 283 | free -m 284 | 285 | sudo apt-get update 286 | 287 | sudo apt-get install -y apt-transport-https ca-certificates curl gpg 288 | 289 | sudo mkdir -p -m 755 /etc/apt/keyrings 290 | curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg 291 | echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list 292 | 293 | sudo apt-get update -y 294 | sudo apt-get install -y kubelet kubeadm kubectl 295 | sudo apt-mark hold kubelet kubeadm kubectl 296 | 297 | sudo systemctl enable --now kubelet 298 | 299 | sudo modprobe overlay 300 | sudo modprobe br_netfilter 301 | 302 | 303 | sudo tee /etc/sysctl.d/kubernetes.conf<