tenategateway 是用于控制 nginxingresscontroller 的CRD,nginxingresscontroller是用于管理真实nginx实例的CRD,详见: https://github.com/kubegems/ingress-nginx-operator
我们的路由ingress
必须打上networking.kubegems.io/ingressClass
,用于在界面上筛选目标网关中使用的路由
此外,我们在kubegems-controller
中使用了webhook来做以下控制:
- 在路由规则
rules
中,如果没指定host
, 随机生成域名 - 检查协议,如果使用grpc必须开启http2
func CheckGatewayAndIngressProtocol(tg gemsv1beta1.TenantGateway, ingresses []networkingv1.Ingress) error { if !IsGatewayHTTP2(tg) { for _, ingress := range ingresses { if IsIngressGRPC(ingress) { return fmt.Errorf("ingress [%s] services [%s] use grpc protocol, the gateway [%s] must config http/2", ingress.Name, ingress.Annotations["nginx.org/grpc-services"], tg.Name) } } } return nil }
- 打上ingressclass标签
在安装gateway插件后,会创建默认的全局网关default-gateway
,所有租户都能看到并使用它,创建逻辑在kubegems-controller
中:
func CreateDefaultTenantGateway(client client.Client, log logr.Logger) {
tg := gemsv1beta1.TenantGateway{
ObjectMeta: metav1.ObjectMeta{
Name: defaultGatewayName,
Namespace: gemlabels.NamespaceGateway,
Labels: map[string]string{
networking.LabelIngressClass: defaultGatewayName,
},
},
Spec: gemsv1beta1.TenantGatewaySpec{
Tenant: notenant,
IngressClass: defaultGatewayName,
},
}
execute := func() error {
nicList := nginxv1beta1.NginxIngressControllerList{}
if err := client.List(context.TODO(), &nicList); err != nil {
return err
}
return client.Create(context.TODO(), &tg)
}
for {
err := execute()
switch {
case err == nil:
log.Info("succeed to create default tenant gateway")
return
case apierrors.IsAlreadyExists(err):
log.Info("default tenant gateway already exist")
return
default:
log.Info(fmt.Sprintf("failed to create default tenant gateway: %v, waiting to try again", err))
time.Sleep(10 * time.Second)
}
}
}
他会不断创建default-gateway
直到创建成功。