ぶていのログでぶログ

思い出したが吉日

hubotでAkamaiのFast Purgeを実行するスクリプトを作った

タイトルの通りです。 package.jsonのdependenciesに追加して、external-scirpts.jsonに追記すれば使えると思います。

www.npmjs.com

github.com

設定

Akamai {OPEN} APIを使っているで事前にクレデンシャルの発行が必要です。 クレデンシャルの発行は以下に公式の日本語の解説ページがあるので参考にしてください。 なお、LunaでAdminロールがついていないと発行できないです。一時的にAdminをつけて発行後に戻すとかでできるかもしれない…(未確認

blogs.akamai.com

クレデンシャルを発行したら client_token / client_secret / access_token / host をそれぞれ対応する環境変数にセットしhubotを起動してください。

おわりに

Fast Purgeが使えるようになったので今までPurgeに5分位かかっていたのが5秒で終わるようになって生産性↑↑です(作ったばかりで実績はまだないけど!!!)

あと、初めてAkamai APIを触ったのですが、ドキュメントが複雑だったり難しいイメージがあり、今まで敬遠していたのですが、Akamaiが用意しているライブラリを使うとあっさりAPIが利用できてかなり便利でした! 他の言語のバインディングもあるので、Akamai APIでゴニョりたいときにはシュッとできそうな気がします。

蛇足

Akamaiが公式でCLIを作っているみたい。 今回作ったFast Purge(CCU v3)もできるようなので、黒画面からポチポチする場合は便利だと思います。 まだ機能はすくないけど今後拡張していくのかな、たぶん。

github.com

OpenStack Octaviaの挙動

前回はOpenStack Octaviaの概要を説明したので、今回はLoadBalancer(LB)が作られたときにOpenStack Octaviaがどのような動作をするか説明したい。 なお、LBの更新や破棄、PoolやListenerなどなどの操作については、今回説明する内容とほとんど同じであるため説明を省略する。

基本構成

f:id:buty4649:20170628180318p:plain

基本構成は前回説明したものと同じ。 neutronとnovaがあり*1、Octaviaが単独のノードとして存在する。 Octaviaはneutron LBaaSのバックエンドととして動作するように設定されている。

1. neutron LBaaS APIが叩かれるとOctaviaに通知が行く

f:id:buty4649:20170628181552p:plain

クライアントからLBの作成要求が来る。 要求を受け取ったneutronは、OctaviaにLB作成要求をする。

OctaviaはREST APIインターフェイスを持っているので、neutronはAPIを叩くだけになっている。 特に、OpenStack OcataからはOctavia API v2.0になりneutron LBaaS API互換となるため、neutronはリクエストをそのままOctavia APIに転送するだけになる。 そのため、クライアントは直接Octavia APIを叩くこともできる*2

2. nova APIを使用しLBインスタンスを作成する

f:id:buty4649:20170628182337p:plain

Octaviaは、nova APIを使用しLBインスタンスを作成する。 nova APIを叩いたあと、インスタンスが起動したことを確認するため、LBインスタンスに定期的に通信を行う。

3. VIPポートの作成と設定

f:id:buty4649:20170628182750p:plain

LBインスタンス用のVIPを作成するために、neutronへポート作成要求を行う。 そして、各LBインスタンスでVIP宛の通信を受信できるように、allow-address-parisの設定を行う。

LBインスタンスでは、agentが起動していてこちらもREST APIインターフェイスを持っている。 このインターフェイスを通し、作成したVIPのアドレスを、LBインスタンスに通知する。

4. 定期的にチェックする

f:id:buty4649:20170628184531p:plain

Octaviaは定期的にLBインスタンスの死活監視を行う。 LBインスタンスの応答がない場合、インスタンスを破棄し新たにLBインスタンスを作成する。

おわりに

ここまでがOpenStack Octaviaの挙動の説明になる。 OctaviaはnovaやneutronのAPIを叩くだけであり、直接インスタンスやプロセスの作成やネットワークを設定するようなことはしない。 また、neutronとは独立したDBを持っているために、実はOctaviaはneutronとも疎な関係にある。 ココラヘンの話は次回以降にしたいと思う。


前回は社内説明用にGoogle Appsの図形描画で書いていた。 今回の記事を書くために draw.io を使って書き直したのだが、レイヤーが使えてとても便利であった。 図形情報の保存先がローカル以外にも複数のクラウドストレージが選べるのもポイントが高い…! もう今後はネットワーク図を書くときはdraw.ioを使おうっと思った次第。

*1:これ以外にもコンポーネントは存在するがここでは説明を省く

*2:そうすると、neutronの管理情報と齟齬がでるが、情報が二重管理になっているのでそれはそれで…というのもある。ここらへんについて次回触れたい

OpenStack Octaviaの概要

最近、OpenStackのOctaviaコンポーネントを弄っていて、だいぶわかってきたのでメモ代わりにまとめておく。

OpenStack Octaviaとは

私ってほんとバカではなく、将来的にOpenStackの標準的なLBaaS APIエンドポイントとして機能すべく開発されているコンポーネント*1である。 OpenStack Mitakaから標準でサポートされ、Pikeでv1.0がリリースされる予定*2になっている。

OpenStackのLBaaSといえば、neutron LBaaSがある。 neutron LBaaSとOctaviaはどう違うのだろうか? Octaviaの説明についてプロジェクトページには以下のように書いてある。

Octavia is an operator-grade open source scalable load balancer for use in large OpenStack deployments.

オペレータグレードでオープンソースなスケーラブルなロードバランサーなのだ! な、なるほど…?

これではよくわからないので、neutron LBaaSとの違いについて構成を見ながら説明していく。 なお、ここでは、neutron LBaaSのバックエンドはhaproxyを使用しているものとして説明する。

neutron LBaaS(haproxy backend)の構成

f:id:buty4649:20170619134354p:plain

上記の図がneutron LBaaS(haroxy backend)を用いた一般的な構成図である。 neutron LBaaS APIを叩きLBを作成すると、network node上にLBが作成される。 Floating IP(fip)はLBのVIPに紐付けているため、インターネットからのパケットはLBを通し、各インスタンスへロードバランスされる。 この構成の場合、必ず network node上にあるLBを介して通信するためここがボトルネックになりやすい*3

それでは、Octaviaではどうなっているか見てもらおう。

OpenStack Octaviaの構成

f:id:buty4649:20170619141017p:plain

Octavia用のノードが増えていることがわかる。 が、これはnetwork nodeと統合しても問題はない。 ここでは説明を簡単にするため分離している。

新しいノードが増えていること以外で、neutron LBaaSとの違いで大きい点は LBがcompute node上にあることだ。 LBを普通のインスタンスとして、compute node上に構築することでネットワークトラフィックをnetwork nodeに集中することを避けている。 また、MitakaのバージョンからはAct/Sby構成が取れるため、LBを作成すると自動的に冗長構成を取ることができる。

これが、neutron LBaaS(haproxy backend)と比べたときのOctaviaのメリットである。

長くなりそうなのでこの記事はここまで。 次回は、LB構築時のフローを紹介したい。

次: OpenStack Octaviaの挙動

*1:https://github.com/openstack/octavia/blob/master/README.rst#octavia

*2:https://wiki.openstack.org/wiki/Octavia/Roadmap#Major_milestone:Octavia_Version_1.0-_Planned

*3:haproxy以外のバックエンドを使えば解決できるかもしれないが、が、環境がないため試していない

ピンチはチャンス

今日は久しぶりに渋かった。。 長年サービス/システムを運用しているとあるあるだと思う。

まさに、今日、私が踏み抜いた。

最初何が起こっているのか理解できなかった。 本当に渋い。誰が悪いのかすらわからないほどだった。

貧乏くじを引いた…

原因が明らかにつれて私は焦った。 私の経験上、この場合知らなかったとはいえ、実作業を行った私の責任になる。 そうなると、何故それをしたのか?何故こうしたのか?糾弾されると思い、社内の上役に説明するのが怖かった。

説明を終えると上役の方は言った。 「貧乏くじではない。これはチャンスだ!」

そう私は、自分の保身に走り見えていなかった。 もっと視野を広げると、今まで分かっていなかったことが明らかになり、今後ビジネスを進めるうえで、一歩進めることが出来ると。 また、今までそう言われたことがなく保身しか考えていなかった、自分が恥ずかしくなった。

そう言った激励もあり、最高の同僚の助けも借り、見事復旧出来た。 最低の体験だと思ったけど、最高の体験ができとてもよかった。

デュアルキーボードを始めた

周りでセパレート型のキーボードがこっそり流行り始めたので、波にのるべくデュアルキーボードで擬似セパレートキーボードを始めた。

とりあえずわかったことは、ブラインドタッチが下手だということ。 擬似セパレートにしたことで、ホームポジションから正しい指でキータイプしないと意図した入力ができない…。 いつもは無意識にオレオレタイピングだったんだろうなぁっと。

セパレートにしたことで、肩幅が広がって猫背が矯正される、らしい。 が、あまり視力がよくなく前屈みになってしまって意味ねーなー感。。

1週間試してみて、良さそうなら左側も有線モデルに買い替えよう。 電池切れで左側だけ使えないのは悲しすぎるので…

iTerm2+tmuxでエスケープシーケンスを使ったクリップボードコピーがいい感じになっていた

tmuxで set-option -g set-clipboard on を設定して、iTerm2の設定からApplications in terminal may access clipboardを有効にするとエスケープシーケンス(OSC52)を使ってクリップボードにコピーされる。 …が、700byteくらいでコピーした内容が途切れてしまうので、pbcopyやrpbcopy を使って回避していた。

いつのまにか途切れなくなっていた

今日iTerm2周りの設定を見直しているときに、久しぶりにset-option -g set-clipboard onしたらなんと 700byte以上コピーできている!!!

$ pbpaste |wc -c
144108

リモートのtmuxでもコピーできるのでとても便利だ!(だけど、なんかやたら遅い…)。 また、私はローカルでもtmuxを使っているので、リモートでtmuxを起動するとtmux on tmuxになる。 それでも、よしなにクリップボードコピーされるのでとても便利なのであった。

おまけ

set-option -g terminal-overrides ',xterm*:Ms=\EPtmux;\E\E]52;%p1%s;%p2%s\007\E\\'

こんな感じでハックするとtmux on tmuxでもOSC52をうまく扱えるのだ!!!! っという記事にしようと思ったのだけど set-option -g set-clipboard on だけでいい感じに動いてしまったのでお蔵入り…

よく使うpuppetモジュールの紹介

これは pepabo Advent Calendar 2016 - Qiita の12日目の記事です。 昨日は id:kumak1 さんの 好きなキーボードを使い続けるためにキーボード作り始めたでした!


こんにちはこんにちは。 ペパボではサーバの構成管理にpuppetを使用しています。 日々の業務でpuppetを使用していて、最近はマニフェストをゴリゴリ書くより公開されているモジュールを使用することが多くなりました。 そこで、今日は私がよく使うpuppetモジュールを紹介したいと思います!

Puppetモジュールの選び方

puppetモジュールの紹介の前に、私がモジュールを選ぶときのポイントを書いておきます。

Puppetモジュールは、Puppet Forgeで公開されています。 数多くの人がモジュールを公開していますが玉石混交ですので、選ぶのも一苦労です😅 そこで、私は以下のようなポイントをチェックしています。 1. puppetlabsが公開しているもの 2. スターが多くついていて定期的に更新されているもの

1に関しては公式モジュールなので定期的にメンテされており、今後puppetがバージョンアップしてもそれに追随してくれる安心感があります! また、puppetモジュールを作る上で参考になる作りになっているので、これを真似て作ると良いと思います*1 2のスターが多いということは、それほど使用者が多くハマってしまって情報が見つかることが多いですし、定期的に更新されていないと、puppetのバージョンアップなどに追随できない可能性があります。 これは、puppetモジュールに限らない話ですね。

クラス名のバッティング

すでに使用しているpuppetマニフェストに、公開されているpuppetモジュールを追加するとクラス名がバッティングする場合があります。 例えば、 ::apache とか ::nginx とか…。 バッティングした場合どうなるかというと、先に定義されているものが使用されます*2。 そのため、公開されているpuppetモジュールを使うつもりでマニフェストに定義すると、エラーになります。。 しかも、パラメータを指定していた場合、 そのようなパラメータはない みたいなエラーになりかなり混乱します…。

バッティングしてしまった場合の対処は、対象をリネームするか利用しているモジュールのサブクラスにするのが良いと思います。 サブクラスにするとは例えば ::apache というクラス名を some_module::apache のように変更することを指します。

モジュールの紹介

puppetlabs-stdlib

puppetlabs/stdlib · Puppet Forge

puppetに様々な関数を追加するライブラリ群です。 validation系の関数も追加されるので、他のモジュールからincludeされていることが多いです。 個人的によく使うのは file_lineensure_resource です。

puppetlabs-puppet_agent

puppetlabs/puppet_agent · Puppet Forge

puppet-agentをよしなに管理してくれるモジュールです。 pupept-agentを3系から4系にアップグレードするときに、このモジュールをincludeするだけでめんどくさいあれやこれをよしなに処理してくれます!

puppetlabs-inifile

puppetlabs/inifile · Puppet Forge

inifileを扱うモジュールです。 iniファイルをfileリソースで、変更後のファイルを用意して適用するスタイルで今までマニフェストを書いていました。 それでは、本当に必要な設定部分がわからなくなってしまいます。 このモジュールを使って、設定部分のみを明示することで後からマニフェストを見た時に、どの部分を変更したのかわかりやすくなります。

以下使用例です。 コミュニティ版のmysql-5.5を使いたい時に、公式で用意されているRPMからインストールすると、デフォルトではmysql56-communityリポジトリが有効化されているので、mysql56-communityを無効化して、mysql55-communityを有効化する必要があります。 以下のように記述すると目的が達成できます*3

package { 'mysql-community-release':
  ensure   => installed,
  source   => 'http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm',
  provider => 'rpm',
} ->
ini_setting {
  'enable mysql55-community repo':
    path    => '/etc/yum.repos.d/mysql-community.repo',
    section => 'mysql55-community',
    setting => 'enabled',
    value   => 1;

  'disable mysql56-community repo':
    path    => '/etc/yum.repos.d/mysql-community.repo',
    section => 'mysql56-community',
    setting => 'enabled',
    value   => 0;
}

puppetlabs-mysql

puppetlabs/mysql · Puppet Forge

mysqlを扱うのに便利なモジュールです。 my.cnfの定義から、DBやユーザの作成までできます。 (私が携わっているサービスでは、ユーザの管理はGratanを使用しているのでmy.cnfやパッケージ、サービスの管理にのみ使っています)

puppetlabs-apache

puppetlabs/apache · Puppet Forge

Apacheを扱うモジュールです。 httpd.confは設定する内容が多いので、templatesファイルで用意してそのままファイルを配置することが多いですが、このモジュールを使うことで変更点が宣言的になってとても読みやすくなります。 例えば、以下の様な定義を書いて使用しています。

class { '::apache':
  apache_version   => '2.2.3',
  user             => 'apache',
  group            => 'apache',
  manage_user      => false,
  manage_group     => false,
  server_signature => false,
  serveradmin      => 'admin@example.com',
  default_vhost    => false,
  trace_enable     => false,
  # MPMのパラメータをカスタマイズしたいので別途定義している
  mpm_module       => false,
  default_mods     => [
    'alias',
    'auth_basic',
    'authn_core',
    'authn_file',
    'authz_user',
    'dir',
    'deflate',
    'mime',
    'negotiation',
    'rewrite',
    'setenvif',
    'status',
  ],
}

class { '::apache::mod::prefork':
  startservers        => '8',
  minspareservers     => '5',
  maxspareservers     => '20',
  serverlimit         => '256',
  maxclients          => '256',
  maxrequestsperchild => '4000',
}

apache::vhost { 'example.com':
  vhost_name      => '*',
  port            => '80',
  servername      => 'example.com',
  error_log       => false,
  docroot         => '/var/www/html',
  manage_docroot  => false,
  custom_fragment => template('sample/apache_custom_fragment.conf'),
}

Class[::apache] では /etc/httpd/conf/httpd.conf の定義が作成されます*4。 また、default_modsに定義されたモジュールが読み込まれるように /etc/httpd/conf.d 配下にconfファイルが作成されます。 apache::vhost でvhostの定義が作成されます。 作成されるファイル名は、上記の例でいくと /etc/httpd/conf.d/50-example.com.conf になります。 ほぼ、この関数に渡すパラメータでカバーできますが、足りない場合は custom_fragment を使って定義を追加できます。

puppet-nginx

puppet/nginx · Puppet Forge

puppetlabs社が公開しているnginxモジュールもあったのですが、開発が停止してこちらのモジュールにリンクが貼られています。 Apache同様に宣言的にパラメータを定義できます。 以下は定義例です。

$ltsv_log_format = join([
  'vhost:$host', 'time:$time_local', 'remote_addr:$remote_addr', 'method:$request_method',
  'path:$request_uri', 'protocol:$server_protocol', 'status:$status', 'size:$body_bytes_sent',
  'referer:$http_referer', 'user_agent:$http_user_agent', 'request_time:$request_time',
  'upstream_time:$upstream_response_time',
], '\t')

class { '::nginx::config':
  confd_purge              => true,
  worker_processes         => 'auto',
  worker_rlimit_nofile     => 4096,
  http_access_log          => '/var/log/nginx/access.log',
  http_format_log          => 'ltsv',
  nginx_error_log_severity => 'warn',
  log_format               => {
    'ltsv' => $ltsv_log_format
  },
  http_cfg_append          => {
    mruby_init_worker => '/etc/nginx/mruby/init_worker.rb',
    mruby_exit_worker => '/etc/nginx/mruby/exit_worker.rb',
  },
}

class { '::nginx':
  # mruby入りの自前ビルド
  package_ensure => '1.11.6-1.el7.centos.ngx',
  manage_repo    => false,
}

nginx::resource::vhost { 'sample':
  server_name          => ['example.com'],
  listen_port          => 80,
  # vhost毎にアクセスログ/エラーログを作られてしまうのを回避
  access_log           => absent,
  error_log            => absent,
  use_default_location => false,
}

nginx::resource::location { 'sample-default':
  location             => '/',
  vhost                => 'example.com',
  www_root             => undef,
  index_files          => undef,
  proxy                => 'http://$backend',
  location_cfg_prepend => {
    mruby_set => '$backend /etc/nginx/mruby/get_backend.rb cache',
  },
}

LTSVなログフォーマットを定義するために少し煩雑になっています…。 また、ngx_mrubyなパラメータはサポートされていないので http_cfg_append / location_cfg_prepend を用いて定義しています。

stahnma-epel

stahnma/epel · Puppet Forge

RedHat系のディストリを使用する場合EPELは必須だと思います。 このモジュールをincludeするだけで、DRY的になるしモジュールにGPGキーも含まれていて、毎回 yum install が走らなくてよいです。

hfm-stns

hfm/stns · Puppet Forge

弊社若手インフラエンジニア @hfm が作ったSTNS を使うためのモジュールです! includeするだけでSTNSに対応できてとても便利です! STNSとは、弊社 id:pyamax が作ったTOMLで管理するシンプルなユーザ管理システムです。 詳しくは以下の記事を参考にしてください。

tomohiro-mackerel_agent

tomohiro/mackerel_agent · Puppet Forge

mackerel を扱うモジュールです。 check-pluginに notification_intervalmax_check_attempts を設定する場合は /etc/mackerel-agent/conf.d に設定ファイルを配置するのが良いと思います。

まとめ

puppetforgeで公開されているpuppetモジュールを利用すると、DRY的になったり設定が宣言的になり、マニフェストがすっきりします。 モジュールの使い方を覚える必要があったり、既存の環境に適用するにはモジュールが定義するコンフィグファイルに合わせて変更しないといけなかったり、デメリットはありますが一度使い方を憶えてしまえばすぐにマニフェストを掛けるメリットがあります! また、バージョンアップしてもモジュール側で吸収できるので、アップデートに伴ってモジュールを作ったり、派生物を作る必要がなくなります。

今回紹介した内容ではclassのパラメータで設定を定義していますが、各モジュール共にhieraが利用できます。 すべてサーバの定義をpuppetモジュールに集約できれば、究極的にはhieraとpuppetモジュールの管理だけでサーバが定義できるようになります。

puppetモジュールをうまく活用し、サーバの構成管理の負担を下げ生産性を上げていきましょう😆

おわりに

個人ブログじゃなくてペパボテックブログに書けばよかったと後悔…

*1:といいつつpuppetモジュールを作ったことないですが 😓

*2:puppetのmodulepathで指定された順にマニフェストが読み込まれます

*3:yumrepoリソースで定義するとうまく適用できません

*4:RedHat系の場合