Posts for: #Infrastructure

寝台特急に初乗車

2時に寝て6時過ぎに起きた。本当はもっと早く寝た方がよいのに22時半から2時前まで作業してた。格闘家に学ぶ体脂肪コントロール 本に睡眠をとることや疲労を溜めないことが代謝をよくすると書いてあって、その通りだとは思うのだけど、なぜかここ最近は2時ぐらいまで作業していることが多い。いろいろうまくいかない。

今日の運動は腕立て,スクワット,背筋をした。統計を 運動の記録 にまとめる。

テスト環境の再構築

テスト環境の見直し の都築。先週末から cockpit 上の仮想マシンに OS をインストールしたりしていた。今日はテスト対象のアプリケーションをインストールして設定をしたり、既存のテスト環境を移行したりしていた。

いまテスト環境は1つしかないが、機能が増えてきて、複数の運用要件を満たす必要があって、1つの環境ですべてを検証するには不便な状態になっていた。そこで1つに全部入りするから相反する要件が競合するのであって、いまわかっている要件を用途別に、1つを3つの環境に分割した。1つしかないものを複数にすると、その重複するところのコストもかかる。その辺りの調整もしていた。テスト環境の構築について、過去に私が作ったものではあるけど、1回作って終わりだと思っていたのか、構築の issue にはなにか書いてあるかもしれないが、wiki には残していなかった。今回3つに作り直すにあたってドキュメントがあれば思い出したり、トライアンドエラーを行うコストも省略できて、ちゃんとドキュメントを書かないとあかんなと反省した。新規に設置した仮想マシンに openldap サーバーを構築する以外の作業は完了したはず。

サンライズ出雲の乗車と遅延

1ヶ月前に予約した 0時11分発の特急サンライズ出雲で東京へ向かう。

20時半にオフィスから家に帰ってきて、洗い物して、お風呂入って、ストレッチして、荷造りして、3時間もあれば余裕で出発できる。初めて寝台特急に乗る。間違いがないよう、改札で駅員に問い合わせる。すると、動物(シカ)と接触して列車が止まってしまっているという。再開予定ではあるが、駅員さんに話しかけた時点ではいつ再開するかはわかっておらず、その情報も乗客からオンラインでは調べられず、駅員さんしか状況を知る方法はないとのこと。動物とぶつかったぐらいで運休はないやろうという話しもあってそのままホームで待つことに。

ホームのアナウンスを聞いていると「運転しています。」と言い切るので再開したのかな?と期待するものの、35分遅れ→40分遅れ→45分遅れと遅延時間がどんどん増えていくので実際には停車していて点検中でも「運転している」とアナウンスするらしいということがわかった。最終的には80分遅れて三ノ宮に到着した。待合室で半分寝てたよ。そのまま目を覚さなくなるところでしたよ。

この時点で今日はゆっくり睡眠をとろうと思っていたのに大きな誤算だった。待ち疲れていたのもあったせいか、部屋に入って消灯してそのままわりとすぐに寝てしまった。列車に乗ったのが1時半、トイレに行って、駅員さんが切符確認に来て、2時頃には寝てしまったのではないかと思う。わりとよく眠れたと思う。列車の揺れと移動音は普通にはあるものの、私はこの手の環境には強いので、もちろん身体は疲労するかもしれないが、感覚的には気にせずそのまま寝ていたと思う。この状態で眠れるかどうかによって寝台特急の是非は変わってくるだろう。カプセルホテルよりは天井も高く、スペースも一回り広くて余裕がある。今回は下の真ん中ぐらいの部屋だったのだけど、場所によって揺れや移動音の聞こえ方も変わるという。通な人は部屋の位置もこだわるのかもしれない。

あと薄い毛布しかないため、冬はちょっと寒い。暖房入れて上着もかけてぎりぎりの暖かさかな。べつに眠れないほど寒いわけではないが、冬なんだからもう一枚布団を用意してくれてもいいのになという感覚はある。朝に起きて窓から線路は延々と眺められる。線路が好きな人にもよさそう。けっこうよかったのでまた来月も予約して寝台特急で出張へ行く。

