mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-12-04 20:57:38 +08:00
215 lines
6.7 KiB
Go
215 lines
6.7 KiB
Go
// RAINBOND, Application Management Platform
|
|
// Copyright (C) 2014-2017 Goodrain Co., Ltd.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
|
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
|
// must be obtained first.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package appm
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/goodrain/rainbond/pkg/db"
|
|
"github.com/goodrain/rainbond/pkg/db/model"
|
|
"github.com/goodrain/rainbond/pkg/event"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
|
|
"k8s.io/apimachinery/pkg/util/intstr"
|
|
"k8s.io/client-go/pkg/api/v1"
|
|
)
|
|
|
|
//K8sServiceBuild K8sServiceBuild
|
|
type K8sServiceBuild struct {
|
|
serviceID, eventID string
|
|
service *model.TenantServices
|
|
tenant *model.Tenants
|
|
dbmanager db.Manager
|
|
logger event.Logger
|
|
replicationType string
|
|
}
|
|
|
|
//K8sServiceBuilder 构建应用对应的k8s service
|
|
func K8sServiceBuilder(serviceID, replicationType string, logger event.Logger) (*K8sServiceBuild, error) {
|
|
dbmanager := db.GetManager()
|
|
service, err := dbmanager.TenantServiceDao().GetServiceByID(serviceID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("find service error. %v", err.Error())
|
|
}
|
|
tenant, err := dbmanager.TenantDao().GetTenantByUUID(service.TenantID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("find tenant error. %v", err.Error())
|
|
}
|
|
return &K8sServiceBuild{
|
|
serviceID: serviceID,
|
|
eventID: logger.Event(),
|
|
dbmanager: dbmanager,
|
|
service: service,
|
|
tenant: tenant,
|
|
logger: logger,
|
|
replicationType: replicationType,
|
|
}, nil
|
|
}
|
|
|
|
//GetTenantID 获取租户ID
|
|
func (k *K8sServiceBuild) GetTenantID() string {
|
|
return k.tenant.UUID
|
|
}
|
|
|
|
//Build 构建应用的所有端口服务
|
|
func (k *K8sServiceBuild) Build() ([]*v1.Service, error) {
|
|
ports, err := k.dbmanager.TenantServicesPortDao().GetPortsByServiceID(k.serviceID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("find service port from db error %s", err.Error())
|
|
}
|
|
var services []*v1.Service
|
|
//创建分端口的负载均衡Service
|
|
if ports != nil && len(ports) > 0 {
|
|
for i := range ports {
|
|
port := ports[i]
|
|
if port.IsInnerService {
|
|
services = append(services, k.createInnerService(port))
|
|
}
|
|
if port.IsOuterService {
|
|
services = append(services, k.createOuterService(port))
|
|
}
|
|
}
|
|
}
|
|
//创建有状态服务DNS服务Service
|
|
if k.replicationType == model.TypeStatefulSet {
|
|
services = append(services, k.createStatefulService(ports))
|
|
}
|
|
return services, nil
|
|
}
|
|
|
|
//BuildOnPort 指定端口创建Service
|
|
func (k *K8sServiceBuild) BuildOnPort(p int, isOut bool) (*v1.Service, error) {
|
|
port, err := k.dbmanager.TenantServicesPortDao().GetPort(k.serviceID, p)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("find service port from db error %s", err.Error())
|
|
}
|
|
if port != nil {
|
|
if !isOut && port.IsInnerService {
|
|
return k.createInnerService(port), nil
|
|
}
|
|
if isOut && port.IsOuterService {
|
|
return k.createOuterService(port), nil
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("tenant service port %d is not exist", p)
|
|
}
|
|
|
|
func (k *K8sServiceBuild) createInnerService(port *model.TenantServicesPort) *v1.Service {
|
|
var service v1.Service
|
|
service.Name = fmt.Sprintf("service-%d-%d", port.ID, port.ContainerPort)
|
|
service.Labels = map[string]string{
|
|
"service_type": "inner",
|
|
"name": k.service.ServiceAlias + "Service",
|
|
}
|
|
var servicePort v1.ServicePort
|
|
if port.Protocol == "udp" {
|
|
servicePort.Protocol = "UDP"
|
|
} else {
|
|
servicePort.Protocol = "TCP"
|
|
}
|
|
servicePort.TargetPort = intstr.FromInt(port.ContainerPort)
|
|
servicePort.Port = int32(port.MappingPort)
|
|
if servicePort.Port == 0 {
|
|
servicePort.Port = int32(port.ContainerPort)
|
|
}
|
|
spec := v1.ServiceSpec{
|
|
Ports: []v1.ServicePort{servicePort},
|
|
Selector: map[string]string{"name": k.service.ServiceAlias},
|
|
}
|
|
service.Spec = spec
|
|
return &service
|
|
}
|
|
|
|
func (k *K8sServiceBuild) createOuterService(port *model.TenantServicesPort) *v1.Service {
|
|
var service v1.Service
|
|
service.Name = fmt.Sprintf("service-%d-%dout", port.ID, port.ContainerPort)
|
|
service.Labels = map[string]string{
|
|
"service_type": "outer",
|
|
"name": k.service.ServiceAlias + "ServiceOUT",
|
|
"tenant_name": k.tenant.Name,
|
|
"services_version": k.service.ServiceVersion,
|
|
"domain": k.service.Autodomain(k.tenant.Name, port.ContainerPort),
|
|
"protocol": port.Protocol,
|
|
"ca": "",
|
|
"key": "",
|
|
"event_id": k.eventID,
|
|
}
|
|
if port.Protocol == "stream" { //stream 协议获取映射端口
|
|
mapPort, err := k.dbmanager.TenantServiceLBMappingPortDao().GetTenantServiceLBMappingPortByService(k.serviceID)
|
|
if err != nil {
|
|
logrus.Error("get tenant service lb map port error", err.Error())
|
|
service.Labels["lbmap_port"] = "0"
|
|
} else {
|
|
service.Labels["lbmap_port"] = fmt.Sprintf("%d", mapPort.Port)
|
|
}
|
|
}
|
|
var servicePort v1.ServicePort
|
|
if port.Protocol == "udp" {
|
|
servicePort.Protocol = "UDP"
|
|
} else {
|
|
servicePort.Protocol = "TCP"
|
|
}
|
|
servicePort.TargetPort = intstr.FromInt(port.ContainerPort)
|
|
servicePort.Port = int32(port.ContainerPort)
|
|
var portType v1.ServiceType
|
|
if os.Getenv("CUR_NET") == "midonet" {
|
|
portType = v1.ServiceTypeNodePort
|
|
} else {
|
|
portType = v1.ServiceTypeClusterIP
|
|
}
|
|
spec := v1.ServiceSpec{
|
|
Ports: []v1.ServicePort{servicePort},
|
|
Selector: map[string]string{"name": k.service.ServiceAlias},
|
|
Type: portType,
|
|
}
|
|
service.Spec = spec
|
|
return &service
|
|
}
|
|
|
|
func (k *K8sServiceBuild) createStatefulService(ports []*model.TenantServicesPort) *v1.Service {
|
|
var service v1.Service
|
|
service.Name = k.service.ServiceAlias
|
|
service.Labels = map[string]string{
|
|
"service_type": "stateful",
|
|
"name": k.service.ServiceAlias + "ServiceStateful",
|
|
}
|
|
var serviceports []v1.ServicePort
|
|
for _, p := range ports {
|
|
var servicePort v1.ServicePort
|
|
servicePort.Protocol = "TCP"
|
|
servicePort.TargetPort = intstr.FromInt(p.ContainerPort)
|
|
servicePort.Port = int32(p.MappingPort)
|
|
servicePort.Name = fmt.Sprintf("%d-port", p.ID)
|
|
if servicePort.Port == 0 {
|
|
servicePort.Port = int32(p.ContainerPort)
|
|
}
|
|
serviceports = append(serviceports, servicePort)
|
|
}
|
|
|
|
spec := v1.ServiceSpec{
|
|
Ports: serviceports,
|
|
Selector: map[string]string{"name": k.service.ServiceAlias},
|
|
ClusterIP: "None",
|
|
}
|
|
service.Spec = spec
|
|
return &service
|
|
}
|