我有一个正在运行 pyppeteer 的 docker 容器。它有内存泄漏,所以它会在 24 小时内停止。
我需要一些自动修复系统,我认为 Kubernetes 可以做到。没有负载均衡,只有一个实例,一个容器。合适吗?
++++
最后我选择了docker-py,使用containers.run、containers.prune进行管理。
它对我有用。
我有一个正在运行 pyppeteer 的 docker 容器。它有内存泄漏,所以它会在 24 小时内停止。
我需要一些自动修复系统,我认为 Kubernetes 可以做到。没有负载均衡,只有一个实例,一个容器。合适吗?
++++
最后我选择了docker-py,使用containers.run、containers.prune进行管理。
它对我有用。
如果你的容器没有状态,并且你知道它每 24 小时就会耗尽内存,我会说 cronjob 是最好的选择。
你可以在 k8s 上做你想做的事,但这太过分了。一个容器的整个 k8s 集群,对我来说听起来不对。
另一件事是,如果您有更多的应用程序或容器,因为 k8s 可以运行大量彼此独立的服务,因此您不会浪费资源。
无需创建完整的 Kubernetes 集群即可使用 Kubernetes 自动修复功能。只需要安装兼容版本docker
和kubelet
软件包。kubeadm
安装软件包也可能会有所帮助。
Kubelet是 Kubernetes 控制平面的一部分,负责保持 Pod处于健康状态。它作为 systemd 服务运行,并使用来自(位置可配置)的YAML 清单文件创建静态 pod 。/etc/kubernetes/manifests
所有其他应用程序故障排除都可以使用常规 docker 命令完成:
docker ps ...
docker inspect
docker logs ...
docker exec ...
docker attach ...
docker cp ...
官方文档中这种方法的一个很好的例子是运行外部 etcd 集群实例。(注意:在最近的 kubelet 版本中,kubelet 配置部分可能无法按预期工作。我在下面提供了更多详细信息。)
kubelet 还可以通过限制pod 规范的一部分来处理 pod 资源的使用。因此,您可以设置内存限制,当容器达到此限制时,kubelet 将重新启动它。
如果 Pod 规范中包含 liveness probe 部分,Kubelet 可以对 pod 中的应用程序进行健康检查。如果您可以创建一个命令来更准确地检查您的应用程序状况,那么当命令连续多次返回非零退出代码时(可配置),kubelet 可以重新启动容器。
如果 kubelet 拒绝启动,您可以使用以下命令检查 kubelet 日志:
journalctl -e -u kubelet
Kubelet 可以拒绝启动主要是因为:
缺少 kubelet 初始配置。它可以使用 kubeadm 命令生成:kubeadm init phase kubelet-start
. (您可能还需要生成 kubelet 配置中提到的 CA 证书 /etc/kubernetes/pki/ca.crt。可以使用 kubadm 完成kubeadm init phase certs ca
:)
docker 和 kubelet 的不同 cgroups 驱动程序设置。Kubelet 与 cgroupsfs 和 systemd 驱动程序都可以正常工作。Docker 默认驱动是 cgroupfs。Kubeamd 还使用 cgroupsfs 驱动程序生成 kubelet 配置,因此请确保它们相同。可以在服务定义文件中指定 Docker cgroups 驱动程序,/lib/systemd/system/docker.service
例如/usr/lib/systemd/system/docker.service
:
#add cgroups driver option to ExecStart:
ExecStart=/usr/bin/dockerd \
--exec-opt native.cgroupdriver=systemd # or cgroupfs
要更改最新 kubelet 版本的 cgroups 驱动程序,需要为服务指定 kubelet 配置文件,因为现在不推荐使用此类命令行选项:
sed -i 's/ExecStart=\/usr\/bin\/kubelet/ExecStart=\/usr\/bin\/kubelet --config=\/var\/lib\/kubelet\/config.yaml/' /lib/systemd/system/kubelet.service
然后更改 kubelet 配置中的 cgroups 行。更多的选择也需要改变。这是我用于相同目的的 kubelet 配置:
address: 127.0.0.1 # changed, was 0.0.0.0
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
anonymous:
enabled: false
webhook:
cacheTTL: 2m0s
enabled: false # changed, was true
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt # kubeadm init phase certs ca
authorization:
mode: AlwaysAllow # changed, was Webhook
webhook:
cacheAuthorizedTTL: 5m0s
cacheUnauthorizedTTL: 30s
cgroupDriver: cgroupfs # could be changed to systemd or left as is, as docker default driver is cgroupfs
cgroupsPerQOS: true
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
configMapAndSecretChangeDetectionStrategy: Watch
containerLogMaxFiles: 5
containerLogMaxSize: 10Mi
contentType: application/vnd.kubernetes.protobuf
cpuCFSQuota: true
cpuCFSQuotaPeriod: 100ms
cpuManagerPolicy: none
cpuManagerReconcilePeriod: 10s
enableControllerAttachDetach: true
enableDebuggingHandlers: true
enforceNodeAllocatable:
- pods
eventBurst: 10
eventRecordQPS: 5
evictionHard:
imagefs.available: 15%
memory.available: 100Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
evictionPressureTransitionPeriod: 5m0s
failSwapOn: true
fileCheckFrequency: 20s
hairpinMode: promiscuous-bridge
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 20s
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
imageMinimumGCAge: 2m0s
iptablesDropBit: 15
iptablesMasqueradeBit: 14
kind: KubeletConfiguration
kubeAPIBurst: 10
kubeAPIQPS: 5
makeIPTablesUtilChains: true
maxOpenFiles: 1000000
maxPods: 110
nodeLeaseDurationSeconds: 40
nodeStatusReportFrequency: 1m0s
nodeStatusUpdateFrequency: 10s
oomScoreAdj: -999
podPidsLimit: -1
port: 10250
registryBurst: 10
registryPullQPS: 5
resolvConf: /etc/resolv.conf
rotateCertificates: true
runtimeRequestTimeout: 2m0s
serializeImagePulls: true
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 4h0m0s
syncFrequency: 1m0s
volumeStatsAggPeriod: 1m0s
重启 docker/kubelet 服务:
systemctl daemon-reload
systemctl restart docker
systemctl restart kubelet
我没有与 Puppeteer 合作,但经过短暂的研究发现:
默认情况下,Docker 运行一个 /dev/shm 共享内存空间为 64MB 的容器。这对于 Chrome 来说通常太小,并且会导致 Chrome 在渲染大页面时崩溃。要修复,请使用 docker run --shm-size=1gb 运行容器以增加 /dev/shm 的大小。从 Chrome 65 开始,这不再是必需的。相反,使用 --disable-dev-shm-usage 标志启动浏览器:
const browser = await puppeteer.launch({
args: ['--disable-dev-shm-usage']
});
这会将共享内存文件写入 /tmp 而不是 /dev/shm。
希望这有帮助。
您的用例有几个选项,其中之一是运行 kubernetes。但是,在为单个容器运行 Kubernetes 时,您应该考虑资源开销和维护负担。
我建议您探索让 systemd 重新启动您的容器以防它崩溃或只是简单地使用 docker 本身:使用--restart=always
参数 docker 守护进程确保容器正在运行。注意:即使在重新启动系统后,docker 也会确保在这种情况下重新启动容器。所以 a--restart=on-failure
可能是更好的选择。
有关更多信息,请参阅此页面:https ://docs.docker.com/config/containers/start-containers-automatically/#use-a-restart-policy