その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

Linux Kernel 4.12以前であればhostマシンのsysctlの値がDocker container環境に引き継がれるかどうか検証した

Docker - IPVS connection timeout issue

これを読んでいたところ

From Linux kernel 4.13 onwards, sysctl default values can be modified per container basis. Container will not inherit changes from the host sysctl modified values.

とあったので,逆にhostマシンのLinux Kernelが4.12以前であればhostマシンのsysctlの値がDocker containerに引き継がれるのか? と思い検証してみました.

TL;DR

  • (手元の環境で試してみた限り) 引き継がれなかった
  • 変なことを考えず,おとなしくdocker run--sysctl オプションを使おう!!
    • Amazon ECSは早くsysctlのサポートしてくれ!!!!!

hostマシン環境

$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
$ docker -v
Docker version 18.06.1-ce, build e68fc7a

コンテナ環境

https://hub.docker.com/_/ubuntu/

ubuntu:bionicを使用.

Kernel 4.13.16でやってみる

$ uname -a
Linux moznion 4.13.16-041316-generic #201711240901 SMP Fri Nov 24 09:02:42 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ sysctl -n net.ipv4.tcp_keepalive_time # <= host
7200
$ sudo docker run ubuntu:bionic sysctl -n net.ipv4.tcp_keepalive_time # <= container
7200
$ sudo sysctl -w 'net.ipv4.tcp_keepalive_time=600' # <= ここでhostのtcp_keepalive_timeをいじってみる
net.ipv4.tcp_keepalive_time = 600
$ sysctl -n net.ipv4.tcp_keepalive_time # <= host
600
$ sudo docker run ubuntu:bionic sysctl -n net.ipv4.tcp_keepalive_time # <= container
7200

引き継がれてないですね.

Kernel 4.12.14でやってみる

$ uname -a
Linux moznion 4.12.14-041214-generic #201709200843 SMP Wed Sep 20 12:46:23 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ sysctl -n net.ipv4.tcp_keepalive_time # <= host
7200
$ sudo docker run ubuntu:bionic sysctl -n net.ipv4.tcp_keepalive_time # <= container
7200
$ sudo sysctl -w 'net.ipv4.tcp_keepalive_time=600' # <= ここでhostのtcp_keepalive_timeをいじってみる
net.ipv4.tcp_keepalive_time = 600
$ sysctl -n net.ipv4.tcp_keepalive_time # <= host
600
$ sudo docker run ubuntu:bionic sysctl -n net.ipv4.tcp_keepalive_time # <= container
7200

あれ,引き継がれないですね.

もちろんsysctlオプションを食わせながらdocker runすれば反映される

$ sudo docker run --sysctl 'net.ipv4.tcp_keepalive_time=600' ubuntu:bionic sysctl -n net.ipv4.tcp_keepalive_time # <= container
600

所感

Kernel 4.12.0とKernel 4.10.17でも試してみましたがhostマシン側のsysctlがcontainerに引き継がれているようには見えませんでした.なんか間違ってるんですかね? それとも引き継がれないのが普通?
とはいえ新しいKernel上ではhostのsysctlは引き継がれないし,やはりdocker runの--sysctlオプションで渡すのが良いでしょう.しかしAmazon ECSではsysctlオプションが対応されておらず*1……嗚呼

LinuxでもMagic Trackpad 2使いたいじゃないですか……って時

なぜかLinux Desktopで生活したくなったのでLinux Desktopで生活しているんですが (Ubuntu 18.04.1),やはり入力インターフェースは良い方が良いわけですよ.良いですか.というわけでMagic Trackpad 2を使いたいですよね.
しかし素の状態ではマシンとBluetoothで繋げないし,USBで繋いだとしてもGenericなマウスとして認識されてしまうのでめちゃめちゃ使い勝手が悪い *1.なんとかなってほしい……

というわけでこれです.

github.com

これはもともとMagic Mouse向けのドライバにMagic Trackpad 2のサポートを足したものらしく,このドライバをインストールするとちゃんとしたTouchpad HIDとして認識してくれるようになる上にBluetoothでの接続も可能となります.
インストールするにあたってはKernel 4.18以降という割と新しめのKernelが求められるので適宜バージョンアップする必要があるでしょう (Ubuntu 18.04.1はデフォルトのKernelが4.15.0だったのでエイヤとKernelをupgradeする必要があった).
ドライバのインストールに関してはREADME.mdにある通りDKMSを使う方法が一番手っ取り早いのでそれでやると良いです.


とまあそんな具合にMagic Trackpad 2がLinux Desktopで使えるようになってめでたいわけですが,しかしmacOSと完全に同じ使い味というわけにはゆかず (やはり選択する際の細かい動きやスクロール感が違う),やはり入力デバイスの良し悪しはOS側の制御と密接に関わっているのだなあと実感しました.とはいえ他の下手な入力デバイスで操作するよりは良いと思います!

*1:具体的に言うとtap to clickが効かなかったり,2本指スクロールが効かなかったりする.後者は致命的

ECS Agent 1.19.0だとDocker containerのメタ情報を取れない場合がある

表題のとおりですが,ECS Agent 1.19.0だとDocker containerのメタ情報を取れず (取れない場合がある),いろいろ困るという現象が発生します.

github.com

このissueにあるようにDocker Container IDをうまく取れないことが問題のようです.
おかげでElastic BeanstalkのDocker環境で動かしているアプリケーションが吐くログをうまく取れなくなってしまって大層困った……

なおこの問題はECS Agent 1.19.1で修正されているので,お使いの方はアップグレードしたほうが良いと思います.以上です.

Kyoto.なんか #4で最近運用しているJenkinsの情報について発表してきました

kyoto-nanka.connpass.com

表題の通り,最近AWS上で運用しているスケールする & 運用が省エネなJenkinsについて発表してきました.

簡単にまとめると

  • JenkinsのslaveをAWS CodeBuildに委譲することで実質無限のスケールアウトとメンテコスト削減を実現
  • JenkinsのストレージをAmazon EFSにすることでロバスト性と自動ボリューム拡張を実現
  • ElasticBeanstalk with Dockerを使って運用することで運用コストの省力化

という内容です.


会場やインターネットで質問されたことについては以下のとおりです:

値段的には従来のサービスを使うよりも下がったかどうか?

  • 試算的には下がっている
  • やはりCIが寝ている時間が多いと,CodeBuildの時間貸しスタイルがうまくはまって効くという感じ
  • とはいえ今後継続的にコストの実測を行って経過観察をする必要がある

強い環境でビルドしたいという話だったが,CodeBuildはインスタンスタイプを選べる?

  • 選べる
  • 3 GB メモリ、2vCPU
  • 7 GB メモリ、4vCPU
  • 15 GB メモリ、8vCPU
  • (会場ではうろ覚えで間違えたスペックを口走ったかもしれません,すみません)

CodeBuild上でのビルド環境はDockerということだったが,このDockerイメージはどこかにアップロードしておく? あとキャッシュみたいなのは効く?

  • CodeBuild上ではサポートされている言語であれば素のDockerイメージが提供されており,その上でビルドを行うことができる
  • 独自のビルド環境が欲しいのであれば自分でDockerイメージを構築してECRにアップロードして利用すれば良い
  • キャッシュについては任意のファイル (or ディレクトリ) をS3に突っ込んでキャッシュすることができるので便利
    • 例えば解決済みの node_modules のようなものをキャッシュしておくことが可能

プラグイン管理が魔界にならないか

Jenkins.instance.pluginManager.plugins.each{
  plugin ->
  println ("${plugin.getShortName()}")
}

Jenkinsは色々とランタイムを入れられて環境が汚くなる印象があるがどのように対処しているか

  • 実際のビルド環境は基本的にCodeBuild上なのでJenkinsがいたずらに汚くなることはなさそう
  • なんらかのランタイムをインストールする必要がある場合はDockerfileで構成管理するぞ,という気持ち
    • (まだその状況に至っていない)


という感じでした.参考になれば幸いです.

Kyoto.なんかはいろいろおもしろい話が聞けて楽しいですね.来年の開催も楽しみにしています!!

あるgit commitがどのpull requestでmergeされているかをAPIでシュッと取ってくる方法

というのを id:side_tana さんが探っていたので,このAPIをGETで叩くとできるよというやつです.

https://api.github.com/search/issues?q=repo:${owner}/${repo-name} pr:merged ${commit-hash}

あ,GitHubの話です.良かったですね.

JenkinsでGitHub Pull Request Builder pluginを使いつつ任意のブランチにpushしたコミットもビルドする

JenkinsでGitHub Pull Request Builder (ghprb) を使っている時に,pull request以外のcommit (例えばmasterへのマージコミットや任意のブランチへの直push) もbuildしたいんすよね〜みたいなことをid:hdkshjmさんに相談したところ良い感じの方法を教えてもらったのでメモとして記すものです.ありがとうございます!

