天天看點

Look,容器中應用的建構方法!

文章導讀

  • 本文僅代表作者的個人觀點;
  • 本文的内容僅限于技術探讨,不能作為指導生産環境的素材;
  • 本文素材是紅帽公司産品技術和手冊;

一、什麼是建構?

建構是:

  • 将輸入參數轉換為結果對象的過程
  • 用于将源代碼轉換為可運作容器映像的建構
  • 建構配置或建構配置檔案的特點是: 建構政策、至少有一個來源
  • 政策決定了過程;源提供輸入

容器中應用的四種建構政策:

4建構政策:

  • Source-to-Image (S2I)
  • Docker
  • Pipeline
  • Custom

作為建構輸入提供的六種源類型:

  • Git
  • Dockerfile
  • Binary
  • Image
  • Input secrets
  • External artifacts

二進制源類型建構

  • 從本地檔案系統到建構器的二進制格式流内容
  • 完全基于oc的起始建構

從二進制源代碼開始建構,使用以下選項之一調用oc start-build:

Look,容器中應用的建構方法!

S2I增量建構重用以前建構的image中的工件 要建立增量建構,請修改BuildConfig政策定義:

Look,容器中應用的建構方法!
  • 指定支援增量建構的映像
  • Flag控制是否嘗試增量建構
  • 如果建構器映像不支援增量建構,則建構仍會成功
  • 由于缺少save-artifacts腳本,日志消息表明增量建構不成功

将建構配置設定給特定節點

通過在建構配置的nodeSelector字段中指定标簽,可以将建構目标定位為在特定節點上運作nodeSelector在排程建構窗體時與節點标簽比對的鍵值對的值集:

Look,容器中應用的建構方法!

與建構配置關聯的建構僅在具有region = primary和nodetype = build标簽的節

連結建構:

Build 1生成編譯的工件

Build 2将工件放置在運作工件的單獨image中。

連結建構示例

S2I建構與Docker建構相結合

在單獨的運作時映像中編譯工件和位置

Look,容器中應用的建構方法!

連結建構BuildConfig - 建構1

第一次建構産生包含WAR的圖像,image被推送到工件image stream,輸出工件路徑取決于S2I建構器的彙編腳本

輸出工件/wildfly/standalone/deployments/ROOT.war:

Look,容器中應用的建構方法!

連結建構BuildConfig - 建構2

在第一次建構時使用輸出圖像内的WAR檔案路徑的image stream

内聯Dockerfile将WAR檔案複制到運作時映像中:

Look,容器中應用的建構方法!

from指定Docker建構包括來自工件圖像圖像流的圖像輸出,即先前建構的目标

paths指定目标映像中包含哪些路徑以包含在目前Docker建構中

運作時映像用作Docker建構的源映像

每次第一次建構成功完成時,ImageChange觸發器都會調用第二次建構

使用OpenShift建構Maven Slave圖像

OpenShift Build Configs可用于建構Maven Slave Image

Build Config必須位于将引用image的Jenkins項目中

示例:使用skopeo建構從屬映像

Look,容器中應用的建構方法!

二、實驗展現

登入Gogs上,在CICDLabs組織下,建立一個名為openshift- task- Private的新存儲庫,并確定它被設定為Private。

制作一個openshift任務庫的副本并将其推入Gogs:

Look,容器中應用的建構方法!

注意GOGS儲存庫路徑。

複制OpenSHIFT任務庫并将其推入Gogs:

Look,容器中應用的建構方法!

建立一個指向此存儲庫的新應用程式:

首先建立一個gogs-secret

oc create secret generic gogs-secret --from-literal=username=david --from-literal=password=david

Look,容器中應用的建構方法!

建立應用:

oc new-app --template=eap70-basic-s2i --param APPLICATION_NAME=tasks --param SOURCE_REPOSITORY_URL=http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git --param SOURCE_REPOSITORY_REF=master --param CONTEXT_DIR=/ --param MAVEN_MIRROR_URL=http://nexus3.xyz-nexus80.svc.cluster.local:8081/repository/maven-all-public

Look,容器中應用的建構方法!
Look,容器中應用的建構方法!

緩存的工件

JBoss EAP S2I builder映像支援在建構之間儲存建構工件,這大大減少了建構時間。建構配置需要反映這一點。

