go程序基於阿里雲CodePipeline的一次devops實踐

背景

最近朋友有個項目代碼託管用的碼雲,測試服務器(阿里雲ECS)只有一臺,三四我的開發,因而想基於阿里雲的CodePipeline快速打造一套自動化cicd的流程,使用docker來進行多套環境部署。html

CodePipeline 介紹

阿里雲CodePipeline是兼容Jenkins標準的、提供快速可靠的持續集成與持續交付服務。基於容器技術和阿里雲基礎服務架構,提供穩定和安全的代碼/Docker編譯構建,測試,掃描和部署的工具服務,並提供Pipeline As Code的編碼級配置模式,知足應用程序和基礎設施快速可靠的交付和更新。mysql

上面是阿里雲的官方介紹,兼容jekins的標準,一次無心的點擊出現了下圖的圖標,感受就是jenkins的基礎上作了一次二次開發。

新建構建項目

構建項目基本配置

基本信息配置

因爲項目使用到了一些國外的lib,固然選擇國內的節點也是能夠的,不過在寫Dockerfile的時候記得加上代理。

源碼管理配置

選擇合適的代碼倉庫,也能夠是私倉,不過須要配上本身的帳號和ssh key相關信息。

構建配置

我這裏使用的是阿里雲的私有的鏡像倉庫基於Dockerfile來構建鏡像,注意配置憑證。 ![在這裏插入圖片描述]linux

項目目錄
gin_demo
├── app
│   └── app.go
├── conf
│   └── app.ini
├── Dockerfile
├── docs
│   └── sql
│       └── mjs.sql
├── go.mod
├── go.sum
├── main.go
├── middleware
│   ├── jwt
│   │   └── jwt.go
│   └── logging
│       └── logger.go
├── mjs.exe
├── models
│   ├── mongo
│   │   └── db.go
│   └── mysql
│       ├── db.go
│       ├── teacher.go
│       └── user.go
├── pkg
│   ├── app
│   │   ├── form.go
│   │   ├── request.go
│   │   └── response.go
│   ├── def
│   │   └── def.go
│   ├── e
│   │   ├── code.go
│   │   ├── def.go
│   │   └── msg.go
│   ├── file
│   │   └── file.go
│   ├── gredis
│   │   └── redis.go
│   ├── logging
│   │   ├── file.go
│   │   └── log.go
│   ├── setting
│   │   └── setting.go
│   ├── upload
│   │   └── image.go
│   └── util
│       ├── jwt.go
│       ├── md5.go
│       ├── pagination.go
│       └── util.go
├── README.en.md
├── README.md
├── routers
│   ├── api
│   │   └── v1
│   └── router.go
├── runtime
│   └── logs
│       ├── log20190528.log
│       └── log20190529.log
└── service
    ├── teacher_service
    │   └── teacher.go
    └── user_service
        └── user.go

複製代碼
Dockerfile
FROM golang:1.12.4 as build

#ENV GOPROXY https://goproxy.io 

WORKDIR /go/cache 
ADD go.mod . ADD go.sum . RUN go mod download 
WORKDIR /go/release 
ADD . . 
RUN GOOS=linux CGO_ENABLED=0 go build -ldflags="-s -w" -installsuffix cgo -o gin_demo main.go 
FROM scratch as prod

COPY --from=build /usr/share/zoneinfo/Asia/Shanghai /etc/localtime COPY --from=build /go/release/gin_demo / COPY --from=build /go/release/conf ./conf CMD ["/gin_demo"] 複製代碼

注:若是選擇國內節點構建必須配上代理 ENV GOPROXY goproxy.iogolang

配置觸發器

這裏選擇一個構建的代碼分支,而後點擊生成,將生成後的url能夠在對應的代碼倉庫配上webhook之類的配置。選擇合適的觸發方式。

配置部署

阿里雲構建步驟裏面部署到ECS上(不方便)和部署到k8s(收費)都不能知足項目場景需求,不過上面支持shell腳本,因而本身想在朋友的那臺阿里雲ECS上跑個ci的web server,這裏構建完以後就去通知下這個接口,而後去執行一些docker指令的腳本,拉取構建完以後的鏡像而且從新啓動,啓動完以後郵件通知。因而寫了這樣一個很簡單的web server。 main

package main

import (
	"fmt"
	"log"
	"net/http"
	"os/exec"
	"path"
)

