Merge branch 'V5.1' into V5.1

This commit is contained in:
黄润豪 2019-03-14 11:36:12 +08:00 committed by GitHub
commit be0a0da07d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 273 additions and 54 deletions

View File

@ -164,18 +164,10 @@ func (g *GatewayAction) UpdateHTTPRule(req *apimodel.UpdateHTTPRuleStruct) (stri
if req.Domain != "" {
rule.Domain = req.Domain
}
if req.Path != "" {
rule.Path = req.Path
}
if req.Header != "" {
rule.Header = req.Header
}
if req.Cookie != "" {
rule.Cookie = req.Cookie
}
if req.Weight > 0 {
rule.Weight = req.Weight
}
rule.Path = req.Path
rule.Header = req.Header
rule.Cookie = req.Cookie
rule.Weight = req.Weight
if req.IP != "" {
rule.IP = req.IP
}
@ -548,44 +540,44 @@ func (g *GatewayAction) RuleConfig(req *apimodel.RuleConfigReq) error {
// TODO: use reflect to read the field of req, huangrh
configs = append(configs, &model.GwRuleConfig{
RuleID: req.RuleID,
Key: "proxy-connect-timeout",
Value: strconv.Itoa(req.Body.ProxyConnectTimeout),
Key: "proxy-connect-timeout",
Value: strconv.Itoa(req.Body.ProxyConnectTimeout),
})
configs = append(configs, &model.GwRuleConfig{
RuleID: req.RuleID,
Key: "proxy-send-timeout",
Value: strconv.Itoa(req.Body.ProxySendTimeout),
Key: "proxy-send-timeout",
Value: strconv.Itoa(req.Body.ProxySendTimeout),
})
configs = append(configs, &model.GwRuleConfig{
RuleID: req.RuleID,
Key: "proxy-read-timeout",
Value: strconv.Itoa(req.Body.ProxyReadTimeout),
Key: "proxy-read-timeout",
Value: strconv.Itoa(req.Body.ProxyReadTimeout),
})
configs = append(configs, &model.GwRuleConfig{
RuleID: req.RuleID,
Key: "proxy-buffers-number",
Value: strconv.Itoa(req.Body.ProxyBuffersNumber),
Key: "proxy-buffers-number",
Value: strconv.Itoa(req.Body.ProxyBuffersNumber),
})
configs = append(configs, &model.GwRuleConfig{
RuleID: req.RuleID,
Key: "proxy-buffer-size",
Value: req.Body.ProxyBufferSize,
Key: "proxy-buffer-size",
Value: req.Body.ProxyBufferSize,
})
configs = append(configs, &model.GwRuleConfig{
RuleID: req.RuleID,
Key: "proxy-buffering",
Value: req.Body.ProxyBuffering,
Key: "proxy-buffering",
Value: req.Body.ProxyBuffering,
})
configs = append(configs, &model.GwRuleConfig{
RuleID: req.RuleID,
Key: "proxy-body-size",
Value: strconv.Itoa(req.Body.ProxyBuffersNumber),
Key: "proxy-body-size",
Value: strconv.Itoa(req.Body.ProxyBuffersNumber),
})
for _, item := range req.Body.SetHeaders {
configs = append(configs, &model.GwRuleConfig{
RuleID: req.RuleID,
Key: "set-header-" + item.Key,
Value: item.Value,
Key: "set-header-" + key,
Value: value,
})
}
@ -602,4 +594,4 @@ func (g *GatewayAction) RuleConfig(req *apimodel.RuleConfigReq) error {
}
tx.Commit()
return nil
}
}

View File

