Write and Run

it's a simple way, but the only way.

無職に飽きたので人工衛星のソフトウェアをRustで作っています

KOBA789 です。

今年2月末に前職を退職してからここ半年ほど無職をしていたのですが、いよいよもって無職に飽きてきたので人工衛星を作ることにしました。

実は9月頭から働いています。

株式会社アークエッジ・スペース

次の職場は株式会社アークエッジ・スペースです。東大の研究室発のスタートアップで、衛星バス開発を得意としている会社です。

衛星バスというのは、言ってしまえば人工衛星の OS に相当するものです。
OS に喩えましたが、もちろんそれは単なるソフトウェアではなく物理的な実体を伴うハードウェアとその中で動作するソフトウェアの集合体です。
ちなみにユーザーランドに相当する部分はミッション機器と呼ばれます。

まだまだ人数の少ない会社ですが、業界の土地勘や人脈に富んだ CEO や、人工衛星開発の経験があるエンジニアが揃っており、スタートアップとしては超実力派です。

ArkEdge Space Inc.

ソフトウェアエンジニアができること

私はソフトウェアエンジニアです。しかも一番得意なのはウェブ技術です。人工衛星開発の経験があるわけでもなければ、メカの設計ができるわけでも姿勢制御に詳しいわけでもありません。
(一応趣味レベルの電気電子の知識と回路設計の経験はありますが)

私もオファーを頂いたときは、まさか(ウェブ系の)ソフトウェアエンジニアが役に立てることがあるなんて、と思っていました。

しかし、面談のなかで現在の人工衛星開発の現場の課題について聞いていくと、ソフトウェア技術で解決できそうな問題が山ほどあることがわかりました。
ソフトウェアエンジニアばかりの職場・エコシステムでは解決されていて当然の課題が、ほぼそのまま転がっているのです。ウェブ系の会社ではありえないことです。
そして同時に、世間で "DX" がこれだけ注目されている理由を本当の意味で理解しました。ソフトウェアエンジニア中心の集団以外では、2021年になった現代でも計算機を十分に使い潰せていないのです。本当に。

私は計算機が好きです。そして特にソフトウェア技術の力を信じています。ソフトウェア技術を味方に付ければ、あらゆる人がもっと多くのことを成せるようになると確信しています。
人工衛星開発というエンジニアリングの最先端でソフトウェア技術を役立てられることを私は誇りに思いました。

具体的にやっていること・やること

とりあえず入社即 Kubernetes クラスタ構築 & ArgoCD で GitOps、AWS のリソースは全部 terraform で管理、という感じにしたりしました。
まぁ、これらについてはただの手癖ですし普通の仕事なので特段おもしろい話はありません。

また、Issue ベースでのコミュニケーションの方法の啓蒙をやったり、データベース勉強会を開いたりといった、「ソフトウェア業界から来た人」業をしています。
現代的な組織であれば、あらゆる人が SQL を書けてほしいし、あらゆる人が SQL を書くメリットを感じられるデータ基盤があるべきですよね、やっぱり。

より人工衛星っぽい仕事としては、オンボードコンピュータ(OBC)のハードウェアとソフトウェア両面の開発をしています。
OBC は名前の通り、人工衛星に搭載されているコンピュータで、接続されている各コンポーネントと通信しながら人工衛星の機能を維持します。 地上にテレメトリを送信したり、地上からのコマンドを解釈してコンポーネントを制御したりもします。
ウェブの技術でいうとまさに API サーバーみたいな感じです。

人工衛星では利用できる電力が限られています。空気の対流もないので放熱も一苦労です。というわけであまり潤沢な計算リソースは使えません。
また打ち上げたら最後、二度と人間の手の届かない場所にデプロイされてしまうため、バグって黙り込んでしまったりするとどうにもなりません。
しかも、たとえソフトウェアがバグっていなくても宇宙線でハードウェアが異常を起こしたりもするので始末に負えません。

