まっしろけっけ

めもてきなやーつ

GMO アワード 2021 にノミネートされてた話

はじめに

だいぶ時間が経ってしまったのですが GMO アワード 2021 というものにノミネートされていました。
is 何?という人は下記を参照

hr.pepabo.com

感想など

前職でも似たようなものは存在していて自分とは無縁と思っていたのでこういうのにノミネートされるのは素直に嬉しいという感想

また、ペパボからの過去のノミネート者を見ても @hsbt@matsumotory など尊敬するエンジニアが名を連ねているので選んでいただけたのはありがたいな〜という感想とまだ自分は先にあげた二人と肩を並べるほどのエンジニアではないので頑張っていかんとな〜と思うなどした。

最後に

という記念カキコでした

DeployGate のアカウントを PullRequest ベースで管理したい

はじめに

DeployGate is
deploygate.com

会社で使ってたりするとアカウント管理とかが大変ですよね。退職したらその人のアカウント消したり、気づかないうちにカオスになってしまうことも....

そんなカオスな事を出来るだけ回避したいので Github などで PullRequest ベースでアカウントの追加/削除ができるとちょっと嬉しい気がします。Enterprise プランであれば SAML が使えるのでそれでも良いと思います。

yaml でユーザを管理する

使う gem はこちら

gem install deploygate-client

これは元同僚の Android エンジニアがまだ一緒に働いてた時に「API とかあるならコードで管理するようにしたら?」と言ったら作ってたやつ。結局コード管理するまで至らずに退職しちゃったんですけどね...

まずは既存のアカウント一覧を yaml に吐き出す。

require 'deploygate/client'
require 'json'
require 'yaml'

org_name = "管理したい org"

client = Deploygate::Client.new(token: ENV['DEPLOYGATE_TOKEN']) # 環境変数の DEPLOYGATE_TOKEN にトークンを設定する
response = client.organization_members(org_name: org_name)
members = JSON.parse(response.body)["members"].map { |val| val["name"] }

YAML.dump({members: members}, File.open('members.yaml', 'w'))

これで members.yaml に既存のアカウントが書き出される

次は yaml に書いてあるアカウントを DeployGate 側に反映される。

require 'deploygate/client'
require 'json'
require 'yaml'

org_name = "管理したい org"
dryrun = ENV['DRY_RUN'] # 環境変数で DRY_RUN を設定するとアカウントの増減はしないで変更予定の出力だけ得られる

client = Deploygate::Client.new(token: ENV['DEPLOYGATE_TOKEN']) # 環境変数の DEPLOYGATE_TOKEN にトークンを設定する

response = client.organization_members(org_name: org_name)
api_members = JSON.parse(response.body)["members"].map { |val| val["name"] }

yaml_members = YAML.load_file('members.yaml')["members"]

add_members = yaml_members - api_members # yaml に書いてあるのに DeployGate に存在しないアカウントは追加したいアカウント
delete_members = api_members - yaml_members # yaml に書いてなくて DeployGate に存在するアカウントは消したいアカウント

add_members.each do |member|
  puts "add #{member}"
  client.add_organization_member(org_name: org_name, user_name: member) unless dryrun
end

delete_members.each do |member|
  puts "delete #{member}"
  client.delete_organization_member(org_name: org_name, user_name: member) unless dryrun
end

こんな感じでこのコードと members.yamlGithub で管理して Actions などで master に merge されたタイミングで実行するようにすれば PullRequest ベースで管理できるようになります。

エラー処理とかは特に行なっていない(ネットワークエラーとかで更新失敗しても再実行すれば yaml と同じ状況にできるので)

最後に

deploygate-client よくできてる。

Istio を利用して HTTP Request 時に問題があったら retry してもらう

はじめに

Istio is
istio.io

service mesh の一種で色々な事ができるので上記参照(雑)
内部的に envoy を使ってたりする。

今回やる事

