diff --git a/Jenkinsfile_Destroy b/Jenkinsfile_Destroy new file mode 100644 index 0000000..ece827d --- /dev/null +++ b/Jenkinsfile_Destroy @@ -0,0 +1,18 @@ +pipeline{ + agent { + label 'kubernetes' + } + stages{ + stage('Destroy arsenalspring.devopsnetwork.net Website'){ + steps{ + withCredentials([aws(accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'aws_cred', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY')]) { + sh "echo 'Destroy arsenalspring.devopsnetwork.net Website'" + sh "terraform init" + sh "terraform validate" + sh "terraform plan" + sh "terraform destroy --auto-approve" + } + } + } + } +} diff --git a/Jenkinsfile_Springapp b/Jenkinsfile_Springapp new file mode 100644 index 0000000..b5b1517 --- /dev/null +++ b/Jenkinsfile_Springapp @@ -0,0 +1,32 @@ +pipeline{ + agent { + label 'kubernetes' + } + stages{ + stage('Provision springapp-issuer to acquire a certificate to secure the arsenalspring.devopsnetwork.net'){ + steps{ + sh "echo cloning code" + sh "kubectl apply -f springapp-issuer.yml" + } + } + stage('Deploy arsenalspring.devopsnetwork.net'){ + steps{ + withCredentials([aws(accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'aws_cred', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY')]) { + sh "echo 'Create arsenalspring.devopsnetwork.net'" + sh "terraform init" + sh "terraform validate" + sh "terraform plan" + sh "terraform apply --auto-approve" + } + } + } + stage('Show Arsenal Java Springapp Running on Fargate Node'){ + steps{ + withCredentials([aws(accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'aws_cred', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY')]) { + sh "echo 'Show arsenal java springapp container running on fargate nodes'" + sh "kubectl get po -o wide -n springapp" + } + } + } + } +} diff --git a/Jenkinsfile_Status b/Jenkinsfile_Status new file mode 100644 index 0000000..b9f59ed --- /dev/null +++ b/Jenkinsfile_Status @@ -0,0 +1,38 @@ +pipeline{ + agent { + label 'kubernetes' + } + stages{ + //stage('Clone Code'){ + //steps{ + //sh "echo cloning code" + //sh "echo clone code complete" + //git 'https://github.com/Konoha-23/Konoha_WP.git' + //} + //} + stage('Get Pods in Konoha Namespace'){ + steps{ + withCredentials([aws(accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'aws_cred', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY')]) { + sh "echo 'Get Pods in Konoha namespace'" + sh "kubectl get po -o wide -n konoha" + } + } + } + stage('Describe Pods in Konoha Namespace'){ + steps{ + withCredentials([aws(accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'aws_cred', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY')]) { + sh "echo 'Describe Pods in Konoha Namespace'" + sh "kubectl describe po -n konoha" + } + } + } + //stage('Check Logs'){ + // steps{ + // withCredentials([aws(accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'aws_cred', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY')]) { + // sh "echo 'Check Logs'" + // sh "kubectl logs wordpress-849fc57f7f-xnf9q -n robot-shop" + // } + // } + //} + } +} diff --git a/README.md b/README.md index 7b4f378..e870e34 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,53 @@ -# DB-Springapp -Deploy Java Springapp connected to mongodb nosql database into the DB cluster running on a Fargate node, using Jenkins +# DB-CD + +# DragonBall Project Part 6 + +## Project Objective + +For this project, set up a pipeline to deploy a stateless Java Springboot app connected to MongoDB NoSQL database into the DB cluster running on a Fargate node using Terraform with the Kubernetes and Helm Providers. + +## Prerequisites + +- MongoDB deployed in DB Cluster (To set MongoDB in the DB cluster, check Project part 5: https://github.com/Ohubabs/DB-Mongo.git). +- Prior knowledge of Terraform, Kubernetes, and Helm, application deployment, charts. + +### Step 1: Go to New Item” from the Dashboard, select “Pipeline”, and name it “Springapp”. + +![Screenshot 2024-06-24 at 3 04 32 PM](https://github.com/user-attachments/assets/718a3ff0-fa52-4eab-a937-3c7dc8997c6c) + +### Step 2: Go to “Configuration”, Select “Poll SCM” and Enter the details for your GitHub repo & Jenkinsfile or copy and paste the Jenkinsfile in this repo. + +![image](https://github.com/user-attachments/assets/e74fe561-2e4b-42b3-8843-e2d8446692a0) + +#### Notes: - + +- To enter details for your MongoDB database, edit the var.tf file to fill in the secret in the krillin.tf file. +- If you change the name for the secret with your MongoDB credentials, you must also change it in the values file for the customized helm chart via the spring-mongo.yml file. +- To expose your application with SSL encryption to the internet, you must edit the spring-issuer.yml file with your email, custom URLs for your site with your AWS registered domain name, and your AWS hosted zone ID. In addition, you will need your AWS credentials, which were saved in a secret made during Project Part 1 (ref: https://github.com/Ohubabs/DB-Pipeline.git) + +### Step 3: Click “Build now” to run your pipeline with Maven, SonarQube, and Docker to Build, Test, Containerize, and Push your Java Springboot Web app to DockerHub. + +![Screenshot 2024-06-24 at 6 27 18 PM](https://github.com/user-attachments/assets/24e6bbd6-5375-479a-8718-76b1d41e081e) + +![Screenshot 2024-06-24 at 6 27 26 PM](https://github.com/user-attachments/assets/6de298f5-c8c2-4c76-9206-f1b38f2e7d2f) + +![Screenshot 2024-06-24 at 6 27 32 PM](https://github.com/user-attachments/assets/45269973-6fa4-44de-839f-5928f30b1421) + +![Screenshot 2024-06-24 at 6 28 58 PM](https://github.com/user-attachments/assets/564b287b-514d-436a-bbea-1a9a960c5eec) + +![Screenshot 2024-06-24 at 6 38 11 PM](https://github.com/user-attachments/assets/8d5c4460-7d03-4784-9c3e-70593cca0580) + +![Screenshot 2024-06-24 at 6 38 28 PM](https://github.com/user-attachments/assets/28ab1f83-1e4f-419a-9ad7-63fbd6b59bf9) + +![Screenshot 2024-06-24 at 6 39 00 PM](https://github.com/user-attachments/assets/b1774b9b-b3ba-4040-aa4d-dd33111d73b0) + +![Screenshot 2024-06-25 at 7 10 13 PM](https://github.com/user-attachments/assets/4f8aa4f2-5344-4936-8996-3b231837189d) + +![Screenshot 2024-06-25 at 7 24 43 PM](https://github.com/user-attachments/assets/abba8171-359e-4c1a-ae42-5af367d27c72) + + +![Screenshot 2024-06-25 at 6 42 42 PM](https://github.com/user-attachments/assets/b37090d8-78f5-4ce0-a12b-bfe7127e1006) + + + + diff --git a/krillin-1.tf b/krillin-1.tf new file mode 100644 index 0000000..5a9201d --- /dev/null +++ b/krillin-1.tf @@ -0,0 +1,12 @@ +resource "kubernetes_secret_v1" "springapp-mongodb-auth" { #do not name krillin so it won't crash with the secret for mongodb + metadata { + name = "springapp-mongodb-auth" + namespace = "springapp" + } + + data = { + MONGO_DB_USERNAME = var.krillin + MONGO_DB_PASSWORD = var.destructodisk + } +} + diff --git a/provider.tf b/provider.tf new file mode 100644 index 0000000..325e322 --- /dev/null +++ b/provider.tf @@ -0,0 +1,32 @@ +terraform { + required_version = "~> 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.0" + } + + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.10" + } + helm = { + source = "hashicorp/helm" + version = ">= 2.4.1" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +provider "helm" { + kubernetes { + config_path = "/home/terra/.kube/config" #changed user needed to correspond with production cluster deploying applications. + } +} + +provider "kubernetes" { + config_path = "/home/terra/.kube/config" + } diff --git a/spring-mongo.tf b/spring-mongo.tf new file mode 100644 index 0000000..4eeea18 --- /dev/null +++ b/spring-mongo.tf @@ -0,0 +1,19 @@ +resource "helm_release" "spring-mongo" { + name = "springapp" + create_namespace = true + namespace = "springapp" + repository = "https://konoha-23.github.io/springapp-mongo/" + chart = "spring-mongo" + values = [ + "${file("spring-mongo.yml")}" + ] +} + +# + + +/*1. Get the application URL by running these commands: + export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=spring-mongo,app.kubernetes.io/instance=spring-mongo" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT*/ diff --git a/spring-mongo.yml b/spring-mongo.yml new file mode 100644 index 0000000..e848ba4 --- /dev/null +++ b/spring-mongo.yml @@ -0,0 +1,147 @@ +# Default values for spring-mongo. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +metadata: + labels: + app: springapp + +replicaCount: 1 + +selector: + matchLabels: + app: "springapp" + +strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + +image: + repository: princebabs/arsenalspringapp #princebabs/springapp + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "v1" #v2 +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: + app: springapp + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + targetPort: 8080 + +serviceSelector: + app: springapp + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + ingress: + ClassName: nginx-example + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +#livenessProbe: +# httpGet: +# path: / +# port: 8080 +#readinessProbe: +# httpGet: +# path: / +# port: 8080 + +#1. Get the application URL by running these commands: +# export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=spring-mongo,app.kubernetes.io/instance=spring-mongo" -o jsonpath="{.items[0].metadata.name}") +# export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") +# echo "Visit http://127.0.0.1:8080 to use your application" +# kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT +#mongodb-0.mongodb-headless.konoha.svc.cluster.local:27017 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +#Mongo DB credentials + +#Enter the name for an existing mongo secret +mongodbsecretName: springapp-mongodb-auth + +#Enter the name for an existing secret key for mongo root user +mongodbrootuserkey: MONGO_DB_USERNAME + + +#Enter the name for an existing secret key for mongo root password +mongodbrootpasswordkey: MONGO_DB_PASSWORD + +#Enter the name for mongo db hostname +mongodbhostname: mongodb diff --git a/springapp-ingress.tf b/springapp-ingress.tf new file mode 100644 index 0000000..d502ca3 --- /dev/null +++ b/springapp-ingress.tf @@ -0,0 +1,77 @@ +##NGINX + +resource "kubernetes_ingress_v1" "springapp-ingress" { + wait_for_load_balancer = true + metadata { + name = "springapp" + namespace = "springapp" + annotations = { + "cert-manager.io/cluster-issuer" = "arsenalspring-issuer" + } + } + spec { + ingress_class_name = "nginx" + tls { + secret_name = "springapp-secret" + hosts = ["arsenalspring.devopsnetwork.net"] + } + rule { + host = "arsenalspring.devopsnetwork.net" + http { + path { + path = "/" + backend { + service { + name = "springapp-spring-mongo" + port { + number = 8080 + } + } + } + } + } + } + } +} + +/*resource "kubernetes_ingress_v1" "springapp-ingress" { + wait_for_load_balancer = true + metadata { + name = "springapp-ingress" + namespace = "springapp" + annotations = { + "alb.ingress.kubernetes.io/load-balancer-name" = "springapp" + "alb.ingress.kubernetes.io/scheme" = "internet-facing" + "alb.ingress.kubernetes.io/target-type" = "ip" + "alb.ingress.kubernetes.io/certificate-arn" = "" + } + } + spec { + ingress_class_name = "alb" + default_backend { + service { + name = "springapp-spring-mongo" #springapp-mongo-spring-mongo + port { + number = 80 + } + } + } + rule { + host = "javaspringmongo.devopsnetwork.net" + http { + path { + path = "/" + path_type = "Exact" + backend { + service { + name = "springapp-spring-mongo" #springapp + port { + number = 80 + } + } + } + } + } + } + } +}*/ diff --git a/springapp-issuer.yml b/springapp-issuer.yml new file mode 100644 index 0000000..9aa0c20 --- /dev/null +++ b/springapp-issuer.yml @@ -0,0 +1,35 @@ +## This issuer will only be provisioned if certmanger has been deployed into the cluster. + +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: springapp-issuer +spec: + acme: + # The ACME server URL + server: https://acme-v02.api.letsencrypt.org/directory + # Email address used for ACME registration + email: + # Name of a secret used to store the ACME account private key + privateKeySecretRef: + name: springapp-priv + # Enable the HTTP-01 challenge provider + solvers: + - selector: + dnsNames: + - "" + dns01: + route53: + region: us-west-2 + # The AWS access key ID can be specified using the literal accessKeyID parameter + # or retrieved from a secret using the accessKeyIDSecretRef + # If using accessKeyID, omit the accessKeyIDSecretRef parameter and vice-versa + hostedZoneID: + accessKeyIDSecretRef: + name: goku + key: kamehameha + secretAccessKeySecretRef: + name: goku + key: spiritbomb + + diff --git a/var.tf b/var.tf new file mode 100644 index 0000000..abe973f --- /dev/null +++ b/var.tf @@ -0,0 +1,9 @@ +variable "krillin" { + description = "Username for springapp mongo db access" + default = "" #Always makes sure this matches the root user or custom user for the mongo database in the mongo helm chart +} + +variable "destructodisk" { + description = "Password for springapp mongo db access" + default = "" +}