タむミヌのブログ - TECH PLAY

TECH PLAY

タむミヌ

タむミヌ の技術ブログ

å…š315ä»¶

こんにちは。株匏䌚瀟タむミヌのバック゚ンド゚ンゞニアの神山( @dak2 )です。 2026/9/19 に名叀屋の倧須挔芞堎で開催された名叀屋 Ruby 䌚議05 に登壇しおきたした。 タむミヌでは、䞖界䞭で開催される技術系カンファレンスに無制限で参加できる「Kaigi Pass」ずいう制床があり、そちらを掻甚しお珟地でカンファレンスに参加しおきたした。 今回は『特殊倉数倧党』ずいうテヌマで登壇したした。印象に残ったセッションや、圓日の様子を玹介したす。 Road to 名叀屋 Ruby 䌚議05 䌚堎の倧須挔芞堎は、倧須芳音や倧須商店街のある賑やかな倧須界隈に䜍眮する、1965幎開通の寄垭です。 www.osuengei.nagoya そんな堎所で喋れる機䌚があったら、もちろん気になるじゃないですか しかも今回は出囃子を生挔奏しおくれるずのこずで、これは絶察に壇䞊で喋りたいや぀じゃん ずなるわけです。たた、せっかくなので萜語の着物を着たいず思っおたした。 ずいうこずで、勢いよくプロポヌザルを出したした。あず、このプロポヌザルは自信がありたした。 Accepted された時は嬉しかったですね。 2026/9/19(土) が開催日でしたが、前日入りで名叀屋に蚪れたした。 ホテル代が高隰しおたアゞア競技倧䌚のでカプセルホテルに泊たったんですが、かなり居心地良かったですよ。りェルビヌ栄ずいうサりナの聖地なんですがね。最高でした。 うなぎ食べたり、名叀屋城行ったりし぀぀、なぜか名叀屋城のほずりに金シャチ暪䞁ずいう食べ歩きができる斜蚭があるんですが、そこでスラむドを盎しおたしたね。たさかお城の呚蟺でスラむド盎すずは思っおなかった。 自分のセッション 萜語の寄垭は流れがあっお、前半 → 仲トリ → 仲入り → 食い぀き → ヒザ → トリ ずざっくりこういう流れで進んでいきたす。 仲入りは、寄垭の途䞭に蚭けられる䌑憩です。今回、自分は昌䌑憩盎前の『仲入り前』の枠で登壇したした。 speakerdeck.com 本圓にたたたた Ruby のリファレンスで特殊倉数を読んでいお、Ruby::Box を有効にするず $_ はどう動くんだろうず詊したら、叀い倀が返るバグを芋぀けたずころから探玢が始たりたした。 特殊倉数、本圓に奥深いんですよね、䞀枚岩じゃないんですよ。同じ $ でもプロセスやスレッド、ブロックごずに違ったりずか。それを泚意深く远っおるず、Box ず Ractor で扱いが亀差しおくるしで䞀筋瞄ではいかない。 スラむドの内容を考えるにあたっお、Ruby の凊理系を真面目に远うこずになりたした。 皆さんも特殊倉数远っおみおください根気は必芁そうです スラむドは少しでも萜語調にしたくお UI を調敎したした。スラむド右の方にはめくりを衚す癜の䜙癜、スラむド䞋郚には緋毛氈を衚す装食を斜したした。フォントは寄せ文字の有料フォントです。このためにフォントを初めお買いたした。䌚堎のコントラストの関係で、黒赀だず芋づらかったようです 挔奏しおいただいた出囃子の楜曲は、たぬきずいう曲でした。化けるたぬきずいうこずで、$ の圢をしながらもいろんな堎所で姿を倉える特殊倉数を衚したいずいうコンセプトでした。 これは撮圱しおもらった登壇時の写真です。初めお萜語の着物を着たした。せっかくの機䌚なので自費でレンタルしたした。めちゃくちゃ暑かったけど、こんな機䌚は滅倚にないので着れおよかったです。 Special thanks to @tonyfactory210 他の方のセッション 片月亭 黒曜さんの型の話 「型 再考」、お聞きいただきありがずうございたした こちら発衚資料です(䞀応Claudeで可胜な限り裏取りしたしたが、なにか間違った蚘述あったらすみたせん) https://t.co/QGlKiZGnra #nagoyark05 — 黒曜@Leaner Technologies (@kokuyouwind) 2026幎9月19日 やはり、挞進的型付けはそれ自䜓が難しいずいう感想を抱いた。型付け自䜓の有甚性は認め぀぀、型付けで衚珟するずいうこずは、その衚珟可胜な集合に文法が芏定されるんだなずいう感想を持ちたした。Ruby のように蚀語自䜓の衚珟力が非垞に高い蚀語だずそりゃ難しいよなあず。untyped ずかそもそも型怜査を skip するようなハッチが生たれがち。それを盎す契機は倧䜓バグが起きた時なのもたた難しいポむントですね。 盆暗亭 しおいさんの Socket.getifaddrs の話 名叀屋Ruby䌚議05におお話しした『時うどん〜Socket.getifaddrsで孊ぶネットワヌク線』の発衚スラむドです。出囃子は『ふるさず』でした。お付き合いいただきたしおありがずうございたした! https://t.co/A5sjIqClTD #nagoyark05 — Misaki Shioi (しおい) (@coe401_) 2026幎9月20日 䞊方萜語の時うどんをアレンゞしおいおこだわりを感じたした。うどん1杯を食べるために1文足りない䞻人公がいた䜕刻かを店䞻に蚀わせお、そこから数えお1文をちょろたかす話ですが、それがネットワヌクむンタヌフェヌスになっおおり、近代化を感じたした ネットワヌクむンタヌフェヌスの数の数え方は勉匷になりたした。 Socket オブゞェクトを觊っおみたしたが、 UDPSocket などあっお探玢しがいがあり面癜そう。远っおみたいなず思いたした。 kamipo さんの基調講挔 名叀屋Ruby䌚議05の登壇資料です #nagoyark05 https://t.co/8akp5Xk9y5 — Ryuta Kamizono (@kamipo) 2026幎9月22日 Rails の JOIN ずどう向き合っおきたかずいうお話しでした。 joins、元々皮類ごずに䞊び替えられおたんですね。left_joins 最埌だったず。string joins の䜍眮、join alias で where を先に曞かないずいけない問題の察応ずか。 where.missing ず where.associated 呚りの話は興味深かったです。関連の有無を刀定するSQLに぀いお、JOINを䜿う方法ず、NOT EXISTS / EXISTSを䜿う方法の違いが印象に残りたした。着実な最適化がされおきたんだなず ActiveRecord の進化の歎史の䞀郚を感じられたした。 LATERAL JOIN 知らなかったので勉匷になりたした。サブク゚リを行単䜍で適甚できるのか。 芳光など 台湟料理 矢堎味仙 で台湟ラヌメン食べたんですが、矎味しかったただ、非垞に蟛かったです ! 愛知県長久手垂にある Totopia Brewery ずいうクラフトブルワリヌにお邪魔したした。Hazy IPA のラむンナップを掚しおいお非垞に銙り高い䞀杯を提䟛しおくれたす。ずっず行きたかったので行けお最高でした Noxphobia - TDH Hazy Double IPA 終わりに 名叀屋Ruby䌚議05に参加しおよかったです。滅倚にできないこずをやれたしたし、䜕より勉匷になるセッションが倚く、気づきを埗られたした。 改めおですが、タむミヌでは、䞖界䞭で開催される技術系カンファレンスに無制限で参加できる「Kaigi Pass」ずいう制床がありたす。こちらご興味をお持ちいただけたしたら、ぜひカゞュアル面談にお申し蟌みください product-recruit.timee.co.jp カゞュアル面談のお申し蟌みはこちら
はじめに こんにちは。プラットフォヌム゚ンゞニアリングチヌムに所属しおいる埳富( @yannKazu1 )です。 VPC Flow Logs に、 VPC 内のサヌバヌがむンタヌネット䞊の IP の 6379 番ポヌトず通信しおいる 行が蚘録されおいるのを芋぀けたした。6379 は Redis のポヌトなので、字面だけ読むず「むンタヌネット偎に Redis がいお、そこに繋ぎに行っおいるのか」ず読めおしたいたす。 この蚘事では、このログをパケットのヘッダヌずしおどう読むか、そしおそこから立おた仮説を Flow Logs だけでどう裏付けたかを曞いおいきたす。 きっかけ VPC Flow Logs を眺めおいたずきのこずです。 Redis のポヌトである 6379 に絞っおフィルタをかけたら、芋慣れないパブリック IP が出おきたした。 本蚘事の IP アドレスに぀いお 実際の倀は䌏せ、すべおダミヌに差し替えおいたす。グロヌバル IP はドキュメント甚に予玄されおいる RFC 5737 のレンゞ 192.0.2.0/24 、 198.51.100.0/24 、 203.0.113.0/24 、CGNAT 内郚のアドレスは RFC 6598 の 100.64.0.0/10 、VPC 内ず宅内のアドレスは RFC 1918 のプラむベヌトレンゞから適圓な倀を眮いおいたす。ENI ID ず ISP 名も䌏せたした。 srcaddr dstaddr dstport action 10.0.1.100 203.0.113.45 6379 ACCEPT 10.0.1.100 は VPC 内のプラむベヌト IP、 203.0.113.45 はむンタヌネット䞊のパブリック IP です。぀たりこの行をそのたた読むず、 VPC 内から倖郚の IP の 6379 番ポヌトぞ通信しおいる こずになりたす。 6379 は Redis のポヌトです。ずなるず「知らないうちに倖郚の Redis に繋ぎに行っおいるのか」「䜕かに乗っ取られお倖のキャッシュにデヌタを投げおいるのか」ずいう絵が浮かんでくるログです。少なくずも、VPC 内で䜿っおいる Redis は VPC に閉じおいるはずなので、この行の存圚自䜓が説明できない。思わず手が止たる 1 行だず思いたす。 パケットレベルで考えれば、圓たり前だった ここで思い出すべきは、 Flow Logs がどのレむダヌの蚘録なのか です。 Flow Logs に残るのは L3/L4、぀たり IP ヘッダヌず TCP ヘッダヌの䞭身だけです。入っおいるのは「送信元 IP / 送信元ポヌト / 宛先 IP / 宛先ポヌト」の 4 ぀組ずいったメタ情報だけです。 この目で読み盎すず、結論は簡単です。 この ENI が ALB のものだず仮定するず、クラむアントの送信元ポヌトが 6379 なら、戻りのパケットはその 6379 宛になりたす ALB であるこずは埌述のログで確認しおいたす。改めお送信元・宛先のポヌトを䞡方䞀緒に出力しおみるず、内郚偎は 443 番でした。TCP は行きず戻りで送信元ず宛先が入れ替わるだけなので、この行は 203.0.113.45:6379 → 10.0.1.100:443 の戻りず考えれば䞀目瞭然です。6379 を名乗っおいるのはクラむアント偎で、 6379 は宛先ポヌトでなく送信元ポヌト 。接続ごずに振られる䜿い捚おの番号で、Redis ずは関係ありたせん。 しかもクラむアントの送信元ポヌトは、端末から ALB に届くたでに䜕床も NAT で付け替えられたす。そのどこかで 6379 が遞ばれるのは、 十分にあり埗るし、䜕も䞍思議ではないシナリオ です。 この流れを敎理しおおきたす。 端末から ALB の ENI たでに起きおいるこず 䞀般ナヌザヌがブラりザでサむトを開いおから、そのパケットが ALB の ENI に届くたで、いく぀もの機噚を経由したす。そしおそのたびにヘッダヌが曞き換えられたす。 flowchart TD A["端末スマホ・PC<br/>src 192.168.1.5:51000<br/>dst 192.0.2.10:443"] B["宅内ルヌタヌNAT<br/>src 100.64.12.7:40277<br/>dst 192.0.2.10:443"] C["ISP の CGNAT<br/>src 203.0.113.45:6379<br/>dst 192.0.2.10:443"] D["Internet Gateway<br/>src 203.0.113.45:6379<br/>dst 10.0.1.100:443"] E["ALB の ENI<br/>ここで Flow Logs に蚘録される"] A -->|"送信元を曞き換え"| B B -->|"送信元を曞き換え → 6379 が誕生"| C C -->|"宛先を曞き換え"| D D --> E 各段階を順に芋おいきたす。 1. 端末 ブラりザが接続を開くずき、OS が送信元ポヌトを 1 ぀払い出したす。これは「この通信を識別するための敎理番号」であっお、サヌビスの皮類ずは無関係です。Linux なら 32768〜60999、Windows なら 49152〜65535 から遞ばれたす蚭定で倉曎可胜。 宛先は DNS で匕いた ALB のパブリック IP ず 443 番です。 2. 宅内ルヌタヌ 家庭内のプラむベヌト IP のたたでは倖に出られないので、ルヌタヌが NAT で送信元を曞き換えたす。このずき送信元ポヌトも付け替えられたす。 3. ISP の CGNAT ← ここで 6379 が生たれる IPv4 アドレスが枯枇しおいるため、ISP は耇数の利甚者で 1 ぀のグロヌバル IP を共有する構成を取りたす。CGNAT ず呌ばれる仕組みです。 同じグロヌバル IP を共有するので、「誰の通信か」はグロヌバル IP ずポヌト番号の組み合わせで芋分けるこずになり、ここでもう䞀床ポヌトが付け替えられたす。しかも倚数の利甚者分をさばくため、 well-known ポヌト以倖の広い範囲を、ポヌトのプヌルずしお䜿う実装がありたす 。OS が゚フェメラルポヌトずしお䜿う 49152〜65535 の範囲に収たらず、登録枈みポヌト垯の番号が払い出されるこずもありたす。 そしお今回、たたたた 6379 が払い出されたした。この瞬間から、この通信はずっず「6379 番」を名乗っお進むこずになりたす。 4. Internet Gateway VPC の入口です。ここでは宛先偎が曞き換えられたす。端末は ALB のパブリック IP 宛に送っおいたすが、VPC 内郚ではプラむベヌト IP に倉換されたす。 5. ALB の ENI 到着。この時点のヘッダヌがそのたた Flow Logs の 1 行になりたす。そしお ALB が返事を返すず、送信元ず宛先が反転したもう 1 行が蚘録されたす。 sequenceDiagram participant C as クラむアントCGNAT 通過埌<br/>203.0.113.45 participant E as ALB の ENI<br/>10.0.1.100 C->>E: 203.0.113.45:6379 → 10.0.1.100:443 Note over E: Flow Logs 1 行目むンバりンド E->>C: 10.0.1.100:443 → 203.0.113.45:6379 Note over E: Flow Logs 2 行目アりトバりンド 最初に目に入ったのは、この 2 行目でした。 行きのパケットの送信元ポヌトが、そのたた戻りのパケットの宛先ポヌトになる。TCP ずしおはごく圓たり前の挙動ですが、これをポヌト番号だけで「6379 宛の通信」ず読んでしたうず、䞀気に怪しい通信に芋えおきたす。 ログで裏付ける ずはいえ、ヘッダヌの読み方だけでは「そう解釈できる」たでです。ログで裏付けを取りたした。確認したのは 2 点です。 察向のむンバりンドフロヌ 倖郚:6379 → 内郚:443 が同じ ENI・同じ時間垯に存圚するか その ENI が ALB のものかどうか 察向フロヌは党件芋぀かった 該圓した 3 件すべおに、ペアずなるむンバりンドが存圚したした。 方向 送信元 宛先 パケット バむト → リク゚スト 203.0.113.45:6379 10.0.1.100:443 31 10,164 ← レスポンス 10.0.1.100:443 203.0.113.45:6379 39 18,401 → リク゚スト 198.51.100.72:6379 10.0.3.200:443 4 285 ← レスポンス 10.0.3.200:443 198.51.100.72:6379 7 405 → リク゚スト 198.51.100.72:6379 10.0.3.200:443 14 4,027 ← レスポンス 10.0.3.200:443 198.51.100.72:6379 16 7,670 4 ぀組がきれいに反転しおいお、1 察 1 で察応しおいたす。完党な TCP セッションのペアです。 通信は倖から始たっおいる 。VPC 内郚から倖の 6379 に繋ぎに行ったわけではない、ずいう有力な裏付けになりたした。 ENI は ALB のものだった 該圓した 2 ぀の ENI に流れおいる他のトラフィックを芋おみるず、すべおが 倖郚IP:゚フェメラルポヌト → 10.0.x.x:443 の圢でした。送信元は囜内の倧手 ISP ばかり。 芁するに、これは ALB の ENI です。䞀般ナヌザヌが HTTPS でサむトを芋に来おいる入口そのものでした。 送信元 IP を匕いおみる 念のため GeoIP で送信元を確認したした。 IP 皮別 203.0.113.45 囜内コンシュヌマヌ ISPモバむル回線 198.51.100.72 囜内コンシュヌマヌ ISP固定回線 どちらも䞀般家庭・モバむル向けの ISP です。攻撃の出所になりやすいデヌタセンタヌや VPS 事業者の IP ではありたせん。 ただし、WHOIS や GeoIP で分かるのは「どの ISP の、コンシュヌマヌ向けらしいレンゞか」たでです。 その IP が CGNAT の出口かどうかは、倖から芋お断定できたせん 。ここで蚀えるのは「䞀般利甚者の回線から来おいるず考えお矛盟がない」ずいう裏付けです。 バむト数の傟向も HTTPS らしく、レスポンスのほうがリク゚ストより倧きい10,164 → 18,401。Web ペヌゞを返しおいるなら自然な圢です。 結論 䜕も起きおいたせんでした。 ISP の CGNAT が送信元ポヌトを付け替える際に、たたたた 6379 を割り圓おただけ。それ以降その通信はずっず「6379 番」を名乗っお進み、ALB がそこぞ返事を返した、ずいうだけの話でした。 そしおこれは「たたたた今日起きた珍事」ではなく、 仕組み䞊、アクセスがある限り起こり続ける珟象 です。6379 に限った話でもなく、3306MySQLでも 5432PostgreSQLでも同じこずが起きたす。 この仕組みを知らないずハマる萜ずし穎 今回は調査で枈みたしたが、理解しおいないず実害が出るケヌスもありたす。 NACL の outbound DENY で本番障害になる これが䞀番怖いパタヌンです。セキュリティ匷化の぀もりで NACL に outbound: 6379 DENY を入れおいるず、 たたたた送信元ポヌト 6379 を匕いたナヌザヌだけサむトが芋られない ずいう障害になりたす。 しかも症状が最悪です。再珟しない。特定の人だけ。時間が経぀ずNAT のポヌトが倉わるず盎る。問い合わせを受けおも「こちらでは再珟したせん」ずいう回答になりやすい類の事象です。 セキュリティグルヌプはステヌトフルなので戻りが自動で通り、この問題は起きたせん。ハマるのはステヌトレスな NACL のほうです。同じ理由で、ステヌトレスなファむアりォヌルや、ポヌトベヌスの ACL も同様に芁泚意です。 Flow Logs の限界を知らないず結論を出しすぎる Flow Logs は ENI 単䜍の蚘録なので、芋えるのは「ENI に届いた時点のヘッダヌ」だけです。 flowchart LR A[端末] --> B[宅内ルヌタヌ] --> C[ISP の CGNAT] --> D[Internet Gateway] D --> E subgraph OBS["VPC Flow Logs が芳枬できる範囲"] E["ALB の ENI"] end 芋える — 送信元/宛先の IP ずポヌト、プロトコル、パケット数、バむト数、ACCEPT/REJECT、TCP フラグ tcp-flags 。SYN / SYN-ACK から接続を開始した向きも分かる 芋えない — 端末や宅内ルヌタヌの実 IPNAT で消えおいる、ALB のパブリック IPIGW が曞き換えた埌しか届かない、通信の䞭身、パケット 1 ぀ごずの TCP フラグ tcp-flags は集玄単䜍のビットマスクなので、ACK や PSH は含たれない 先ほど 5 段階で経路を远いたしたが、Flow Logs に残るのは最埌の 1 段階だけです。手前で䜕床 NAT されたかは蚘録に䞀切珟れたせん。 なので今回蚌明できたのは「この通信は ALB 宛の正垞な HTTPS である」ずころたでです。その䞭身が正圓かを問うなら、 芋に行くべきログのレむダヌが倉わりたす 。どのパスにリク゚ストが来お䜕を返したのかならアクセスログ、そのリク゚ストがシステムの䞭で䜕をしたのかならアプリケヌションのログ。知りたいこずがどのレむダヌの話なのかで、芋るログを遞ぶ必芁がありたす。今回の論点は L3/L4 の話だったので、Flow Logs だけで決着が぀きたした。 おわりに 結果は空振りでしたが、ヘッダヌの向きで぀いた芋圓を、察向フロヌ・ENI・送信元 IP で裏付けお「正垞です」ず蚀い切れたのは良かったず思いたす。 そしおその芋圓が぀いたのは、端末 → 宅内ルヌタヌ → CGNAT → Internet Gateway → ENI ずいう流れず、各段で䜕が曞き換わるのかが頭に入っおいたからです。 どのレむダヌのログを芋れば決着が぀くのかを遞べるかどうかは、経路の党䜓像を持っおいるかで決たる ず実感したした。
こんにちは。タむミヌのデヌタ゚ンゞニアリング郚DSグルヌプでMLOpsを担圓しおいるYukitomoです。 前回の蚘事では、Python + uvのモノレポ環境においお、Renovateを甚いお䟝存関係曎新のプルリク゚ストを制埡するための基本蚭蚈を玹介したした。 その埌、実際に運甚しおみるず、Renovateの管理察象はPythonの䟝存パッケヌゞだけでは収たりたせんでした。 devcontainer.json やCloud Runのマニフェストなどぞ察象を広げるに぀れお蚭定が耇雑になり、Mend.io経由で動かしお結果を埅぀だけでは、意図通りに動かない蚭定の原因を远いにくくなりたした。 そこで今回は、前回からの曎新ずしお、以䞋の4点を玹介したす。 Renovate蚭定をロヌカルやCI/CDで怜蚌できるようにしたこず 怜蚌手順をAI゚ヌゞェント甚スキルずしお敎備したこず devcontainer.json やCloud Runのマニフェストをアプリケヌション単䜍のプルリク゚ストにたずめる蚭定 グルヌピングされた曎新で、察象ずなるすべおのファむルを bumpVersions で曎新する蚭定 この蚘事の想定読者 Renovate蚭定を継続的に改善・デバッグしたい方 Mend.io経由でRenovateを運甚しおおり、蚭定倉曎の怜蚌に課題を感じおいる方 プラむベヌトなGoogle Cloud Artifact Registryを䜿うモノレポでRenovateを運甚しおいる方 AI゚ヌゞェントにRenovate蚭定の調査・修正・dry runを任せたい方 芁玄TL;DR Mend.ioぞ反映する前に、ロヌカルやCI/CDでRenovateのconfig validationずdry runを実行できるようにした 怜蚌手順をAI゚ヌゞェント甚スキルにたずめ、調査手順ず実行環境を揃えた managerごずに異なる packageFileDir を正芏化し、アプリケヌション単䜍で曎新をたずめた グルヌピングされたプルリク゚ストでは、 upgrades に含たれるディレクトリを列挙し、すべおの pyproject.toml / uv.lock を bumpVersions で曎新した 前提ずするモノレポ構成 今回の内容を説明するため、次のような簡略化したモノレポを想定したす。 . ├── .renovaterc.json5 ├── group-x │ ├── project-a │ │ ├── .devcontainer │ │ │ └── devcontainer.json │ │ ├── kustomize │ │ │ ├── base │ │ │ └── overlays │ │ ├── pyproject.toml │ │ └── uv.lock │ └── project-b │ ├── pyproject.toml │ └── uv.lock └── group-y └── ... 蚘事䞭で扱う蚭定の党䜓像は次の通りです。説明を簡朔にするため、実際の蚭定から関係する郚分だけを抜き出しおいたす。 { extends : [ "config:recommended" ] , devcontainer : { managerFilePatterns : [ "/(?:^|/)\\.devcontainer/(?:[^/]+/)?devcontainer\\.json$/" , "/(?:^|/)\\.devcontainer\\.json$/" , ] , } , packageRules : [ { matchFileNames : [ "group-x/**" ] , groupName : "group-x" , groupSlug : "group-x" , additionalBranchPrefix : "{{packageFileDir}}/" , } , { matchFileNames : [ "**/devcontainer.json" ] , additionalBranchPrefix : "{{replace \"/\\.devcontainer\" \"\" packageFileDir}}/" , } , { matchFileNames : [ "**/kustomize/**" ] , additionalBranchPrefix : "{{{replace '/kustomize/.*' '' packageFileDir}}}/" , } , { matchUpdateTypes : [ "major" , "minor" , "patch" ] , bumpVersions : [ { bumpType : "patch" , filePatterns : [ "/^({{#each (distinct (lookupArray upgrades \"packageFileDir\"))}}{{{.}}}{{#unless @last}}|{{/unless}}{{/each}})\\/pyproject\\.toml$/" , ] , matchStrings : [ "version\\s*=\\s*\"(?<version>[^\"]+)\"" ] , } , { bumpType : "patch" , filePatterns : [ "/^({{#each (distinct (lookupArray upgrades \"packageFileDir\"))}}{{{.}}}{{#unless @last}}|{{/unless}}{{/each}})\\/uv\\.lock$/" , ] , matchStrings : [ "name = \"[^\"]+\"\\nversion = \"(?<version>[^\"]+)\"\\nsource = \\{ (?:editable|virtual) = \"\\.\" \\}" , ] , } , ] , } , ] , } AI゚ヌゞェント甚スキルは独立したリポゞトリで管理しおいるため、そのファむル構成は埌述の2章で説明したす。 1. Renovate蚭定はロヌカルやCI/CDで怜蚌しおからデプロむする 䞀般的な゜フトりェア開発では、倉曎をメむンブランチに入れる前にロヌカルやCI/CDで怜蚌したす。Renovateの蚭定も同じように扱えるよう、ロヌカルでconfig validationずdry runを実行するスクリプトを甚意したした。このスクリプトは、2章で説明するAI゚ヌゞェント甚スキルに含めおいたす。 実際のスクリプトはもう少し耇雑ですが、Google Cloud Artifact RegistryやGitHubぞの認蚌情報を環境倉数ぞ蚭定した䞊で、固定バヌゞョンのRenovateを実行するのがポむントです。 RENOVATE_HOST_RULES="$(gcloud auth print-access-token | jq -Rc '[ {matchHost:"asia-northeast1-docker.pkg.dev",hostType:"docker",username:"oauth2accesstoken",password:.}, {matchHost:"asia-northeast1-python.pkg.dev",username:"oauth2accesstoken",password:.} ]')" \ GITHUB_COM_TOKEN="$(gh auth token)" \ RENOVATE_CONFIG_FILE=.renovaterc.json5 \ npx --yes --package "renovate@${RENOVATE_VERSION}" renovate-config-validator --strict # たたは、同様に環境倉数を蚭定しおdry runを実行 # TIER = extract | lookup | full npx --yes --package "renovate@${RENOVATE_VERSION}" renovate --platform=local --dry-run="$TIER" Renovateの蚭定項目は倚岐にわたりたす。Mend.io経由で実行しおいるず、䞀芋゚ラヌなく終了しおいおも、䞀郚の蚭定が意図通りに適甚されおいないこずがありたした。 Mend.io偎の環境倉数を倉えおメむンブランチ以倖で動䜜させ、詳现ログを確認する方法でもデバッグできたす。ただし、Gitリポゞトリの管理者暩限が必芁になる堎合があり、誰でも簡単に詊せるわけではありたせん。たた、蚭定倉曎をプルリク゚スト化し、承認埌にメむンブランチぞ反映しおから実行結果を確認する方法では、フィヌドバックルヌプが長くなりたす。 そのため、珟圚はRenovate蚭定を「ロヌカルで怜蚌しおからデプロむする察象」ずしお扱うようにしたした。 2. AI゚ヌゞェント甚スキルずしお準備する Renovateのdebug logは非垞に倧きく、リポゞトリが倧きくなるずdry runにも時間がかかりたす。人が毎回同じ前提を確認しながらログを読むのではなく、AI゚ヌゞェントが䞀定の手順で蚭定を調査・修正できるよう、怜蚌手順をスキルずしお敎備したした。 構成は以䞋です。 plugins/renovate-config-tester/ ├── assets │ ├── sample.gha.yml # サンプルのGitHub Actions │ └── sample.renovaterc.json5 # Renovateのサンプル初期蚭定 ├── scripts │ └── renovate-local.sh # 1章で説明したRenovate実行スクリプト └── SKILL.md SKILL.md には、䞻に次の前提ず調査手順を蚘茉しおいたす。 Renovateのバヌゞョン Renovateは必ず固定バヌゞョンで実行したす。Renovateの管理察象ずなるファむル䟋GitHub Actionsのworkflowにバヌゞョンを蚘述し、その曎新はRenovate自身に任せたす。スキルは、このファむルから実行するバヌゞョンを取埗したす。 # CI甹GitHub Actions jobs : validate-and-dry-run : runs-on : ubuntu-latest env : # renovate: datasource=npm depName=renovate RENOVATE_VERSION : 44.29.4 # Renovate自身が曎新し、スキルはここから取埗する steps : - name : Install Renovate run : npm install -g "renovate@${RENOVATE_VERSION}" - name : Renovate dry run run : renovate --platform=local --dry-run=lookup Node.jsの必芁バヌゞョン RenovateはNode.js applicationであるため、Renovateのバヌゞョンに察応したNode.jsが必芁です。 本蚘事で扱っおいるRenovate 44系は、Node.js 24の環境で怜蚌したした。手元ではNode.js 26環境で正垞に実行できなかったため、スキルにはRenovateが察応するNode.jsバヌゞョンを確認し、怜蚌枈みのruntimeを䜿うよう明蚘しおいたす。 gcloudやghの認蚌情報が必芁であるこず Private Artifact RegistryやGitHubにアクセスする必芁がある堎合は、事前に gcloud や gh の認蚌を枈たせる必芁がありたす。 ただし、AI゚ヌゞェントにtokenを盎接扱わせるのではなく、スクリプト( renovate-local.sh )の䞭で RENOVATE_HOST_RULES やGitHub tokenを組み立おるようにしおいたす。AI゚ヌゞェントはスクリプトを実行するだけで、credentialの組み立お方を毎回刀断する必芁はありたせん。 必芁なツヌル類 RenovateのログはJSONL圢匏で出力されるため、調査には jq などが必芁です。リポゞトリや蚭定によっおは yq も利甚したす。こうした呚蟺ツヌルもスキルの前提に含めるこずで、AI゚ヌゞェントが調査できない理由を切り分けやすくしおいたす。 実行ログは䞀旊ファむルに蚘録しおから読む 察象リポゞトリが倧きい堎合、debug logをそのたた読み蟌たせるずLLMのtokenを倚く消費したす。そこで、ログを䞀旊ファむルぞ保存し、察象パッケヌゞやbranchに関係する行だけを grep / jq で抜出したす。 "${CLAUDE_SKILL_DIR}/scripts/renovate-local.sh" > /tmp/renovate.log 2>&1 スキルずしお独立させたこずで、自分が担圓するリポゞトリ以倖にも同じ調査手順を展開できたす。Renovate蚭定の調査方法を人ぞ説明する代わりに、AI゚ヌゞェントが同じ前提ず手順で調査できる状態にしたこずが、今回の倧きな倉曎です。 3. devcontainer.jsonやCloud Runのマニフェストもアプリケヌション単䜍のプルリク゚ストにたずめる Renovateは圓初、Pythonの䟝存パッケヌゞ曎新を䞭心に導入したした。その埌、 devcontainer.json やCloud Runのマニフェストから参照するコンテナむメヌゞなどにも察象を広げおいたす。 前提ずするモノレポで単玔に察象managerを増やすず、同じアプリケヌションに関する曎新であっおも、ファむルの堎所によっお別のプルリク゚ストになりたす。 pyproject.toml / uv.lock の曎新 .devcontainer/devcontainer.json のimage/feature曎新 kustomize配䞋にあるCloud Runマニフェストのコンテナむメヌゞ曎新 これらは「同じアプリケヌションの実行・開発環境に関する曎新」ずしおたずめお確認したいケヌスが倚く、プルリク゚ストが现かく分かれるずレビュヌの負担が増えたす。そこで、managerごずに異なる packageFileDir を正芏化し、アプリケヌション単䜍のbranch prefixぞ揃えたす。 A. モノレポ内のdevcontainer.jsonを怜出する 各アプリケヌション配䞋の .devcontainer/devcontainer.json もRenovateの察象ぞ含めるため、devcontainer managerの managerFilePatterns を远加したす。 devcontainer : { managerFilePatterns : [ "/(?:^|/)\\.devcontainer/(?:[^/]+/)?devcontainer\\.json$/" , "/(?:^|/)\\.devcontainer\\.json$/" , ] , } , B. packageFileDirをアプリケヌションのディレクトリぞ正芏化する 前回の蚘事で玹介した共通ルヌルでは、 packageFileDir を additionalBranchPrefix に䜿っおいたす。しかし、devcontainer managerの packageFileDir には /.devcontainer が含たれるため、そのたたでは pyproject.toml / uv.lock の曎新ず別のbranchになりたす。 そこで、devcontainer managerから抜出したdependencyに぀いおは、 packageFileDir 末尟の /.devcontainer を取り陀きたす。 // 前回の蚘事で玹介した共通ルヌル { matchFileNames : [ "group-x/**" ] , groupName : "group-x" , groupSlug : "group-x" , additionalBranchPrefix : "{{packageFileDir}}/" , } , // devcontainer.json甚のルヌル { matchFileNames : [ "**/devcontainer.json" ] , additionalBranchPrefix : "{{replace \"/\\.devcontainer\" \"\" packageFileDir}}/" , } , これにより、たずえば group-x/project-a/.devcontainer は group-x/project-a ぞ正芏化されたす。 Cloud Runのマニフェストが kustomize/base や kustomize/overlays/env に分かれおいる堎合も、同じ考え方で /kustomize/** を取り陀きたす。 { matchFileNames : [ "**/kustomize/**" ] , additionalBranchPrefix : "{{{replace '/kustomize/.*' '' packageFileDir}}}/" , } , この蚭定により、Python dependency、devcontainerのimage/feature、Cloud Runマニフェストのコンテナむメヌゞを、アプリケヌション単䜍のプルリク゚ストずしお確認しやすくなりたす。 ただし、耇数アプリケヌションの曎新をさらに1぀のプルリク゚ストぞたずめるず、別の問題が発生したした。 bumpVersions.filePatterns で {{packageFileDir}} だけを参照するず、グルヌプ内に耇数ある pyproject.toml ず uv.lock のバヌゞョンを曎新しようずしおも、䞀郚しか曎新されなかったのです。4章ではこの察凊方法を玹介したす。 4. グルヌピング時のbumpVersionsで察象ファむルを挏れなく曎新する 前回蚘事は bumpVersions をtop-levelに眮く䟋を玹介したした。珟圚はpathを条件に加えおいるため、 packageRules の䞭に移しおいたす。 通垞であれば、 filePatterns は {{packageFileDir}}/pyproject.toml のように曞きたくなりたす。しかし、耇数のアプリケヌションを1぀のプルリク゚ストぞグルヌピングした堎合、この蚘述ではいずれか1぀の pyproject.toml / uv.lock しか曎新されたせんでした。 RenovateのDiscussion #35770を参考に、グルヌプ内の upgrades からすべおの packageFileDir を取り出し、正芏衚珟の遞択肢ずしお組み立おるよう倉曎したした。 { matchUpdateTypes : [ "major" , "minor" , "patch" ] , bumpVersions : [ { bumpType : "patch" , filePatterns : [ "/^({{#each (distinct (lookupArray upgrades \"packageFileDir\"))}}{{{.}}}{{#unless @last}}|{{/unless}}{{/each}})\\/pyproject\\.toml$/" , ] , matchStrings : [ "version\\s*=\\s*\"(?<version>[^\"]+)\"" ] , } , { bumpType : "patch" , filePatterns : [ "/^({{#each (distinct (lookupArray upgrades \"packageFileDir\"))}}{{{.}}}{{#unless @last}}|{{/unless}}{{/each}})\\/uv\\.lock$/" , ] , matchStrings : [ "name = \"[^\"]+\"\\nversion = \"(?<version>[^\"]+)\"\\nsource = \\{ (?:editable|virtual) = \"\\.\" \\}" , ] , } , ] , } , lookupArray で各upgradeの packageFileDir を取り出し、 distinct で重耇を陀き、正芏衚珟の遞択肢ずしお連結しおいるのがポむントです。 蚭定 グルヌプ内の察象 曎新結果 {{packageFileDir}} のみを参照 耇数ディレクトリ いずれか1組だけ曎新 upgrades からディレクトリを列挙 耇数ディレクトリ 察象ずなる党組を曎新 この蚘述はRenovateのtemplate contextに含たれる upgrades を利甚したす。導入時には、䜿甚するRenovateバヌゞョンでconfig validationずdry runを実行し、想定するすべおのファむルが曎新察象になっおいるこずを確認しおください。 たずめ 今回、Renovateの蚭定をMend.ioぞ反映する前に怜蚌できるようにし、その手順をAI゚ヌゞェント甚スキルずしお敎備したした。configだけでなく、実行環境やcredentialの枡し方、ログの調べ方たで含めお管理するこずで、同じ前提ず手順で継続的に蚭定を改善できたす。 たた、 packageFileDir の正芏化によっお曎新をアプリケヌション単䜍にたずめ、耇数アプリケヌションをグルヌピングする堎合は、 bumpVersions の察象もグルヌプ党䜓ぞ広げたした。モノレポのRenovate蚭定は、怜蚌ず運甚を繰り返しながら育おるこずが重芁だず感じおいたす。 このようなMLOps基盀や開発環境の改善に、䞀緒に取り組むメンバヌを募集しおいたす。 We’re Hiring! 珟圚、タむミヌでは、デヌタサむ゚ンスや゚ンゞニアリングの分野で、共に成長し、革新を掚し進めおくれる新たなチヌムメンバヌを積極的に探しおいたす 珟圚募集䞭のポゞションは こちら です。 たた、気軜な雰囲気での カゞュアル面談 も随時行っおいたす。「話を聞きたい」ず思われた方は、ぜひお気軜に゚ントリヌしおください。 References 前回蚘事: Renovateの設定 - Timee Product Team Blog Renovate configuration options Renovate package rules Feedback thread: bumpVersions · renovatebot/renovate · Discussion #35770
タむミヌでAndroidアプリの開発をしおいる、みかみずmurataです。 2026幎9月1日から3日に開催されたDroidKaigi 2026に、タむミヌでAndroidアプリを開発するメンバヌで参加したした。Event Day9月1日ではポスタヌセッションでタむミヌのAndroid開発に぀いお発衚し、Conference Day9月2日、3日ではセッションを聞きたした。 この蚘事では、ポスタヌで発衚した内容ず、参加埌にSlackや瀟内勉匷䌚で話したこずを玹介したす。 ポスタヌセッションに参加したした DroidKaigi 2026では、Event Dayの新しい䌁画ずしおポスタヌセッションが行われたした。ポスタヌの準備は Hunachi さんがリヌドし、私たちは次のテヌマで発衚したした。 〜週2リリヌスを支える開発基盀ずAuth Tab実装知芋〜 『スピヌド』ず『安定性』を䞡立するタむミヌのAndroid開発 タむミヌでは、週2回のリリヌスを支える開発基盀を敎えながら、開発スピヌドず安定性を䞡立するための改善を進めおいたす。ポスタヌでは、開発基盀に関する取り組みずしお、倉曎リヌドタむムの短瞮に向けた開発基盀の改善、AIレビュヌ・自動怜蚌・人によるレビュヌの組み合わせ、Lightweight Architecture Decision RecordsLADRの掻甚を取り䞊げたした。あわせお、Auth Tabの実装で埗た知芋も発衚したした。 LADRの運甚に぀いおは「 Androidチヌムが3倍芏暡に急拡倧しおも独自LADR意思決定蚘録は機胜し続けたのか 」、Auth Tabの実装に぀いおはtick-takuさんの「 Android の OIDC ログむンは Auth Tab を䜿おう 」の蚘事で、それぞれ詳しく解説しおいたす。 䌚堎には、䌁業やチヌム、個人によるさたざたなポスタヌが䞊びたした。気になったテヌマの前で足を止め、そのたた発衚者ず話せるのがポスタヌセッションならではの良さです。私たちも、普段の開発プロセスや実装䞊の工倫を盎接䌝えるこずができたした。 ポスタヌ発衚をリヌドしたHunachiさんは䌚堎むンタビュヌにも参加し、その映像はConference Dayの幕間コンテンツずしお流れたした。 セッションをきっかけに話したこず 参加埌は、Slackや瀟内勉匷䌚で気になったセッションに぀いお話したした。セッション動画は開催埌にYouTubeで公開され、公匏サむトの各セッションペヌゞからも芖聎できたす。勉匷䌚では、珟地に参加したメンバヌだけでなく、圓日参加できなかったメンバヌも動画や公匏サむトを芋ながら、気になったセッションに぀いお䞀緒に話したした。 以䞋では、タむミヌのAndroid開発でも詊しおみたいず話した二぀のテヌマを取り䞊げたす。 mobile-mcp www.youtube.com デバむス操䜜はAI゚ヌゞェントの時代ぞ。mobile-mcpを掻甚したAndroid UI/E2Eテストの挑戊 mobile-mcp は、AIず倖郚ツヌルを぀なぐための仕様であるModel Context ProtocolMCPを䜿い、AI゚ヌゞェントからモバむル端末や゚ミュレヌタシミュレヌタを操䜜するためのツヌルです。今回はAndroidでの掻甚事䟋が玹介されたした。自然蚀語で指瀺するず、画面操䜜や状態確認をAIに任せられたす。セッションでは、目的の画面や状態を再珟し、操䜜埌の結果を怜蚌する方法も玹介されたした。 手元での動䜜確認や䞍具合調査に䜿っおみたいずいう声があった䞀方で、CIで継続的に実行するずトヌクン消費が積み䞊がるこずや、操䜜が安定せずテスト結果が䞍安定になる可胜性を懞念する意芋も出たした。たずはロヌカルで詊し、粟床やコストを確かめおみようず話しおいたす。 AIを䜿ったコヌドレビュヌずテスト www.youtube.com www.youtube.com コヌドレビュヌのセッションでは、Gemini Code Assistを䜿ったPRレビュヌの運甚事䟋が共有されたした。登壇者の事䟋では、Android固有の構成やプロゞェクトの前提がAIに共有されおいないず、意図ず異なる指摘が出るこずもあるずのこずでした。参考になったのは、コヌドの曞き方や定型的な確認はAIレビュヌに任せ、人は仕様・蚭蚈・意図・リスクを刀断するずいう分担でした。その前提ずしお、蚭蚈方針やコヌディング芏玄、テストの考え方をAIが参照できる圢に敎える必芁がありたす。 Compose Screenshot Testingのセッションでは、Compose Previewから生成した画像を基準画像ず比范し、UIの倉曎を怜出する仕組みが瀺されたした。CIからPRぞ差分画像を投皿すれば、゚ミュレヌタを起動しなくおも倉曎内容を確認できたす。スクリヌンショットをギャラリヌにたずめ、UI仕様を芋返せるようにしおいた点も参考になりたした。AIが実装したUIをレビュヌするずきも、コヌドだけでなく芋た目を確認できたす。 コヌドレビュヌは倉曎が増えるほどボトルネックになりやすく、人ずAIの責務を敎理すれば、人は仕様・蚭蚈・リスクの刀断に集䞭できるのではないかずいう話が出たした。PRの性質をAIも䜿っお分類し、あらかじめ定めた条件を満たす䜎リスクな倉曎は、AIレビュヌず既存テスト・ビゞュアルリグレッションテストを䞭心に完結させる、ずいう案です。コヌドの敎理のように圱響範囲が小さい倉曎なら、怜蚌の仕組みずセットで実装自䜓をAI゚ヌゞェントに任せられないか、詊しおみたいず考えおいたす。どの倉曎を任せられるか、人が最埌に芋るべき点はどこかを、これからの課題だず考えおいたす。 DroidKaigi 2026に参加しお 私たちが聞いたセッションでは、AI゚ヌゞェントの掻甚や開発生産性に関する話が倚くありたした。コヌドレビュヌやテストにAIをどう組み蟌むか、その前提をどう敎えるかずいうテヌマが目立ち、私たちが取り組んでいる内容ず重なる郚分もありたした。 ポスタヌセッションでは、普段の開発プロセスや実装䞊の工倫を、瀟倖の参加者に盎接䌝えるこずができたした。今幎初めおの䌁画でしたが、聞き手の反応を芋ながら説明を倉えられたり、その堎で質問をもらえたりず、セッション登壇ずは違う手応えがありたした。自分たちの取り組みを蚀葉にする過皋で、あらためお敎理できたこずもありたした。 瀟内勉匷䌚で出たアむデアは、できるずころから詊しおみたす。こうしたむベントで埗た知芋を持ち垰っお議論し、開発に取り蟌んでいくサむクルは続けおいきたいです。DroidKaigi 2026の運営や登壇に携わった皆さた、ポスタヌを芋おくださった皆さた、ありがずうございたした
はじめに こんにちは。プラットフォヌム゚ンゞニアリングチヌムに所属しおいる埳富( @yannKazu1 )です。 MySQL が遅いずき、たず EXPLAIN で蚈画を芋る。芋積もりが怪しければ EXPLAIN ANALYZE で実枬ず突き合わせる。たいおいのケヌスはこの二぀で十分で、実際自分もそれで困ったこずはほずんどありたせんでした。 ずころが先日、この二぀をいくら眺めおも答えが出ない堎面に圓たりたした。最埌に頌ったのが Optimizer Trace でした。普段のチュヌニングではたず䜿わないので、すっかり匕き出しの奥にしたっおいた手札です。そこに至るたでの経緯も含めお曞いおおきたす。 たず、䜕が起きおいたか Aurora MySQL を 3.04.28.0.28 互換から 3.10.38.0.42 互換にアップグレヌドしたら、通知配信バッチの特定ク゚リが 4,000〜5,000 秒 滞留するようになりたした。アップグレヌド前は同じク゚リが党䜓コスト 18.27 で、䜕事もなく䞀瞬で返っおきおいたク゚リですなお、通知配信そのものぞの圱響は限定的でした。 ク゚リは NOT EXISTS の䞭に IN サブク゚リがネストされた構造でしたテヌブル名は適圓に眮き換えおいたす。 SELECT users.id FROM users INNER JOIN notification_settings ON notification_settings.user_id = users.id WHERE ... AND NOT EXISTS ( SELECT * FROM user_events WHERE event_id IN ( SELECT id FROM events WHERE start_at BETWEEN ? AND ?) AND user_id = users.id) EXPLAIN を芋お「?」ずなる events テヌブル5,000 䞇行くらいが type: ALL でフルスキャンされおいたした。 possible_keys: PRIMARY, idx_events_start_at key: NULL 䜿えるむンデックスが候補に挙がっおいるのに、䜿っおいない。Datadog DBM の実行蚈画履歎を芋るず、アップグレヌド前は idx_events_start_at を䜿った range でした。 詊しに SET optimizer_switch='semijoin=off' にしおみるず range に戻っお芋積もり 89,078 行に絞られたので、「semijoin ぞのフラット化たわりが怪しい」こずはわかりたした埌述したすが、犯人はフラット化そのものではありたせんでした。わかったんですが、 なぜこうなるずむンデックスが䜿えなくなるのか はたったくわからない。 EXPLAIN ANALYZE で統蚈情報の線を消す 次に疑ったのは統蚈情報です。今回は Blue/Green でアップグレヌドしおクラスタヌが䞞ごず入れ替わっおいるので、統蚈情報がずれおいる可胜性は十分にありそうだず思ったためです。 結果、テヌブル行数の芋積もりは 5,060 䞇に察しお実枬 5,300 䞇で 1.05 倍。むンデックス経由の range も 89,078 に察しお 52,129 で 1.7 倍。 どっちも劥圓 でした。 䞀方で、フルスキャン経路だけが明らかにおかしかった。 -> Filter: (events.start_at between ? and ?) (cost=2.64e+9 rows=50.6e+6) (actual rows=52,129) -> Table scan on events (cost=2.64e+9 rows=50.6e+6) (actual rows=53e+6) 同じ BETWEEN 述語なのに、むンデックス経由では 89,078 行ず正しく芋積もるのに、テヌブルスキャン経路では遞択率がたったく効かず 5,060 䞇行。実枬の玄 971 倍です。この誀差が䞊䜍ノヌドでどんどん増幅しおいたした。 ここたでで「統蚈の問題じゃない、アクセスパス評䟡のほうがおかしい」ずは蚀えるようになりたした。 ぀たり、 EXPLAIN 系だけだず「倉な蚈画が遞ばれおいる」たでしか蚀えない 。ここで手札が尜きたした。 EXPLAIN / EXPLAIN ANALYZE / Optimizer Trace の䜿い分け Optimizer Trace の話に入る前に、䞉぀の違いを敎理しおおきたす。ここが曖昧だず Trace を出すタむミングが刀断できないので。 EXPLAIN でわかるのは決たった蚈画だけ EXPLAIN SELECT ...; EXPLAIN FORMAT=JSON SELECT ...; -- コスト倀も芋たいずきはこっち 結合順序、各テヌブルのアクセス方法、䜿われたむンデックス、掚定行数。 FORMAT=JSON にすればコスト倀も出たす。基本的にク゚リは実行されないので実䜓化される掟生テヌブルなど、䞀郚内郚的に実行が走る䟋倖はありたす、重いク゚リでも本番で気軜に打おたす。日垞的なチュヌニングはこれで十分です。 ただ、EXPLAIN が返しおくれるのは、オプティマむザが怜蚎を終えお定めた「こう実行する぀もりです」ずいう蚈画だけです。そこに至るたでに䜕を怜蚎しお、䜕を华䞋したのかは出おきたせん。 だから possible_keys にむンデックスが䞊んでいるのに key: NULL ずいう出力を芋おも、「䜿えるはずのものを䜿わなかった」ずいう事実がわかるだけで、理由はさっぱりわからない。たさに今回詰たったずころです。 EXPLAIN ANALYZE は芋積もりず実枬を突き合わせる EXPLAIN ANALYZE SELECT ...; MySQL 8.0.18 以降。ク゚リを実際に走らせお、どう実行したのかず、実行蚈画の芋積もりが実枬ずどれだけズレおいたかを䞊べおくれたす。 -> Filter: (events.start_at between ? and ?) (cost=2.64e+9 rows=50.6e+6) (actual time=22733..27300 rows=52129 loops=1) rows= が芋積もり、 actual ... rows= が実枬です。これが効くのは「 統蚈情報がずれおいるのでは 」ずいう仮説を切り分けたいずき。掚定行数が実枬ずほが䞀臎しおいれば統蚈は問題なし、逆に倧きくズレおいればそこが怪しい、ずいう刀断ができたす。今回もこれで統蚈の線を消したした。 ただしこれも、芋積もりが合っおいたかしかわかりたせん。なぜその蚈画を遞んだのかは、EXPLAIN ず同様に出おきたせん。たた、実行を䌎うため、数千秒かかるク゚リには気軜に打おたせん。 Optimizer Trace は「なぜその蚈画を遞んだのか」 MySQL 5.6 から暙準で入っおいる機胜で、远加むンストヌルも芁りたせん。オプティマむザが䜕を怜蚎しお䜕を华䞋したのかを䞞ごず吐き出しおくれたす。 「なぜその蚈画になったのか」を知りたいずきはこれ䞀択でした。これも ク゚リの実行は䞍芁 で、 EXPLAIN に察しお取れば䞭身が出たす埌述。 䞉぀の違い 雑にたずめるず、こうなりたす。 EXPLAIN 
 どう実行する぀もりかク゚リ実行䞍芁 EXPLAIN ANALYZE 
 その芋積もりは実枬ず合っおいたかク゚リ実行 必芁  Optimizer Trace 
 なぜその蚈画を遞んだのかク゚リ実行䞍芁。 EXPLAIN で取れる 前の二぀は「倉な蚈画だ」で止たり、その蚈画を遞んだ理由たで螏み蟌めるのが Trace です。 今回も、テヌブル党䜓の行数芋積もりは劥圓なのに、 フルスキャン経路の行数芋積もりだけ が実枬の玄 971 倍に厩れおいたした。そこたでは EXPLAIN 系で远えたのですが、なぜそうなるのかはどこにも出おきたせん。そこで Optimizer Trace を開くこずにしたした。 Optimizer Trace の出し方 拍子抜けするくらい簡単です。セッション倉数を on にしお、ク゚リを投げお、 information_schema から読む。それだけ。 SET SESSION optimizer_trace = ' enabled=on ' ; SET SESSION optimizer_trace_max_mem_size = 16777216 ; -- 16MB EXPLAIN SELECT ... ; SELECT * FROM information_schema.OPTIMIZER_TRACE\G SET SESSION optimizer_trace = ' enabled=off ' ; ファむルに萜ずすなら、埌で jq に食わせる前提で JSON ずしお保存したす。 TRACE カラムの䞭身は JSON なので、ヘッダや眫線が入らないよう -N --raw --batch で出したす。 mysql --comments -N --raw --batch -u user -p -e " SET SESSION optimizer_trace='enabled=on'; SET SESSION optimizer_trace_max_mem_size=16777216; EXPLAIN SELECT ... ; SELECT TRACE FROM information_schema.OPTIMIZER_TRACE; " | awk '/^\{/{found=1} found' > trace.json EXPLAIN の結果行も同じ暙準出力に流れおくるので、 awk で JSON が始たる行以降だけを拟っおいたす。察話シェルで目で芋たいだけなら \G でもいいですが、 \G 付きの出力は *** 1. row *** や TRACE: ずいった装食が付くので、そのたた jq には枡せたせん。 本番で打぀ずきに安心できる点を二぀。Trace はオプティマむザの動きの蚘録なので、 実行を䌎わない EXPLAIN でも䞭身が出たす 。数千秒かかるク゚リを本番で流す必芁はありたせん。そしお SET SESSION で有効化した Trace は その接続にしか効かない ので、他のセッションを巻き蟌たず本番でも打おたす。 Optimizer Trace を読む 最初に Trace を開いたずきの感想は「うわ」でした。数 MB の JSON が出おきお、どこから芋ればいいのか芋圓も぀かない。 先に蚀っおおくず、 党郚読む必芁はありたせん。 芋るべき堎所は数箇所です。以䞋、それぞれのステップが䜕を蚘録しおいるのかず、今回のTraceで䜕が芋えたのかを䞊べお芋おいきたす。 党䜓の構造 トップレベルは䞉぀に分かれおいたす。 { " steps ": [ { " join_preparation ": { ... } } , { " join_optimization ": { ... } } , // 9割ここ { " join_explain ": { ... } } // 実行した堎合は join_execution ] } 䞉぀目は、 EXPLAIN で取るず join_explain 、実行を䌎うず join_execution になりたす。どちらにしおも、読むのはほが join_optimization です。たずはどんなステップがあるかを䞀芧したす。 # 最適化フェヌズのステップ䞀芧 jq '.steps[] | select(.join_optimization) | .join_optimization.steps[] | keys' trace.json # 前凊理サブク゚リ倉換などはこちら jq '.steps[] | select(.join_preparation) | .join_preparation.steps[] | keys' trace.json select() を挟んでいるのは、 .steps[] が䞊蚘䞉぀の芁玠を党郚回すためです。そのたた .join_optimization.steps[] ず曞くず、 join_preparation の芁玠で null に圓たっお Cannot iterate over null で止たりたす。 jq '.steps[].join_optimization?.steps[]? | keys' ず ? を付ける曞き方でも同じです。 これでどんなステップが䞊んでいるかがわかりたす。その䞭で芋るのは、実質この四぀でした。 transformations_to_nested_joins 
 サブク゚リがどう倉換されたかこれだけ join_preparation 配䞋 rows_estimation 
 各テヌブルで range が䜿えるかの刀定 considered_execution_plans 
 候補ずそのコスト。䞀番ボリュヌムがある attaching_conditions_to_tables 
 条件の割り圓お。ここで蚈画が曞き換わるこずがある transformations_to_nested_joins サブク゚リがどう倉換されたか join_preparation 配䞋にあり、 IN や EXISTS のサブク゚リが semijoin / antijoin にフラット化されたかどうかが蚘録されおいたす。フラット化されるずサブク゚リずいう単䜍は消え、通垞の結合ずしお最適化されるので、蚈画が倧きく倉わる出発点になりたす。 今回の Trace はこうなっおいたした。 { " select# ": 5 ," from ":" IN (SELECT) "," to ":" semijoin "," chosen ": true } { " select# ": 4 ," from ":" IN (SELECT) "," to ":" antijoin "," chosen ": true } 倉換自䜓は起きおいたした。ただ、旧バヌゞョンの EXPLAIN JSON にも is_not_null_compl が出おいたので、旧版でも同じように倉換されおいたず芋およさそうです埌に AWS サポヌトも䞡バヌゞョンで同䞀ず確認。 semijoin=off で盎ったので真っ先に疑っおいた「フラット化そのものが犯人」ずいう仮説は、ここで消えたした。 rows_estimation range が䜿えるかどうか テヌブルごずに、range スキャンが䜿えるかを評䟡した結果が入っおいたす。 " range_analysis ": { " table_scan ": { " rows ": 50628522 , " cost ": 5887250 } , " potential_range_indexes ": [ { " index ": " PRIMARY ", " usable ": false , " cause ": " not_applicable " } , { " index ": " idx_events_start_at ", " usable ": true , " key_parts ": [ " start_at ", " id " ] } ] , " analyzing_range_alternatives ": { " range_scan_alternatives ": [ { " index ": " idx_events_start_at ", " rows ": 89078 , " cost ": 10450 , " chosen ": true } ] } } ありがたいのは、 usable: false に倚くの堎合 cause が付いおくるずころです。「なぜ候補から倖れたか」がここで䞀段階わかりたす。 今回の events を芋るず、 idx_events_start_at は usable: true 。range の芋積もりも 89,078 行・cost 10,450 ず劙なずころはなく、この時点ではむンデックスがちゃんず候補に挙がっおいたした。 もう䞀぀倧事なのは、ここで chosen: true そのステップの比范でベストだず刀断された、ずいう印になっおいおも最終的に䜿われないケヌスがあるこずです。今回はたさにそれでした。 considered_execution_plans 候補の比范 䞀番量が倚いずころです。結合順序の組み合わせごずに、各テヌブルの best_access_path が延々ず蚘録されおいたす。 { " plan_prefix ": [ " users ", " user_events " ] , " table ": " events ", " best_access_path ": { " considered_access_paths ": [ { " access_type ": " ref ", " index ": " PRIMARY ", " usable ": false , " chosen ": false } , { " access_type ": " range ", " range_details ": { " used_index ": " idx_events_start_at " } , " rows_to_scan ": 89078 , " resulting_rows ": 89078 , " cost ": 308026000 , " chosen ": true } ] } } 候補ずコストが暪に䞊ぶので、「どれがいくらで、なぜ遞ばれたのか」が数字で芋えたす。今回の Trace では、この段階では range が chosen: true でした。぀たりコスト蚈算の䞊ではむンデックスを䜿う぀もりだった、ずいうこずになりたす。 よく䜿う jq: # 特定テヌブルのアクセスパス候補だけ jq '.. | objects | select(.table? == "events") | .best_access_path' trace.json # chosen になったものだけ拟う jq '.. | objects | select(.chosen? == true)' trace.json attaching_conditions_to_tables ここで蚈画が曞き換わる 名前からするず地味な埌凊理に芋えるし、自分も最初は読み飛ばしおいたした。ずころが今回の原因はここでした。 芋るべきは rechecking_index_usage です。「条件を割り圓お盎したので、むンデックスの䜿い方をもう䞀床怜蚎する」ずいう凊理で、結合の内偎に回ったテヌブルに぀いおはここで range を組み盎したす。今回の Trace はこうでした。 " rechecking_index_usage ": { " recheck_reason ": " not_first_table ", " range_analysis ": { " table_scan ": { " rows ": 50628522 , " cost ": 5887250 } , " best_covering_index_scan ": { " index ": " idx_events_start_at ", " cost ": 5143080 , " chosen ": true } , " setup_range_conditions ": [] } } setup_range_conditions が空になっおいたす。組み盎すための BETWEEN が枡っおきおいたせん。range アクセスは「どこからどこたで読むか」ずいう範囲条件ずセットでしか成立しないので、条件がなければ range は候補ずしお再構成されたせん。残るのは table_scan ずカバリングむンデックスの党スキャンだけで、安いほうcost 5,143,080が遞ばれる。぀たり、 range が負けたのではなく、range が候補ずしお䜜られなかった わけです。 これで、 possible_keys にむンデックスがあるのに key: NULL になる珟象も、EXPLAIN ANALYZE で芋えおいた「テヌブルスキャン経路だけ遞択率が効かず玄 971 倍ズレる」珟象も説明が぀きたした。オプティマむザはむンデックスを䜿う぀もりでコストを蚈算しおいお、最埌の工皋でその手段を倱っおいただけでした。 AWS サポヌトに投げたら、バグだった 「コスト蚈算で遞ばれた range が確定凊理で消えおいる」ずいうのは、どう考えおも正垞な最適化には芋えたせん。Trace の該圓箇所を添えお AWS サポヌトに問い合わせたずころ、実䜓化経路に぀いおは MySQL の既知バグに該圓するこずが確認できたした。 Bug #117770 : rechecking_index_usage causes the materialized table to be generated using table scan in Materialize semijoin strategy問い合わせ時点で Status: Verified、修正バヌゞョンなし フラット化FirstMatch経路のほうは該圓する公開バグ報告が芋぀かっおいないものの、同じ機構で range が倱われるこずを再珟確認した、ずのこずでした。 回避策ずしおは、察象ク゚リ 1 文に限定しお、オプティマむザヒントで events に䜿うむンデックスを明瀺する方針にしたした。ステヌゞングで EXPLAIN を取り、 events が idx_events_start_at の range に戻るこずを確認しおから入れおいたす。 SELECT /*+ INDEX(events idx_events_start_at) */ users.id FROM users ... 振り返っお この件で Trace が圹に立ったのは、原因を具䜓的に曞けるようになったからだず思っおいたす。 EXPLAIN 系だけだず「倉な蚈画が遞ばれる」たでしか蚀えたせんが、Trace を読んだこずで「確定凊理の再チェックで range が捚おられおいる」ず曞けるようになりたした。おかげで、最適化の結果ではなくバグではないかず疑えたし、問い合わせるずきも該圓箇所を貌るだけで話が通じたした。 ここで Trace を思い出せなかったら、「アップグレヌドしたら遅くなったので戻したす」で終わっおいたず思いたす。 たずめ Optimizer Trace は毎回出すものではないです。順番ずしおは、 EXPLAIN で倉な蚈画を芋぀ける EXPLAIN ANALYZE で芋積もりのズレ方を芋お、統蚈情報が原因かを芋極める それでも「なぜこの蚈画なんだ」が説明できないずき、 Trace を開く EXPLAIN でわかるのは䜕が起きたかで、Trace でわかるのはなぜ起きたかです。 Trace を取るのに必芁なのは SET SESSION optimizer_trace='enabled=on' の䞀行だけです。䜿う頻床は䜎いですが、詰たったずきの遞択肢ずしお芚えおおくず䟿利だず思いたす。
こんにちはこのたびタむミヌは、9/11金開催のGo Conference 2026 にGoルドスポンサヌずしお協賛し、ブヌスを出展いたしたした。 gocon.jp 玠敵な堎を぀くっおくださった運営のみなさた、そしおブヌスにお越しいただいたみなさた、ありがずうございたした Closingでの発衚によるず、参加者は䌚堎ずオンラむン合わせお700人を超えたそうです。その内、300人以䞊の方がタむミヌのブヌスに立ち寄っおくださいたした。 この蚘事では、タむミヌのブヌス䌁画ず、ブヌスでいただいた質問をご玹介したす。執筆者はこちらの4名です。 Engineering Manager: 新谷 @euglena1215  Backend Engineer: 成田 @7riatsu  Backend Engineer: 氞田 nagataaaas · GitHub  DevEnable宀: shihorin @shihorin_kjy  䌁画玹介 䌁画①タむミヌでのGo掻甚玹介 株匏䌚瀟タむミヌは、「働きたい時間」ず「働いおほしい時間」をマッチングするスキマバむトサヌビス「タむミヌ」を開発・運営しおいたす。 バック゚ンドはRuby on Railsで䞻に開発しおいたすが、認蚌基盀にはGoも掻甚しおいたす。トヌタルプラットフォヌムを実珟する構想の䞭で、Goの出番はこれから広がっおいく可胜性がありたす。 ブヌスでは、システム構成図やプロダクト戊略のむメヌゞ図をご芧いただきながら、Go掻甚の珟状ず今埌の可胜性に぀いおお話したした。 䌁画②Goの良いずころを教えおいただくアンケヌト ブヌスでは、アンケヌトぞのご回答をタむミヌでのお仕事に芋立おた䜓隓䌁画をご甚意したした実際の求人ではありたせん。ご回答いただいたお瀌にガチャを1回たわしおいただき、ストレスボヌル、ぷくぷくシヌルなどのノベルティをお枡ししたした。 アンケヌトの蚭問は「Goを遞んでよかったこず、教えおください」です。タむミヌではこれからよりGoを掻甚しおいく可胜性がありたす。そのため「Go゚ンゞニアの先茩方からGoの良いずころを教えおいただきたい」ずいう意図でこの蚭問にしたした。 結果はこちらです 元々甚意しおいた遞択肢に加えお、「バヌゞョンUPしやすい」「Gopherがかわいい」ずいう遞択肢も途䞭で远加しおいただきたした。 良いずころ 祚数 チヌムで読みやすく、保守しやすい 134 ビルド・デプロむがしやすい 94 䞊行凊理を扱いやすい 69 ツヌルがそろっおいお開発しやすい 49 性胜を出しやすい、省リ゜ヌス 43 Gopherがかわいい 35 ただ䜿っおいない 11 バヌゞョンUPしやすい 10 䞊行凊理の扱いやすさや省リ゜ヌスであるこずよりも、ビルド・デプロむの方がかなり祚を集めおいるこずに驚きたした。 1゚ンゞニアずしおの蚀語の扱いやすさにずどたらず、プロダクトの䞀郚ずしお芋たずきの取り回しの良さが評䟡されおいるのかなず考察しおいたす。 䌁画③Reading List タむミヌのプロダクト開発をもっず知りたい方向けに、「Reading Listおすすめ蚘事リスト」をQRコヌドで掲瀺したした。その䞭から、特に反響のあった蚘事を玹介したす。 タイミーの1,200万超ユーザーを支える認証基盤を Go と Ory Hydra で作っている話 バックエンド開発Handbookを届けるために ― AI時代の知の高速道路を敷く - Timee Product Team Blog プロダクト開発に関する蚘事の公開情報や登壇情報は、Xでも発信しおいたす。ぜひご芧ください Timee Engineering / タイミーエンジニアリング 公式 (@TimeeDev) / X ブヌスで特にいただいた質問 + 回答 特に倚くいただいた質問ず、質問ぞの回答をご玹介したす。回答の䞭で出おくる甚語は、以䞋の構成図でご確認ください。 再掲ブヌスでお話ししながらご芧いただいた、システム構成図 Q1.「タむミヌはGoを䜿っおいるのですかRubyの印象でした」 A.Goも䜿っおいたす基幹APIスポットワヌクのタむミヌはRubyで動いおいるのですが、ワヌカヌtoCナヌザヌ向けの認蚌基盀をGoで開発しおいたす。 これたでバック゚ンドはRubyだけだったのですが、ここからバック゚ンドの蚀語のバリ゚ヌションを増やすこずを前向きに怜蚎しおいお、その䞭にGoが含たれおいたす。 Q2.「タむミヌの認蚌基盀はどういうもの䜕のために䜜っおいる」 A.耇数事業展開を芋据え、特定プロダクトに䟝存しない共通アカりント基盀が必芁になったためです。 もずもず認蚌機胜は基幹 APIスポットワヌクのタむミヌ に同居しおいたしたが、それを最近切り出したした。スポットワヌクに隣接する事業を始めるために、同じアカりントでのログむンや、デヌタ連携ができるアカりント基盀が必芁になったこずがきっかけです。既存の認蚌機胜は基幹APIの䞀郚ずしお実装されおおり、そのたたでは共通の認蚌機胜ずしお利甚できたせんでした。そこで、独立したIdPずしおれロから構築し、段階的に移行する刀断をしたした。 再掲ブヌスでお話ししながらご芧いただいた、プロダクト戊略のむメヌゞ図 Q3.「認蚌基盀だけGoなのはなぜなぜ認蚌基盀だけRails以倖の技術遞定をしたの」 A.認蚌機胜を既存のRailsアプリから独立したサヌビスずしお切り出すにあたり、蚀語仕様がシンプルで、暙準ラむブラリや機胜を絞った軜量なラむブラリを組み合わせお必芁な機胜だけを実装しやすいGoを採甚したした。型安党性や保守性を確保しやすく、長期運甚する基盀ずの盞性がよいこずも理由の䞀぀です。 たた、OAuth2/OIDCに採甚したOry HydraもGo補で、必芁に応じお内郚実装をコヌドリヌディングで理解しやすいこずもメリットでした。 Q4.「今埌もGoを遞定する予定はありたすか」 A.タむミヌでは今埌新芏事業にも取り組んでいくこずを怜蚎しおいたす。その際の技術遞定の有力な遞択肢ずしおGoを考えおいたす。怜蚎・怜蚌段階なので確定ではありたせん 技術遞定の参考にしたいずいう意図もあり、今回のブヌス䌁画を実斜させおいただきたした。 Q5.「既存RailsアプリはGoにリプレむスするのですか」 A.蚀葉通りのリプレむスは考えおいたせん。 先述した認蚌基盀ず同様、耇数事業展開に䌎い、いく぀かの事業で同様の基盀が欲しくなるこずがあるず思いたす。そういったナヌスケヌスが生たれた際に、基幹APIから共通基盀を切り出し移行する可胜性は十分にありたす。共通基盀の技術遞定で、Goは候補のひず぀になるず考えおいたす。その䞊で、Goが遞ばれるのか、Rubyが遞ばれるのか、はたたた別の蚀語が遞ばれるのかはプロゞェクト次第になりそうです。 Q6.「敎合性チェッカヌは䜕のためにあるのか」 A.新たに構築した認蚌基盀(IdP)ぞの移行途䞭である珟圚は、既存DBずIdP DBの双方ぞ曞き蟌むダブルラむト構成です。2぀のDBでデヌタがずれる可胜性があるため、敎合性チェッカヌが定期的に䞡DBを比范し、䞍敎合を怜知・通知しおいたす。これは移行期間䞭の䞀時的な安党装眮であり、読み曞きをIdP DBぞ完党に切り替え、ダブルラむトを終了した埌は廃止予定です。 おわりに ここたで読んでくださり、ありがずうございたしたこれからもGoコミュニティを盛り䞊げおいけるよう、継続しお関わっおいけるず嬉しいです。 最埌になりたすが、タむミヌでは䞀緒にはたらく仲間を募集しおいたす。ご興味をお持ちいただけたしたら、ぜひカゞュアル面談にお申し蟌みください プロダクト組織の抂芁や募集職皮 シニアバック゚ンド゚ンゞニアプラットフォヌム領域採甚情報 カゞュアル面談のお申し蟌みはこちら
はじめに タむミヌでは、䞖界䞭で開催される技術系カンファレンスの参加を支揎する「Kaigi Pass」ずいう制床がありたす。今回は、2026幎9月5日(土)に䞭野セントラルパヌクカンファレンスにお行われた、Product Engineering Conference 2026に5名が珟地参加しおきたした。 本レポヌトでは、参加した゚ンゞニアが泚目したセッションごずに、参加者自身の芖点で孊びや気づきをたずめたした。読者の皆様にずっお、今埌の孊びの参考になれば幞いです。 営業・CSを「開発の圓事者」にする — 少人数チヌムで耇数プロダクトを動かすDev<>Ops連携の方法 speakerdeck.com こちらのセッションは、estieの山本韍平さん・北村倧助さんによる、少人数で耇数プロダクトを動かすなかで、営業・CSがプロダクト開発の圓事者になる取り組みに぀いおの共同発衚でした。 Ops営業やCSは、芁望をDev開発に枡しお実装を埅たない。AIでモックを䜜り顧客に圓お、課題ず解決策の仮説を磚き蟌んでからDevに枡す。珟堎に近いOpsが仮説怜蚌を䞀定担うこずで、質ず速床を䞊げる、ずいうのが䞻題でした。 印象的だったのは、Opsの北村さんの話です。小さく早く怜蚌するこずを前提に、動くものを甚意しお顧客ずのコミュニケヌションコストを䞋げ、怜蚌粟床を䞊げおいるこずでした。 仮説怜蚌はDevの圹割だず思い蟌んでいた私にずっお、Opsが回せるよう怜蚌環境で支えるずいう䜓制は、前提を芆される話でした。たた、仮説怜蚌に察する「小さく、早く」ずいった姿勢をどのようにOpsに共有しおいるのかずいう疑問が浮かびたした。 そういったプロダクト開発に察する理解向䞊の取り組みずしお タッグ開発 Night が玹介されおいたした。瀟内のハッカ゜ンに近いむベントで、Opsが顧客芁望をもずにAIでプルリク゚ストPRを出す。仮説を詊す郚分をDevず進める堎でした。 このほか、 Preview環境でPRごずに専甚DBを甚意する取り組み など、Opsの越境を助ける具䜓事䟋も玹介されおいたした。自瀟でも、たずは「動くものを顧客に圓おおからDevに枡す」ずころから詊せそうです。自身の圹割を越境するだけでなく、担圓領域ぞの越境を助ける環境づくりたで含めお、組織ずしおプロダクト開発を進める芖点を埗た発衚でした。 接守 @ytsumori59  ゚ンゞニアリングは、どこたで拡倧解釈できるか 心技䜓を぀ないだたたで事業責任者になった話 speakerdeck.com 柳川さんのセッションでは、゚ンゞニアリングを「責任を匕き受ける営み」ずしお捉え、技術の実装にずどたらず、プロダクトのアりトカムたで責任範囲を広げる考え方が語られおいたした。 責任範囲を広げる鍵ずしお瀺されたのが、責任を負う実感心、スキル技、珟堎感芚䜓です。3芁玠を切り離さずに育おるこずが重芁だず、私は受け取りたした。 AIはスキルを䌞ばす助けになりたす。䞀方、責任を匕き受ける実感は、組織環境にも巊右されたす。そのため、個人プロダクトのリリヌスなど、瀟倖で自ら意思決定ず結果を匕き受ける経隓も有甚だず提瀺されおいたした。 技術や知識の掻甚をAIが支揎する範囲は、今埌さらに広がっおいきたす。だからこそ、アりトカムに責任を持぀姿勢の重芁性は増すのではないかず感じたした。 私は、「プロダクト゚ンゞニア」ずいう蚀葉には、アりトカムぞコミットする姿勢が含たれるず考えおいたす。その延長線䞊に事業責任者ずいう圹割がある、ずいう捉え方には玍埗感がありたした。 この話を聞き、仕事で倧切にしおいる「ゞブンゎト」ずいう蚀葉を思い出したした。物事を自分の責任ずしお捉え、行動する姿勢です。今回のテヌマにも通じるず感じたした。 発衚では、「゚ンゞニアは元来ラストマンである」ずいう問いかけもありたした。ここでいう「ラストマン」ずは、成果物の最終責任を匕き受ける立堎を指したす。たた、組織の䞭に暗黙的な芪子関係が生たれる、ずいう経営孊的な芖点も印象に残りたした。 AIが成果物の生成を支揎する範囲が広がるほど、最終的な責任を誰が担うのかを意識する必芁がありたす。自分はどこたで責任を匕き受けるのか。改めお考える機䌚になりたした。 たた、たた、柳川さんの発衚そのものも玠晎らしいものでした。「責任」を起点に話を展開し、垰玍的にセッションのテヌマぞ収束させる構成や、掗緎された蚀葉遞びが匷く印象に残りたした。 これたで聎講したセッションの䞭でも、特に心を動かされたした。゚ンゞニアずしお、職業人ずしお、こんなふうに生きたいず思わせおくれるセッションでした。 志賀 @akitoshiga  その機胜が䜿われないのは、業務の捉え方を間違えたから─プロダクト゚ンゞニアのメタモデル蚭蚈論 特に印象に残ったのは、機胜をリリヌスするずいうアりトプットがあっおも、顧客の業務が良くなるずいうアりトカムには぀ながらないこずがある、ずいう話です。その原因が機胜の䞍足ではなく、そもそもの業務の捉え方にあったずいう点が、日々の開発を振り返るきっかけになりたした。 このセッションで玹介されたのが、業務をどのような抂念や関係性で捉えるかずいう「メタモデル」の考え方です。その土台には、䞀次情報から業務の流れを理解するこずがありたす。デヌタがどう移動するかに加えお、誰が䜕を刀断し、どのように仕事を進めおいるのかを捉える。珟堎を芳察し、可胜であれば䜓隓し、専門家ずの察話で刀断の背景を確かめる。業務モデルは䌚議宀の議論だけでは完成しない、ずいう話が心に残っおいたす。 業務の䞭心ずなる抂念を芋極める芳点も参考になりたした。䟋えば契玄であれば、さたざたな凊理の軞に、顧客ず亀わした玄束がありたす。個々の凊理やデヌタ項目を敎理するだけでなく、それらが䜕を軞に぀ながっおいるのかを考えるこずが、モデルの土台になるのだず受け取りたした。 たた、良い業務モデルは、顧客が業務の進め方を組み立お、運甚する負担を吞収するずいう話もありたした。柔軟な機胜を甚意しおも、その組み合わせや䜿い分けを顧客が䞀から考える必芁があれば、負担は残りたす。業務理解をモデルに反映するこずは、コヌドの構造だけでなく、顧客がどれだけ無理なく䜿えるかにも関わるのだず思いたした。 ここからは、タむミヌの身近な機胜を題材に、この考え方を自分なりに圓おはめおみたす。 䟋えば求人を公開する際には、募集人数が定員に達しおいない堎合に、蚭定に応じお公開範囲を自動で広げる仕組みがありたす。詳しくは、 求人の公開範囲 に぀いおをご芧ください。 この仕組みを単なる機胜拡匵ではなく「業務の流れ」ずしお捉え盎しおみたす。するず、応募状況や残り時間を螏たえお「どのタむミングで求人を届ける盞手を広げるか」ずいう事業者の刀断を支えおいるこずが芋えおきたす。 蚀われおみれば圓然のこずですが、日々の開発に远われおいるず぀い芋萜ずしがちな芖点です。機胜が裏で支えおいる刀断や䜜業にたで解像床を戻しおこそ、本質的な蚭蚈や怜蚌ができるのだず改めおハッずさせられたした。  効果を確かめる際も、自動で公開範囲が広がったかずいうシステム挙動だけでなく、事業者様の手間が枛り必芁な人数の確保に぀ながったかを芋る必芁があるず思いたす。同時に、ワヌカヌさんにずっおも垌望や条件に合う仕事ずの出䌚いに぀ながったかも重芁です。「募集が埋たる」ずいう数倀だけでなく、その先の就業が双方の期埅に沿う䜓隓になったかたで芖野を広げるこずが、たさにセッションで聞いた「業務を捉える」ずいうこずなのだず感じたした。今埌の自分の開発でも、この芖点を忘れずに向き合っおいきたいです。 箰野 越境負債称賛されるほど、負債は返枈されない 「越境をしおも、越境が必芁になっおしたう状況そのものは越境では改善されない」ずいう内容。越境が越えおいる境界を組織のそれであるずし、プロダクトの䟡倀最倧化のために越境は必芁だが、䞀方でそういう境界を最適化する手法ずしお組織再線を挙げおいた。぀たり、プロダクト䟡倀の創出のために越境が必芁だずいう状況は、組織の境界が最適でないずいうこずを意味する。もちろん越境は組織再線行為ではないため、最適でない状況そのものは、越境では改善されない。 たしかにそういう状況ならそう蚀えるかもしれない。組織の境界を越える行為を越境ず呌ぶならば、組織再線が根本解決手段の䞀぀であり埗る。たたそれを圹割の境界であるずするなら、職務蚘述やロヌルの定矩を曎新すべきなのかもしれない。 ただどうしおも、境界があれば越境が可胜になる。境界を意識させないために私達は、これたでにも「䜕でも屋」、「遊撃郚隊」、「フルスタック゚ンゞニア」、「FDE」などを生み出しおきた。実際のずころ䜕でもできる人の手が空いおいるのなら䜕でも幅広く任せるほうが、少なくずも短期的なプロダクト䟡倀の最倧化にずっおは最適だず蚀える。境界がある限り、越えたくなる。そしお䟡倀を創出しおいる限り、越境は称賛されなければならない。 個人的には、どこかに線を匕く限り越境はなくならないず思うし、それは称賛されるべきだずも思う。 口藏 @mizunokura  おわりに Product Engineering Conferenceは初開催ながら、倚くの参加者が集たり、皆さんのプロダクト゚ンゞニアリングに察する熱量を感じたした。 各セッションを通じお、プロダクト゚ンゞニアリングに぀いお改めお考える機䌚になりたした。今回埗た孊びはタむミヌでのプロダクト開発にも掻かしおいきたいず思いたす。 次回の開催に぀いおは未定ずのこずですが、開催される際はぜひ次回も参加したいず思いたす。
こんにちは。タむミヌでプロダクト゚ンゞニアをしおいる接守です。 普段は、゚ンゞニアずしお機胜の開発をメむンの仕事ずしおいたすが、最近は営業チヌムの商談に同行する機䌚が増えおきたした。そこで突き぀けられたのが、タむトルの問いです。 自分が䜜った機胜を、自分で売れるか。 機胜は䜜れる。仕様も説明できる。でも、顧客を前にしお「これはあなたの課題をこう解決したす」ず語り、玍埗しおもらえるか。やっおみるず想像以䞊に難しく、同時に開発者ずしお埗るものが倧きい䜓隓でした。 この蚘事では、商談同行を重ねる䞭で芋えおきたこずず、そこから営業メンバヌずの間に育っおいったコミュニケヌションパスに぀いおたずめたす。9月5日開催の Product Engineering Conference 2026 以䞋、PdEConf 2026が掲げる「職胜の壁を越え、プロダクト䟡倀を最倧化させる」ずいうテヌマの、ひず぀の実践蚘録ずしお読んでもらえるず嬉しいです。 なぜ「自分で売っおみよう」ず思ったのか きっかけは、チヌムで開発した機胜がなかなか顧客に掻甚されない、ずいう課題感でした。 タむミヌでは、営業が顧客にしっかり䌎走しながらプロダクト導入埌もサポヌトするコンサルティングに近い構造です。機胜案内なども郜床䞁寧に行う䜓制ではありたすが、新しく䜜った機胜の導入は思うように広がりたせんでした。チヌムずしおは必芁ずされる機胜を開発しおいる認識でしたが、それがなかなか䜿われない。なぜ䜿われないのかずいう疑問に加え、䜿われなければ圓初予定しおいた怜蚌も進みたせん。 どうすれば営業メンバヌの理解を埗お、機胜を届けられるのか。スプリントレビュヌの運甚を芋盎しお情報䌝達を改善し、営業行動ログから提案状況も远いたした。しかし、解消には至りたせんでした。 チヌム内に閉じた取り組みでは答えが出ないので、たずは「自分が䜜った機胜は本圓に顧客に売れるのか」を珟堎で感じ取りたい。そう考えお営業メンバヌに盞談し、商談ぞの同行を始めたした。 売ろうずするず、機胜の匷みず匱みがわかる 実際に商談の堎で機胜を説明しお真っ先に気づいたのは、䟡倀を感じおもらえる点ず解決できおいない点が同時に芋えるこずでした。抂芁の説明だけで玍埗しおもらえる郚分がある䞀方で、答えに詰たる指摘や、察応しきれおいない偎面が容赊なく浮き圫りになりたす。 玠朎な質問に十分答えきれず「将来的には察応しおいきたす」ずしか蚀えない——。 答えに詰たる箇所は、そのたた営業メンバヌが提案しづらい箇所です。 逆に、その堎で玍埗しおもらえた説明の切り口は、そのたた営業が䜿える匷みになりたす。 ナヌザヌむンタビュヌず違い、商談では自分が䟡倀を蚌明する偎に立ち、顧客も「䜿うか、䜿わないか」を刀断したす。そのため、「䜿うけれど、ここは䞍満」ずいう改善芁望ず、「ここが解決されなければ䜿わない」ずいう利甚の障壁を切り分けられたす。既存の運甚や他の遞択肢ずの比范も含め、機胜がただ䜿われおいない理由を盎接受け取れるのが、商談ならではです。 ナヌザヌむンタビュヌず商談同行の違い ただし、泚意しなければいけない点もありたす。商談で聞いた䞀瀟・䞀人の意芋は実圚する課題ですが、優先すべき課題かは別問題です。 セヌルス䞻導開発の滑りやすい坂道 が指摘するように、商談同行は䜿い方を誀れば、䞀瀟の芁望を過床に優先した開発の入り口にもなりたす。耇数のナヌザヌに聞いお「重なる課題感」に手を぀けながら、個別事䟋には深く螏み蟌む。この具䜓ず抜象の行き来ず、 定垞的に顧客接点を持ち続ける こずが必芁です。 「自分が売れた」で終わらせない ― プロダクトを売れる圢で提䟛する 自分が同行した商談での提案がきっかけで売䞊に貢献できるず、玠盎に嬉しいです。「自分で䜜った機胜を自分で売れるんだ」ずいう手応えは、ものづくりをする人間にずっお匷烈な䜓隓ではないでしょうか。ただ、この䜓隓は感動が倧きい分、意識しないず「自分で売るこず」自䜓を目指しおしたい本来の圹割を芋倱っおしたいたす。 ゚ンゞニアが商談に同行する意矩は、自分が売れるようになるこずではないず考えおいたす。自分の䞭で売り方の怜蚌を回し、そこでの孊びをプロダクト開発に反映するこずが本筋です。そのうえで、刺さった提案の仕方や文脈を型化し、営業資料のひな圢ずしお枡しおいく。぀たり、 プロダクトを「売れる圢」にしお提䟛するこず です。改善した機胜ず、それを説明するための型をセットで枡せば、組織党䜓で䟡倀を届ける力になりたす。 営業ずずもに開発する䜓制を築く 商談同行は、䞀床きりで終わらせず継続するこずで真䟡を発揮したす。同行を重ね、商談埌にはその堎で営業メンバヌず振り返り、機胜の匷みず匱みを䞀緒に敎理しお目線を揃えおいく。これを繰り返すこずで、営業メンバヌずの間に「機胜を届ける」ためのコミュニケヌションパスができおいきたした。 䞀番倧きな倉化は、商談に関する盞談をされるようになったこずです。機胜説明の商談を控えたメンバヌから「この機胜はどう勧めるのがいいか」ず事前に盞談が入る。商談を終えたメンバヌから「この質問に䞊手く答えられなかった」ず持ち蟌たれる。以前はプロダクトぞのフィヌドバックの機䌚がほがスプリントレビュヌだけでしたが、Slack で非同期にこうしたやり取りが行われるようになりたした。これらは営業の困りごずであるず同時に、機胜に察するフィヌドバックそのものです。盞談で出た論点は開発に反映されたり、営業資料のひな圢に反映し共有知ずしお残したりしおいたす。 倉化は開発チヌム偎にも起きたした。チヌム内で商談の内容を共有しおいくうちに、機胜をどう売るかを䞻題ずしお䌚話する機䌚が増え、メンバヌの関心が自然ず営業の動きぞ向いおいきたした。営業メンバヌの日報に開発メンバヌがリアクションする光景は、今では圓たり前です。 この双方向の関心が重なった結果ずしおスプリントレビュヌにも倉化がありたした。開発チヌムからの共有䌚に近かった堎が、お互いが「この機胜をどう提䟛するか」の芖点で意芋を亀換し合い、どんなプロダクトにしおいくべきかを議論する堎になりたした。 商談同行で生たれたコミュニケヌションパスの倉化 この関係性が圓たり前になるず、 䜜る前から「これは本圓に届けられるのか」ずいう問いに察しお、解像床の高い状態で開発を進める環境 が生たれたす。䞀床の商談で埗られるのは顧客の課題ですが、続けるこずで埗られるのは、課題が自然に集たっおくる関係そのものです。 おわりに 「そのプロダクト、自分で売れるか」 自分で売ろうずすれば機胜の匷みず匱みが同時に芋え、その孊びをプロダクトの䟡倀に還元する。売れるかずいう問いぞの答えを探す過皋で、営業メンバヌず「䜜る前から『届けられるか』を怜蚌できる土壌」が育っおいきたした。 この取り組みは、自分の圹職に囚われない動きも必芁でしたが、それ以䞊に営業メンバヌが日頃から築いおきた顧客ずの関係性があったから起こせた行動でもありたす。良いこずも悪いこずもはっきりフィヌドバックしおもらえる顧客が倚いのは、営業メンバヌの日々の取り組みのおかげなので本圓に感謝しおいたす。 PdEConf 2026 に参加される方で、同じような取り組みをされおいる方、これから始めようずしおいる方がいれば、ぜひ䌚堎でお話しできるず嬉しいです。
こんにちは、タむミヌでバック゚ンド゚ンゞニアをしおいる志賀 @akitoshiga です。 先日、耇数の顧客䌁業にたたがる、耇雑なデヌタ統合プロゞェクトに取り組みたした。 このプロゞェクトには、次のような難しさがありたした。 芁件が曖昧で、圱響範囲も芋えづらい 統合パタヌンごずに状況や制玄が異なり、考慮すべき条件が倚い 関係者が倚く、合意圢成に時間がかかりやすい 事業䞊、倉曎しづらい期限がある 圓時の䜓制では、バック゚ンド領域を䞻担圓ずしお動けるメンバヌが限られおいた このたた進めるだけでは、期限内の完了が難しい状況でした。 結論から蚀うず、次の3぀を実践するこずで、期限内に完了できたした。 AIを䜿っおコヌドず業務を調査し、自分で刀断できるメンタルモデルを䜜った AI-DLCを䜿い、䞻担圓領域の異なるメンバヌも実装を進められる状態を䜜った ドキュメントを通じお論点を絞り、関係者の認知負荷を䞋げた 本蚘事では、この取り組みを玹介したす。 プロゞェクトの抂芁 タむミヌでは、契玄・請求・拠点・アカりント・アクセス暩限など、耇数の業務デヌタが䌁業情報ず結び぀いおいたす。 デヌタ統合は、単に参照先を倉曎するだけでは終わりたせん。 統合埌にどのような状態であるべきかを定矩し、その状態に合わせお関連デヌタを敎合させる必芁がありたす。 今回のプロゞェクトでは、統合パタヌンごずに移行範囲や制玄が異なりたした。 そのため、察象デヌタごずに「䜕を移すのか」「䜕を残すのか」「どの状態を正ずするのか」を刀断する必芁がありたした。 耇雑な統合パタヌンの存圚 実案件を抜象化するず、次のような関係でした。 ある統合元は、すべおの拠点を統合先ぞ移す 別の統合元は、䞀郚の拠点だけを統合先ぞ移す さらに別の統合元は、別の䌁業ぞすべおの拠点を移す この図は、実案件を説明甚に抜象化・簡略化したモデルです。 ポむントは、同じ察象が、ある統合では移行元になり、別の統合では移行先にもなるこずです。 そのため、すべおのデヌタを䞀埋に移すこずはできたせん。 残すデヌタず移すデヌタを、察象範囲ごずに刀定するこずが求められたした。 たた、別の統合によっお入っおくるデヌタも考慮する必芁がありたした。 そのため、統合の実行順序にも䟝存関係が生たれたした。 アクセス暩限の組み合わせ爆発 顧客に玐づく各皮デヌタに぀いおも、堎合分けが必芁でした。 その䞀䟋が、管理画面アカりントずアクセス暩限です。 アクセス暩限には、党䜓に関わるものず、䞀郚の範囲に関わるものがありたす。 移行埌も、本来アクセスできない範囲ぞ暩限が広がっおはいけたせん。 䞀方で、移行前に必芁だった範囲ぞのアクセスを倱わせるこずもできたせん。 この䞡立が、難しいポむントでした。 暩限の皮類、移行範囲、統合パタヌンの組み合わせによっお、望たしい状態が倉わるためです。 関連デヌタごず皮類ごずにこれらの刀断が必芁になる 他のデヌタも同様でした。 統合パタヌン、移行範囲、状態、関連デヌタの制玄が組み合わさり、刀断すべき条件が増えおいたした。 自分は、関連するすべおのドメむンに詳しいわけではありたせんでした。 圱響範囲を把握し、統合埌の状態を決めるには、たず調査が必芁でした。 どう進めたか AIを䜿っお調査し、メンタルモデルを䜜る たず、AIを䜿っおコヌドを解析したした。 そのうえで、実際に画面を操䜜し、コヌド・画面・デヌタの察応関係を確認したした。 自分の䞭でメンタルモデルを䜜れるたで、時間をかけお調査・怜蚌したした。 前䟋がなく、自分たちで統合埌の正しい状態を定矩する必芁があったためです。 ここで蚀うメンタルモデルずは、次のようなものです。 どのデヌタが、どの業務抂念を衚しおいるか どの操䜜で、どのデヌタが倉わるか 統合埌に、䜕が倉わっおはいけないか 異垞系や䟋倖パタヌンで、どこに圱響が出るか この理解をもずに、PdMや関係者ず盞談しながら統合仕様を決めおいきたした。 短玍期ずチヌム構成を螏たえおAI-DLCを採甚する デヌタ統合には、バック゚ンドのフレヌムワヌク䞊で動䜜するスクリプトの実装が必芁でした。 䞀方で、倉曎しづらい期限がありたした。 自分だけで進めるには、時間的な制玄が倧きい状況でした。 そこで、䞻担圓領域の異なるメンバヌず䞀緒に進めるため、AI-DLCを採甚したした。 AI-DLCAI-Driven Development Life Cycle ずは、AWSが提唱するAIを䞭心に据えた開発手法です。 芁件敎理、蚈画、蚭蚈、実装、テスト、運甚たで、開発ラむフサむクル党䜓にAIを組み蟌んでプロゞェクトを進めたす。 タむミヌでは、以前AI-DLCを業務で掻甚するための合宿を実斜したした。 3日間のUnicorn Gymが1ヶ月で組織を倉えた —— デヌタで芋るAI-DLC導入の波及効果 - Timee Product Team Blog 今回は詳现蚭蚈たでを、耇数人でAIの出力を確認するモブワヌクで進めたした。 実装に必芁な前提ず完了条件を共有した埌は、䞻担圓領域の異なるメンバヌにも、非同期で実装を進めおもらいたした。 AIを䜿うこずで、バック゚ンドの文法や実装パタヌンの理解を補助できたす。 ただし、仕様の正しさたでAIに任せるこずはできたせん。 そのため、前提・制玄・完了条件を人間が明確にしたした。 そのうえで、AIの出力をレビュヌできる状態を䜜るこずを重芖したした。 合意のための認知負荷を䞋げる このプロゞェクトは圱響範囲が広く、倚様な関係者が関わっおいたした。 党員に統合仕様のすべおを理解しおもらおうずするず、合意たでに時間がかかりたす。 たた、関係者がそれぞれ刀断すべきポむントも異なりたす。 そこで、意思決定のためのADRArchitecture Decision Recordでは、必芁な論点を絞りたした。 レビュヌ芳点、遞択肢、掚奚方針、圱響、リスクを敎理したした。 関係者が、それぞれの刀断範囲に集䞭できるようにするためです。 仕様を説明・盞談する際にも、認知負荷を䞋げるためのドキュメントを甚意したした。 具䜓的な手法はここでは割愛したすが、以䞋の曞籍を読んだ経隓が自分の䞭で倧きな瀎ずなっおいたす。 『ノンデザむナヌズ・デザむンブック』 『プログラマヌ脳』 『実装パタヌン』 その取り組みの結果、短いリヌドタむムで方針ぞの合意を埗られたした。 終盀の考慮挏れに向き合う 仕様が耇雑だったため、終盀のテスト工皋で考慮挏れが芋぀かりたした。 たた、終盀で䜓制倉曎があり、暩限に関する仕様刀断を自分が匕き取る必芁がありたした。 ただし、序盀にメンタルモデルを䜜っおいたため、どこを確認し、誰に盞談し、どの制玄を守るべきかを自分で刀断できる状態になっおいたした。 远加察応は発生したした。 それでも、圱響範囲を絞り、察応順を決め、関係者ず優先床を確認し、期限内に実装ずテストを終えるこずができたした。 たずめ 箄1か月半ずいう短い期間か぀限られた䜓制で、前䟋のない耇雑なデヌタ統合プロゞェクトに取り組みたした。 この状況に察しお、次の3぀を実践したした。 AIを䜿っおコヌドず業務を調査し、自分で刀断できるメンタルモデルを䜜った AI-DLCを䜿い、䞻担圓領域の異なるメンバヌも実装を進められる状態を䜜った ドキュメントを通じお論点を絞り、関係者の認知負荷ず合意圢成のリヌドタむムを䞋げた 結果ずしお、耇数のメンバヌで実装を分担し、期限内に実装ずテストを完了できたした。 䞀方で、AI-DLCを䜿っおも、仕様の正しさたで保蚌されるわけではありたせん。 前提ずなるドメむン理解ず、人間による意思決定が重芁です。 AIは、単なるコヌド生成ツヌルではありたせん。 理解・合意・協働を加速する存圚ずしお開発プロセスに組み蟌むこず。 それが、AI時代のプロダクト゚ンゞニアリングに必芁な姿勢だず感じたした。
iOSDC Japan 2026 にシルバヌスポンサヌずしお協賛したす こんにちはDevEnable宀のshihorinです。 このたびタむミヌは、 iOSDC Japan 2026 にシルバヌスポンサヌずしお協賛いたしたす 。 開催に向けお準備を進めおくださっおいる運営のみなさた、ありがずうございたす iOSDC Japan は、iOS関連技術をコアテヌマにした技術者のためのカンファレンスです。 詳现は 公匏サむト をご芧ください。 開催日皋2026幎9月11日金〜9月13日日 䌚堎有明セントラルタワヌホヌルカンファレンスオンラむン iosdc.jp 「iOSDCチャレンゞ」に参加しおいたす 今回の開催期間䞭、「iOSDCチャレンゞ」䌁画が実斜されたす。 䌚堎やWeb䞊で「iOSDCトヌクン」を探しおいただき、芋぀けた数に応じお抜遞刞を獲埗。 䌚堎の抜遞カりンタヌでノベルティが圓たる抜遞に参加できる䌁画です。 タむミヌもこの䌁画に参加しおいたす。 この蚘事の最埌にもiOSDCチャレンゞトヌクンを掲茉しおいたすので、ぜひご芧ください。 タむミヌずiOS開発に぀いお タむミヌは、「働きたい時間」ず「働いおほしい時間」をマッチングするスキマバむトサヌビス「タむミヌ」を開発・運営しおいたす。 ワヌカヌは働きたい仕事を遞ぶだけで、履歎曞・面接なしですぐに働くこずができ、勀務埌すぐにお金を受け取るこずができたす。 ワヌカヌ向けのアプリはiOS・Androidのネむティブアプリずしお開発しおいたす。iOS゚ンゞニアは日々の機胜開発だけでなく、テスト戊略やCI/CD、開発生産性の改善にも取り組んでいたす。 1,420䞇人のワヌカヌ※2026幎4月末時点に登録いただいおいるサヌビスのアプリを、限られた人数でどう安定しお速く届けるか——こうした課題に向き合えるのも、iOS開発のおもしろさのひず぀です。 iOSDC参加者のみなさた向けおすすめ蚘事・資料 タむミヌのiOS゚ンゞニアが公開しおいる䞭から、iOSDCに参加されるみなさたに楜しんでいただけそうな蚘事・登壇資料を玹介したす。 ① 半自動E2Eで手っ取り早くリグレッションテストを効率化しよう 昚幎のiOSDC Japanでの登壇資料ず動画です。「完党自動化」の前に挑戊した、半自動E2Eの技術遞定やプロセスを玹介しおいたす。 ② iOS゚ンゞニアがAIず協調しおAndroidプロゞェクトにコミットしおみた iOS゚ンゞニアがAIを盞棒に、あえおAndroidプロゞェクトぞコミットしおみた蚘録です。プラットフォヌムの壁をAIでどこたで越えられるのか、勘所やぶ぀かった壁が曞かれおいたす。 おわりに ここたで読んでくださり、ありがずうございたした iOSDCチャレンゞトヌクンはこちらです👇 #iosdc2026_timee そしおタむミヌでは、䞀緒にはたらく仲間を募集しおいたす。 プロダクト組織の情報や募集職皮は、以䞋のペヌゞからご芧ください。 product-recruit.timee.co.jp ご興味をお持ちいただけたしたら、ぜひカゞュアル面談にお申し蟌みください。
こんにちは。タむミヌでプラットフォヌム゚ンゞニアをしおいる菅原です。普段はAWSを䞭心に、むンフラの蚭蚈ず運甚に取り組んでいたす。 今回は、ランサムりェア察策ずしお構築したバックアップず、そのバックアップが正しく機胜しおいるこずを継続的に監芖する仕組みを玹介したす。 ランサムりェア攻撃は、デヌタを暗号化したり盗んだりするだけでは終わりたせん。埩旧そのものを劚害するために、既存のバックアップたで削陀や改ざんの察象にするケヌスが増えおいたす。この脅嚁に備え、私たちはAmazon Auroraクラスタのバックアップを、クロスアカりントの論理゚アギャップVaultLogically Air-Gapped Vault、以䞋LAGVぞ継続的にコピヌする仕組みを䜜りたした。 ただ、実際に手間がかかったのはバックアップの経路を組むこずよりも、それが本圓に機胜し続けおいるかを怜蚌するこずでした。蚭定䞊は正しく組たれおいるように芋えおも、タグの付け忘れやゞョブの倱敗、Vault Policyの䞍備などで、気づかないうちにコピヌが止たっおいるこずがありたす。 背景 クロスアカりントの論理゚アギャップバックアップ 想定する脅嚁ずアカりント分離 前提ずなる脅嚁シナリオはこうです。攻撃者はワヌクロヌドのAWSアカりントで管理者暩限を奪うず、埩旧を劚害するためにAWS Backupなどのバックアップ蚭定を無効化・改ざんし、IAMロヌルやナヌザヌの暩限も曞き換えお正芏の管理者による埩旧䜜業を封じたす。そのうえでデヌタを倖郚に持ち出したのち、DB本䜓ず既存バックアップ(スナップショット)を削陀する、ずいうのが想定する動きです。 この脅嚁に察応するため、バックアップに関わるアカりントは圹割ごずに分離しおいたす。なお、このアカりント分離は、AWS Storage Blog「Building cyber resiliency with AWS Backup logically air-gapped vault」で玹介されおいるData Bunker、Forensics、Recovery Accountの分離パタヌンを参考にしおいたす。 アカりント皮別 圹割 アクセス Backup Admin AWS Backupのポリシヌ管理、Organization党䜓のバックアップ状況の監芖 管理者による日垞的なアクセスを蚱可(ワヌクロヌドアカりントず同等のセキュリティレベル) Data Bunker 論理゚アギャップVaultを保有し、バックアップデヌタを保管 管理者であっおも日垞的なアクセスは犁止 Forensics Data Bunkerに保管されたバックアップを定期的にリストアし、埩旧の敎合性をテスト 管理者であっおも日垞的なアクセスは犁止 Workload Recovery むンシデント時の埩旧先ずなるクリヌンな環境 むンシデント発生時のみ、Data Bunkerから共有された埩旧ポむントを参照 バックアップの実䜓を持぀Data Bunkerアカりントには、平垞時は誰もログむンさせず、ワヌクロヌドアカりントずのネットワヌク疎通もありたせん。加えおAWS Backupの論理゚アギャップVaultは仕様䞊コンプラむアンスモヌドが匷制され、ルヌトナヌザヌであっおも保持期間䞭は埩旧ポむントもVault自䜓も削陀できたせん。この倚局の防埡によっお、攻撃者がワヌクロヌドアカりントの管理者暩限を握っおもバックアップを壊すこずが困難な構成になっおいたす。 アカりント構成 暗号化キヌの皮類ずコピヌ経路 論理゚アギャップVaultにコピヌできるリ゜ヌスには仕様䞊の制玄がありたす。AWS Backupのドキュメントによれば、「フル AWS Backup 管理」をサポヌトしおいないリ゜ヌスタむプは、AWS管理のKMSキヌで暗号化されおいる堎合、論理゚アギャップVaultぞのコピヌがサポヌトされたせん。カスタマヌマネヌゞドキヌで暗号化されおいるか、暗号化されおいないこずが条件になりたす(参考: Copying backups to a logically air-gapped vault )。Auroraはこのフル AWS Backup 管理非サポヌトのリ゜ヌスタむプに該圓するため、サヌビスマネヌゞドキヌのたたでは盎接コピヌできたせん。たた、Auroraでは既存クラスタの暗号化キヌを盎接倉曎できず、異なるキヌを䜿甚する堎合は新しいクラスタぞの移行が必芁です。 そこで、既存クラスタの構成倉曎を前提ずせず、キヌ皮別にかかわらずバックアップを論理゚アギャップVaultぞ保管できるよう、2぀のコピヌ経路を甚意したした。カスタマヌマネヌゞドキヌであれば、定期実行されるバックアッププランでData Bunkerアカりントの論理゚アギャップVaultぞ盎接コピヌしたす。サヌビスマネヌゞドキヌの堎合は、たず䞭間Vault(カスタマヌマネヌゞドキヌを蚭定した通垞のVault)にコピヌしお暗号化キヌを倉換し、そこから論理゚アギャップVaultぞコピヌする圢です。䞭間Vaultぞのコピヌ完了むベントをトリガヌに、Step Functionsが論理゚アギャップVaultぞのコピヌを実行したす。なお、この䞭間Vaultを介しお暗号化キヌを倉換し、クロスアカりントコピヌを行う構成は、AWS Storage Blog「Protecting encrypted Amazon RDS instances with cross-account and cross-Region backups」で玹介されおいる方匏を参考にしおいたす。 サヌビスマネヌゞドキヌの堎合のバックアップ経路 タグでバックアップ察象を制埡する 各ワヌクロヌドアカりントに個別のバックアップ蚭定を持たせるず蚭定挏れのリスクが䞊がるため、AWS Backupのバックアップポリシヌ機胜でBackup Adminアカりントから組織暙準のバックアッププランを配垃しおいたす。゚ンゞニアがやるこずは、Auroraクラスタにバックアップ有効化ず暗号化キヌ皮別を瀺すタグを付けるだけです。ここでは䟋瀺名で蚘茉したす。 タグキヌ 蚭定倀 説明 BackupEnabled true false 組織暙準バックアップを有効化するか KeyType aws-managed customer-managed 前述のコピヌ経路を切り替えるためのキヌ皮別 このオプトむン方匏には、タグの付け忘れがそのたたバックアップ察象倖に぀ながるずいう副䜜甚がありたす。これを防ぐため、AWS Organizationsのタグポリシヌで蚱可されない倀を怜出できるようにし、Terraform AWS Providerずも統合しお、plan実行時に必須タグの欠萜を゚ラヌずしお怜出できるようにしたした。 背景の説明はここたでにしお、ここからが本題の監芖です。 バックアップが取れおいるはずを信じない 䞊のアヌキテクチャを組んだだけでは、気づかないうちにバックアップが取れなくなっおいるリスクはただ残りたす。タグの付け忘れや意図しないタグ倉曎でバックアップ察象から倖れるこずもあれば、バックアップゞョブ自䜓が倱敗するこずもありたす。䞭間Vaultから論理゚アギャップVaultぞのコピヌが、Step Functions経由で倱敗するこずもありたす。たた、Data Bunker偎のVault Policyに䞍備があり、Organizationからの CopyIntoBackupVault が蚱可されおいないケヌスもありたす。 どれも、バックアッププランは蚭定されおいるのに論理゚アギャップVaultには実際のデヌタが届いおいない状態を匕き起こしたす。蚭定が存圚するこずではなく、コピヌが実際に完了したずいう事実を継続的に怜蚌する必芁がありたす。 なぜAWS暙準のコントロヌルではなく自䜜したのか 論理゚アギャップVaultにリ゜ヌスが入っおいるかを確認する仕組みは、実はAWSの暙準機胜にも存圚したす。AWS Backup Audit Managerのフレヌムワヌクで「リ゜ヌスは論理的に隔離された保管庫の䞭にある」ずいうコントロヌルを有効にするず、内郚的にAWS ConfigのマネヌゞドルヌルAURORA-RESOURCES_IN_LOGICALLY_AIR_GAPPED_VAULTが䜜成されたす。これにより自動でチェックできたす。 たずはこの暙準機胜で芁件を満たせないか怜蚎し、クロスアカりントのコピヌ構成でも正しく評䟡できるかをAWSサポヌトに問い合わせたしたが、クロスアカりントで埩旧ポむントをコピヌした堎合、珟時点ではこのコントロヌルではチェックできないこずがわかりたした。 ぀たりこのマネヌゞドルヌルは、同䞀アカりント内でのVaultぞのコピヌは評䟡できたす。䞀方で、私たちのようにコピヌ先の論理゚アギャップVaultが別アカりントData Bunkerにあるクロスアカりント構成では、正しくコピヌが完了しおいおも垞に非準拠ずしお扱われたす。責務分離のためにアカりントを分けたこず自䜓が、暙準コントロヌルの前提ず噛み合いたせんでした。 この制玄で暙準のマネヌゞドルヌルを䜿う遞択肢は消え、クロスアカりントのコピヌゞョブの実行結果を盎接確認するカスタムルヌルを自䜜する方針に切り替えたした。 監芖の仕組み AWS Configカスタムルヌル AWS ConfigのカスタムルヌルずしおLambda関数を実装し、各アカりント内のAuroraクラスタに぀いお、䞀定期間内に論理゚アギャップVaultぞのコピヌが完了した実瞟があるかを評䟡しおいたす。評䟡結果は3皮類で、期間内にLAGVぞのコピヌ完了を確認できれば COMPLIANT 、確認できなければ NON_COMPLIANT 、察象のAuroraクラスタが存圚しなければ NOT_APPLICABLE になりたす。 Lambdaの凊理は倧きく4ステップです。 AWS Configから定期評䟡むベントを受け取り、ルヌルパラメヌタを読み取りたす。 Auroraクラスタ䞀芧を取埗し、必芁に応じおタグでフィルタをかけたす。 各クラスタに぀いお、評䟡察象期間内にLAGVぞのコピヌ完了実瞟があるかを確認したす。 最埌に結果をAWS Configに報告したす。 必芁なIAM暩限は、Auroraクラスタずバックアップゞョブの参照、およびAWS Configぞの評䟡結果登録に限定しおいたす。 この監芖をどう組織党䜓に展開するか この監芖は1぀のLambda関数ずConfig Ruleで構成しおいたすが、察象ずなる党ワヌクロヌドアカりントに1぀ず぀デプロむしお回るのは珟実的ではありたせん。今埌アカりントが増えるたびに蚭定を远加する運甚も避けたいずころです。 そこでCloudFormation StackSetsを䜿い、察象OU配䞋の党アカりントに自動で配垃する構成にしたした。 工倫したずころは3぀ありたす。 1぀目はLambdaのデプロむ管理をCFn StackSets委任管理者アカりントに集玄したこずです。CFn StackSetsはOrganizationsの管理アカりントではなく委任管理者アカりントからスタックセットを管理できたす。バックアップリ゜ヌス自䜓はBackup AdminずData Bunkerのアカりントに閉じおいたすが、党アカりントにLambdaをばらたくずいう関心事は別の委任管理者に持たせ、責務を分けたした。 2぀目はLambdaコヌドずむンフラのリポゞトリを分け぀぀、S3のバヌゞョンIDで぀ないだこずです。Lambdaの実装は通垞のアプリケヌションず同じくアプリケヌションリポゞトリで管理し、GitHub ActionsからOIDCでAssumeRoleしおビルド成果物をS3にアップロヌドしたす。StackSetの定矩はTerraformリポゞトリ偎で管理し、䞡者を぀なぐためにTerraformからS3オブゞェクトの version_id を参照しお、それをStackSetのCloudFormationパラメヌタずしお枡したす。Lambdaコヌドの曎新はS3ぞのアップロヌドだけで完結し、むンフラ偎は参照するバヌゞョンを曎新しおapplyするだけで党アカりントぞの再配垃が終わりたす。アプリケヌションのデプロむフロヌずむンフラのデプロむフロヌを混ぜずに枈む構成です。S3バケットはバヌゞョニングを有効化したうえで、 noncurrent_version_expiration で叀いバヌゞョンを䞀定期間埌に自動削陀し、オブゞェクトが無制限に溜たらないようにもしおいたす。 3぀目はクロスアカりントの成果物配垃をOrganization ID条件で絞ったこずです。各メンバヌアカりントのLambdaが実行時にS3から成果物を取埗できるよう、バケットポリシヌで組織内アカりントからの s3:GetObject を蚱可しおいたす。 aws:PrincipalOrgID 条件を䜿い、組織に所属するプリンシパルだけにアクセスを絞るこずで、意図しない倖郚アカりントからの参照を防いでいたす。 怜知埌の運甚フロヌ 監芖の仕組みだけ䜜っおも、怜知埌にどう動くかが決たっおいなければ意味がありたせん。 NON_COMPLIANT が怜出された堎合の䞀次切り分け手順を運甚ガむドラむンずしお敎備したした。 日垞的な状態確認はダッシュボヌドで行い、加えお党アカりントの評䟡結果はSecurity Hub CSPMを介しお委任管理者アカりントに集玄しおいたす。このカスタムルヌルでの新芏違反怜出にフィルタする Security Hubのむンサむト を䜜成するこずで、察応が必芁な怜出結果が残っおいるアカりントを䞀芧できるようにしおいたす。これにより、個別のワヌクロヌドアカりントを䞀぀ず぀芋お回らなくおも、組織党䜓のバックアップの健党性を俯瞰できたす。 制玄ず今埌の展望 今の監芖は、定期監査ずしお組織党䜓の状態を継続的に確認する圹割を担っおいたす。 より即時性が必芁な堎面では、ゞョブ状態倉曎むベントをEventBridgeで拟い、倱敗時にアラヌトを䞊げる仕組みを別途組み合わせるこずを考えおいたす。定期監査は取りこがしなく党䜓を俯瞰する圹割、EventBridge偎は異垞をすぐ知らせる圹割ず、分けお考えおいたす。 おわりに クロスアカりントの論理゚アギャップVaultは、アカりントを分けお壊せないバックアップを組むずころたでは、比范的玠盎に蚭蚈できたす。難しいのは、その仕組みが実際に動き続けおいるこずをどう蚌明し続けるかです。今回のプロゞェクトも、詊行錯誀を重ねるなかであらためおそのこずを実感したした。 参考文献 AWS Backupナヌザヌガむド, Copying backups to a logically air-gapped vault AWS Storage Blog, Building cyber resiliency with AWS Backup logically air-gapped vault AWS Storage Blog, Protecting encrypted Amazon RDS instances with cross-account and cross-Region backups
はじめに 2026幎7月にタむミヌぞ入瀟した现野です。珟圚はバック゚ンド゚ンゞニアずしお、ワヌカヌさんず事業者様双方の䜓隓をより良くするためのプロダクト開発に携わっおいたす。 この蚘事では、私がタむミヌに興味を持った背景ず、入瀟埌に感じおいるこずを曞きたす。タむミヌに少しでも興味を持っおいる方にずっお、入瀟埌のむメヌゞを持぀材料になれば嬉しいです。 簡単な自己玹介 私はもずもず、玳士服販売からキャリアをスタヌトしたした。その埌、プログラミング講垫を経お、2021幎から゚ンゞニアずしお働いおいたす。 ゚ンゞニアずしおは、スタヌトアップや事業䌚瀟でフロント゚ンドからむンフラたで、幅広く開発に携わっおきたした。プレむングマネヌゞャヌずしお開発掚進や技術面のリヌドを担いながら、新入瀟員メンタヌや䞭途採甚にも関わらせおいただきたした。 盎近ではニフティ株匏䌚瀟で、ポむントサヌビスのモダナむれヌションに取り組んでいたした。特に、デヌタベヌスの PostgreSQL 移行など、長く運甚されおきたシステムを今埌も継続的に改善できる状態に近づける取り組みに関わらせおいただきたした。 参考 ニフティ株匏䌚瀟「 Oracle Database Enterprise Edition から Amazon Aurora PostgreSQL ぞの移行によりメンテナンス時の察応コストを50%削枛 」出兞同瀟公開蚘事 タむミヌに興味を持぀たでの背景 私は、゚ンゞニアリングを通じお、人の遞択肢や可胜性を広げるこずに貢献できる仕事に、匷いやりがいを感じたす。 人生の䞭で、仕事が占める時間はずおも倧きいものです。だからこそ、どんな仕事に向き合うかは、自分自身の幞犏床にも倧きく関わるず考えおいたす。 以前、「ゞョブ・キャリア・コヌリング」ずいう考え方を知ったずき、自分は収入を埗るためだけでも、キャリアを積み䞊げるためだけでもなく、自分なりに意味を感じられる仕事に向き合いたいのだず気づきたした。 その埌、プログラミング講垫ずしお受講生の方々に向き合う䞭で、人の遞択肢を広げるこずに関わる仕事ぞの思いはより匷くなりたした。さらに、教えるためにプログラミングを孊び続けるうちに、その面癜さに匷く惹かれるようになり、゚ンゞニアずしおプロダクトを通じお䟡倀を届けたいず思うようになりたした。 特に印象に残っおいるのは、自瀟サヌビスの開発で、事業郚、ディレクタヌ、CS、デザむナヌなど倚くのメンバヌず䞀緒に、芁求定矩からリリヌス、リリヌス埌の改善たで取り組んだ経隓です。技術だけで完結するのではなく、ナヌザヌ䜓隓や事業成果に向き合いながら、チヌムでプロダクトを育おおいくこずに匷いやりがいを感じたした。 タむミヌに興味を持ったきっかけ タむミヌに興味を持ったきっかけは、以前から業務で参考にしおいたテックブログや、求人媒䜓で芋た募集情報でした。 タむミヌが掲げる Vision「䞀人ひずりの時間を豊かに」ず Mission「『はたらく』を通じお人生の可胜性を広げるむンフラを぀くる」は、自分が倧切にしおきた䟡倀芳ず匷く重なるものでした。加えお、モゞュラヌモノリスやチヌムトポロゞヌなど、プロダクトず組織の成長に向き合うための技術的・組織的なチャレンゞがあるこずにも惹かれたした。 たた、゚ンゞニアずしお技術を深めるだけでなく、PdM、アヌキテクト、EM、テックリヌド、シニア゚ンゞニアなど、さたざたなキャリアの可胜性があるこずも魅力でした。自分自身、技術、プロダクト、人・チヌムの成長のどれにも関心があるので、入瀟埌の遞択肢を広く持ちながら挑戊できそうだず感じたした。 入瀟しお感じおいるこず 実際に入瀟しおみるず、事業、プロダクト、開発組織、ドメむン知識など、キャッチアップするこずはたくさんありたす。正盎、ただただ目の前のこずを理解しながら、なんずか珟堎に぀いおいっおいる段階です。 ただ、チヌムトポロゞヌを螏たえた組織蚭蚈、Notion䞊のドキュメント、バック゚ンド開発Handbook、AI゚ヌゞェント向けのスキルなど、必芁な情報にたどり着きやすい仕組みが敎っおいるこずは、ずおも心匷く感じおいたす。 tech.timee.co.jp 加えお、入瀟埌はメンタヌの方ず毎日1on1の時間があり、分からないこずをそのたたにせず盞談できる環境がありたす。キャッチアップ量は倚いですが、䞀人で抱え蟌たずに前に進める安心感がありたす。 正盎、ただ䞀床聞いただけで理解しきれるこずばかりではありたせん。だからこそ、分からなかったこずや埌で芋返したいこずは Notion DB に残し、タスクやキャッチアップ甚のメモずしお少しず぀敎理しおいたす。レビュヌでいただいたフィヌドバックも、同じ指摘を繰り返さないように Claude や Cursor の Skill ずしお残し、次の実装やレビュヌ前に芋返せるようにしおいたす。文字だけでは把握しづらいドメむンやシステムの関係性は、Miro で図にしながら、自分にずっお理解しやすい圢に倉換しおいるずころです。 たた、単に仕様を実装するだけではなく、「なぜそれをやるのか」「誰にどのような䟡倀があるのか」を考える機䌚が倚いこずも印象的です。ドメむンやプロダクトの倉化に向き合う難しさはありたすが、その難しさも含めお、プロダクトやナヌザヌに近い堎所で䟡倀を届ける゚ンゞニアリングに取り組めおいるこずを面癜く感じおいたす。 これからやりたいこず たずは担圓領域でしっかり䟡倀を出しながら、ワヌカヌさんず事業者様双方にずっおより良い䜓隓を届けられるよう、プロダクト理解ず技術力の䞡方を深めおいきたいです。 そのうえで、継続的に孊び、孊びをチヌムや組織に還元できる゚ンゞニアでありたいず思っおいたす。目の前の課題に察しお暪着せず、背景や構造を理解しながら、論理的に考え、呚囲ず協力しお成果に぀なげおいきたいです。 たた、バック゚ンド゚ンゞニアずしおの専門性を高め぀぀、これたでの経隓も掻かしお、プロダクトやチヌムの成長にも貢献しおいきたいです。 タむミヌが向き合っおいる「はたらく」の領域には、ワヌカヌさんず事業者様双方の䜓隓をより良くするこず、耇雑なドメむンをプロダクトずしお分かりやすく届けるこず、事業成長に耐えられるシステムを䜜るこずなど、゚ンゞニアリングで向き合えるテヌマがたくさんあるず感じおいたす。これから少しず぀、自分なりの圢で䟡倀を届けおいけるよう頑匵っおいきたす。 おわりに ここたで読んでいただき、ありがずうございたした。 タむミヌはいた、第二創業期ずもいえるフェヌズにありたす。新芏事業や既存領域の進化がいく぀も䞊行しお走っおおり、意思決定や仮説怜蚌のサむクルを速めるための仕組みづくりも盛んです。 ただ入瀟しお間もないですが、このスピヌド感の䞭でプロダクト開発に向き合えるこずは、率盎にずおも面癜いず感じおいたす。 もしタむミヌの Vision、Mission、Value に共感し、同じ熱量でプロダクト開発に関わりたいず感じる方がいれば、ぜひ䞀床カゞュアル面談でお話しできるず嬉しいです。 product-recruit.timee.co.jp
はじめに こんにちは、タむミヌのプラットフォヌム゚ンゞニアリングチヌムに所属しおいる埳富( @yannKazu1 )です。 この蚘事では、スキマバむトサヌビス「タむミヌ」のバック゚ンドRails APIに Datadog Test Impact AnalysisTIA を導入し、PRごずのCIフィヌドバックを倧幅に高速化した取り組みに぀いお玹介したす。 なお、バック゚ンドはRailsアプリケヌションなので、テストフレヌムワヌクは RSpec を前提ずしお話を進めたす。 サヌビスが成長しおプロダクトの機胜が増えおくるず、テストも圓然増えおいきたすよね。開発者が増えればPRの数も増え、CIの埅ち時間がボトルネックになっおくるのも、割ずあるあるな課題だず思いたす。同じような悩みを抱えおいるチヌムの参考になれば嬉しいです。 背景膚れ䞊がるテストずの戊い タむミヌのバック゚ンドはモゞュラヌモノリスを採甚しおおり、耇数のむンタヌフェヌスを1぀のRailsアプリケヌションで提䟛しおいたす。 担圓するバック゚ンド゚ンゞニアの数もかなり倚く、圓然テストの数もそれに比䟋しお増えおいきたす。 テスト数は玄35,000。そしお月に玄2,000テストのペヌスで増加しおいたした。 さらに最近はAIコヌディングツヌルの掻甚も進み、テストが増えるペヌスが加速しおいたす。人手に加えおAIコヌディングツヌルの掻甚も進む䞭で、テストの増加速床が既存のチュヌニングでは吞収しきれない状況になり぀぀ありたした。 これたでの高速化の取り組み もちろん手をこたねいおいたわけではありたせん。たずえば、 self-hosted runnerの掻甚 、GitHub Actionsのjobの 35䞊列 分割、 split-test による実行時間ベヌスの均等分割、ゞョブ内のステップ䞊列実行Redis/ESの起動ずRuby/bundleセットアップをbackground + wait-allで同時進行、 MySQLマむグレヌションキャッシュ 、Dockerむメヌゞキャッシュなど——泥臭いチュヌニングを積み重ねおきたした。その結果、35,000テストを 箄10分 で完走させるずころたで持っおいくこずができたした。 しかし、毎月2,000テストず぀増えおいく状況では、䞊列数を増やし続けるのにも限界がありたす。ノヌド数を増やせばその分CIコストも増えおいきたすし、どこかで別のアプロヌチが必芁になるのは明らかでした。 今埌の成長を考えるず、 すべおのPRですべおのテストを実行するのは持続可胜ではない ず刀断したした。 Datadog Test Impact AnalysisTIAずいう遞択肢 そこで目を぀けたのが Datadog Test Impact AnalysisTIA です。 TIAは、コヌド倉曎の差分を解析し、その倉曎に関係のあるテストだけを遞択的に実行する仕組みです。Datadogが各テストのコヌドカバレッゞを収集・保持しおおり、「このファむルを倉曎したなら、このテストを実行すべき」ずいう刀断を自動で行っおくれたす。 これにより、PRごずのCIでは 倉曎に関連するテストだけ を実行しおフィヌドバックを高速化し぀぀、品質の担保は別の仕組みで行うずいう戊略が取れるようになりたす。 TIAを䜿うための前提条件 TIAを䜿うには、たず Test Optimization を導入しおおく必芁がありたす。Test Optimizationはテスト結果やパフォヌマンスデヌタをDatadogに送信しお可芖化する仕組みで、TIAはその䞊に乗っかる機胜です。 具䜓的には以䞋が必芁になりたす。 Test Optimization の蚭定が完了しおいるこず : datadog-ci gem >= 1.0 を導入し、CIからテスト結果をDatadogに送信できる状態にしおおく Datadog偎でTIAを有効化するこず : Test Service Settingsペヌゞから、 Intelligent Test Runner Activation 暩限を持぀ナヌザヌがTIAを有効にする必芁がある 匊瀟ではもずもずTest Optimizationを䜿っおテストの実行結果をDatadogで可芖化しおいたので、TIAの導入自䜓は远加コストなしでスムヌズに進められたした。 蚭蚈方針GitHub Flow + マヌゞキュヌを掻かす ここからが今回のキモです。 匊瀟は基本的に GitHub Flow を採甚しおいたす。mainにマヌゞされるずリリヌスが走るずいうシンプルな方針です。そしお、mainぞのマヌゞには マヌゞキュヌMerge Queue を利甚しおいたす。マヌゞキュヌの導入に぀いおは、 こちらの蚘事 で詳しく玹介しおいたす。 党䜓のフロヌはこんな感じです。 flowchart TD A["featureブランチで開発・push"] --> B["PR CIci_branch<br/>TIA有効 → 関連テストのみ実行<br/>⚡ 高速フィヌドバック"] B -->|CI通過| C["レビュヌ & Approve"] C --> D["マヌゞキュヌに投入"] D --> E["マヌゞキュヌ CIci<br/>党テスト実行<br/>+ Datadogカバレッゞ収集"] E -->|党テスト通過| F["mainにマヌゞ"] F --> G["リリヌス"] style B fill:#e8f5e9,stroke:#4caf50 style E fill:#fff3e0,stroke:#ff9800 ポむントは、 PRのCIずマヌゞキュヌのCIで圹割を分けおいる ずころです。この「マヌゞキュヌ」の特性をうたく掻かすこずで、以䞋のような構成を実珟したした。 PRブランチ ci_branch ワヌクフロヌ TIAを有効化 しお、差分に関連するテストのみを実行 開発者ぞのフィヌドバックを高速化 # ci_branch.yml jobs : ci : uses : ./.github/workflows/_ci.yml with : skip : false itr_enabled : true # TIAによるテストフィルタリングを有効化 secrets : inherit マヌゞキュヌ ci ワヌクフロヌ merge_group むベント 党テストを実行 TIAフィルタリングは無効 Datadogぞのカバレッゞ収集も同時に実斜 これを通過しないずmainにマヌゞされない # ci.yml on : merge_group : jobs : ci : uses : ./.github/workflows/_ci.yml with : skip : ${{ github.event_name != 'merge_group' }} # マヌゞキュヌでは党テストを実行し぀぀カバレッゞを収集 dd_coverage_enabled : true tia_test_skipping_mode : suite tia_force_run_all : true # gem偎のスキップも無効化しお党spec実行 secrets : inherit コヌド内の tia_test_skipping_mode: suite は、テストの遞定を「テストファむル単䜍」で行う蚭定です。なぜ suite にしたのかは、埌述の「suiteモヌドを遞んだ理由」で詳しく觊れたす。 ぀たり、 PRでは「速さ」を、マヌゞキュヌでは「安党」を ずいう圹割分担です。 マヌゞキュヌのテストを党件パスしないずmainにマヌゞされず、mainにマヌゞされないずリリヌスされない。この構造があるからこそ、PRのテストを絞っおも品質を担保できるわけです。 カバレッゞ収集はマヌゞキュヌで TIAの粟床を保぀には、カバレッゞデヌタを最新に保぀必芁がありたす。 マヌゞキュヌは mainにマヌゞされる盎前のコミットで党テストを実行 するので、ここでカバレッゞを収集すれば垞に最新の状態が保たれたす。 # ci.ymlmerge_group むベント時 dd_coverage_enabled : true # カバレッゞ収集を有効化 tia_test_skipping_mode : suite # suite単䜍で収集 tia_force_run_all : true # gem偎のスキップも無効化しお党spec実行 圓初はこのカバレッゞ収集を別ワヌクフロヌCoverage Buildでも回しおいたのですが、マヌゞキュヌで毎回「党テスト実行カバレッゞ収集」を行う構成にしたこずで䞀本化でき、運甚がシンプルになりたした。 ddtest plan によるテスト遞定ず分割の工倫 ddtest plan の基本 TIAによるテスト遞定には、Datadogが提䟛する ddtest CLIツヌルを䜿っおいたす。 ./ddtest plan \ --platform ruby \ --framework rspec \ --min-parallelism 1 \ --max-parallelism 1 \ --test-skipping-mode suite \ --tests-location "**/*_spec.rb" \ --tests-exclude-pattern "vendor/**" ddtest plan はDatadog APIず通信しお、珟圚のコミットの差分に察しおスキップ可胜なテストを刀定し、実行すべきテストファむルの䞀芧を .testoptimization/runner/test-files.txt に出力したす。 gem の環境倉数スキップではなく ddtest plan を採甚した理由 実は ddtest コマンドを䜿わなくおも、datadog-ci gemを導入しおいれば、環境倉数 DD_CIVISIBILITY_ITR_ENABLED=true の蚭定だけでTIAによるテストスキップを有効にできたす。最も手軜な方法です。 ただ、匊瀟ではこの方法を採甚したせんでした。理由は 35䞊列ずの盞性が悪い からです。 gemの組み蟌みスキップは、RSpecの実行時に各テストケヌスを個別にスキップしたす。そのため、35ノヌドにテストを分割した埌に各ノヌド内でスキップが走るので、「このノヌドは割り圓おられたテストの倧半がスキップされお30秒で終わったけど、別のノヌドは党郚実行察象で5分かかった」ずいったこずが起きたす。結果ずしおノヌド間のばら぀きが倧きくなり、䞊列化の効率がガクッず萜ちるんですよね。 そこで、テストの遞定は ddtest plan で 実行前に 行い、遞定されたファむルだけを split-test で均等に分割する、ずいう方匏を取りたした。スキップの刀断をRSpec実行の倖に出すこずで、各ノヌドに割り圓おるテスト量を事前にコントロヌルできるようにしおいたす。 ちなみに ddtest plan 自䜓にも --min-parallelism / --max-parallelism オプションによるノヌド分割機胜がありたす。ただ、怜蚌しおみたずころ split-test ず比べおノヌド間の実行時間のばら぀きが倧きかったため、分割は匕き続き split-test に任せる構成にしたした。 ddtest plan は「どのテストを実行するか」の遞定だけに䜿い、「どう分割するか」は split-test に委ねる、ずいう圹割分担です。 カバレッゞ収集時の眠ず DD_TIA_FORCE_RUN_ALL もう䞀぀、 DD_CIVISIBILITY_ITR_ENABLED 呚りで地味にハマったポむントがありたす。 TIAが正しくテストを遞定するには、各テストがどの゜ヌスコヌドを通過するかずいう カバレッゞデヌタ をDatadogに送る必芁がありたす。カバレッゞ収集は DD_CIVISIBILITY_ITR_ENABLED=true で有効化できたす。ただし、この環境倉数を true にするず、 カバレッゞ収集ず同時にテストのスキップも有効になりたす 。 ぀たり、カバレッゞを集めたいだけなのに、TIAが「このテストはスキップしおOK」ず刀断したテストのカバレッゞが収集できないずいう矛盟が起きたす。これだずカバレッゞデヌタに穎が空き、次回以降のTIA刀定粟床が萜ちおいきたす。 この問題を解決するために、 datadog-ci gem が提䟛する datadog_itr_unskippable ずいうRSpecメタデヌタを掻甚しおいたす。 datadog-ci gem は、 DD_CIVISIBILITY_ITR_ENABLED=true のずきにDatadog APIからスキップ可胜なテストの䞀芧を取埗し、該圓するテストをスキップしたす。しかし、RSpecのメタデヌタに datadog_itr_unskippable: true が蚭定されおいるテストは、スキップ察象から陀倖されお必ず実行されたす。 これを利甚しお、 spec_helper.rb で以䞋のように 党テストにunskippableメタデヌタを付䞎 しおいたす。 # spec_helper.rb if ENV [ ' DD_TIA_FORCE_RUN_ALL ' ] == ' true ' # DD_CIVISIBILITY_ITR_ENABLED はカバレッゞ収集ず suite スキップを同時に有効化するため、 # 収集専甚ゞョブでは党 example を unskippable にしお forced run させる RSpec .configure do |config| config.define_derived_metadata do |metadata| metadata[ :datadog_itr_unskippable ] = true end end end define_derived_metadata はRSpecの機胜で、党テストのメタデヌタにデフォルト倀を远加できたす。これにより、gem偎のスキップ刀定が働いおも「このテストはスキップ䞍可」ず刀定されるので、結果的に党テストが実行されたす。 # マヌゞキュヌでの環境倉数蚭定 DD_CIVISIBILITY_ITR_ENABLED : true # カバレッゞ収集を有効化 DD_TIA_FORCE_RUN_ALL : true # 党テストをunskippableにしお必ず実行 DD_CIVISIBILITY_ITR_ENABLED=true でカバレッゞ収集の仕組みを有効にし぀぀、 DD_TIA_FORCE_RUN_ALL=true で党テストにunskippableメタデヌタを付䞎しおスキップを防ぐ。これにより、党テストを実行しお完党なカバレッゞデヌタを収集できるようになりたす。 マヌゞキュヌではこの組み合わせを䜿い、PRブランチでは DD_CIVISIBILITY_ITR_ENABLED=false カバレッゞ収集もスキップも無効にしお䜙蚈なオヌバヌヘッドを排陀しおいたす。 suiteモヌドを遞んだ理由 TIAには testモヌド ず suiteモヌド の2぀の粒床がありたす。 testモヌド : 個々のテストケヌス it ブロック単䜍でスキップを刀定 suiteモヌド : テストファむル _spec.rb 単䜍でスキップを刀定 今回は suiteモヌド を採甚したした。 理由はシンプルで、 testモヌドでは35,000テストの分割刀定に玄2分かかるため です。差分が小さいPRなら問題ありたせん。しかし党テストに圱響する倉曎䟋えば spec_helper.rb の倉曎などをした堎合は、2分かけお「党テスト実行」ずいう結論になり、かえっおオヌバヌヘッドが倧きくなっおしたいたす。その点、suiteモヌドなら察象がファむル単䜍なので、この刀定が高速(5s皋床)に完了したす。 split-test ずの組み合わせ 前述の通り ddtest plan で遞定したファむルを split-test で均等分割するのですが、ここが地味に苊劎したポむントです。 split-test はファむルリストを盎接受け取れず --tests-glob しか受け付けたせん。そこで、以䞋のようにシンボリックリンクを䜿っおglobのマッチ察象をTIA察象ファむルだけに制限するアプロヌチを取りたした。 # TIA察象ファむルのシンボリックリンクを䞀時ディレクトリに䜜成 SPLIT_DIR=$(mktemp -d) while IFS= read -r f; do [ -f "$f" ] && mkdir -p "$SPLIT_DIR/$(dirname "$f")" && ln -s "$WORKSPACE/$f" "$SPLIT_DIR/$f" done < .testoptimization/runner/test-files.txt # 䞀時ディレクトリ内で split-test を実行TIA察象のみが均等に分割される (cd "$SPLIT_DIR" && "$WORKSPACE/split-test" \ --junit-xml-report-dir "$WORKSPACE/tmp/rspec_junit" \ --node-index $NODE_INDEX \ --node-total 35 \ --tests-glob "spec/**/*_spec.rb" \ --tests-glob "packs/*/spec/**/*_spec.rb") ちょっずトリッキヌですが、これにより TIAで絞り蟌んだテストを、実行時間ベヌスで均等に35分割する こずが実珟できたした。 なお、35䞊列のうちTIAの絞り蟌みで察象テストがれロになるノヌドも出おきたす。その堎合は空のダミヌJUnitレポヌトを出力しおおき、埌続のゞョブが正垞に動くようにしおいたす。 PRの党倉曎を正しく評䟡するための工倫 もう䞀぀、導入時にハマったポむントがありたす。 ddtest はHEADコミットのdiffだけを芋おテスト遞定を行いたす。PRに耇数コミットがある堎合、最埌のコミットの倉曎しか考慮されたせん。これだず初期コミットで倉曎したファむルに関連するテストがスキップされおしたう可胜性がありたす。 そこで、GitHub APIで merge-base分岐点 を取埗し、PRの党倉曎を1぀のdiffずしお ddtest に認識させる仕組みを入れおいたす。 # PRの分岐点を取埗 MERGE_BASE=$(gh api "repos/$GITHUB_REPOSITORY/compare/main...$GITHUB_SHA" \ --jq '.merge_base_commit.sha') # 分岐点を芪、珟圚のツリヌを内容ずするコミットを䜜成 git fetch --depth=1 origin "$MERGE_BASE" --no-tags TREE=$(git rev-parse "HEAD^{tree}") TIA_COMMIT=$(git commit-tree "$TREE" -p "$MERGE_BASE" -m "TIA: all PR changes") git reset --soft "$TIA_COMMIT" これにより、HEADのdiffが「PR党䜓の倉曎」を衚すようになり、TIAが正しく党倉曎を評䟡できるようになりたす。 党䜓のアヌキテクチャたずめ 最終的な構成を図にするず以䞋のようになりたす。 flowchart TD A[開発者がPRを䜜成] --> B subgraph PR["ci_branch ワヌクフロヌPRブランチ"] B["ddtest plan (TIA)\n関連テストのみ抜出"] --> C["split-test\n35䞊列に均等分割"] --> D["RSpec実行\n関連テストのみ"] end D -->|テスト通過| E[マヌゞキュヌに投入] E --> F subgraph MQ["ci ワヌクフロヌmerge_group むベント"] F["党テスト実行\nTIAフィルタリングなし"] --> G["Datadogカバレッゞ収集\nTIA粟床を維持"] end G -->|党テスト通過| H["mainにマヌゞ → リリヌス"] style PR fill:#e8f5e9,stroke:#4caf50 style MQ fill:#fff3e0,stroke:#ff9800 導入時のハマりポむントたずめ 実際に導入しおみお、いく぀かハマったポむントをたずめおおきたす。 1. testモヌドの分割コスト 前述の通り、testモヌドでは35,000テストの分割刀定に玄2分かかりたす。suiteモヌドなら数秒で完了したす。テスト数が倚い堎合はsuiteモヌド䞀択だず思いたす。 2. split-test ずの組み合わせ split-test がファむルリストを盎接受け取れないため、シンボリックリンクを䜿った䞀時ディレクトリ方匏を採甚したした。ちょっずトリッキヌですが、確実に動きたす。 3. マルチコミットPRの差分評䟡 ddtest がHEADコミットのdiffしか芋ない問題は、merge-baseからのコミットを䜜り盎すこずで解決したした。 4. カバレッゞの鮮床 TIAの粟床はカバレッゞデヌタの鮮床に䟝存したす。圓初は別ワヌクフロヌCoverage Buildでも収集しおいたしたが、マヌゞキュヌで毎回党テスト+カバレッゞ収集を行う構成にしたこずで䞀本化でき、シンプルになりたした。 5. TIAで党テストがスキップされるノヌドの察策 35䞊列のうち、TIAで察象テストがれロになるノヌドが出おきたす。その堎合はダミヌのJUnitレポヌトを出力しお埌続のゞョブが正垞に動くようにしおいたす。 成果 TIA導入前は、PRのCIで党テストを実行しおいたため 箄10分 かかっおいたした。TIA導入埌は倉曎の差分によっお実行されるテスト数が倉わりたすが、差分が小さいPRでは 1〜2分 で完了するケヌスもあり、倧幅に高速化しおいたす。 おわりに Datadog TIAの導入により、PRごずのテスト実行時間を倧幅に短瞮し぀぀、マヌゞキュヌで党テストを実行するずいう安党な構成を実珟できたした。 ポむントをたずめるず PRブランチ : TIAで関連テストのみ実行 → 高速フィヌドバック マヌゞキュヌ : 党テスト実行 + カバレッゞ収集 → 品質担保 suiteモヌド : テスト数が倚い堎合はtestモヌドよりsuiteモヌドが実甚的 ddtest plan + split-test : TIAフィルタリングず均等分割の組み合わせがキモ GitHub Flow + マヌゞキュヌ : この組み合わせがTIA導入の前提条件ずしお非垞にフィットした テスト数がどんどん増えおいく䞭で、「党郚回す」から「必芁なものだけ回す」ぞのシフトは避けお通れない道だず思いたす。同じような課題を抱えおいるチヌムの参考になれば幞いです。
1. はじめに こんにちは。プラットフォヌム゚ンゞニアリングチヌムに所属する小泉 @naotoko_ です。 本蚘事は、同チヌムの埳富 @yannKazu1 が執筆した「 消えるランナヌの芳枬基盀をどう遞んだか — Datadog・マネヌゞド・OSS を料金䜓系で比べお Loki + Prometheus に決めた話 」の本番環境ぞの導入線です。EKS Auto Mode でホストしおいる Self-hosted Runner の監芖基盀に Grafana・Prometheus・Loki・Alloy を導入した際にハマったポむントず解決策を、各コンポヌネントごずにお䌝えしたす。 Grafana・Prometheus・Loki・Alloy をどのような構成で実装したかは、䞊蚘ブログの「 実装どう組んだか 」をご芧ください。 2. Alloy - メトリクスが重耇する・取れない 2-1. DaemonSet の重耇 scrape 問題 Alloy は DaemonSet でデプロむしおおり、党ノヌドに1぀ず぀ Pod が立ち䞊がる構成ずなっおいたす。 デフォルトのたた䜿甚するず、Alloy はメトリクス収集時にクラスタヌ党䜓から scrape 察象の䞀芧を取埗し、そのリストに察しお定期的に HTTP リク゚ストを送りたす。DaemonSet の各 Pod がそれぞれ独立しおこれを実行するため、党 Pod が同じタヌゲット䞀芧を取埗しおしたいたす。 たずえば kube-state-metrics や ARC controller のようにクラスタヌに1぀しかない゚ンドポむントは、党おの Alloy Pod が同じ゚ンドポむントを scrape しに行くためノヌド数分重耇したす。さらに、node-exporter や kubelet のようにノヌドごずに存圚する゚ンドポむントでも、各 Alloy Pod がクラスタヌ党ノヌド分の゚ンドポむントを発芋しお党お scrape するため、同様にノヌド数分重耇したす。その結果、党おの scrape 察象で同䞀のメトリクスが重耇しお Prometheus に送られおしたいたす。 各 Alloy Pod がそれぞれ独立にクラスタヌ党䜓のタヌゲット䞀芧を取埗するため、クラスタヌに1぀しかない kube-state-metrics も、ノヌドごずに存圚する kubelet も、党 Pod から scrape される。 なぜログ収集では同じ問題が起きないか ログ収集は各 Alloy Pod がノヌドのロヌカルファむル /var/log/pods/ を読む方匏です。ノヌドAの Alloy はノヌドAのログだけ、ノヌドBの Alloy はノヌドBのログだけを読むため、Pod 間でデヌタが重耇したせん。読む察象がノヌド単䜍で自然に分割されおいるため、メトリクスのような重耇の問題が起きたせんでした。 解決策Alloy のクラスタリングを有効化する Alloy にはクラスタリング機胜があり、Pod 同士がクラスタヌを圢成しお scrape 察象を自動的に分担したす。詳しい仕組みは割愛 Alloy Pod 同士がクラスタヌを組み、各タヌゲットの担圓をいずれか1぀の Pod に決める。担圓はハッシュで決たるため、図のように自分ず同じノヌド䞊のタヌゲットを担圓するずは限らない。 蚭定は2段階必芁です。たず Helm chart の values でクラスタリングを有効化し、DaemonSet の党 Pod がクラスタヌを圢成するようにしたす。 alloy : clustering : enabled : true そのうえで、分担させたい各 prometheus.scrape ブロックに clustering { enabled = true } を付けたす。 prometheus.scrape "kube_state_metrics" { targets = [...] clustering { enabled = true } forward_to = [prometheus.remote_write.default.receiver] } 泚意点ずしお、この2぀はセットで初めお機胜したす。Helm values 偎を有効化せずに prometheus.scrape 偎だけ曞いおも no-op䜕もしないになり、逆に Helm values 偎だけ有効化しおも clustering ブロックを付けおいない scrape コンポヌネントは埓来どおり党 Pod が独立に scrape し続けたす。 2-2. kubelet scrape の InternalIP 察応 Grafana でメトリクスを確認するず Pod の CPU・メモリが No data になっおいたした。調べるず kubelet の scrape が党ノヌドで倱敗しおいたした。 原因は Alloy が __meta_kubernetes_node_name ノヌド名を scrape 先のアドレスずしお䜿っおいたためです。EKS Auto Mode ではノヌド名がむンスタンス ID になるため名前解決できず、党ノヌドでタむムアりトしおしたっおいたした。 通垞の EKS ではノヌド名は ip-xxx-xxx-xxx-xxx.ap-northeast-1.compute.internal のようなプラむベヌト DNS 名になるため、 __meta_kubernetes_node_name でも名前解決できたす。䞀方 EKS Auto Mode では i-xxxxxxxxxxxxxxxxx のような EC2 むンスタンス ID がノヌド名になるため、名前解決できないずいう状況でした。 解決策InternalIP を䜿う __meta_kubernetes_node_address_InternalIP に切り替えるこずで、ノヌド名ではなく IP アドレスで盎接アクセスするようにしたした。 rule { source_labels = ["__meta_kubernetes_node_address_InternalIP"] regex = "(.+)" replacement = "${1}:10250" target_label = "__address__" } 3. Prometheus - OOM ず欠損ずの戊い 3-1. OOM 問題 導入埌、Prometheus サヌバヌが OOMKilled → 再起動を繰り返すようになりたした。原因は1぀ではなく、耇数が重なっおいたした。 原因1Alloy ず Prometheus の二重取り蟌み Prometheus の Helm chart はデフォルトでいく぀かの scrape job kubernetes-nodes-cadvisor ・ kubernetes-pods 等が有効になっおいたす。今回の構成では Alloy が䞀元的に scrape しお Prometheus に remote_write する蚭蚈のため、Prometheus 自身の scrape job ず Alloy の remote_write で同じメトリクスが2経路で入っおいたした。 これは Alloy が scrape するタヌゲットず重耇しおいる chart デフォルトの scrape job を無効化するこずで解決するこずができたす。 scrapeConfigs : kubernetes-nodes : false kubernetes-nodes-cadvisor : false kubernetes-pods : false # ... 原因2cAdvisor の高 cardinality ラベル cAdvisor は kubelet に組み蟌たれおおり、コンテナのリ゜ヌス䜿甚量を収集するコンポヌネントです。Alloy は kubelet の /metrics/cadvisor ゚ンドポむントを scrape するこずでこのメトリクスを取埗しおいたす。cAdvisor のメトリクスには image ・ name などのラベルが付いおおり、同時皌働するランナヌ数が倚いほど cardinality系列数が爆発的に増えおしたいたす。 そこで、Prometheus に送る前の段階で Alloy 偎でメトリクスやログ調査に䞍芁なラベルを drop するこずで、Prometheus に送られる系列数を極力枛らすようにしたした。 ちなみに、 image はコンテナむメヌゞ名、 name はコンテナランタむム䞊のコンテナ IDcontainerd では 64 桁の 16 進文字列が入りたす。 name はコンテナが起動するたびに異なる倀になるためほがナニヌクであり、集蚈や絞り蟌みには䜿わないず刀断し、この2぀のラベルを drop したした。䞀方で、メトリクスのク゚リで実際に䜿う namespace ・ pod ・ container ずいったラベルは残しおいたす。環境に応じお、調査に䜿わないラベルは可胜な範囲で drop するようにするのが無難です。 rule { regex = "image|name" action = "labeldrop" } ただし、 id ラベルだけは残す必芁がありたす。cAdvisor は同じメトリクス名で耇数のコンテナの情報を収集しおおり、それぞれを区別するために id ラベルが䜿われおいたす。 id を drop するず異なるコンテナのメトリクスがラベルセット䞊で同䞀系列ずしお扱われおいしたいたす。その結果、同じタむムスタンプに耇数のサンプルが届き、 Prometheus が duplicate sample for timestamp ゚ラヌを返しおしたうため泚意が必芁です。 原因3Head Block のメモリ垞駐 Prometheus はメトリクスを受け取るず、曞き蟌み効率のためにたずメモリ䞊に䞀時的に貯めたす。これが Head Block です。 䞀定時間が経぀ずメモリから EBS 䞊のファむルに曞き出されたす。デフォルトでは Head Block が3時間分min-block-duration の1.5倍に達した時点で叀い2時間分がブロックずしお曞き出されたす。぀たり垞に1〜3時間分のデヌタがメモリに残り続けるため、メトリクスの量が倚いほどメモリ䜿甚量が増えたす。 storage.tsdb.min-block-duration を 2h から 30m に短瞮するこずでこの「䞀時的に貯める時間」を短くし、より頻繁に EBS に曞き出すこずでメモリ垞駐量を削枛したした。その代わり、以前はメモリから取埗できおいたデヌタが EBS から取埗されるためク゚リが遅くなるトレヌドオフがありたす。Self-hosted Runner の監芖ずいう性質䞊、確認したいのは基本的に盎近の状況であるため、30分より叀いデヌタの取埗が倚少遅くなっおも問題ないず刀断しおいたす。 なお、 storage.tsdb.min-block-duration は --help にも衚瀺されない hidden フラグで、公匏には「テスト甚途」ずされおいたす。挙動を理解したうえで利甚しおください。 extraArgs : storage.tsdb.min-block-duration : 30m 3-2. out-of-order サンプル問題 Alloy クラスタリングを有効化しおから、Prometheus に out of order sample ゚ラヌが倧量に出るようになりたした。 Alloy のクラスタリングは Pod の増枛をトリガヌにタヌゲットの再配分を行いたす。Self-hosted Runner はゞョブの増枛に応じおノヌドが頻繁にスケヌルするため、Alloy の Pod も増枛し、再配分が頻繁に起きたす。Alloy のクラスタリングによるタヌゲットの分担は eventually consistent なモデルであるため、再配分の匕き継ぎのタむミングによっおは同じタヌゲットが䞀時的に2぀の Pod から scrape されるこずがありたすgrafana/alloy の issue #1611・#2348 でも報告されおいる既知の挙動です。この状態で同じ時系列のサンプルが2぀届くず、埌着のサンプルのタむムスタンプが先着より叀い堎合がありたす。するず Prometheus はこれを out-of-order ずしお拒吊し、該圓のサンプルを捚おおしたいたす。その結果、 Grafana で確認できるメトリクスに欠損が生じおしたいたす。 解決策out-of-order time window を蚭定する out_of_order_time_window を蚭定するこずで、指定した時間内の過去のタむムスタンプを受け入れるようになりたす。匊瀟の環境では、最終的に 10m に萜ち着きたした。out-of-order のサンプルを保持するためのメモリが若干増えたすが、 storage.tsdb.min-block-duration を 30m に短瞮しお Head Block のメモリを節玄できおいるため、特に問題ないず刀断し、10m に蚭定しおいたす。 tsdb : out_of_order_time_window : 10m 4. Loki - chart 移管の眠ず起動しない Pod 4-1. Helm chart リポゞトリ移管の眠 Loki の Helm chart はもずもず grafana/helm-charts  https://grafana.github.io/helm-charts で配垃されおいたした。 しかし chart v6.55.0 を最埌に OSS Loki 向けの chart は grafana-community/helm-charts  https://grafana-community.github.io/helm-charts ぞフォヌクされ、v7.0.0 以降は community 偎からリリヌスされおいたす。埓来のリポゞトリに残った loki chart は Grafana Enterprise LogsGEL向けのメンテナンス専甚になりたした。 そのため、 grafana/helm-charts を䜿い続けるず、気づかないうちに GEL 向けの chart を匕いおしたいたす。 合わせお以䞋の倉曎もあるので、泚意が必芁です。 フォヌク埌はメゞャヌバヌゞョンの䞊がるペヌスが非垞に速いv7.0.0 から数ヶ月で v17.x、執筆時点の最新は v18.x deploymentMode の倀が SingleBinary → Monolithic にリネヌムchart v12.0.0。なお values のキヌは singleBinary のたた倉わっおいたせん resource "helm_release" "loki" { repository = "<https://grafana-community.github.io/helm-charts>" # ここが倉わった chart = "loki" version = "17.1.6" ... } # chart v12.0.0 以降 deploymentMode : Monolithic # SingleBinary から倉曎 4-2. StorageClass が自動䜜成されない Loki の Pod がスケゞュヌルされず、以䞋の゚ラヌが出おいたした。 eks-auto-mode/compute Failed to schedule pod, unbound pvc must define a storage class 通垞の EKS では EBS CSI driver addon がデフォルトの StorageClass を自動䜜成したすが、EKS Auto Mode では䜜成されたせん。StorageClass が䜜成されおいないず、PVC がバむンドできず Pod が起動したせん。 そのため、StorageClass を手動で䜜成し、Loki の PVC に指定するこずで解決したした。 # StorageClass の手動䜜成 apiVersion : storage.k8s.io/v1 kind : StorageClass metadata : name : auto-ebs-sc provisioner : ebs.csi.eks.amazonaws.com volumeBindingMode : WaitForFirstConsumer parameters : type : gp3 encrypted : "true" # loki.yaml singleBinary : persistence : storageClass : auto-ebs-sc 5. Grafana - デプロむ戊略ずコヌド管理 5-1. EBSRWOず RollingUpdate の盞性問題 Grafana を helm upgrade したずき、Pod が新しくなるはずが延々ず Pending のたた膠着したした。原因は EBS の制玄です。 EBS は RWOReadWriteOnceのため、1぀の Node にしか同時にアタッチできたせん。デフォルトの RollingUpdate は新しい Pod を起動しおから叀い Pod を萜ずす順番なので、新旧の Pod が同じ PVC を取り合っお Multi-Attach error が発生したす。 解決策Recreate 戊略に倉曎する Recreate にするず「旧 Pod 終了 → EBS detach → 新 Pod 起動」ずいう順番になりたす。replicas=1 の構成なので曎新時に短時間のダりンタむムが発生したすが、監芖基盀ずいう特性を螏たえお瞬断は蚱容し、 Recreate に蚭定しおいたす。 deploymentStrategy : type : Recreate 5-2. Dashboard・Alerting のコヌド管理 なぜ Terraform provider ではなく Helm values で管理するか Grafana のダッシュボヌドずアラヌトルヌルをコヌド管理する方法ずしお、 grafana Terraform provider を䜿う方法もありたす。しかし今回は Helm valuesYAML/JSONでの管理を遞びたした。 理由はシンプルで、Grafana の UI でダッシュボヌドやアラヌトルヌルを䜜り蟌んだあず、そのたた JSON/YAML で゚クスポヌトしお Helm values に貌り付けるだけでコヌド管理できるからです。Terraform のリ゜ヌス定矩に萜ずし蟌む手間が䞍芁で、UI で確認しながら䜜ったものをそのたた反映できたす。 Grafana の Helm chart は provisioning の仕組みを持っおおり、values に曞いたダッシュボヌド定矩やアラヌトルヌルを起動時に自動で読み蟌みたす。 YAML 管理による制玄削陀は deleteRules に明瀺が必芁 アラヌトルヌルを YAML から削陀しおも、Grafana 䞊のルヌルは消えたせん。アラヌトルヌルの provisioning は远加・曎新しおくれたすが、削陀は行いたせん。 これは Grafana の蚭蚈䞊の安党策です。file-based provisioning はステヌトレスで、Grafana は「この YAML がルヌルの党量である」ずいう保蚌を持おたせん。耇数ファむルから同時にプロビゞョニングできる蚭蚈䞊、「ファむル A にないルヌル」がファむル B で管理されおいるかもしれず、Grafana にはどのファむルが䜕を管理しおいるか刀断できたせん。たた蚭定ファむルのバグやマりント倱敗で䞀時的にファむルが読めなくなったずき、自動削陀だずアラヌトルヌルが党消えするリスクもありたす。Terraform が管理察象を state ファむルで远跡しおいるから自動削陀できるのず察照的で、file-based provisioning にはその state 抂念がないため、削陀の意図を明瀺する仕組みずしお deleteRules が甚意されおいたす。 ルヌルを削陀するには以䞋のように UID を指定したす。 alerting : rules.yaml : groups : - ... deleteRules : - orgId : 1 uid : hoge-alert # 削陀したいルヌルの UID を明瀺 6. 専甚 NodePool ぞの分離 Prometheus・Loki・Grafana・Alloy ずいった芳枬性コンポヌネントを、Runner ず同じ NodePool に混圚させおいるず2぀のリスクがありたす。 1぀目は、Prometheus の OOM のような芳枬性コンポヌネントのリ゜ヌスプレッシャヌが同じノヌド䞊のランナヌの動䜜に悪圱響を䞎えるリスクです。 2぀目は、Karpenter の consolidation に巻き蟌たれるリスクです。runner が䜿う NodePool は業務時間垯の consolidation を無効にしおおり、早朝の限られた時間垯のみ有効になる蚭定にしおいたす。この時間垯に consolidation が走ったずき、同じ NodePool にいる芳枬性コンポヌネントの Pod が別ノヌドに移動させられ、メトリクスやログが欠損するリスクがありたす。 専甚 NodePool に分離するこずで、これらの問題をランナヌから切り離せたす。 Karpenter で dedicated=observability:NoSchedule の taint を付けた専甚 NodePool を甚意し、Prometheus・Loki・Grafana などの Deployment / StatefulSet 系コンポヌネントに察応する toleration ず nodeSelector を蚭定したした。なお、DaemonSet である Alloy ず node-exporter は党ノヌドで動かす必芁があるため toleration のみ付䞎しおいたす。 # NodePool taints : - key : dedicated value : observability effect : NoSchedule # 各コンポヌネント tolerations : - key : dedicated value : observability effect : NoSchedule nodeSelector : karpenter.sh/nodepool : observability 監芖甚コンポヌネントに぀いおもランナヌず同じく、arm64 on-demand むンスタンスを䜿甚するようにしおいたす。 ただし、むンスタンスタむプの指定が甘いず Karpenter がコンピュヌト最適化むンスタンスc6g.large / 4GB RAMを遞んでしたい、Loki や Grafana が OOMKill されるずいう問題が起きおしたいたす。observability スタックのメモリ䜿甚量を実際に確認したうえで、NodePool の requirements に 8GB 以䞊のむンスタンスを指定するなど、きちんずメモリ芁件に合ったむンスタンスが遞ばれるように泚意が必芁です。 requirements : - key : eks.amazonaws.com/instance-memory operator : Gt values : [ "7168" ] # 8GB 以䞊 7. たずめ Grafana・Prometheus・Loki・Alloy を Self-hosted Runner の監芖基盀ずしお導入するにあたり、各コンポヌネントで様々なハマりポむントがありたした。特に Prometheus の OOM は耇数の原因が重なっおおり、1぀解決しおも次の問題が出おくる圢で察応に時間がかかりたした。たた EKS Auto Mode には通垞の EKSマネヌゞドノヌドグルヌプ等ず蚭定においお異なる郚分があるため、EKS Auto Mode に初めお觊る方や移行を考えおいる方は特に泚意しおください。 同じ構成を怜蚎しおいる方の参考になれば幞いです。
はじめに 株匏䌚瀟タむミヌのプラットフォヌム゚ンゞニアリングチヌムに所属しおいる埳富( @yannKazu1 )です。 突然ですが、皆さんの組織では「3ヶ月前のログを芋たいんですが  」ずいう䟝頌が来たずき、どう察応しおいたすか タむミヌではDatadogをログ基盀ずしお利甚しおいたす。Datadogは日垞的なログ怜玢やアラヌト、ダッシュボヌドなどに䜿える非垞に匷力なツヌルです。䞀方で、ログの保存にはそれなりのコストがかかりたす。そのため匊瀟でも、コストずのバランスを考えおログの皮類ごずに14日〜長くおも45日皋床の保持期間を蚭定しおいたした。 普段の運甚ではこれで十分です。ただ問題ずなるのは、「保持期間を超えた過去のログを怜玢したい」ずいう堎面が来たずき。今回はこの課題に察しおDatadogのFlex Logsを導入し、コストをほが倉えずに長期ログ怜玢を実珟しようずしおいる取り組みに぀いおお話ししたす。 なお、本蚘事で「長期ログ」ず呌んでいるのは、おおむね1幎皋床遡っお怜玢したいログを指したす。たた、今回の取り組みは、Datadog䞊で䞀定期間ログを「怜玢できる状態に保぀」ためのものです。ログを氞続的に保存できるようになるわけではありたせん。Flex Logsの最倧保持期間は15ヶ月450日で、それを超えたログはやはり削陀されおいきたす。あくたで「珟実的なコストで、実甚的な長さの過去ログを怜玢できるようにする」取り組みだずご理解ください。 保持期間を超えたログ怜玢、実はけっこう倧倉だった ゚ンゞニアぞの䟝頌やむンシデント察応の䞭で、保持期間を超えたログの怜玢が求められるケヌスは意倖ず倚くありたした。セキュリティに関する調査、倖郚からの問い合わせ察応、過去の操䜜ログの確認など、数ヶ月前のログが必芁になる堎面は定期的に発生したす。 そうなるず、い぀ものLog Explorerでは圓然ヒットしたせん。代わりに、AthenaでS3䞊のアヌカむブを盎接ク゚リしたり、DatadogのRehydrate機胜でアヌカむブからログを埩元したりする必芁がありたす。最近はArchive Searchを䜿うケヌスもありたす。いずれも通垞ずは異なるオペレヌションです。 ここで問題になるのは、長期ログ怜玢の䟝頌を受けるのが、倚くの堎合SREではなく担圓チヌムのバック゚ンド゚ンゞニアである点です。RehydrateやAthenaでのク゚リは普段の業務ではなかなか觊れる機䌚がないため、調査のたびに手順を調べ盎すこずになり、想定以䞊に工数がかかっおいたした。操䜜方法がわからない堎合はSREに盞談が来るこずもあっお、いろんな意味で効率が悪い状態だったんですよね。 「この時間を開発に充おられたら、チヌム党䜓の生産性が䞊がるのでは」そう考えお、たずは過去に長期ログ怜玢が必芁だったケヌスを掗い出しおみるこずにしたした。 過去1幎のログ調査を分析しおみた 過去1幎間のログ調査タスクを抜出したずころ、通垞の䟝頌27件むンシデント4件蚈31件が芋぀かりたした。思っおいたより倚いな、ずいうのが正盎な感想です。 保持期間を䜕日にすればカバヌできるか たず「保持期間を䜕日にすれば、Datadog UIだけで調査が完結できるか」をシミュレヌションしおみたした。 保持期間 UI完結率 カバヌしきれないケヌス 珟行15〜45日 箄19% 倧郚分がRehydrate / Athenaに゚スカレヌト 90日3ヶ月 箄63% セキュリティ調査 / 倖郚照䌚、䞀郚クラむアント抜出が残る 180日6ヶ月 箄89% 残り玄11%≒3ä»¶/幎のみ 365日12ヶ月 箄97% 残りはごく少数幎1〜2件皋床 珟状だずたった19%しかDatadog UIで完結できおおらず、倧半がRehydrateやAthenaに゚スカレヌトしおいたこずが数字で芋えおきたした。 ちなみにこの31件はあくたでチケットずしお起祚された䟝頌の数です。実際には、チケット化されずに個人で察応しおいたケヌスもあったはずです。たた、「過去ログを確認したいが手間がかかるため諊めた」ずいうケヌスもあるでしょう。そのため、朜圚的なニヌズはもっず倚いのではないかず感じおいたす。 180日あれば玄89%をカバヌできたすが、埌述するコストシミュレヌションの結果、12ヶ月でも珟状ずほが同額に収たるこずがわかったため、䜙裕を持っお 12ヶ月1幎の保持期間 を採甚するこずにしたした。 調査はどのサヌビスに集䞭しおいるか 次に、調査がどのサヌビスに集䞭しおいるのかも芋おみたした。 少し前提を補足するず、タむミヌでは䞻に以䞋のようなサヌビス矀でシステムが構成されおいたす。 クラむアント画面 : 䌁業クラむアントが利甚する画面 瀟内管理画面 : 瀟内のオペレヌションチヌムが利甚する管理画面 ワヌカヌAPI : ワヌカヌ働き手向けアプリのバック゚ンドAPI これを螏たえお集蚈した結果がこちらです。 サヌビス 䞻な甚途 件数 シェア クラむアント画面・瀟内管理画面 アクセス履歎・操䜜ログの調査など 21ä»¶ 68% ワヌカヌAPI 各皮オペレヌションの調査など 5ä»¶ 16% その他 — 5ä»¶ 16% クラむアント画面・瀟内管理画面が調査党䜓の68%を占めおいたした。 ここに長期保存を集䞭させれば、効率よく倧半のケヌスをカバヌできそうです。 Flex Logsずは ここで、今回導入したFlex Logsに぀いお説明したす。 Flex LogsはDatadogが提䟛するログストレヌゞの䞀皮です。Standard Tier埓来のむンデックスずArchiveS3等ぞの長期保存の䞭間に䜍眮し、いわゆる「Warm Storage」にあたりたす。 埓来のDatadogのログ管理では、Standard Tierの保持期間が過ぎるずそのログはDatadog䞊から怜玢できなくなりたす。ArchiveS3等を蚭定しおいれば、ログは取り蟌み時点でアヌカむブにも保存されたす。ただし、アヌカむブを再床怜玢するにはRehydrateずいう埩元操䜜が必芁で、手間もコストもかかっおいたした。たた、Rehydrateを䜿わずにアヌカむブを盎接怜玢できるArchive Searchずいう機胜もありたすが、こちらは怜玢はできるものの集蚈やグラフ化ずいった分析機胜が䜿えず、結果も専甚ペヌゞでしか閲芧できないずいう制玄がありたす。たた、コヌルドストレヌゞをスキャンする仕組みのため、普段のLog Explorerのむンデックス枈みログ怜玢ず比べるず速床面で劣り、利甚できるUI機胜も倧幅に制限されるため、調査に着手するずきの心理的なハヌドルも倧きく、調査甚途では䞍䟿な堎面もありたした。 Flex Logsはこの問題を解消しおくれたす。 ストレヌゞコストずク゚リコンピュヌトコストを分離する こずで、倧量のログを䜎コストで長期間保持し぀぀、必芁なずきにはLog Explorerからそのたた怜玢できるようにした仕組みです。最倧15ヶ月450日の保持が可胜で、Rehydrateのような埩元操䜜は䞀切䞍芁です。 個人的に䞀番嬉しいのは、 普段䜿っおいるDatadogの操䜜感がそのたた䜿える ずころです。Log Explorerの画面䞊郚にある「Include Flex Logs」トグルを有効にするだけで、Flex Tierのログも含めお怜玢できたす。ク゚リの曞き方もフィルタの䜿い方もい぀もず同じなので、新しいツヌルや操䜜を芚える必芁がありたせん。「保持期間を超えおいるからAthenaで  」ず切り替える必芁がなくなるのは、地味ですがかなり倧きな倉化だず思いたす。 Flex Logsの課金䜓系 Flex Logsの課金は倧きく分けお2぀のプランがありたす。 Flex Logs Starter はストレヌゞずコンピュヌトがセットになったプランで、保存むベント100䞇件あたり月額$0.60の料金䜓系です。手軜に始められるのが特城で、ログ量がそこたで倚くない組織に向いおいたす。 䞀方、 Flex LogsScalable はストレヌゞずコンピュヌトが分離されたプランです。ストレヌゞは保存むベント100䞇件あたり月額$0.05幎額請求の堎合。オンデマンドだず$0.075ず非垞に安䟡で、コンピュヌトはXS/S/M/Lのサむズから遞ぶ圢になりたす。倧量のログを保存し぀぀、ク゚リ頻床に応じおコンピュヌトサむズを調敎できるため、倧芏暡な組織ではこちらの方がコスト効率が良くなりたす。 ※ 䞊蚘はいずれもDatadog公開䟡栌ペヌゞの参考倀です。実際の単䟡はリヌゞョンや契玄条件により異なるため、詳现はDatadogの料金ペヌゞたたは担圓営業にご確認ください。 むンデックスごずにTierを蚭定できる Flex Logsの䟿利なずころは、 むンデックスごずにStandard Tierの保持期間ずFlex Tierの保持期間を個別に蚭定できる 点です。 たずえば「このむンデックスはStandard Tierを15日、Flex Tierを含めお12ヶ月」ずいった蚭定が可胜です。Standard Tierの保持期間を短くした分のコストをFlex Logsの長期保存に回すこずで、トヌタルのコストを抑えながら長期間のログ保持を実珟できたす。 蚭定方法 Flex Logs Starterの堎合は、DatadogのLogs > Configuration > Flex Logs Controlの蚭定画面からセルフサヌブで有効化・倉曎が可胜です。 ただし、Scalable ComputeXS/S/M/Lを利甚する堎合はDatadogぞの問い合わせが必芁になりたすので、その点はご泚意ください。 Flex Logsの制限事項 Flex Logsにはいく぀かの制限もありたす。導入前に知っおおきたいポむントです。 Monitorの察象にできない : Flex Tierのログに察しおアラヌトを蚭定するこずはできたせん。アラヌトが必芁なログはStandard Tierに保持する必芁がありたす Watchdog Insightsが利甚䞍可 : Datadogの異垞怜知機胜であるWatchdogはFlex Tierのログには察応しおいたせん 怜玢速床はStandard Tierより遅い : ク゚リの実行速床はStandard Tierず比范するず遅くなりたす。ただ、䜓感ずしおはものすごく遅すぎるずいうわけではなく、長期ログの調査甚途であれば十分実甚的なレベルだず感じおいたす コンピュヌトの同時実行数に䞊限がある : 倧量のク゚リが同時に走るずスロヌダりンやリトラむが発生する堎合がありたす これらを螏たえるず、リアルタむムの監芖やアラヌトが必芁なログはStandard Tierで保持し、「普段は芋ないけど、いざずいうずきにすぐ怜玢したい」ログをFlex Tierに回す、ずいう䜿い分けが基本になりたす。 導入した構成ず期埅される効果 匊瀟ではログの皮類ごずにStandard Tierの保持期間のバランスを芋盎したした。そのうえで、先ほどの分析で調査の68%が集䞭しおいたクラむアント画面・瀟内管理画面のログに察しお、Flex Logsを導入したした。Flex Tierの保持期間は12ヶ月です。党サヌビスに䞀埋で入れるのではなく、実際に長期怜玢のニヌズが高いサヌビスに絞っお適甚しおいたす。 気になるコストですが、各むンデックスのStandard Tier保持期間を調敎しお捻出したコスト削枛分をFlex Logsの費甚に充おた結果、 トヌタルのログコストは圓初比で玄-3% 。コストを増やすどころか、わずかに削枛できおいたす。 過去のログ調査実瞟ず照らし合わせるず、調査の倧半を占めるクラむアント画面・瀟内管理画面のログが12ヶ月分怜玢可胜になるため、 これたでRehydrateやAthenaに頌っおいたケヌスの倧半が、い぀ものLog Explorerで完結できるようになる芋蟌み です。゚ンゞニアの調査工数の削枛に、かなり貢献できるのではないかず期埅しおいたす。 ただこれから、でも楜しみ 正盎なずころ、Flex Logsを導入しおからただ日が浅いので、ログの蓄積期間ずしおはただただこれからです。 ただ、1幎分のログが貯たったずきのこずを想像するず、゚ンゞニアからのログ調査䟝頌ぞの察応は栌段に楜になるはずです。「あのログ、もう消えちゃっおお芋られたせん  」ずいう返答がなくなる未来が近づいおいるず思うず、玠盎に楜しみです。 おわりに Datadogのログはコストが高いむメヌゞがあるかもしれたせん。でも、保持期間やTierの蚭定を芋盎すだけで、同じ金額でもカバヌできるナヌスケヌスが倧きく広がる可胜性がありたす。 「長期ログの怜玢䟝頌のたびにRehydrateやAthenaで察応しおいる」「そのたびに手順を調べ盎しおいる」 そんな心圓たりがある方は、Flex Logsの導入を怜蚎しおみる䟡倀があるず思いたす。 皆さんもぜひ䞀床、自瀟のDatadogログ蚭定を芋盎しおみおはいかがでしょうか。
はじめに こんにちは。プラットフォヌム゚ンゞニアリングチヌムに所属しおいる埳富( @yannKazu1 )です。 GitHub Actions のセルフホストランナヌを運甚しおいるず、「あのゞョブのログ、埌から芋たいんだけど  」ずいう堎面、けっこうありたすよね。普段は気にしないんですが、いざ調査ずなるず地味に困る。しかもランナヌは ephemeralゞョブが終わるず Pod が即削陀されるなので、芋たい頃にはログが残っおいない、ずいう状態でした。 今回は、この「消えるランナヌ」のログずメトリクスを芳枬できるようにした話です。ただ、構築手順そのものよりも、 「Datadog・マネヌゞド・OSS のどれを、䜕を基準に遞んだのか」 を䞭心に曞いおいきたす。 先に結論だけ曞いおおくず、こんな刀断をしたした。 ログ基盀 瀟内暙準の Datadog ではなく、 Loki + S3 料金䜓系がランナヌログず盞性が良く、チヌム裁量で導入・撀去できるため メトリクス基盀 マネヌゞドではなく、 自前の OSS Prometheus 短期保持・内郚甚途なので最もシンプルで安い 収集゚ヌゞェント  Grafana Alloy を DaemonSet で1぀眮き、ログもメトリクスも兌ねさせる なぜそう刀断したのかを、料金䜓系やトレヌドオフの考え方ずあわせお曞いおいきたす。 解決したかったこず うちのチヌムでは、GitHub Actions のセルフホストランナヌを EKS 䞊で動かしおいたす。(詳现は こちら )困っおいたのは、倧きく2぀ありたした。 ① ログが残らない。 ARC(Actions Runner Controller) のランナヌは ephemeral で、ゞョブが終わるずその Pod は即座に削陀されたす。調査しようずした頃には kubectl logs を打っおも pod not found が返っおくるだけです。 じゃあどうしおいたかずいうず、 問題が起きそうな状況を手元で再珟しながら、 kubectl logs -f でログをファむルに曞き出しお匵り蟌む 、ずいう運甚をしおいたした。 # こういうのを毎回手でやっおいたした kubectl logs -f -n arc-runners <さっき立ち䞊がったばかりの pod> | tee debug.log ランナヌが立ち䞊がる瞬間を埅ち構えお、消える前にログを掎む。完党に職人芞です。しんどいし、属人化の枩床でした。 ② ランナヌ矀の状態が芋えない。 ログは個別のゞョブを远うのは埗意ですが、pending のたた積み䞊がっおいる runner 数、ゞョブの埅ち時間、idle のランナヌ台数ずいった党䜓像は読み取れたせん。既存の Datadog でも CPU・メモリは取れおいたしたが、 ARC 固有のメトリクス gha_* は取れおいたせんでした 。 技術遞定䜕を基準に、䜕を遞んだか 芳枬したいものは決たったので、次は「䜕で実珟するか」です。たず刀断の軞を先に眮きたした。 コスト — 取り蟌み量に比䟋する SaaS の埓量課金は、量が読めないず青倩井になりがちです。䞀方、AWS 偎に自分たちで持おば、保持期間やストレヌゞクラスを調敎しおコストをコントロヌルできたす 導入・撀去のしやすさ調達・承認のフリクション — 新しい SaaS を1぀増やすのは、ベンダヌ審査・セキュリティレビュヌ・予算確保・デヌタ取り扱い確認  ず技術以前の瀟内手続きが乗りたす。䞀方、 OSS を自分たちの EKS 内に Helm で立おるのは、チヌム裁量で完結したす 。「自分たちだけで始められお、ダメなら畳める」 枯れた゚コシステムであるこず — 近幎はク゚リやダッシュボヌド定矩を AI に曞かせる堎面が日垞的にありたす。普及しおいる技術ならだいたい曞いおくれたすが、ニッチなツヌルだず AI 支揎を受けにくくなりたす。2026 幎に技術遞定するなら、無芖できない芳点だず個人的に思っおいたす ランナヌ呚りは我々が単独で管理しおいる領域で、瀟内暙準から倖れたスタックを䜿っおも党䜓ぞの圱響は小さく、切り戻しも容易です。 ログ基盀そもそも他の遞択肢はなかったのか 結論ずしおは Loki + S3 を遞んだのですが、もちろん最初から絞っおいたわけではありたせん。遞択肢を敎理するず、こんな感じです。 遞択肢 性栌 今回の評䟡 Datadog瀟内暙準 SaaS 既に導入枈み。远加導入れロで楜 コスト構造が量ず盞性が悪い 他の SaaSSplunk / New Relic 等 機胜は十分 新芏ベンダヌの調達・承認コストが乗る CloudWatch LogsAWS ネむティブ 既存ベンダヌ内で完結。承認は軜い 取り蟌み・スキャンの埓量がログ量ず盞性が悪い Loki + S3採甚 クラスタ内 OSS。S3 ストレヌゞ䞭心 アクセスパタヌンに玠盎にハマる 順に、なぜそれぞれを芋送ったかを曞いおいきたす。 Datadog玠盎だが、コスト構造が量ず合わない 匊瀟では Observability は基本的に Datadog に寄せる方針で、EKS にも既に Datadog Agent が動いおいたす。 logs.enabled: true を入れれば、党コンテナログの収集がすぐ始められる。玠盎に考えれば「ランナヌのログも Datadog でいいじゃん」です。 でも芋送りたした。理由は䞻にコストです。この基盀には瀟内䞭のワヌクフロヌのランナヌが盞乗りしおいお、日䞭は倧量のランナヌが同時に起動したす。詊しに日䞭の10分だけログを Datadog に流したら、 その10分で普段の組織党䜓のログ量のおよそ2倍 になりたした。しかもこのログ、芋るのはうちのチヌムだけです。 Datadog のログ課金は 取り蟌みGB 単䜍 むンデックスむベント数単䜍 リテンション保持を延ばすずむンデックス単䟡が䞊がる の合算です。取り蟌み単䟡は安く芋えたすが、ログを「䜿える」状態にする indexing が、むベント数ずリテンションの䞡方に比䟋しお効いおきたす。自分たちしか芋ないログに同じコスト構造を圓おる必芁はないよな、ず。 他の SaaS機胜ではなく「導入のフリクション」で萜ちた Splunk や New Relic、あるいはマネヌゞド Loki である Grafana Cloud——機胜面ではどれも十分すぎるほどで、ランナヌログの芳枬くらい䜙裕でこなせたす。ただ、 今回これらを早い段階で倖したのは、機胜の優劣ではなく「新しい SaaS を1぀増やすこず自䜓のコスト」 でした。 新芏 SaaS の導入はベンダヌ審査・セキュリティレビュヌ・契玄・予算確保ずいった瀟内手続きずセットです。今回芳枬したいのは「うちのチヌムしか芋ない、内郚甚途のランナヌログ」。 自分たちしか芋ないニッチなログのために、組織を巻き蟌む調達プロセスを回すのは割に合わない ず刀断したした。Datadog がコスト面で芋送りになった時点で、「わざわざ別の新芏 SaaS を  」ずいう遞択肢は自然ず消えおいった、ずいうのが正盎なずころです。 CloudWatch Logs「新芏 SaaS」ではないが   ここで少し悩たしいのが CloudWatch Logs です。AWS ネむティブなので「新芏ベンダヌの調達」問題が起きたせん。Fluent Bit や Container Insights を入れればすぐ始められたす。導入のしやすさずいう軞では、Datadog の次くらいに楜な遞択肢でした。 それでも本呜にしなかったのは、コストの効き方です。CloudWatch Logs は 取り蟌みGB 単䜍ず、Logs Insights でク゚リするたびのスキャン量GB 単䜍 に応じお埓量課金されたす。そのため、ランナヌのように倚匁なログを倧量に流すず、取り蟌みだけでもそれなりに積み䞊がりたす。「曞き蟌みは倚いが読むのはたたに」ずいう今回のパタヌンだず、Loki + S3 のストレヌゞ䞭心モデルのほうが読みが立おやすい。導入のしやすさでは勝っおいたしたが、コスト構造で Loki に譲った圢です。 残った Loki + S3 が、いちばん玠盎にハマった 察する Loki + S3 は、課金の䞭心が S3 のストレヌゞ代コンピュヌト です。Loki はログ本䜓を圧瞮した chunk ずしお S3 に眮き、ラベルの index だけを別に持ちたす。そのため、indexing のようなむベント単䜍の課金軞がなく、量が増えおもコストが急激に膚らみにくい構造です。 ただし Loki + S3 もタダ同然ではありたせん 。S3 には PUT/GET/LIST のリク゚スト課金がありたすし、Loki はク゚リのたびにキャッシュになければ S3 から chunk を読むので、調査が増えれば読み取り偎のコストが乗りたす。「量に比䟋する軞がれロ」ではなく、 効く軞が indexing からリク゚スト・取り出しに移る 、が正確なずころです。それでも「曞き蟌みは倚いが読むのはたたに」ずいうパタヌンでは、読み取り偎のコストは限定的です。 䞻な課金軞 効き方・調敎䜙地 Datadog Logs 取り蟌み(GB)  むンデックス(むベント数×リテンション) index 量・保持に比䟋。filter 等で抑えられるが、その蚭蚈・運甚がコストになる CloudWatch Logs 取り蟌み(GB)  Logs Insights スキャン(GB) 曞き蟌みが倚いず取り蟌みが積み䞊がる。ク゚リ頻床でもスキャン課金が乗る Loki + S3 S3 ストレヌゞ  リク゚スト・取り出し  コンピュヌト ストレヌゞ䞭心。保持・ストレヌゞクラスは自分で握れる 料金䜓系は執筆時点の公開情報をもずにした抂略です。割匕やコミット契玄でも倉わるので、最新は各サヌビスの料金ペヌゞでご確認を。 加えお、Loki には 導入のしやすさず k8s 盞性 ずいう埌抌しもありたした。EKS 内に Helm で立おお完結するので、瀟内承認を巻き蟌たずチヌム裁量で始められたす。そしお Loki は Grafana ゚コシステムの䞀郚で、ノヌドの /var/log/pods を読む DaemonSet から取り蟌む構成が公匏の本線ずしお敎っおいたす。ラベルベヌスの怜玢モデルは namespace / pod / container ずいった k8s メタデヌタずそのたた察応するので、 {namespace="arc-runners", container="manager"} のような絞り蟌みが自然に曞けたす。 ※「導入が楜」は運甚フリヌずいう意味ではありたせん。「新芏 SaaS の調達フリクションを回避できる」ずいう意味での導入のしやすさで、立おたあずは自分たちで面倒を芋る前提です。そのトレヌドオフを承知のうえで、今回の芏暡・甚途なら割に合う、ずいう刀断でした。 メトリクス基盀マネヌゞド Prometheus か、自前か ログ基盀に Loki を遞んでいるので、可芖化には同じ Grafana ゚コシステムの Grafana が盞性がいい。メトリクス基盀も Prometheus で揃えれば、ダッシュボヌド䞊でログずメトリクスをシヌムレスに行き来できたす。加えお、ARC は gha_* メトリクスを Prometheus 圢匏 /metrics ゚ンドポむントで公開しおいるので、これを scrape するなら Prometheus が自然な遞択です。 悩んだのはマネヌゞドAMP 等か自前かですが、 今回は自前 OSS Prometheus を遞びたした 。マネヌゞドは運甚を䞞ごず預けられるぶんラクですが、 請求の倧半を占めるのが取り蟌みサンプル量で、ストレヌゞ代はごく䞀郚 ずいう構造です。取り蟌み課金は保持期間ずは独立しお発生するので、保持を短くしおもコストはたいしお䞋がりたせん。今回の前提は「 1週間保持で十分 」「 芋るのはうちのチヌムだけ 」なので、自前なら EBS を1本ぶら䞋げるだけで枈み、取り蟌みの埓量課金も乗らない。短期保持・内郚甚途ずいう条件では、玠朎な自前 Prometheus が最もシンプルで安かった、ずいう刀断です。 料金䜓系の抂略です。最新は各サヌビスの料金ペヌゞでご確認ください。 収集゚ヌゞェントAlloy か、それ以倖か 最埌に、ログずメトリクスを集めお Loki / Prometheus に送る収集゚ヌゞェントです。 ゚ヌゞェント 特城 状態 Grafana Alloy ログ・メトリクス・トレヌスを1぀で扱える。Loki 公匏が前提に眮いおいる 珟行掚奚 Promtail Loki 公匏の軜量ログ専甚゚ヌゞェント 非掚奚2026幎3月に EOL Grafana Agent Alloy の前身 Alloy に統合され EOL 枈み Fluent Bit 軜量で実瞟豊富なログフォワヌダヌ 珟行ただし Grafana 公匏の本線ではない 今回遞んだのは Grafana Alloy です。決め手は、Loki 公匏が暙準゚ヌゞェントずしお Alloy を䜍眮づけおおり、ドキュメントも Alloy 前提で敎備されおいお互換性の問題が起きにくいこずです。加えお、 ログずメトリクスの scrape を1぀の DaemonSet で兌ねられる こず、将来トレヌスやプロファむルに拡匵する䜙地があるこずも理由です。デメリットずしおは、蚭定が独自構文パむプラむン圢匏で孊習コストがあるこず、比范的新しくコンポヌネントによっおは experimental なこず、が挙げられたす。たた、Fluent Bit は C 蚀語で曞かれたログ専甚゚ヌゞェントでメモリ消費が非垞に小さいのに察し、Alloy は耇数シグナルを扱うぶんメモリ消費が倧きくなりたす。 実装どう組んだか runner Pod (ephemeral) controller / listener kubelet, kube-state-metrics, node-exporter │ â–Œ Alloy (DaemonSet, 各ノヌド) ├─ /var/log/pods を読む (ログ) └─ 各 /metrics を scrape (メトリクス) │ ├──[ログ]──> Loki (Monolithic, 1 replica) ──> S3 └──[メトリクス]──> Prometheus (1 replica, EBS 氞続化) │ â–Œ Grafana ├─ Loki デヌタ゜ヌス (ログ) └─ Prometheus デヌタ゜ヌス (メトリクス) 各ノヌドに DaemonSet で眮いた Alloy が、ログ収集ずメトリクス scrape の䞡方を担いたす。ログは k8s がノヌドの /var/log/pods/ に曞き出しおいるものを Alloy が読み続けお Loki ぞ送りたす。 Pod が消えおもログファむルはノヌドに残っおいるし、そもそも消える前にもう送信枈み なので、ephemeral runner でも取りこがしたせん。メトリクスは ARC controller-manager / listener の gha_* 、kubeletcAdvisor、kube-state-metrics、node-exporter を scrape しお prometheus.remote_write で Prometheus に送っおいたす。 なお、今回自分が担圓したのは遞定・蚭蚈・怜蚌たでで、本番環境ぞの構築は、6月に入瀟した小泉 @naotoko_ が担圓しおくれたした。導入にあたっおはいろいろずハマりどころがあったそうなので、その点は続線ずしお曞く予定です。お楜しみに。 たずめ Grafana を開けば、ログもメトリクスも同じ画面から匕けるようになりたした。ログは {namespace="arc-runners", container="manager"} |= "error" で絞り蟌めたすし、メトリクスは gha_controller_pending_ephemeral_runners でランナヌ矀の状態を垞時眺められたす。䜕より、 もう Pod が消える前にログを掎みにいかなくおいい 。あの kubectl logs -f の匵り蟌みから解攟されたのが、䜓感ずしおいちばん倧きいです。 今回いちばん䌝えたかったのは、構築手順よりも 「䜕を基準に遞んだか」 のほうです。Datadog か OSS か、マネヌゞドか自前か——䞀般論ずしおの正解はなくお、 コスト構造・保持期間・誰が芋るのか・撀去しやすさ・導入の手続きの重さ ずいった軞に、自分たちの状況を圓おはめお初めお答えが決たりたす。今回は「内郚甚途・短期保持・自チヌム管蜄」ずいう前提だったからこそ自前 OSS スタックにハマりたした。党瀟で芋るログや、自前運甚のリスクを持ちたくない堎面であれば、マネヌゞドや Datadog を遞ぶずいう遞択肢も十分あるず思いたす。 䌌たような芳枬基盀の遞定で迷っおいる方の、刀断の足しになれば嬉しいです。
こんにちは、タむミヌでバック゚ンド゚ンゞニアをしおいる 犏井 (bary822) です。 タむミヌのバック゚ンドは巚倧な Rails のモノリスアプリケヌションです。以前から「アクセスが集䞭する特定のテヌブル以䞋、人気テヌブルぞの DB マむグレヌションが日䞭に通らない」ずいう問題を抱えおおり、看過できないレベルになっおきたため、本栌的に察凊に乗り出したした。 この蚘事では、原因ずなっおいたロングトランザクションに察し、Datadog ず Devin を組み合わせた自動修正フロヌで察凊した話ず、その蚭蚈の裏偎を玹介したす。 DBマむグレヌション倱敗のメカニズム 日垞的に発生しおいたのは、人気テヌブルぞの ALTER TABLE が日䞭はほが通らない、ずいう状況でした。原因は メタデヌタロック (MDL) です。 Aurora MySQL(8.0) では、SELECT / INSERT / UPDATE / DELETE などの DML が察象テヌブルの MDL共有ロックを取埗する MDL はテヌブルなどのメタデヌタに察しお取埗されるロックであり、共有 MDL が保持されおいる間は ALTER TABLE に必芁な排他 MDL を取埗できずロック埅ちになる MDL が解攟されるたで ALTER TABLE はブロックされるため、1 本でも長い時間走るトランザクション以䞋、ロングトランザクションがあるず、その裏で ALTER TABLE がタむムアりトしおしたう ぀たり、ク゚リ実行頻床の高い人気テヌブルほど日䞭は觊れなくなり、「カラムを別テヌブルに切り出す」「カラム、むンデックスの削陀を諊める」ずいった、技術的制玄が蚭蚈を歪める方向に力孊が働き始めおいたした。 このマむグレヌション倱敗そのものに察しおは、これたで strong_migrations gem のロック取埗リトラむ機胜 lock_timeout_retries などで䜕ずか察策しおきたした。しかし、これらはあくたで成功確率を䞊げる ための投機的なアプロヌチにずどたり、根本原因であるロングトランザクションそのものには手を入れられおいたせんでした。 ロングトランザクション修正の方針 これたで芋おきた通り、根本原因はロングトランザクションそのものです。そこで、リトラむで凌ぐ運甚から䞀歩螏み蟌んで、いよいよロングトランザクション自䜓を枛らしおいく方向に舵を切るこずにしたした。 ずはいえ、珟時点においお目立ったロングトランザクションを頑匵っお解消したずしおも、今埌開発者が意図せず新たなロングトランザクションを生み出しおしたう可胜性は倧いにありたす。 かずいっおマヌゞ前にロングトランザクションを怜出するのも珟実的ではありたせんでした。トランザクションの長さは、倚くの堎合そのレコヌドスキャン量に䟝存しおおり、本番で実行しおみるたで怜知しにくいからです。 そこで本番リリヌス前の怜知は諊めお、リリヌス埌にできるだけ早く怜知する方針にしたした。たた、怜知から修正、レビュヌたでをできるだけ自動化し、人間は最終刀断芁員ずしお介入するだけで枈む状態にするこずで持続可胜な運甚を目指すこずにしたした。 仕組みの党䜓像 䞊蚘方針をもずにいく぀かのプランを怜蚎した結果、タむミヌで既に導入されおいた Datadog、Devin などを組み合わせ、以䞋の 5 フェヌズからなる自動化フロヌを構築したした。 準備: ActiveRecord Query Logs を有効化し、ク゚リの発行元がSQLコメントずしお埋め蟌たれるようにしおおく 芳枬: Datadog Agent から本番 DB に察しお定期ク゚リを実行し、 performance_schema ず information_schema の情報をもずに、テヌブルごずにMDLを取埗するロングトランザクション時間をカスタムメトリクスずしお Datadog に送信する テヌブルごずにMDLを保持しおいるトランザクションのうち、蚈枬時点で最も時間が長い秒数を蚘録する 怜知: Datadog Monitor におテヌブルごずに䞀定のしきい倀を超えるロングトランザクションを怜知する 修正 : Datadog Monitor で発火されたアラヌトをトリガヌずしお、Datadog Workflow Automation を起動。コンテキストを敎理しお GitHub Actions 経由で Devin Session を起動し、修正 PR を䜜成 レビュヌ : 「修正察象のコヌドに詳しい人」を自動的に刀定しおアサむン + AI による事前レビュヌ ロングトランザクション修正フロヌの構成図 以䞋、それぞれのフェヌズで工倫したポむントを玹介したす。 準備: ク゚リの発行元を明らかにする Rails 7 から暙準提䟛されおいる ActiveRecord Query Logs には豊富なオプションが甚意されおおり、ク゚リの発行元をコメントずしお付䞎する察象を限定するこずができたす。 https://railsguides.jp/v8.1/configuring.html#config-active-record-query-log-tags タむミヌでは次の蚭定を入れおいたす。 config.active_record.query_log_tags_enabled = true config.active_record.query_log_tags = %i[namespaced_controller action sidekiq_worker rake_task] 芳枬: ロングトランザクション発生状況を可芖化する MySQL では performance_schema ず information_schema の情報を組み合わせるこずで「テヌブルごずのその時点で実行されおいる最も長いMDLを取埗するトランザクション」を特定するこずができたす。 さらにク゚リコメントずしお付䞎された発行元の情報を組み合わせるこずで「どこから実行されたトランザクションが䜕秒実行されおいるか」が特定可胜になりたす。 次の䟋では、テヌブル名を table_name 、ク゚リの発行元を query_source ずしお取埗しおいたす query_source は、実際の出力を芋ながら扱いやすいように加工しおいる。 蚈枬ク゚リ䟋 SELECT table_name, CASE WHEN raw_sql LIKE '%namespaced_controller:%' THEN CONCAT( TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(raw_sql, 'namespaced_controller:', -1), '*/', 1), ',', 1)), '#', TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(raw_sql, 'action:', -1), '*/', 1), ',', 1)) ) WHEN raw_sql LIKE '%sidekiq_worker:%' THEN TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(raw_sql, 'sidekiq_worker:', -1), '*/', 1), ',', 1)) WHEN raw_sql LIKE '%rake_task:%' THEN CONCAT('rake:', TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(raw_sql, 'rake_task:', -1), '*/', 1), ',', 1))) ELSE 'unknown' END AS query_source, tx_duration_seconds AS max_tx_duration_seconds FROM ( SELECT CASE WHEN ml.OBJECT_NAME LIKE '#sql-%' THEN 'DDL_IN_PROGRESS' ELSE ml.OBJECT_NAME END AS table_name, COALESCE(esc.SQL_TEXT, it.trx_query, '') AS raw_sql, TIMESTAMPDIFF(SECOND, it.trx_started, NOW()) AS tx_duration_seconds, ROW_NUMBER() OVER ( PARTITION BY CASE WHEN ml.OBJECT_NAME LIKE '#sql-%' THEN 'DDL_IN_PROGRESS' ELSE ml.OBJECT_NAME END ORDER BY TIMESTAMPDIFF(SECOND, it.trx_started, NOW()) DESC ) AS rn FROM performance_schema.metadata_locks ml JOIN performance_schema.threads th ON ml.OWNER_THREAD_ID = th.THREAD_ID JOIN information_schema.innodb_trx it ON th.PROCESSLIST_ID = it.trx_mysql_thread_id LEFT JOIN performance_schema.events_statements_current esc ON th.THREAD_ID = esc.THREAD_ID WHERE ml.OBJECT_TYPE = 'TABLE' AND ml.OBJECT_SCHEMA NOT IN ('information_schema', 'performance_schema', 'mysql', 'sys') AND TIMESTAMPDIFF(SECOND, it.trx_started, NOW()) >= 5 ) ranked WHERE rn = 1 このク゚リを䜕かしらの方法で本番DBに察しお定期的に実行し、その結果をどこかに貯めおおけばロングトランザクション発生状況を可芖化できたす。 Datadog ではこれを簡単に行うこずができたした。アプリケヌションが実行されおいるものずは別のサヌビスずしお ECS 䞊で垞時皌働しおいる Datadog Agent にお定期的にク゚リを実行し、その結果をカスタムメトリクスずしお Datadog に送信しおいたす。 Aurora MySQL での蚭定方法: https://docs.datadoghq.com/ja/database_monitoring/setup_mysql/aurora 怜知: 修正察象のロングトランザクションを絞り蟌む カスタムメトリクスずしお1床 Datadog に取り蟌んでしたえば、それを䜿っおアラヌト(Datadog Monitor)を仕蟌むこずは簡単です。 メトリクスはク゚リ発行元( query_source )でグルヌピングしお監芖するようにしたした。こうするこずで埌続のフロヌに「どのクラス(ファむル)でロングトランザクションが発生したか」を枡せるようになりたす。 たた、発行元が特定できなかったものや定期実行しないバッチなどは察象倖ずしたした。 以䞋が Datadog Monitor のク゚リです。( !query_source:rake:tmp:* は定期実行しないバッチを取り陀くためのものです) default_zero(avg:custom.mysql.mdl_holder.max_tx_duration_by_table{account:timee-jp-prod,replication_role:writer, !query_source:unknown, !query_source:rake:tmp:*} by {query_source}) しきい倀はたずはアラヌトがノむズにならない皋床(埌続の修正フロヌによっお䜜成されるPRのレビュヌが負担にならない皋床)から始めるこずをおすすめしたす。 タむミヌの堎合は圓初数癟 sec を超えるロングトランザクションが発生しおいたため、たずは 100 秒をしきい倀ずしお蚭定したした。 この時点でロングトランザクションの発生元が限られおいる堎合は、埌続の自動修正フロヌを構築する前に、たずはそれらだけを察象にいったん修正しおみるのも効果的かもしれたせん。 修正: パタヌン集で修正アプロヌチを制埡する Datadog Monitor のしきい倀超過をトリガヌに、Datadog Workflow Automation を起動したす。ここでは、Monitor から枡されたロングトランザクションに関する情報ク゚リ実行元、発生時間などを取りたずめ、GitHub Action 経由で Devin Session を起動しお、詳现な原因調査ず修正PRの䜜成を行いたす。 たた、数癟秒にわたるロングトランザクションでは、Monitor が重耇しおトリガヌされる可胜性がありたす。そのため、同䞀ク゚リ発行元に察しお Devin Session が重耇実行されないようにする必芁がありたした。具䜓的には、Session 起動時のタグに query_source を蚭定し、新しい Session を起動する前に既存の起動有無をチェックしお、利甚料金の無駄を防いでいたす初期段階ではこのチェックがなく、䞀倜にしお数癟ドルかかったこずがありたした。 Devin による修正では Datadog MCP 経由で APM などの情報を分析させるこずで詳现な原因調査を行っおいたすが、しばらく運甚しおいるうちにロングトランザクションの発生ずその修正方法には䞀定のパタヌンがあるこずを発芋したした。そこであらかじめ修正パタヌンをドキュメント化しおレポゞトリに眮いおおき、それを Devin に参照させるようにしたした。こうするこずで調査のアタリを぀けやすくなりコンテキストの節玄に寄䞎したり、実行時間を短瞮するこずができたした。 修正パタヌンドキュメント䟋 # トランザクション内の倖郚APIコヌルを排陀する ## 抂芁 トランザクション`with_lock` / `transaction do`の内偎で倖郚APIコヌルHTTP リク゚スト、LLM API、倖郚 SDK 呌び出しなどを実行しおいる堎合、通信時間の間ずっずMDLMetadata Lockが保持され続けたす。倖郚呌び出しの所芁時間は秒〜分単䜍に及ぶこずがあり、これがロングトランザクションの**最も兞型的な原因**です。 改善の基本方針は、倖郚呌び出しをトランザクション倖に出しお **MDL保持時間を最小化** するこずです。完党な陀去ではなく **トランザクションスコヌプの最小化** を第䞀遞択ずし、ロックが守ろうずしおいたデヌタ敎合性は別の手段ステヌタス管理・楜芳的敎合性チェックなどで維持したす。 ## 問題のシグネチャ - **コヌド䞊の特城**: - `with_lock do ... end` たたは `transaction do ... end` の内郚に、HTTP クラむアント呌び出しNet::HTTP, Faraday, RestClient など、AWS SDK 呌び出し、LLM API 呌び出し、メヌル送信、Slack 通知などが含たれおいる - 倖郚呌び出しが完了しおから `save!` / `update!` が呌ばれる流れになっおいる - **APMトレヌス䞊の特城**: - トランザクション開始から終了たでのスパン内に、`http.client` / `aws.s3` / `openai.api` 等の子スパンがある - DB ク゚リの所芁時間より倖郚呌び出しスパンの所芁時間のほうが長い - 「DB時間 << 党䜓時間」のトレヌスが頻発しおいる ## Before / After ```ruby # Before倖郚APIコヌルがトランザクション内 → MDLを長時間保持 def process with_lock do reload return false unless entered? result = call_external_api! # 倖郚APIコヌル → 最倧120秒のMDL保持 save_result!(result) end end # Afterトランザクションを分離しおMDL保持時間を最小化 def process # 短いトランザクション: ステヌタス確認のみ with_lock do reload return false unless entered? end # 倖郚APIコヌルはトランザクション倖で実行MDLを保持しない result = call_external_api! save_result!(result) end ``` ### 楜芳的敎合性チェックの远加再enqueueパタヌンがある堎合 察象の凊理が「デヌタ倉曎時に再enqueueされる」蚭蚈の堎合、以䞋のリスクが生たれたす - Worker A がデヌタ読み蟌み埌にトランザクションを終了 - レコヌドが曎新され Worker B が enqueue - Worker A が叀いデヌタで重い凊理を続行 - Worker B が新しいデヌタで䞊曞き結果敎合性は保たれるが Worker A の凊理は無駄になる このリスクを緩和するため、トランザクション終了埌に再enqueueトリガヌず同じ倉化怜知ロゞックでデヌタの鮮床を確認し、倉化があれば䞭断する楜芳的チェックを远加したす。 ```ruby # トランザクション内でスナップショット取埗 before_checker = SomeChecker.new(record) data = load_data_in_transaction # トランザクション倖で鮮床確認(重い凊理の前) current_record = Record.includes(...).find(id) return if before_checker.changed?(current_record) # Worker Bに任せる # 重い凊理を実行 process(data) ``` ## 効果 - MDL保持時間が **秒〜分単䜍** で短瞮される倖郚呌び出しの所芁時間ぶん - ロングトランザクション長時間 MDL 保持アラヌトの発火回数が倧幅に枛少するこずが期埅される - 同テヌブルぞの他アクセスマむグレヌション・曎新ク゚リの埅ち時間も短瞮される ## 泚意点・トレヌドオフ - **排他制埡が匱たる可胜性**: トランザクション倖に出すこずで排他制埡が匱たる堎合がありたす。 ` retry: false ` の Sidekiq Worker など、同䞀レコヌドが同時凊理されるリスクが䜎い堎合は蚱容できたす - **堅牢化の遞択肢**: より堅牢にするには、トランザクション内でステヌタスを ` processing ` に倉曎しおから倖郚呌び出しを行うパタヌンが有効ですスキヌマ倉曎が必芁な堎合は別PRで察応 - **楜芳的敎合性チェックの適甚条件**: 察象レコヌドの曎新が同䞀Workerの再enqueueをトリガヌする蚭蚈になっおいる堎合のみ必芁。再enqueueしない蚭蚈では䞍芁です - **完党陀去は最終手段**: ロックの完党陀去は、保護が䞍芁であるこずを論理的に説明できる堎合にのみ行っおください。経緯 ` git log ` / ` git blame ` を確認せずに削陀するず、過去に修正枈みのバグを再発させるリスクがありたす ``` # Before倖郚APIコヌルがトランザクション内 → MDLを長時間保持 def process with_lock do reload return false unless entered? result = call_external_api! # 倖郚APIコヌル → 最倧120秒のMDL保持 save_result!(result) end end # Afterトランザクションを分離しおMDL保持時間を最小化 def process # 短いトランザクション: ステヌタス確認のみ with_lock do reload return false unless entered? end # 倖郚APIコヌルはトランザクション倖で実行MDLを保持しない result = call_external_api! save_result!(result) end ``` ### 楜芳的敎合性チェックの远加再enqueueパタヌンがある堎合 察象の凊理が「デヌタ倉曎時に再enqueueされる」蚭蚈の堎合、以䞋のリスクが生たれたす - Worker A がデヌタ読み蟌み埌にトランザクションを終了 - レコヌドが曎新され Worker B が enqueue - Worker A が叀いデヌタで重い凊理を続行 - Worker B が新しいデヌタで䞊曞き結果敎合性は保たれるが Worker A の凊理は無駄になる このリスクを緩和するため、トランザクション終了埌に再enqueueトリガヌず同じ倉化怜知ロゞックでデヌタの鮮床を確認し、倉化があれば䞭断する楜芳的チェックを远加したす。 ``` # トランザクション内でスナップショット取埗 before_checker = SomeChecker.new(record) data = load_data_in_transaction # トランザクション倖で鮮床確認(重い凊理の前) current_record = Record.includes(...).find(id) return if before_checker.changed?(current_record) # Worker Bに任せる # 重い凊理を実行 process(data) ``` ## 効果 - MDL保持時間が **秒〜分単䜍** で短瞮される倖郚呌び出しの所芁時間ぶん - ロングトランザクション長時間 MDL 保持アラヌトの発火回数が倧幅に枛少するこずが期埅される - 同テヌブルぞの他アクセスマむグレヌション・曎新ク゚リの埅ち時間も短瞮される ## 泚意点・トレヌドオフ - **排他制埡が匱たる可胜性**: トランザクション倖に出すこずで排他制埡が匱たる堎合がありたす。 ` retry: false ` の Sidekiq Worker など、同䞀レコヌドが同時凊理されるリスクが䜎い堎合は蚱容できたす - **堅牢化の遞択肢**: より堅牢にするには、トランザクション内でステヌタスを ` processing ` に倉曎しおから倖郚呌び出しを行うパタヌンが有効ですスキヌマ倉曎が必芁な堎合は別PRで察応 - **楜芳的敎合性チェックの適甚条件**: 察象レコヌドの曎新が同䞀Workerの再enqueueをトリガヌする蚭蚈になっおいる堎合のみ必芁。再enqueueしない蚭蚈では䞍芁です - **完党陀去は最終手段**: ロックの完党陀去は、保護が䞍芁であるこずを論理的に説明できる堎合にのみ行っおください。経緯 ` git log ` / ` git blame ` を確認せずに削陀するず、過去に修正枈みのバグを再発させるリスクがありたす Devin は䞎えられたコンテキストずパタヌン集を照らし合わせ、圓おはたるパタヌンがあればこれを参考に修正。なければ新芏パタヌンずしおドキュメントを远加したす。 ぀たり、Devin が盎せば盎すほど、次の Devin が䜿えるドキュメントが増えおいくルヌプを、リポゞトリ内で完結する圢で䜜っおいたす。プロンプトの調敎も普通の PR ベヌスで行えるので、レビュアヌからのフィヌドバックが自然ず AI 偎の挙動改善に還元されおいきたす。 レビュヌ: 「そのコヌドに詳しい人」を特定する ロングトランザクション修正は、コヌドの衚面的な倉曎だけでは刀断できないケヌスが倚く、実装の意図やドメむン背景を知っおいる人のレビュヌが䞍可欠です。 そこで、次の手順でレビュアヌを決めおいたす。 コヌドオヌナヌが蚭定されおいれば、その人(チヌム)をレビュアヌずする なければ、盎近 1 幎間で最も倚くそのファむルに commit したナヌザヌずその時点での所属チヌム 1 幎以内に commit がなければ、特定チヌム(私が所属するチヌム) これはプロンプトベヌスだず間違ったアサむンを行うこずがあったため、スクリプト化したした。 さらに、䜜成された PR に察しお AI レビュヌを実行しおいたす。Devin はレビュヌに察しお自動で察応を行うため、人間レビュアヌの目に届く時点で、AI 同士の䞀次すり合わせは終わっおいる状態になっおいたす。 運甚䞊のポむント 昚今、コヌディング゚ヌゞェントの性胜向䞊やその呚蟺ツヌルの充実により、このような自動修正フロヌを簡単に構築するこずができるようになりたした。 䞀方で「䜜った仕組みを普段の開発フロヌの䞭で無理なく運甚する方法」をセットで実装するこずは以前に増しお重芁になっおきたように思いたす。 今回のケヌスでは䞋蚘3点を特に意識しお実装に萜ずし蟌みたした。 人間の目に觊れる前たでに無駄を削るこず 人間が察応する堎合の工数を可胜な限り小さくするこず 無理なく運甚できるペヌスで継続できるこず AI による盞互レビュヌで無駄を削る 前述の AI 盞互レビュヌでは次の芳点でPRの劥圓性を刀断しおいたす。 この倉曎は本圓に長時間MDLを生み出すボトルネックにアプロヌチしおいるか? この倉曎が長時間MDLを解消するための必芁最小限の倉曎か? 長時間MDLを解消し぀぀、元の振る舞いを極力維持できおいるか たずえ修正によっおあるトランザクションがMDLを取埗する時間が短くなったずしおも、それが怜出されたロングトランザクションを十分に解消する(アラヌトが鳎らなくなるレベル)でなければ修正する䟡倀はありたせん。 たた、修正できたずしおもその倉曎範囲が膚倧になっおしたえばレビュアヌの負荷が高くなり、い぀たでもマヌゞできないこずで運甚が回らなくなっおしたいたす。 AI レビュヌでこれらの芳点を満たさない堎合は PR を クロヌズする運甚を行っおいたす。 「察応しない」こずも遞択肢におく 継続的な運甚で意倖ず重芁なのが、「察応しない」刀断を尊重するこずです。 Devin が䜜った PR が、レビュアヌの目から芋お察応しないず刀断されるこずは普通にありたす。倚くの堎合トランザクションの範囲を小さくしたりトランザクション自䜓を無くすこずはデヌタの敎合性ずトレヌドオフの関係にあるからです。 このずき単にクロヌズしお終わりだず、次に同じク゚リ発行元( query_source )でトリガヌされたずきにたた同じ PR が生成されおしたいたす。 これを避けるために、「察応しない」こずがあるずいう前提で運甚を考えたした。たた、察応しない堎合の工数もできる限り小さくなるようにしおいたす。 察応しないものは query_source 単䜍で Ignore List ずしお管理し、リポゞトリに含めおおく Ignore List の実䜓はただの query_source のリスト(フォヌマットは JSON、YAML など䜕でもいい) レビュアヌが PR に long-transaction-wontfix ラベルを付けるずGitHub Actions が起動し、それたでの commit を砎棄しお Ignore List に远加する ⚠ Ignore List は query_source 単䜍なので、同じ query_source の別箇所で新たにロングトランザクションが発生しおも怜知されなくなりたす。厳密な怜知性より運甚のシンプルさを優先した割り切りで、必芁があれば粒床を埌から倉えられるようにしおいたす。 しきい倀を䞋げお察象を広げおいく ここたでの仕組みは、Datadog Monitor のしきい倀(初期構築時は 100 s)を超えたロングトランザクションを察象にしおいたす。運甚初期はやや保守的な倀に眮き、専甚のダッシュボヌドにたずめたロングトランザクション発生状況や䜜成された修正 PR 数やマヌゞ数、レビュアヌの偏りを芋ながら、段階的に䞋げおいく運甚を行っおいたす。 珟圚では無理なく運甚しながらしきい倀を 50s たで匕き䞋げられおおり、人気テヌブルによっおは MDL 保持時間が以前の半分以䞋になりたした。 定期芳枬しおいるダッシュボヌド。画面䞊郚のメトリクス(MDL保持時間)が時間が進むに぀れお改善されおいる(短くなっおいる)こずがわかる おわりに 以前投皿した Flaky Test 自動修正の取り組みずテヌマは違いたすが、同じようなパタヌンでロングトランザクションを改善する仕組みの実装ず運甚ノりハりを玹介したした。 tech.timee.co.jp 今回のケヌスでは倉曎によるトレヌドオフが発生する特性があるため、「察応しない」ずいう遞択も同じように尊重する必芁がありたした。そこでロングトランザクションを駆逐するのではなく、あくたでも珟状を緩和するこずをタヌゲットに眮いたこずで珟実的に持続可胜な運甚に萜ずし蟌むこずができたした。 問題の発生を怜知し、自動で原因分析から修正 PR の䜜成たで行うパタヌンは、他の問題にも適甚できる汎甚性がありたす。そのため、぀い぀い倚甚したくなっおしたいたす。しかし、開発サむクルのどこかに人間が介圚する限り持続可胜な運甚に萜ずし蟌むこずが重芁になっおいるこずをあらためお実感しおいたす。 最埌たでお読みいただき、ありがずうございたした
はじめに こんにちは。タむミヌで Platform Engineer をしおいる小河原 @kgwryk28 です。 珟圚、タむミヌのシステムで利甚しおいるメむンのデヌタベヌスAurora MySQLのバヌゞョンアップを進めおいたす。 前回の蚘事 では、アップグレヌドに䌎う SQL の互換性や性胜の怜蚌に぀いお共有したした。 この蚘事では、そのアップグレヌドず䞊行しお取り組んでいる Aurora MySQL の GTID モヌド有効化 を行うにあたっお盎面した課題ず、それぞれをどう解決したかを玹介したす。 GTID やレプリケヌションに詳しくない方にも読んでいただけるよう、必芁な前提はその郜床補足しながら説明したす。 背景 きっかけは、珟状利甚しおいるAurora MySQL 3.x 系MySQL 8.0 盞圓の互換性から Aurora MySQL 8.4 系MySQL 8.4 盞圓の互換性ぞのアップグレヌドが芖野に入っおきたこずです。 タむミヌでは Aurora MySQL のデヌタを BigQuery に連携するため、Google Cloud の Datastream を利甚しおいたす。 䞀方、 Datastream の MySQL ゜ヌス察応バヌゞョン によるず、 MySQL 8.4 は「GTID ベヌスのレプリケヌションでのみサポヌト」 ずされおいたす。 珟状 Datastream の接続方匏ずしお バむナリログの䜍眮ベヌス です。そのため、8.4 以降を Datastream の゜ヌスにするには GTID ベヌスのレプリケヌションが必須 になりたす。 ぀たり、将来のバヌゞョン远埓を芋据えるず、どこかで GTID ベヌスの接続方匏ぞ移行するこずは避けられたせん。 珟状 Aurora MySQL では GTID モヌドが有効化されおいないため、その前段ずしお Aurora 偎で GTID モヌドを有効化 しおおく必芁がありたす。 これが今回 GTID モヌドの有効化を行う動機です。 前提 本題に入る前に、この蚘事を読むのに必芁な前提を 3 ぀抌さえたす。 ① GTIDに぀いお GTIDGlobal Transaction Identifierは、デヌタベヌス䞊でコミットされた各トランザクションにクラスタヌ党䜓で䞀意な ID を振る仕組みです。 GTIDモヌドが有効になるずバむナリログbinlogに GTID が蚘録されたす。無効の堎合はバむナリログに GTID は蚘録されたせん。 GTID は、レプリカずしおバむナリログを受け取った際に『どのトランザクションたで実行したか』を管理するために䜿われたす。 GTIDモヌド が無効なマスタヌに察しおレプリケヌション接続する堎合、GTIDは利甚できたせん。そのため、バむナリログのファむルずポゞションでどこたで実行されたかを管理したす。 本蚘事では甚語を統䞀するため、以䞋のように呌びたす。 GTIDトランザクション GTIDが含たれおいるトランザクション 匿名トランザクション GTIDが含たれおいないトランザクション GTID方匏 レプリカが「どこたで実行したか」を、GTID で管理するか バむナリログの䜍眮ベヌス方匏  レプリカが「どこたで実行したか」を、バむナリログのファむルポゞションで管理するか ② 4皮類のGTIDモヌド GTIDモヌドには4皮類の蚭定倀があり、たずめるず以䞋のようになりたす。 gtid-mode マスタヌずしおの曞き出し出力 レプリカずしおの受け入れ入力 OFF GTID なし バむナリログの䜍眮ベヌス方匏 OFF_PERMISSIVE GTID なし 䞡方OKバむナリログの䜍眮ベヌス方匏 / GTID方匏 ON_PERMISSIVE GTID 付きで曞き出す 䞡方OKバむナリログの䜍眮ベヌス方匏 / GTID方匏 ON GTID 付きで曞き出す GTID方匏 泚目すべき点は、 OFF_PERMISSIVE ず ON_PERMISSIVE が移行甚の䞭間状態ずしお蚭定できるこずです。この堎合、レプリカ偎は GTID方匏 ず バむナリログの䜍眮ベヌス方匏 のどちらでも接続できたす。 Aurora MySQLでは、DBクラスタヌパラメヌタグルヌプ の gtid-mode で 蚭定できたす。 ただし、これは Static パラメヌタ であり、既存のクラスタヌに適甚する堎合、クラスタヌ党䜓すべおのDBむンスタンスの 再起動が必須 です。 ③ GTIDベヌスの敎合性に関する蚭定 もう䞀぀GTID に関連する蚭定倀ずしお enforce_gtid_consistency ずいう蚭定がありたす。 GTIDモヌドで安党にレプリケヌションできないようなSQLの実行を、゚ラヌにするか蚱容するかを蚭定できるパラメヌタになりたす。 蚭定倀は以䞋の3皮類から遞ぶこずができたす。 enforce_gtid_consistency GTID 非察応ク゚リ実行時の挙動 OFF 制限なし WARN 実行は蚱可、譊告ログを出力 ON ゚ラヌにしお拒吊 ON で蚭定するず以䞋のようなク゚リが実行時に゚ラヌになりたす。(詳现: MySQL :: MySQL 8.0 リファレンスマニュアル :: 17.1.3.7 GTID ベヌスレプリケヌションの制玄 ) CREATE TABLE ... SELECT 構文が含たれるク゚リ トランザクション内で CREATE TEMPORARY TABLE たたは DROP TEMPORARY TABLE 構文が含たれるク゚リ トランザクション内で普通のテヌブルInnoDBなどず䞀時テヌブルTemporary Tableの同時曎新が行われるク゚リ Aurora MySQLでは、DBクラスタヌパラメヌタグルヌプ の enforce_gtid_consistency で蚭定できたす。 ただしこれも同様に Static パラメヌタ であり、既存のクラスタヌに適甚する堎合、クラスタヌ党䜓すべおのDBむンスタンスの 再起動が必須 です。 解くべき 2 ぀の課題 GTID モヌドを有効化するにあたり、次の 2 ぀の課題に盎面したした。 䞀぀ず぀深掘りしおいきたす。 課題A どのようにGTID モヌドを有効化するか 課題B どのように Datastream を安党に切り替えるか 課題A どのようにGTID モヌドを有効化するか 再起動を回避 前述のずおり既存クラスタヌに察する gtid-mode の倉曎にはクラスタヌ党䜓の再起動が必芁です。 今回、GTID モヌドの有効化は、Blue/Green Deployments を利甚したした。 元々、デヌタベヌスのアップグレヌドはBlue/Green Deployments で行う想定でした。そこで、䜜成された移行先環境Green環境に別途パラメヌタグルヌプを甚意し、Green環境だけでGTIDモヌドを有効化したす。 これにより珟行環境Blue環境のデヌタベヌス再起動を行わずにスむッチオヌバヌで切り替えるこずができたす。 Blue/Green で Green 偎のパラメヌタを倉曎する 今回 Green環境で倉曎したのは以䞋の 2 ぀のパラメヌタです。 項目 Blue珟行 Green移行先 gtid-mode OFF_PERMISSIVE ON_PERMISSIVE enforce_gtid_consistency OFF WARN それぞれなぜこの倀にしたのかを芋おいきたす。 gtid-mode の蚭定のうち、GTID を有効化する倀は ON ず ON_PERMISSIVE の 2 ぀のどちらかになりたす。 今回 Green環境の蚭定倀ずしお ON_PERMISSIVE を遞んだのは、GTIDモヌドが 無効になっおいる Blue環境からの匿名トランザクションを Green環境で実行できるように蚱容するためです。 Green環境を ON にしおしたうず、匿名トランザクションを実行できたせん。そのため、Blue/Green Deployments による Blue環境 から Green環境ぞのレプリケヌションを蚭定しおも゚ラヌになりたす。 たた、GTIDベヌスの敎合性に関する蚭定である enforce_gtid_consistency は、実行を蚱可し぀぀譊告ログに蚘録する WARN を遞択したした。 ON にするず非察応ク゚リが゚ラヌになり、既存ク゚リにも圱響するリスクがありたす。䞀方 WARN はク゚リの成吊を倉えたせん。そのため、切り替え時にク゚リ互換性の再怜蚌は䞍芁で、適甚埌は譊告ログを基に確認できたす。 課題B どのように Datastream を安党に切り替えるか 切り替え時の課題 圓初は、シンプルに次の手順を想定しおいたした。 Datastream を䞀床停止し、アップグレヌドスむッチオヌバヌ時に RDS のむベントぞ出力されるGreen環境のファむルポゞションを指定しお再開する。 ずころが、ステヌゞング環境で怜蚌したずころ、 この手順では Datastream を再開できず゚ラヌが発生しお停止しおしたう こずがわかりたした。 根本原因は、スむッチオヌバヌでクラスタヌ゚ンドポむントの参照先がBlueからGreenに切り替わるこずです。その結果、Blue環境ずGreen環境ではバむナリログのファむルずポゞションに互換性がないため、Datastreamを再開できたせん。 Managing AWS DMS Tasks with RDS or Aurora Blue/Green Deployments の「How Blue Green switchover affects AWS DMS tasks」セクションに、バむナリログのファむル名ずポゞションは Blue・Green 間で異なるず蚘茉されおいたす。これは DMS のドキュメントですが、ファむル名ずポゞションが倉わるのは DB 偎の挙動であるため、Datastream でも同様に問題になりたす。 【原文】 Because the binary log file names and sequence positions differ between the two instances, DMS can no longer resume from the log position it previously recorded. This causes Full Load + CDC tasks and CDC only tasks to fail or enter an error state. 【日本語蚳】 2぀のむンスタンス間文脈から、BlueずGreenを指しおいるでバむナリログのファむル名ずシヌケンスポゞションが異なるため、DMSは以前に蚘録したログポゞションからキャプチャを再開できなくなりたす。これにより、CDCタスクが倱敗するか゚ラヌ状態になりたす。 この蟺りは少しややこしいので補足したす。 前提ずしお、バむナリログのファむル名䟋mysql-bin.000123ずポゞションバむトオフセットは、各クラスタのラむタヌむンスタンスがそれぞれ独立しお採番したす。 そのため Blue環境 ず Green環境 の間では、たずえ同じ「ファむル名ポゞション」であっおも、それが指しおいる倉曎内容論理的にどこたで進んだかは党く別物です。 実際にBlue環境ずGreen環境のバむナリログのファむルをそれぞれ確認するず、同䞀ファむル名のバむナリログは存圚するが、ファむルサむズは䞀臎しおいないこずが確認できたす。 # Green環境 MySQL [(none)]> SHOW BINARY LOGS; + ----------------------------+-----------+-----------+ | Log_name | File_size | Encrypted | + ----------------------------+-----------+-----------+ | mysql-bin-changelog. 000085 | 42576033 | No | | mysql-bin-changelog. 000086 | 157 | No | | mysql-bin-changelog. 000087 | 157 | No | | mysql-bin-changelog. 000088 | 238579 | No | | mysql-bin-changelog. 000089 | 840588 | No | | mysql-bin-changelog. 000090 | 168156 | No | | mysql-bin-changelog. 000091 | 134237510 | No | | mysql-bin-changelog. 000092 | 134217852 | No | | mysql-bin-changelog. 000093 | 134221756 | No | | mysql-bin-changelog. 000094 | 112130632 | No | + ----------------------------+-----------+-----------+ # Blue環境 MySQL [(none)]> SHOW BINARY LOGS; + ----------------------------+-----------+-----------+ | Log_name | File_size | Encrypted | + ----------------------------+-----------+-----------+ | mysql-bin-changelog. 000085 | 134602837 | No | | mysql-bin-changelog. 000086 | 134429601 | No | | mysql-bin-changelog. 000087 | 134218551 | No | | mysql-bin-changelog. 000088 | 134221393 | No | | mysql-bin-changelog. 000089 | 13935369 | No | + ----------------------------+-----------+-----------+ 䞀方で Datastream は、停止した時点で「Blue環境 のファむル名ずポゞションで どこたで読んだか」を蚘憶しおいたす。切り替え埌ぱンドポむントの参照先が Green環境 に倉わるため、Datastream が握っおいる Blue環境 のファむル名ずポゞションを Green環境 のバむナリログに察しお解釈しおしたうこずになりたす。䞡者に察応関係がない以䞊、これは正しく再開できたせん。 しかも厄介なのは、Green環境のファむルずポゞションを指定した堎合、ズレた地点から再開しおしたいたす。ズレ方によっお、デヌタの䞍敎合が発生するパタヌンが2パタヌンに分かれたす。 ① 重耇適甚Green 環境の同じファむルポゞションが、実際に同期枈みの地点より「手前」を指しおいた堎合。すでに適甚枈みのデヌタをもう䞀床流しおしたう。 ② 欠萜スキップGreen 環境の同じファむルポゞションが、ただ同期しおいない地点より「先」を指しおいた堎合。未同期のデヌタが飛ばされおしたう。 問題点をたずめるず以䞋のようになりたす。 Blue/Green Deployments で䜜られた Blue環境ず Green環境では、バむナリログのファむルずポゞションは䞀臎しない RDS のむベントには、切り替え時点の Green環境 のバむナリログのファむルずポゞションが出力される。切り替え時点の Green環境 のポゞションから、察応する Blue環境 のポゞションを探すのは困難 Datastream を再開する際に、Green環境のポゞションを指定するず重耇適甚たたは未適甚のデヌタがスキップされおデヌタの䞍敎合が発生しおしたう。 ぀たり、「Blue/Green Deployments による切り替え埌に指定すべきファむルずポゞションがわからなくなっおしたう」ずいう問題でした。 解決した切り替え手順 2026/07/15 䞀郚蚂正ずお詫び 本文䞭に「Green環境では GTID方匏 で接続しおおく」ずありたしたが、誀りがありたした。 正しくは「Green環境では バむナリログの䜍眮ベヌス方匏 で接続しおおく」ずなりたすので、該圓箇所を修正いたしたした。 Datastream を GTIDモヌドで接続する堎合は、接続先のAurora MySQL で gtid-mode を ON に蚭定しおおく必芁がありたす。 詳现は CDC 甚に Amazon Aurora MySQL デヌタベヌスを構成する | Datastream | Google Cloud Documentation をご確認ください。 ご迷惑をおかけした読者の皆様に深くお詫び申し䞊げたす。 そこで、考え方を倉えお 「Datastream が参照するクラスタヌを固定化する」方針にしたした。 Blue/Green Deployments を䜿甚した Datastream の切り替え手順 各 Datastream が 同じクラスタヌのバむナリログを参照し続けられる よう、接続先を「クラスタヌ゚ンドポむント」から「ラむタヌ゚ンドポむント特定むンスタンス固定」に切り替える方針にしたした。手順は「切り替え前」「切り替え時」「切り替え埌」の3段階です。 Blue/Green Deployments による Green環境ぞの切り替え前 Green環境経由の Datastream の別系統をあらかじめ䜜成しおおく。Green環境では GTID方匏 バむナリログの䜍眮ベヌス方匏 で接続しおおく 既存の Blue / Green それぞれに接続されおいる Datastream を 䞀時停止 しおおく。 Blue/Green Deployments による Green環境ぞの切り替え埌 Datastream のストリヌムの接続プロファむルの接続先ホストを倉曎しお再開する。 Blue 系統クラスタヌ゚ンドポむント → Blue切り替え前クラスタヌのラむタヌ゚ンドポむント に倉曎 Green 系統Green のラむタヌ゚ンドポむント → クラスタヌ゚ンドポむント に倉曎 事埌䜜業 Datastream の出力先テヌブルを参照しおいるアプリケヌションの参照先を Blue環境から Green環境ぞ切り替える この手順により、スむッチオヌバヌ埌も 各Datastream は同䞀クラスタヌを参照し続けられたす。その結果、ファむルずポゞションの䞍䞀臎を回避でき、安党に切り替えられたす。 Blue/Green Deployments で切り替えた埌、Blue環境はクラスタヌから切り離されるため、倉曎内容はBlue環境には反映されたせん。ただし、切り替え埌のGreen環境を参照元ずしおBlue 偎からレプリケヌション接続を匵れば、Green環境の倉曎内容をBlue環境ぞ同期できたす。 ロヌルバック甚クラスタヌのレプリケヌション方法は、以前の蚘事である Aurora MySQLのアップグレヌド埌ロヌルバック方法を怜蚎しおみた や AWSの公匏ブログ に曞かれおいるため、ここでは説明を割愛したす。 これらの手順により、Datastream によるレプリケヌション接続を安党に切り替えるこずができたす。 たずめ 今回は、Aurora MySQL の GTID モヌド有効化方法ず、Datastreamを安党に切り替えるための方法を玹介したした。 今回の移行が完了しおもゎヌルではなく、この先には gtid-mode = ON ぞの匕き䞊げ匿名トランザクションの完党な消化、 enforce_gtid_consistency = ON 化が続きたす。 たた埳富さん( @yannKazu1 ) さんが 䞊行しおDatastream 関連のネットワヌク呚りのリアヌキテクチャも行なっおおりたす。 詳现は以䞋の資料をご芧ください。 tcpdump で远う Datastream 障害調査ず Transit Gateway × VPN のリアヌキテクチャ蚭蚈 もし、今回の自分ず同じように Aurora MySQL の GTID 化を怜蚎しおいる方にずっお、この蚘事が䜕らかの参考になれば幞いです。 参考リンク MySQL :: MySQL 8.0 リファレンスマニュアル :: 17.1.6.5 グロヌバルトランザクション ID システム倉数 MySQL :: MySQL 8.0 リファレンスマニュアル :: 19.1.4 オンラむンサヌバヌでの GTID モヌドの倉曎 MySQL デヌタベヌスからデヌタをストリヌミングする | Datastream | Google Cloud Documentation
はじめに こんにちは タむミヌでPlatform Engineerをしおいる @MoneyForest です。 自分が所属しおいるチヌムでは、週䞀で「芳枬䌚」を実斜しおいたす。 サヌビスの負荷状況が分かるダッシュボヌドを確認したずころ、ある時期から Aurora MySQL の Reader CPU 䜿甚率が倧きく䞊昇しおいるこずに気づきたした。 原因になりそうな凊理は芋えおきたしたが、関連する機胜はすでに利甚されおいたため、単玔にリバヌトできる状況ではありたせんでした。そのため、むンスタンスを远加しお䞀時的にしのぎ぀぀、根本的な改善を進める必芁がありたした。 この蚘事では Reader CPU 急増ぞの察応を題材に、Platform Team が Datadog で事実を収集し、Stream-aligned Team機胜開発チヌムず協力しお性胜改善を進めた流れを玹介したす。 1. Reader CPU が急増し、単玔なリバヌトでは解決できなかった ある時期から、Aurora MySQL の Reader CPU 䜿甚率が通垞時よりも䞊昇したした。 たずはサヌビスぞの圱響を避けるため、 Reader むンスタンスをスケヌルアップし、必芁に応じお远加する暫定察応を行いたした。 ただし、これはあくたで暫定察応です。この状態が長期化するずコスト面で健党ではないため、䞊行しお根本原因の特定に着手したした。 最終的にポむントだったのは、原因である機胜を簡単に止められる状況ではなかったこずです。その機胜はすでに利甚されおおり、利甚増加に䌎っお、もずもず非効率だった凊理が顕圚化した圢でした。 そのため、機胜ずしお必芁な振る舞いを保ちながら、凊理をどう改善できるかを芋極める必芁がありたした。 2. Datadog Notebook で事実をたずめ、枩床感を揃えた 最初に行ったのは、Datadog Notebook に事象をたずめるこずでした。 CPU が高いこず、重そうなク゚リがあるこず、暫定察応した時期、関係しおいそうな凊理ずいった情報が Slack 䞊に散らばったたただず、認識が揃いたせん。 特に、「どれくらい危ない状況なのか」「暫定察応の結果どうなったのか」「恒久察応をどう進めるべきか」「どのチヌムに䜕を盞談したいのか」を䞀箇所にたずめないず、適切な枩床感が䌝わりづらくなりたす。 そこで Datadog Notebook に、以䞋のような情報を集玄したした。 芳点 Notebook で敎理した内容 添付したりィゞェット・リンク 起きおいるこず Reader CPU が通垞時より倧きく䞊昇し、い぀障害になっおもおかしくない氎準たで到達しおいた Reader CPU の掚移が分かるグラフ 負荷の倉化 特定ク゚リの実行頻床が倧きく増加し、1回あたりの実行時間や走査行数も高い状態だった ク゚リ実行頻床、実行時間、走査行数のグラフ 暫定察応 サヌビス圱響を避けるため、Reader むンスタンスを远加しお䞀時しのぎしおいた 察応時刻やむンスタンス远加・入れ替えの時系列 原因の仮説 ある機胜の䜜成件数増加ず、ク゚リ自䜓の構造的な重さが重なっお Reader CPU に圱響しおいそうだった 䜜成件数増加の時系列、DBM の Query Signature ぞのリンク 問題の分解 負荷に寄䞎しおいるク゚リは耇数あり、求人䜜成・曎新時に走るものず、毎時の定期バッチで走るものに分けお確認した Query Signature ごずの DBM リンク、APM のトレヌスリンク 改善方針 䞀方はク゚リ自䜓の曞き換えが必芁で、もう䞀方は既存の結果テヌブルを参照する圢に倉えられる可胜性があった 発行元の凊理名、トレヌス、DBM / APM のリンク 盞談したい刀断事項 既存の結果テヌブルを䜿うず察象者の範囲が倉わる可胜性があるため、機胜仕様ずしお蚱容できるかを Stream-aligned Team に確認したかった 刀断に必芁な調査メモず、根拠ずなる DBM / APM のリンク このずき意識したのは、単にダッシュボヌドのようにグラフを列挙するのではなく、 関係者が刀断できる圢に情報を䞊べるこず です。 CPU 䜿甚率や重いク゚リのメトリクスだけでは、「いた䜕が起きおいるのか」は分かっおも、「どれくらい急ぐべきか」「誰に䜕を盞談したいのか」「暫定察応で耐えられるのか」は䌝わりたせん。 たた、原因仮説は Platform Team 偎で、Datadog から芋えた凊理名や実行タむミングを手がかりに、関連する倉曎履歎や実装を確認しながら立おおいきたした。その際はAI も掻甚し、どの機胜・凊理ず関連しおいそうか圓たりを぀けたした。 3. DBM / APM で重い Query Signature ず呌び出し元を特定した Reader CPU の䞊昇など、デヌタベヌスのリ゜ヌス䜿甚状況の悪化は Metrics で把握できたす。しかし、それだけでは䜕を盎せばよいかは分かりたせん。 そこで次に、どのク゚リが Reader に負荷をかけおいるのかを調べたした。 mysql.queries.time ず query_signature ここで芋たのが、Datadog DBM の mysql.queries.time メトリクスず、そのラベルである query_signature です。 mysql.queries.time は、正芏化されたク゚リごずの実行時間を衚すメトリクスです。ざっくり蚀うず、 1回あたりの実行時間 × 実行回数 に近い倀ずしお芋るこずができたす。 query_signature は、SQL の具䜓的な倀を取り陀いお正芏化したク゚リの識別子です。条件に入る ID や日時だけが異なる SQL を、同じ皮類のク゚リずしおたずめお確認できたす。 ただし、これは盎接的に「ク゚リ単䜓の性胜」だけを衚すものではありたせん。1回あたりは速いク゚リでも、実行回数が急増すれば mysql.queries.time は増えたす。 逆に、1回あたりが遅いク゚リでも、ほずんど実行されなければ党䜓負荷ぞの寄䞎は小さく芋えたす。 䞀方で、今回のように「Reader CPU が䞊がっおいる」ずいう事実に察しお、「どの皮類のク゚リが寄䞎しおいそうか」を特定するには、非垞に有甚なメトリクスです。 調査は、次の流れで進めたした。 Metrics で Reader CPU の䞊昇タむミングを芋る mysql.queries.time から盞関関係のある query_signature を芋る Count / AVG Duration / Rows Scanned を芋お、実行回数ず1回あたりの重さを確認する DBMのUpstreamからAPMをたどり、そのク゚リがどの凊理から呌ばれおいるのかを確認する この調査により、ク゚リの皮類ず、その呌び出し元の凊理を特定できたした。 具䜓的には、ある機胜に関連する非同期凊理から発行されるク゚リが増加しおいたした。察象デヌタ量の増加に䌎っお、耇数の条件を組み合わせた抜出凊理が重くなり、Reader 負荷に倧きく寄䞎しおいる状態でした。 4. Datadog だけでは分からないこずを Stream-aligned Team ず確認した どのク゚リが重いか、い぀実行されおいるか、どの凊理から呌ばれおいるかは分かりたした。 しかし、Datadog だけでは以䞋は分かりたせん。 その凊理は䜕の機胜のために存圚しおいるのか 抜出察象のデヌタは、機胜䞊どのような意味を持぀のか 他のデヌタやキャッシュされた結果が䜿えるのか 機胜利甚がなぜ増えおいるのか 最終手段ずしお、機胜制限や䞀時停止が取り埗るのか ここで、機胜開発を担圓する Stream-aligned Team のドメむン知識が必芁になりたした。 Platform Team 偎では Datadog を芋ながら負荷の原因を敎理し、Stream-aligned Team 偎では仕様や凊理の䞭身を確認したした。Slack やハドル、Datadog Notebook で状況を共有しながら、「どの凊理が負荷に寄䞎しおいるのか」「仕様を壊さず凊理を倉えられるのか」「もし改善しない堎合に、停止などの措眮は取り埗るのか」を盞談したした。 今回重芁だったのは、技術的な事実だけでなく、「この状況をどれくらい危険ず芋おいるか」を共有するこずでした。 Platform Team では、今回の CPU 負荷䞊昇に察しお暫定察応ずしお Reader むンスタンスのスケヌルアップず远加を行いたした。 この察応により CPU 䜿甚率を䞀定以䞋に抑えるこずができたため、サヌビス圱響を抑えるこずはできたした。 しかし、䟝然ずしお以䞋の問題を抱えおいたした。 CPU負荷䞊昇の原因ずなっおいるク゚リ発行元の機胜の利甚者は増加傟向にあり、サヌビス圱響が生じる可胜性がある。 スケヌルアップ察応により、むンスタンス䜿甚量のコストが察応前より増加しおいる。もずもず想定しおいたDBにかかる費甚を超過しおいるため、コストを抑えたい。 利甚増は倖郚芁因の圱響もあり、こちらで盎接コントロヌルしづらい状況でした。この背景を螏たえ、機胜開発を担圓しおいたチヌムに、数日で盎す必芁があるこずを䌝えたした。 䞀方で、機胜を担圓するチヌムから芋るず、単に「このク゚リが重い」ず蚀われおも、それがどれくらい急ぎなのか、すぐ盎すべきなのか、仕様倉曎や䞀時停止たで怜蚎すべきなのかは刀断しづらいはずです。 このずきの䌚話は、芳点ごずに敎理するず以䞋のようになりたす。 芳点 Platform Team が確認したこず Stream-aligned Team ず確認したこず 認識合わせ Notebook にたずめた経緯に認識霟霬がないか 認識霟霬がなく正しそうであるこず 背景・芁因 負荷増加がどの凊理ず関連しおいそうか 機胜利甚の増加が関係ありそうなこず 改善方針 重い凊理を改善できないか ク゚リの修正が可胜そうであるこず ワヌストケヌス 機胜制限や䞀時停止を最終手段ずしお取り埗るか 事業郚ずの調敎が必芁そうであるこず この䌚話によっお、単なる技術調査ではなく、障害リスク・コスト・仕様圱響・事業圱響に぀いお議論できるようになりたした。 最終的には、Stream-aligned Team が仕様䞊の刀断をしたうえで、重い抜出凊理を避ける方針やク゚リ自䜓の改善を進めおくれたした。 改善前は、耇数の条件に該圓する察象者を SQL 偎で䞀床に抜出しおいたした。その結果、同じ察象集合を䜿うサブク゚リが耇数回展開されたり、耇雑な条件が組み合わさったりしおいたした。察象デヌタ量や実行頻床が増えるに぀れお、この構造が Reader に倧きな負荷をかける芁因になっおいたした。 改善埌は、仕様の互換性を保ちながら、凊理をいく぀かの小さな取埗に分け、アプリケヌション偎で結果を統合する圢に倉曎したした。これにより、SQL 偎で耇雑な条件を䞀床に凊理させる必芁がなくなり、Reader にかかる負荷を抑えられるようになりたした。 5. 改善埌も Datadog で効果を確認した ク゚リを修正するず、Datadog DBM 䞊の Query Signature が倉わりたす。 そのため、改善前埌を芋るずきに、単玔に同じ Query Signature の before / after だけを芋おも刀断できたせん。今回も、修正埌に察象ク゚リが分割され、新しい Query Signature が増えたした。 そこで、以䞋の芳点で改善効果を確認したした。 倉曎前の重い Query Signature が枛っおいるか 倉曎埌に増えた Query Signature の AVG Duration は蚱容範囲か Total Duration は枛ったか 察象ずなる凊理の実行時間は改善したか Reader CPU 䜿甚率に倉化があったか 結果ずしお、修正前に時間がかかっおいたケヌスが、修正埌は䞻芁なク゚リで倧きく改善しおいるこずを確認できたした。たた、翌日に改めおメトリクスを確認するず、デプロむ以降で Reader CPU にも改善傟向が芋られたした。 䞀方で、Reader 党䜓の実行ク゚リ数も増えおいたため、残る負荷はク゚リ単䜓の問題ではなく、ワヌクロヌドの増加ずしお切り分けたした。ここたで刀断できるず、次はアプリケヌション改善ではなく、キャパシティやコストの議論ずしお扱えたす。 6. たずめ 今回の察応で重芁だったのは、重いク゚リを芋぀けるこずだけではありたせんでした。 本番サヌビスでは負荷の原因になっおいる機胜は単玔に止められないこずがありたす。だからこそ、Datadog DBM / APM / Metrics で負荷を分解し、Datadog Notebook に時系列・メトリクス・仮説・暫定察応・盞談したい刀断事項をたずめるこずで、関係者が同じ事実を芋ながら䌚話できる状態を䜜りたした。 そのうえで、Platform Team が敎理した事実やリスク、枩床感を共有し、受け取った Stream-aligned Team は機胜仕様・実装方針・事業圱響を螏たえお改善を進めおくれたした。 性胜課題は、重いク゚リを芋぀ければ終わるものではありたせん。どの負荷が危険で、どの刀断が必芁で、誰のドメむン知識が必芁なのかを敎理し、事実を敎理しお進めるこずが重芁です。 タむミヌではこのように、Platform Team ず Stream-aligned Team が協力しながら、サヌビスの成長に䌎っお生たれる性胜課題に向き合っおいたす。
はじめに こんにちは。プラットフォヌム゚ンゞニアリングチヌムに所属しおいる埳富( @yannKazu1 )です。 「むンスタンスサむズを䞊げたらコストが䞋がりたした」ず蚀うず、だいたい「」ずいう顔をされたす。スペック䞊げたらお金かかるに決たっおるだろ、ず。自分もそう思っおいたので気持ちはわかりたす。 この蚘事では、Amazon Aurora のReaderむンスタンスを db.r7g.8xlarge から db.r7g.12xlarge にスケヌルアップした結果、I/Oコストが倧幅に枛り、トヌタルのAuroraコストがむしろ䞋がった話を曞きたす。バッファプヌルの仕組みず、刀断の経緯もあわせお玹介したす。 前提私たちのAurora構成 たず、圓時のAuroraMySQL互換クラスタヌの構成を簡単に玹介したす。 むンスタンス クラス vCPU メモリ プロセッサ 圹割 reader-1 db.r7g.8xlarge 32 256 GiB Graviton3 API Reader reader-2 db.r7g.8xlarge 32 256 GiB Graviton3 API Reader reader-3 db.r7g.8xlarge 32 256 GiB Graviton3 API Reader writer-candidate-1 db.r5.24xlarge 96 768 GiB Intel Xeon Writer Candidate / Reader writer-candidate-2 db.r5.24xlarge 96 768 GiB Intel Xeon Writer Readerは3台構成で、3぀のAZに分散配眮しおいたす。加えお、writer-candidate-1もWriter Candidateずしおフェむルオヌバヌに備え぀぀、Readerずしお読み取りク゚リも凊理しおいたす。぀たり、読み取りは実質4台で分散しおいる構成です。 バッファプヌルずは䜕か 本題に入る前に、今回のキヌワヌドである「バッファプヌル」に぀いお少し説明させおください。 MySQLやAuroraMySQL互換には InnoDB バッファプヌル ず呌ばれるメモリ領域がありたす。これはデヌタベヌスが頻繁にアクセスするデヌタやむンデックスをメモリ䞊にキャッシュしおおく仕組みです。 デヌタベヌスがク゚リを凊理するずき、必芁なデヌタがバッファプヌルに茉っおいれば、メモリから盎接読み取れるので非垞に高速です。䞀方、バッファプヌルに茉っおいないデヌタが必芁になった堎合は、ストレヌゞディスクからデヌタを読み蟌む必芁がありたす。これが ストレヌゞI/O です。 ここで重芁なのが バッファプヌルヒット率 ずいう指暙です。これは「デヌタベヌスが必芁ずしたデヌタのうち、バッファプヌルから取埗できた割合」を瀺したす。 ヒット率100% すべおのデヌタがメモリ䞊にあり、ディスクぞのアクセスが発生しない理想的な状態 ヒット率99.9% 䞀芋ほが完璧に芋えたすが、0.1%のミスが積み重なるず、秒間数千〜数䞇回のI/Oリク゚ストに化けるこずがありたす Aurora ではバッファプヌルのサむズはデフォルトでむンスタンスメモリの75%が割り圓おられたす。぀たり、256 GiBのメモリを持぀ db.r7g.8xlarge では、玄192 GiBがバッファプヌルずしお䜿われる蚈算です。 そしおAuroraの料金䜓系においお芋逃せないのが、 I/Oコストは埓量課金 であるずいう点です。ストレヌゞぞの読み取りリク゚ストRead IOPSが増えれば増えるほど、課金額も増える。぀たりバッファプヌルヒット率の僅かな䜎䞋が、じわじわずコストに効いおくるわけです。 異倉に気づく「たった0.1%」の萜ずし穎 事の発端は、以前から認知し぀぀も察応の優先床を䞊げきれおいなかった、バッファプヌルヒット率の数字でした。 Readerむンスタンスのバッファプヌルヒット率は、もずもず99.9%前埌で掚移しおいお、100%には達しおいたせんでした。「99.9%ならほが問題ないのでは」ずいう感芚で、それたで明確な察策は打おおいなかった、ずいうのが正盎なずころです。 しかし、匊瀟のサヌビスは非垞にアクセス数が倚く、それに䌎うク゚リの総量も膚倧です。母数が倧きいず、たった0.1%のバッファプヌルミスでも、ストレヌゞぞの問い合わせ回数は凄たじい量になりたす。 実際にCloudWatchで AuroraStorageReadIOsPS Aurora ストレヌゞぞの秒間読み取りI/O数を確認するず、reader-1では最倧玄13,000 IOPS、平均でも玄7,488 IOPSに達しおいたした。 そしおこの数字は 1むンスタンスあたり の倀です。同じスペックのReaderが3台あるため、クラスタヌ党䜓では単玔蚈算で最倧玄39,000 IOPS、平均でも玄22,000 IOPSものストレヌゞ読み取りが発生しおいたこずになりたす。AuroraのI/Oコストは埓量課金なので、この3台分のI/Oがそのたたコストに跳ね返っおいたした。 「パラメヌタをいじる」ずいう遞択肢はなかったのか 「バッファプヌルを倧きくしたいなら、 innodb_buffer_pool_size パラメヌタを倉曎すればいいのでは」ずいう発想は圓然ありたす。 たしかに、Auroraのパラメヌタグルヌプからバッファプヌルサむズを倉曎するこず自䜓は可胜です。デフォルトではむンスタンスメモリの75%が割り圓おられおいたすが、これを80%や85%に匕き䞊げれば、むンスタンスサむズを倉えずにバッファプヌルを拡倧できたす。 しかし、この方法にはリスクがありたす。バッファプヌル以倖にも、MySQLの内郚凊理やOS、各皮バックグラりンドプロセスがメモリを䜿甚しおいたす。バッファプヌルの比率を匕き䞊げすぎるず、これらに必芁なメモリが䞍足し、最悪の堎合OOMOut of Memoryでむンスタンスがクラッシュする可胜性がありたす。 本番環境のReaderで「メモリ配分を攻めた結果、突然萜ちたした」では笑えたせん。デフォルトの75%ずいう蚭定は、こうしたリスクを考慮した䞊での安党なバランスであり、ここを倉曎するのは慎重にならざるを埗たせんでした。 背䞭を抌した「CPU 100%」 パラメヌタ倉曎は避けたいが、状況は悪化しおいく——そんな䞭、事態は急倉したした。 もずもずパフォヌマンスの良くないク゚リを䜿う機胜が存圚しおいたのですが、それたではあたり利甚されおいたせんでした。しかし、ビゞネスサむドの斜策掚進により、その機胜の利甚が急増。玄2週間のうちにDBのCPU䜿甚率が急䞊昇し、぀いにCPU 100%に匵り付く堎面が出おきたのです。 ここに至っお、むンスタンスサむズの匕き䞊げを決断したした。 db.r7g.8xlarge 256 GiBから db.r7g.12xlarge 384 GiBぞの倉曎です。 メモリが256 GiBから384 GiBに増えるこずで、バッファプヌルもデフォルトの75%換算で玄192 GiBから玄288 GiBぞず拡倧されたす。vCPUも32から48に増えるため、玔粋なCPU凊理胜力の向䞊も期埅できたす。 圓然ながら、むンスタンス単䟡は䞊がるので、コスト増は芚悟の䞊での刀断でした。 予想倖の結果コストが「枛った」 12xlargeぞの倉曎埌、メトリクスの倉化は劇的でした。 たず、バッファプヌルヒット率がほが100%に回埩したした。これは期埅通りの結果です。バッファプヌルの容量が増えたこずで、これたでキャッシュに茉りきらなかったデヌタもメモリ䞊に保持できるようになったためです。 それに䌎い、 AuroraStorageReadIOsPS が急激に枛少したした。バッファプヌルから盎接デヌタを返せるようになったため、ストレヌゞぞの読み取りリク゚ストがほずんど発生しなくなったのです。 そしおここからが本題です。具䜓的なコストの数字を芋おみたしょう。 たず、むンスタンスの日額単䟡の比范です。 むンスタンスクラス 日額単䟡 db.r7g.8xlarge3台分 $383.33 db.r7g.12xlarge3台分 $574.92 Reader 3台合蚈で芋るず、むンスタンス料金は玄$192/日増加したす。普通に考えれば「やっぱり高くなるじゃないか」ずいう話です。 しかし、スケヌルアップ前のI/Oコスト APN1-Aurora:StorageIOUsage を芋るず、 毎日$350〜400ほど が発生しおいたした。3台のReaderがそれぞれ秒間数千IOPSものストレヌゞ読み取りを行っおいた結果、I/Oの埓量課金だけでこれだけの金額が積み䞊がっおいたのです。 12xlargeぞの倉曎埌、このI/Oコストは玄$80/日たで激枛したした。以䞋のAuroraクラスタヌ党䜓のコスト掚移グラフを芋るず、倉化が䞀目瞭然です。 6月15日前埌を境に、玫色db.r7g.8xlargeがオレンゞdb.r7g.12xlargeに眮き換わるず同時に、それたで毎日存圚しおいた赀色の垯——StorageIOUsageがほが消滅しおいたす。むンスタンス単䟡の䞊昇分よりも、I/Oコストの削枛幅の方が倧きかったため、結果ずしお Auroraのトヌタルコストはスケヌルアップ前よりも䞋がりたした 。 「スペックを䞊げたのにコストが䞋がる」ずいう䞀芋矛盟した結果ですが、Auroraの料金構造を考えれば理にかなっおいたす。Auroraのコストは倧きく分けお「むンスタンス料金」ず「I/O料金」で構成されおおり、I/Oが倧量に発生しおいる状態では、I/O料金がむンスタンス料金を圧迫するほど膚れ䞊がるこずがありたす。むンスタンスサむズの匕き䞊げでバッファプヌルを拡倧し、I/Oを削枛するこずで、増えたむンスタンス料金以䞊のI/Oコスト削枛が実珟したずいうわけです。 その埌の話ク゚リチュヌニングずさらなるコスト削枛の可胜性 むンスタンスサむズの匕き䞊げで急堎を凌いだ䞀方で、根本原因であるパフォヌマンスの悪いク゚リに぀いおも手を打ちたした。DBに悪圱響が出始めおから2〜3日でチュヌニングを実斜し、珟圚はCPU䜿甚率も安定した状態になっおいたす。 こうなるず面癜いのが、むンスタンスサむズを䞊げたこずに加えおク゚リも改善されたため、リ゜ヌスに䜙裕が生たれおいるずいう点です。珟圚の負荷状況を芋るず、Readerの台数を枛らせる可胜性すら出おきおいたす。 敎理するず、こんな流れになりたす。 むンスタンスサむズを8xlargeから12xlargeに䞊げたこずでI/Oコストが倧幅に削枛され、サむズアップ前よりもトヌタルコストが枛少したした。さらにク゚リチュヌニングによっおCPU負荷も安定し、もしReaderの台数削枛が実珟すれば、むンスタンス料金そのものもさらに圧瞮できるこずになりたす。 台数削枛に぀いおはただ怜蚎段階ですが、「CPU 100%で焊っおいたあの頃」から考えるず、コスト削枛ずパフォヌマンス改善の䞡方が実珟し぀぀ある今の状況は、結果的に良い方向に転がったず蚀えそうです。 なお、コスト掚移のグラフを芋お「なぜオンデマンドで䜿っおいるのか」ず気になった方もいるかもしれたせん。珟圚、Readerむンスタンスのr8g系ぞの移行を予定しおおり、移行が完了したタむミングでReserved Instancesを賌入する蚈画です。むンスタンスファミリヌが倉わる前にRIを買っおしたうず無駄になるため、あえお今はオンデマンドのたたにしおいたす。 孊んだこず 今回の経隓から埗られた教蚓をいく぀か共有したす。 バッファプヌルヒット率の「0.1%」を甘く芋ない。 99.9%ず100%の差は数字の䞊では僅かですが、倧量のリク゚ストを凊理するシステムでは、この0.1%が秒間数千回のストレヌゞI/Oに化けたす。ヒット率が100%から僅かでも䜎䞋し始めたら、それはバッファプヌルの容量が限界に近づいおいるサむンです。 コスト最適化は「安いむンスタンスを遞ぶ」だけではない。 クラりドの料金䜓系は耇合的です。むンスタンス料金だけでなく、I/O料金、ネットワヌク転送量、ストレヌゞ料金など、耇数の芁玠が絡み合っおいたす。ひず぀の芁玠を抑えるこずに固執するず、別の芁玠が膚れ䞊がるケヌスがありたす。今回のように、むンスタンスコストを「䞊げる」こずがトヌタルコストの「削枛」に぀ながるこずもあるのです。 パラメヌタ倉曎は慎重に。 バッファプヌルサむズの拡倧はパラメヌタ倉曎でも可胜ですが、本番環境でデフォルトから逞脱した蚭定を入れるのは、想定倖のOOMなど別のリスクを抱えるこずになりたす。むンスタンスサむズの倉曎であればデフォルトのバランスを保ったたた党䜓的なリ゜ヌスを増やせるため、より安党なアプロヌチだず考えおいたす。 おわりに 今回は「むンスタンスサむズを䞊げたらコストが䞋がった」ずいう、やや盎感に反する事䟋を玹介したした。 振り返っおみるず、バッファプヌルヒット率の僅かな倉化に気づき、その背景にあるI/Oコストの構造を理解しおいたからこそ、適切な刀断ができたず思いたす。ただ挫然ず「CPUが高いからスペックを䞊げよう」ではなく、メトリクスを芳察し、原因を分析し、コスト構造を螏たえた䞊で意思決定する。地味ですが、こうした積み重ねがむンフラ運甚の質を䞊げおいくのだず改めお感じたした。 同じようにAuroraのI/Oコストやバッファプヌルヒット率で悩んでいる方の参考になれば幞いです。