かまたま日記3

プログラミングメイン、たまに日常

Nginxで同じポートでUDPとTCPをリッスンして別のバックエンドにプロキシする

たとえばNLBを使ってUDPをロードバランシングする場合、ヘルスチェックのために、UDPをリッスンするのと同じポートでTCPをリッスンする必要があります *1

そういう場合、バックエンドがNginxの場合は以下のような map$protocol を使った方法で振り分けることが出来ます。ここでは5001番がヘルスチェック用のポートです

stream {
  map $server_port:$protocol $backend {
    5000:UDP "example.com:5000";
    5000:TCP "127.0.0.1:5001";
  }

  server {
    listen 5000 udp;
    listen 5000;
    proxy_pass $backend;
  }

  # Health check
  server {
    listen 5001;
    return "OK";
  }
}

余談

このmapでbackendを切り替える方法は。Nginxが動的にホスト名の名前解決をしてくれない問題の対策にもなります。 (httpの方でよく使う set $backend example.com と同じ効果を得られる)

*1:デフォルトの場合。設定でヘルスチェックを別ポートにすることも可能

Travis CIの設定用のTerraform providerを作った話

この記事はTerraform Advent Calendar 2019 の9日目の記事です。

私の所属しているSEQSENSEではTravis CIを主に利用しています。 CIサービスを使うにあたって、ビルドで使う環境変数SSH鍵などの管理は課題の一つです。

一つ一つ手動で設定していってもいいのですが、リポジトリ数が多くなると

  • リポジトリを横断して一括で設定を変更するのが大変
  • どのリポジトリに何のクレデンシャルが使われているのかがわからないので、うかつにRevokeすると変なところでビルドが落ちる

などの問題が発生したりします。 それを解決するためにTravis CIの設定をコードナイズして一括管理するためのTerraform providerを作成しました。

github.com

よかったら、使ってみてください! *1

使い方

これはオレオレprovider (正式名称はThird-party plugin) のため、バイナリをGitHubのReleasesから落として来る必要があります。

curlなんかを使ってCLIでインストールする場合はこんな感じでしょうか。

