Slide 1

Slide 1 text

Deploy and Run Java Applications on OKE with the MySQL Database Service Olivier DASINI MySQL, EMEA Marc GUEURY AppDev, EMEA

Slide 2

Slide 2 text

MySQL Copyright © 2021, Oracle and/or its affiliates. All rights reserved. The world’s most popular open source database 2 2

Slide 3

Slide 3 text

Innovative enterprises across many industries run MySQL Social E-Commerce Tech Finance Manufacturing Copyright © 2021, Oracle and/or its affiliates. All rights reserved. 3 3

Slide 4

Slide 4 text

MySQL for Cloud Native Copyright © 2021, Oracle and/or its affiliates. All rights reserved. Why it is a Natural Choice? 4 4

Slide 5

Slide 5 text

MySQL is the Natural Choice for Cloud Native l MySQL can perform multiple roles: - Traditional RDBMS (SQL) - JSON Document Store (NoSQL) l MySQL is lightweight, inexpensive and easy to operate - Deploying multiple instances is not a problem l MySQL produces container-ready images - For both Community Edition and Enterprise Edition - MySQL has a Kubernetes Operator making the deployment of HA MySQL containers simplistic l MySQL has connectors for all mainstream programming and scripting languages l MySQL can be consumed as a service in Oracle Cloud Infrastructure l MySQL Database Service – the only service to be 100% MySQL - Concentrate on your schema – we do all the rest (support, updates, backup, appropriate config, etc) - Removes complexity of handling state in orchestration environments such as Kubernetes Copyright © 2021, Oracle and/or its affiliates. All rights reserved. 5 5

Slide 6

Slide 6 text

MySQL High Availability Copyright © 2021, Oracle and/or its affiliates. All rights reserved. Avoid loss of service by reducing the risk of failures 6 6 Fault Tolerance

Slide 7

Slide 7 text

A complete built-in High Availability solution for MySQL MySQL InnoDB Cluster l MySQL Servers synchronously replicate - Secondary servers are read-only - Failover is automated l No human intervention needed - New members clone from others (cloning) - Restored members catch up (synchronization) l MySQL Router sends the write sessions to the primary server only - Read-only sessions are distributed by MySQL Router to the secondary servers - Automatically sends writes to the new primary after failover l MySQL Shell provides a full administration interface to the cluster Copyright © 2021, Oracle and/or its affiliates. All rights reserved. 7 7

Slide 8

Slide 8 text

MySQL InnoDB Cluster Consistency: No Data Loss (RPO=0) • In event of failure of primary member • Split brain prevention (quorum) Elasticity / Read Scaling • Add/remove members as needed • Replication Lag handling with Flow Control • Configurable consistency levels • Eventual • Full consistency (no stale reads) Highly Available: Automatic Failover • Primary members are automatically elected • Automatic network partitioning handling Goals Copyright © 2021, Oracle and/or its affiliates. All rights reserved. 8 8

Slide 9

Slide 9 text

Options for where you run MySQL Clustering For High-Availability Compute nodes / VMs MySQL InnoDB Cluster Easy to setup Easy to manage Automated failover Not a managed service Kubernetes MySQL Operator Easier to setup Easier to manage Automated failover Mostly managed service Public Cloud MySQL Database Service Easiest to setup Easiest to manage Automated failover Fully managed service Copyright © 2021, Oracle and/or its affiliates. All rights reserved. 9 9

Slide 10

Slide 10 text

MySQL Database Service Copyright © 2021, Oracle and/or its affiliates. All rights reserved. 100% Developed, Managed & Supported by the MySQL Team 10 10

Slide 11

Slide 11 text

MySQL Database Service Overview Copyright © 2021, Oracle and/or its affiliates. All rights reserved. 11 100% Developed, Managed and Supported by the MySQL Team

Slide 12

Slide 12 text

MySQL Database Service: High Availability, multi AD Region 12 Copyright © 2021, Oracle and/or its affiliates. All rights reserved. Deployed across fault and availability domains Native MySQL Group Replication No data loss in case of failure (RPO=0) Online and fast fail-over (RTO=minutes) Inbound Replication MySQL Database Service Applications (Secondary) (Secondary) (Primary) AD1 MySQL Group Replication AD2 AD3 Fault-tolerant system with automatic failover & zero data loss through Group Replication