@ -80,6 +80,7 @@ type Config struct {
RepoGrMeIP string
NodeName string
HostIP string
EnableInterface []string
}
// ListenPorts describe the ports required to run the gateway controller
@ -113,6 +114,8 @@ func (g *GWServer) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&g.HealthPath, "health-path", "/healthz", "absolute path to the kubeconfig file")
fs.DurationVar(&g.HealthCheckTimeout, "health-check-timeout", 10, `Time limit, in seconds, for a probe to health-check-path to succeed.`)
fs.IntVar(&g.ListenPorts.Health, "healthz-port", 10254, `Port to use for the healthz endpoint.`)
fs.IntVar(&g.ListenPorts.HTTP, "service-http-port", 80, `Port to use for the http service rule`)
fs.IntVar(&g.ListenPorts.HTTPS, "service-https-port", 443, `Port to use for the https service rule`)
fs.BoolVar(&g.EnableMetrics, "enable-metrics", true, "Enables the collection of rbd-gateway metrics")
// rainbond endpoints
fs.BoolVar(&g.EnableRbdEndpoints, "enable-rbd-endpoints", true, "switch of Rainbond endpoints")
@ -130,6 +133,7 @@ func (g *GWServer) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&g.NodeName, "node-name", "", "this gateway node host name")
fs.StringVar(&g.HostIP, "node-ip", "", "this gateway node ip")
fs.BoolVar(&g.Debug, "debug", false, "enable pprof debug")
fs.StringArrayVar(&g.EnableInterface, "enable-interface", nil, "The network interface name that support listening and managing by gateway")
}
// SetLog sets log

View File

