AKS と Key Vault を AZ CLI でサービス接続した直後に、オペレーター Pod が scaksextension.azurecr.io/prod/image/sc-operator:20250417.1 を取得できず起動しない――最近複数環境で同時多発的に起きたこの事象は、Service Connector の AKS 拡張(microsoft.servicelinker.connection)が古いことが原因でした。更新(または削除して再作成)で即復旧できます。以下に仕組みと再発防止までを詳説します。
現象と前提
AZ CLI の az aks connection create keyvault を実行して AKS クラスターと Azure Key Vault のサービス接続を構成したところ、以下のようにオペレーター Pod がイメージを取得できず ErrImagePull / ImagePullBackOff で停止します。
Failed to pull image "scaksextension.azurecr.io/prod/image/sc-operator:20250417.1":
rpc error: code = Unknown desc = Error response from daemon: manifest unknown / unauthorized
Back-off pulling image "scaksextension.azurecr.io/prod/image/sc-operator:20250417.1"
- 以前は同じ手順で問題なし。
- 複数の AKS クラスタ/リソースグループで同時期に再現。
- Key Vault 側のポリシーや RBAC を変更していない。
結論(先に要点)
原因は AKS にインストールされた Service Connector 拡張(microsoft.servicelinker.connection)のバージョンが古いことです。拡張が参照するコンテナイメージや取得方法に更新が入り、古い拡張だと最新のレジストリ状態に追随できず、イメージ取得が失敗する場合があります。対応はシンプルで、拡張を最新へ更新、もしくは削除して再作成します。
背景:Service Connector(旧 Service Linker)と sc‑operator の役割
az aks connection create keyvault は、AKS 上に Service Connector のコントロールプレーン(オペレーター)を拡張として導入し、対象ワークロードに Key Vault への接続情報(Secret、マウント、環境変数注入など)を安全に供給します。この拡張の実体は、microsoft.servicelinker.connection という AKS 拡張で、内部で sc-operator というコンポーネントを Pod として起動します。
このオペレーターは Microsoft 管理のレジストリ(例:scaksextension.azurecr.io)からイメージを取得します。レジストリ側のタグや署名、配布方法、匿名 Pull 設定、証明書チェーンなどに変更が入ることがあり、古い拡張が新しい前提に対応していないとイメージの取得が失敗します。
症状のバリエーション(ログ例)
ErrImagePull/ImagePullBackOffmanifest unknown/requested access to the resource is denied- ネットワーク制限が厳しい環境では
i/o timeoutやtls handshake timeout
# 代表的な確認コマンド
kubectl -n kube-system get pods -l app=sc-operator -o wide
kubectl -n kube-system describe pod <sc-operator-pod名> | sed -n '/Events/,$p'
kubectl get events -A --field-selector reason=Failed
最短で復旧する手順
以下のとおり、まず拡張を特定し、状態が良ければ更新、ダメなら削除→再作成します。
| 手順 | コマンド例 | 補足 |
|---|---|---|
| 拡張機能一覧を確認 | az k8s-extension list \ --cluster-name <CLUSTER> \ --resource-group <RG> \ --cluster-type managedClusters | extensionType が microsoft.servicelinker.connection のものを特定 |
| 更新(正常状態なら) | az k8s-extension update \ --name <EXT_NAME> \ --cluster-name <CLUSTER> \ --resource-group <RG> \ --cluster-type managedClusters | 更新だけで多くの環境は復旧 |
| 削除 → 再作成(エラー状態時) | # 削除 az k8s-extension delete \ --name <EXT_NAME> \ --cluster-name <CLUSTER> \ --resource-group <RG> \ --cluster-type managedClusters \ --yes # 再作成(例:Key Vault 連携) az aks connection create keyvault --name --resource-group --cluster-name --keyvault | 拡張が壊れて更新できない場合の確実策 |
| 動作確認 | kubectl -n kube-system get pods kubectl -n kube-system logs deploy/sc-operator --tail=100 | オペレーターが稼働し、対象ワークロードが Key Vault を参照できることを確認 |
詳細な診断手順(原因切り分け)
1. AKS 拡張の特定と状態確認
# すべての拡張を一覧
az k8s-extension list \
--cluster-name <CLUSTER> \
--resource-group <RG> \
--cluster-type managedClusters
# 個別拡張の詳細(バージョン、状態、リリーストレイン等)
az k8s-extension show
--name
--cluster-name
--resource-group
--cluster-type managedClusters | jq '.provisioningState, .type, .version, .autoUpgradeMinorVersion'
- ProvisioningState が
Succeeded以外なら更新または再作成が有効。 - version が古い/autoUpgradeMinorVersion が
falseなら更新推奨。
2. Pod レベルの事象確認
# sc-operator の Deployment/POD を探す(kube-system で稼働することが多い)
kubectl -n kube-system get deploy,rs,pods -l app=sc-operator -o wide
# イベントで ImagePull 系の失敗理由を収集
kubectl -n kube-system describe pod | sed -n '/Events/,$p'
ここで manifest unknown や unauthorized が出る場合、レジストリのタグ/署名/アクセス条件の更新に拡張が追随できていない公算が高いです。
3. ネットワークと名前解決
- Outbound を制限している場合、FQDN
scaksextension.azurecr.ioへの 443/TCP を許可。 - HTTP プロキシや TLS インスペクションがある場合、Microsoft 管理レジストリの証明書ピンニング/署名検証を阻害していないか確認。
- Private DNS ゾーンの上書きで
*.azurecr.ioが誤解決していないか確認。
4. ノード状態・コンテナランタイム
- ノードの時刻ずれ(NTP)により TLS ハンドシェイクが失敗するケース。
- コンテナランタイムのディスク枯渇(
/var/lib/containerd)。 - 大量再試行によるエフェメラルポート枯渇。
対処:拡張の更新/再作成
更新(最優先の簡易手当)
az k8s-extension update \
--name <EXT_NAME> \
--cluster-name <CLUSTER> \
--resource-group <RG> \
--cluster-type managedClusters
# ついでに自動マイナー更新を有効化(再発予防)
az k8s-extension update
--name
--cluster-name
--resource-group
--cluster-type managedClusters
--auto-upgrade-minor-version true
更新後は、Deployment の新しい ReplicaSet がローリングし、イメージの取得が成功して Pod が Running になることを確認します。
削除 → 再作成(壊れた状態をリセット)
# 削除
az k8s-extension delete \
--name <EXT_NAME> \
--cluster-name <CLUSTER> \
--resource-group <RG> \
--cluster-type managedClusters \
--yes
# 再作成(Key Vault 接続の例)
az aks connection create keyvault
--name
--resource-group
--cluster-name
--keyvault
この再作成手順により、拡張設定・Secret・ServiceAccount・CRD などが最新の期待状態で再配置され、sc-operator が新しいイメージを正しく取得できるようになります。
検証ポイント
kubectl -n kube-system get pods -l app=sc-operatorが Running。- 該当ワークロードが Key Vault から Secret を取得できる(アプリの起動ログ/実機テスト)。
- イベントに
BackOff等が残っていない。
再発防止のベストプラクティス
- 自動マイナー更新の有効化:
--auto-upgrade-minor-version trueを設定。 - CI/CD に前段タスクを追加:デプロイ前に毎回
az k8s-extension updateを実行。 - リング展開:検証クラスタ → 準本番 → 本番の順で拡張を更新し、影響を段階吸収。
- ネットワークの FQDN 許可:
*.azurecr.ioをアウトバウンド許可。Azure Firewall/プロキシのルールも明示。 - 監視:
ImagePullBackOffをシグナルにしたアラート(kube_pod_container_status_waiting_reason等)を構成。 - ノード健全性:ディスク・時刻・プロキシ設定のドリフト検出を自動化。
環境によって追加で点検したいこと
| 観点 | 確認ポイント | 対処のヒント |
|---|---|---|
| 権限(AcrPull) | 自社 ACR からの Pull が必要なワークロードが同居しているか | ノード MI / Kubelet MI に AcrPull を付与、imagePullSecrets を整備 |
| ネットワーク | UDR/Firewall/Proxy 下で scaksextension.azurecr.io へ到達できるか | 443/TCP と名前解決を許可、TLS インスペクションの例外設定 |
| コンテナランタイム | containerd のディスク容量、キャッシュ破損 | 古いイメージのクリーンアップ、ノードの再起動計画 |
| 時間同期 | ノードの NTP ずれ | AKS 既定 NTP か企業内 NTP に統一、アラート化 |
よくある質問(FAQ)
Q. ローカルの AZ CLI 拡張(例:serviceconnector-passwordless や aks-preview)も更新すべき?
A. 今回の直接原因は AKS 側の拡張ですが、運用上はローカルの CLI 本体と拡張も最新を維持する方が安全です。バグ修正や最新 API 追随の恩恵が得られます。
Q. 拡張を削除したら既存の接続は壊れますか?
A. 拡張の削除中はオペレーターが不在になるため、新規作成や同期が停止します。再作成直後に復旧します。影響が許容できない本番はメンテナンス時間で実施してください。
Q. それでも ImagePullBackOff が消えません。
A. ネットワーク/プロキシ/DNS/TLS 検査などの外的要因を疑い、curl と nslookup を Pod 内から実行して疎通を確認してください。証明書検証に失敗している場合はセキュリティ機器の例外設定が必要です。
Q. イメージタグ 20250417.1 固定は推奨?
A. 固定は再現性を高める一方、公開レジストリ側の変更に追随できず逆効果になることがあります。Service Connector 拡張の更新で追随する方が安定的です。
現場で使えるコマンド集(コピペ用)
# 1) どの拡張が入っているか
az k8s-extension list \
--cluster-name <CLUSTER> \
--resource-group <RG> \
--cluster-type managedClusters | jq -r '.[] | [.name,.extensionType,.provisioningState] | @tsv'
# 2) Service Connector 拡張だけ抽出
az k8s-extension list
--cluster-name
--resource-group
--cluster-type managedClusters
--query "[?extensionType=='microsoft.servicelinker.connection']"
# 3) バージョンと自動更新設定
az k8s-extension show
--name
--cluster-name
--resource-group
--cluster-type managedClusters
--query "{state:provisioningState,version:version,auto:autoUpgradeMinorVersion}"
# 4) 更新(安全)
az k8s-extension update
--name
--cluster-name
--resource-group
--cluster-type managedClusters
# 5) 自動マイナー更新を有効化
az k8s-extension update
--name
--cluster-name
--resource-group
--cluster-type managedClusters
--auto-upgrade-minor-version true
# 6) 削除(壊れて更新できないとき)
az k8s-extension delete
--name
--cluster-name
--resource-group
--cluster-type managedClusters
--yes
# 7) Key Vault 接続の再作成
az aks connection create keyvault
--name
--resource-group
--cluster-name
--keyvault
# 8) Pod 監視
kubectl -n kube-system get pods -l app=sc-operator -w
# 9) 代表的な失敗イベントの抽出
kubectl get events -A --field-selector reason=Failed,reason=BackOff | tail -n 50
チェックリスト(復旧と予防)
| 項目 | 確認内容 | 状態 |
|---|---|---|
| 拡張の更新 | microsoft.servicelinker.connection が最新 | □ 済 / □ 未 |
| 自動更新 | autoUpgradeMinorVersion が true | □ 済 / □ 未 |
| ネットワーク | scaksextension.azurecr.io:443 に到達可能 | □ 済 / □ 未 |
| 監視 | ImagePullBackOff のアラート化 | □ 済 / □ 未 |
| ノード健全性 | ディスク・時刻・プロキシ設定の定期点検 | □ 済 / □ 未 |
フローチャート(思考プロセスの型)
- 症状の観測:ImagePullBackOff / ErrImagePull を確認。
- 拡張の把握:
az k8s-extension list→ Service Connector 拡張の状態・バージョン確認。 - 即時対応:
az k8s-extension update。ダメならdelete→create keyvault。 - Pod 健全性:
kubectl describeでイベント精査、Running になるか確認。 - 外的要因:ネットワーク/DNS/TLS/ランタイムの健全性を点検。
- 再発防止:自動更新・CI/CD 前段タスク・監視・リング展開。
まとめ
AKS と Key Vault のサービス接続で sc-operator のイメージ取得が突然失敗した場合、まず疑うべきは AKS 拡張のバージョン遅延です。microsoft.servicelinker.connection を更新(または削除して再作成)すれば、ほとんどのケースで即時復旧します。あわせて、autoUpgradeMinorVersion の有効化や CI/CD での前段更新、FQDN 許可、監視の整備までをセットで導入することで、将来のレジストリ側変更にも強い運用になります。本記事のコマンド群とチェックリストをテンプレート化し、全クラスタで横展開することをおすすめします。
付録:トラブルの根本原因が拡張の古さに収斂する理由(考察)
Microsoft 管理レジストリの公開条件・タグ付与方針・署名や SBOM 配布の方式は随時アップデートされます。古い拡張は、新しいレジストリ前提(例:匿名 Pull の制限、タグの再編、レイヤ署名の強化、証明書チェーン更新、マニフェストスキーマの更新)に追随できません。結果として manifest unknown や unauthorized が発生します。拡張を最新化すると、Deployment の定義、imagePullSecrets の取り扱い、イメージ参照タグ/ダイジェストが更新され、レジストリの最新仕様に整合します。
付録:安全に本番へ適用するための運用の型
- 検証クラスタで拡張を更新 → 24 時間観測。
- 準本番で適用 → 主要ワークロードの e2e テスト実施。
- 本番へ段階的ローリング。ロールバックは「削除→直前バージョンで再作成」。
- 変更管理:拡張の
versionと変更理由、検証結果を記録。
付録:失敗をゼロに近づけるための観測項目
- Pod の待機理由別件数(Waiting Reason 別の時系列)
- レジストリ FQDN への egress レイテンシ・失敗率
- ノードディスク消費率(
/var/lib/containerd・/var/lib/kubelet) - 時刻同期ドリフト(閾値 2〜5 秒)
付録:代表的な誤設定パターンと対策
| 誤設定 | 症状 | 対策 |
|---|---|---|
| プロキシの TLS インスペクションが有効 | 握手タイムアウト、証明書検証エラー | レジストリ FQDN を除外し、SNI ベースの例外を追加 |
DNS で *.azurecr.io を社内 A レコードに固定 | 誤 IP へ向き、タイムアウト | Private DNS の適用範囲を精査、外部解決を許可 |
| ノードディスク逼迫 | イメージ展開に失敗、Pod が CrashLoop | 古いイメージの GC、ノードプールの SKU/OS ディスク再設計 |
本記事の要点(一行まとめ)
sc-operator のイメージ取得エラーは、まず「Service Connector の AKS 拡張を最新化」で解決。

コメント