概要 #
Dockerのlive-restore: true設定で起動中コンテナは継続される理解はあるものの
実際に試したことはありませんでした。
なので、nginxをWebサーバーとして使用してDockerのlive-restore: true設定での動作を検証しました。
live-restore動作原理 #
Dockerのコンポーネント分離 #
Docker Engineは以下の3つの主要コンポーネントで構成されています:
- dockerd: APIサーバー兼デーモン。
docker psやdocker runの窓口 - containerd: コンテナのライフサイクル管理を担う常駐プロセス
- runc: OCI Runtime。実際に
clone(2)やcgroupsを操作してコンテナを起動
live-restoreの仕組み #
dockerdの設定で"live-restore": trueを有効にすると:
-
dockerdが停止してもcontainerd/runcはkillされない
- 「デーモンの生存」と「コンテナの生存」が分離される
- コンテナはLinuxカーネルの機能(namespaces/cgroups/実行中のプロセス)で独立して稼働
-
制御プレーンを失うため制約が発生
- 新規コンテナ作成不可
- 既存コンテナの制御(stop/restart/exec/logs)不可
- 監視やAPI呼び出し不可
-
デーモン復帰時の再インポート
- containerdを再接続して「孤立していたコンテナ」を再インポート
/run/docker/libcontainerd/以下の状態を読み込んで再同期
ポイント: コンテナは本質的にLinuxのプロセスであり、dockerdはあくまで管理の窓口。
live-restore: trueによって「dockerdをkillしてもcontainerdを巻き添えにしない」ようになるため、
コンテナは影響を受けません。
検証環境 #
- minikube: v1.36.0 (k8s-doker-testプロファイル)
- Kubernetes: v1.28.0
- Container Runtime: Docker
- Webサーバー: nginx:alpine
- アクセス方法: NodePort 30081
検証環境構成図 #
graph TB
subgraph "Host Machine (WSL2)"
subgraph "minikube VM (k8s-doker-test)"
subgraph "Docker Architecture"
subgraph "Docker Daemon (dockerd)"
DD["dockerd
API Server
Container Management"]
end
subgraph "Container Runtime (containerd)"
CR["containerd
Container Lifecycle
Image Management"]
end
subgraph "Runtime (runc)"
RC1["runc
Container 1"]
RC2["runc
Container 2"]
end
subgraph "Container Processes"
CP1["nginx Process
POD 1
Port: 80"]
CP2["nginx Process
POD 2
Port: 80"]
end
end
subgraph "Kubernetes Cluster"
subgraph "default namespace"
subgraph "nginx-web PODs"
NW1["nginx:alpine
ConfigMap: nginx-web-config
HTML: nginx-web-html"]
NW2["nginx:alpine
ConfigMap: nginx-web-config
HTML: nginx-web-html"]
end
end
subgraph "Services"
NWS["nginx-web-service
NodePort: 30081"]
end
end
subgraph "Docker Configuration"
DCF["daemon.json
live-restore: true
log-driver: json-file"]
end
end
subgraph "External Access"
CLIENT["Web Browser
curl http://192.168.103.2:30081"]
end
end
CLIENT -->|"HTTP Request"| NWS
NWS -->|"Load Balance"| NW1
NWS -->|"Load Balance"| NW2
NW1 -.->|"Runs in"| CP1
NW2 -.->|"Runs in"| CP2
DD -->|"Manages"| CR
CR -->|"Creates"| RC1
CR -->|"Creates"| RC2
RC1 -->|"Executes"| CP1
RC2 -->|"Executes"| CP2
DCF -.->|"Configures"| DD
classDef dockerDaemon fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef containerd fill:#e8f5e8,stroke:#388e3c,stroke-width:2px
classDef runc fill:#fff3e0,stroke:#f57c00,stroke-width:2px
classDef containerProcess fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef kubernetesPod fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
classDef service fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px
classDef config fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef client fill:#fce4ec,stroke:#880e4f,stroke-width:2px
class DD dockerDaemon
class CR containerd
class RC1,RC2 runc
class CP1,CP2 containerProcess
class NW1,NW2 kubernetesPod
class NWS service
class DCF config
class CLIENT client
検証フロー #
-
minikube起動 (k8s-doker-test)
-
Docker daemon.json設定 (live-restore: true)
-
Dockerデーモン再起動 (設定適用)
-
nginx Webサーバーデプロイ (2レプリカ)
-
POD起動待機 (Ready状態確認)
-
初期状態確認 (POD・Service状態)
-
Webサーバー動作確認 (メインページ・Health Check)
-
Dockerデーモン停止 (live-restore効果確認)
-
停止中POD状態確認 (継続実行確認)
-
停止中Web動作確認 (サービス継続確認)
-
Dockerデーモン再起動 (接続復旧確認)
-
再起動後POD状態確認 (状態復旧確認)
-
再起動後Web動作確認 (サービス復旧確認)
-
nginx設定変更 (ConfigMap更新)
-
POD再起動 (設定変更適用)
-
最終状態確認 (新設定での動作確認)
-
最終Web動作確認 (全エンドポイント確認)
検証手順 #
1. minikube環境の起動 #
minikube start --cni calico --container-runtime=docker --bootstrapper=kubeadm --kubernetes-version=v1.28.0 -p k8s-doker-test
結果:
😄 [k8s-doker-test] minikube v1.36.0 on Ubuntu 22.04 (kvm/amd64)
✨ Using the docker driver based on existing profile
👍 Starting "k8s-doker-test" primary control-plane node in "k8s-doker-test" cluster
2. Docker daemon.jsonの設定 #
現在の設定を確認:
minikube ssh -p k8s-doker-test "cat /etc/docker/daemon.json"
現在の設定:
{"exec-opts":["native.cgroupdriver=systemd"],"log-driver":"json-file","log-opts":{"max-size":"100m"},"storage-driver":"overlay2"}
live-restore: trueを追加:
minikube ssh -p k8s-doker-test "sudo tee /etc/docker/daemon.json > /dev/null" << 'EOF'
{
"exec-opts": ["native.cgroupdriver=systemd"],
"live-restore": true,
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
更新後の設定:
{
"exec-opts": ["native.cgroupdriver=systemd"],
"live-restore": true,
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
Dockerデーモンを再起動:
minikube ssh -p k8s-doker-test "sudo systemctl restart docker"
3. nginx Webサーバーのデプロイ #
nginx Webサーバーのテスト環境YAMLファイルを作成:
アクセスURL構成
/: メインページ(カスタムHTML)/health: ヘルスチェック用エンドポイント/status: ステータス確認用エンドポイント/test: 設定変更後のテスト用エンドポイント
# nginx Webサーバーのテスト環境
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-web-config
data:
nginx.conf: |
events {
worker_connections 1024;
}
http {
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html;
}
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
location /status {
access_log off;
return 200 "nginx is running\n";
add_header Content-Type text/plain;
}
}
}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-web-html
data:
index.html: |
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Docker Live Restore Test</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background-color: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.header {
text-align: center;
color: #2c3e50;
margin-bottom: 30px;
}
.status {
background-color: #e8f5e8;
padding: 15px;
border-radius: 5px;
border-left: 4px solid #4caf50;
margin: 20px 0;
}
.info {
background-color: #e3f2fd;
padding: 15px;
border-radius: 5px;
border-left: 4px solid #2196f3;
margin: 20px 0;
}
.timestamp {
color: #666;
font-size: 0.9em;
text-align: center;
margin-top: 30px;
}
.test-links {
margin: 20px 0;
}
.test-links a {
display: inline-block;
margin: 5px 10px 5px 0;
padding: 8px 16px;
background-color: #2196f3;
color: white;
text-decoration: none;
border-radius: 4px;
}
.test-links a:hover {
background-color: #1976d2;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>Docker Live Restore Test</h1>
<h2>nginx Web Server</h2>
</div>
<div class="status">
<h3>サービス状態</h3>
<p><strong>nginx Webサーバーが正常に動作しています</strong></p>
<p>このページはDockerのlive-restore設定の検証用です。</p>
</div>
<div class="info">
<h3>検証内容</h3>
<ul>
<li>Dockerデーモン停止時のコンテナ継続実行</li>
<li>デーモン再起動後の接続復旧</li>
<li>Webサーバーの可用性確認</li>
<li>Kubernetes PODの状態管理</li>
</ul>
</div>
<div class="test-links">
<h3>テスト用エンドポイント</h3>
<a href="/health">Health Check</a>
<a href="/status">Status Check</a>
</div>
<div class="timestamp">
<p>ページ生成時刻: <span id="timestamp"></span></p>
<script>
document.getElementById('timestamp').textContent = new Date().toLocaleString('ja-JP');
</script>
</div>
</div>
</body>
</html>
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-web
spec:
replicas: 2
selector:
matchLabels:
app: nginx-web
template:
metadata:
labels:
app: nginx-web
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: config
configMap:
name: nginx-web-config
- name: html
configMap:
name: nginx-web-html
---
apiVersion: v1
kind: Service
metadata:
name: nginx-web-service
spec:
selector:
app: nginx-web
ports:
- port: 80
targetPort: 80
nodePort: 30081
type: NodePort
リソースをデプロイ:
kubectl apply -f nginx-web-test.yaml
結果:
configmap/nginx-web-config created
configmap/nginx-web-html created
deployment.apps/nginx-web created
service/nginx-web-service created
デプロイされるリソース:
- ConfigMap: nginx-web-config (nginx設定)
- ConfigMap: nginx-web-html (HTMLコンテンツ)
- Deployment: nginx-web (2レプリカ)
- Service: nginx-web-service (NodePort 30081)
POD起動確認:
kubectl get pods -l app=nginx-web -o wide
結果:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-web-685455c7cb-bgz72 1/1 Running 1 (32s ago) 6m20s 10.244.130.211 k8s-doker-test <none> <none>
nginx-web-685455c7cb-cq7ng 1/1 Running 1 (32s ago) 6m20s 10.244.130.210 k8s-doker-test <none> <none>
4. 初期動作確認 #
メインページ:
curl -s http://192.168.103.2:30081 | grep -o "<title>.*</title>"
結果:
<title>Docker Live Restore Test</title>
Health Check:
curl -s http://192.168.103.2:30081/health
結果:
healthy
Status Check:
curl -s http://192.168.103.2:30081/status
結果:
nginx is running
5. live-restore検証 #
Dockerデーモン停止前の状態 #
kubectl get pods -l app=nginx-web -o wide
結果:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-web-685455c7cb-bgz72 1/1 Running 1 (2m ago) 7m48s 10.244.130.211 k8s-doker-test <none> <none>
nginx-web-685455c7cb-cq7ng 1/1 Running 1 (2m ago) 7m48s 10.244.130.210 k8s-doker-test <none> <none>
Dockerデーモン停止 #
minikube ssh -p k8s-doker-test "sudo systemctl stop docker"
結果:
Warning: Stopping docker.service, but it can still be activated by:
docker.socket
停止中のPOD状態確認 #
kubectl get pods -l app=nginx-web -o wide
結果:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-web-685455c7cb-bgz72 1/1 Running 1 (2m16s ago) 8m4s 10.244.130.211 k8s-doker-test <none> <none>
nginx-web-685455c7cb-cq7ng 1/1 Running 1 (2m16s ago) 8m4s 10.244.130.210 k8s-doker-test <none> <none>
Dockerデーモンが停止していても、PODはRunning状態を維持しています!
これはlive-restore: true設定により、dockerdが停止してもcontainerd/runcが継続実行されるため。
コンテナはLinuxカーネルの機能(namespaces/cgroups)で独立して稼働し続けます。
停止中のWeb動作確認 #
# メインページ(停止中)
curl -s http://192.168.103.2:30081 | grep -o "<title>.*</title>"
# Health Check(停止中)
curl -s http://192.168.103.2:30081/health
# Status Check(停止中)
curl -s http://192.168.103.2:30081/status
結果:
<title>Docker Live Restore Test</title>
healthy
nginx is running
Dockerデーモンが停止していても、Webサーバーは正常に動作し続けています!
これはlive-restore: trueにより、dockerdの停止がcontainerd/runcに影響せず、
コンテナプロセスが継続実行されるためです。
WebサーバーはLinuxカーネルレベルで動作しているため、Dockerデーモンの状態に依存しません。
Dockerデーモン再起動 #
minikube ssh -p k8s-doker-test "sudo systemctl start docker"
再起動後のPOD状態確認 #
kubectl get pods -l app=nginx-web -o wide
結果:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-web-685455c7cb-bgz72 1/1 Running 1 (3m24s ago) 9m12s 10.244.130.211 k8s-doker-test <none> <none>
nginx-web-685455c7cb-cq7ng 1/1 Running 1 (3m24s ago) 9m12s 10.244.130.210 k8s-doker-test <none> <none>
Dockerデーモン再起動後も、PODは正常にRunning状態を維持しています!
Dockerデーモン再起動時に、dockerdがcontainerdを再接続し、 孤立していたコンテナを再インポートするため、既存のPODは継続して動作し続けます。
再起動後のWeb動作確認 #
# メインページ(再起動後)
curl -s http://192.168.103.2:30081 | grep -o "<title>.*</title>"
# Health Check(再起動後)
curl -s http://192.168.103.2:30081/health
# Status Check(再起動後)
curl -s http://192.168.103.2:30081/status
結果:
<title>Docker Live Restore Test</title>
healthy
nginx is running
Dockerデーモン再起動後も、Webサーバーは正常に動作しています!
Dockerデーモン再起動により、dockerdがcontainerdと再接続し、 孤立していたコンテナが再び管理下に戻るため、Webサーバーは継続して正常動作します。
6. nginx設定変更検証 #
ConfigMap更新 #
kubectl patch configmap nginx-web-config --patch '{
"data": {
"nginx.conf": "events {\n worker_connections 1024;\n}\nhttp {\n server {\n listen 80;\n location / {\n root /usr/share/nginx/html;\n index index.html;\n }\n location /health {\n access_log off;\n return 200 \"healthy - updated\\n\";\n add_header Content-Type text/plain;\n }\n location /status {\n access_log off;\n return 200 \"nginx is running - updated\\n\";\n add_header Content-Type text/plain;\n }\n location /test {\n access_log off;\n return 200 \"Live Restore Test - Updated Configuration\\n\";\n add_header Content-Type text/plain;\n }\n }\n}"
}
}'
POD再起動 #
kubectl rollout restart deployment nginx-web
新設定での動作確認 #
# 更新されたHealth Check
curl -s http://192.168.103.2:30081/health
# 更新されたStatus Check
curl -s http://192.168.103.2:30081/status
# 新しいTestエンドポイント
curl -s http://192.168.103.2:30081/test
結果:
healthy - updated
nginx is running - updated
Live Restore Test - Updated Configuration
設定変更が正常に適用されました!
7. live-restore制限事項の検証 #
Dockerデーモン停止時の制限事項を確認します:
Dockerデーモン停止(制限事項検証用) #
minikube ssh -p k8s-doker-test "sudo systemctl stop docker"
新規コンテナ作成の制限確認 #
minikube ssh -p k8s-doker-test "docker run --rm hello-world"
結果:
docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Run 'docker run --help' for more information
既存コンテナの制御制限確認 #
# コンテナ一覧表示
minikube ssh -p k8s-doker-test "docker ps"
# コンテナ実行
minikube ssh -p k8s-doker-test "docker exec nginx-web-685455c7cb-bgz72 echo 'test'"
# ログ確認
minikube ssh -p k8s-doker-test "docker logs nginx-web-685455c7cb-bgz72"
# コンテナ停止
minikube ssh -p k8s-doker-test "docker stop nginx-web-685455c7cb-bgz72"
# コンテナ再起動
minikube ssh -p k8s-doker-test "docker restart nginx-web-685455c7cb-bgz72"
結果:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Dockerデーモンが停止しているため、すべての結果がエラーになります。
Docker API呼び出し制限確認 #
# ローカルのDockerデーモンにUnixソケット経由で接続し、現在Dockerホスト上にあるコンテナの一覧をJSON形式で取得する
minikube ssh -p k8s-doker-test "curl -s --unix-socket /var/run/docker.sock http://localhost/containers/json"
結果:
curl: (7) Failed to connect to unix socket /var/run/docker.sock: No such file or directory
既存コンテナの継続動作確認 #
curl -s http://192.168.103.2:30081/health
結果:
healthy - updated
Dockerデーモンが停止していても、既存のコンテナは継続実行され、Webサービスは正常に動作し続けています!
これはlive-restore: trueにより、dockerdが停止してもcontainerd/runcが継続実行され、
コンテナプロセスがLinuxカーネルレベルで独立して動作し続けるためです。
ただし、制御プレーン(dockerd)を失うため、新規コンテナ作成や既存コンテナの制御はできません。
Dockerデーモン再起動(制限事項検証後) #
minikube ssh -p k8s-doker-test "sudo systemctl start docker"
8. Kubernetes POD作成の制限検証 #
Dockerデーモン停止状態でKubernetesでPODを作成した場合の動作を確認します:
Dockerデーモン停止(POD作成制限検証用) #
minikube ssh -p k8s-doker-test "sudo systemctl stop docker"
既存PODの状態確認 #
kubectl get pods -l app=nginx-web -o wide
結果:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-web-5478b586cd-5vgfx 1/1 Running 0 25h 10.244.130.214 k8s-doker-test <none> <none>
nginx-web-5478b586cd-7z96q 1/1 Running 0 25h 10.244.130.215 k8s-doker-test <none> <none>
新しいPOD作成の試行 #
kubectl run test-pod --image=nginx:alpine --restart=Never
結果:
pod/test-pod created
新規PODの状態確認 #
kubectl get pods test-pod -o wide
結果:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-pod 0/1 ContainerCreating 0 10s <none> k8s-doker-test <none> <none>
POD詳細情報確認 #
kubectl describe pod test-pod
結果(一部抜粋) :
Status: Pending
Containers:
test-pod:
State: Waiting
Reason: ContainerCreating
Ready: False
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 44s default-scheduler Successfully assigned default/test-pod to k8s-doker-test
Warning FailedCreatePodSandBox 44s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to inspect sandbox image "registry.k8s.io/pause:3.9": Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Dockerデーモン停止時は、KubernetesでPODを作成してもContainerCreating状態で停止し、
実際のコンテナは作成されません!
これはlive-restore: trueにより、dockerdが停止していてもcontainerd/runcは生存していますが、kubeletがDockerデーモンに接続できないため、新規コンテナの作成ができないためです。
Kubernetes APIではPOD作成が成功しますが、実際のコンテナ作成は失敗します。
既存PODの動作確認 #
curl -s http://192.168.103.2:30081/health
結果:
healthy - updated
既存のPODは継続して動作しています!
live-restore: trueにより、既存のコンテナはcontainerd/runcレベルで継続実行されているため、
Webサービスは正常に動作し続けます。
Dockerデーモン再起動(POD作成制限検証後) #
minikube ssh -p k8s-doker-test "sudo systemctl start docker"
Dockerデーモン再起動後のPOD状態確認 #
kubectl get pods test-pod -o wide
結果:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-pod 1/1 Running 0 98s 10.244.130.216 k8s-doker-test <none> <none>
Dockerデーモン再起動後、新規PODが正常にRunning状態になりました!
Dockerデーモン再起動により、dockerdがcontainerdと再接続し、 kubeletがDockerデーモンに接続できるようになったため、新規PODのコンテナ作成が正常に完了しました。
新規PODの動作確認 #
kubectl exec test-pod -- nginx -v
結果:
nginx version: nginx/1.29.1
テストPODの削除 #
kubectl delete pod test-pod
検証結果まとめ #
- Dockerデーモン停止時でも、Webページへのアクセスが継続可能
- live-restore制限事項の実証: Dockerデーモン停止時の制限が確認できた
- 新規コンテナ作成:
Cannot connect to the Docker daemon - 既存コンテナ制御:
Cannot connect to the Docker daemon - Docker API呼び出し:
Failed to connect to unix socket - 既存コンテナ継続: Webサービスは正常動作継続
- 新規コンテナ作成:
- Kubernetes POD作成の制限実証: Dockerデーモン停止時のKubernetes動作が確認できた
- 新規POD作成: Kubernetes APIでは成功するが、実際のコンテナは作成されない
- POD状態:
ContainerCreating状態で停止 - エラー詳細:
Failed to create pod sandbox: Cannot connect to the Docker daemon - 既存POD継続: 停止前のPODは継続実行
- デーモン再起動後: 新規PODが正常に
Running状態になる
結論 #
nginxをWebサーバーとして使用したlive-restore検証が成功しました。
live-restore: true設定により、dockerdの停止がcontainerd/runcに影響せず、
コンテナプロセスがLinuxカーネルレベルで継続実行されることが確認できました。
また、新規コンテナを作成することやコンテナへの変更などのコンテナを 管理することができないことも確認できました。
これにより、Dockerデーモンのメンテナンス時でも既存PODの可用性を確保できることが確認できました。
参考資料: