重力に縋るな

千種夜羽です

最近は人工衛星作ってます(ブログタイトル回収)

こんにちは.最近元気になってきてツイート数が減っているsksatです. 最近労働ってやつがおもしろいのでその話をします.

おもしろ労働というと実は5月ぐらいからTierIVという会社でLLVMをいじくり回していていてとてもおもしろいです. が,今日は8月からバイトしてるもう一つの会社の話をします.

ArkEdge Space

ということで社ですが,ここです.

ArkEdge Space Inc.

はい.ずっとやりたいと思っていた本物の宇宙開発です.やったぜ.

具体的にどういう会社かというと,東大中須賀研発の超小型人工衛星のスタートアップです. 本当にまだ人の少ない会社ですが,かなり強い人材が揃っていますし,実際既に衛星も受注してます.

経緯

最近色々と仲良くしてもらってるKOBA789さんがオファーを受けるタイミングに何故かついてきた謎のオタクをやり, めちゃくちゃ興味あるんですが...→おk,みたいなかんじで入りました.そんなことある?

ということでKOBAさんの転職エントリもどうぞ. diary.hatenablog.jp

やっていること

僕の将来の目標はかなり前から「"枯れた技術"に強く依存した宇宙開発に新しいソフトウェア技術で殴り込んでいく」だったりします. そして,この会社は僕のこの目標とかなり方向性が近く,実際そういうことをやらせて貰っていますし,やっていくと思います.

具体的にはKOBAさんが言及しているようなRust製のフライトソフトウェア開発や, フライトソフトウェアの動作を含めて再現するシミュレータの開発といったことに取り組んでいます. もちろんやることは山積みですが,何十年くらいでやっていけるかな,と思っていたこの目標は自分の想像よりもかなり早く達成できそうです.

感想とか

とりあえず1ヶ月ぐらい働いてみた感想としては,マジで楽しいです. 大学が始まったら働ける時間が減っちゃうな,と思ってしまうぐらいには楽しい. 今までの個人的な(なんだかんだ稀有な)経験がかなり役に立っているのもかなりポイント高いです. 自分の関わったものが文字通り軌道に乗るのが待ち遠しいですね.

ということでWe are hiringというかんじなので,気になる人はぜひ. でもまずは僕が正社員になりたいですね(?)

マイクラサーバをGitHubで運用する

こんちわ〜.珍しく1ヶ月という短期間でブログ記事を書くsksatです. 今回はここ数ヶ月運用しているマインクラフトサーバについて書きます.

Minecraft

みなさんマイクラやってますか?僕はそんなにやってないです.運用するのはまあまあおもしろい.

とはいえそんなにやってないわけでもなくて,5月頃はけっこうやっていて,空中から海をブチ抜いて地中まで刺さっている畑などがあります. まあかなりのcontribution(?)は他のオタク各位ですけどね.

で,このマイクラサーバなんですが,以下のようなかんじで運用しています.

  • サーバ: PaperMC 1.17.1
  • モード: サバイバル
  • Mod/Plugin: 基本バニラ.使ってるものは以下.
    • PrometheusExporter
    • DiscordSRV
    • CoreProtect
  • ユーザ管理: ホワイトリストGitHub repoへのPull Requestで追加

GitHubでのマインクラフト運用

というわけで本題ですが,このサーバはGitHubを使って運用しています.

github.com

どういうことだよ,となると思うんですが,見ればわかる. このサーバはdocker-composeを使って運用していて,このリポジトリにはマイクラサーバをデプロイするためのスクリプト群がある,ということです.かんたんだね.

じゃあこのリポジトリをcloneしてきて,docker-compose upすればマイクラサーバが立ち上がってうれしい,ということかと思うじゃないですか. それは半分正解です.しかしそれだけではありません.

正確には,このリポジトリは常にmainブランチが本番環境に同期されるようになっています.

そしてよく見てほしいのですが,このリポジトリにはdata/whitelist.jsonがあります. そしてこのサーバに参加しているオタクが登録されています. 極めつけはREADMEの一番下.

how to join

Edit whitelist.json and send a pull request

はい.GitHubで運用するということは,つまりそういうことです.

なので,このマイクラサーバに参加したい人がいる時,僕はサーバにSSHしてwhitelist.jsonを書き換える必要はまったくありません. 必要なのは,「あ,じゃあmc.yohane.suのREADME読んでプルリク送ってね」の一言と,マージボタンを押すことだけです.

CD(Continuous Deployment)

みなさんマイクラサーバ運用でCDしてますか?僕はしてる.

mainブランチが本番環境に同期されるというのはこれの話です.

CD,したいですよね.でもこれdocker-composeなんですよね. CDするための良さげなツールとかないんですよ(あったら教えてほしい). Kubernetes使ってたらArgoCDでポン,みたいなかんじでいいんですけどね. というかできるならそのうちそっちに移行したい.

じゃあどうしてるのかというと,雑なスクリプトを書きました. 「docker-composeでもCDをしたい!」ということで,その名もcompose-cd

github.com

これはmc.yohahe.suのためではなく,kuso-subdomain-adderというものの運用自動化のために書いたスクリプトなんですが,けっこう便利なので最近はよく使ってます.

kuso-subdomain-adderteleka.suというクソドメインサブドメインを生やすためだけのWebサービス(?)です. ここらへんの話はVRC-LT #9でやりました.

speakerdeck.com

というのはさておき,compose-cdの話に戻りますが,使い方は超簡単. 各リポジトリdocker-compose.ymlがあるディレクトリに.compose-cdという設定ファイルを置くだけです.

compose-cdでは,docker-composeなプロジェクトで使うために,デプロイが走るタイミングとしてリポジトリ自体が更新される場合と,リポジトリで使っているイメージが更新される場合を想定しています.

リポジトリが更新される場合というのは,リポジトリでコンテナからマウントされるような設定ファイル(マイクラであればwhitelist.json)を管理していて,それが更新される場合です.

次にイメージの更新ですが,これは新しいバージョンのイメージが出たら更新する,という話ではありません. CDなんてことをする以上,ある時点でのリポジトリからはそのリポジトリ内で設定されているバージョンのモノがデプロイされるべきです. 更新してupstreamのリポジトリも更新するようにすればよいかもしれませんが,それは管理のしやすさ的にもセキュリティ的にもよくないでしょう.

端的に言うと,compose-cdの責任範囲はupstreamのリポジトリとイメージの更新を確認し,更新があればデプロイを実行する,ということまでだということです. ただし,latestのようなイメージタグを使っている場合は例外です. まあlatestなんて基本的に使うべきではないわけですが,別にプロダクションではなく趣味なので雑に使いたい時もありますよね. 最近は後述するRenovateのおかげでほぼないけども...

これらの2つの場合に対応するため,.compose-cdでは基本的にリポジトリ,イメージ,イメージタグを指定します. 例えば,kuso-subdomain-adderではこんなかんじ.ghcr.ioにも対応しています.

REPO="https://github.com/sksat/kuso-subdomain-adder"
REGISTRY="ghcr.io"
IMAGE="sksat/kuso-subdomain-adder"
IMG_TAG=master

compose-cdがやっていることはめちゃくちゃ単純です. 実際実装も300行程度のBashスクリプトとsystemd timerです.

compose-cd.timerがsystemd timerの設定で,毎分compose-cd.serviceを呼び出すだけです. compose-cd.serviceはcompose-cd updateを呼び出すだけです. compose-cd updateでは,SEARCH_ROOT以下のディレクトリで.compose-cdがあるディレクトリを探索し,.compose-cdにある設定に従ってリポジトリとイメージの更新を確認し,更新があればgit pullないしdocker-compose pullをして再起動(docker-compose down, docker-compose up -d)します.

まあ超単純なんでそんなに書くことはないですね. ghcr.ioだとうまくいくのにDockerHubだとうまくいかなかったりとか, うまくいっていたghcr.ioが突然動かなくなったりしたのは面白かったですが*1

github.com

ところで,今これを書いていてイメージだけの更新を使う場合に複数イメージ使うことを一切想定してないな,という気付きがあったので気が向いたら実装します. とはいってもそんな場合は自分で使っている分にはほぼないので別に要らないかな...ちゃんとdocker-compose.ymlでハッシュまで指定してくれ.

CI(Continuous Integration)

みなさんマイクラサーバ運用でCIしてますか?僕はしてる.

mc.yohane.suでは前述の通りwhitelist.jsonGitHubで管理しており,ユーザの追加はPull Requestで行うのですが, JSONって手書きするのダルいですよね.いやそんなにダルくない人もいるだろうし別にwhitelist.jsonは全然ダルくないんですが,プルリクが送られてきたのを何も見ずにマージするのも渋い.そこでCIです.

というわけでできたのがこちら.minecraft-whitelist-validatorです.

github.com

