web專案遷移到k8s
這篇文章應該會很長。
前言
小說 是我以前寫的一個專案,主要是為了練手vue,後端用lumen(php框架)寫的。附上碼雲的連結 vue-novel,前後端程式碼都很簡單。最近把它遷移到了k8s,配合gitlab-runner和rancher-ui實現了CI/CD,在此記錄一下。附上遷移後的專案地址:
最開始這個專案是怎麼執行的呢?我在vultr買了個vps,安裝 lnmp 整合環境,專案程式碼用FTP傳上去,配置一下nginx就跑起來了。遷移到k8s後,提交和釋出程式碼的大致流程如下:
- 把程式碼推送到master分支
- gitlab-runner自動打包映象並推送到docker私有倉庫
- 進入rancher後臺介面,把專案的映象更新為剛才的映象
可以看到,我們要做的僅僅是推送程式碼,然後去後臺更新專案的映象,專案就上線了。
需要準備的
- 至少兩臺vps,並且相互之間可以ping通。
- gitlab倉庫(自己搭建或直接用官網都行)。
- 自己的域名。
需要做的
- 打包兩個docker的基礎映象。所有後端程式碼用一個基礎映象,前端程式碼用另一個。
- 搭一個k8s叢集。我選擇用 k3s。這是個精簡版的k8s,功能夠用,搭建簡單,對機器配置要求低。
- 搭一個rancher-ui。rancher2.0,搭建也很簡單,用來視覺化地操作k8s叢集。
- 搭一個docker私有倉庫。有 官方映象,可以參考一下,我是搭好集群后直接用rancher搭了個docker私有倉庫。
- 搭一個gitlab或者用 官網,把專案放進去。我是直接用的官網。
- 配置gitlab-runner
- 改一下專案的目錄結構,給專案編寫 .gitlab-ci.yml、Dockerfile、nginx.conf 3個檔案
- 最最重要的一點,把機器(也就是vps)配置好,不然會出現各種問題。
vps配置
每臺vps都要配置。
#!/bin/sh
# 1. stop firewalld
systemctl stop firewalld && systemctl disable firewalld
# 2. stop SElinux
sudo sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
# 3. set timezone
timedatectl set-timezone Asia/Shanghai
# 4
yum install vim htop -y
# 5. increase swap
dd if=/dev/zero of=/home/swap bs=1024 count=5120000
/sbin/mkswap /home/swap
/sbin/swapon /home/swap
# 6. install docker
curl -fsSL get.docker.com | sh
systemctl start docker && systemctl enable docker
複製程式碼
增加交換記憶體是因為我機器配置不夠,才1G記憶體;防火牆和SElinux是一定要關閉的,不然叢集肯定搭建不成功;docker也要安裝一下。
基礎映象打包
程式碼上容器肯定要用映象,說一下需要什麼映象。
後端用php,那麼需要一個nginx-php映象,我在github上找了一個,不過有一點小bug,fork過來稍微改了下,附上鍊接:nginx-php。 這個映象基於alpine,然後原始碼安裝了php和nginx,我們自己擴充套件和更新比較方便。根據這個Dockerfile打包映象,然後推送到 dockerhub,最終得到一個 nginx-php映象。如果不想讓你的基礎映象公開,可以不推到dockerhub,等私有倉庫搭好後放到私有倉庫。至於怎麼打包和推送映象,這個比較簡單,就不細說了。
前端的同理,把Dockerfile裡安裝php相關的部分刪掉,打包並推送映象,最終得到一個 nginx 映象。
搭建k8s叢集
server搭建
使用k3s搭建叢集其實就是幾個命令的事,但是國內伺服器不行,因為k8s依賴pause映象,這個映象你在國內肯定下不下來,所以國內搭叢集只能手動。
自動搭建
執行官方指令碼。
curl -sfL https://get.k3s.io | sh -
複製程式碼
看到systemd: Starting k3s就可以了。修改配置:
vim /etc/systemd/system/multi-user.target.wants/k3s.service
複製程式碼
把ExecStar的值改為
/usr/local/bin/k3s server --docker --no-deploy traefik --cluster-secret=hjp
複製程式碼
- --docker 用docker做底層容器(預設的是containerd)
- --no-deploy traefik 不安裝traefik元件
- --cluster-secret=hjp 設定密碼,待會新增agent(節點)就不需要去檢視token了
然後重新載入配置,重啟k3s。
systemctl daemon-reload
systemctl restart k3s
複製程式碼
執行
k3s kubectl get nodes
複製程式碼
檢視一下節點
有一個master節點,這是安裝server的時候自帶的,這樣其實就已經建立了有一個master節點的k8s叢集。注意這裡有個坑。 按照官方檔案的說法,其實可以直接執行命令的時候指定配置
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--docker --no-deploy traefik --cluster-secret=hjp" sh -
複製程式碼
這樣就不用再修改配置。但是這樣啟動k3s後,後面搭建docker私有倉庫、docker-registry配置ingress會一直顯示initializing,所以還是安裝後手動修改配置吧。
手動搭建
我是國外的伺服器,所以直接用指令碼搭建的,k3s的 官方檔案 最下面寫了怎麼手動搭建。其實就是去github上把 k3s 下載,然後上傳到伺服器執行。然而國內伺服器要多做一步,即在這之前先把pause映象手動下載,重新打個tag。dockerhub上有個映象谷歌倉庫,附上鍊接 pause映象。
docker pull mirrorgooglecontainers/pause:3.1
docker tag mirrorgooglecontainers/pause:3.1 k8s.gcr.io/pause:3.1
複製程式碼
把下載的k3s檔案複製到/usr/local/bin/k3s
cp ./k3s /usr/local/bin/k3s
chmod 777 /usr/local/bin/k3s
複製程式碼
啟動k3s
k3s server &
複製程式碼
之後的操作步驟應該跟自動搭建是一樣的。
k3s命令目錄
k3s命令目錄在/usr/local/bin/
要解除安裝的話,先執行k3s-killall.sh,再執行k3s-uninstall.sh。
搭建rancher-ui
ui搭建
接下來要搭個 rancher 介面來操作叢集,其實也是一個命令的事。進入另一臺vps,執行
docker run -d -v /var/lib/rancher/:/var/lib/rancher/ --restart=unless-stopped --name rancher-server -p 80:80 -p 443:443 rancher/rancher:stable
複製程式碼
注意rancher和k3s不能裝在同一臺機器上,不然這個容器啟動會報錯。k3s V0.8.1版本的時候還是可以的,不知道最近更新了什麼,附上 github該問題的連結。把域名(rancher.hjply.com)指向這臺vps的ip,然後瀏覽器訪問rancher.hjply.com。由於rancher是自簽名證書,會彈出安全警告,直接無視即可。
設定密碼後進入。
搭建完成,右下角可以切換語言。
叢集匯入
把叢集匯入rancher後,才能視覺化地操作叢集。
在剛才的頁面點選 "新增叢集",選擇 “匯入現有的Kubernetes叢集”, 名字隨便寫個,點建立
進入這個頁面複製最後一條命令,在k3s server那臺機器上執行
過一會自動跳轉到這個頁面狀態會從waiting變成active,表示匯入完成。
如果這個狀態一直沒變化,或者頁面沒有自動跳轉,估計就是防火牆、SElinux沒關,或者k3s和rancher兩臺機器互相ping不通。
匯入成功後檢視一下叢集。
可以看到有一個節點,就是k3s server自帶的master節點,如果有需要可以繼續新增節點。
叢集新增節點
再開一臺機器,vps配置同上,然後配置一個host
vi /etc/hosts
複製程式碼
加一條
127.0.0.1 vultr3
複製程式碼
執行命令
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--docker --node-name=vultr3" K3S_URL=https://217.69.8.236:6443 K3S_CLUSTER_SECRET=hjp sh -
複製程式碼
- --node-name一定要設定,還要把節點名稱(隨便填寫,如:vultr3)指向本機ip,並且node-name不能和已有的節點名稱重複。如果不設定node-name就會預設使用機器的hostname,可能會重複導致加入叢集失敗。
- K3S_URL就是k3s server就填k3s server這臺機器的ip
- K3S_CLUSTER_SECRET就是建立k3s server時候設定的密碼
再檢視一下叢集。
看到有2個節點,表示成功。
Docker私有倉庫搭建
直接用rancher搭建私有倉庫比較方便。
先進入叢集頁面,建立一個專案。點選新增專案,專案名稱隨便寫,系統的這2個專案(Default和System)不要動。
進入這個專案,然後進到應用商店。
點“啟動”,選擇docker-registry,點“檢視詳情”進入部署頁面。
部署的時候需要注意2點。
- 需要一個ssl證書
- 需要手動生成帳號密碼
為什麼需要啟用https?因為我們要使用帳號密碼控制私有倉庫的訪問許可權,不能誰都可以往裡面push映象,而啟用帳號密碼就必須用https(官方檔案要求,如圖)。
直接在阿里雲申請個免費證書,下載到電腦
接下來就是生成帳號密碼。進入k3s server那臺機器(一定要用這臺機器,因為不同機器生成的密碼不一樣),依次執行:
mkdir -p /home/registry/auth
docker run --entrypoint htpasswd registry -Bbn hjp hjp >>/home/registry/auth/htpasswd
cat /home/registry/auth/htpasswd
複製程式碼
(帳號hjp,密碼hjp)_
複製一下生成的密碼,填入部署頁面
配置一下負載均衡,使用自定義域名(registry.hjply.com指向k3s server這臺機器)
點選啟動,就建立了docker倉庫。這裡我沒有做持久化配置,所以容器刪掉后里面的映象也會被刪除。最後還差一步配置ssl和帳號密碼。
進入證書頁面
新增證書,把從阿里雲下載的證書匯入,點選儲存即可。然後升級一下倉庫的ingress,點選“升級”,把SSL證書勾選上,儲存。
這樣倉庫的https就配置好了,我們測試一下,開啟網頁 registry.hjply.com/v2/_catalog
輸入賬號密碼
看到倉庫是空的,裡面沒有映象,到此docker私有倉庫就搭建完了。最後還要把倉庫的賬號密碼儲存在叢集,因為待會拉取映象需要許可權認證。
點選映象庫憑證
把帳號密碼填寫一下,儲存即可。
gitlab-runner配置
gitlab-runner有3種,即
- Specific Runners
- Shared Runners
- Group Runners
其中Specific Runners是針對專案的,每個專案可以分別配置自己的runner;
Shared Runners是gitlab上別人共享出來的runner,我們不用,把它禁用掉;
Group Runners是針對專案組的,只要給專案組配置一個runner,組內的所有專案都可以使用這個runner。
新建一個group,把專案都放進去
進入group_hjp的CI/CD配置頁面
可以看到現在還沒有安裝runner。找一下 檔案,裡面有寫怎麼安裝gitlab-runner,我們直接在vps上安裝,依次執行
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash
sudo yum install gitlab-runner
複製程式碼
即可。安裝之後需要註冊,執行
gitlab-runner register
複製程式碼
- URL填gitlab的地址,如果沒有自己搭建的話,就是https://gitlab.com/
- token去剛才CI/CD的頁面複製一下
- description隨便寫
- tags隨便寫,多個用逗號分隔
- executor看你的gitlab-runner用來做什麼,我是用來執行shell,所以選shell
這樣就註冊完成了。重新整理網頁驗證一下
進入到專案的CI/CD頁面,驗證Groups Runners是否可用。
最後,因為待會要用這個runner打包和推送映象到docker私有倉庫,所以還需要配置一下docker。
先把私有倉庫地址加入docker配置檔案(新版docker沒有這個檔案,直接vim建立即可)
vim /etc/docker/daemon.json
複製程式碼
把私有倉庫地址寫入檔案,儲存退出。
重新載入docker配置
systemctl reload docker
複製程式碼
同理,在k3s server上也要把私有倉庫地址加到/etc/docker/daemon.json配置檔案裡,因為拉取映象需要用。
然後切換到gitlab-runner使用者,登入registry.hjply.com並儲存賬號密碼
如果報 /var/run/docker.sock 沒有許可權的錯誤,需要把gitlab-runner這個使用者新增到docker使用者組
usermod -G docker gitlab-runner
複製程式碼
到這裡gitlab-runner和docker配置就完成了。
專案改造
以後端程式碼為例,先把目錄層級改一下。
我們加個src目錄,把程式碼全放進去,然後開始編寫 .gitlab-ci.yml、Dockerfile、nginx.conf檔案
nginx.conf
server {
listen 80 default_server;
client_max_body_size 5m;
client_body_buffer_size 256k;
client_header_buffer_size 256k;
large_client_header_buffers 4 8k;
set $rootPath '/data/src/public';
root $rootPath;
index index.php index.html index.htm;
server_name localhost;
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php/$1 last;
}
location ~ ^(.+\.php)(.*)$ {
fastcgi_pass unix:/usr/local/php/var/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_buffer_size 128k;
fastcgi_buffers 256 16k;
client_body_buffer_size 1024k;
include fastcgi_params;
}
}
複製程式碼
這就是個很普通的php專案nginx配置,就不多說了。
Dockerfile
FROM hongjiapei/nginx-php
COPY nginx.conf /usr/local/nginx/conf.d/nginx.conf
COPY src /data/src
RUN chown -R www-data.www-data /data/src/ && chmod -R 755 /data/src \
&& rm -rf /usr/local/php/etc/php-fpm.d/www.conf
WORKDIR /data/src
EXPOSE 80
CMD sh -c 'nginx && php-fpm -D && tail -f /usr/local/nginx/logs/error.log'
複製程式碼
繼承了我們之前打包的nginx-php映象,然後用自己的nginx.conf覆蓋掉預設的配置,最後前臺啟動nginx和php-fpm、列印nginx錯誤日誌。注意這裡不能後臺啟動nginx和php-fpm,不然等你命令執行完了容器就自動退出了。
.gitlab-ci.yml
stages:
- build
- push
build_image:
stage: build
script:
- ls -la
- CI_COMMIT_TAG=`git log | grep -e "^commit.*" | wc -l` && docker build --pull -t registry.hjply.com/group_hjp/xsbe:"$CI_COMMIT_TAG" .
only:
- master
tags:
- abc
push_image:
stage: push
script:
- CI_COMMIT_TAG=`git log | grep -e "^commit.*" | wc -l` && docker push registry.hjply.com/group_hjp/xsbe:"$CI_COMMIT_TAG" && docker rmi registry.hjply.com/group_hjp/xsbe:"$CI_COMMIT_TAG"
only:
- master
tags:
- abc
複製程式碼
這裡分為兩步,第一步打包映象,第二步推送映象。only:master表示只有master推送的時候才啟動流水線,tags:abc表示使用tag包含abc的runner,所以剛才註冊gitlab-runner寫的tag是什麼這裡就寫什麼,git log | grep -e "^commit.*" | wc -l 表示git日誌裡帶有commit關鍵字的條數,一般提交一次就多一條,我們用這個數字作為映象的tag,推送完映象後把本機的映象刪掉。
到這裡配置就全部完成了,接下來提交程式碼測試一下。
提交和釋出程式碼
提交程式碼
在master提交程式碼,進入專案頁面檢視
可以看到專案正在執行流水線,點進去看下
等兩個階段都成功就表示執行完成,檢視一下映象
剛才提交的程式碼映象是registry.hjply.com/group_hjp/xsbe:4
釋出程式碼
初次部署
進入rancher後臺,第一次需要部署服務,以後只需要更新。
點選“部署服務”,使用剛才的映象啟動,把80埠暴露出來,部署服務之前要確保兩件事
- k3s server這臺機器 /etc/docker/daemon.json已經配置了insecure-registry
- 已經在叢集儲存了映象庫憑證
如果沒配置好,映象拉取會失敗的。
等狀態變成active就表示部署完成
然後配置ingress,這樣就可以通過域名把請求轉發到容器。
進入“負載均衡”,點選“新增ingress規則”
把域名指向容器的80埠,儲存。
初次部署基本完成,開啟網頁驗證一下(要提前把這個域名指向k3s server這臺機器)。
專案配置
剛才只用了一個pod啟動專案,如果效能不夠,可以多加幾個pod,點選那個“+”號即可。
到這裡專案還沒有完全部署完成,還差最後一步,即配置檔案。lumen的配置檔案為.env檔案,一般資料庫、redis配置都寫在裡面,這個檔案肯定不會放在git裡,下面說一下怎麼給專案新增配置檔案。
點選“配置對映”
鍵就用配置檔案的檔名.env,值就是檔案內容,可以填多行,儲存,然後升級專案。
給專案新增一個ConfiMap卷,儲存。
等專案自動更新pod。
更新完成,隨便進入一個pod,檢視一下是否有.env檔案。
有.env檔案,開啟看一下是否正確
跟剛才配置的一樣,到這裡初次部署就完成了。
專案更新
專案更新就比較簡單了,新增一個介面xsbe.hjply.com/test,在master提交程式碼,等流水線執行完,然後去看看映象的tag是什麼
去rancher後臺更新一下專案
把tag改為剛才映象的tag,儲存即可。
等pod更新完後,開啟網頁驗證一下
說明程式碼更新成功。
流水線失敗的處理
流水線失敗不可怕,根據報錯資訊去解決即可。以前端專案為例,提交程式碼後發現流水線失敗了
點進去看看報錯資訊
發現是npm命令找不到,原來是gitlab-runner這臺機器忘了裝nodejs,安裝一下
yum install nodejs -y
複製程式碼
點選最右邊的重新整理按鈕重新執行流水線
成功後去看看映象的tag
去rancher後臺部署一下
配置ingress
部署完成,開啟網頁測試一下
到這裡就完成了。
最後我們看一下私有倉庫裡的映象
就是我們剛才推送的2個映象。
最後
- 資料庫並沒有打算用k8s來部署,因為資料庫是有狀態應用,要考慮資料的儲存、可用性、擴充套件性、事務、災備等等,太複雜了。
- docker-registry應該把資料存在機器上,不然重啟就沒了,當然最好還是不要用k8s來部署。
- 每次master提交都會生成一個映象,這樣釋出和回滾程式碼都比較方便。
- 機器不夠了可以隨時新增,專案掛了會自動重啟,重試若干次還是沒有成功才會啟動失敗。
- rancher還有很多功能,可以看 官方檔案