Chronicles from the engine room #1
A few days ago, bored of weaselling and polishing countless power points slides that make so much of the output of any tech exec, I decided to explore the lower end of the call buttons of the elevator.
A brief trip to the engine room was long due. Indeed it has been years since I last venture where engineers spend all of their time in what I remember to be dark, secluded spaces below the waterline, relentlessly typing on their keyboards with the sole purpose to keep the ship running.
To my utmost surprise, the cabin accelerated at exhilarant speed upwards; in the blink of an eye, I found myself high in the sky, surrounded by puffy, white clouds.
Welcome to the cloud revolution.
Suddenly, what used to be tedious, meticulous work around servers and logs and protocols and scripts and so much more became as simple as flipping a few switches.?
Within a few days (and several hours stolen from my beloved presentations), I managed to code, test, build, and deploy the MVP of an analytical front end for my clients using the tech I was more acquainted with (Java, Scala, Spring).
Here's a brief compendium of my trip to the engine room.
It happened to be the MS Azure cloud, with which I have a certain familiarity, but I don't think it'd be much more different over any other platforms.
For this exercise I used the following stack:
(Disclaimer: This article is focused on the tenants of the cloud software deployment cycle, I'm not going to dig into the intricacies of the application architecture. It's just worth to mention that: I'm having incredible fun in working with Snowflake and their amazing customer support team; Spring Boot as a powerful, flexible and scalable framework, SonarQube as valuable tool to help my code to become better and better at every refactoring cycle and so much more.)
Meet Azure DevOps services.
What used to be a complex set-up of platforms and services during the glory days of XP (Extreme Programming, yes, I am that old) it's now a well polished and seamlessly integrated turn-key tool.
With some configuration and a few clicks, I had a top-notch environment to manage my code lifecycle, accept and trace user requests, and monitor release pipelines.
Let's start!
First and foremost, I had to install a local instance of the JDK and Maven, install my IDEA of choice (Intellij), install Docker, download SonarQube community edition image and run it:
docker run -d --name sonarqube -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true -p 9000:9000 sonarqube:latest
Git clone and I have my Azure DevOps repository ready to start!
Azure DevOps needs to be bound together at project level with a few configurations points within Maven:
Add the required server configuration and credentials to access the Azure DevOps Repo & Feed the maven settings.xml,
<server>
??<id>[FEED NAME]</id>
??<username>[username]</username>
??<password>[password]</password>
</server>
<server>
??<id>[REPOSITORY NAME]</id>
??<username>[username]</username>
<password>[password]</password>
</server>
To configure the <scm/> section on the maven pom.xml and complete the <distributionManagement/> in order to map it to the server.xml server entry, the followings need to be added to the pom.xml;
<distributionManagement>
?<repository>
<id>[FEED NAME]</id>
<url>[FEED URL]</url>
?</repository>
</distributionManagement>
<properties>
<project.scm.id>[REPOSITORY NAME]</project.scm.id>
</properties>
and the I'm ready to open the front page of Stack Overflow, all set and ready to code.
Hit the wall: face first at speed.
Coding is an extreme endurance sport; it takes training—a lot of it. Even if I thought I knew what I was doing, the intellectual instruments I used to master and the concepts and abstractions level I used to flip and spin at my will were nowhere to be seen anymore.
Lesson #1, never venture to the engine room without your toolbox!
Luckily, Stack Overflow is there to help, and with some patience, digging and scavenging for precious code snippets, I managed to replenish my box with the tools I needed and flex my sore muscles into proper coding.
Over the next few days, little by little, my code started to take some shape vaguely resembling my intentions.
Lesson #2, test first is good practice.
mvn clean test (repeat)
The first attempt was like trying to cook spaghetti carbonara, messy.
All unit tests worked perfectly, I had a staggering ~80% test coverage, but my code was a tight bundle of boilerplate, configurations, business logic and presentation models.
With the precious help of SonarQube Issue list, IntelliJ refactoring tools and the overly underestimated support of extensive unit tests, after a few hours of intense work it starts taking a decent shape.
Build, deploy, release.
It was now time to proceed with the first deployment attempt.
Spring boot is of great help to building applications as a Docker image. Ever since version 2.3-x it's possible to use Cloud Native Buildpacks from Maven using the spring-boot-maven-plugin.
If all works well, after having built the application's image, we can now push it?to Microsoft Azure App Services quickly and swiftly.??
A few considerations here. Using JDK 17 comes with some trickery, for some dependency conflict I had to add the
--add-opens java.base/java.lang=ALL-UNNAMED
argument to the JVM, it took quite a bit of digging and trying, at the end I found (Stack Overflow!) that it's possible to configure the image start command using the buildpack by adding the following configuration point to the spring-boot-maven-plugin:
<configuration>
<image
<env>
<BPE_DELIM_JAVA_TOOL_OPTIONS xml:space="preserve"/>
<BPE_APPEND_JAVA_TOOL_OPTIONS>--add-opens=java.base/java.lang=ALL-UNNAMED</BPE_APPEND_JAVA_TOOL_OPTIONS>
</env>
</image>
</configuration>
Moreover, by plugging the buildpack goal execution in the package phase I can now include the image composing with the broader maven package goal:
<executions
<execution>
<id>buildImage</id>
<phase>package</phase>
<goals>
<goal>build-image</goal>
</goals>
</execution>
</executions>
Nevertheless, out of the package goal, it's possible to build the docker image using the following:
领英推荐
mvn spring-boot:build-image
We can verify that the image has been correctly built:
docker image ls -a
So far, so good, easy. Now let's focus on the Azure set up.
All of the configurations can be done using the Azure Portal front end, but I have a preference for old school command line. Time to roll up my sleeves and get a terminal window.
Login into Azure
az login
Create a resource group:
az group create --name [RESOURCE GROUP NAME] --location [AZURE REGION]
Create the container registry:
az acr create --resource-group [RESOURCE GROUP NAME] --name [REGISTRY NAME] --sku [PRICING TIER OF CHOICE]
Now before pushing'n pulling images, we have to login into the registry:
az acr login --name [REGISTRY NAME]
Push the image from our local docker registry to the newly created Azure registry by using the FQDN:
docker tag [IMAGE NAME]:[VERSION] [REGISTRY NAME]/[IMAGE NAME]:[VERSION]
and we're good to push the image:
doker push [REGISTRY NAME]/[IMAGE NAME]:[VERSION]
Just to make sure all went as expected, a quick query to the registry for the specified image:
az acr repository list --name [REGISTRY NAME] --output table
I have now an image registered within my resource group that I can push up as application within Windows App Services:
Browse to the Azure portal and sign in.
Review the information and select Create. When the deployment is complete, select "Go to resource". The deployment page displays the URL to access the application.
Importantly, we have to keep in mind that Azure maps Internet requests to embedded Tomcat server that is running on the port - 80. If spring is configured to run on another port (e.g. 8080), we need to add an environment variable to the web app that defines the port for the embedded server.
In the Application settings section, add a new setting named WEBSITES_PORT and enter the custom port number for the value. Or, alternatively:
az webapp config appsettings set --[RESOURCE GROUP NAME] --name [APP NAME] --settings WEBSITES_PORT=[PORT]
And this is it! I can now test the app at the following URL:
https://[APP NAME].azurewebsites.net/[CONTEXT PATH]
Alternatively, and depending on our deployable artefact -say that we have built a microservice, it's possible to configure and run the container as follows:
az container create --resource-group [RESOURCE GROUP NAME]--name [CONTAINER GROUP NAME] --image [REGISTRY NAME]/[IMAGE NAME]:[VERSION] --dns-name-label [DNS NAME] --ports [PORT]
At this point, az cli will prompt for the registry username and password, it is possible to obtain these information by enabling admin user (disabled by default at registry creation) and retrieving locally the corresponding credentials:
az acr update --name [REGISTRY NAME] --admin-enabled true
and then
az acr credential show --name?[REGISTRY NAME]
testing it would be as easy as:
curl 'https://[DNS NAME].[AZURE REGION].azurecontainer.io:[PORT]/[CONTEXT]'
Conclusions
It's been incredibly fun to get back to coding, learn to use Azure Cloud, Azure DevOps, push my limits beyond standard deployment to containers and wrap it all together in a usable interface that I can now expose as MVP to my customers.
Did I have to do it? Probably not, I could have acted as a normal architecture lead and push down requirements and presentations to the engine room achieving the same net result for the business. So why did I do it?
I've been following Gregor Hope ever since the 90's and I absolutely agree with him when he says:
"The Architect Elevator is all about connecting levels: levels of abstraction, levels of corporate hierarchy, levels of strategy. To be effective at connecting these levels, it’s important for architects to actually visit them every once in a while. This can mean a physical (or video-virtual) visit to the penthouse for a strategy or steering meeting, a self-guided tour of reading the latest analyst reports, or trying out some technologies down in the engine room. In any case, it’s important to actual get out of the elevator lest you be rendered a “lift boy/person”"
I wanted to check out the cloud from a very practical and concreted starting point, it's easy to discuss cloud strategy at the penthouse, but it's also as easy to forget what it means from a practical standpoint.
To give my job title any justice and to be able to understand what it means to actually build services and solutions. This visit to the engine room has been extremely important and allowed me to define a few clear priorities when I architect solutions and platforms:
In the next article of this series I will focus on how to bind this all together in order to automate test/release/deploy cycle leveraging the Azure DevOps structure.
For now, it's time to get back to the elevators and get back to the penthouse for some neglected ivory tower duties requiring my attention!
Client Solutions Specialist | Custom Software for Marketing Tech Success
1 年Angelo, thanks for sharing!
Financial Services Executive | Digital Transformation Pioneer | Innovation Strategist | Fintech & Insurtech |
2 年I'm going to steal this --> "Scalability and efficient resource handling is key. In a place where there's access to almost infinite resources, it is of paramount importance to cautiously allocate said resources - for scalability comes at a cost and the cost can become steep very quickly."