特定の pod から別の pod にアクセスする際に稀にネットワーク的な問題で繋がらなかったり、アクセス先の pod が高負荷でたまたま処理に失敗するなどが発生する時がある。

そういう時に pod で動いているアプリケーション側で retry の機構を実装する事も可能なのだけれど、外部との通信で毎回書くのはダルかったりコードが複雑になったりするわけなのでそれを service mesh 層でやってもらおうという作戦。

Retry してもらう

istio の install などは省きます。

設定方法はここにそのまま書いてあるのですが実際に動作確認したいよねとなるので動作確認用のアプリケーションを書いたのがこちら

main という web アプリケーションから sub というアプリケーションに Request を送るだけの簡単なもの

deployment にはまだ istio-proxy 等が追加されていないので apply する際は追加してあげる必要がある

$ istioctl kube-inject -f manifests/deployments.yaml | kubectl apply -f -
$ kubectl apply -f manifests/services.yaml
$ kubectl apply -f manifests/virtual-services.yaml

これで準備終わり。別の pod から curl http://istio-example-app-main-svc:9080/ を打つとこの設定だと普通に Response が受け取れるはず。

sub のアプリは 2s sleep 後に Response を返す実装なので VirtualService の設定の timeout を 2s 以下に変更する。
変更箇所はここ

$ kubectl apply -f manifests/virtual-services.yaml

この状態で curl http://istio-example-app-main-svc:9080/ すると upstream request timeout となり Response が受け取れません。
なぜかというと istio-proxy が VirtualService で設定されている perTryTimeout で設定されている時間で一旦接続を切り attempts の回数分再度同じ Request を行なっているからです。

この様子をログで確認する方法は下記

$ kubectl logs -f main-pod istio-proxy
$ kubectl logs -f sub-pob istio-proxy

これで Response Time によって Retry を設定する方法がわかったので次は HTTP status などによって Retry する設定です。
これはここの retryOn で設定ができます。

どういう設定を書けばいいのかは envoy の docs に書いてあります。

動作確認をしたい場合はこちらを使用して上記と同じ手順を辿れば確認できます。

最後に

今回紹介した機能以外にも istio にはいっぱい機能がある(ありすぎる)ので何かしらの課題を解決する為に導入してみるのも良いかと思います。

シン・エヴァンゲリオンの感想と自分語りと(ネタバレあり)

ネタバレがあるよ気をつけて










3/10(水)仕事の深夜メンテが終わり 2 時間半ほど寝た後にエヴァの最後を見に行った。あまり寝てないので途中で寝ないかすごく心配だったがそんな心配は杞憂だった。エヴァを見始めてから二十数年TV/旧劇/漫画版と見てきたが今ではうろ覚えな部分もある。終わってしまうのか〜悲しいなという気持ちが強かった気がする。

映画館に座り、上映が始まるまでにフォースチルドレンを首になった彼は死んでまったのかな?(妹はでてきたけど)などど考えながらまっていた。真っ暗な画面から歌謡曲が聞こえすぐにマリだと気づく坂本真綾ファンなのでこれを聴くためにシンエヴァを見にきたと言っても過言ではない。冒頭10分は一年半前くらいに公開された時にすぐ見たので記憶が曖昧だったもののこんな感じだったな〜という感想。

その後シンジたちに場面が切り替わるが、すぐに上映前に死んだのかな?とか思ってたトウジが出てきてなんかすまん...となった。トウジ/ケンスケ共に 28 にしては考えがしっかりしすぎていて見た目的にも老けすぎでは?とも思ったが、トウジが言っていた「お天道様に顔向けできないこともした」という発言からもいろいろな苦労をして実年齢以上に精神年齢が上なのだなと思った。後ケンスケのキャラデザなんか加持さんに似てないか?とも思った(加持さんのような見た目と加持さんのような大人の余裕からアスカは惹かれたのかなと終盤のぬいぐるみから出てくるところで気づいた)

