安裝DCOS,關於docker異常引發的調查


  入門DCOS,剛開始安裝,碰到了一個異常:

Bind for 0.0.0.0:9000 failed: port is already allocated.
  調試這個問題花費了好長時間,因為無法通過netstat以及lsof看到究竟是什么應用占用了程序;后來我才發現原來是因為docker的原因;如果docker被run了兩次
   docker run -it -p 9000:80 mesosphere/dcos-genconf:d932fc405eb80d8e5b-b7c22f7cfb481d9f95 /bin/bash 
  第一次失敗,那么這個端口將會被一直占用,即使docker容器並沒有創建並沒有。解決辦法就是重啟docker服務:
   service docker restart 
  (也有人說要sudo rm /var/lib/docker/network/files/local-kv.db,但是在我看來並不需要)
  這個是docker里面的bug,看到這個issue在論壇里面討論的熱火朝天,但是這是2014年的事了。
  再回過頭來,那么既然是run兩次失敗會爆這個異常,那么,docker run失敗原因是什么呢?
exec: "docker-proxy": executable file not found in $PATH.
  這個異常的原因是docker啟動后將會執行docker-proxy指令,但是在shell中加載的$PATH中無法找到對應的指令。與之類似是docker-runc無法找到,這個原因是在/usr/libexec/docker下面,在安裝的時候可能因為沒有完全安裝導致的兩個link沒有安裝上,用如下方法進行修補:

1 cd /usr/libexec/docker/
2 sudo ln -s docker-proxy-current /usr/bin/docker-proxy 

  daocker執行應該首先回到/usr/libexec/docker下面找執行文件,沒有,再到$PATH定義的路徑下找,再沒有,則報錯。
  另外,當發生以下異常:
/usr/bin/docker-current: Error response from daemon: shim error: docker-runc not installed on system.
  也是需要創建軟連接方式來解決:
   sudo ln -s docker-runc-current /usr/bin/docker-runc 

prestart hook 1 caused \\\"error running hook: exit status 1
  這個問題如果這樣貼出來,是沒有意義的,想要看更加詳細的錯誤信息:

1 service docker status -l
2 journalctl -xe

  這樣結合起來可以看到更加詳細的信息。
  看到的錯誤信息:Failed to open file '/sys/class/net/vethf6a3cb0/operstate'
  vethXXX應該是docker內部的網絡接口的名稱;初步推測應該是因為某個異常導致的docker內部的網卡沒有啟動起來。
  在調查的過程中發現了一個命令:brctl show,用來顯示網橋,其實docker默認的網橋是docker0(docker0並不是一個網絡接口,而是一個網橋)。
  至於如何來創建網橋
  https://docs.docker.com/engine/userguide/networking/default_network/build-bridges/
  以及相關docker的文檔:
  https://docs.docker.com/v1.7/articles/networking/
  https://forums.docker.com/t/relationship-between-interface-vethxxxxx-and-container/12872/22

  后來深入跟蹤這個問題,發現其實是因為不知道什么原因會增加一個override.conf,這個override.conf將storage-driver設置成了overlay(難道是因為設docker_proxy?),至於發現這個的過程是這樣的,比較docker info的差異,發現有問題的機器采用的是overlay的方式,OK機器采用的是devicemapper的方式;然后我又嘗試修改為devicemapper,方式就是在/etc/docker/daemon.json文件中寫入
   {"storage-driver": "devicemapper"} 
  但是啟動docker的時候爆了一個異常:
  unable to configure the Docker daemon with file /etc/docker/daemon.json: the following directives are specified both as a flag and in the configuration file: storage-driver: (from flag: overlay, from file: devicemapper)\n"
  這里關於option我還想了半天,最后是懷疑是啟動docker服務的時候應該指定了storage-driver參數,和我在配置文件中的沖突了。我還手動啟動了一下dockerd --storage-drive=devicemapper,在docker run dcos的image沒有問題。
  然后我使用了service docker status,來查看docer服務的詳細內容,才發現status里面包含了非常豐富的內容,之前只是記得會顯示執行的指令以及參數選項(option)

 1 Redirecting to /bin/systemctl status  docker.service
 2 ● docker.service - Docker Application Container Engine
 3    Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
 4   Drop-In: /etc/systemd/system/docker.service.d
 5            └─override.conf
 6    Active: activating (auto-restart) (Result: exit-code) since Sat 2017-11-11 22:28:38 CST; 2s ago
 7      Docs: http://docs.docker.com
 8   Process: 31055 ExecStart=/usr/bin/dockerd --storage-driver=overlay (code=exited, status=1/FAILURE)
 9   Process: 31050 ExecStartPre=/sbin/ip link del docker0 (code=exited, status=0/SUCCESS)
