AWSで動かすGitLab CI runner の改善

AWS で GitLab Runnerを動かしているのですが、いろいろ改善している話です。

dockerhub registry mirror

みなさんご存じの通り、 dockerhubは、anonymous pull に制限をかけました。CIで dockerhubのイメージを利用していると、すぐ制限にひっかかります。

また、近いほうがimage pull が速いということもあります。

そこで、 dockerhub registry の mirrorを設置しました。

詳細は Docker Registry | Docker Documentation を見ていただくとして。

AWSなので、ストレージにはS3を利用しています。 s3 を利用する際、

package manager

JAVA系を利用していると maven central からパッケージをダウンロードしてくることが多いのですが、 maven central には dockerhub同様 ダウンロード制限がかかっており、 CIで大量にダウンロードしていると、制限にひっかかります。

そこで、パッケージマネージャ Nexus Repository OSS - Software Component Management | Sonatype を利用しています。

maven centralのほかにも、よく使うものを mirrorしておくことで、安定した環境を用意しています。

vpc endpoint

ci runner 自体に外からアクセスする必要はまずないので、 private subnet に置いています。 すると、 s3 からデータを取得するたびに、nat-gatewayを経由することになり、AWS内通信なのに通信料がすごくかかる。

ということもあり s3 のvpc endpoint を設置しています。 上記 dockerhub registry mirror のほか、 AWS ECRからの image pull もs3 経由ですので、それなりに効果があります。

vpc endpoint service

GitLab Server と CI runner は、AWSの別アカウントで管理しています。そのため、 CI runner から GitLab Serverへの通信がやはり internet経由となりnat-gateway を経由しており、ここでも通信料がかさんでしまう状態なので

GitLab Serverを vpc endpoint service として別アカウントに公開できるようにし、 CI runner の動いているアカウントで vpc endpoint として 利用しています。

auto scale

CI runner については Autoscaling GitLab Runner on AWS EC2 | GitLab のドキュメントに従い、docker-machine によるSpot instance を利用した auto scale で動かしています。

終わりに

値段とスケーリング、速度に関して、改善を行っている現状を記載しました。

これからもいろんな状況に応じて、いろんな改善を行っていくつもりです。

2020の振り返り

転職した

4月から新しい職場で働いています。入社数日して、会社から出社するなアナウンスが出て、新しい職場にはまだ都合5日くらいしか行っていません。

副業を始めた

8月からちょっとした副業を始めました。大したことができてないので役に立ててるのかはよくわかっていません。

まだまだ副業先は募集中です。コード書く仕事したいです。

ゲームをプレイしている

SEKIRO始めました。土日しか遊んでないので遅々として進んでいませんが。

リングフィットアドベンチャーも始めました、こちらは継続しており、100日を超えました。腕の筋肉がないなぁと実感しています。

全体として

引きこもりに磨きがかかっており、体調のほうを少し心配しています。

リモートでの仕事はとてもやりやすくて、もうずっとリモートで仕事していきたいなとすら思っています。

もともと他人と積極的にコミュニケーションをとるのが下手なので、非同期に適当に意思疎通ができる環境がとても良いです。

来年以降

このままフルリモートで仕事ができることを願ってやまない。

楽しい副業先を見つけたい。

やりたいことをもう少し明確にして、やりたいことに向かっていけるようにしたい。

引っ越ししたい。

Elasticsearchのindex分割について考える

ITインフラ関連の仕事をしていると、日々いろんなところからログを集めて可視化するということがままあります。

そんなとき、Elasticsearchがそこそこ使われていると思うのですが、そのindexについて考えます。

logstashで何も考えずにElasticsearchへログを投げていると、だいたい、indexが1日ごとに作成されているかとおもいます。

Elasticsearchへのログ保管の要件として、1週間とか1か月とか、ログの検索したい時期によって変わってきます。

そんな時、いつでも1日ごとにindexを分ける運用でいいんでしょうか?

リソースが無限にあればいいですが、実際はそうでもありません。CPUもメモリも限られています。

ではどのくらいがいいのでしょうか。それもケースバイケースなのですが

Elasticsearch 7以降では、デフォルトで1ノードのshard数は1000に制限されています。通常、ノード障害に備え、replicaは1以上にする必要がありますので

2ノードの clusterでは、primary shard 数としては1000が限界ということになります。

2ノードあたり 1000 shard という数は多いでしょうか、少ないでしょうか。

それも扱うログの数によって変わってきます。 たとえば100サービスあって、100indexが毎日つくられるとすると、 100x2(replica)x1(shard)x7=1400shard となり、 2ノードでは足りず、3ノード必要となります。

また、1shardあたりのサイズは10-50GB程度がちょうどよいとされています。shardが増えるごとにデータが増えるのとは別でCPUやメモリを消費するからです。大きすぎると検索パフォーマンスに影響が出ます。

たくさんのサービスがあり、それぞれが生成する1日当たりのログサイズが2,3GBしかないというケースでは、そもそも1shardのサイズが小さすぎ、もったいない。という状況になります。

では、 indexを日付で分けず、indexあたりのshard数を適切な数字に設定すればよいでしょうか。

実はそうでもありません。ディスクにも限りがあるので、古いデータは削除して容量をあけていく必要があるのです。削除するためにindexを検索して対象を探して削除する、というのはまぁ負荷がかかります。

それに対し index丸ごと削除するのであれば、そこまで負荷もかからず、短時間で終わります。

ですので、数日単位で適切にindexを分割するということや、 別サービスであっても、ログの schemaが同じであれば、同じindexに入れて、検索時にカラムを指定してわけられるようにする。

といった方法で いい感じにまとめていく必要があります。これは完全にケースバイケースなので、うまくやる方法を個別に考える必要があります。

数日単位でindex分割する。というのは、 保存期間が30日以上など、そこそこ長い期間の時に有効です。 1週間ごとにindexをわければ、 30日データがほしければ 37日分くらいのデータが保存できるストレージを用意することで、35日たったindexを削除するという方法で 削除負荷もほとんどなく、いい塩梅に調整できるでしょう。

別サービスだけどschemaが同じものをまとめる場合は、1日あたりないしは1つのindexにまとめる日付単位の実際のログデータ量を見て、10-50Gが1shardになるとよいというのを基準にまとめていく作業が必要となります。

こんな感じに、時系列のログデータをいい感じに Elasticsearchで扱うには、すこし、indexの分割について考える必要があります。

程よい分割と集約を行い、値段あたりのパフォーマンスを向上させていきましょう。