- Java
- Servlet
- Maven
- Tomcat
- Jenkins
- Docker
- Kubernetes
- Web Application made with
Java Servlet pom.xmlformavento build the application and package it into a.jarDockerfilewhich holds the steps to build a docker image of the web applicationJenkinsfileto helpJenkinsautomate the building and deploying the web application intodocker hub
git clone https://github.com/ariG23498/webapp_maven.git cd webapp_maven mvn package cd target/bin/ ./webappThe web application is running on your localhost at post 9090
Go to your favorite web-browser and in the address bar type localhost:9090
In the following steps we will talk specifically of the Kubernetes cluster that has been created, the cluster consists of 2 VM instances one working as the master other as the worker. The VMs must be in same resource group and share the same virtual network. In each of the VMs we need to run the following block of codes.
sudo apt-get remove docker docker-engine docker.io containerd runc sudo apt-get update sudo apt-get install -y \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo apt-key fingerprint 0EBFCD88 sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io cat > /etc/docker/daemon.json <<EOF { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2" } EOF mkdir -p /etc/systemd/system/docker.service.d systemctl daemon-reload systemctl restart dockerapt-get update && apt-get install -y apt-transport-https curl curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - cat <<EOF >/etc/apt/sources.list.d/kubernetes.list deb https://apt.kubernetes.io/ kubernetes-xenial main EOF apt-get update apt-get install -y kubelet kubeadm kubectl apt-mark hold kubelet kubeadm kubectlAuthorize Jenkins bye creating a new kubernetes service account and generating a base64 secret key:
kubectl -n webapp create sa jenkins kubectl create clusterrolebinding jenkins --clusterrole cluster-admin --serviceaccount=webapp:jenkins kubectl get -n webapp sa/jenkins --template='{{range .secrets}}{{ .name }} {{end}}' | xargs -n 1 kubectl -n webapp get secret --template='{{ if .data.token }}{{ .data.token }}{{end}}' | head -n 1 | base64 -d -Save the secret as secret text credential for using kubernetes-cli-plugin with Jenkins.
After setting up each VMs, we are creating a stateful persistent volume of 4 GiB for our MySQL database storage:
apiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv-volume labels: type: local spec: storageClassName: manual capacity: storage: 4Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pv-claim spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 4GiNow, we need to deploy the mysql:5.7 image as a deployment in the kubernetes cluster.
apiVersion: v1 kind: Service metadata: name: mysql spec: type: ClusterIP ports: - name: mysql port: 3306 protocol: TCP targetPort: 3306 selector: app: mysql --- apiVersion: apps/v1 kind: Deployment metadata: name: mysql spec: selector: matchLabels: app: mysql strategy: type: Recreate template: metadata: labels: app: mysql spec: containers: - image: mysql:5.7 name: mysql env: # Use secret in real usage - name: MYSQL_ROOT_PASSWORD value: Dare2@hack ports: - containerPort: 3306 name: mysql volumeMounts: - name: mysql-persistent-storage mountPath: /var/lib/mysql volumes: - name: mysql-persistent-storage persistentVolumeClaim: claimName: mysql-pv-claimSetup Jenkins as directed by Jenkins. For the CI/CD pipeline we had to authenticate Jenkins with GitHub, Docker Hub and Kubernetes. We have used the following deployment file to expose our webapp:
{ "apiVersion": "v1", "kind": "Service", "metadata": { "name": "webapp-v$BUILD_NUMBER", "labels": { "run": "webapp-v$BUILD_NUMBER" }, "namespace": "webapp" }, "spec": { "externalIPs": [ "104.211.230.185" ], "externalTrafficPolicy": "Cluster", "ports": [ { "nodePort": 32607, "port": 9090, "protocol": "TCP", "targetPort": 9090 } ], "selector": { "run": "webapp-v$BUILD_NUMBER" }, "sessionAffinity": "None", "type": "LoadBalancer" }, "status": { "loadBalancer": {} } }The rest of the CI/CD pipeline is taken care of by Jenkins. ❤️