ここからはアヤナミレイが人間性を得ていく場面、綾波が周りの影響を受けて成長(?)していく場面は他のシリーズでもあったいい場面だよなと思ったがちょっと長いなとも思った。その間シンジくんはずっといじけてるし、アスカはそんなシンジくんに冷たい態度をとりつつ心配していてほんとツンデレで可愛い。
その後アヤナミレイが消えたことでシンジくんは立ち直るのだが今まで散々いじけてたのに急すぎないか?とは思った。その後もケンスケは相変わらず優しすぎるしいい男すぎないか?

ケンスケに連れられてミサトさんの子供の加持くんに会うことになるのだけれど、ここら辺から割とずっと泣いていた気がする。ミサトさんと加持さんの過去作での関係とかも思い出したら一時でも幸せな時があったんだなと思ってしまった。

シンジくんはヴィレに戻りヴィレの面々は南極に向かうわけですが、ここで出てくるのが冬月先生。冬月先生毎回損な役回りばかりじゃないですかね...いい人すぎるでしょ...

アスカとマリが出撃する直前にシンジくんの元に寄ることになるんですが、この時のマリの行動がそのままエンディングに出てくるんですよね。アスカはシンジくんと答え合わせをして好きだったと伝えるんですがここでやっと Q のときにキレていた理由を視聴者は知ることができるわけです。好きだった男が自分を助けようともせずに駄々こねてたらそりゃ切れるよな〜。
更に出撃後にはなぜ 3 号機と一緒に使徒に侵食されたはずのアスカが人として存在できているか?という謎も判明しましたね。変な棒便利!

その後リツコさんがゲンドウを撃ったり(いいぞもっとやれと思った)、ミサトさんがシンジくんを庇って打たれたりがあり皆んなやっぱりシンジくんを心配してる(もちろん心配している反面憎んでもいる)優しい世界だったんだよかったとなった(じゃなきゃ Q 時点でミサトさんがシンジくんのこと殺しててもおかしくないしね)シンジくんのプラグスーツを保存しておくくらいだしね。ヴィレの皆んなも新しい槍をシンジくんに届けるために協力してくれるのが良い。これだから若い男はって言われたい(若くないけど)

その後シンジくんは初号機に戻るんですが、そこで髪の長い綾波レイが座っているんですよね。この髪が伸びているというのはシンの中盤でアスカの髪をマリが切ってあげる場面と通じていると思っていて、この時アスカは「こんな体になっても髪は伸びてうざい」と言った愚痴を言うんですが、マリは「まだ人間であることの証拠だよ」的なことを言って諭すというやりとりがあります。アスカのように綾波もあんな姿ではあるものの人間としてシンジくんを待ち続けたということなのかなと...ニアサーのときに救えなかったと思っていた綾波をちゃんと救えていたんだねよかったねと思って泣いた。

終盤はスタジオを撤収していく演出によって世界をいったん畳んで作り直すというのを表しているはずで、その中でシンジくんとゲンドウは初めて向き合って会話をすることになるんですが、この時のゲンドウの内面にとても共感してしまった。さらに僕自身が親のことを好きではなく、特に親父のことはとても嫌いで昨年亡くなったのだが葬式もいかなければ、その後一度も帰っていない。正直他人レベルだと思っている。そんな僕の親父もゲンドウと同じく子供とどう接すればいいかわからなかったのか?(だからと言って嫌いじゃなくなるわけではないが)とシンジくん(子供側の)目線でも考えさせられた。ゲンドウは最終的に夢が叶ってよかったね。

最後は砂浜で(シンの世界では白いプラグスーツだったけど)はち切れた赤いプラグスーツ(だったよね?)をきた大人アスカに好きだったと伝えるシンジくん。この時のアスカの照れ顔がめっちゃ可愛かった。そしてマリ end で終わるわけです。

マリ end に関しては冒頭でも書いた通り坂本真綾ファンなので全く問題ないのですが、漫画版で保管されているとは言え謎の多い女性のまま終わったなという気持ち(監督の奥さんがモデルになっているというのは考察などを読んで知った)アスカファンはケンケン事件も含め大変そうなどと思った。

One Last Kiss を聴きながらスタッフロールを見てエヴァが終わってしまった喪失感を噛み締めていたがスタッフロールが長いのでこれ途中で曲変わるのかな?など考えていたら Beautiful World (Da Capo Version) が流れ始めたのだが One Last Kiss の CD を買ってはいたが Da Capo Version を聞いてなかったので最初はなんの曲かわからなかった。
しかし、もしも願い一つだけ叶うならの歌詞で Beautiful World と理解し、宇多田ヒカルの歌声の前に歌詞の内容が脳内で浮かんできた瞬間にこれはゲンドウとユイの歌なのだと気づき号泣してしまった。ゲンドウに感情移入してしまっていたというのがあり声を我慢しなければならないほど泣いた。スタッフロールなので完全に油断していた。新劇の最後のスタッフロールが新劇の最初の序のテーマソングで終わるというのはエヴァというループを最後まで表していて(解放されたはずなのに)エヴァっぽいと思った。

Q に引き続き鈴原サクラの関西弁は可愛かった。

Q に引き続きマリとアスカのイチャイチャはよかった。マリがアスカを「姫」と呼ぶのも好き。尊い

シンを見たら視聴者とシンジくんを置き去りにし Q ってなんだよ!と言われた Q も必要だったのかな?とちょっと思う。

成長したシンジくんを見れてよかった。いつまでもいじけてたり、アスカの裸を見てオナニーして「最低だ、俺って」って発言するシンジくんをまた見たいなんて思ってなかったからな!

シン・エヴァンゲリオンは感想とか見てても賛否あるようですが、否側の人々が見たかったり俺が考えた最高のエヴァンゲリオンもカオルくんが何十(?)何百(?)と繰り返してきた 1 回の中にはあったんだと思うよ。そう思えば多少救われるんじゃないですかね?(知らんけど)
だけど監督が最後として選んだのは今回のシン・エヴァンゲリオンだっただけなんだよきっと。


あと何回か映画館に見に行きたいし新劇の BD-BOX を出してくれるなら買うので頼む。

ありがとう、全てのエヴァンゲリオン
ありがとう、大好きな宇多田ヒカルが全テーマソングを担当した新劇。

さらば、全てのエヴァンゲリオン

RDS for MySQL の version up (5.6 -> 5.7) 時のアレコレ

はじめに

長年 RDS for MySQL の 5.6 を使っていたのですが、昨年の 10 月くらいにリザーブドが切れるタイミングで(安くなって性能も上がるので)インスタンスタイプを変更しようと思ったのですよ。インスタンスタイプ変更なのでメンテ挟んで〜ということになるので、準備などをしてメンテ前日を迎えたわけです。

新しいインスタンスタイプでレプリカを作っておくというのをやろうとしたら、作れないと言われる...色々調べてみたら MySQL 8 以降じゃないとそのインスタンスタイプは使えないと...(料金表にはそんなこと書いてないじゃないかクソが!などと思った記憶があるのですが)そんなこんなで 2021 年のお仕事の一つが MySQL の version up に決定。

2 月に 5.7 にするか〜と思っていたら 5.6 サポート終了のお知らせ が出てました。

ということで 5.7 にする際に調べた RDS の挙動などをメモっておく

5.6 -> 5.7 の変更点

社の福利厚生で @yoku0825 さんに気軽に質問出来るので教えてください〜と言ったら
大量に教えてもらった。

5.7 に関してはこのくらいで 8 に関しては 5 倍くらいの情報を教えてくれた(感謝)
自分のサービスで使用している RDS で気にしないといけないところは特になかった。というのも、sql_mode は 5.7 デフォルトのパラメータグループであれば 5.6 と一緒だし、innodb_tmp_data_file_path に関しては RDS では変更不可。

