はじめに
- Jenkinsサーバから、成果物やその他ファイルをリモートホストへ転送する方法を紹介します
- Jenkins PipelineとAnsibleを組み合わせたらシンプルに実装ができました
経緯
- 今まで以下の組み合わせでやっていてイケてなさすぎたので、最近のイケてるツールで実装してみたかった
- JenkinsジョブのGUI設定 + scpでのファイル転送(expectでPASSWORD入力)
補足
-
- Jenkins2.0からビルトインで提供されている機能。今までジョブの設定はWebUIベースであったが、DSL(Groovy)を記述することでジョブの設定が可能になる
-
- サーバの構成管理ツール。YAML形式でタスクを定義することで様々な処理を自動化することが可能
イメージ図
Jenkinsで使用するリポジトリの構成
-
今回はGitlabを使用していますが、GitHub,SVNなんでもよいです
-
簡単なサンプルはこちらGithub
.
jenkinsfile/
deploy_file.groovy # Jenkinジョブで呼び出すJenkinsfile
ansible/
ansible.cfg
hosts # リモートホストの接続情報を定義
deploy_local_file.yml # Ansible taskファイル
deploy_files/ # 転送するファイルの一時置き場
test.txt
検証環境
- CentOS 7
- Jenkins ver. 2.73.1
- ansible 2.4.0.0
実行サンプル
- まずはどんな感じで使えるかをサンプルで
Jenkinsジョブ設定
Pipelineジョブの作成
Pipeline設定
Jenkinsジョブ実行
- ※ Jenkinsfileでパラメータを設定する場合、一度ジョブを実行してJenkinsfileを呼び出さないとジョブの設定に反映されません
パラメータ付ビルド
- ファイルが転送されました!
[remote_user@remote_host ~]$ ls -l /tmp/test.txt
-rw-r--r-- 1 remote_user group 5 xxx xx yy:yy /tmp/test.txt
ソースコードを書けばあとはジョブの設定して、実行するだけです!
これから中で何が動いているのかを記載します
仕組み解説
- 今回の例
- 転送するローカルファイル: test.txt
- 転送先リモートホスト: stg の /tmp配下
Ansible
実行するtask
-
今回使用するAnsibleモジュールはcopyモジュールです
-
taskファイルは以下
- 変数は実行時にextra-varsとして渡します
deploy_local_file.yml
- hosts: '{{ host }}'
tasks:
- copy:
src: '{{ local_path }}'
dest: '{{ remote_path }}'
force: yes
hosts
- 複数リモートホストを定義しています。今回は環境ごとにホストを定義しました
- Jenkinsジョブのパラメータとして指定できるようにします
## prd
[prd]
192.168.10.100
[prd:vars]
ansible_ssh_port=22
ansible_ssh_user="remote_user"
ansible_ssh_pass="password"
## stg
[stg]
192.168.20.100
[stg:vars]
ansible_ssh_port=22
ansible_ssh_user="remote_user"
ansible_ssh_pass="password"
## dev
[dev]
192.168.30.100
[dev:vars]
ansible_ssh_port=22
ansible_ssh_user="remote_user"
ansible_ssh_pass="password"
- 今回は環境識別子でホストを定義していますが、以下のように定義することも可能です
## web server
[web]
192.168.10.200
[web:vars]
ansible_ssh_port=22
ansible_ssh_user="remote_user"
ansible_ssh_pass="password"
呼び出し方法
- 後述しますが、ansible-playbookで以下のように実行します
- extra-varsとして以下の変数をtaskファイルに渡します
- host : hosts内で定義しているホスト
- deploy_file: ローカル上の転送するファイルのパス
- remote_file: 転送先のパス
ansible-playbook deploy_local_file.yml --extra-vars "host=${remote_host} local_path=${deploy_file} remote_path=${remote_path}"
Jenkinsfile
- ジョブパラメータ設定
- リモートホストを指定できるようにパラメータ化しています
deploy_file.gvy
// ジョブパラメータ設定
properties([
[$class: 'ParametersDefinitionProperty',
parameterDefinitions: [
[$class: 'StringParameterDefinition',
name: 'REMOTE_HOST',
//defaultValue: 'some value', デフォルト値も設定可能だが、今回は使用しない
description: '環境識別子[prd,stg,dev]']]
]
])
- 変数定義
deploy_file.gvy
// Define
def remote_host = "${env.REMOTE_HOST}" // get Jenkins Parameter
def deploy_file = "./deploy_files/test.txt"
def remote_path = "/tmp/"
// for git clone
def credentialsId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // Jenkinsで使用可能なCredential
def git_repo_jenkins = "jenkins-pipeline-ansible-deploy"
def git_url_jenkins = "https://github.com/tarosaiba/${git_repo_jenkins}.git" // 自環境に合わせて設定
// for get deploy file (使用しないが例として)
// def wget_url = "http://xx.xx.xx.xx:8080/job/hoge-job/lastSuccessfulBuild/artifact/fuga-artifact.tar.gz"
- Pipeline
deploy_file.gvy
// Pipeline
node {
stage('Workspase') {
// Workspace有効化
ws('workspace') {
}
}
stage('GitClone') {
// Jenkins repoをclone
git credentialsId: "${credentialsId}", url: "${git_url_jenkins}"
}
stage('GetDeployFile') {
// 転送用ファイルの取得
// 本サンプルは"./deploy_files/test.txt"を使用するため何もしない
sh ":"
//// Sample 以下のようにJenkinsの成果物をwgetで取得することも可能
//// sh "wget ${wget_url} -P ./ansible/deploy_files"
}
stage('DeployFileToRemotehost') {
// 指定ファイルの転送
sh "cd ./ansible && ansible-playbook deploy_local_file.yml --extra-vars \"host=${remote_host} local_path=${deploy_file} remote_path=${remote_path}\""
}
}
転送用ファイルについて
-
転送用ファイルは、GetDeployFileのstageにて以下のようにして準備すると便利です
- Jenkinsジョブの成果物をwget (ソースの例)
- 他リポジトリをJenkinsPipeline内でクローンして、指定ファイルを"./ansible/deploy_filesに移動"
- など、色々
-
転送用ファイルのファイルパス"deploy_file"をJenkinsジョブのパラメータ化してもよいです。(例えば以下)
- もちろん"remote_path"も可能
(..)
// Define
def remote_host = "${env.REMOTE_HOST}" //get Jenkins Parameter
def deploy_file = "${env.DEPLOY_FILE}" // 転送用ファイルパスのパラメータ化
(..)
最後に
-
JenkinsのPipeline as Codeは、最初はなれませんでしたがGUIでやっていたことはほとんど設定可能でした
- 慣れてしまったらこっちの方が絶対にいいです。管理がすごく楽
-
Ansibleのtaskファイルで作業を定義すると、処理がかなりシンプル(YAML形式)に定義できてうれしい
- Ansibleはサーバプロビジョニングだけではなく、普段の作業の自動化に役立てそうなことがたくさんありました