gotosocialのサーバーを別のマシンに移動した

サーバーコスト削減の流れで、全てをさくらのVPSに集約することができた。

gotosocialのサーバー移動はやや手間取ったが、終わってみれば別段難しいことではなかった。一応ドキュメントに記述があるが、大雑把だ。

https://docs.gotosocial.org/en/latest/admin/backup_and_restore/

やったこと

  • 新しいサーバーにdocker-compose.ymlを配置する
    • gotosocialのdocker imageのバージョンが変わらないように注意する。ここを間違えて0.6から0.7に上がってしまい手間取った。gotosocialのバージョンが上がるとDBのスキーマが変わることがあり、マイグレーションが上手く通らなくてDBを参照できずに落ちる。
gotosocial    | timestamp="04/03/2023 15:27:59.346" func=admin.(*processor).MediaPrune.func3 level=ERROR msg="MediaPrune: error pruning meta: SQL logic error: no such column: account.last_webfingered_at (1)"

https://github.com/superseriousbusiness/gotosocial/blob/main/internal/db/bundb/migrations/20230202212700_rename_account_webfingered_to_fetched.go この辺かな?

  • 古いサーバーのsqliteのデータをdumpする
$ cd data
$ sqlite3 sqlite.db
> .output ./dump.sql
> .dump
  • このdump.sqlを新しいサーバーに持っていく
    • scpなりrsyncなりご自由に
  • 新しいインスタンス用のsqliteデータベースを作りdumpファイルを読み込む
    sqlite3 newdb
    .read ./dump.sql
  • 画像等のファイル(dataディレクトリ内のsqliteではないフォルダ群)も新サーバーに持ってくる
  • docker-compose.ymlをよしなに変更する
    • sqliteデータベースの名前とか注意
  • docker-compose upしてDNSを新しいサーバーのIPに向け直す
    • DNSが効くまで時間がかかって面倒なときはローカルマシンの /etc/hosts に書き込んじゃうとすぐ動作確認できる

日記

急に本格派の焼売が食べたくなったので中国人がやってる中華料理屋で食べた。その後近所を少し散歩した。
コミュニティセンターのような施設があって初めて入ってみたら、大小いろいろな集まりの募集があって面白かった。しかし公的な施設というのはどこも節電で薄暗くて陰気で良くない。

帰宅してのんびりアニメを見たり、RimWorldを見たり、カレーを食べたり。今のロットのカレーはじゃがいもも人参も大きすぎて火の通りが悪いのが反省点だ。

エアコンのフィルタの掃除をした。猛烈にほこりが飛ぶかと思ったがそこまででもなく、粘着コロコロと流水だけでかなりきれいになった。掃除機がなくてもなんとかなるね。

digのオプションが多すぎる

ってmanに書いてあって笑った。

BUGS
       There are probably too many query options.

もっと面白いバージョンもあるようだ。翻訳前の文章は見つからなかった。
https://linuxjm.osdn.jp/html/bind/man1/dig.1.html

dig は "潜行性機能過多" を患っています。 これは開発中に潜在的な用途をいくつも考えていた結果です。 苛酷なダイエットをしたらきっとよくなるでしょう。 同様に、表示フラグとそれで指定できる表示項目の粗さとから、 これらがその場限りの必要性から追加されたものだということが わかるはずです。

ところでdigしたときのANSWER SECTIONの謎の数字って残りキャッシュ時間らしいんだけど本当ですかね?確かに減っていくんだけど。

新しいことへの挑戦とリファクタリングを同時にしてはならない 五木寛之『生きるヒント 自分の人生を愛するための12章』を読んでいる

新しいことへの挑戦とリファクタリングを同時にしてはならない

サーバーコスト節約と技術的チャレンジを同時にやろうとしてk8sがわからなくて遅れているけどとりあえずサーバーコストだけでも落としたほうが良い。一番の金食い虫のt2.microのインスタンスを早急に潰したい。