これはRustでちょろっと書きました. またしてもやってることは超単純で,whitelist.jsonをserde_jsonで読んで,Mojang APIを使ってユーザとそのUUIDを検証するだけです. そして,Docker Imageを作ってGitHub Action化もしたので,uses: sksat/minecraft-whitelist-validator@v0.2.0みたいなかんじで使えます.やったね.

そしてcargo initした後に気付いたんですが,これってcurlとjqでいいんですよね.まあRust書きたかったのでいいでしょう.

イクラマルチ鯖をGitHub repoでIaCしてwhitelist.jsonへのPRを募っていて, UUIDとかが合ってるかぐらいをCIでチェックしたい人がもし万が一僕以外にもいれば使ってあげてください(?)

コンテナイメージ

さてここまでwhitelist.jsonGitHubとプルリクでやっている話をしましたが,たぶんみなさんが気になるところがあるとすればdocker-composeでどんなイメージを使っているかでしょう. もちろんこれも自作です.

まあDocker/docker-composeでマイクラマルチサーバやるなら普通有名なitzg/docker-minecraft-server使えばいいとは思うんですが,ここまで自作の物体でガチャガチャやっておいてイメージも自作しないわけはありません.

github.com

というわけで作ったのがこちら.papermc-dockerです.

github.com

PaperMCというのはJava版マイクラサーバに大量のパッチを当てまくることでなんかいいかんじにすることで有名なSpigotのforkのPaperというやつのことです.

papermc.io

なんかパフォーマンスがいいらしく,オタクにも人気らしい.ということで使っています.詳しいことは知らない. ちなみにitzg/docker-minecraft-serverにもPaperMCのexampleはあります.マジで要らないね.

github.com

と思ったけど僕の方がイメージサイズが小さいな.じゃあ勝ちということで.

ちなみに,マイクラサーバをコンテナ化するにあたって,SpigotとかPaperMCみたいに公式のJava版サーバにパッチを当てまくる系の奴は注意が必要です. docker build時に元の公式サーバのjarファイルを含めた上でイメージをpublicにしてしまうと再配布になってしまいますからね. しかしPaperMCなら安心.Paperclipというものがあります.

github.com

Paperclipはマインクラフトサーバのランチャーであると同時に,Paperのパッチをバニラのサーバに適用するシステムです. これは普通に起動するだけでマイクラサーバとして使えるのですが, 初回起動時にバニラのサーバのjarファイルをダウンロードしてきて,それにパッチを当てて起動します. 2回目以降の起動時はパッチ適用後のjarファイルを直接呼び出します.

なので,これを使ってpapermc-dockerを作ったというわけです.

papermc-dockerでは,GitHub ActionsでイメージをビルドしてGitHub Container RegistryとDockerHubにイメージをpushしています.

で,このビルドなんですが,Paperは普通にいいかんじにビルドされて各commit毎のビルド済みバイナリが公開されているので,それを取ってきてイメージに埋め込めばいいだけです.

papermc.io

だけなんですが,そんなつまらないことはしておらず,ソースからビルドしています. しかも,masterに追従するようにしています. 毎日自動でmasterのPaperをcloneして,更新があったらupdate/paperブランチに自動でcommitされるようにはなっているので,適当なタイミングでプルリクを作ってマージしています. マージはともかくプルリク作るのは自動化したいですね.

papermc-dockerの自動更新

さて,そんなわけでmc.yohane.suではpapermc-dockerを使っているのですが,papermc-dockerでやっているイメージのビルドなどは元々mc.yohane.suでやっていました. これを分離したのは,単にゴチャッとしていて気持ち悪かったのもありますが,イメージの自動更新をいいかんじに,というかRenovateを使ってやりたかったからです.

Renovateはdependencyの更新をするPull Requestを自動で生やしてくれる奴です.

github.com

そして,Renovateはdocker-composeに対応しているので,docker-compose.yml内で指定されているイメージが更新されたらプルリクを作ってくれます. これをcompose-cdと組み合わせるとCI/CDってやつで優勝できるってワケよ.

papermc-docker分離以前は,

mc.yohane.suでPaperのcommitを更新→イメージのビルド開始→compose-cdgit pull・再起動→イメージのビルド終了→compose-cddocker-compose pull・再起動

となっていたのが,

papermc-dockerupdate/paperをマージ→mainでのイメージビルド→Renovateがdocker-compose.ymlの更新PRを生成→PRをマージ→compose-cdgit/docker-compoe pull・再起動

というかんじになりました.無意味な再起動が減ってうれしいですね.

ちなみに,mc.yohane.su.compose-cdの中身はこんなかんじです.

REPO="https://github.com/sksat/mc.yohane.su"
UPDATE_REPO_ONLY=true
UPDATE_IMAGE_BY_REPO=true

UPDATE_REPO_ONLYはイメージの更新をスキップしてリポジトリの更新のみをcompose-cdが行うオプションで, UPDATE_IMAGE_BY_REPOはイメージの更新の責任をリポジトリが負うことにするオプションです. これらはつまり,イメージのマニフェストを見に行ってdocker-compose pullすることはしないが, git pull時にdocker-compose pullもする,ということです.

こんなことをやってるので,mc.yohane.suのdocker-compose.ymlではイメージの指定にタグではなくハッシュ値を指定しています.

ちなみに,compose-cdはログをDiscordに流す機能もあるので,こんなかんじの見た目になります.

f:id:sksat:20210826012307p:plain

papermc-dockerもRenovateで自動更新(2021/09/11追記)

実はRenovate先生は独自フォーマットのファイルの更新もできちゃいます.

swfz.hatenablog.com

ということで,papermc-dockerもRenovateで更新できるのでは?ということに気付きました.

まあ元々はこれできるの知らなくて,自分でGitHub Actions組んでやろうとしていたんですけどね. 書くの忘れてたけどupdate/paperブランチなるものはまさにそれで, GitHub Actionsのcronで毎晩update/paperブランチの,envファイル(Paperのcommit hashが入っている)を更新していました. なので定期的にupdate/paperをマージすればよかった,というわけです.

github.com

本当はこういうPull Requestも自動で出したかったんですけど, GitHub Actionsからsecrets.GITHUB_TOKENを使ってプルリクを出してしまうとCIが走ってくれないという罠があったりするんですよね. まあやってなかったのは面倒だったというだけなんですが.

workflowはこんなかんじ. github.com

で,これもRenovateでできた,というわけです.Renovateすげ〜. 実際のrenovate.jsonはこんなかんじになりました.

papermc-docker/renovate.json at bf275c89842a9cb1cf3f26d6cf81c3799bf7a35b · sksat/papermc-docker · GitHub

{
  "extends": [
    "config:base"
  ],
  "regexManagers": [
    {
      "fileMatch": [".env"],
      "matchStrings": ["depName=(?<depName>.*?)?\\s.*?_COMMIT=(?<currentValue>)(?<currentDigest>.*?)\\s"],
      "versioningTemplate": "git",
      "datasourceTemplate": "git-refs"
    }
  ]
}

papermc-dockerはPaperMC/Paperの(めちゃくちゃ更新される)masterブランチに追従しようとしている狂ったイメージなので,datasourceにはgit-refsを使っています. そもそもPaperはタグ打ちもリリースもしてくれないのでこうするしかないんですがね!(公式サイトにcommit毎のビルド済みバイナリあるんだからそれでいいんだよなあ)

で,無事にRenovate先生がプルリクを出してくれるようになりました.やったぜ.

github.com

プラグインの自動更新(2021/09/11追記)

みなさんマイクラサーバ運用でプラグインアップデート自動化してますか?僕はしてる.

Renovateで独自フォーマットのファイルも更新できることが分かりました. あっこれプラグインの更新もできますねえ.できるならやるしかない.

実は元々プラグインってやつの管理どうしたらいいかな〜とは思っていたんですよね. マイクラプラグインってやつはフォーラムにバイナリがポン置きされてるとかいうマジで狂ったWindowsとかいうクソボケOSみたいな文化が蔓延っているらしいんですが, 幸いにも僕が欲しいものはGitHub上で開発されてタグ打ちされてリリースも出されているようなやつだったので,なんとかなりました*2

これはどうやって実装したかというと,特定バージョンのプラグインをダウンロードして配置するシェルスクリプトを書き, これをcompose-cdのカスタムスクリプト機能で呼び出す,という方法です. compose-cdには再起動前ないし後にカスタムスクリプトを実行する機能がある*3ので, このスクリプトを再起動前に実行します.

プラグインのデプロイスクリプトのバージョン指定はこんなかんじ.

mc.yohane.su/deploy-plugin.sh at 43c4f50829a6153ccfbddef1bd9e9a0218f5da04 · sksat/mc.yohane.su · GitHub

