<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>bobuhiro11&#39;s blog</title>
    <link>/</link>
    <description>Recent content on bobuhiro11&#39;s blog</description>
    <image>
      <title>bobuhiro11&#39;s blog</title>
      <url>https://blog.bobuhiro11.net/summary_card_with_large_image_600x314.png</url>
      <link>https://blog.bobuhiro11.net/summary_card_with_large_image_600x314.png</link>
    </image>
    <generator>Hugo -- 0.127.0</generator>
    <language>ja</language>
    <lastBuildDate>Fri, 14 Aug 2026 00:59:34 +0900</lastBuildDate>
    <atom:link href="/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>XDP によるパケットミラーリング</title>
      <link>/2026/08-14-xdp-mirror.html</link>
      <pubDate>Fri, 14 Aug 2026 00:59:34 +0900</pubDate>
      <guid>/2026/08-14-xdp-mirror.html</guid>
      <description>Linux においてパケットミラーを実現する方法はいくつかあるが、 XDP単体ではパケットミラーリングは実装できないのではないかと思っていた。 つまりTCなど他の機能と組み合わせる必要があると考えていた。
いくつか実験の結果、devmap 全エントリへの同時送信の機能を使うことによってパケットミラーリングできることがわかったので記録を残しておく。 コードは xdp_mirror.py として公開している。
全体像はこのような感じ。3台のホスト h1-3 があり、ゲートウェイ gw がそれらを接続している。 ホストとゲートウェイは netns で仮想的に作ったもので、veth ペアで接続されている。 h1からh2へ Packet1 が転送されている状況において、 gwが事前に設定した5tupleにマッチした場合には、 h2へ転送するのに加えてパケットを加工しつつh3へも転送する。 繰り返しになるが TC などの外部の機能を使わずXDP単体で実装する。 灰色のブロックがXDPプログラムを示す。全部で4種類ある。 host_pass.c は veth のために作成したが本質ではないので無視して良い。
filter.c では5tupleによるマッチングを行い、マッチした場合には devmap の全エントリに対してパケットを送信する。
// filter.c SEC(&amp;#34;xdp&amp;#34;) int xdp_filter(struct xdp_md *ctx) { ip = ... ; udp = ... ; struct five_tuple key = { .saddr = ip-&amp;gt;saddr, .daddr = ip-&amp;gt;daddr, .sport = udp-&amp;gt;source, .dport = udp-&amp;gt;dest, .proto = ip-&amp;gt;protocol, }; // Mirror Enabled: the packet is sent to // all entries (for h2 &amp;amp; h3) in the devmap.</description>
    </item>
    <item>
      <title>AIの使い道</title>
      <link>/2026/03-06-how-i-use-ai.html</link>
      <pubDate>Fri, 06 Mar 2026 01:31:34 +0900</pubDate>
      <guid>/2026/03-06-how-i-use-ai.html</guid>
      <description>2026年3月時点でどんな感じでAIを活用しているかを残しておこう。 変化の大きい領域なので後からふりかえると楽しいかもしれない。
