目の前に僕らの道がある

勉強会とか、技術的にはまったことのメモ

GDG DevFest Tokyo 2019に行ってきた

tokyo.gdgjapan.org

珍しく、何も予定が入ってない土曜日だったので、行ってきました。

最近GCPを触る機運が出てきたのでちょうどいいタイミングでした。

以下メモ

GCP 101 | 坂田 純 | GDG DevFest Tokyo 2019

主にCloudRunの話。 HTTPをlistenするコンテナを起動するサービス。使った分だけ課金対象となる。リクエスト数次第で自動的にスケールする。とお手軽にできそうな印象。

インターフェースがHTTPなので基本的にはパブリックでアクセス出来てしまうが、--no-allow-unauthticatedオプションをつけてデプロイするとで限られた人だけ実行できるようになります。これでバッチ的なことができそう?

マイクロサービスの開発とテストファースト/テスト駆動開発 | 柴田 芳樹 | GDG DevFest Tokyo 2019

ちょいちょいブログとかは見てましたが、話を聞くのは初めてでした。還暦を迎えてもコードをバリバリ書いてるのは素直に尊敬します。

メルペイのマイクロサービスのテストにも興味深かったですが、組み込みでのテストの話も興味深く聴かせてもらいました。 ツールや環境の充実度の差はあれど、組み込みでもウェブでもやるべきことは同じなのだなと思いました。

CloudNative 時代における GKE/Kubernetes ではじめる開発 | 青山 真也 | GDG DevFest Tokyo 2019

k8sの紹介的な話。k8s好きになりました。話がすごいうまくて、めんどくさそうだなあと思ってたkubernetesの印象が変わりました。

その他

:D社のブースを覗いたらMOVの構成図が展示されていて、IoT関連だけAWSを使っていてそれ以外はGCPを使ってるのが興味深かった。 IoT関連のものも別で実装して、AWSからは引き上げるようなことを言ってて、なるほどなあとなりました。

基本的にAWSで構成されたインフラばかり見てたのでなかなか新鮮でした。

障碍対応と私

この記事は、モバイルファクトリー Advent Calendar 2015 18日目の記事です

昨日は @yashims85さんのAndroid drawableは画像を入れておくだけじゃないでした。今日は障碍の話です。

普段障碍対応しているときにやってること考えてることをざっくりと時系列を追って書いていきたいと思います。 コンテキストとしてはLinuxサーバでwebサービスをやっていると思っていただければと思います。

障碍の検知

webサービスを運営していれば、何かしらの監視システムからSlackなりIRCなりメールなり電話なりでアラートの通知が来ると思います。

対応報告

障碍対応をしている旨をメールなり、何かの連絡手段で伝えます。同じく見ている人がいれば調査作業の分担もできます。

状況把握

どこで障碍?

アラートの通知内容にどのサーバで何が起きた的なことが書いてあるはずなので、それを確認します。 だいたいの組織に於いてはサーバ管理表的なものがwebなりExcelなり設定ファイルなりにあるはずなので、そこと照らし合わせてどのプロジェクトのどのロールなのかを把握します。

直前に何をした? いつもと違うことは何?

webアプリケーションであれば直前に入れた変更が原因かもしれません。また、ちょっと前に入れていた変更だが、cronで時限発火したというケースも考えられるかも知れません。 イベント開始で急にトラフィックが上がったと言うことも考えられるかも知れません。普段と変わったことは何かということが把握出来れば対処の幅が広がります。

影響範囲は?

サービス全体なのか、サービスの1機能の障碍なのか、ミドルウェア障碍なのか、影響がどの範囲に及んでいるのかを見ます。 ミドルウェア障碍であれば、最近であれば、冗長化されてるのが普通なので、サービスから切り離して、監視から外せば終わりというパターンも多いです。 サービス全体が落ちている場合は、ひとまず重要な関係者に状況の1次連絡すぐにした方が良いでしょう。

接続出来る?

そもそも、該当サーバに接続出来ない場合は、できることはほぼないので、該当サーバをサービスから外した上で、監視対象から外します。(単体のサーバ障碍の場合)

# pingは通る?
ping ${IP}

# sshできる?
ssh ${IP}

ログの確認

該当サーバ上で動いているミドルウェアアプリケーションサーバのエラーログを主に見ます。だいたいこの辺に重要な情報が出力されている可能性があります。

システムのログも確認した方が良いです。主にsyslogやkernelログを見ると良いでしょう。

# syslogを見る
less /var/log/syslog

# kernelログを見る
less /var/log/kern.log

# kernelログを見る2
dmesg

サーバ状態の確認

負荷の関係で障碍が起きているのであれば、現在のサーバの状態を確認しましょう。 以下のようなコマンドが現状把握に役立つでしょう。

# loadaverageおよびログイン中のユーザを見る
w

# 変なプロセス無いか見る
ps -ef
# or
ps auxwwww


# 開いているポートを確認する
netstat -tlnp

# ネットワークコネクションを確認する
netstat -taopen

# なにかCPU使いまくってないか見る
top

# 現在の負荷の経過を見る
dstat -tamsl 5

