AKSのワーカノードのノードプールにVMSSをつかっていて、
本番環境のノードイメージが先に新しくなって問題が起きる事件が2回くらいあったので自動更新をステージングだけにしようかという話に。
https://learn.microsoft.com/ja-jp/azure/aks/planned-maintenance
https://learn.microsoft.com/ja-jp/azure/aks/auto-upgrade-cluster
terraformで環境毎のパラメータを変数にして管理していて、リソースは共通で書いてるので、リソース内部に差分を出す書き方をしないといけなかった(dynamicで解決。countやfor_eachではリソース毎になり細かいブロックの差を出せない)
resource "azurerm_kubernetes_cluster" "app" {
name = "${var.system_prefix}-${var.region_prefix}-cluster-aks"
location = azurerm_resource_group.all.location
resource_group_name = azurerm_resource_group.all.name
dns_prefix = "${var.system_prefix}-${var.region_prefix}-cluster-aks"
kubernetes_version = var.aks_app_version
automatic_channel_upgrade = try(var.automatic_channel_upgrade, null)
dynamic "maintenance_window" {
for_each = try(var.maintenance_window, null) == null ? [] : [1]
content {
dynamic "allowed" {
for_each = var.maintenance_window.allowed == null ? [] : [1]
content {
day = var.maintenance_window.allowed.day
hours = var.maintenance_window.allowed.hours
}
}
}
}
要はnullを返すようにとdynamicブロックの利用で解決。
もう少し細かい話だと、
tryで変数値がなかったらnullを返していて、
dynamic内のfor_eachではcountでやるように値がnullかそうでないかの条件分岐みたいな感じで変数が無かったら配列やらマップやらを渡さない動きになる模様。環境によって設定自体が要らないようなケースでこの書き方をするしかないことに。
resource "azurerm_frontdoor" "stg" {
count = var.env == "stg" ? 1 : 0
name = "${var.env}${var.system_prefix}-${var.region_prefix}-fd"
location = "global"
~略~
変数側↓
automatic_channel_upgrade = "node-image"
maintenance_window = {
allowed = {
day = "Friday"
hours = ["1","2","3","4","5","6","7"]
}
["1","3"]という指定だと日本時間の10時台と12時台だけ発動するんだと思われる。
変数スキーマ↓
variable "automatic_channel_upgrade" {
default = ""
}
variable "maintenance_window" {
default = {
allowed = {
day = ""
hours = []
}
}
}
参考
https://github.com/aztfmod/terraform-azurerm-caf/blob/main/modules/compute/aks/aks.tf#L267
https://qiita.com/minamijoyo/items/3a7467f70d145ac03324#try
https://qiita.com/minamijoyo/items/3a7467f70d145ac03324#dynamic-blocks
- ノードイメージの手動更新方法
ステージングと同じバージョンにしないと自動と変わらない話になるのでどうにかなりませんかとサポートに聞いてみたところ
→特定のバージョンを指定してノードイメージを更新することはできないと回答あり。
ただし、現状上げられる最新バージョンの確認は可能だし現在のバージョンの確認も可能
なので、STGのバージョンと現在上げられるバージョンが同じだった場合に更新する方向にする手動オペレーションに。
上げられる最新バージョンの確認コマンドは以下
rg=<リソースグループ名>
aksname=<AKSクラスタ名>
subscription=<サブスクリプションID>
nodepool=<ノードプール名>
az account set --subscription $subscription
az aks nodepool get-upgrades \
--nodepool-name ${nodepool} \
--cluster-name ${aksname} \
--resource-group ${rg}
現在のノードイメージバージョンはノードプールのノードの一覧から、またはkubectl get nodes -o wide
などで確認できる
イメージ更新コマンドはケースによるようですがとりあえず以下でよさそう
https://learn.microsoft.com/ja-jp/azure/aks/planned-maintenance
az aks upgrade \
--resource-group myResourceGroup \
--name myAKSCluster \
--node-image-only
更新をトリガーされると終わるまで止まらない(kuredだと中途半端に止まったりしていたので公式に寄せた経緯がある)がPodDusruptionBudget(クラスタ上に最低限起動させておきたいPod数をDeployment単位で指定する等の定義)の影響でサスペンドされたりすることは自動の場合でもありました(設定の問題というよりはNWやノードの調子がアレとかのほかとの複合という感じ)。
イメージ更新された履歴をたどりたい場合は以下のKustoクエリで取れる
AzureActivity
| where OperationNameValue contains "REIMAGE/ACTION"
ステージング環境の現在のバージョンと本番環境の上げられる最新が一致してなければ見送りとかをスクリプト組んでやってもいい気はするけど、タイミングによっては延々見送りになりかねなかったりしそうというか。
クラスタのパッチバージョンだけでなくノードイメージのバージョン指定もさせてくれないかなーという気持ちです。(VMSSとしてならできてもAKS越しだからという話だったりはしそうで、ただVMSSとしていじりまわすとAKSの管理から外れそうでやめといたほうがよさそうなので公式的になんとかしてくれないかなという気持ち)
以上