本篇內容主要講解“Docker中常見(jiàn)的異??偨Y”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強。下面就讓小編來(lái)帶大家學(xué)習“Docker中常見(jiàn)的異??偨Y”吧!
docker ps
無(wú)響應, Node 節點(diǎn)表現為 NotReady。
$ docker -v $ Docker version 17.03.2-ce, build f5ec1e2 $ docker-containerd -v $ containerd version 0.2.3 commit:4ab9917febca54791c5f071a9d1f404867857fcc $ docker-runc -v $ runc version 1.0.0-rc2 $ commit: 54296cf40ad8143b62dbcaa1d90e520a2136ddfe $ spec: 1.0.0-rc2-dev
有兩種方法可以啟用調試。 建議的方法是在 daemon.json
文件中將 debug
設置為 true
。 此方法適用于每個(gè) Docker 平臺。
1.編輯 daemon.json
文件,該文件通常位于 /etc/docker/
中。 如果該文件尚不存在,您可能需要創(chuàng )建該文件。 2.增加以下設置
{ "debug": true }
3.向守護程序發(fā)送 HUP 信號以使其重新加載其配置。
sudo kill -SIGHUP $(pidof dockerd)
可以看到 Docker debug 級別的日志:
Dec 14 20:04:45 dockerd[7926]: time="2018-12-14T20:04:45.788669544+08:00" level=debug msg="Calling GET /v1.27/containers/json?all=1&filters=%7B%22label%22%3A%7B%22io.kubernetes.docker.type%3Dpodsandbox%22%3Atrue%7D%7D&limit=0" Dec 14 20:04:45 dockerd[7926]: time="2018-12-14T20:04:45.790628950+08:00" level=debug msg="Calling GET /v1.27/containers/json?all=1&filters=%7B%22label%22%3A%7B%22io.kubernetes.docker.type%3Dcontainer%22%3Atrue%7D%7D&limit=0" Dec 14 20:04:46 dockerd[7926]: time="2018-12-14T20:04:46.792531056+08:00" level=debug msg="Calling GET /v1.27/containers/json?all=1&filters=%7B%22label%22%3A%7B%22io.kubernetes.docker.type%3Dpodsandbox%22%3Atrue%7D%7D&limit=0" Dec 14 20:04:46 dockerd[7926]: time="2018-12-14T20:04:46.794433693+08:00" level=debug msg="Calling GET /v1.27/containers/json?all=1&filters=%7B%22label%22%3A%7B%22io.kubernetes.docker.type%3Dcontainer%22%3Atrue%7D%7D&limit=0" Dec 14 20:04:47 dockerd[7926]: time="2018-12-14T20:04:47.097363259+08:00" level=debug msg="Calling GET /v1.27/containers/json?filters=%7B%22label%22%3A%7B%22io.kubernetes.docker.type%3Dpodsandbox%22%3Atrue%7D%7D&limit=0" Dec 14 20:04:47 dockerd[7926]: time="2018-12-14T20:04:47.098448324+08:00" level=debug msg="Calling GET /v1.27/containers/json?all=1&filters=%7B%22label%22%3A%7B%22io.kubernetes.docker.type%3Dcontainer%22%3Atrue%7D%2C%22status%22%3A%7B%22running%22%3Atrue%7D%7D&limit=0" Dec 14 20:04:47 dockerd[7926]:
dockerd
一直在請求 list containers 接口,但是沒(méi)有響應。
$ kill -SIGUSR1 $(pidof dockerd)
生成的調試信息可以在以下目錄找到:
...goroutine stacks written to /var/run/docker/goroutine-stacks-2018-12-02T193336z.log ...daemon datastructure dump written to /var/run/docker/daemon-data-2018-12-02T193336z.log
查看 goroutine-stacks-2018-12-02T193336z.log 文件內容,
goroutine 248 [running]: github.com/docker/docker/pkg/signal.DumpStacks(0x18fe090, 0xf, 0x0, 0x0, 0x0, 0x0) /root/rpmbuild/BUILD/docker-ce/.gopath/src/github.com/docker/docker/pkg/signal/trap.go:82 +0xfc github.com/docker/docker/daemon.(*Daemon).setupDumpStackTrap.func1(0xc421462de0, 0x18fe090, 0xf, 0xc4203c8200) /root/rpmbuild/BUILD/docker-ce/.gopath/src/github.com/docker/docker/daemon/debugtrap_unix.go:19 +0xcb created by github.com/docker/docker/daemon.(*Daemon).setupDumpStackTrap /root/rpmbuild/BUILD/docker-ce/.gopath/src/github.com/docker/docker/daemon/debugtrap_unix.go:32 +0x10a goroutine 1 [chan receive, 91274 minutes]: main.(*DaemonCli).start(0xc42048a840, 0x0, 0x190f560, 0x17, 0xc420488400, 0xc42046c820, 0xc420257320, 0x0, 0x0) /root/rpmbuild/BUILD/docker-ce/.gopath/src/github.com/docker/docker/cmd/dockerd/daemon.go:326 +0x183e main.runDaemon(0x0, 0x190f560, 0x17, 0xc420488400, 0xc42046c820, 0xc420257320, 0x10, 0x0) /root/rpmbuild/BUILD/docker-ce/.gopath/src/github.com/docker/docker/cmd/dockerd/docker.go:86 +0xb2 main.newDaemonCommand.func1(0xc42041f200, 0xc42045df00, 0x0, 0x10, 0x0, 0x0) /root/rpmbuild/BUILD/docker-ce/.gopath/src/github.com/docker/docker/cmd/dockerd/docker.go:42 +0x71 github.com/docker/docker/vendor/github.com/spf13/cobra.(*Command).execute(0xc42041f200, 0xc42000c130, 0x10, 0x11, 0xc42041f200, 0xc42000c130) /root/rpmbuild/BUILD/docker-ce/.gopath/src/github.com/docker/docker/vendor/github.com/spf13/cobra/command.go:646 +0x26d github.com/docker/docker/vendor/github.com/spf13/cobra.(*Command).ExecuteC(0xc42041f200, 0x16fc5e0, 0xc42046c801, 0xc420484810) /root/rpmbuild/BUILD/docker-ce/.gopath/src/github.com/docker/docker/vendor/github.com/spf13/cobra/command.go:742 +0x377 github.com/docker/docker/vendor/github.com/spf13/cobra.(*Command).Execute(0xc42041f200, 0xc420484810, 0xc420084058) /root/rpmbuild/BUILD/docker-ce/.gopath/src/github.com/docker/docker/vendor/github.com/spf13/cobra/command.go:695 +0x2b main.main() /root/rpmbuild/BUILD/docker-ce/.gopath/src/github.com/docker/docker/cmd/dockerd/docker.go:106 +0xe2 goroutine 17 [syscall, 91275 minutes, locked to thread]: ...
至此,我們可以確定,containerd
無(wú)響應導致的 docker ps
無(wú)響應,在堆棧中我們也可以看到調用 containerd
無(wú)響應是因為加了lock.
通過(guò) dmesg 查看系統異常信息,發(fā)現 cgroup
報 OOM 溢出錯誤。
[7993043.926831] Memory cgroup out of memory: Kill process 20357 (runc:[2:INIT]) score 970 or sacrifice child
查看了大部分機器的 dmesg 信息,發(fā)現都有 OOM 這個(gè)錯誤,至此我們懷疑是由于某個(gè)容器 OOM 導致的 containerd 無(wú)響應.
既然懷疑是容器 OOM 異常導致的 containerd 無(wú)響應,那我們干脆自己創(chuàng )造現場(chǎng)模擬一下。
首選我們創(chuàng )建一個(gè) OOM 的部署,通過(guò) nodeSelector 讓這個(gè)部署調度到指定 Node。
apiVersion: extensions/v1beta1 kind: Deployment metadata: labels: wayne-app: oomtest wayne-ns: test app: oomtest name: oomtest spec: selector: matchLabels: app: oomtest template: metadata: labels: wayne-app: oomtest wayne-ns: test app: oomtest spec: nodeSelector: kubernetes.io/hostname: test-001 containers: - resources: limits: memory: 0.2Gi cpu: '0.2' requests: memory: 0.2Gi cpu: '0.1' args: - '-m' - '10' - '--vm-bytes' - 128M - '--timeout' - 60s - '--vm-keep' image: progrium/stress name: stress
發(fā)現過(guò)了一會(huì ) test-001 這臺 Node 出現了 docker ps
無(wú)響應的情況,查看 dmesg
以及 containerd
的堆棧信息,發(fā)現和之前的 Node 出現的異常一致。至此,基本可以確定是某個(gè)容器 OOM 導致的 containerd hung 住。
通過(guò)查找社區 Issues 及相關(guān) PR,最后發(fā)現根本原因是 runc 的bug。
使用 runc start
或 runc run
啟動(dòng)容器時(shí),stub process(runc [2:INIT])打開(kāi)一個(gè) fifo
進(jìn)行寫(xiě)入。 它的父 runc 進(jìn)程 將打開(kāi)相同的 fifo 閱讀。 通過(guò)這種方式,它們可以同步。
如果 stub process 在錯誤的時(shí)間退出,那么父 runc
進(jìn)程 會(huì )永遠被阻塞。
當兩個(gè) runc
操作相互競爭時(shí)會(huì )發(fā)生這種情況:runc run / start
和 runc delete
。 它也可能由于其他原因而發(fā)生, 例如 內核的 OOM killer 可以選擇殺死 stub process。
通過(guò)解決 exec fifo 競爭來(lái)解決這個(gè)問(wèn)題。 如果 在我們打開(kāi) fifo 之前 stub process 退出,那么返回一個(gè)錯誤。
containerd
官方已經(jīng)在 v1.0.2 版本合并了這個(gè)修改。因此這個(gè)問(wèn)題可以通過(guò)升級 Docker 版本解決。我們目前已經(jīng)將部分機器升級到 Docker 18.06。 已升級的機器暫時(shí)未發(fā)現類(lèi)似問(wèn)題。
相關(guān)issues: https://github.com/containerd/containerd/issues/1882 https://github.com/containerd/containerd/pull/2048 https://github.com/opencontainers/runc/pull/1698
Docker 在 Centos 系統下以 direct-lvm 模式運行, 無(wú)法啟動(dòng)
Error starting daemon: error initializing graphdriver: devicemapper: Non existing device docker-thinpool Dec 14 03:21:03 two-slave-41-135 systemd: docker.service: main process exited, code=exited, status=1/FAILURE Dec 14 03:21:03 two-slave-41-135 systemd: Failed to start Docker Application Container Engine. Dec 14 03:21:03 two-slave-41-135 systemd: Dependency failed for kubernetes Kubelet. Dec 14 03:21:03 two-slave-41-135 systemd: Job kubelet.service/start failed with result 'dependency'.
這個(gè)問(wèn)題發(fā)生在使用 devicemapper 存儲驅動(dòng)時(shí)Docker試圖重用之前使用 LVM thin pool。例如,嘗試更改節點(diǎn)上的 Docker 的數據目錄時(shí)會(huì )發(fā)生此問(wèn)題。由于安全措施旨在防止 Docker 因配置問(wèn)題而意外使用和覆蓋 LVM thin pool 中的數據,因此會(huì )發(fā)生此錯誤。
要解決阻止Docker啟動(dòng)的問(wèn)題,必須刪除并重新創(chuàng )建邏輯卷,以便Docker將它們視為新的thin pool。
警告:這些命令將清除Docker數據目錄中的所有現有鏡像和卷。 請在執行這些步驟之前備份所有重要數據。
1.停止 Docker
sudo systemctl stop docker.service
2.刪除 Dodcker 目錄
sudo rm -rf /var/lib/docker
3.刪除已經(jīng)創(chuàng )建的 thin pool 邏輯卷
$ sudo lvremove docker/thinpool Do you really want to remove active logical volume docker/thinpool? [y/n]: y Logical volume "thinpool" successfully removed
4.創(chuàng )建新的邏輯卷
lvcreate -L 500g --thin docker/thinpool --poolmetadatasize 256m
根據實(shí)際磁盤(pán)大小調整 thinpool 和 metadata 大小
如果您想要讓Docker自動(dòng)為您配置direct-lvm模式,請繼續執行以下步驟。
1.編輯/etc/docker/daemon.json
文件以將dm.directlvm_device_force = value
從false
更改為true
。 例如:
{ "storage-driver": "devicemapper", "storage-opts": [ "dm.directlvm_device_force=true" ] }
2.除了刪除邏輯卷之外,還要刪除docker卷組:
$ sudo vgremove docker
3.啟動(dòng)Dokcer
sudo systemctl start docker.service
Docker 雖然是目前最常用的容器解決方案,但它仍舊有很多不足。
Docker 的隔離性比較弱,混布容易導致業(yè)務(wù)互相影響,可能因為一個(gè)服務(wù)有問(wèn)題就會(huì )影響其他服務(wù)甚至影響整個(gè)集群。
Docker 自己存在一些 bug, 由于歷史原因,很多 bug 無(wú)法完全歸因于內核或者 Docker,需要 Docker 和內核配合修復。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站