テスト環境を作り直す

21時頃から寝て何度か起きて7時半に起きた。昨日は頭が痛かったら早く帰って安静にしてた。安静にしたら直ったので大したことはなかったみたい。

今日の筋トレは腹筋:15x2,腕立て:10x1,スクワット15x2をした。

テスト環境の見直し

いまどきの開発の定番としては ci/cd でコミット単位にテスト環境にデプロイする仕組みを構築している。テスト環境は1つだけになるのだけど、プロダクトの開発を1年以上やってきて機能が増えたことによって、1つのテスト環境で相容れない複数の要件や機能を混在させることで管理や運用が煩雑になってきた。気付いたタイミングがよい時期だと思うのでこの機会に1つのテスト環境を3つのテスト環境に分散させようと思う。既存データを確認するだけなら1つでもよいが、id 連携という機能の特性上、複数のシステム間でデータ連携するため、システム間での依存関係が発生する。それを整理しないといけなくなったという次第。今日のところは現状把握や移行に必要な段取りなどを設計していた。

hugo のハンズオン資料作り

昨日の続き 。23時過ぎに外に出たついでにオフィスに寄り道して書き始めたらまた熱中してしまって2時ぐらいまで書いていた。ハンズオンで説明する内容は一通り書いたつもり。せっかくの機会だから上級者向けにもう少し知っていることを書いてみようとは思う。

コンテナイメージの移行

1時に寝て3時に起きて6時半に起きた。スマホで呪術廻戦のゲームを開いたまま寝てた。

サードパーティの mongodb コンテナへの移行

昨日の mongodb のサードパーティのコンテナイメージ調査 の続き。

レプリカセットの削除

基本的に一度作ったレプリカセットを削除することはないせいか、レプリカセットを削除するユーティリティは提供されていない。なんらかの理由でレプリカセットを再作成したいときは、レプリカセットの設定が保存されている local database を削除する。

またレプリカセットの稼働中に local database を削除することはできないため、mongod サーバーを --replSet を指定していない状態で起動させ、そのときに次のようにして local database を削除できる。

test> use admin
admin> db.grantRolesToUser("root", ["__system"]);
{ ok: 1 }
admin> use local
switched to db local
local> db.dropDatabase()
{ ok: 1, dropped: 'local' }
local> use admin
switched to db admin
admin> db.revokeRolesFromUser("root", ["__system"]);
{ ok: 1 }

コンテナを使ったレプリカセットの初期設定

bitnami/mongodb を使うと、ローカルのシングルノードでレプリカセットを使うには次のような設定になる。

  mongo:
    image: docker.io/bitnami/mongodb:7.0.1
    user: root  # デフォルトは非 root ユーザーで起動するのでローカルの開発環境なら root で実行した方が手間がない
    volumes:
      - ./volumes/mongodb:/bitnami/mongodb
    environment:
      MONGODB_ROOT_USER: "${MONGO_USER}"  # 認証ユーザー
      MONGODB_ROOT_PASSWORD: "${MONGO_PASSWORD}"  # 認証ユーザーのパスワード
      MONGODB_ADVERTISED_HOSTNAME: "mongo-primary"  # レプリカセットのノードを ip アドレスではなくホスト名で指定する
      MONGODB_REPLICA_SET_NAME: "myrs"  # レプリカセットの名前
      MONGODB_REPLICA_SET_MODE: "primary"  # プライマリノードとして設定
      MONGODB_REPLICA_SET_KEY: "my/replication/common/key123"  # キーファイルのコンテンツ (base64 でデコードできる値)
      MONGODB_SYSTEM_LOG_VERBOSITY: 0  # ログレベル
    hostname: mongo-primary  # コンテナの内外から解決できるホスト名を指定
    container_name: mongo  # コンテナ名 (docker container ls で表示される名前)
    ports:
      - 27017:27017  # レプリカセットを運用する場合はポート番号のマッピングを一致させる必要がある
    restart: "always"