10  Main PID: 31055 (code=exited, status=1/FAILURE)

  注意加粗三句話,所有的問題都是通過三句話來解開的:
  第一句話是說明服務啟動的文件,我進去看了,發現里面的storage-driver的配置文件里面默認配置的就是devicemapper。這個過程稍微有點復雜:/usr/lib/systemd/system/docker.service里面指定了storage的配置文件(/etc/sysconfig/docker-storage),需要查看storage的配置文件,但是呢這個配置文件還是多重繼承的意思,總是最后根上是/usr/share/container-storage-setup/container-storage-setup文件,打開一看:STORAGE_DRIVER=devicemapper,這說明默認就是devicemapper的方式,那么為什么通過docker info看到的方式是overlay呢?
  第二句話是說明配置項已經被覆蓋了,覆蓋的配置文件是 /etc/systemd/system/docker.service.d/override.conf,里面內容是:

1 art=always
2 StartLimitInterval=0
3 RestartSec=15
4 ExecStartPre=-/sbin/ip link del docker0
5 ExecStart=
6 ExecStart=/usr/bin/dockerd --storage-driver=overlay

  第三句話(還有下面的process語句)是真正的執行的指令和參數,其實就是override.conf里面定義的內容。

  看到這里我明白了,原來docker的啟動過程被覆蓋了。於是我將override.conf文件重命名了,然后重啟docker服務,爆了提示:
  Warning: docker.service changed on disk. Run 'systemctl daemon-reload' to reload units.
  daemon-reload是指重新加載服務的核心配置文件,即單元文件(里面定義了服務以來單元以及服務定義),這里因為我已經把服務的單元文件給刪掉了,所以需要重新加載配置文件(看來linux是把單元文件加載到內存中,每次重啟服務並不重新讀取單元文件)。重啟之后,搞定了。

  再看service docker status:

1 Redirecting to /bin/systemctl status  -l docker.service
2 ● docker.service - Docker Application Container Engine
3    Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
4    Active: active (running) since Sat 2017-11-11 22:37:20 CST; 19s ago
5      Docs: http://docs.docker.com
6  Main PID: 34181 (dockerd-current)
7    CGroup: /system.slice/docker.service
8            ├─34181 /usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --selinux-enabled --log-driver=journald --signature-verification=false
9            └─34186 /usr/bin/docker-containerd-current -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --shim docker-containerd-shim --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --runtime docker-runc --runtime-args --systemd-cgroup=true

  別問我為什么會有override.conf,我也不知道他是怎么出現的。
  但是如果提到了override.conf,則需要提到了systemd,其實systemd是Linux的一組基礎組建的工具集合(替代centos之前的initd),用於啟動守護進程,監控服務等一系列操作系統的基礎功能。
  服務(屬於單元的一種)一般是打包安裝,為了不需要修改打包原生的配置文件,systemd提供了一種可以在外部覆蓋原生配置文件的方式,這種就是:
   systemctl edit unit 
  修改之后,就會生成/etc/systemd/system/unit.d/override.conf(unit.d在我們這里就是docker.service.d)
后來,安裝dcos熟練了,才知道,這是因為dcos在安裝的時候會把master以及agent節點都配置為overlay,而修改配置侵入最小的方式就是采用override.conf的方式。我之前的問題就是在於把boot節點(setup節點)同時作為了master節點,所以有此問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM