We will now take our first step toward modernizing our application by moving it to the cloud. In this chapter, we will not be making any changes to the application itself, but instead we will be looking at the absolute minimum infrastructure architecture needed to run the application on Google Cloud. Once we have our initial architecture, we will then go step by step through implementing the architecture on Google Cloud using the Google Cloud Console.
In this chapter, we will cover the following:
In order to follow along and implement the steps in this book, you will need to have the following:
Our starting point will be the legacy infrastructure architecture illustrated in Figure 9.1:
The key elements from this architecture that we need to consider for our initial rehosting are as follows:
Before we begin to design our infrastructure architecture, there are a few Google Cloud terms that we need to define as they are key to understanding how Google Cloud is organized, and where we will place our resources. A resource in Google Cloud is classified as a global resource, regional resource, or zonal resource:
Now we understand global, regional, and zonal resources, we can begin to map out our infrastructure architecture.
In Google Cloud, our network is provided by a Virtual Private Cloud (VPC). This is a virtualized version of a physical network. A VPC is a global resource meaning it is not associated with a specific region or zone. When we create a project in Google Cloud a default VPC is provisioned for us automatically. This VPC has a subnet automatically provisioned for every Google Cloud region available. A subnet is a regional resource so cannot be in more than one region but is available to every zone in its region. In a production scenario we would not use the default VPC, but instead specify and configure a VPC based exactly on what we need in terms of zones and IP address ranges. For the purposes of our modernization journey, we will use the default VPC.
Our next step is to decide which region we will be using. As I am based in the UK, I chose europe-west2 as that region is hosted in the UK. Choose a region that is close to you in order to minimize latency. Finally, we pick a zone to place our VMs in (remember that VMs are an example of a zonal resource). In this case we have chosen europe-west2-c.
These choices mean we have the following start to our infrastructure architecture, shown in the following figure depicting the initial infrastructure architecture (network):
Now we have made our decisions on which region and zone we will be working in; we can continue onward and consider what VMs we will provision. From Figure 9.1, we can identify that we will need a minimum of three VMs. At this point, we are not considering concerns such as availability, we are just looking at the minimum to get our functionality running in Google Cloud..
The VMs we will need are as follows:
Adding these VMs to our infrastructure architecture gives us the following:
As this is development rather than production, we will initially give all the VMs public IP addresses. In production, this would be a serious security issue and must not be done. We are keeping things simple to focus on the actual modernization tasks and we have no private or confidential data at risk. For serious development, we would use either a VPN to access the VMs or create a Bastion host for the same purpose.
Now we have our network and VMs identified and added to our architecture. What next?
Although we are giving every VM a public IP address, we will still need to implement some network security. The focus here will be on the network security for the application rather than our administration of the VMs. We will be making use of Google Cloud firewall rules.
This is a global service provided by Google Cloud and allows us to filter traffic based on the following:
Rules can be applied to ingress (incoming) and egress (outgoing) traffic, and either allow or deny traffic that matches the given rule.
Our rules from our legacy application state the following:
As we are working in a learning sandbox, we will leave the default rule provided by Google Cloud in place that allows ingress to all VMs from any address to SSH. Again, we cannot stress enough that this is not recommended for production environments.
Now that we have taken firewalls into consideration, we have the final version of our initial infrastructure architecture laid out, which we will continue to build on in the rest of this book. The following diagram depicts that initial infrastructure and network architecture:
Now that an initial network architecture has been created, let's plan to create the modernization Google Cloud project.
Before we start building out our architecture in Google Cloud we need to set up the structure for our account. At the root of the structure, we have the organization we created when we set up Cloud Identity for Identity and Access Management (IAM). An account can have only one organization. The organization can contain folders and/or projects. A folder can contain folders or projects. This provides us with a tree structure for organizing our resources, called the resource hierarchy.
The purpose of our resource hierarchy is to do the following:
For our organization, we will keep things simple and create a folder called modernization and within that folder a project called BankingApplication. Our resource hierarchy will then look like this:
A more realistic resource hierarchy for an enterprise may look like this:
Now we have defined our resource hierarchy, we will create it in Google Cloud using the following steps:
Now that we have established our resource hierarchy and created our project, we can begin implementing our infrastructure architecture.
We described earlier in this chapter how when a project is created, a default VPC is automatically created for us. This means we can simply reuse that VPC for our modernization work. What remains to be done is implementing the firewall rules we defined previously. To recap, the rules are as follows:
We will now implement these firewall rules using the following steps:
You will now see the default rules that are allocated to our project:
a) Name: A unique name for your firewall rule. In this case, we'll use allow-http-https.
b) Network: default(in new line L-regular)
c) Priority: 1000
d) Direction of traffic: Ingress
e) Action on match: Allow
f) Targets: Specified target tags
g) Target tags: web
h) Source filter: IP ranges
i) Source IP ranges: 0.0.0.0/0
j) Protocols and ports: Specified protocols and ports
k) Select tcp and enter 80 and 443:
a) Name: allow-redis
b) Network: default
c) Direction of traffic: Ingress
d) Action on match: Allow
e) Targets: Specified target tags
f) Target tags: redis
g) Source filter: Source tags
h) Source tag: web
i) Protocols and ports: Specified protocols and ports
j) Select tcp and enter 6379
a) Name: allow-mysql
b) Network: default
c) Direction of traffic: Ingress
d) Action on match: Allow
e) Targets: Specified target tags
f) Target tags: mysql
g) Source filter: Source tags
h) Source tag: web
i) Protocols and ports: Specified protocols and ports
j) Select tcp and enter 3306
Let's summarize what we have just done:
In the next section, we will implement our VMs, applying the tags we referenced in our firewall rules to enable the required communications for our application.
Now we get to the core of this chapter: implementing our VMs. We will build these up manually and create them using the Google Cloud Console. A later chapter will cover automation and creating a CI/CD pipeline in order to enable DevOps.
We will start at the backend of the solution and move forward. There are two backend services in our solution, sessions and persistence. As we must choose one or the other, we will start with persistence, meaning our MySQL database.
As we want to make as few changes as possible, and not have to install software if we can avoid it, we will make use of the Google Cloud Marketplace. Specifically, we will use the MySQL certified by Bitnami image from the Marketplace.
This VM image comes with MySQL preinstalled and is set up to minimize costs for a development environment. It is well suited for the purpose of learning about modernization.
We will create and configure the MySQL VM using the following steps:
sudo apt-get -y update
Next, we will change the password we recorded in the previous step 7. To do this we need to log in to the MySQL server from our SSH session following the steps:
mysql -u root -p
alter user '''root''@''localhost' 'localhost'' identified by ''<yournewpassword>'';
flush privileges;
quit
Log in again using the command from step 1 and your new password to ensure this has worked. At this point, we have an empty MySQL server ready to configure as needed for our application.
create database banking;
create user ''bankinguser''@''%'' identified with mysql_native_password by ''<newpassword>'';
grant all on banking.* to ''bankinguser''@''%'';
With the preceding commands we did the following:
a) Created the database.
b) Created our user with the name bankinguser, allowed access from any host using the % location, and set <newpassword> as the password. In production, we would lock down the location more precisely. Please be sure to record the password.
c) Granted our user all authorizations on the banking database. In production, we would not need all authorizations, but as we are in development, our application will create the database artifacts (schemas, tables, and others) as needed.
The final step in setting up this server is to apply our firewall rule. We will do this by adding the mysql tag to the VM. As we used the marketplace image for the MySQL server, a tag has already been added, but it is important to understand how to add network tags to our servers, hence we will do this, even though if we had used the tag provided by the marketplace, we would not have needed to do this.
To apply the mysql tag, follow the steps:
That completes the provisioning and configuration of our MySQL VM. We have prepared the database for our application and applied the mysql tag to allow for communication between the Tomcat server and the MySQL server.
Now we will create our Redis VM. The steps already explained previously will not be repeated in detail for this VM:
sudo apt-get -y update
redis-cli -h redis-vm
AUTH <CURRENTPASS>
CONFIG SET requirepass <NEWPASS>
AUTH <NEWPASS>
Finally, we will create our Tomcat VM. The steps already explained will not be repeated in detail for this VM:
sudo /opt/bitnami/bncert-tool
Domain list []: www.banking.jasonmarston.me.uk banking.jasonmarston.me.uk
Enable HTTP to HTTPS redirection [Y/n]: ny
Enable non-www to www redirection [Y/n]: n
Enable www to non-www redirection [y/N]: ny
Do you agree to these changes? [Y/n]: y
E-mail address []: [email protected]
Do you agree to the Let's Encrypt Subscriber Agreement? [Y/n]: y
Press [Enter] to continue:
# MySQL Configuration
export BANKING_DATASOURCE_DDL_AUTO="update"
export BANKING_DATASOURCE_DIALECT="org.hibernate.dialect.MySQL5Dialect"
export BANKING_DATASOURCE_PASSWORD="<YOUR_MYSQL_PASSWORD>"
export BANKING_DATASOURCE_URL="jdbc:mysql://mysql-vm.europe-west2-c:3306/banking?useSSL=false&allowPublicKeyRetrieval=true"
export BANKING_DATASOURCE_USERNAME="bankinguser"
# Hostname for use in emails
export BANKING_HOST_NAME="<YOUR_FULLY_QUALIFIED_DOMAIN_NAME>"
# Administration user configuration
export BANKING_INITIAL_ADMIN_CONTEXT_PATH="/"
export BANKING_INITIAL_ADMIN_EMAIL="<YOUR_EMAIL_ADDRESS>"
export BANKING_INITUAL_ADMIN_PASSWORD="<YOUR_INITIAL_PASSWORD>"
We will continue with the configuration for logging, email, environment, and Redis:
# Logging configuration
export BANKING_LOGGING_LEVEL="WARN"
# Email Configuration
export BANKING_MAIL_AUTH="true"
export BANKING_MAIL_FROM="noreply@<YOUR_DOMAIN>"
export BANKING_MAIL_HOST="<YOUR_SMTP_SERVER>"
export BANKING_MAIL_PASSWORD="<YOUR_SMTP_PASSWORD>"
export BANKING_MAIL_PORT="<YOUR_SMTP_PORT>"
export BANKING_MAIL_SOCKET_FACTORY="javax.net.ssl.SSLSocketFactory"
export BANKING_MAIL_STARTTLS="false"
export BANKING_MAIL_USERNAME="<YOUR_SMTP_USERNAME>"
# Environment configuration
export BANKING_PROFILES_ACTIVE="DEV"
# Redis configuration
export BANKING_REDIS_HOST="redis-vm.europe-west2-c"
export BANKING_REDIS_PORT="6379"
export BANKING_REDIS_PASSWORD="<YOUR_REDIS_PASSWORD>"
The preceding configuration does the following:
a) Informs the application that we are using MySQL as the relational database, and how to connect to it
b) Sets the logging level to WARN (we can change this to INFO or DEBUG if we need more detailed logging)
c) Provides the details of our initial administration user for the application
d) Provides the information needed to send emails from the application
e) Specifies that this is a development environment
f) Provides the details on how to connect to Redis
sudo rm -rf /opt/bitnami/tomcat/webapps/*
sudo cp ~/ROOT.war /opt/bitnami/tomcat/webapps
sudo chown tomcat:tomcat /opt/bitnami/tomcat/webapps/ROOT.war
Now you have deployed the application and, in a few minutes, you can test it using the fully qualified domain name you set up earlier. In my case, the custom domain I set up was www.banking.jasonmarston.me.uk.
Once that is completed, we need to ensure the database is updated appropriately.
The goal now is to create an applicable table in the database and the rows associated with that table. The necessary files are provided in the repository:
sudo mysqldump –add-drop-table -u root -p banking > banking.sql
Copy the file to the destination server:
mysql -u root -p banking < banking.sql
Then follow the earlier steps to make sure that bankinguser exists and has the correct permissions.
In this chapter, we looked at the infrastructure architecture of our legacy application and designed a simple initial infrastructure architecture for moving the application into the Google cloud. We decided that there would be no changes to the application code base, and we would only be changing the infrastructure. The infrastructure architecture did not address concerns such as scalability or availability, but instead focused on hosting our functionality and on network security between the layers of our application.
We then created our organizational structure and the project we will be working on throughout this book. Next, we implemented the firewall rules and the three VMs using the Marketplace. Then, we introduced persistence with a MySQL VM, sessions storage using the Redis VM, and an application web server with the Tomcat VM. Finally, we deployed our application and performed a basic test to see if we could access it.
In the next chapter, we will continue to refine our infrastructure architecture. Specifically, we will start to address concerns such as scalability and availability by making use of Google Cloud features such as zones and load balancers.