@ -27,6 +27,8 @@ import (
"syscall"
"time"
"github.com/goodrain/rainbond/gateway/cluster"
"github.com/go-chi/chi"
"github.com/goodrain/rainbond/util"
@ -49,11 +51,15 @@ func Run(s *option.GWServer) error {
errCh := make(chan error)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
//create cluster node manage
_, err := cluster.CreateNodeManager(s.Config)
if err != nil {
return fmt.Errorf("create gateway node manage failure %s", err.Error())
}
reg := prometheus.NewRegistry()
reg.MustRegister(prometheus.NewGoCollector())
reg.MustRegister(prometheus.NewProcessCollector(os.Getpid(), "gateway"))
mc := metric.NewDummyCollector()
var err error
if s.Config.EnableMetrics {
mc, err = metric.NewCollector(s.NodeName, reg)
if err != nil {

118
gateway/cluster/node.go Normal file
View File

@ -0,0 +1,118 @@
// RAINBOND, Application Management Platform
// Copyright (C) 2014-2019 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 cluster
import (
"fmt"
"net"
"time"
"github.com/goodrain/rainbond/util"
"github.com/Sirupsen/logrus"
"github.com/goodrain/rainbond/cmd/gateway/option"
)
//NodeManager node manager
type NodeManager struct {
localV4Hosts []net.IP
localV16Hosts []net.IP
config option.Config
}
//CreateNodeManager create node manager
func CreateNodeManager(config option.Config) (*NodeManager, error) {
nm := &NodeManager{
config: config,
}
if err := nm.initLocalHost(); err != nil {
return nil, err
}
if ok := nm.checkGatewayPort(); !ok {
return nil, fmt.Errorf("Check gateway node port failure")
}
return nm, nil
}
func (n *NodeManager) initLocalHost() error {
tables, err := net.Interfaces()
if err != nil {
return err
}
for _, t := range tables {
if n.config.EnableInterface != nil && len(n.config.EnableInterface) > 0 {
if ok := util.StringArrayContains(n.config.EnableInterface, t.Name); !ok {
continue
}
}
logrus.Infof("Network interface %s is enable manage by gateway", t.Name)
addrs, err := t.Addrs()
if err != nil {
return err
}
for _, a := range addrs {
ipnet, ok := a.(*net.IPNet)
//ipnet.IP.IsLoopback()
if !ok {
continue
}
if ipv4 := ipnet.IP.To4(); ipv4 != nil {
n.localV4Hosts = append(n.localV4Hosts, ipnet.IP.To4())
}
if ipv16 := ipnet.IP.To16(); ipv16 != nil {
n.localV16Hosts = append(n.localV16Hosts, ipnet.IP.To16())
}
}
}
return nil
}
func (n *NodeManager) checkGatewayPort() bool {
ports := []uint32{
uint32(n.config.ListenPorts.Health),
uint32(n.config.ListenPorts.HTTP),
uint32(n.config.ListenPorts.HTTPS),
uint32(n.config.ListenPorts.Status),
}
return n.CheckPortAvailable("tcp", ports...)
}
//CheckPortAvailable checks whether the specified port is available
func (n *NodeManager) CheckPortAvailable(protocol string, ports ...uint32) bool {
if protocol == "" {
protocol = "tcp"
}
timeout := time.Second * 3
for _, port := range ports {
for _, ip := range n.localV4Hosts {
c, _ := net.DialTimeout(protocol, fmt.Sprintf("%s:%d", ip.String(), port), timeout)
if c != nil {
logrus.Errorf("Gateway must need listen port %d, but it has been uesd.", port)
return false
}
}
}
return true
}
//GetLocalV4IPs get current host all available IP
func (n *NodeManager) GetLocalV4IPs() []net.IP {
return n.localV4Hosts
}

View File

@ -0,0 +1,42 @@
// RAINBOND, Application Management Platform
// Copyright (C) 2014-2019 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 cluster
import (
"testing"
"github.com/goodrain/rainbond/cmd/gateway/option"
)
func TestCreateNodeManager(t *testing.T) {
nm, err := CreateNodeManager(option.Config{
ListenPorts: option.ListenPorts{
HTTP: 80,
},
})
if err != nil {
t.Fatal(err)
}
t.Log(nm.localV4Hosts)
if ok := nm.checkGatewayPort(); !ok {
t.Log("port check is not pass")
} else {
t.Log("port check is passed")
}
}

View File

@ -37,7 +37,7 @@ import (
"github.com/goodrain/rainbond/cmd/gateway/option"
"github.com/goodrain/rainbond/gateway/controller/openresty/model"
"github.com/goodrain/rainbond/gateway/controller/openresty/template"
"github.com/goodrain/rainbond/gateway/v1"
v1 "github.com/goodrain/rainbond/gateway/v1"
"github.com/goodrain/rainbond/util"
"github.com/goodrain/rainbond/util/cert"
)
@ -145,7 +145,10 @@ func (o *OrService) PersistConfig(conf *v1.Config) error {
// http
if len(l7srv) > 0 {
filename := "http/servers.conf"
if err := template.NewServerTemplate(l7srv, filename); err != nil {
if err := template.NewServerTemplate(&template.ServerContext{
Servers: l7srv,
Set: *o.ocfg,
}, filename); err != nil {
logrus.Errorf("Fail to new nginx Server ocfg file: %v", err)
return err
}
@ -154,7 +157,10 @@ func (o *OrService) PersistConfig(conf *v1.Config) error {
// stream
if len(l4srv) > 0 {
filename := "stream/servers.conf"
if err := template.NewServerTemplate(l4srv, filename); err != nil {
if err := template.NewServerTemplate(&template.ServerContext{
Servers: l4srv,
Set: *o.ocfg,
}, filename); err != nil {
logrus.Errorf("Fail to new nginx Server file: %v", err)
return err
}
@ -217,9 +223,13 @@ func getNgxServer(conf *v1.Config) (l7srv []*model.Server, l4srv []*model.Server
"service_id": vs.ServiceID,
},
}
if vs.SSLCert != nil {
server.SSLCertificate = vs.SSLCert.CertificatePem
server.SSLCertificateKey = vs.SSLCert.CertificatePem
if vs.ForceSSLRedirect {
}
}
for _, loc := range vs.Locations {
location := &model.Location{
@ -353,8 +363,9 @@ func (o *OrService) newRbdServers() error {
if o.ocfg.EnableKApiServer {
ksrv := kubeApiserver(o.ocfg.KApiServerIP)
if err := template.NewServerTemplateWithCfgPath(
[]*model.Server{
ksrv,
&template.ServerContext{
Servers: []*model.Server{ksrv},
Set: *o.ocfg,
}, tcpCfgPath, "server.default.tcp.conf"); err != nil {
return err
}
@ -395,7 +406,10 @@ func (o *OrService) newRbdServers() error {
resrv := repoGoodrainMe(o.ocfg.RepoGrMeIP)
srv = append(srv, resrv)
}
if err := template.NewServerTemplateWithCfgPath(srv, httpCfgPath,
if err := template.NewServerTemplateWithCfgPath(&template.ServerContext{
Servers: srv,
Set: *o.ocfg,
}, httpCfgPath,
"servers.default.http.conf"); err != nil {
return err
}

View File

@ -24,6 +24,8 @@ import (
"path"
text_template "text/template"
"github.com/goodrain/rainbond/cmd/gateway/option"
"github.com/Sirupsen/logrus"
"github.com/goodrain/rainbond/gateway/controller/openresty/model"
@ -78,8 +80,14 @@ func NewNginxTemplate(data *model.Nginx, defaultNginxConf string) error {
return nil
}
//ServerContext ServerContext
type ServerContext struct {
Servers []*model.Server
Set option.Config
}
// NewServerTemplate creates a configuration file for the nginx server module
func NewServerTemplate(data []*model.Server, filename string) error {
func NewServerTemplate(data *ServerContext, filename string) error {
if e := Persist(tmplPath+"/servers.tmpl", data, CustomConfigPath, filename); e != nil {
return e
}
@ -87,7 +95,7 @@ func NewServerTemplate(data []*model.Server, filename string) error {
}
// NewServerTemplateWithCfgPath creates a configuration file for the nginx server module
func NewServerTemplateWithCfgPath(data []*model.Server, cfgPath string, filename string) error {
func NewServerTemplateWithCfgPath(data *ServerContext, cfgPath string, filename string) error {
if e := Persist(tmplPath+"/servers.tmpl", data, cfgPath, filename); e != nil {
return e
}

View File

@ -25,6 +25,7 @@ import (
"net"
"os"
"reflect"
"strconv"
"strings"
"sync"
@ -36,7 +37,7 @@ import (
"github.com/goodrain/rainbond/gateway/controller/config"
"github.com/goodrain/rainbond/gateway/defaults"
"github.com/goodrain/rainbond/gateway/util"
"github.com/goodrain/rainbond/gateway/v1"
v1 "github.com/goodrain/rainbond/gateway/v1"
corev1 "k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -547,7 +548,7 @@ func (s *k8sStore) ListVirtualService() (l7vs []*v1.VirtualService, l4vs []*v1.V
vs = l7vsMap[virSrvName]
if vs == nil {
vs = &v1.VirtualService{
Listening: []string{"80"},
Listening: []string{strconv.Itoa(s.conf.ListenPorts.HTTP)},
ServerName: virSrvName,
Locations: []*v1.Location{},
ForceSSLRedirect: anns.Rewrite.ForceSSLRedirect,
@ -555,7 +556,7 @@ func (s *k8sStore) ListVirtualService() (l7vs []*v1.VirtualService, l4vs []*v1.V
vs.Namespace = ing.Namespace
vs.ServiceID = anns.Labels["service_id"]
if len(hostSSLMap) != 0 {
vs.Listening = []string{"443", "ssl"}
vs.Listening = []string{strconv.Itoa(s.conf.ListenPorts.HTTPS), "ssl"}
if hostSSLMap[virSrvName] != nil {
vs.SSLCert = hostSSLMap[virSrvName]
} else { // TODO: if there is necessary to provide a default virtual service name
@ -565,7 +566,6 @@ func (s *k8sStore) ListVirtualService() (l7vs []*v1.VirtualService, l4vs []*v1.V
l7vsMap[virSrvName] = vs
l7vs = append(l7vs, vs)
}
for _, path := range rule.IngressRuleValue.HTTP.Paths {
svckey := fmt.Sprintf("%s/%s", ing.Namespace, path.Backend.ServiceName)
name, err := s.GetServiceNameLabelByKey(svckey)
@ -573,7 +573,6 @@ func (s *k8sStore) ListVirtualService() (l7vs []*v1.VirtualService, l4vs []*v1.V
logrus.Warningf("key: %s; error getting service name label: %v", svckey, err)
continue
}
locKey := fmt.Sprintf("%s_%s", virSrvName, path.Path)
location := srvLocMap[locKey]
l7PoolMap[name] = struct{}{}

View File

@ -20,6 +20,7 @@ package cmd
import (
"fmt"
"os"
"strconv"
@ -46,7 +47,18 @@ func NewCmdCluster() cli.Command {
func getClusterInfo(c *cli.Context) error {
//show cluster resource detail
clusterInfo, err := clients.RegionClient.Cluster().GetClusterInfo()
handleErr(err)
if err != nil {
if err.Code == 502 {
fmt.Println("The current cluster node manager is not working properly.")
fmt.Println("You can query the service log for troubleshooting.")
fmt.Println("Exec Command: journalctl -fu node")
os.Exit(1)
}
fmt.Println("The current cluster api server is not working properly.")
fmt.Println("You can query the service log for troubleshooting.")
fmt.Println("Exec Command: journalctl -fu rbd-api")
os.Exit(1)
}
table := uitable.New()
table.AddRow("", "Used/Total", "Use of")
table.AddRow("CPU", fmt.Sprintf("%2.f/%d", clusterInfo.ReqCPU, clusterInfo.CapCPU),

View File

@ -433,8 +433,9 @@ func showServiceDeployInfo(c *cli.Context) error {
if pod.Spec.Volumes != nil && len(pod.Spec.Volumes) > 0 {
value := ""
for _, v := range pod.Spec.Volumes {
valueline := ""
if v.HostPath != nil {
value += v.HostPath.Path
valueline += v.HostPath.Path
}
if v.PersistentVolumeClaim != nil {
claimName := v.PersistentVolumeClaim.ClaimName
@ -444,11 +445,16 @@ func showServiceDeployInfo(c *cli.Context) error {
pv, _ := clients.K8SClient.Core().PersistentVolumes().Get(pvn, metav1.GetOptions{})
if pv != nil {
if hostPath := pv.Spec.HostPath; hostPath != nil {
value += hostPath.Path
valueline += hostPath.Path
}
}
}
}
//if not pvc, do not show
if valueline == "" {
continue
}
value += valueline
con:
for _, vc := range pod.Spec.Containers {
m := vc.VolumeMounts

View File

@ -1,10 +1,17 @@
{{ range $srv := . }}
{{ $http_port := .Set.ListenPorts.HTTP }}
{{ range $srv := .Servers }}
{{ if $srv.ForceSSLRedirect }}
server {
listen 80;
listen {{ $http_port }};
{{ if $srv.ServerName }}server_name {{$srv.ServerName}};{{end}}
rewrite ^ https://$http_host$request_uri? permanent;
{{ range $loc := $srv.Locations }}
location {{$loc.Path}} {
rewrite ^ https://$http_host$request_uri? permanent;
{{ if $loc.DisableAccessLog }}
access_log off;
{{ end }}
}
{{ end }}
}
{{ end }}
server {

View File

@ -138,19 +138,16 @@ func (d *Monitor) discoverCadvisor(c *callback.Cadvisor, done <-chan struct{}) {
switch event.Type {
case watch.Added:
isSlave := gjson.Get(event.GetValueString(), "labels.rainbond_node_rule_compute").String()
if isSlave == "true" {
c.Add(&event)
}
case watch.Modified:
isSlave := gjson.Get(event.GetValueString(), "labels.rainbond_node_rule_compute").String()
if isSlave == "true" {
c.Modify(&event)
}
case watch.Deleted:
isSlave := gjson.Get(event.GetValueString(), "labels.rainbond_node_rule_compute").String()
if isSlave == "true" {
c.Delete(&event)

View File

@ -21,9 +21,10 @@ package v1
import (
"crypto/sha256"
"fmt"
"github.com/goodrain/rainbond/db/model"
"time"
"github.com/goodrain/rainbond/db/model"
corev1 "k8s.io/api/core/v1"
)
@ -77,6 +78,19 @@ var (
//GetServiceStatus get service status
func (a *AppService) GetServiceStatus() string {
if a.ServiceKind == model.ServiceKindThirdParty {
var readyEndpointSize int
endpoints := a.GetEndpoints()
for _, ed := range endpoints {
for _, s := range ed.Subsets {
readyEndpointSize += len(s.Addresses)
}
}
if readyEndpointSize > 0 {
return RUNNING
}
return ABNORMAL
}
if a == nil {
return CLOSED
}