微服務從代碼到k8s部署應有盡有大結局(k8s部署)

我們用一個系列來講解從需求到上線、從代碼到k8s部署、從日誌到監控等各個方面的微服務完整實踐。

整個項目使用了go-zero開發的微服務,基本包含了go-zero以及相關go-zero作者開發的一些中間件,所用到的技術棧基本是go-zero項目組的自研組件,基本是go-zero全家桶了。

實戰項目地址:https://github.com/Mikaelemmmm/go-zero-looklook

1、概述

上一節,我們已經把gitlab、jenkins、harbor、k8s都已經搭建好了,這一節我們來編寫jenkins的pipline將我們的服務通過jenkins完整的發佈到k8s中。

2、部署中間件

將mysql、redis、es等部署到k8s之外 , 模擬用作線上獨立環境(至於線上你想把某些中間件部署到k8s內部這個自行處理,本次重點是如何將go-zero開發的微服務部署到k8s集羣內部),這裏我就直接使用項目下的docker-compose-env.yaml了,把所有依賴的第三方中間件環境直接安裝在srv-data.com(192.168.1.181)這臺服務器,前提是這臺服務器已經安裝好docker、docker-compose。

登陸到 192.168.1.181

$ mkdir data && cd data && vim docker-compose.yml
$ docker-compose up -d
$ docker-compose ps #查看確認

3、獨立配置

將每個服務的配置都獨立出來,統一放在一個git倉庫,這樣只給一個人線上倉庫的權限,如果線上配置有變直接修改這個倉庫的文件,在jenkins做cd的時候,會先拉取代碼再拉取對應服務的配置自動構建,具體可以看後面的pipline。

【問】爲什麼不用配置中心?

1)修改db、redis等需要重啓服務,但是有一些配置又不需要重啓服務,運維又要去記,記混了比較容易造成線上事故

2)方便回滾。我們發新版本到線上,並且又改了新版本配置。這時候線上用戶反饋有問題,線上需要快速回滾的話,如果我們使用將文件構建到鏡像中,直接使用k8s一行命令就可以將上一個版本代碼加配置直接回滾回來。如果使用了配置中心,回滾了代碼,還要將上個版本的配置去配置中心改回來,很麻煩。

獨立線上倉庫目錄結構如下(這個結構是跟pipline中寫法相關的)

倉庫地址 : https://github.com/Mikaelemmmm/go-zero-looklook-pro-conf , 直接下載就好

1、修改配置中的中間件,數據庫、redis等都要改成192.168.1.181這臺機器,我們把這臺機器當成線上環境的中間件。

2、另外一個就是我們的服務發現,線上我們部署在k8s中,go-zero直接支持k8s服務發現,所以不需要etcd等,我們在配置zrpc client的時候,要改成target,k8s的配置方式。

4、編寫 jenkins 的 pipline

4.1 配置參數

訪問 http://192.168.1.180:8989/ 打開jenkins,進入jenkins首頁,點擊左側菜單新建Item

我們先創建 identity 授權服務的流水線

然後點擊“General” , 選擇“This project is parameterized” , "添加參數",“Choice Parameter”,如下圖

然後編寫內容如下

直接保存。

4.2 編寫pipline

向下滑動找到Pipeline script,填寫腳本內容

