理想の働き方について

共著ブログ私信電信、今回のテーマは「理想の働き方」

理想の働き方と聞いて、働く上での姿勢と作業環境の2点が思い浮かんだ

働く上で大事にすること

¬ 友情・努力・勝利

これは解説すると「{信用,信頼} しない」「努力と感じることをしない」「終わりがない」と言う話

{信用,信頼} しない

一つ目は言葉通りだが、例えば

  • システムを組む上で人間を使う限りはミスや悪意を受容する。
  • 実績や過去の功績でコードやアーキテクチャに関する評価を決めない。
  • 自分が書いたコードはバグなく動くという誤った認知を持たない。

Trust But Verifyが言葉として近いかもしれない

ちなみに「信用と信頼は違ってTrustは信頼で〜」みたいなこと言うてる人間よくおるけど、日本にそんな文化存在せんから嘘やとおもてる。あるのは誰が腹を切るか決める文化だけ。まぁもっと最悪なのは腹切ることを責任と勘違いしている人間。

努力と感じることをしない

二つ目は、個人と仕事の話があって意味が若干違う。

個人の話は学習順序かな

たいして興味ないことに対して義務感で勉強するのはやめたほうが良い。精神に悪いし身につかない。 当然なんでも知っているに越したことはないが、興味が湧かない理由の一つに学習する上での前提として必要な経験や知識がまだ自分に足りていないんだな、と思っている。 そもそもその分野に興味がないなら時間は有限なので辞める。

仕事の話は、姿勢というか心掛けで

単に業務上必要な学習はコードを書く時間と比べてなんら変わらないただの"仕事"なので、いちいち努力と分けて考えない。

そもそも努力っていう言葉自体が僕自身の中で「行動の意図を理解しないまま頑張る」みたいな意味になってるかもしれん。

終わりがない

これはソフトウェア開発サイクルに終わりはないのでExitしようが開発は続く。"終わり"を前提としたソフトウェア開発は"終わり"より早く破綻する。

「これ、ちょっとの間しか使わないんで適当で」って作られたJobはそれが災厄を引き起こすまで動き続けるし、仮説検証のためのプロトタイプは大体書き直されることはない。

「だからちゃんと設計しよう」ではなくて「後悔しない意思決定にしとこう」みたいな話、終わりはないので。

「他に得意な言語はあるけど、聞いた感じ開発早そうなんでRailsで!これが適材適所!」

正気か?

作業の環境

音楽がかかっていると良い。「アトモスフィア;かかっている」が大事で自分でセレクトした曲が流れるのは好きじゃない。 音楽がかかっていないと?なんか気が散る感じがする。他人の気配とか話し声とか。 そもそも気は散るものなので散る対象が音楽に限定されるのが良いんかもしれない

歩き回れる方が良い。 癖かもしれないし慣れかもしれないが、思考と体の動きが動きが相関している気がする。

椅子はいい方がいい。今年に入ってherman millerのエンボディを買ったがかなり良かった。 ただ自宅がカフェとかに比べてひらけてない(=オープンでない=Not 鴨吻)ので、そこは不満

猫。 猫はストレスを極めて減らしてくれるが、仕事中に構って欲しがってくるので集中できない。危険

f:id:hiroqn:20211027192039j:plain

安易なSaaSのユーザー数課金は体験が最悪

サマリ

  • ユーザー数が増加しても、顧客の感じる価値が線形に増えない。
  • Entityに対して情報が公開されている範囲の制限できる場合、一部のユーザーはほとんど価値を感じていないが課金されている状態になる。
  • 全体のリソースはユーザー数に対して時間で積分した量になるので、ユーザー数が増えれば増えるほど価値を感じていない人間が増える。

ユーザー数課金をしているいい例

Slack

馬鹿みたいにprivate channelを作る会社でなければ、一人のユーザーに対して情報が制約されている状態にはほぼならない。 そもそも、一人の人間のとりうるコミュニケーション量は上限がある(と思われる)ので、でかい企業と小さい企業で一人のユーザーが体験する価値は(多分)変わらない。 また、guest などの機能はまともに使っていると実質無料でついてくる。

KING OF TIME

理由:(略)

これは労務管理している側と勤怠つけるだけ側に分かれるので、admin側ユーザ課金+一般ユーザー課金でもいいと思ったがユーザ課金だけらしい。

