メモ - RyuSA

技術的なメモ書きとか試してみたこと

大神ミオさんのソロライブ(Our Sparkle)に応援広告とフラスタを贈った忘備録

轍を残す意味も兼ねて、推し活における応援広告とフラスタに関して主催者目線での忘備録を書いておこうと思います。今後、応援広告やフラスタやろうとしてる人の何かしらの糧になれば……

大神ミオさんのソロライブ Our Sparkle を応援するため、盛り上げるために応援広告とフラワースタンドを贈りました〜!!🎉🎉

一応メンバーが増える可能性を考慮して「ミオファの森の盛り上げ"隊"」という名義で活動していましたが……うん、ひとり部隊でしたね。(絵師さんたち入れていいなら3人部隊!)

かかった費用大公開

まず気になるであろう費用感について。気になるものは先出ししていくスタイル。イラストやデザインなどの個人間取引の費用は個人情報なので非公開ですが、他の部分についてはまとめておきました。参考までに。

応援広告

  • 広告枠
  • ポスター
    • 仮印刷(B3 4枚) 8800円
    • 本印刷(B0 3枚) 24000円

計 21万円ちょっと

ポストカード スタードリームFS クリスタル 209kg マットPP 角丸加工 箔押し加工 3万円ちょい

フラワースタンド

  • フラワースタンド本体 66000円
  • パネル
    • 本印刷(B3 耐水紙 UVマット カットライン作成 3枚) 10000円

計 8万円いかないくらい

累計は……おっと?意外といったな(白目)

応援広告編

この辺りを一通りまとめておいたドキュメントがこちらであります。(ただしLLM用) 参考にしてみてください。ざっと読むとどんなタスクが出てくるのか何が必要になるのかわかると思います。(この記事では省略します)

docs.google.com

ということで、以下はそんな波乱万丈にならなかった応援広告の自分語り。

ざっくり目的と手段の確認

今回ぼくの応援広告の目的は「(ファンからも)大神ミオさんの故郷に錦を!」でした。群馬に絶対送りたい、群馬県民の皆さま、大神ミオを、大神ミオをよろしくお願いします!!一方、明らかに時期的にプライベートの時間があまり取れないことがわかっており、手間はなるべく避けたいというお気持ちでいっぱいでした。

そこで次のルールで動くことにしました。

  • 目標は「ミオさんの故郷に広告を!」「大神ミオを知っている人が『そろそろじゃん!』とそわそわしてほしい」に絞る。目立とうとするな。
  • 任せらる部分はひとりに集約してコミュニケーションを最小限にする。ただしこれは「クオリティを疎かにできる」ための免罪符ではない。質が下がるなら、やれ。
  • 予算は目一杯使う。一片たりとも残すな。少しオーバーしても良い。

メモを書く

書く。書く。ひらすらに書く。割と注力してました。今回はGoogle Docsにすべての情報をまとめて書きました。そして「TODOリスト」「問い合わせたこと」「選んだ理由」「ダメだったこと」「今後使うサイトのリンク」まで、ぜーーーんぶ書きました。仕事柄、Visibilityには気を遣いたい派だったのでイラスト/デザインの担当の人にもドキュメントを丸ごと共有しました。

特に消えがちな「なぜ」はしっかり書くようにした。偉いぞ過去の自分。

意外と過去の自分が調べたことに助けられることがあり、良かった良かった。これがデザイン担当の人にどれくらい役立ったのかは不明……お、おしえてほしいな〜チラッ

タイムラインの線引き

広告は掲出日が決まるとほぼ自動的にデッドラインが定まります。今回は掲出の終わりを9月10日直後にしたかったので自然とこのようなタイムラインが浮かび上がりました。(実績)

  • 4月29日 応援広告の機運を感じる
  • 5月7日 応援広告許諾申請
  • 7月27日 デザインレビュー入稿
  • 8月15日 SNSレビュー
  • 8月20日 ポスター入稿
  • 9月4日 広告開始

広告の開始日から1ヶ月+αくらい前にはデザインが出来上がっていないといけないので、ある意味デッドラインがわかりやすいというか……

実際には広告代理店さんに相談して色々日程を調整してもらったりしました。本当に感謝。

参考 掲出スケジュール(週別) – 応援広告(センイル広告) Cheering AD| よくあるご質問

ちなみに、今回はキービジュアルの公開(6月28日)からデザインレビューまで1ヶ月しかないというタイトスケジュールでした。ありがとうPAISHENさん。しかも2枚。どう考えても狂ってる。(激褒め) 本当にありがとう🍍

予算決定

諸事情である程度まとまったお金が浮いていたことがあり、それをベースに使うことを決めました。足りないけど。クラファンで足りない分を集めることも考えましたが、プライベートの時間があまり取れないことがわかっていたので

  • 集めたり告知する時間があまり取れない可能性
  • 費用を細かく計算しないといけない手間
  • 単純に面倒臭い

今回はひとりで全部出すことにしました。ひとりで全額出すのはアホのやることです。お財布がビビります。余程の理由がなければクラファンを利用しましょう。そして何より、ひとりは寂しいぞ

許諾取り

応援先の団体によって異なるとは思いますが、多くの場合事前に許諾が必要なはず……?今回はカバー株式会社hololiveプロダクションへの広告となるため、ガイドラインに従って許可を取りました。ガイドラインがない事務所さん等であれば、一度問い合わせたほうが良いでしょうね。

hololivepro.com

申請後、運営さんが対応して1-2営業日ほどで許諾が取れました。許諾を取る際に「団体名」「どこの駅にどの期間」など聞かれますので、ある程度準備した上で許諾を取る必要があります。100%詳細を決めていないといけないわけではないので、まずやる気が起きたら予算と場所くらいのイメージはつけて問い合わせしましょう。これがないと何も始まらない。

今回は「群馬県と東京、会場付近に出したい」「9月10日を含めたい」程度の内容で申請を出しました。サポートの方とはかなりいろんな話をして、追加のあれこれがとてもスムーズに拡張できました。体験◎

場所選定

群馬県フォーカスが最初の最初。そこで、高崎駅前橋駅水沼駅、フラワーパークetc……当初は群馬オンリーで固める布陣だったのですが、調べていくと応援広告を受け付けてなかったり休業中だったりで思ったとおりに進められないと判断して群馬オンリーを断念。無念。いろんな人に相談しつつ、掲出場所は次に決めました。

3箇所にした理由は予算の都合上。東京山手圏内、たっかい。許されるなら「高崎駅ジャック!」とかやりたかった……

イラスト、デザイン

応援広告の機運を感じた瞬間、イラストは𝙋𝘼𝙄𝙎𝙃𝙀𝙉さんという方にお願いしようと心に決めていました。PAISHENさんのイラストのキャラクターから感じられる前後の動きや感情、息遣いを一目で感じられる独特な間と空気感が素敵です。道ゆく乗客さんたちが一瞬しかチラ見してくれない駅の広告で、悪目立ちせずに魅せるには良いだろうと思ってました。快諾してくださり、本当に感謝です。ちなみにここぞとばかりにデザインのお仕事もお願いするキラーパスをDMでぶん投げてました、改めてごめんなさい。引き受けてくださりありがとうございます。

個人的に、イラストの依頼するときにそのイラストの取り扱いと権利については明確にしておくと良いと思います。今回は「著作権等諸々は全部PAISHENさんに帰属したまま」「ぼくは使わせていただく立場」「事が終わったらいっぱい使って」と伝えておきました。

ステークホルダーの選定

ここまで来ると具体的な業者さんを探さないといけないためひたすらDeepResearchと睨めっこの日々でした。

応援広告で選ばないといけないのは3つ

  • クラファンプラットフォーム
  • 広告代理店
  • 印刷業者

今回クラファンはしない選択でしたので、残りの2つを選定。ちなみにこれらをすべてまとめてやってくれる業者さんもいますが、後述の理由で今回は別々に選びました。

広告代理店

駅広告の場合はほぼ確実に代理店さんを通さないといけないです。今回はCheering ADさんを採用しました。有名どころであることと、広告を掲出したい駅すべてをサポートしていたこと、そしてサポートからの応答がそれなりに早いため調整を多少進められたのでここに決めました。いろんな相談をして助けてもらい、大変に感謝!

