0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

#11. Ubuntuの無人Edge端末を24/365で安定稼働させる ― systemd timerで定期メンテナンスと自己復旧を設計する

0
Posted at

はじめに

Ubuntuを搭載したEdge PCを24時間365日、無人で運用する場合、

OSが起動する
Dockerが起動する
Applicationが起動する
Cloudへ接続できる

だけでは十分ではありません。

実際の長期運用では、

時刻がずれる
DNSの状態が変わる
Routeが戻らない
Firewall / NATの状態が崩れる
NICが正常に復帰しない
Update後にRebootが必要になる
Container Runtimeの状態が変わる
電源断後に一部だけ正常に戻らない

といった問題も考える必要があります。

そこで今回のEdge PCでは、

異常を一度も発生させないことを目指すのではなく、異常が発生しても正常状態へ戻りやすい構成にする

という方針にしました。

その中心として使用したのが、

systemd service
systemd timer

です。

この記事では、Ubuntu Edge PCを24/365で無人運用するために実際に採用した、

  • 定期Maintenance
  • 処理時間の分散
  • 定期Reboot
  • Boot後の自己復旧
  • NTP / DNS / Route / NAT / Firewall確認
  • UpdateとRebootの分離
  • NIC復旧
  • systemd timerの監視
  • 外部監視との役割分担

について整理します。


結論:無人Edge端末は「壊れない」より「戻れる」ようにする

今回の構成を先にまとめると、

① 壊れにくくする
    ↓
② 壊れたら正常状態へ戻す
    ↓
③ 戻せなければ外部から検知する

という3段階です。

具体的には、

予防
├─ Version管理
├─ Security Update
├─ 定期Maintenance
└─ Maintenance時間の分散

自己復旧
├─ 定刻Reboot
├─ Boot後のRoute確認
├─ Firewall / NAT確認
├─ DNS確認
├─ NTP同期
├─ NIC復帰
└─ 必要時Reboot

外部検知
├─ Ping
├─ Heartbeat
├─ Telemetry
├─ rsyslog
└─ netconsole

という構成にしました。

ポイントは、

一つの強力な仕組みで安定させようとしない

ことです。


1. 「正常に起動した」だけでは24/365運用にならない

開発時には、

Power ON
↓
Ubuntu起動
↓
Docker起動
↓
Azure IoT Edge起動
↓
Application起動
↓
Cloud接続

まで確認できれば、正常に見えます。

しかし、無人運用で重要なのはその瞬間ではありません。

1日後
1週間後
1か月後
Update後
Network断後
Power Failure後

にも、同じ正常状態へ戻れる必要があります。

そのため今回の設計では、

正常状態を最初に作る

だけでなく、

正常状態を定期的に作り直す

ことを重視しました。

例えば、

一時的なNetwork異常
Router / DHCP側の変化
時刻ずれ
Package Update
Process停止
予期しないReboot
Power Failure

などは、Edge PCだけでは完全には防げません。

そこで、

異常を完全に防ぐ

という考え方から、

現在状態を確認
↓
正常なら何もしない
↓
異常なら修復
↓
Normal Stateへ戻す

という考え方へ変更しました。


2. Maintenance処理を巨大な1本のScriptにしない

最初に避けたのが、

毎晩01:00

NTP確認
DNS確認
Network再設定
Package Update
Container Restart
Reboot

のように、すべてを1本のScriptで処理する構成です。

確かにFile数は少なくできます。

しかし障害時に、

どこで失敗したのか分からない
一つ失敗すると後続処理まで止まる
Network処理とUpdateが衝突する
Rebootされると原因を追いにくい

という問題があります。

そこで役割ごとに、

NTP
NAT
DNS
IoT Edge Update
OS Reboot判定
IoT Edge Reboot判定
NIC復帰
Route修復
Firewall確認
Diagnostic

を分離しました。


3. systemd serviceとtimerで「実行時刻」と「処理」を分ける

Ubuntuでは、

systemd service
+
systemd timer

を使っています。

基本構成は、

.timer
↓
いつ実行するか

.service
↓
何を実行するか

です。

例えばNTP同期なら、

mdlinkage-ntp-sync.timer
↓
mdlinkage-ntp-sync.service
↓
NTP同期処理

という形です。

Timer自体の状態は、

systemctl status mdlinkage-ntp-sync.timer

で確認できます。

実際に実行された処理は、

journalctl -u mdlinkage-ntp-sync.service

で確認できます。

この構成のメリットは、

「いつ動かすか」と「何をするか」を分離できる

ことです。


4. 実際のMaintenance Schedule

今回のEdge PCでは、主なMaintenanceを次のように分散しました。

00:15
定刻Reboot

00:45
NTP Sync
NAT確認

01:00
DNS確認・再設定

01:30
IoT Edge / Moby Patch確認

02:30
OS Updateによる
reboot-required確認

03:30
IoT Edge / Moby Update後の
Reboot Flag確認

04:30
NIC状態確認・復帰

さらにBoot後にも、

Route
NAT
Firewall
NIC
Network関連設定
NTP

を再確認します。

重要なのは、

すべてを同時に実行しないこと

です。


5. Maintenance時間をずらす理由

例えば同じ時刻に、

NTP同期
Package Update
DNS変更
Container Restart
Network再設定
Reboot

を実行したとします。

一つ一つは正常でも、組み合わせによって、

Networkが一時的に切れる

Update途中でRebootする

DNS確認中にNICがRestartする

Container確認中にRuntimeが更新される

といった問題が発生する可能性があります。

また障害が起きても、

NTP?
DNS?
Update?
Network?
Reboot?

と原因を切り分けにくくなります。

そこで、

処理A
↓
時間を空ける
↓
処理B
↓
時間を空ける
↓
処理C

としています。

Maintenance処理同士も障害原因になり得る

という前提です。


6. 定期Rebootを入れるなら「Reboot後に戻れること」が前提

今回の構成では、

00:15

に定刻Rebootを実行しています。

目的は、

長時間動作による一時的な状態蓄積
Application / Runtimeの状態変化
Network Stackの一時的な異常
Processの想定外状態

などを一度CleanなBoot状態へ戻すことです。

ただし、

定期Rebootを入れれば安定する

という意味ではありません。

例えばReboot後に、

Networkが戻らない
Routeがない
Firewallが戻らない
NATがない
NICがDown
IoT Edgeが起動しない

となれば、Rebootそのものが障害原因になります。

そのため、

Reboot
↓
Ubuntu Boot
↓
Network Ready
↓
Route確認
↓
Firewall / NAT確認
↓
NIC確認
↓
NTP同期
↓
Application復旧

までを一つのRecovery設計として考えます。


7. Recovery Scriptは「正常なら何もしない」

Boot後のRoute確認では、

現在のRoute確認
↓
正常
↓
OKとして終了

とします。

異常な場合だけ、

現在のRoute確認
↓
Route不足
↓
期待状態へ修復

します。

FirewallやNATも同様です。

現在のRule確認
↓
正常
↓
何もしない

または、

現在のRule確認
↓
不足・異常
↓
期待状態へ戻す

です。

つまり、

Timer起動
↓
毎回設定を書き直す

のではありません。

Timer起動
↓
現在状態を確認
↓
正常なら終了
↓
異常なら修復

としています。

Maintenance処理は、

何度実行しても正常状態を壊しにくいこと

が重要です。


8. NTP / DNSも「最初に設定したからOK」ではない

NTP

Edge Gatewayでは時刻も重要です。

時刻がずれると、

TLS Certificate
Log時刻
Cloud通信
障害解析
複数端末間のLog比較

などへ影響します。

特にTroubleshootingでは、

Edge PC Log
Network Log
Cloud Log

を時系列で比較するため、各機器の時刻がずれていると解析が難しくなります。

今回の構成では、

00:45
NTP Sync

に加え、

Boot
↓
Network Ready
↓
NTP Sync

も行っています。


DNS

Cloud接続ではDNSも重要です。

例えば、

IP通信
↓
OK

DNS Resolve
↓
NG

なら、Network Interface自体が正常でもAzure IoT Hubへ接続できません。

利用者から見ると、

Networkはつながっている

でも

CloudへDataが送れない

という状態です。

そのためDNSも一度設定して終わりではなく、定期的に確認します。

切り分けも、

NIC
↓
Network
↓
Route
↓
DNS
↓
Cloud

のようにLayerごとに分けて考えます。


9. Update処理とReboot処理を分離する

無人運用では、

Update
↓
即Reboot

という構成にはしていません。

例えばUbuntu側でKernelや重要Packageが更新されると、

/var/run/reboot-required

が生成される場合があります。

今回の構成では、

Update完了
↓
時間を空ける
↓
02:30
↓
reboot-required確認
↓
あり → Reboot
なし → 何もしない

としています。

つまり、

Updateする処理とRebootする判断を分離する

構成です。


10. IoT Edge / Container RuntimeのUpdateも専用処理にする

Azure IoT Edge / Container Runtimeについても、OS Maintenanceとは分離しました。

01:30

に、

Installed Version確認
↓
Candidate Version確認
↓
同一世代か確認
↓
Dry-run
↓
依存関係確認
↓
条件を満たせばPatch
↓
Health Check

という専用の処理を通します。

UpdateによってRebootが必要になった場合は、

IoT Edge / Moby Update
↓
pending-iotedge-reboot

のようにFlagを残します。

その後、

03:30
↓
Flag確認
↓
条件確認
↓
必要ならReboot

します。

これにより、

Update
↓
即Reboot

ではなく、

Update
↓
Flag
↓
Maintenance Window
↓
Reboot

という制御ができます。

また複数台のEdge PCを想定し、

RandomizedDelaySec

も利用しています。

これにより全端末が完全に同じ瞬間にMaintenanceを開始することを避けます。


11. Maintenanceの最後にNICも確認する

ApplicationやContainerが正常でも、

NIC Down

であればGatewayとしては動作できません。

そのため、

04:30
NIC状態確認

も行います。

今回の設計では、

Application
Container
OS
Network Interface

を別々のLayerとして考えています。

Application正常
+
Container正常
+
OS正常
+
NIC異常

であれば、

Gatewayとしては異常