PLUGINS=(
  # datasource=github-releases versioning=docker
  "PlayPro/CoreProtect v20.1 CoreProtect"
  # datasource=github-releases
  "DiscordSRV/DiscordSRV v1.24.0 DiscordSRV-Build"
  # datasource=github-releases
  "sladkoff/minecraft-prometheus-exporter v2.4.2 minecraft-prometheus-exporter"
)

あとはrenovate.jsonからこんなかんじで拾って上げれば大丈夫です.

mc.yohane.su/renovate.json at 43c4f50829a6153ccfbddef1bd9e9a0218f5da04 · sksat/mc.yohane.su · GitHub

{
  "extends": [
    "config:base"
  ],
  "regexManagers": [
    {
      "fileMatch": ["deploy-plugin.sh"],
      "matchStrings": [
        "datasource=(?<datasource>.*?)( versioning=(?<versioning>.*?))?\n  \"(?<depName>.*?) (?<currentValue>.*) .*?\"\n"
      ],
      "versioningTemplate": "{{#if versioning}}{{versioning}}{{else}}semver{{/if}}"
    }
  ]
}

というわけで,こんなかんじのプルリクが生えてくれるようになりました.やったね!

github.com

ちなみに,CoreProtectのバージョニングがdockerなのはバージョニングがクソボケだからです. クソボケなのでクソボケな正規表現versioning=regex:~~~みたいに書いたろ,と思ったんですがそれは無理でした.

github.com

無理だったんですが,みなさんだいすきなドッカーイメージってやつも頻繁によくクソボケなバージョニングがされているので, dockerを指定してお茶を濁しています. 問題はなかった.

docs.renovatebot.com

あと,プラグインを色々入れるなら入れた後もちゃんと起動するか確認したいですよね. というわけでCIの出番です.

github.com

まあこれはpapermc-dockerで既にやってたんでそれをパクってきただけですね*4

*1:結局,これはDockerHubがちゃんと認証をやっていたのにghcr.ioの挙動が雑で何も考えずに使えていたのが後から修正されたということっぽかったんですけどね.まあちゃんと両方いけるようになったのでOK.

*2:CoreProtectとかいうやつはかなりちょっとだいぶ微妙なんですが,まあ途中からとはいえGitHubに上がって今回使えたのはいいことではあるので許してあげましょう.

*3:これはセキュリティ的にどうなんだという気持ちがややあり,あんまりautomergeする気になれなかったりする.

*4:master追従なんてしてたら平気で起動しなくなることがあるので

REALFORCEを買った

はい.バイト代が入ったのでまた勢いで買った. あとなんか楽天ポイントが8000円分くらいあったので*1

sksat.hatenablog.com

前回メカニカルキーボード買ったのが去年3月とかなんで,1年強ぐらいでの乗り換えになりましたね.まあいいか,

静電容量無接点方式のキーボードにはずっと興味があったんですよねえ. それこそメカニカルキーボード買う前から.めちゃくちゃHHKBやらREALFORCEの方向見ながら「いや高いしな...」となってじゃあ1万以下ぐらいのメカニカルキーボードで...となってアレを買ったような気がする. と思ったら記事の最後でめちゃくちゃ未練滲み出てますね.

そんなこんななので,今のがダメだ!と思って乗り換えたというわけではなく,勢いで前から欲しかったものを買ったというだけ.

最近誕生日でオタクからトラックボールマウスを貰ったというのもあり,この機会に手の負担軽減キャンペーンやっちゃうか!みたいな気持ちもあった.まあ勢いだな.

静電容量無接点方式

前回と大きく違うのはここ.端的に言うと高いけどすごいやつ.なんの説明にもなってねえ. まあREALFORCEなりHHKBなりのサイト見た方が早いけど,マジで名前の通りで静電容量でやってるんで接点が必要ないので耐久性がよかったりする.なるほどよさそうじゃねーの.

www.realforce.co.jp

あと,なぜか知らんけどセブン銀行ATMのテンキーがこの方式なんですよね.たしかにあれはよくできてるし打鍵感もいい.

で,問題は何を買うか.まあ何をといってもHHKBかREALFORCEかなんですが. ただ,HHKBは思想は分かるんだけどちょっと僕には合わないなあと思ったので最初から候補には無かったですね. 前にオタクの家に行った時に触らせて貰ったけどやっぱりちょっと無理だった.慣れればいけるかもしれないですけどね. 少し前にTwitterで流れてきたHHKB誕生秘話みたいなやつで最初から小さくて持ち運びやすいことが割と主眼に置かれてたのはなるほどなあと思ったし,実際持ち運びたいのはすごいわかる. でも僕はちゃんとデカいキーボードじゃないとやっていけないかな...テンキーは要らないけど.

というわけでREALFORCEにするのは確定.じゃあどれにするか. REALFORCEのサイトに条件絞るボタンが付いてるので,ポチポチする.

www.realforce.co.jp

まずオタクは黒が好きなのでブラック. APCはよくわからんがあるに越したことはないだろう.保留. レイアウトはもうUSじゃないとちょっと嫌だなという体になってしまったのでUS. 今のキーボードはちょっとうるさいなと思っているので,せっかく買うなら静音がいい.

ということで残ったのがこれ. f:id:sksat:20210726141019p:plain

実は先週ぐらいにこのPFU limited editionとかいうのがセールでちょっと安くなってたんですよね. なんの割引もなくキーボードにドンと3万は出せないし... なので正直欲しかったんですが,その時はマジの無一文でどう足掻いても買えませんでした.オイ.

ということで,(セール直後に買うのは悔しいし)30gか55gか変荷重か.それなら変荷重にしてみるかなあ, となり今回はR2TLS-USV-BKを買うことにしたのでした.

で,どうなの

打鍵感はこの記事書いててもかなりいいです. とはいえ,前回がマジでゴミみたいなキーボードから比較的まともなメカニカルキーボード,という大きな変化だったので,それに比べると驚きは少ないかな,というかんじ. もちろん感覚はかなり違うのだけど,流石に新天地が開けてやべえ,とはならない.第一印象あっセブン銀行ATM,だし. あーでもこう気楽に文字書いてるとちょっとなるほどなあという気持ちにはなりますかね.

少し思ったのは,変荷重にしてはみたけれど実際外側の方のキー叩く時にちょっと強く叩きすぎてるかな,みたいな認識があるので,もしかしたら等荷重の方が合っていたのかもしれない. 感覚がかなり違うというのはあるので,慣れの問題かもしれませんが.

じゃあ2万出したけどそんなに感動しませんでした,ということかというとそういうわけでもない. 静音性は本当にすごい.そりゃあわざわざ静音モデル選んで買ってるんだから静かじゃないと困るんですが,これは本当にすごい. 「え,でもWH-1000XM3つけてノイキャンするんだから別に変わんなくね?」そうかもしれん. でもこれはいいですよ.あとキーボードの近くにマイクあるからボイスチャットの向う側の人もうれしいでしょたぶん(マイクをキーボードの近くに置くな)(いやでもどうせバカがきて高速ミュートするし)(じゃあいいか)

余談

全然キーボード関係ない話なんですが,実は数か月前に静的ブログシステムもどき,というか正確にはMarkdownもどきのパーサと,それを使った雑な静的ブログシステムもどきコマンドとOGP画像生成をRust+wasm+Cloudflare Workersでやる太郎を書いたりしたんですよね. なので実はずっとブログをそっちに移行したいな,次のブログ投稿はその移行記事にしよう,と思っていたんですが全然進めてなかったりする. https://blog.sksat.net/にデプロイされてはいるんですけどね.見て分かる通り無があります. 実はHTMLになった記事が存在しているので,URLをエスパーすれば記事が読める.記事リンク一覧くらい作れよ.

blog.sksat.net

ちょっと気合入れたら最低限ブログの形をするところまではすぐ行くと思うので,やるだけですね.やらんかい.

とはいえもう夏休みなんで(まあ今年はちょっとやることが色々あるのだけど),やるだろ. やったら移行するかはちょっと分からないですけどね.同時に投稿してもなんだかなというかんじだし. Markdownもどきの仕様決めとパーサ書くのがやりたかっただけで,実はブログを作りたかったわけではないというのはかなりある気がする. あとOGP生成太郎.こっちはもしかしてできるのか?と思ってやったらPoCができてしまったので飽きた. さっきembedで置いたリンクのところに"お〜じ〜ぴ〜"とかいうクソやる気ない文字列が出てたらそれです. こっちもやるだけではあるのだけど,結局文字描画なんで真面目にやるとクソダルいはず.ダルいなあ.

そんなこんなで,この記事はTwiterでキーボードに言及してそういや去年は書いたなと思って書いた体をした,課題やるのが微妙にダルいし眠いので逃避して書いてるやつでした,というオチで締めたいと思います.締まってないな.あと普通にスルスル文字打てて気持ちよかったです.よし締まった.

*1:たぶんE495のポイントが紆余曲折の末結局ちゃんと入ってたのを放置してたっぽい

ラズパイで Kubernetesを 立ててみる(575)

