Deploy cluster with docker-swarm to AWS EC2

11
8 min readJan 17, 2020

首先,不免俗的要先來介紹一下何謂docker swarm, docker swarm 是 docker 原生內建一個可以用來設定與維護叢集的工具,一種管理調度平台。

Docker Swarm 具備了以下幾種特性:

  • 去中心化設計
  • 容器規模縮放機制
  • TLS安全機制
  • 滾動式更新
  • 協調預期狀態與實際狀態的一致性

Docker Swarm 裡主要分為兩個角色Manager與Worker,兩者主要工作如下 :

  • Manager: 主要負責排程Task,Task可以表示為Swarm的節點中的Node啟動的容器,並負責編派容器與叢集管理。除此之外,Manager也具備Worker功能。
  • Worker: 主要接收來自 Manager的Task指派,並依據指示啟動Docker容器服務

首先你需要準備一個專案,並寫好dockerfile build好後並push到duckerhub,等等我們會把他pull下來到AWS EC2的docker — swarm

// 這是我的docker image$ docker pull libterty8186/server_web

或是可以參考我的dockerfile寫法

FROM node:latestRUN mkdir -p /usr/src/appWORKDIR /usr/src/appCOPY package.json ./RUN npm installRUN npm install pm2 -gCOPY . .EXPOSE 80CMD ["npm", "start"]

緊接者我們要來設定AWS EC2 instance了,當然在此之前你需要有AWS 帳號。

設定的部分非常簡單

AMI的部分請選擇Amazon Linux 2 AMI (HVM)

中間的地方一直按next就好XD

緊接者在Configure Security Group要設定節點主機間的連線方式

  • TCP PORT 2377 : 用於Dcoker Swarm 叢集服務管理
  • UDP PORT 4789 : 用於 Docker Swarm Overlay Network跨主機網路流量,overlay可以用 docker network ls 看到
  • TCP/UDP PORT 7946 : 用於 Docker Swarm 叢集主機互相通訊
設定內容
Instance 結果

接下來在 Launch instance 前需要設定 private key,並且並且一定要記得下載下來!!

接下來我們要來用下載下來 *.pem 檔連線到 AWS EC2 Instance ( 記得 *.pem如果放到專案內要把 *.pem 加入到 .gitignore 和 .dockerignore)

我們建立一個txt file 並把你剛建好的 instance 的IPV4放到裡面

$ cat > nodes.txt$ node 1: <- Your IPV4 ->

緊接者我們要修改你的 *.pem 權限把-rw-r — r — @ 改成 -r — — — @ 只能做讀的動作

// nodes.pem 只是範例
$ chmod 400 nodes.pem
$ ssh -i nodes.pem ec2-user@<- Your IPV4 ->

你就可以看到permisson的Amazon Linux畫面,這時候可以藉由輸入logout或是ctrl + D離開。

接者重複上述動作創立第二和第三 AWS Instance,不同的地方在於不用重複做security config,藉由選取existing security group可以沿用我們第一個創立的config包含了key Pair訊息。

並把你創建好第二和第三 AWS Instance 的 IPV4 放入到之前創立的nodes.txt裡面

接下來把 .txt 轉換成bash,因為接下來在使用上會比較方便。在切換不同instance時不用一直輸入 ssh 指令

$ cat nodes.txt > nodes.sh$ code nodes.sh
// nodes.sh
#!/bin/bashif [ $1 = 1 ]; then ssh -i <- your pem -> ec2-user@ <- your First Instance IPV4 ->elif [ $1 = 2 ]; then ssh -i <- your pem -> ec2-user@ <- your Second Instance IPV4 ->elif [ $1 = 3 ]; then ssh -i <- your pem -> ec2-user@ <- your Third Instance IPV4 ->fi// 最後讓雙方可以連線$ chmod +x ./nodes.sh

這樣子之後,假設第一個instance 是 Manager,第二個instance 是worker。在兩邊之間切換的時候我知需要輸入 ./nodes.sh 1 或是 ./nodes.sh 2

接下來我們要在 instance 內安裝 Docker,我們就從 instance 1 示範,並且把 instance 1 定義成 Manager

$ ./nodes.sh 1
$ sudo yum install -y docker
$ sudo service docker start // service是用來run docker的script
$ sudo service docker stop // 停止docker

這時候你會發現一些docker的script是被deny,因為這邊的user本身是沒有被permission,可以藉由下面的script去修正

$ sudo usermod -G docker ec2-user

退出 instance 再重新連線到 instance 內就可以使用 docker

$ ./nodes.sh 1

為了讓容器之間可以相互連線,當然需要一組溝通用IP

$ ifconfig

在 init Docker-Swarm前我們要複製 eth0 裡的 IP (以上圖來說就是inet 172.31.22.81)

$ docker swarm init --advertise-addr=<- your eth0 inet IP ->

這時候會產生一組token跟default port讓其他workers之間可以相互溝通

$ ./nodes.sh 2
$ docker swarm join --token <- your token -> <- IP:PORT ->

如果你去看docker network你會發現雖然他們是不同的container但都被放置在同樣的Namespace

$ docker network inspect ingress

到這邊基本上我們的 docker swarm 已經完成 90% ,最後的地方當然是建立服務

$ docker pull <- your image ->

把 Image 從 dockerHub 抓下來後

$ docker service create \
--name=<- your service name -> \
--env-file=<- your environment variable ->
--publish=80:80 \
<- your image name ->

最後的最後為了要避免nodes突然掛點或是避免traffic issue,可以把原先的cloning出來

$ docker service update --replicas <- number of replicas your want -> <- your service name ->

大功告成~~

這邊提供我的電子商務side project docker image 給大家練習,這樣就可以跳過前面需要準備 docker image 的時間

環境參數設定

JWT_SECRET=
imgur_id=
URL= // your instance url
MERCHANT_ID= // 藍新金流商店ID
HASH_KEY= // 藍新金流商店HASH_KEY
HASH_IV= // 藍新金流商店HASH_IV
GMAIL_ACCOUNT= // GMAIL_ACCOUNT
clientId= // GCP的clientId
clientSecret= // GCP的clientSecret
refreshToken= // GCP的refreshToken
testEmail= // testEmail
PM2_SECRET_KEY= // PM2的SECRET_KEY
PM2_PUBLIC_KEY= // PM2的PUBLIC_KEY
JAWSDB_URL= // RDBMS url
MONGODB_URI= // NOSQL MONGODB url
REDIS_CACHE_URL= // REDIS url
REDIS_URL= // REDIS url

--

--