Slide 13

Slide 13 text

MySQL HeatWave MySQL in-Memory Query Accelerator Copyright © 2021, Oracle and/or its affiliates. All rights reserved. 13 13

Slide 14

Slide 14 text

MySQL HeatWave - MySQL in-Memory Query Accelerator 14 Copyright © 2021, Oracle and/or its affiliates. All rights reserved. Easily run high performance analytics against your MySQL database, no ETL required Single MySQL database for OLTP & analytics applications All existing applications work without any changes Extreme performance: 400x faster than MySQL, scales to thousands of cores OLAP Applications OLTP Applications OLTP Engine Analytics Engine MySQL Database Service

Slide 15

Slide 15 text

*Benchmark queries are derived from the TPC-H benchmark, but results are not comparable to published TPC-H benchmark results since they do not comply with the TPC-H specification 400G, 64 cores MySQL HeatWave dramatically speeds up analytic queries 15 Copyright © 2021, Oracle and/or its affiliates. All rights reserved.

Slide 16

Slide 16 text

MySQL Operator for k8s Copyright © 2021, Oracle and/or its affiliates. All rights reserved. Manage MySQL InnoDB Cluster inside a Kubernetes Cluster 16 16 Kubernetes

Slide 17

Slide 17 text

Official MySQL container distribution published and supported by Oracle • MySQL Server • MySQL Router Community Edition available on l https://hub.docker.com/u/mysql Commercial Edition available on l https://container-registry.oracle.com l https://edelivery.oracle.com l https://support.oracle.com Like Community version, but adds: • Security/privacy plugins • MySQL Enterprise Backup MySQL 8.0 Docker Images Copyright © 2021, Oracle and/or its affiliates. All rights reserved. 17 17 Accelerate how you build, share, and run MySQL

Slide 18

Slide 18 text

• Automated deployment and management of • MySQL Server • MySQL Router • Self-healing • Backup & Restore • Scaleup/Scaledown of Router & Server • Community Edition, Open Source License (UPL) • Enterprise Edition • Fully supported by Oracle • Rolling upgrades with minimal downtime • Configuration Management • Deploy from InnoDB CLONE • Private container registries MySQL Operator for Kubernetes Public preview state : https://github.com/mysql/mysql-operator The MySQL Operator for Kubernetes is designed to help operate MySQL InnoDB Cluster in Kubernetes environment: • Greatly simplify operations • Improve high-availability • Offer a more "native" Kubernetes experience to the user Copyright © 2021, Oracle and/or its affiliates. All rights reserved. 18 18 Manage MySQL InnoDB Cluster inside a Kubernetes Cluster

Slide 19

Slide 19 text

Copyright © 2021, Oracle and/or its affiliates 19 Docker Refresher Basic Docker commands to build and run containers

Slide 20

Slide 20 text

1. Install and start Docker on your machine 2. Write an application 3. Write a Dockerfile • Command to pull a base image from Docker Hub (or other repository) • Commands to modify the base image, these will include both the installation & config of the app • Provide an entry point to the application 4. Build the new Docker image using the Dockerfile 5. Run the Docker image as a container 6. Optionally, make the image available to others Docker: The Basics Copyright © 2021, Oracle and/or its affiliates 20

Slide 21

Slide 21 text

Minimal Java, simple database schema import java.sql.*; public class QueryDB { public static void main(String[] args) { try { Connection cnx = DriverManager.getConnection(args[0]); Statement stmt = cnx.createStatement(); ResultSet rs = stmt.executeQuery("SELECT id, name FROM t1"); while (rs.next()) { System.out.println(rs.getInt(1) + " " + rs.getString(2)); } cnx.close(); } catch (SQLException e) { e.printStackTrace(); } } } An Application to Demonstrate Docker Copyright © 2021, Oracle and/or its affiliates 21 mysql> CREATE DATABASE db1; mysql> USE db1; mysql> CREATE TABLE t1 ( -> id INT AUTO_INCREMENT PRIMARY KEY, -> name VARCHAR(20) NOT NULL -> ); mysql> CREATE USER 'app'@'%' -> IDENTIFIED BY 'Welcome1!'; mysql> GRANT SELECT ON db1.* TO 'app'@'%'; mysql> INSERT INTO t1(name) VALUES ('fred'); ...

