某小公司專案環境部署演變之路

邵磊發表於2018-04-24

前言

在環境部署問題上,我們經歷了3個階段:傳統安裝、映象恢復、自動發現註冊+指令下達。目前映象恢復後,啟動虛擬機器,一旦能ping通我們公司地址,就會自動註冊這臺機器(即使沒有其他外網訪問許可權、也未開放任何對外埠),我們也就有了這臺機器的管理許可權,可批量群控下發指令。(第二階段、第三階段均為我自主設計。)

某小公司專案環境部署演變之路

背景

我們是一家產品+定製化需求公司,專案做好之後會直接部署到客戶伺服器上。而客戶很少選擇雲伺服器,因為他們有自己的機房,部署前會提供給我們1-2臺虛擬機器,然後整個環境部署問題就交給我們了。

演變

第一階段:傳統安裝

使用時間:?~2016年

  1. 需甲方提供windows或linux伺服器遠端連線方式(這裡各個甲方提供都不一樣,有堡壘機、vpn、直接定向開放埠、vpn+堡壘機等)非常複雜,只能case by case
  2. 遠端到伺服器上
  3. 上傳資料庫、jdk、tomcat各類安裝包(受限頻寬因素,往往很耗時)
  4. 安裝安裝資料庫
  5. 安裝jdk、tomcat、nginx(linux環境下,使用寫好的sh指令碼直接執行,依然比較耗時)
  6. 人工部署war包等 等

某小公司專案環境部署演變之路
此方式缺點太多,往往需要3-5人天才能完成所有部署,但我們只有一位運維人員,所以當專案衝突時,極為被動。而且因為各個軟體版本發生變動、甲方提供的虛擬機器3個碟符、2個碟符,或者沒有D盤(雖然可以通過計算機管理更改驅動器顯示號,但可能導致其他軟體無法執行)所以環境比較亂。

這種方式比較老,我也不介紹更多。當然,據我瞭解,目前還有一些小公司在沿用這種部署方式,所以在這裡勸採用這種方式的公司儘快完成轉型。

第二階段:映象恢復

使用時間:2016年~2017年

  1. 需甲方提供windows或linux伺服器遠端連線方式(這裡各個甲方提供都不一樣,有堡壘機、vpn、直接定向開放埠、vpn+堡壘機等)非常複雜,只能case by case
  2. 使用vm映象恢復虛擬機器並設定好ip(內含docker)
  3. 通過deploy模組一鍵部署war包

deloy模組
此方式,我們將第一階段的2、3、4、5封裝成vm虛擬機器映象、開發了deploy模組、抽取專案無狀態。

這時我們對運維人員依賴大大減少,工作量大大減少至2-6小時。(這個階段起,我們公司沒有運維人員,進入DevOps時代。事實上,此階段初我們運維人員離職,使得我不得不加快設計)

第三階段:自動發現註冊+指令下達

使用時間:2017年~2018年

  1. 甲方使用我們vm映象恢復並設定好ip,保證能ping通我們公司地址
  2. 自動發現註冊+指令下達
  3. 通過deploy模組一鍵部署war包

此階段,我們部署耗時在5-10分鐘,而且我們不再需要甲方提供遠端,我們還可以批量管理所有機器,不僅滿足了此時的需求,併為後面擴充套件做了鋪墊。

具體技術

這裡主要講二、三兩個階段

因為傳統方式缺點特別多,所以在我向領導介紹方案後,領導很感興趣,很快就安排我著手去幹。為了提高效率,期間選型多款工具或框架組成的方案,本文只介紹最終選型的設計。

frp

frp是一款內網穿透軟體,可以使得沒有外網ip的機器暴露在外網裡,但本文利用它將一臺內網機器埠暴露在另外一個內網中的特性。

安裝frp服務端

選擇一臺內網機器比如172.0.0.2,需臨時保證這臺伺服器走公網固定ip線路

wget --no-check-certificate https://raw.githubusercontent.com/clangcn/onekey-install-shell/master/frps/install-frps.sh -O ./install-frps.sh
chmod 700 ./install-frps.sh
./install-frps.sh install
複製程式碼

全部引數都有預設值,直接回車就是輸入預設值:

Please input frps bind_port [1-65535](Default Server Port: 5443): #輸入frp提供服務的埠,用於伺服器端和客戶端通訊,預設即可
Please input frps vhost_http_port [1-65535](Default vhost_http_port: 80): #輸入frp進行http穿透的http服務埠,建議不用預設
Please input frps vhost_https_port [1-65535](Default vhost_https_port: 443): #輸入frp進行https穿透的https服務埠,建議不用預設
Please input frps dashboard_port [1-65535](Default dashboard_port: 6443):#輸入frp的控制檯服務埠,用於檢視frp工作狀態,預設即可
Please input dashboard_user (Default: admin):#登入控制檯的使用者名稱,預設即可
Please input dashboard_pwd (Default: kpkpM7VZ):#登入控制檯的密碼,如果記不住預設的建議修改
Please input privilege_token (Default: 9m2UAOWa6hx5Eise):#輸入frp伺服器和客戶端通訊的密碼,預設是隨機生成的,預設即可
Please input frps max_pool_count [1-200](Default max_pool_count: 50):#設定每個代理可以建立的連線池上限,預設50
##### Please select log_level #####
1: info
2: warn
3: error
4: debug
#####################################################
Enter your choice (1, 2, 3, 4 or exit. default [1]): 預設即可
Please input frps log_max_days [1-30](Default log_max_days: 3 day):
##### Please select log_file #####
1: enable
2: disable
#####################################################
Enter your choice (1, 2 or exit. default [1]):預設即可
複製程式碼