コーディング 特にこだわりを持たずClaude Code、Codex、GitHub Copilot CLI を使っている。 どれも有料あるいはそれ相当のプランで利用している。 それぞれ小さな違いはあれどどれを使っても満足できる品質のコードが出てくる。 Allow/deny-tools、MCP、カスタムスラッシュコマンドをいくつか設定している程度でカスタムは少なめだと思う。 自分がコードを書くときはプランモードで計画を作ることから始める。不明点があれば最近はコーディングエージェント側から質問（選択肢 + 自由入力のハイブリッド）してくれるのでそれに答えながらまとまった文書に仕上げていく。この段階で最終的なアウトプットまで確定させておく。例えば Pull Request が欲しいならその指示を含めておくし、プロジェクト管理ツールのステータス・コメントを更新するならその指示を含めるようにする。テストについては、期待するスコープ・カバレッジを伝え、ローカルのテストとCIが成功するまで継続的にウォッチ・修正するよう指示する。そこまでできればあとは YOLO モード （all-allowとかautopilotとかとも呼ぶ）で一気に完遂させる。 サブエージェントとかAgent Teamとかそういう事は考えていない。 タスクの進め方についてはコーディングエージェントに任せて、人間は仕様の策定に集中する。ここまでで動くところまでは持っていけることが多い。
そこから先、PRの提出先によっては体裁を整えることにそれなりの時間を使っている気がする。例えば、コミット粒度やメッセージが適切かとか、これまでのコードの書きっぷりと差がないかとか外堀の部分。場合によってはコーディングエージェントの出力を横に置いてもう一度書き直していることもある。書いたのがAIであってもAuthor はこれまで通り自分だという感覚。ここが変わってない。
コードレビュー 溜まったReview Requestsに対して一括でレビューするようなカスタムスラッシュコマンドを作っている。 毎日一回程度実行して参考情報として使っている。 あくまでも参考情報をもらうだけで、Approve/Rejectの判断は人間がやっている。 馴染みのあるコードについては引き続き自分でレビューしている。 馴染みがないものや大規模なものは一発コーディングエージェントに投げてみて、質問を繰り返して理解を深めてから中身に入る。 実はここはあまりコーディングエージェントの恩恵を得られていないところでもある。 コードレビューをしている時には、純粋にコードの良し悪しだけを見ているのではなく、 他の変更と衝突しないだろうかとか、 安全にデプロイできるだろうかとか、 関連するユーザやチームのワークロードに影響はないだろうかとか、 適切な人がレビュアーに入っているだろうかとか、 どこまでの完成度を求めるべきだろうかとか、 いろんなことを考えていてそれを手放しにコーディングエージェントに任せる事はできていない。 長期の信頼によって成立しているところがあり、それができていないAIにはまだ完全にお願いするということはできず人間のApprove 作業が残っていてスケールできていない。 判断基準の言語化さえ出来ればおのずとツールは揃うことになるし、段々と人の手を離れていくのかな。
ドキュメント 人間がめんどくさいと感じる領域でありつつ、コーディングエージェントに向いている領域なので効果的に使えている。ここの負荷はだいぶ下がった気がする。コードとドキュメントそれぞれの全体を広く見回した上での一貫性のある編集はAIの得意分野だと思う。 デプロイメントのリスクが小さくリカバリーも容易いので向いている。
トラブルシューティング エラーメッセージと関連するリポジトリを渡して原因を特定するような小さなものは非常にフィットする。ただ「なんかたまに失敗するなあ」みたいなところを出発点にして、仮説と調査を繰り返すみたいなことはまだできていない。これは性質的に割り込みタスクであるし緊急性が高いことが多く精神的にも肉体的にもあらゆる面で人間の負荷が高い。AI導入の価値が大きい領域だと思う。十分な量のReadonly なツール群と安全な小さなWrite系ツール群がありかつ自律性の高いエージェントを作れば、AIは体力が無限にあるのでうまくフィットしそうな気がする。
定常的な作業 AIの導入を進めるというよりも、日々AIを使いながら自動化を進めていくのが良いと思っている。例えば、AIに日々の作業の手順書を書かせるのではなく、手順書が不要になるような自動化のためにAIの力を借りるという感じ。
文書作成 ここはAIがハマるかと思いきやそうでもない。 自分が普段使う資料は議論を促すようなものや誰かと方向性を合わせるために使うものが多く、AIに書かせたとしても文書を読んだ後のディスカッションに耐えないのでそのままでは使えない。資料があってそれを互いに読んでラフな理解があった前提で、そこからの会話が本番という感じなので自分の言葉が入っている必要がある。
おわりに 便利ツールの一つとして使い倒そうと考えている。仕事を奪われるとかそういうのはあまり感じることがない。 人間の代わりになるとも思わない。
遥かに人間を超越した知識や推論ができるけど長期的なプランを持っていない受け身なロボットが出てきたという感じ。今日時点だと人間が手綱を握るフェーズなのかな。
AIと人間の間には（人間同士にあるような）学習のフィードバックがないので、チームで動いた時に人間側が受け取ると期待される知識・経験が不足してしまう。 AIと一緒に何かを検討したり作ったりしたとしても、（ツールとしてAIを活用しているだけなので）個人開発の域を出ない気がしている。 あれ難しかったよね、実はあそこは… みたいなカジュアルな振り返りの会話が大事なんだろうね。 それが1エンジニアとして長期的にやっていくのに必要なものなんだろうと思う。
数年後はどうなってるだろうか楽しみ。 おしまい。</description>
    </item>
    <item>
      <title>Alacritty&#43;Tmux環境でShift&#43;Enterを使う</title>
      <link>/2026/02-27-shift-enter.html</link>
      <pubDate>Fri, 27 Feb 2026 01:31:34 +0900</pubDate>
      <guid>/2026/02-27-shift-enter.html</guid>
      <description>Claude Code や Codex CLI でプロンプト入力中にShift+Enterで改行したいときのTipsをメモしておく。 Alacritty と Tmux を組み合わせた時デフォルトではうまく動作しなかったため、それぞれ以下のように設定した。 Claude Code や他のツールでは /terminal-setup のような初期設定のための機能を提供してくれていることがあるが、 どうもそれではダメそうだった。
