TAP 系列文章5 | 云原生构建服务

本文介绍了Tanzu构建服务如何解决传统应用容器化过程中的问题,如编译环境配置、Dockerfile撰写和维护等。通过使用Tanzu构建服务,开发人员无需编写Dockerfile,只需简单命令即可将源代码打包成容器镜像。TBS基于Cloud Native Buildpacks,提供了自动化、安全和易维护的构建方案,与CI/CD工具集成,简化了企业级应用的构建流程。
摘要由CSDN通过智能技术生成

背景

通常的应用开发过程,是由开发人员使用某种计算机语言,比如Java,开发特定项目然后提交到代码仓库。紧接着,源代码会被编译成二进制代码,被放置于特定的环境中运行,比如Java运行时或者Web Server等。随着容器以及容器编排技术的发展和成熟,越来越多的应用将从传统的虚拟机部署方式改为容器部署模式。这就增加了一个关键的步骤:把应用打包成容器镜像,也称为应用容器化。

那么这个步骤还是由开发人员完成吗?开发人员的内心os:我难道不应该专注于写业务逻辑吗?这个打包也要由我来完成?好吧,但是打包写Dockerfile我没有经验啊!要怎么避开里面的陷阱呢?以后源代码或者基础镜像更新了,还要由我来维护吗?

带着这些疑问,我们来仔细看看应用容器化的具体过程是怎么样的吧。


从源代码到容器镜像

当开发人员完成了一个应用项目并提交代码库之后,为了让代码能在容器环境中运行,需要把源代码转换成符合OCI标准的容器镜像,这个过程称为构建(build)。构建过程通常分为两个子步骤,第一步是将源代码编译成二进制文件,第二步是加上基础操作系统和相关依赖(比如Java运行时)合并成标准容器镜像。

第一步的编译取决于应用项目所采用的语言和框架,第二步常规的方法则是以撰写Dockerfile以及使用docker build来完成的。以使用Spring框架开发的项目为例,我们可以看到常规的构建过程是这样的:

  • 首先,将源代码下载到本地,使用Maven命令对Spring项目进行Java编译:
% mvn -Dmaven.test.skip=true package
       
[INFO] Scanning for projects...
[INFO] 
[INFO] --------------------< io.buildpacks.example:sample >--------------------
[INFO] Building sample 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
。。。
[INFO] 
[INFO] --- maven-jar-plugin:3.1.2:jar (default-jar) @ sample ---
[INFO] Building jar: /Users/mingjiex/git/samples/apps/java-maven/target/sample-0.0.1-SNAPSHOT.jar
[INFO] 
[INFO] --- spring-boot-maven-plugin:2.1.18.RELEASE:repackage (repackage) @ sample ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.671 s
[INFO] ------------------------------------------------------------------------

在编译过程中会自动下载大量的Java依赖包,如果没有编译错误,那么最终会在target目录下生成一个二进制可执行的sample-0.0.1-SNAPSHOT.jar包。

  • 然后,撰写Dockerfile文件,声明构建的步骤和参数,样本文件如下:

FROM openjdk:8-jre
              
ADD ./target/sample-0.0.1-SNAPSHOT.jar /
               
ENTRYPOINT ["java"]               
CMD ["-jar", "/sample-0.0.1-SNAPSHOT.jar"]
               
EXPOSE 8080

其中FROM语句是引用的基础镜像名称,该镜像包含了底层的操作系统和依赖的Java运行环境,将被从公共或者私有镜像库中下拉。

ADD语句说明在需要加入的文件,ENTRYPOINT和CMD语句构成了启动命令,EXPOSE语句说明了暴漏的端口。

这是一个最简单的Dockerfile样例,实际的要复杂得多。由于容器镜像采用的是Overlay型的文件系统,Dockerfile中的每一个步骤将在最终镜像中产生一个层级(layer),所以Dockerfile撰写的好坏决定着应用镜像的运行效率。

  • 最后,执行docker build命令,打包完成后得到最终的应用镜像。

