如何運行多進程Docker容器?

jopen 8年前發布 | 17K 次閱讀 Docker 多進程

簡介

一般來說,Docker容器比較適合運行單個進程。例如,項目” 使用多個Docker容器運行Kubernetes “,Kubernetes的各個組件分別運行在各個容器之中,每個容器只運行單個進程。

然而,很多時候我們需要在Docker容器中運行多個進程。例如,項目” 使用單個Docker容器運行Kubernetes “,kubernetes的各個組件均運行在同一個容器中,該容器中運行了多個進程。那么, 如何運行多進程Docker容器?

一種方法是使用 Shell腳本 ,另一種方法是使用進程管理工具 Supervisorkiwenlau/kubernetes-shellkiwenlau/kubernetes-supervisor 分別采用了這兩種方法,用于啟動多個進程來運行Kubernetes的各個組件,從而實現” 使用單個Docker容器運行Kubernetes “。下面我將分別介紹兩種不同方法。

使用Shell腳本運行多進程Docker容器

這個方法大家應該會比較熟悉,使用Shell腳本依次啟動Kubernetes的各個組件即可。以下為 start-kubernetes.sh

#!/bin/bash

# start docker daemon
docker daemon > /var/log/docker.log 2>&1 &

# start etcd
etcd --data-dir=/var/etcd/data > /var/log/etcd.log 2>&1 &

# wait for ectd to setup
sleep 5

# start apiserver
kube-apiserver --service-cluster-ip-range=10.0.0.1/24 --insecure-bind-address=0.0.0.0 --etcd_servers=http://127.0.0.1:4001 > /var/log/kube-apiserver.log 2>&1 &

# wait for apiserver to setup
sleep 5

# start controller manager, sheduler, kubelet and proxy
kube-controller-manager --master=http://0.0.0.0:8080 > /var/log/kube-controller-manager.log 2>&1 &
kube-scheduler --master=http://0.0.0.0:8080 > /var/log/kube-scheduler.log 2>&1 &
kubelet --api_servers=http://0.0.0.0:8080 --address=0.0.0.0 --cluster_dns=10.0.0.10 --cluster_domain="kubernetes.local" --pod-infra-container-image="kiwenlau/pause:0.8.0"  > /var/log/kubelet.log 2>&1 &
kube-proxy --master=http://0.0.0.0:8080 > /var/log/kube-proxy.log 2>&1 &

# just keep this script running
while [[ true ]]; do
    sleep 1
done

然后在Dockerfile中,將 start-kubernetes.sh 指定為Docker容器默認執行的命令即可:

CMD ["start-kubernetes.sh"]

需要注意的一點在于, start-kubernetes.sh 腳本將作為Docker容器的1號進程運行,必須始終保持運行。因為 Docker容器僅在1號進程運行時保持運行 ,換言之,Docker容器將在1號進程退出后 Exited 。由于Kubernetes的各個組件都以后臺進程方式執行,我在腳本末尾添加了死循環,以保持 start-kubernetes.sh 腳本始終處于運行狀態。

# just keep this script running
while [[ true ]]; do
    sleep 1
done

使用supervisor運行多進程Docker容器

Supervisor 是進程管理工具。這時,需要編寫supervisor的配置文件 kubernetes.conf :

[supervisord]
nodaemon=true

[program:etcd]
command=etcd --data-dir=/var/etcd/data
autorestart=true
stdout_logfile=/var/log/etcd.stdout.log
stderr_logfile=/var/log/etcd.stderr.log

[program:kube-apiserver]
command=kube-apiserver --service-cluster-ip-range=10.0.0.1/24 --insecure-bind-address=0.0.0.0 --etcd_servers=http://127.0.0.1:4001
autorestart=true
stdout_logfile=/var/log/kube-apiserver.stdout.log
stderr_logfile=/var/log/kube-apiserver.stderr.log

[program:kube-controller-manager]
command=kube-controller-manager --master=http://0.0.0.0:8080
autorestart=true
stdout_logfile=/var/log/controller-manager.stdout.log
stderr_logfile=/var/log/controller-manager.stderr.log

[program:kube-scheduler]
command=kube-scheduler --master=http://0.0.0.0:8080
autorestart=true
stdout_logfile=/var/log/kube-scheduler.stdout.log
stderr_logfile=/var/log/kube-scheduler.stderr.log

[program:kubelet]
command=kubelet --api_servers=http://0.0.0.0:8080 --address=0.0.0.0 --cluster_dns=10.0.0.10 --cluster_domain="kubernetes.local" --pod-infra-container-image="kiwenlau/pause:0.8.0"
autorestart=true
stdout_logfile=/var/log/kubelet.stdout.log
stderr_logfile=/var/log/kubelet.stderr.log

[program:kube-proxy]
command=kube-proxy --master=http://0.0.0.0:8080
autorestart=true
stdout_logfile=/var/log/kube-proxy.stdout.log
stderr_logfile=/var/log/kube-proxy.stderr.log

[program:docker]
command=docker daemon
autorestart=true
stdout_logfile=/var/log/docker.stdout.log
stderr_logfile=/var/log/docker.stderr.log

可知,將Kubernetes的各個組件的啟動命令設為command即可。autorestart參數設為true,意味著supervisor將負責重啟意外退出的組件。stdout_logfile和stderr_logfile參數則可以用于設置命令的標準輸出文件和標準錯誤輸出文件。

然后在Dockerfile中,將 supervisord 指定為Docker容器默認執行的命令即可:

CMD ["supervisord", "-c", "/etc/supervisor/conf.d/kubernetes.conf"]

此時, supervisord是Docker容器中的1號進程,也需要始終保持運行狀態。nodaemon設為true時,表示supervisor保持前臺運行而非在后臺運行。若supervisor在后臺運行,則Docker容器也會在執行supervisord命令后立即Exited.

[supervisord]
nodaemon=true

總結

使用Shell腳本運行多進程Docker容器,優勢是大家比較熟悉。由于需要保持Docker容器的1號進程始終運行,這一點比較容易出錯。若要實現進程意外退出后自動重啟的話,使用shell腳本比較麻煩。

使用supervisor運行多進程Docker容器,非常方便。另外,保持1號進程保持運行,以及進程意外退出后自動重啟,實現起來都很簡單。

使用多個Docker容器運行Kubernetes

GitHub地址

下圖顯示了我在Ubuntu主機上運行單機版Kubernetes的架構。可知,我一共運行了7個容器,分別運行Kubernetes的各個組件。

使用單個Docker容器運行Kubernetes

GitHub地址:

該項目中,我將kubernetes的所有組件:etcd, controller manager, apiserver, scheduler, kubelet, proxy以及docker daemon均運行在同一個Docker容器之中。

容器啟動時,各個組件由shell腳本或者supervisor啟動。

參考

  1. Using Supervisor with Docker
  2. How To Install and Manage Supervisor on Ubuntu and Debian VPS
  3. 基于Docker搭建單機版Kuberntes
  4. kiwenlau/single-kubernetes-docker

來自: http://kiwenlau.com/2016/01/09/160109-multiple-processes--docker-container/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!