まず Alacritty の設定ファイル alacritty.yml に以下のように追記する。
[[keyboard.bindings]] key = &amp;#34;Return&amp;#34; mods = &amp;#34;Shift&amp;#34; chars = &amp;#34;\u001b[13;2u&amp;#34; 続いて Tmux の設定ファイル .tmux.conf に以下のように追記する。 ダブルクォートの中には特殊文字が含まれていて、 おそらく &amp;lt;Control&amp;gt;-v &amp;lt;ESC&amp;gt; [ 1 3 ; 2 u と連続して入力すれば良いはず。
bind-key -n S-Enter send-keys -l &amp;#34;[13;2u&amp;#34; ちなみに、Claude Code と Codex CLI では期待通り改行できたが、 Copilot CLI ではうまく動作しなかった。 まあいずれ対応するだろう。
ファイル全体はこちら。 おしまい。</description>
    </item>
    <item>
      <title>イシューからはじめよ 読書メモ</title>
      <link>/2026/01-22-issue.html</link>
      <pubDate>Thu, 22 Jan 2026 00:01:40 +0900</pubDate>
      <guid>/2026/01-22-issue.html</guid>
      <description>数年前に買って積んでいた本だが読んでみるとなかなか刺さる内容だった。 生産性が高いというのは人よりも素早くタスクをこなせるとか大量にこなせるとかそういうことではない。 時間（だけじゃなくいろんなもの）は有限なので解くべき問題の見極めが重要になる。 限界まで働くとか、労働時間で勝負するようでは生産性の高い人にはなれない。 イシューの度合いと解の質が両立するコアな問題に取り組むことが大事になる。 この部分でベテランだったり、同僚だったりの知識も活用できる。 イシューを見極めたら、イシューの分割、仮説とストーリーラインの設定、検証を繰り返す。
