support service monitor resource create #370

This commit is contained in:
barnettZQG 2020-09-10 14:37:04 +08:00
parent f7b001f4b8
commit 7dc2b39cd3
39 changed files with 1348 additions and 141 deletions

View File

@ -78,6 +78,9 @@ type ServiceInterface interface {
GetDeployVersion(w http.ResponseWriter, r *http.Request)
AutoscalerRules(w http.ResponseWriter, r *http.Request)
ScalingRecords(w http.ResponseWriter, r *http.Request)
AddServiceMonitors(w http.ResponseWriter, r *http.Request)
DeleteServiceMonitors(w http.ResponseWriter, r *http.Request)
UpdateServiceMonitors(w http.ResponseWriter, r *http.Request)
}
//TenantInterfaceWithV1 funcs for both v2 and v1

View File

@ -273,6 +273,11 @@ func (v2 *V2) serviceRouter() chi.Router {
r.Put("/xparules", middleware.WrapEL(controller.GetManager().AutoscalerRules, dbmodel.TargetTypeService, "update-app-autoscaler-rule", dbmodel.SYNEVENTTYPE))
r.Get("/xparecords", controller.GetManager().ScalingRecords)
//service monitor
r.Post("/service-monitors", middleware.WrapEL(controller.GetManager().AddServiceMonitors, dbmodel.TargetTypeService, "add-app-service-monitor", dbmodel.SYNEVENTTYPE))
r.Put("/service-monitors/{name}", middleware.WrapEL(controller.GetManager().UpdateServiceMonitors, dbmodel.TargetTypeService, "update-app-service-monitor", dbmodel.SYNEVENTTYPE))
r.Delete("/service-monitors/{name}", middleware.WrapEL(controller.GetManager().DeleteServiceMonitors, dbmodel.TargetTypeService, "delete-app-service-monitor", dbmodel.SYNEVENTTYPE))
return r
}

View File

@ -0,0 +1,59 @@
package controller
import (
"net/http"
"github.com/go-chi/chi"
"github.com/goodrain/rainbond/api/handler"
"github.com/goodrain/rainbond/api/middleware"
api_model "github.com/goodrain/rainbond/api/model"
httputil "github.com/goodrain/rainbond/util/http"
)
//AddServiceMonitors add service monitor
func (t *TenantStruct) AddServiceMonitors(w http.ResponseWriter, r *http.Request) {
var add api_model.AddServiceMonitorRequestStruct
ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &add, nil)
if !ok {
return
}
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
tsm, err := handler.GetServiceManager().AddServiceMonitor(tenantID, serviceID, add)
if err != nil {
httputil.ReturnBcodeError(r, w, err)
return
}
httputil.ReturnSuccess(r, w, tsm)
}
//DeleteServiceMonitors delete service monitor
func (t *TenantStruct) DeleteServiceMonitors(w http.ResponseWriter, r *http.Request) {
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
name := chi.URLParam(r, "name")
tsm, err := handler.GetServiceManager().DeleteServiceMonitor(tenantID, serviceID, name)
if err != nil {
httputil.ReturnBcodeError(r, w, err)
return
}
httputil.ReturnSuccess(r, w, tsm)
}
//UpdateServiceMonitors update service monitor
func (t *TenantStruct) UpdateServiceMonitors(w http.ResponseWriter, r *http.Request) {
var update api_model.UpdateServiceMonitorRequestStruct
ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &update, nil)
if !ok {
return
}
name := chi.URLParam(r, "name")
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
tsm, err := handler.GetServiceManager().UpdateServiceMonitor(tenantID, serviceID, name, update)
if err != nil {
httputil.ReturnBcodeError(r, w, err)
return
}
httputil.ReturnSuccess(r, w, tsm)
}

View File

@ -28,10 +28,10 @@ import (
"strings"
"time"
"github.com/sirupsen/logrus"
"github.com/coreos/etcd/clientv3"
"github.com/jinzhu/gorm"
"github.com/pquerna/ffjson/ffjson"
"github.com/sirupsen/logrus"
"github.com/twinj/uuid"
"github.com/goodrain/rainbond/api/proxy"
@ -2046,6 +2046,7 @@ func (s *ServiceAction) delServiceMetadata(serviceID string) error {
db.GetManager().TenantPluginVersionENVDaoTransactions(tx).DeleteEnvByServiceID,
db.GetManager().ServiceProbeDaoTransactions(tx).DELServiceProbesByServiceID,
db.GetManager().ServiceEventDaoTransactions(tx).DelEventByServiceID,
db.GetManager().TenantServiceMonitorDaoTransactions(tx).DeleteServiceMonitorByServiceID,
}
if err := GetGatewayHandler().DeleteTCPRuleByServiceIDWithTransaction(serviceID, tx); err != nil {
tx.Rollback()

View File

@ -78,4 +78,8 @@ type ServiceHandler interface {
AddAutoscalerRule(req *api_model.AutoscalerRuleReq) error
UpdAutoscalerRule(req *api_model.AutoscalerRuleReq) error
ListScalingRecords(serviceID string, page, pageSize int) ([]*dbmodel.TenantServiceScalingRecords, int, error)
UpdateServiceMonitor(tenantID, serviceID, name string, update api_model.UpdateServiceMonitorRequestStruct) (*dbmodel.TenantServiceMonitor, error)
DeleteServiceMonitor(tenantID, serviceID, name string) (*dbmodel.TenantServiceMonitor, error)
AddServiceMonitor(tenantID, serviceID string, add api_model.AddServiceMonitorRequestStruct) (*dbmodel.TenantServiceMonitor, error)
}

View File

@ -0,0 +1,59 @@
package handler
import (
api_model "github.com/goodrain/rainbond/api/model"
"github.com/goodrain/rainbond/api/util/bcode"
"github.com/goodrain/rainbond/db"
dbmodel "github.com/goodrain/rainbond/db/model"
"github.com/jinzhu/gorm"
)
//UpdateServiceMonitor update service monitor
func (s *ServiceAction) UpdateServiceMonitor(tenantID, serviceID, name string, update api_model.UpdateServiceMonitorRequestStruct) (*dbmodel.TenantServiceMonitor, error) {
sm, err := db.GetManager().TenantServiceMonitorDao().GetByName(serviceID, name)
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, bcode.ErrServiceMonitorNotFound
}
return nil, err
}
_, err = db.GetManager().TenantServicesPortDao().GetPort(serviceID, update.Port)
if err != nil {
return nil, bcode.ErrPortNotFound
}
sm.ServiceShowName = update.ServiceShowName
sm.Port = update.Port
sm.Path = update.Path
sm.Interval = update.Interval
return sm, db.GetManager().TenantServiceMonitorDao().UpdateModel(sm)
}
//DeleteServiceMonitor delete
func (s *ServiceAction) DeleteServiceMonitor(tenantID, serviceID, name string) (*dbmodel.TenantServiceMonitor, error) {
sm, err := db.GetManager().TenantServiceMonitorDao().GetByName(serviceID, name)
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, bcode.ErrServiceMonitorNotFound
}
return nil, err
}
return sm, db.GetManager().TenantServiceMonitorDao().DeleteServiceMonitor(sm)
}
//AddServiceMonitor add service monitor
func (s *ServiceAction) AddServiceMonitor(tenantID, serviceID string, add api_model.AddServiceMonitorRequestStruct) (*dbmodel.TenantServiceMonitor, error) {
_, err := db.GetManager().TenantServicesPortDao().GetPort(serviceID, add.Port)
if err != nil {
return nil, bcode.ErrPortNotFound
}
sm := dbmodel.TenantServiceMonitor{
Name: add.Name,
TenantID: tenantID,
ServiceID: serviceID,
ServiceShowName: add.ServiceShowName,
Port: add.Port,
Path: add.Path,
Interval: add.Interval,
}
return &sm, db.GetManager().TenantServiceMonitorDao().AddModel(&sm)
}

