摘要:自定义镜像部分自定义镜像部分安装工具安装工具工具官方下载工具解压工具到查看版本初始化目录结构初始化目录结构笔者是在目录下开始操作的,提前说下免得读者操作有误。修改修改脚本只作启动功能,为了方便传调优参数,定制了环境变量供使用。
由于 OpenShift 官方提供的镜像与模板(OpenJDK8)不完全满足业务需要:
不包含飞行记录功能。只有 OpenJDK11 以上才被 Oracle 开源
生成堆 dump 很大很慢(公司项目 JVM 堆最小16G,最大32G),导出-压缩-传输
较长(半小时以上),对业务停顿时间过长
镜像内置的获取性能指标的命令很少,常规网络状态查询命令如 netstat
、ping
等都没有
镜像内部s2i流程编写得过于复杂,镜像构建过程缓存多且未移除,导致最终镜像普遍体积过大(350M的业务应用,打出镜像有 1.1G…)
为了方便定位性能问题,笔者仔细阅读了 OpenShift v3.11 版本的 s2i 构建流程、镜像自定义等相关文档,定制出了自己的模板与镜像,目前已经在生产环境上验证通过,在这里记录一二。如果有帮到你,点个关注和赞再走吧~
本文主体思路是使用 s2i工具创建基础的构建调试环境,修改Dockerfile与构建脚本生成镜像,再推送镜像和模板到上篇文章OpenShift 本地开发环境配置(基于 Minishift)的环境中,用一个demo测试下最终效果。
s2i 工具官方Release Page:https://github.com/openshift/source-to-image/releases
#下载s2i工具wget https://github.com/openshift/source-to-image/releases/download/v1.3.1/source-to-image-v1.3.1-a5a77147-linux-amd64.tar.gz#解压s2i工具到/usr/binsudo tar zxf source-to-image-v1.3.1-a5a77147-linux-amd64.tar.gz -C /usr/bin#查看s2i版本s2i version
笔者是在
~/WorkSpace/openshift
目录下开始操作的,提前说下免得读者操作有误。
#生成s2i脚本目录结构,create参数为创建,第3参数为镜像名,第3参数为生成目录名s2i create oracle-jdk-8 oracle-jdk-8-catelog#进入生成的目录中cd oracle-jdk-8-catelog#查看基本目录结构tree -L 3.├── Dockerfile #镜像Dockerfile├── Makefile #Makefile构建脚本├── README.md├── s2i│ └── bin #s2i脚本目录│ ├── assemble #装配脚本│ ├── run #运行脚本│ ├── save-artifacts #可选,保存制品脚本,增量构建时用│ └── usage #使用说明脚本└── test ├── run #测试运行脚本 └── test-app #构建的源码(本例中可以是jar包) └── index.html
这里笔者用不到 s2i/bin/save-artifacts
,因为不需要增量构建,删除之; test/test-app/index.html
也用不到,删除之。
rm -rf s2i/bin/save-artifactsrm -rf test/test-app/index.html
由于笔者已经将jdk8安装包下载好了,下载 OracleJDK 付费版本以前的版本,参考我的博客,这里就直接从 ~/Downloads
解压到 ~/WorkSpace/openshift/oracle-jdk-8-catelog
下
#解压jdk安装包tar zxvf ~/Downloads/jdk-8u181-linux-x64.tar.gz -C ~/WorkSpace/openshift/oracle-jdk-8-catelog#进入jdk解压目录cd /home/hellxz/WorkSpace/openshift/oracle-jdk-8-catelog/jdk1.8.0_181#适度精简,删除源码包,能小26Mrm -rf javafx-src.zip src.zip#回到模板初始化的目录cd ..
vim Dockerfile
,把默认的都删除掉,添加下边的内容:
FROM debian:busterENV BUILDER_VERSION 1.0# Set labels used in OpenShift to describe the builder imageLABEL description="Source To Image (S2I) image for Hellxz Providing Oracle JDK 8" / maintainer="Hellxz Zhang " / io.k8s.description="Platform for building and running Java applications with Oracle JDK 8" / io.k8s.display-name="Java Applications" / io.openshift.expose-services="8080:http" / io.openshift.tags="builder,java" / io.openshift.s2i.scripts-url="image:///usr/libexec/s2i" / io.openshift.s2i.destination="/tmp"# Copy Oracle JDK8COPY ./jdk1.8.0_181 /usr/lib/jvm# Copy scripts to s2i build path, must same as `io.openshift.s2i.scripts-url` label specified.COPY ./s2i/bin/ /usr/libexec/s2i# EnvironmentsENV JAVA_HOME="/usr/lib/jvm" / PATH="/usr/lib/jvm/bin:${PATH}" / TZ="Asia/Shanghai"# Create oraclejdk user with home dir /deployments# Grant user exec privilege# Set apt mirror and install some utils then clean # Generate UTF-8 localesRUN mkdir /deployments && / useradd -M -d /deployments -u 1001 -s /bin/bash oraclejdk8 && / chown oraclejdk8 /deployments && chmod 777 /deployments && / bash -c "echo -e /"deb http://mirrors.163.com/debian/ buster main non-free contrib/ndeb http://mirrors.163.com/debian/ buster-updates main non-free contrib/ndeb http://mirrors.163.com/debian/ buster-backports main non-free contrib/ndeb http://mirrors.163.com/debian-security/ buster/updates main non-free contrib/" > /etc/apt/sources.list" && / apt-get update -y && apt-get install -y net-tools locales procps && / apt-get clean all -y && rm -rf /var/lib/apt/lists/* && / sed -i "/en_US.UTF-8/s/^# //g" /etc/locale.gen && locale-gen# To avoid build image error tips set LC env after locale.genENV LC_ALL="en_US.UTF-8"# Switch userUSER 1001# Switch WorkDirWORKDIR /deploymentsEXPOSE 8080 8443# Set the default CMD for the imageCMD ["/usr/libexec/s2i/usage"]
上述的Dockerfile做了什么呢?
CMD
入口完成Dockerfile的修改还没完,我们还需要修改 s2i 构建与运行脚本,以适应刚刚修改的镜像配置
s2i脚本在 s2i/bin
目录下,我们需要修改 assemble
脚本来改变组装流程,修改 run
脚本以更换启动命令。
vim s2i/bin/assemble
#!/bin/bash -e## S2I assemble script for the "oracle-jdk-8" image.# The "assemble" script builds your application source so that it is ready to run.## For more information refer to the documentation:# https://github.com/openshift/source-to-image/blob/master/docs/builder_image.md## Prevent some horror bugs. example: rm -rf ${SOME_UNEXISTS_VARIABLE}/* set -e# If the "oracle-jdk-8" assemble script is executed with the "-h" flag, print the usage.if [[ "$1" == "-h" ]]; then exec /usr/libexec/s2i/usagefiecho "---> Moving Artifact from source..."mv /tmp/src/*.jar /deployments/echo "---> Clearing tmp dir..."rm /tmp/src/.git -rfecho "<--- Build Success..."
以上脚本主要做了两件事,一个是从 /tmp/src
下将 jar 包复制到部署目录,在之前的文章中介绍过 s2i 的工作流程,在构建时会从 Git 上拉取制品或源码到 /tmp/src
下;另一个是删除 /tmp/src/.git
目录,原因是 Git 的 .git
目录会同样保存压缩后的制品或源码文件,删除以减小镜像体积。
vim s2i/bin/run
#!/bin/bash -e## S2I run script for the "oracle-jdk-8" image.# The run script executes the server that runs your application.## For more information see the documentation:# https://github.com/openshift/source-to-image/blob/master/docs/builder_image.md#exec java ${JVM_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /deployments/*.jar
run 脚本只作启动功能,为了方便传 JVM 调优参数,定制了 JVM_OPTS
环境变量供使用。参数中的随机数配置能提高服务生成随机数的能力,提高启动速度。
修改Makefile的作用是简化构建镜像的命令,笔者这里修改了镜像名以及添加了推送私有镜像仓库的参数,这点上 npm
有点类似于 Makefile
。
IMAGE_NAME = 192.168.99.1:5000/oracle-jdk-8.PHONY: testtest: docker build -t $(IMAGE_NAME)-candidate . IMAGE_NAME=$(IMAGE_NAME)-candidate test/run.PHONY: pushpush: docker build -t $(IMAGE_NAME) . docker push $(IMAGE_NAME)
想了解更多 Makefile 写法,可以参考
左耳朵耗子
陈皓 写的《跟我一起写Makefile》
test/run
这个测试脚本相当于完成了一次 s2i 到部署的过程,先准备测试镜像,再运行s2i的构建过程增量构建(将测试制品程序与镜像进行组装,容器内部调用了 assemble
脚本),然后启动容器,运行定时测试脚本访问容器端口地址,通过就算成功了。
由于默认测试脚本中测试服务是否可用是访问地址判断返回值是否200状态码,我这边提供个springboot的demo 部署后访问 /test
端点返回结果 ,首先构建下这个demo:
#克隆测试demogit clone https://github.com/hellxz/cicd-demo.git test/test-app#手动构建cd test/test-appmvn package -DskipTests#复制jar包并删除本文无关的内容mv target/*.jar .rm -rf *.sh *file *.xml *.md src target .git *.yaml .gitignore .mvn#回到Makefile所在目录cd ../..
修改 test/run
脚本,调整探测间隔与访问的接口地址,本demo中需修改116行为5,以及120和121行访问路径添加 /test
执行测试
make test
我们能看到 springboot 的 banner 下有行字 Starting CicdDemoApplication v0.0.1 using Java 1.8.0_181 on f770c60456f4 with PID 1 (/deployments/cicd-demo-0.0.1.jar started by oraclejdk8 in /deployments)
,这可以证明测试的demo的确是以 oraclejdk8 用户运行成功的,而且 pid 为 1。再往下看也没有检测报错的信息,说明测试通过,可以使用 Minishift测试了。
#执行Makefile中定义的构建推送命令make push
hellxz@debian:~/WorkSpace/openshift/oracle-jdk-8-catelog$ make pushdocker build -t 192.168.99.1:5000/oracle-jdk-8 .Sending build context to Docker daemon 389.2MBStep 1/12 : FROM debian:buster ---> 2b6f409b1d24Step 2/12 : ENV BUILDER_VERSION 1.0 ---> Using cache ---> 46de72742080Step 3/12 : LABEL description="Source To Image (S2I) image for Hellxz Providing Oracle JDK 8" maintainer="Hellxz Zhang " io.k8s.description="Platform for building and running Java applications with Oracle JDK 8" io.k8s.display-name="Java Applications" io.openshift.expose-services="8080:http" io.openshift.tags="builder,java" io.openshift.s2i.scripts-url="image:///usr/libexec/s2i" io.openshift.s2i.destination="/tmp" ---> Using cache ---> fcbadb0d0d39Step 4/12 : COPY ./jdk1.8.0_181 /usr/lib/jvm ---> Using cache ---> ebb551cc9d4cStep 5/12 : COPY ./s2i/bin/ /usr/libexec/s2i ---> Using cache ---> 5f08421b9527Step 6/12 : ENV JAVA_HOME="/usr/lib/jvm" PATH="/usr/lib/jvm/bin:${PATH}" TZ="Asia/Shanghai" ---> Using cache ---> 3c663a5370c8Step 7/12 : RUN mkdir /deployments && useradd -M -d /deployments -u 1001 -s /bin/bash oraclejdk8 && chown oraclejdk8 /deployments && chmod 777 /deployments && bash -c "echo -e /"deb http://mirrors.163.com/debian/ buster main non-free contrib/ndeb http://mirrors.163.com/debian/ buster-updates main non-free contrib/ndeb http://mirrors.163.com/debian/ buster-backports main non-free contrib/ndeb http://mirrors.163.com/debian-security/ buster/updates main non-free contrib/" > /etc/apt/sources.list" && apt-get update -y && apt-get install -y net-tools locales procps && apt-get clean all -y && rm -rf /var/lib/apt/lists/* && sed -i "/en_US.UTF-8/s/^# //g" /etc/locale.gen && locale-gen ---> Using cache ---> 5e9c181bb69bStep 8/12 : ENV LC_ALL="en_US.UTF-8" ---> Using cache ---> 60091bb63284Step 9/12 : USER 1001 ---> Using cache ---> f8e6a2e96a8aStep 10/12 : WORKDIR /deployments ---> Using cache ---> 66f6925e3ab6Step 11/12 : EXPOSE 8080 8443 ---> Using cache ---> bda814465820Step 12/12 : CMD ["/usr/libexec/s2i/usage"] ---> Using cache ---> f30388d3181cSuccessfully built f30388d3181cSuccessfully tagged 192.168.99.1:5000/oracle-jdk-8:latestdocker push 192.168.99.1:5000/oracle-jdk-8Using default tag: latestThe push refers to repository [192.168.99.1:5000/oracle-jdk-8]16970671df83: Pushed 97a51654d23f: Pushed 16fd63c1b14c: Pushed d6a325d281f2: Pushed latest: digest: sha256:904e52bcfe7c4ea8a156de4bd9cb073770f4af703ac6acb59a9180c272d41b79 size: 1160
这里Minishift导入镜像到内部仓库和OpenShift是一致的,说是OpenShift也可以。
#导入需要oc命令行工具,minishift默认已经提供了,但未加入到Path中,可以执行如下命令临时把oc加入Patheval (minishift oc-env) #如果报错,则只执行括号内命令,根据提示执行相应命令oc import-image 192.168.99.1:5000/oracle-jdk-8:latest --confirm --insecure
hellxz@debian:~/WorkSpace/openshift$ oc import-image 192.168.99.1:5000/oracle-jdk-8:latest --confirm --insecureimagestream.image.openshift.io/oracle-jdk-8 importedName: oracle-jdk-8Namespace: myprojectCreated: 1 second agoLabels: Annotations: openshift.io/image.dockerRepositoryCheck=2021-11-21T14:24:57ZDocker Pull Spec: 172.30.1.1:5000/myproject/oracle-jdk-8Image Lookup: local=falseUnique Images: 1Tags: 1latest tagged from 192.168.99.1:5000/oracle-jdk-8:latest will use insecure HTTPS or HTTP connections * 192.168.99.1:5000/oracle-jdk-8@sha256:904e52bcfe7c4ea8a156de4bd9cb073770f4af703ac6acb59a9180c272d41b79 1 second agoImage Name: oracle-jdk-8:latestDocker Image: 192.168.99.1:5000/oracle-jdk-8@sha256:904e52bcfe7c4ea8a156de4bd9cb073770f4af703ac6acb59a9180c272d41b79Name: sha256:904e52bcfe7c4ea8a156de4bd9cb073770f4af703ac6acb59a9180c272d41b79Created: 1 second agoAnnotations: image.openshift.io/dockerLayersOrder=ascendingImage Size: 221.8MB in 4 layersLayers: 50.44MB sha256:07471e81507f7cf1100827f10c60c3c0422d1222430e34e527d97ec72b14a193 161.8MB sha256:98b418031cdbc51e52d88a2632516069e753d5293ec440dae46163a45880492a 899B sha256:61addb0f8207e85f3a734299eda8b8afae987076de0cf67b60f33c9c9846f6b6 9.598MB sha256:09daea12eb7b9cd76b4629e22d566a6646eb6e19ea3c92706c7bc41bf0285384Image Created: 30 minutes agoAuthor: Arch: amd64Command: /usr/libexec/s2i/usageWorking Dir: /deploymentsUser: 1001Exposes Ports: 8080/tcp, 8443/tcpDocker Labels: description=Source To Image (S2I) image for Hellxz Providing Oracle JDK 8 io.k8s.description=Platform for building and running Java applications with Oracle JDK 8 io.k8s.display-name=Java Applications io.openshift.expose-services=8080:http io.openshift.s2i.destination=/tmp io.openshift.s2i.scripts-url=image:///usr/libexec/s2i io.openshift.tags=builder,java maintainer=Hellxz Zhang Environment: PATH=/usr/lib/jvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin BUILDER_VERSION=1.0 JAVA_HOME=/usr/lib/jvm TZ=Asia/Shanghai LC_ALL=en_US.UTF-8
如果报错,优先考虑是否登录了oc,
oc login -u developer
,执行后再尝试导入。
这里直接提供模板内容,基于 openjdk8的模板修改而来的:
oraclejdk-8-basic-s2i.yaml
apiVersion: template.openshift.io/v1kind: Templatemessage: A new java application has been created in your project.metadata: annotations: description: An Java application using Oracle JDK 8. iconClass: icon-rh-openjdk openshift.io/display-name: OracleJDK 8 by Hellxz openshift.io/provider-display-name: Hellxz Zhang . tags: java template.openshift.io/long-description: This template defines resources needed to develop Oracle JDK 8 Java based application. template.openshift.io/support-url: hellxz001@foxmail.com version: 0.0.1 labels: template: oraclejdk-8-basic-s2i xpaas: 0.0.1 name: oraclejdk-8-basic-s2iobjects:- apiVersion: v1 kind: Service metadata: annotations: description: The application"s http port. labels: application: ${APPLICATION_NAME} name: ${APPLICATION_NAME} spec: ports: - port: 8080 targetPort: 8080 selector: deploymentConfig: ${APPLICATION_NAME}- apiVersion: v1 id: ${APPLICATION_NAME}-http kind: Route metadata: annotations: description: Route for application"s http service. labels: application: ${APPLICATION_NAME} name: ${APPLICATION_NAME} spec: host: ${HOSTNAME_HTTP} to: name: ${APPLICATION_NAME}- apiVersion: v1 kind: ImageStream metadata: labels: application: ${APPLICATION_NAME} name: ${APPLICATION_NAME}- apiVersion: v1 kind: BuildConfig metadata: labels: application: ${APPLICATION_NAME} name: ${APPLICATION_NAME} spec: output: to: kind: ImageStreamTag name: ${APPLICATION_NAME}:latest source: contextDir: "" git: ref: ${SOURCE_REPOSITORY_REF} uri: ${SOURCE_REPOSITORY_URL} type: Git strategy: sourceStrategy: forcePull: true from: kind: ImageStreamTag name: oracle-jdk-8:latest namespace: ${IMAGE_STREAM_NAMESPACE} type: Source triggers: - imageChange: {} type: ImageChange - type: ConfigChange- apiVersion: v1 kind: DeploymentConfig metadata: labels: application: ${APPLICATION_NAME} name: ${APPLICATION_NAME} spec: replicas: 1 selector: deploymentConfig: ${APPLICATION_NAME} strategy: type: Recreate template: metadata: labels: application: ${APPLICATION_NAME} deploymentConfig: ${APPLICATION_NAME} name: ${APPLICATION_NAME} spec: containers: - env: [] image: ${APPLICATION_NAME} imagePullPolicy: Always name: ${APPLICATION_NAME} ports: - containerPort: 8778 name: jolokia protocol: TCP - containerPort: 8080 name: http protocol: TCP - containerPort: 8443 name: https protocol: TCP terminationGracePeriodSeconds: 75 triggers: - imageChangeParams: automatic: true containerNames: - ${APPLICATION_NAME} from: kind: ImageStreamTag name: ${APPLICATION_NAME}:latest type: ImageChange - type: ConfigChangeparameters:- description: The name for the application. displayName: Application Name name: APPLICATION_NAME required: true value: oraclejdk8-app- description: Git source URI for application displayName: Git Repository URL name: SOURCE_REPOSITORY_URL required: true- description: Git branch/tag reference displayName: Git Reference name: SOURCE_REPOSITORY_REF value: master- description: "Custom hostname for http service route. Leave blank for default hostname, e.g.: -." displayName: Custom http Route Hostname name: HOSTNAME_HTTP- description: Namespace in which the ImageStreams for Red Hat Middleware images are installed. These ImageStreams are normally installed in the openshift namespace. You should only need to modify this if you"ve installed the ImageStreams in a different namespace/project. displayName: ImageStream Namespace name: IMAGE_STREAM_NAMESPACE required: true value: myproject
模板的结构简单说明:
oc apply -f oraclejdk-8-basic-s2i.yaml
hellxz@debian:~/WorkSpace/openshift$ oc apply -f=oraclejdk-8-basic-s2i.yaml template.template.openshift.io/oraclejdk-8-basic-s2i created
由于OpenShift是由Git仓库拉取制品或源码进行构建的,所以需要把测试程序(上文中用到的cicd-demo-0.0.1.jar)上传到 Git 版本控制中,这里延用上篇文章中 Minishift 开发环境中配置的 Gitea(需要预先创建个账号和仓库,这里创建的仓库名为demo,用户名为hellxz)。
#进入测试程序jar所在目录cd ~/WorkSpace/openshift/oracle-jdk-8-catelog/test/test-app#初始化当前目录为git仓库git init#添加远程仓库地址(按实际操作来,变通一些)git remote add origin git remote add origin http://localhost:3000/hellxz/demo.git#设置用户名和emailgit config --local user.name hellxzgit config --local user.email hellxz001@foxmail.com#提交git add .git commit -m "init"#推送远程仓库git push --set-upstream origin master
如下图,已经推送完毕。
模板中引用的是自定义镜像的名称,命名空间也是myproject(Minishift默认的,生产环境可以改成需要的名称再上传,调整可多次导入)
首次部署流程比较麻烦,这里分多个动图录制
Gitea 配置的对外地址配置得有点问题,不过问题不大……
需要告知s2i构建脚本 Git 仓库的用户和密码,这样才能拉得下来制品,仅首次创建应用时需要创建。
如图,容器运行已经是 Ready: true 状态,说明启动状态正常。
由于没有外部的dns,域名可以修改 /etc/hosts
文件代替
测试通过,自定义镜像和模板都能正常工作。
写作不易,如果本文对您有所帮助,就点个关注点个赞再走呗~ 我是 Hellxz,我们下次再见。
本文同步发布以下两个地址,未经许可禁止转载。
- 博客园 https://www.cnblogs.com/hellxz
- CSDN https://blog.csdn.net/u012586326
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/124123.html
摘要:是一套工具包和工作流程,用于从源代码构建重复性镜像。由上图可以看出,方式的构建过程比较直接根据定义的步骤,读取源代码,生成镜像成品。源代码相关编译源代码部署二进制程序定义服务启动方式等。 前言 写Dockerfile是构建Docker镜像最通常的方式,接触过Docker的童鞋多少了解一些。前段时间研究OpenShift(paas的一种),发现了另外一种构建Docker镜像的方式:S2I...
摘要:镜像可先推送到私有仓库测试发现镜像有问题镜像以用户运行切换,赋权对参数做定制将创建域,组织名称为域管理员及管理员密码持久化存储,本例使用已创建好的存储系统,其支持动态提供。 前言 如同Linux操作系统安装完成后,管理员需为应用创建不同的用户,那么,K8S/OKD/Openshift集群同样也需如此,而在OKD/Openshift集群里,我们可集成OpenLDAP目录系统,方法如下所示...
摘要:镜像可先推送到私有仓库测试发现镜像有问题镜像以用户运行切换,赋权对参数做定制将创建域,组织名称为域管理员及管理员密码持久化存储,本例使用已创建好的存储系统,其支持动态提供。 前言 如同Linux操作系统安装完成后,管理员需为应用创建不同的用户,那么,K8S/OKD/Openshift集群同样也需如此,而在OKD/Openshift集群里,我们可集成OpenLDAP目录系统,方法如下所示...
摘要:鉴于这一特征,用户必须转变他们使用以及管理容器时的心态。不要将应用分开发布有些人会将容器视为虚拟机,他们中的大部分人认为,应该在现有的运行容器中部署应用。不要以用户运行进程默认情况下,容器以权限运行。 【编者按】本文作者为 Rafael Benevides,主要介绍使用 Docker 容器时应该注意的十个陷阱。文章系国内 ITOM 管理平台 OneAPM 编译呈现,以下为正文。 sho...
摘要:第二具备轻量化特性容器的体积非常小巧。他们大多认为自己应该将应用程序部署至当前正在运行的容器当中。不要创建大型镜像体积过大的镜像会加大其发布难度。总体来讲,在向生产环境中部署容器时,必须避免使用最新标签。 当下最火爆的Docker,是一个开源的应用容器引擎。大家已经开始认同并接受容器技术,并意识到它能够解决多种现实问题并具备一系列无可比拟的优势。今天小数就和大家聊一聊容器技术的优势和误...
阅读 3833·2021-11-24 09:39
阅读 3751·2021-11-22 12:07
阅读 1102·2021-11-04 16:10
阅读 794·2021-09-07 09:59
阅读 1900·2019-08-30 15:55
阅读 932·2019-08-30 15:54
阅读 721·2019-08-29 14:06
阅读 2471·2019-08-27 10:54