pipeline {
  agent any
  parameters {
      gitParameter name: 'branch', 
      type: 'PT_BRANCH',
      branchFilter: 'origin/(.*)',
      defaultValue: 'master',
      selectedValue: 'DEFAULT',
      sortMode: 'ASCENDING_SMART',
      description: '選擇需要構建的分支'
  }

  stages {
      stage('服務信息')    {
          steps {
              sh 'echo 分支:$branch'
              sh 'echo 構建服務類型:${JOB_NAME}-$type'
          }
      }

      stage('拉取代碼') {
          steps {
              checkout([$class: 'GitSCM', 
              branches: [[name: '$branch']],
              doGenerateSubmoduleConfigurations: false, 
              extensions: [], 
              submoduleCfg: [],
              userRemoteConfigs: [[credentialsId: 'gitlab-cert', url: 'ssh://[email protected]:2222/root/go-zero-looklook.git']]])
          }   
      }

      stage('獲取commit_id') {
          steps {
              echo '獲取commit_id'
              git credentialsId: 'gitlab-cert', url: 'ssh://[email protected]:2222/root/go-zero-looklook.git'
              script {
                  env.commit_id = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
              }
          }
      }

      stage('拉取配置文件') {
              steps {
                  checkout([$class: 'GitSCM', 
                  branches: [[name: '$branch']],
                  doGenerateSubmoduleConfigurations: false, 
                  extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'conf']], 
                  submoduleCfg: [],
                  userRemoteConfigs: [[credentialsId: 'gitlab-cert', url: 'ssh://[email protected]:2222/root/go-zero-looklook-pro-conf.git']]])
              }   
      }

      stage('goctl版本檢測') {
          steps{
              sh '/usr/local/bin/goctl -v'
          }
      }
      
      stage('Dockerfile Build') {
          steps{
                 sh 'yes | cp  -rf conf/${JOB_NAME}/${type}/${JOB_NAME}.yaml  app/${JOB_NAME}/cmd/${type}/etc'   //線上配置文件
                 sh 'cd app/${JOB_NAME}/cmd/${type} && /usr/local/bin/goctl docker -go ${JOB_NAME}.go && ls -l'
                 script{
                     env.image = sh(returnStdout: true, script: 'echo ${JOB_NAME}-${type}:${commit_id}').trim()
                 }
                 sh 'echo 鏡像名稱:${image} && cp app/${JOB_NAME}/cmd/${type}/Dockerfile ./  && ls -l && docker build  -t ${image} .'
          }
      }

      stage('上傳到鏡像倉庫') {
          steps{
          	  //docker login 這裏要注意,會把賬號密碼輸出到jenkins頁面,可以通過port.sh類似方式處理,官網文檔有這裏我就不詳細寫了
              sh 'docker login --username=${docker_username} --password=${docker_pwd} http://${docker_repo}' 
              sh 'docker tag  ${image} ${docker_repo}/go-zero-looklook/${image}'
              sh 'docker push ${docker_repo}/go-zero-looklook/${image}'
          }
      }

      stage('部署到k8s') {
          steps{
              script{
                  env.deployYaml = sh(returnStdout: true, script: 'echo ${JOB_NAME}-${type}-deploy.yaml').trim()
                  env.port=sh(returnStdout: true, script: '/root/port.sh ${JOB_NAME}-${type}').trim()
              }

              sh 'echo ${port}'

              sh 'rm -f ${deployYaml}'
              sh '/usr/local/bin/goctl kube deploy -secret docker-login -replicas 2 -nodePort 3${port} -requestCpu 200 -requestMem 50 -limitCpu 300 -limitMem 100 -name ${JOB_NAME}-${type} -namespace go-zero-looklook -image ${docker_repo}/${image} -o ${deployYaml} -port ${port} --home /root/template'
              sh '/usr/local/bin/kubectl apply -f ${deployYaml}'
          }
      }

       stage('Clean') {
           steps{
               sh 'docker rmi -f ${image}'
               sh 'docker rmi -f ${docker_repo}/${image}'
               cleanWs notFailBuild: true
           }
       }
  }
}

非常重要!!!

  1. 構建優化:pipline中生成dockerfile的時候,我們是使用k8s方式部署不需要etcd,但是這種方式部署需要指定賬號(有去k8s的endpoints中get的權限,使用默認default就好了,每次創建一個新的命名空間k8s會自動幫我們創建好一個default),但是使用goctl 生成的 k8s yml沒有添加指定賬號選項,這個已經反饋了,可能後續版本會加上,這裏我們也用模版做了,同樣模版是在項目目錄下https://github.com/Mikaelemmmm/go-zero-looklook/tree/main/deploy/goctl,pipline中構建指定這個模版即可

  2. ${credentialsId}要替換爲你的具體憑據值,即【添加憑據】模塊中的一串字符串,我們之前配置的是gitlab-cert所以這裏就填寫gitlab-cert,如果你不是這個自己要更換,${gitUrl}需要替換爲你代碼的git倉庫地址,其他的${xxx}形式的變量無需修改,保持原樣即可。

  3. 這裏跟官方文檔有一點點不一樣,由於我項目文件夾目錄不同,goctl生成的dockerfile文件我手動做了點調整,在一個我不是在構建時候生成的dockerfile,是在創建項目時候就把dockerfile一起放在目錄下,這樣構建鏡像時候不需要goctl了

5、配置k8s拉取私有倉庫鏡像