そういうわけでかなり特殊なコンピュータが必要なので、ハードウェア・ソフトウェア両面から課題に取り組んでいます。
ソフトウェアのみならずコンピュータ全体が興味範囲の私としては、これほどエキサイティングな仕事は他にありません。

みなさん気になっているのはそのソフトウェアの開発言語だと思うんですが、Rust で開発しています。
実行効率と安全性と生産性に優れている Rust は人工衛星のフライトソフトウェアを書くのにぴったりです。 それに、やっぱり軌道上に Rust 製のソフトウェアをデプロイしてみたいですよね。 しかし Rust での組み込みソフトウェア開発は地上でもまだまだ例が少なく、エミュレータやデバッガなどの開発環境や、デバイスドライバをはじめとするハードウェア固有のコード資産などは C 言語ほど充実していません。
これらの課題をクリアしながら Rust で開発するメリットを最大限活かせるようになるにはたくさんのチャレンジが必要です。

気になる方はぜひ一緒に人工衛星を開発しましょう。

ISUCON11予選に今年もRubyで出場して敗退した

KOBA789 です。

今年もチーム「ソレイユ(osyoyu, koba789, s4ichi)」で ISUCON に Ruby で出場し、敗退しました。

まずは我々の戦法や秘密兵器の紹介から。

伝統と信頼のサーバーサイドプログラミング

ISUCON7 くらいのときから続けている手法で、競技用のサーバーに開発環境を構築し、3人とも同じホストに SSH でログインして同じファイルシステム上のソースコードを書き換えます。

他人の変更をリアルタイムに確認できることや後述するようにソースコードのバージョン管理が不要なことなどがメリットです。

SSH 時に WATASHI という環境変数で自分の名前を渡すことで、同じ isucon ユーザーへのログインであっても各個人の普段使いの dotfiles がロードされるようになっています。

これは「実家システム」と呼ばれており、チームの生産性に大きく貢献しています。

あいかわらず git ほぼ禁止

全員で同じコードベースを編集しているため、分散バージョン管理は必要ありません。 とはいえ分散しないバージョン管理は便利なため、リモートリポジトリなしで git を使っています。

また、ISUCON のような切羽詰まった環境では merge ミスなどで時間を浪費するという考えから、branch を使うことも禁止です。 常に歴史が master 一本になるように運用しています。

mamiya2020

お手製の最強デプロイスクリプト。名前は sora_h パイセンの mamiya にあやかっています。

初めて mamiya と名の付くデプロイスクリプトを用意したのは ISUCON7 のときで、そのときは競技時間中に osyoyu が書いてくれたのですが、この mamiya2020 は私が昨年 ISUCON10 に向けて開発したものです。

この mamiya2020 は、webapp/ruby 以下のアプリケーションのソースコードは当然のこと、/etc/nginx.conf/etc/my.cnf などもデプロイしてくれるというスグレモノ。 しかも .gitignore を考慮して配布ファイルをフィルタしてくれるので不要なログファイルなどを転送してしまう無駄もなし。

ちなみに、deploy などという名前を使わず、わざわざこんなふざけた命名をしているのかといえば、Ruby で優勝した sora_h パイセンへの憧れを忘れずにいようとかそういうことはなく、まぁ単にふざけただけです。

それでも今となってはチーム内の大切なユビキタス言語となっており、競技終了間際では「ベンチ前にマミって!」「マミった!」「ベンチ回します!!」という声が響いています。

isukekka

たぶん詳細は初公開。チーム「ソレイユ」の秘密兵器のひとつ。

ベンチマーク走行終了後、ベンチマーク走行中のログを自動で集計・分析し、結果を通知してくれるというもの。 これも私、KOBA789 作。

ざっくり言うと、/initialize のリクエストハンドラ内で各種ログをローテート、別プロセスで sleep 75 を開始して、75秒後に溜まったログを分析するために alppt-query-digest を起動するということになっています。

