Cloud native 与 Spring Cloud 最佳实践

Cloud native 与 Spring Cloud_入门_5_OpenShift

本地连接OpenShift上的DB
  • 1.命令行登录到 OpenShift, 找到 postgres 的 pod 名称,
  • 2.通过 oc port-forward pod_name 主机端口: Container端口 做端口转发.
oc login --token=sha256~xxxxxxx --server=https://c100-e.jp-tok.containers.cloud.ibm.com:30954
oc projects | grep jre
oc project xxxcloud-dev
oc get po
oc port-forward postgres-1-r24h2 15432:5432
  • 3.最后通过 DBeaver 或 IDEA 连接
host: localhost
port: 15432
user: postgres
password: xxxxxxxxx
database: xxxxcloud

使用IBM Log Analysis

官方文档: https://cloud.ibm.com/docs/log-analysis?topic=log-analysis-getting-started

在 spring boot 应用中,使用 lombok 结合 slf4j 日志框架来输出日志, 如下:

ProductController.java

@Slf4j
public class ProductController {
    @Autowired
    private ProductService productService;

    @GetMapping
    public PageInfo<Product> list(@Valid ProductSearchInput input, HttpServletRequest request) {
        if (log.isInfoEnabled()) {
            log.info("User from {} tries to retrieve products via {}.", request.getRemoteHost(), request.getHeader("User-Agent"));
        }

        PageInfo<Product> data = productService.search(input);

        log.info("{} records found.", data.getTotal());

        return data;
    }

product 示例应用 在 application.yaml 中设置了根日志级别为 info, 同时为了打印 SQL,将 mapper 包日志级别设置为 debug

---
spring.config.activate.on-profile: openshift
server.port: 8080
logging:
  level:
    root: info
    com.ibm.jrecloud.productapi.mapper: debug
  • 3. 可选方案

有两种主要的方案可以实现这一需求:

1.基于开源的 EFK (Elastic Search/Fluentd/Kibana) : 在 OpenShift 的 OperatorHub 中, 通过安装 OpenShift Elasticsearch Operator 和 Cluster Logging Operator, 使用 Kibana 控制台来监控应用程序日志, EFK 会占用集群较多的资源(CPU 和 Memory),使用相对复杂,可以做为一种备选方案。

2.基于 IBM Log Analysis: 这是 IBM Cloud 提供的基于 LogDNA 的日志解决方案,使用非常简单,Lite Plan 有 30 天的免费使用时间。

  • 4. 集成 IBM Log Analysis

打开 cluster 页面

向下滚动找到 Integrations > Logging, 点击 Connect

可以选择一个现有的 IBM Log Analysis 实例

如果没有则创建一个新的 Instance, (Lite Plan 可以免费使用 1 个月)

  • 5. 使用 IBM Log Analysis

Instance 创建成功后, 点击 Cluster 页面 Integrations Logging 下的 Launch 按钮打开 IBM Log Analysis 控制台.

在 Apps 下拉菜单中可以看到集群内所有 app,如下图所示,我们可以通过输入 app 的名字,比如product定位到我们的微服务:

此处我们勾选 product-compositeproduct这两个 app,点击 Apply 按钮

浏览器新开一个 Tab 页,输入:https://gateway-jrecloud-dev.roks-iip-48-2029222ed72d9643e3d07091333056f5-0000.jp-tok.containers.appdomain.cloud/product/api/v1/products

稍等片刻, 就可以在 IBM Log Analysis 控制台中看到 Product 微服务输出的日志:

我们可以将当前的视图保存起来, 如下图所示,我保存了一个名为 xxxcloud 的视图,用来查看与 xxxcloud 相关的 app 日志。

  • 6. 是否有必要使用日志文件?

Kubernetes 官方提供了 Logging 架构指导

The easiest and most adopted logging method for containerized applications is writing to standard output and standard error streams.

这样做有两个好处:

  1. 方便使用 kubectl logs 或 oc logs 命令查看日志
  2. 避免冗余的日志存储

如果需要持久化日志, 可以购买 IBM Log Analysis 服务,将日志归档到 IBM Cloud Object Storage, 也可以使用开源的 EFK 技术栈, 将日志通过 Fluentd 存储到 Elastic Search。


使用Secret

在 spring boot 应用中,通过 application.yaml 配置应用程序参数,其中包括 DB 用户名和密码。

spring.config.activate.on-profile: openshift
server.port: 8080
spring:
  datasource:
    password: mypassword
    url: jdbc:postgresql://postgres:5432/mydb
    username: myusername

我们希望在生产环境下, DB 的用户和密码对 Developer 不可见。

在 Cloud 环境下,可以使用 Kubernetes Secret 存储用户名和密码等敏感信息。

