完全指南:在容器中運行 Jenkins 構建

完全指南:在容器中運行 Jenkins 構建

來自專欄 Linux7 人贊了文章

容器應用程序平台能夠動態地啟動具有資源限制的獨立容器,從而改變了運行 CI/CD 任務的方式。

現今,由於 Docker 和 Kubernetes(K8S)提供了可擴展、可管理的應用平台,將應用運行在容器中的實踐已經被企業廣泛接受。近些年勢頭很猛的微服務架構也很適合用容器實現。

容器應用平台可以動態啟動指定資源配額、互相隔離的容器,這是其最主要的優勢之一。讓我們看看這會對我們運行 持續集成/持續部署(continuous integration/continuous development)(CI/CD)任務的方式產生怎樣的改變。

構建並打包應用需要一定的環境,要求能夠下載源代碼、使用相關依賴及已經安裝構建工具。作為構建的一部分,運行單元及組件測試可能會用到本地埠或需要運行第三方應用(如資料庫及消息中間件等)。另外,我們一般定製化多台構建伺服器,每台執行一種指定類型的構建任務。為方便測試,我們維護一些實例專門用於運行第三方應用(或者試圖在構建伺服器上啟動這些第三方應用),避免並行運行構建任務導致結果互相干擾。為 CI/CD 環境定製化構建伺服器是一項繁瑣的工作,而且隨著開發團隊使用的開發平台或其版本變更,會需要大量的構建伺服器用於不同的任務。

一旦我們有了容器管理平台(自建或在雲端),將資源密集型的 CI/CD 任務在動態生成的容器中執行是比較合理的。在這種方案中,每個構建任務運行在獨立啟動並配置的構建環境中。構建過程中,構建任務的測試環節可以任意使用隔離環境中的可用資源;此外,我們也可以在輔助容器中啟動一個第三方應用,只在構建任務生命周期中為測試提供服務。

聽上去不錯,讓我們在現實環境中實踐一下。

註:本文基於現實中已有的解決方案,即一個在 Red Hat OpenShift v3.7 集群上運行的項目。OpenShift 是企業級的 Kubernetes 版本,故這些實踐也適用於 K8S 集群。如果願意嘗試,可以下載 Red Hat CDK,運行 jenkins-ephemeraljenkins-persistent 模板在 OpenShift 上創建定製化好的 Jenkins 管理節點。

解決方案概述

在 OpenShift 容器中執行 CI/CD 任務(構建和測試等) 的方案基於分散式 Jenkins 構建,具體如下:

  • 我們需要一個 Jenkins 主節點;可以運行在集群中,也可以是外部提供
  • 支持 Jenkins 特性和插件,以便已有項目仍可使用
  • 可以用 Jenkins GUI 配置、運行任務或查看任務輸出
  • 如果你願意編碼,也可以使用 Jenkins Pipeline

從技術角度來看,運行任務的動態容器是 Jenkins 代理節點。當構建啟動時,首先是一個新節點啟動,通過 Jenkins 主節點的 JNLP(5000 埠) 告知就緒狀態。在代理節點啟動並提取構建任務之前,構建任務處於排隊狀態。就像通常 Jenkins 代理伺服器那樣,構建輸出會送達主節點;不同的是,構建完成後代理節點容器會自動關閉。

不同類型的構建任務(例如 Java、 NodeJS、 Python等)對應不同的代理節點。這並不新奇,之前也是使用標籤來限制哪些代理節點可以運行指定的構建任務。啟動用於構建任務的 Jenkins 代理節點容器需要配置參數,具體如下:

  • 用於啟動容器的 Docker 鏡像
  • 資源限制
  • 環境變數
  • 掛載的卷

這裡用到的關鍵組件是 Jenkins Kubernetes 插件。該插件(通過使用一個服務賬號) 與 K8S 集群交互,可以啟動和關閉代理節點。在插件的配置管理中,多種代理節點類型表現為多種 Kubernetes pod 模板,它們通過項目標籤對應。

這些代理節點鏡像以開箱即用的方式提供(也有 CentOS7 系統的版本):

  • jenkins-slave-base-rhel7:基礎鏡像,啟動與 Jenkins 主節點連接的代理節點;其中 Java 堆大小根據容器內容設置
  • jenkins-slave-maven-rhel7:用於 Maven 和 Gradle 構建的鏡像(從基礎鏡像擴展)
  • jenkins-slave-nodejs-rhel7:包含 NodeJS4 工具的鏡像(從基礎鏡像擴展)

