Linux中國

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

現今,由於 DockerKubernetes(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 系統的版本):

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

入門學習資料

有很多不錯的博客和文檔介紹了如何在 OpenShift 上執行 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 https://git.mycompany.com:443/myapplication.git
  • 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: v1
kind: Secret
metadata:
  name: mygit-ssh
stringData:
  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 文件對應,其中每個站點對應文件中的一行:
https://username:password@git.mycompany.com
https://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 "https://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 -Xmx64m
MAVEN_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 -Xmx64m
MAVEN_OPTS=-Xms128m -Xmx128m
JAVA_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 &apos;maven&apos;
  }

  stages {
    stage(&apos;Pull Source&apos;) {
      steps {
        git url: &apos;ssh://git@git.mycompany.com:22/myapplication.git&apos;, branch: &apos;master&apos;
      }
    }
    stage(&apos;Unit Tests&apos;) {
      steps {
        sh &apos;mvn test&apos;
      }
    }
    stage(&apos;Deploy to Nexus&apos;) {
      steps {
        sh &apos;mvn deploy -DskipTests&apos;
      }
    }
  }
}

當然,對應真實項目,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: v1
kind: List
metadata: {}
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: &apos;[git.mycompany.com]:22 ecdsa-sha2-nistp256 AAAdn7...&apos;
- 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=&apos;1.0&apos; encoding=&apos;UTF-8&apos;?>
<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: https://opensource.com/article/18/4/running-jenkins-builds-containers

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

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


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國