微妙な例

Google Worksapce

機能が多いのはいいことだが、会社全体でHardUseしていない場合、例えばインターン生のメールアドレスだけ発行したい場合などに高いなと感じる。

Entityに対して情報が公開されている範囲の制限できる場合、一部のユーザーはほとんど価値を感じていないが課金されている状態になる。

悪い例

読者(およびサービスプロバイダ)の課題とする

後書き

ビジネスの話はしていない。課金に対する体験の話をしている。 金を払うという行為は納得していないと体験として悪いと考えている。 例えば、時価で提供している飲食店もそうで注文した際に金額がわかっていればその時点でまずかろうが金を払うことに納得はしているが、後から金額がわかることは微妙と考える(特に美味しくなかった場合)。

最近おもしろかった漫画( 7月~)

これは何?

最近読んで良かった漫画 | 私信電信

概要

ざっくり7月〜で読んだ本、一旦書き出して振り返ってみる Primeの特典とかkindle unlimitedで読んだ本で特に印象に残らなかったものは省いている

八百森のエリー 1~5

野菜市場の仲卸の漫画、仲卸って流通の間に挟まっているなにか 、みたいな認識だったけど色々やってるんだなぁみたいな気持ちになった。 野菜界における「重版出来」的ポジションの漫画、雑誌移転により一瞬止まっていたぽい

ブラック・ラグーン(12)

最初に読んだのは高校生の頃だろうか、久々に新刊が出て懐かしい気持ちになった。 "ブラック・ラグーン"であることに間違いはないが、なんか雰囲気が変わったというか馴染みの定食屋でいつも頼むメニュー的な?。作品の年齢より作者の年齢の方が早く進みますからね... BUMP OF CHICKENで言うとユグドラシル以降という感じ。

山賊ダイアリー

一度猟に行って見たいなぁと思ってはいるが銃の免許をとるのは(面倒さの)ハードルが高い 脱サラして猟師なった人のエッセー的な漫画なのでイメージがつきやすくて良いね

来世ではちゃんとします 7

あずまんが形式の(今時4コマで話が進むのが当たり前なので今更こういう言い方はしないのだろうか?)"""現代的な価値観の"""恋愛漫画 登場人物は多いが話が独立しているので読みやすい

クマ撃ちの女

なんかちょっとDirtyな部分も描かれているが、実態はもっとDirtyなのかもしれない。 取材漫画的な感じだけど、どこまで事実なんだろう

ランウェイで笑って(22)