cheering-ad.jeki.co.jp

印刷業者

個人的に一番大変だったのが印刷業者さん選びでした。実はCheering ADさんには印刷までまとめてやってくれるプランがあるのですが、そこで利用される紙が半光沢タイプの少しテカテカするようなタイプだったんですね。PAISHENさんの画風上、バキッとした強いコントラストが映えるような紙よりも表面がマットで発色の良い用紙の方が良い可能性があるよな〜と思い、別枠でやることに。この頃はまだデザインどうなるかも定まっていない時期でしたしね。

印刷業者さんを探して、今回はプリオさんを採用しました。RGB入稿が可能でポスター用紙の種類が多く、そしてサポートの応答が非常に早いこと、相談にかなり乗ってくれたおかげで見通しが立ちやすかったです。最終的な駅へのポスター搬入の方法まで事前に相談できたのは本当にありがたかったです。

www.oleshop.net

広告枠購入

代理店さんが決まったところで枠を購入します。特別難しいことはなく、「この枠買います!」とECサイトよろしくカートに入れてチェックアウトするだけです。ただし裏で在庫がなくなっていたりすることもあります(一敗)、購入後に正式に連絡が来るのでそれまで待機。

購入後に代理店さんからいろんな詳細情報がもらえます。特に駅固有の制限(QRコードのサイズや個数)や注意書き(例: XXをポスターに入れてください)があったりするので、しっかりメモしてすべてデザイン担当に渡す必要があったり。

なお、広告代理店さんによっては「個人NG」「過去実績ない場合はNG」みたいなこともあったりするので、しっかり条件は読みましょう。(※ Cheering ADさんではないです)

デザイン制作(待機)

暇である。

そう、主催側はやることがないのである!!!!!!この期間、暇である!!!!(5月下旬〜7月上旬)

約1ヶ月ほどやることがなくなったので、自分はこんなことして過ごしていました。ぼけーっとしていると、あっという間に自分の番になりますからね。

  • 広告の告知の方法(クラファンやっていないので認知を上げる方法)
    • SNSやファンサイトでなんとかできないか考えたり
  • メモをする
  • グッズ作って現地で配布したい
    • ポストカード(後述)の制作に必要なものを調べたり
  • メモを整理する
  • SNSレビューの準備
    • 並行してできます
  • メモをする
  • 仮印刷の準備
    • 一発勝負は怖いので、B3サイズでいろんな用紙に印刷してみる
    • これがかなり良かった
  • デザイン入稿後のシミュレーション
    • 何をするのか、ブロッキングがないことを明確にする
    • 「デザインレビュー間に合わない場合、どうすればいい?(1日くださいはできる?いつまでに連絡すればいい?)」「デザインレビューでRejectされた場合の再入稿のフロー(何営業日もらえる?超えるとやばい?)」「印刷後にどうやって配送すればいい?(配送場所は?時間指定はある?フォーマットは?)」
  • 「進捗いかがすか〜」

クラファンとかやる場合はこの期間に告知してお金を集める勘定したりとさらにバタバタするんだろうな〜と思ってました。

仮印刷

デザインデータを印刷業者へ入稿後、その印刷物を目で見るのは掲出後です。印刷ミスや色合いが想定外等のトラブルがあると公開後に気がつくことになります。そこで今回は事前に仮印刷を刷ることにしました。

プリオさんに相談してみたところ、小さいサイズで印刷すると発色は同じように見れるよとのアドバイス。今回は試しに2種類の紙質でそれぞれ小さいサイズで印刷しました。刷ってみた感想ですが、用紙ごとに思っていたよりも色の出方は違いました。たとえば高崎駅バージョンのイラストの場合、耐水紙とマット合成紙で色の表現や表面の反射の色が異なり雰囲気がぐっと変わりました。

白の表現が紙によって違う

今回のポスターデザインは空気感重視だったこともあり、ここでしっかり検証できたのは大きかったです。期日とお金に余裕があれば試してみる価値あるかもしれません。

デザインレビュー入稿

完成したデータを広告代理店さんに渡してレビューです。これ以降、デザインの手直しができなくなるので提出前に細かいチェックは忘れずに。デザインレビュー通過後、納品先の情報や納品時の注意事項がもらえました。

SNSレビュー

応援広告特有というか、迷惑にならないようにする大切な予防線。掲出日前に「この日この駅に広告が出るよ!」と事前告知すると人が集まったりして迷惑になってしまうので、「告知は掲出日の正午以降」「告知内容は事前にレビューしたものを使う」というのがCheering ADさんでのルールでした。

こんな感じに告知する際のツイートポストの内容を事前に決めて、掲出の3週間前までにレビューを出します。「この文言入れて」「この表現ダメ」みたいな駅固有ルールもあったりするので、ささっと情報集めて用意しておきました。画像もこのときに準備するのじゃぞ!

ポスター印刷

仮印刷で用紙も入稿方法もデータ不備チェックも済んでたので、さっと入稿しておしまい。ちなみにプリオさんは納品配送時の伝票情報を変更できるので、そこで注文番号など書いてCheering ADさん宛のフォーマットにしておきました。

……が、ここでトラブル発生🚨 Cheering ADさんから「納品されたポスターに傷が……」と連絡が。リアルな物品が関わる部分なのでこうゆうことも起こる。すぐプリオさんの再印刷できるか相談し、Cheering ADさんからのアドバイスに従って速やかに再納品されました。みなさん、トラブルにも関わらず速やかに対応してくださり本当に感謝です。

掲出

事前に掲出される時間は保証されてないからね〜という話を聞いてたのですが、いざ行ってみたらどの駅も朝イチで掲出されてました。うわぁぁぁありがてぇぇぇ。🙏ちなみに掲出現場に行く必要はないらしいとの。遠くに掲出しても安心だね💕

ま、行くけど。

また群馬の高崎駅のポスターを見に行った際、ついでにタワーレコード高崎店へ伺いました。ミオさんを推してくれてる同志の香りのする店舗……!そしたらなんとすでに広告を見てくださった店員さんがおり、和気藹々に意気投合。不思議な出会いでしたが、縁ができてあり良かったです。ありがとうございました。

……って呟かれてる!?ありがてぇ🙏

後日談

応援広告の後処理はないです。ポスターは処分されます。ポスターは処分されます。 大事なことなので2回言いました。なにか残しておきたい場合は、ポストカードとかにして残しておくと良いと思います。ぼくはせっかくなのでスーパーリッチ仕様のポストカード作りました。(イラスト担当の方に許諾を得ました)

一応ポストカード

盛りたかったのです。素敵なイラスト描いてくれたので、それなりの良いポストカードを……!なんて思いあれこれ考えた結果、こうなりました。

  • 紙: スタードリームFS クリスタル 209kg
    • キラキラしたパール加工が雰囲気とマッチ◎ 箔押し加工をしたかったので重めの紙にしました。
  • マットPP
    • 長期保存したい
  • 角丸加工
    • 角削れてダメージ入るの嫌だった
    • 目立たせたかった
  • 箔押し加工
    • どうしてもやりたかった……どうしても

原価1枚100円近くするポストカードってどうゆうことなんですかね(白目)

手に取れた方はラッキーです。200枚ほど現地で配布したのですが、あっという間に完配し終えてしまったようで……これ以上はお財布の都合で刷れないんだ。

応援広告まとめ

主催してみて思ったことは、主催者はあまりやることがないのである!!!!

【注意】個人の感覚です、ここでは継続的に4時間/週くらい集中して作業する程度のことは「やることがあまりない」としています。たぶんRyuSAは4ヶ月間で60時間くらい稼働してます。

上記の通り、基本的にはマネジメントだけなので交通整理しているだけで大体終わります。調べることいっぱいありますが、世の中には多くの実践者がいてゴールデンパスが確立されているのでそこまで大変ではなかったです。間違いなくこの応援広告の立役者はイラスト兼デザイン担当のPAISHENさんでした。みなとみらい駅の広告、ライブ後に見て完成するの卑怯っすよ……

会場からの帰り道に見かけて泣いてしまった