はい.

Kubernetes,去年ぐらいから名前は聞いたことあったんですよね.なんなのかはまったく知らなかったけど. たまにTLに出てくるやつ.あとオタクがプロフィールにk8sとか書いてたりする. まあk8s=Kubernetesだということを知ったのもだいぶ最近なので,完全に謎の文字列として見ていましたが*1

じゃあなんで急に手を出したのかというと,KOBA789とかいうオタクが自宅サーバで使っていて,Kubernetes The Hard WayしているところやArgoCDからポチポチやってpodがポコポコ生えたりする様子を見せてもらったりしたんですよね. しかもこれがクラスタ上で動いているらしい.高校生の時にノートPC3,4台並べてMPIで並列計算や!とかやっていた程度には計算機クラスタという概念に対する憧れみたいなものもあるので,これはやるしかねえなと思ったのでした.

一応簡単にKubernetesがどんなものか書いておくと,コンテナに固めたアプリケーションをクラスタに対してガンガンデプロイしていくための物体です. あらゆるリソースをYAMLで記述し(マニフェスト),それをKubernetesに対して適用する形でデプロイとか設定とかをやっていきます. そんんでもってクラスタ上で動いているのでもちろんコンテナをスケールアウトさせることとかもできる,みたいなところですかね.

そんなかんじのものなので,クソデカクラウドサービスの裏側とかで結構使われているらしいです. まあそんなものを自宅で飼う必要性は皆無なわけですが,実は大学に入ってから計算機が増えたこともあって,自室内にちょこちょこサーバを立てて使ってるんですよね*2. 去年はそれらをほぼすべてdocker-composeに移行したりしてました.こいつらは既にコンテナになっている. なので今年はこいつらをKubernetesに移行してみたいという野望があったりします.楽しそうなので. 今回はその前に色々な概念を理解するためにラズパイで雑にKubernetesクラスタを作ってみます. 前置き終わり,

ではやっていきましょう.

ラズパイのセットアップ

オタクの皆さんの散らかった部屋にはラズパイが山のように転がっていると思うんですが,僕は無いんですよね. なので自室ネットワークのクソデカSPoF太郎になっているラズパイとなんか前にラズパイ欲しいってツイートしたら大学教員から高速発射されてきたラズパイ(何?)を使うことにしました.

したんですが,なんか机の上の紙束の下に埋もれてたラズパイがあったのでこれと飛んできたラズパイを使うことにしました. クソデカSPoF太郎はマジでクソデカSPoF太郎なので,こいつが死ぬとインターネットってやつから切り離されちゃうんですよね.

まあ別に実用するわけではないですし,専用で使えるノードが2個(control plane, worker)あればええねん. そもそもこれ全部3B+とかなので実用はスペック的にもやや無理がある.

送られてきたラズパイにはGUI付きのRaspbian,なんか出てきたラズパイにはRaspbianが入っていたので,とりあえずこれらは吹き飛ばしてなんか別のものを入れます. なんか出てきたラズパイは高校生の時に使っていたやつだったらしく,受験期に限界になって部屋の電灯のAPIをインターネットに公開してツイキャスで配信とかしてたやつ*3スクリプトとかが出てきて懐かしい気持ちになるなどしました.

で何を入れるかは色々調べてHypriotとかと迷ったんですが,そういや僕の部屋で動いているディストリはおそらく全てArch Linuxだったな,と思い直して(?),Arch Linux ARMを入れることにしました. SPoF太郎もそうだし.ただしせっかくなのでAArch64版を入れることにしました.といってもtar.gzをAArch64版にするだけ.

archlinuxarm.org

インストールできたらホスト名を決めます.例によってここが一番時間かかった気すらする.

https://imgs.xkcd.com/comics/permanence.png

xkcd: Permanence

結局あまり考えずに(は?),クラスタ→星団ということで順番にプレイアデス7姉妹の名前を付けていくことにしました.これが7台になることは無いと思うけど. なんでプレアデス星団かって?だって散開星団は若くて寿命が短い星が多いから...

やる

ようやく肝心のKubernetesのインストールです.といっても最近は超簡単にクラスタをセットアップできるツールが色々あるらしいです.やったね.

ということでk0s - Zero Friction Kubernetesを使ってセットアップしようとしたんですが,めちゃくちゃFrictionしまくったので公式ツールのkubeadmを自分でチマチマ叩くことにしました. そもそもわざわざ実際にクラスタ組んでるのがminikubeがうまく動かなかったからだったりもする(なんでだよ).まあたぶん僕の環境が悪い.

ここらへんを見てやっていきます.まずはコンテナランタイムから.

kubernetes.io

コンテナランタイムはcontainerdを使うことにしました.Docker非推奨になったらしいし,どうせDockerはcontainerd使ってるし. 次やるときはcri-oにしてみますかね.コンテナランタイムがCRI*4に準拠しているやつなら自由に選べるというのはおもしろいですね.

$ cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

$ sudo modprobe overlay
$ sudo modprobe br_netfilter
$ cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
$ sudo sysctl --system
$ yay -S containerd
$ sudo systemctl enable --now containerd
$ sudo mkdir /etc/containerd

これの後に/etc/containerd/config.tomlを作ってゴチャゴチャ弄ってオンオンkubeletが動かん,とか言ってたんですがそもそもこのファイルを消したら動いた回などがありました.

github.com

次にkubeadmを入れます.

kubernetes.io

$ cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
$ sudo reboot
$ lsmod | grep br_netfilter
br_netfilter           28672  0
bridge                245760  1 br_netfilter
$ cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
$ sudo sysctl --system
$ yay -S kubeadm-bin kubelet-bin kubectl-bin
$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.2", GitCommit:"faecb196815e248d3ecfb03c680a4507229c2a56", GitTreeState:"clean", BuildDate:"2021-01-13T13:25:59Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/arm64"}
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now kubelet

Kubernetes本体は迂闊にバージョン上げると死ぬらしいのでIgnorePkgに追加しておきます.

これで純美ができたのでControl Plane(master node)を建立します.

$ yay -S crictl ebtables ethtool socat conntrack-tools
$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=Mem --cri-socket unix:///run/containerd/containerd.sock

事前に--dry-runしてからやった方がいいです.失敗したらkubeadm reset

成功したら$HOME/.kubeを作れとか言われるのでその通りにする.あとちゃんと/etc/hostsは書いておいた方がいい.

あとはWorker Nodeをセットアップする.

# pacman-key --init
# pacman-key --populate archlinuxarm
# pacman -Syu
# pacman -S vim sudo git
# pacman -S --needed git base-devel
# EDITOR=vim visudo
# useradd -m -G wheel -s /bin/bash sksat
# passwd sksat
$ mkdir build
$ cd build
$ git clone https://aur.archlinux.org/yay.git
$ cd yay
$ makepkg -si
$ sudo vim /etc/fstab
$ sudo vim /etc/hostname
$ cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
$ cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
$ cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
$ sudo sysctl --system
$ sudo reboot
$ yay -S containerd kubeadm-bin kubelet-bin kubectl-bin cni-plugins
$ sudo systemctl enable --now containerd
$ yay -S crictl ebtables ethtool socat conntrack-tools
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now kubelet
$ kubeadm join electra:6443 --token <TOKEN> --discovery-token-ca-cert-hash sha256:<HASH>

ちゃんとjoinできてたらkubectl get nodesを叩くとちゃんとノードが生えていてうれしい. ただしstatusがNotReadyとか書いてあるので,これをReadyにする必要がある. ここで必要なのがオーバーレイネットワークというやつ.これも色々実装があっておもしろい.今回はラズパイなのでシュッと動いてくれそうなflannelを使うことにした(なので--pod-network-cidrを10.244.0.0/16にした).

coreos.com

あとflannel回りでコケている時はkubeadm resetする前にこれもやる.

# ip link delete cni0
# ip link delete flannel.1

ちゃんと動くとノードがReadyになってうれしい.よかったね.

使う

後はwatch kubectl get pods --all-namespacesでも見ながらpodをポコポコ生やしたり潰したりして遊びます.たのしい.

これで終わってもいいんですが,正直kubectlを叩くのはダルい.あとYAMLを手元でゴチャゴチャ弄ってapplyするのはダルい.どうにかならんのか.ということでどうにかする.

どうにかするのがGitOpsとかいうやつ.これもオタクがツイートしているのは見たことある文字列だな. まあマニフェストファイルとかをGitで管理して運用をGitリポジトリの管理にすり替えちゃえばいいじゃん,みたいなかんじなんですかね. サーバにsshしてコマンド叩いて,みたいな作業を消せてうれしいしrevertとかもできる.

そんんでもってこのGitOpsをKubernetesでいいかんじにやるためのやつがArgoCDというわけです. 最初にオタクに見せてもらってオオ〜となったやつ.まあ名前忘れてたんで「アレdashboardの実装の一つなのか...?」とか思って探したりしたんですが(その後このYAML共はどう管理したらええねんとなって普通にGitOpsの文脈から再発見した).

