CF Buildpacks(golang) で Dynatrace-oneagent がインストールされる仕組み


概要

  • トレーシングとしてDynatraceを使用しており、agentであるone-agentがどのようにruntimeに組み込まれるのか気になった
  • buildpackのfinalize時にインストールされていた

Buildpacksの動作ロジック

  1. detect: pushしたcodeがどのbuilcpackを使用するか判定する
  2. supply: codeの依存解決
  3. finalize: appが起動するために必要な諸々の処理 <- oneagent install
  4. release: appがどのように実行されるべきかをCloudControllerに送る

の順番で動作する

finalizeの処理を少し深ぼる

buildpacksの仕組みが動作するときに上記の順番で動作するのですが、実際にはスクリプトでキックされます。
その中で、finalize処理はgo言語で書かれたコードで実行されます

GOROOT=$GoInstallDir/go $GoInstallDir/go/bin/go build -mod=vendor -o $output_dir/finalize ./src/go/finalize/cli

https://github.com/cloudfoundry/go-buildpack/blob/70cbfa711f48fae071d6c146e232a5674d53e5fe/bin/finalize#L16

叩き先のメソッドはこちら

https://github.com/cloudfoundry/go-buildpack/blob/70cbfa711f48fae071d6c146e232a5674d53e5fe/src/go/finalize/cli/main.go#L12-L59

色々と書かれていますが、ポイントはこの2つかなと思います。

  • finalize.Run(gf)
  • libbuildpack.RunAfterCompile(stager)

https://github.com/cloudfoundry/go-buildpack/blob/70cbfa711f48fae071d6c146e232a5674d53e5fe/src/go/finalize/cli/main.go#L44

Run()

いわゆる go build とか環境変数のセットアップが行われています

https://github.com/cloudfoundry/go-buildpack/blob/70cbfa711f48fae071d6c146e232a5674d53e5fe/src/go/finalize/finalize.go#L83-L165

RunAfterCompile()

今回のDynatraceの肝となります。

hooksに追加されていたエントリーを実施しています。

https://github.com/cloudfoundry/libbuildpack/blob/6d89ff5fe3c0719d16b79671aa9e15c202e84aa0/hooks.go#L37

hooksへの追加はinit()メソッドで実行されるのでmainメソッドよりも前に自動で実行されます

https://github.com/cloudfoundry/go-buildpack/blob/70cbfa711f48fae071d6c146e232a5674d53e5fe/src/go/hooks/dynatrace.go#L8-L10

Dynatraceのインストールに必要なapi_endpointやapi_tokenが設定されているかを確認します。
FullStackかUPSが設定されていない場合にはインストールされないですね。

creds := h.getCredentials()
	if creds == nil {
		h.Log.Debug("Dynatrace service credentials not found!")
		return nil
	}

https://github.com/Dynatrace/libbuildpack-dynatrace/blob/1640532fc77fcc0ec768eeeb9af7c46bfdb4c5a6/hook.go#L68-L72

downloaderを落とした後にinstallerを実施して、oneagentをinstallしています

if os.Getenv("BP_DEBUG") != "" {
		err = h.Command.Execute("", os.Stdout, os.Stderr, installerFilePath, stager.BuildDir())
	} else {
		err = h.Command.Execute("", ioutil.Discard, ioutil.Discard, installerFilePath, stager.BuildDir())
	}
	if err != nil {
		return err
	}

https://github.com/Dynatrace/libbuildpack-dynatrace/blob/1640532fc77fcc0ec768eeeb9af7c46bfdb4c5a6/hook.go#L106-L113

まとめ

  • buildpackの実行順序を軽くまとめた
  • golangのケースを基にDynatrace oneagentがinstallされる仕組みを追ってみた