How to do it...

We need to add the code for the rest of the system into our micro repository that we created in the previous recipe.

To do this let's copy the following top-level directories from the Adding a queue-based service micro folder into the root of our current micro folder (the one that is initialized as a GitHub) repository:

  • auditservice
  • eventservice
  • webapp
  • report
  • fuge

Our micro repository directory structure should now look as follows:

micro
├── .gitignore
├── adderservice
├── auditservice
├── deployment
├── eventservice
├── fuge
├── report
└── webapp

Let's go ahead and commit our changes and push them to GitHub:

$ cd micro
$ git add .
$ git commit -m 'added services and webapp'
$ git push origin master

Now let's apply the same build structure to eventservice, auditservice, and webapp.

Check with Fuge
We have copied across our Fuge config (fuge/fuge.yml) with our microservice system. We can start the system up anytime with Fuge to check that the system is running correctly (simply run fuge shell fuge/fuge.yml). Note that Jenkins runs on port 8080 by default, as does our adderservice, which leads to an unfortunate port conflict, so when testing in Fuge we need to stop Jenkins temporarily. It's left as an exercise for the reader to solve this collision.

To do this, copy the .dockerignore, Dockerfile, Jenkinsfile, and build.sh files from the adderservice folder to each of the eventservice, auditservice, and webapp folders:

$ cp adderservice/{.dockerignore,Dockerfile,Jenkinsfile,build.sh} eventservice
$ cp adderservice/{.dockerignore,Dockerfile,Jenkinsfile,build.sh} auditservice
$ cp adderservice/{.dockerignore,Dockerfile,Jenkinsfile,build.sh} webapp

Once copied, we will need to modify the Jenkinsfile and build.sh files to match the service that they now pertain to.

Specifically, this means replacing references to the name of the service (which currently is adderservice) and the port number.

We can do the bulk of necessary customizations quickly with sed. We can process each Jenkinsfile like so:

$ cat auditservice/Jenkinsfile | sed -e s/adderservice/auditservice/ | tee auditservice/Jenkinsfile
$ cat eventservice/Jenkinsfile | sed -e s/adderservice/eventservice/ | tee eventservice/Jenkinsfile
$ cat webapp/Jenkinsfile | sed -e s/adderservice/webapp/| tee webapp/Jenkinsfile

We can alter the build.sh file in a similar manner:

$ cat auditservice/build.sh | sed -e s/adderservice/auditservice/ -e s/8080/8081/ | tee auditservice/build.sh
$ cat eventservice/build.sh | sed -e s/adderservice/eventservice/ -e s/8080/8082/ | tee eventservice/build.sh
$ cat webapp/build.sh | sed -e s/adderservice/webapp/ -e s/8080/3000/ | tee webapp/build.sh

Notice how we also convert the port number in each case from 8080 to the relevant port for the service (based on how we've typically mapped services to ports thus far, as laid out initially in fuge/fuge.yml).

As in our previous recipe, we need to tweak the test field in the package.json for each service so it has an exit code of zero. As mentioned previously, we're simulating successfully passing unit tests, but in a real scenario we would want each service to run unit tests instead of having a faux successful exit code.

We can run the following commands to alter the package.json in each service:

$ node -e 'o = require(`./auditservice/package.json`);o.scripts.test = `echo "Error: no test specified" && exit 0`;fs.writeFileSync(`./auditservice/package.json`, JSON.stringify(o, 0, 2))'
$ node -e 'o = require(`./eventservice/package.json`);o.scripts.test = `echo "Error: no test specified" && exit 0`;fs.writeFileSync(`./eventservice/package.json`, JSON.stringify(o, 0, 2))'
$ node -e 'o = require(`./webapp/package.json`);o.scripts.test = `echo "Error: no test specified" && exit 0`;fs.writeFileSync(`./webapp/package.json`, JSON.stringify(o, 0, 2))'

The webapp/Dockerfile should be modified with the final CMD instruction set to npm start instead of node index.js.

The entire webapp/Dockerfile file should look as follows:

FROM node:slim
RUN mkdir -p /home/node/service
WORKDIR /home/node/service
COPY package.json /home/node/service
RUN npm install
COPY . /home/node/service
CMD [ "npm", "start" ]

Once we have completed these changes for the auditservice, eventservice, and webapp folders, we can commit them to the GitHub master branch:

$ git add .
$ git commit -m 'added build files'
$ git push
Independent variation
We have chosen to clone and modify our build script and Jenkinsfile for each service. While we could have created a single parameterized script to deploy our services, it is usually better to have a build script per service. That way, the build may be customized as required for each service without introducing complications into a master build script.

Recall from our Chapter 10, Building Microservice Systems, that auditservice and eventservice require mongodb and redis to run correctly. Therefore we need to ensure that these elements are deployed as part of our overall pipeline. To do this, let's create a directory called infrastructure under micro and add a build.sh file and a Jenkinsfile

The build.sh should contain the following code:

#!/bin/bash
source ~/.bashrc
case "$1" in
mongo)
sed -e s/_NAME_/mongo/ -e s/_PORT_/27017/
< ../deployment/service-template.yml > svc.yml
sed -e s/_NAME_/mongo/ -e s/_PORT_/27017/ -e s/_IMAGE_/mongo/
< ../deployment/deployment-template.yml > dep.yml
sudo -i -u <user> kubectl apply -f $(pwd)/svc.yml
sudo -i -u <user> kubectl apply -f $(pwd)/dep.yml
;;
redis)
sed -e s/_NAME_/redis/ -e s/_PORT_/6379/
< ../deployment/service-template.yml > svc.yml
sed -e s/_NAME_/redis/ -e s/_PORT_/6379/ -e s/_IMAGE_/redis/
< ../deployment/deployment-template.yml > dep.yml
sudo -i -u <user> kubectl apply -f $(pwd)/svc.yml
sudo -i -u <user> kubectl apply -f $(pwd)/dep.yml
;;
*)
echo 'invalid build command'
exit 1
;;
esac