完結しちゃいましたねぇ(ニチャァ(略 カエルDXの絵

よかったですね

違国日記

普通の(ここでの普通さとは社会性の高い人間が自己を正当化する上で使うもの)女子高生が、非健常者の(ここでの健常者は自己の健常さを自己の定義する健常性から定義するもの)家で、"""コミュニケーションの仕方"""を学ぶ

これは結構良くて〜なんか距離感的な〜(言語野が壊れた)

東京入星管理局

設定が飛ばしすぎてて難しいけど、スピード感ある

サイバネ飯

上と同じ作者、こっちの方が好き

読切いろいろ

山本先生いいですね〜

昭和元禄落語心中

シュッと読む分には面白いが、が、作者の嗜好との違いによる引っ掛かりが。ネタバレになるんで書かないが、「腐系の方ってこういうことするよね〜〜??」ってなるアレ。わかりますよね?

メイドインアビス(10)

新刊が1年ペースなので、また1年待たねばならんのか... 出てくるキャラクターが可愛いので好きです。あと作者とのシナジーがある。

JKハルは異世界で娼婦になった

異世界転生俺TUEEメタ作品、テーマであるところの娼婦が生かせてないように感じた。倉科遼っぽく書いてもウケないのはわかるが。

Artiste

いい人が出てくるいい話、料理漫画ではない、好き

衛府の七忍

誤チェストでごわす、の本

10巻読んでもどういう世界観なのかわからない

この世界は不完全すぎる(4)

SAOの世界でデバッガが閉じ込められてしまいました、みたいな話。 職業柄、親近感があるのでいいですね

葬送のフリーレン(5)

この漫画読んで最初に思ったこととして「こういう叙事詩?的な漫画って増えてる感じするよな〜メタが進んでる的な〜」 今の時代に物語を描きたくても例えばタイの大冒険みたいに「魔王を倒す過程を描きます」を描いてもウケないのはわかる。 傘でアバンストラッシュしたよね?みたいな前提で話を作ってるよね。

AV男優はじめました

そもそも自分は業界の話みたいなのが好きなんすよね〜 映像作品とかだとドキュメンタリしか見ないし、その中で汁男優からAV男優やります!っていうのは新しいかなって

BEASTARS 22

なんかこういう設定の作品って多いよね?共存できない存在が頑張って共栄する的な

この作中でいう草食動物や肉食動物は我々の世界でいうソレらと実は違ってメタファー的な存在なんだけど、現実世界の存在とメタファー存在の境界を曖昧にぼかしていることにより作品への没頭感というか親しみやすさを与えているのがすげーうまいなって思った。 作者の性癖が強く出ているが、その点も曖昧にしちゃってるんで凄いですね、パワープレイしていますね。

抜刀(1)

なんか荒いけど攻めてて面白いが次の巻は買う決断に至らなかった、続きが気になるかというと?

運用中のS3を暗号化する話

概要

"""社会"""にはいろいろあるので、運用中のS3を暗号化しました

HERPの話です。採用してます。

careers.herp.co.jp

ざっくり以下の内容(+ S3 Bucket Key)をやった、という感じです

Encrypting objects with Amazon S3 Batch Operations | AWS Storage Blog

制約と方向性

ここでいう暗号化はSSE(Server Side Encryption)です

AWS Key Management Service (SSE-KMS) に保存されている CMK でサーバー側の暗号化を使用してデータを保護する - Amazon Simple Storage Service

S3の暗号化はオブジェクトごとなので、暗号化済みオブジェクトとそうでないものが混ざったBucketに対して権限さえ適切であれば問題なくR/Wすることができます。

ちなみに鍵の指定方法として

  • Amazon S3 が管理する暗号化キー
  • AWS 管理の CMK
  • カスタマー管理の CMK
  • 持ち込みの暗号化キー

がありますが、今回はカスタマー管理のCMKにすることにしました。SSE-KMSです。

カスタマー管理のCMKはクロスアカウントできるとか、キーロテーションの期間を変更することができるとかのメリットがあります。

なので、今回の適切な権限はアプリケーション側が使用している権限に以下が追加されることを想定しています

        {
            "Action": [
                "kms:GenerateDataKey",
                "kms:Decrypt"
            ],
            "Effect": "Allow",
            "Resource": [
                "なんか鍵"
            ]
        }

2020年ごろに S3 バケットキーという感じの機能が追加されて、R/WのたびにKMS使用コストがかかっていたのが不要になるのでそっちを使います

Amazon S3 バケットキーを使用した SSE-KMS のコストの削減 - Amazon Simple Storage Service

KMS キーポリシーが適切なPrincipalに対して kms:Decrypt が許可されているのを確認します。クロスアカウントでなければ問題ないはずです。

余談ですが、Principalが s3.amazonaws.com でなくていいんすね。ここら辺のPrincipal感覚はあまりわかっていないですね。

フロー

というわけで、以下のフローでやります

  1. アプリケーションに上記の権限を足して、デプロイする

  2. BucketのSSEを有効にする

  3. 暗号化されていないものを暗号化する

BucketのSSEを有効化

terraformの擬似コードですが、以下のようになります

resource "aws_kms_key" "this" { }

resource "aws_s3_bucket" "this" {
  bucket = "example"
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        kms_master_key_id = aws_kms_key.this.arn
        sse_algorithm     = "aws:kms"
      }
      bucket_key_enabled = true
    }
  }
  versioning {
    enabled = true
  }
}

暗号化されていないものを暗号化する

Objectを再Putすると暗号化されます。 最近はs3 batchと呼ばれる便利なものがあるのでそれを使います

inventory 設定

s3 batchを実行するためにkeyのリストが必要なので s3 inventoryを使います。

s3 inventoryの実行結果を保存するBucketを用意します。

resource "aws_s3_bucket" "s3-batch" {
  bucket        = "example-s3-batch"
  force_destroy = true
  policy        = <<EOF
{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Effect": "Allow",
      "Principal": {
          "Service": "s3.amazonaws.com"
      },
      "Action": [
          "s3:PutObject"
      ],
      "Resource": [
          "arn:aws:s3:::example-s3-batch/*"
      ],
      "Condition": {
          "ArnLike": {
              "aws:SourceArn": "arn:aws:s3:::*"
          },
          "StringEquals": {
              "aws:SourceAccount": "${アカウントID}",
              "s3:x-amz-acl": "bucket-owner-full-control"
          }
      }
    }
  ]
}
EOF
}