  • 1. 创建 Secret

在 OpenShift 中新建 PostgreSQL 数据库以后, 实际上 OpenShift 已经为我们创建了一个同名的 Secret.

  • 2. 查看自动创建的 Secret

在 OpenShift 中创建 Postgres DB 时,会同时创建一个名为 postgres 的 Secret, 里面包含 database-name, database-password, database-user 3 个键值对。

我们可以通过 oc 命令查看 Secret, 找到这 3 组键值对:

$ oc get secret

NAME            TYPE            DATA            AGE
postgres  Opaque        3                   14d

$ oc describe secret postgres

oc describe secret postgres
Name:         postgres
Namespace:    jrecloud-dev
Labels:  ...

Type:  Opaque

Data
====
database-name:      8 bytes
database-password:  8 bytes
database-user:      8 bytes
  • 3. 修改 app 配置文件

为避免将密码泄漏给 Developer,我们修改 spring boot 的 application.yaml,使用如下环境变量来代替实际的密码, 这些环境变量将会在下一节中定义。

spring:
  datasource:
    driver-class-name: org.postgresql.Driver
    password: ${POSTGRES_PASSWORD}
    url: jdbc:postgresql://postgres:5432/${POSTGRES_DB}
    username: ${POSTGRES_USER}

4. 通过 Web Console 传递 DB 参数

在 OpenShift web console 中新建 App 时,可以修改 Deployment 的配置, 向 Spring boot 应用程序(Container) 传递自定义的环境变量。

Topology > product 应用 图标上 > 右键 Edit product

点击 Deployment 展开更多配置, 如下:

然后点击 Add from ConfigMap or Secret:

重复 3 次创建如下 3 个环境变量:

点击 Save 按钮, 等待 product app 重新部署。

至此,我们已经将application.yaml中明文密码替换成了环境变量,并且在创建 app 时通过 Add from Secret 的方式给这些环境变量设定了正确的值。

  • 5. 通过 yaml 文件传递 DB 参数(补充)

不通过 OpenShift web console,我们可以直接修改 deployment.yaml 文件,向 spring boot 应用传递 DB 参数。

  1. 变量名和 spring boot application.yaml 中将要用到的名字一致
  2. 变量值则来自名为 postgres 的 Secret。

如下(deployment.yaml)

spec:
  template:
    spec:
      containers:
        - env:
            - name: POSTGRES_USER
              valueFrom:
                secretKeyRef:
                  name: postgres
                  key: database-user
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: postgres
                  key: database-password
            - name: POSTGRES_DB
              valueFrom:
                secretKeyRef:
                  name: postgres
                  key: database-name

最后, 执行 oc apply -f deployment.yaml 应用变更。

6. 通过命令行创建 Secret(补充)

通过 kubectl create secretoc create secret 命令创建 Secret,如下:

$ oc create secret generic postgres \
--from-literal=database-db=mydb \
--from-literal=database-user=myname \
--from-literal=database-password=mysecret

输入 oc create secret 查看与 创建 Secret 相关的帮助信息:

$ oc create secret
Create a secret using specified subcommand.

Usage:
  oc create secret [flags]

Available Commands:
  docker-registry Create a secret for use with a Docker registry
  generic         Create a secret from a local file, directory or literal value
  tls             Create a TLS secret

Use "oc <command> --help" for more information about a given command.
Use "oc options" for a list of global command-line options (applies to all commands).

输入 oc help secret 查看使用 Secret 相关的帮助信息:

$ oc help secret
Manage secrets in your project

 Secrets are used to store confidential information that should not be contained inside of an image. They are commonly
used to hold things like keys for authentication to other internal systems like container image registries.

Aliases:
secrets, secret

Usage:
  oc secrets [flags]

Available Commands:
  link        Link secrets to a service account
  unlink      Detach secrets from a service account

Use "oc <command> --help" for more information about a given command.
Use "oc options" for a list of global command-line options (applies to all commands).