Compute InstanceのCloud SDK更新対応


## はじめに
立ち上げているGCEインスタンスでgcloudのバージョンが古くなっているのを解消しようとしたところ、バージョンアップに難儀しました。引っかかるにはあまりにも非生産的で不毛だな、という気持ちが大変強かったので、記事に書くことにしました。

## 先に結論
 - GCEインスタンスで gcloudコマンドでのSDK更新は出来ない
 - aptでインストールするにも、公開鍵設定などのコマンド実行が必要

## 前提
今回の検証対象VMは以下の通りです。
Google Cloud SDK 375.0.0
debian-10-buster-v20220303

```
Linux test-vm 4.19.0-18-cloud-amd64 #1 SMP Debian 4.19.208-1 (2021-09-29) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
$ gcloud version
Google Cloud SDK 375.0.0
alpha 2022.02.25
beta 2022.02.25
bq 2.0.74
bundled-python3-unix 3.8.11
core 2022.02.25
gsutil 5.6
```

# 現状の確認
まずは、PCなどローカル端末でgcloud SDKを更新するのと同様、VMに対してもgcloudコマンドで更新を試してみます。
```
$ gcloud components update  
To help improve the quality of this product, we collect anonymized usage data and anonymized stacktraces when crashes are encountered; additional information is
 available at <https://cloud.google.com/sdk/usage-statistics>. This data is handled in accordance with our privacy policy 
<https://cloud.google.com/terms/cloud-privacy-notice>. You may choose to opt in this collection now (by choosing 'Y' at the below prompt), or at any time in the
 future by running the following command:

    gcloud config set disable_usage_reporting false

Do you want to opt-in (y/N)?  y

Beginning update. This process may take several minutes.
ERROR: (gcloud.components.update) 
You cannot perform this action because the Google Cloud CLI component manager 
is disabled for this installation. You can run the following command 
to achieve the same result for this installation: 

sudo apt-get update && sudo apt-get --only-upgrade install google-cloud-sdk-app-engine-python-extras google-cloud-sdk-datalab google-cloud-sdk-nomos
 google-cloud-sdk-bigtable-emulator google-cloud-sdk-kubectl-oidc google-cloud-sdk-app-engine-go
 google-cloud-sdk-app-engine-grpc google-cloud-sdk-cloud-build-local google-cloud-sdk-kpt google-cloud-sdk-spanner-emulator google-cloud-sdk-skaffold
 google-cloud-sdk-firestore-emulator google-cloud-sdk-pubsub-emulator kubectl google-cloud-sdk-local-extract google-cloud-sdk-app-engine-java
 google-cloud-sdk-app-engine-python google-cloud-sdk-minikube google-cloud-sdk-datastore-emulator google-cloud-sdk
 google-cloud-sdk-gke-gcloud-auth-plugin google-cloud-sdk-cbt google-cloud-sdk-anthos-auth
 google-cloud-sdk-terraform-validator google-cloud-sdk-config-connector google-cloud-sdk-cloud-run-proxy

```
</details>


gcloud SDKでupdateコマンドがあるにもかかわらず、GoogleCloud管理下にあるはずのCompute Instanceなのにもかかわらず、大体手段が提示されるのはやや違和感がぬぐえません。しかも、apt-getで大量に入れていけ、というのも美しくない方法を推してくるもので、本当にこれが適切なのか、と言いたくなるのが正直な感想です。

とはいえ、代替手段として提示される以上はこれに従う他無いでしょうから、実行してみます。

<details><summary>apg-getコマンド実行</summary>

```
$ sudo apt-get update && sudo apt-get --only-upgrade install google-cloud-sdk-app-engine-python-extras google-cloud-sdk-datalab google-cloud-sdk-nomos google-cloud-sdk-bigtable-emulator google-cloud-sdk-kubectl-oidc google-cloud-sdk-app-engine-go google-cloud-sdk-app-engine-grpc google-cloud-sdk-cloud-build-local google-cloud-sdk-kpt google-cloud-sdk-spanner-emulator google-cloud-sdk-skaffold google-cloud-sdk-firestore-emulator google-cloud-sdk-pubsub-emulator kubectl google-cloud-sdk-local-extract google-cloud-sdk-app-engine-java google-cloud-sdk-app-engine-python google-cloud-sdk-minikube google-cloud-sdk-datastore-emulator google-cloud-sdk google-cloud-sdk-gke-gcloud-auth-plugin google-cloud-sdk-cbt google-cloud-sdk-anthos-auth google-cloud-sdk-terraform-validator google-cloud-sdk-config-connector google-cloud-sdk-cloud-run-proxy
Hit:1 http://deb.debian.org/debian buster InRelease
Hit:2 http://deb.debian.org/debian buster-updates InRelease                            
Hit:3 http://deb.debian.org/debian buster-backports InRelease                          
Hit:4 http://security.debian.org/debian-security buster/updates InRelease              
Get:5 http://packages.cloud.google.com/apt cloud-sdk-buster InRelease [6396 B]         
Err:5 http://packages.cloud.google.com/apt cloud-sdk-buster InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05
Get:6 http://packages.cloud.google.com/apt google-cloud-packages-archive-keyring-buster InRelease [5163 B]
Err:6 http://packages.cloud.google.com/apt google-cloud-packages-archive-keyring-buster InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05
Get:7 http://packages.cloud.google.com/apt google-compute-engine-buster-stable InRelease [5136 B]
Err:7 http://packages.cloud.google.com/apt google-compute-engine-buster-stable InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05
Fetched 11.6 kB in 1s (8436 B/s)
Reading package lists... Done
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: http://packages.cloud.google.com/apt cloud-sdk-buster InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: http://packages.cloud.google.com/apt google-cloud-packages-archive-keyring-buster InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: http://packages.cloud.google.com/apt google-compute-engine-buster-stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05
W: Failed to fetch http://packages.cloud.google.com/apt/dists/cloud-sdk-buster/InRelease  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05
W: Failed to fetch http://packages.cloud.google.com/apt/dists/google-cloud-packages-archive-keyring-buster/InRelease  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05
W: Failed to fetch http://packages.cloud.google.com/apt/dists/google-compute-engine-buster-stable/InRelease  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05
W: Some index files failed to download. They have been ignored, or old ones used instead.
Reading package lists... Done
Building dependency tree       
Reading state information... Done
google-cloud-sdk is already the newest version (375.0.0-0).
Skipping google-cloud-sdk-anthos-auth, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-app-engine-go, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-app-engine-grpc, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-app-engine-java, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-app-engine-python, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-app-engine-python-extras, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-bigtable-emulator, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-cbt, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-cloud-build-local, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-cloud-run-proxy, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-config-connector, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-datalab, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-datastore-emulator, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-firestore-emulator, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-gke-gcloud-auth-plugin, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-kpt, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-kubectl-oidc, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-local-extract, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-minikube, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-nomos, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-pubsub-emulator, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-skaffold, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-spanner-emulator, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-terraform-validator, it is not installed and only upgrades are requested.
Skipping kubectl, it is not installed and only upgrades are requested.
0 upgraded, 0 newly installed, 0 to remove and 72 not upgraded.
```
</details>

