搭建Docker應用棧--第一個Docker集羣

一個容器只能運行一個進程,即只提供一種服務,對於用戶而言,單一的容器是無法滿足需求的。通常用戶需要利用多個容器,分別提供不同的服務,並在容器間互相通信,最後形成一個Docker集羣。

基於Docker集羣構建的應用我們稱爲Docker APP Stack,即Docker應用棧。

在2019年的今天,爲了完整的搭建,確實費了好多力氣,因爲版本升級和其他一些原因,在搭建過程中會出現很多錯誤,所以不能再一味的參考書去做,而是多方面查閱資料,然後排錯,一步步搞定。當你自己完整的搭建成功,會對Docker以及Docker集羣有更深入的認識和理解。

說明一下:所有的搭建是基於KaliLinux,時間2019-11.權限:root。

kali版本:

Linux kali 4.19.0-kali4-amd64 #1 SMP Debian 4.19.28-2kali1 (2019-03-18) x86_64 GNU/Linux

docker版本:

鏡像是docker的基礎,此次搭建是利用從Dockerhub上已有的Docker資源搭建應用棧。搭建之前,需要對要搭建的集羣做以瞭解:

一個HAProxy代理點,兩個Web應用節點,一個主Redis數據庫節點,兩個從Redis數據庫節點,具體結構如下:

 其中:HAProxy是負載均衡節點;Redis是非關係型數據庫;APP是應用,這裏使用的是Python語言,基於Django架構設計一個訪問數據庫的基礎web應用。

1.獲取應用棧各節點所需鏡像:HAProxy、Redis、Django。

docker pull ubuntu

docker pull django

docker pull haproxy

docker pull redis

下載的過程可能會出現卡頓或者網絡連接不通的消息從而斷開,重複docker pull命令即可。

然後查看下載的鏡像

docker images

2.啓動應用棧容器節點

1)先創建主Redis-master

docker run -it --name redis-master redis /bin/bash

-i代表使用交互模式,始終保持輸入流開放

-t代表分配僞終端,一般兩個參數同時使用 -it。

--name 自定義命名,若無,則隨機分配.

然後退出,再創建redis-slave1和redis-slave2

master以‘exit’退出後需要重新啓動否則無法關聯。關閉窗口的話後臺還是運行着的。

2)使用--link進行關聯

docker run -it --name redis-slave1 --link redis-master:master redis /bin/bash
docker run -it --name redis-slave2 --link redis-master:master redis /bin/bash

查看redis下的容器

3)啓動djiango容器:

docker run -it --name APP1 --link redis-master:db -v ~/Projects/Django/APP1:/usr/src/app django /bin/bash
docker run -it --name APP2 --link redis-master:db -v ~/Projects/Django/APP2:/usr/src/app django /bin/bash

值得注意的是,連接Redis數據庫時,使用了--link參數創建db連接來代替具體的IP地址;

4)最後啓動HAProxy

docker run -it --name HAProxy --link APP1:APP1 --link APP2:APP2 -p 6301:6301 -v ~/Projects/HAProxy:/tmp haproxy /bin/bash

爲了方便後續與容器進行交互式操作,統一設定啓動命令爲/bin/bash。在啓動每個新的容器時都分配一個終端執行。

啓動的容器信息可以查看下

至此,所有搭建應用棧所需容器啓動工作已經完成。

下一階段,應用棧容器節點的配置

搭建好的應用棧容器啓動後,需要對它們進行修改和配置,以便實現特定的功能和通信協作。

1.redis-master主數據庫容器節點的配置

需要在容器中添加Redis的啓動配置文件如果你本機裝有redis數據庫,在/etc/redis/redis.conf就可以找到此配置文件:

,如果沒有配置文件的話你可以直接安裝redis然後去目錄查看,

或者直接下載redis.conf:https://github.com/yhsong-linux/docker-redis/blob/master/redis.conf

這個配置文件是啓動Redis數據庫的,不可缺少。

由於容器輕量化的設計,缺乏相應的文本編輯器,這個時候使用volume實現文件的創建。在啓動容器時加上-v參數掛載volume,實現在主機和容器之間共享數據,這樣就可以直接在主機上創建和編輯數據相關文件,省去了在容器中安裝編輯工具的麻煩。