その後さくらの方に全部移してみて、それでスペック足りるようだったら一旦終わりにしよう。大半のアプリケーションは常時起動が前提だからElasticである必要がない(何にでもElasticを注ぐAWS)。

五木寛之『生きるヒント 自分の人生を愛するための12章』を読んでいる

ぼんやりと落ち込んでいた時期に友人に勧められた本。今4章。

筆者が人生経験と知識に基づいて、「こうあると人生が楽しいんじゃないか」という話を取り留めなく書き連ねている。職業柄厳密に事実を書いた本を読むことが多いけど、こういう「私の感想」全開の本というのも良い。時間も空間も超えて他人の言葉に触れられるという本の特質を鑑みれば、むしろこういう本こそ読書の楽しみなのだと思う(まあ金持ってるジジイだから余裕ぶっこいた物言いができるんだよね、と鼻白むようなところもないでもない)。

3章「悲む」ではまず明治時代に「悲しいではないか」を挨拶とした若者たちがいたことに触れ、人生には悲しみが満ちていることを認め、現代の娯楽が明るさを求めすぎていることを指摘し、私達はもっと率直に悲しんで良いはずだと主張する。

みんなが、〈暗い〉と言われることを恐れている。そして明るく軽快で楽しげであることを求めている。
これはひとつの病気ではないかと、ぼくには思えるのです。

これは僕もその通りだと思う。アニメを見ていてキャラクターの底なしの明るさと作品に満ちるエネルギーに圧倒されてしまうことが多い。思えば記憶に残るお気に入りの作品は静かで悲しいものが多い。

仕事をしていても、目標は高く輝かしく、失敗も問題点の分析と修正して次は頑張ろうというエネルギーに転化される。もちろん営利企業だからそのエネルギー、欲望でカツオのように泳ぎ続ける宿命にあるわけだが、一人の人間としてはついていくのが辛いときもある。

k8sデカスギSGSG

t4g.microの上に小さいクラスタ立てて練習しようとか思ってたけど、プロダクション向けのクラスタ立てツールであるkubeadmを走らせてみたらいきなり「メモリは最低1700MB用意しろ」とか言われてひっくり返ってる。ノードも複数台で本格的にやることしか想定してなさそうだし、これどうすればいいんだ(世の趣味でkubernetesで使っている人間は結構なインフラコストを払ってやっているのか?EKS最小構成でも月額73ドルらしい)。

k8sはクラスタ自体が容易に作成・管理できるものではないといろいろな場所で言われていたが、やってみてようやく規模感が理解できた。そして困った。

minikubeはproductionに使うなと繰り返し書かれているが、練習だからと割り切って使ってしまうのもありだろう。

また k8s lightweight とかで雑に検索してみると

  • k3s
  • microk8s
  • k0s

などがヒットした。k3sならいけるか、見てみよう。あるいは自宅に物理鯖置いてそこにクラスタを組み、トンネリングツールか何かで公開するという方法もあるのかな(もう全く安くないが)。

k8sをやってみる―サービスの公開―

サービスを公開する

https://kubernetes.io/ja/docs/tutorials/kubernetes-basics/expose/expose-intro/

なんかいろいろ公開の種類もあるが、随分ローレベルだなあと思ったらServiceとは別にIngressというやつがあるらしい。

https://kubernetes.io/ja/docs/concepts/services-networking/ingress/

Ingressにはいろいろな実装?がある。kubernetes自体が未知の領域なのでなるべく慣れたものに寄せるため、nginxによる実装を使う。

https://kubernetes.github.io/ingress-nginx/deploy/

インストール方法に with kubectl apply, using YAML manifests がある。嬉しい。

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/cloud/deploy.yaml

で必要なリソースが諸々立つらしい。先に作っていたDeploymentとここで作るリソースを統合するためkustomizeを導入する。と言っても

resources:
- deployment.yml
- https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/cloud/deploy.yaml

と書かれたファイルを用意し、起動コマンドを kubectl apply -k . に変更するだけだ。