alppt-query-digest の出力は autoindex on な nginx でサーブされており、以下のようにアクセスできます。

f:id:koba789:20210822164852p:plain
isukekka が吐き出したファイル

同時にチームの GitHub リポジトリにも上記ファイルへのリンクが書かれた Issue が作られ、その通知が Slack に流れます。

f:id:koba789:20210822165013p:plain

この isukekka により、「Slack の通知が来たらそれを見てプロファイリングすればいい」というワークフローが完成しています。

isukit

環境構築便利ツール集。Itamae レシピの集合体。 ISUCON 9 のときに s4ichi と osyoyu が整備してくれたのが発端。 今回は無職時間を有効活用して私がだいぶメンテしました。

我々は前述のとおりサーバーサイドプログラミング戦法を採用しているわけですが、そのためにはいつも使っている様々なコマンドラインツールが揃っていないと不便です。 それらをチマチマインストールしたり設定していたりしては時間がもったいないので、すべて自動化しています。

また MySQL 8 に強い執着のある我々のために MySQL 公式の mysql-server パッケージをインストールするためのレシピもほぼ自動化されています。 このおかげで、ISUCON11 予選でもなんの迷いもなく MariaDB 10.3 から MySQL 8 に乗り換えることができました。

そういえば元々は Itamae レシピの集合体だったのだけれど、最近はそれらを含む秘密兵器セット全体を指すようになってる、気がする。

osyoyu/stackprof と speedscope

osyoyu/stackprof はその名の通り、osyoyu が改造した stackprof。 speedscope は各種プロファイラの flamegraph をかなりいい感じに可視化してくれるビジュアライザ。

osyoyu/stackprof の詳細は本人が書いてくれる、と思うのだけれど、speedscope での可視化の結果はかなり映えるので貼っておく。

f:id:koba789:20210822170312p:plain
映えるspeedscope。Ruby のプロファイリングができる

yalp

SQL で再実装された alp。KOBA789 作。

本家 alp は非常に手軽に一方で、集計条件などの細かい設定はできない(またはやりづらい)という特徴があります。

KOBA789 は SQL が得意なため、だったら SQL で書きゃいいじゃんということで書き直しました。再実装をすると、alp の集計内容の筋の良さがよくわかります。

SQL で書き直したことで、 「ユニークユーザー数のカラムも欲しい」みたいな要望にすぐ対応できるようになりました。

うちのチームで「alp」と言った場合、この yalp を指します。

たたかいのきろく