在利用Redis鏡像啓動容器時,鏡像中已經集成了volume的掛載命令,所以需要通過docker inspect來查看所掛載volume的情況。

1)現在就是要找到docker中對應的本地文件的目錄,然後將redis.conf複製過去。

docker inspect 4f --format "{{.Volumes}}"

 那個4f是容器id的前兩位,因爲ID號太長,所以docker中可以用id前2位以上的id來使用。

出現了錯誤,查了一下,解決:

1,使用 “.Config.Volumes” 替換 “.Volumes”

但是沒有出現我們想要的目錄。

2,直接看容器的所有信息 再grep

 docker inspect 4f |grep Mount -A 10

這下好像可以找到,既然是inspect的內容,前期出現問題不妨全部查看下

目錄出來了,剛纔去/var下了,也發現了這些東西,但是沒注意到,沒想到竟然擦肩而過。

2)安裝一個redis,或者下載redis.conf將配置文件複製到容器的目錄下.

可以將註釋的內容全部過濾然後複製到相應的目錄下:

3)然後編輯配置文件:vim redis.conf

4)主機創建好配置文件後,切換到容器中的volume目錄,然後配置:

 cd /data/

 cp redis.conf /usr/local/bin/

 cd /usr/local/bin/

 ls

 redis-server  redis.conf

現在已經將redis.conf複製到相應的docker目錄中。

正常的操作是這樣的,但是這個過程充滿着艱辛和無數的小問題。

這段東西搞了三天吧,因爲主從redis不能同步的問題,很是煩人,問題就出在了配置文件:redis.conf中

在測試的時候:

在master的容器中啓用redis:redis-server redis.conf 加載配置文件,出現了問題:日誌文件沒有目錄

在這裏說一個小細節:從本機複製到容器目錄下的配置文件,不是能夠正常運行的。

爲什麼呢?

先看第一個:提示沒有日誌文件的目錄或者文件,在kali裏面是有的,但是容器中沒有,所以要自行創建文件夾和日誌文件,爲了保險起見,我還加上了 chmod 777 redis-server.log。防止日誌文件寫不進去。

5)執行redis-server redis.conf:報錯

6)然後再次鍵入redis-server redis.conf,又出現了問題:缺少文件夾

那就再創建新的文件夾。

值得一提的是,當日志文件沒有創建的時候,所有的redis的信息輸出都會在終端顯示

當創建新的日誌文件的時候,所有的日誌文件都會輸出到log裏面:

查看日誌:

當從redis試圖連接master的時候,日誌中也會記錄:

下圖是slave配置好後連接成功的master中記錄的日誌文件

這個時候master數據庫容器基本完成。

2.從數據庫節點配置

最麻煩的還是從數據庫容器。也不是麻煩,就是出了問題半天不知道在哪裏,各種嘗試各種查看。甚至重新run各個容器。或者刪除redis 的image,重新下,或者懷疑redis.conf有問題卸載redis,重新安裝,拉出redis.conf,對比網上的配置文件。。。等等八萬種操作。

和master一樣,創建新的日誌文件和目錄,然後創建系統提醒不存在的目錄,兩次創建和master一樣。

但是要在salve容器中的redis.conf 中要多添加一個: salveof master 6379

就是告訴當前redis數據庫,自己是master的從數據庫,端口是6379.

寫上後保存,然後redis-server redis.conf 啓用

但是總是出現這個問題

起初以爲是配置文件參數改了,查了好長時間,將網上的配置文件和剛下載的redis.conf 進行對比,發現slaveof是不一樣的,在我的機子中沒有slaveof這個東西,取而代之的是replicaof還以爲參數錯了,但是當我用第二個slave2配置的時候用的參數就是slaveof master 6379.竟然成功連接了,所以不是參數的問題。

看最後一行:bind:不能指定請求地址,說明問題在bind這裏。

於是我就將bind ip改成了0.0.0.0

最後連接成功,然後檢測:

在住容器中運行:

redis-cli,進入redis,可能會出現連接失敗的錯誤,重新運行redis-server redis.conf即可。

