Upgrade to OpenShift  4.9 - 更新の準備 (Preparing to update)

Red Hat OpenShift Container Platform (OCP) 4.9 の Release Note に記載があるように、OCP 4.9 へ Upgrade する場合には、`更新の準備 (Preparing to update)` という特別な手順が必要です。

__Required administrator acknowledgment when upgrading from OpenShift Container Platform 4.8 to 4.9__
https://docs.openshift.com/container-platform/4.9/release_notes/ocp-4-9-release-notes.html#ocp-4-9-admin-ack-upgrading
>OpenShift Container Platform 4.8.14 introduced a requirement that an administrator must provide a manual acknowledgment before the cluster can be upgraded from OpenShift Container Platform 4.8 to 4.9. 

この手順は OCP 4.8.14 で実装された機能によるものです。
ここでは、OCP 4.8.39 環境における更新の準備 (Preparing to update) の実行例をご紹介します。
#### OCP 4.9 への Upgrade Path の確認
OCP 4.8 の環境で Upgrade Path を確認すると、`Upgradeable=False` が表示され OCP 4.9 への Upgrade ができない状態であることが分かります。
```shell
$ oc get clusterversion
NAME      VERSION   AVAILABLE   PROGRESSING   SINCE   STATUS
version   4.8.39    True        False         2d21h   Cluster version is 4.8.39

$ oc get clusterversion -o jsonpath='{.items[].spec.channel}{"\n"}'
stable-4.9

$ oc adm upgrade
Cluster version is 4.8.39

Upgradeable=False

  Reason: AdminAckRequired
  Message: Kubernetes 1.22 and therefore OpenShift 4.9 remove several APIs which require admin consideration. Please see the knowledge article https://access.redhat.com/articles/6329921 for details and instructions.


Updates:

VERSION IMAGE
4.9.31  quay.io/openshift-release-dev/ocp-release@sha256:2a28b8ebb53d67dd80594421c39e36d9896b1e65cb54af81fbb86ea9ac3bf2d7
```
OCP Console では、以下のように表示されます。
![pic1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128125/8ad20873-3575-6e5f-78ce-aa386a2ae585.png)

この状態で `oc adm upgrade` コマンドによる Upgrade を実行しても、処理は開始されません。
```shell
$ oc adm upgrade --to=4.9.31
Cluster version is 4.8.39

Upgradeable=False

  Reason: AdminAckRequired
  Message: Kubernetes 1.22 and therefore OpenShift 4.9 remove several APIs which require admin consideration. Please see the knowledge article https://access.redhat.com/articles/6329921 for details and instructions.


Updates:

VERSION IMAGE
4.9.31  quay.io/openshift-release-dev/ocp-release@sha256:2a28b8ebb53d67dd80594421c39e36d9896b1e65cb54af81fbb86ea9ac3bf2d7
```
OCP Console でも同様に、`Update` ボタンを押しても、処理は開始されません。
![pic2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128125/c70deb65-3f7e-051c-120d-5a426a2aef16.png)