この設定でレプリカセットを初期した場合、レプリカセットの initialize 処理は、次のような config/member をもつ。

members: [{ _id: 0, host : "mongo-primary:27017", priority: 5 }]

コンテナの内部からは mongo-primary というホスト名に対して、コンテナネットワーク内のローカル ip アドレスが解決される。

c67a5ca94a77:/app# dig +short mongo-primary
192.168.240.3

ここで host os 上のアプリケーションから mongo コンテナに対してレプリカセット接続をする場合 replicaSet=${レプリカセットの名前} のパラメーターを追加する。

mongodb://root:password@localhost:27017/?authMechanism=DEFAULT&replicaSet=myrs

これは localhost:27017 にレプリカセットの接続を試行し、接続できるとレプリカセットのメンバーが返される。

レプリカセットのメンバーには mongo-primary:27017 という設定が行われているため、mongo-primary というホスト名に対して host os 上で名前解決できる必要がある。そのために /etc/hosts に次の設定を行う。

$ sudo vi /etc/hosts
...
127.0.0.1 	mongo-primary

compass で接続した場合、レプリカセット接続であれば、レプリカセットの名前が接続情報として表示される。

ダイニングテーブル引き取り

実は火曜日にも長机を引き取りに行ってきて、今日はダイニングテーブルを引き取りに行ってきた。この3日間で2つもテーブルが手に入った。いつも目ぼしいと思ったものは、すぐに他の人と取り引きが成立してしまうのに、たまたま続けて私と取り引きが成立した。車で20分ぐらいの距離のマンションまで引き取りに行った。20時の予定を、19時10分には着いてしまって、先方も快く対応してくれた。私よりも見た目すこし年配の方で人当たりのよい感じの方だった。ジモティのやり取りはその人の性格が出るもので、受け渡しだけささっとやって余計な話しはしないパターンもあれば、愛想よく話しながら受け渡しをするパターンもある。先方によると、大事に使っていたテーブルのようにみえるので私も離れのオフィススペースで大事に使おうと思う。

mongodb のサードパーティのコンテナイメージ

23時に寝て3時に起きて寝たかどうか覚えていないうちに6時半になっていて7時半に起きた。

json を介した go の bool 値のバリエーション

go-playground/validator のバリデータには required というバリデーションオプションがある。しかし、このオプションは go のゼロ値でないことをチェックするという仕様になっている。bool のゼロ値は false となるため、リクエストした JSON データに false を設定していたのか、未設定だったのかの違いを検出できない。これはバリデータの問題ではなく、go の json ライブラリの制約のようなもので使い勝手のよい仕様とは言えない。私もこの振る舞いに起因する不具合に遭遇したこともあるし、こういうときにどうしたらよいかも過去に3回ぐらいは調べている気がする。

現時点での私の最適化は次のコードになる。データ構造として *bool 型にすれば、ポインタ型のゼロ値は nil となるため、true, false, nil の3値でバリデーションできる。しかし、私はこのデータ構造を好ましく思わない。というのは、内部的には true/false の2値でしか管理しないメンバーを、json のバリデーションのためだけに nil も許容する3値にすることがよい設計だと私は思えない。そこでバリデータによるバリデーションは諦めて、json の Unmarshal 処理をフックしてバリデーション相当の処理を自分で実装する。このやり方のデメリットはメンバーが追加されたときに自分で UnmarshalJSON() メソッドを保守する必要がある点になる。しかし、メリットとして内部のデータ構造の型は bool 型で扱える。一概にどちらがよいとは言いにくいかもしれないし、設計上の好みかもしれない。

type reqMyData struct {
	Name       string `json:"name"`
	View       *bool  `json:"view"`
}

type MyData struct {
	Name       string `json:"name"`
	View       bool   `json:"view"`
}

func (d *MyData) UnmarshalJSON(data []byte) error {
	var tmp reqMyData
	if err := json.Unmarshal(data, &tmp); err != nil {
		return fmt.Errorf("failed to unmarshal as reqMyData")
	}
	if tmp.View == nil {
		return fmt.Errorf("required view field")
	}
	d.Name = tmp.Name
	d.View = *tmp.View
	return nil
}