ここで大事なのが、
仮説段階であってもストーリーライン（背景から結論までの一貫した話の流れ）まで考え抜くこと。早まって検証に移らない。検証・実験によるデータを待つのではなく、それより前に仮説をベースにした自分なりの考えを結論まで考え抜く。もちろんここでは間違っていて良い。 継続して言語化を怠らないこと。 その準備ができてから検証や実験に移る。 そしてその結果を次のサイクルの仮説やストーリーラインの設定に反映する。 このサイクルを高速に回す。
言語化について。 主語や動詞を明記して曖昧さをなくす。 Why ではなく Where/What/How のいずれかの形でイシューを設定する。 答えを出す、という前提で設定するとこれらの表現になることが多い。
成果物の設定について。 論文やプレゼンテーションを成果とする場合、その絵コンテはデータが揃い切る前に大胆に描く。 ここでもデータに先行して進めておくことが大事。 大胆に描くことで、検証方法・実験方法の制約を受けずに済む。 インパクトある結果は、新しい実験方法の提案とともに出てくることも多い。 一つのグラフは一つのことを説明するようにする。 これは文書構造でも同じだろう。 聴衆はデルブリュックの教えに則って仮定する。
無意識のうちにここで書かれたことを正反対のことをやってしまい遠回りしていることが多い。 深みにハマりそうなら早くに抜け出したいし、これらが当たり前の進め方として自分の中で消化できれば良いなと思う。 おしまい。</description>
    </item>
    <item>
      <title>石垣島マラソン 2026</title>
      <link>/2026/01-21-ishigakijima_marathon.html</link>
      <pubDate>Wed, 21 Jan 2026 23:31:34 +0900</pubDate>
      <guid>/2026/01-21-ishigakijima_marathon.html</guid>
      <description>2026/01/18 石垣島でハーフマラソンを走ってきた。 例年は雨模様だったようだが今年はスタート前にパラパラ雨があったくらいでそれ以降は曇り空といった感じ。 20℃くらいあったと思うけど走りには特に影響なかった。 前回のマラソンで膝を痛めてリタイアしたことや、最近軽く走っただけでも同じように痛むことがあったので無理せず完走を目指すことにした。 怪我によるリタイアはやりきれない思いになりかねないので安全重視で行くことに。 ハーフの制限時間はたっぷり4時間あるので登り坂・下り坂では意識的に歩きながら走った。 沿道からはめちゃくちゃ応援してくれたり、エイドが充実してたり、と楽しむことができた。 八重山そばを食べハンバーガーを食べ帰ってきた。 飛行機の距離のマラソン大会は初めてかもしれない。 いつも思うがもっと練習して颯爽と走り抜きたい。 ではでは。</description>
    </item>
    <item>
      <title>プログラマが知るべき97のこと 読書メモ</title>
      <link>/2024/12-25-97-things-programmer.html</link>
      <pubDate>Wed, 25 Dec 2024 00:59:34 +0900</pubDate>
      <guid>/2024/12-25-97-things-programmer.html</guid>
      <description>プログラマが知るべき97のこと をスキマ時間に読んでいた。気になったところをメモしておく。
技術的負債は、即座に次のイテレーションで返済する。そうでなければ利息が膨れ上がる。 ゼロから描き直したい衝動・誘惑に打ち勝たなければならない。できるだけ既存コードを生かす。 新たな変更を加える時には1箇所でも良いので改善する。 コードを書くことは設計をすること。機械的な作業ではなく、創造的なもの。 コードレビューの目的は誤りの修正だけでなく、コードの共有所有を確立すること。 コメントには読む人が価値があるものを書く。つまり、コードに書いていないことや、コードにかけないことが書かれるべき。 プロジェクトの初期からデプロイ作業を始める。 1万時間やればエキスパートに必ずなれる。ほぼ自分がなろうとするかという意思の問題。 Windows 2000には&amp;quot;TERRIBLE HORRIBLE NO GOOD VERY BAD&amp;quot; と書かれている。見られて恥ずかしいデータは使わないこと。 厄介なのは今はプログラマでなくても以前プログラミングを「ちょっとしたことがある」くらいの人。 SCM へのチェックイン後は開発者は傍観者になるべき 開発者は開発サーバより後の環境へはアクセスしない、QA・顧客は開発サーバへアクセスしない API自身だけじゃなく、APIを利用するコードのテストもする ハードワークは報われない。自分の働く時間や労力を減らすほどプロジェクトへの貢献が大きくなる。 知識と技術の研鑽を怠ってはならない。 バグレポートには、バグの再現方法、頻度、本来の仕様、実際の動作を書く。 パラダイムの異なる第二の言語を学ぶ。 データ構造、アルゴリズムの時間と空間の複雑性を知る。 見積もりを求められた時には、見積もり、ターゲット、コミットメントを区別する。 正しく使用する方がミスするよりも簡単。インターフェイスが良ければ、正しく使用できる。 メモリ共有の代わりに、メッセージパッシングを使う。 テスト担当者は敵ではなく友人。 環境に関する情報もバージョン管理する。 互いの理解には、定義の共有ではなく経験の共有が必要。 シングルトンパターンはテストや保守性の点で不利。 Ubuntuはズールー語で他者への思いやりという意味。 このコードは生涯、自分がサポートし続けると思って書く。 テストは見る人のために書く。 顧客には頻繁に疑問を投げかける。顧客から言われたことを自分の言葉で言い直すと良い。 議論の時は図や絵を利用することが大切。設計の早い段階でモックアップを作るのも良い。 ステートを取り扱う時はステートマシンを意識する。 コードネームをつける。身近でよく知っている名前が良い。チームの結束のための合言葉。 単純作業であってもルーチンワークを1日の最初に行う余地を残しておくと良い。 師匠となる人を見つけると良い。 快適な環境を追求する。 声の大きいユーザからの要望に忠実に答えると、バグの出やすいソフトウェアになってしまう。Feature Creepに陥る。 命名にこだわる。機能の設計の重要な一つ。 </description>
    </item>
    <item>
      <title>入門 eBPF 読書メモ</title>
      <link>/2024/12-05-learning_ebpf.html</link>
      <pubDate>Thu, 05 Dec 2024 00:59:34 +0900</pubDate>
      <guid>/2024/12-05-learning_ebpf.html</guid>
      <description>入門eBPF を読んだので、 読書メモを残しておきたい。去年発売された本でずっと読みたかったもの。 lizrice/learning-ebpf - github.com にサンプルコードが豊富に準備されているので参考になる。 文脈は意識せずとりあえず個人的に気になったところをメモしておく。