前提として

  • ghprbの設定は済んでいる
  • Git pluginがインストールされている
  • GitHub pluginがインストールされている
  • GitHubリポジトリのWebhook設定で $JENKINS_BASE_URL/github-webhook/ に向けてpushイベントを設定している

ものとします.

そんでもって以下のようにすると良い:

  • プロジェクト設定のGit SCMのリポジトリ設定でRefspecに +refs/pull/*:refs/remotes/origin/pr/* +refs/heads/*:refs/remotes/origin/* を指定する (高度な設定から設定できる)
    • ghprbではpull requestだけがターゲットなので +refs/pull/*:refs/remotes/origin/pr/* を指定しておけば良い
    • それに加えて +refs/heads/*:refs/remotes/origin/* を指定することによって任意のブランチへのpushも引っ張ってこれるようにしておく
  • 「ビルドするブランチ」にビルドしたいブランチの名前 (e.g. master, develop and etc) を指定する
    • ghprb向けには ${sha1} とか設定されているはずなので *1,そこに追加するという感じ
  • トリガ設定で GitHub hook trigger for GITScm polling にチェックを入れる

これでOK! 例えば「ビルドするブランチ」に master を設定しておけばmasterへのマージコミットや直push (まあ野蛮!) についてもbuildを回すことができて便利です.
pull-requestについてはghprb pluginがbuildをキックし,一方で指定したブランチへのpushについてはGitHub pluginがbuildをキックするという感じです.基本的に互いが重複してbuildをキックすることは無いでしょう (「ビルドするブランチ」に指定したブランチを他のブランチに向けるpull-requestを作ったら話は別ですが).


ところでJenkins 2.0以降を使っている場合Jenkinsfile及びパイプラインが使えますから,pipeline-githubあたりを駆使するとgroovyでプログラマブルに色々操作できるため,今となってはghprbを使わずにJenkinsfileでやったほうが良いかもわかりませんね.そう思います.現場からは以上です.

*1:${ghprbActualCommit} if you want to use the head of the pull request branch (e.g. refs/pull/4/head); or ${sha1}, to use GitHub's tentative merge of the compare and base branches (e.g. refs/pull/4/merge) if the PR can be automatically merged or the head of the pull request branch (e.g. refs/pull/4/head) if they can not be automatically merged. GitHub - jenkinsci/ghprb-plugin: github pull requests builder plugin for Jenkins

Over HTTPでやり取りするAWS Lambdaのfunctionを書く時にはKeep-Aliveがパフォーマンスに効く(場合がある)

サーバレスだ! Microservicesだ! というふうなアーキテクチャになってくるとAWS Lambdaのような実行環境でコードを動かすことが多くなってくると思います.そしてそうした環境下で他のコンポーネントとHTTP越しにやりとりをするコードを動かすこともままあるでしょう.
そういった時にKeep-Aliveを有効にしておくとLambdaは一度張ったコネクションを使いまわしてくれるので,「同じエンドポイントを頻繁に叩く」かつ「呼ばれる回数が多い」Lambda functionだと結構パフォーマンスに効いてきます (もちろん接続先がkeep-aliveに対応している必要がありますが).

ということをLambdaのパフォーマンス周りのトラブルシューティングを行っている最中にふと気づき,やってみたところ果たしてパフォーマンスの問題は見事解決したわけですが,その後AWSが出しているLambdaのベストプラクティスのドキュメントを読んでみるとまさに同じことが書いてあり,やはり公式のドキュメントは強い……

> 前回の呼び出しで確立した接続を (HTTP、データベースなど) をキープアライブにして再利用します
AWS Lambda 関数を使用する際のベストプラクティス - AWS Lambda

AWS Lambdaはそのプロセスが立ち上がってからはライフサイクルに従って一定期間同一のプロセスが使用されるので,一度確保したリソースを使い回すことができます.従ってKeep-Aliveを有効にしておくと一度確立したコネクションを使いまわしてくれるため,コネクションを毎度張らずに済んでそのぶんの実行コストが減って経済的という感じです.助かった!


なお他のコンポーネントとOver HTTPでコミュニケーションするタイプのLambdaのアーキテクチャの是非についてはid:y_uukiさんのブログに良い考察があります:


ところで

この件ですがみなさんはどう呼んでいますか? おたよりをお待ちしています.