Slide 22

Slide 22 text

Development Server File System Dockerfile Docker Image (from openjdk:11) Dockerfile Copyright © 2021, Oracle and/or its affiliates 22 FROM openjdk:11 COPY . /app COPY lib /app/lib WORKDIR /app RUN javac QueryDB.java CMD ["java", "-classpath", "lib/*:.", "QueryDB", "jdbc:mysql://10.0.30.243/db1? user=app&password=Welcome1!"] lib QueryDB.java QueryDB.class mysql- connector- java-8.0.27.jar app / Notes: • If the code was compiled (using javac) on the development server we could remove the RUN line. The first COPY would copy the class file across • CMD must be written on one line • DB URL & credentials should be externalized In our case this file has one line: Dockerfile lib QueryDB.java Dockerfile mysql- connector- java-8.0.27.jar .dockerignore dev

Slide 23

Slide 23 text

Docker containers can be run in the background using the detach flag, -d (pointless for this container) It’s also possible to look inside a container without running the app (good for debugging) Building and Running Copyright © 2021, Oracle and/or its affiliates 23 opc@devserver% docker build –t querydb . opc@devserver% docker images REPOSITORY TAG IMAGE ID CREATED SIZE querydb latest 63c6dd1be4d9 28 seconds ago 662MB openjdk 11 0719902862f3 7 days ago 659MB opc@devserver% opc@devserver% docker run querydb 1 fred 2 wilma ... opc@devserver% opc@devserver% docker run -it --entrypoint /bin/bash querydb root@454027f81771:/app# ls QueryDB.class QueryDB.java lib root@454027f81771:/app# exit opc@devserver%

Slide 24

Slide 24 text

• High Availability • Handling life cycle events • Starting/stopping containers • Scale-in, scale-out, maintaining a desired state • Upgrades without downtime, rollback/roll forward • Handling erroring containers • Handling state • Integration with our CI/CD processes • …and we need to do all this securely Raw Docker in Production? Copyright © 2021, Oracle and/or its affiliates 24

Slide 25

Slide 25 text

Copyright © 2021, Oracle and/or its affiliates 25 Kubernetes The case for orchestration Key components Stateless and Stateful Persistence Options Building a Kubernetes Environment in OCI

Slide 26

Slide 26 text

Kubernetes is an orchestration system • Manages containerized workloads and services including - deployment (automated rollout/rollback), scaling - service discovery, storage orchestration, batch execution and more • It facilitates both declarative configuration and automation - provides consistency, repeatability - enforces desired states – implement highly available services Kubernetes is Open Source • Originates from Google • Now maintained by the Cloud Native Computing Foundation Kubernetes has become the Market Leader • Used by many Cloud Vendors – Oracle Kubernetes Environment (OKE) Why Kubernetes? Copyright © 2021, Oracle and/or its affiliates 26

Slide 27

Slide 27 text

Oracle Cloud (OCI) VCN OKE Public Subnet Private Subnet Sample Architecture Copyright © 2021, Oracle and/or its affiliates 27 Kubernetes Load Balancer Developer Kubernetes API Server Bastion Users Node Java Node Java Node MySQL Database Service

Slide 28

Slide 28 text

A Pod is the smallest element of scheduling • Serves as a wrapper to your container • You cannot run bare containers A pod may additionally have a side car • Side cars are typically used for logging / monitoring • The can additionally be used to run commands • MySQL Operator for Kubernetes • The Master node schedules the pod on a specific node and coordinates with the container runtime to launch the container. • (Horizontal) Scaling is achieved by adding or removing Pods, for example • To scale a web server we can increase the number of pods which are running an nginx web server • In this case to scale sensibly we would need to use a load-balancer service Kubernetes Pods Copyright © 2021, Oracle and/or its affiliates 28 Pod Container

Slide 29

Slide 29 text