が、ミスったら推しの顔に泥を塗るものなので重圧はやばかったです。関係者にも「あ、この人のファンは応援広告すらできないのか〜」と思われたらどうしよう、と必死こいて失敗しないよう予防線張りまくって安牌コンチプラン充実ルートで進んでました。これは大変だった。気軽におすすめできるようなものではないですが、覚悟と時間とお金があるのならぜひ。

フラワースタンド

やることはとても少なかったけど、かなりバタバタしましたね……

今回、Our Sparkle宛のフラスタは当選が必要なパターンだったのでこのようなタイムラインでした。(実績)

  • 2025年7月31日 当落発表
  • 2025年8月31日 パネル入稿
  • 2025年9月某日 搬入
  • 2025年9月某日 搬出

当落発表から1カ月ちょっとでデザイン、イラストを完成させてパネル印刷してお花を組み立てて搬入しないといけない……だと!?

超スーパータイトな日程だったので、事前にある程度は考えてました……が、さすがに当選でないとお金払えないのでもどかしい感情……ぐぬぬ

全体の流れ

後から見返すと、大きく分けてこんなフェーズを考える必要がありました。

  • 目的を明確にする
  • 予算組む
  • デザイン担当依頼
  • イラスト担当依頼
  • お花さん担当依頼
  • デザインこねこね
  • パネル印刷
  • 組み上げ、搬入、搬出

特にデザインは花の部分を含めてデザインしないといけないので、お花屋さんとよく相談しないといけないな〜と。

タスク - 人探し

今回目的は明確で「ミオファからミオさんへプレゼント花を送りたい」ことでした。なので「お祝いのためのお花プレゼント」「パネルはすべてミオファだけ、祝われる側の大神ミオは出さない」「お花をメインにしたい」にすると決めてました。そしてそこから導き出されたイラスト担当の方は……そう、我らが父、ぱんじゃむのなめさん

連絡を取ったところOKをいただき、さらに(恐らくぼくの不甲斐ないデザイン力に呆れて)デザインの担当までお願いいたしました。神。パパ、ごめん……おれイメージをイメージできない脳のデザインしているんだ……

お花屋さんは、せっかく横浜であること、お花が好きなミオさんが満足できるよう、結婚式などを担当してくれているハマフローリストさんにお願いしました。搬入搬出もまとめて取り仕切ってくれて、とても感謝……!

www.hamaflorist.co.jp

パネル印刷はすでにやり取りしてるプリオさんに引き続き依頼しました。ありがとう、プリオさん。ちなみにカットラインについて、初回だったことと時間がタイトだったのでプリオさんにカットラインの追加を依頼しました。ミオファのシルエットが定まった段階でプリオさんに相談し、これなら1営業日でできますよと連絡いただけました。ありがとうございました、プリオさん。

タスク - こねこね

こちらが最初期のデザインです。(by RyuSA)

苦笑。

が、ここからやりたいこととキービジュアルのイメージをハマフローリストさんとぱんじゃむのなめさんにお伝えして使えるアイテムなどが出揃ってきたところで、ぱんじゃむのなめさんからこんなデザインが。

ど、どうゆうことだってばよ??ハマフローリストさんも「ここは造花で、このお花で、色合いは……」と、あれよあれよという間に決まりました。プロってすげぇ……。

パネルの素材は、水回り触れる可能性があるかもしれないと判断して耐水紙を選択。作業環境もわからないので、念のためUVカット加工も追加してもらいました。こ、これで良かったんかな……?

