顯示具有 jenkins 標籤的文章。 顯示所有文章
顯示具有 jenkins 標籤的文章。 顯示所有文章

2024年2月6日 星期二

Docker 開發筆記 - 使用 Docker Compose 架設 Jenkins 服務 @ macOS 14.2.1



過年找點樂子,用 Docker 把一些工作上常見的服務都架設一次好了 XD 整體工作上仍主要都還是 ansible 管理數百台機器,近期有同事對 docker 很感興趣,我就努力推坑,推坑前也得親自走一下是吧 :P

連續動作:

% cat docker-compose.yml 
# https://docs.docker.com/compose/compose-file/compose-versioning/
version: '3.8' 
services:
  jenkins:
    # https://hub.docker.com/_/jenkins
    image: jenkins/jenkins:lts
    # https://docs.docker.com/config/containers/start-containers-automatically/#use-a-restart-policy
    restart: unless-stopped 
    privileged: true
    user: root
    ports:
      # HOST:CONTAINER
      - 8080:8080 
    container_name: jenkins
    volumes:
      - ~/docker_jenkins_home:/var/jenkins_home

% docker-compose up 
[+] Running 1/0
 ✔ Container jenkins  Created                                                                                                                                          0.0s 
Attaching to jenkins
jenkins  | Running from: /usr/share/jenkins/jenkins.war
jenkins  | webroot: /var/jenkins_home/war
...
jenkins  | *************************************************************
jenkins  | *************************************************************
jenkins  | *************************************************************
jenkins  | 
jenkins  | Jenkins initial setup is required. An admin user has been created and a password generated.
jenkins  | Please use the following password to proceed to installation:
jenkins  | 
jenkins  | 54b6458ba37b4178bdc77f7d9eccbd0f
jenkins  | 
jenkins  | This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
jenkins  | 
jenkins  | *************************************************************
jenkins  | *************************************************************
jenkins  | *************************************************************

這時就可以到 http://localhost:8080 繼續走完 jenkins 的架設,包括也看到的啟動碼,當然,也可以搞剛用 docker exec 指令來列出:

% docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
54b6458ba37b4178bdc77f7d9eccbd0f


除此之外,在本機 ~/docker_jenkins_home 也可以看到相關結構:

% tree -L 1 ~/docker_jenkins_home
/Users/user/docker_jenkins_home
├── config.xml
├── copy_reference_file.log
├── hudson.model.UpdateCenter.xml
├── jenkins.telemetry.Correlator.xml
├── jobs
├── nodeMonitors.xml
├── nodes
├── plugins
├── secret.key
├── secret.key.not-so-secret
├── secrets
├── updates
├── userContent
├── users
└── war

9 directories, 7 files

只是剩下的就靠 http://localhost:8080 走安裝流程,收工

而原先跑 docker-compose up 的那個環境可以用 ctrl+c 來停掉,未來可以靠 docker-compose up -d 來重新啟動

^CGracefully stopping... (press Ctrl+C again to force)
[+] Stopping 1/1
 ✔ Container jenkins  Stopped                                                                                                                                          0.2s 
canceled

2016年1月22日 星期五

DevOps 筆記 - Jenkins 處理 Git Submodule Authentication/Credential 問題

已經很習慣用 Bitbucket 做 git service,然後有個 project 裡有個 sub-project 一樣有存取控管,而 Jenkins 預設只有第一層存取時,可以正確透過 Credentials 來解決,但是 submodule 就會失敗。

依照原理解法有兩招:

  1. 直接在 Jenkins 執行者的 $HOME/.ssh/ 去撰寫底層 ssh 連線認證方式
  2. 使用 Jenkins plugin - SSH Agent Plugin

為了管理維護方便,當然就用 SSH Agent Plugin 啦,安裝完後,每一個 Project 就會多一個 SSH Agent 的設定選項,只需設定好即可。

