LoginSignup
0
0

More than 5 years have passed since last update.

mackerel-agentでのAWSインテグレーション周りのソースコード(主にCustomIdentifier)

Posted at

自分用のメモ

logo.png

さくらのクラウドとMackerelの連携ツール「sackerel」を実装した時のメモ。


mackerel-agentの0.34.0にてAWSインテグレーションができるようになったそうです。
詳細はMackerelブログ8月19日の記事にありました。

エージェント側でどういう風にインテグレーションを行っているか気になったので調べました。

以下は執筆時点でのmasterブランチ最新コミット(cd6a67a)を元に調査しています。
今後の開発により処理方法が変更になる可能性があります。

ホスト情報の収集(command/command.go)

それらしいものが以下にありました。

引用元 : command/command.go#L472

command/command.go
// collectHostSpecs collects host specs (correspond to "name", "meta", "interfaces" and "customIdentifier" fields in API v0)
func collectHostSpecs() (string, map[string]interface{}, []spec.NetInterface, string, error) {
    // (省略)

    // 479行目〜
    cGen := spec.SuggestCloudGenerator()

    // (省略)

    // 485行目〜
    var customIdentifier string
    if cGen != nil {
        customIdentifier, err = cGen.SuggestCustomIdentifier()
        if err != nil {
            logger.Warningf("Error while suggesting custom identifier. err: %s", err.Error())
        }
    }

    // (省略)

collectHostSpecs()はMackerelエージェントがホストの情報を収集するためのもののようです。
その中でCustomIdentifireという値の収集のためにspec.SuggestCloudGenerator()を呼んでいます。
こいつのSuggestCustomIdentifier()CustomIdentifierを返してくれるようですね。

CustomIdentifireはマニュアルなどに記載はないですが、MackerelのホストIDとは別に
任意のIDを持たせるためのフィールドのようです。
GET /api/v0/hostsなどの、ホスト情報参照APIでもレスポンス内に値がきちんと含まれていました。

それでは呼ばれる先のspec.SuggestCloudGenerator()を見てみましょう。

クラウド事業者ごとにCustomIdentifireの生成をする(spec/cloug.go)

引用元 : spec/cloud.go#L47

spec/cloud.go
// SuggestCloudGenerator returns suitable CloudGenerator
func SuggestCloudGenerator() *CloudGenerator {
    if isEC2() {
        return &CloudGenerator{&EC2Generator{ec2BaseURL}}
    }
    if isGCE() {
        return &CloudGenerator{&GCEGenerator{gceMetaURL}}
    }

    return nil
}

CustomIdentifireを生成するためのジェネレータを作成して返すファクトリメソッドです。
ここでisEC2()またはisGCE()でプラットフォームを判定し、適切なジェネレータを作成しています。

もし対応クラウドプラットフォームを増やしたい場合はここに追加対応ですね!
(過去のソースにDigitalOcean対応の残骸があったりします)

引用元 : spec/cloud.go#L59

spec/cloug.do
func isEC2() bool {
    cl := http.Client{
        Timeout: timeout,
    }
    // '/ami-id` is may be aws specific URL
    // (筆者注 : ec2BaseURL := "http://169.254.169.254/latest/meta-data")
    resp, err := cl.Get(ec2BaseURL.String() + "/ami-id")
    if err != nil {
        return false
    }
    defer resp.Body.Close()

    return resp.StatusCode == 200
}

メタデータを取得して判定していますね。
EC2であるかの判定で、/ami-idをリクエストすることでOpenStackなどと区別するようですね。

実際のCustomIdentifire生成処理は以下にあります。

引用元 : spec/cloud.go#L156

spec/cloud.go
// SuggestCustomIdentifier suggests the identifier of the EC2 instance
func (g *EC2Generator) SuggestCustomIdentifier() (string, error) {
    client := http.Client{Timeout: timeout}
    key := "instance-id"
    resp, err := client.Get(g.baseURL.String() + "/" + key)

    // (省略)

    instanceID := string(body)

    // (省略)

    return instanceID + ".ec2.amazonaws.com", nil
}

メタデータからインスタンスIDを取得し、インスタンスID.ec2.amazonaws.comを返すだけです。

AWSやGCE以外のクラウドプラットフォーム対応する場合はここも実装が必要ですね。


収集したCustomIdentifierは以下でMackerelへ送信されます。

ホスト情報の登録

引用元 : command/command.go#L29

command/command.go

// prepareHost collects specs of the host and sends them to Mackerel server.
// A unique host-id is returned by the server if one is not specified.
func prepareHost(conf *config.Config, api *mackerel.API) (*mackerel.Host, error) {
    // (省略)

            // (66行目〜)
            doRetry(func() error {
                hostID, lastErr = api.CreateHost(mackerel.HostSpec{
                    Name:             hostname,
                    Meta:             meta,
                    Interfaces:       interfaces,
                    RoleFullnames:    conf.Roles,
                    DisplayName:      conf.DisplayName,
                    CustomIdentifier: customIdentifier,
                })
                return filterErrorForRetry(lastErr)
            })

    // (省略)

}

ホスト情報の更新

引用元 : command/command.go#L501

command/command.go
// UpdateHostSpecs updates the host information that is already registered on Mackerel.
func (c *Context) UpdateHostSpecs() {
    // (省略)

    hostname, meta, interfaces, customIdentifier, err := collectHostSpecs()

    // (省略)

    err = c.API.UpdateHost(c.Host.ID, mackerel.HostSpec{
        Name:             hostname,
        Meta:             meta,
        Interfaces:       interfaces,
        RoleFullnames:    c.Config.Roles,
        Checks:           c.Config.CheckNames(),
        DisplayName:      c.Config.DisplayName,
        CustomIdentifier: customIdentifier,
    })

    // (省略)
}

というわけで、実装を見てみました。
mackerel-agent側でカスタムIDを生成すると何が嬉しいかというと、AWSインテグレーションみたいなエージェントレス監視に対し、後からエージェントをインストールした時に同一ホストかの判定ができるんですね。

さくらのクラウドとMackerelの連携ツール「sackerel」がまさにこれが必要でした。

以上です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0