k8s的咖啡伴侶 -- 自動化部署工具Drone

剛開始打算用Jenkins+shell 部署鏡像到K8S,無意間看到網上推薦的drone,用了之后覺得drone和docker、K8S非常般配,Jenkins更像上一代產品。在這里分享和總結一下drone的使用過程。

通過docker-compose安裝drone,和官網版本差不多,分享一個我的

#  cat drone/docker-compose.yaml
version: '2'

services:
  drone-server:
    image: drone/drone:0.8
    ports:
      - 8078:8000
      - 9000
    volumes:
      - /var/lib/drone:/var/lib/drone/
    restart: always
    environment:
      - DRONE_OPEN=true
      - DRONE_ADMIN=[git user name]
      - DRONE_HOST=[http url]
      - DRONE_GITEA=true
      - DRONE_GITEA_URL=[git url]
      - DRONE_SECRET=aHVubGlqaWRyb25lMTAw
        #   - DRONE_DATABASE_DRIVER=mysql
        #   - DRONE_DATABASE_DATASOURCE=root:123456@tcp(ip:3306)/drone?parseTime=true

  drone-agent:
    image: drone/agent:0.8
    command: agent
    restart: always
    depends_on:
      - drone-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - DRONE_DEBUG=true
      - DRONE_SERVER=drone-server:9000
      - DRONE_SECRET=aHVubGlqaWRyb25lMTAw

歷史原因

  • MVC中V被拆出來,作一個單獨的git庫。我們的項目框架是ThinkPHP3,經典的MVC模式,前端是.tpl文件,里面會用到controller傳遞的變量,所以部署上無法分離。
  • 接著前端加入了webpack/react/vue等等技術棧,生出了10多個不同功能的git庫。drone對合并git倉庫并不友好,這對打包鏡像帶來難度。
  • 我的解決方法是
    1. 把必要的2個代碼庫(php和tpl)通過volume cache插件,互相掛載。當php有更新時,把最新的tpl掛載過來(是最近一次tpl倉庫更新完成才掛載出去的)。反之tpl更新時亦然。
    2. 對于其他git庫,通過nginx反向代理到原服務器上, 后期再剝離部署。

Dockerfile

FROM registry.cn-hangzhou.aliyuncs.com/ns/alpine-php-fpm-nginx

COPY souce_code /server_root/.

php git庫里的.drone.yml

#設置工作目錄
workspace:
  base: /www
  path: php
pipeline:
  build: #集成前后端代碼,打包鏡像
      image: registry.cn-hangzhou.aliyuncs.com/ns/alpine-php-fpm-nginx
      secrets: [ docker_username, docker_password ]
      volumes:
          - /tmp/cache/tpl:/www/tpl
      commands:
          - cp -rf * /www/tpl/
  cache: #把最新的php文件掛載到宿主機
      image: drillster/drone-volume-cache
      rebuild: true
      mount:
        - /www/php
      volumes:
        - /tmp/cache:/cache
  publish-image: #調用目錄下Dockerfile打包鏡像,并push到遠程倉庫
      image: plugins/docker
      registry: registry.cn-hangzhou.aliyuncs.com
      repo: registry.cn-hangzhou.aliyuncs.com/namespace/project #遠程倉庫地址
      secrets: [ docker_username, docker_password ]
      tags: latest
  k8s-deploy: #調用k8s部署鏡像
      image: registry.cn-hangzhou.aliyuncs.com/namespace/deploy #自己做的一個部署鏡像,執行sh命令
      secrets: [ docker_username, docker_password ]
      commands:
          - deploy.sh ${DRONE_REPO_NAME}  ${DRONE_BUILD_NUMBER} ingress_name project:latest #把項目名、構建序號傳遞過去,便于管理版本
  notice: #企業微信通知一下
      image: clem109/drone-wechat
      secrets: [plugin_corpid, plugin_corp_secret, plugin_agent_id]
      to_user: "user token"
      title: "${DRONE_REPO_NAME} build No.${DRONE_BUILD_NUMBER} ${DRONE_PREV_BUILD_STATUS} !"
      description: "Author: ${DRONE_COMMIT_AUTHOR} \nBranch: ${DRONE_COMMIT_BRANCH} \n\n點擊查看drone自動化部署報告->"
      msg_url: ${DRONE_BUILD_LINK}

branches: [ master ] #只對master代碼觸發部署

接著,介紹下k8s master上的相關腳本

目錄結構

project
│   deployment.yaml #部署模板
│   upgrade.sh #執行部署任務,藍綠發布
│   keepone.sh #php服務占用內存太高,只希望保持最新版本的服務,不考慮版本回退
│
└───deploys #deploys yaml logs
│   │   project.drone_num.yaml
│   │   ...
│   
└───ingress #ingress yaml 

deployment.yaml 定義了部署容器組和服務

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: <deploy_name> #定義個變量,通過文本替換的方式賦值
  labels:
    app: <deploy_name>
spec:
  replicas: 1
  selector:
    matchLabels:
      app: <deploy_name>
  template:
    metadata:
      labels:
        app: <deploy_name>
    spec:
      containers:
      - name: <deploy_name>
        image: registry.cn-hangzhou.aliyuncs.com/namespace/<image_name>
        imagePullPolicy: Always #總是拉取最新的
        livenessProbe:#存活檢查
          failureThreshold: 3
          httpGet:
            path: path_to_api
            port: <image_port>
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 3
        ports:
        - containerPort: <image_port>
      imagePullSecrets:
        - name: <image_secret> #替換為自己的保密字典