エラーが出て更新もされていません。提示された代替手段はいったい何だったのか。

# 解消方法

いくつか試してみましたが、[gcloud CLIをインストールする](https://cloud.google.com/sdk/docs/install?hl=ja)に基づくコマンド実行をすることで解消できる、というのが現時点で見つかっていて、再現性のあるものでした。

ただしその前に、gcloud SDKがどこに入っているかは確認しておきましょう
```
$ which gcloud
/usr/bin/gcloud
```

今回のケースだと、/usr/bin/gcloudです。
たとえばubuntuの場合だと、[snapパッケージ](https://cloud.google.com/sdk/docs/downloads-snap?hl=ja)でインストールされている場合もあるので、その場合には今回の手順ではなく、gcloud CLI スナップ パッケージでのインストール手順に従う方が良さそうです。

### 更新手順

>始める前に
>gcloud CLI をインストールする前に、ご使用のオペレーティング システムが次の要件を満たしていることを確認してください。
```
$ sudo apt-get install apt-transport-https ca-certificates gnupg
```

> インストール
> 1 gcloud CLI の配布 URI をパッケージ ソースとして追加します。使用しているディストリビューションで signed-by オプションがサポートされている場合は、次のコマンドを実行します。
```
$ echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
```

> 2 Google Cloud の公開鍵をインポートします。使用しているディストリビューションの apt-key コマンドが --keyring 引数をサポートしている場合は、次のコマンドを実行します。
```
$ curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
```

:::note warn  
これはエラーで失敗します
> 3 gcloud CLI を更新してインストールします。
```
$ sudo apt-get update && sudo apt-get install google-cloud-cli
```
:::

:::note info　　
代わりに最初のgcloud components update失敗時に出たコマンドを実行します
```
$ sudo apt-get update && sudo apt-get --only-upgrade install google-cloud-sdk-app-engine-python-extras google-cloud-sdk-datalab google-cloud-sdk-nomos google-cloud-sdk-bigtable-emulator google-cloud-sdk-kubectl-oidc google-cloud-sdk-app-engine-go google-cloud-sdk-app-engine-grpc google-cloud-sdk-cloud-build-local google-cloud-sdk-kpt google-cloud-sdk-spanner-emulator google-cloud-sdk-skaffold google-cloud-sdk-firestore-emulator google-cloud-sdk-pubsub-emulator kubectl google-cloud-sdk-local-extract google-cloud-sdk-app-engine-java google-cloud-sdk-app-engine-python google-cloud-sdk-minikube google-cloud-sdk-datastore-emulator google-cloud-sdk google-cloud-sdk-gke-gcloud-auth-plugin google-cloud-sdk-cbt google-cloud-sdk-anthos-auth google-cloud-sdk-terraform-validator google-cloud-sdk-config-connector google-cloud-sdk-cloud-run-proxy
```
:::

しばらくの後、インストールが済むとSDKの更新が完了しています。

```
$ gcloud version
Google Cloud SDK 416.0.0
alpha 2023.01.30
beta 2023.01.30
bq 2.0.84
bundled-python3-unix 3.9.16
core 2023.01.30
gcloud-crc32c 1.0.0
gsutil 5.19
```

```
$ sudo gcloud version
Google Cloud SDK 416.0.0
alpha 2023.01.30
beta 2023.01.30
bq 2.0.84
bundled-python3-unix 3.9.16
core 2023.01.30
gcloud-crc32c 1
```

## まとめ

後からSDKを入れた端末と、最初からSDKが入っている状態の端末とで、SDKの管理のされ方が違うのは分からないこともないです。
...が、失敗時の代替コマンドでも失敗し、正しい手順らしきものも説明されていないというのは罠だなと感じます。GCEのCloud SDK更新方法について公式ではどのように取り扱うのが想定なのでしょうか。
ご存じの方がいらっしゃいましたら、情報をお寄せいただけると幸いです。