BCC まずはBCCを使った例から始まる。 bpf_trace_printk() を使うと擬似ファイル/sys/kernel/debug/tracing/trace_pipeにテキストを出力できる。 簡易的にはこれを使えば良いが、eBPFプログラムごとに出力先を分けたい場合には、BPF MAP を使って自前で カーネルとユーザ間でデータをやり取りすれば良い。 PerfリングバッファやBPFリングバッファを使えば柔軟なデータ構造（構造体）でやり取りできる。 前者はCPUごとに領域が分かれているが、後者は全てのCPUで共通の領域で順番も正しい。さらに性能も良いらしい。 Tail Callという仕組みを使えば別のeBPFプログラムを呼び出せる。 Tail Callは完了しても元のeBPFプログラムには戻ってこないのでジャンプのようなもの。 Tail Callを使うにはあらかじめ BPF_MAP_TYPE_PROG_ARRAY 型のMAPを準備しておく必要がある。
仮想マシン 汎用レジスタは10個、そしてスタックフレームポインタがある 1。 Calling Conventionについて解説がされていた。 reg0がeBPFプログラムの引数で、reg1がその戻り値となる。 関数呼び出しではreg1からreg5が引数となる。 命令長は64bitだけど、それを組み合わせたワイド命令もある。 SEC()マクロでコンパイル後のセクション名がわかる。 CからeBPFバイトコードへ、あるいはRustからeBPFバイトコードへコンパイルできる。
bpf(2) bpftool コマンドは eBPF のロードやアタッチができる便利なツールだが、その中では bpf(2)が使われている。 多くの操作は bpf(2) で実現できるが、アタッチに関してはいくつかバリエーションがあり、bpf(2)な場合もあればperf_even_open(2)とioctl(2)を組み合わせる場合もある。 カーネルにロードされたeBPFプログラムやMAPは、複数参照カウンタが0になれば自動削除されるが、BPF linkや特殊なファイルへのピニングによって参照カウンタを1つ増やせる。 これによって bpftool コマンドは実行が終了したとしても、eBPFプログラムをロードしたままにできる。
CO-RE, libbpf CO-RE (Compile Once - Run Everywhere)を使うには BCC ではなく libbpf を使う。 カーネル5.4以降でサポートされている 。vmlinux.h を include するとカーネル内の多くの構造体を使える。 bpf_core_read を使うと実行カーネルバージョンとコンパイル時カーネルバージョンの差を埋めるよう、自動的にリロケートを考慮しつつカーネルデータを読み込める。 -g をつけてコンパイルしておくとeBPF検証機のデバッグも楽になる。 以前はループをunrollする必要があったが、今はbpf_loopやbpf_for_eachが用意されている。</description>
    </item>
    <item>
      <title>OVSでSRv6を使ってみる</title>
      <link>/2024/03-29-ovs_srv6.html</link>
      <pubDate>Fri, 29 Mar 2024 00:59:34 +0900</pubDate>
      <guid>/2024/03-29-ovs_srv6.html</guid>
      <description>OVS（Open vSwitch） 3.2でSRv6がサポートされた 1 ので使ってみる。 その使い方を端的にいうと以下のように type=srv6 としたポートを作成すれば良い。 VXLANやGeneveなど既存のトンネリングと同様のフレームワークを使って実装されているので、 options:remote_ipやoptions:local_ip でトンネルの両端（SRv6では双方のSIDに相当）を指定する。 それらに加えてSRv6では中継するルータをSegment Listとして設定できるよう特別なオプション options:srv6_segs が存在する。 ちなみにInner PacketとしてはIPv4、IPv6両方をサポートしている。
ovs-vsctl add-br br0 ovs-vsctl add-port br0 srv6_0 -- \ set int srv6_0 type=srv6 \ options:remote_ip=fc00:100::1 \ options:srv6_segs=&amp;#34;fc00:100::1,fc00:200::1,fc00:300::1&amp;#34; OVSでは主にkernelspaceとuserspaceの2種類のデータパスが存在しているが、 SRv6はuserspaceのみ対応している 2。 つまりDPDKやAFXDP 3 のような仕組みを使ってデプロイする必要がある。
Feature Linux upstream Linux OVS tree Userspace GRE 3.11 1.0 2.4 VXLAN 3.12 1.10 2.4 Geneve 3.18 2.4 2.4 &amp;hellip; &amp;hellip; &amp;hellip; &amp;hellip; SRv6 NO NO 3.2 さてどうやって動かすのか。 mininetのスクリプト 4 をベースとしてそれをシンプルなコマンド列に落とし込んだ。 以下のような構成で動かしてみる。</description>
    </item>
    <item>
      <title>Ansible実践ガイド ［基礎編］ 第4版 読書メモ</title>
      <link>/2023/12-01-ansible.html</link>
      <pubDate>Fri, 01 Dec 2023 00:59:34 +0900</pubDate>
      <guid>/2023/12-01-ansible.html</guid>
      <description>どうやら2016年にもAnsibleを勉強していたようだが 1 、 すっかり忘れてしまったので改めて Ansible実践ガイド 第4版［基礎編］ を読んだ。 気になったところをメモしていく。
Playbookの階層 1つのPlaybookはいくつかのPlayから構成される。 PlayはTargets、Vars、Tasks、Handlersの4つのセクションから構成される。 TargetsとTasksは基礎的なセクションで、 それぞれ対象のホストと実行するタスクの一覧を指定するために使われる。 VarsとHandlersは補助的なセクションで、それぞれ変数と実行制御 （例えばsystemdサービスのリスタート）を指定するために使われる。
Playbook Play: Targets Vars Tasks Handlers Play: Targets Vars Tasks Handlers テスト 単純なテストはansible.builtin.assertモジュールでカバーできる。 複雑なテストのためには Ansible Molecule 2 を使う。 テスト環境構築、文法チェック、冪等性のチェックなどの仕組みを持っている。 あるいは Ansible Spec 3 を使うと、RubyのRSpecを利用した Serverspecによってテストできる。
Ansible Galaxy ansible-galaxy install geerlingguy.mysql のようにしてロールをインストールできる。 ~/.ansible/roles あるいは /usr、/etc 配下に配置される。 --roles-path で指定することもできる。
Collectionは ~/.ansible/collections に配置される。 requirements.txt でその一覧を管理することができる。
チューニング ansible.cfgまたはANSIBLE_CACHE_PLUGINでファクトキャッシュを有効化しておくと良い。 forksを増やしておくと、 ローカルノードのリソースやネットワークの負荷とトレードオフになるが、 並列数を増やせる。
Ansibleは並列実行するとき全てのホストで足並みを揃えてタスクを1つずつ実行している。 これはストラテジプラグインで制御できる。 例えば ansible.builtin.free とするとホストごとに独立してタスクを進められる。 もちろんホスト間の依存には注意する。
SSHの多重接続（ControlMaster、ControlPath、ControlPersist）を有効化しておくと、 タスクごとにSSHを確立することによるオーバーヘッドを削減できる。 ちなみにOpenSSH6.</description>
    </item>
    <item>
      <title>つくって学ぶkubebuilder 読書メモ</title>
      <link>/2023/09-29-kubebuilder.html</link>
      <pubDate>Fri, 29 Sep 2023 00:59:34 +0900</pubDate>
      <guid>/2023/09-29-kubebuilder.html</guid>
      <description>つくって学ぶkubebuilder を読んだ。
