私はKaigi on Railsのオーガナイザーのひとりです。Kaigi on Rails 2023は物理会場にて開催されることが公開されました。そうなるともちろん、会場でのインターネットについてはどうなる、どうする、という問題が出てきます。それに備えて、先輩イベントであるRubyKaigiを参考にしようというわけで、自分の理解のために書くことにしました。
私はRubyKaigi 2022のネットワークをお手伝いしましたが、ケーブルの巻き直し、APの設営、撤収時の諸々を手伝ったのみです。よってこれから言及する内容については、一般参加者に毛が生えた程度の事前知識しかありません。
またこれから読み解くコードにおいて、コメントする内容の正確性は一切ないものと思って読んでください。
RubyKaigiのネットワークにおけるL3(OSI参照モデルで言うネットワーク層以上)より上の構成(多分)については、このリポジトリで公開されています。
何とは言わんが現場絶賛公開中なんだよな、宿題を放置した自分が全部悪いといいながらやってます https://t.co/J6SoHxBd4P https://t.co/GcPJLU69Rn
— そらは (@sora_h) September 3, 2022
今回は、2022年の会場ネットワークの構築が始まったあたりからのcommitを順を追う形で読み解いていきます。
今回のネットワークの準備はここから開始したと見られます。これ以前にもcommitsはあるのですが、それらは2019年以前のものをimportしたもののようなので、今年には関係ないとして無視します。 実際、このcommitでもitamaeのrecipeを削除してscratchからやりなおす、という意図を感じられます。
subnetを3つ、route_tableをひとつ定義しています
AWS Direct Connect ゲートウェイを定義しています。AWS Direct Connectとは……
AWS Direct Connect は、お客様の内部ネットワークを AWS Direct Connect ロケーションに、標準のイーサネット光ファイバケーブルを介して接続するサービスです。 https://docs.aws.amazon.com/ja_jp/directconnect/latest/UserGuide/Welcome.html
とのことです。(今知った)
Route 53に rubykaigi.net
のZoneを定義しています。ネットワーク関係の色々は *.rubykaigi.net
で提供されました。
踏み台インスタンスを定義しています。関連するIAM roleであったり、SSH loginできるユーザーの公開鍵の設定などもあります。
DNSの逆引きを設定しているんだと思います。この記載で 10.0.0.0
になるってこと……?
https://manual.iij.jp/dpf/help/19004700.html
これは単純にTerraformのdirectory構成の変更ですね。
様々な機器のDatacenter、Network、CIDR、IP等を定義したhosts.txtを作成(というより更新)し、その内容から aws_route53_record
を作成するRuby scriptを経由してRoute 53にTerraformからrecordを登録するようにしています。まあこれは手では書いていられないですね……最終的なhosts.tfは1400行弱になっています。
Roadworkerを削除しています。RoadworkerはRubyによるRoute 53をDSLによって管理できるgemです。Terraformによる管理に乗り換えたから、ということなんでしょう。
awsroute53record 大量に発生すると一瞬で terraform apply 遅すぎてやってられん状態になるし roadworker はなんだかんだ捨てられないなぁ
— そらは (@sora_h) August 22, 2022
NAT Gatewayが有効になりました。
EKSによるKubernetes clusterが爆誕しました。というか、Cookpad org以下にterraform moduleが公開されているんですね。
https://github.com/cookpad/terraform-aws-eks
注目すべきは、このクラスタは全部ARM instanceで稼動するような設定になっているところです。
VPN間でのrouteのpropagationを設定しています。
K8s clusterに属するnodeの設定です。
https://github.com/aws/aws-node-termination-handler をHelm経由でdeployしています。こんなのがあるんですね。
AWS Load Balancer Controllerをclusterにdeployしています。
AWS Load Balancer Controller アドオンのインストール - Amazon EKS
証明書とALBを作成して *.rubykaigi.net
ないくつかのhostを定義しています。こんなの生えてたのか。
dexをdeployしています。dexというのは https://dexidp.io/ です。 これで何をしたいかというと、 *.rubykaigi.net
でhostされているいくつかのresources(例えば grafana.rubykaigi.net
)へのアクセス権限を絞るためです。今回はGitHubの特定teamに所属しているメンバーに対しての許可を与えるような設定が書かれています。
また主にこのcommit以降からだと思いますが、K8sで使用するYAMLをJsonnetから生成するようになっています。
で、そのテスト用のendpointを作成しています。ちゃんとAuthrorizeされていれば画像が見れるはず、というやつ。
wgbridgerを導入しています。wgbridgerというのは、
build L2 bridge using Wireguard to bring NGN to behind IPv4 NAPT only environment…
というもの(?) これはあれかな、準備作業中に見せてくれた、どこでもNGNに繋がる便利Raspberry Piの実体かな?
dexをOIDC準拠IdPとして使用した認証を利用し、AWS Management Consoleへのアクセス権限を特定のIAM Roleによって行えるような機構、AMCを用意しています。つまりどういうことかというと、あるGitHub teamに所属している場合、その認証情報を用いてAWSのConsoleに入れる仕組みです。 tf/amc/src/app.rb
がキモだと思うんですが、難しいよぉ……
AMCのREADMEに追記が行われています。
AMCに関連する処理のなかで、curlによる証明書チェーンが正当かどうかの検証を追加しています。
ここからKeaのための準備が始まります。Keaが何者かというと、DHCP serverです。このcommitでは、Docker imageのbuildやKeaを起動するためのscriptなどの準備をしています。
これはKeaのためのAuroraを準備しています。
JsonnetをYAMLにするscript内部で、生成したファイルの扱いがちょっと変更されています。rsyncにしたのは更新日時とかそのあたりの都合?
Keaが運用され始めました。
Keaに対するhealthcheck用のendpointを用意しています、Rustで。Healthcheckそうやってやるんだ……なるほど……?
NocAdmin roleに対してロードバランサーへの権限を解放しています。
Kea関連のdeploymentで参照しているcommit hashを更新しています。
NocAdmin roleに対してRDSへの権限を解放しています。
これはちょっとわからない……NocAdminBaseとNocAdminに権限を分離して、権限昇格を防いでいるんだと思いますが多分。
権限の昇格を防ぎ、アクセス許可の境界で IAM ユーザー範囲を限定する
🍝
NocAdminに対して許可するiamへの権限をいっぱい追加しています。
687e37bで導入されたterraform moduleをfork先のものからfork元のものを使うよう修正しています。ARM対応がmergeされたのがこのタイミングだったのかな。
Terraformのexternal data sourceとして、Jsonnetを指定してJSONを吐くときに使うためのRuby scriptを定義しています。
このあたりからPrometheusの設定が始まります。ここではALBのための設定を作成しています。これらのendpointもdexを経由して認証されるようにしていますね。
Helm経由でPrometheusをK8s clusterにdeployしています。
blackbox exporter を用意しています。ICMP (ping)でどこかを監視する用かな。
8.8.8.8
に対して60秒ごとにICMPを投げるように設定しています。これはインターネットへの疎通確認かな?
Prometheusのdata retensionを1分から30日に変更しています。
clusterへの設定を他のtfから参照できるようにoutputしています。
ハードコードしていた設定値を、先ほどoutputしたclusterの設定を用いた形に書き換えています。
hosts.txtが更新されました
snmp-exporterを設定しています。SNMPはSimple Network Management Protocolのこと。CiscoのWireless LAN ControllerやNECのIX Routerの監視に用いていたのかな。
先のcommitで作成した設定値をprometheus側に反映されるようにK8sのmanifestを設定している、という理解でいいのかな
Grafanaです。
Keaの監視もPrometheusで行うようになりました
wgbridgerのためにMTU値を上げています
Wireless LAN Controllerにアクセスできるようになりました。
PrometheusからのアラートがSlackに送られるようにしています。
Jsonnetに対してformatterをかけています。
Prometheusがmetricsをscrapeする間隔を60秒から20秒に変更しています。
clusterでのOIDC configを別tfから参照できるようにexportしています
NocAdmin roleに対してDynamoDBに関する権限を解放しています。なんかで使うんでしょう。
なるほど、State lockでDynamoDBを使うためだったんですね。
Backend Type: s3 | Terraform | HashiCorp Developer
NocAdmin roleに対して iam:UpdateAssumeRolePolicy
を許可するよう変更しています。
cloudwatch_exporterを有効にしています。AWSのresourceもPrometheusでモニタリングするためでしょうね
hosts.txtを更新しています。IPv6の指定が増えてますね。
さらにhosts.txtの更新。もりっとhostが追加されています。
hosts.txtからtfに変換するscriptを修正しています。IPv6の取り扱いとかに修正が入ってますね。
typo
これは……なんだろう、多分何かの機器用の設定を生成するためのscript。NECのルーターだと思うけど。
Syslogを置くためのS3 bucketへの権限をNocAdmin roleに付けています
Syslog関連のterraformのための場所を作っています。
Syslogのためのfluentdを置くECR repositopryを定義しています
Syslogのためのfluentd containerを作成しています。GitHub Actionsでdocker buildをしていますね。
git submoduleのrepository URLをssh形式からhttps形式に変更しています。鍵がない環境でcloneできないから、でしたっけ。たぶんGitHub Actionsで不都合になったのか……?
fluentd pluginを作成しています。これはまずhealthcheckだけやってる感じ?
GitHub ActionsからECRにpushできるような権限を付与しています
Syslog用のIAM role、K8sのservice accountを作成しています。EKSでIAM roleとの連携ってこうやってやるんだ。
fluentdの設定、k8sのdeployment諸々が作成されています。これでEKS clusterにfluentd containerが稼動し始めたのかな。
SyslogのためのSecurity groupを作成しています。fluentdに向かう通信を許可しているはず。
fluentdのhealthcheckのために、pluginを作ってやっていたものからmonitor_agentを使う方式に変更しています。
https://docs.fluentd.org/input/monitor_agent
GitHub Actions内で参照していたpathの修正です
S3に置くlog fileにhostnameを付与するようにしています
fluentdが終了するときにbuffer(?)をflushするようにしています。これないと書き出し切らずに終了してしまう?
tagでchunkが分離されてしまうのを防いでいる?
terraformでbastion instanceに対してはAMIの変更を無視するようにしています。
use static NAT on onpremises router devices so they don’t need to handle dynamic NAPT table and allow redundancy
「オンプレミスのルーターデバイスで静的NATを使用することにより、動的NAPTテーブルを処理する必要がなく、冗長性を確保できる。」 あ~はいはいなるほど完全に理解した
unboundがアップを始めている
unboundをCache DNS serverとして運用するみたいで、そのためのECRとsecurity groupを定義しています。
独自のunbound exporterによる監視を有効にしたunboundのcontainerをbuildしています。Jsonnet大活躍。
フィックスタイポ
unboundの設定です。
特定の逆引きに対しては特定のIPに送るようにしてい……る?このIPがVPC resolverを指している?
deployされるunboundを更新しています。
68c205fで設定したlocal-zoneに対してnodefaultを付けています。unboundなにもわからない。
nodefault AS112ゾーン(※)のデフォルトの設定をオフにする ※ AS112ゾーンはプライベートアドレスやリンクローカルアドレスの逆引きのゾーンのことです。Unboundではデフォルトでこのゾーンに対する問い合わせにはNXDOMAIN(情報なし)を返します。 第4回 Unboundサーバ運用Tips | gihyo.jp
NXDOMAIN
を返さないようにした、ということなんでしょうか。
unboundの設定を変更して性能を調整しています。
unboundが unbound
userで動作するようにしています。
グオオオ
venue下のsubnetに対してKaeで払い出すIP rangeを指定している……でいいのか?
unbound containerに対してTCPでも通信できるようにしています。heathcheckとかでも使うから。
https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/deploy/pod_readiness_gate/
なる、ほど、ね……?
😜
NLBのsubnetからunboundへのhealthcheck accessをできないようにしています。metricも同じportで提供するから、というのはmetricに影響が出る?
これはterraformのfor loopの設定。
./gen-workflows.rbを実行した結果をcommitしたんだと思います。
Availability Zoneごとに配置されるよう、nodeのmin_sizeを2にしています
hosts.txtが更新されました。tmpに対して名前が付きましたね。
unboundに対するPrometheusからの監視を設定しています。internalなhostnameとexternalなhostnameに対する名前解決もするようにしていそう。
unboundに対してtopologySpreadConstraintsを設定しています。Zoneごとにちゃんとばらけてくれるようにしています。
KeaがDNS resolverとして使うものを 8.8.8.8
からunboundに変更しています。
IP addr足りなかった?
PrometheusがSNMPで監視する対象のhostを増やしています。
CiscoのWLCに対してSNMPで取得するmetricを追加しています。
5788b2eで指定したWLCのhostnameを修正しています
これちょっとよくわからない……WLCの居場所に関する設定?
ダメらしい。 f52e1bc で追加した一部の設定をコメントアウトしています。
hosts.txtを更新しています。順番が上に移動しただけ?
さて、会場でRubyKaigiのライブ配信を見ようとした場合には見られなくなっていたと思いますが、これがそれです。特定のS3 bucketに対し、会場内ネットワークからのアクセスであればDenyするような設定をしています。
ライプ配信視聴アプリ側ではここでその制御を行っています。
AWS Direct Connectのmetricもcloudwatch-exporterで収集するようにしています。
AWS Elemental MediaLiveのmetricもcloudwatch-exporterで収集するようにしています。
RubyKaigiのライブ配信がどのようにAWSのサービスを使用して実現されているかはこの記事に詳しいです。まあ作者が書いてるので……
プリンター?
一時的に val-permissive-mode: yes
にしています。これなに?
DNSSECを無効にする方法 – 日本Unboundユーザー会
なるほどね。
先の変更を削除し、zoneの逆引きの設定を変更しています。
privateなzoneは信頼するように設定しています……というかDNS周りのこれらの設定を日本語に起こすときの言葉の選択が正しいのか全然自信がない。
private IPのみ逆引きをforwardするよう変更しています。
EC2やEBSなどへの監視設定をPrometheusに対して行っています。
sorah/cnwからPrometheusの設定を拝借しています。
ここからは設営日 (9/9)になります。
SNMPで監視する対象がDOWNしている場合のアラートを設定しています。
NECのルーターに対してのアラートを設定しています。CPU使用率かな?
WLCに対してSNMPで取得する項目を追加しています。
プリンターの居場所(というよりはhosts.txtから生成される定義?)が間違っていたっぽく、それを修正しています。
今思い出したけど、これテプラのラベルプリンター?
SNMPで監視している対象の機器が再起動したときのアラートを設定しています。
NocAdmin roleに対してtakeout-app(配信視聴アプリ)関連のS3 bucketへの権限を付与しています。
自分が会場ネットワークにいるかどうかの判定に使用するBucketのresponse cacheが長いので1時間に変更しています。
いかがでしたか?