1. 程式人生 > 程式設計 >web專案遷移到k8s

web專案遷移到k8s

這篇文章應該會很長。

前言

小說 是我以前寫的一個專案,主要是為了練手vue,後端用lumen(php框架)寫的。附上碼雲的連結 vue-novel,前後端程式碼都很簡單。最近把它遷移到了k8s,配合gitlab-runner和rancher-ui實現了CI/CD,在此記錄一下。附上遷移後的專案地址:

最開始這個專案是怎麼執行的呢?我在vultr買了個vps,安裝 lnmp 整合環境,專案程式碼用FTP傳上去,配置一下nginx就跑起來了。遷移到k8s後,提交和釋出程式碼的大致流程如下:

  1. 把程式碼推送到master分支
  2. gitlab-runner自動打包映象並推送到docker私有倉庫
  3. 進入rancher後臺介面,把專案的映象更新為剛才的映象

可以看到,我們要做的僅僅是推送程式碼,然後去後臺更新專案的映象,專案就上線了。

需要準備的

  1. 至少兩臺vps,並且相互之間可以ping通。
  2. gitlab倉庫(自己搭建或直接用官網都行)。
  3. 自己的域名。

需要做的

  • 打包兩個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點。

  1. 需要一個ssl證書
  2. 需要手動生成帳號密碼

為什麼需要啟用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埠暴露出來,部署服務之前要確保兩件事

  1. k3s server這臺機器 /etc/docker/daemon.json已經配置了insecure-registry
  2. 已經在叢集儲存了映象庫憑證

如果沒配置好,映象拉取會失敗的。

等狀態變成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還有很多功能,可以看 官方檔案