argoproj.github.io

というわけでArgoCDでポチポチしたらGitリポジトリと繋がってポンポンpodが生やせるしいいかんじに可視化されてうれしい,となればよかったんですがうまくいきませんでした.かなしい. というか色々確かめてみた結果(ログと実態がだいぶ違ったりして厳しかった),pod内部からの名前解決が異様に遅い上にできたりできなかったりしているっぽいことが分かりました.そもそもセットアップ微妙に失敗している可能性がある.かなしい.でもCoreDNSのpod生きてるしなあ.なぜ〜〜〜

ということで煮えきらないかんじですが今回はここで終了です.どうにかなったら追記します.

*1:微妙に界隈が違う人が多めだったりして特に調べようとも思わなかったんだと思う.たぶんはいはいWebのなんかね,ぐらいの認識

*2:よく使っているのはCoreDNS,Nextcloud,Jellyfinあたり

*3:https://twitcasting.tv/sksat_tty/movie/516218129

*4:Container Runtime Interface

RustでUEFIアプリケーションを書く 2020 Edition

RustでUEFIアプリケーションを書く 2020 Edition

みなさんこんにちは.sksatです. 最近はVRで生活したり,オタクで を取ってゲラゲラしたりしています.

ちなみに映画化しました*1.よろしくお願いします. youtu.be

さて,これは自作OS Advent Calendar 2020の21日目の記事なわけですが, Advent Calendarに登録していたことを完全に忘れていて,Twitterで教えてもらいました.オイオイ. 今日中に公開したら許してほしい*2.今は13:50(JST)です.

adventar.org

ということでなんも準備してないわけですが(は?), 実は今年のセキュリティ・キャンプ全国大会のYトラック自作OSゼミでチューターをやったりしていました. まあ今回はオンライン開催だったということもあり,受講生の人と一緒にワイワイデバッグしながらガッと開発,みたいなことはできなかったんですが*3,チューターをやっている間に(ようやく重い腰を上げて)Rustに入門したり,RustでUEFIアプリケーションを書いたりしていたのです.なのでこの話をします.

Rust

言わずと知れた最近ブイブイ言わせている*4プログラミング言語です. なんか最も愛されていたりするらしい.ℒ𝒪𝒱ℰ...

簡単に紹介しておくと,コンパイラに天才を投入し書き手に制約を課しコンパイル時間を天に捧げる*5ことで, 最高の開発体験と高速に動作するバイナリを得ることができるプログラミング言語です.

Rust,ずっと気になってはいたんですよね. どれくらい気になっていたかというとRustはいいぞというツイートを見て「ホォ〜ン良さそうじゃん.僕はC++17書くけど...」とか言ったり, AmazonのwishlistにRustの本入れたり, wishlistに入れてたRustの本がRust好きなフォロワーに買われて届いたけど積んだり, 積んだRustの本をチラチラ見て「いいじゃ〜んそういうのだよそういうの」とか呟いたり, Rustで書かれた組み込みOSを眺めてみたりThe Rust Programing Language 日本語版をチラチラ見たり, プログラミング言語の入門にはLISP書いてみるといいですよとTwitterで言われて一理あるなと思って所有権とかなんもわからんままLISPインタプリタ実装しかけてAST作ったところで詰んだりしていました.

そんなこんなでRustやるんだかやらないんだか微妙なところで踏みとどまっていたんですが,まあ例によってVRChatのオタクに布教されたので教えてもらいながら始めました. VRChatは最高.

ここまででVRChatとRustが最高なことしか情報がないですね.そういうこともある.

自作OS的に分かりやすいRust最高ポイントはpanicをちゃんと実装してあげれば突然の死の時にもある程度情報が得られるところとか,ターゲットアーキテクチャバチバチ切り替えられるところとか,ユニットテストフレームワークが言語標準で付いてるところとか,OS(std)に依存しないライブラリ(crate)がたくさんある上にそれらを標準のビルドツール(cargo)で引っ張ってくることができるところとかですかね.

UEFIアプリケーションを書きたい

というわけでRustってやつでUEFIアプリケーションを書いてみましょう. LLVMだしclang+lldの時みたいにやればできるでしょ.

Rust UEFI [検索]

\ババーン/ github.com

なんとライブラリがあります.UEFIアプリケーションを書くための.何?(こういうところもRust最高ポイントですね)

これを使ってHello World!する話は例によってオタクが書いてますね. neriring.hatenablog.jp

しかしせっかくなら全部自分で書いてみたいです.車輪の再発明も車輪をバラすのも大好きなので. セキュリティ・キャンプでも受講生の一人が最初uefi.hをUEFI Specificationを見ながら手打ちしていて,「わかる〜」となりました*6

んでもってそういう記事も既にあるわけです.やった〜 garasubo.github.io

でもこれは今は動かなくなっています.まあcargo-xbuildのバージョンをこの当時のものにすれば大丈夫な気はしますが.

とはいえRustは進化の速い言語です.最新のRustでもuefi-rsを使わずにUEFIアプリケーションを書きたい.僕は書きたかったです. ということで書きました.

github.com

apt update && apt install -y curl git gcc
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env
git clone https://github.com/sk2sat/uefi-hello-rs
cd uefi-hello-rs
rustup component add rust-src
cargo build --release

こんなかんじでビルドできるはずです.Dockerでもいける.

rustupはRustツールチェーンのバージョンやらターゲットやらをいいかんじに管理できるやつです. Rustはディストリのパッケージマネージャから入れるよりも https://rustup.rsに書いてあるワンライナーで入れた方がいいまである. 実際これで一回詰まった((実はrustupでRustを入れると使えるrustcとかcargoとかはそれそのものではなくてrustupのシンボリックリンクになってるんですよね. ls -l which cargoとかしてみると分かる.Buildrootかな?まあなるほど感はあるけど微妙に挙動が違って非常に時間を溶かしたので,なにも考えずにpacman -S rustとかやらない方がいいです.communityにrustupあるから使おうね.)). 実態は$HOME/.rustupとかにいるので環境をブチ壊さなくて安心.エコってやつです.

cargoはビルドシステム+パッケージマネージャみたいなやつです.これの存在もRust最高ポイントの一つですね. なんとライブラリを追加するのはCargo.tomlのdependenciesでcrate名とバージョンを指定するだけ*7. ほとんどのcrateはhttps://crates.io に登録されているのでこれだけで大丈夫な上,gitで取ってくるとかもできます. あとはcargo buildとか叩くとガーッと依存物がダウンロードされビルドが走ります.

cargo buildで自作OSをビルドしたい

Rustで開発する時はほぼcargoしか叩かない(rustcを直接呼んだりmakeを使ったりしない)んですが, 諸事情により自作OSではcargoではなくxargoやそのforkのcargo-xbuildが使われていました. xargomakeで呼んでるやつとかも見ますね.

でも,せっかくRustを使っているわけですし,cargo buildでおもむろに自作OSがビルドできるようになってほしいですよね. 僕はなってほしいです. そこで,今cargo-xbuildのリポジトリを見にいくと,

github.com

Cargo now has its own feature for cross compiling the sysroot: build-std. You can use it by passing -Z build-std=core,alloc to cargo build. Alternatively, you can specify the following in a .cargo/config.toml file:

[unstable]
build-std = ["core", "compiler_builtins", "alloc"]

The above requires at least Rust nightly 2020–07–15. With the above config in place, the normal cargo build command will now automatically cross-compile the specified sysroot crates.

とあります.おや?なんか最近のやつならいけそうじゃあないですか.これはやるしかない.

ということでなんとcargoだけでビルドできるようになりました.やった〜.

まずはなにもしないやつ

cargo buildでビルドできるようになったところでHello, Worldやっていきましょう.まずはなにもしないものを作ります.

#![no_std]
#![no_main]

use core::panic::PanicInfo;

#[no_mangle]
pub extern "C" fn efi_main() {
    loop {}
}

#[panic_handler]
fn panic(_panic: &PanicInfo<'_>) -> ! {
    loop {}
}

最初の#![~~~]はcrate-level attributeというもので,ソースコード中で色々な指定ができます. ここではno_stdno_mainですね. no_std-nostdlibみたいなやつで, no_mainmainなんていう関数は無いけど怒らないでねってやつです. いつものやつですね.

次のusePanicInfoという型を後で使うのでそれを引っ張ってきています. C++usingみたいなやつですね. ここで急に出てきたcoreは何かというと,なんと標準ライブラリみたいなやつです. 普段なら自作OSで標準ライブラリが使えるわけないだろ!下がってろ!となるところですが, なんとcoreはOSの機能に依存しておらず自作OSでも使えるのです.やった〜((coreがOSの機能に依存していない,というよりは標準ライブラリを作るにあたってOSの機能に依存しないが必要なものをcoreとして明確に切り分けて実装した,というのが適切なんじゃないかなと思います.たぶん.))

