TECH
[CloudGarage]

CloudGarageにおけるOSイメージ管理 〜 Ansible,Serverspec,Jenkins

TECH
インフラ開発チーム

この記事は#CloudGarage Advent Calendar 2017の21日目の記事です。

はじめに

今回はCloudGarage上で提供しているOSイメージの管理方法を説明したいと思います。

CloudGarageで提供しているOSイメージは、公式のcloud imageで起動したVMを修正し再イメージ化した上で提供を行っています。この修正を行う際に作業の自動化・品質アップ・属人性の排除を行う目的のもとAnsible,Serverspec,Jenkinsと言ったOSSツールを導入しており、その提供OSイメージの元となるVM修正作業の一部をこれから説明したいと思います。

 

作業フロー

提供OSイメージ管理作業フロー

 

作業フローは以下の流れになります。

①公式のcloud imageで提供元となるVMを作成

②管理VMのJenkinsから提供元VMに対してAnsible(VM修正作業)とServerspec(修正確認作業)を実行

③修正と確認作業が完了したVMをイメージ化しCloudGarageにアップロード

またAnsibleやServerspecで扱う構成ファイルは社内のGitで管理しています。

この中で提供OSイメージの元となる②の修正作業について
Jenkins,Ansible,Serverspec構築詳細の一部を説明していきます。

 

Ansible 構築詳細

管理VM(CentOS7)にAnsibleをインストールします。

# yum install epel-release -y && yum --enablerepo=epel -y install ansible

OSタイムゾーンをUTCから日本へ変更するPlaybookを作成します。
(今回は全体の修正内容から一部を公開しています)

# mkdir /root/playbook
# vi main.yml
-------------------------------------------------------------------
- hosts: all
  tasks:
  ### NTP_timezone修正
    - name: command timezone change
      shell: timedatectl set-timezone Asia/Tokyo
      when: (ansible_distribution == "Ubuntu") or
            (ansible_distribution == "CentOS" and ansible_distribution_major_version == "7") or
            (ansible_distribution == "Debian" and ansible_distribution_major_version == "8") or
            (ansible_distribution == "Debian" and ansible_distribution_major_version == "9") or
            (ansible_distribution == "Fedora") or
            (ansible_distribution == "openSUSE Leap")
      tags: ntp

    - name: command timezone change
      shell: ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
      when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6")
      tags: ntp
-------------------------------------------------------------------

 

Serverspec 構築詳細

次に管理VMにServerspecをインストールします。

# yum install -y ruby && \
gem install serverspec rake highline

Serverspecで利用するファイルを作成します。 (以下、対話式で利用ファイルが生成されていきます)

# mkdir /root/serverspec && cd /root/serverspec && \
serverspec-init
-----------------------------------------------
Select OS type:

1) UN*X
2) Windows

Select number: 1 (※1を入力)

Select a backend type:

1) SSH
2) Exec (local)

Select number: 1 (※1を入力)

Vagrant instance y/n: n (※nを入力)
Input target host name: <VMのIP> (※提供元VMのIPを入力)
 + spec/
 + spec/<VMのIP>/
 + spec/<VMのIP>/sample_spec.rb
 + spec/spec_helper.rb
 + Rakefile
 + .rspec
-----------------------------------------------

Serverspecを実行する際にパスワード指定で行うため設定ファイル(spec_helper.rb)を以下のように追記修正します。

# vi spec/spec_helper.rb
-------------------------------------------------------------------
require 'serverspec'
require 'net/ssh'

set :backend, :ssh

if ENV['ASK_SUDO_PASSWORD']
 begin
   require 'highline/import'
 rescue LoadError
   fail "highline is not available. Try installing it."
 end
 set :sudo_password, ask("Enter sudo password: ") { |q| q.echo = false }
else
 set :sudo_password, ENV['SUDO_PASSWORD']
end

host = ENV['TARGET_HOST']

options = Net::SSH::Config.for(host)

## ここから追記
#options[:login_password] = ENV['LOGIN_PASSWORD'];
if ENV['ASK_LOGIN_PASSWORD']
 begin
   require 'highline/import'
 rescue LoadError
   fail "highline is not available. Try installing it."
 end
 options[:password] = ask("\nEnter login password: ") { |q| q.echo = false }
else
 options[:password] = ENV['LOGIN_PASSWORD']
end
## ここまで追記

options[:user] ||= Etc.getlogin

set :host, options[:host_name] || host
set :ssh_options, options

# Disable sudo
# set :disable_sudo, true


# Set environment variables
# set :env, :LANG => 'C', :LC_MESSAGES => 'C'

# Set PATH
# set :path, '/sbin:/usr/local/sbin:$PATH'
-------------------------------------------------------------------

 

サンプルコードを保存し、OSタイムゾーンが日本へ変更されているか確認するコードを新たに作成します。
(今回は全体の修正内容から一部を公開しています)

# mv spec/<VMのIP>/sample_spec.rb spec/<VMのIP>/sample_spec.rb.org
# vi spec/<VMのIP>/base_spec.rb
-------------------------------------------------------------------
require 'spec_helper'

describe command('date | grep JST') do
 its(:exit_status) { should eq 0 }
end
-------------------------------------------------------------------