#### 更新の準備 - Preparing to update to OpenShift Container Platform 4.9
先述の Release Note の内容に従って、更新の準備 (Preparing to update) をしてみます。これに関する記載は少なくとも以下の2箇所にありますが、ここでは公式ドキュメントの方を参考にしてみます。
- 公式ドキュメント
__Preparing to update to OpenShift Container Platform 4.9__
https://docs.openshift.com/container-platform/4.9/updating/updating-cluster-prepare.html#updating-cluster-prepare
- Knowledgebase
__Preparing to upgrade to OpenShift Container Platform 4.9__
https://access.redhat.com/articles/6329921
##### Reviewing alerts to identify uses of removed APIs
ドキュメントに記載されている `APIRemovedInNextReleaseInUse` と `APIRemovedInNextEUSReleaseInUse` の状況を確認してみます。まずは、発報 (Fire) された Alert を確認します。 
```shell
$ ALERT_MANAGER=$(oc get route alertmanager-main -n openshift-monitoring -o jsonpath='{@.spec.host}')
$ SA=$(oc sa get-token prometheus-k8s -n openshift-monitoring)
$ curl -skH "Authorization: Bearer $SA" https://$ALERT_MANAGER/api/v1/alerts | jq -r '.data[].labels.alertname' | sort | uniq -c
      1 AlertmanagerClusterFailedToSendAlerts
      3 AlertmanagerFailedToSendAlerts
      1 APIRemovedInNextEUSReleaseInUse
      1 APIRemovedInNextReleaseInUse
      1 ClusterNotUpgradeable
      1 ElasticsearchClusterNotHealthy
      1 KubeJobCompletion
      2 KubeJobFailed
      1 TargetDown
      1 UpdateAvailable
      1 Watchdog
```
`APIRemovedInNextReleaseInUse` と `APIRemovedInNextEUSReleaseInUse` の詳細を確認してみます。
```shell
$ A1=APIRemovedInNextReleaseInUse
$ A2=APIRemovedInNextEUSReleaseInUse
$ curl -skH "Authorization: Bearer $SA" https://$ALERT_MANAGER/api/v1/alerts | jq -r --arg A1 $A1 --arg A2 $A2 '.data[] | .labels.alertname as $L | select($L == $A1 or $L == $A2) | .labels ,.annotations'
{
  "alertname": "APIRemovedInNextReleaseInUse",
  "group": "networking.k8s.io",
  "prometheus": "openshift-monitoring/k8s",
  "resource": "ingresses",
  "severity": "info",
  "version": "v1beta1"
}
{
  "message": "Deprecated API that will be removed in the next version is being used. Removing the workload that is using the networking.k8s.io.v1beta1/ingresses API might be necessary for a successful upgrade to the next cluster version. Refer to `oc get apirequestcounts ingresses.v1beta1.networking.k8s.io -o yaml` to identify the workload."
}
{
  "alertname": "APIRemovedInNextEUSReleaseInUse",
  "group": "networking.k8s.io",
  "prometheus": "openshift-monitoring/k8s",
  "resource": "ingresses",
  "severity": "info",
  "version": "v1beta1"
}
{
  "message": "Deprecated API that will be removed in the next EUS version is being used. Removing the workload that is using the networking.k8s.io.v1beta1/ingresses API might be necessary for a successful upgrade to the next EUS cluster version. Refer to `oc get apirequestcounts ingresses.v1beta1.networking.k8s.io -o yaml` to identify the workload."
}
```
##### Using APIRequestCount to identify uses of removed APIs
ドキュメントに記載されている `oc get apirequestcounts` コマンドで、API Request Count を確認してみます。
```shell
$ oc get apirequestcounts -o jsonpath='{range .items[?(@.status.removedInRelease!="")]}{.status.removedInRelease}{"\t"}{.metadata.name}{"\n"}{end}'
1.22    certificatesigningrequests.v1beta1.certificates.k8s.io
1.22    customresourcedefinitions.v1beta1.apiextensions.k8s.io
1.21    flowschemas.v1alpha1.flowcontrol.apiserver.k8s.io
1.22    ingresses.v1beta1.extensions
1.22    ingresses.v1beta1.networking.k8s.io
1.22    validatingwebhookconfigurations.v1beta1.admissionregistration.k8s.io

$ oc get apirequestcounts | awk '$2 ~ /^1\.2[12]$/ || $2 == "REMOVEDINRELEASE"'
NAME                                                                           REMOVEDINRELEASE   REQUESTSINCURRENTHOUR   REQUESTSINLAST24H
certificatesigningrequests.v1beta1.certificates.k8s.io                         1.22               0                       0
customresourcedefinitions.v1beta1.apiextensions.k8s.io                         1.22               0                       0
flowschemas.v1alpha1.flowcontrol.apiserver.k8s.io                              1.21               0                       0
ingresses.v1beta1.extensions                                                   1.22               14                      363
ingresses.v1beta1.networking.k8s.io                                            1.22               6                       180
validatingwebhookconfigurations.v1beta1.admissionregistration.k8s.io           1.22               0                       0
```
上記から、`ingresses.v1beta1.extensions` と `ingresses.v1beta1.networking.k8s.io` が使用されている (= API Request Count が 0 ではない) 事が分かります。
##### Using APIRequestCount to identify which workloads are using the removed APIs
ドキュメントに記載されている方法で、対象 API Request の使用者を確認してみます。
※ Linux Distribution によっては、`column` コマンドのオプションが異なる可能性があるようです。
```shell
$ oc get apirequestcounts ingresses.v1beta1.networking.k8s.io -o jsonpath='{range .status.currentHour..byUser[*]}{..byVerb[*].verb}{","}{.username}{","}{.userAgent}{"\n"}{end}' | sort -k 2 -t, -u | column -t -s,
watch  system:serviceaccount:cert-manager:cert-manager  controller/v0.0.0

$ oc get apirequestcounts ingresses.v1beta1.extensions -o jsonpath='{range .status.currentHour..byUser[*]}{..byVerb[*].verb}{","}{.username}{","}{.userAgent}{"\n"}{end}' | sort -k 2 -t, -u | column -t -s,
watch  system:kube-controller-manager  cluster-policy-controller/v0.0.0
watch  system:kube-controller-manager  kube-controller-manager/v1.21.8+ed4d8fd
```
これによって、`ingresses.v1beta1.networking.k8s.` と `ingresses.v1beta1.extensions` の使用者に関する UserName、Verb、UserAgent が分かります。これらについて OCP 4.9 の Upgrade に対応するための処置を行うことになります。なお、公式ドキュメントの記載にあるように `system:kube-controller-manager` は無視をして問題ないため、ここでは `system:serviceaccount:cert-manager:cert-manager` のみが処置の対象になります。
##### Providing the administrator acknowledgment
OCP 4.9 の Upgrade に対応するための処置が完了した後、`管理者の確認 (Administrator Acknowledgment)`   を設定することで、OCP 4.9 への Upgrade が可能になります。
`Administrator Acknowledgment` は以下に設定しますが、初期値はありません。
```shell
$ oc get cm admin-acks -n openshift-config
NAME         DATA   AGE
admin-acks   0      3d4h

$ oc -o json get cm admin-acks -n openshift-config | jq -r '.data'
null
```
以下のコマンドで、`Administrator Acknowledgment` を設定します。
```shell
$ oc -n openshift-config patch cm admin-acks --patch '{"data":{"ack-4.8-kube-1.22-api-removals-in-4.9":"true"}}' --type=merge
configmap/admin-acks patched

$ oc get cm admin-acks -n openshift-config
NAME         DATA   AGE
admin-acks   1      3d4h

$ oc -o json get cm admin-acks -n openshift-config | jq -r '.data'
{
  "ack-4.8-kube-1.22-api-removals-in-4.9": "true"
}
```
`Administrator Acknowledgment` 設定後、`oc adm upgrade` コマンドを実行すると `Upgradeable=False` のメッセージが表示されなくなります。
```shell
oc adm upgrade
Cluster version is 4.8.39

Updates:

VERSION IMAGE
4.9.31  quay.io/openshift-release-dev/ocp-release@sha256:2a28b8ebb53d67dd80594421c39e36d9896b1e65cb54af81fbb86ea9ac3bf2d7
```
同様に、OCP Console でもメッセージが表示されなくなります。
![pic3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128125/a6c7aa74-7bb8-09fe-47b3-e127908a2069.png)
これで更新の準備 (Preparing to update) が完了となり、OCP 4.9 への Upgrade が可能となります。