です。


12. 定期MaintenanceだけでなくBootをRecovery Triggerにする

Timerを毎日設定していても、

Power Failureが、

00:30

に発生した場合、次の定期Maintenanceまで待つわけにはいきません。

そこで一部の処理では、

OnBootSec

を使っています。

対象は例えば、

NTP
NAT
Route
NIC
Firewall

です。

つまり、

Power Failure
↓
Power Restore
↓
Ubuntu Boot
↓
Recovery処理開始

として、

BootそのものをRecovery Triggerにする

設計です。


13. Persistent=trueは処理によって使い分ける

systemd timerには、

Persistent=true

があります。

例えば01:00に予定していた処理の時間にPCが停止していた場合、

01:00
PC OFF
↓
処理できない
↓
次回Boot
↓
未実行処理を実行

とできます。

ただし、すべてのTimerで有効にするわけではありません。

例えば毎日00:15の定刻Rebootについて、

昨日00:15
PC OFF
↓
今日Boot
↓
昨日Rebootできなかったので今Reboot

とする必要はありません。

そのため、

実行漏れをBoot後に補う処理

と、

実行漏れを補わない処理

を分けます。

重要なのは、

Persistent=trueを使うかどうかではなく、その処理の目的

です。


14. Timerを作っただけではなく「実際に動いた証拠」を確認する

無人端末では、人が画面を見て処理成功を確認できません。

そのためLogを残します。

Service単位のLogは、

journalctl -u mdlinkage-ntp-sync.service

で確認できます。

Timer全体は、

systemctl list-timers --all

で確認できます。

Maintenance用Timerだけ確認するなら例えば、

systemctl list-timers --all | grep -E \
'mdlinkage|mdl-|reboot-if'

のように確認できます。

見るべきなのは、

Timer Fileが存在する

だけではありません。

enabledか
activeか
期待する時刻になっているか
実際にServiceが実行されたか
Exit Codeが正常か

まで確認します。

今回のAcceptance Checkでは、

00:15 定刻Reboot

00:45 NTP

00:45 NAT

01:00 DNS

01:30 IoT Edge Patch

02:30 OS Reboot Check

03:30 IoT Edge Reboot Check

04:30 NIC Wakeup

が期待どおり登録されているか確認します。

さらにBoot後には、

Route
NTP
NAT
Firewall
NIC

などが、

現在のBoot Sessionで実際に実行された証拠

まで確認します。

設定Fileが存在することと、実際に動作したことは別です。


15. 自己復旧だけでは検知できない障害もある

ここまでの仕組みによって、

時刻
DNS
Route
Firewall
NAT
NIC
IoT Edge
Container Runtime
Reboot Requirement

など、多くの状態をEdge PC自身で確認できます。

しかし、Edge PCそのものが完全にFreezeした場合は別です。

Edge PC
↓
Freeze
↓
CPU / Kernel / Network停止

となれば、

systemd timer
Health Check
Log保存
Recovery Script

自体が動きません。

そこで、

Edge PC自身
↓
正常状態を維持
異常なら自己復旧

と、

External Monitor
↓
Edge PCが本当に生きているか
外側から確認

を分けました。

外部監視側では、

Ping
Heartbeat
Telemetry
rsyslog
netconsole

など複数の経路を使います。

これによって、

Applicationだけ停止

Networkだけ停止

OS全体がFreeze

Kernel Crash

などの切り分けをしやすくします。


16. 24/365無人Edge端末の設計を整理する

今回の設計をまとめると、3つのLayerになります。

① 予防
────────────────

Version管理
Security Update
定刻Maintenance
Maintenance時間の分散


② 自己復旧
────────────────

定刻Reboot
Boot後のRoute確認
Firewall / NAT確認
DNS確認
NTP同期
NIC復帰
必要時Reboot


③ 外部検知
────────────────

Ping
Heartbeat
Telemetry
rsyslog
netconsole

つまり、

壊れにくくする
↓
壊れたら戻す
↓
戻せなければ外から検知する

という構成です。


まとめ

24/365の無人Edge端末を安定稼働させるために、特別なTechnologyを一つ導入したわけではありません。

使用しているのは、

systemd
systemd timer
journal
nftables
Shell Script
Health Check

など、Linuxでは一般的な仕組みです。

重要だったのは、

どの異常に対して

どのLayerで

いつ確認して

どこまで自動復旧し

どこから外部監視へ任せるか

をSystem全体として設計することでした。

そしてRecovery処理についても、

毎回設定を書き直す

のではなく、

現在状態を確認
↓
正常なら何もしない
↓
異常なら期待状態へ戻す

ようにしています。

24時間365日の無人運用では、「止まらないこと」だけではなく、「正常状態へ戻れること」と「戻れなかったことを検知できること」が重要です。

次回は、Edge PC自身が完全にFreezeした場合に備えて、

監視対象とは別のLinux端末からEdge PCを監視する構成

について整理します。

Edge PC
↓
Ping
Heartbeat
Telemetry
rsyslog
netconsole
↓
External Monitor

自己復旧できない障害を、どのように外側から検知し、Freeze直前の情報を残すかを紹介します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?