ssmjp 2019/03 ヤマサキ春のサメ祭り へ行ってきました

アウトプットしないのは知的な便秘!ということで、アウトプット枠にて とても久しぶりにssmjpに行きましたが、ssmjpらしい回でした。

サメ祭りということで

  • サメの話
  • サメじゃないサメの話
  • 運用自動化の話
  • JAWSDAYSの話

という内容でしたl

内容とか雰囲気はtogetterにまとまっているのでいいとして、さくっと感想とかを。

サメの話

古今東西サメ映画の話。

初代ジョーズくらいは見たことありましたが、ホラー映画が苦手なのもあって全然サメ映画見てなかったのですが、

ネタ枠などとても幅広い映画が存在することを知った日になりました。

また、サメ映画に対する愛がとても感じられる発表でした。

シャークネード海底47mが初心者にお勧めらしいのでサメ映画に入門したい方はぜひ!

サメじゃないサメの話

今回の発表のために、愛知県豊根村までチョウザメ養殖場見学とチョウザメを食してきたという発表。

地元の近くやな?いけるかな?と思ったけれど、チョウザメ料理は団体予約が必要らしい。

村の人口が1100人くらいなのに、10人でそれより多くのチョウザメを育ててるの、凄いですね。

味はタイと河豚のあいのこみたいだけれど小骨が多いのが玉に瑕という、いつになったら役に立たつのかわからないとてもいい話を聞けました。

蓬莱泉の空が紹介されていましたが、こちら、特約店的なところにしかおりてこない、年1回か2回の販売しかされない。という微妙に手に入りにくい酒なのですがとてもおいしいです。東三河の地酒置いてるところで飲めることがあるので見つけたら飲んでみることをお勧めします。