k8s在默認情況下,只能拉取harbor鏡像倉庫的公有鏡像,如果拉取私有倉庫鏡像,則是會報 ErrImagePullImagePullBackOff 的錯誤

1、先在jenkins發佈機器登陸harbor

$ docker login 192.168.1.180:8077
$ Username: admin
$ Password:
Login Succeeded

2、在k8s中生成登陸harbor配置文件

#查看上一步登陸harbor生成的憑證
$ cat /root/.docker/config.json  
{
	"auths": {
		"192.168.1.180:8077": {
			"auth": "YWRtaW46SGFyYm9yMTIzNDU="
		}
}

3、對祕鑰文件進行base64加密

$ cat /root/.docker/config.json  | base64 -w 0

ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjEuMTgwOjgwNzciOiB7CgkJCSJhdXRoIjogIllXUnRhVzQ2U0dGeVltOXlNVEl6TkRVPSIKCQl9Cgl9Cn0=

4、創建docker-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: docker-login
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjEuMTgwOjgwNzciOiB7CgkJCSJhdXRoIjogIllXUnRhVzQ2U0dGeVltOXlNVEl6TkRVPSIKCQl9Cgl9Cn0=
$ kubectl create -f docker-secret.yaml -n go-zero-looklook

secret "docker-login" created

6、構建

我們進入首頁,點擊idenity進入詳情頁

然後可以看到,上面我們配置好的identity服務,如下圖 ,點擊“Build with Parameters”, 然後選擇rpc,點擊“開始構建”

第一次構建在拉代碼時候都會失敗,應該是初始化啥東西,再點一次就好了。

部署成功

同樣道理,去構建identity-api,再去配置usercenter服務 構建usercenter-rpc、構建usercenter-api,接着配置其他服務、構建即可,本次我們先只構建identity-api、identity-rpc、usercenter-rpc、usercenter-api給大家演示。

6、添加網關

因爲我們的api服務通過goctl發佈在k8s中都會暴露nodeport端口,索引我們看下k8s中go-zero-looklook命名空間下的service的nodeport端口服務,然後將nodeport配置在nignx即可。

本次我們獨立一臺虛擬機在k8s之外,安裝nginx,將k8s後端api服務通過nodeport方式把端口暴露給nginx,然後nginx在配置中配置此api服務,這樣nginx就充當網關使用。

nginx的安裝就不再這裏多說了,記得一定要有auth_request模塊,沒有的話自己去安裝。

nginx的配置

server{
    listen 8081;
    access_log /var/log/nginx/looklook.com_access.log;
    error_log /var/log/nginx//looklook.com_error.log;

    location /auth {
	    internal;
      proxy_set_header X-Original-URI $request_uri;
	    proxy_pass_request_body off;
	    proxy_set_header Content-Length "";
	    proxy_pass http://192.168.1.182:31001/identity/v1/verify/token;
    }

    location ~ /usercenter/ {
       auth_request /auth;
       auth_request_set $user $upstream_http_x_user;
       proxy_set_header x-user $user;

       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header REMOTE-HOST $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_pass http://192.168.1.182:31002;
   }

   location ~ /travel/ {
       auth_request /auth;
       auth_request_set $user $upstream_http_x_user;
       proxy_set_header x-user $user;

       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header REMOTE-HOST $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_pass http://192.168.1.182:31003;
   }

   location ~ /order/ {
       auth_request /auth;
       auth_request_set $user $upstream_http_x_user;
       proxy_set_header x-user $user;

       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header REMOTE-HOST $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_pass http://192.168.1.182:31004;
   }

   location ~ /payment/ {
       auth_request /auth;
       auth_request_set $user $upstream_http_x_user;
       proxy_set_header x-user $user;

       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header REMOTE-HOST $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_pass http://192.168.1.182:31005;
   }
}

如果是線上的話,應該配置多臺nignx保持高可用,在nignx前面還會有一個slb,你的域名包括https配置都應該解析到slb,在slb前面在有防火牆等這些。

8、結束語

至此,整個系列就結束了,整體架構圖應該如第一篇所展示,本系列希望能給你帶來幫助。

項目地址

https://github.com/zeromicro/go-zero

歡迎使用 go-zerostar 支持我們!

微信交流羣

關注『微服務實踐』公衆號並點擊 交流羣 獲取社區羣二維碼。

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