% docker build .        
      
[+] Building 4.5s (7/7) FINISHED                                                                                        
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 37B                                                                                0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load metadata for docker.io/library/openjdk:8-jre                                                   4.4s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 82B                                                                                   0.0s
 => [1/2] FROM docker.io/library/openjdk:8-jre@sha256:59c47099aed504b2987fb5eea4376f96cf0f53d2c9081c30fd6a554c7a6  0.0s
 => CACHED [2/2] ADD ./target/sample-0.0.1-SNAPSHOT.jar /                                                          0.0s
 => exporting to image                                                                                             0.0s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:8335af64e29a7e69a047e424863ef3706349d5c5d325ff4f84447fa21a9fc496

问题

我们发现,在上述常规使用docker build的构建过程会存在一些问题,包括但不限于:

1.需要为每种不同类别的项目准备合适的编译环境。

2.不同的人员会撰写不同风格的Dockerfile,一致性难以保证。

3.撰写Dockerfile过于自由,可能会引入安全漏洞,包括不安全的基础镜像。

4.如果要对安全漏洞进行修复,则需要更新Dockerfile为引用最新的基础镜像。

5.需要为每个项目单独写一个Dockerfile,在微服务架构中可能会有以百计的项目数,维护困难。

6.Dockerfile如果写的不够优化,那么最终产生的层级会很多,容器的运行效率也会打折扣。
。。。

所以我们需要一种更为便捷,安全而且易维护的构建方法来避免以上的各种问题。


Tanzu构建服务

基于云原生构建开源项目Cloud Native Buildpacks(CNB),Tanzu构建服务(以下简称TBS)将为您解决以上提到的各种问题。开发人员将不再需要撰写Dockerfile,而只需要使用一个简单的命令,就能把各种类型的源代码项目打包成最终的应用镜像。

而Tanzu构建服务,已经集成在Tanzu Application Platform的平台里,作为一个关键的企业级特性提供给用户来实现构建服务。

我们来看一个例子,还是使用上面的样例Spring项目。在下面使用的命令行里,kp是Tanzu构建服务的命令行工具,–git参数指明源代码仓库地址,–git-revision 参数指明git分支名称,–sub-path参数指明源代码子目录,–tag参数指明最终应用镜像的推送仓库地址:


% kp image create my-image --tag registry.tanzu.online:5000/tbs/test-app --git http://124.222.5.35:8888/mingjiex/samples.git --git-revision master --sub-path ./apps/java-maven --wait
      
Creating Image Resource...
Image Resource "my-image" created
===> PREPARE
Build reason(s): CONFIG
CONFIG:
resources: {}
- source: {}
+ source:
+   git:
+     revision: 1bf16cdcce9454d4922f20000efa1650c195b53b
+     url: http://124.222.5.35:8888/mingjiex/samples.git
+   subPath: ./apps/java-maven
Loading secret for "registry.tanzu.online:5000" from secret "my-registry-creds" at location "/var/build-secrets/my-registry-creds"
Cloning "http://124.222.5.35:8888/mingjiex/samples.git" @ "1bf16cdcce9454d4922f20000efa1650c195b53b"...
Successfully cloned "http://124.222.5.35:8888/mingjiex/samples.git" @ "1bf16cdcce9454d4922f20000efa1650c195b53b" in path "/workspace"
===> ANALYZE
Previous image with name "registry.tanzu.online:5000/tbs/test-app" not found
===> DETECT
7 of 34 buildpacks participating
paketo-buildpacks/ca-certificates   2.4.2
paketo-buildpacks/bellsoft-liberica 8.9.0
paketo-buildpacks/maven             5.7.0
paketo-buildpacks/executable-jar    5.3.1
paketo-buildpacks/apache-tomcat     6.4.0
paketo-buildpacks/dist-zip          4.3.0
paketo-buildpacks/spring-boot       4.7.0
。。。
。。。
。。。
Paketo Executable JAR Buildpack 5.3.1
  https://github.com/paketo-buildpacks/executable-jar
  Class Path: Contributing to layer
    Writing env/CLASSPATH.delim
    Writing env/CLASSPATH.prepend
  Process types:
    executable-jar: java org.springframework.boot.loader.JarLauncher (direct)
    task:           java org.springframework.boot.loader.JarLauncher (direct)
    web:            java org.springframework.boot.loader.JarLauncher (direct)
          