---
apiVersion: v1
kind: Service #開個服務
metadata:
  labels:
     run: <deploy_name>
  name: <deploy_name>-svc
spec:
  ports:
  - port: <image_port>
    protocol: TCP
    targetPort: <image_port>
  selector:
    app: <deploy_name>
  sessionAffinity: None
  type: NodePort

upgrade.sh

# 調用方式deploy.sh ${DRONE_REPO_NAME}  ${DRONE_BUILD_NUMBER} ingress_name docker_image:tag
#!/bin/bash
#只保證最新的服務存活
keep_one_live() {
        sleep 300 #給老版本的容器時間處理正在執行的進程
        wait
        sh keepone.sh $1
}

if [ ! $1 ]; then
  echo -e "\033[41;37m param1 enter a deploy name \033[0m \n"
  exit
fi
if [ ! $2 ]; then
  echo -e "\033[41;37m param2 enter a deploy version \033[0m \n"
  exit
fi
if [ ! $3 ]; then
  echo -e "\033[41;37m param3 enter ingress name or string 'none' \033[0m \n"
  exit
fi

if [ ! $4 ]; then
  echo -e "\033[41;37m param4 enter docker image name:tag \033[0m \n"
  exit
fi
LABEL=$1
VERSION=$2
INGRESS=$3
DOCKERIMAGE=$4
if [ ! $5 ]; then
  IMAGEPORT=80
else
  IMAGEPORT=$5
fi
DEPLOYMENTNAME=$1-$2
SERVICE=`echo $1-$2-svc`
DEPLOYMENTFILE="deploys/$1.$2.yaml"
INGRESSFILE="ingress/$3.yaml"
DEMO="deployment.yaml"

echo -e "\033[47;32m 1. Start to deployment:$DEPLOYMENTNAME \033[0m \n" #加個騷氣的顏色 參考 https://blog.csdn.net/David_Dai_1108/article/details/70478826
cp -f $DEMO $DEPLOYMENTFILE #拷貝一份到deploys目錄
sed -i "s/<deploy_name>/$DEPLOYMENTNAME/g" $DEPLOYMENTFILE #替換變量
sed -i "s/<image_name>/$DOCKERIMAGE/g" $DEPLOYMENTFILE
sed -i "s/<image_port>/$IMAGEPORT/g" $DEPLOYMENTFILE

echo -e "\033[47;32m 2. Create new service:$SERVICE \033[0m \n"
cat $DEPLOYMENTFILE
kubectl apply -f $DEPLOYMENTFILE #按模板創建容器組和服務

#此時會運行V1 V2 兩個版本的容器,等V2啟動成功,再切換路由,就是藍綠發布
echo -e "\033[47;32m 3. Wait until the deployment:$DEPLOYMENTNAME is ready \033[0m \n";
READY=$(kubectl get deploy $DEPLOYMENTNAME -o json | jq '.status.conditions[] | select(.reason == "MinimumReplicasAvailable") | .status' | tr -d '"')
while [[ "$READY" != "True" ]]; do
READY=$(kubectl get deploy $DEPLOYMENTNAME -o json | jq '.status.conditions[] | select(.reason == "MinimumReplicasAvailable") | .status' | tr -d '"')
sleep 5
done

if [ $INGRESS !== "none" ]; then
  echo -e "\033[47;32m 4. Update ingress with service:$SERVICE \033[0m \n"
  LASTSVC=$(kubectl get ing $INGRESS -o json | jq '.spec|.rules|.[0]|.http|.paths|.      [0]|.backend|.serviceName' | grep  -oP "\w+(\-\w+)+")
  kubectl get ing $INGRESS -o yaml > $INGRESSFILE #把當前路由配置做個備份
  sed -i "s/$LASTSVC/$SERVICE/g" $INGRESSFILE #把v1服務替換v2服務
  kubectl replace -f $INGRESSFILE #應用當前路由配置
fi

echo -e "\033[47;32m 5. Delete old versions \033[0m \n"
keep_one_live $LABEL & #利用shell子進程,異步刪除V1的容器組和服務

echo -e "\033[47;32m 6. Deployment:$DEPLOYMENTNAME job done. \033[0m \n"

keepone.sh

path="deploys"
files=$(ls $path -t) #按時間排序部署過的yaml文件
i=0
j=0
for filename in $files
do
   dp=`echo $filename  | cut -d "." -f1`
   if [ $dp == $1 ];then #只匹配相同項目名的文件
    ((i++))
    if [ $i -gt 1 ];then #排除最新的一個,保留2個版本就改為 `gt 2`
      ((j++))
      if [ $j -lt 2 ];then #這里有點繞,是為了避免刪除已刪除的容器組和服務
        echo "$filename deleted"
        kubectl delete -f "$path/$filename" #找到次新的yaml,刪除其容器組和服務
      fi
    fi
   fi
done


通過以上腳本,就實現了自動化部署,drone的功能很簡潔,沒有一絲多余,最后放一張部署成功的截圖


drone.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容