KubeEdgeエッジノード障害対応ガイド

KubeEdgeエッジノード障害対応ガイド

1. 背景

最近のプロジェクトでプログラムを運用する過程において、「kubectl get nodes」で「NotReady」状態になっていたり、「kubectl exec」が応答しなくなったり、Podが突然Evicted状態に変わったりするなど、さまざまな問題に遭遇しました。そこで、実際の運用中に遭遇した4種類の障害に基づき、事例を中心としたKubeEdge環境での問題対応ガイドを以下のようにまとめます。

2. はじめに

Kubernetesベースの一般的なクラスターとは異なり、KubeEdgeにはクラウドとエッジノードの間に CloudCore ↔ EdgeCore トンネルが追加で存在します。そのおかげで、ネットワークが不安定な現場環境でもエッジノードを運用できますが、同時に障害の原因もさらに複雑になります。

3. 障害の種類

障害の種類1

kubectl execの失敗 — "unexpected EOF"

(1) 症状

$ kubectl exec -it my-app-6jf2m -n iot-edge -- /bin/bash
error: Internal error occurred: error sending request:
Post "https://192.168.1.3:10351/exec/...": unexpected EOF

「kubectl exec」を実行したところ、接続自体が切断され、何もできない状況です。同じノード上にある別のPodはRunning状態に見えるのに、execだけが動作しない場合もあります。

(2) 原因分析

KubeEdgeで「kubectl exec」を動作させるには、 EdgeStream機能が有効になっている必要があります。この機能が無効になっていると、API Server → CloudCore → EdgeCoreへと続くexecトンネル自体が確立されません。

一般的なKubernetesでは、API Serverがkubeletの10250ポートに直接アクセスしてexecを処理しますが、KubeEdgeにはこの経路がありません。EdgeStreamがなければ、exec、logs、port-forwardはすべて動作しません。

[kubectl exec flow in KubeEdge]
API Server
    ↓
CloudCore (streamPort: 10003)
    ↓ ← without this tunnel, unexpected EOF occurs
EdgeCore (edgeStream.server)
    ↓
컨테이너

(3) 解決方法

CloudCoreの設定確認および有効化:

# cloudcore.yaml
cloudStream:
  enable: true
  streamPort: 10003
  tlsTunnelCAFile: /etc/kubeedge/ca/rootCA.crt
  tlsTunnelCertFile: /etc/kubeedge/certs/server.crt
  tlsTunnelPrivateKeyFile: /etc/kubeedge/certs/server.key

EdgeCoreの設定確認および有効化:

# edgecore.yaml
edgeStream:
  enable: true
  handshakeTimeout: 30
  readDeadline: 15
  server: <CloudCore_IP>:10004
  tlsTunnelCAFile: /etc/kubeedge/ca/rootCA.crt
  tlsTunnelCertFile: /etc/kubeedge/certs/server.crt
  tlsTunnelPrivateKeyFile: /etc/kubeedge/certs/server.key
  writeDeadline: 15

設定変更後は、両方を再起動する必要があります:

# On the master node where CloudCore is running
systemctl restart cloudcore.

# On the edge node
systemctl restart edgecore

障害の種類2

DiskPressureによるPod Eviction

(1) 症状

$ kubectl get po -A -o wide | grep <NodeName>
iot-edge chronograf-xxxxx 0/1 Evicted 0 2m
iot-edge influxdb-xxxxx 0/1 Evicted 0 9m
iot-edge my-app-xxxxx 0/1 Evicted 0 14m

特定のノード上にあるPodが一斉にEvicted状態になります。1つや2つではなく、そのノード上のすべてのPodが退去させられる場合は、ノードレベルのリソース問題を疑う必要があります。

(2) 原因分析

Evictionは、kubelet(KubeEdgeではedgecore)がノードのリソース不足を検知した際に、Podを強制終了するメカニズムです。「kubectl describe node」で直接原因を確認できます:

kubectl describe node <NodeName> | grep -A5 "Conditions"