Paketo Spring Boot Buildpack 4.7.0
  https://github.com/paketo-buildpacks/spring-boot
  Launch Helper: Contributing to layer
    Creating /layers/paketo-buildpacks_spring-boot/helper/exec.d/spring-cloud-bindings
  Spring Cloud Bindings 1.8.0: Contributing to layer
    Reusing cached download from buildpack
    Copying to /layers/paketo-buildpacks_spring-boot/spring-cloud-bindings
  Web Application Type: Contributing to layer
    Servlet web application detected
    Writing env.launch/BPL_JVM_THREAD_COUNT.default

TBS会下载源代码,自动识别代码项目的类型而采用合适的编译打包工具,并编译打包成容器镜像,最终推送入指定的镜像仓库。

那么TBS究竟是如何完成这系列构建步骤的呢?我们来看一下TBS的组件。
TBS依赖于几类关键资源:

  • ClusterStore:是云原生构建包的仓库,基于开源社区项目(Cloud Native Buildpacks,CNB)。
  • ClusterStack:是用于构建和运行的操作系统镜像,需要不断更新以修复安全漏洞。
  • ClusterBuilder:是ClusterStore和ClusterStack的组合所形成的构建器。
    TBS发布版自带了这些资源,以供客户开箱即用。如果客户有特殊需求,则可以根据要求定制。使用TBS的命令行工具kp查看可用资源,这些资源需要在准备就绪(Ready=True)的状态:
% kp clusterstore list  
NAME       READY
default    True

% kp clusterstack list  
NAME       READY    ID
base       True     io.buildpacks.stacks.bionic
default    True     io.buildpacks.stacks.bionic
full       True     io.buildpacks.stacks.bionic
tiny       True     io.paketo.stacks.tiny

% kp clusterbuilder list
NAME       READY    STACK                          IMAGE
base       true     io.buildpacks.stacks.bionic    registry.tanzu.online:5000/tbs/build-service:clusterbuilder-base@sha256:f7600c5e5864fa14bc1a6ba31fdd932cb2cec128d3d42cf0537f7d29e63c09d0
default    true     io.buildpacks.stacks.bionic    registry.tanzu.online:5000/tbs/build-service:clusterbuilder-default@sha256:f7600c5e5864fa14bc1a6ba31fdd932cb2cec128d3d42cf0537f7d29e63c09d0
full       true     io.buildpacks.stacks.bionic    registry.tanzu.online:5000/tbs/build-service:clusterbuilder-full@sha256:bb9b938e5534fe06279bfdeafb351d1c0466af50c2082495eeed258a7cb580f7
tiny       true     io.paketo.stacks.tiny          registry.tanzu.online:5000/tbs/build-service:clusterbuilder-tiny@sha256:0c8c05b28fb57e69c0fe7c821d22634dc9fe42cd5368a02dc7f619560e44a69a

有了可用的构建器,就可以如同一开始使用的样例项目,使用kp image create命令创建Image Resource,对源代码执行构建。

% kp image create my-image --tag registry.tanzu.online:5000/tbs/test-app --git
http://124.222.5.35:8888/mingjiex/samples.git --git-revision master --sub-path ./apps/java-maven --wait

查看Image Source列表,后续可以执行更改、删除操作:

mingjiex@mingjiex-a01 java-maven % kp image list
NAME        READY    LATEST REASON    LATEST IMAGE                            NAMESPACE
my-image    True     CONFIG           registry.tanzu.online:5000/tbs/test-
app@sha256:5fabc1e1f968f5ad09566ce1cf74a28a67d65815b7e6518604160daa8abcd86a    default

当Image Resource被创建后,如果源代码有新的提交,或者基础镜像发生更新,或者Image Resource参数发生变化的时候(各种REASON),新的构建任务将会被触发。每次构建都会产生一个build号,成功的构建会产生新的应用镜像并推送到应用镜像仓库。我们可以使用kp build命令查看每次build生成的镜像:

% kp build list
BUILD    STATUS     BUILT IMAGE                                                REASON    IMAGE RESOURCE
1        SUCCESS    registry.tanzu.online:5000/tbs/test-app@sha256:0b660ee0af25b0bba80a76b31d82537eafd649c15bcb0ff08b0c06f8f6d40317    CONFIG    my-image
2        SUCCESS    registry.tanzu.online:5000/tbs/test-app@sha256:72a19a7c37158a8fc56da7c4a36cc78bd33336a91d0b220cef17a7282d167eef    COMMIT    my-image
3        SUCCESS    registry.tanzu.online:5000/tbs/test-app@sha256:5fabc1e1f968f5ad09566ce1cf74a28a67d65815b7e6518604160daa8abcd86a    CONFIG    my-image

为了达到优化目的,还可以对Image Resource施加特定参数来干预构建过程,比如指定构建器,改变缺省的Java版本,创建cache以加速后续的构建,等等。这些需要您在实践中去体会了。


Tanzu构建服务和CI/CD集成

Tanzu构建服务和持续集成/持续交付(CI/CD)工具非常容易集成。通过CI/CD工具设置Image Resource,然后触发TBS对提交入代码库的源代码项目执行构建服务,最后推入容器镜像仓库。通常的集成方式如下图:

在这里插入图片描述

TBS包含在Tanzu Application Platform(简称TAP)的发行版内,而且已经作为预制件集成进了TAP的软件供应链Choreograph里面,成为了开箱即用的构建工具。如下图所示,Tanzu构建服务是TAP软件供应链的第一步,而和后续的安全扫描,部署,运行等等连接在一起组成完整的应用安全运维过程:

在这里插入图片描述


Tanzu构建服务之价值总结

对于试图在商业环境中构建和部署容器的开发人员和运维人员来说,构建容器镜像并通过所需的依赖关系(例如运行库/二进制文件和基本操作系统镜像)对其进行修补是一件困难的事情。在大型企业环境中,挑战尤为严峻,在这种环境中,许多开发人员会构建各种应用,而这些应用必须严格遵守安全性和审核政策。

由于 IT 运维人员需要全面重新设计他们的系统以对容器的维护进行管理,因此,从基于虚拟机或基于 PaaS 的部署过程迁移到 Kubernetes 往往十分复杂。

Tanzu构建服务在Kubernetes的固有对象之上添加了抽象层,以提高企业开发人员和 IT 运维人员的工作效率。客户通过持续集成/持续交付 (CI/CD) 系统使构建过程自动化,并可从 Tanzu Network 获取最新的堆栈和生成包版本。VMware 旨在遵循行业最佳实践,及时提供 CVE 补丁,保障客户系统的安全。对于开发人员而言,这减轻了通过新的依赖关系来更新容器所造成的负担。对于运维人员而言,它可以集中控制所有容器的依赖关系,从而更好地满足安全性、合规性和审核需求。


作者简介:

在这里插入图片描述
熊铭杰,VMware大中华区应用现代化部门高级解决方案架构师,在加入VMware之前,曾先后任职BEA System、IBM、Redhat等企业。多年来一直从事企业级软件开发、中间件和云原生相关领域工作,对企业级软件开发和架构设计、微服务架构设计以及容器平台的架构设计、软件开发、实施和运维等工作具有丰富的经验积累;CNCF认证CKA工程师;VMware认证Spring Professional工程师。

来源|公众号:VMwareTanzu云原生

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值