注意:本解決方案與 OpenShift 中的 Source-to-Image(S2I) 構建無關,雖然後者也可以用於某些特定的 CI/CD 任務。

入門學習資料

有很多不錯的博客和文檔介紹了如何在 OpenShift 上執行 Jenkins 構建。不妨從下面這些開始:

  • OpenShift Jenkins 鏡像文檔及 源代碼
  • 網路播客:基於 OpenShift 的 CI/CD
  • 外部 Jenkins 集成 劇本

閱讀這些博客和文檔有助於完整的理解本解決方案。在本文中,我們主要關注具體實踐中遇到的各類問題。

構建我的應用

作為示例項目,我們選取了包含如下構建步驟的 Java 項目:

  • 代碼源: 從一個 Git 代碼庫中獲取項目代碼
  • 使用 Maven 編譯: 依賴可從內部倉庫獲取,(不妨使用 Apache Nexus) 鏡像自外部 Maven 倉庫
  • 發布成品: 將編譯好的 JAR 上傳至內部倉庫

在 CI/CD 過程中,我們需要與 Git 和 Nexus 交互,故 Jenkins 任務需要能夠訪問這些系統。這要求參數配置和已存儲憑證可以在下列位置進行管理:

  • 在 Jenkins 中: 我們可以在 Jenkins 中添加憑證,通過 Git 插件能夠對項目添加和使用文件(使用容器不會改變操作)
  • 在 OpenShift 中: 使用 ConfigMap 和 Secret 對象,以文件或環境變數的形式附加到 Jenkins 代理容器中
  • 在高度定製化的 Docker 容器中: 鏡像是定製化的,已包含完成特定類型構建的全部特性;從一個代理鏡像進行擴展即可得到。

你可以按自己的喜好選擇一種實現方式,甚至你最終可能混用多種實現方式。下面我們採用第二種實現方式,即首選在 OpenShift 中管理參數配置。使用 Kubernetes 插件配置來定製化 Maven 代理容器,包括設置環境變數和映射文件等。

注意:對於 Kubernetes 插件 v1.0 版,由於 bug,在 UI 界面增加環境變數並不生效。可以升級插件,或(作為變通方案) 直接修改 config.xml 文件並重啟 Jenkins。

從 Git 獲取源代碼

從公共 Git 倉庫獲取源代碼很容易。但對於私有 Git 倉庫,不僅需要認證操作,客戶端還需要信任伺服器以便建立安全連接。一般而言,通過兩種協議獲取源代碼:

  • HTTPS:驗證通過用戶名/密碼完成。Git 伺服器的 SSL 證書必須被代理節點信任,這僅在證書被自建 CA 簽名時才需要特別注意。

    git clone git.mycompany.com:443/m

  • SSH:驗證通過私鑰完成。如果伺服器的公鑰指紋出現在 known_hosts 文件中,那麼該伺服器是被信任的。

    git clone ssh://git@git.mycompany.com:22/myapplication.git

對於手動操作,使用用戶名/密碼通過 HTTP 方式下載源代碼是可行的;但對於自動構建而言,SSH 是更佳的選擇。

通過 SSH 方式使用 Git

要通過 SSH 方式下載源代碼,我們需要保證代理容器與 Git 的 SSH 埠之間可以建立 SSH 連接。首先,我們需要創建一個私鑰-公鑰對。使用如下命令生成:

ssh keygen -t rsa -b 2048 -f my-git-ssh -N

命令生成的私鑰位於 my-git-ssh 文件中(口令為空),對應的公鑰位於 my-git-ssh.pub 文件中。將公鑰添加至 Git 伺服器的對應用戶下(推薦使用「服務賬號」);網頁界面一般支持公鑰上傳。為建立 SSH 連接,我們還需要在代理容器上配置兩個文件:

  • 私鑰文件位於 ~/.ssh/id_rsa
  • 伺服器的公鑰位於 ~/.ssh/known_hosts。要實現這一點,運行 ssh git.mycompany.com 並接受伺服器指紋,系統會在 ~/.ssh/known_hosts 文件中增加一行。這樣需求得到了滿足。

