ãã£ã¦ããã¨
仿´ãããããªããã©, ã®ã§ã¼ã ã§ä»¥ä¸ã®ãããªãã¨ããã£ã¦, ããæ°æ¥ã§éç¨ãåã£ã¦ããæ°ãããã®ã§ã¡ã¢ãã¦ãã.
- itamae ã®ã¬ã·ãã amazonlinux ã³ã³ããã«é©ç¨
- é©ç¨ããã³ã³ããã«å¯¾ã㦠Serverspec ã§ãã¹ã
- 1 㨠2 ã Jenkins ã®ãã«ããã¤ãã©ã¤ã³ã§æµã
- 3 ãæ£å¸¸ã«çµäºããã, pull request ã使, åã¯ãã¼ã¸
- master ãã©ã³ãã®ã¬ã·ãããµã¼ãã¼ã«æåã§é©ç¨
Jenkins ã®ããã³ã·ã£ã«ã¨ itamae 㨠Serverspec ã®ä½¿ããããã«æ¹ãã¦æåããæ¬¡ç¬¬.
ã¡ã¢
Jenkins ãåããç°å¢
Docker ã¤ã¡ã¼ã¸
- amazonlinux
- ç´ ã® amazonlinux ã¤ã¡ã¼ã¸ã ã¨è²ã ã¨è¾ãã£ãã®ã§, 以ä¸ã®ãã㪠Dockerfile ãç¨æãã¦ã¤ã¡ã¼ã¸ã使
以ä¸, Dockerfile.
FROM amazonlinux RUN yum install -y sudo util-linux which diffutils RUN useradd ec2-user RUN echo 'ec2-user ALL = NOPASSWD: ALL' > /etc/sudoers.d/ec2-user RUN yum reinstall -y glibc-common ADD clock /etc/sysconfig/clock ADD cloud.cfg /etc/cloud/cloud.cfg ENV LANG ja_JP.UTF-8
以ä¸, clock 㨠cloud.cfg ã®ä¸èº«.
# clock ZONE="UTC" UTC=true
cloud.cfg ãç´æ¥ç·¨éããã®ã¯è¯ããªãããã.
# cloud.cfg # WARNING: Modifications to this file may be overridden by files in # /etc/cloud/cloud.cfg.d # If this is set, 'root' will not be able to ssh in and they # will get a message to login instead as the default user (ec2-user) disable_root: true # This will cause the set+update hostname module to not operate (if true) preserve_hostname: true datasource_list: [ Ec2, None ] repo_upgrade: security repo_upgrade_exclude: - kernel - nvidia* - cudatoolkit mounts: - [ ephemeral0, /media/ephemeral0 ] - [ swap, none, swap, sw, "0", "0" ] # vim:syntax=yaml
clock 㨠cloud.cfg ã¯, itamae ã®ä¸ã§ããããæ¸ãæããçºã®ã¬ã·ããç¨æããçº, äºåã«æ¸ãæããããåã®ãã¡ã¤ã«ãç¨æãã.
itamae ã¬ã·ã
以ä¸ã®ãããªã¬ã·ããç¨æãã.
# cookbooks/common/default.rb # Package install %w(wget git).each do |pkg| package pkg end # Edit /etc/sysconfig/clock file '/etc/sysconfig/clock' do action :edit block do |content| content.gsub!('ZONE="UTC"', 'ZONE="Asia/Tokyo"') content.gsub!('UTC=true', 'UTC=false"') end end # Set LocalTime local_file_exists = 'ls /usr/share/zoneinfo/Japan' execute 'Set LocalTime' do command 'ln -nfs /usr/share/zoneinfo/Japan /etc/localtime' only_if local_file_exists end # Disable Package Update and Set Locale Language remote_file '/etc/cloud/cloud.cfg.d/99_customize.cfg' do action :create mode '0644' owner 'root' group 'root' source 'files/etc/cloud/cloud.cfg.d/99_customize.cfg' end
itamae ã®ãã£ã¬ã¯ããªæ§é ã¯ä»¥ä¸ã®éã.
$ tree . -L 2 . âââ Gemfile âââ Gemfile.lock âââ Rakefile âââ cookbooks â  âââ common âââ docker â  âââ Dockerfile â  âââ clock â  âââ cloud.cfg âââ node.json âââ roles â  âââ docker-test.rb âââ vendor âââ bundle 6 directories, 8 files
Serverspec ãã¹ã
以ä¸ã®ãããªãã¹ããç¨æ.
require "spec_helper" %w(wget git).each do |pkg| describe package(pkg) do it { should be_installed } end end describe file('/etc/sysconfig/clock') do it { should exist } its(:content) { should match /ZONE="Asia\/Tokyo"/ } its(:content) { should match /UTC=false/ } end describe file('/etc/localtime') do it { should be_symlink } end describe file('/etc/cloud/cloud.cfg.d/99_customize.cfg') do it { should exist } it { should be_mode 644 } it { should be_owned_by 'root' } it { should be_grouped_into 'root' } end describe command('date') do its(:stdout) { should contain('JST') } end describe command('locale') do its(:stdout) { should contain('ja_JP.UTF-8') } end
spec_helper.rb ã«ã¡ãã£ã¨ã²ã¨æéå ãã¦, ç°å¢å¤æ°ã« Docker ã¤ã¡ã¼ã¸ãæå®ã㦠rspec ãèµ°ãããã«ãã¦ãã.
require 'serverspec' require 'net/ssh' require 'json' properties = YAML.load_file('properties.yml') if ENV['DOCKER_IMAGE'] begin require 'docker' rescue LoadError fail "docker-api is not available. Try installing it." end set :backend, :docker set :docker_image, ENV['DOCKER_IMAGE'] else ... çç¥ ... end
ãã£ã¬ã¯ããªæ§é ã¯ä»¥ä¸ã®éã.
$ tree . -L 2 . âââ Gemfile âââ Gemfile.lock âââ Rakefile âââ properties.yml âââ spec â  âââ common â  âââ spec_helper.rb âââ vendor âââ bundle 4 directories, 5 files
Jenkins ã®æºå
ãã©ã°ã¤ã³
以ä¸ã®ãã©ã°ã¤ã³ãå©ç¨ãã.
- rbenv plugin
- Parameterized Trigger plugin
- Build Pipeline Plugin
Build Pipeline Plugin ã¯å¿ é ã§ã¯ç¡ã.
Docker å¨ã
jenkins ã¦ã¼ã¶ã¼ã§ docker ã³ãã³ãå©ããããã«ãã¦ãã.
sudo gpasswd -a jenkins docker
ãããªæã.
$ sudo -u jenkins docker version Client: Version: 17.12.0-ce API version: 1.35 Go version: go1.9.2 Git commit: 3dfb8343b139d6342acfd9975d7f1068b5b1c3d3 Built: Mon Mar 5 20:42:27 2018 OS/Arch: linux/amd64 Server: Engine: Version: 17.12.0-ce API version: 1.35 (minimum version 1.12) Go version: go1.9.2 Git commit: 402dd4a/17.12.0-ce Built: Mon Mar 5 20:43:34 2018 OS/Arch: linux/amd64 Experimental: false
ã¸ã§ã
以ä¸ã®ããã«ã¸ã§ãã 2 ã¤ç¨æãã. (ã¸ã§ãåã¯ãªãã§ããã)
- infra-itamae
- infra-serverspec
åã ã®ã¸ã§ãã§å ±éãã¦ä»¥ä¸ã®å 容ãè¨å®ãã.
- ã½ã¼ã¹ã³ã¼ã管ç (ä»åã Backlog Git ãå©ç¨)
- rbenv build wrapper ã§ Ruby 2.5.0 ãå©ç¨ããããã«ãã
以ä¸ã®ããã« infra-itamae ãæåããã, infra-serverspec ãå®è¡ãããããã«è¨å®ãã.
infra-itamae ã®è¨å®
[ãã«ã] ã® [ã·ã§ã«å®è¡] ã«ä»¥ä¸ã®ããã«ã·ã§ã«ã¹ã¯ãªãããæ¸ãã.
cd itamae.sandbox bundle install --path vendor/bundle cd docker docker build -t itamae-test . cd ../ bundle exec itamae docker --image=itamae-test roles/docker-test.rb --log-level=info --no-color 2>&1 | tee test.log if [ "$(cat test.log | tail -1 | awk -F":" '{print $4}')" != "" ];then echo -n "DOCKER_IMAGE=$(cat test.log | tail -1 | awk -F":" '{print $4}')" > ${WORKSPACE}/docker_image.txt else exit 1 fi
itamae 㯠Docker ã³ã³ããã«å¯¾ãã¦ãããã¸ã§ãã³ã°ãã¦, ã³ã³ããã¤ã¡ã¼ã¸ã使ãããã¨ãåºæ¥ã.
$ bundle exec itamae --help docker Usage: itamae docker RECIPE [RECIPE...] Options: [--recipe-graph=PATH] # [EXPERIMENTAL] Write recipe dependency graph in DOT -j, [--node-json=NODE_JSON] -y, [--node-yaml=NODE_YAML] -n, [--dry-run], [--no-dry-run] [--shell=SHELL] # Default: /bin/sh [--login-shell], [--no-login-shell] [--ohai], [--no-ohai] # This option is DEPRECATED and will be unavailable. [--profile=PATH] # [EXPERIMENTAL] Save profiling data [--detailed-exitcode], [--no-detailed-exitcode] # exit code 0 - The run succeeded with no changes or failures, exit code 1 - The run failed, exit code 2 - The run succeeded, and some resources were changed -l, [--log-level=LOG_LEVEL] # Default: info [--color], [--no-color] # Default: true -c, [--config=CONFIG] [--image=IMAGE] # This option or 'container' option is required. [--container=CONTAINER] # This option or 'image' option is required. [--tls-verify-peer], [--no-tls-verify-peer] # Default: true [--tag=TAG] Create Docker image
[ãã«ãå¾ã®å¦ç] ã§ [Trigger parameterize build on other projects] ãæå®ã, 以ä¸ã®ãã©ã¡ã¼ã¿ãè¨å®ãã.
ãã©ã¡ã¼ã¿å | å¤ | æ¦è¦ |
---|---|---|
Projects to build | infra-serverspec | 䏿µããã¸ã§ã¯ããæå® |
Trigger when build is | Stable | 䏿µããã¸ã§ã¯ãããã«ããããåºæº |
Perameters from properties file | 鏿 | ãã¡ã¤ã«ãããã©ã¡ã¼ã¿ãæå®ãã |
Use properties from file | docker_image.txt | ${WORKSPACE} 以ä¸ã«çæããããã¡ã¤ã«åãæå® |
Use properties from file ã§æå®ãããã¡ã¤ã«ã¯ä»¥ä¸ã®ãããªãã©ã¼ãããã§ããå¿ è¦ããã.
KEY=value
ä»åã ã¨, 䏿µããã¸ã§ã¯ãã§ãã infra-serverspec ã§å©ç¨ãã Docker ã¤ã¡ã¼ã¸åãç°å¢å¤æ°ã«æå®ãã¦ããããã®ã§, 以ä¸ã®ãããªå 容ã«ãªã.
DOCKER_IMAGE=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
å°, itamae å®è¡æã« --no-color
ãªãã·ã§ã³ãä»ä¸ãã¦ãããªãã¨, ãã°åºåã«ã«ã©ã¼ã³ã¼ããå«ã¾ãã¦ãã¾ã, æå³ããªãç°å¢å¤æ°ãå®ç¾©ãããã®ã§æ³¨æãã.
infra-serverspec ã®è¨å®
[General] ã® [ãã«ãã®ãã©ã¡ã¼ã¿å] ã«ãã§ãã¯ãå ¥ãã¦, 以ä¸ã®ããã«è¨å®ãã.
- ããã¹ãã® [åå] ã«ã¯
DOCKER_IMAGE
ãæå®
[ãã«ã]ã® [ã·ã§ã«å®è¡] ã«ä»¥ä¸ã®ããã«ã·ã§ã«ã¹ã¯ãªãããæ¸ãã.
cd serverspec.sandbox bundle install --path vendor/bundle bundle exec rake serverspec:docker-test && docker rmi -f ${DOCKER_IMAGE}
åãã¦ãå³
Build Pipeline
ãã°
以ä¸, infra-itamae ã®å®è¡ãã° (ã³ã³ã½ã¼ã«åºå).
Started by user xxxxxxx Building in workspace /var/lib/jenkins/workspace/infra-itamae > git rev-parse --is-inside-work-tree # timeout=10 Fetching changes from the remote Git repository ... INFO : Image created: sha256:fc7d8989c992a4035da943f19ff13758d659dc2c66e85b354a81ed35eac092a9 ++ cat test.log ++ tail -1 ++ awk -F: '{print $4}' + '[' fc7d8989c992a4035da943f19ff13758d659dc2c66e85b354a81ed35eac092a9 '!=' '' ']' ++ cat test.log ++ tail -1 ++ awk -F: '{print $4}' + echo -n DOCKER_IMAGE=fc7d8989c992a4035da943f19ff13758d659dc2c66e85b354a81ed35eac092a9 Triggering a new build of infra-serverspec Finished: SUCCESS
以ä¸, infra-serverspec ã®å®è¡ãã° (ã³ã³ã½ã¼ã«åºå).
Started by upstream project "infra-itamae" build number 3 originally caused by: Started by user xxxxxxxx Building in workspace /var/lib/jenkins/workspace/infra-serverspec > git rev-parse --is-inside-work-tree # timeout=10 Fetching changes from the remote Git repository ... Command "date" stdout should contain "JST" Command "locale" stdout should contain "ja_JP.UTF-8" Finished in 1.39 seconds (files took 0.36337 seconds to load) 12 examples, 0 failures + docker rmi -f 21f1cc87aee8a670710128fc65699f8554de4b38027c355dc39048a026850819 Deleted: sha256:21f1cc87aee8a670710128fc65699f8554de4b38027c355dc39048a026850819 Deleted: sha256:6605e21eb4b68cca7fa9c95da3f4f927f40988798c038ed7f42fc68caabb5f84 Deleted: sha256:1e12645118a9dbb47e9963ee37669022e91bb0a07c2a5757f30aaf88e83fde46 Deleted: sha256:2e643788655c8c760d1e980eca0b46251b7301af1b759b5df5ab7bbe642b0c9d Deleted: sha256:00f5d50a957784ab20fd7b550fdfeca505dc4e550959ba7f73f2def824041d44 Deleted: sha256:e0f2d8168d9eaa1ed9592791b8a4e436b5476db41b99fa12bf32076891b9fd22 Deleted: sha256:b7937fd11c3afb70b655e281ef6acdc4d3afc3cd912a19fe14cfb3b93c0e7688 Deleted: sha256:9989831a58db4d3c31f5f18d590c5ffc08ad41ac4f424b3ea870fded4440e591 Deleted: sha256:4ac2d011c778bf4d55459f2549bb80bc89b3327e747384446c1f08652997bbfb Deleted: sha256:7522d03ea4bb3188185376f4aa675724bc8c46e961fa0625dc73b164408b5736 Deleted: sha256:f0a3ff27c8c1d0e4242beb150786fae71a8b52a328b3810581c0a50d9101c89d Deleted: sha256:95f9b360e9435265a8e1888110af30e93a90e563fe969c8249f14d446791c996 Deleted: sha256:be94791a1fc4eb636d443b0fb18b56eed7c32b0cd3a2b3912b10b7945d840179 Deleted: sha256:fff1c0462adfdaa1e8c815e4fc17c228b205479a23161cd717342dad5d9345b2 Finished: SUCCESS
ãã¹ããéã£ãæã ã, ã³ã³ããã¤ã¡ã¼ã¸ãåé¤ãã¡ãã.
以ä¸
ãã£ããã¨ããã¡ã¢ã§ãã.