The Jenkinsfile should look as follows:

pipeline {
agent any

stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('DeployMongo'){
steps {
sh 'source ~/.bashrc && cd infrastructure && sh build.sh mongo'
}
}
stage('DeployRedis'){
steps {
sh 'source ~/.bashrc && cd infrastructure && sh build.sh redis'
}
}
}
}

We can now commit and push the infrastructure additions to GitHub:

$ git add infrastructure
$ git commit -m 'infrastructure'
$ git push

Now we are ready to configure Jenkins.

From the main Jenkins dashboard, let's click New Item and select the Pipeline type. We'll give our new pipeline the name: infrastructure. Jenkins provides a convenient shortcut. We can instruct Jenkins to copy settings from the adderservice pipeline configuration as follows:

This means the GitHub configuration and the infrastructure pipeline are copied automatically. It also means that the Script Path setting points to adderservice/Jenkinsfile instead of infrastructure/Jenkinsfile. Let's navigate to the configuration screen for the infrastructure pipeline section and change the Script Path setting from adderservice/Jenkinsfile to infrastructure/Jenkinsfile. We can now manually trigger a build of our infrastructure pipeline. Once this is done, we can inspect Kubernetes using the dashboard:

$ minikube dashboard 

The Minikube should look similar to the following screenshot:

That takes care of our infrastructure.

We now just need to configure our other services. To complete this, we must repeat the preceding steps for each of eventservice, auditservice, and webapp, making sure to copy settings from adderservice and updating the Script Path setting in each case.

Once we have completed configuring all our services, our main Jenkins dashboard should look as follows:

We can now trigger builds for each of our services and the webapp by clicking the left-hand menu, selecting each and clicking build now.

Once all of the builds have completed, we can open up the minikube dashboard, which should look similar to the following screenshot:

Finally, we can test that our system is up and running correctly.

We need to determine the external port number that Kubernetes assigned to our web app and also the Kubernetes IP address:

$ minikube ip
192.168.99.100
$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
adderservice 10.0.0.139 <nodes> 8080:30743/TCP 22m
auditservice 10.0.0.209 <nodes> 8081:32391/TCP 19m
eventservice 10.0.0.41 <nodes> 8082:32104/TCP 13m
mongo 10.0.0.172 <nodes> 27017:31000/TCP 17m
redis 10.0.0.57 <nodes> 6379:31863/TCP 17m
webapp 10.0.0.54 <nodes> 3000:30607/TCP 9m

In the case of the preceding output, we can see that the webapp is available on IP address 192.168.99.100 port number 30607. If we now go ahead and point our browser to http://192.168.99.100:30607/add we should see the webapp page rendered as before. When we enter some numbers and press add, we should see a result. Also, the audit endpoint at http://192.168.99.100/30607/audit should show a recording of all of our calculations.

A final thing we can do is to automate the build pipeline to trigger after pushing to GitHub.

To do this, we need to repeat the step of the previous recipe by selecting the Poll SCM setting for each project and setting the schedule to * * * * * to poll every minute.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset