Unyablog.

のにれんのブログ

Ansible で大量のホストに対して実行する場合のメモリ対策

Ansible で大量のホストを対象として Playbook を実行すると、大量の変数を保持する結果、メモリが足りなくなることがある。

以下はその対策。

gather_subset を用いて収集する fact を制限する

Ansible は gather_facts(または setup モジュール)で大量の fact を取得するが、これを必要最低限にすることでメモリ使用量を抑えることができる。

gather_subset という setup モジュールのオプションを使う。

gather_facts: no
tasks:
- name: Gather facts
  setup:
    gather_subset: min

serial を用いて数回に分けて PlayBook を実行する

serial: 150 とすることで 、150ホストごとに PlayBook が走る。

使い終わった巨大な変数は初期化しておく

serial にしていても PlayBook の実行ごとにメモリ使用量は増えることがある。

このような場合は、PlayBook の最後で巨大な変数を初期化する(最終手段っぽい)。

tasks:
- name: Save large output
  command: command_outputs_large_text
  register: large_output
  
...

- name: Init values
  set_fact:
    large_output: !!null

systemd 240 と Java の OOM

ArchLinux 上で Debian stretch を systemd-nspawn で立ち上げているのだが、最近 pacman -Syu したら Debian のコンテナで Java が立ち上がらなくなった。

原因

だいたいここに書いてある。

  1. systemd 240 で RLIMIT_NOFILE が大きくなった
  2. Debian の PAM では、RLIMIT_NOFILE (hard nofile)を PID 1 からコピーしている
  3. なので、ログインセッションなどでも RLIMIT_NOFILE が大きくなった
  4. ところで、Java は起動時に RLIMIT_NOFILE 分の配列を作成する
  5. このような環境だと RLIMIT_NOFILE が大きすぎるので OOM で落ちる

というもの。

Debian sid も systemd 241 なのに落ちなくてなぜだろうなと思ったら、そもそも hard nofile limit がそんなに大きくなかった。

大きくならないように、ビルド時にフラグをつけるようにしたらしい。

Arch で ulimit -H -s するとめちゃくちゃ大きかったので、特に触ってないのでしょう*1

どうするか

/etc/security/limits.conf.d に hard nofile をそれなりの値に戻すような config を置く。

今回は /etc/init.d/hogehoge なスクリプトを立ち上げるだけなので大丈夫だが、 ssh でのセッションとかでも対処するなら UsePrivilegeSeparation あたりを変えないといけないらしい(未検証)。

おまけ

この事象は systemd が立ち上げるプロセスには関係せず、pam_limits.so を経由するものに関係がある。

今回、 Elasticsearch では動いたのに Jenkins で動かなかったのは何故だろうと調べていたら、Jenkins は今も /etc/init.d/jenkins なので su 経由で起動し、PAM の影響を受けるということだった。

こういうところで違いが出るんだなあ。

*1:Arch は PAM で PID 1 をコピーしてないので(未確認)、そのような問題は起きないのだと思う(未確認)。今回は systemd-nspawn で Debian を立ち上げたために起こった。

レポジトリから直接ダウンロードした deb ファイルを自分で検証する

apt ではなく dpkg を直接インストールするとき、 http://security-cdn.debian.org/ 等から直接 dpkg をダウンロードする。

HTTPで取得した dpkg が改ざんされていないか気になったので自前で検証してみた。

具体的な構造は以下が詳しい。

kmuto.jp

GPG Key をインポート・信頼

$ sudo apt-key list # 今 apt で使っている key を見る。ここにあるものは信頼できるだろう。(一応 fingerprint を見て確認しても良いかも)
$ gpg --import /etc/apt/trusted.gpg.d/~.gpg
$ gpg --edit-key <key id> # import したものを ultimately trust する

Release ファイルの検証

いくつかの key で署名されていたので、複数 import して確認した。

$ gpg --verify Release.gpg Release

Packages のハッシュ確認

Release の中に Packages ファイルのハッシュが記載されているので、あってるか確認する。

deb のハッシュ確認

Packages の中に deb ファイルのハッシュが記載されているので、あってるか確認する。

ここまででエラーがなければ deb ファイルが検証された、と思う(多分!!

mackerel-plugin-strongswan を作った

Mackerel アドベントカレンダーが空いていたので、半年ほど前に作ったプラグインの話を軽くします。22 23日目の記事です*1

qiita.com

昨日は sfujiwara さんで、「Mackerel と連携する外形監視エージェント maprobe でマネージドサービスのメトリック収集を自動化する」でした。

sfujiwara.hatenablog.com

作ったもの

  • mackerel-plugin-strongswan

github.com

これは何

strongSwan という広く使われている IPSec 実装があります。

このプラグインは、 strongSwan の IKE デーモンである charon のインターフェースである vici を用いて、アドレスプールの状況や確立された SA (Security Association) の数を出力するものです。

vici は 5.4.0 からデフォルトで有効になっていますが、 swanctl を使わないパッケージの場合は無効になっていて使えないことがあるかもしれません。

libreswan には vici はないので使えません。

作った理由

SA の状況を監視したかったのですが、無かったので作りました。貼ってる SA の数が上限する様子を見て楽しんでいます。

f:id:nonylene:20181223010228p:plain

0 -> 1 になっているのは端末から接続したからですね。 1 -> 2 になってるのは常時接続しているルーターが reboot したからです。このルーター不安定でたまに reboot するのですが、その様子がよく分かります。

技術的な話

Python3 で書いています。公式に提供されているバインディングPython, Ruby, Perl だったので Python にしました。設置する場合は pipenv installpip instsall して vici モジュールを入れてください。

strongswan/src/libcharon/plugins/vici/python at e4a3ef2e4da28e4553262f4cc91f0b3e17066a71 · strongswan/strongswan · GitHub

コード自体は、 vici モジュール経由で API を叩いてメトリックにしているだけなので単純です。

mackerel-plugin-strongswan/main.py at master · nonylene/mackerel-plugin-strongswan · GitHub

その他

strongSwan は ipsec.conf に設定を書いていくという形式*2でしたが、新しく swanctl というのが開発され、strongswan.conf と同じ形式で非常に分かりやすく & 書きやすくなりました。今のところ困る点もなく使えており、おすすめです。

例えば、 left right というどっちがどっちか良く分からない名前も、localremote になっています。

wiki.strongswan.org

ちなみに、 swanctl 内部では vici を使って charon とやり取りしています。

*1:初め22日目だと勘違いしていた

*2:FreeS/Wan 由来

脱 PuTTY をしようとした話

この記事は KMCアドベントカレンダー 11日目の記事です。

adventar.org

昨日は id:nakario_jp さんで、「KMCとボードゲーム超人ロック」」 でした!

nakario.hateblo.jp

WSL で脱 PuTTY しようとして便利に暮らしているが、 Windows 側のツール群はまだ無理そうだという話をします。

PuTTY の機運

PuTTYWindows における SSH Client として定番で、今まで使っていた。

そんな中、他の OS では OpenSSH を使い慣れており、 Windows だけ違うのは面倒だった。

OpenSSH と PuTTY の違い

OpenSSH と PuTTY では色々と違っていて、

などなど*1

OpenSSL / OpenSSH に関する PuTTY の言い分も多少分かるが、普段使っているものと統一したい。

また、設定画面の文字が小さくて高 dpi だと目が疲れるという問題も割とある…。

f:id:nonylene:20181222235812p:plain

SSH Client としての WSL

ということで、「SSH Client + tty」としての用途では WSL (Windows Subsystem for Linux) を使うことにした。mingw とかでもいいのだけど、

  • クライアントとして使うだけなら Windows のファイルに触る必要はない
    • むしろ Linux 側の config で Windows 側のホームを汚さなくて良いとも言える
  • そこそこちゃんとした Ubuntu 環境で使える
    • mingw 特有の知識が不要、既存のツールが使える

といった理由で選ばなかった。

ただ、WSL 特有の困りは多少あって、October update かかるまで ssh-agent がエラー吐いてて辛かった*2

github.com

Windows のデフォルトのコンソールは微妙なので、 WSLtty という mintty が作っている WSL 用のアプリケーションを使っている。

github.com

基本的に mintty なので、ターミナルエミュレータ面ではほとんど困っていない*3。tmux 等もちゃんと使えて便利。

WSL 側で Port forwarding しても、ちゃんと Windows 側の Chrome で見れる。

Windows 側どうするか

これで PuTTY は不要、めでたしめでたし…ではなく、 git や scp を Windows 側で使うときの問題がある。 WSL の中で ssh-agent を立ち上げていても Windows 側からは見えない。

なので、 git bash からは毎回パスフレーズを打つはめになってしまっていた。

WSL 側で Windows 側の ssh-agent を使う

WSL 側で ssh-agent を立ち上げずに、 Windows 側のを使うという方法。以下のような変換してくれるものがあるので、これを使えばいけそう。

github.com github.com

今回は結局使っていない。

Windows 側で別に立ち上げる

Pagent を使えば解決するが、今回は脱 PuTTY をしたいので Microsoft が最近開発している OpenSSH を使ってみる。

https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_overview

この機能を使うと、cmd.exe や PowerShell で OpenSSH コマンド群が使える。

インストールしたら ssh-agent のサービスが入っているので、これを有効にすれば ssh-add なども使えるようになる!!すごい!!

f:id:nonylene:20181222233324p:plain

…のだけど、まだ WinSCP がこれに対応していなかった。 バグトラッカーにはある状態。

winscp.net

一応 scp コマンドは cmd.exe から使えるが、 WinSCP のほうが便利なので脱 PuTTY は先になりそう*4。まあ Pagent 使うだけなら追加するだけだし目が疲れないのでいいか…。

ちなみに git bash では

$ /c/WINDOWS/System32/OpenSSH/ssh -tt ...

としたら agent も認識して接続できた。(が、Ctrl-D などが使えない?)

補足

cmd.exe の ssh が使えるなら cmder なり使えば ssh-agent が2つ必要な問題は解決では?

それでも良いのだけど、Linux / Ubuntu の環境の方が慣れているので。mingw にしなかったのと同じような理由。

今日は何日ですか?

平成30年12月22日です。今23日になりました。

まとめ

結局 PuTTY を完全に脱することはできず、 Pagent (+ PPK) は使うことになった*5

結局言いたかったのは WSL + WSLtty が便利ということです。

遅刻してすみません

明日は id:yamunaku さんで、「競プロコンテストサイトを7つぐらいまとめる」だそうです!どのような記事になるか楽しみですね…!*6

yamunaku.hatenablog.com

yamunaku さんのアイコンは「はたらく UFO」ですね。自分は結構前に全部クリアしました!! HAL 研開発の買い切りスマホゲームでおすすめです。

play.google.com

ところでおすすめの曲があって、「more one night」っていうんですけど、おすすめです。最近は「ローリング△さんかく」もよく聞いてます。

*1:そもそも CUIGUI という違いもある

*2:しかも昔開発者モードをオンにしていたので無限にアップデート失敗していた

*3:極稀に再起動しないと再描画されないことがあるが、 mintty 側か WSLtty 側なのかは不明

*4:WinSCP に OpenSSH 形式の鍵を渡すと PPK に変換されるので、脱 PPK もできない

*5:実は Windows であまり開発しないこともあって、この記事を書くときに初めて Microsoft の OpenSSH を見た

*6:11日前から存在しています

tmux の if-shell は sh で実行される

tmux の if-shell ではシェルコマンドの結果に応じて実行するコマンドを変更できる。

今までここにバージョンによって設定を変化させるように書いていたが上手く動いていない時があった。

if-shell "[[ `tmux -V` =~ 2.[1-9]$ ]]" "set -g mouse on"

理由

tmux は sh -c でシェル部を実行しているため、 sh の実装が bash でない場合は [[ が使えない。*1

tmux/job.c at ddffda4da55e2d4040c981bfb5257c4f7281000f · tmux/tmux · GitHub

Fix

[ など、 sh でも使えるような(POSIX に準拠した)スクリプトに修正する。

今回は grep を使うようにした。

if-shell "tmux -V | grep -q '2.[1-9]'" "set -g mouse on"

github.com

間違えて yes を入れたときに、終了するために ps 見てたら sh -c yes が起動していたので気づいた。

*1:今回は dash だった

ISUCON8 予選・本選に参加しました(チーム名 :thinking_face:)

3年前から参加している ISUCON の、予選と本選に行ってきた。

結果を先に書くと、 5981 点で学生5位、全体では14位だった。

チーム

ざっくり自分がインフラ担当、 utgw が SQL 等の改善、 wass がアプリケーションの改善と方針立てをやっていた。

予選

自分が二人とチーム組むのは初めてだったので二回ぐらい練習して挑んだ。

utgwkk.hateblo.jp

↑は utgw の記事。

自分は

  • サーバーのセットアップ
  • h2o を Nginx に
  • MariaDBMySQL 5.7 に移そうとして失敗
    • 確か未定義動作の動作が違っていた
  • 複数台構成
  • 見守り
    • レスポンス比べるとか
  • ベンチマーカーへの祈り

といったことをやっていた。現代は Systemd なので CentOS でも大体いける。

アプリはほとんど見ていなかった。チームメイトに感謝。

本選

scrapbox.io

↑ は wass の記事。

github.com

↑のレポジトリの Your Name が大体自分。

タイムライン

前日

  • 新幹線が遅延したので21時ごろに東京着
  • カプセルに止まったらいびきステレオ環境だった
    • 結局頑張って4時間ぐらい寝た

09:10 頃

新宿につく。バスタのコンビニで菓子買おうとしたら混雑していたので諦める。

09:30 前

会場に到着。標準的なテーブルを獲得。物理的な準備をする。

f:id:nonylene:20181022191824j:plain

10:00

開始。なるほど isucoin! 仮想通貨ネタ!

まずはドキュメントを読み、 tmux-cssh を使って鍵配布やアカウント作成を行う。 雑な shell script ぐらいは用意しておいても良かったかもしれない。

10:30

  • firewall 止める、ulimit 解除する、 pt-query-digest 入れるあたりのことをやる。
    • ちなみに docker-compose で行くなら ulimit は解除しなくても良かった。
  • 全体的な構成をざっくり見る。 docker-compose で立ち上がってるのを見て脱出を検討する。

Restart したら iptables がどうのこうのと出てさっぱり分からなかったので脱出を決定*1

とりあえず本体である

  • isucoin 本体
  • MySQL
  • Nginx

を脱出することに。

isucoin 本体

Python だけを systemd unit に切り出した。 pipenv なのでやるだけ *2 だったのだけど、使ってる Python が 3.7 だったのでコンパイルした *3

作業してるとコンパイルが微妙に早いホストと遅いホストがあった*4ので早いホストに MySQL 入れることに。

isucoin-python.service · wass88/isucon8-final@1eeb658 · GitHub

MySQL

MySQL は 8.0 だった。 予選の段階で 8.0 が yum でサクッと入っているのは分かっていたので入れる。

ただ、 my.cnf.d 読んでくれなかったり、 8.0 はオプションがちょくちょく違ったりで困った。validate_password で色々とハマるとか*5

データの流し込みとかはサクッとできた *6

Nginx

特に困らなかった。 upstream がなくて link でやってるのはへ〜って思った。

これらの作業が全て終わったのが 12:40 ほど。

f:id:nonylene:20181022191026p:plain

12:45

昼飯。

13:15〜

見つけたところから色々やっていく。

  • Nginx で静的ファイル送信
  • keepalive
  • http2
  • MySQL ホスト分離・メモリ増やす・スロークエリ出すなど
  • アプリケーション複数台構成
  • initialize を各ホストにくばる
  • worker 増やす
  • Nginx でセッションごとの振り分け(sticky)できるようにコンパイルし直す

その他諸々。複数台を除くと顕著な効果はなくて、他のネックが解消された際に困らない程度だと思う。

たまにペアプロを手伝ったりもした。アプリケーション側の改善のおかげで点数が上がっていった。

終盤(16:30~)

終盤は htop とか見ながら、ペアプロで手伝いをしていた。

最後再起動試験をし、 share を有効にしてみて fail し、 BAN を実装しかけて fail し、5分前に差し戻して終了。

5981 点で学生5位、全体では14位だった。まあまあですね。

f:id:nonylene:20181022192735p:plain

反省

Docker の切りだし

Docker の切り出しには2時間かかった。

その間は(iptables のエラー出てて)ベンチ回せず他の所を見てもらっていた。その時間ベンチできてれば伸ばせたかもしれない。

ただ、Docker 切り出した後構成関係で詰まることはなかったので、個人的には良かったと思っている。

Docker も docker-compose も、触りぐらいしか触ったことないので本格的に触らないとな〜〜〜〜と言い続けている。妙な苦手意識が未だにある。

Share

Share はもう少し早く見るべきだった。最後の15分ほどでアクセス大量に来て落ちたのを見て止めたけど、他のチームが 1/3 ぐらい返していたという話を聞いて、なるほど〜〜〜〜〜 AB テスト〜〜〜ってなった。

アプリケーション

自分は Python も Go も触るので非同期処理をしている様子をもう少し手伝うべきだった。 Nginx に sticky を入れたりはもう少し様子見てからでよかったのでは?

インフラ方面は大体やることやったので満足している。

その他感想

  • 3年ぶりの本選ですが、学生のレベルが優勝するほど高くなっててすごい。
  • 鍵などの準備はしてなかったけど、あまり困らなかった。
  • 非同期したくなったときに Go か node か書く練習はするべきだな〜と思う。
  • pipenv や Python 3.7.0 が使われているのは Python 大好き人間としては嬉しかった。手数は増えたけど😇。
    • 実は Python での参戦は初めて。コードが高速に読めてよかった。
  • tmux-cssh を使ってみたらめちゃくちゃ便利だった。isucon 程度であれば ansible もなくて良さそう感。
  • 情報を表示するだけの PC を持ち込んだのは正解だった。いつでも netdata や htop を眺めることができた。

チームメイトだった id:utgwkk id:wass80 に感謝。本選でもアプリケーション面はほぼやってもらった。

楽しかったです

予選も本選も特に不満がなくて素晴らしい大会だったと思います。問題もすごく良かったです。

来年あればもちろん参加するし、今度こそ優勝したい!!

運営の皆さん、本当にありがとうございました!!!!!

*1:ちなみにこれは docker restart したら直ることに後で気づいた

*2:utgw と nonylene は pipenv をよく使っている

*3:とは言っても yum-builddep して tar 持ってきて make するだけ

*4:よくある話

*5:あのときは同じパスワードじゃないと落とされるかもなとか思ったけど、今考えたらこだわる必要なかった

*6: mysqldump に mariadb のコメントがあったときはヒヤッとしたけど、初めのクライアントがそうだからそうですね