実際の事例では、以下のようなメッセージが表示されました:

DiskPressure True ...
Message: The node was low on resource: ephemeral-storage.
  Threshold: 37556267476 (~35GB)
  Available: 36674584Ki (~34.9GB)

空きディスク容量がしきい値を下回ると、kubeletがそのノードのPodを強制的に退去させます

ディスク使用量の確認
エッジノードにSSH接続し、どこでディスクを消費しているのかを確認します:

df -h
du -sh /* 2>/dev/null | sort -rh | head -15

実際の事例では、特定のアプリケーションのログディレクトリ1つが、ディスク全体の89%を占有していました。

$ du -sh /var/app/logs/*/
166G /var/app/logs/device-001.ASSET/

(3) 解決方法

古いログの整理(削除前に保存が必要かどうかを必ず確認してください!)

# Delete files older than N days
find /var/app/logs -mtime +7 -type f -delete

使用していないコンテナイメージの整理

crictl rmi --prune

edgecoreを再起動してDiskPressureを再評価

systemctl restart edgecore

Evicted Podの整理および再デプロイ

# On the master node
kubectl get pods -A | grep Evicted | awk '{print "kubectl delete pod " $2 " -n " $1}' | sh

障害の種類3

Init Container ImagePullBackOff — DNS障害

(1) 症状

$ kubectl describe pod my-app-qn6r8 -n iot-edge
Init Containers:
  init-snapshot:
    State: Waiting
      Reason: ImagePullBackOff
    Image: registry.company.internal:5000/infra/busybox:latest

メインコンテナではなく、Init ContainerでイメージのPullに失敗する場合です。Init Containerが失敗すると、メインコンテナは起動すらしません。

この場合、メインコンテナの以前の終了状態を確認すると、以下のように表示されます:

Last State: Terminated
  Reason: Unknown
  Exit Code: 255

Exit Code 255は、コンテナランタイムがプロセスを強制終了したことを意味し、多くの場合、ノードレベルの問題(以前のDiskPressure、ネットワーク切断など)による結果です。

(2) 原因分析 — プライベートレジストリのDNS障害

ImagePullBackOffの原因はさまざまですが、社内のプライベートレジストリを使用するIoT環境では、 DNS障害が特に頻繁に発生します。

確認方法:

# On the edge node
nslookup registry.company.internal

DNS SERVFAILが表示される場合、ドメイン自体を名前解決できていない状態です。

server can't find registry.company.internal: SERVFAIL

(3) 解決方法

迅速な一時対応 — /etc/hosts への登録
別の正常なノードでIPアドレスを確認した後、「/etc/hosts」に直接登録します。

# Resolve IP from a healthy node
nslookup registry.company.internal
# Add entry to /etc/hosts on the affected node
echo "<IP> registry.company.internal" >> /etc/hosts
# Test image pull
crictl pull registry.company.internal:5000/infra/busybox:latest

DNSの根本原因を解決

一時対応後、「systemd-resolved」の状態を確認して再起動します。

systemctl status systemd-resolved
systemctl restart systemd-resolved

# Verify DNS resolution is restored
nslookup registry.company.internal

DNS復旧後のPod再起動

# Force delete and recreate the Pod from the master node
kubectl delete pod my-app-qn6r8 -n iot-edge --force --grace-period=0

# Watch Pod status
kubectl get pod -n iot-edge -w | grep my-app

4. まとめ

- 「kubectl exec」が実行できない場合、kubeletの問題ではなく、EdgeStreamの設定に問題がある可能性がある。

- Podが大量にEvictedになる場合は、まずノードのディスク使用量を確認する。

- ImagePullBackOffはイメージの問題ではなく、DNS障害が原因である可能性がある。

エッジ環境には、データセンターとは異なり、現場ネットワークの不安定さ、限られたディスク容量、多数の分散ノードの管理という複合的な課題があります。上記のチェックリストをチーム内で共有しておけば、誰がオンコールを担当していても対応時間を短縮できます。

Jsia

Site footer