另外,有一派會建議把原先 Jenkins Project 裡的 Git Credentials 去掉,一律都用 SSH Agent Plugin 的設定,但這招會導致後續要做 Git Publisher 要做 git tag 時產生問題。

2015年11月27日 星期五

DevOps 筆記 - 使用 Jenkins、Git、RPM、Ansible、Slack 建置持續整合架構(Continuous integration)

今天終於端出一盤比較好吃的菜了,用料有點雜筆記一下吧!之前已經用 Jenkins + Git + Slack 可以做到持續發布跟通知開發者了,但面對 AWS Auto Scaling 議題還是頗抖的,因為建立 AMI (Amazon Machine Image) 後,機器的狀態被保留在某一刻,這時服務量一大自動開啟機器時,就會出現服務更新的需求。原先同事採用 Puppet 方案,但仍不適合處理 Auto Scaling 的問題,因為 Puppet 需要比較強的關係式(Server/Client認證),雖然硬做也是 ok 的,但要一直維護 Server/Client 架構還是頗累,所幸有了 Ansible 的出現!這提供比較分散式的管理架構,Server 跟 Client 都是透過 keypair + ssh remote command 溝通的。

粗略配置作法:
  • Git
    • 主要特色還是 branch 的規劃,跟公司文化有關
      • master:正式網站的狀態
      • alpha:內部最新網站狀態
      • develop:最新程式碼
    • 開發者都是從 develop branch 開發服務,當有版本要釋出時,merge 進 alpha branch 後,發佈到 alpha site 測試,妥當後再把 alpha branch merge 進 master branch
      • 概念上有點從 develop -> alpha -> master 角度
      • 若有 hotfix 時,從 master 產生 branch 修正後,在 merge 回 alpha 跟 develop
      • 在 alpha site 測試出問題時,不斷地在 alpha branch 處理,到最後才 merge 回 develop branch,以及發佈到 master branch
    • 透過 Jenkins 每一次發版時,會下 git tag 標記狀態
      • develop-version-number
      • alpha-version-number
      • production-version-number
    • 相關資料:A successful Git branching model
  • Jenkins 
    • 新增 Slack Notification Plugin/Version Number Plug-In
    • 權限設定,為了不要暴露太多專案給開發者,做了簡易的權限管控
      • 設定全域安全性
        • 安全性領域:採用 Jenkins 內建使用者資料庫 且不允許註冊
        • 授權:採用專案型矩陣授權策略
          • 每一個 task 都可以自訂可以觀看的使用者
    • 管理方面,新增工作分成 build 跟 deploy 兩種
      • build 就是把 source code 包成 RPM ,方便作業系統管理和除錯追蹤,另外,對於開發者測試機的準備也有幫助
        • 取得最新程式碼後,透過 RPMBuild 包裝起來,擺至指定位置
        • 每一次 build 都會下 git tag 標記版本狀態,方便之後除錯
        • 若封裝過程可以接觸到 git 資訊,則把 source code 最後 3 筆 commit log 拉出來製作版本資訊
          • git log -3 --pretty=format:"{\"commit\":\"%H\",\"update\":\"%ad\",\"author\":\"%an\"}"
      • deploy 就是透過 ansible 進行發佈,因此也可以把 ansible 操作用 git 管理
        • 發布過程中,第一步先到指定位置找出最新的 RPM files
        • 第二部透過 AWS EC2 API 得知待更新機器列表
        • 透過 ssh remote command 進行機器更新
        • 盡量把所有動作濃縮至 Ansible command,而透過 Jenkins Web UI 撰寫幾個指令就好 
      • 工作通知
        • 每一次 build 或 deploy 都可以透過 slack plugin 將更新訊息發佈至指定頻道通知相關開發者
      • 採用輪詢 SCM 方式,由 Jenkins 主動確認程式碼狀態,以此決定是否出 build ,不採用 git hook 等被動方式進行工作任務
        • 無法規範開發者 git push 行為,擔心 push 太多造成大量 build event
      • build 完畢後,可以設立相關專案,自動進行 deploy 任務
  • AWS
    • 透過 AIM 建立一個只有 AmazonEC2ReadOnlyAccess 權限的帳號
    • 對於需被管理的機器,都透過 Tag 標記管理
      • 使用 AWS EC2 API 來動態查詢指定的機器,以此取得機器列表,例如指定 ELB 裡所有的機器
    • 關於 Auto Scaling
      • 由於機器 IP 非固定,在不同 data center 溝通容易踩到 Security Group 限制,建議還是把服務以 data center 切開
        • 例如有美西跟日本時,若 db server 開在美西,那需要存取此 db server 的機器就擺在美西就好,這樣 Security Group 比較好做(類似限制 LAN 即可)
  • Ansible
    • 將 RPM 複製到機器上安裝,在 Ubuntu server 可偷懶用 alien :P
    • 依照腳本,進行機器的環境配置,如 limits、web server 等
    • 埋入一個 boot script ,當開機時透過 ssh remote command 向 deploy server 要求更新自己