次はefi_main関数ですね.エントリポイントです.この関数にはno_mangleというattributeが付いているのでマングリングが行われません.お手軽ですね.

最後はpanic handlerです. panicした時にダイイングメッセージを書く奴ですね. no_std環境では標準出力なんてものがあるわけがないので自分で実装する必要があります. この引数にさっきのPanicInfoが来るわけですね.

Hello, World!

さてHello, World!していきましょう. UEFIアプリケーションなので,とりあえず必要な分だけシステムテーブルの構造体を作ってSimpleTextOutputProtocolを取ってきてOutputString関数を叩くだけです. かんたんですね(そうかな?)

ということでsrc/uefi.rsがこんなかんじになりました.

use core::ffi::c_void;

#[derive(Clone, Copy)]
#[repr(C)]
pub struct Handle(*mut c_void);

#[repr(usize)]
pub enum Status {
    Success = 0,
}

#[repr(C)]
pub struct TableHeader {
    signature: u64,
    revision: u32,
    header_size: u32,
    crc32: u32,
    _reserved: u32,
}

#[repr(C)]
//#[repr(packed)] // packedを付けると32bit縮められて死ぬ
pub struct SystemTable {
    pub hdr: TableHeader,
    pub firmware_vendor: *const u16,
    pub firmware_revision: u32,
    pub console_handle: Handle,
    pub _con_in: usize,
    pub console_out_handle: Handle,
    pub con_out: *mut SimpleTextOutputProtocol,
}

#[repr(C)]
pub struct SimpleTextOutputProtocol {
    reset: unsafe extern "efiapi" fn(this: &SimpleTextOutputProtocol, extended: bool) -> Status,
    output_string:
        unsafe extern "efiapi" fn(this: &SimpleTextOutputProtocol, string: *const u16) -> Status,
    _resb2: u128,
}

impl SystemTable {
    pub fn stdout(&self) -> &mut SimpleTextOutputProtocol {
        unsafe { &mut *self.con_out }
    }
}

impl SimpleTextOutputProtocol {
    pub fn reset(&self, extended: bool) -> Status {
        unsafe { (self.reset)(self, extended) }
    }

    pub fn output_string(&self, string: *const u16) -> Status {
        unsafe { (self.output_string)(self, string) }
    }
}

最初は自分でゴチャゴチャやってたんですけど結局uefi-rsを参考にしました.uefi-rs使った方がいいです. あと,C/C++のノリで「あ〜こういうのはpacked付けとけばいいでしょ」と思って付けまくってたら動きませんでしたね. なんかメンバのアドレスが32bitズレてたりしてました. ちゃんと挙動を調べたかったのでメンバのオフセットが合ってるかみたいなユニットテストを書きたかったんですが,これもイマイチやり方がわからず時間を溶かしました. ウーム.今度ちゃんと調べます(ホンマか?)

あともちろん,いきなり構造体のメンバのアドレスを関数だと思って呼ぶなどというCでは一般的な野蛮な活動はRustでは許されないので,unsafeを付けています.

UTF-16

これでHello, World!する準備が整ったので,あとはefi_main関数でoutput_string()とかを呼んであげればいいわけですが, ここで一つ問題があります. それは文字列です.

Rustでは文字列はUTF-8です. これもRust最高ポイントですね.

どこぞのC++とかいうプログラミング言語は最近ようやく文字とは何かを理解したわけですが...(なお...) qiita.com

さてここでUEFI Specificationを見てみましょう

\ババーン/

FI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString()

_人人人人人_
> CHAR16 <
 ̄Y^Y^Y^Y^Y^ ̄

┏-┷-┓
┃ U ┃
┃ n ┃
┃ i ┃
┃ c ┃
┃ o ┃
┃ d ┃
┃ e ┃
┗━━┛

はい.まあUEFIMicrosoftが策定にガッチリ絡んでますからね. MicrosoftUnicodeと言ったらUTF-16ですし,型はCHARとかWCHARですよ.まあCHAR16なだけだいぶマシですかね. UEFIは滲み出るwindows.h感でとても懐かしい気持ちになる物体としておすすめです.

こういうこと言うとWindows 10のMay 2019 Updateでnotepad.exeのデフォルトがUTF-8になったじゃないかとか, WSLは最高の開発体験だとか言われることがありそうな気がしますが, そういう人はWin10のシステムロケールUTF-8にしてみるといいんじゃないでしょうか.あまりに色んなものがブチ壊れて楽しいですよ.

まあ僕も最近VR関連の諸々のためにWin10使うことがだいぶ増えてはきましたけどね*8. それでもArch Linux使う時間の方がずっと長いですが.

話が逸れました.さてUTF-16です. まあUEFIアプリケーションのサンプルでたまにありがちな,文字列を一旦バッファに入れてunsigned 16bitの型の配列の下位8bitに雑に詰めるやつをやってもいいんですが, あれはなにかに敗北した気持ちになるのでやりたくないです.まあどうせ表示するのはASCIIのHello, World!なんですけど.

なのでUTF-16な文字列リテラルとかがあるとうれしいんですが,Rustにはそういうのは無いらし...おや?

github.com

こんなcrateがありました.求めていたものっぽい.

これはRustのマクロを使ってUTF-16な文字列リテラルの真似事をするというものです. 具体的にはutf16_literal::u16というマクロに普通に文字列を突っ込むとu16の配列になって出てくるようになっています. UTF-8の文字列をUTF-16の文字列に変えるなんて処理は動的メモリ確保が無い状態だとちょっとつらいですし, なにより今回は表示するものが決まっているので,UEFIアプリケーション上で処理する必要すらないわけです.

ということでこんなかんじになりました.やったぜ.

extern crate utf16_literal;
use utf16_literal::utf16;

mod uefi;
use uefi::Status;

#[no_mangle]
pub extern "efiapi" fn efi_main(_image: uefi::Handle, stable: uefi::SystemTable) -> Status {
    let stdout = stable.stdout();
    stdout.reset(false);
    stdout.output_string(utf16!("Hello, World!").as_ptr());

    loop {}
}

cargo runでQEMUが起動してほしい...起動してほしくない?

Rustで普通のHello, World!したことある人なら分かると思うんですが(分からない場合はcargo new hoge && cd hoge && cargo run), cargo runってやると書いたアプリケーションが起動するじゃないですか. あれが最高なので,というか普段Makefile書いてmake runしてる人間なのでcargo runしたらQEMUなりBochsなりが起動してほしい.起動してほしいです.頼む.

で,まさにそういうことができるものがあります.custom runnerってやつですね.

これは.cargo/configにこんなかんじに追記してやればいいです.

[target.x86_64-unknown-uefi]
runner = "qemu-system-x86_64"

これで行けるならいいんですけどね.残念ながらUEFIアプリケーションなのでmnt/EFI/BOOT/BOOTx64.EFIとかにバイナリを置いてマウントする必要があります((でも,カーネルだけならqemu-system-x86_64 -kernelで行けるし,なにかトチ狂ってLinuxでWin32AP直叩きアプリケーションを書くとき(たまにある)にwineを指定できたり,夢が広がりますね(?).)). なので最初はじゃあディレクトリ切ってコピーするワンライナーを前に押し込んでやればいいなとか思ったんですが, これはsystem()が呼ばれるとかではない(シェルが呼ばれるわけではない)のでそういうことはできませんでした.

あと,cargo runMakefileでよくあるようにcargo build->cargo runと実行されるわけではなく, なにかそれで時間をめちゃくちゃ溶かした気がするのですが覚えてないです. 完全に先入観のせいなんですが「え?これどうなってるんだ」とcargoのソースコードを読みに行ったのはよかったような気がします.

結局これは以下のようなrun-qemuというシェルスクリプトを作ってgot kotonakiしました.

#!/bin/sh
echo $1
mkdir -p mnt/EFI/BOOT
cp $1 mnt/EFI/BOOT/BOOTx64.EFI
qemu-system-x86_64 --bios bios/RELEASEX64_OVMF.fd -drive format=raw,file=fat:rw:mnt

これでcargo runすると... f:id:sksat:20201221203836p:plain

やった〜

cargo runQEMUが起動するようになって満足し,その後進捗がありませんでした. いかがでしたか?

*1:Q. これはなに A. クソドメイン部 Q. クソドメイン部ってなんですか A. 僕も知りたい

*2:履修も受講も課題提出も全部失敗してるオタクがアドベントカレンダー書けるわけないじゃん.じゃあ登録するな.https://soude.su

