「新米サーバ/インフラ担当者のための 仮想サーバ/クラウド技術の常識」を読んだ

ご縁で書籍「新米サーバ/インフラ担当者のための 仮想サーバ/クラウド技術の常識」と一部の方にはおなじみ「さくらのクラウド2万円クーポン」を頂戴しました!

新米サーバ/インフラ担当者のための 仮想サーバ/クラウド技術の常識」はさくらのクラウドを例に、クラウドサービスの申込からWordPressサイトの構築、果ては障害監視や可用性向上まで一貫して扱った書籍です。

クーポンとセットで頂いたら、これはもう「このクーポン使って本の通りに試すしかないでしょ!」ということでありがたく読ませていただきました。

目次

まず結論を一言

本書は「クラウドサービスを申し込んでWordPressのサイトを公開しましょう!」という内容に留まらず、WordPressをはじめとしたWebアプリケーションを実践的な運用についての指南まで一貫して書かれた素晴らしい書籍です!

実際、ある程度のコーポレートサイトやWebサイト・Webサービスであれば本書の内容+αで運用を始められるのではないでしょうか。

こういう方にオススメ!

申込やWordPressサイトの構築・設定自体ももちろんとても丁寧に説明されていますが、読者が本当に実践的にWordPressサイトを長期運用できるよう、以下のように順にステップアップしていきます。

  1. 初期構築(1台に全部入れ)+独自ドメイン取得
  2. データベースサーバーを分離する
  3. コントロールパネルでスケールアップする
  4. ロードバランサーを使ってスケールアウトする
  5. セキュリティ向上のためファイアウォールとメンテナンス用VPNを設定する(簡単)
  6. Zabbixを使ってサーバーの監視設定をする
  7. データベースを冗長化する

なお本書の最後の章でも触れられていますが、本書の内容はWordPressに限らず色々なWebアプリケーションを運用する際にとても役立ちます。

サーバー/インフラ運用をはじめる方

たとえば以下のような場合に、(1)の「1台に全部入れ」については豊富に情報があるものの、スケールアウト・セキュリティ・冗長化や監視については躓きやすいポイントではないでしょうか?

  • Web制作+開発してる方が「これレンサバでできないからサーバ運用しよう」と考えた
  • 受託開発メインの方が「自社でWebサービスを作って公開しよう!」と思った
  • iOSやAndroid向けのスタートアップサービスで「そろそろサーバーサイドも自社開発してサポートサイトも作るか!」と思い立った
  • なんとなくVPSやクラウドサーバーでサービス運用しているけど、じつは一回綺麗に仕切り直したい
  • 非ITエンジニアとしてWebサービスのディレクションをしているが運用について理解したい

それぞれ散らばった情報はあるものの、最初の申込や構築から運用できるフェイズまで、増えたアクセスのためにロードバランシングしつつファイアウォールを導入しつつ、でも社外の方/関係各社/お客様にそれぞれ適切で快適な接続方法を提供しながら同時にセキュリティも担保して・・となるとなかなか一貫した情報が得づらい部分があるのではないでしょうか?

そんな方に本書は最適な指南書になると思います。
クラウドサーバーの費用も本書に従って1週間5営業日で申込からデータベースの冗長化まで全てを一通りやったとしても1万円ほどで済みますし、本書にも書かれていますが予算や必要に応じてもっと小さな構成にすることもできます。
※2016年6月現在の価格で試算。
※もちろんサーバーを使い続ければ相応に費用が発生します。

教える立場の方

また、本書の構成や説明の順序、どこまで細かく深い説明をするかは「誰かに何かを説明する」という観点でとても勉強になりました。

著者の方は(さくらインターネット研究所の所長さんですし)相当に深い知識をお持ちだと思いますが、しかし全ての知識を羅列されるわけではなく、読者にとって必要な知識を理解しやすい順番で適度に説明されている気遣いを感じました。

本書は教える立場の方にも大いに参考になるのではないのでしょうか。
私もぜひ見習いたいと思います。

これから読まれる方へ

クレジットカードの用意を忘れずに

書籍内でも明記されていますが、さくらのクラウドを使うためにクレジットカードが必要ですので用意しておきましょう!

とくに今現在クレジットカードを持っていない方、会社のクレジットカード決済方法がわからない方が事前に確認/用意が必要です。
なおクーポンを使うと本書の内容を最初から最後まで無料で試してお釣りがきます。クーポンはさくらインターネット様のイベントでいただけることもあるようですね!

Linuxを触ったことがあるとより理解しやすい

また、本書は入門書ですので読むにあたってサーバー運用の経験は必要ないと思いますが、Linuxの操作経験はある方が望ましいように思います。
ただし本書内では丁寧にコマンドや実行結果が紹介されていますので「Linux触ったことない」という方でもGoogleで検索しながら読み進めることはできるでしょう!

本書は入門書としてとてもわかりやすく書かれていますが扱っている範囲が広いため、読む方によっては聞きなれない「IaaS」「LAMP」「可用性」等の言葉が出てきます。
これらの言葉もGoogle検索しながら読むとより理解が深まると思います。

書籍内のネットワークとIPアドレスについて

本書中ではLAN用のIPアドレスとして 192.168.0.0/24 ( 192.168.0.1192.168.0.254 )を使って解説が進められます。
最初は1台のクラウドサーバーから始まりますが、最終的にはVPNや監視サーバーまで一通り含めたネットワークが出来上がりますので、できる限り本書の通りのIPアドレスを使うことをお勧めします。
本書のIPアドレスの割り振りはとてもよく考えられています。

もし書籍とIPアドレスが重複している場合

ただし、もし本書を試されるご自宅や職場のネットワークが 192.168.0.0/24 で構成されていると途中のVPNのところでうまく接続できなくなる恐れがあります。

VPN接続以外の部分では支障はないのでそのまま読み進めても良いのですが、お使いのPCに 192.168.0.1192.168.0.254 のIPアドレスが割り当てられているのであれば、本書のIPアドレスの 192.168.x.y のうち x の部分を 1254 のいずれかに変更して読み進めると、VPN接続の際の問題を避けることができます。

もちろんお使いのPCのIPアドレスが 192.168.0.1192.168.0.254 でなければ何も変更せずに本書の通りに進めることができます。

MacでVPN接続する場合

本書はWindowsのVPN接続手順についてスクリーンショット入りで解説されています。
MacでのVPN接続方法については本書中には記載がありませんので下記の記事を書きました。ご参照ください。

blog.mazgi.net

マップ表示について

また本書中にさくらのクラウドのマップ表示が何度か登場しますが、マップは図の矢印のように色々なところを動かすことができます。
マップ内を自由に動かして書籍内の図に合わせると理解が進むと思います。 f:id:mazgi:20160628150148p:plain ※図のマップの内容は本書とは関係ありません。
※図の英語表示は私のPCが英語に設定されているためで、通常は日本語で表示されます。

どのクラウドサービスを使うか

また、本書ではさくらインターネット株式会社の「さくらのクラウド」を使うことを前提として書かれています。

筆者がいわゆる「中の人」であるからこそ、クラウドサービスの申込やコントロールパネルとLinuxサーバー上でのシームレスな操作説明や、クラウドサーバーへの申込と独自ドメインの取得/設定を同じ会員IDで行える説明、果てはクラウドサーバーはどのように実現されているかという技術的バックグラウンドの解説までをたった200ページ強の書籍の中で一貫して扱えるのだと感じました。

しかし本書の内容は他のクラウドサービスでも十分に応用できますので、他のクラウドサービスにすでに慣れている方や、何らかの理由で他のクラウドサービスを使う必要がある方は、本書を片手に読み替えながら試すこともできるでしょう。

もちろん読み替えには相応の知識が必要となりますので、どのクラウドサービスと決めていない方、読み替えることに不安がある方は、まずは本書の通りに「さくらのクラウド」で理解を深めてから改めてどのクラウドサービスを使うかを検討されても良いのではないでしょうか。
他のクラウドサービスとしては例えば以下のようなものがあります。

感想

まずは何と言っても著者の深い知識に裏打ちされた説明が、分かりやすく順を追って一貫して書かれている点が魅力です。

入門書ではなかなか冗長構成やセキュリティまで手が回らないことが多いように思いますが、本書ではクラウドサーバーとVPCルータ等を活用することで、比較的簡単に一定レベルの可用性やセキュリティを担保しています。

理解しやすく実用的な技術解説

また、実際の運用で活用されている技術についても分かりやすく解説されています。

例えばロードバランサの項では、まず「ロードバランサとはどういうものか」が説明された後で、実際のWebサービスでよく使われる「DSR」方式のロードバランサについて分かりやすく解説されています。

もちろん事前に持っている知識によっては「パケット」や「MAC(アドレス)」について調べる必要があるかもしれませんが、それくらいの知識を身につけることで読者は理解を進め実際にロードバランサを設定することができるようになります。

一貫した活かせる運用が学べる

そして、著者ご自身がクラウドサービスの内部までよくご存知ですので、「仮想環境と物理環境の違い」や「サーバーの種類」等前提として持っている方が望ましい知識や「データベースサーバーの負荷分散」等の難しい話題にも触れられていますので、本書で「入門」した読者は、今後どのように知識を身に付け経験を積んでいけば良いか、道筋を知ることができる点も魅力だと感じました。

また、企業や組織として「Webサービスを公開しよう!」と思い立った時についつい考慮が後回しになりがちな「セキュリティ」「運用」「冗長化」「障害監視」などについて必要性とともに構築/設定方法について解説されている点が特に素晴らしいと思います!

構築は最初だけですが運用はずっと続きます。
そしてWebサービスは運用しなければ、セキュリティ上の問題を突かれて個人情報を漏洩したり、何かの踏み台にされたり、いつの間にか増えていたアクセスによってダウンしたり、それはもう本当に色々な問題が起きます。

本書を読んで「本当は最初からここまで含めて入門すべき」としみじみ感じました。
本書は索引の最後のページまで含めてもたったの223ページですが、改めてWebサービスに携わる者として大切なことを学べました。

さいごに

なお頂いたクーポンの残高は私のサイトに使わせていただきます(๑´ڡ`๑)
本当にありがとうございました。

新米サーバ/インフラ担当者のための 仮想サーバ/クラウド技術の常識

新米サーバ/インフラ担当者のための 仮想サーバ/クラウド技術の常識

複数のサーバーに対してSSL証明書の期限を確認する

会社のサーバーが一斉にSSL証明書更新のシーズンを迎えたのでOpenSSLの各種コマンドで確認の手間を減らしてみる。

まず、 openssl s_client コマンドで /dev/null を標準入力に入れつつ標準エラー出力を捨てるとこんな出力が得られる。

$ openssl s_client -connect www.mvrck.co.jp:443 < /dev/null 2> /dev/null                                        
CONNECTED(00000003)
---
Certificate chain
 0 s:/CN=*.mvrck.co.jp
   i:/C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
 1 s:/C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
---
Server certificate
(snip)
    Verify return code: 0 (ok)
---

openssl s_client の結果を -startdate, -enddate オプションを指定しつつ openssl x509 コマンドに渡すとこんな出力が得られる。

$ openssl s_client -connect www.mvrck.co.jp:443 < /dev/null 2> /dev/null | openssl x509 -noout -startdate -enddate 
notBefore=Feb 24 16:02:53 2016 GMT
notAfter=Mar 28 02:59:00 2017 GMT

のでこんな感じで複数のホストのSSL証明書の期限を確認できる。

$ for h in {foo,bar,baz}.example.com
do
echo -n "$h:"
openssl s_client -connect $h:443 < /dev/null 2> /dev/null | openssl x509 -noout -enddate | grep -E '^\s*notAfter='
done
foo.example.com:notAfter=Mar 28 01:23:45 2017 GMT
bar.example.com:notAfter=Mar 28 01:23:45 2017 GMT
baz.example.com:notAfter=Mar 28 01:23:45 2017 GMT

便利!

#Gentoo で普通の CVE-2015-7547 対策

追記

私が何か勘違いしてたようですが glibc-2.21-r2 (~amd64マスクされてない)でpatchが取り込まれてますね。。

# emerge -fOq glibc
>>> Fetching (1 of 1) sys-libs/glibc-2.21-r2::gentoo
# tar tf /usr/portage/distfiles/glibc-2.21-patches-7.tar.bz2 | grep 'CVE-2015-7547'
patches/00_all_0028-CVE-2015-7547-getaddrinfo-stack-based-buffer-overflo.patch

本文

皆さまにおかれましては CVE-2015-7547 の対応お疲れ様です。

glibc ライブラリの脆弱性 (CVE-2015-7547) に関する注意喚起

さてGentoo Linuxの場合はどうかというと、 glibc-2.22-r2 でpatchが取り込まれているようです。

574880 – (CVE-2015-7547) <sys-libs/glibc-2.21-r2: stack overflow in getaddrinfo (CVE-2015-7547)

試しにfetchしてpatchを探してみましょう。

# ACCEPT_KEYWORDS="~amd64" emerge -fOq \=sys-libs/glibc-2.22-r2
>>> Fetching (1 of 1) sys-libs/glibc-2.22-r2::gentoo
# tar tf /usr/portage/distfiles/glibc-2.22-patches-10.tar.bz2 | grep 'CVE-2015-7547'
patches/10_all_glibc-CVE-2015-7547.patch

入ってますね。

であればあとはこんなファイルを用意して ~amd64 マスクを外し、

# cat /etc/portage/package.accept_keywords/sys-libs.glibc
# for CVE-2015-7547 ( https://bugs.gentoo.org/show_bug.cgi?id=574880 )
=sys-libs/glibc-2.22-r2 ~amd64

emerge して再起動するだけです。

# emerge -pvq sys-libs/glibc
[binary   R   ] sys-libs/glibc-2.22-r2  USE="(multilib) nscd -debug -gd (-hardened) -profile (-selinux) -suid -systemtap -vanilla" 

#Gentoo Tips: いつなんどきでも #GentooInstallBattle で最新のstage3を入手する

前提

2015年も残す所あと数日ですね。
今年はあと何回#gentooinstallbattleにエントリーできるでしょうか。
Gentoo Linuxをインストールためには2つのアーカイブファイルをダウンロードします。

  • stage3
    • / ツリーのアーカイブ, つまりOSとして成立するために必要なあらゆるファイル
    • (以前はstage1, stage2もありました)
  • portageスナップショット
    • Gentoo Linuxのパッケージ管理システムであるPortageのリポジトリのアーカイブ

このうち、portageスナップショットについては ${ミラーサイトのURL}/snapshots/portage-latest.tar.{xz,bz2} というURIで常に最新のアーカイブを入手できるので毎回同じコマンドラインが使えます。
お気に入りのミラーサイトを見つけたらgistに curl -LO 'ftp://ftp.jaist.ac.jp/pub/Linux/Gentoo/snapshots/portage-latest.tar.xz' とでもメモしておけば、あとはインストールのたびに貼り付けてEnterキーを押すだけです。

f:id:mazgi:20151228021027p:plain

しかしstage3はファイル名にビルドされた日付が含まれるため毎回同じURIで、というわけにはいきません。

f:id:mazgi:20151228021031p:plain

Gentoo Linuxをインストールするなら少しでも楽をしたいというのが人情だと思いますので、今回は楽にstage3をダウンロードする方法を考えてみます。

方法

最新のstage3ファイルのpathはこのようなフォーマットで latest-stage3-${ARCH}.txt というファイルに書かれています。

root@sysresccd /mnt/gentoo % curl -L 'ftp://ftp.jaist.ac.jp/pub/Linux/Gentoo/releases/amd64/autobuilds/latest-stage3-amd64.txt'
# Latest as of Sun, 27 Dec 2015 12:30:01 +0000
# ts=1451219401
20151225/stage3-amd64-20151225.tar.bz2 249949601

そこでgrepを使って # で始まる行を除外し、awkを使ってスペースで区切られた1つ目のフィールドを取り出すことでstage3ファイルのpathを得ることができます。

curl -L 'tp://ftp.iij.ad.jp/pub/linux/gentoo/releases/amd64/autobuilds/latest-stage3-amd64.txt' -s | grep -vE '^\s*(#|$)' | awk '{print $1}'

したがって、このようにすればいつでも最新のstage3ファイルを得ることができます。

root@sysresccd /mnt/gentoo % MIRROR='ftp://ftp.jaist.ac.jp/pub/Linux/Gentoo'; curl -LO "${MIRROR}/releases/amd64/autobuilds/$(curl -L ${MIRROR}/releases/amd64/autobuilds/latest-stage3-amd64.txt -s | grep -vE '^\s*(#|$)' | awk '{print $1}')"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  238M  100  238M    0     0  6255k      0  0:00:39  0:00:39 --:--:-- 8091k

これで#gentooinstallbattleが少し楽になりますね!

ssmjp で Gentoo の話をしてきました

先週の話ですがssmjp 2015/09の回におじゃましてきました。

「一緒にプロダクション環境でのGentoo勉強会」やりましょう!という話を現実にしてくださった@usaturnさん、そして初参加&&初登壇&&Gentooネタという暴挙(?)を広い懐で受け入れてくださった #ssmjp の皆様、本当にありがとうございました!

内容とか

以前会社のblogに書いた「自社サービスをGentoo Linuxのパッケージ形式であるebuildでパッケージングしてdeployする」という話をベースになぜそのような選択に至ったかなどをお話させていただきました。

techlog.mvrck.co.jp

当日のスライドはこちらにアップロードしております。

www.slideshare.net

オフィシャルblogでのGentooカミングアウトに留まらず発表の場までいただきありがとうございました!
おかげさまで無事フラグを回収できました。

普通のScalaアプリケーションをebuildでdeployする

会社ではほとんどのアプリケーションをScalaで開発しさくらのクラウドやハウジング環境で運用しているのですが、どんな言語で開発するにせよどのような環境で運用するにせよ、当然ながらアプリケーションはdeployする必要があります。

deployに関しては色々な方法があると思うのですが、私は「ミドルウェアのインストールやアップデートと同じように自社プロダクトもパッケージとしてdeployしたい」と考えていました。
つまりnginxやMariaDBをアップデートするように yum updateapt-get upgrade , emerge -uND world (「うどんアップデート」というらしいですね)すると自社プロダクトもアップデートされるということです。

そう!emerge !!
portageパッケージ管理システムに則ってアプリのebuildを作ればいいではないですか!!!
1日に何回も何十回もcommitがpushされる自社プロダクトで、もし都度バイナリパッケージを作るとなるとパッケージ作成自体のコストが高く感じてしまいますが、ebuildなら「GitHubのリポジトリから直接masterのHEADを取得後コンパイルしインストールする」という手順自体をパッケージングできます!
portageにはインストールすると同時にバイナリパッケージを作る機能もあるので、たとえScalaアプリのコンパイルに初回は1曲聴ける程度の時間がかかったとしても2回目以降はイントロを聴いている間にインストールできます!

ということでScalaアプリをebuildでdeployするようになってから数ヶ月経ち課題を残しつつも安定してきたので概要を書き留めておきます。

なお、世間にはGentoo Linuxでサービス運用している会社が少なくとも2社あるようです。

2000年以前はおそらくどこにも採用されていなかったことを考えると近年の導入会社数の伸び率は目覚ましく、ひとりのGentoo Linuxユーザーとしてもうれしい限りです。

流れ

例としてHelloPlayというPlayFrameworkを使ったScalaのサンプルアプリケーションをebuildでパッケージングしてみます。 インストール先はさくらのクラウドですが、今回プラットフォーム固有の機能は使っていないのでクラウドでもハウジングでも差異はありません。
また、バージョンとして下記2つを想定します。

  • 安定版である 0.0.1 → tag v0.0.1 がインストールされる
  • 開発版である 9999 → その時点のmasterのHEADがインストールされる

なおこのアプリケーションでは v0.0.1 に対して masterGET /hello というエンドポイントが追加されており、リクエストを受けるとステータス200で"Hello"というメッセージを返す機能が追加されています。
差分はこんな感じです。

f:id:mazgi:20150818223830p:plain

ebuild作成

このアプリケーションを www-apps/playscala-example というパッケージにします。
こんなebuildを書いてみました。
また、 application.conf の雛形や起動スクリプトなども作成します。

ebuild自体の差分としては開発版である 9999 には ~amd64 キーワードを指定しますが、安定版である 0.0.1 にはキーワードを指定しません
ebuild内でバージョンを判定することにより 0.0.1 ではtagを、 9999 ではmasterのHEADを取得するよう振る舞いを分けます。

if [[ ${PV} != 9999 ]]; then
    # set tag as "EGIT_COMMIT"
    EGIT_COMMIT="v${PV}"
    SLOT=$(get_version_component_range 1-2)
fi

リポジトリ登録

repositories.xmlを作成自身のportageリポジトリのrootに配置します。

内容はこのようなXMLファイルです。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE repositories SYSTEM "/dtd/repositories.dtd">
<repositories xmlns="" version="1.0">
  <repo quality="experimental" status="unofficial">
    <name><![CDATA[mazgi-experimental]]></name>
    <description lang="en"><![CDATA[An overlay by @mazgi]]></description>
    <homepage>http://mazgi.com/</homepage>
    <owner type="person">
      <email>MATSUKI.Hidenori@gmail.com</email>
      <name><![CDATA[Hidenori MATSUKI]]></name>
    </owner>
    <source type="git">git://github.com/mazgi/portage-overlay.git</source>
  </repo>
</repositories>

このrepositories.xml/etc/portage/repos.confに今回はmazgi-experimental.confという名前で配置します。
内容はこんな感じです。

$ cat /etc/portage/repos.conf/mazgi-experimental.conf
[mazgi-experimental]
location = /var/lib/portage/repo.data/mazgi-experimental
sync-type = git
sync-uri = git://github.com/mazgi/portage-overlay.git
auto-sync = yes

またScalaアプリケーションをsbtでビルドするようebuildを書いたので、sbtが必要になりますが、sbtのebuildパッケージも作成して同じリポジトリに入れています。
普通にsbtのebuildとして使えますのでもし必要でしたら上記の設定を行って emerge sbt-bin してみてください。

インストール

まずは sync して先ほど設定したリポジトリを取得します。

$ sudo emaint sync -r mazgi-experimental
>>> Syncing repository 'mazgi-experimental' into '/var/lib/portage/repo.data/mazgi-experimental'...
/usr/bin/git pull
Already up-to-date.
=== Sync completed for mazgi-experimental

Action: sync for repo: mazgi-experimental, returned code = 0

またJDK周りのUSEフラグを必要に応じて変更しておきます。

$ sudo flaggie dev-java/oracle-jdk-bin -awt -fontconfig
$ sudo flaggie dev-java/icedtea-bin -X -alsa -cups

ここまでやって emerge playscala-example すると下記のようにJDKやsbt等必要なパッケージを含めて全てがリストアップされます。

$ sudo emerge -uav playscala-example

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N     ] media-libs/giflib-4.1.6-r3::gentoo  USE="-X -rle -static-libs" ABI_X86="(64) -32 (-x32)" 0 KiB
[ebuild  N     ] app-eselect/eselect-java-0.1.0::gentoo  0 KiB
[ebuild  N     ] dev-util/patchelf-0.8::gentoo  0 KiB
[ebuild  N     ] media-libs/libpng-1.6.16:0/16::gentoo  USE="-apng (-neon) -static-libs" ABI_X86="(64) -32 (-x32)" 0 KiB
[ebuild  N     ] media-libs/lcms-2.6-r1:2::gentoo  USE="threads zlib -doc -jpeg -static-libs {-test} -tiff" ABI_X86="(64) -32 (-x32)" 0 KiB
[ebuild  N     ] dev-java/java-config-wrapper-0.16::gentoo  0 KiB
[ebuild  N     ] sys-apps/baselayout-java-0.1.0::gentoo  0 KiB
[ebuild  N     ] dev-lang/nasm-2.11.08::gentoo  USE="-doc" 0 KiB
[ebuild  N     ] dev-java/java-config-2.2.0:2::gentoo  PYTHON_TARGETS="python2_7 python3_4 -python3_3" 0 KiB
[ebuild  N     ] gnome-base/gsettings-desktop-schemas-3.14.2::gentoo  USE="-introspection" 0 KiB
[ebuild  N     ] media-libs/libjpeg-turbo-1.3.1::gentoo  USE="-java -static-libs" ABI_X86="(64) -32 (-x32)" 0 KiB
[ebuild  N     ] virtual/jpeg-62:62::gentoo  ABI_X86="(64) -32 (-x32)" 0 KiB
[ebuild  N f   ] dev-java/oracle-jdk-bin-1.8.0.51:1.8::gentoo  USE="-alsa -awt -cups -derby -doc -examples -fontconfig -javafx -jce -nsplugin -pax_kernel (-selinux) -source" 0 KiB
[ebuild  N    ~] virtual/jdk-1.8.0:1.8::gentoo  0 KiB
[ebuild  N     ] dev-java/icedtea-bin-7.2.5.5:7::gentoo  USE="-X -alsa -cjk -cups -doc -examples -nsplugin -pulseaudio (-selinux) -source -webstart" 0 KiB
[ebuild  N     ] virtual/jdk-1.7.0:1.7::gentoo  0 KiB
[ebuild  N    ~] virtual/jre-1.8.0:1.8::gentoo  0 KiB
[ebuild  N     ] virtual/jre-1.7.0:1.7::gentoo  0 KiB
[ebuild  N     ] dev-java/sbt-bin-0.13.7:0.13::mazgi-experimental  0 KiB
[ebuild  N     ] www-apps/playscala-example-0.0.1:0.0::mazgi-experimental  USE="autoclean symlink -doc" 0 KiB

Total: 20 packages (20 new), Size of downloads: 0 KiB
Fetch Restriction: 1 package

The following keyword changes are necessary to proceed:
 (see "package.accept_keywords" in the portage(5) man page for more details)
# required by www-apps/playscala-example-0.0.1::mazgi-experimental
# required by playscala-example (argument)
=virtual/jdk-1.8.0 ~amd64
# required by www-apps/playscala-example-0.0.1::mazgi-experimental
# required by playscala-example (argument)
=virtual/jre-1.8.0 ~amd64

The following license changes are necessary to proceed:
 (see "package.license" in the portage(5) man page for more details)
# required by virtual/jdk-1.8.0::gentoo
# required by virtual/jre-1.8.0::gentoo
# required by www-apps/playscala-example-0.0.1::mazgi-experimental
# required by playscala-example (argument)
>=dev-java/oracle-jdk-bin-1.8.0.51 Oracle-BCLA-JavaSE

Would you like to add these changes to your config files? [Yes/No] 

JDK 1.8 のmaskを外し、Oracle JDKのライセンスに同意し、インストールを進めます。

$ sudo dispatch-conf
$ sudo emerge -uav playscala-example

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N     ] app-eselect/eselect-java-0.1.0::gentoo  0 KiB
[ebuild  N     ] dev-java/java-config-wrapper-0.16::gentoo  0 KiB
[ebuild  N     ] sys-apps/baselayout-java-0.1.0::gentoo  0 KiB
[ebuild  N     ] dev-java/java-config-2.2.0:2::gentoo  PYTHON_TARGETS="python2_7 python3_4 -python3_3" 0 KiB
[ebuild  N f   ] dev-java/oracle-jdk-bin-1.8.0.51:1.8::gentoo  USE="-alsa -awt -cups -derby -doc -examples -fontconfig -javafx -jce -nsplugin -pax_kernel (-selinux) -source" 0 KiB
[ebuild  N    ~] virtual/jdk-1.8.0:1.8::gentoo  0 KiB
[ebuild  N    ~] virtual/jre-1.8.0:1.8::gentoo  0 KiB
[ebuild  N     ] dev-java/sbt-bin-0.13.7:0.13::mazgi-experimental  0 KiB
[ebuild  N     ] www-apps/playscala-example-0.0.1:0.0::mazgi-experimental  USE="autoclean symlink -doc" 0 KiB

Total: 9 packages (9 new), Size of downloads: 0 KiB
Fetch Restriction: 1 package

Would you like to merge these packages? [Yes/No] 

インストールできたら application.conf を作成し、startしてみます。

$ sudo cp /etc/playscala-example/application.conf{.example,}
$ sudo /etc/init.d/playscala-example start
 * Starging playscala-example ...                                                     [ ok ]
$ /etc/init.d/playscala-example status
 * status: started
$ curl -L 'localhost:9000/' -o /dev/null -w '%{http_code}\n' -s
200

無事 / へのGETが200を返すことを確認できました!

アップデート

安定版である 0.0.1 がインストールできました。

$ curl -L 'localhost:9000/hello' -o /dev/null -w '%{http_code}\n' -s
404

しかしながら 0.0.1/hello へのGETが404になってしまいます。 そこで、今度は開発版の 9999 にアップデートしてみます。

9999 は特定のtagを参照しているわけではなくemergeした時点でのmasterのHEADがインストールされます。

$ sudo emerge -uavq \=www-apps/playscala-example-9999
[ebuild  NS   ] www-apps/playscala-example-9999 [0.0.1] USE="autoclean -doc symlink" 

The following keyword changes are necessary to proceed:
 (see "package.accept_keywords" in the portage(5) man page for more details)
# required by =www-apps/playscala-example-9999 (argument)
=www-apps/playscala-example-9999 ~amd64

Would you like to add these changes to your config files? [Yes/No] 

Autounmask changes successfully written.

 * IMPORTANT: config file '/etc/portage/package.accept_keywords/00_default' needs updating.
 * See the CONFIGURATION FILES section of the emerge
 * man page to learn how to update config files.

~amd64 でマスクされていますので外します。

$ sudo dispatch-conf

マスクを外したら改めてemergeします。

$ USE="-symlink" sudo emerge -uavq \=www-apps/playscala-example-9999
[ebuild  NS   ] www-apps/playscala-example-9999 [0.0.1] USE="autoclean -doc -symlink" 

Would you like to merge these packages? [Yes/No] 

このパッケージは /var/lib/playscala-example/versions 以下にバージョン毎にsymlinkを作る構造になっているのでsymlinkを貼り替えます。

$ cd /var/lib/playscala-example/versions
/var/lib/playscala-example/versions ~
$ sudo rm current
$ sudo ln -s playscala-example.9999.957b03072271df6586c1e6db8b2b76b4be5e3f08 current
$ sudo chown play:play -h current
$ ls -l
total 4
lrwxrwxrwx 1 play play  63 Aug 31 16:19 current -> playscala-example.9999.957b03072271df6586c1e6db8b2b76b4be5e3f08/
drwxr-xr-x 1 play play 100 Aug 31 03:10 playscala-example.0.0.1.9e023916c4c911408145ff5f181a42543fbced4a/
drwxr-xr-x 1 play play 102 Aug 31 16:12 playscala-example.9999.957b03072271df6586c1e6db8b2b76b4be5e3f08/

サービスを再起動します。

$ sudo /etc/init.d/playscala-example restart
 * Stopping playscala-example ...                                                     [ ok ]
 * Starging playscala-example ...                                                      [ ok ]
$ sudo /etc/init.d/playscala-example status
 * status: started

/hello へのGETが通るようになったか確認してみます。

$ curl -L 'localhost:9000/' -o /dev/null -w '%{http_code}\n' -s
200
$ curl -L 'localhost:9000/hello' -w '\n%{http_code}\n'
Hello
200

無事アップデートされ /hello へのGETが200を返すことが確認できました!

まとめのかわりに

以上、さらっと普通のScalaアプリケーションをebuildでdeployする方法を書いてみたのですが、これ、「よーし!当社もGentooにしたしちょっとebuild作成に挑戦するぞ!」っていう方にとっては暗黙知が多すぎて伝わらないですね。

自分でフラグ立ててしまったので回収しつつ、もう少し順を追って書いてみようと思います。

まずは自社サービスのebuild化とdeployについて会社のブログに書くところからかな...!

さくらのクラウドで普通のゲートウェイサーバーを構築する

会社では相変わらずさくらのクラウド上で色々やっていますが、以前のGentooの記事が好評だったので今回も同じくGentooでいこうと思います!

今回は図のような構成でごく普通のGatewayサーバーを構築し、矢印で示したサーバーがインターネットに出られるようにします。

f:id:mazgi:20150814211433p:plain

まずはカーネルのコンフィグレーションですが、CONFIG_IP_NF_TARGET_MASQUERADEを有効にしておきます。

[root@gateway-left] # uname -a
Linux gateway-left 4.0.5-gentoo #1 SMP Fri Aug 14 20:27:22 JST 2015 x86_64 Intel(R) Xeon(R) CPU E5-2640 0 @ 2.50GHz GenuineIntel GNU/Linux
[root@gateway-left] # zgrep CONFIG_IP_NF_TARGET_MASQUERADE /proc/config.gz
CONFIG_IP_NF_TARGET_MASQUERADE=m

またsysctlnet.ipv4.ip_forward1に設定します。

[root@gateway-left] # sysctl -p
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1

iptablesはこんな感じにしてみます。
なお、eth0がWAN側インタフェース、eth1がLAN側インタフェースです。

[root@gateway-left] # iptables -L -v
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
  671  100K ACCEPT     all  --  any    any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  lo     any     anywhere             anywhere
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere
    1    60 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:22 ctstate NEW limit: up to 2/min burst 3 mode srcip-dstip
    0     0 DROP       tcp  --  any    any     anywhere             anywhere             multiport dports epmap,netbios-ssn,microsoft-ds
    0     0 DROP       udp  --  any    any     anywhere             anywhere             multiport dports epmap,netbios-ns,netbios-dgm,microsoft-ds
   15   764 LOG_AND_DROP  all  --  any    any     anywhere             anywhere

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
   36 12342 ACCEPT     all  --  eth1   any     anywhere             anywhere
   31 21996 ACCEPT     all  --  eth0   any     anywhere             172.x.0.0/16

Chain OUTPUT (policy ACCEPT 506 packets, 66758 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  any    lo      anywhere             anywhere
    0     0 LOG_AND_DROP  all  --  any    eth0    anywhere             255.255.255.255

Chain LOG_AND_DROP (2 references)
 pkts bytes target     prot opt in     out     source               destination
   15   764 LOG        all  --  any    any     anywhere             anywhere             limit: avg 1/sec burst 5 LOG level warning prefix "(IPTABLES_DROPPED)"
   15   764 DROP       all  --  any    any     anywhere             anywhere

natテーブルはこんな感じで。

[root@gateway-left] # iptables -L -v -t nat
Chain PREROUTING (policy ACCEPT 2155 packets, 139K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain INPUT (policy ACCEPT 1 packets, 60 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 30 packets, 1931 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 30 packets, 1931 bytes)
 pkts bytes target     prot opt in     out     source               destination
   11 10788 MASQUERADE  all  --  any    eth0    anywhere             anywhere

Gateway経由でインターネットにでる各サーバーの設定はこんな感じです。
172.x.y.zがGatewayのIPアドレスです。

$ cat /etc/conf.d/net.eth1
config_eth1="172.x.a.b/16"
routes_eth1="default via 172.x.y.z"
dns_servers_eth1="172.x.v.1 172.x.v.2"
dns_domain_eth1="example.com"

以上、お手軽ですね。

ところでさくらのクラウドにはVPCルーターというアプライアンスが用意されており、これを使うともっとお手軽にネットワークを構築することができます。

VPCルータ | さくらのクラウドニュース