Deployments define what we want to achieve • e.g. the number of Pods of a particular type (i.e. replicas) • Referred to as the desired state which Kubernetes will maintain • i.e. compares current state with desired state and adjusts accordingly Deployments facilitate scaling, updates and rollbacks Pods that run in deployments are • Not started in any particular order • Restarted if deemed unhealthy or dead • Will not have any state persisted Run stateless containers in deployments Kubernetes Deployments Copyright © 2021, Oracle and/or its affiliates 29 Deployment Pod Container Pod Container

Slide 30

Slide 30 text

Kubernetes was originally design to run stateless apps • Stateless containers may use state but they have no need to persist it beyond a container’s lifetime • Stateful sets provide an answer to storing state beyond container lifetime and sharing/accessing external file based state between containers Statefulsets manage the deployment and scaling of a set of Pods, and provide guarantees about the ordering and uniqueness of these Pods • Statefulset Pods have a sticky identity whereas they are anonymous with ReplicaSets • Pods can be started in a specific order • Pods may not be replaced Kubernetes Stateful Sets Copyright © 2021, Oracle and/or its affiliates 30 Statefulset Pod Container Persistent Volume Claim (PVC) Volume Claim (Physical Storage) MySQL when deployed in containers using the MySQL Operator for Kubernetes creates a Statefulset for the cluster tier. The MySQL Router tier is implemented as a deployment

Slide 31

Slide 31 text

Services provide an interface between Kubernetes Deployments or Stateful sets and the outside world. Services: • Manage IP addresses • Provide service information • Perform port mapping • (Optionally) connection load balancing Kubernetes Services Copyright © 2021, Oracle and/or its affiliates 31

Slide 32

Slide 32 text

32 Container Engine for Kubernetes (OKE) • Certified Kubernetes conformant • Open Container Initiative compliant • No vendor lock-in • Highly available by default • Automatic scaling • Self-healing cluster nodes • Managed data plane components • Node Doctor for easy troubleshooting • Heterogenous Clusters • Flexible Infrastructure • Available as a day 1 service globally in all 37+ regions • Available on Dedicated Region Cloud@Customer • No cluster management fees • Enterprise support included • Rightsized compute through Flex shapes • Private clusters • Audit Logging • Image Scanning & Signing • Regulatory Compliance (FedRAMP, HIPAA, SOC2, etc.). • Conformance with Kubernetes STIG and NSA/CISA/DoD guidelines. Open Standards Deployment Flexibility Built-in Management Reduced Costs Advanced Security • Rich compute shape support - HPC, GPU, ARM, Flex, Bare metal, and VM • Industry leading cluster provisioning times • Predictable and consistent performance of Gen-2 infrastructure High Performance Copyright © 2022, Oracle and/or its affiliates. All rights reserved.

Slide 33

Slide 33 text

Governance OKE Cluster Data Plane Worker nodes Container images Kubernetes Persistent Volume Claims Identity and Access Networking Encryption Seamless integration with other OCI services 33 Copyright © 2022, Oracle and/or its affiliates. All rights reserved. Bare Metal Compute Virtual Machine OCI VCN OCI VCN Security Lists/Groups OCI Container Registry OCI VCN Route Table Auditing Logging OCI IAM Groups OCI Key Vault Monitoring OCI File Storage Container Engine For Kubernetes Kubernetes Services type Load Balancer OCI Block Storage OCI IAM Policies 3rd party identity system OCI Load Balancer Application users federation Control Plane Kubernetes API Server etcd Node kubelet kube-proxy OS • X86 • Flex • Arm • GPU OCI Vulnerability Scanning CI/CD and Automation OCI DevOps OCI Bastion Resource Manager (Terraform) controller scheduler CCM

Slide 34

Slide 34 text

Copyright © 2021, Oracle and/or its affiliates 34 Deploying applications in OKE Deploying an application Externalized configuration

Slide 35

Slide 35 text

