Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Deploy and Run Java Applications on OKE with th...

Deploy and Run Java Applications on OKE with the MySQL Database Service

Learn how to optimally deploy a simple Java application with MySQL backend in Oracle Cloud Infrastructure.
Discover the MySQL Database Service, explore it's capabilities and import a sample database and data.
Then a Java application will be containerized and deployed in Oracle Kubernetes Engine (OKE).
Explore how easy it is to connect cloud native applications with MySQL Database Service and leverage the capabilities of OKE to scale and administer these applications.

Olivier DASINI

March 02, 2022
Tweet

More Decks by Olivier DASINI

Other Decks in Programming

Transcript

  1. Deploy and Run Java Applications on OKE with the MySQL

    Database Service Olivier DASINI MySQL, EMEA Marc GUEURY AppDev, EMEA
  2. MySQL Copyright © 2021, Oracle and/or its affiliates. All rights

    reserved. The world’s most popular open source database 2 2
  3. 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
  4. MySQL for Cloud Native Copyright © 2021, Oracle and/or its

    affiliates. All rights reserved. Why it is a Natural Choice? 4 4
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. MySQL Database Service Copyright © 2021, Oracle and/or its affiliates.

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

    affiliates. All rights reserved. 11 100% Developed, Managed and Supported by the MySQL Team
  12. 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
  13. MySQL HeatWave MySQL in-Memory Query Accelerator Copyright © 2021, Oracle

    and/or its affiliates. All rights reserved. 13 13
  14. 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
  15. *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.
  16. 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
  17. 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
  18. • 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
  19. Copyright © 2021, Oracle and/or its affiliates 19 Docker Refresher

    Basic Docker commands to build and run containers
  20. 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
  21. 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'); ...
  22. 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
  23. 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%
  24. • 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
  25. 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
  26. 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
  27. 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
  28. 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
  29. 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
  30. 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
  31. 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
  32. 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.
  33. 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
  34. Copyright © 2021, Oracle and/or its affiliates 34 Deploying applications

    in OKE Deploying an application Externalized configuration
  35. 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
  36. 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
  37. 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); } }
  38. 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://<server>/query will be mapped to this function Hard-coded database URL (for now). IP address is the MDS private IP address
  39. 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 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.11.1</version> </dependency> 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 <artifactId> and <version> 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"]
  40. 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)
  41. 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
  42. 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 <none> 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%
  43. 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
  44. 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%
  45. 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
  46. 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
  47. 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
  48. 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
  49. 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
  50. 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
  51. [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.
  52. 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
  53. 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
  54. 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