version up 方法

続いてはどうやって version up させるか?という話。
前提としてプライマリに対して n 台のレプリカ紐づいているという構成

検証なので本番のスナップショットから復元した検証用の構成を使っている

プライマリを 5.7 にする

何も考えずプライマリを 5.7 にあげようとしたところ、レプリカが全台プライマリより上の version じゃないとプライマリは version up 出来ないと言われて終了。

レプリカを 5.7 にする

上記のような結果になったので全てのレプリカを 5.7 にした。5.7 にしている最中は一定時間接続出来なくなる。

再度プライマリの 5.7 化にチャレンジ

すんなりいけた。
これで 5.7 にするという方法は理解できたのだけれど、何か問題があって一定時間稼働させた後に 5.6 に戻したいとなった場合に辛いなと思ったのでそこら辺の検証をした。

version のロールバック方法の検証

上記の version up の検証をする前に考えていたのは下記

レプリカ一台を 5.6 のままにしておき、他のプライマリ/レプリカ全台を 5.7 にする。この状態で問題が起きたら 5.6 のレプリカを昇格させる。だったのだが上記の検証でそれが不可能なことが発覚した。

次に試したのが、プライマリ 5.6 の状態でレプリカが 5.7 と 5.6 の状態で 5.7 のレプリカを昇格させると 5.6 のレプリカのレプリケーション先は昇格した 5.7 のシン・プライマリに向くんでは?というやーつ。試したが 5.6 レプリカは 5.6 プライマリに対してレプリケーションしてた(元々こういう挙動だったっけ?)

実際に試した方法は上記だけで、他には binlog や全クエリのログを保存しているのでそれを使って差分を流し込むなどが考えられる。
その他にも RDS から EC2 とかで自前で建てた MySQLレプリケーションが出来ればごにょごにょできるよね〜という選択肢もあるにはあるか?など考えていた。

結局簡単に戻せる方法はないのか?が知りたかったので AWS の中の人に直接聞いたら、結論としては簡単に戻せる方法はないのでクエリのログとかから手動で頑張ってという回答をいただいた。

さいごに

そんなこんなで問題が起きたら手動で頑張るしかないのか〜(手順はわかるが)めんどくさいな〜と思いつつ、水曜日の早朝にメンテナンスを行い 5.7 に上げたが特に問題は発生していないので、大勝利。

8 への version up も少し時間を空けてからトライする予定。

PC を自作した

はじめに

今月の初めくらいに人生で初めて PC を自作した。
自作自体は 10 年以上前からやりたい〜とは思っていたのですが当時はお金もあまりなく(今の給料の 1/3 以下?)、それなりにお金を稼げるようになってからは windows は使わなくなりもっぱら Mac だったので今更ゲーミング PC に 10 ~ 20 万もかけるのはなぁ...という気持ちがあった。

しかし、最近では windows 環境でも開発がしやすくなりゲーミング + 開発用と考えれば windows あっても困らんなと思い出したり。
マンションを購入して広い書斎が持てたのでデカイ PC あっても困らんなという考えから自作することにした。

構成

構成はこんな感じ
自作PC 構成見積もり てすと

CPU は本当は Ryzen 7 5800X BOX を買う予定だったのだけれど売ってない...ということで変更した。
あとは、ゲーミング PC なので無駄に光らせるかという気持ちで光るケースファンを選んだ。

f:id:shiro-16:20201205155354j:plain

組み立て

実際に組み立てたわけですが、3,4 時間あれば終わるかと思って夕方くらいに始めたのだけれど色々あり次の日の夜くらいに OS のインストールが終わるという長丁場になった。(途中予定があり外出なども有り)

それほど困らず全体を組み終わったのですが、実際に電源を入れてみると BIOS が表示されんなぁというのであれこれやっていて初日は終わり。

