Golang で NVML(NVIDIA Management Library)を使いたかったので、NVIDIA/gpu-monitoring-tools のライブラリを使わせてもらおうと思ったら、躓いてしまったのでメモ。
環境
$ go version go version go1.15 darwin/amd64
サンプルコード
NVIDIA/gpu-monitoring-tools リポジトリにあるサンプルコードを参考にしています。
package main import ( "fmt" "github.com/NVIDIA/gpu-monitoring-tools/bindings/go/nvml" ) func getGpuUsage() error { if err := nvml.Init(); err != nil { return err } defer nvml.Shutdown() count, err := nvml.GetDeviceCount() if err != nil { return fmt.Errorf("error getting device count: %v", err) } for i := uint(0); i < count; i++ { device, err := nvml.NewDevice(i) if err != nil { return fmt.Errorf("error getting device %d: %v\n", i, err) } st, err := device.Status() if err != nil { return fmt.Errorf("error getting device %d status: %v\n", i, err) } fmt.Println(st.Utilization) } return nil }
go build
をすると unknown revision v0.0.0
でコケます。
$ go mod init $ go build go: finding module for package k8s.io/api go: finding module for package github.com/NVIDIA/gpu-monitoring-tools/bindings/go/nvml go: found github.com/NVIDIA/gpu-monitoring-tools/bindings/go/nvml in github.com/NVIDIA/gpu-monitoring-tools v0.0.0-20201006233419-a544dbcaacb0 go: found k8s.io/api in k8s.io/api v0.19.2 go: github.com/NVIDIA/gpu-monitoring-tools@v0.0.0-20201006233419-a544dbcaacb0 requires k8s.io/kubernetes@v1.18.2 requires k8s.io/api@v0.0.0: reading k8s.io/api/go.mod at revision v0.0.0: unknown revision v0.0.0
原因
Go Modules で依存パッケージを取得する際に kubernetes が必要で、kubernetes が依存している kubernetes/api
のバージョン v0.0.0
というのが無いためエラーになっていました。順に追って説明します。
NVIDIA/gpu-monitoring-tools
の go.mod
の require
に k8s.io/kubernetes v1.18.2
があるため、kubernetes v1.18.2 を取得しようとします。
# https://github.com/NVIDIA/gpu-monitoring-tools/blob/master/go.mod#L12 require ( ... k8s.io/kubernetes v1.18.2 )
kubernetes v1.18.2 の go.mod
を見ると、k8s.io/api v0.0.0
があるため、kubernetes/api v0.0.0
を取得しようとします。
# https://github.com/kubernetes/kubernetes/blob/v1.18.2/go.mod#L141 require ( ... k8s.io/api v0.0.0 ... )
しかし、kubernetes/api
を見ると、v0.0.0 がないためここでコケてしまうというわけです。
回避策
Issue を見ると replace を使うのが良さそうです。実は kubernetes/api
以外も多くのパッケージが同じエラーになったので次のようになりました。
module hogehoge_module go 1.15 replace ( k8s.io/api => k8s.io/api v0.0.0-20190620084959-7cf5895f2711 k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20190620085554-14e95df34f1f k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719 k8s.io/apiserver => k8s.io/apiserver v0.0.0-20190620085212-47dc9a115b18 k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20190620085706-2090e6d8f84c k8s.io/client-go => k8s.io/client-go v0.0.0-20190620085101-78d2af792bab k8s.io/cloud-provider => k8s.io/cloud-provider v0.0.0-20190620090043-8301c0bda1f0 k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.0.0-20190620090013-c9a0fc045dc1 k8s.io/code-generator => k8s.io/code-generator v0.0.0-20190612205613-18da4a14b22b k8s.io/component-base => k8s.io/component-base v0.0.0-20190620085130-185d68e6e6ea k8s.io/cri-api => k8s.io/cri-api v0.0.0-20190531030430-6117653b35f1 k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.0.0-20190620090116-299a7b270edc k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.0.0-20190620085325-f29e2b4a4f84 k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.0.0-20190620085942-b7f18460b210 k8s.io/kube-proxy => k8s.io/kube-proxy v0.0.0-20190620085809-589f994ddf7f k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.0.0-20190620085912-4acac5405ec6 k8s.io/kubectl => k8s.io/kubectl v0.0.0-20201008135616-e95e378e5972 k8s.io/kubelet => k8s.io/kubelet v0.0.0-20190620085838-f1cb295a73c9 k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.0.0-20190620090156-2138f2c9de18 k8s.io/metrics => k8s.io/metrics v0.0.0-20190620085625-3b22d835f165 k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.0.0-20190620085408-1aef9010884e )
今回使いたい NVML ライブラリ自体は kubernetes が必要でないため、バージョンは古くてもOKなので Issue に載っていたものをパクリました。Issue にかかれていないパッケージ(kubectl など)は自分で追記しなければなりません。
Go Modules の仕様としてバージョンの後ろは「リビジョンのタイムスタンプ」と「リビジョン」を入れなければなりません。
replace ( k8s.io/api => k8s.io/api v0.0.0-<リビジョンのタイムスタンプ>-<リビジョン> )
リジョンは Git コミット ID の先頭12文字となります。リビジョンのタイムスタンプは committer date となるので git log --pretty=fuller
で取得できます。UTC なのでタイムゾーンがずれていたら直します。
go.mod
に replace を追記して go build
をすると正常に依存パッケージを取得できてビルドできるようになりました。
参考文献
- 'unknown revision v0.0.0' errors, seemingly due to 'require k8s.io/foo v0.0.0' · Issue #79384 · kubernetes/kubernetes
- Pin go.mod dependencies for different k8s api versions - General Discussions - Discuss Kubernetes
- Go 1.13 Release Notes - The Go Programming Language
- Git のコミットのタイムスタンプには author date と committer date の 2 種類があるという話 - ひだまりソケットは壊れない