What does it do? 1. Waits for a (REST) http GET request 2. In response to the request the code makes a call to the MySQL database and queries a table 3. The results set from the query is processed / formatted and then returned to the caller How is it built? • Spring / Java based • Spring is the #1 framework for Java • Spring makes microservice development simple • Provides a comprehensive set of extensions and 3rd party libraries • Provides a build environment • Provides both an application context and an auto-configured, embedded web server • Use the Spring Initializr web site to jumpstart the project (https://start.spring.io/) • Add Spring Web • Maven project, Spring Boot 2.6.2, Java 11, Jar Packaging, use the Spring Web Package A Simple Web Application Copyright © 2021, Oracle and/or its affiliates 35

Slide 36

Slide 36 text

Oracle Cloud (OCI) VCN OKE Public Subnet Private Subnet Sample Architecture Copyright © 2021, Oracle and/or its affiliates 36 Kubernetes Load Balancer Developer Kubernetes API Server Bastion Users Node Java Node Java Node MySQL Database Service

Slide 37

Slide 37 text

Spring Initializr creates the above code – we don’t have to do anything to it We do need to create a Controller class • This will provide the logic that serves the GET request Spring Bootstrap Class – Created by Spring Initializr [Date] Copyright © 2021, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted 37 package com.mysql.web.basic; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class BasicApplication { public static void main(String[] args) { SpringApplication.run(BasicApplication.class, args); } }

Slide 38

Slide 38 text