意思就是在住redis中創建master變量master,值爲“4fb”。

如果從數據庫正常連接的話,也會在redis-slave1和redis-slave2中查看到,否則不然。

從數據庫連接成功後查看成功:

slave2的配置和slave1一樣。細心配置即可。

至此應用棧的數據可部分就搭建完成,實在不容易。

2.APP容器節點(Django)的配置

(Django:Django是一個開放源代碼的Web應用框架,由Python寫成。採用了MTV的框架模式,即模型M,視圖V和模版T。它最初是被開發來用於管理勞倫斯出版集團旗下的一些以新聞內容爲主的網站的,即是CMS(內容管理系統)軟件。並於2005年7月在BSD許可證下發布。這套框架是以比利時的吉普賽爵士吉他手Django Reinhardt來命名的。)

Django容器啓動後,需要利用Django框架,開發一個簡單的web程序。

爲了訪問數據庫,需要在容器中安裝Python預言的redis支持包:

1)進入Django容器APP1:

pip install redis
python
import redis
print(redis.__file__)

然後測試:

沒有報錯,說明已經可以用python語言來調用Redis數據庫。

下面開始創建web程序,以APP1爲例,在容器啓動的時候,掛載了

-v ~/Projects/Django/APP2:/usr/src/app的volume

(-v參數就是將容器中的目錄對應在本地指定目錄下方便進入主機的目錄來對新建APP進行編輯。)

2)在容器的/usr/src/app/下,創建APP:

  cd /usr/src/app/
  ls
  mkdir dockerweb
  cd dockerweb/
  django-admin.py startproject redisweb
  ls
  cd redisweb/
  ls
  python manage.py startapp helloworld
  ls

 這段可能命令看不懂,沒關係,先繼續往下看

3)在容器內創建APP後,切換到主機的~/Projects/Django/APP1進行相應的編輯來配置APP,過程如下。

#代碼如下:
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
#創建自己的view
import redis

def hello(request):
    str=redis.__file__
    str+="<br>"
    r = redis.Redis(host='db',port=6379,db=0)
    info = r.info()
    str+=("Set Hi <br>")
    r.set('Hi','HelloWorld-APP1')
    str+=("Get Hi: %s <br>" % r.get('Hi'))
    str+=("Redis Info:<br>")
    str+=("Key: Info Value")
    for key in info:
        str+=("%s: %s <br>" %(key,info[key]))
        return HttpResponse(str)

值得注意的是,連接Redis數據庫時,使用了--link參數創建db連接來代替具體的IP地址;同理,對於APP2,使用相應的db連接即可。

4)完成view.py的文件修改後,接下來修改Redisweb項目中的配置文件setting.py,添加新的helloworld應用,如下:

5)最後修改redisweb項目中的URL模式文件url.py,它將設置訪問應用的URL模式。併爲URL模式調用視圖函數之間的映射列表:如下,引入helloworld應用的hello視圖,併爲hello視圖添加一個urlpatterns變量

6)在主機修改完這幾個文件後,再次進入容器,在/usr/src/app/dockerweb/redisweb下完成項目的生成,如下:

 第一次執行出現了語法錯誤,原來在第七行def hello(request)後沒加  ':'.小細節一定注意哈。修改後執行命令:


python manage.py makemigrations

python manage.py migrate

python manage.py syncdb

然後執行syndb創建用戶

爲什麼syndb不能用呢,其實在Django1.9之後,這個命令就不支持了,而且沒有提醒。然後查看help文檔。

可以看到一個createsuperuser。明顯這個就是想要的命令

7)執行:

python manage.py createsuperuser

可以看到,創建成功。

至此,所有APP1容器的配置已經全部完成,另一個APP2容器配置也是同樣的過程,只需要將第三步稍作修改即可。完成APP2的配置後,就完成了應用棧的APP部分的全部配置過程。

 

在啓動APP的web服務器時,可以指定服務器的端口和IP地址,爲了通過HAProxy容器節點接受外網所有的公共IP地址訪問,實現負載均衡,需要指定服務器的IP地址和端口,對於APP1使用8001端口,而APP2使用8002端口,同時,都是用0.0.0.0地址,以APP1爲例,啓動服務器過程如下:

執行腳本一定要去對應的redisweb目錄下。

DjangoAPP的配置就結束了。

3.下面開始HAProxy的配置

這個配置是用來進行負載均衡的,部署一個HAProxy負載均衡的容器節點,所有對應用棧的訪問都將通過它來實現負載均衡。

1)首先,利用容器啓動是掛載的volume將HAProxy的啓動配置文件複製進容器中,執行如下:

cd ~/Projects/HAProxy
vim haproxy.cfg
global
	log	127.0.0.1	local0  #日誌輸出配置,所有日誌都記錄在本機,通過local0輸出
	maxconn	4096            #最大連接數
	chroot	/usr/local/sbin    #改變當前工作目錄
	daemon                  #以後臺形式運行HAProxy
	nbproc	4               #啓動四個HAProxy實例
	pidfile	/usr/local/sbin/haproxy.pid    #pid文件位置

defaults
	log	127.0.0.1 		local3   #日誌文件的輸出定向
	mode	http          #{tcp|http|health}設定啓動實例的協議類型
	option	dontlognull   #保證HAProxy不吉利上級負載均衡發送過來的用於檢測狀態沒有數據的心跳包
	option	redispatch    #當serverId對應的服務器掛掉後,強制定向到其他健康的服務器
	retries	2            #重試兩次連接失敗就認爲服務器不可用,主要通過後面的check檢查
	maxconn	2000        #最大連接數
	balance	roundrobin    #balance有兩個可用選項:roundrobin和source,其中roundrobin表示輪 
                          #詢,source表示HAProxy不採用輪詢策略,而是把來自某個IP的請求轉發給 
                          #一個固定IP的後端
	timeout	connect 5000ms     #連接超時時間
	timeout	client	50000ms    #客戶端連接超時時間
	timeout	server	50000ms    #服務器端連接超時時間

listen redis_proxy 
    bind 0.0.0.0:6301
    bind-process 2
	stats enable
	stats uri /haproxy-stats
	server APP1 APP1:8001 check inter 2000 rise 2 fall 5  #你的均衡節點
	server APP2 APP2:8002 check inter 2000 rise 2 fall 5

隨後進入容器的/tmp目錄下,將啓動配置文件複製過來:

cp /tmp/haproxy.cfg /usr/local/sbin/haproxy.cfg

然後再/usr/local/sbin/目錄下執行:haproxy -f haproxy.cfg

需要提醒的是,配置文件修改後需要killall proxy,或者重新啓動容器也行。

至此,HAProxy的配置全部完成。

測試

整個應用棧的訪問時通過HAProxy代理點來進行的,在HAProxy容器節點啓動時,通過-p 6301:6301參數,映射了容器訪問的端口到主機上,因此可以在其他主機上通過本地主機的IP地址和端口來訪問搭建好的應用棧。

在本地機上可以查看IP:

然後訪問:http://172.17.0.1:6301/helloworld 來查看APP1或者APP2的內容了

看樣子又出現了報錯,不過我已經習慣了。。。

它給出瞭解決方法,先試試吧

在APP1和APP2的setting.py文件裏,修改ALLOWED_HOSTS = [ ] 字段:

目錄要找對

改完後記得把APP2 下面的配置文件也要一起改

然後再刷新

終於出來了!

具體訪問到的APP內容節點會由HAProxy代理進行均衡分配。同時可以訪問

172.17.0.1:6301/haproxy-stats查看HAProxy的後臺管理頁面。

很花樣,很nice,很滿意,很開心。。。

本地測試通過後,嘗試在其主機上通過應用棧入口主機IP地址和暴露的6301端口來訪問該應用棧的APP,

用外網其他主機訪問:

192.168.142.4是宿主機的IP,

當訪問helloworld項目時,出現這個,明顯需要添加IP,在APP1和APP2裏面的setting.py都加上

然後訪問成功。

至此,應用棧的搭建以及測試所有工作結束。用時3天,排錯2.5天。。。看着書弄的,書是死的,外界的更新是獲得,得思考和發現錯誤以及解決錯誤,才能效率高速度快。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章