よくわからんので youtube とかで同じマザボ使って組み立てている人の動画なども眺めてメモリがちゃんとハマってるようではまってないのでは?と思い挿し直してみたら BIOS が起動して歓喜したのですが一旦色々バラしており最小構成で BIOS 起動まで行ったので諸々ちゃんと組み立てたらまた BIOS が起動しないということでハマる...

何箇所かパーツ抜き差ししてたら起動するようになったので OS インストールや〜となってパーティションの設定で SSD が認識されているのにうまくいかんとなり SSD を抜き差しするイベントが発生するなどが有り無事に OS のインストールも終わり出来上がり。

f:id:shiro-16:20201207161045j:plain

ちゃんと光ってる様子

最後に

初めての自作だったので色々ハマったが無事に出来てよかった...
ついでにキーボードも自作するか?と考えたがまだあわてるような時間じゃないと思い直して今回は見送り

ゲーミング PC 作って何をやっているかというと数年ぶりにエオルゼアを旅しています。(前は新生発売時に PS3 でやっていた)

k8s に Datadog を導入して APM のみ有効にしたい

はじめに

www.datadoghq.com

Datadog とはサーバのモニタリングなどを行ってくれるサービス。
一般的なメトリクスのモニタリング以外にも log を集約したりなど様々な機能があり、設定次第でそれぞれを有効化/無効化できます。

で今回はメトリクスのモニタリングは別でやってるので APM だけ有効にしたいんだよね〜ということをやっていきます。

Datadog 導入

まず Datadog には agent というものが存在します。
この agent が Datadog の server にメトリクスの情報を送るなどを行ってくれるものになります。

NewRelic などは gem として入れた agent が直接情報を NewRelic の server に送信しますが、Datadog は agent を別でインストールし、それに加えて gem も入れるということになります。この gem が agent に情報を送り agent が server に情報を送るという構成になっています。

APM としての機能だけではなく、server のメトリクス収集なども行ってくれるのでおそらくこういう構成になっているんでしょうね。

kubernetes に agent を install

導入方法はマニュアルの ここ に書いてありますが、k8s 上では daemonset として agent を deploy します。(見てもらえればわかりますが helm を使った install 方法なども書いてあります)

$ kubectl apply -f "https://raw.githubusercontent.com/DataDog/datadog-agent/master/Dockerfiles/manifests/rbac/clusterrole.yaml"

$ kubectl apply -f "https://raw.githubusercontent.com/DataDog/datadog-agent/master/Dockerfiles/manifests/rbac/serviceaccount.yaml"

$ kubectl apply -f "https://raw.githubusercontent.com/DataDog/datadog-agent/master/Dockerfiles/manifests/rbac/clusterrolebinding.yaml"

必要な RBAC を設定していきます。

次に API key の secret を作成

$ kubectl create secret generic datadog-agent --from-literal api-key="<DATADOG_API_KEY>" --namespace="default"

最後に daemonset を apply

$ cat daemonset.yaml
---
# Source: datadog/templates/install_info-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: datadog-agent-installinfo
  labels: {}
  annotations:
    checksum/install_info: 9f58f4fe71f1b79dfabae5311eb8f5373bd03072d4636e248cd3f581f8752627
data:
  install_info: |
    ---
    install_method:
      tool: kubernetes sample manifests
      tool_version: kubernetes sample manifests
      installer_version: kubernetes sample manifests
---
# Source: datadog/templates/daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: datadog-agent
  labels: {}
spec:
  selector:
    matchLabels:
      app: datadog-agent
  template:
    metadata:
      labels:
        app: datadog-agent
      name: datadog-agent
      annotations: {}
    spec:
      containers:
        - name: agent
          image: "gcr.io/datadoghq/agent:7.23.1"
          imagePullPolicy: IfNotPresent
          command: ["agent", "run"]
          resources: {}
          ports:
            - containerPort: 8125
              name: dogstatsdport
              protocol: UDP
          env:
            - name: DD_API_KEY
              valueFrom:
                secretKeyRef:
                  name: "datadog-agent"
                  key: api-key
            - name: DD_KUBERNETES_KUBELET_HOST
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
            - name: KUBERNETES
              value: "yes"
            - name: DOCKER_HOST
              value: unix:///host/var/run/docker.sock
            - name: DD_LOG_LEVEL
              value: "INFO"
            - name: DD_DOGSTATSD_PORT
              value: "8125"
            - name: DD_APM_ENABLED
              value: "false"
            - name: DD_LOGS_ENABLED
              value: "false"
            - name: DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL
              value: "false"
            - name: DD_LOGS_CONFIG_K8S_CONTAINER_USE_FILE
              value: "true"
            - name: DD_HEALTH_PORT
              value: "5555"
            - name: DD_ENABLE_PAYLOADS_EVENTS
              value: "false"
            - name: DD_ENABLE_PAYLOADS_SERIES
              value: "false"
            - name: DD_ENABLE_PAYLOADS_SERVICE_CHECKS
              value: "false"
            - name: DD_ENABLE_PAYLOADS_SKETCHES
              value: "false"
            - name: DD_PROCESS_AGENT_ENABLED
              value: "false"
          volumeMounts:
            - name: installinfo
              subPath: install_info
              mountPath: /etc/datadog-agent/install_info
              readOnly: true
            - name: config
              mountPath: /etc/datadog-agent
            - name: runtimesocketdir
              mountPath: /host/var/run
              mountPropagation: None
              readOnly: true
            - name: procdir
              mountPath: /host/proc
              mountPropagation: None
              readOnly: true
            - name: cgroups
              mountPath: /host/sys/fs/cgroup
              mountPropagation: None
              readOnly: true
          livenessProbe:
            failureThreshold: 6
            httpGet:
              path: /live
              port: 5555
              scheme: HTTP
            initialDelaySeconds: 15
            periodSeconds: 15
            successThreshold: 1
            timeoutSeconds: 5
          readinessProbe:
            failureThreshold: 6
            httpGet:
              path: /ready
              port: 5555
              scheme: HTTP
            initialDelaySeconds: 15
            periodSeconds: 15
            successThreshold: 1
            timeoutSeconds: 5
        - name: trace-agent
          image: "gcr.io/datadoghq/agent:7.23.1"
          imagePullPolicy: IfNotPresent
          command: ["trace-agent", "-config=/etc/datadog-agent/datadog.yaml"]
          resources: {}
          ports:
            - containerPort: 8126
              hostPort: 8126
              name: traceport
              protocol: TCP
          env:
            - name: DD_API_KEY
              valueFrom:
                secretKeyRef:
                  name: "datadog-agent"
                  key: api-key
            - name: DD_KUBERNETES_KUBELET_HOST
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
            - name: KUBERNETES
              value: "yes"
            - name: DOCKER_HOST
              value: unix:///host/var/run/docker.sock
            - name: DD_LOG_LEVEL
              value: "INFO"
            - name: DD_APM_ENABLED
              value: "true"
            - name: DD_APM_NON_LOCAL_TRAFFIC
              value: "true"
            - name: DD_APM_RECEIVER_PORT
              value: "8126"
          volumeMounts:
            - name: config
              mountPath: /etc/datadog-agent
            - name: runtimesocketdir
              mountPath: /host/var/run
              mountPropagation: None
              readOnly: true
          livenessProbe:
            initialDelaySeconds: 15
            periodSeconds: 15
            tcpSocket:
              port: 8126
            timeoutSeconds: 5
        - name: process-agent
          image: "gcr.io/datadoghq/agent:7.23.1"
          imagePullPolicy: IfNotPresent
          command: ["process-agent", "-config=/etc/datadog-agent/datadog.yaml"]
          resources: {}
          env:
            - name: DD_API_KEY
              valueFrom:
                secretKeyRef:
                  name: "datadog-agent"
                  key: api-key
            - name: DD_KUBERNETES_KUBELET_HOST
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
            - name: KUBERNETES
              value: "yes"
            - name: DOCKER_HOST
              value: unix:///host/var/run/docker.sock
            - name: DD_LOG_LEVEL
              value: "INFO"
            - name: DD_ORCHESTRATOR_EXPLORER_ENABLED
              value: "false"
          volumeMounts:
            - name: config
              mountPath: /etc/datadog-agent
            - name: runtimesocketdir
              mountPath: /host/var/run
              mountPropagation: None
              readOnly: true
            - name: cgroups
              mountPath: /host/sys/fs/cgroup
              mountPropagation: None
              readOnly: true
            - name: passwd
              mountPath: /etc/passwd
            - name: procdir
              mountPath: /host/proc
              mountPropagation: None
              readOnly: true
      initContainers:
        - name: init-volume
          image: "gcr.io/datadoghq/agent:7.23.1"
          imagePullPolicy: IfNotPresent
          command: ["bash", "-c"]
          args:
            - cp -r /etc/datadog-agent /opt
          volumeMounts:
            - name: config
              mountPath: /opt/datadog-agent
          resources: {}
        - name: init-config
          image: "gcr.io/datadoghq/agent:7.23.1"
          imagePullPolicy: IfNotPresent
          command: ["bash", "-c"]
          args:
            - for script in $(find /etc/cont-init.d/ -type f -name '*.sh' | sort) ; do bash $script ; done
          volumeMounts:
            - name: config
              mountPath: /etc/datadog-agent
            - name: procdir
              mountPath: /host/proc
              mountPropagation: None
              readOnly: true
            - name: runtimesocketdir
              mountPath: /host/var/run
              mountPropagation: None
              readOnly: true
          env:
            - name: DD_API_KEY
              valueFrom:
                secretKeyRef:
                  name: "datadog-agent"
                  key: api-key
            - name: DD_KUBERNETES_KUBELET_HOST
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
            - name: KUBERNETES
              value: "yes"
            - name: DOCKER_HOST
              value: unix:///host/var/run/docker.sock
          resources: {}
      volumes:
        - name: installinfo
          configMap:
            name: datadog-agent-installinfo
        - name: config
          emptyDir: {}
        - hostPath:
            path: /var/run
          name: runtimesocketdir
        - hostPath:
            path: /proc
          name: procdir
        - hostPath:
            path: /sys/fs/cgroup
          name: cgroups
        - name: s6-run
          emptyDir: {}
        - hostPath:
            path: /etc/passwd
          name: passwd
      tolerations:
      affinity: {}
      serviceAccountName: "datadog-agent"
      nodeSelector:
        kubernetes.io/os: linux
  updateStrategy:
    rollingUpdate:
      maxUnavailable: 10%
    type: RollingUpdate

# Source: datadog/templates/containers-common-env.yaml
# The purpose of this template is to define a minimal set of environment
# variables required to operate dedicated containers in the daemonset

$ kubectl apply -f daemonset.yaml

元々の daemonset.yaml と比べてもらえるとわかりますがいくつかの環境変数を設定することで APM のみを有効にしています。

gem を install

今回は Rails のアプリケーションに APM を入れるので Gemfile に書いていきます。

$ vi Gemfile
+ gem 'ddtrace'
$ bundle install
$ vi config/initializers/datadog.rb
Datadog.configure do |c|
  c.tracer enabled: true
  c.use :rails, service_name: "hoge"
end

この状態でリリースしてあげると Datadog の画面上で APM の情報が見れるようになると思います。

最後に

APM のみ有効にしてみましたが、導入して一ヶ月経っていないので支払いがまだ発生しておらず APM のみになっているか不安ではあるのですが Usage の画面を見ると APM の情報のみしか出ないのでおそらく成功していると思われます。