s3 inventoryの設定は以下のようになります

resource "aws_s3_bucket_inventory" "auth" {
  bucket                   = aws_s3_bucket.this.bucket
  name                     = "exapmle"
  included_object_versions = "All"
  optional_fields          = ["EncryptionStatus"]//, "BucketKeyStatus"
  schedule {
    frequency = "Daily"
  }

  destination {
    bucket {
      format     = "CSV"
      bucket_arn = "arn:aws:s3:::example-s3-batch"
    }
  }
}

このコメントアウトされているBucketKeyStatus部分はBucket Keyで暗号化されているかのステータスが取れるので本当は欲しいんですが、terraformのaws providerで対応されていないのでterraformでやりたければ諦める必要があります。(今週末時間があれば修正したいな...)

inventory結果

24~48時間程度たつと、結果がexample-s3-batchに保存され始めます。 Dailyでどのタイミングのリストかわからないので、余裕を持つ必要があります。 X日にSSEを有効にしていた場合、X+2日の日付のを使うぐらいがいいんじゃないでしょうか。

s3 batch

s3 batch実行用のRoleを作ります

Granting permissions for Amazon S3 Batch Operations - Amazon Simple Storage Service

上を参考にしますが、ブログ用に書き直すがめんどくさかったので、サンプルのコードではs3の任意actionを許可しました。 kmsの権限を足すことを忘れないように

resource "aws_iam_role" "s3-batch" {
  name               = "s3-batch"
  assume_role_policy = <<EOF
{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Effect":"Allow",
         "Principal":{
            "Service":"batchoperations.s3.amazonaws.com"
         },
         "Action":"sts:AssumeRole"
      }
   ]
}
EOF
}

resource "aws_iam_role_policy" "s3-batch" {
  policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:*"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::*"
        },
        {
            "Action": [
                "kms:GenerateDataKey",
                "kms:Decrypt"
            ],
            "Effect": "Allow",
            "Resource": [
                "*"
            ]
        },
    ]
}
EOF
  role   = aws_iam_role.s3-batch.id
}

実行していきます。s3 inventoryから出力されたcsvからs3 batchを積むスクリプトが以下になります。適宜環境変数は埋めましょう。 わかりにくいですが、envはs3 inventoryのname属性になります。

manifest_bucket=
env=
target_bucket=
date=

# manifest.jsonにcsvのpathが入っている
target_bucket_arn=arn:aws:s3:::$target_bucket
key=$(aws s3 cp s3://$manifest_bucket/$target_bucket/$env/$date/manifest.json - | \
jq -r '.files[].key')

# Amazon S3 Selectを使って暗号化されていないobjectのpathだけ取得する
# s._4が isLatest s._6がEncryptionStatus
aws s3api select-object-content \
  --bucket "$manifest_bucket" --key "$key" \
  --input-serialization 'CSV={},CompressionType=GZIP' \
  --output-serialization 'CSV={}'\
  --expression "select s._1, s._2 from s3object s where s._4 = 'true' and s._6 = 'NOT-SSE'" \
  --expression-type SQL $env-output.csv

csv_key=$env/output.csv

# なんかs3に上がってないとダメなんでアップロードする

aws s3 cp $env-output.csv s3://$manifest_bucket/$csv_key

etag=$(aws s3api head-object --bucket $manifest_bucket --key $csv_key | jq -r .ETag)

# s3 batchのJobを積む
aws s3control create-job \
    --region ap-northeast-1 \
    --account-id "$AWS_ACCOUNT_ID" \
    --operation "S3PutObjectCopy={BucketKeyEnabled=true,TargetResource=$target_bucket_arn}" \
    --manifest '{"Spec":{"Format":"S3BatchOperations_CSV_20180820","Fields":["Bucket", "Key"]},"Location":{"ObjectArn":"arn:aws:s3:::'$manifest_bucket/$csv_key'","ETag":'$etag'}}' \
    --report "Bucket=arn:aws:s3:::$manifest_bucket,Prefix=s3-batch-reports,Format=Report_CSV_20180820,Enabled=true,ReportScope=FailedTasksOnly" \
    --priority 42 \
    --role-arn "$ROLE_ARN" \
    --client-request-token $(uuidgen) \
    --description "$env" \
    --no-confirmation-required

