- 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. ❤️