サードパーティの mongodb コンテナイメージ

先日の mongodb のレプリカセット調査 の続き。コードレビューをしていて bitnami/mongodb というサードパーティのコンテナイメージを使った方がよいのではないか?というコメントがあったのでその調査をしてみた。VMware 社が提供しているサードパーティのコンテナイメージらしい。

MongoDB(R) is run and maintained by MongoDB, which is a completely separate project from Bitnami.

まず MongoDB プロジェクトとはまったく別管理であることが書いてある。

Bitnami イメージを使用する理由

  • Bitnamiはアップストリームソースの変更を綿密に追跡し、自動化されたシステムを使用してこのイメージの新しいバージョンを迅速に公開します。
  • Bitnami イメージでは、最新のバグ修正と機能をできるだけ早く利用できます。
  • Bitnamiのコンテナ、仮想マシン、クラウドイメージは、同じコンポーネントと構成アプローチを使用しているため、プロジェクトのニーズに応じて形式を簡単に切り替えることができます。
  • Bitnamiのイメージはすべて、minideb(最小限のDebianベースのコンテナイメージ)またはscratch(明示的に空のイメージ)をベースにしています。
  • Docker Hubで利用可能なすべてのBitnamiイメージは、Docker Content Trust(DCT)で署名されています。DOCKER_CONTENT_TRUST=1 を使用して、イメージの完全性を確認できます。
  • Bitnamiコンテナイメージは定期的にリリースされ、最新のディストリビューションパッケージが利用可能です。

MongoDB®を本番環境で使用したいですか?Bitnami Application Catalogのエンタープライズ版であるVMware Tanzu Application Catalogをお試しください。

mongo の公式イメージは ubuntu をベースイメージにしている。ubuntu よりは minideb の方が軽いのかな?そしてちゃんと upstream にも追随しているみたい。このベースイメージの違いによるものかは定かではないが、結合テストのイメージも移行してみたところ、10-20秒ほど結合テストの実行時間が速くなった。割合にすると10%程度かな。

KubernetesにMongoDB®をデプロイするには?

Bitnami アプリケーションを Helm Chart としてデプロイすることは、Kubernetes 上で当社のアプリケーションを使い始める最も簡単な方法です。インストールの詳細については、Bitnami MongoDB® Chart GitHub リポジトリを参照してください。

Bitnami コンテナは、クラスタへの Helm Charts のデプロイと管理に Kubeapps と一緒に使用できます。

helm chart も提供しているようで、いずれクラウド版を作るときに MongoDB も k8s 上にデプロイする上でこのことは都合がよいように思える。

レプリケーションを前提とした初期設定があり、entrypoint スクリプトもいくつか読んでみた感じだと、きれいに管理されていて保守もちゃんとやってくれそうにみえる。

昨日、導入したばかりの公式イメージ + 自作スクリプトによるレプリケーション設定を廃止して、Bitnami のコンテナイメージを使うことに決めた。

owner/permission の違うファイルとリポジトリ管理

23時に寝て2時に起きて6時に起きて7時過ぎに起きた。なんか微妙な寝方をした。

先日の mongodb のレプリカセットの調査 の整理をしてマージリクエストを作成した。共通鍵の keyFile をどう扱えばいいのか、わからなくて、一旦コンテナ内の tmp 領域にコピーして、それを entrypoint スクリプトでコピーしてから owner/permission を変更するというやり方で、リポジトリ管理で共有しやすいようにしてみた。entrypoint スクリプトは root 権限で実行されることも理解した。

volumes:
  - ./mongo/keyfile:/var/tmp/keyfile.orig
command:
  - mongod
  - --keyFile
  - /data/keyfile
  - --replSet
  - "myrs"
entrypoint:
  - bash
  - -c
  - |
    if [[ ! -f /data/keyfile ]]; then
      cp /var/tmp/keyfile.orig /data/keyfile
      chmod 400 /data/keyfile
      chown mongodb:mongodb /data/keyfile

    fi
    exec docker-entrypoint.sh $$@    