operationのoptionに BucketKeyEnabled=true が含まれているんですが、S3 Bucket Keyが有効である場合このオプションなしで動くと思っていたんですが、つけないとダメでした。

このオプションなしだとS3 Bucket Keyなしで暗号化されます。

最初、kms のkey policyのPrincipalにs3 batchが含まれていないことが原因かと思ったのですが、そこそこ試した結果kmsのkey policyは関係ないと判断しました。

AWS有識者の情報をお待ちしております。

確認

暗号化されているか確認するために後日再びS3 Selectを使って確認します

select s._1, s._2 from s3object s where s._4 = 'true' and s._6 = 'NOT-SSE' の結果が空であれば全ての暗号化が完了しています。 現状Objectを上書きする運用をしていないので、今回s._4を見る必要がない気はします。 BucketKeyStatus を有効にしてあれば、s._7 も確認すると S3 Bucket Keyが使われているか確認することができます。

再掲

careers.herp.co.jp

上記の内容はConsoleをぽちぽちしていてもできると思いますが、HERPでは仕事の完了の定義の中にコード化することを含めています。

OSSへの貢献

私信電信(https://shishindenshin.vercel.app)、二回目のテーマは「OSSへの貢献」

1

自分は厳格なFreeSoftware 主義者というほど極端ではないかもしれないがそれよりだと思う。

今まで過程を考えると、高校までまわりにプログラミング言語と英語の区別もついてない田舎でインターネットの情報を頼りに勉強するしかなかったので、OSS特にJavaScriptがメインとなっていく。 そのうちWebFrontendを特に専門に仕事を始めるがこれもOSS無くして成り立たないわけで(最近はSREをやっているがこちらもOSS無しでは成り立たない)、

そういった環境で生きてきたことからOSSに還元すべきという考えに至るのは当然のように感じる

2

とはいえOSSに貢献するということはめちゃくちゃ難しく感じるが、それは難しく考えすぎているのだと思う。

貢献の仕方として例えば、「GitHubのIssueの中からバグや不足している機能を探してきてPRを作成してmergeする」というものがあるが、 このレベルのものはこれが解決しないと業務が進まない事象に直面してようやくできることで、そもそも詳しくないと無理。 「なりたい職業?そうですねぇ。不動産収入の不労所得で暮らしたいですねぇ」ぐらい夢。

だからもっと簡単をする、バグ報告とかドキュメント書くとかブログ書くとか勉強会で{発表,参加}するとかtwitterするとか。 OSSの中の再頒布の自由に近いかもしれないけど、情報を頒布して自由な技術を広めるのもは貢献という意味でも価値が高い。それも気力がいる。

だからもっともっと簡単できて、少しでもOSSに対して貢献できるように大事にしていることは

「わからないことを聞く」「聞かれたら答える」

そもそも人が何をわからないかってわかんないんで、自分がわからないこと、という情報を広めるのは大事。 それと同様に聞かれたら答える。答えたことをブログに書くとかすればベストだけど、一人増えるだけでも良いかなと。

ヒヤリハットハインリッヒの法則に近いところはあるかなって思っていて、一件の重要なPRは300件の"わかんない"からみたいなね。

3

ちょっと別の話にはなるけど、OSSの開発者が十分な報酬を受けていないというのは「まぁそうだよね〜〜」って感じで今の会社の方でもスポンサーするにはしているけど(以下のリンク参照)金額の妥当性みたいなところは難しい

github.com

いろんなOSSにスポンサーしてる時雨堂とかはすごいなって思う

4

ちなみに自分のここ最近のOSS活動は「NixOSをmac book pro(16.1)で動かす」ということをテーマに空き時間にやっているが、去年の冬ぐらいからやっていてあんまり時間を避けていなのはあるが進捗が乏しい

その活動の中で若干反省があって、

とあるドライバのための以下のnixファイルを書いたんだけど、本家の方にPRを送っていなかった。正直自分しか使わないと思っていたのもあるが、完成してから出そうとしていた

github.com

ところが、その後にPRを送った人がいてmergeされていた。

github.com

最終的にこっちの方が良くできているから結果としては問題ないんだが、これは本当に良くなかったなって、もっと行動をちゃんと起こすべきだなって反省している。

5

本当に難しいことはApex Legendsに割いている時間をその活動に日々割くことだ。 つまりはモチベーションの維持ということだが。

実際、競技プログラミングって採用時にどうよ?

これは?

私信電信という共著ブログ(?)を友人たちと始めた。

今回「実際、競技プログラミングって採用時にどうよ?」というお題で書く

現状の解説

実際今いる会社ってHRの会社なので、採用側の視点で。

会社の規模はエンジニアが15人ぐらい(全社員で40人中)

採用時のフローは、 カジュアル面談→技術面接→社長面接→トライアル(最近はあんまやってない)

ちなみにトライアルは業務委託契約で1~7日ぐらい既存の課題を手伝ってもらう感じで、互いの負担は大きいがミスマッチは防ぐのが目的でやってる(やってた?)

今のところコーディングテストみたいなのは導入してない。

現職であるところの株式会社HERP では全社員で採用に取り組む「スクラム採用」を推していて、エンジニア全員が面接に出たりする。 面接も出るけど、最近はカジュアル面談をやることの方が多い。

余談だけど、面談した人の面接は出ないようにしている。以下のような理由。

  • ジャッジしない体で話を聞いた後にもう一回ジャッジする体で話を聞くのはなんか違う
  • アニメもそうなんだけど、性格的に2回目はかなり興味が薄れている

そういえば、構造化面接みたいなことは一瞬やろうとしてたけど結局やってなくて、面接の評価が構造化されているわけではない ジュニアかシニアみたいな区別は今のところ明確には無くて、業務経験のある「ある程度できる人」を採用する感じになってる気がする

競技プログラミングどう?

競技プログラミング関係なく趣味がエンジニアリングに関係することはかなりプラスよね。 土日(平日の夜とかも)の時間の使い方として何かしらやっている人の方が評価されるのはそらまぁ。

競技プログラミングの特性として、コンテストとかへの参加というわかりやすい形で残るのは評価しやすそう。OSSとかに貢献しようとしても土日そのコードを読んでいるだけだと形としてはのこんなかったりするからね。

余談ですが、最近とあるOSSに自分の書いてたコードの上位互換みたいなのがmergeされてて悲しかった(単純にプロジェクトの途中だったのでPRを出していなかった)

これらはあくまでやってるかどうかっていう話なんで、年齢が上がるにつれて可処分時間は減る気がしてて難しい問題ですね、今と比べると大学生のときはめちゃ時間あったので。

とはいえ、転職のために別に趣味でもない競プロやるっていうのはもったいないよね、時間の使い方として。 いい会社に入るためにいい大学に入るために勉強するみたいで、つまらん上にけしからんですね。

転職のために、業務委託でやっていた会社のコードをGitHub上にあげちゃうのも、けしからんですね

今後、コーディングテスト(面接)する?

自分はした方がいいと思っている。 けど、会社の人材要件定義に合うような問題を作るコストがデカくね?みたいな感じになっててやってない気がする 弊社だと、やるとしたらHaskellの型合わせ問題を解くとか特定の言語のサブセットのパーサーを作るとか、フロントエンドだったら簡単なアプリケーションを用意して改造してもらうとかになりそう

既存サービスについて

とはいえ問題を作るのがめんどいので、既存のサービスを使うというのはある。 けど、プログラムがほとんどできない人に対しての足切り的な使い方になちゃうんじゃないかな 競プロの難しい問題が解ける能力を採用時の評価の上で差をつけれないと思う。

AさんとBさんどっちを取りますか?っていう話になった時に、現状カルチャーフィットの方が重視されてる。

今後応募が増えてきた際に使うことはあるかもしれないけど、必要になるほど応募が来るのか?

採用、募集して〼

careers.herp.co.jp

CockroachDB壊れちゃった話

概要

社内で使っていたツールのDatabaseに実験用途でCockroachDB(v20.1.3)を使っていた。構成は以下となる。

AWS EKS1.6上にStatefuleSetで3Podで運用。StorageClassはEBS gp2(kube masterのin treeの中にある実装)のPVでデータを保存」

実はこの構成はそこそこ問題があって、Nodeの入れ替えなどでPodの再配置が起きた際に過去のPVと新しく配置されたPodのAZが一致しないとStatusがPendingになりコンテナが作られない。 これはAWSのEBSがAZを跨げないためであるが、 kube1.7以降の環境でVolume Binding Modeを WaitForFirstConsumer にして、CSI Driverがいい感じであればうまく行くという説がある(参照:Storage Classes | Kubernetes) これは、あんまり興味がない点だったので認識が間違っていて嘘の可能性もある。

そんなこんなで、PendingになったPodを動かすためには以下の2通りのオペをする必要がある。

  1. Podを削除して、過去のPVと同じAZに配置されることを祈る
  2. PVかPVCを消すなりして、新しいPodに新しいPVが作られるようにする。

ただ、2のオペレーションをした場合はデータが消えるので、CockroachDBの新規のNodeとしてClusterにJoinすることになる。

経緯

実は詳細な原因が特定できていないので、省かせてもらうがNodeの入れ替え作業中に """いろいろあって"""Clusterが起動しなくなってしまった

以下は現在わかっていること

X日の15:00(JST)ごろに入れ替え作業をして一旦は動いていた

16:00ごろまで以下のログが出始める。

W210126 07:17:43.388615 906 server/node.go:830  [n2,summaries] health alerts detected: {Alerts:[{StoreID:2 Category:METRICS Description:ranges.underreplicated Value:11}]}

上記のWarningが出ている状態でなんらかの原因で再起動がかかり、

server drained and shutdown completed

おそらく正常に終了はしたが、他のPodも以下の状態になってしまう

W210126 07:18:57.177231 201 kv/kvserver/node_liveness.go:488  [n2,liveness-hb] failed node liveness heartbeat: operation "node liveness heartbeat" timed out after 4.5s

17:00(JST)ごろアプリケーションが動いていないことで気づく

エラー内容はこれに近いように感じた。

forum.cockroachlabs.com

色々と修正しようと頑張っている内に以下のエラーを吐くようになった。

W210126 13:32:11.928294 156 kv/kvserver/store.go:1631  [n2,s2,r6/3:/Table/{SystemCon…-11}] could not gossip system config: [NotLeaseHolderError] r6: replica (n2,s2):3 not lease holder; lease holder unknown
W210126 13:32:12.743191 127 kv/kvserver/replica_range_lease.go:554  can't determine lease status due to node liveness error: node not in the liveness table

現在振り返って考えると17:00ごろはなんとかなったかもしれないが、21:00ごろから上のエラーがで始めた時点で厳しい感じがする。(=よくない操作をした)

データ復旧に関して

CockroachDBは様々な方法でバックアップやデータのdumpができるようになっているが、Clusterが起動している状態でないできない。

上のVersionでは内部のストレージ部分にRocksDBを使っているので(最近のVersionはPebbleになっている)RocksDBと向き合いながら頑張ればデータを復旧できるという説がある。自分の認識では理屈上2Nodeのデータがあればいいはず

今回はデータは捨てる判断にしたが、大事なデータを保存していてバックアップもとっていない人はチャレンジするための資料を置いておく

Goを使ってRocksDBから復旧を試みる

sudonull.com

データ構造に関しては、以下のスライドが参考になる

ccvanishing.hateblo.jp

以下のソースコードのコメントもデータ構造に関してわかるかもしれない

github.com

余談

ちなみにcockroach debug rocksdb でデータを直接操作することができる。

cockroach debug rocksdb scan でK/Vっぽいものを取得できるが、cockroach debug rocksdb get KEY_NAME にscanした結果のkeyを使うことができない。

あまり理解していないが、cockroach debug rocksdb scan は CockroachDBの内部でてくるKey (例:/Local/Store/gossipBootstrap) で、RocksDB側で使われているKeyは別のbinary表現のkeyに変換しているようだ。RocksDBの私が理解していない機能を使っている気がする。

なので、 cockroach debug rocksdb scancockroach debug rocksdb scan --hexvalueを比較することで、同一のkeyを取得することができ、cockroach debug rocksdb get --hex HEX_KEY_NAMECLIから値を操作することができる。

cockroach debug rocksdb scan はほとんどデータがないはずのDBから数GBのファイルを生成してくるので、地獄みたいな作業になる。

RocksDBの操作はかのブログで雰囲気を察することをお勧めする

www.jianshu.com