id_rsa 對應的私鑰和 known_hosts 對應的公鑰保存到一個 OpenShift 的 secret(或 ConfigMap) 對象中。

apiVersion: v1kind: Secretmetadata: name: mygit-sshstringData: id_rsa: |- -----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY----- known_hosts: |- git.mycompany.com ecdsa-sha2-nistp256 AAA...

在 Kubernetes 插件中將 secret 對象配置為卷,掛載到 /home/jenkins/.ssh/,供 Maven pod 使用。secret 中的每個對象對應掛載目錄的一個文件,文件名與 key 名稱相符。我們可以使用 UI(管理 Jenkins / 配置 / 雲 / Kubernetes),也可以直接編輯 Jenkins 配置文件 /var/lib/jenkins/config.xml

<org.csanchez.jenkins.plugins.kubernetes.PodTemplate><name>maven</name>... <volumes> <org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume> <mountPath>/home/jenkins/.ssh</mountPath> <secretName>mygit-ssh</secretName> </org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume> </volumes>

此時,在代理節點上運行的任務應該可以通過 SSH 方式從 Git 代碼庫獲取源代碼。

註:我們也可以在 ~/.ssh/config 文件中自定義 SSH 連接。例如,如果你不想處理 known_hosts 或私鑰位於其它掛載目錄中:

Host git.mycompany.com StrictHostKeyChecking no IdentityFile /home/jenkins/.config/git-secret/ssh-privatekey

通過 HTTP 方式使用 Git

如果你選擇使用 HTTP 方式下載,在指定的 Git-credential-store 文件中添加用戶名/密碼:

  • 例如,在一個 OpenShift secret 對象中增加 /home/jenkins/.config/git-secret/credentials文件對應,其中每個站點對應文件中的一行:

    username:password@git.mycompany.com

    user:pass@github.com

  • 在 git-config 配置中啟用該文件,其中配置文件默認路徑為 /home/jenkins/.config/git/config

    [credential]

    helper = store --file=/home/jenkins/.config/git-secret/credentials

如果 Git 服務使用了自有 CA 簽名的證書,為代理容器設置環境變數 GIT_SSL_NO_VERIFY=true 是最便捷的方式。更恰當的解決方案包括如下兩步:

  • 利用 ConfigMap 將自有 CA 的公鑰映射到一個路徑下的文件中,例如 /usr/ca/myTrustedCA.pem)。
  • 通過環境變數 GIT_SSL_CAINFO=/usr/ca/myTrustedCA.pem 或上面提到的 git-config 文件的方式,將證書路徑告知 Git。

    [http "git.mycompany.com"]

    sslCAInfo = /usr/ca/myTrustedCA.pem

註:在 OpenShift v3.7 及早期版本中,ConfigMap 及 secret 的掛載點之間不能相互覆蓋,故我們不能同時映射 /home/jenkins/home/jenkins/dir。因此,上面的代碼中並沒有使用常見的文件路徑。預計 OpenShift v3.9 版本會修復這個問題。

Maven

要完成 Maven 構建,一般需要完成如下兩步:

  • 建立一個社區 Maven 庫(例如 Apache Nexus),充當外部庫的代理。將其當作鏡像使用。
  • 這個內部庫可能提供 HTTPS 服務,其中使用自建 CA 簽名的證書。

對於容器中運行構建的實踐而言,使用內部 Maven 庫是非常關鍵的,因為容器啟動後並沒有本地庫或緩存,這導致每次構建時 Maven 都下載全部的 Jar 文件。在本地網路使用內部代理庫下載明顯快於從網際網路下載。

Maven Jenkins 代理鏡像允許配置環境變數,指定代理的 URL。在 Kubernetes 插件的容器模板中設置如下:

MAVEN_MIRROR_URL=https://nexus.mycompany.com/repository/maven-public

構建好的成品(JAR) 也應該保存到庫中,可以是上面提到的用於提供依賴的鏡像庫,也可以是其它庫。Maven 完成 deploy 操作需要在 pom.xml 的分發管理 下配置庫 URL,這與代理鏡像無關。

<project ...><distributionManagement> <snapshotRepository> <id>mynexus</id> <url>https://nexus.mycompany.com/repository/maven-snapshots/</url> </snapshotRepository> <repository> <id>mynexus</id> <url>https://nexus.mycompany.com/repository/maven-releases/</url> </repository></distributionManagement>