あくまで KOBA789 の視点です。見えてないところでも他のメンバーはなんかやってた。

  • 10:00 競技開始
    • koba789: CFn スタックを作る
    • koba789: マニュアルを音読しはじめる
  • 10:20
    • koba789: マニュアルの通読が終わる
    • osyoyu&s4ichi: アプリケーション仕様の理解のための議論開始
    • koba789: インフラ構築開始
  • 10:21 頃
    • koba789: ubuntu-cloud-image のデフォルトパッケージとの差分をとり、MariaDB に気づく
  • 10:28
    • koba789: 2台目のサーバーに実家環境構築完了
      • 他の2名がいつものエディタでコードを読める環境ができた
  • 10:46
    • koba789: 1台目のサーバーで完全な開発環境の構築完了
      • MariaDBMySQL 8 に移行された
      • 上記秘密兵器がすべて利用可能な状態になった
  • 11:04
    • koba789: すべてのサーバーで完全な環境の構築が完了
      • 1台目のサーバーのコード・設定を他の2台に mamiya で配れるようになった
      • いつでもトラフィックを分散可能になった
  • 11:10 頃
    • koba789: osyoyu&s4ichi から読解したアプリケーション仕様の申し送りを受ける
  • 11:30 頃
    • koba789: ISU のメトリクスの write heavy であることに気づく
    • koba789: 構造の抜本的な改善ができるか考えるため、read エンドポイントのロジックを読み解き始める
  • 12:30 頃
    • koba789: graph のロジックに完全に頭をやられる
    • osyoyu: icon を DB から降ろそうとして盛大にバグらせはじめる
  • 13:00 頃
    • koba789: icon 周りのバグは nginx の try_files のミスであることを指摘
    • osyoyu: なお icon 周りでバグが出て悩む
  • 13:30 頃
    • koba789: icon のバグは認証の不備であること指摘。X-Accel-Redirect を提案
    • koba789: graph の読解を諦める
    • koba789: s4ichi に /api/trend は SQL の LATERAL JOIN で解けると提案
  • 14:00 頃
    • s4ichi: /api/trend を非同期化
      • 非同期化というか、別デーモン化(loop do; sleep; end)
      • 定期的に JSON をファイルに吐いて nginx に配らせることに
      • 勝手に E-Tag も付いて便利最高
  • 15:00 頃
    • koba789: 適当にインデックスを貼る
  • 15:30 頃
    • koba789: 2台目・3台目も活用する構成にする
      • ようやく2万点
    • s4ichi: calculate_condition_level 消さないと速くならんよと指摘
    • このへんで mysql2 gem がめっちゃマルチスレッド絡みっぽいエラーを出し始めた
    • s4ichi: puma から unicorn へ切り替え
  • 16:10 頃
    • koba789: is_dirty, is_overweight, is_broken を各カラムに分離、generated column で condition_level を埋めた isu_condition2 テーブルを作成
  • 16:30 頃
    • osyoyu&s4ichi&koba789: isu_condition2 テーブルを使うようにすべてのクエリを書き換え完了
  • 17:00 頃
    • osyoyu: GET /api/isu がめっちゃバグる
      • koba789 の提案に従って LATERAL JOIN を使ったが、LEFT OUTER にならなくて悩む
  • 17:15 頃
    • ベンチマーカー(ポータル)が落ちる
  • 17:30 頃
    • koba789: 冷静になるチャンスをもらったと前向きになる
  • 17:54
    • koba789: 冷静さを取り戻す前に闇雲に apt install redis-server
  • 18:05 頃
    • ベンチマーカーが復活
  • 18:10 頃
    • koba789: 冷静になった末、isu_condition2 テーブルの DB 分割を決断
      • 他のメンバーに LATERAL JOIN 使えとか言っておきながら JOIN が使えないインフラ構成への変更を強行(なお競技終了35分前)
  • 18:39
    • s4ichi: 分割された isu_condition2 テーブルへの対応を完了
    • 過去最高スコアを記録
  • 18:45 競技終了
    • 最後に見たスコアは 83520

まとめ

Ruby で出場すると準備含めてやることがたくさんあって楽しい!!!!!

Ruby で戦っているチームだからこそ見える Go の優位性があり、それが見えるからこその戦法とツール開発があります。

たぶんまた来年も Ruby で出ます。

WEB+DB PRESS Vol.122に特集「Rustで実装!作って学ぶRDBMSのしくみ」を書いた

f:id:koba789:20210408181437p:plain:w735

KOBA789 です。

時が経つのは早いもので、気づけば2月末に無職になってから1ヶ月以上が過ぎていました。

その間に何をしていたのかといえば、表題の特集記事の執筆をしていました。

宣伝

このブログ記事は WEB+DB PRESS Vol.122 を読みたくなるためのものです。ぜひ買ってね。買ったらちゃんと読んでね。

gihyo.jp

使用言語は Rust だし、RDBMS はそもそも難しいトピックだしで結構重めの内容ですが、まずは読み物として寝転びながらでもいいので読んでみてほしいです。

ゴールデンウィーク*1の自由研究のお供にもどうぞ。たぶんちょうどいい分量なんじゃないかなぁ。ゴールデンウィーク明けは自作 RDBMS を友人・同僚に自慢しましょう。