View File

@ -26,7 +26,6 @@ import (
"net/http"
"strings"
"github.com/sirupsen/logrus"
"github.com/go-chi/chi"
"github.com/goodrain/rainbond/api/handler"
"github.com/goodrain/rainbond/api/util"
@ -35,6 +34,7 @@ import (
"github.com/goodrain/rainbond/event"
httputil "github.com/goodrain/rainbond/util/http"
"github.com/jinzhu/gorm"
"github.com/sirupsen/logrus"
)
//ContextKey ctx key type

View File

@ -0,0 +1,45 @@
package model
//AddServiceMonitorRequestStruct add service monitor request
type AddServiceMonitorRequestStruct struct {
// name
// in: body
// required: true
Name string `json:"name" validate:"name|required"`
// service_show_name
// in: body
// required: true
ServiceShowName string `json:"service_show_name" validate:"service_show_name|required"`
// port
// in: body
// required: true
Port int `json:"port" validate:"port|required"`
// path
// in: body
// required: true
Path string `json:"path" validate:"path|required"`
// interval
// in: body
// required: true
Interval string `json:"interval" validate:"interval|required"`
}
//UpdateServiceMonitorRequestStruct update service monitor request
type UpdateServiceMonitorRequestStruct struct {
// service_show_name
// in: body
// required: true
ServiceShowName string `json:"service_show_name" validate:"service_show_name|required"`
// port
// in: body
// required: true
Port int `json:"port" validate:"port|required"`
// path
// in: body
// required: true
Path string `json:"path" validate:"path|required"`
// interval
// in: body
// required: true
Interval string `json:"interval" validate:"interval|required"`
}

124
api/util/bcode/bcode.go Normal file
View File

@ -0,0 +1,124 @@
package bcode
import (
"fmt"
"strconv"
"strings"
"github.com/jinzhu/gorm"
"github.com/pkg/errors"
)
var (
// OK means everything si good.
OK = new(200, 200)
// StatusFound means the requested resource resides temporarily under a different URI.
StatusFound = new(302, 302)
// BadRequest means the request could not be understood by the server due to malformed syntax.
// The client SHOULD NOT repeat the request without modifications.
BadRequest = new(400, 400)
// NotFound means the server has not found anything matching the request.
NotFound = new(404, 404)
// ServerErr means the server encountered an unexpected condition which prevented it from fulfilling the request.
ServerErr = new(500, 500)
// TokenInvalid -
TokenInvalid = new(400, 401)
)
// Coder has ability to get Code, msg or detail from error.
type Coder interface {
// Status Code
GetStatus() int
// business Code
GetCode() int
Error() string
Equal(err error) bool
}
var (
codes = make(map[int]struct{})
)
func new(status, code int) Coder {
if _, ok := codes[code]; ok {
panic(fmt.Sprintf("bcode %d already exists", code))
}
codes[code] = struct{}{}
return newCode(status, code, "")
}
func newByMessage(status, code int, message string) Coder {
if _, ok := codes[code]; ok {
panic(fmt.Sprintf("bcode %d already exists", code))
}
codes[code] = struct{}{}
return newCode(status, code, message)
}
// Code business a bussiness Code
type Code struct {
Status int `json:"status"`
Code int `json:"code"`
Message string `json:"msg"`
}
func newCode(status, code int, message string) Coder {
return &Code{Status: status, Code: code, Message: message}
}
// GetStatus returns the Status Code
func (c *Code) GetStatus() int {
return c.Status
}
// GetCode returns the business Code
func (c *Code) GetCode() int {
return c.Code
}
func (c *Code) Error() string {
if c.Message != "" {
return c.Message
}
return strconv.FormatInt(int64(c.Code), 10)
}
// Equal -
func (c *Code) Equal(err error) bool {
obj := Err2Coder(err)
return c.Code == obj.GetCode()
}
// Err2Coder converts the given err to Coder.
func Err2Coder(err error) Coder {
if err == nil {
return OK
}
coder, ok := errors.Cause(err).(Coder)
if ok {
return coder
}
if err == gorm.ErrRecordNotFound {
return NotFound
}
return Str2Coder(err.Error())
}
// Str2Coder converts the given str to Coder.
func Str2Coder(str string) Coder {
str = strings.TrimSpace(str)
if str == "" {
return OK
}
i, err := strconv.Atoi(str)
if err != nil {
return ServerErr
}
return newCode(400, i, "")
}
// NewBadRequest -
func NewBadRequest(msg string) Coder {
return newCode(400, 400, msg)
}

10
api/util/bcode/service.go Normal file
View File

@ -0,0 +1,10 @@
package bcode
var (
//ErrPortNotFound -
ErrPortNotFound = newByMessage(404, 10001, "service port not found")
//ErrServiceMonitorNotFound -
ErrServiceMonitorNotFound = newByMessage(404, 10101, "service monitor not found")
//ErrServiceMonitorNameExist -
ErrServiceMonitorNameExist = newByMessage(400, 10102, "service monitor name is exist")
)

View File

@ -108,9 +108,6 @@ func (a *Worker) CheckEnv() error {
if err := os.Setenv("GRDATA_PVC_NAME", a.Config.GrdataPVCName); err != nil {
return fmt.Errorf("set env 'GRDATA_PVC_NAME': %v", err)
}
if os.Getenv("CUR_NET") == "" {
return fmt.Errorf("please set env `CUR_NET`")
}
if os.Getenv("EX_DOMAIN") == "" {
return fmt.Errorf("please set env `EX_DOMAIN`")
}

View File

@ -23,7 +23,6 @@ import (
"os/signal"
"syscall"
"github.com/sirupsen/logrus"
"github.com/eapache/channels"
"github.com/goodrain/rainbond/cmd/worker/option"
"github.com/goodrain/rainbond/db"
@ -39,6 +38,7 @@ import (
"github.com/goodrain/rainbond/worker/master"
"github.com/goodrain/rainbond/worker/monitor"
"github.com/goodrain/rainbond/worker/server"
"github.com/sirupsen/logrus"
"k8s.io/client-go/kubernetes"
)
@ -87,7 +87,7 @@ func Run(s *option.Worker) error {
startCh := channels.NewRingChannel(1024)
updateCh := channels.NewRingChannel(1024)
probeCh := channels.NewRingChannel(1024)
cachestore := store.NewStore(clientset, db.GetManager(), s.Config, startCh, probeCh)
cachestore := store.NewStore(restConfig, clientset, db.GetManager(), s.Config, startCh, probeCh)
appmController := appm.NewAPPMController(clientset, cachestore, startCh, updateCh, probeCh)
if err := appmController.Start(); err != nil {
logrus.Errorf("error starting appm controller: %v", err)

View File

@ -499,3 +499,12 @@ type TenantServiceScalingRecordsDao interface {
ListByServiceID(serviceID string, offset, limit int) ([]*model.TenantServiceScalingRecords, error)
CountByServiceID(serviceID string) (int, error)
}
// TenantServiceMonitorDao -
type TenantServiceMonitorDao interface {
Dao
GetByName(serviceID, name string) (*model.TenantServiceMonitor, error)
GetByServiceID(serviceID string) ([]*model.TenantServiceMonitor, error)
DeleteServiceMonitor(mo *model.TenantServiceMonitor) error
DeleteServiceMonitorByServiceID(serviceID string) error
}

View File

@ -23,11 +23,11 @@ import (
"fmt"
"time"
"github.com/sirupsen/logrus"
"github.com/goodrain/rainbond/db/config"
"github.com/goodrain/rainbond/db/dao"
"github.com/goodrain/rainbond/db/mysql"
"github.com/jinzhu/gorm"
"github.com/sirupsen/logrus"
)
//Manager db manager
@ -126,6 +126,9 @@ type Manager interface {
TenantServceAutoscalerRuleMetricsDaoTransactions(db *gorm.DB) dao.TenantServceAutoscalerRuleMetricsDao
TenantServiceScalingRecordsDao() dao.TenantServiceScalingRecordsDao
TenantServiceScalingRecordsDaoTransactions(db *gorm.DB) dao.TenantServiceScalingRecordsDao
TenantServiceMonitorDao() dao.TenantServiceMonitorDao
TenantServiceMonitorDaoTransactions(db *gorm.DB) dao.TenantServiceMonitorDao
}
var defaultManager Manager

18
db/model/monitor.go Normal file
View File

@ -0,0 +1,18 @@
package model
//TenantServiceMonitor custom service monitor
type TenantServiceMonitor struct {
Model
TenantID string `gorm:"column:tenant_id;size:40" json:"tenant_id"`
ServiceID string `gorm:"column:service_id;size:40" json:"service_id"`
Name string `gorm:"column:name;size:40;unique_index" json:"name"`
ServiceShowName string `gorm:"column:service_show_name" json:"service_show_name"`
Port int `gorm:"column:port;size:5" json:"port"`
Path string `gorm:"column:path;size:255" json:"path"`
Interval string `gorm:"column:interval;size:20" json:"interval"`
}
// TableName returns table name of TenantServiceMonitor
func (TenantServiceMonitor) TableName() string {
return "tenant_services_monitor"
}

69
db/mysql/dao/monitor.go Normal file
View File

@ -0,0 +1,69 @@
package dao
import (
"github.com/goodrain/rainbond/api/util/bcode"
"github.com/goodrain/rainbond/db/model"
"github.com/jinzhu/gorm"
)
//TenantServiceMonitorDaoImpl -
type TenantServiceMonitorDaoImpl struct {
DB *gorm.DB
}
//AddModel create service monitor
func (t *TenantServiceMonitorDaoImpl) AddModel(mo model.Interface) error {
m := mo.(*model.TenantServiceMonitor)
var oldTSM model.TenantServiceMonitor
if ok := t.DB.Where("name = ? and tenant_id = ?", m.Name, m.TenantID).Find(&oldTSM).RecordNotFound(); ok {
if err := t.DB.Create(m).Error; err != nil {
return err
}
} else {
return bcode.ErrServiceMonitorNameExist
}
return nil
}
//UpdateModel update service monitor
func (t *TenantServiceMonitorDaoImpl) UpdateModel(mo model.Interface) error {
tsm := mo.(*model.TenantServiceMonitor)
if err := t.DB.Save(tsm).Error; err != nil {
return err
}
return nil
}
//DeleteServiceMonitor delete service monitor
func (t *TenantServiceMonitorDaoImpl) DeleteServiceMonitor(mo *model.TenantServiceMonitor) error {
if err := t.DB.Delete(mo).Error; err != nil {
return err
}
return nil
}
//DeleteServiceMonitorByServiceID delete service monitor by service id
func (t *TenantServiceMonitorDaoImpl) DeleteServiceMonitorByServiceID(serviceID string) error {
if err := t.DB.Where("service_id=?", serviceID).Delete(&model.TenantServiceMonitor{}).Error; err != nil {
return err
}
return nil
}
//GetByServiceID get tsm by service id
func (t *TenantServiceMonitorDaoImpl) GetByServiceID(serviceID string) ([]*model.TenantServiceMonitor, error) {
var tsm []*model.TenantServiceMonitor
if err := t.DB.Where("service_id=?", serviceID).Find(&tsm).Error; err != nil {
return nil, err
}
return tsm, nil
}
//GetByName get by name
func (t *TenantServiceMonitorDaoImpl) GetByName(serviceID, name string) (*model.TenantServiceMonitor, error) {
var tsm model.TenantServiceMonitor
if err := t.DB.Where("service_id=? and name=?", serviceID, name).Find(&tsm).Error; err != nil {
return nil, err
}
return &tsm, nil
}

View File

@ -577,3 +577,17 @@ func (m *Manager) TenantServiceScalingRecordsDaoTransactions(db *gorm.DB) dao.Te
DB: db,
}
}
//TenantServiceMonitorDao monitor dao
func (m *Manager) TenantServiceMonitorDao() dao.TenantServiceMonitorDao {
return &mysqldao.TenantServiceMonitorDaoImpl{
DB: m.db,
}
}
//TenantServiceMonitorDaoTransactions monitor dao
func (m *Manager) TenantServiceMonitorDaoTransactions(db *gorm.DB) dao.TenantServiceMonitorDao {
return &mysqldao.TenantServiceMonitorDaoImpl{
DB: db,
}
}

View File

@ -21,10 +21,10 @@ package mysql
import (
"sync"
"github.com/sirupsen/logrus"
"github.com/goodrain/rainbond/db/config"
"github.com/goodrain/rainbond/db/model"
"github.com/jinzhu/gorm"
"github.com/sirupsen/logrus"
// import sql driver manually
_ "github.com/go-sql-driver/mysql"
@ -141,6 +141,7 @@ func (m *Manager) RegisterTableModel() {
m.models = append(m.models, &model.TenantServiceAutoscalerRules{})
m.models = append(m.models, &model.TenantServiceAutoscalerRuleMetrics{})
m.models = append(m.models, &model.TenantServiceScalingRecords{})
m.models = append(m.models, &model.TenantServiceMonitor{})
}
//CheckTable check and create tables

10
go.mod
View File

@ -15,6 +15,7 @@ require (
github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292 // indirect
github.com/containerd/continuity v0.0.0-20200228182428-0f16d7a0959c // indirect
github.com/coreos/etcd v3.3.17+incompatible
github.com/coreos/prometheus-operator v0.38.3
github.com/docker/cli v0.0.0-20190711175710-5b38d82aa076
github.com/docker/distribution v2.7.1+incompatible
github.com/docker/docker v1.4.2-0.20200309214505-aa6a9891b09c
@ -36,7 +37,7 @@ require (
github.com/go-sql-driver/mysql v1.5.0
github.com/gogo/protobuf v1.3.1
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/mock v1.4.1
github.com/golang/mock v1.4.3
github.com/golang/protobuf v1.4.2
github.com/goodrain/rainbond-operator v1.0.0
github.com/gorilla/mux v1.7.4 // indirect
@ -47,7 +48,7 @@ require (
github.com/jinzhu/gorm v1.9.16
github.com/json-iterator/go v1.1.10
github.com/kr/pty v1.1.8
github.com/mattn/go-runewidth v0.0.2
github.com/mattn/go-runewidth v0.0.6
github.com/mattn/go-shellwords v1.0.10 // indirect
github.com/mitchellh/go-ps v1.0.0
github.com/mitchellh/go-wordwrap v1.0.0
@ -79,10 +80,11 @@ require (
golang.org/x/net v0.0.0-20200707034311-ab3426394381
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
google.golang.org/grpc v1.27.1
google.golang.org/grpc v1.29.0
gopkg.in/src-d/go-git.v4 v4.13.1
gopkg.in/yaml.v2 v2.3.0
k8s.io/api v0.19.0
k8s.io/apiextensions-apiserver v0.19.0
k8s.io/apimachinery v0.19.0
k8s.io/apiserver v0.19.0
k8s.io/client-go v12.0.0+incompatible
@ -102,7 +104,7 @@ replace (
github.com/prometheus/client_golang => github.com/prometheus/client_golang v0.8.1-0.20161124155732-575f371f7862
github.com/xeipuuv/gojsonschema => github.com/xeipuuv/gojsonschema v0.0.0-20160323030313-93e72a773fad
k8s.io/api => k8s.io/api v0.16.15
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20191016113550-5357c4baaf65
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.16.15
k8s.io/apimachinery => k8s.io/apimachinery v0.16.15
k8s.io/apiserver => k8s.io/apiserver v0.16.15
k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20191016114015-74ad18325ed5

513
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,6 @@ COPY entrypoint.sh /run/entrypoint.sh
RUN chmod 655 /run/rainbond-worker
ENV EX_DOMAIN=ali-sh.goodrain.net:10080
ENV CUR_NET=midonet
ENV RELEASE_DESC=__RELEASE_DESC__
ENTRYPOINT ["/run/entrypoint.sh"]

View File

@ -36,7 +36,7 @@ function localbuild() {
if [ "$STATIC" = "true" ];then
ldflags="${ldflags} -extldflags '-static'"
fi
CGO_ENABLED=1 go build -v -ldflags "${ldflags}" -o ${outputname} ./cmd/$1
go build -v -ldflags "${ldflags}" -o ${outputname} ./cmd/$1
fi
}

View File

@ -9,7 +9,6 @@ if [ "$BUILD_IMAGE_BASE_NAME" ];
then
IMAGE_BASE_NAME=${BUILD_IMAGE_BASE_NAME}
fi
CACHE=true
GO_VERSION=1.13
if [ -z "$GOOS" ];then
@ -77,7 +76,6 @@ build::image() {
sudo cp -r ./hack/contrib/docker/$1/* "${build_image_dir}"
pushd "${build_image_dir}"
echo "---> build image:$1"
sudo ls -al
sudo sed "s/__RELEASE_DESC__/${release_desc}/" Dockerfile > Dockerfile.release
sudo docker build -t "${IMAGE_BASE_NAME}/rbd-$1:${VERSION}" -f Dockerfile.release .
sudo docker run -it --rm "${IMAGE_BASE_NAME}/rbd-$1:${VERSION}" version

View File

@ -25,6 +25,8 @@ import (
"net/url"
"reflect"
"github.com/goodrain/rainbond/api/util/bcode"
"github.com/go-chi/render"
govalidator "github.com/goodrain/rainbond/util/govalidator"
"github.com/sirupsen/logrus"
@ -172,3 +174,11 @@ func ReturnResNotEnough(r *http.Request, w http.ResponseWriter, msg string) {
r = r.WithContext(context.WithValue(r.Context(), render.StatusCtxKey, 412))
render.DefaultResponder(w, r, ResponseBody{Msg: msg})
}
//ReturnBcodeError bcode error
func ReturnBcodeError(r *http.Request, w http.ResponseWriter, err error) {
berr := bcode.Err2Coder(err)
logrus.Debugf("path %s error code: %d; status: %d; error msg: %s", r.RequestURI, berr.GetCode(), berr.GetStatus(), berr.Error())
r = r.WithContext(context.WithValue(r.Context(), render.StatusCtxKey, berr.GetStatus()))
render.DefaultResponder(w, r, berr)
}

View File

@ -1,64 +0,0 @@
## 一期项目说明
### 设计说明:
* 支持可配置的资源模型选择应用使用标签进行部署类型选择。本月支持StatefulSets。
* 支持两种数据持久化源etcd and mysql本月支持mysql。
* 支持单实例启停,重启操作,多实例滚动升级操作,水平伸缩,垂直伸缩操作,应用组启动策略操作。
* 支持基于应用标签的高级调度
### 功能点和时间点规划
* [*] 消息队列HTTP API @8.1
* [*] 消息队列gRPC完成golang,python客户端完成 @8.18
* [*] 各种操作类型模型确定 @8.2
* [*] 数据持久层接口实现mysql插件 @8.3-8.4
* [*] 使用zmq进行日志服务客户端封装 @8.3-8.4
* [*] 任务发现器 @8.7-8.8 @崔斌
* [ ] podname dns解析服务 @8.12-8.15 @崔斌
* [*] 任务分析模块 @8.9-8.11 @崔斌
1. 任务截流
2. 数据库相关操作
3. 任务分析
4. logger创建
5. 测试 @8.17
* [ ] 任务执行器 @8.7-8.18
* [*]无状态单应用启动停止,重启,伸缩。
* [*]有状态单应用启动停止,重启,伸缩。
* [*]应用滚动升级。
* [ ]应用组启动停止。
* [ ] 控制台支持应用标签指定应用使用v2 API @8.16-8.18
* [*] region api v2版API @8.14-8.17 @崔斌
1. 兼容API已完成
* [*] region api 端口分配修改。原接口使用podname获取服务数据。新接口podname 与服务数据难对应。思考调整 @崔斌
* [*] 应用运行状态控制器status_manager @8.17 @崔斌
* [ ] 原数据库数据校验与清理
[*] 应用部署信息表:service_deploy_record,(同步部署信息,集群同步回来)
[ ] 应用与Pod信息表:tenant_service_pod
### 模块说明
* 任务发现器
任务发现器持续从消息队列中获取任务信息,并发往任务分析器进行分析。任务分析器需要控制当前节点任务等候数量,如果超过配置值,任务发现器需要将任务重新放回任务队列。
* 任务分析器
任务分析器接收到任务以后分析任务类型,需要的任务数据,封装成执行任务添加到任务执行器中。
高级功能:维护任务的状态。
* 任务执行器
### gRPC
```
cd pkg/api/grpc
protoc --go_out=plugins=grpc:./ message.proto
```
### 部署说明
#### 环境变量
* EX_DOMAIN 数据中心对应域名 例如 `ali-sh.goodrain.net:10080`
* CUR_NET 网络类型 例如 `midonet`
## 二期项目说明
### 设计说明:
* 支持任务执行过程可中断,可恢复,可回滚。
## 无状态说明
本组件设计目标无状态目前POD状态维护具有有状态性应用状态维护具有有状态性.
POD状态问题影响不大已数据库一致性为主。
应用状态多实例间忽略数据不一致,会导致应用状态异常设置。

View File

@ -23,10 +23,12 @@ import (
"sync"
"time"
"github.com/sirupsen/logrus"
"github.com/goodrain/rainbond/worker/appm/store"
"github.com/goodrain/rainbond/event"
"github.com/goodrain/rainbond/util"
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -156,7 +158,7 @@ func (s *startController) startOne(app v1.AppService) error {
}
}
}
//step 6: create hpa
if hpas := app.GetHPAs(); len(hpas) != 0 {
for _, hpa := range hpas {
if len(hpa.ResourceVersion) == 0 {
@ -169,7 +171,27 @@ func (s *startController) startOne(app v1.AppService) error {
}
}
//step 6: waiting endpoint ready
//step 7: create CR resource
if crd, _ := s.manager.store.GetCrd(store.ServiceMonitor); crd != nil {
if sms := app.GetServiceMonitors(true); len(sms) > 0 {
smClient, err := s.manager.store.GetServiceMonitorClient()
if err != nil {
logrus.Errorf("create service monitor client failure %s", err.Error())
}
if smClient != nil {
for _, sm := range sms {
if len(sm.ResourceVersion) == 0 {
_, err := smClient.MonitoringV1().ServiceMonitors(sm.GetNamespace()).Create(sm)
if err != nil && !errors.IsAlreadyExists(err) {
logrus.Errorf("create service monitor failure: %s", err.Error())
}
}
}
}
}
}
//step 8: waiting endpoint ready
app.Logger.Info("Create all app model success, will waiting app ready", event.GetLoggerOption("running"))
return s.WaitingReady(app)
}

View File

@ -23,10 +23,11 @@ import (
"sync"
"time"
"github.com/sirupsen/logrus"
"github.com/goodrain/rainbond/event"
"github.com/goodrain/rainbond/util"
"github.com/goodrain/rainbond/worker/appm/store"
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -144,7 +145,7 @@ func (s *stopController) stopOne(app v1.AppService) error {
}
}
}
//step 7: deleta all hpa
if hpas := app.GetHPAs(); len(hpas) != 0 {
for _, hpa := range hpas {
err := s.manager.client.AutoscalingV2beta2().HorizontalPodAutoscalers(hpa.GetNamespace()).Delete(hpa.GetName(), &metav1.DeleteOptions{})
@ -154,7 +155,25 @@ func (s *stopController) stopOne(app v1.AppService) error {
}
}
//step 7: waiting endpoint ready
//step 8: delete CR resource
if crd, _ := s.manager.store.GetCrd(store.ServiceMonitor); crd != nil {
if sms := app.GetServiceMonitors(true); len(sms) > 0 {
smClient, err := s.manager.store.GetServiceMonitorClient()
if err != nil {
logrus.Errorf("create service monitor client failure %s", err.Error())
}
if smClient != nil {
for _, sm := range sms {
err := smClient.MonitoringV1().ServiceMonitors(sm.GetNamespace()).Delete(sm.GetName(), &metav1.DeleteOptions{})
if err != nil && !errors.IsNotFound(err) {
logrus.Errorf("delete service monitor failure: %s", err.Error())
}
}
}
}
}
//step 9: waiting endpoint ready
app.Logger.Info("Delete all app model success, will waiting app closed", event.GetLoggerOption("running"))
return s.WaitingReady(app)
}

View File

@ -23,11 +23,12 @@ import (
"sync"
"time"
"github.com/sirupsen/logrus"
"github.com/goodrain/rainbond/event"
"github.com/goodrain/rainbond/util"
"github.com/goodrain/rainbond/worker/appm/f"
"github.com/goodrain/rainbond/worker/appm/store"
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
"github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -222,6 +223,16 @@ func (s *upgradeController) upgradeOne(app v1.AppService) error {
_ = f.UpgradeSecrets(s.manager.client, &app, oldApp.GetSecrets(true), app.GetSecrets(true), handleErr)
_ = f.UpgradeIngress(s.manager.client, &app, oldApp.GetIngress(true), app.GetIngress(true), handleErr)
if crd, _ := s.manager.store.GetCrd(store.ServiceMonitor); crd != nil {
client, err := s.manager.store.GetServiceMonitorClient()
if err != nil {
logrus.Errorf("create service monitor client failure %s", err.Error())
}
if client != nil {
_ = f.UpgradeServiceMonitor(client, &app, oldApp.GetServiceMonitors(true), app.GetServiceMonitors(true), handleErr)
}
}
return s.WaitingReady(app)
}

View File

@ -22,7 +22,7 @@ import (
"github.com/goodrain/rainbond/db"
"github.com/goodrain/rainbond/db/model"
"github.com/goodrain/rainbond/util"
"github.com/goodrain/rainbond/worker/appm/types/v1"
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
)
func init() {
@ -36,7 +36,10 @@ func init() {
RegistConversion("TenantServicePlugin", TenantServicePlugin)
//step5 conv service inner and outer regist
RegistConversion("TenantServiceRegist", TenantServiceRegist)
//step6 -
RegistConversion("TenantServiceAutoscaler", TenantServiceAutoscaler)
//step7 conv service monitor
RegistConversion("TenantServiceMonitor", TenantServiceMonitor)
}
//Conversion conversion function

View File

@ -24,12 +24,12 @@ import (
"strconv"
"strings"
"github.com/sirupsen/logrus"
"github.com/goodrain/rainbond/db"
"github.com/goodrain/rainbond/db/model"
"github.com/goodrain/rainbond/event"
"github.com/goodrain/rainbond/gateway/annotations/parser"
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
"github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -509,11 +509,7 @@ func (a *AppServiceBuild) createOuterService(port *model.TenantServicesPort) *co
strings.ToLower(string(servicePort.Protocol)), port.ContainerPort)
servicePort.Port = int32(port.ContainerPort)
var portType corev1.ServiceType
if os.Getenv("CUR_NET") == "midonet" {
portType = corev1.ServiceTypeNodePort
} else {
portType = corev1.ServiceTypeClusterIP
}
spec := corev1.ServiceSpec{
Ports: []corev1.ServicePort{servicePort},
Type: portType,

View File

@ -0,0 +1,98 @@
package conversion
import (
"fmt"
"time"
mv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/goodrain/rainbond/db"
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
"github.com/jinzhu/gorm"
"github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
//TenantServiceMonitor tenant service monitor
func TenantServiceMonitor(as *v1.AppService, dbmanager db.Manager) error {
sms := createServiceMonitor(as, dbmanager)
if sms != nil {
for i := range sms {
as.SetServiceMonitor(sms[i])
}
}
return nil
}
func createServiceMonitor(as *v1.AppService, dbmanager db.Manager) []*mv1.ServiceMonitor {
tsms, err := dbmanager.TenantServiceMonitorDao().GetByServiceID(as.ServiceID)
if err != nil && err != gorm.ErrRecordNotFound {
logrus.Errorf("get service %s monitor config failure %s", as.ServiceID, err.Error())
return nil
}
if tsms == nil || len(tsms) == 0 {
return nil
}
services := as.GetServices(false)
var portService = make(map[int32]*corev1.Service, len(services))
for i, s := range services {
for _, port := range s.Spec.Ports {
if _, exist := portService[port.Port]; exist {
if s.Labels["service_type"] == "inner" {
portService[port.Port] = services[i]
}
} else {
portService[port.Port] = services[i]
}
}
}
var re []*mv1.ServiceMonitor
for _, tsm := range tsms {
if tsm.Name == "" {
logrus.Warningf("service %s port %d service monitor name is empty", as.ServiceID, tsm.Port)
continue
}
service, exist := portService[int32(tsm.Port)]
if !exist {
logrus.Warningf("service %s port %d not open, can not set monitor", as.ServiceID, tsm.Port)
continue
}
// set service label app_name
service.Labels["app_name"] = tsm.ServiceShowName
as.SetService(service)
if tsm.Path == "" {
tsm.Path = "/metrics"
}
_, err = time.ParseDuration(tsm.Interval)
if err != nil {
logrus.Errorf("service monitor interval %s is valid, set default", tsm.Interval)
tsm.Interval = "10s"
}
sm := mv1.ServiceMonitor{}
sm.Name = tsm.Name
sm.Labels = as.GetCommonLabels()
sm.Namespace = as.TenantID
sm.Spec = mv1.ServiceMonitorSpec{
// service label app_name
JobLabel: "app_name",
NamespaceSelector: mv1.NamespaceSelector{Any: true},
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"service_port": service.Labels["service_port"],
"port_protocol": service.Labels["port_protocol"],
"name": service.Labels["name"],
"service_type": service.Labels["service_type"],
},
},
Endpoints: []mv1.Endpoint{
mv1.Endpoint{
Port: fmt.Sprintf("%d", tsm.Port),
Path: tsm.Path,
Interval: tsm.Interval,
},
},
}
re = append(re, &sm)
}
return re
}

View File

@ -27,7 +27,6 @@ import (
"github.com/jinzhu/gorm"
"github.com/sirupsen/logrus"
"github.com/goodrain/rainbond/builder"
"github.com/goodrain/rainbond/db"
"github.com/goodrain/rainbond/db/model"
@ -36,6 +35,7 @@ import (
"github.com/goodrain/rainbond/util"
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
"github.com/goodrain/rainbond/worker/appm/volume"
"github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
@ -267,8 +267,6 @@ func createEnv(as *v1.AppService, dbmanager db.Manager) (*[]corev1.EnvVar, error
}
envs = append(envs, corev1.EnvVar{Name: "MONITOR_PORT", Value: portStr})
}
//set net mode env by get from system
envs = append(envs, corev1.EnvVar{Name: "CUR_NET", Value: os.Getenv("CUR_NET")})
//set app custom envs
es, err := dbmanager.TenantServiceEnvVarDao().GetServiceEnvs(as.ServiceID, []string{"inner", "both", "outer"})
if err != nil {

View File

@ -22,6 +22,10 @@ import (
"fmt"
"time"
monitorv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/coreos/prometheus-operator/pkg/client/versioned"
"github.com/goodrain/rainbond/gateway/annotations/parser"
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
"github.com/sirupsen/logrus"
autoscalingv2 "k8s.io/api/autoscaling/v2beta2"
corev1 "k8s.io/api/core/v1"
@ -31,9 +35,6 @@ import (
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"github.com/goodrain/rainbond/gateway/annotations/parser"
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
)
const (
@ -523,3 +524,58 @@ func UpgradeEndpoints(clientset kubernetes.Interface,
}
return nil
}
// UpgradeServiceMonitor -
func UpgradeServiceMonitor(
clientset *versioned.Clientset,
as *v1.AppService,
old, new []*monitorv1.ServiceMonitor,
handleErr func(msg string, err error) error) error {
var oldMap = make(map[string]*monitorv1.ServiceMonitor, len(old))
for i := range old {
oldMap[old[i].Name] = old[i]
}
for _, n := range new {
if o, ok := oldMap[n.Name]; ok {
n.UID = o.UID
n.ResourceVersion = o.ResourceVersion
ing, err := clientset.MonitoringV1().ServiceMonitors(n.Namespace).Update(n)
if err != nil {
if err := handleErr(fmt.Sprintf("error updating service monitor: %+v: err: %v",
ing, err), err); err != nil {
return err
}
continue
}
as.SetServiceMonitor(n)
delete(oldMap, o.Name)
logrus.Debugf("ServiceID: %s; successfully update service monitor: %s", as.ServiceID, ing.Name)
} else {
ing, err := clientset.MonitoringV1().ServiceMonitors(n.Namespace).Create(n)
if err != nil {
if err := handleErr(fmt.Sprintf("error creating service monitor: %+v: err: %v",
ing, err), err); err != nil {
return err
}
continue
}
as.SetServiceMonitor(ing)
logrus.Debugf("ServiceID: %s; successfully create service monitor: %s", as.ServiceID, ing.Name)
}
}
for _, ing := range oldMap {
if ing != nil {
if err := clientset.MonitoringV1().ServiceMonitors(ing.Namespace).Delete(ing.Name,
&metav1.DeleteOptions{}); err != nil {
if err := handleErr(fmt.Sprintf("error deleting service monitor: %+v: err: %v",
ing, err), err); err != nil {
return err
}
continue
}
logrus.Debugf("ServiceID: %s; successfully delete service monitor: %s", as.ServiceID, ing.Name)
}
}
return nil
}

View File

@ -0,0 +1,50 @@
package store
import (
"time"
externalversions "github.com/coreos/prometheus-operator/pkg/client/informers/externalversions"
"github.com/coreos/prometheus-operator/pkg/client/versioned"
"github.com/sirupsen/logrus"
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
)
//ServiceMonitor service monitor custom resource
const ServiceMonitor = "servicemonitors.monitoring.coreos.com"
func (a *appRuntimeStore) GetCrds() (ret []*apiextensions.CustomResourceDefinition, err error) {
return a.listers.CRD.List(nil)
}
func (a *appRuntimeStore) GetCrd(name string) (ret *apiextensions.CustomResourceDefinition, err error) {
return a.listers.CRD.Get(name)
}
func (a *appRuntimeStore) GetServiceMonitorClient() (*versioned.Clientset, error) {
if c := a.crClients["ServiceMonitor"]; c != nil {
return c.(*versioned.Clientset), nil
}
c, err := versioned.NewForConfig(a.kubeconfig)
if err != nil {
return nil, err
}
a.crClients["ServiceMonitor"] = c
return c, nil
}
func (a *appRuntimeStore) initCustomResourceInformer(stopch chan struct{}) {
if cr, _ := a.GetCrd(ServiceMonitor); cr != nil {
smc, err := a.GetServiceMonitorClient()
if err != nil {
logrus.Errorf("get service monitor client failure %s", err.Error())
}
if smc != nil {
smFactory := externalversions.NewSharedInformerFactory(smc, 5*time.Minute)
informer := smFactory.Monitoring().V1().ServiceMonitors().Informer()
informer.AddEventHandlerWithResyncPeriod(a, time.Second*10)
a.informers.CRS[ServiceMonitor] = informer
logrus.Infof("[CRD] ServiceMonitor is inited")
}
}
a.informers.StartCRS(stopch)
}

View File

@ -39,6 +39,15 @@ type Informer struct {
Claims cache.SharedIndexInformer
Events cache.SharedIndexInformer
HorizontalPodAutoscaler cache.SharedIndexInformer
CRD cache.SharedIndexInformer
CRS map[string]cache.SharedIndexInformer
}
//StartCRS -
func (i *Informer) StartCRS(stop chan struct{}) {
for k := range i.CRS {
go i.CRS[k].Run(stop)
}
}
//Start statrt
@ -58,6 +67,7 @@ func (i *Informer) Start(stop chan struct{}) {
go i.Events.Run(stop)
go i.HorizontalPodAutoscaler.Run(stop)
go i.Claims.Run(stop)
go i.CRD.Run(stop)
}
//Ready if all kube informers is syncd, store is ready
@ -65,7 +75,7 @@ func (i *Informer) Ready() bool {
if i.Namespace.HasSynced() && i.Ingress.HasSynced() && i.Service.HasSynced() && i.Secret.HasSynced() &&
i.StatefulSet.HasSynced() && i.Deployment.HasSynced() && i.Pod.HasSynced() &&
i.ConfigMap.HasSynced() && i.Nodes.HasSynced() && i.Events.HasSynced() &&
i.HorizontalPodAutoscaler.HasSynced() && i.StorageClass.HasSynced() && i.Claims.HasSynced() {
i.HorizontalPodAutoscaler.HasSynced() && i.StorageClass.HasSynced() && i.Claims.HasSynced() && i.CRD.HasSynced() {
return true
}
return false

View File

@ -19,6 +19,7 @@
package store
import (
crdlisters "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion"
appsv1 "k8s.io/client-go/listers/apps/v1"
autoscalingv2 "k8s.io/client-go/listers/autoscaling/v2beta2"
corev1 "k8s.io/client-go/listers/core/v1"
@ -40,4 +41,5 @@ type Lister struct {
StorageClass storagev1.StorageClassLister
Claims corev1.PersistentVolumeClaimLister
HorizontalPodAutoscaler autoscalingv2.HorizontalPodAutoscalerLister
CRD crdlisters.CustomResourceDefinitionLister
}

View File

@ -25,10 +25,12 @@ import (
"sync"
"time"
monitorv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/coreos/prometheus-operator/pkg/client/versioned"
"github.com/goodrain/rainbond/util/constants"
"k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset"
"k8s.io/apimachinery/pkg/types"
"github.com/sirupsen/logrus"
"github.com/eapache/channels"
"github.com/goodrain/rainbond/cmd/worker/option"
"github.com/goodrain/rainbond/db"
@ -39,17 +41,21 @@ import (
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
workerutil "github.com/goodrain/rainbond/worker/util"
"github.com/jinzhu/gorm"
"github.com/sirupsen/logrus"
appsv1 "k8s.io/api/apps/v1"
autoscalingv2 "k8s.io/api/autoscaling/v2beta2"
corev1 "k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
storagev1 "k8s.io/api/storage/v1"
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
internalinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
listcorev1 "k8s.io/client-go/listers/core/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/cache"
)
@ -80,6 +86,9 @@ type Storer interface {
RegisterVolumeTypeListener(string, chan<- *model.TenantServiceVolumeType)
UnRegisterVolumeTypeListener(string)
InitOneThirdPartService(service *model.TenantServices) error
GetCrds() ([]*apiextensions.CustomResourceDefinition, error)
GetCrd(name string) (*apiextensions.CustomResourceDefinition, error)
GetServiceMonitorClient() (*versioned.Clientset, error)
}
// EventType type of event associated with an informer
@ -111,7 +120,10 @@ type ProbeInfo struct {
//appRuntimeStore app runtime store
//cache all kubernetes object and appservice
type appRuntimeStore struct {
kubeconfig *rest.Config
clientset kubernetes.Interface
crdClient *internalclientset.Clientset
crClients map[string]interface{}
ctx context.Context
cancel context.CancelFunc
informers *Informer
@ -130,26 +142,41 @@ type appRuntimeStore struct {
}
//NewStore new app runtime store
func NewStore(clientset kubernetes.Interface,
func NewStore(
kubeconfig *rest.Config,
clientset kubernetes.Interface,
dbmanager db.Manager,
conf option.Config,
startCh *channels.RingChannel,
probeCh *channels.RingChannel) Storer {
ctx, cancel := context.WithCancel(context.Background())
store := &appRuntimeStore{
kubeconfig: kubeconfig,
clientset: clientset,
ctx: ctx,
cancel: cancel,
informers: &Informer{},
informers: &Informer{CRS: make(map[string]cache.SharedIndexInformer)},
listers: &Lister{},
appServices: sync.Map{},
conf: conf,
dbmanager: dbmanager,
crClients: make(map[string]interface{}),
startCh: startCh,
resourceCache: NewResourceCache(),
podUpdateListeners: make(map[string]chan<- *corev1.Pod, 1),
volumeTypeListeners: make(map[string]chan<- *model.TenantServiceVolumeType, 1),
}
crdClient, err := internalclientset.NewForConfig(kubeconfig)
if err != nil {
logrus.Errorf("create crd client failure %s", err.Error())
}
if crdClient != nil {
store.crdClient = crdClient
crdFactory := internalinformers.NewSharedInformerFactory(crdClient, 5*time.Minute)
store.informers.CRD = crdFactory.Apiextensions().InternalVersion().CustomResourceDefinitions().Informer()
store.listers.CRD = crdFactory.Apiextensions().InternalVersion().CustomResourceDefinitions().Lister()
}
// create informers factory, enable and assign required informers
infFactory := informers.NewSharedInformerFactoryWithOptions(conf.KubeClient, 10*time.Second,
informers.WithNamespace(corev1.NamespaceAll))
@ -291,7 +318,6 @@ func NewStore(clientset kubernetes.Interface,
store.informers.Nodes.AddEventHandlerWithResyncPeriod(store, time.Second*10)
store.informers.StorageClass.AddEventHandlerWithResyncPeriod(store, time.Second*300)
store.informers.Claims.AddEventHandlerWithResyncPeriod(store, time.Second*10)
store.informers.Events.AddEventHandlerWithResyncPeriod(store.evtEventHandler(), time.Second*10)
store.informers.HorizontalPodAutoscaler.AddEventHandlerWithResyncPeriod(store, time.Second*10)
return store
@ -395,7 +421,6 @@ func (a *appRuntimeStore) Start() error {
if err := a.init(); err != nil {
return err
}
stopch := make(chan struct{})
a.informers.Start(stopch)
a.stopch = stopch
@ -621,6 +646,30 @@ func (a *appRuntimeStore) OnAdd(obj interface{}) {
}
}
}
if sm, ok := obj.(*monitorv1.ServiceMonitor); ok {
serviceID := sm.Labels["service_id"]
version := sm.Labels["version"]
createrID := sm.Labels["creater_id"]
if serviceID != "" && createrID != "" {
appservice, err := a.getAppService(serviceID, version, createrID, true)
if err == conversion.ErrServiceNotFound {
smClient, err := a.GetServiceMonitorClient()
if err != nil {
logrus.Errorf("create service monitor client failure %s", err.Error())
}
if smClient != nil {
err := smClient.MonitoringV1().ServiceMonitors(sm.GetNamespace()).Delete(sm.GetName(), &metav1.DeleteOptions{})
if err != nil && !errors.IsNotFound(err) {
logrus.Errorf("delete service monitor failure: %s", err.Error())
}
}
}
if appservice != nil {
appservice.SetServiceMonitor(sm)
return
}
}
}
}
func (a *appRuntimeStore) listHPAEvents(hpa *autoscalingv2.HorizontalPodAutoscaler) error {
@ -803,6 +852,18 @@ func (a *appRuntimeStore) OnDeletes(objs ...interface{}) {
}
}
}
if sm, ok := obj.(*monitorv1.ServiceMonitor); ok {
serviceID := sm.Labels["service_id"]
version := sm.Labels["version"]
createrID := sm.Labels["creater_id"]
if serviceID != "" && createrID != "" {
appservice, _ := a.getAppService(serviceID, version, createrID, true)
if appservice != nil {
appservice.DeleteServiceMonitor(sm)
return
}
}
}
}
}

View File

@ -23,6 +23,7 @@ import (
"os"
"strconv"
monitorv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/apps/v1"
autoscalingv2 "k8s.io/api/autoscaling/v2beta2"
@ -117,6 +118,7 @@ type AppService struct {
delSecrets []*corev1.Secret // secrets which need to be deleted
pods []*corev1.Pod
claims []*corev1.PersistentVolumeClaim
serviceMonitor []*monitorv1.ServiceMonitor
// claims that needs to be created manually
claimsmanual []*corev1.PersistentVolumeClaim
status AppServiceStatus
@ -682,6 +684,38 @@ func (a *AppService) SetHPA(hpa *autoscalingv2.HorizontalPodAutoscaler) {
a.hpas = append(a.hpas, hpa)
}
// SetServiceMonitor -
func (a *AppService) SetServiceMonitor(sm *monitorv1.ServiceMonitor) {
for i, s := range a.serviceMonitor {
if s.Name == sm.Name {
a.serviceMonitor[i] = sm
return
}
}
a.serviceMonitor = append(a.serviceMonitor, sm)
}
//DeleteServiceMonitor delete service monitor
func (a *AppService) DeleteServiceMonitor(sm *monitorv1.ServiceMonitor) {
if len(a.serviceMonitor) == 0 {
return
}
for i, old := range a.serviceMonitor {
if old.GetName() == sm.GetName() {
a.serviceMonitor = append(a.serviceMonitor[0:i], a.serviceMonitor[i+1:]...)
return
}
}
}
// GetServiceMonitors -
func (a *AppService) GetServiceMonitors(canCopy bool) []*monitorv1.ServiceMonitor {
if canCopy {
return append(a.serviceMonitor[:0:0], a.serviceMonitor...)
}
return a.serviceMonitor
}
// GetHPAs -
func (a *AppService) GetHPAs() []*autoscalingv2.HorizontalPodAutoscaler {
return a.hpas

View File

@ -26,12 +26,12 @@ import (
"strconv"
"strings"
"github.com/sirupsen/logrus"
"github.com/goodrain/rainbond/db"
"github.com/goodrain/rainbond/db/model"
dbmodel "github.com/goodrain/rainbond/db/model"
"github.com/goodrain/rainbond/util"
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
"github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -333,8 +333,6 @@ func createEnv(as *v1.AppService, dbmanager db.Manager) (*[]corev1.EnvVar, error
}
envs = append(envs, corev1.EnvVar{Name: "MONITOR_PORT", Value: portStr})
}
//set net mode env by get from system
envs = append(envs, corev1.EnvVar{Name: "CUR_NET", Value: os.Getenv("CUR_NET")})
//set app custom envs
es, err := dbmanager.TenantServiceEnvVarDao().GetServiceEnvs(as.ServiceID, []string{"inner", "both", "outer"})
if err != nil {