上傳成品可能涉及認證。在這種情況下,在 settings.xml 中配置的用戶名/密碼要與 pom.xml 文件中的對應的伺服器 id 下的設置匹配。我們可以使用 OpenShift secret 將包含 URL、用戶名和密碼的完整 settings.xml 映射到 Maven Jenkins 代理容器中。另外,也可以使用環境變數。具體如下:

  • 利用 secret 為容器添加環境變數:

    MAVEN_SERVER_USERNAME=admin

    MAVEN_SERVER_PASSWORD=admin123

  • 利用 config map 將 settings.xml 掛載至 /home/jenkins/.m2/settings.xml

    <settings ...>

    <mirrors>

    <mirror>

    <mirrorOf>external:*</mirrorOf>

    <url>${env.MAVEN_MIRROR_URL}</url>

    <id>mirror</id>

    </mirror>

    </mirrors>

    <servers>

    <server>

    <id>mynexus</id>

    <username>${env.MAVEN_SERVER_USERNAME}</username>

    <password>${env.MAVEN_SERVER_PASSWORD}</password>

    </server>

    </servers>

    </settings>

禁用交互模式(即,使用批處理模式) 可以忽略下載日誌,一種方式是在 Maven 命令中增加 -B 參數,另一種方式是在 settings.xml 配置文件中增加 <interactiveMode>false</interactiveMode> 配置。

如果 Maven 庫的 HTTPS 服務使用自建 CA 簽名的證書,我們需要使用 keytool 工具創建一個將 CA 公鑰添加至信任列表的 Java KeyStore。在 OpenShift 中使用 ConfigMap 將這個 Keystore 上傳。使用 oc 命令基於文件創建一個 ConfigMap:

oc create configmap maven-settings?--from-file=settings.xml=settings.xml?--from-file=myTruststore.jks=myTruststore.jks

將這個 ConfigMap 掛載至 Jenkins 代理容器。在本例中我們使用 /home/jenkins/.m2 目錄,但這僅僅是因為配置文件 settings.xml 也對應這個 ConfigMap。KeyStore 可以放置在任意路徑下。

接著在容器環境變數 MAVEN_OPTS 中設置 Java 參數,以便讓 Maven 對應的 Java 進程使用該文件:

MAVEN_OPTS=-Djavax.net.ssl.trustStore=/home/jenkins/.m2/myTruststore.jks-Djavax.net.ssl.trustStorePassword=changeit

內存使用量

這可能是最重要的一部分設置,如果沒有正確的設置最大內存,我們會遇到間歇性構建失敗,雖然每個組件都似乎工作正常。

如果沒有在 Java 命令行中設置堆大小,在容器中運行 Java 可能導致高內存使用量的報錯。JVM 可以利用全部的宿主機內存,而不是使用容器內存現在並相應設置默認的堆大小。這通常會超過容器的內存資源總額,故當 Java 進程為堆分配過多內存時,OpenShift 會直接殺掉容器。

雖然 jenkins-slave-base 鏡像包含一個內建腳本設置堆最大為容器內存的一半(可以通過環境變數 CONTAINER_HEAP_PERCENT=0.50 修改),但這隻適用於 Jenkins 代理節點中的 Java 進程。在 Maven 構建中,還有其它重要的 Java 進程運行:

  • mvn 命令本身就是一個 Java 工具。
  • Maven Surefire 插件 默認派生一個 JVM 用於運行單元測試。

總結一下,容器中同時運行著三個重要的 Java 進程,預估內存使用量以避免 pod 被誤殺是很重要的。每個進程都有不同的方式設置 JVM 參數:

  • 我們在上面提到了 Jenkins 代理容器堆最大值的計算方法,但我們顯然不應該讓代理容器使用如此大的堆,畢竟還有兩個 JVM 需要使用內存。對於 Jenkins 代理容器,可以設置 JAVA_OPTS
  • mvn 工具被 Jenkins 任務調用。設置 MAVEN_OPTS 可以用於自定義這類 Java 進程。
  • Maven surefire 插件滋生的用於單元測試的 JVM 可以通過 Maven argLine 屬性自定義。可以在 pom.xmlsettings.xml 的某個配置文件中設置,也可以直接在 maven 命令參數 MAVEN_OPS 中增加 -DargLine=…