package com.mysql.web.basic.controller; import org.springframework.web.bind.annotation.*; import java.sql.*; @RestController public class BasicController { private String DB_URL = "jdbc:mysql://10.0.30.243/db1?user=app&password=Welcome1!"; @GetMapping("/query") public String query() { StringBuilder str = new StringBuilder(""); try(Connection conn = DriverManager.getConnection(DB_URL); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM t1")) { while (rs.next()) { str.append(rs.getInt(1) + ":" + rs.getString(2) + " "); } } catch(SQLException e) { str = new StringBuilder(e.getMessage()); } return str.toString(); } } The Controller Class Copyright © 2021, Oracle and/or its affiliates 38 A GET request for http:///query will be mapped to this function Hard-coded database URL (for now). IP address is the MDS private IP address

Slide 39

Slide 39 text

Building Java Further dependencies: • Need to add the MySQL Connector/J JDBC driver to the Maven pom.xml file • Connector/J also has a dependency on Google Protobuf Dockerfile for docker build Java Build and Dockerfile Copyright © 2021, Oracle and/or its affiliates 39 mysql mysql-connector-java com.google.protobuf protobuf-java 3.11.1 In the root of the application use maven to build: opc@devserver% ./mvnw clean package Note: • The maven build (mvnw) produces a jar file in the target directory. • The name of the jar file is created from the values of the and tags in the pom.xml file. FROM openjdk:11 RUN useradd -M -r -U swd USER swd COPY --chown=swd:swd target/basicweb-1.jar /app/app.jar WORKDIR /app ENTRYPOINT ["java","-jar","app.jar"]

Slide 40

Slide 40 text

Process: 1. Build a local Docker image 2. Re-tag the image so that it can be pushed to the repository • The tag must reflect the path to your repository. 3. Push the newly tagged image Docker Build and Push to Repository Copyright © 2021, Oracle and/or its affiliates 40 opc@devserver% docker build -t webquerydb:v1 . opc@devserver% docker images REPOSITORY TAG IMAGE ID CREATED SIZE webquerydb v1 2b2036db3c6a 25 hours ago 682MB ... opc@devserver% docker tag webquerydb:v1 lhr.ocir.io/lrqh4m9w3t3b/swd/webquerydb:v1 opc@devserver% docker images REPOSITORY TAG IMAGE ID CREATED SIZE webquerydb v1 2b2036db3c6a 25 hours ago 682MB lhr.ocir.io/lrqh4m9w3t3b/swd/webquerydb v1 2b2036db3c6a 25 hours ago 682MB ... opc@devserver% docker push lhr.ocir.io/lrqh4m9w3t3b/swd/webquerydb:v1 opc@devserver% View the results in the OCI Console (main menu – Developer Services – Container Registry)

Slide 41

Slide 41 text

Deploying the application in Kubernetes Copyright © 2021, Oracle and/or its affiliates 41 apiVersion: apps/v1 kind: Deployment metadata: name: webquerydb-deployment spec: selector: matchLabels: app: webquerydb replicas: 3 template: metadata: labels: app: webquerydb spec: containers: - name: webquerydb image: lhr.ocir.io/lrqh4m9w3t3b/swd/webquerydb:v1 ports: - containerPort: 8080 imagePullSecrets: - name: ocirsecret --- apiVersion: v1 kind: Service metadata: name: webquerydb-service spec: type: LoadBalancer ports: - port: 80 protocol: TCP targetPort: 8080 selector: app: webquerydb Apply the file, query deployment/service opc@devserver% kubectl apply –f webquerydb1.yaml deployment.apps/webquerydb-deployment created service/webquerydb-service created opc@devserver% Create a file, webquerydb1.yaml, this shall: • describe the deployment • describe the service The external port (80) is mapped Onto the container’s port (8080) The image to be pulled Mapping to deployment Credentials to access container registry 3 replicas form the deployment

Slide 42

Slide 42 text

Using the Application Copyright © 2021, Oracle and/or its affiliates 42 opc@devserver% kubectl get all NAME READY STATUS RESTARTS AGE pod/webquerydb-deployment-849bbc756c-gwzv9 1/1 Running 0 11m pod/webquerydb-deployment-849bbc756c-kvc2k 1/1 Running 0 11m pod/webquerydb-deployment-849bbc756c-n6jwp 1/1 Running 0 11m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 443/TCP 25d service/webquerydb-service LoadBalancer 10.96.222.16 140.238.127.19 80:31789/TCP 22m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/webquerydb-deployment 3/3 3 3 22m NAME DESIRED CURRENT READY AGE replicaset.apps/webquerydb-deployment-849bbc756c 3 3 3 11m opc@devserver% To access the application use either a browser, http://140.238.127.19/query or curl The service’s external IP address Is used to access the app 3 pods forming replica set deployment opc@devserver% curl –X GET http://140.238.127.19/query 1:DOLPHIN 2:TIGER 3:PENGUIN 4:LION opc@devserver%

Slide 43

Slide 43 text

The application uses a hard-coded database URL – very poor practice • Security risk – database credentials can easily be read • Makes the application inflexible • code changes required for each new environment the application is deployed in • If the database changes then recode and redeploy • Error prone: a configuration management and operations nightmare Kubernetes offers two solutions • Configuration Maps – allow the injection of properties into a container – its elements are “in the clear” • Secrets – obfuscate sensitive data and can be passed into a container as environment variables or mounted on volumes in the container Spring provides “hooks” to allow us to take advantage of these solutions • The following example uses a Configuration Map for the server and database part of the URL and a Secret for the database credentials Externalizing Configuration and Credentials Copyright © 2021, Oracle and/or its affiliates 43

Slide 44

Slide 44 text

Create the configuration map using a yaml file Creating a Configuration Map Copyright © 2021, Oracle and/or its affiliates 44 apiVersion: v1 kind: ConfigMap metadata: name: webquerydb-config data: config.json: >- { "webquerydb.db.url": "jdbc:mysql://10.0.30.243/db1" } Only one property is shown, more can be added JSON format has been used for convenience – other formats can be used (see the docs) The key, “webquerydb.db.url”, is a user-defined name that must correspond with your code. Apply the configuration map as before opc@devserver% kubectl apply -f webquerydb-cfg.yaml configmap/webquerydb-config created opc@devserver%

Slide 45

Slide 45 text

A secret can be created from a yaml file or from the command line Creating a Secret Copyright © 2021, Oracle and/or its affiliates 45 opc@devserver% kubectl create secret generic db-secret \ --from-literal=username=root \ --from-literal=password=Welcome1! secret/db-secret created opc@devserver% • Kubernetes will Base64 encode secrets • On its own this is not very secure • OKE will further encrypt the Base64 encrypted secret so that it is securely stored (in Etcd) • Transparent to user/application aes-cbc encrypted Base 64 encoded Clear Data Clear Data Clear Data Persist Secret Retrieve Secret Pod Container CREATE SECRET USE SECRET Encoding provided by Kubernetes Decoding provided by Kubernetes Encryption and decoding provided by OKE Base 64 Encoded Clear Data Base 64 encoded Clear Data External key store Keys can be managed by EITHER Oracle OR the customer Etcd https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengencryptingdata.htm

Slide 46

Slide 46 text

The entry/bootstrap class (source below) needs to be instructed to enable the loading of properties • The annotation @EnableConfigurationProperties in the source code enables this • It instructs the compiler to insert code so that when the application is bootstrapped other objects whose source code has the @Configuration annotation will read their associated properties into memory. • The bootstrap class can then inject those configuration objects into other objects that are @AutoWired through their constructors Externalizing Database Configuration – Java Source Code changes 1/3 Copyright © 2021, Oracle and/or its affiliates 46 package com.mysql.web.basic; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; @SpringBootApplication @EnableConfigurationProperties public class BasicApplication { public static void main(String[] args) { SpringApplication.run(BasicApplication.class, args); } } Source code file: ~/basicwebext/src/main/java/com/mysql/web/basic/BasicApplication.java

Slide 47

Slide 47 text

We need to introduce a new source file, which when instantiated as an object will be populated with a property ‒ The class/object is implemented as a simple bean ‒ It only has one property it could have many. Each property must have a get and set method ‒ Note: @Configuration annotation, and the prefix which we will use later. Externalizing Database Configuration – Java Source Code changes 2/3 Copyright © 2021, Oracle and/or its affiliates 47 package com.mysql.web.basic.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @Configuration @ConfigurationProperties(prefix = "webquerydb.db") public class DbProperties { private String url; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } } Source code file: ~/basicwebext/src/main/java/com/mysql/web/basic/config/DbProperties.java So the property will be known as webquerydb.db.url

Slide 48

Slide 48 text

The controller code: the @Autowired annotation allows the injection of the DbProperties bean into the constructor Externalizing Database Configuration – Java Source Code changes 3/3 Copyright © 2021, Oracle and/or its affiliates 48 ... import org.springframework.beans.factory.annotation.Autowired; import com.mysql.web.basic.config.DbProperties; @RestController public class BasicController { private String dbUrl = null; @Autowired public BasicController(DbProperties properties) { String baseUrl = properties.getUrl(); String username = System.getenv("DB_USERNAME"); String password = System.getenv("DB_PASSWORD"); this.dbUrl = baseUrl + "?user=" + username + "&password=" + password; } @GetMapping("/query") public String query() { StringBuilder str = new StringBuilder(""); try(Connection conn = DriverManager.getConnection(this.dbUrl); Statement stmt = conn.createStatement(); ... Source code file: ~/basicwebext/src/main/java/com/mysql/web/basic/controller/BasicController.java

Slide 49

Slide 49 text

Copy the original webquerydb1.yaml file to webquerydb2.yaml then edit it by including and env: section to the deployments specification Externalizing Database Configuration – webquerydb2.yaml Copyright © 2021, Oracle and/or its affiliates 49 spec: containers: - name: webquerydb image: lhr.ocir.io/lrqh4m9w3t3b/swd/webquerydb:v2 ports: - containerPort: 8080 env: - name: SPRING_APPLICATION_JSON valueFrom: configMapKeyRef: name: webquerydb-config key: config.json - name: DB_USERNAME valueFrom: secretKeyRef: name: db-secret key: username - name: DB_PASSWORD valueFrom: secretKeyRef: name: db-secret key: password imagePullSecrets: - name: ocirsecret --- The name of the new Docker image which contains the code changes (see next slide) Advises Spring that config properties Are described in JSON The configuration map we created And the key to the json that holds the properties (just 1 prop in our case) The environment variable used by the Spring/Java code and the secret from where it can be obtained

Slide 50

Slide 50 text

Bringing it altogether Copyright © 2021, Oracle and/or its affiliates 50 opc@devserver% ./mvnw clean package opc@devserver% docker build –t webquerydb:v2 . opc@devserver% docker images REPOSITORY TAG IMAGE ID CREATED SIZE webquerydb v2 6063e7f9317f 2 hours ago 682MB webquerydb v1 2b2036db3c6a 25 hours ago 682MB lhr.ocir.io/lrqh4m9w3t3b/swd/webquerydb v1 2b2036db3c6a 25 hours ago 682MB ... opc@devserver% docker tag webquerydb:v2 lhr.ocir.io/lrqh4m9w3t3b/swd/webquerydb:v2 opc@devserver% docker images REPOSITORY TAG IMAGE ID CREATED SIZE webquerydb v2 6063e7f9317f 2 hours ago 682MB lhr.ocir.io/lrqh4m9w3t3b/swd/webquerydb v2 6063e7f9317f 2 hours ago 682MB webquerydb v1 2b2036db3c6a 25 hours ago 682MB lhr.ocir.io/lrqh4m9w3t3b/swd/webquerydb v1 2b2036db3c6a 25 hours ago 682MB ... opc@devserver% docker push lhr.ocir.io/lrqh4m9w3t3b/swd/webquerydb:v2 opc@devserver% kubectl apply –f webquerydb2.yaml deployment.apps/webquerydb-deployment configured service/webquerydb-service unchanged opc@devserver% Kubernetes will perform a rolling upgrade – use kubectl get all and see how it swaps over

Slide 51

Slide 51 text

[Date] Copyright © 2021, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted 51 https://marcgueury.github.io/learning-library/developer-library/mysql-java/workshops/freetier/index.html Lab: Develop and Deploy Java, Spring Boot on Kubernetes with MySQL In this workshop, you will: • Setup an MySQL DB Service, Kubernetes cluster. • Create a simple Java program to connect to it. Run it in Docker. • Create a Spring Boot program that connects to MySQL. Run it in Kubernetes.

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

It is possible to run the same workshop on ARM processor. It is basically the same step to one exception. - The cloud console is running on an x86 processor. This will then build Linux docker images. - Since docker cross compilation is not easy to set up. It is easier to create a ARM development compute instance to build your customer ARM containers. This works thanks to the support of ARM (AARCH64) by Java and . - Java 11 runs on ARM processor (AARCH64) - MySQL 8.0 too ARM [Date] Copyright © 2021, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted 53

Slide 54

Slide 54 text

Resources • Introducing the MySQL Database Service – https://blogs.oracle.com/mysql/introducing-the-mysql-database-service • Migrate from on premise MySQL to MySQL Database Service – https://blogs.oracle.com/mysql/migrate-from-on-premise-mysql-to-mysql-database-service • Documentations – https://docs.cloud.oracle.com/en-us/iaas/mysql-database/index.html – https://www.oracle.com/mysql/ • HeatWave – A MySQL cloud feature to speed up your queries – http://dasini.net/blog/2021/04/13/heatwave-a-mysql-cloud-feature-to-speed-up-your-queries/ • MySQL Operator for Kubernetes – https://github.com/mysql/mysql-operator • OCI Service Operator for Kubernetes – https://blogs.oracle.com/cloud-infrastructure/post/oci-service-operator-for-kubernetes • Create, Manage and Connect to MySQL Database Service using OCI Service Operator for Kubernetes – https://mysqlsg.blogspot.com/2021/09/create-manage-and-connect-to-mysql.html • MySQL InnoDB Cluster – https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-innodb-cluster.html MySQL Database Service / MySQL HeatWave / MySQL Operator for k8s Copyright © 2021, Oracle and/or its affiliates. All rights reserved. 54 54

Slide 55

Slide 55 text

Resources • Why MySQL? – https://www.mysql.com/why-mysql/ • MySQL Customers – https://www.mysql.com/customers/ • MySQL InnoDB Cluster – https://dev.mysql.com/doc/refman/8.0/en/mysql-innodb-cluster-introduction.html • MySQL Database Service – https://www.oracle.com/fr/mysql/ • MySQL HeatWave Database Service – https://www.oracle.com/mysql/ • MySQL 8.0 Docker Images l Community Edition – https://blogs.oracle.com/cloud-infrastructure/post/oci-service-operator-for-kubernetes l Commercial Edition available on – https://container-registry.oracle.com – https://edelivery.oracle.com – https://support.oracle.com • MySQL Operator for Kubernetes – https://github.com/mysql/mysql-operator Copyright © 2021, Oracle and/or its affiliates. All rights reserved. 55 55