Deploying sample Spring Boot app on Kubernetes with a MySQL RDS - dpsp-summit/wiki GitHub Wiki
In this tutorial we are going to deploy a sample application on a Kubernetes cluster and connect it to an external database.
The sample application is Products from this repository.
The database is going to be MySQL and will be created in AWS RDS.
Go to the AWS console -> Services -> RDS Select "Create Database"
Select "MySQL" then "Next"
On the "Use Case" screen and for the purpose of this tutorial we are going to select "Dev/Test - MySQL" then "Next"
On the "Instance Specifications" screen we are going to check the "Only enable options eligible for RDS Free Usage Tier" on the "Free Tier" card.
On the same page, for the "Settings" card set an instance identifier, master username and master password then "Next"
Finally, on the "Network & Security" card, the available VPC and Subnet options will depend on your AWS configuration. For this tutorial, we are selecting the default VPC and Subnet, which is public, but this is not recommended for a production environment.
Also, for the Database name we will input "products" as we will be using the Products sample app. Then we click "Next", and we are done configuring our RDS.
After a few minutes the status of the instance is going to transition to "Available".
We need to make sure that our Kubernetes cluster worker nodes can access the RDS instance. For that, we need to add the Kubernetes node IPs as inbound rules for the RDS security group or else we won't be able to reach the RDS from the nodes.
On the database details, click on the "VPN Security group"
This will take you to the "Security groups" page with your security group selected. There, click on "Inbound" on the details section. You will see that there's only one IP allowed:
Click on "Edit", then "Add Rule". For the rule type select "MYSQL/Aurora" and on Source add your node ips separated by commas as in the next image:
Click "Save" and you're done!
Once ready, we can test our MySQL connection locally by using the mysql client:
mysql -h mysqlinstance.ctnhfqspsvbe.us-west-2.rds.amazonaws.com -u username -p
Then we input the password and connect successfully to the instance.
To test if we can connect to our db from the Kubernetes cluster, we need to do the following:
- Run an Ubuntu pod that you can use as a client:
kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -il
- Install the mysql client:
apt-get update && apt-get install mysql-client -y
- Connect using the mysql cli, then provide your password:
mysql -h mysqlinstance.ctnhfqspsvbe.us-west-2.rds.amazonaws.com -p
Then we input the password and connect successfully to the instance.
Once connected to the DB, we create Products the schema:
create schema products;
use products;
Create the products table:
CREATE TABLE IF NOT EXISTS products (
id INT AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
And insert some sample data:
INSERT INTO products VALUES (1, 'Produto 1');
INSERT INTO products VALUES (2, 'Produto 2');
INSERT INTO products VALUES (3, 'Produto 3');
INSERT INTO products VALUES (4, 'Produto 4');
INSERT INTO products VALUES (5, 'Produto 5');
As we are connecting to an external resource, is a good practice to create an external service, so our application doesn't have to know about the real location of the database.
We create a file named external_service.yaml:
apiVersion: v1
kind: Service
metadata:
name: mysql-external
spec:
type: ExternalName
externalName: mysqlinstance.ctnhfqspsvbe.us-west-2.rds.amazonaws.com
ports:
- port: 3306
Remember to replace the "externalName" value with your actual RDS url.
And we create the service:
kubectl create -f external_service.yaml
Now that we have our database and external service ready, we need to deploy the Products App. The code for our application is in this repository.
Create a file named products.yaml for the products and service deployment:
kind: Deployment
apiVersion: apps/v1
metadata:
name: products
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: products
template:
metadata:
labels:
app: products
spec:
containers:
- name: products
image: fbereche/products-api:4.0.0
env:
- name: DB_SERVER
value: mysql-external
- name: DB_USERNAME
value: username
- name: DB_PASSWORD
value: mypassword
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: products-service
spec:
selector:
app: products
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 8080
Note: Remember to replace the DB_SERVER value with your external service name, and to replace DB_USERNAME and DB_PASSWORD values with the username and password defined in your RDS instance.
Execute the creation:
kubectl create -f products.yaml
After deploying the products service, we should see a new Load Balancer being created on the AWS console. Similar to this:
afd0aa50ea0fd11e9b53a02f515ffc3f-1489305742.us-west-2.elb.amazonaws.com
We can confirm this is the same URL shown for our products-service on Kubernetes:
kubectl get svc
The result should show something similar to this:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 100.64.0.1 <none> 443/TCP 14d
mysql-external ExternalName <none> mysqlinstance.ctnhfqspsvbe.us-west-2.rds.amazonaws.com 3306/TCP 22h
products-service LoadBalancer 100.65.111.242 afd0aa50ea0fd11e9b53a02f515ffc3f-1489305742.us-west-2.elb.amazonaws.com 80:31808/TCP 22h
It will take a few minutes to transition from OutOfService to InService. After it is ready, we can do a GET to the following URL:
afd0aa50ea0fd11e9b53a02f515ffc3f-1489305742.us-west-2.elb.amazonaws.com/products
We should get the following information:
[{"id":1,"name":"Produto 1"},{"id":2,"name":"Produto 2"},{"id":3,"name":"Produto 3"},{"id":4,"name":"Produto 4"},{"id":5,"name":"Produto 5"}]
Now you have an Spring Boot application connecting to an RDS instance. Congratulations!