Ansible 的自動化能力簡化了 Jenkins 伺服器的組態與管理,尤其在需要頻繁調整或擴充套件 CI/CD 流程的環境中更顯優勢。本文提供的 Ansible Playbook 涵蓋了 Jenkins 伺服器的完整生命週期管理,從容器化佈署、組態檔案管理、外掛程式安裝到 Job 建立,都可透過 Ansible 進行自動化操作。此方法不僅減少了手動操作的錯誤率,也提升了組態效率,讓開發團隊更專注於軟體開發本身。此外,透過 Docker 容器化佈署 Jenkins,更確保了環境的一致性,方便跨平台佈署和管理。
Jenkins:持續整合與交付的強大工具
Jenkins作為一個領先的CI/CD工具,經歷了多次演進,至今已發展到第三代。第三代Jenkins引入了Jenkins Workflow和Jenkinsfile,結合了前兩代的優點,並帶來了更多創新。
Jenkins Workflow與Jenkinsfile的革新
Jenkins Workflow允許使用根據Groovy的DSL(Domain-Specific Language)編寫整個Pipeline(pipeline)。這使得流程可以被寫成一個單一的指令碼,充分利用現有的Jenkins功能。相較於傳統的Jenkins作業定義(XML格式),Workflow指令碼大大減少了程式碼量和作業數量,從而簡化了管理和維護。同時,Jenkinsfile的引入使得開發者可以在程式碼倉函式庫中定義Workflow指令碼,從而更好地控制CI/CDPipeline。這樣一來,責任劃分更加明確:整體Jenkins管理集中化,而個別CI/CDPipeline則與程式碼存放在一起。此外,結合Multibranch Workflow作業型別,可以根據分支對Pipeline進行微調。例如,可以在master分支中定義完整的流程,而在每個feature分支中使用較短的流程。Jenkins會根據分支的建立和刪除自動建立和刪除作業。
Docker Workflow的整合
Docker Workflow的引入使Docker成為Jenkins中的一等公民。這進一步增強了Jenkins在CI/CD領域的領先地位。如果需要更多功能,可以考慮使用CloudBees Jenkins Platform - Enterprise Edition,它提供了出色的功能,特別是在需要大規模執行Jenkins時。
Jenkins的外掛生態系統
Jenkins的強大之處在於其豐富的外掛生態系統。幾乎可以找到滿足任何需求的外掛,從連線到程式碼倉函式庫到向Slack傳送通知,甚至使用自定義公式解析日誌。然而,這種豐富性也是一把雙刃劍。使用者可能會安裝過多的外掛,導致不必要的複雜性。例如,可以使用Ansible外掛作為構建步驟,並填寫相關欄位,如Playbook路徑、Inventory、要跳過的Tags等。但是,一種替代方法是使用Execute Shell構建步驟,直接執行Ansible命令。這樣可以減少需要填寫或忽略的欄位,並且可以使用相同的命令作為參考,以便在Jenkins外部重複相同的過程。
使用指令碼進行自動化
在許多情況下,自動化應該在Jenkins(或任何其他CI/CD工具)外部進行。然後,只需告訴Jenkins要執行的指令碼即可。該指令碼可以儲存在與服務程式碼相同的倉函式庫中(例如deploy.sh),或者透過一些命名約定進行概括並用於所有服務。無論自動化指令碼如何組織,在大多數情況下,在Jenkins中執行與這些指令碼相關的命令是最簡單、最有效的方法。現在,隨著Jenkinsfile的加入,我們可以在專案倉函式庫中保留專案特定的指令碼,並利用Jenkins特定的功能,如在特定節點上執行某些操作,或使用儲存在Jenkins中的身份驗證資訊。
設定Jenkins
首先,我們將建立虛擬機器來探索Jenkins。我們將建立cd節點來託管我們的Jenkins伺服器,以及將透過它執行的Ansible playbooks。
內容解密:
vagrant up cd prod:啟動名為cd和prod的虛擬機器,用於後續的Jenkins安裝和Ansible playbook執行。vagrant ssh cd:透過SSH連線到cd虛擬機器,以便進行後續操作。ansible-playbook /vagrant/ansible/prod2.yml -i /vagrant/ansible/hosts/prod:執行Ansible playbook來組態prod節點。sudo mkdir -p /data/jenkins:建立用於持久化Jenkins資料的目錄。sudo chmod 0777 /data/jenkins:設定目錄許可權,以允許Jenkins容器存取。docker run -d --name jenkins -p 8080:8080 -v /data/jenkins:/var/jenkins_home -v /vagrant/.vagrant/machines:/machines jenkins:使用Docker執行Jenkins容器,將主機的8080埠對映到容器的8080埠,並掛載資料卷以持久化Jenkins組態和作業資料。
此圖示說明瞭 Ansible plugin 在 Jenkins 中的使用方式
內容解密:
此圖示展示瞭如何在Jenkins中使用Ansible外掛來執行Ansible Playbook。主要步驟包括組態Playbook路徑和Inventory,然後執行Ansible Playbook。
使用Ansible自動化Jenkins設定
在前面的章節中,我們已經探討瞭如何使用Docker安裝和執行Jenkins。現在,我們將探討如何使用Ansible自動化Jenkins的安裝和設定。
為什麼需要自動化Jenkins?
大多數人使用Jenkins都是透過其圖形使用者介面(GUI)進行操作。雖然GUI非常直觀,但隨著工作數量和複雜度的增加,透過GUI進行管理和維護變得越來越困難。例如,如果我們想要為所有工作新增Slack通知,逐一修改每個工作是不現實的。
自動化Jenkins的方法
有多種方法可以實作Jenkins的自動化。我們可以使用一些Jenkins外掛,如Job DSL和Job Generator外掛。然而,在這裡,我們將採用不同的方法。由於Jenkins的所有設定都儲存在/var/jenkins_home目錄下的XML檔案中,我們可以直接修改這些檔案來改變Jenkins的行為。由於我們已經熟悉Ansible,我們將繼續使用它來安裝和維護Jenkins。
移除現有的Jenkins安裝
首先,我們需要移除現有的Jenkins容器和相關的目錄。
docker rm -f jenkins
sudo rm -rf /data/jenkins
使用Ansible設定Jenkins
使用Ansible設定Jenkins相對簡單。我們將使用jenkins-node.yml和jenkins.yml兩個playbook來完成這項工作。
首先,執行以下命令來設定Jenkins節點和Jenkins本身。
ansible-playbook /vagrant/ansible/jenkins-node.yml \
-i /vagrant/ansible/hosts/prod
ansible-playbook /vagrant/ansible/jenkins.yml \
-c local
jenkins-node.yml playbook
這個playbook負責設定Jenkins節點。它確保JDK已經安裝,並且建立了/data/jenkins_slaves目錄。
jenkins.yml playbook
這個playbook負責安裝和設定Jenkins。下面是jenkins.yml的內容。
- hosts: localhost
remote_user: vagrant
serial: 1
sudo: yes
roles:
- consul-template
- jenkins
這個playbook安裝了Consul Template和Jenkins。主要的任務定義在roles/jenkins/tasks/main.yml檔案中。
roles/jenkins/tasks/main.yml
這個檔案定義了設定Jenkins所需的任務。
1. 建立必要的目錄
第一個任務是建立必要的目錄。
- name: Directories are created
file:
path: "{{ item.dir }}"
mode: 0777
recurse: yes
state: directory
with_items: configs
tags: [jenkins]
2. 執行Jenkins容器
接下來的任務是執行Jenkins容器。
#### 內容解密:
此任務使用Docker模組執行Jenkins容器。由於容器的啟動速度很快,但Jenkins本身需要一些時間才能完全執行,因此我們註冊了一個變數`container_result`,並在稍後暫停playbook的執行,以確保Jenkins已經完全執行。
```yml
- name: Run Jenkins container
docker_container:
name: jenkins
image: jenkins/jenkins:lts
ports:
- "8080:8080"
volumes:
- /data/jenkins:/var/jenkins_home
register: container_result
3. 等待Jenkins完全執行
為了確保Jenkins已經完全執行,我們暫停playbook的執行。
- name: Pause playbook execution
pause:
seconds: 30
when: container_result.changed
內容解密:
此任務暫停playbook的執行30秒,以確保Jenkins已經完全執行。只有在container_result發生變化時才會執行此任務。
此圖示展示了使用Ansible自動化Jenkins設定的流程
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Ansible自動化Jenkins持續整合佈署
package "Docker 架構" {
actor "開發者" as dev
package "Docker Engine" {
component [Docker Daemon] as daemon
component [Docker CLI] as cli
component [REST API] as api
}
package "容器運行時" {
component [containerd] as containerd
component [runc] as runc
}
package "儲存" {
database [Images] as images
database [Volumes] as volumes
database [Networks] as networks
}
cloud "Registry" as registry
}
dev --> cli : 命令操作
cli --> api : API 呼叫
api --> daemon : 處理請求
daemon --> containerd : 容器管理
containerd --> runc : 執行容器
daemon --> images : 映像檔管理
daemon --> registry : 拉取/推送
daemon --> volumes : 資料持久化
daemon --> networks : 網路配置
@enduml
內容解密:
此圖示展示了使用Ansible自動化Jenkins設定的流程。首先,移除現有的Jenkins安裝。然後,執行jenkins-node.yml和jenkins.yml兩個playbook。接下來,建立必要的目錄,執行Jenkins容器,並等待Jenkins完全執行。最後,完成整個流程。
持續整合(CI)、交付與佈署(CD)工具的 Ansible 自動化組態
在現代化的軟體開發流程中,持續整合(CI)和持續交付/佈署(CD)扮演著至關重要的角色。透過自動化工具的輔助,開發團隊能夠更高效地進行程式碼整合、測試和佈署,從而加快軟體的交付速度並提高品質。本文將探討如何使用 Ansible 自動化組態 Jenkins 伺服器,以實作 CI/CD 流程的自動化。
Jenkins 伺服器的容器化佈署
首先,我們使用 Docker 容器來佈署 Jenkins 伺服器。透過以下 Ansible playbook,我們可以輕鬆地啟動一個 Jenkins 容器並對映必要的埠和卷。
- name: Container is running
docker:
name: jenkins
image: jenkins
ports: 8080:8080
volumes:
- /data/jenkins:/var/jenkins_home
- /vagrant/.vagrant/machines:/machines
register: container_result
tags: [jenkins]
- pause: seconds=30
when: container_result|changed
tags: [jenkins]
內容解密:
docker模組:用於管理 Docker 容器。在這裡,我們指定了容器的名稱為jenkins,使用的映象也是jenkins,並將主機的 8080 埠對映到容器的 8080 埠。同時,我們掛載了兩個卷,分別用於持久化 Jenkins 的主目錄和存取 Vagrant 虛擬機器的相關資訊。register:將任務的執行結果註冊到變數container_result中,以便後續任務根據此結果進行條件判斷。pause模組:讓 Ansible 暫停執行 30 秒,確保 Jenkins 容器有足夠的時間啟動。當container_result發生變化時(即容器被建立或重新啟動),這個任務才會執行。
組態檔案的佈署
接下來,我們需要將一些組態檔案複製到 Jenkins 容器中,例如憑證檔案 (credentials.xml) 和一些節點組態檔案 (cd_config.xml, prod_config.xml 等)。這些檔案對於 Jenkins 的正常執行至關重要。
- name: Configurations are present
copy:
src: "{{ item.src }}"
dest: "{{ item.dir }}/{{ item.file }}"
mode: 0777
with_items: configs
register: configs_result
tags: [jenkins]
內容解密:
copy模組:用於將檔案從控制節點複製到受控節點(此處指 Jenkins 容器)。透過迴圈變數configs,我們可以批次複製多個組態檔案。with_items:迴圈遍歷configs列表中的每個專案,並執行複製操作。register:將任務結果註冊到configs_result,以便後續任務根據組態檔案的變化情況進行相應操作。
Jenkins 外掛程式的安裝
為了使 Jenkins 支援 Git 操作和日誌解析等功能,我們需要安裝一些必要的外掛程式。與直接下載外掛程式不同,我們採用了透過傳送 HTTP 請求到 Jenkins 的 /pluginManager/installNecessaryPlugins 介面來安裝外掛程式及其依賴項的方法。
- name: Plugins are installed
shell: "curl -X POST \
-d '<jenkins><install plugin=\"{{ item }}@latest\" /></jenkins>' \
--header 'Content-Type: text/xml' \
http://{{ ip }}:8080/pluginManager/installNecessaryPlugins"
args:
creates: /data/jenkins/plugins/{{ item }}
with_items: plugins
register: plugins_result
tags: [jenkins]
內容解密:
shell模組:執行 shell 命令,在這裡我們使用curl傳送 POST 請求到 Jenkins 的外掛程式安裝介面,請求體中包含了需要安裝的外掛程式名稱。args:指定了creates引數,用於檢查指定的外掛程式目錄是否存在。如果存在,則跳過該任務,避免重複安裝。with_items:遍歷plugins列表,批次安裝所需的外掛程式。
Jenkins Job 的建立與過載
最後,我們使用 Ansible 的 template 模組來建立 Jenkins Job。透過定義一個範本,我們可以為多個服務建立相似的 Job 組態,從而簡化了 Job 的建立和管理過程。
- name: Job directories are present
file:
path: "{{ home }}/jobs/{{ item.name }}"
state: directory
mode: 0777
with_items: jobs
tags: [jenkins]
- name: Jobs are present
template:
src: "{{ item.src }}"
dest: "{{ home }}/jobs/{{ item.name }}/config.xml"
mode: 0777
with_items: jobs
register: jobs_result
tags: [jenkins]
- name: Jenkins is reloaded
uri:
url: http://{{ ip }}:8080/reload
method: POST
status_code: 200,302
when: jobs_result|changed
ignore_errors: yes
tags: [jenkins]
內容解密:
file模組:為每個 Job 建立一個目錄,用於存放 Job 的組態檔案。template模組:根據範本生成 Job 的組態檔案 (config.xml)。透過替換範本中的變數,可以為不同的服務生成特定的 Job 組態。uri模組:當 Job 組態發生變化時,傳送過載請求到 Jenkins,使新的 Job 組態生效。