テックブログを読む会

昨日、西原さんに教えてもらった テックブログを読むイベント を探したら毎週月曜日に行われているようだった。早速 テックブログ一気読み選手権20231211杯 に参加した。HackMD で読んだメモを管理している。記事を選択して、読んで、所感をまとめて、他の人たちと共有する。ただそれだけのイベント。ちょうど30分で終わって、自分の勉強にもなったし、他の人の話しも聞いて参考になった。たった30分でも、なにもやらないよりずっとよい。1ヶ月ほど参加してやり方を学んだらチームにも展開してみようかと考えている。

mongodb のレプリカセットのデプロイ調査

4時前に寝て6時半に起きた。1時過ぎまで作業して、帰って少しゲームして、うまく眠れなくてだらだらしていた。

mongodb のレプリカセットの調査

以前 mongodb でトランザクションを使うときにレプリカセットが必要 なことがわかった。他機能の開発途中だったので一旦後回しにしていたものを回収している。状況によってはメンバーに委譲してもよかったんだけど、私が遊撃で出張ってみることにした。実際に調べてみてコンテナの運用も考慮するとけっこう難しいことがわかってきた。

mongosh からは Replication Methods を使ってレプリカセットの操作ができる。これはユーティリティのようなもので mongodb としての低レベルのコマンド操作は Replication Commands になる。mongo-go-driver はレプリカセット向けのユーティリティを提供していないため、Replication Commands を RunCommand() の低レベル API を使って自分で実装しないといけない。

例えば、レプリカセットの初期化をするときは次のように replSetInitiate というコマンドを適切なパラメーターで呼び出す。あまりドキュメントで丁寧に説明されていないので試行錯誤でエラーメッセージをみながら実装することになる。とくにはまるのが mongod のサーバーは --replSet myrs のようにレプリカセットを指定して起動させるものの、初期化コマンドを実行するときはまだレプリカセットを設定していないため、レプリカセットを指定せず、且つ direct パラメーターをセットしないと mongod サーバーに接続できない。この微妙な設定を把握するのにはまった。これが正しい手順かどうかもわからないが、ググったりしているとフォーラムでそういったコメントが散見されたりする。おそらく mongosh の Replication Methods を使うと、クライアントからサーバー接続は裏方でよしなにやってくれるのでそっちの方が簡単ではある。

func (r *ReplicaSet) Initiate(ctx context.Context, config bson.M) error {
	client, err := r.connectDirect(ctx)
	if err != nil {
		return fmt.Errorf("failed to connect with direct: %w", err)
	}
	defer client.Disconnect(ctx)

	var result bson.M
	cmd := bson.D{{Key: "replSetInitiate", Value: config}}
	if err := client.Database(r.db).RunCommand(ctx, cmd).Decode(&result); err != nil {
		return fmt.Errorf("failed to run replSetInitiate(): %w", err)
	}
	log.PrettyPrint("completed to initiate", result)
	return nil
}

func (r *ReplicaSet) connectDirect(ctx context.Context) (*mongo.Client, error) {
	opts := options.Client().
		SetAuth(options.Credential{
			Username: r.config.User,
			Password: r.config.Passwd.String(),
		}).
		SetHosts(r.config.Hosts).
		SetDirect(true) // must be true
	return mongo.Connect(ctx, opts)
}

func InitSingleReplicaSet(
	ctx context.Context, cfg *config.MongoDB,
) error {
	rs := NewReplicaSet(cfg)
	initConfig := bson.M{
		"_id": cfg.ReplicaSet,
		"members": []bson.M{
			{"_id": 0, "host": "localhost:27017"},
		},
	}
	return rs.Initiate(ctx, initConfig)
}

さらに mongod サーバーを起動するときに --replSet--keyFile (認証が必要な場合のみ?) という2つのパラメーターを指定する必要がある。--replSet はレプリカセットの識別子を指定する。そして --keyFile は共通鍵を指定する。この共通鍵を生成するには次のようにする。