至此frp服務端就搭建好了

客戶端

這裡我們以linux為例

開啟http://diannaobos.iok.la:81/frp/frp-v0.14.0/

下載frp_0.14.0_linux_amd64.tar.gz檔案,只保留frpc開頭的檔案(frp客戶端)

以frp資料夾形式解壓到linux的home目錄

編寫reg.sh指令碼

reg.sh也放在linux的home目錄

UUID=$(cat /sys/class/dmi/id/product_uuid)
wget -O frpc.ini http://114.114.114.114/frp.php?file=$UUID;
a=`du -s frpc.ini | awk '{print $1}'`  
if [ $a -lt 1 ]  
then  
       echo "none"  
else  
        echo "action"  
	pkill frpc
	sleep 2s
	rm -rf ~/frp/frpc.ini
	cp frpc.ini ~/frp/frpc.ini
	~/frp/./frp.sh
fi
複製程式碼

其中UUID為伺服器唯一標識,即使vm虛擬機器映象相同,但uuid不會相同。

其中114.114.114.114為公司對外註冊中心

編寫crontab

crontab -e
*/5  * * * * ~/reg.sh
複製程式碼

每隔5分鐘執行一次,意思是每隔5分鐘去註冊一次或者說是拉取一次變更請求,當服務端配置不改變時不會重啟服務。

frp開機自啟

linux

chmod +x ~/frp/frp.sh
vi /etc/rc.d/rc.local
#檔案底部追加
bash ~/frp/frp.sh

chmod +x  /etc/rc.d/rc.local
#重啟即可
複製程式碼

frp.php簡易版內容如下

<?php  
$filename=$_GET['file'].'.ini';
$filename='frp/'.$filename;

if(!file_exists($filename)){
	file_put_contents($filename,"");
	file_put_contents($filename.'.update',$_SERVER['REMOTE_ADDR']);
}else{
	if (!file_exists($filename.'.update')){
		$str = file_get_contents($filename);
		echo $str;
		file_put_contents($filename.'.update',$_SERVER['REMOTE_ADDR']);
	}
}
?>
複製程式碼

某小公司專案環境部署演變之路
當有機器註冊時,frp資料夾下會有id對應的檔名,我們只需要在.ini中寫入配置,再刪除.update檔案即可,待服務端收到frp新配置後,會自動再建立一個.update檔案,並且將ip寫入.update檔案。

.ini例子

[common]
server_addr = 114.114.114.114
server_port = 5443
privilege_token =金鑰

[webserver]
type = tcp
local_ip = 127.0.0.1
local_port = 22
use_encryption = false
use_compression = false
remote_port = 7001


[a-web]
type = http
local_ip = 127.0.0.1
local_port = 80
use_encryption = false
use_compression = true
custom_domains = a.a.com
複製程式碼

common為公共部分

webserver是將本地22埠使用隧道技術穿透到公司的172.0.0.2機器裡

內網機器遠端只需訪問172.0.0.2的7001埠

a-web是本機80埠在公司內網中的直接訪問url:a.a.com

某小公司專案環境部署演變之路
通過frp管理後臺,可以實時檢視到各個機器連線情況。

某小公司專案環境部署演變之路

至此,我們可以遠端機器、訪問該機器80埠,理論上可以訪問該機器所有埠,如新增埠穿透,只需要去修改.ini,這是一簡易版的介紹。

再接入ansible即可遠端群控。

ansible

ansible 是一款自動化運維工具,具體使用可參考我另外一篇博文《自動化運維工具ansible的實踐》

外網對映

假設公司外網為114.114.114.114 需將114.114.114.114的5443埠對映到172.0.0.2的5443上,其他埠均不要對映,

docker

某小公司專案環境部署演變之路
前兩年docker很火,DevOps很火,所以我們選擇了docker,以便我們docker映象快速部署我們系統。可參考我另外一篇博文《我是如何重構整個研發專案,促進自動化運維DevOps的落地?》

Portainer

可參考我的另外一篇博文《Docker的web端管理平臺對比(DockerUI 、Shipyard、Portainer、Daocloud)》

deploy

deploy為我們自研,底層原理可參考《java web專案war包自動升級部署方案》

總結

本文主要講利用frp內網穿透、構建隧道的技術實現對無外網、無埠機器的運維部署;利用ansible工具實現群控;利用docker進行快速部署;通過自研deploy進行版本控制等。

該套方案極大的節省了我們的運維成本,使我們這樣的小公司跑步進入了一個無運維人員、DevOps時代。

如果你有類似場景,希望本文對你有所幫助。

相關文章