*3:footnoteなのであんまり関係ない話していいですか?いいよあり. 今日もCOVID☆19さんが全世界で猛威をふるっていらっしゃるわけですが,なんというかこの伝染病は良くも悪くもFateシリーズの聖杯ってかんじですよね. 伝染病が大流行しているような事態はこれっぽちもよくはないわけですが, 色々なところで言われているように(要出典),これには巨大なデメリットと同時にメリットも振り撒いていますよね. 未だかつてこんなにも世界中の「IT化」が進んだ瞬間があったでしょうか.まあパワーのある政治をやっている国ならあったかもしれませんが. そんなメリットの一つが外に出なくてい(ry,じゃなかった,今回のセキュリティキャンプだったり大学の講義だったりのオンライン化だと個人的には思っています. もちろんこれちゃんとやるのは非常に難しいんですけどね. まあ難しいだろうなと思って大学の講義を見ていたわけですが,セキュキャンで実際やる側に少し回ってみてやはりこれは大変だなと思いましたね. メリットの話をしましょうか.まあ大きいのは参加のハードルの低下,録画の公開(の一般化)ですかね. でもこれデメリットも同じくらいあるんですよね(オイ).通話に参加すること事態のハードルは低くても, (見ず知らずの人間と)ミュート解除して話すコストはめちゃくちゃ高いし.とくにGoogle MeetなりZoomなりだと初期設定の虚無アイコンがババーンと表示されてるだけですしね. これはかなり前からだいぶ気にしていて,5月くらいからFaceRigを試したりしていました.実はVRにどっぷりハマったのもそういう経緯があったり無かったりする(どうかな). 研究室でも最初に美少女になったのは僕でしたね.その後数人が3teneとかでやってましたね. まあここ最近精神と生活リズムが完全にブチ壊れていてろくにミーティング出られてないんですけど.すみません. 僕は最近はVRChatでストリームカメラ or VRM化したアバターをVMagicMirrorに突っ込んだものOBSでキャプチャしてやっています. 毎回Index被るのはさすがに面倒だったり不都合があったりするのでVMagicMirrorは重宝してますね. 普通に便利だしあそこらへんのツールで唯一(?)wineでまともに動くし.Linuxデスクトップ太郎としてはな. 仮想カメラで美少女が喋ってると個人的にはだいぶ話すハードル下がると思うんですよね.他の人がどうかはよく分からないけれど. 今年のセキュキャンはせっかくオンライン開催だったのでほぼ全編美少女で参加しました. 受講生の人の心理的なハードルを少しでも下げられていたらよかったなと思います. あとLTでVRへの勧誘したり時間外にVRChatへの勧誘したり元々VRChatにいた参加者・チューター・講師とワチャワチャしたりしました(あれ?) 話を戻しますか.まあこれ全部脱線だけど. あー録画の話ですね.これは非常にありがたいとともに個人的な恨みつらみがたくさんあります. 講義が録画されるようになることとそれが受講者に対して公開されるムーブ自体は最高なんですが,問題はその共有方法です. まあ権利的に難しかったりするわけで同情できないわけではないんですが,あの不自由まみれの状態は一体なんなんですかね. 他の大学だとだいぶマシだったりするみたいですが,クソみたいなDRMのかかったクソみたいに使いにくい動画ビューアに始まり, それをWindowsでしか動かないカスゴミアプリケーション上でのみ再生できるようにするだのリクエストがあった時のみ公開するだの1週間経ったら公開を停止するだの. まあこんなことに一丁前にキレてたら色んなものが破滅したんですけど. 最後のやつは毎週ちゃんと見ろよと言われたらまあそうですねとなるし. それにしたってこういう状況なんだからせっかくのメリットを生かしてほしい気持ちが非常に強いですけどね. 毎週講義準備するのが恐ろしく大変だということは少しは分かるつもりではいるので,そんなに強いこと言う気にはならないんですが. さてこの欄は本編書くのに飽きたら書いてたんですが本編書き終わったので終了です.ひでえfootnoteだ.

*4:V言語でゎなぃ

*5:これはリンク以外はCPUが十分強ければまあまあ速くなります.僕の(ろくに活用されていなかった)Ryzen 3700Xがフル活用されて最高.とはいえ自作OSならクソデカライブラリ使わないのでリリースビルドでもだいぶ速く済みますけどね.

*6:Q. 別に仕様書見てるならただやるだけのものを手打ちする必要は無いのでは? A. ち,ちがうんですよ!ぜんぶじぶんでかいてみたいじゃん!

*7:ライブラリの追加もcargo-editを入れておくとcargo addだけでできて最高です.

*8:でもこれProtonが進化してVRChat上で動画が見られるようになったり,xrdesktopとかでいいかんじにXS Overlayが代替できればWin10使う理由かなり減るんですよね.Valve Softwareの異常者がんばってほしい.なんである程度は動いてるのかわかるけど意味分からんけども.あとはWebEx Trainingとかいうカスですかね.まあこっちはVMでいい気もする.そしてそもそも不自由な形式での講義動画の配布をやめればいい話.

Google Summer of Code 2020に採択された

Google Summer of Code 2020(以下GSoC)に出していたProposalが採択されました. やったぜ.

記録と来年以降GSoCに申し込む人のために書いておきます. 僕も先人のブログにめちゃめちゃ助けられましたしね.

GSoCって何

Google Summer of Code. よくGSoCとも呼ばれます.

GSoCは端的に言うと,「学生の人,夏休み暇でしょ?メンターからの指導を受けつつオープンソースプロジェクトにcommitしてみない?ちなみにGoogleから金も貰えるんだが」というかんじのイベント(?)です.

summerofcode.withgoogle.com

Google Summer of Code is a global program focused on bringing more student developers into open source software development. Students work with an open source organization on a 3 month programming project during their break from school.

僕は周囲の参加してるオタクとか,しゅううせんせーのブログとかで存在を知った覚えがあります.

syuu1228.hatenablog.com

夏休みと書きましたが,これはもちろん海の向こう側の話なので我々日本の民が参加する際は注意が必要です. 思いっきり期間中に大学の試験期間がありますからね. その点で言えばCOVID-19で世の中や大学が混乱してる時期にできるのはアドかもしれないなあと思ったり. 1限の試験とかやりながら他のことモリモリやるとか僕には無理です. まあ全部リモートになっても1限は無理なんですけど.

なにやるの

summerofcode.withgoogle.com

じゃあお前はGSoCで何やるねんということなんですが, emboxという組み込みOSをMAiX BiTに移植します.したい.

github.com

emboxは簡単に言うとPOSIXなアプリケーションが動く組み込みOSです. 色々な「それ絶対組み込みで動かんやろ」みたいなやつがなんかシュッと移植されて動いたりする.

なんかQtがSTM32で動いたりするらしいです.マジかよ...

Porting Qt to STM32 / Embox Blog / Sudo Null IT News

で,このemboxなんですが,かなり色々なプラットフォームで動きます. アーキテクチャも色々あるしなんなら普通のx86アプリケーションとしても動いたりする. 比較的最近になってみんな大好きRISC-Vにも対応しました. といってもHiFiveだけだけど.

でもHiFiveって高いじゃないですか.いやまああの値段でRISC-Vなマイコンが買えるならって思うとそんなにってかんじだとは思いますが. とはいえしがない学生からするとマイコンにスッと6000円とか出すのはまあまあ厳しいものがありますよね. まあ今まで積んできた本やらマイコンやらの合計金額確認ゲフンゲフン.

それでもRISC-Vを実機で触ってみたい. どうにかしたいですよね. そして最近はそんな夢を叶えるべく(?), sipeedが超パワーでお財布に優しいRISC-Vマイコンをぽんぽん出してくれているわけです.

その1つが今回のターゲットのMAiX BiTです.

www.switch-science.com

3500円でRISC-V 64bitデュアルコアかつ色々なアクセラレータも載ってるマイコンが買えるのヤバくないですか?ヤバい. やべーっつってアキバのShigezoneで買ってMicroPythonとPlatformIOでちょっと遊んだ後積んでました*1. そして,Proposalどうしようかな〜と悩んでいるときに,ふと「これに移植できたら面白いのでは...?」と思ったので,なんかそんなかんじのProposalを書いて送ってみたら通ったってかんじです.

申し込み

申し込みにあたっては,先人たちのブログ記事がめちゃくちゃ参考になりました.ありがたや.

hakatashi.hatenadiary.com

yamaguchi-1024.hatenablog.com

n-yoshikawa.hatenablog.com

Organizationが発表*2されたら,まずは公式サイトを見て面白そうなプロジェクトを見繕います. Organizationはかなりたくさんあります.

summerofcode.withgoogle.com

LLVMとかNeoVimとか,いつも使ってるビッグネームが並んでいてすごい. その一方で,今まで知らなかった面白OSSもかなりあってこの一覧を見るだけでも面白かったです. 今回僕が応募したemboxもここで始めて知りました.

一応僕が見ていておもしろそ〜と思ったOrganizationのリストを載せておきます. メモはかなり雑なのであんまり気にしないでください.

hackmd.io

プロジェクトを見定めたら,メンター候補の人に連絡を取ってみましょう. たぶんどのプロジェクトでもメールアドレスが書いてあると思います. というかGSoCのページにまずはメールしろ!と書いてあるプロジェクトも多いんじゃないですかね. その後の対応はプロジェクトによってかなり違うんじゃないかなという気がしますが, なんやかんやあった後はちょっとcontributeするかんじになると思います.

emboxの場合は"goot first issue"ラベルの付いたIssueが量産されていたので, 「これやりてえ!」ってコメントしてアサインしてもらってからプルリク送るとええ,ってかんじでした.

github.com

というわけで僕はこんなかんじのプルリクを送って無事マージされました. OSSにプルリクを送ったのは多分これが始めてだと思います. プルリクがマージされるとえらいきもちがええんじゃ.

その後,"Student Application Period"が始まったら登録ができるようになります. そうしたら後は適当なGoogleアカウントを登録して, 自分が学生だということを証明したりProposalをガシガシ書いたりするだけです.

学生の証明は学生証をスキャンしてPDFとかにして送りつけるだけです. ただし,学生証が日本語の場合ダメで〜す!wと言われるので, 後で書いてある内容を英訳したものを送る必要があります.

Proposal

これらの諸々ができたら,あとはProposalを書いて送りつけるだけです.簡単だね!(ぇ)

基本的にはOrganizationのGSoCのページに「idea list」があるので, その中から面白そうなものを選んで,GSoCの期間中にそれをどう実装していくかを書くことになります.

ですが,大体そのidea listの一番下とかに「お前のアイデアを送りつけてもいいぜ!」みたいなことが書いてあります. さすがにいきなり独自アイデアをブチ込む勇気は僕には無かったんですが,idea listにあったネタでProposalを書いていて「いや全然わからん...何からどう実装したらいいのかわからんしそのスケジュールとか立てられん...」となったので,本当にふと思いついたネタで特攻したというわけです. まさか選ばれるとは...

ProposalはまずdraftをGoogle Documentとかで書いて早めに出して,中の人からコメントを貰ってからPDFをGSoCのダッシュボードから提出します. 僕はGoogle Documentがあんまり好きではなかったので*3どうしようかなと思ったんですが, 中の人がコメントできるならURL貼っ付けていいよ,みたいなことが書いてあったのでGistに書いて出しました. emboxはGitHub上で開発されててメンター全員100%GitHubアカウントありますしね. 実際普通にコメント来たので大丈夫だったっぽいです. まあGistくらいならOSSバリバリやってる人には大丈夫でしょ!wと思いますが, 普通は無難にGoogle Documentに書いた方が良いと思います.たぶん.

ちなみに,Final Proposalは期限まであと数日というところで, 唐突にSATySFiで書くか!wっつってSATySFiで書いて送りました. SATySFiで文章書くのはこれが始めてでした(なんで?) 色々教えてくれた丼のオタク,ありがとうね...

あと,自分の中では数日前のつもりだったんですけど, 今確認したら3/30の真夜中にSATySFiわからんとかトゥートしてたので, 正確には1日前っぽいです.バカなの?

可能性がある.知らんけど.

慣れたらかなり良さげっぽいなあとは思ったので,ちょいちょいやっていきたいですね.SATySFi.

というわけで僕は結局期限の数時間前くらいに提出したと思うんですが(記憶がない)91分前に出してたんですが, もっと早めに出した方がいいです. タイムゾーンも違うしね...

まあタイムゾーンに関しては案内にもかなり口酸っぱく書いてありますし, 直前にダッシュボードにアクセスするとご丁寧にJSTでの期限と残り時間が表示されていたので任意の提出物ギリギリ提出オタク各位はダッシュボードとにらめっこするとよいです.

あと,ギリギリ提出オタク各位向け有用情報としては,PDFはいくらでも再登録できるので, ある程度書けたと思ったらとりあえず登録しておいて,少し直したら登録しなおす,というのをやると最悪の事態は避けられます. また,直前に慣れてないもので書こうとか思わない方がいいです.いやそれは普通か...

mstdn.maud.io

さいごに

自分の過去のProposal見せてくれたり,僕のdraftに色々ケチつけてくれたり,SATySFiのこと教えてくれたりした末代各位,ありがとうございました.

あと,今年は全てのEvaluationを通すと$5400貰えるらしいです.ヤバい*4

developers.google.com

ちゃんとEvaluation通せるように頑張っていきたい.

*1:正確には積んでいたのはMaixduinoで,色々弄るにはMAiX BiTの方が良いよと丼のオタクに勧められたのでProposal書きながらMAiX BiTを買った

*2:今年の場合は2/21

*3:あと,G Suiteのアカウントでやろうとしたらワーニングが出たというのもある

*4:VR環境とか整えたいですね(取らぬ狸の皮算用)

メカニカルキーボードを買った

𝑴𝒚 𝒏𝒆𝒘 𝒈𝒆𝒂𝒓...

はい.ついに買いました.やったぜ. いや買ったのはかなり前なんですが海を彷徨ってようやく届いたので今書いてます.はい.

カニカルキーボードって何

よく家電屋でゲーミング任意売り場に置いてあるようなやつです. 光らないやつもある.最初全部光るのかと思ってたのはナイショです. 好きなオタクと違う方向性のキーボードが好きなオタクがいるらしいです.

こいつらの特徴として,打鍵感を決定する「「「軸」」」とかいうものが何種類かあります. あるらしいです. オタクがよくツイッターで赤軸とか青軸とか吠えてるじゃないですか.あれです. あとなんかこの軸ってやつにはCherry MXという規格的なものがあるらしく,とっかえひっかえできるらしいです.楽しそうですね.知らんけど.

軸の種類の解説とかは色々あるけどここらへん見ておけばいいと思います.たぶん. www.diatec.co.jp

買った経緯

相変わらずノリと勢いです. 衝動に従え.

まあもともと気になってはいたんですよ.お高いキーボードってやつ. でもお高いから躊躇してたんですよね.あと沼っぽいし.

じゃあなんで今回買ったかというと,安く買えたからなんですね. 今回メカニカルキーボードを買うのにはDropというサイトを使いました. 昔はMassDropという名前だったそうです.

drop.com

いわゆるgroup buyサービスってやつです. キーボード関連のものとかアウトドアギアとかなんかよくわからんカッコイイ構造物とかが期間限定でたまに安く買えたり買えなかったりします. つまりめちゃくちゃマイニューギアりたい時におすすめです.

alu.jp

ということで,今回買ったキーボードは何かというと,"Durgod Taurus K320 TKL Mechanical Keyboard"というものです.

Amazon CAPTCHA

amazon.jpだと静音軸しか残ってなくて高いですね.2万かあ.

www.amazon.com

amazon.comだと普通の軸が選べますね.99ドルかあ.

じゃあお前はいくらで買ったんかいなというとこんなかんじです

f:id:sksat:20200318172804p:plain

76ドル!やったね!

軸は茶軸にしました.初心者なので. まあ一応ビックカメラのゲーミング任意ゾーンに行ってみたら赤青茶の体験が出来たのでポチポチはしてみましたけどね. 感想としては赤ウーン青ウザッ茶なるほどというかんじです. まあ茶にして良かったんじゃないでしょうか.

あと10ドルくれ!!!!!

↓↓↓

drop.com

※ここから登録すると俺とお前に10ドルやるよリンクです.頼ム〜ッ

使用感

さっき使い始めたのであんまり分かってはいないですが, 今この記事を書いている感想としては書きやすいです. スラスラタイピングできる.あと軽い. なんだったんだ今までのあの力の要るタイピングは代という気持ちです. あと前のは手に合ってなかったんだな感.まあアキバで雑にかった700円とかのキーボードなのでそれはそう.

やっぱり,多分一生パソコンカタカタオタクやっていくわけですし,毎日使うものにはお金かけた方がいいんだなということが分かってきましたね.QoL大事. デスクトップマシン初めて組んでコア数とメモリ容量がドカンと増えた時も良かったし,キーボードなんて物理的に叩くものですからね. やっぱり大事ですよ.

最近はコード以外にもドキュメントとか技術同人誌とか書くようになってきたのもあって,タイプ数/日が激増してる気がするんですよね. 手首とか肩が微妙に痛くなる頻度も上がってきたし. 新しいキーボードでここらへん改善したらいいなあ.

あと,キーボードそのものには関係ないんですがUS配列使うの初めてなので主にそこで苦しんでます. 記号打とうとすると脳がバグる.しばらくは記号打つときはタッチタイピングできないですね. ついでに,今までibus-mozcだったのをfcitx-mozcにしてみました.悪くない.

今後

静電容量無接点方式とか自作キーボードにも手を出していきたいですね. あと割れてるやつとか.マウスも正直微妙だと思ってるのでたまにみるゴロゴロするやつとかも試してみたい.