go の kubernetes モジュールを GKE バージョンに合わせて更新

ゲーム専用サーバで使っていた Agones, Open Match をバージョンアップしたので、GKE もバージョンアップしたらエラー発生! なんとかしましょー

はじめまして、エンジニアのよっしーです。 ゲーム専用サーバで開発していたアプリの最新環境対応のために GKE, Agones, Open Match を最新版に更新したところ、 kubernetes client-go モジュールで関数 argument の不整合エラーが発生!

GKE, Agones, Open Match のバージョンアップ時に遭遇しがちな go モジュールバージョン不整合の解決方法についてお話しします。

1.GKE, Agones, Open Match を最新バージョンにしてみる (2021/06/16現在)

それぞれの最新バージョンが

  • GKE : “1.19.9-gke1900” - Regularチャンネルのデフォルトバージョン
  • Agones : “release-1.15.0”
  • Open Macth : “release-1.2”

と確認できたので、それぞれバージョンアップを実行し、Agones, Open Match を GKE クラスタにデプロイ。 すると、 Open Match を使用するアプリ起動時に client-go モジュールの watch.NewStreamWatcher 関数呼び出しで argument の不整合エラーが発生!

 # k8s.io/client-go/rest
 ../../../../../../pkg/mod/k8s.io/client-go@v11.0.1-0.20191029005444-8e4128053008+incompatible/rest/request.go:598:31: not enough arguments in call to watch.NewStreamWatcher
    have (*versioned.Decoder)
    want (watch.Decoder, watch.Reporter)

2.GKE, Agones, Open Match それぞれの go の設定について調べてみる。

まずは go バージョン

  • GKE
$ kubectl version | grep Server | awk -F ',' '{print $3 $7}'
GitVersion:"v1.19.9-gke.1900" GoVersion:"go1.15.8b5"
  • Agones
$ cat agones/go.mod | grep "^go "
go 1.14
  • Open Match
$ cat open-match/go.mod | grep "^go "
go 1.14

GKE は go1.15 であり、Agones, Open Match は go1.14 を指定していた。

しかし、go の公式サイト(golang.org)では、go version 1 のマイナーバージョン間では ソースレベルの互換性を約束しているため、 1.14 と 1.15 間では、ほとんど全ての Go プログラムを 再コンパイルすれば、go アプリを実行できると考えられる。

また、go 公式サイトにはこうも書かれている。
“The APIs may grow, acquiring new packages and features, but not in a way that breaks existing Go 1 code.”
(既存の go 1 コードを破壊するほどではないが、API は新しいパッケージや機能を取得することがある。)
ということで、kubernetes API に関するモジュール指定を確認すると、

  • Agones
$ cat agones/go.mod | grep "k8s.io"
k8s.io/api v0.18.15
k8s.io/apiextensions-apiserver v0.18.15
k8s.io/apimachinery v0.18.15
k8s.io/client-go v0.18.15
k8s.io/kube-openapi v0.0.0-20200410163147-594e756bea31 // indirect
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89
  • Open Match
$ cat open-match/go.mod | grep "k8s.io"
k8s.io/api v0.0.0-20191004102349-159aefb8556b // kubernetes-1.14.10
k8s.io/apimachinery v0.0.0-20191004074956-c5d2f014d689 // kubernetes-1.14.10
k8s.io/client-go v11.0.1-0.20191029005444-8e4128053008+incompatible // kubernetes-1.14.10
k8s.io/klog v1.0.0 // indirect
k8s.io/utils v0.0.0-20200729134348-d5654de09c73 // indirect

特に Open Match では kubernetes-1.14.10 をサポートするモジュールを指定している。 ということで、エラーの出ている client-go と api 関連のモジュールを kubernets-1.19.9 対応バージョンに更新しよう。

3.モジュールの更新

  • モジュールの更新には “go get” コマンドを使用する。
  • kubernetes-1.19.9 対応のモジュールを指定するには、モジュール名の後に "@kubernetes-1.19.9" を付与する。

実行例

$ go get k8s.io/client-go@kubernetes-1.19.9
go: k8s.io/client-go kubernetes-1.19.9 => v0.19.9

$ go get k8s.io/apimachinery@kubernetes-1.19.9
go: k8s.io/apimachinery kubernetes-1.19.9 => v0.19.10-rc.0

$ go get k8s.io/api@kubernetes-1.19.9
go: k8s.io/api kubernetes-1.19.9 => v0.19.9
go build k8s.io/api: no non-test Go files in /usr/local/gopath/1.15.1/pkg/mod/k8s.io/api@v0.19.9

$ go get k8s.io/apiextensions-apiserver@kubernetes-1.19.9
go: k8s.io/apiextensions-apiserver kubernetes-1.19.9 => v0.19.9
  • “go.mod” ファイルの存在するディレクトリで実行すると、go.mod 内の該当モジュールのバージョンも自動的に書き換えてくれる。
  • Agones
$ cat agones/go.mod | grep "k8s.io"
k8s.io/api v0.19.9
k8s.io/apiextensions-apiserver v0.19.9
k8s.io/apimachinery v0.19.10-rc.0
k8s.io/client-go v0.19.9
k8s.io/klog v1.0.0 // indirect
k8s.io/utils v0.0.0-20200729134348-d5654de09c73
  • Open Match
$ cat open-match/go.mod | grep "k8s.io"
k8s.io/api v0.19.9
k8s.io/apimachinery v0.19.10-rc.0
k8s.io/client-go v0.19.9
k8s.io/klog v1.0.0 // indirect
k8s.io/utils v0.0.0-20200729134348-d5654de09c73 // indirect
  • Agones, Open Match 意外にも該当 go モジュールを使用しているアプリがあれば、モジュールの更新を勧める。

go モジュールのバージョン指定は “@kubernetes-1.19.9” 以外にも指定方法があるので、下記サイトを参照のこと。
client-go/INSTALL.md at master · kubernetes/client-go · GitHub

モジュール更新後の Agones, Open Match を GKE クラスタに再デプロイし、アプリを起動するとエラーは解消した。

終わりに

kubernetes 環境では各ツールのバージョン間の互換性が問題になることが多いと思われますが、 問題解決の救済処置がしっかりしているツールもあります。 多くのエンジニアがハマりそうな有用な情報は、是非共有を進めて行きましょう!