参考URL Serverspec – Advanced Tips

以上でAnsibleとServerspecの実行環境は整いました。
実際の実行はJenkinsを利用して行っていきます。

Jenkins 構築詳細

管理VMにJenkinsをインストールし実行ユーザーを変更します。

# yum install java-1.8.0-openjdk -y && \
yum install wget -y && \
wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo && \
rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key && \
yum install jenkins -y
# vi /etc/sysconfig/jenkins
-------------------------------
#JENKINS_USER="jenkins"
JENKINS_USER="root"
-------------------------------

起動と自動起動の設定を行います。

# systemctl start jenkins && \
chkconfig jenkins on

Jenkinsのセットアップが完了後、ブラウザから下記にアクセスにします。

http://<VMのIP>:8080

 

Jenkinsセットアップ

初回セットアップ画面では管理パスワード入力を求められますので
以下を実行した値を入力しログインします。

こちらのパスワードは管理VM上で以下を実行すると表示されます。
cat /var/lib/jenkins/secrets/initialAdminPassword

Jenkinsセットアップ - 初期ログイン-

最初にインストールするプラグインを選択します。
> customize jenkins > install suggested plugin

Jenkinsセットアップ - プラグイン選択-

プラグインが自動インストールされた後
初期adminユーザーを作成します。
Jenkinsセットアップ - 初期ユーザー作成-

以上で初回セットアップは終了です。

これからジョブを作成していきます。

JenkinsによるAnsible実行

初めにJenkinsからAnsibleを実行するジョブを作成します。

Jenkinsセットアップ - ジョブ作成-

> 新規ジョブ作成  > Enter an item name :ジョブの名前 (任意)
フリースタイル・プロジェクトのビルド :  選択

Jenkinsセットアップ - ジョブ作成-

 

入力後、OKを選択します。

Jenkinsセットアップ - ジョブ作成-

 

> ビルド > ビルド手順の追加 > シェルの実行
シェルスクリプト欄に以下を入力します。

# cd /root/playbook/
# ansible-playbook -i "<VMのIP>," --user=<VM接続ユーザー> --become --private-key=<SSH秘密鍵> -e "ansible_python_interpreter=/usr/bin/python" main.yml

入力後、保存します。

こちらではAnsible構築詳細で作成したファイル(main.yml)を指定し実行しています。

–user :  接続先のSSHユーザーを指定します。公式のcloud imageに初期作成されているユーザー(CentOSイメージならばcentosなど)を指定しています。このユーザーは提供時には削除しています。

–become : sudoでの実行を指定します。

–private-key :  SSHの秘密鍵を指定。ansibleではSSHKeyかパスワードによる実行が可能ですが、公式のcloud imageではVMに接続するためのSSHパスが設定されていないためSSHKeyを指定しています。 この秘密鍵は提供時には削除しています。

-e “ansible_python_interpreter=/usr/bin/python” :  接続先VMのpyhonパスを指定します。

 

> ビルド実行

シェルを実行します。

Jenkinsセットアップ - ジョブ実行 -

シェル実行の終了後、ビルド結果を確認します。
> ビルド #番号  >  コンソール出力 を選択

Jenkinsセットアップ - ジョブ実行 -

Ansibleによるシェルが正常終了したことが確認できます。

JenkinsによるServerspec実行

次にJenkinsからServerspecを実行するジョブを作成します。

ジョブ作成からビルド手順の追加まではこれまで行ったansibleの手順と同じです。

Jenkinsセットアップ - ジョブ作成 -

新規ジョブ作成 > ビルド > ビルド手順の追加 > シェルの実行
> シェルスクリプト欄に以下を入力します。

# cd /root/serverspec
# USER=root LOGIN_PASSWORD=<password> /usr/local/bin/rake

入力後、保存します。

こちらではServerspec構築詳細で作成したファイル(base_spec.rb)を指定し実行しています。

ここでは仕様としてServerspecの実行用にパスワードを指定していますが、実行前のVMに対してあらかじめ一時的なrootパスを設定しています。提供時にはこのrootパスワードは初期化されています。

> ビルド実行

シェルを実行します。

Jenkinsセットアップ - ジョブ実行 -

 

シェル実行の終了後、ビルド結果を確認します。
> ビルド #番号  >  コンソール出力 を選択

Jenkinsセットアップ - ジョブ実行 -

Serverspecによるシェルが正常終了したことが確認できます。

 

以上でJenkinsを利用したAnsibleとServerspecを実行する設定が完了しました。あとは作業が完了したVMをイメージ化しCloudGarage環境にアップロードするまでが一連の流れになります。

今回はJenkinsを利用したAnsibleとServerspecの実行例を紹介しましたが、サービスで提供するOSイメージのバーションアップなどインフラ運用作業の効率化のためこうしたツールを組み合わせていくのは良いのではないかと思います。

明日はFoxBoxsnetさんです。よろしくお願いします。

この記事を書いた人

インフラ開発チーム

IaaS型パブリッククラウドサービス「CloudGarage」のインフラ・開発エンジニア。 サーバー構築からミドルウェア設定、バックエンドやフロントエンドのアプリケーション開発まで幅広く行う。

この記事のタグ

オススメの記事

ページトップへ