内容

タイトルのとおり、Rust で RDBMS を自作します。といっても主眼は RDBMS 自作ではなく、RDBMS の仕組みを知ることです。

作ろうとすると仕組みを知らざるをえないので、学びたいなら作りゃいいじゃんという理屈です。

実際の内容は下記目次を見てください。知ってる人が見ると「あれがない」「これがない」となりそうな目次ですが、まさか full-featured な RDBMS を学習目的で作るわけにはいかないのでご容赦ください。

目次: WEB+DB PRESS Vol.122|技術評論社

きっかけ

以下自分語り。

当ブログの以下の記事を見つけた WEB+DB PRESS の編集の方からお誘いの連絡をいただきました。些細なことでもブログに書いておくもんですね。

diary.hatenablog.jp

ちなみに、WEB+DB PRESS の特集記事で扱っている題材の RDBMS は、上記ブログ記事で取り上げている実装 qp とは別物です。

いくらかコードは流用していますが、WEB+DB PRESS 用に新規で書き下ろしています。発売に合わせてリポジトリを公開します。公開したらここにも追記しておきます。

追記: 先行販売にあわせてリポジトリを公開しました。

github.com

執筆

執筆は想像以上に大変で、想像より楽しかったです*2

実はこの規模の文章の執筆経験というのはあまりなく、しかも特集丸々ひとつを一人で考えて書かなきゃいけなかったので大変でした。

ある程度分量があると1日では書き切れないので作業が日を跨ぎます。するとモチベーションのコントロールが必要で、しかしこれは一人でやってるとどうにも難しい。

執筆自体は楽しくて、いつものノリで早口オタクを繰り広げたやつを文字にするだけでした。バーッと吐き出して、余計だなぁと思ったところを切り取るといった感じです。

吐き出すのはすごく楽しいですが、切り取るのは楽しくないですね。編集の方にいろいろ手伝ってもらいながらなんとか整えました。

感想

機会に恵まれたなぁと思います。私自身は極めて怠惰なので自発的に何かを成し遂げるということがなく、だいたいは大見得切ったばっかりに引くに引けなくなって最後までやることになるパターンです。

今回のように大見得切るチャンスをいただけると、自発的にはできないようなことを(結果的に)成せるのでありがたいです。

そういえば、かつて青木峰郎(前職の上司、って表現でいいのかな)に「ふつうの RDBMS」って本書いてくださいよ、と言ったことがありました。

結局未だに書いてくれてないんですが、どうしても読みたいので少しくらいは自分で書かないとダメかなと思って今回書いたみたいな経緯があります。

今後

発売めでたいハイ終わり、でもいいんですが、DBMS オタクとしてはまだまだ語り足りないことも多いのでどこかでまた吐き出せたらいいなと思っています。

DBMS フレンズがあまりいないので話したいことが溜まってるんですよね。無職になって一番困ってるのは DBMS の話をできる人間が近くにいなくなったことですし。

とにもかくにも飽き性なのですっかり忘れてるってこともありえますが、もし覚えてたらやっていきます。よろしくどうぞ。

追記2: YouTube にサンプルコードのデモを含む紹介動画を投稿しました。ゴールデンウィーク中は何本か追加で解説動画を公開していきます。こちらもよろしくどうぞ。 www.youtube.com

*1:無職は毎日ゴールデンウィークです

*2:編集の方には大変ご迷惑をおかけしました……

クックパッド株式会社を退職しました

タイトルの通りです。2月26日付でクックパッド株式会社を退職しました。有給は6時間しか余っていなかったので最終出社日=契約最終日です。

社内の人は社内ブログにもうちょいマシな記事を置いてきているはずなのでそちらを読んでください。

なんでやめたの?

改めて説明するのがダルいのであまり詳しく書きたくはないのですが、要らぬ邪推を避けるために書いておくと、少なくとも給与やオフィス移転などへの不満ではないです。