$ latest=$(curl -s https://api.github.com/repos/kamatama41/terraform-provider-unofficial-travis/releases/latest | jq -r ".name")
$ os=$(uname | tr '[:upper:]' '[:lower:]')
$ curl -LO https://github.com/kamatama41/terraform-provider-unofficial-travis/releases/download/${latest}/terraform-provider-utravis_${latest}_${os}_amd64.zip
$ unzip terraform-provider-utravis_${latest}_${os}_amd64.zip && rm terraform-provider-utravis_${latest}_${os}_amd64.zip

インストール後、実際のTFファイルの書き方はこんな感じになっています。

# Configure the unofficial Travis Provider (utravis)
provider "utravis" {
  base_url = "https://api.travis-ci.com/"
  token = "${var.travis_api_token}"
}

# Add an environment variable to the repository
resource "utravis_env_var" "my-repo" {
  slug = "myuser/my-repository"
  name = "FOO"
  value = "bar"
  public = true
}

# Add a private key to the repository
resource "utravis_key_pair" "my-repo" {
  slug = "myuser/my-repository"
  value = "${file("~/.ssh/id_travis_rsa")}"
}
  • プロバイダ名は utravis
    • base_url でアクセスするAPIを指定する (travis-ci.com or travis-ci.org)
    • tokenTravis CIのコンソールで取得する
  • utravis_env_var環境変数を設定するためのリソースです
    • public フラグでTravisのコンソール上で表示するかどうかを指定できます (デフォルトはfalse)
  • utravis_key_pairSSH Keyを登録するためのリソースです。 value秘密鍵の中身を指定します

注意

  • 両リソースのValueはSHA-256でハッシュ化された値をstateファイルに保存して生のデータではどこにも保存しませんが、valueを渡すまでののクレデンシャルの管理には十分注意してください *2
  • Travis CIにはブランチごとに環境変数を出し分けるEnvironment variables per branch という機能が少し前に追加されましたが未対応です

*1:そもそもTravisを会社で使ってるというのを(ry

*2:無いとは思いますが、直接tfファイルに書くなどは当然NG

AWS Savings Plans メモ

AWSのSavings Plansのセミナーに参加してきたのでそのメモ。

Fargateに対しても割引が効いたりするし、インスタンスタイプの垣根が無いので*1、そろそろM6が出そうなので、M5のRI買うのやめとこうみたいなのが発生しないのがイイですね。

Savings Plansとは?

  • AWSの計算リソース割引プラン、リザーブインスタンス(RI)より柔軟性が高い
  • 1時間あたりのコミットメント金額 に対して適用される
  • Compute Savings Plans と EC2 Instance Savings Plansがある
    • Compute Savings Plans: より柔軟なプラン。インスタンスファミリー、リージョン、OSに関わらず割引が適用。Fargateの割引もされる
    • EC2 Instance Savings Plans: 割引率が高いもの、インスタンスファミリー、リージョン、OSの指定が必要、Fargateは対応外 (今のRIと同じ)
      • 違いとしてはインスタンス単位ではなく コミットメント金額 単位で購入するという違いがある
  • 割引率は、インスタンスファミリー、Fargateによって違う(https://aws.amazon.com/jp/savingsplans/pricing/) ので、自分で計算するのは面倒。
    • Recommendationsで直近 7 or 30 or 60 日の使用量をベースに推奨値を出してくれるので、それに従うのが良い
  • 割引は一番安くなるように (割引率が高いものから順番に) 適用される
  • RDSは対象外

*1:Compute Savings Plansの場合

俺的00年代アニソン 前編

昔90年代 でやったやつの00年代版です。そろそろ2010年代も終わるのでやってみました。 今回は特にランキングは付けず思い入れのある曲を紹介していきます。紹介したいのが多くなったので続きます (たぶん..)

続きを読む

Datadog LogsをCLIでtailするツールを作った

github.com

モチベーションとしては、Datadog LogsのWebコンソールはメッセージの全文が長いと全部表示されなかったり普通のtailと違って時間の降順に並んだりで微妙に見づらかったりするので、CLItail -fコマンド感覚で見れて雑にgrepとかしたいと思って作りました。

インストール

Releases からバイナリをダウンロードしてパスを通してください。
あと多分 go get -u github.com/kamatama41/taildog でもインストールできると思います。

使い方

まず、DD_API_KEYDD_APP_KEY (application key) の2つの環境変数を設定する必要があります。DatadogのWebコンソールから取得してきてください。

全ログを追跡する

$ taildog

クエリで絞り込む

$ taildog -q "service:my-app"

一定期間のログを表示する (追跡はしない、 max 1000行)

$ taildog -q "service:my-app" --from 2019-07-10T11:00:00Z --to 2019-07-10T11:00:05Z

出力のフォーマットを変える

Goのtemplateのスタイルで記述します。使用できる項目はDatadogのLog Query APIのレスポンスのcontentの内容に準拠します。 デフォルトは "{{.Timestamp}} {{.Host}} {{.Service}} {{.Message}}" です。

$ taildog -q "service:my-app" -f "{{.Timestamp}} {{.Message}}"

注意

  • 実際にログがインジェストされてからAPIで見れるようになるまで、微妙にタイムラグ (5~30秒くらい) があります。
  • Log Query APIは300回/時間/組織のレートリミットがあるので*1、複数人で長時間使うとエラーになる可能性があります。
  • 上記の理由からデフォルトで15秒おきにポーリングするようにしていて、そこまでリアルタイム性は高くないです。

よかったら使ってみてください〜!

*1:必要に応じで拡張はできるそうです

Mercari meetup for SRE Vol. 2 に参加してきた

mercari.connpass.com

データセンタープロジェクトの進捗って言うのが面白そうで抽選通ったので参加してきました。基本的には今自分が所属している小さいスタートアップでは直接的に参考になることはあまり無かったですが、こういうスケールの大きな話を聞くのは刺激になりました。その後の懇親会では負荷試験をどうやってするかと言うのをメインで話して、みんな「やりたいけど環境作るのが難しいよね」という感じで意見が一致しました。

Percona XtraDB Clusterに寄り添う @ichirin2501

Percona XtraDB Cluster を使ってMySQLクラスタリングを一つのサービスに適用してみた話。

  • ロードバランシングにProxySQLを使おうと思ったけどはまりポイントが多くてHAProxyに落ち着いた
  • PXC5.7.16から5.7.17で10倍ぐらいの性能の差がある
  • 移行後, DBのCPU使用率は2倍になったが、もともとのデッドロックを解消したら半分になった
  • 将来的には社内RDSとして提供していく予定

Progress of Data Center Project @kazeburo

去年発表した自社DC (TC) のその後のお話

  • Google <-> TC はグローバルで繋がっていて さくら石狩 <-> TC はプライベートで繋がっている
  • Google -> TC -> さくら の場合、TCでSSL終端しそこからhttpでさくらに渡す
  • さくら -> TC -> Googleの場合 chocon をさくらとTCの2段置いて使っている
  • 16kvaを使って(?) ラックの凝縮度を上げる・それに合わせた空調も整備
  • DB as a serviceを提供するためにDB-Gatewayを作った
    • Gatewayはwebsocketをしゃべって裏のDBのプロキシをする
      • Go言語のRegisterDialを使うイメージ
    • 認証は deteco を使って行う
  • 将来的にはマルチクラウドのハブだったり金融機関との連携などでもTCを活用していく予定

DockerのUbuntuコンテナでsystemdを動かす

TL; DR

  • とりあえず --privileged をつける。つけないでいい感じで動かすのは大変そう。
  • CentOSは公式でsystemd用のベースイメージを用意してくれているので、Ubuntuを使いたい人以外はそちらを使うのが良さそう
  • STOPSIGNAL SIGRTMIN+3 をつける

FROM ubuntu:18.04

RUN apt-get update \
 && apt-get install -y \
    openssh-server \
 && rm -rf /var/lib/apt/lists/*

RUN mkdir -p /var/run/sshd && chmod 755 /var/run/sshd

ARG GITHUB_USER
# ADD ubuntu user, and set password and public key
ADD https://github.com/${GITHUB_USER}.keys /home/ubuntu/.ssh/authorized_keys
RUN useradd -u 1000 ubuntu \
 && usermod -s /bin/bash -G adm,sudo ubuntu \
 && echo "ubuntu ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers \
 && mkdir -p /home/ubuntu && chown -R ubuntu.ubuntu /home/ubuntu

STOPSIGNAL SIGRTMIN+3
CMD [ "/sbin/init" ]

例えばこんな感じのDockerfileでSSHサーバをsystemd経由で起動しようとすると、想定どおりに動作していません。 (ubuntuユーザでコンテナにSSH出来ない)

$ docker build --build-arg GITHUB_USER=${GITHUB_USER} -t kamatama41-ubuntu-systemd-test .

$ docker run -p 2222:22 -d --rm kamatama41-ubuntu-systemd-test
1faf7f57aabba3ccb935cbc3de84224f304021c87a31a7487164a2ac157e33b1

$ ssh ubuntu@localhost -p 2222
ssh_exchange_identification: Connection closed by remote host 

docker runのときに --privileged オプションを付けると想定通りの動きになります。

$ docker run -p 2222:22 -d --privileged --rm kamatama41-ubuntu-systemd-test
f4adaea692edd55bdc059536cebe3b5aac03d842af33c0b902bb79ccb1251e3a

$ ssh ubuntu@localhost -p 2222                                             
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.9.125-linuxkit x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

ubuntu@f4adaea692ed:~$ 

とりあえず、テスト用途で動かす場合はこれで大丈夫そうですが、本番では使わない方が良いでしょう。ググった感じsystemdをnon-privilegedなUbuntuのコンテナで動かすのは結構大変そうです。

CentOSは公式でsystemd用のベースイメージを提供してくれているので、本番で使いたい場合はこちらを使うのが良いでしょう。

あと1点注意点として、systemdのコンテナを止めるときは SIGRTMIN+3 を使わないといけないようなので、 STOPSIGNAL を変えてあげておきましょう。