$ openssl rand -base64 756 > my-mongo-keyfile
$ chown mongodb:mongodb my-mongo-keyfile
$ chmod 400 my-mongo-keyfile

普通のサーバーインスタンスならすぐできることだが、コンテナの運用において面倒なのが owner とパーミッションを設定しないといけないところ。mongo のコンテナは mongodb ユーザーで起動するため、root でマウントされたファイルシステムには書き込みできなかったりして keyFile の配置をどう扱えばよいのかが難しい。docker hub の mongo の issues でもどうやって設定したらいいの?って議論が発散している。mongo 本体が公式のスクリプトや仕組みを提供していれば済む話しだけど、どうもそうではないみたい。だから泥臭い方法で自分でなんとかしないといけないようにみえる。

dockertest でもレプリカセットの設定について次の issue として登録されている。mongo のコンテナを使ったテストの場合、dockertest のレイヤーが挟まるのでさらにわかりにくくなっている。テストを動かすためにどういった設定が必要かは把握できたのでなにかよい方法を考えてコントリビュートしたい。

selinux はなるべく有効にして使うもの

22時ぐらいから寝始めて何度か起きて6時に起きた。早く寝たから早く起きた。

selinux の微妙な振る舞い

今日は火曜日なのでチームの定例会議をやって、ドキュメントを書いて、その後はインフラの細かい作業をわちゃわちゃやって、ドキュメントを書いてとわちゃわちゃやってた。

先週、最新の almalinux 8 をインストールして、その後、lvm の論理ボリュームの結合 とか、rootless コンテナ の設定とか、テスト環境を構築していた。gitlab ci/cd から ssh で公開鍵認証を使ってデプロイしている。作り直したこのテスト環境に対してその公開鍵認証がうまく動かない現象に遭遇した。よくある設定や権限のトラブルではなく、デバッグ用の sshd を起動すると公開鍵認証できた。なにかしら systemd 経由で起動する sshd の設定ミスなんじゃないかと、2-3時間デバッグしてもわからなくて社内の有識者に尋ねてみた。

$ sudo /usr/sbin/sshd -d -p 2222

selinux を無効にしてみたら?というアドバイスをいただいて、試しに enforced から disabled にしたら動いたので selinux のなにかしらの設定を変えてしまったのかな?とそのときは思っていた。しかし、別の開発者からデフォルト設定で enforced でも動くはずという情報をもらって、もう一度 disabled から enforced に戻して再起動したら普通に動いて、その前の公開鍵認証の失敗を再現できなくなった。私にはこの先のデバッグはまったくわからない。お手伝い先のシニアエンジニアの方にみてもらって次のようなことを教えてもらった。

SElinuxが怪しいなと思ったら、/var/log/audit/audit.log とかausearch -m avcコマンドを確認。
authorized_keysのアクセスが拒否されているので確かにSELinuxの問題があったことがわかります。
type=AVC msg=audit(1696315292.258:1446): avc: denied { read } for pid=446534 comm=“sshd” name=“authorized_keys” dev=“dm-0” ino=201836096 scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0
現在、authorized_keysのコンテキストは期待通りunconfined_u:object_r:ssh_home_t:s0となっているけど、問題が起きていたときは、unconfined_u:object_r:default_t:s0 だったことがわかります。
詳しい経緯はわからないけど、.ssh/authorized_keysを作成した時点でopenssh用のselinuxポリシーが適用されていなかったと考えられます。
その後なにかのイベント(再起動?)でrestorecon 相当が行われて、コンテキストがssh_home_tに変更され問題は解消した。
なんだかよくわかないけど、OSのマイナーバージョンアップで微妙にセキュリティコンテキストが変更されてrestoreconすると解決する、ってのは時々起きてますね。
たぶんopensshインストール前にrsyncしたのでコンテキストがdefault_tになってたんじゃないかと。なかなかの罠ですね。