平たく言えば COVID-19 Situation に疲れたというやつです。

転職先は?

転職しません。無職をやります。

フリーランスやるんですか、ともよく聞かれるんですがフリーランスは無職ではありません。

しばらくはやりたいことをやって過ごそうかと思います。学びたいことはたくさんあるし。

最後に

元同僚のみなさんへ。改めて、本当にお世話になりました。

この狭い業界で、あるいはこの広い世界のどこかで、いつかまた互いの行く道が交わるときが来たのなら、そのときは仲良くしてくれると嬉しいです。

草草不一

クエリエクスキューターの気持ちになる

これは 自作DBMS Advent Calendar 2020 - Adventar 25日目の記事です。

LSM-Tree 実装するとか言ってたけど奥歯に穴が空くなどのインシデントがあり、できませんでした。

代わりと言ってはなんですが、簡単な Tuple-at-a-time 方式のクエリエクスキューターを書いてみたのでご紹介します。

github.com

実装した理由はもちろん自分の学習のためでもあるのですが、会社の同僚が MySQL のインデックスの貼り方で悩んでいるときにパッと説明用に取り出せる小さいコードが欲しかった、という背景があります。 そういうわけで今回は Rust ではなく Ruby で書いてみました。

クエリ実行にだけ焦点を当てたかったため、データはすべてナイーブなインメモリで書き込みなし、データ構造も B-Tree ですらなくて静的に構築されたただのソート済み配列です。

B-Tree もソート済み配列も検索の時間計算量は O(log(n)) であり、違うのは挿入と削除の時間計算量です。 DBMS の利用者的な観点で言えば、B-Tree は挿入と削除の時間計算量が O(n) ではなく O(log(n)) な魔法のソート済み配列とみなすことができます。

このような激しい割り切りにより、わずか200行程度で SeqScan, IndexScan, Limit, Sort の基本的なオペレーターと4種類の実行計画のサンプルコードを実装できています。この実装の小ささは Ruby の Enumerable の便利さも一役買っています。

これくらい短いコードであれば DBMS 初学者にもポンと渡して十分気軽に遊んでもらえるのではないかと思います。

サンプルコードのテストデータとして ISUCON9 予選問題のデータを利用しています。 参考実装からクエリを拾って、それを題材に適切なインデックスと実行計画を考える練習ができます(問題公開されてるのはマジで偉大)。

ISUCON の練習や MySQL の学習と称して布教をし、うっかりこちら側に足を滑らせてくれる人が増えないかなと目論んでいる次第です。

というわけで、Ruby 200行から始める DBMS 沼のご紹介でした。

Happy Holidays!

Amazonのコンテナホスト用OS「Bottlerocket」をなんとかして自宅サーバーで使う

id:koba789 です。

ここのところ B-Tree の話ばかり書いていたのでたまには別のネタを。

自宅サーバー管理めんどくさい問題

みなさん自宅にサーバーはありますか。
まぁ当然あると思うんですけど、管理めんどくさくないですか。私はめんどくさいなぁと思っています。

主に何がめんどくさいかといえば各種(たくさんの)パッケージの定期的なアップデートや構成管理だと思います。

Mutable な物体の管理はめんどくさい、Immutable なら毎度発破解体して作り直せばいいので気がラクでよい、というのがここ10年くらいのトレンドであり、ベアメタルにインストールする OS なんてのはコンテナが動けばそれで十分であって、コンテナの外のユーザーランドに余計なモノを置くのはジリープアー(徐々に不利)だということにみなさん薄々気づいているわけです。

私は10年くらい前からそのような事実に気づいていたので、当時から SmartOS というおもしろ OS を使っていたのですが、最近は開発元である Joyent の異常者CTO が辞めてしまって先行きが不安ということと、そもそもカーネルLinux ではないのでやはり互換性の面で不安というのがあり、使うのをやめていました。
というか Linux カーネルじゃないのに Linux の Docker イメージが動くってどういうことなんだマジで(こういうことらしいです)。

というわけで最近は RancherOS というやつを使っていたのですが、これがまたいまいち開発に元気がなくなってきてしまったので乗り換え先を探していました。
ちなみに、乗り換えるときも kube のマニフェストをスッとするだけでだいたい済むのはコンテナ OS のいいところですね。

乗り換え先 Bottlerocket

乗り換え先として Bottlerocket という OS に目をつけました。

aws.amazon.com

これは Amazon が開発しているコンテナホスト用 OS です。
いまのところは AWS 向けに開発が進んでいるため、EC2 以外の環境でそのまま動かすことはできません。
EC2 以外でも動かせるようにする計画はありそうなのですが、少なくとも現時点ではコードに手を入れるしかありません。 もっとも、ベアメタルで動かそうと思うと相応の苦しみがあります(後述)。

自宅で動くように改造する

SSH できるようにする

Bottlerocket では管理用のシェル環境すらもコンテナ内です。管理用コンテナには control と admin の2種類があります。

control は Bottlerocket の apiclient(ちょっと設定変更とかができる)を叩く用、admin はトラブル時にホストの ns に入ってトラブルシューティングをする用です。admin はデフォルトで無効化されており、control コンテナに入って有効化してはじめて起動します。

後者の admin コンテナのシェルへのアクセスは普通に SSH なのですが、前者の control コンテナのシェルへのアクセスは、セキュリティ上の理由から SSM(AWS Systems Manager Session Manager) を使うことになっています。
もちろんそんなもの(SSM)はおうちにないですし、apiclient は admin からでも叩けるので、自宅では control コンテナを使わないことにします。
常に admin コンテナを有効にしておくことになるのでセキュリティ的には弱くなりますが、自宅に SSH 以上のセキュリティを求めるのは難しいので諦めます。

で、この admin コンテナの ssh に使う公開鍵はオリジナルだと IMDS から取得することになっているのですが、これもまたおうちにはないので使わないこととし、代わりに公開鍵をコンテナイメージに焼き込みます。

これで SSH 可能になりました。

パッチはこんな感じ。

github.com github.com

ouchi(おうち)。アウチではない。

アップデートを配るリポジトリを用意する

さて、ここまでで自宅の VM で起動するようにはなっています。しかしアップデートは動きません。

Bottlerocket は TUF 準拠の仕組みでアップデートを行います。
オリジナルの Bottlerocket は S3 にある TUF Repository でアップデートを配っているのですが、私はカスタムビルドのアップデートを配らねばならないため、別途専用のリポジトリが必要です。

私は minio を使って自宅のネットワーク内に構築しました。

ベアメタルで動くようにする

ここからが本当の地獄です。

Bottlerocket のカーネルには、 EC2 の VM インスタンスまたはベアメタルインスタンスで動くのに十分なドライバしか含まれていません。

さらに悪いことに initrd や initramfs を使わないブートシーケンスを採用しているため、rootfs をマウントするまでに必要なドライバはモジュールにしてはいけません。

足らない場合、rootfs のマウント前にブートがコケて止まるわけなので調査は困難を極めます。ログをビデオカメラで撮影して追いかけるなどのテクが必要になります(シリアルコンソールを使え)。

最終的にうちのサーバーで起動させるのに必要な kernel config は以下のパッチのようになりました。

github.com

Bottlerocket は AmazonLinux 2 ベースなので、docker で amazonlinux:2 を起動してその中で make menuconfig するのが便利だと思います。

config を足してはビルドして、USB メモリに焼いてサーバーに刺して電源 ON、そしてブートが途中で止まる、というようなことを5億回くらいやりました。MegaRAID は許さん。

まとめ

