SlideShare a Scribd company logo
成長を加速する
minne の技術基盤戦略
変化するサービスとチームを支える
self.introduce
=>
{
name: “SHIBATA Hiroshi”,
nickname: “hsbt”,
title: “Chief engineer at GMO Pepabo, Inc.”,
commit_bits: [“ruby”, “rake”, “rubygems”, “rdoc”, “tdiary”,
“hiki”, “railsgirls”, “railsgirls-jp”, …],
sites: [“hsbt.org”, ruby-lang.org”, “rubyci.com”, “railsgirls.com”,
“railsgirls.jp”],
}
成長を加速する minne の技術基盤戦略
Do scale-out
with automation
2014/11 の minne の状況
• IaaS の上で動くシンプルな Rails アプリケーション
• Rails が動いているサーバーは 6 台
• デプロイは capistrano 2 を使用
• ジョブワーカーは Web サーバーに同居
• 用途不明なサーバーもちらほら…
オペレーションは心温まる手作業
• 動いているサーバーを LB から外して “Golden Image” を
作成し、インスタンスを複製
• 複製したインスタンスの設定変更は手順書をもとに手作
業で実施
• おおよそ 4-6 時間の工程…
No ssh
“No SSH” ルールを作成し、Packer でイメージ構築を自動化
“No SSH” のコンセプト
ある程度の規模のサービスにとっては 1 サーバーは UNIX
でいう 1 プロセスと同等である
プロセスに gdb でアタッチしたりしない
→ インスタンスに ssh ログインしない
プロセスのメモリを書き換えて変数を変えたりしない
→ インスタンスの設定ファイルを変えたりしない
遅い処理
OS 起動
puppet/chef 実行
Rails アプリケーションの
デプロイ
No SSH によるサーバー構築の流れ
速い処理
OS 設定の変更
Capistrano の準備
LB に接続(サービスイン)
Packer によるイメージ作成
• 公式 OS イメージ
• プラットフォーム提供