おそらく lvm の論理ボリュームのバックアップ/リストアに rsync -a を使った (本当は cp -aの方がよい) ことによる問題ではないかということ。私が報告した状況と selinux のログからすぐ助言できるのが素晴らしいと思う。まだまだ私のインフラエンジニアとしての未熟さを実感した瞬間でもあった。一昔前は selinux は disabled にするものという常識だったが、最近は初期設定で動くようになっているのでなるべく selinux は有効にして運用するものという意識に変わってきているらしい。

インフラの式年遷宮

1時に寝て何度か起きて5時に起きた。それからだらだらして寝てまた7時に起きた。

テスト環境の再整備と rootless コンテナ

インフラの式年遷宮のようなことをしていて、テスト環境をリファクタリングして再整備していた。これまで root でコンテナを実行していたが、最近は rootless コンテナがセキュリティ強化の観点から望ましいということで次のドキュメントをみながら設定した。

設定はとくに難しくないが、dockerd や containerd の起動を systemd のユーザーインスタンスに依存することになる。systemd のユーザーインスタンスは基本的にユーザーがログインしたときに生成されるものなので OS が再起動したときなどに困る。OS 再起動時にも systemd のユーザーインスタンスを生成するには linger という仕組みを有効にすればよいらしい。systemd –user の扱いと linger のことまで理解していれば、たぶん大丈夫なのかな?これで運用がうまくいくことを祈りたい。

$ sudo loginctl enable-linger ucidm

初めて lvm を操作してみた

0時に寝て何度か起きて7時に起きた。最近は寝る前にはてブのアプリで適当に記事を読みながら寝ることが多い。

隔週の雑談

顧問のはらさんと隔週の打ち合わせ。今日の議題はこれら。

ここ1-2週間ぼーっとしていて、忙しくもなく、なにかやっているわけでもないけど、のんびり過ごしている。軽いバーンアウトだと思う。先週末は休みも取った。「hugo のテンプレート作り」のような新規開発を、どこかのもくもく会やイベントに行って、その場で集中してやったらいいんじゃないか?というアドバイスをいただいて、確かにそういうやり方もよいように思えた。今週末は課題管理のコンテンツを考えて、できればブログに書いてみようと思う。

lvm の論理ボリュームの結合

新規に almalinux 8 で仮想マシンを作った。デフォルト設定でインストールしたら //home でパーティション分割されていて、これは使い勝手が悪いなと思ってパーティションを結合することにした。

$ df -h
ファイルシス               サイズ  使用  残り 使用% マウント位置
devtmpfs                     1.9G     0  1.9G    0% /dev
tmpfs                        2.0G     0  2.0G    0% /dev/shm
tmpfs                        2.0G  8.6M  2.0G    1% /run
tmpfs                        2.0G     0  2.0G    0% /sys/fs/cgroup
/dev/mapper/almalinux-root    70G  6.5G   64G   10% /
/dev/mapper/almalinux-home   437G  5.0G  432G    2% /home
/dev/vda1                   1014M  221M  794M   22% /boot
tmpfs                        393M   12K  393M    1% /run/user/1000

基本的には次の記事をみてやったらうまくいった。

/home をバックアップする

# mkdir /home-bkup
# cp -a /home/ /home-bkup/

emergency モードに入る?

# systemctl emergency

結合したい領域を unmount して、home の論理ボリュームを削除する。

# umount /dev/mapper/almalinux-home
# lvremove /dev/mapper/almalinux-home
Do you really want to remove active logical volume almalinux/home? [y/n]: y
  Logical volume "home" successfully removed.

バックアップからデータを戻す。

# cp -a /home-bkup/ /home/

/etc/fstab から不要なパーティション設定を削除する。

# vi /etc/fstab
...
/dev/mapper/almalinux-home  /home  xfs  defaults  0  0  # <- この行を削除
...

root の論理ボリュームに余っている領域を拡張する。

# lvextend -l +100%FREE -r /dev/mapper/almalinux-root
  Size of logical volume almalinux/root changed from 70.00 GiB (17920 extents) to <507.04 GiB (129802 extents).
  Logical volume almalinux/root successfully resized.