簡潔によく纏まっている資料で勉強になった。 読んだ感想としてCustom Resource（CR）は自由度が高いので作りたくなるけど、 迂闊にその数を増やすと管理しきれなくなると思う。 おそらく本質的にCRでないと実現できない課題に対してのみ採用して、 かつミニマムに作ったり使ったりするのが良いんだろうと感じた。 例えばここで題材としたMarkdownViewに関しては、 現実にはCRじゃなく標準リソースの組み合わせで実現した方が良いんだろう。 もちろん題材としてはとっつきやすく良かった。
性能面はどうだろうか。 Reconcileループは1ループを軽量にしないと収束時間の予測が難しく運用しづらそう。 リトライはその状態を次のループにわたすなど、おそらく実装上のテクニックがいくつかあるんだろう。 標準のコントローラ、etcd、kube-apiserverへ与える性能影響も気になる。
Kubebuilerに相当するフレームワークは他にあるんだろうか？ Kubebuilderが標準でメジャーなのかな。 ざっくり調べたところKubernetes Way（client-goとcode-generator）とOperator SDKがありそうだ。
ここからメモ。私は Kubebuilder を今回初めて触るので誤解も含まれているはず。
序章 KubebuilderはCustom ControllerやOperatorを開発するためのフレームワークで、 controller-toolsとcontroller-runtimeが含まれる。 Custom Resource（CR）のコントローラをCustom Controllerと呼ぶ。 CRの仕様はCRD（Custom Resource Definition）で定義され、これはGoの構造体から自動生成される。 Kubernetesのリソースは宣言的、冪等、レベルドリブントリガーといった特徴があるので、 それに則った形で実装する。 MarkdownViewというCustom Resource/Controllerを題材にして手を動かしながら学べる。 ここ にコードが公開されているのであわせて読むと良い。
MarkdownView Custom Resourceを使うと以下を実現できる。
ConfigMapにMarkdownを1ファイルずつ保存する MarkdownのレンダラーとしてmdBookイメージを使ったDeploymentを作成する コンテナイメージとレプリカ数をCustom Resourceで指定する mdBookのDeploymentに外部からHTTPでアクセスできるようSerivceを作成する kubebuilder init/edit サブコマンド まずは空のディレクトリ上でinitサブコマンドを発行してプロジェクトの雛形を作る。 途中で変更する場合にはeditサブコマンドを使う。 重要なオプションは以下の2つ。
--domainでCRDのグループ名を指定する --repoにGoモジュール名を指定 makeコマンドを頻繁に使うのでmake helpでmakeターゲット一覧を確認しておくと良い。 ファイル中の//+kubebuilderは重要なマーカーなので削除しないよう注意する。 cmd/main.goがCustom Controllerのエントリポイントとなる。 config/配下にマニフェストが集約されている。 これらマニフェストは kustomization.yaml でまとめて管理されている。
create サブコマンド createサブコマンドで新たなAPIやWebhookを追加することができる。 例えばAPIの場合には、 create apiサブコマンドでCustom ResourceやCustom Controllerの雛形を生成できる。</description>
    </item>
  </channel>
</rss>