• Minimal イメージ(phase 1)
• Network, User, Package 設定のみ実行
• puppet/chef, プラットフォームの cli ツールを追加
• Role 専用イメージ(phase 2)
• 起動するだけで Role 特有のアプリケーションが起動
Minimal イメージ
cloud-init provisioner
#cloud-config
repo_update: true
repo_upgrade: none
packages:
- git
- curl
- unzip
users:
- default
locale: ja_JP.UTF-8
timezone: Asia/Tokyo
rpm -ivh http://yum.puppetlabs.com/
puppetlabs-release-el-7.noarch.rpm
yum -y update
yum -y install puppet
yum -y install python-pip
pip install awscli
sed -i 's/name: centos/name: cloud-user/' /etc/
cloud/cloud.cfg
echo 'preserve_hostname: true' >> /etc/cloud/
cloud.cfg
www イメージ
cloud-init provisioner
#cloud-config
preserve_hostname: false
puppet agent -t
set -e
monit stop unicorn
/usr/local/bin/globefish -w
rm -rf /var/www/deploys/minne/releases/*
rm -f /var/www/deploys/minne/current
# tar xf するだけで動くRails アプリケーションを取得
(snip)
# mackerel のホスト設定が packer 実行時のものとかぶらないように初期化
rm /var/lib/mackerel-agent/id
# cloud-init をもう一度動かすようにする準備
rm -rf /var/lib/cloud/sem /var/lib/cloud/instances/*
packer の実行は ruby の thor から実行
$ some_cli_tool ami build-minimal
$ some_cli_tool ami build-www
$ some_cli_tool ami build-www —init
$ some_cli_tool ami build-www -a ami-id
module SomeCliTool
class Ami < Thor
method_option :ami_id, type: :string, aliases: "-a"
method_option :init, type: :boolean
desc 'build-www', 'wwwの最新イメージをビルドします'
def build_www
…
end
end
end
thor でオペレーションをコード化
$ some_cli_tool instances launch -c …
$ some_cli_tool mackerel fixrole
$ some_cli_tool scale up
$ some_cli_tool deploy blue-green
イメージ作成
その他 IaaS 操作コマンド
インスタンス挙動のテスト
http(s) でアクセスした時の
挙動のみテストを行う
サーバー内部のパッケージ
個別のバージョンナンバー
などはテストの対象としな
い
インフラCIの導入
サーバーにインストール済みのパッケージや起動している
プロセスなどの詳細は Serverspec を用いて継続的にテスト
を実行
Puppet + Drone CI(with Docker) + Serverspec = WIN
CIがあれば何でも(puppet マニフェストをアグレッシブにリ
ファクタリング)できる!
Serverspec
“RSpec tests for your servers configured
by CFEngine, Puppet, Ansible, Itamae or anything else.”
http://serverspec.org/
% rake -T
rake mtest # Run mruby-mtest
rake spec # Run serverspec code for all
rake spec:base # Run serverspec code for base.minne.pbdev
rake spec:batch # Run serverspec code for batch.minne.pbdev
rake spec:db:master # Run serverspec code for master db
rake spec:db:slave # Run serverspec code for slave db
rake spec:gateway # Run serverspec code for gateway.minne.pbdev
(snip)
Drone CI
“CONTINUOUS INTEGRATION FOR GITHUB AND BITBUCKET THAT
MONITORS YOUR CODE FOR BUGS”
https://drone.io/
Drone CI は nyah と呼ばれる Openstack の上に構築
Integration tests with Packer
Packer の実行後にも Serverspec でテスト実行 (by @udzura)
"provisioners": [
(snip)
{
"type": "shell",
"script": "{{user `project_root`}}packer/minimal/provisioners/run-serverspec.sh",
"execute_command": "{{ .Vars }} sudo -E sh '{{ .Path }}'"
}
]
yum -y -q install rubygem-bundler
cd /tmp/serverspec
bundle install --path vendor/bundle
bundle exec rake spec
packer configuration
run-serverspec.sh
Blue-Green
Deployment
Blue-Green デプロイの手順
1.起動するインスタンスを Packer で作成し、hakata コマ
ンドで起動
2.LB に接続して、“InService” となるまで待機
3.古いインスタンスを廃棄
B-G デプロイの hakata コマンド
class deploy < Thor
def blue_green
old_instances = running_instances(load_balancer_name)
invoke Instances, [:launch], options.merge(:count => old_instances.count)
catch(:in_service) do
sleep_time = 60
loop do
instances = running_instances(load_balancer_name)
throw(:in_service) if (instances.count == old_instances.count * 2) &&
instances.all?{|i| i.status == 'InService'}
sleep sleep_time
sleep_time = [sleep_time - 10, 10].max
end
end
old_instances.each do |oi|
oi.delete
end
end
end
nginx + consul-template の様子
Mackerel
“A Revolutionary New Kind ofApplication Performance
Management. Realize the potential in Cloud Computingby
managing cloud servers through “roles””
https://mackerel.io
consul + consul-alerts
Disposable なインスタンスのプロ
セス監視は consul と consul-alerts
で実行
https://github.com/hashicorp/consul
https://github.com/AcalephStorage/consul-
alerts
td-agent と log collector
動的に変化するイン
スタンスのログは td-
agent で集約
<match nginx.**>
type forward
send_timeout 60s
recover_wait 10s
heartbeat_interval 1s
phi_threshold 16
hard_timeout 60s
<server>
name aggregate.server
host aggregate.server
weight 100
</server>
<server>
name aggregate2.server
host aggregate2.server
weight 100
standby
</server>
</match>
<match nginx.access.*>
type copy
<store>
type file
(snip)
</store>
<store>
type tdlog
apikey api_key
auto_create_table true
database database
table access
use_ssl true
flush_interval 120
buffer_path /data/tmp/td-agent-td/access
</store>
</match>
Large-scaled
Deploy with
Rails application
2015/11 現在の minne の状況
• Rails 4.2.4 and Ruby 2.2.3, MySQL 5.6.23
• Capistrano 3, stretcher + consul
• solr(with sunspot), delayed_job
• Models: 136, Controllers 143, Code to Test Ratio: 1:1.7
• サーバー台数 100台弱
capistrano によるデプロイ問題
• ある日、社内の GHE が不定
期に重くなるという報告
• GHE にログインしてプロセス
リストを見てみると…
• git…git…git…(100個くらい)
• minne がデプロイすると全
サーバーが GHE に git clone/
fetch を実行する
consul with stretcher
• トリガとして consul/serf
のイベントを受け取って動
作するプログラム
• インスタンスが自律的にコー
ド更新を実行
• 更新するコードは s3 から
取得
https://github.com/fujiwara/stretcher
Bundled package of Rails application
Rails アプリケーションを Ruby だけあれば起動するような
tgz を作成(bundle install/assets precompile 済み)
capistrano を用いてビルド専用サーバーで各種タスクを実
行後に s3 へアップロード
$ bundle exec cap production archive_project
desc "Create a tarball that is set up for deploy"
task :archive_project =>
[:ensure_directories, :checkout_local, :bundle, :npm_install, :bower_install,
:asset_precompile, :create_tarball, :upload_tarball, :cleanup_dirs]
consul の event を通知するために consul watch で stretcher
を systemd でデーモン化
consul watch と stretcher
[Unit]
Description=Stretcher Deamon with Consul
Documentation=https://github.com/fujiwara/stretcher
[Service]
User=rails
Group=rails
EnvironmentFile=-/etc/sysconfig/consul
Environment="AWS_CONFIG_FILE=/home/rails/.aws/config"
ExecStart=/usr/bin/consul watch -type event -name <%= @event_name %> stretcher
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGINT
[Install]
WantedBy=multi-user.target
systemd への完全移行
supervisord や monit で動かしていた consul などを全て OS
標準の systemd へと移行
[Unit]
Description=Rack HTTP server for fast clients and Unix
Documentation=http://unicorn.bogomips.org/
[Service]
User=rails
Group=rails
EnvironmentFile=-/etc/sysconfig/unicorn
WorkingDirectory=/var/www/rails_applicaiton
PIDFile=/var/www/rails_application/shared/pids/unicorn.pid
ExecStart=/usr/local/rbenv/shims/bundle exec unicorn -c config/unicorn.conf -E <%= @environment %>
ExecReload=/bin/kill -USR2 $MAINPID
ExecStop=/bin/kill -QUIT $MAINPID
KillSignal=SIGINT
[Install]
WantedBy=multi-user.target
rails 向け stretcher manifests
src: s3://your-buckets-name/production/application-<%= env.now %>.tgz
checksum: <%= checksum %>
dest: /var/www/rails/releases/<%= env.now %>
commands:
pre:
-
post:
- ln -nfs /var/www/rails/releases/<%= env.now %> /var/www/rails/current
- rm -rf /var/www/rails/current/log
- ln -nfs /var/www/rails/shared/log /var/www/rails/current/log
- mkdir -p /var/www/rails/current/tmp
- ln -nfs /var/www/rails/shared/pids /var/www/rails/current/tmp/pids
- ln -nfs /var/www/rails/shared/data /var/www/rails/current/data
success:
- <%= h[:cmd] %> && rm-releases /var/www/rails/releases 5
failure:
- cat >> /tmp/failure
- (slack に失敗メッセージを通知)
- "*.pid"
- "*.socket"
yaml を erb から生成
し、s3 にアップロー
ドする cap task を作
成
tgz 作成後に実行
capistrano との統合
namespace :minne do
desc 'Deploy via Stretcher'
task :deploy do
set :deploying, true
invoke "minne:archive_project"
(ENV['ROLES'] || fetch(:minne_deploy_roles)).split(',').each do |target_role|
on application_builder_roles do
opts = ["-name deploy_#{target_role}_#{fetch(:stage)}"]
opts << "-node #{ENV['HOSTS']}" if ENV['HOSTS']
opts << “s3://your-buckets-name/manifest_#{target_role}.yml"
execute :consul, :event, *opts
end
end
end
before 'minne:deploy', 'slack:deploy:starting'
after 'minne:deploy', ‘slack:deploy:finished'
end
stretcher を用いて cap からデプロイ
1. build サーバーで rails + bundler gems + node modules +
assets 入りの tgz を作成、s3 にアップロード
2. stretcher 用の manifests を作成して s3 にアップロード
3. consul event を指定した roles に対して発行
4. event を受け取った role に所属するインスタンスで
stretcher が起動、コードの更新
$ bundle exec cap production minne:deploy
今後に向けて
今後に向けた技術基盤の刷新
検索によるユーザー価値の創造
• solr から elasticsearch への移行
• ハンドメイドならではの検索結果の表示
高速なサイトを目指して
• 高可用性ジョブキュー(sidekiq)への変更
効果的なモバイルUIの構築に向けて
• モバイルログ基盤の構築
IaaS のハイブリッド利用
• OpenStack への段階的な移行
• 10/21 時点で1-2割のサーバーが OpenStack で稼働中
完全オートスケールの導入
• OpenStack 上で実現するツールの開発
今後に向けた技術基盤の刷新
もっと
おもしろく
できる
成長を加速する minne の技術基盤戦略

More Related Content

成長を加速する minne の技術基盤戦略

  • 2. self.introduce => { name: “SHIBATA Hiroshi”, nickname: “hsbt”, title: “Chief engineer at GMO Pepabo, Inc.”, commit_bits: [“ruby”, “rake”, “rubygems”, “rdoc”, “tdiary”, “hiki”, “railsgirls”, “railsgirls-jp”, …], sites: [“hsbt.org”, ruby-lang.org”, “rubyci.com”, “railsgirls.com”, “railsgirls.jp”], }
  • 5. 2014/11 の minne の状況 • IaaS の上で動くシンプルな Rails アプリケーション • Rails が動いているサーバーは 6 台 • デプロイは capistrano 2 を使用 • ジョブワーカーは Web サーバーに同居 • 用途不明なサーバーもちらほら…
  • 6. オペレーションは心温まる手作業 • 動いているサーバーを LB から外して “Golden Image” を 作成し、インスタンスを複製 • 複製したインスタンスの設定変更は手順書をもとに手作 業で実施 • おおよそ 4-6 時間の工程…
  • 7. No ssh “No SSH” ルールを作成し、Packer でイメージ構築を自動化
  • 8. “No SSH” のコンセプト ある程度の規模のサービスにとっては 1 サーバーは UNIX でいう 1 プロセスと同等である プロセスに gdb でアタッチしたりしない → インスタンスに ssh ログインしない プロセスのメモリを書き換えて変数を変えたりしない → インスタンスの設定ファイルを変えたりしない
  • 9. 遅い処理 OS 起動 puppet/chef 実行 Rails アプリケーションの デプロイ No SSH によるサーバー構築の流れ 速い処理 OS 設定の変更 Capistrano の準備 LB に接続(サービスイン)
  • 10. Packer によるイメージ作成 • 公式 OS イメージ • プラットフォーム提供 • Minimal イメージ(phase 1) • Network, User, Package 設定のみ実行 • puppet/chef, プラットフォームの cli ツールを追加 • Role 専用イメージ(phase 2) • 起動するだけで Role 特有のアプリケーションが起動
  • 11. Minimal イメージ cloud-init provisioner #cloud-config repo_update: true repo_upgrade: none packages: - git - curl - unzip users: - default locale: ja_JP.UTF-8 timezone: Asia/Tokyo rpm -ivh http://yum.puppetlabs.com/ puppetlabs-release-el-7.noarch.rpm yum -y update yum -y install puppet yum -y install python-pip pip install awscli sed -i 's/name: centos/name: cloud-user/' /etc/ cloud/cloud.cfg echo 'preserve_hostname: true' >> /etc/cloud/ cloud.cfg
  • 12. www イメージ cloud-init provisioner #cloud-config preserve_hostname: false puppet agent -t set -e monit stop unicorn /usr/local/bin/globefish -w rm -rf /var/www/deploys/minne/releases/* rm -f /var/www/deploys/minne/current # tar xf するだけで動くRails アプリケーションを取得 (snip) # mackerel のホスト設定が packer 実行時のものとかぶらないように初期化 rm /var/lib/mackerel-agent/id # cloud-init をもう一度動かすようにする準備 rm -rf /var/lib/cloud/sem /var/lib/cloud/instances/*
  • 13. packer の実行は ruby の thor から実行 $ some_cli_tool ami build-minimal $ some_cli_tool ami build-www $ some_cli_tool ami build-www —init $ some_cli_tool ami build-www -a ami-id module SomeCliTool class Ami < Thor method_option :ami_id, type: :string, aliases: "-a" method_option :init, type: :boolean desc 'build-www', 'wwwの最新イメージをビルドします' def build_www … end end end thor でオペレーションをコード化 $ some_cli_tool instances launch -c … $ some_cli_tool mackerel fixrole $ some_cli_tool scale up $ some_cli_tool deploy blue-green イメージ作成 その他 IaaS 操作コマンド
  • 15. インフラCIの導入 サーバーにインストール済みのパッケージや起動している プロセスなどの詳細は Serverspec を用いて継続的にテスト を実行 Puppet + Drone CI(with Docker) + Serverspec = WIN CIがあれば何でも(puppet マニフェストをアグレッシブにリ ファクタリング)できる!
  • 16. Serverspec “RSpec tests for your servers configured by CFEngine, Puppet, Ansible, Itamae or anything else.” http://serverspec.org/ % rake -T rake mtest # Run mruby-mtest rake spec # Run serverspec code for all rake spec:base # Run serverspec code for base.minne.pbdev rake spec:batch # Run serverspec code for batch.minne.pbdev rake spec:db:master # Run serverspec code for master db rake spec:db:slave # Run serverspec code for slave db rake spec:gateway # Run serverspec code for gateway.minne.pbdev (snip)
  • 17. Drone CI “CONTINUOUS INTEGRATION FOR GITHUB AND BITBUCKET THAT MONITORS YOUR CODE FOR BUGS” https://drone.io/ Drone CI は nyah と呼ばれる Openstack の上に構築
  • 18. Integration tests with Packer Packer の実行後にも Serverspec でテスト実行 (by @udzura) "provisioners": [ (snip) { "type": "shell", "script": "{{user `project_root`}}packer/minimal/provisioners/run-serverspec.sh", "execute_command": "{{ .Vars }} sudo -E sh '{{ .Path }}'" } ] yum -y -q install rubygem-bundler cd /tmp/serverspec bundle install --path vendor/bundle bundle exec rake spec packer configuration run-serverspec.sh
  • 20. Blue-Green デプロイの手順 1.起動するインスタンスを Packer で作成し、hakata コマ ンドで起動 2.LB に接続して、“InService” となるまで待機 3.古いインスタンスを廃棄
  • 21. B-G デプロイの hakata コマンド class deploy < Thor def blue_green old_instances = running_instances(load_balancer_name) invoke Instances, [:launch], options.merge(:count => old_instances.count) catch(:in_service) do sleep_time = 60 loop do instances = running_instances(load_balancer_name) throw(:in_service) if (instances.count == old_instances.count * 2) && instances.all?{|i| i.status == 'InService'} sleep sleep_time sleep_time = [sleep_time - 10, 10].max end end old_instances.each do |oi| oi.delete end end end
  • 23. Mackerel “A Revolutionary New Kind ofApplication Performance Management. Realize the potential in Cloud Computingby managing cloud servers through “roles”” https://mackerel.io
  • 24. consul + consul-alerts Disposable なインスタンスのプロ セス監視は consul と consul-alerts で実行 https://github.com/hashicorp/consul https://github.com/AcalephStorage/consul- alerts
  • 25. td-agent と log collector 動的に変化するイン スタンスのログは td- agent で集約 <match nginx.**> type forward send_timeout 60s recover_wait 10s heartbeat_interval 1s phi_threshold 16 hard_timeout 60s <server> name aggregate.server host aggregate.server weight 100 </server> <server> name aggregate2.server host aggregate2.server weight 100 standby </server> </match> <match nginx.access.*> type copy <store> type file (snip) </store> <store> type tdlog apikey api_key auto_create_table true database database table access use_ssl true flush_interval 120 buffer_path /data/tmp/td-agent-td/access </store> </match>
  • 27. 2015/11 現在の minne の状況 • Rails 4.2.4 and Ruby 2.2.3, MySQL 5.6.23 • Capistrano 3, stretcher + consul • solr(with sunspot), delayed_job • Models: 136, Controllers 143, Code to Test Ratio: 1:1.7 • サーバー台数 100台弱
  • 28. capistrano によるデプロイ問題 • ある日、社内の GHE が不定 期に重くなるという報告 • GHE にログインしてプロセス リストを見てみると… • git…git…git…(100個くらい) • minne がデプロイすると全 サーバーが GHE に git clone/ fetch を実行する
  • 29. consul with stretcher • トリガとして consul/serf のイベントを受け取って動 作するプログラム • インスタンスが自律的にコー ド更新を実行 • 更新するコードは s3 から 取得 https://github.com/fujiwara/stretcher
  • 30. Bundled package of Rails application Rails アプリケーションを Ruby だけあれば起動するような tgz を作成(bundle install/assets precompile 済み) capistrano を用いてビルド専用サーバーで各種タスクを実 行後に s3 へアップロード $ bundle exec cap production archive_project desc "Create a tarball that is set up for deploy" task :archive_project => [:ensure_directories, :checkout_local, :bundle, :npm_install, :bower_install, :asset_precompile, :create_tarball, :upload_tarball, :cleanup_dirs]
  • 31. consul の event を通知するために consul watch で stretcher を systemd でデーモン化 consul watch と stretcher [Unit] Description=Stretcher Deamon with Consul Documentation=https://github.com/fujiwara/stretcher [Service] User=rails Group=rails EnvironmentFile=-/etc/sysconfig/consul Environment="AWS_CONFIG_FILE=/home/rails/.aws/config" ExecStart=/usr/bin/consul watch -type event -name <%= @event_name %> stretcher ExecReload=/bin/kill -HUP $MAINPID KillSignal=SIGINT [Install] WantedBy=multi-user.target
  • 32. systemd への完全移行 supervisord や monit で動かしていた consul などを全て OS 標準の systemd へと移行 [Unit] Description=Rack HTTP server for fast clients and Unix Documentation=http://unicorn.bogomips.org/ [Service] User=rails Group=rails EnvironmentFile=-/etc/sysconfig/unicorn WorkingDirectory=/var/www/rails_applicaiton PIDFile=/var/www/rails_application/shared/pids/unicorn.pid ExecStart=/usr/local/rbenv/shims/bundle exec unicorn -c config/unicorn.conf -E <%= @environment %> ExecReload=/bin/kill -USR2 $MAINPID ExecStop=/bin/kill -QUIT $MAINPID KillSignal=SIGINT [Install] WantedBy=multi-user.target
  • 33. rails 向け stretcher manifests src: s3://your-buckets-name/production/application-<%= env.now %>.tgz checksum: <%= checksum %> dest: /var/www/rails/releases/<%= env.now %> commands: pre: - post: - ln -nfs /var/www/rails/releases/<%= env.now %> /var/www/rails/current - rm -rf /var/www/rails/current/log - ln -nfs /var/www/rails/shared/log /var/www/rails/current/log - mkdir -p /var/www/rails/current/tmp - ln -nfs /var/www/rails/shared/pids /var/www/rails/current/tmp/pids - ln -nfs /var/www/rails/shared/data /var/www/rails/current/data success: - <%= h[:cmd] %> && rm-releases /var/www/rails/releases 5 failure: - cat >> /tmp/failure - (slack に失敗メッセージを通知) - "*.pid" - "*.socket" yaml を erb から生成 し、s3 にアップロー ドする cap task を作 成 tgz 作成後に実行
  • 34. capistrano との統合 namespace :minne do desc 'Deploy via Stretcher' task :deploy do set :deploying, true invoke "minne:archive_project" (ENV['ROLES'] || fetch(:minne_deploy_roles)).split(',').each do |target_role| on application_builder_roles do opts = ["-name deploy_#{target_role}_#{fetch(:stage)}"] opts << "-node #{ENV['HOSTS']}" if ENV['HOSTS'] opts << “s3://your-buckets-name/manifest_#{target_role}.yml" execute :consul, :event, *opts end end end before 'minne:deploy', 'slack:deploy:starting' after 'minne:deploy', ‘slack:deploy:finished' end
  • 35. stretcher を用いて cap からデプロイ 1. build サーバーで rails + bundler gems + node modules + assets 入りの tgz を作成、s3 にアップロード 2. stretcher 用の manifests を作成して s3 にアップロード 3. consul event を指定した roles に対して発行 4. event を受け取った role に所属するインスタンスで stretcher が起動、コードの更新 $ bundle exec cap production minne:deploy
  • 37. 今後に向けた技術基盤の刷新 検索によるユーザー価値の創造 • solr から elasticsearch への移行 • ハンドメイドならではの検索結果の表示 高速なサイトを目指して • 高可用性ジョブキュー(sidekiq)への変更 効果的なモバイルUIの構築に向けて • モバイルログ基盤の構築
  • 38. IaaS のハイブリッド利用 • OpenStack への段階的な移行 • 10/21 時点で1-2割のサーバーが OpenStack で稼働中 完全オートスケールの導入 • OpenStack 上で実現するツールの開発 今後に向けた技術基盤の刷新