以上使用的相關資源:
  • RPM 打包目錄專用
    • https://github.com/changyy/rpm-builder
    • 若打包目錄有 .git 時,會抓出最後幾筆 commit log 塞進 version.json 檔案內,可協助往後的偵錯
    • 由於 RPMBuild 很吃環境變數,面對 Jenkins 同時出 build 會衝到共用資源的部分,在此已經透過修改 $HOME 目錄來避開共用資源的問題,因此不用再擔心 Jenkins 一次只能出一個 build
  • AWS EC2 機器查詢
    • http://docs.ansible.com/ansible/intro_dynamic_inventory.html#example-aws-ec2-external-inventory-script
    • Jenkins 建置範例(script),只要修改 yml 檔案名稱即可:
      • develop site
        • export ANSIBLE_HOST_KEY_CHECKING=False
          export EC2_INI_PATH=$WORKSPACE/dynamic-inventory-ec2.ini
          export AWS_ACCESS_KEY_ID=XXX
          export AWS_SECRET_ACCESS_KEY=OOO
          export DEPLOY_TARGET=site-develop.yml

          ansible-playbook $WORKSPACE/$DEPLOY_TARGET -i $WORKSPACE/bin/ec2.py --private-key=$HOME/.ssh/ansible-deploy.pem
      • alpha site
        • export ANSIBLE_HOST_KEY_CHECKING=False
          export EC2_INI_PATH=$WORKSPACE/dynamic-inventory-ec2.ini
          export AWS_ACCESS_KEY_ID=XXX
          export AWS_SECRET_ACCESS_KEY=OOO
          export DEPLOY_TARGET=site-alpha.yml

          ansible-playbook $WORKSPACE/$DEPLOY_TARGET -i $WORKSPACE/bin/ec2.py --private-key=$HOME/.ssh/ansible-deploy.pem
      • production site
        • export ANSIBLE_HOST_KEY_CHECKING=False
          export EC2_INI_PATH=$WORKSPACE/dynamic-inventory-ec2.ini
          export AWS_ACCESS_KEY_ID=XXX
          export AWS_SECRET_ACCESS_KEY=OOO
          export DEPLOY_TARGET=site-production.yml

          ansible-playbook $WORKSPACE/$DEPLOY_TARGET -i $WORKSPACE/bin/ec2.py --private-key=$HOME/.ssh/ansible-deploy.pem
  • Ansible 找尋最新 package files
  • Ansible 設置自動要求更新
    • $ ansible-galaxy install changyy.self-update 
    • https://github.com/changyy/ansible-role-self-update
    • 比較雜亂一點,原理:
      • 機器部署時,建立一個 auto update script (負責通報 deploy server 更新指定 host),將此 script 埋入開機執行區( /etc/rc.local )
        • 當機器啟動時執行該 script ,把部署此機器該有的資訊以 ssh remote command 丟給 deploy server 
      • 該 ssh remote command 包含的動作
        • 登入 deploy server 並切換至 ansible workspace
        • 透過 dynamic inventory 建立動態 host 資訊
        • 執行 ansble-playbook 批次指令
      • Deploy server workspace 範例:
        • $ cat bin/echo.sh
          #!/bin/bash
          echo "{\"$HOST\":$DATA}"

          $ HOST=MySite DATA=[\"SERVER_IP\"] bash bin/echo.sh
          {"MySite":["SERVER_IP"]}

          $ cd ansible-deploy-dir && \
          ANSIBLE_HOST_KEY_CHECKING=false \
          HOST=MySite \
          DATA=[\"SERVER_IP\"] \
          ansible-playbook MySite.yml \
          -i bin/echo.sh \
          --private-key=mysite-login-key.pem

2015年11月10日 星期二

[Linux] 架設 Jenkins 筆記,以 Git plugin 與 PHP CodeIgniter - command-line interface (CLI) 定期任務為例 @ Ubuntu 14.04

架設還滿簡單的,幾行指令搞定:

$ wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
$ sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
$ sudo apt-get update
$ sudo apt-get install jenkins
$ sudo service jenkins start


如此一來,預設在 http://localhost:8080 就可以瀏覽到。

接著安裝一些工具,之後會用到:

$ sudo apt-get install git

接著紀錄一下自己的操作設定:
  • 管理 Jenkins -> 設定全域安全性
    • 勾選 Disable remember me
    • 安全性領域
      • 使用 Jenkins 內建使用者資料庫
    • 授權
      • 矩陣型安全性
        • 關閉 匿名使用者 所有權限
  • 管理 Jenkins -> 管理外掛程式
    • 更新
      • 把所有項目更新
    • 可用的
      • 搜尋 GIT plugin 跟 GIT client plugin 並安裝(若系統沒有 git,安裝完可以在 Jenkins 組態裡看到一些錯誤訊息)
其中授權那塊,必須先建立使用者,可以先從"登入成功的使用者可以做任何事"開始設定,過程會導入到建立使用者的流程。若有設定錯誤的地方導致無法管理時,可以修改 /var/lib/jenkins/config.xml 將 <useSecurity>true</useSecurity> 改成 <useSecurity>false</useSecurity> 後,再重新啟動 jenkins (sudo service jenkins restart)即可解決。

如此一來,就建立好 Jenkins 環境,而新工作也能夠用 git 了!擬個範例試試:假設專案在 bitbucket 管理,並使用 PHP CodeIgniter 架構,定期透過此專案來執行分析任務

作法:
  • Jenkins -> 新增作業 -> 填寫作業名稱(StudyJenkinsRoutine) -> 建置 Free-Style 軟體專案
    • 原始碼管理
      • Git
        • Repository URL: git@bitbucket.org:group/project.git
        • Credentials -> Add -> SSH Username with private key -> Enter directly (搭配 Bitbucket SSH 存取即可)
        • Additional Behaviours -> Advanced sub-modules behaviors -> 勾選 Recursively update submodules
    • 建置觸發程序
      • 定期建置(每十五分鐘跑一次,語法跟 crontab 一樣,但會建議用 H/15 來使用)
        • */15 * * * *  
    • 建置
      • 執行 Shell
        • php $WORKSPACE/index.php controller/function
如此一來,透過 Jenkins 的 Web 介面就可以設定與執行一些功能了,唯一留意的是執行工作上是否擁有相關的環境資源,例如範例是執行 PHP Framework 做事,那就得確保 php5-cli 裝了沒,若做的事跟資料庫相關,又得確定 php5-mysql 裝了沒等等。此外,上頭執行的 Shell 有用到 Jenkins 環境變數,要留意有些資料是跟 Jenkins 建立的工作名稱是相關的,例如工作名稱若有空白、等號以及相關的特殊符號時,極有可能會影響 shell script 的執行的。

關於 Jenkins 相關的路徑安排都跟 jenkins 帳號相關,例如 Jenkins 家目錄在 /var/lib/jenkins ,而添加一個任務名為 StudyJenkinsRoutine 時,其 $WORKSPACE 會是 /var/lib/jenkins/jobs/StudyJenkinsRoutine/workspace 的,這個位置也是 git clone 的資料所在。

最後,如果 Jenkins 是架設在 AWS EC2 上,若可以搭配 ELB 跟 SSL 憑證時,可以偷懶使用 ELB 將 https 流量導向到 Jenkins 8080 ,可以無痛提供 https 服務囉。

2015年10月20日 星期二

透過 Bitbucket、Jenkins、Slack 打造持續發佈打屁等自動化架構

透過 Bitbucket 作為 git 版本控制的服務托管處,而 slack 則是工程師打屁好去處,而 Jenkins 則是打造一鍵發佈的便利介面。雖說連續動作也可以化簡成一隻 script,但能夠端出 Web UI 介面,還是大勝!

首先提一下 git 版本控制,透過 Bitbucket 服務,人多的話還是花一點小錢了!在 Bitbucket 可以建立群組概念,大概可粗略分成 Administrators、Developer、Deploy 三個個群組(若要細分則可以變成 iOS Developer、Android Developer、Web developer 或是甚至以專案為單位等),這邊設計讓所以有成員都進 Developer 並且 Developer group 預設對所有專案擁有 read only 權限。而埋了一個機器人在 deploy group 中,預設沒有任何權限(機器人不需進入 developer group)。當有專案要搭建自動發佈流程時,請專案擁有者或管理者,讓專案可供 Deploy Group 有 write 權限,這是為了 Jenkins 發佈新版時,能夠打個 tag 記錄狀態。而 Deploy group 裡的機器人,就只需添加個 ssh key 即可。

在 Jenkins Web UI:
  1. 建立作業 => 填寫作業名稱 => 建置 Free-Style 軟體專案 
  2. 設定 Slack Notifications => 進階設定 Team Domain、Integration Token 和 Project Channel => Test Connection
  3. 原始碼管理 => git => git@bitbucket.org:group/project.git => Credentials 搭配 Bitbucket SSH key => Branches to build 要指定 => Additional Behaviours => Advanced sub-modules behaviours => Recursively update submodules
  4. 建置環境 => Create a formatted version number => 設定 Environment Variable Name (VERSION) => Version Number Format String (1.0.0) 
  5. 建置 => 例如拉完程式碼後想要做的事,如 /path/project-build.sh project-name  $VERSION $BUILD_NUMBER $JOB_NAME 
  6. 建置後動作 => Git Publisher => Push Only If Build Succeeds => Tag to push (develop-$VERSION-$BUILD_NUMBER) => Target remote name (origin)
如此一來,開發者可以用 bitbucket 持續開發,並且用不同 branch 管理,如 develop branch、alpha branch、release branch 等,而 Jenkins 就建立三個任務,分別從上述 branch 取資料出來使用,而在 "建置" 跟 "建置後動作" 都可以對各個 branch 操作做細部的調整。

例如"建置"中的 /path/project-build.sh 的程式,就可以包含建立 RPM 、更新 repos 等行為,同時有環境變數 $VERSION $BUILD_NUMBER $JOB_NAME 拿來輔助。

以上就是將程式碼編譯打包的流程,若要再添加上 deploy 流程時,可以再額外建置一個 Jenkins 工作,裡頭只需填寫 slack 通知和建置項目,而建置項目就可以一隻 script 處理發佈的動作即可,而在相對應工作中,把剛剛的 deploy task 建立相依性即可。

如此一來,當 Jenkins 每一次建置時,各個階段的都丟訊息至 slack 指定的頻道,等同通知相關人員。若需要做類似 git hook 來達成自動建置時,可以使用 Jenkins "建置觸發程式" 裡的輪詢  SCM 項目,例如每 10 分鐘確認一次 bitbucket 專案狀況等,達成類似 git hook 行為。