更改建構配置以增量方式建構。将forcePull更改為false。這可以防止OpenShift每次在建構應用程式時都拉拽生成器映像,這将花費很多時間。

使用oc patch編輯bc,在sourceStrategy下添加增量标志,并将forcePull更改為false:

oc patch bc/tasks --patch='{"spec": {"strategy": {"sourceStrategy": {"incremental": true}}}}'

oc patch bc/tasks --patch='{"spec": {"strategy": {"sourceStrategy": {"forcePull": false}}}}'

Look,容器中應用的建構方法!
Look,容器中應用的建構方法!
Look,容器中應用的建構方法!

三、實驗展現:環境介紹實作二進制建構

使用OpenJDK S2I映像示範使用現有Spring引導應用程式進行的二進制建構。

建立Spring啟動應用程式

從https://github.com/wkulhanek/ola.git建立一個新的Java Spring引導應用程式。

使用帶有1.2标簽的redhat-openjdk18-openshift image stream來建構應用程式。

Look,容器中應用的建構方法!

確定在應用程式建立之後為其建立路由:

Look,容器中應用的建構方法!

確定應用在運作:

Look,容器中應用的建構方法!

部署使用二進制建構

使用二進制建構政策建構相同的應用程式,這意味着您首先在本地建構應用程式,然後建立一個二進制建構配置,最後使用本地建構的JAR檔案作為二進制建構的輸入啟動一個二進制建構。

cd $HOME

git clone https://github.com/wkulhanek/ola.git

cd ola

mvn clean package

Look,容器中應用的建構方法!

檢視建構成功的jar:

Look,容器中應用的建構方法!

java -jar $HOME/ola/target/ola.jar

Look,容器中應用的建構方法!

建立一個名為ola-binary的二進制建構,這個建構現在需要本地檔案系統中的二進制部署工件。

Look,容器中應用的建構方法!

啟動一個新的建構,并将編譯後的檔案流到建構中。確定在建構執行時遵循它。

Look,容器中應用的建構方法!
Look,容器中應用的建構方法!

當您執行oc start-build指令時,您将看到建構很快完成。二進制建構複制預建構的工件,并将副本移動到正确的目錄中。在本例中,它複制ola。jar檔案放入S2I映像,然後将其移動到/deployments。

建構完成後,從新建立的映像部署應用程式。

将應用程式公開為ola-binary route。

oc new-app ola-binary

oc expose svc/ola-binary --port=8080

Look,容器中應用的建構方法!
Look,容器中應用的建構方法!

四、實驗展現:實作連結建構

連結建構,首先使用build image建構應用程式。然後将建構的工件部署到第二次運作時映像中。這隻對Java或Go這樣的編譯語言有意義。

第一步,通過S2I建構應用鏡像

在這個步驟中,我們就是上對go進行了編譯。

go應用的源碼:

https://github.com/tonykay/ose-chained-builds/blob/master/go-scratch/hello_world/main.go

package main

import (

"fmt"

"net/http"

)

const (

port = ":8080"

)

var calls = 0

func HelloWorld(w http.ResponseWriter, r *http.Request) {

calls++

fmt.Fprintf(w, "Hello, world! You have called me %d times.\n", calls)

fmt.Fprintf(w, "You have successfully finished this lab.\n")

}

func init() {

fmt.Printf("Started server at http://localhost%v.\n", port)

http.HandleFunc("/", HelloWorld)

http.ListenAndServe(port, nil)

}

func main() {}

然後,使用S2I - Go作為builder image,編譯go源碼。

首先,從DockerHub導入jorgemoralespou/ S2I - Go映像作為您的S2I Go映像。

Look,容器中應用的建構方法!

建立一個新的建構來編譯示例Go應用程式。

要使用的上下文目錄是/go-scratch/hello_world。

oc new-build s2i-go~https://github.com/tonykay/ose-chained-builds \

--context-dir=/go-scratch/hello_world --name=builder

遵循建構日志,等待Go應用程式編譯,并等待映像完成建構,然後繼續下一步。

我們檢視go編譯的日志:

[xiwei-redhat.com@bastion 0 ~]$ oc logs builder-1-build

===> Build started at Wed Aug 29 05:55:55 UTC 2018

---> Preparing source...

---> Downloading dependencies...

main

---> Building application source...

runtime/internal/sys

runtime/internal/atomic

