点击左上角,关注:“锅外的大佬”
专注分享国外最新技术内容,帮助每一个技术人更优秀地成长
你可能优先选择 OpenShift
而不是 Kubernetes
的原因之一是运行一个新应用的简便性。使用 Kubernetes
时,你需要提供已构建好的镜像和部署模板去运行它。 OpenShift
引入了 Source-2-Image
功能,用于从代码构建可运行的 Docker
镜像。使用 S2I
,不需要提供任何 KubernetesYAML
模板或自己构建 Docker
镜像, OpenShift
将为你做这些。准备好示例的应用程序代码,测试它最好的方式是使用 Minishift
。
我已经在之前的一篇文章中描述了如何在 Kubernetes
上运行 Java
应用程序—— QuickGuidetoMicroserviceswithKubernetes,SpringBoot2.0andDocker
。我们将使用那篇文章的代码,同时也方便你比较两份教程的异同。 Github
地址: sample-spring-microservices-new
,分支 openshift
。
示例的系统架构图:
每个微服务都是 SpringBoot
应用,使用 Maven
构建工具 spring-boot-maven-plugin
,用于构建应用的 jar
包,这是 source-2-image
需要的:
org.springframework.boot
spring-boot-maven-plugin
每个应用程序都包含以下依赖:
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
io.springfox
springfox-swagger2
2.9.2>/version<
io.springfox
springfox-swagger-ui
2.9.2
org.springframework.boot
spring-boot-starter-data-mongodb
每个 SpringBoot
应用程序都暴露 REST API
,以便进行简单的 CRUD
操作。 Controller
层代码如下:
@RestController
@RequestMapping(“/employee”)
public class EmployeeController {
private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeController.class);
@Autowired
EmployeeRepository repository;
@PostMapping("/")
public Employee add(@RequestBody Employee employee) {
LOGGER.info("Employee add: {}", employee);
return repository.save(employee);
}
@GetMapping("/{id}")
public Employee findById(@PathVariable("id") String id) {
LOGGER.info("Employee find: id={}", id);
return repository.findById(id).get();
}
@GetMapping("/")
public Iterable findAll() {
LOGGER.info("Employee find");
return repository.findAll();
}
@GetMapping("/department/{departmentId}")
public List findByDepartment(@PathVariable("departmentId") Long departmentId) {
LOGGER.info("Employee find: departmentId={}", departmentId);
return repository.findByDepartmentId(departmentId);
}
@GetMapping("/organization/{organizationId}")
public List findByOrganization(@PathVariable("organizationId") Long organizationId) {
LOGGER.info("Employee find: organizationId={}", organizationId);
return repository.findByOrganizationId(organizationId);
}
}
SpringBootMongoDB
配置如下:
spring:
application:
name: employee
data:
mongodb:
uri: mongodb://${MONGO_DATABASE_USER}:${MONGO_DATABASE_PASSWORD}@mongodb/${MONGO_DATABASE_NAME}
服务间通信使用 OpenFeign
定义的 RESTClient
,包含微服务 department
和 organization
,示例代码:
@FeignClient(name = "employee", url = "${microservices.employee.url}")
public interface EmployeeClient {
@GetMapping("/employee/organization/{organizationId}")
List findByOrganization(@PathVariable("organizationId") String organizationId);
}
FeignClient
访问的目标服务的地址在 application.yml
中设置,通过 OpenShift/KubernetesService
实现通信,每个服务的名称也通过环境变量注入。
spring:
application:
name: organization
data:
mongodb:
uri: mongodb://${MONGO_DATABASE_USER}:${MONGO_DATABASE_PASSWORD}@mongodb/${MONGO_DATABASE_NAME}
microservices:
employee:
url: http://${EMPLOYEE_SERVICE}:8080
department:
url: http://${DEPARTMENT_SERVICE}:8080
本地运行,需要先下载 Minishft
,拷贝 minishift.exe(Windows)
到 PATH
路径,然后使用 minishift start
运行。更多详细内容参考 Quickguide to deployingJavaapps onOpenShift
。当前使用的 Minishift
版本是 1.29.0
。
启动 Minishift
之后,我们需要运行其他的 oc
命令启用 source-2-image
。首先,给用户 admin
添加权限,使其能够访问 openshift
, 在这个项目中, OpenShift
存储了所有使用的内置模板和 image stream
,例如 S2I
构建器。让我们从启用 admin-user
插件开始:
minishift addons apply admin-user
现在,我们可以将角色 cluster-admin
授予用户 admin
:
oc login -u system:admin
oc adm policy add-cluster-role-to-user cluster-admin admin
oc login -u admin -p admin
至此,通过 admin/admin
访问 web
控制台,你应该可以看到 openshift
项目。这还不够,默认情况下,用于构建可执行的 Javaapps
的 openjdk18-openshift
不可用,我们可以通过 ocimport-image
命令应用插件 xpass
:
minishift addons apply xpaas
此时,你可以访问 web
控制台了(我这边的地址是 https://192.168.99.199:8443
),选择 openshift>Builds>Images
,可以看到列表里的image stream redhat-openjdk18-openshift
首先,部署一个 MongoDB
实例,因为 Mongo
模板在构建服务的目录里面有,所以用 OpenShift
非常容易。我们可以提供自己的配置设置或保留默认值。
OpenShift
提供的 S2I
构建器镜像可以通过 Image Stream redhat-openjdk18-openshift 使用,此镜像适用于通过主类运行的基于 Maven
的Java 独立项目,例如 SpringBoot
应用程序。如果在创建新应用时不提供任何构建器,则 OpenShift
会自动检测应用的类型,Java 编写的源代码将部署在 WildFly
服务器上。当前版本的 Java S2I 构建器镜像支持 OpenJDK1.8
、 Jolokia1.3.5
和 Maven3.3.9-2.8
。
从微服务 employee
开始,在 OpenShift
上部署第一个 Java
应用。在正常情况下,每个微服务都将位于独立的 Git
仓库中,在我们的示例中,所有项目都放在一个仓库中,因此我们通过设置参数 --context-dir
来提供当前应用的位置,我们还将默认分支修改为 openshift
。
oc new-app redhat-openjdk18-openshift:1.3~https://github.com/piomin/sample-spring-microservices-new.git#openshift --name=employee --context-dir=employee-service
由于所有的微服务都连接到 MongoDB
,因此我们还必须将连接设置和 secert
注入应用 Pod,可以通过向 BuildConfig
对象注入 mongodb secret
来实现。
oc set env bc/employee --from="secret/mongodb" --prefix=MONGO_
BuildConfig
是运行 ocnew-app
之后创建的 openshift
对象,同时也创建 DeploymentConfig
、 Service
、 ImageStream
以及最新的 docker
应用镜像。构建流程:下载 Git 代码 -> Maven
构建 -> 构建 Docker
镜像 -> 保存镜像到仓库。
接着,部署另外一个应用 department
:
oc new-app redhat-openjdk18-openshift:1.3~https://github.com/piomin/sample-spring-microservices-new.git#openshift --name=department --context-dir=department-service -e EMPLOYEE_SERVICE=employee
和上面一样,注入 mongodb secret
到 BuildConfig
对象:
oc set env bc/department --from="secret/mongodb" --prefix=MONGO_
手动执行构建 oc start-build department
部署最后一个微服务,命令如下:
oc new-app redhat-openjdk18-openshift:1.3~https://github.com/piomin/sample-spring-microservices-new.git#openshift --name=organization --context-dir=organization-service -e EMPLOYEE_SERVICE=employee -e DEPARTMENT_SERVICE=department
oc set env bc/organization --from="secret/mongodb" --prefix=MONGO_
通过 web 控制台 Builds -> Builds,可以看到如下的三个 BuildConfig
对象,每个都是简单的应用。也可以通过命令 ocgetbc
查看。
历史构建记录如下:
查看 BuildConfig
的 YAML
配置
每个应用的构建都会推送到镜像仓库, Minishift
内嵌的仓库地址:172.30.1.1:5000,可以通过 web 控制台 Builds -> Images 查看。
每个应用通过 service
自动暴露端口 8080(HTTP)/8443(HTTPS)/8778(Jolokia),你也可以通过 Minishift
使用命令 oc expose
创建 OpenShiftRoute
暴露服务到外部。
执行测试前,需要先暴露服务,命令如下:
oc expose svc employee
oc expose svc department
oc expose svc organization
然后通过地址 http://${APP_NAME}-${PROJ_NAME}.${MINISHIFT_IP}.nip.io
访问服务,如下图所示:
每个微服务都生成了 Swagger2API
文档,页面 swagger-ui.html
值得注意的是,每个应用程序都使用三种方法将环境变量注入到 pod 中:
1、版本号存储在代码仓库中的 .s2i/environment
中, S2I
构建器读取该文件中定义的所有属性,并将它们设置为构建器 Pod
的环境变量,然后是应用 Pod
。我们的属性名是 VERSION
,它是使用 Spring @Value
注入的,并设置为 SwaggerAPI
(代码在下面可见)。
2、在为服务 department
和 organization
执行命令 ocnew-app
时,我已经将依赖服务的名称设置为 ENV
变量。
3、我还使用 ocsetenv
命令将 MongoDBsecret
注入每个 BuildConfig
对象。
@Value("${VERSION}")
String version;
public static void main(String[] args) {
SpringApplication.run(DepartmentApplication.class, args);
}
@Bean
public Docket swaggerApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("pl.piomin.services.department.controller"))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder().version(version).title("Department API").description("Documentation Department API v" + version).build());
}
本文介绍了在OpenShift上部署应用程序的简便性。你不需要创建任何YAML描述符文件或自己构建Docker镜像来运行您的应用程序。因为它是直接从你的源代码构建的。
原文链接:https://piotrminkowski.wordpress.com/2019/01/08/running-java-microservices-on-openshift-using-source-2-image/
作者:Piotr Mińkowski
译者:Anoyi