/* * @Author:hanyajun * @Date:2019/5/28 16:44 * @Name:ci_tools * @Function: ci 工具 */

//
func HandleCi(w http.ResponseWriter, req *http.Request) {
	user := path.Base(req.URL.Path)
	//針對不一樣開發人員的push拉取不一樣的鏡像和映射不一樣的端口
	var port string
	switch user {
	case "zhangsan":
		port = "8088"
	case "lisi":
		port = "8087"
	case "wangmazi":
		port = "8086"
	case "dev":
		port = "8085"
	case "master":
		port = "8084"

	}
	println(user)
	result := Run(user,port)
	client:=NewMailClient("smtp.qq.com",465,"******@qq.com","*********")//注意使用465 ssl發送,25端口阿里雲ecs禁止了。
	s:=&SendObject{
		ToMails:[]string{"******@qq.com","******@qq.com","******@qq.com"},
		CcMails:[]string{"******@qq.com"},
		Object:"cicd流程結果通知",
		ContentType:"text/html",
		Content:user+" has push something to the branch: "+user+"\n"+"result: "+string(result),
	}
	err:=client.SendMail(s)
	if err!=nil{
		println("send mail fail",err)
	}
	_, _ = w.Write(result)
}
func main() {
	http.HandleFunc("/ci/", HandleCi)
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

func Run(user string,port string) []byte {

	shellPath := "/root/ci/ci.sh"
	command := exec.Command(shellPath, user,port) 
	err := command.Start()                   
	if nil != err {
		fmt.Println(err)
		return []byte(err.Error())
	}
	fmt.Println("Process PID:", command.Process.Pid)
	err = command.Wait() //等待執行完成
	if nil != err {
		fmt.Println(err)
		return []byte(err.Error())
	}
	fmt.Println("ProcessState PID:", command.ProcessState.Pid())
	return []byte("success")
}

複製代碼

mail.goweb

package main

import (
	"fmt"
	"gopkg.in/gomail.v2"
)

/* * @Author:15815 * @Date:2019/5/8 17:47 * @Name:mail * @Function:郵件發送 */

type Client struct {
	Host     string
	Port     int
	Mail     string
	Password string
}

type SendObject struct {
	ToMails     []string
	CcMails     []string
	Object      string
	ContentType string
	Content     string
}

func NewMailClient(host string, port int, sendMail, password string) *Client {
	return &Client{
		Host:     host,
		Port:     port,
		Mail:     sendMail,
		Password: password,
	}
}
func (m *Client) SendMail(s *SendObject) error {
	mgs := gomail.NewMessage()
	mgs.SetHeader("From", m.Mail)
	mgs.SetHeader("To", s.ToMails...)
	mgs.SetHeader("Cc", s.CcMails...)
	mgs.SetHeader("Subject", s.Object)
	mgs.SetBody(s.ContentType, s.Content)
	d := gomail.NewDialer(m.Host, m.Port, m.Mail, m.Password)
	if err := d.DialAndSend(mgs); err != nil {
		fmt.Printf("send mail err:%v", err)
		return err
	}
	return nil
}

複製代碼

ci.shredis

#!/bin/bash
funCiTools()
{
    docker pull registry.cn-shanghai.aliyuncs.com/***/***:$1
    docker rm -f $1
    docker run -d -p $2:8000 --name $1 registry.cn-shanghai.aliyuncs.com/***/***:$1
}
funCiTools $1 $2
複製代碼

第一個參數是對應開發人員啓動容器的名字以及構建鏡像的tag和上面構建的配置一致,第二個參數是映射的端口。 構建ci_web_server
本身的電腦是windows的,朋友的阿里雲ecs上又沒有go環境,想構建基於linux的二進制程序,因而直接利用docker image 來構建了鏡像,一個指令解決問題。 build.shsql

docker run --rm -i -v `pwd`:/go/src/ci -w /go/src/ci  golang:1.11.5   go build -o ci  ci
複製代碼

使用nohup直接將ci server放置後臺運行。docker

nohup ./ci  >output 2>&1 &
複製代碼

效果測試

直接修改點東西提交代碼後就等郵件通知了,是否是感受很爽。 shell

提交完代碼後就開始觸發構建了。
最後構建完完成後觸發ci server 進行deploy,完成郵件通知。
登陸到阿里雲Ecs上咱們發現咱們的容器已經啓動成功了。
相關文章
相關標籤/搜索