とりあえず起動して SSH が通るところまではできました。
しかしまだ admin コンテナが起動するだけで、kubelet が不在の状態なので使い物になりません。

ここまで来ればあとは普通の Linux なのでなんとか常用するところまでもっていきたいですね。

B-Treeを図示するときの細かいテクニック

これは 自作DBMS Advent Calendar 2020 - Adventar の12日目の記事です。
自作 DBMS ネタというか、課題で B-Tree を書かされてる学生向けって気もしますが、いずれにせよ誰かの役に立つと信じて。

Disk-Oriented な DBMS で欠かせないデータ構造といえば B-Tree です。 で、そのデータ構造をちゃんと把握するには図示が有効なわけですが、これがまた大変というか、理解のために書いてるのに理解してないからうまく書けなくて余計混乱するという悪循環に陥りがちなわけです。

というわけでこの記事では B-Tree を図示するときの細かいテクニックをご紹介します。 (ボケーっとしながら書いたら真の B-Tree と B+Tree が混ざってしまった。適当に脳内で補完して読んでください)

ノードはキーと値(ポインタ)の2階建てにする

素朴に実装する場合、キーと値のペアの構造体を配列で持ったものをノードすると思います。
Rust で書くとこんな感じ。

struct Pair {
    key: K,
    value: V,
}

struct Node {
    pairs: Vec<Pair>,
}

こうすると、メモリ上では キー, 値, キー, 値, … という風にキーと値が交互に並ぶわけですが、これをそのまま図にするのはおすすめできません。
眺めているうちにどれがキーでどれが値だかわからなくなるからです。

そこで、キーと値を分けて2階建にします。こんな感じ。

f:id:koba789:20201211235116p:plain
2階建てにする

左上の斜線が入っている部分は使わないキーのフィールドです。 B-Tree のノードでは必ず値の個数がキーの個数より1個多くなりますから、素朴にペアを交互に並べた場合は必ずどこかに余りが出ます。
この使わない余りを右端にするか左端にするか悩むところですが、おすすめは左端です。
その理由については、図示のテクニックというより実装のテクニックなので今回は省略します。またの機会に。 (2分探索でもさらにもう一本書けるんじゃないか)

一番左の矢印は子ノードの右上に、それ以外は左上に

先程の図で、値のフィールドにキーとの不等式(?)が書いてあったのに気が付いたでしょうか。 キーの直下のポインタの先にあるノードのキーはいずれもそのキー以上であり、キーの左下のポインタの先にあるノードのキーはいずれもそのキー未満である、という意味です。 この関係を矢印に反映させることで混乱を減らせます(主観)。

f:id:koba789:20201212005005p:plain
キーの大小関係を意識して矢印を引く

ルートノードの一番左のポインタ、つまり未使用キーの下から伸びる矢印は一番左のノードの右上を指すようにします。 「一番左のノードには5未満のキーしかない」ことをわかりやすくするためです。
もちろん、メモリ上のアドレス的には左のノードの先頭のキーのあたりを指しているんですが、この場合そっちに忠実になるよりはキーの大小関係に着目したほうがわかりやすいと思います(個人差があります)。

それ以外の矢印については ノードの左上を指しましょう。こちらも決してノードの真上とかを指さないように。

このようにすると、木が B-Tree の要件を満しているかどうかを素早く判断できるようになります。
矢印の向きがそのままキーの大小関係になっているため、左向きの矢印の先でキーが大きくなっていないか、右向きの矢印の先でキーが小さくなっていないかを確認するだけで済みます。簡単ですね。

まとめ

というわけで今回は超小ネタを紹介しました。
もちろん図示の仕方はこれだけが正解ではありません。ぜひ自分にあった作図の方法を探ってみてください。

今回紹介できなかったノードの構造のパターンや2分探索のパターンなどはまた後日気が向いたときに記事にします。アドベントカレンダーにはまだたくさんの空欄がありますからね!

ではまた。