点击左上角,关注:“锅外的大佬”

专注分享国外最新技术内容,帮助每一个技术人更优秀地成长

你可能优先选择 OpenShift而不是 Kubernetes的原因之一是运行一个新应用的简便性。使用 Kubernetes时,你需要提供已构建好的镜像和部署模板去运行它。 OpenShift引入了 Source-2-Image功能,用于从代码构建可运行的 Docker镜像。使用 S2I,不需要提供任何 KubernetesYAML模板或自己构建 Docker镜像, OpenShift将为你做这些。准备好示例的应用程序代码,测试它最好的方式是使用 Minishift

1. 准备代码

我已经在之前的一篇文章中描述了如何在 Kubernetes上运行 Java应用程序—— QuickGuidetoMicroserviceswithKubernetes,SpringBoot2.0andDocker。我们将使用那篇文章的代码,同时也方便你比较两份教程的异同。 Github地址: sample-spring-microservices-new,分支 openshift
示例的系统架构图:
每个微服务都是 SpringBoot应用,使用 Maven构建工具 spring-boot-maven-plugin,用于构建应用的 jar包,这是 source-2-image需要的:
  1. <build>
  2. <plugins>
  3. <plugin>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-maven-plugin</artifactId>
  6. </plugin>
  7. </plugins>
  8. </build>
每个应用程序都包含以下依赖:
  1. <dependencies>
  2. <!-- web 应用 -->
  3. <dependency>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-starter-web</artifactId>
  6. </dependency>
  7. <!-- actuator -->
  8. <dependency>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-actuator</artifactId>
  11. </dependency>
  12. <!-- API 文档 -->
  13. <dependency>
  14. <groupId>io.springfox</groupId>
  15. <artifactId>springfox-swagger2</artifactId>
  16. <version>2.9.2>/version<
  17. </dependency>
  18. <dependency>
  19. <groupId>io.springfox</groupId>
  20. <artifactId>springfox-swagger-ui</artifactId>
  21. <version>2.9.2</version>
  22. </dependency>
  23. <!-- 集成 MongoDB -->
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-data-mongodb</artifactId>
  27. </dependency>
  28. </dependencies>
每个 SpringBoot应用程序都暴露 REST API,以便进行简单的 CRUD操作。 Controller层代码如下:
  1. @RestController
  2. @RequestMapping(“/employee”)
  3. publicclassEmployeeController{
  4. privatestaticfinalLogger LOGGER =LoggerFactory.getLogger(EmployeeController.class);
  5. @Autowired
  6. EmployeeRepository repository;
  7. @PostMapping("/")
  8. publicEmployee add(@RequestBodyEmployee employee){
  9. LOGGER.info("Employee add: {}", employee);
  10. return repository.save(employee);
  11. }
  12. @GetMapping("/{id}")
  13. publicEmployee findById(@PathVariable("id")String id){
  14. LOGGER.info("Employee find: id={}", id);
  15. return repository.findById(id).get();
  16. }
  17. @GetMapping("/")
  18. publicIterable<Employee> findAll(){
  19. LOGGER.info("Employee find");
  20. return repository.findAll();
  21. }
  22. @GetMapping("/department/{departmentId}")
  23. publicList<Employee> findByDepartment(@PathVariable("departmentId")Long departmentId){
  24. LOGGER.info("Employee find: departmentId={}", departmentId);
  25. return repository.findByDepartmentId(departmentId);
  26. }
  27. @GetMapping("/organization/{organizationId}")
  28. publicList<Employee> findByOrganization(@PathVariable("organizationId")Long organizationId){
  29. LOGGER.info("Employee find: organizationId={}", organizationId);
  30. return repository.findByOrganizationId(organizationId);
  31. }
  32. }
SpringBootMongoDB配置如下:
  1. spring:
  2. application:
  3. name: employee
  4. data:
  5. mongodb:
  6. uri: mongodb://${MONGO_DATABASE_USER}:${MONGO_DATABASE_PASSWORD}@mongodb/${MONGO_DATABASE_NAME}
