登壇レポート Ruby OpenStack DevOps

RubyWorld Conference 2015に登壇し、OpenStackの取り組みについてお話ししました

登壇レポート Ruby OpenStack DevOps

GMOペパボの近藤うちお(@udzura)です。普段は福岡に勤務しており、技術基盤チームとして、RubyやPuppetを書いています。Fukuoka.rbというコミュニティをやっていたりもします。どうぞよろしくお願いします。

今回は、今月12日〜13日に開催された RubyWorld Conference 2015 に登壇した際、お話しした内容について書かせていただきます。

RubyWorld Conferenceとは

RubyWorld Conferenceとは、今年で7回目となる、島根県松江市で開催されるRubyのカンファレンスです。毎年、Matzの基調講演を始め、様々な利用事例や技術動向の紹介がされています、そういった中で、ペパボとしては、最近全社で導入を進めているOpenStackの話しと、OpenStackを使いこなすためにペパボのエンジニアでRubyのライブラリ・ツールを開発しているお話しをしました。

スライドは以下になります。

ペパボとOpenStack、そしてRubyのツール

ペパボでは、今年度より全社のサーバーインフラ基盤としてOpenStackの採用を決定し、導入を開始しました。現在ではカラメルJUGEMといった大きなサービスを含む、各サービスで導入が進んでおり、今後も広めていくべく開発を進めています。

その検証・開発の過程で、さまざまなOpenStackの管理ツールとライブラリを、Rubyで作成しました。スライドでは手短でしたので、この場をお借りしてもう少し詳細に説明したいと思います。

なお、ペパボでは、古くからPuppetの導入を進めているなど、サーバ状態や設定のコード化を推進しています。今回紹介するものも、そういった観点のツールが中心になります。

kaname

kaname は、OpenStack KeystoneのAPIを経由して、OpenStackのユーザ管理をするためのツールです。

具体的には以下のようなYAMLの設定ファイルをkeystone.ymlという名前で用意します。

antipop:
  email: "antipop@example.com"
  tenants:
    kiban: "cto"
hsbt:
  email: "hsbt@example.com"
  tenants:
    minne: "admin"
    kiban: "member"
udzura:
  email: "hsbt@example.com"
  tenants:
    minne: "member"
    kiban: "member"

このファイルを元にkaname applyコマンドを実行することで、OpenStack Keystone上のユーザがYAMLの状態に収束するよう、設定が適用されます。コマンドには--dryrunオプションもあります。

$ kaname apply

Keystoneのユーザ設定を、設定ファイルの形で管理できるので、VCSで変更履歴を管理したり、GitHubのようなツールを用いることで変更のレビューをしたりすることが可能になりました。

kakine

kakine は、OpenStackのそれぞれのテナントごとに、Security Groupの構成を管理するためのツールです。

こちらも、以下のような設定ファイルを作成します。テナントがkibanという名前であればkiban.yamlになります。

app:
  rules:
    - direction: ingress
      protocol: tcp
      port: 443
      remote_ip: 0.0.0.0/0
    - direction: ingress
      protocol: tcp
      port: 80
      remote_ip: 0.0.0.0/0
  description: app hosts
cache:
  rules:
    - direction: ingress
      protocol: tcp
      port: 11211
      remote_ip: 10.10.10.0/24
  description: memcached hosts

このルールを元に、kibanテナントのSecurity Groupの設定をするには、以下のようなコマンドを実行します。なお、こちらもkanameと同様--dryrunオプションがあります。

$ kakine apply -t kiban

AWSでの運用経験がある方は共感していただけると思いますが、Security Groupの管理はなかなか罠が多く、具体的には全貌を把握するのが困難であることや、アドホックな対応により追加したルールがずっと残ってしまっていたりすることがよくあります。Security Groupをコードの形で残せることのメリットは、クラウド基盤では非常に大きいものと思います。

pec

pec はインスタンスを構築、また構成を管理するためのツールです。インストールしたら、以下のようにプロジェクトでセットアップを走らせることができます。

$ pec init
create - /Pec.yaml
create - /user_data/web_server.yaml.sample

生成されたPec.yamlを、例えば以下のように編集して利用していきます。

# yamlのマージ記法を使うことができます
_default_: &def
  os_type: centos
  tenant: kiban
  image: centos-7.1
  flavor: m1.small
  availability_zone: az001

# vm config
manage001:
  <<: *def
  networks:
    eth0:
      bootproto: static
      allowed_address_pairs:
        - 10.1.1.5/24
      ip_address: 10.1.1.1/24
      gateway: 10.1.1.254
      dns1: 8.8.8.8
      dns2: 8.8.8.8
    eth1:
      bootproto: dhcp
  security_group:
    - default
    - ssh
  templates:
    - base.yaml
    - webserver.yaml
  user_data:
    hostname: manage001
    fqdn: manage001.pepabo.nyah
    repo_releasever: 7.1.1503
web001:
  <<: *def
  networks:
    ....
log001:
  ...

設定を記述した後は、例えばmanage001サーバを立ち上げる際は、pec up manageをコマンドを実行すれば、manageにマッチするmanage001を自動で検出して立ち上げてくれます。