runtime

errors

internal/race

sync/atomic

math

unicode/utf8

unicode

sort

container/list

crypto/subtle

sync

io

syscall

internal/singleflight

hash

crypto/cipher

hash/crc32

crypto/hmac

bytes

strings

bufio

path

strconv

math/rand

time

internal/syscall/unix

reflect

crypto

crypto/aes

crypto/rc4

encoding/base64

crypto/sha512

crypto/md5

crypto/sha1

crypto/sha256

encoding/pem

os

path/filepath

net

fmt

encoding/binary

crypto/des

io/ioutil

compress/flate

math/big

encoding/hex

log

internal/golang.org/x/net/http2/hpack

mime

mime/quotedprintable

net/http/internal

net/url

compress/gzip

crypto/elliptic

crypto/dsa

crypto/rand

encoding/asn1

crypto/rsa

net/textproto

crypto/ecdsa

crypto/x509/pkix

crypto/x509

mime/multipart

crypto/tls

net/http

main

===> Build completed at Wed Aug 29 05:56:37 UTC 2018

Binary at /opt/app-root/src/go/src/main

===> Elapsed time: 42 seconds

Pushing image docker-registry.default.svc:5000/xyz-builds80/builder:latest ...

Pushed 0/7 layers, 1% complete

Pushed 1/7 layers, 19% complete

Pushed 2/7 layers, 32% complete

Pushed 3/7 layers, 48% complete

Pushed 4/7 layers, 62% complete

Pushed 5/7 layers, 95% complete

Pushed 6/7 layers, 97% complete

Pushed 7/7 layers, 100% complete

Push successful

從上面标黃的部分可以看到,go建構成功以後的二進制檔案,放到了/opt/app-root/src/go/src/main目錄下。

當image建構成功以後,我們用将其部署成pod,也可以看到建構成功的檔案:

Look,容器中應用的建構方法!

而/opt/app-root/src/go/src/main/main是個可運作的二進制檔案:

Look,容器中應用的建構方法!

接下來,我們檢查生成的建構程式imagestream:

Look,容器中應用的建構方法!

建立第二個(連結的)建構,它擷取建構的工件(/opt/app-root/src/go/src/main/main)并将其部署到一個小的運作時映像scratch中。而scratch實際上是一個空檔案。

步驟是:使用scratch Docker映像作為基礎映像,然後,将/opt/app-root/src/go/src/main/main拷貝到/main目錄下,然後使用docker build完成

oc new-build --name=runtime \

--source-image=builder \

--source-image-path=/opt/app-root/src/go/src/main/main:. \

--dockerfile=$'FROM scratch\nCOPY main /main\nEXPOSE 8080\nENTRYPOINT ["/main"]'

上面的指令行,相當于建立如下一個docker file,然後在建構的時候,執行docker build

Look,容器中應用的建構方法!

檢視指令輸出結果:

Look,容器中應用的建構方法!

[xiwei-redhat.com@bastion 0 /]$ oc logs -f bc/runtime

Pulling image "docker-registry.default.svc:5000/xyz-builds80/builder@sha256:3a674cf1b914720204509ab8da9af6f8255a51bd6f1709ea98cbeeabd2d6ebea" ...

Step 1/6 : FROM scratch

--->

Step 2/6 : COPY main /main

---> Using cache

---> 5c07c74949ea

Step 3/6 : EXPOSE 8080

---> Using cache

---> 10efcc15fba7

Step 4/6 : ENTRYPOINT /main

---> Using cache

---> e8c2c705d4ed

Step 5/6 : ENV "OPENSHIFT_BUILD_NAME" "runtime-1" "OPENSHIFT_BUILD_NAMESPACE" "xyz-builds80"

---> Running in 4a2467b85f03

---> 42ecaf43ece5

Removing intermediate container 4a2467b85f03

Step 6/6 : LABEL "io.openshift.build.name" "runtime-1" "io.openshift.build.namespace" "xyz-builds80"

---> Running in d6f93173f1a7

---> 06c1644c70e3

Removing intermediate container d6f93173f1a7

Successfully built 06c1644c70e3

Pushing image docker-registry.default.svc:5000/xyz-builds80/runtime:latest ...

Push successful

oc new-app runtime --name=my-application

oc expose svc/my-application

Look,容器中應用的建構方法!