蓬莱泉といえば、設楽と豊田のほうで、(日本酒量り売り もしているので、近くに行く機会があればそちらも是非。季節によって違うお酒を量り売りしてます。

運用自動化の話

うなずく人と、そうでない人で二極化してた話。

波多野さんは、運用自動化に割と積極的な人という印象がありますが運用自動化に反対してると思っている方もいるくらい、 ダメな運用自動化を批判してる方でもあります。

そんな波多野さんが良い運用自動化について引き続き話をしていました。

運用自動化の効果をきちんと定量的に測定しているケースが少ないという話が胸に刺さったり、しつつ、なるほどなぁと話を聞きました。

個人的な経験でも指標を持って効果の測定をするという経験が確かにほとんどなく、確かに楽になったねとか、 いつも2,3日かかっていたものが1日でユーザに完了連絡できるようになったね、みたいな肌感だけで進んでいて、ちゃんと測定はしてなかったなぁと反省しました。

そういう、効果を測定することで、評価してもらいやすくもなりそうなので、これからはきちんと、測定も行っていきたいと思いました。

JAWSDAYSの運用の話

JAWSDAYSがどう開催されたのか、その裏側についての話。

物理的な配置から予算やスケジュールの話など、盛りだくさんな話でした。

タスクやスケジュール管理については、チームにあったものを選ぶべきだという話があったり、

会場の無線回線の安定稼働はやっぱり難しいという話があったり、

スポンサー来てくださいって全体アナウンスするだけだとやっぱり大変なので、個別に声をかけたという話があったり、

イベントを開催するのはやっぱり大変ですよねって。

それはそれとして、JAWS-UGでもコアな運営メンバはやはり比較的少数で掛け持ちしてるんだなぁというどこの界隈でもいっしょやな、スタッフ集め苦労してるなという感想を持ちました。

この辺は手伝うくらいならいくらでも手伝いたいなという思いはあるものの、コミュニケーション能力だとかが無なので、コアスタッフとして活動するのは無理だなぁという自分の自分に対する評価があるので、できる人でがんばってくださいという気持ちです。

おわりに

次回はDNS回らしいので、DNSの勉強をしたい方は是非、次回のssmjpをお楽しみに。

Gitlab Runner(docker) のAutoscale with AWS

Autoscaling GitLab Runner on AWS | GitLab

を試してみた話。

概要

Gitlab Runner は、実行方法としてdockerを選択すると、Gitlab Runner上でdocker runする形で実行されます。

その意味するところは、

  • Gitlab Runner本体のリソース上限の範囲でjobを実行しなければならない。
  • jobが1個でも2個でも消費するリソースは同一。
  • runnerが落ちると全てのjobが巻き込まれて落ちる。

というところです。

特に3つ目の点には注意が必要で、同時実行数の設定を間違うと、OOMキラーなどにより、gitlab runner プロセス自体が殺されたりします。つらい。

Gitlab Runner の docker+machine という実行方法を選択すると、Gitlab Runner自体ではjobが実行されず、docker machineを通して、他のノードで実行されるようになります。

そうすると

  • Gitlab Runner がdocker machineを通してアクセスできるノード1つにつき1jobが実行されるので死ぬのはjob単位。
  • Gitlab Runner 自体ではjobが実行されないので、Gitlab Runner自体が死ぬ可能性が低くなる
  • ノードの数がうまい具合に上下してくれるとjobの数だけしかリソースを消費しない。

というようなメリットが出てきます。 固定ノードによるdocker+machine 運用もありですが、3点目の利点を活かすには、オートスケールの仕組みを取り入れるのが良いです。 またノードにSpot Instanceを利用することで、コスト削減効果も見込めます。

といったところで本題の AWS を利用したAutoscaleです。

AWSを利用したAutoscaleと言っても、Gitlab Runnerが特別なことを行なっているわけではなく、docker machineの awsec2 driverがそのあたりの制御を行なっています。

なお、現在、docker machineはメンテナンスフェーズに入っており、 Direct support for AWS autoscaling groups and spot instances (#3877) · Issues · GitLab.org / gitlab-runner · GitLab のようなissueが立っていたりします。

具体的に何が問題なのかというと、docker machineがAmazonLinuxに対応していないため、ノードとしてubuntuを利用する必要がある、という点です。

ざっくりとした構成

gitlab runnerはGitlabをpollingして、jobがあればspot instanceを立ち上げ、実行を依頼する。

見ての通り、gitlab runnerには EC2インスタンスを作成するという、強めの権限が必要になります。

また、実行ノードには、状況に応じて、各種サービスへのアクセス権が必要となります。

セキュリティ

gitlab runner

構成で軽く説明した通り、gitlab runner には強い権限を与える必要があるため、乗っ取られたりするリスクを最小限にする必要があります。

具体的には、セキュリティグループなどを利用して、

  • Gitlabへのアクセス
  • ノードへのアクセス
  • OSのセキュリティアップデートなどのアクセス
  • 管理者がgitlab runnerを制御するためのインバウンドアクセス

しかできないようにすると良いでしょう。

ノードを作成するのに必要な権限としては

      "ec2:DescribeSpotInstanceRequests"
      "ec2:CancelSpotInstanceRequests"
      "ec2:GetConsoleOutput"
      "ec2:RequestSpotInstances"
      "ec2:RunInstances"
      "ec2:StartInstances"
      "ec2:StopInstances"
      "ec2:TerminateInstances"
      "ec2:CreateTags"
      "ec2:DeleteTags"
      "ec2:DescribeInstances"
      "ec2:ImportKeyPair"
      "ec2:DeleteKeyPair"
      "ec2:DescribeKeyPairs"
      "ec2:DescribeRegions"
      "ec2:DescribeImages"
      "ec2:DescribeAvailabilityZones"
      "ec2:DescribeSecurityGroups"
      "ec2:DescribeSubnets"

このあたりです。

ノード

ノードには、環境にもよりますが、キャッシュを利用するためS3へアクセスできるようにしたり、ECRを利用していればそちらへのアクセス権、 その他、外部サービスなどへのアクセスが必要であれば、それらの権限が必要になります。 こちらも、それなりに強い権限になることが予想されますので、

  • 必要なサービスへのアクセス
  • gltlab runner からのインバウンドアクセス

のみに限るようにしておくと良いでしょう。

インストールと設定

まずはGitlab Runnerのインストールです。

debian系(ubuntuほか)であれば

curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash

sudo apt-get install gitlab-runner

RedhatLinux系(Ceotsほか)であれば

curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash

sudo yum install gitlab-runner
sudo /usr/share/gitlab-runner/post-install

あとは docker, docker machine もインストールしておきます。

docker machine のインストールは Releases · docker/machine · GitHub を参考に。

/usr/local/bin/docker-machine へインストールすることを推奨していますが、一部環境では サービスの実行時に見に行くPATHに/usr/local/bin/ が含まれていないことがあるため、/usr/bin/docker-machine へインストール(もしくはシンボリックリンクを作成)する必要があるかもしれません。

次にgitlab runnerのGitlabへの登録です。

通常の手順と大きく変わりはしませんが、executorとしてdocker+machineを選んでください。

最後に設定

設定は/etc/gitlab-runner/config.tomlを直接変更する方がわかりやすい気がしています。

オフィシャルサイトに記載のサンプルを足したものがこちら

concurrent = 10
check_interval = 0
[[runners]]
  name = "gitlab-aws-autoscaler"
  url = "<URL of your GitLab instance>"
  token = "<Runner's token>"
  executor = "docker+machine"
  limit = 20
  [runners.docker]
    image = "alpine"
    privileged = true
    disable_cache = true
  [runners.cache]
    Type = "s3"
    Shared = true
    [runners.cache.s3]
      ServerAddress = "s3.amazonaws.com"
      AccessKey = "<your AWS Access Key ID>"
      SecretKey = "<your AWS Secret Access Key>"
      BucketName = "<the bucket where your cache should be kept>"
      BucketLocation = "us-east-1"
  [runners.machine]
    IdleCount = 1
    IdleTime = 1800
    MaxBuilds = 10
    OffPeakPeriods = [
      "* * 0-9,18-23 * * mon-fri *",
      "* * * * * sat,sun *"
    ]
    OffPeakIdleCount = 0
    OffPeakIdleTime = 1200
    MachineDriver = "amazonec2"
    MachineName = "gitlab-docker-machine-%s"
    MachineOptions = [
      "amazonec2-access-key=XXXX",
      "amazonec2-secret-key=XXXX",
      "amazonec2-region=us-central-1",
      "amazonec2-vpc-id=vpc-xxxxx",
      "amazonec2-subnet-id=subnet-xxxxx",
      "amazonec2-zone=x",
      "amazonec2-use-private-address=true",
      "amazonec2-tags=runner-manager-name,gitlab-aws-autoscaler,gitlab,true,gitlab-runner-autoscale,true",
      "amazonec2-security-group=xxxxx",
      "amazonec2-instance-type=m4.2xlarge",
    ]

global

グローバルな設定として重要なものにconcurrentがあります、これは、gitlab runnerで同時に実行できるjobの上限を決めるものです。 状況に合わせてチューニングしましょう。0は無限を意味しないので気をつけてください。

runners

つぎに[[runners]]設定です。ここには、gitlab runnerを登録した時の情報が含まれています。runnerは一つのrunnerにつき、複数設定できます。

具体的には、gitlab-runner register するたびに増えていきます。例えば、リソースを多く必要とするjobとそうでないjobがある場合に、使う設定を変更したい、というような場合、複数登録するというのはアリかもしれません、gitlab runnerを複数用意する方が素直なケースが多いですが。

runnerの設定では、limitというのがあります、これは、立ち上げ可能なノードの数を示しています。実行中ノードと待機中ノードの数を足したものの上限が設定されます。

runners.docker

runnerごとの設定に[runners.docker]があります。ここで重要なのはprivilegedです、jobでdocker in docker が必要な場合(docker buildしたい場合など)はtrueに設定しておく必要があります。

runners.cache

同じくrunnerごとの設定に[runners.cache]があります。Type=s3とすることで、s3をキャッシュとして利用できます、またshared=trueとすることで、ノードでキャッシュが共用できるようになります。基本的にはsharedtrueで良いでしょう。

アクセスキーやシークレットについては、適切なinstance profileが設定されていれば不要です。

runners.machine

同じくrunnerごとの設定に[runners.machine]があります。 ここで、ノードの設定を行います。

アクセスキーやシークレットについては、適切なinstance profileが設定されていれば不要です。

  • IdleCountというのが、待機中のノードの数です。待機中のノードの数がこの数より少なくなったら、ノードを立ち上げて待機します。
  • IdleTimeというのは、ジョブが終わったあと、待機する時間です、IdleCountよりたくさんのノードが待機中担っていた場合、この時間がすぎるとノードはシャットダウンされます。
  • MaxBuildsというのは、ノードがこの回数jobを実行するとシャットダウンするという数値です。ノードを定期的にクリーンアップするのに利用できます。
  • OffPeakPeriodsは、いわゆる、夜間や休日に関する設定です。この期間は、IdleCountIdleTimeの代わりにOffPeakIdleCountOffPeakIdleTimeが利用されます。
  • MachineDriverこれは今回の説明ではAWSを利用すると言っているのでawsec2です、利用できるのはdocker machimeがサポートしているものです。
  • MachineOptions ここが重要なところで、ノードとして作成するインスタンスに関する情報を記載します。設定はだいたい見ての通りなので大丈夫でしょう。amazonec2-amiで利用するAMI IDが指定できますので、カスタムイメージを利用する場合は設定すると良いでしょう。ただし、AmazonLinuxベースのものは利用できません。

考えるべきこと

globaなconcurrent、ノード単位の limit, IdleCount が重要な数値となります。

runnerが1つの場合、

  • concurrent=15, limit=20, IdleCount=5 な状況では、最大20台のノードが立ち上がります。最大同時実行数は15です。(5台はidle状態をキープしている)
  • concurrent=15, limit=15, IdleCount=5 な状況では、最大15台のノードが立ち上がります。最大同時実行数は15です。(最大実行時にはidle状態のノードがなくなる)
  • concurrent=15, limit=10, IdleCount=5 な状況では、最大10台のノードが立ち上がります。最大同時実行数は10です。(limitのほうがconcurrentより小さいので、設定した最大実行数に満たない数しか同時実行されない)

runnerが複数の場合、

  • concurrent=15, limit=20, IdleCount=5, limit=20, IdleCount=5 な状況では、最大25台のノードが立ち上がります。最大同時実行数は15です。(各runner5台はidle状態をキープしている)

  • concurrent=15, limit=10, IdleCount=5, limit=10, IdleCount=5 な状況では、最大20台のノードが立ち上がります。最大同時実行数は15です。(各runnerでidle状態をキープしている台数はジョブの実行数に依存します)

  • concurrent=15, limit=5, IdleCount=5, limit=5, IdleCount=5 な状況では、最大10台のノードが立ち上がります。最大同時実行数は10です。(runnerの登録の仕方によりますが、片方のrunnerに余裕があるのに、もう片方のrunnerのlimitにひっかかって、同時実行数に余裕があるけれど同時実行されないケースも出てきます。)

というところで、環境に応じた設定が必要になりますし、runnerを複数設定することは、若干の無駄を許容するという感じになりそうです。

私の理解したBFF

BFFとは Backend for frontend の略。

FrontendのためのBackend。

それはなんでしょうか?

背景として、Frontendは、API呼び出しをして、もらったデータをレンダリングするのが主になっているような気がそこはかとなくしています。

このような状況で、Frontendというのは、いろんなドメインにまたがる情報を表示する必要があったりします。

するとどうなるか、大量のAPI呼び出しが必要になります。

リッチな環境であれば、API呼び出し回数が多少多くても問題ありませんが、リッチでない環境ですと、API呼び出しにかかるコスト(時間的コスト)が大きくなってきます。

すると、API呼び出しを減らしたい。でもいろんなドメインにまたがるデータも欲しい。という要求がでてきます。

そこに登場するのがBFFです。

BFFでは、Frontendのユースケースに依存したAPIを持ち、Frontendからのリクエストに応じて時には複数のBackendに要求をだし、それらをFrontendが望む形に組みたて、返却します。

安定したドメインで作られるバックエンドAPIに対し、BFFでは、変更の多いFrontendのユースケースによってAPIが用意されます。 この点が、BFFはフロントエンドチームが作った方が良いと言われる所以かなと思っています。