# 過去の負荷情報を見る
## CPU
sar
## memory
sar -r
## la
sar -q

対処

直前のコミットにバグを入れ込んでしまったのであればリバートすれば解決するでしょうし、特定のサーバ落ちたのであれば、サービスから外してあげるだけで良いかも知れません。 障碍の内容によって対処方法は様々です。ここで気を付けたいのは二次災害を起こさないことです。 可能であれば、コマンドなり対処スクリプトのレビューをしてもらったり、現状認識に間違いがないかを周りの人にしてもらうと良いでしょう。 (往々にして一人で障碍対応せざるを得ない場合もありますが。。)

事後報告

障碍対応が終わったら、記憶が新鮮なうちに下記の内容をまとめてしかるべき場所に投稿します。 この辺の報告のフォーマットはだいたいの組織において決まっていることが多いでしょう。

  • 障碍内容
  • 影響範囲
  • 経過
  • 対処方法
  • 将来の対策

面倒くさがらずに事実をなるべく詳細に書いておくと未来の自分や自組織のためになると思います。 私の組織でも過去の障碍報告がだいぶ良い感じにデータベースになっており、たまに読み返すと気付きが得られます。

また、この障碍報告を元に、同種の障碍をなるべく起こさない仕組み作りをしていくことが肝要だと思います。

終わりに

自分が障碍対応しているときにやってること、考えてることをざっくり書いてきました。 誰にやり方を教わったわけでもないので、そこは違うとかこうした方がいいとかあれば、いただけると幸いです。

明日は、@lycoris102さんのGameJam部 活動年間活動報告です。きっと面白い話なのではないでしょうか。

#chibapm Chiba.pm#7に参加しました。

参加しました。雑なスライドですみません。

スライド中に出てきてるやつはどれも五反田のお店で出てきます。 五反田企業のガイアックスさんとかモバイルファクトリーさんはPerlの会社なので、美味しいごはんを食べたい人は検討してみてはいかがでしょうか。

そういえば、Chiba.pmの開催回数がKichijoji.pm、Gotanda.pmに抜かされそうです。。

Plack/PSGIなwebアプリケーションの実行環境

この記事は、モバイルファクトリー Advent Calendar 2015 11日目の記事です

※ 投稿内容は私個人の意見であり、所属企業・部門見解ならびに技術戦略を代表するものではありません。

昨日は@rymizukiさんのnpmライブラリの運用と管理についてでした。今日はPerlの話です。

お仕事やプライベートでPerlのwebアプリケーションを書くことが多く、いろいろ知見が溜まってきてるので、ここで少し紹介しようと思います。 今回はPlack/PSGIなwebアプリケーションの実行環境の話です。mod_perlなアプリケーションとはちょっとコンテキストが違います。 少しかっちりコンテキストに近いです。個人で軽くwebアプリケーション立てるならもう少しゆるふわでも問題ないはずです。

OS

UbuntuのLTSを使うことが多いです。Ubuntu前提の内容が後に続きます。

Perl

System Perlは使ってません。OS/ディストリビューションが変わってもなるべくそのまま動くようにしたいためです。 perl-buildで独自ビルドしたPerlを使います。インストール場所としては、 /usr/local/perl/perl-5.${VERSION} に置きます。 Perlを独自ビルドしたものをDebian package化して実行環境にはインストールします。

他の方法としては、ビルド済みのperlをtarで固めて、配布するというのもあります。 どちらでも構わないのですが、ローカルネットワークにaptサーバ立てている関係で、Debian packageの方が運用しやすいのです。 また、perlのマイナーバージョンアップの際もDebian packageを作り直した上で、 apt-get upgrade (or aptitude safe-upgrade)で完結するので、aptの操作に慣れていて楽というのもあります。

モジュール管理

今風にcpanfileでモジュール管理してます。モジュールインストールはCartonを使ってます。

Cartonの後継でCarmelも開発されてます。個人的にはそろそろ触っておきたいところです。

また、cpanfile.snapshotもレポジトリに入れています。 一般的なモジュールは特定の(古い)バージョンに依存せずに動くべきですが、 依存モジュールのバージョン違いによって現在動いているアプリケーションが壊れるのを防ぐために、バージョン固定します。 cpanfile.snapshotがある状態で下記のように carton install してあげると、どの環境でも同じバージョンの モジュールがインストールされます。

carton install --deployment --without develop,test

今やってないですが、別方法としては、モジュールがインストール済みの状態で、 carton bundle すると vendar/ にモジュールのtarが固められるので、それもレポジトリ管理した上で、下記の様にインストールするという手もあります。インストールの際は vendor/bin/carton にfatpackされたcartonコマンドが入るのでそれを使います。 (アプリ実行環境にcartonを敢えて入れる必要は無い)

# 依存モジュールを固める
carton bundle

# インストール
# env.shは後述
./script/env.sh vendor/bin/carton install --cached --deployment --without develop,test

さらに別方法としては、ビルドサーバで依存モジュールをビルドした上で、ディレクトリごと実行環境にrsyncしてあげる方法です。 ビルドサーバを運用しているならば、この方法でも良いでしょう。