下面例子給出 Maven 代理容器環境變數設置方法:

JAVA_OPTS=-Xms64m -Xmx64mMAVEN_OPTS=-Xms128m -Xmx128m -DargLine=${env.SUREFIRE_OPTS}SUREFIRE_OPTS=-Xms256m -Xmx256m

我們的測試環境是具有 1024Mi 內存限額的代理容器,使用上述參數可以正常構建一個 SpringBoot 應用並進行單元測試。測試環境使用的資源相對較小,對於複雜的 Maven 項目和對應的單元測試,我們需要更大的堆大小及更大的容器內存限額。

註:Java8 進程的實際內存使用量包括「堆大小 + 元數據 + 堆外內存」,因此內存使用量會明顯高於設置的最大堆大小。在我們上面的測試環境中,三個 Java 進程使用了超過 900Mi 的內存。可以在容器內查看進程的 RSS 內存使用情況,命令如下:ps -e -o pid,user,rss,comm,args

Jenkins 代理鏡像同時安裝了 JDK 64 位和 32 位版本。對於 mvnsurefire,默認使用 64 位版本 JVM。為減低內存使用量,只要 -Xmx 不超過 1.5 GB,強制使用 32 位 JVM 都是有意義的。

JAVA_HOME=/usr/lib/jvm/Java-1.8.0-openjdk-1.8.0.161–0.b14.el7_4.i386

注意到我們可以在 JAVA_TOOL_OPTIONS 環境變數中設置 Java 參數,每個 JVM 啟動時都會讀取該參數。JAVA_OPTSMAVEN_OPTS 中的參數會覆蓋 JAVA_TOOL_OPTIONS 中的對應值,故我們可以不使用 argLine,實現對 Java 進程同樣的堆配置:

JAVA_OPTS=-Xms64m -Xmx64mMAVEN_OPTS=-Xms128m -Xmx128mJAVA_TOOL_OPTIONS=-Xms256m -Xmx256m

但缺點是每個 JVM 的日誌中都會顯示 Picked up JAVA_TOOL_OPTIONS:,這可能讓人感到迷惑。

Jenkins 流水線

完成上述配置,我們應該已經可以完成一次成功的構建。我們可以獲取源代碼,下載依賴,運行單元測試並將成品上傳到我們的庫中。我們可以通過創建一個 Jenkins 流水線項目來完成上述操作。