服务间通信使用 OpenFeign定义的 RESTClient,包含微服务 department和 organization,示例代码:
  1. @FeignClient(name ="employee", url ="${microservices.employee.url}")
  2. publicinterfaceEmployeeClient{
  3. @GetMapping("/employee/organization/{organizationId}")
  4. List<Employee> findByOrganization(@PathVariable("organizationId")String organizationId);
  5. }
FeignClient访问的目标服务的地址在 application.yml中设置,通过 OpenShift/KubernetesService实现通信,每个服务的名称也通过环境变量注入。
  1. spring:
  2. application:
  3. name: organization
  4. data:
  5. mongodb:
  6. uri: mongodb://${MONGO_DATABASE_USER}:${MONGO_DATABASE_PASSWORD}@mongodb/${MONGO_DATABASE_NAME}
  7. microservices:
  8. employee:
  9. url: http://${EMPLOYEE_SERVICE}:8080
  10. department:
  11. url: http://${DEPARTMENT_SERVICE}:8080

2. 运行Minishift

本地运行,需要先下载 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 插件开始:
  1. minishift addons apply admin-user
现在,我们可以将角色 cluster-admin授予用户 admin
  1. oc login -u system:admin
  2. oc adm policy add-cluster-role-to-user cluster-admin admin
  3. oc login -u admin -p admin
至此,通过 admin/admin访问 web控制台,你应该可以看到 openshift项目。这还不够,默认情况下,用于构建可执行的 Javaapps的 openjdk18-openshift不可用,我们可以通过 ocimport-image命令应用插件 xpass
  1. minishift addons apply xpaas
此时,你可以访问 web控制台了(我这边的地址是 https://192.168.99.199:8443),选择 openshift>Builds>Images,可以看到列表里的image stream redhat-openjdk18-openshift

3.使用 S2I 部署 Java 程序

首先,部署一个 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
  1. 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 来实现。
  1. oc set env bc/employee --from="secret/mongodb"--prefix=MONGO_
BuildConfig 是运行 ocnew-app之后创建的 openshift 对象,同时也创建 DeploymentConfig、 Service、 ImageStream 以及最新的 docker 应用镜像。构建流程:下载 Git 代码 -> Maven 构建 -> 构建 Docker 镜像 -> 保存镜像到仓库。
接着,部署另外一个应用 department :
  1. 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对象:
  1. oc set env bc/department --from="secret/mongodb"--prefix=MONGO_
手动执行构建 oc start-build department
部署最后一个微服务,命令如下:
  1. 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
  2. oc set env bc/organization --from="secret/mongodb"--prefix=MONGO_

4. 深入了解创建的 OpenShift 对象

通过 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 暴露服务到外部。

5. 测试上述系统

执行测试前,需要先暴露服务,命令如下:
  1. oc expose svc employee
  2. oc expose svc department
  3. 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 对象。
  1. @Value("${VERSION}")
  2. String version;
  3. publicstaticvoid main(String[] args){
  4. SpringApplication.run(DepartmentApplication.class, args);
  5. }
  6. @Bean
  7. publicDocket swaggerApi(){
  8. returnnewDocket(DocumentationType.SWAGGER_2)
  9. .select()
  10. .apis(RequestHandlerSelectors.basePackage("pl.piomin.services.department.controller"))
  11. .paths(PathSelectors.any())
  12. .build()
  13. .apiInfo(newApiInfoBuilder().version(version).title("Department API").description("Documentation Department API v"+ version).build());
  14. }

6.总结

本文介绍了在OpenShift上部署应用程序的简便性。你不需要创建任何YAML描述符文件或自己构建Docker镜像来运行您的应用程序。因为它是直接从你的源代码构建的。
原文链接:https://piotrminkowski.wordpress.com/2019/01/08/running-java-microservices-on-openshift-using-source-2-image/
作者:Piotr Mińkowski
译者:Anoyi
继续阅读
阅读原文