参照

独自モジュール

なるべく、独自モジュールは使わない方が良いのですが、個人的な事情などで、CPANに公開出来ないモジュールに関しては、OrePAN2 でDarkpanを作ってそこからローカルに配信するようにしてます。 OrePAN2のサーバを簡単に立ち上げられるOrePAN2::Serverがありますが、一時期は使っていましたが、モジュールのアップロード機能は別にいらないなどの理由で今はwebサーバから静的配信してます。

環境変数

プロジェクトのレポジトリconfig/env.rc という名前で、アプリケーションを動かすために必要な環境変数を定義したファイルを作ります。

PERL5_VERSION="22"
export PROJECT_BASE="/path/to/project"
export PERL_CARTON_MIRROR="http://orepan.local/"
export PERL5LIB="${PROJECT_BASE}/local/lib/perl5:${PROJECT_BASE}/lib"
export PATH="${PROJECT_BASE}/local/bin:/usr/local/perl/perl-5.${PERL5_VERSION}/bin:${PATH}"
export PLACK_PORT=5555

また、 script/env.sh という名前で config/env.rc を読み込んだ上で、プログラムを実行するラッパースクリプトを作ります。 スクリプトなどは基本的にこれを通して実行します。

#!/bin/bash -ue
# 諸々環境変数を設定した上でコマンドを実行する君
#
#       env.sh perl hogehoge.pl
#
source /path/to/project/config/env.rc
exec "$@"

開発環境で、いちいちラッパースクリプト通すのが面倒な場合は、config/env.rc のsymlinkをプロジェクトルートに .envrc として張った上で、direnv使って済ましてしまう場合もあります。

web サーバ起動スクリプト

psgiファイルを plackup するのではなく、こんな感じのスクリプトscript/web みたいな名前で 用意してアプリケーションサーバを起動するようにしてます。

#!/usr/bin/env perl
use strict;
use warnings;

use lib "$ENV{PROJECT_BASE}/lib";
use Plack::Loader;
use SomeApplication::Config;
use SomeApplication::Web::Handler;

my $config = SomeApplication::Config->load();
my $app    = SomeApplication::Web->to_app();

Plack::Loader->load(
    $config->{psgi}->{server},
    %{ $config->{psgi}->{config} },
)->run($app);

また、このスクリプトstart_serverを経由して起動することで、(graceful restartによる)ホットデプロイをできるようにしてます。 start_server のプロセスにSIGHUPを送ると子プロセスのアプリケーションサーバを再起動してくれるのですが、 plackup コマンドで起動してると start_server に渡した引数をそのまま使ってplackup を再起動するので、 max_workers の数を変えたいときなど、 start_server 自体のプロセスを再起動しなくてはならないので不便です。 なので、起動スクリプトを作ってます。そのほかにも理由があるのですが、参照リンクに詳しくあります。

サーバ実装としては、StarletGazelleを使ってます。

参照

デーモン管理

現在はUpstartアプリケーションサーバのデーモン管理してます。 以下の理由で、個人的には好きでした(過去形)。最新のUbuntuはSystemdに変わってしまったので、将来的にはSystemdに移行することになるでしょう。

  • Ubuntuに標準で入っていて
  • サーバ起動時の自動起動してくれて
  • デーモン異常終了時に自動再起動してくれて
  • 設定はわりかしわかりやすい

/etc/init/web-some-application.conf みたいな名前でこんな設定ファイルを作ります

description 'some web application'
author 'masasuzu <hogehoge@masasuzu.net>'
start on runlevel [2345]
stop on starting rc RUNLEVEL=[016]

setuid webapp
setgid webapp

# 異常時に再起動する
respawn

script
    . /path/to/project/config/env.rc
    export PLACK_ENV="production"

    exec ${PROJECT_BASE}/local/bin/start_server \
        --interval 10           \
        --port ${PLACK_PORT}    \
        -- ${PROJECT_BASE}/script/service/web
end script

上記のファイルを作ると以下のように操作出来ます。reloadでSIGHUPが送れるので、アプリケーションサーバのstart_server経由のgraceful restartができます。

# 起動
service web-some-application start

# 停止
service web-some-application stop

# (start_serverのプロセスごと)再起動
service web-some-application restart

# Plackサーバを再起動
service web-some-application reload

アプリケーションサーバ以外も、ジョブのワーカーなども、独自に設定ファイルを作って、Upstart経由で起動したりしてます。

Upstart以外の選択肢としては、先に挙げたSystemdの他、以下のものがあるでしょう。 好みと要件に合わせて使えば良いと思います。

参照

おわりに

WAF(Web Application Framework)やログの話など膨らまそうと思えばもっと膨らませられますが、実行環境の話なので、ここまでで抑えておきます。

ざっくりと、Plack/PSGIなアプリケーションの実行環境について説明してきました。 PerlでWebアプリケーションを作る時に何か参考になれば幸いです。 また、もっと良い方法があれば、教えていただけるとありがたいです。

明日は、@nekobato さんです webpackのなにか面白い話があるんじゃないかとわくどきしてます。