pipeline { /* Which container to bring up for the build. Pick one of the templates configured in Kubernetes plugin. */ agent { label maven } stages { stage(Pull Source) { steps { git url: ssh://git@git.mycompany.com:22/myapplication.git, branch: master } } stage(Unit Tests) { steps { sh mvn test } } stage(Deploy to Nexus) { steps { sh mvn deploy -DskipTests } } }}

當然,對應真實項目,CI/CD 流水線不僅僅完成 Maven 構建,還可以部署到開發環境,運行集成測試,提升至更接近於生產的環境等。上面給出的學習資料中有執行這些操作的案例。

多容器

一個 pod 可以運行多個容器,每個容器有單獨的資源限制。這些容器共享網路介面,故我們可以從 localhost 訪問已啟動的服務,但我們需要考慮埠衝突的問題。在一個 Kubernetes pod 模板中,每個容器的環境變數是單獨設置的,但掛載的卷是統一的。

當一個外部服務需要單元測試且嵌入式方案無法工作(例如,資料庫、消息中間件等) 時,可以啟動多個容器。在這種情況下,第二個容器會隨著 Jenkins 代理容器啟停。

查看 Jenkins config.xml 片段,其中我們啟動了一個輔助的 httpbin 服務用於 Maven 構建:

<org.csanchez.jenkins.plugins.kubernetes.PodTemplate> <name>maven</name> <volumes> ... </volumes> <containers> <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate> <name>jnlp</name> <image>registry.access.redhat.com/openshift3/jenkins-slave-maven-rhel7:v3.7</image> <resourceLimitCpu>500m</resourceLimitCpu> <resourceLimitMemory>1024Mi</resourceLimitMemory> <envVars> ... </envVars> ... </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate> <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate> <name>httpbin</name> <image>citizenstig/httpbin</image> <resourceLimitCpu></resourceLimitCpu> <resourceLimitMemory>256Mi</resourceLimitMemory> <envVars/> ... </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate> </containers> <envVars/></org.csanchez.jenkins.plugins.kubernetes.PodTemplate>

總結

作為總結,我們查看上面已描述配置的 Jenkins config.xml 對應創建的 OpenShift 資源以及 Kubernetes 插件的配置。

apiVersion: v1kind: Listmetadata: {}items:- apiVersion: v1 kind: ConfigMap metadata: name: git-config data: config: | [credential] helper = store --file=/home/jenkins/.config/git-secret/credentials [http "http://git.mycompany.com"] sslCAInfo = /home/jenkins/.config/git/myTrustedCA.pem myTrustedCA.pem: |- -----BEGIN CERTIFICATE----- MIIDVzCCAj+gAwIBAgIJAN0sC... -----END CERTIFICATE------ apiVersion: v1 kind: Secret metadata: name: git-secret stringData: ssh-privatekey: |- -----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY----- credentials: |- https://username:password@git.mycompany.com https://user:pass@github.com- apiVersion: v1 kind: ConfigMap metadata: name: git-ssh data: config: |- Host git.mycompany.com StrictHostKeyChecking yes IdentityFile /home/jenkins/.config/git-secret/ssh-privatekey known_hosts: [git.mycompany.com]:22 ecdsa-sha2-nistp256 AAAdn7...- apiVersion: v1 kind: Secret metadata: name: maven-secret stringData: username: admin password: admin123

基於文件創建另一個 ConfigMap:

oc create configmap maven-settings --from-file=settings.xml=settings.xml --from-file=myTruststore.jks=myTruststore.jks

Kubernetes 插件配置如下:

<?xml version=1.0 encoding=UTF-8?><hudson>... <clouds> <org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud plugin="kubernetes@1.0"> <name>openshift</name> <defaultsProviderTemplate></defaultsProviderTemplate> <templates> <org.csanchez.jenkins.plugins.kubernetes.PodTemplate> <inheritFrom></inheritFrom> <name>maven</name> <namespace></namespace> <privileged>false</privileged> <alwaysPullImage>false</alwaysPullImage> <instanceCap>2147483647</instanceCap> <slaveConnectTimeout>100</slaveConnectTimeout> <idleMinutes>0</idleMinutes> <label>maven</label> <serviceAccount>jenkins37</serviceAccount> <nodeSelector></nodeSelector> <nodeUsageMode>NORMAL</nodeUsageMode> <customWorkspaceVolumeEnabled>false</customWorkspaceVolumeEnabled> <workspaceVolume class="org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume"> <memory>false</memory> </workspaceVolume> <volumes> <org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume> <mountPath>/home/jenkins/.config/git-secret</mountPath> <secretName>git-secret</secretName> </org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume> <org.csanchez.jenkins.plugins.kubernetes.volumes.ConfigMapVolume> <mountPath>/home/jenkins/.ssh</mountPath> <configMapName>git-ssh</configMapName> </org.csanchez.jenkins.plugins.kubernetes.volumes.ConfigMapVolume> <org.csanchez.jenkins.plugins.kubernetes.volumes.ConfigMapVolume> <mountPath>/home/jenkins/.config/git</mountPath> <configMapName>git-config</configMapName> </org.csanchez.jenkins.plugins.kubernetes.volumes.ConfigMapVolume> <org.csanchez.jenkins.plugins.kubernetes.volumes.ConfigMapVolume> <mountPath>/home/jenkins/.m2</mountPath> <configMapName>maven-settings</configMapName> </org.csanchez.jenkins.plugins.kubernetes.volumes.ConfigMapVolume> </volumes> <containers> <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate> <name>jnlp</name> <image>registry.access.redhat.com/openshift3/jenkins-slave-maven-rhel7:v3.7</image> <privileged>false</privileged> <alwaysPullImage>false</alwaysPullImage> <workingDir>/tmp</workingDir> <command></command> <args>${computer.jnlpmac} ${computer.name}</args> <ttyEnabled>false</ttyEnabled> <resourceRequestCpu>500m</resourceRequestCpu> <resourceRequestMemory>1024Mi</resourceRequestMemory> <resourceLimitCpu>500m</resourceLimitCpu> <resourceLimitMemory>1024Mi</resourceLimitMemory> <envVars> <org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar> <key>JAVA_HOME</key> <value>/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.161-0.b14.el7_4.i386</value> </org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar> <org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar> <key>JAVA_OPTS</key> <value>-Xms64m -Xmx64m</value> </org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar> <org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar> <key>MAVEN_OPTS</key> <value>-Xms128m -Xmx128m -DargLine=${env.SUREFIRE_OPTS} -Djavax.net.ssl.trustStore=/home/jenkins/.m2/myTruststore.jks -Djavax.net.ssl.trustStorePassword=changeit</value> </org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar> <org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar> <key>SUREFIRE_OPTS</key> <value>-Xms256m -Xmx256m</value> </org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar> <org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar> <key>MAVEN_MIRROR_URL</key> <value>https://nexus.mycompany.com/repository/maven-public</value> </org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar> <org.csanchez.jenkins.plugins.kubernetes.model.SecretEnvVar> <key>MAVEN_SERVER_USERNAME</key> <secretName>maven-secret</secretName> <secretKey>username</secretKey> </org.csanchez.jenkins.plugins.kubernetes.model.SecretEnvVar> <org.csanchez.jenkins.plugins.kubernetes.model.SecretEnvVar> <key>MAVEN_SERVER_PASSWORD</key> <secretName>maven-secret</secretName> <secretKey>password</secretKey> </org.csanchez.jenkins.plugins.kubernetes.model.SecretEnvVar> </envVars> <ports/> <livenessProbe> <execArgs></execArgs> <timeoutSeconds>0</timeoutSeconds> <initialDelaySeconds>0</initialDelaySeconds> <failureThreshold>0</failureThreshold> <periodSeconds>0</periodSeconds> <successThreshold>0</successThreshold> </livenessProbe> </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate> <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate> <name>httpbin</name> <image>citizenstig/httpbin</image> <privileged>false</privileged> <alwaysPullImage>false</alwaysPullImage> <workingDir></workingDir> <command>/run.sh</command> <args></args> <ttyEnabled>false</ttyEnabled> <resourceRequestCpu></resourceRequestCpu> <resourceRequestMemory>256Mi</resourceRequestMemory> <resourceLimitCpu></resourceLimitCpu> <resourceLimitMemory>256Mi</resourceLimitMemory> <envVars/> <ports/> <livenessProbe> <execArgs></execArgs> <timeoutSeconds>0</timeoutSeconds> <initialDelaySeconds>0</initialDelaySeconds> <failureThreshold>0</failureThreshold> <periodSeconds>0</periodSeconds> <successThreshold>0</successThreshold> </livenessProbe> </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate> </containers> <envVars/> <annotations/> <imagePullSecrets/> </org.csanchez.jenkins.plugins.kubernetes.PodTemplate> </templates> <serverUrl>https://172.30.0.1:443</serverUrl> <serverCertificate>-----BEGIN CERTIFICATE-----MIIC6jCC...-----END CERTIFICATE-----</serverCertificate> <skipTlsVerify>false</skipTlsVerify> <namespace>first</namespace> <jenkinsUrl>http://jenkins.cicd.svc:80</jenkinsUrl> <jenkinsTunnel>jenkins-jnlp.cicd.svc:50000</jenkinsTunnel> <credentialsId>1a12dfa4-7fc5-47a7-aa17-cc56572a41c7</credentialsId> <containerCap>10</containerCap> <retentionTimeout>5</retentionTimeout> <connectTimeout>0</connectTimeout> <readTimeout>0</readTimeout> <maxRequestsPerHost>32</maxRequestsPerHost> </org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud> </clouds></hudson>

嘗試愉快的構建吧!

原文發表於 ITNext,已獲得翻版授權。


via: opensource.com/article/

作者:Balazs Szeti 選題:lujun9972 譯者:pinewall 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


推薦閱讀:

亞馬遜ECS和Kubernetes管理百萬容器的8個洞察
docker swarm mode的服務發現和LB詳解
Docker Remote API 如何使用?
Docker 重要更新: 原生支持多階段構建(multi-stage build)
將JVM運行於DOCKER上,有什麼意義嗎?或者,什麼場景下,需要把JVM運行於DOCKER上?

TAG:持續集成CI | Docker | 計算機科學 |