前言

山姆鍋最近需要安裝 Jenkins 這個持續整合軟體 , 但不打算採用過去手動的安裝模式 , 而是嘗試運用 Vagrant, Puppet 跟 Virtualbox 來做自動部署 。 持續整合軟體一般建議不要在 Master 上執行建構工作 , 所以 , 本次的實驗就以安裝一台 Master 與一台 Slave 主機為目標 。

由於之後應該陸續會有類似的實驗 , 山姆鍋將相關的程式碼放在 devops-labs 這個 GitHub 項目以方便讀者參考 。 本文主要 Puppet 的 manifests 腳本放在 recipies/jenkins-ci 這個目錄中 。 為了完整性 , 山姆鍋也將相關需要的 Puppet modules 放在這個項目中 , 這樣讀者只要 git clone 之後 , 便可以簡單以下列指令看實際執行的結果 :

$ git submodule update --init
$ cd recipes/jenkins-ci
$ vagrant up

如果執行順利 , 使用瀏覽器連到 http://192.168.33.10:8080/computer, 應該可以看到下列畫面 :

Jenkins dashboard

請注意 : 本文的設置 ,Jenkins 並沒有開啓任何安全設定 , 也就是說 , 沒有加上必要安全認證之前 , 不要在網路上使用 !

準備工作

您的測試機上需已經安裝有下列軟體 :

  1. Git
  2. Vagrant 1.1+
  3. VirtualBox 4.1 or 4.2

注意 :Vagrant 目前不支援 VirtualBox 4.3。

本文的方法需要依賴下列 Puppet 模組 :

puppet-java 這個模組 , 跟在 「 使用 Puppet 在 Ubuntu 系統上自動安裝 Oracle JDK」 說明的差不多 , 不過改成使用 puppet-apt 來做系統套件庫管理 。

虛擬機設定

目標是要安裝兩台服務器 , 一台當作 Jenkins master, 一台當作 Jenkins slave。 Jenkins slave 會自動加入 Jenkins master 的叢集中 , 如此 ,master 就可以開始分配工作給 slave 執行 。 理想上 , 可以按照需要依照同樣的設定增加 Jenkins slave。

下面是有關服務器的 Vagrant 設定檔 :

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

    config.vm.box_url = "http://files.vagrantup.com/precise64.box"

    config.vm.define :master, primary: true do |master|
        master.vm.box = "precise64"
        #master.vm.forward_port 8080, 8080
        master.vm.network :private_network, ip: "192.168.33.10"
        master.vm.hostname = "ci-master.example.com"

        master.vm.provider :virtualbox do |vb|
            # Use VBoxManage to customize the VM. For example to change memory:
            vb.customize ["modifyvm", :id, "--memory", "512"]
        end

        master.vm.provision :puppet, :module_path => "../../modules"  do |puppet|
            puppet.manifests_path = "manifests"
            puppet.manifest_file  = "master.pp"
            puppet.facter = { 'fqdn' => master.vm.hostname }
        end
    end

    config.vm.define :slave do |slave|
        slave.vm.box = "precise64"

        slave.vm.network :private_network, ip: "192.168.33.11"
        slave.vm.hostname = "ci-slave.example.com"

        slave.vm.provider :virtualbox do |vb|
            # Use VBoxManage to customize the VM. For example to change memory:
            vb.customize ["modifyvm", :id, "--memory", "512"]
        end

        slave.vm.provision :puppet, :module_path => "../../modules"  do |puppet|
            puppet.manifests_path = "manifests"
            puppet.manifest_file  = "slave.pp"
            puppet.facter = { 'fqdn' => slave.vm.hostname }
        end
    end
end

由於 Vagrant box 內建的 Puppet 無法正確取得 'fqdn'( 主機域名 ), 需要加入 puppet.facter = { 'fqdn' => master.vm.hostname } 與 puppet.facter = { 'fqdn' => slave.vm.hostname } 來讓 Puppet 可以直接使用而不嘗試採用 facter 取得 。

網路的部分 , 使用 private network, 也就是 hostonly 模式 。 這樣虛擬機之間 , 主機與虛擬機就可以互相溝通 。

Master 的 Puppet 組態檔

下列是 Jenkins master 的組態檔內容 :

class { 'apt':
}

class { 'java':
}

class {'jenkins':
    install_java => false,
}

include jenkins::master

因為 ,Jenkins 這個 Puppet 模組預設會試圖安裝 Java 環境 , 所以 , 'install_java' 設為 false 就是讓它跳過安裝 Java 的步驟 。

Slave 的 Puppet 組態檔

跟 Jenkins master 的主要差別在於 'class {'jenkins::slave' 這個部分 , 其中也指定 Jenkins master 的為止 , 讓 Jenkins slave 可以自行向 master 註冊 。 'ui_user' 跟 'ui_pass' 目前是沒有作用的 。

class { 'apt':
}

class { 'java':
}

class { 'jenkins::slave':
    masterurl => 'http://192.168.33.10:8080',
    ui_user => 'adminuser',
    ui_pass => 'adminpass',
    install_java => false,
}

結語

希望這個配方 (recipe) 對您有些幫助 , 但就像醫師的配方一樣 , 不同人的配方或多或少不同 , 可不能隨便服用 。 同樣地 , 本文提供的配方 , 主要目的是了解如何以 Vagrant, Puppet 來進行自動部署 , 使用 Jenkins 只是希望有個比較實際的例子 。