meta-data=/dev/mapper/almalinux-root isize=512    agcount=4, agsize=4587520 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=0 inobtcount=0
data     =                       bsize=4096   blocks=18350080, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=8960, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 18350080 to 132917248

この時点で1つの領域に結合されたことがわかる。

# df -h
ファイルシス               サイズ  使用  残り 使用% マウント位置
devtmpfs                     1.9G     0  1.9G    0% /dev
tmpfs                        2.0G     0  2.0G    0% /dev/shm
tmpfs                        2.0G   78M  1.9G    4% /run
tmpfs                        2.0G     0  2.0G    0% /sys/fs/cgroup
/dev/mapper/almalinux-root   508G   14G  494G    3% /
/dev/vda1                   1014M  221M  794M   22% /boot

バックアップを削除する。

# rm -rf /home-bkup/

マシンを再起動する。

# reboot

これで問題なければ完了。

また podman に苦戦する

23時に寝て何度か起きて7時に起きた。出張帰りでなんかバテててなにもせず休んでいた。少し喉に引っかかりがある。出張で飲み歩いたし、そろそろコロナ感染?の疑いをもって生活してみる。

podman と dbus-daemon とsystemd の調査

2次開発の成果物をドッグフーディングの目的で社内へ導入する。メンバーが作業していて nginx が正常に動作しないという。ログをみろとすぐにコンテナネットワーク内の dns サービスが正常に動いていないということはわかった。podman は aardvark-dns というサービスを使って dns を管理する。但し、このサービスがまだまだ安定していなくて不具合があるのを以前にも確認した。このサービスの振る舞いがよく分からなくて、意図しない状況や状態に対して正常に動作してくれない。

他にも調査をしていて rootless で podman コマンドを実行すると次の issue で書かれているようなワーニングが出力される。dbus-user-session というパッケージを導入すれば解決するとある。

dbus-daemon のサービスは systemd で動いていて、systemd のユーザーモードと dbus が正常に動いていないというところまではすぐに分かった。その状態だと rootless な podman が正常に動作しないということもすぐに分かった。ここまではすぐに調査できたが、問題はどうやれば sytemd のユーザーモードを dbus を正常に動くように復旧できるのかがまったく分からない。systemd がそもそも難しいのに、そのユーザーモードは権限管理が関係するのでさらにもっと難しい。1日調べてお手上げで他の社員さんにも相談してみた。

今日は自分の作業は進捗しなかったけど、メンバーの作業の進捗をみていて、メンバーがはまっていたところを助言して、その問題は解決してうまくいって、それだけで満足していた。

msgraph-sdk-go のビルド問題

1時に寝て何度か起きて7時に起きた。昨日は少し早めにお仕事を終えて家で休んでいたので少し回復した。

msgraph-sdk-go を使った開発

昨日の続き 。前日に作ったマージリクエストをチームのメンバーにレビューしてもらっていくつか修正して、マージを終えた。一段落。

さらにこの sdk を使うことで8月の前半に開発していた差分比較のところも変更しないといけないことに気付いた。public な構造体のメンバーにアクセスして差分比較する処理を実装していたが、この sdk は getter で構造体のメンバーにアクセスしないといけないことに気付いた。reflectoin の処理に追加で実装を入れるだけなのでそんなに難しくはない。そういった修正をしていたら1日終わってしまった。開発していると時間が過ぎるのは早い。

たまたま ci/cd ジョブの実行時間の上限を10分にしていて超えるときがあってジョブが失敗した。 調べてみると、msgraph-sdk-go の api が巨大過ぎてメモリを浪費したりコンパイルに時間がかかったりするという issue をみつけた。

私のローカル環境で測ってみると、約36秒で完了していたテストが2分23秒かかるようになっていた。テストの実行が4-5倍ぐらい遅くなった。さらにコンテナイメージのサイズは 36 MiB から 109 MiB と3倍ほど増えた。無駄に開発を遅らせる環境要因になっているのでこれは別途調査して対応しないといけないことに気付いた。