Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bootstrap: Add Loadbalancer service and namespace to bootstrap file. #661

Merged
merged 3 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/cl-dataplane/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ const (

// Name is the app label of dataplane pods.
Name = "cl-dataplane"
// IngressSvcName is the ingress service name for the dataplane pods.
IngressSvcName = "clusterlink"
)

// Options contains everything necessary to create and run a dataplane.
Expand Down
10 changes: 5 additions & 5 deletions cmd/clusterlink/cmd/deploy/deploy_peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ func (o *PeerOptions) Run() error {
Tag: o.Tag,
}

// Create clusterlink instance YAML for the operator.
if o.IngressPort != apis.DefaultExternalPort { // Set the port config only if it has changed.
platformCfg.IngressPort = o.IngressPort
}

if o.StartInstance == NoStart {
// Create a YAML file for deployment without using the operator.
k8sConfig, err := platform.K8SConfig(platformCfg)
Expand Down Expand Up @@ -260,11 +265,6 @@ func (o *PeerOptions) Run() error {
return err
}

// Create clusterlink instance YAML for the operator.
if o.IngressPort != apis.DefaultExternalPort { // Set the port config only if it has changed.
platformCfg.IngressPort = o.IngressPort
}

instance, err := platform.K8SClusterLinkInstanceConfig(platformCfg, "cl-instance")
if err != nil {
return err
Expand Down
103 changes: 86 additions & 17 deletions pkg/bootstrap/platform/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,16 @@ import (
apis "github.com/clusterlink-net/clusterlink/pkg/apis/clusterlink.net/v1alpha1"
cpapi "github.com/clusterlink-net/clusterlink/pkg/controlplane/api"
dpapi "github.com/clusterlink-net/clusterlink/pkg/dataplane/api"
corev1 "k8s.io/api/core/v1"
)

const (
nsTemplate = `---
apiVersion: v1
kind: Namespace
metadata:
name: {{.namespace}}
`
certsTemplate = `---
apiVersion: v1
kind: Secret
Expand Down Expand Up @@ -64,7 +71,6 @@ data:
{{.peerKeyFile}}: {{.peerKey}}
{{.fabricCertFile}}: {{.fabricCert}}
`

k8sTemplate = `---
apiVersion: apps/v1
kind: Deployment
Expand Down Expand Up @@ -181,18 +187,6 @@ spec:
- name: controlplane
port: {{.controlplanePort}}
---
apiVersion: v1
kind: Service
metadata:
name: cl-dataplane
namespace: {{.namespace}}
spec:
selector:
app: {{ .dataplaneAppName }}
ports:
- name: dataplane
port: {{.dataplanePort}}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
Expand Down Expand Up @@ -237,7 +231,8 @@ roleRef:
subjects:
- kind: ServiceAccount
name: default
namespace: {{.namespace}}`
namespace: {{.namespace}}
`
ClusterLinkInstanceTemplate = `apiVersion: clusterlink.net/v1alpha1
kind: Instance
metadata:
Expand All @@ -263,6 +258,24 @@ spec:
namespace: {{.namespace}}
tag: {{.tag}}
`
ingressTemplate = `---
apiVersion: v1
kind: Service
metadata:
name: {{.dataplaneService}}
namespace: {{.namespace}}
spec:
type: {{.ingressType}}
ports:
- name: dataplane
port: {{.ingressPort }}
targetPort: {{.dataplanePort}}
{{ if .ingressNodePort }}
nodePort: {{.ingressNodePort }}
{{ end }}
selector:
app: {{.dataplaneAppName}}
`
)

// K8SConfig returns a kubernetes deployment file.
Expand Down Expand Up @@ -299,19 +312,36 @@ func K8SConfig(config *Config) ([]byte, error) {
"dataplanePort": dpapi.ListenPort,
}

var k8sConfig bytes.Buffer
t := template.Must(template.New("").Parse(k8sTemplate))
var k8sConfig, nsConfig bytes.Buffer
// ClusterLink namespace
t := template.Must(template.New("").Parse(nsTemplate))
if err := t.Execute(&nsConfig, args); err != nil {
return nil, fmt.Errorf("cannot create K8s namespace from template: %w", err)
}

// ClusterLink components
t = template.Must(template.New("").Parse(k8sTemplate))
if err := t.Execute(&k8sConfig, args); err != nil {
return nil, fmt.Errorf("cannot create k8s configuration from template: %w", err)
}

// ClusterLink certificates
certConfig, err := K8SCertificateConfig(config)
if err != nil {
return nil, err
}

k8sBytes := certConfig
// ClusterLink ingress service
ingressConfig, err := k8SIngressConfig(config)
if err != nil {
return nil, err
}

k8sBytes := nsConfig.Bytes()
k8sBytes = append(k8sBytes, certConfig...)
k8sBytes = append(k8sBytes, k8sConfig.Bytes()...)
k8sBytes = append(k8sBytes, ingressConfig...)

return k8sBytes, nil
}

Expand Down Expand Up @@ -372,6 +402,7 @@ func K8SClusterLinkInstanceConfig(config *Config, name string) ([]byte, error) {
}
args["ingressPort"] = config.IngressPort
}

var clConfig bytes.Buffer
t := template.Must(template.New("").Parse(ClusterLinkInstanceTemplate))
if err := t.Execute(&clConfig, args); err != nil {
Expand Down Expand Up @@ -404,3 +435,41 @@ func K8SEmptyCertificateConfig(config *Config) ([]byte, error) {

return certConfig.Bytes(), nil
}

// k8SIngressConfig returns a kubernetes ingress service.
func k8SIngressConfig(config *Config) ([]byte, error) {
var ingressConfig bytes.Buffer

ingressType := string(corev1.ServiceTypeClusterIP)
if config.IngressType == string(apis.IngressTypeNodePort) || config.IngressType == string(apis.IngressTypeLoadBalancer) {
ingressType = config.IngressType
}

args := map[string]interface{}{
"namespace": config.Namespace,
"ingressPort": apis.DefaultExternalPort,
"ingressType": ingressType,

"dataplaneService": dpapp.IngressSvcName,
"dataplaneAppName": dpapp.Name,
"dataplanePort": dpapi.ListenPort,
}

if config.IngressPort != 0 {
if config.IngressType == string(apis.IngressTypeNodePort) {
args["ingressNodePort"] = config.IngressPort
if (config.IngressPort < 30000) || (config.IngressPort > 32767) {
return nil, fmt.Errorf("nodeport number %v is not in the valid range (30000:32767)", config.IngressPort)
}
} else {
args["ingressPort"] = config.IngressPort
}
}

t := template.Must(template.New("").Parse(ingressTemplate))
if err := t.Execute(&ingressConfig, args); err != nil {
return nil, fmt.Errorf("cannot create K8s namespace from template: %w", err)
}

return ingressConfig.Bytes(), nil
}
4 changes: 2 additions & 2 deletions pkg/controlplane/control/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ func (m *Manager) checkJWKSecret(ctx context.Context, name types.NamespacedName)

// addEndpointSlice adds a dataplane / import endpoint slices.
func (m *Manager) addEndpointSlice(ctx context.Context, endpointSlice *discv1.EndpointSlice) error {
if endpointSlice.Labels[discv1.LabelServiceName] == dpapp.Name && endpointSlice.Namespace == m.namespace {
if endpointSlice.Labels[discv1.LabelServiceName] == dpapp.IngressSvcName && endpointSlice.Namespace == m.namespace {
m.logger.Infof("Adding a dataplane endpoint slice: %s", endpointSlice.Name)

mergeImportList := v1alpha1.ImportList{}
Expand Down Expand Up @@ -808,7 +808,7 @@ func (m *Manager) addImportEndpointSlices(ctx context.Context, imp *v1alpha1.Imp
err := m.client.List(
ctx,
&dataplaneEndpointSliceList,
client.MatchingLabels{discv1.LabelServiceName: dpapp.Name},
client.MatchingLabels{discv1.LabelServiceName: dpapp.IngressSvcName},
client.InNamespace(m.namespace))
if err != nil {
return err
Expand Down
11 changes: 3 additions & 8 deletions pkg/operator/controller/instance_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ const (
ControlPlaneName = "cl-controlplane"
DataPlaneName = "cl-dataplane"
GoDataPlaneName = "cl-go-dataplane"
IngressName = "clusterlink"
OperatorNamespace = "clusterlink-operator"
InstanceNamespace = "clusterlink-system"
FinalizerName = "instance.clusterlink.net/finalizer"
Expand Down Expand Up @@ -204,10 +203,6 @@ func (r *InstanceReconciler) applyClusterLink(ctx context.Context, instance *clu
}

// Create datapalne components
if err := r.createService(ctx, DataPlaneName, instance.Spec.Namespace, dpapi.ListenPort); err != nil {
return err
}

if err := r.applyDataplane(ctx, instance); err != nil {
return err
}
Expand Down Expand Up @@ -516,7 +511,7 @@ func (r *InstanceReconciler) createExternalService(ctx context.Context, instance
// Create a Service object
service := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: IngressName,
Name: dpapp.IngressSvcName,
Namespace: instance.Spec.Namespace,
Annotations: instance.Spec.Ingress.Annotations,
},
Expand Down Expand Up @@ -632,7 +627,7 @@ func (r *InstanceReconciler) deleteClusterLink(ctx context.Context, namespace st
}

// Delete external ingress service
ingerssObj := metav1.ObjectMeta{Name: IngressName, Namespace: namespace}
ingerssObj := metav1.ObjectMeta{Name: dpapp.IngressSvcName, Namespace: namespace}
return r.deleteResource(ctx, &corev1.Service{ObjectMeta: ingerssObj})
}

Expand Down Expand Up @@ -720,7 +715,7 @@ func (r *InstanceReconciler) checkDataplaneStatus(ctx context.Context, instance

// checkIngressStatus check the status of the ingress components.
func (r *InstanceReconciler) checkIngressStatus(ctx context.Context, instance *clusterlink.Instance) (bool, error) {
ingress := types.NamespacedName{Name: IngressName, Namespace: instance.Spec.Namespace}
ingress := types.NamespacedName{Name: dpapp.IngressSvcName, Namespace: instance.Spec.Namespace}
serviceStatus, err := r.checkExternalServiceStatus(ctx, ingress, &instance.Status.Ingress)
if err != nil {
return false, err
Expand Down
5 changes: 3 additions & 2 deletions pkg/operator/controller/instance_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"

dpapp "github.com/clusterlink-net/clusterlink/cmd/cl-dataplane/app"
clusterlink "github.com/clusterlink-net/clusterlink/pkg/apis/clusterlink.net/v1alpha1"
"github.com/clusterlink-net/clusterlink/pkg/operator/controller"
)
Expand Down Expand Up @@ -150,8 +151,8 @@ func TestClusterLinkController(t *testing.T) {
}
roleResource := []client.Object{&rbacv1.ClusterRole{}, &rbacv1.ClusterRoleBinding{}}
dpID := types.NamespacedName{Name: controller.DataPlaneName, Namespace: controller.InstanceNamespace}
dpResource := []client.Object{&appsv1.Deployment{}, &corev1.Service{}}
ingressID := types.NamespacedName{Name: controller.IngressName, Namespace: controller.InstanceNamespace}
dpResource := []client.Object{&appsv1.Deployment{}}
ingressID := types.NamespacedName{Name: dpapp.IngressSvcName, Namespace: controller.InstanceNamespace}

t.Run("Create ClusterLink deployment", func(t *testing.T) {
// Create ClusterLink namespaces
Expand Down
3 changes: 2 additions & 1 deletion tests/e2e/k8s/test_import.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"

dpapp "github.com/clusterlink-net/clusterlink/cmd/cl-dataplane/app"
"github.com/clusterlink-net/clusterlink/pkg/apis/clusterlink.net/v1alpha1"
"github.com/clusterlink-net/clusterlink/pkg/controlplane/control"
"github.com/clusterlink-net/clusterlink/tests/e2e/k8s/services"
Expand Down Expand Up @@ -407,7 +408,7 @@ func (s *TestSuite) TestImportMerge() {
// delete dataplane endpoint slice by deleting the dataplane service
var dataplaneService v1.Service
require.Nil(s.T(), cl[0].Cluster().Resources().Get(
context.Background(), "cl-dataplane", cl[0].Namespace(), &dataplaneService))
context.Background(), dpapp.IngressSvcName, cl[0].Namespace(), &dataplaneService))
require.Nil(s.T(), cl[0].Cluster().Resources().Delete(
context.Background(), &dataplaneService))

Expand Down
19 changes: 9 additions & 10 deletions tests/e2e/k8s/util/fabric.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ import (

appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/e2e-framework/klient/wait"
"sigs.k8s.io/e2e-framework/klient/wait/conditions"

dpapp "github.com/clusterlink-net/clusterlink/cmd/cl-dataplane/app"
"github.com/clusterlink-net/clusterlink/cmd/clusterlink/config"
"github.com/clusterlink-net/clusterlink/pkg/apis/clusterlink.net/v1alpha1"
"github.com/clusterlink-net/clusterlink/pkg/bootstrap"
Expand Down Expand Up @@ -142,13 +144,6 @@ func (f *Fabric) SwitchToNewNamespace(name string, appendName bool) error {
f.baseNamespace = name
}

// create new namespace
for _, p := range f.peers {
if err := p.cluster.CreateNamespace(name); err != nil {
return fmt.Errorf("cannot create namespace %s: %w", name, err)
}
}

if f.namespace != "" {
// delete old namespace
for _, p := range f.peers {
Expand All @@ -165,7 +160,7 @@ func (f *Fabric) SwitchToNewNamespace(name string, appendName bool) error {
}
}

if err := p.cluster.DeleteNamespace(f.namespace); err != nil {
if err := p.cluster.DeleteNamespace(f.namespace); err != nil && !apierrors.IsNotFound(err) {
return fmt.Errorf("cannot delete namespace %s: %w", f.namespace, err)
}
}
Expand All @@ -181,6 +176,11 @@ var deployFunc func(target *peer, cfg *PeerConfig) error
func (f *Fabric) deployUsingOperator(target *peer, cfg *PeerConfig) error {
instanceName := "cl-instance" + f.namespace

// Create namespace to run ClusterLink
if err := target.cluster.CreateNamespace(f.namespace); err != nil {
return fmt.Errorf("cannot create namespace %s: %w", f.namespace, err)
}

// Create ClusterLink instance
instance, err := f.generateClusterlinkInstance(instanceName, target, cfg)
if err != nil {
Expand Down Expand Up @@ -259,9 +259,8 @@ func (f *Fabric) deployClusterLink(target *peer, cfg *PeerConfig) (*ClusterLink,
return nil, fmt.Errorf("namespace not set")
}

svcNodePort := "cl-dataplane"
svcNodePort := dpapp.IngressSvcName
if cfg.DeployWithOperator {
svcNodePort = controller.IngressName
deployFunc = f.deployUsingOperator
} else {
deployFunc = f.deployUsingK8sYAML
Expand Down
Loading
Loading