https://github.com/chao7150/barrack-k8s-spec/commit/977fb3c90989f96c5a070508e90aad45b570adad

この段階でこれらのファイルを保存しておくGitHubのリポジトリを作った。

本題に戻って外部からいい感じに内部のサービスにリクエストが通るように進める。

https://kubernetes.github.io/ingress-nginx/deploy/#local-testing

既にDeploymentは存在するとして、exposeでそのDeploymentを公開し(これはServiceを立てることと等しいので後々ymlでそれを書く)

kubectl create ingress demo-localhost --class=nginx \
  --rule="demo.localdev.me/*=demo:80"

でアクセスをDeploymentに向けるようなingressを立てる。classはいろいろあり得るingressの実装のなかでingress-nginxを使いますよという意味。ruleは demo.localdev.me/* へのアクセスをdemoという名のDeploymentの80番ポートにフォワーディングしますよという意味。

なんで demo.localdev.me がlocalhostに向いてるんだよと思って調べてみたら

https://qiita.com/masahata/items/89b2be02ee36b82cfced

このドメインを誰かが取得して 127.0.0.1 に向けているらしい。マジかよ。そして何の説明もなしにやるなよドキュメントで。

ここから先は本番のクラスタでやることらしいので、次回は本番のサーバにクラスタを組んでもろもろやっていくか。本番のサーバは既にgotosocialで稼働しているので、nginxでgotosocial以外へのアクセスをk8sクラスタに流す方針でやってみる。SSLオフロードとかも前段nginxでやっちゃいたい。

IYマイレジ ピピットスマホを会員限定にするな うたもくとgfnと酒を飲んだ

たまには日記を書く。

起きて、昼食に丸亀製麺のトマトカレーうどんチーズのせを食べた。

スポーツクラブに行って30分歩いたり走ったりした。本来日曜日は泳ぐのだが、今日は足腰の筋肉痛が持続していたので軽くした。マシントレーニングで同じ筋肉を週1回鍛えるとして、筋肉痛が1週間持続したらその間その筋肉の負荷は抑えるべきらしいので、有酸素運動を軽減せざるを得ない。なんというか、配分が難しい。人生を通してきちんと体を鍛えたことがなかったのでどうやればいいのかわからないことが多い。

IYマイレジ ピピットスマホを会員限定にするな

その後スーパーで納豆とヨーグルトを買って帰った。これまでスーパーではスマホをセルフレジ代わりにするサービスが使えたのだが、今日行ったら会員登録しないと使えなくなっていた。しかもその会員登録がスマホからしかできず、登録したらメール送りまくりますメール停止は面倒にしておきますと宣言するかのような文言があったので、腹が立って登録をやめた。

スマホに通知を飛ばせるという点でアプリをインストールさせるのが効果的なのは理解するが、会員登録には

  • メールアドレスの入力
  • パスワードマネージャによるパスワード生成

という作業が必要であり、これらを豆粒みたいなキーボードと1つのアプリしか同時に起動できない制約のあるスマホでやるのは面倒くさい。

そもそもスマホレジは有人レジを減らして人件費を抑えながらレジの待ち時間を減らせるwin-winの仕組みのはずなのに、どうしてそこに会員登録誘導というハードルを設けてしまうんだろう。

うたもくとgfnと酒を飲んだ

やっていきエナジーをかなり充填したのだが、2人はコードを書くことで世界に対してオンリーワンの貢献をしている一方で、僕は至って普通の職業ソフトウェアエンジニアで、ともすれば社内の事情や評価のことを考えがちだ。能力の高低以前に世界観のスケールが違う。

とは言っても彼らは会社のことなんか知らないで技術的探求に耽溺しているというわけでもない。むしろ技術的な最先端を突き進むことが会社の利益につながっていたり、逆に会社での制約を経験することで技術的な視野を広げたりしている。

レベルを上げて物理で殴れば全てが手に入るのだろうか。答えはわからない。具体例があるだけだ。ただ、こうして刺激をもらえる機会があるというのはありがたいことだ。

k8sをやってみる―Deploymentを作る―

※この記事は私の学習のメモであり、有益な知見は含まれていません。読まないでください。

k8sのクラスタを作る

チュートリアルのnginxのコンテナを立ててスケールさせて…みたいなやつは大昔に一度やった。今回はymlファイルのアレ(何て言うんでしょう?)で宣言的に管理できる状態を目指す。

チュートリアルを読むといきなりMinikubeというやつが出てくる。

https://kubernetes.io/ja/docs/tutorials/hello-minikube/

kubernetesのクラスタを作るのにkubernetes hogeとかkubectl fugaみたいなコマンドじゃなくて別の何かが必要になるのか…

https://kubernetes.io/docs/setup/

kubernetesのクラスタを作る方法を選ぶためのページがある。ローカルでの開発にはminikubeを、プロダクションにはkubeadamということにしよう。

https://minikube.sigs.k8s.io/docs/start/

minikubeを入れた。

minikube start

するとkubectlが見つかりませんと表示された。そこで

https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/#curl%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6linux%E3%81%B8kubectl%E3%81%AE%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B

に従ってkubectlを入れた。あとでaptで入れればよかったと後悔したが、まあ良い。minikube deleteして再度minikube startするとなんとなく問題なさそうなログが出て作成が完了した。

ymlファイルを書いてなんかアプリケーションをデプロイしたい

k8sのドキュメントの中で情報を探すのに苦労したが、どうやら

https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/
https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/

この辺りを読めばいいらしい。ymlで設定ファイルを書ける機能はkubernetesの(というかkubectlの?)標準機能としてありDeclarative Managementと呼ばれていて、kustomizeはその拡張?のようなものだろうか。

そもそもどうやるとアプリケーションをデプロイできるのかというのを忘れてしまっているので、チュートリアルの内容をDeclarative Managementの作法で進めてみる。

チュートリアルによるとまずはDeploymentを作るらしい。

https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/#how-to-create-objects

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

というファイルを作って同じディレクトリで kubectl apply -f . してみるとDeploymentが作られた。metadataとかselectorとか無くても動かんかw?と思って削ってみたらダメだった。これがホントの最小構成らしい。

次はこうして立てたコンテナに外からアクセスできるようにしたい。チュートリアルの方はしばらくデバッグ用と思われる kubectl proxy を使いながら基本的な操作の説明をするようだ。

サーバーゼニ節約&kubernetes入門

ふと毎月のサブスク費用を確認したらAWSとさくらインターネットで月額5000円くらいかかっていて、いくらなんでも辛いのでこれを圧縮する。

原因は必要以上に多くのサーバーを稼働していること。現在稼働しているのは3つ。

さくらインターネット 2GB

  • 1738円/月
  • 2017年から借りており、中途半端な技術的挑戦の残骸が最も多い
  • 金額に対するスペックが良い

積載物

AWS EC2 t2.micro

  • 1544円/月

積載物

AWS EC2 t4g.micro

  • 1076円/月
  • AWS謹製のGravitonプロセッサなので安くて高性能。ただしArm。

積載物

  • gotosocialインスタンス

移行計画

どうしたものか…

とりあえずEC2は新世代ほど高コスパの原則があり、t2.microはt4g.microに移行すべき。自分の学習を考えるとさくらはやめてEC2に揃えたい。全部t4g.microに相乗りを狙ってみようか。

そしてどうせならkubernetesに全部載せてみたい。複数のアプリケーションを相乗りさせるときのトラフィック管理をこれまではjwilder/nginx-proxyでやっていたが、もうちょっとナウいやつに移行して監視とかも統一的にやりたい。

ActivityPub用のtwilogみたいなやつを作っている(notestockがあるのは知ってるよ!)

gotosocialからnotestockが使えなくて、少し調べてもわからなかった上にnotestockがソースコードを公開しておらず(してないよね?)調査を進めるのが困難そうだったので、自分で作ってみることにした。もとより自分のデータを自分で管理することは重要だと思っていたので、そういう意味もある。

https://github.com/chao7150/activitypublog

使用技術はGo+Echo+MySQL8.0。まあ正直手慣れたRemix+Prismaでやったほうが早いとは思うんだけど、たまには違うことをやったほうがいい。自分でアプリケーションをGoで書くのはこれが初めて。普段一番書いているTypeScriptに比べると、補間、エコシステム、ドキュメント、ビルドの速さが優れている。型システムは劣っている。module/packageが難しく、挙動もベストプラクティスもよくわかっていない。この辺を読んで参考にしている

また、具体的なGoの書き方の作法はGoToSocialを真似ている。

Goで良いなと思ったのは、timeだ。たとえば

// Go
time.Now().Add(5 * time.Minute)

は間違いなく

// JavaScript
new Date(Date.now() + 5 * 1000 * 60)

よりエレガントだ。

フォーマット文字列も好きだ。大抵は%vでどうにかなるという逃げ道を残しつつ、各データ型の中でも様々な表現を可能にしている。

if err...の洪水については、エラーメッセージを真面目に考える契機になる。すなわち、エラーはerrを通して呼び出し元に順に伝播するわけだが、その過程の各関数の中で徐々に情報を付け加えることができる

if err != nil {
    return c.String(http.StatusInternalServerError, fmt.Sprintf("error GET /: %v", err))
}

具体的に何が失敗したのかはerrの中身をそのまま表示しつつ、この階層では GET / という場所でエラーが起きたという情報を付け加えている。

自分用ActivityPubインスタンスとしてGoToSocialを立てた

ツイッターがいよいよヤバそうなのでActivityPubのインスタンスを立てたくなった。まずMastodonを検討したが、リソースの要求が高いので諦めた。不慣れなRoRだしTypeScriptじゃないし構成も複雑なので個人で管理・改造するのは負担が大きいというのもある。

改めてActivityPub実装の中で軽量なものを探したところGoToSocialが良さそうだったので立てた。AWS EC2のt4g.microで現状問題なく稼働している。と言ってもまだフォローが少ないからかもしれない。ActivityPub、というか分散型SNSという仕組み上フォロー関係が増えると加速度的に通信が増大していくはず。

GoToSocial

GoToSocialはGoで書かれている。シングルバイナリで吐かれるアプリケーションとsqliteで動き、公式に提供されるdocker-compose.ymlを少し調整してリバースプロキシとしてnginxを立てるだけで動かすことができた。

現段階ではアルファリリースという位置づけであるが、大部分の基本的な機能に問題はない。今自分が把握している問題は以下の2つだ。

  • 動画が表示されない
  • notestockが利用できない
    • 利用を開始するためのnotestockのbotアカウントへのメッセージ送信がエラーで失敗する
    • mastodonには送れるのでnotestock側に何か問題があるのではと思っているが、notestockのソースコードは公開されていないので詳細不明

フロントエンドをほとんど持たず、サードパーティのクライアントから叩かれるAPIサーバーに専念している。推奨されているクライアントはpinaforeだが、pinaforeは2023年1月に開発の停止が発表された。webクライアントに限ればこれが最も盛んに開発されていたので先行きが不安だ(しかし作者自身が述べているようにpinaforeもだいぶ技術スタックが尖っていて将来性は怪しかった…)。ActivityPubデビューする人は最初にサーバーに登録してからクライアントを導入するだろうが、GoToSocialはユーザー登録用のフロントエンドも持っていないので一般に公開するにはハードルが高めかなと思う。自分はdockerコンテナに入ってCLIからアカウントを作成した。

自分でちょっとした改造を試みたときにdocker buildが大量のメモリを食ってEC2が落ちた(2GBでは足りなかった)。Dockerfileからswagger関連の処理をゴリッと消してやると直る。