pecの特徴として、事前にNeutron(ネットワークコンポーネント)のポート(仮想NIC)を作成してからインスタンスを立ち上げるので、いわゆるOpenStackのDHCPやL3 agentが利用できないような構成でもインスタンスを作成することが可能な点があります。

また、ロールごとのそれぞれのflavor(インスタンスタイプ)やuser-dataなどを構成管理できるようになるので、CloudFormationTerraformのようなものと比べ、より簡易的なオーケストレーションツールとして利用することも可能です。OpenStackにはHeatというオーケストレーションのコンポーネントがありますが、ロールごとの構成を管理したい、という程度であればpecのシンプルさは便利かと思います。

YAO

YAO's logo

YAO は、ここまでに説明してきたOpenStackのツール群のために作った、Rubyのための新しいOpenStack API Wrapperです。現在、ペパボのメンバーを中心として開発を進めています。また、ロゴも弊社の@horaotokoの作成です。

YAOの前まで、OpenStackのRuby wrapperには、以下の二つのgemがありました。

このうちのfogは、もともとOpenStackのためだけでなく、複数のクラウドにまたがった共通のレイヤーを提供するものであるため、非常にたくさんの依存gemが存在してしまっています。また、OpenStackの機能が現状では単独のgem切り出されておらず、その動きもなかなか進んでいないように見受けられ、現状ではOpenStackの機能を使うためにfog全体を利用するほかない状態です。

もう一つのRuby OpenStackは、2013年で開発が止まっており、プルリクエストも放置されている状況のようです。

一方で、OpenStackのAPI自体は、非常に綺麗なRESTful APIの規約に則っています。例として、Compute APIの一部をご紹介します。

GET    /v2.1/​{tenant_id}​/servers             List servers
POST   /v2.1/​{tenant_id}​/servers             Create server
GET    /v2.1/​{tenant_id}​/servers/​{server_id}​ Get server details
PUT    /v2.1/​{tenant_id}​/servers/​{server_id}​ Update server
DELETE /v2.1/​{tenant_id}​/servers/​{server_id}​ Delete server

GET    /v2.1/images            List images
GET    /v2.1/images/detail     List images details
GET    /v2.1/images/​{image_id}​ Get image details
DELETE /v2.1/images/​{image_id}​ Delete image

以上のことから、既存のgemを頑張って使いまわすことより、新規かつ自分たちでコントロールできる形で実装する方がコストも大きくなく、メリットも得られると判断しました。そして開発をスタートすることとしました。

YAOは、以下のような設計思想で作られています。

  • 最低限の依存
  • 個々のコンポーネントに依存しない、利用者から見たリソース単位での操作をする

「最低限の依存」については、現状、jsonfaradayfaraday_middlewareにのみ依存している状態です。faraday_middlewareへの依存も開発が進んで必要な機能が絞れたら外す方向で検討しています。そのため、依存関係のコンフリクト等の心配をすることなく、個々のプロジェクト内で利用できるようになっていると思います。

また、「個々のコンポーネントに依存しない、利用者から見たリソース単位での操作をする」点については、Nova、Neutronといったコンポーネントの種類ごとにRuby側の実装をするのではなく、Server、Network、Userといった、より利用者のメンタルモデルに沿ったリソース単位でのクラス分けを基本としています。

これらのリソースクラスについて、OpenStackのRESTfulなAPIを生かし、以下のような小さなDSLを書くことで定義可能となっています。

module Yao::Resources
  class Flavor < Base
    friendly_attributes :name, :vcpus, :disk, :swap
    map_attribute_to_attribute "os-flavor-access:is_public" => :public?
    map_attribute_to_attribute "OS-FLV-DISABLED:disabled"   => :disabled?

    self.service        = "compute"
    self.resource_name  = "flavor"
    self.resources_name = "flavors"
  end
end

現在は、上述したpec、kanameのOpenStackラッパーについて、fogからYAOへの置き換えが完了しています。その他のツールでも随時利用していく予定です。

また、YAOを使ったツールはGitHubのyaocloudオーガニゼーションにOSSとして配置し、一種のショーケースとして利用可能なようにしています。

まとめ

上記で紹介したような「コード化」の推進は、昨今のDevOpsの動きの潮流に沿ったものでもありますし、何より構成管理、自動化、レビューの容易さといった様々なメリットを受けられるものですので、引き続き進めていきたいと思っています。開発にあたり、Codenize.toolsの各gemの思想を参考にしました。この場をお借りして感謝します。

また、その基盤として作り始めたOpenStackのライブラリ「YAO」ですが、自分たちで使うことにより順調に開発が進んでいるように思われます。クオリティを上げ、世界中のOpenStackユーザに届くようなライブラリに育てていきたいと思います。OpenStackを利用している方々からのプルリクエストもお待ちしております。

最後になりますが、このような、OpenStackやDevOps、オープンソース開発の分野に興味のあるエンジニアを、ペパボでは絶賛募集しております!

(Photo from https://www.flickr.com/photos/hsbt/22406887374/ by @hsbt)