メンバーと決めること決まれば主催側は用無し。イラスト担当の方からデータを受け取って印刷所に渡してお花屋さんに転送、組み立ててもらって搬入と搬出をしてもらい……あれ?こうやって文章にすると、ぼく何もしてない(ry

後日談

「終わった後に何も残らない」というもの寂しいので、今回お花屋さんに相談してパネルを返却してもらえないか相談してみました。ありがたいことにOKをいただけで、現在自分の手元にあります。はぁ〜〜〜〜〜かわよ🥰

また、お花屋さんが会場近くでしたのでライブ当日に感謝を伝えるために挨拶に伺いました。そのタイミングで実際にフラスタを組み立ててくれた店員さんがいらっしゃり「楽しかったですよ〜」というコメントもらえてとても嬉しかったです。ハマフローリストさん、本当にありがとうございました!

フラスタまとめ

おそらくフラスタに関しては絵が描ける人、少なくとも頭の中にイメージを作れてそれを絵にアウトプットできる人がメンバーにいるとスムーズなんじゃないかなと思います。そうじゃないとマジで話進められない……

できる人はこちら↓

note.com

ちなみにお花屋さんとデザインを詰める際、コミュニケーションが結構大事だなと思います。物理的な話になるので「ここはこうゆう材質で」「この部分はこんなお花が合いそう」など、すり合わせが大事になってきます。ま、今回はのなめさんのデザインPOWERとハマフラさんの知識がハマったようであまり大変にはならなかったのですが……

このフラスタは動画配信でも取り上げてもらえました、𝕙𝕒𝕡𝕡𝕚𝕟𝕖𝕤𝕤

youtu.be

供養:最初の最初は999本の薔薇計画があったりしたのですが、ぼくのフラスタの目的から逸れるということで自分で中止に。本邦初公開、お焚き上げ〜〜〜。

トータルまとめ

たのしかった〜〜〜〜〜〜。ホクホクの思い出。

夢の名残

Kubernetesのいろんな資格とった話

数年前にCKA/CKADを取得しました。懐かしいですね。

ryusa.hatenablog.com

あれから数年、すでにあの頃取得したCKA/CKADはExpiredしてしまいましたが、新しくKubernetes関連の資格を取得してみました。

  • CKA
  • CKAD
  • KCNA
  • KCSA
  • CKS

そう、いわゆるKubestronautってやつです。この記事は忘備録的な内容です。

www.credly.com

……と思って筆を走らせてみたのですが、当時と違って最近ではすでに多くの人が体験記を書いている時代になりました。Kubernetesもよりメジャーになったと言うことでしょう、良い時代だ。

一般的な話やよく使える教材などの紹介は避けて、ここではぼくの場合固有の問題とかについて語るに留めておこうと思います。

メタ情報 👀

受験した際のメタ情報を書いておきます、初心者ではないのです。

試験環境周り

Environment Checkとして、部屋に余計なものがない環境で受験する必要があります。先人の知恵を借りて、自宅の浴室を使って受験しました。

給湯器のことは適当にHouse Controllerとか言って回答しました。Environment Checkの担当者が給湯器のこと知らないこともあるはずだし、まぁ間違ってないはず……

トラブル

CKA編

ノートPCのバッテリーが切れました(マジで申し訳ない) 元々バッテリーのへたってた貧弱ノートPC使ってたのがよくなかったです

慌てて充電ケーブルで充電してSecure Browser開き直したらそのまま試験続行して良いよと回答もらえたので本当に助かりました。たぶんこの対応には保証はないはずですが、同じようにバッテリー切れた場合は素直に「ノートPCの充電切れちゃいました」と伝えましょう。もしかしたらワンチャン助けてくれるかもしれません。

CKS編

接続先のリモートPCとVMが非常に不安定で試験どころではない状態のままスタート……してそのままフィニッシュでした。このときも素直にチャットで「文字入力してから数秒後に入力が表示される」「カーソルが瞬間移動する」「画面がしょっちゅうタイムアウトする」と連絡して20分ほどトラブルシューティングしてもらいましたが原因は不明。「終わった後にチケット上げてね」という形で再開して終わりました。(冒頭20分返して……)

残念ながら結果的にそのまま合格しちゃったので、実際にこのパターンはどうなるのか不明……

いずれも言えることは、困ったら素直にヘルプを求めましょう。たぶんきっと何か前進できるはず。(少なくともログには「ヘルプを求めた」事実は残るので重要なはず)

勉強教材

killer.sh

Killer.shを信じろ

……と言ったものの、実際Killer.shは素晴らしいです。特に試験に付属するシミュレーターは本番で利用する環境とUIから使い勝手まで大体一緒です。ぜひ使ってみてください。

なお、Killer.shのCKA/CKADコースを一通り学び 理解して 理解して 理解して コマンドぱぱっと叩けるようになれればおそらくCKA/CKADは足りると思います。

CKSはこの座学だけでは足りない、純粋なLinux力も必要ですがITエンジニアとしての総合力と勘が大事な気がします。この不足分をどこで補えるのかは正直不明……。とりあえずKKDが大事。

ちなみにKiller.shの出しているCKSの教材はYouTubeに上がっています。知識面はだいたいこれで補えます。おいおいマジかよ(Udemyで買ってたマン)

www.youtube.com

それとタイピングが遅いそこのあなたには寿司打おすすめです。

sushida.net

ぼくはタイピングが致命的に遅かった(=お勧めコースクリアできなかった)ので、これで練習しました。高級コースクリアしたい。

最後に

ぼくはKubernetesたのしい〜〜〜^^派なのでゲーム感覚で楽しめました。業務ではめっきりKubernetesに触れることがなくなってしまったので、久しぶりにkubectlにたっぷり触れて満足でした。個人的な話ですが、この試験ラッシュの最中に自分も alias k=kubectl 派に改宗しました。

サポートしてくれた家族、夜中作業のお供にいてくれた大神ミオさん(の配信)にこの場を借りて感謝……!!

kubenews#57 Cloud Nativeなニュース - プロダクト紹介縛り

本記事はkubenewsの第57回目のゲスト枠で参加するRyuSAのコンテンツです。

なお、本登壇および本記事はあくまで 私自身の見解 であり、私の所属団体・企業における立場、戦略、意見を代表するものではありません。

Markdoc

markdoc.io

Stripe社の公開したドキュメントをMarkdownで書くためのOSSです。利用できるMarkdownGitHub Flavored……でありつつも一部AsciiDoc的に似た拡張を使ってドキュメントを記述できます。そのため多くのエンジニアが普段から書き慣れているMarkdownを使ってドキュメントのメンテナンスを行うことができます。

---
title: What is Markdoc?
---

# {% $markdoc.frontmatter.title %} {% #overview %}

Markdoc is a Markdown-based syntax and toolchain for creating custom documentation sites. Stripe created Markdoc to power [our public docs](http://stripe.com/docs).

{% callout type="check" %}
Markdoc is open-source—check out its [source](http://github.com/markdoc/markdoc) to see how it works.
{% /callout %}

## How is Markdoc different?

Markdoc uses a fully declarative approach to composition and flow control, where other solutions… [Read more](/docs/overview).

## Next steps
- [Install Markdoc](/docs/getting-started)
- [Explore the syntax](/docs/syntax)

またNext.jsやReactなどと組み合わせて複雑なビルドやレイアウトのごにょごにょができたりと、拡張の方法はかなり自由のため社内WikiのGit管理などに使えるような気がします。

Talos Linux

www.talos.dev

Kubernetes"専用"のOS……え??専用???となりますがそんな不思議なOSがTalos Linux。このLinuxディストリビューションはコンテナ向けOSLinuxのひとつで、特にKubernetesを起動/運用するためのものです。OSにSSHすることはできず、設定はすべてはtalosctlを使ったAPI経由で行うことになります。

Talos LinuxはDockerで起動することが可能で、手元でサクッと動作検証することができます。

個人的に好みなのは、このOS自体がメモリ上で展開できるためサーバーがステートフルになることを防ぐことができます。PXEブートなどにも当然対応しているため、Raspberry Piなどが活躍するワークロード(IoTや誤自宅勢とか)にはとても便利なんじゃないかなと思います。

trivy

超便利だったので共有したい、というだけ……

aquasecurity.github.io

23:22:35 ryusa@TUNA-KAN:~/develop/local/kubenews#57
$ trivy kubernetes --report summary cluster
2022-07-13T23:22:54.708+0900    INFO    Need to update DB
2022-07-13T23:22:54.708+0900    INFO    DB Repository: ghcr.io/aquasecurity/trivy-db
2022-07-13T23:22:54.708+0900    INFO    Downloading DB...
32.96 MiB / 32.96 MiB [---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------] 100.00% 19.91 MiB p/s 1.9s
141 / 141 [----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------] 100.00% 7 p/s

Summary Report for admin@talos-default
┌─────────────┬──────────────────────────────────────────────────────────────┬────────────────────┬────────────────────┬───────────────────┐
│  Namespace  │                           Resource                           │  Vulnerabilities   │ Misconfigurations  │      Secrets      │
│             │                                                              ├───┬───┬───┬────┬───┼───┬───┬───┬────┬───┼───┬───┬───┬───┬───┤
│             │                                                              │ C │ H │ M │ L  │ U │ C │ H │ M │ L  │ U │ C │ H │ M │ L │ U │
├─────────────┼──────────────────────────────────────────────────────────────┼───┼───┼───┼────┼───┼───┼───┼───┼────┼───┼───┼───┼───┼───┼───┤
│ kube-system │ Role/system::leader-locking-kube-scheduler                   │   │   │   │    │   │   │   │ 1 │    │   │   │   │   │   │   │
│ kube-system │ Role/system::leader-locking-kube-controller-manager          │   │   │   │    │   │   │   │ 1 │    │   │   │   │   │   │   │
│ kube-system │ Deployment/coredns                                           │ 1 │ 1 │   │    │   │   │   │ 3 │ 5  │   │   │   │   │   │   │
│ kube-system │ DaemonSet/kube-flannel                                       │   │ 6 │ 8 │ 6  │ 2 │   │ 2 │ 9 │ 30 │   │   │   │   │   │   │
│ kube-system │ Role/system:controller:cloud-provider                        │   │   │   │    │   │   │   │ 1 │    │   │   │   │   │   │   │
│ kube-system │ Role/system:controller:token-cleaner                         │   │   │   │    │   │ 1 │   │   │    │   │   │   │   │   │   │
│ kube-system │ Role/system:controller:bootstrap-signer                      │   │   │   │    │   │ 1 │   │   │    │   │   │   │   │   │   │
│ kube-system │ DaemonSet/kube-proxy                                         │ 6 │ 8 │ 2 │ 57 │   │   │ 2 │ 4 │ 10 │   │   │   │   │   │   │
│ kube-system │ Service/kube-dns                                             │   │   │   │    │   │   │   │ 1 │    │   │   │   │   │   │   │
│ kube-public │ Role/system:controller:bootstrap-signer                      │   │   │   │    │   │   │   │ 1 │    │   │   │   │   │   │   │
│             │ ClusterRole/cluster-admin                                    │   │   │   │    │   │ 2 │   │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:namespace-controller           │   │   │   │    │   │ 1 │   │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:job-controller                 │   │   │   │    │   │   │ 1 │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:endpointslice-controller       │   │   │   │    │   │   │ 1 │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:root-ca-cert-publisher         │   │   │   │    │   │   │   │ 1 │    │   │   │   │   │   │   │
│             │ ClusterRole/system:kube-scheduler                            │   │   │   │    │   │   │ 2 │   │    │   │   │   │   │   │   │
│             │ ClusterRole/admin                                            │   │   │   │    │   │ 3 │ 7 │ 1 │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:endpoint-controller            │   │   │   │    │   │   │ 1 │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:resourcequota-controller       │   │   │   │    │   │ 1 │   │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:replicaset-controller          │   │   │   │    │   │   │ 1 │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:generic-garbage-collector      │   │   │   │    │   │ 1 │   │   │    │   │   │   │   │   │   │
│             │ ClusterRole/edit                                             │   │   │   │    │   │ 2 │ 7 │ 1 │    │   │   │   │   │   │   │
│             │ ClusterRole/system:aggregate-to-edit                         │   │   │   │    │   │ 2 │ 7 │ 1 │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:deployment-controller          │   │   │   │    │   │   │ 2 │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:horizontal-pod-autoscaler      │   │   │   │    │   │ 2 │   │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:persistent-volume-binder       │   │   │   │    │   │ 1 │ 2 │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:expand-controller              │   │   │   │    │   │ 1 │   │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:replication-controller         │   │   │   │    │   │   │ 1 │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:aggregate-to-admin                        │   │   │   │    │   │ 1 │   │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:endpointslicemirroring-contro- │   │   │   │    │   │   │ 1 │   │    │   │   │   │   │   │   │
│             │ ller                                                         │   │   │   │    │   │   │   │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:kube-controller-manager                   │   │   │   │    │   │ 5 │ 2 │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:node                                      │   │   │   │    │   │ 1 │   │   │    │   │   │   │   │   │   │
│             │ ClusterRole/system:controller:cronjob-controller             │   │   │   │    │   │   │ 2 │   │    │   │   │   │   │   │   │
└─────────────┴──────────────────────────────────────────────────────────────┴───┴───┴───┴────┴───┴───┴───┴───┴────┴───┴───┴───┴───┴───┴───┘
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN

う、美しい……!(jsonでのレポートもできるので自動化もしやすいたすかる)

Trivy Operator

github.com

というそんなTrivyのOperatorについても紹介、要するに↑をKubernetes内部からチェックしてくれるとても素晴らしいOperator。CRとしてPodや各種設定の脆弱性を出力してくれます。

00:14:21 ryusa@TUNA-KAN:~/develop/local/kubenews#57
$ kubectl apply -f https://raw.githubusercontent.com/aquasecurity/trivy-operator/v0.1.3/deploy/static/trivy-operator.yaml
customresourcedefinition.apiextensions.k8s.io/vulnerabilityreports.aquasecurity.github.io created
customresourcedefinition.apiextensions.k8s.io/configauditreports.aquasecurity.github.io created
customresourcedefinition.apiextensions.k8s.io/exposedsecretreports.aquasecurity.github.io created
customresourcedefinition.apiextensions.k8s.io/clusterconfigauditreports.aquasecurity.github.io created
customresourcedefinition.apiextensions.k8s.io/clusterrbacassessmentreports.aquasecurity.github.io created
customresourcedefinition.apiextensions.k8s.io/rbacassessmentreports.aquasecurity.github.io created
namespace/trivy-system created
serviceaccount/trivy-operator created
clusterrole.rbac.authorization.k8s.io/trivy-operator created
clusterrole.rbac.authorization.k8s.io/aggregate-config-audit-reports-view created
clusterrole.rbac.authorization.k8s.io/aggregate-exposed-secret-reports-view created
clusterrole.rbac.authorization.k8s.io/aggregate-vulnerability-reports-view created
clusterrolebinding.rbac.authorization.k8s.io/trivy-operator created
role.rbac.authorization.k8s.io/trivy-operator created
rolebinding.rbac.authorization.k8s.io/trivy-operator created
role.rbac.authorization.k8s.io/trivy-operator-leader-election created
rolebinding.rbac.authorization.k8s.io/trivy-operator-leader-election created
secret/trivy-operator created
secret/trivy-operator-trivy-config created
configmap/trivy-operator created
configmap/trivy-operator-trivy-config created
configmap/trivy-operator-policies-config created
Warning: would violate PodSecurity "restricted:latest": runAsNonRoot != true (pod or container "trivy-operator" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "trivy-operator" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
deployment.apps/trivy-operator created
service/trivy-operator created

00:21:19 ryusa@TUNA-KAN:~/develop/local/kubenews#57
$ kubectl create deployment nginx --image nginx:1.16
Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "nginx" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
deployment.apps/nginx created

00:22:10 ryusa@TUNA-KAN:~/develop/local/kubenews#57
$ kubectl get vulnerabilityreports -o wide
NAME                                REPOSITORY      TAG    SCANNER   AGE   CRITICAL   HIGH   MEDIUM   LOW   UNKNOWN
replicaset-nginx-7f597d689d-nginx   library/nginx   1.16   Trivy     32s   38         74     57       119   1

現在の最新バージョンで用意されているのは - clusterconfigauditreports - clusterrbacassessmentreports - configauditreports - exposedsecretreports - rbacassessmentreports - vulnerabilityreports の6つのリソース、雑に環境に放り込んでおくだけでそれっぽくなりそうな予感

Sigstore

www.sigstore.dev

ソフトウェアのサプライチェーンを防ぐための仕組みを考えよう!という実験的なプロジェクト Sigstoreは - cosign - Fulcio - Rekor の3つのソフトウェアを組み合わせて機能でき、最終的な目的としては「アーティファクトをキーレスで署名して、その署名を改竄できないログとして保存して、アーティファクトを公開する」ことです。これにより、だれでもアーティファクトが正しく署名されていることを検証することができつつ鍵の管理が不要なので色々幸せになれそうな予感……!

残念ながら手元のWindows環境ではなぜかうまく動かなかった&話するとかなり長くなるので詳細は先人の神資料を参考に……

knqyf263.hatenablog.com

OCIイメージに対しての署名もできる一方、当然普通にバイナリにも署名ができるのでJavaのGradleやRubyRubyGemsなどでIssueとしてあがっています。Sigstoreが広がって、すべてのソフトウェアのサプライチェーンを守れるようなそんな世界が来るといいですね。

github.com

github.com

とあるYouTube Streamerのファンサイトを作った話

この活動は自分個人の趣味であり、所属する企業や組織の立場、戦略、意見を代表するものではありません。

こんなの作ってました。たのしかった(小並感

milliooon.ryusa.app

リリースしてからしばらく経ったので、少し技術的な選定の話とかをまとめておきます。尖ったことはあまりしてないのでアレですが……🤔

Question. そもそもなんで作ったの?

Answer. 久しぶりにフロントエンド作りたかったから🤪

ここ最近はKubernetesDNSなどのインフラストラクチャーばかり触ってたので、たまにはリフレッシュしたいな〜と……

要件と技術選定を進める

今回の要件はこんな感じでした。個人プロジェクトなので自分中心で楽しくやりたいってのが理由ですね。

  • まだ触ったことがないものに挑戦したい
    • 個人開発である以上モチベを維持しやすいように新しいものに触れることを前提に
  • 安く早く済ませたい
    • 言わずもがな
  • マネージドなサーバーを持ちたくない
    • 管理したくない(怠惰
    • ホットなコンテンツを相手にする以上、もしかしたらスパイクが発生するかも……?(という想定訓練は大事)
  • デプロイ自動化が可能
    • 令和ですよ?Continuous Deploymentくらいは標準搭載ですよね??
    • 万が一怒られた際にロールバックがスムーズにできるようにする(これから怒られる可能性はまだありますので、怒られたら速攻で消します)
  • ガイドラインを読む(超大事)
  • ガイドラインを読む(大事なことなので(ry
  • ガイドラインを読む(超大事なことなので(ry

ということを前提に技術選定を進めました。

プラットフォーム

まずはプラットフォームの選定。今回のコンテンツ的には静的なもので十分(=バックエンドで動的にコンテンツを生成する必要がない)のでサーバーどころかLambdaすら不要。単純なSPA等の静的ファイル配信ができればOKです。

そこで今回はNetlifyかVercelかCloudflare Pagesのいずれかをプラットフォームとして使おうかなと🤔Netlify / Vercel / Cloudflare Pages はいずれもフロントエンドホスティングサービスで、ReactやVueなどで作ったSPAなどをホスティングCDN配信してくれるとても素敵なサービスたちです。……が、実はNetlifyはかつて使ったことがあり、いろんなところで話題に聞くVercelが気になったので今回はまったく触ったことがないVercelでホストすることに決めました👀ごめんねCloudflare Pages

ドメイン名とか証明書とか

このファンサイトは二次創作のプロダクトであり、万が一ご本家様とドメイン名争奪戦が起こっては大変なので自分のドメインryusa.appからのサブドメインを切り出しました。

Vercelは、ホスティングサイトなので当然ではありますがカスタムドメインを利用してサイトを公開することができます。

vercel.com

自分のryusa.appGoogle Domainsで用意しているドメインなので、GoogleDNSにVercel向けのCNAMEだったりTXTレコードだったりを登録してVercel側にドメインの登録を完了しました。超簡単。

……ちなみにVercelにドメインの登録をすると、自動的にLet’s EncryptTLS証明書を発行してくれるようになります。マジでなにも考えなくてもTLS証明書がホストされるようになります。超簡単。

vercel.com

言語とか

今回はTypeScript/Reactベースで実装することを決定しました。最初は今アツいSvelteで行こうかと思いましたが、React 18がちょうど出たタイミングだったので波に乗るなら今だ!!と思って今回はReactベースにしました。Svelteはまた今度ね……🥰また最初はSPAとしてビルドしようと思っていましたが、フロントエンドの規模的にそこまで大きくなく、かつ動的なAPI呼び出しも発生しないことを踏まえると静的ビルドで十分と判断し、今回はまだ触ったことのないGatsbyを利用することにしました。

ちなみに、実装中に検証としてExperimentalで公開されてるReactのServer Componentも触ってみましたがかなり良さげでした。そこまでコストかけずにバンドルサイズを減らせるのは強い……!ただ今回は検証の時間がそこまでなかったので見送り……

CI/CD

GitHub ActionでビルドしてVercel側で自動デプロイ……というのが当初の予定でしたが、実はそもそもVercel側にGitリポジトリをfetchして自動ビルドをかける機能が存在しているんですよね。自分は知らなかったのですが、Vercelにはリポジトリを連携するとリポジトリの中身をチェックして自動的にビルドコマンドとデプロイコマンドを生成してくれる神機能が付いていました。

ビルドコマンドや環境設定をカスタマイズすることもできる

実装周りとか

そんな難しいことしてないし特に書くものなくね??と思っていましたが、個人的に気を配ったことだけ……

IEのサポートを、しない

力強く!

日本はやたらIEシェアが高いらしいですが、別にお仕事でもないプライベートプロジェクトなのでIE対応はしませんでした。React 18からIEのサポートも切れることですしIEそのものも消えますし、まぁ妥当かなと。

ja.reactjs.org

(IEを除く)ブラウザシェア上位 95% を(目安に)サポートする

ファンサイトとしてホストする以上、モダンブラウザをサポートしておかないと場合によっては他の熱心なファンが応援できない可能性があります。「(レイアウト崩れを見て)なんだよーFirefoxはサポートしてくれないのかー」となっては悲しいですし、せっかくの盛り上がりに水を差してしまうでしょう。ということで今回はChromeを始めとしてブラウザシェア95%に入るブラウザをサポートすることを目標に動作検証を行いました。なのでCSSsvh@layerなどの超モダンな機能群が使えなくて少し悲しいところではありましたが……

業務ではモダンブラウザサポートなんて当然の作業ですが、個人プロジェクトで動作検証しっかりやったのは初めてでしたね……一部環境の動作検証にお手伝いいただいた方々には、改めてこの場で感謝を。ありがとうございました!(iPhone民/Samsung民)

まとめ

Vercelとフロントエンド周りのエコシステムが本当に充実しており、CI/CDの環境をサクッと構築できるおかげで手元で開発して本番デプロイまでが数分でできる世界観でした。ブランチで本番環境にデプロイするアセットを管理できるので、これであれば大規模なフロントエンド開発チームでの開発フローにも導入できそうです。

今度Cloudflare Pagesも使ってみる予定なので、もしタイミングがあれば具体的なNetlify / Vercel / Cloudflare Pages の比較ができるかもしれないですね👍


最後に、お手伝いいただけたみなさんありがとうございました。wappaさんも素敵なイラストを提供&OGP画像作成ありがとうございました。

twitter.com

久しぶりの人目に触れるプロダクトを公開し、いろんな人からの感想がもらえたのはすごく励みになりました👏ありがとうございました!

あいあいじぇいを退職します👋

エンジニアもすなる退職ブログといふものを……

2022年3月31日を最終出社日として、株式会社インターネットイニシアティブを退職します👏 新卒で入社してちょうど4年間、大変お世話になりました。

退職ブログを書いてみようと筆を走らせてみたものの、思いのほかたくさん書けそうになく……ですが、せっかくなので少しだけですが、将来の自分のためにもエントリーを残しておきます

IIJでどんなことしていたの

僕はIIJのとある金融サービスの部署のエンジニアとして仕事をしていました。最終的な肩書きがただの「エンジニア」なのは、それはそれでちょっぴり寂しい気もする……ww

主な業務内容としては次のようなものに携わってきました。

  • アプリケーション開発
    • フロントエンド
    • バックエンド
  • インフラ開発
    • AWS関連
    • Kubernetes
    • プラットフォームエンジニア的なやつ

……おぉ、こうやって並べてみると専門領域がフワッフワしてるなぁw スキルセット的にはインフラ領域1に対してアプリケーション3……ぐらいの立ち位置ですね🤔

最初はアプリケーションエンジニアとして金融システムを開発し、その後インフラに近い領域からプラットフォームエンジニア的な立ち位置で開発メンバーの補佐や技術検証などをやってきました。とはいえ今でも自分の一番の専門と言える領域はアプリケーション開発ですね。コーディング楽しい🤪

メイン業務とは若干外れますが、IIJのブログにこんなネタを投稿していました。多々反響もらえて(特にKubernetesネタ)非常に楽しかったですw

eng-blog.iij.ad.jp

eng-blog.iij.ad.jp

Why 退職?

退職する主な理由は、転職するからです。(?🤔?)

新しい環境で挑戦してみたいな〜と考えていた矢先、とあるクラウドベンダーさんとお仕事する機会があったので挑戦してみようと思い転職を決めました。やっぱりね、刺激が欲しいんですよww

おそらく今の環境に残っていても様々なキャリア、技術面を磨くことはできるとは思いますが……それはあくまでもIIJという会社から見える世界でのみ、やっぱり一度外に出てみたいなと思うわけです。

最後に

4年間、面倒を見てくださったメンバーに最大限の感謝を。たくさん尻拭いしてくださり本当に感謝しております。この4年間は、自分にとって大切な4年間になりました👏

また社内に転がっている様々なコミュニティ(IIJ Bootcamp GitHub - iij/bootcamp: Bootcamp ハンズオンで使用する資料集 とか)での会話も非常に楽しかったです。気軽に困ったことや技術ネタをネットミームとともに盛り上がれる場があるのは、なんというかすごくIIJらしさを感じてますw

とはいえ退職するからと言って人が変わるわけでもなく、今後もTwitter等で元気よく自生しておりますので

ではでは👋

技術書典 #12で「Java開発 for Kubernetes」を頒布します🎉

はじめての技術同人誌ですが、がんばります💪

Java開発 for Kubernetes:ツナ缶本舗 | 技術書典12

どんな書籍?

「次のプロジェクトでは、DockerとKubernetesクラウドネイティブだ!」 ……なーんて話を聞かされて、困っている開発者の人はいませんか?

アプリケーションの実行環境をコンパクトにまとめた隔離環境「コンテナ」 コンテナを自在にデプロイし面倒くさい管理を自動化できるエコシステム「Kubernetes

大コンテナ時代を迎えようとしている今、どのようにJavaでアプリケーションを書き、どのように開発フローを回し、どのように運用/監視していくのか、ざっくり表面だけ舐め回すことができるコンテンツを集めました。 JavaのWebアプリケーションとしてSpring Bootを使いながら、実際にコマンドを叩いてアプリケーションをコンテナにしてKubernetesにデプロイする開発フローを体験してみましょう!

という感じの本です。つまるところ「Kubernetes上で動かすコンテナアプリケーションを開発するにあたって、どんなツールがあったり嬉しいものがあったりするの?」ってのをざっくりをまとめたエッセンス本です。注意していただきたいのは「これを読めばKubernetes完全に理解できる!」タイプの本ではないです。マジでアプリケーションサイド目線の話しか書いていません。なのでインフラの話はほぼ出てきません。

コンテンツ

  • 含まれているもの
    • コンテナの概要説明
    • Kubernetesの概要説明
    • コンテナのための開発フロー体験
    • 開発ヘルパーツールの紹介とざっくり使い方
    • 運用のために覚えておくこと
    • これらのサンプルコード
  • 含まれていないこと
    • Kubernetesのバックエンド(kubeadmとかkubeletとか)
    • インフラの話(OSとかCNIとかコンテナランタイムとか)

ターゲットとなる人

主に開発者、特にJava/Spring Bootの開発を行なっている人にとっては良い本だと思っています。またJavaで書かれたワークロードをメンテナンスするぜ!という(広義での)SREの方も読んでおくとアプリケーション開発者と会話しやすいかもしれないです。 自分はアプリケーション開発者である一方でCKA等も取得しKubernetes完全にわからんを通過してきた身でもあります。その背景を元に「こんな情報が横断的にあったら嬉しかったのにな〜」というものをかき集めてました。すいません、実は書ききれてないです物理的な予算が足りなかったです。

ということで、買って💕

電子書籍版は1000円、電子書籍+物理本セットも1000円で頒布しています!一応別の場所でも頒布する予定はありますが、お値段上がったり電子版/物理本いずれか……など、セットでは購入できなくなると思います。

GitLab OperatorはGitLab運用の自動化の夢を見るか

注意 : GitLab Operatorは10月9日現在まだv0.1.0のリリースがあったばかりです。本番環境への適用にはまーだ早いのでご注意してください🤔

–– さぁ、GitLab OperatorでGitLab運用の自動化をはじめよう!!

gitlab.com

背景

GitLabはおそらく多くのエンジニア、組織で利用されているGitリポジトリ管理ツールです。しかし、GitLabには多様な機能が日々追加されており今やGitLabはただのGitリポジトリツールではなくっている……と個人的に思っています。

GitLabのIssue/Milestoneをはじめ、MavenやコンテナイメージのリポジトリKubernetes Integrationなど多様なコミュニケーション機能や開発者向けの機能が追加されています。GitLabに求められる可用性は日々上がっている一方、ますます複雑になるGitLab運用は人間の手でやりたくないですよね。

そこで使えるのがGitlab Operator、Helmに次ぐ新しい"Cloud Native"なGitlabホスト方法です。

全体像

GitLab Operatorは様々なコンポーネントと接続してGitLabを起動する

検証環境

AWSのEKS上で実施します。ただEKS専用の機能を使う部分は限定的なため、他のKubernetes環境でも同じように起動することができるはずです。

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: ryusa-gitlab
  version: "1.21"

# 後述のExternalDNSとcert-managerをRoute53で管理するためのIRSAを定義
iam:
  withOIDC: true
  serviceAccounts:
  - metadata:
      name: external-dns
      namespace: external-dns
      labels: {}
    wellKnownPolicies:
      externalDNS: true
    roleName: eksctl-ryusa-external-dns-role
  - metadata:
      name: cert-manager
      namespace: cert-manager
      labels: {}
    wellKnownPolicies:
      certManager: true
    roleName: eksctl-ryusa-cert-manager

managedNodeGroups:
  - name: workers
    minSize: 1
    maxSize: 6
    desiredCapacity: 3
    spot: true
    instanceTypes: 
          - t3.medium
          - t3.large
    volumeSize: 60
    volumeType: "gp3"

Getting Startedする

依存関係のセットアップ

GitLab Operatorは

  • NGINX Ingress Controller
  • cert-manager
  • DNSを変更できるツール(今回はExternalDNSを採用)

を利用してGitLabを起動します。まずはこれらを適当にKubernetesにデプロイしておきましょう。

NGINX Ingress Controller

GitLabをKubernetesの外からアクセスできるようにするためのIngress ControllerとしてNGINX Ingress Controllerが推奨されています。実際にはIngress Controllerとして

  • Ingressのプロビジョニングができる
  • TCP:22でProxyができる(SSH用)

の2点が必要な機能だと思います。

kubernetes.github.io

推奨に従ってNGINX Ingress ControllerをKubernetesにHelmでデプロイします。使うHelmチャートはingress-nginx/ingress-nginxValueファイルは下記のYAMLで実装します。

# Helmチャート ingress-nginx/ingress-nginx 

controller:
  ingressClassResource:
    name: nginx
    enabled: true
    default: true
 
# NGINX Ingress ControllerにSSH用のTCPプロキシーを作成する
# 22: ${GITLAB_NAMESPACE}/${GITLAB_NAME}-gitlab-shell:22
tcp:
  22: "gitlab-system/vulture-gitlab-shell:22"

cert-manager

GitLabのTLS証明書を発行するためにインストールが必須です、GitLabのシステム内部で利用する自己証明書の作成もcert-managerのIssuerを使って実装されています。

cert-manager.io

推奨に従ってcert-managerをKubernetesにHelmでデプロイします。使うHelmチャートはjetstack/cert-managerValueファイルは下記のYAMLで実装します。一部項目にEKSからRoute53を変更するためのIRSAの設定が入ってますが、不要な方はスルーしてください。

# Helmチャート jetstack/cert-manager

installCRDs: true
 
# EKSのIRSAを利用するための設定
serviceAccount:
  create: false
  name: cert-manager
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::XXX:role/eksctl-ryusa-cert-manager
 
securityContext:
  enabled: true
  fsGroup: 1001

今回はIssuerとしてLet's Encryptを利用するため、Let's EncryptのACMEを持つClusterIssuerを先に作成しておきます。

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt
  namespace: cert-manager
spec:
  acme:
    email: YOUR_EMAIL
    privateKeySecretRef:
      name: letsencrypt-privatekey
    server: https://acme-v02.api.letsencrypt.org/directory
    solvers:
    - dns01:
        route53:
          region: YOUR_REGION
          hostedZoneID: HOST_ZONE_ID

External DNS

Ingressに割り振るドメイン名を自動的にDNSに設定するツールのインストールが推奨されています。GitLabをデプロイ後、デフォルトの状態で「GitLab」「MinIO」「Repository」の3つのIngressが作成され、それぞれ適切なドメイン名で名前解決できることが期待された状態でコンポーネントが起動してきます。

github.com

もちろん、Ingress作成後に手動でDNSを操作しても良いですが……素直にExternalDNSを利用した方が良いでしょう。今回はExternalDNSの公式リポジトリでホストされているマニフェストを利用してデプロイすることにします。

# 公式のRBACの定義は省略
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
  namespace: external-dns
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: external-dns
  template:
    metadata:
      labels:
        app: external-dns
      annotations:
        # IRSAのための設定
        iam.amazonaws.com/role: arn:aws:iam::XXX:role/eksctl-ryusa-external-dns-role
    spec:
      serviceAccountName: external-dns
      containers:
      - name: external-dns
        image: k8s.gcr.io/external-dns/external-dns:v0.7.6
        args:
        - --source=service
        - --source=ingress
        - --domain-filter=ryusa.example.com
        - --provider=aws
        - --policy=upsert-only
        - --aws-zone-type=public
        - --registry=txt
        - --txt-owner-id=some-identifier
      securityContext:
        fsGroup: 65534

GitLab Operatorインストール

公式ドキュメントに沿ってインストールしていきます。

docs.gitlab.com

❯ GL_OPERATOR_VERSION=0.1.0
❯ PLATFORM=kubernetes                
❯ kubectl create namespace gitlab-system
namespace/gitlab-system created
❯ kubectl apply -f https://gitlab.com/api/v4/projects/18899486/packages/generic/gitlab-operator/${GL_OPERATOR_VERSION}/gitlab-operator-${PLATFORM}-${GL_OPERATOR_VERSION}.yaml
Warning: apiextensions.k8s.io/v1beta1 CustomResourceDefinition is deprecated in v1.16+, unavailable in v1.22+; use apiextensions.k8s.io/v1 CustomResourceDefinition
customresourcedefinition.apiextensions.k8s.io/gitlabs.apps.gitlab.com created
serviceaccount/gitlab-app created
serviceaccount/gitlab-manager created
serviceaccount/gitlab-nginx-ingress created
role.rbac.authorization.k8s.io/gitlab-leader-election-role created
role.rbac.authorization.k8s.io/gitlab-nginx-ingress created
clusterrole.rbac.authorization.k8s.io/gitlab-app-role created
clusterrole.rbac.authorization.k8s.io/gitlab-manager-role created
clusterrole.rbac.authorization.k8s.io/gitlab-proxy-role created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRole is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRole
clusterrole.rbac.authorization.k8s.io/gitlab-metrics-reader created
rolebinding.rbac.authorization.k8s.io/gitlab-leader-election-rolebinding created
rolebinding.rbac.authorization.k8s.io/gitlab-nginx-ingress created
clusterrolebinding.rbac.authorization.k8s.io/gitlab-gitlab-app-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/gitlab-gitlab-manager-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/gitlab-gitlab-proxy-rolebinding created
service/gitlab-controller-manager-metrics-service created
service/gitlab-webhook-service created
deployment.apps/gitlab-controller-manager created
Warning: cert-manager.io/v1alpha2 Certificate is deprecated in v1.4+, unavailable in v1.6+; use cert-manager.io/v1 Certificate
certificate.cert-manager.io/gitlab-serving-cert created
Warning: cert-manager.io/v1alpha2 Issuer is deprecated in v1.4+, unavailable in v1.6+; use cert-manager.io/v1 Issuer
issuer.cert-manager.io/gitlab-selfsigned-issuer created
Warning: admissionregistration.k8s.io/v1beta1 ValidatingWebhookConfiguration is deprecated in v1.16+, unavailable in v1.22+; use admissionregistration.k8s.io/v1 ValidatingWebhookConfiguration
validatingwebhookconfiguration.admissionregistration.k8s.io/gitlab-gitlab-validating-webhook-configuration created
 
❯ kubectl get all -n gitlab-system
NAME                                             READY   STATUS    RESTARTS   AGE
pod/gitlab-controller-manager-645466b464-jxn5l   2/2     Running   0          2m5s
 
NAME                                                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/gitlab-controller-manager-metrics-service   ClusterIP   10.100.68.88     <none>        8443/TCP   2m10s
service/gitlab-webhook-service                      ClusterIP   10.100.163.107   <none>        443/TCP    2m9s
 
NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/gitlab-controller-manager   1/1     1            1           2m10s
 
NAME                                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/gitlab-controller-manager-645466b464   1         1         1       2m11s

いい感じに起動しますね、ヨシ!これからGitLab OperatorがWatchしているGitLabリソースをKubernetesにデプロイして、GitLab OperatorにGitLab本体をデプロイしてもらいましょう。

GitLabをデプロイする

GitLab Operatorをデプロイした際にGitLabリソースのCustom Resource Definition(CRD)もデプロイされています。

❯ kubectl api-resources --api-group apps.gitlab.com        
NAME      SHORTNAMES   APIVERSION                NAMESPACED   KIND
gitlabs   gl           apps.gitlab.com/v1beta1   true         GitLab

GitLab OperatorはOperator SDKのHelm Operatorで実装されています。つまりGitlabリソースのスキーマはHelmチャート(gitlab/gitlab)と同一になっています。

sdk.operatorframework.io

GitLabのHelmチャートを参考にしつつ、cert-managerとExternalDNS、NGINX Ingress Controllerと連携するGitLabリソースを作成していきます。

docs.gitlab.com

docs.gitlab.com

まずは*.ryusa.example.comワイルドカードの証明書のためCertificateリソースを作成しておきます。このリソースをあとでGitLabリソースに連携し、すべてのIngressがこのCertificateリソースを参照できるようにします。

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: gitlab-tls
  namespace: gitlab-system
spec:
  dnsNames:
  - "*.ryusa.example.com"
  issuerRef:
    group: cert-manager.io
    kind: ClusterIssuer
    name: letsencrypt
  secretName: gitlab-tls

Certificateリソースが作成され、TLS証明書が発行されたらGitLabをデプロイしましょう。

apiVersion: apps.gitlab.com/v1beta1
kind: GitLab
metadata:
  name: vulture
  namespace: gitlab-system
spec:
  chart:
    version: "5.2.4"
    values:
      global:
        hosts:
          # `gitlab` `registory` `minio`のサブドメインが生えてくる
          domain: ryusa.example.com
        ingress:
          # NGINX Ingress Controllerを使うように指定
          class: nginx
          configureCertmanager: false
          # *.ryusa.example.com ワイルドカード証明書を指定
          tls:
            secretName: gitlab-tls
      nginx-ingress:
        enabled: false
      certmanager:
        install: false

これでGitLabをKubernetes上に展開できました。(長い……)

サクッと運用してみる

それではGitLabで運用作業をやってみましょう!とはいえGitLab OperatorはDay 2 Operationを効率化するためのツールなので、バックアップやバージョンアップなどは非常にシンプルに行うことができます。

実際にコマンドを叩いて動かしてみます。

バックアップ

GitLabリソースを作成するとデフォルトでハウスキーピング用のTask-Runnerが起動します。このTask-Runnerにバックアップ含め様々な作業をお願いすることができます(らしい)。Task-RunnerのPodにはデフォルトでMinIOへの接続情報が保存されているため、Podの内部でbackup-utilityコマンドをキックするだけでバックアップを保存することができます。

docs.gitlab.com

❯ kubectl exec -it \
     -n gitlab-system task-runner-b854bfbd7-zrfgw -- backup-utility
Defaulted container "task-runner" out of: task-runner, certificates (init), configure (init)
Dumping database ... 
Dumping PostgreSQL database gitlabhq_production ... [DONE]
done
...
Dumping pages ...
empty
Packing up backup tar
[DONE] Backup can be found at s3://gitlab-backups/XX_gitlab_backup.tar

すごく簡単、これでMinIOのオブジェクトストレージにバックアップが保存されました。

MinIOのDashboard上でバックアップされたオブジェクトを確認できます

なお、GitLabリソースのTask-Runnerのサブチャートにバックアップのcron設定を追加することで定期的にバックアップを取ってくれるようになるらしいです。(未確認

apiVersion: apps.gitlab.com/v1beta1
kind: GitLab
metadata:
  name: vulture
  namespace: gitlab-system
spec:
  chart:
    version: "5.2.4"
    values:
      # 省略
      gitlab:
        task-runner:
          enabled: true
          backups:
            cron:
              enabled: true
              # 毎日朝3時にバックアップを取得
              schedule: '0 3 * * *'   

リストア

リストア……を完全自動化することはあまりないと思いますが、手動バックアップと同じようにデータをリストアすることができます。バックアップと同じようにTask-Runner Podのコンテナ上でbackup-utilityコマンドをキックするだけです。

docs.gitlab.com

❯ kubectl exec -it -n gitlab-system vulture-task-runner-7dd4d9c4bd-dgs6l \
     -- backup-utility --restore -f 'https://minio.ryusa.example.com/gitlab-backups/XXX_gitlab_backup.tar?...'
...
[DONE]
done

ただし上記コマンドでリストアできるのはデータのみであり、鍵などの秘密情報はリストアしてくれません。GitLabの再インストールなどする場合は、Secretリソースを自分でリストアする必要があります。(ドキュメントに記載あり)

GitLabアップグレード

Gitlabのバージョンをアップグレードするには、対応するHelmチャートのバージョンを変更してapplyすればOKです。あとの処理はOperatorが実施してくれます。

上記でインストールしたGitLabリソースのHelmチャートバージョンは5.2.4ですので、これを5.3.0にアップグレードにします。これによりインストールされるGitLabのバージョンが14.2.4から14.3.0に上がります。

docs.gitlab.com

apiVersion: apps.gitlab.com/v1beta1
kind: GitLab
metadata:
  name: vulture
  namespace: gitlab-system
spec:
  chart:
    # 5.2.4 -> 5.3.0
    version: "5.3.0"
    # あとは省略

kubectl apply でリソース変更後に

まとめ

GitLab Operatorを利用することでKubernetes上にGitLabを展開し、Kubernetesの言葉でGitLabを管理できるようになるところを確認しました。日時のバックアップや機能の拡張、アップデートなど日々の作業の多くをkubectlコマンドだけで管理できるようになるのは、少なくとも個人的には嬉しいですね。

今回はcert-managerやNGINX Ingress ControllerをGitLab Operator内蔵のものではないExternalなものと連携しましたが、他にもいくつかのコンポーネントをExternalに変更できるみたいです。特にPostgreSQLやObject Storageなどの状態を持つものはマネージドサービスで使いたいところですね。

docs.gitlab.com

このGitLab Operatorはまだまだ開発中とのことで、Issueを見ている限り面白そうなIssueがいくつか上がってます。(ダウンタイムなしアップグレードとか、アツい……!)

Operator: enable true Zero downtime upgrades (#59) · Issues · GitLab.org / Cloud Native / GitLab Operator · GitLab

現時点ではまだHelm版とOperator版のGitLabの間のクリティカルなギャップがあるわけではない(と思う)ですが、Operatorによる管理はHelmより柔軟な運用が可能になるのでこれからのロードマップに期待ですね。