Skip to content

Commit

Permalink
run singleton hosted mode
Browse files Browse the repository at this point in the history
Signed-off-by: Jian Qiu <jqiu@redhat.com>
  • Loading branch information
qiujian16 committed Sep 5, 2023
1 parent b8cac8f commit 4b91426
Show file tree
Hide file tree
Showing 16 changed files with 41 additions and 35 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
kind load docker-image --name=kind quay.io/open-cluster-management/addon-manager:e2e
- name: Test E2E
run: |
IMAGE_TAG=e2e KLUSTERLET_DEPLOY_MODE=Hosted make test-e2e
IMAGE_TAG=e2e KLUSTERLET_DEPLOY_MODE=SingletonHosted make test-e2e
env:
KUBECONFIG: /home/runner/.kube/config
e2e-singleton:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,5 @@ spec:
{{if eq .InstallMode "SingletonHosted"}}
- name: spoke-kubeconfig-secret
secret:
secretName: { { .ExternalManagedKubeConfigWorkSecret } }
secretName: {{ .ExternalManagedKubeConfigWorkSecret }}
{{end}}
8 changes: 6 additions & 2 deletions pkg/operator/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ func LoadClientConfigFromSecret(secret *corev1.Secret) (*rest.Config, error) {
func DetermineReplica(ctx context.Context, kubeClient kubernetes.Interface, mode operatorapiv1.InstallMode, kubeVersion *version.Version) int32 {
// For hosted mode, there may be many cluster-manager/klusterlet running on the management cluster,
// set the replica to 1 to reduce the footprint of the management cluster.
if mode == operatorapiv1.InstallModeHosted {
if IsHosted(mode) {
return singleReplica
}

Expand Down Expand Up @@ -599,7 +599,7 @@ func KlusterletNamespace(klusterlet *operatorapiv1.Klusterlet) string {
// AgentNamespace returns the namespace to deploy the agents.
// It is on the managed cluster in the Default mode, and on the management cluster in the Hosted mode.
func AgentNamespace(klusterlet *operatorapiv1.Klusterlet) string {
if klusterlet.Spec.DeployOption.Mode == operatorapiv1.InstallModeHosted {
if IsHosted(klusterlet.Spec.DeployOption.Mode) {
return klusterlet.GetName()
}

Expand Down Expand Up @@ -752,3 +752,7 @@ func FeatureGateEnabled(features []operatorapiv1.FeatureGate,
func IsSingleton(mode operatorapiv1.InstallMode) bool {
return mode == operatorapiv1.InstallModeSingleton || mode == operatorapiv1.InstallModeSingletonHosted
}

func IsHosted(mode operatorapiv1.InstallMode) bool {
return mode == operatorapiv1.InstallModeHosted || mode == operatorapiv1.InstallModeSingletonHosted
}
2 changes: 1 addition & 1 deletion pkg/operator/helpers/queuekey.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const (
)

func ClusterManagerNamespace(clustermanagername string, mode operatorapiv1.InstallMode) string {
if mode == operatorapiv1.InstallModeHosted {
if IsHosted(mode) {
return clustermanagername
}
return ClusterManagerDefaultNamespace
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func getHubResources(mode operatorapiv1.InstallMode, config manifests.HubConfig)
hubResources = append(hubResources, mwReplicaSetResourceFiles...)
}
// the hubHostedWebhookServiceFiles are only used in hosted mode
if mode == operatorapiv1.InstallModeHosted {
if helpers.IsHosted(mode) {
hubResources = append(hubResources, hubHostedWebhookServiceFiles...)
if config.RegistrationWebhook.IsIPFormat {
hubResources = append(hubResources, hubHostedWebhookEndpointRegistration)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (c *runtimeReconcile) reconcile(ctx context.Context, cm *operatorapiv1.Clus
// In the Hosted mode, ensure the rbac kubeconfig secrets is existed for deployments to mount.
// In this step, we get serviceaccount token from the hub cluster to form a kubeconfig and set it as a secret on the management cluster.
// Before this step, the serviceaccounts in the hub cluster and the namespace in the management cluster should be applied first.
if cm.Spec.DeployOption.Mode == operatorapiv1.InstallModeHosted {
if helpers.IsHosted(cm.Spec.DeployOption.Mode) {
clusterManagerNamespace := helpers.ClusterManagerNamespace(cm.Name, cm.Spec.DeployOption.Mode)
err := c.ensureSAKubeconfigs(ctx, cm.Name, clusterManagerNamespace,
c.hubKubeConfig, c.hubKubeClient, c.kubeClient, c.recorder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
workclientset "open-cluster-management.io/api/client/work/clientset/versioned"
workv1client "open-cluster-management.io/api/client/work/clientset/versioned/typed/work/v1"
operatorapiv1 "open-cluster-management.io/api/operator/v1"

"open-cluster-management.io/ocm/pkg/operator/helpers"
)

type managedClusterClientsBuilderInterface interface {
Expand Down Expand Up @@ -70,7 +72,7 @@ func (m *managedClusterClientsBuilder) withKubeConfigSecret(namespace, name stri
}

func (m *managedClusterClientsBuilder) build(ctx context.Context) (*managedClusterClients, error) {
if m.mode != operatorapiv1.InstallModeHosted {
if !helpers.IsHosted(m.mode) {
return &managedClusterClients{
kubeClient: m.kubeClient,
apiExtensionClient: m.apiExtensionClient,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (n *klusterletCleanupController) sync(ctx context.Context, controllerContex
// we should clean managedcluster resource when
// 1. install mode is not hosted
// 2. install mode is hosted and some resources has been applied on managed cluster (if hosted finalizer exists)
if config.InstallMode != operatorapiv1.InstallModeHosted || hasFinalizer(klusterlet, klusterletHostedFinalizer) {
if !helpers.IsHosted(config.InstallMode) || hasFinalizer(klusterlet, klusterletHostedFinalizer) {
managedClusterClients, err := n.managedClusterClientsBuilder.
withMode(config.InstallMode).
withKubeConfigSecret(config.AgentNamespace, config.ExternalManagedKubeConfigSecret).
Expand Down Expand Up @@ -257,7 +257,7 @@ func isTCPNoSuchHostError(err error) bool {
// readyToAddHostedFinalizer checkes whether the hosted finalizer should be added.
// It is only added when mode is hosted, and some resources have been applied to the managed cluster.
func readyToAddHostedFinalizer(klusterlet *operatorapiv1.Klusterlet, mode operatorapiv1.InstallMode) bool {
if mode != operatorapiv1.InstallModeHosted {
if !helpers.IsHosted(mode) {
return false
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func (n *klusterletController) sync(ctx context.Context, controllerContext facto

// update klusterletReadyToApply condition at first in hosted mode
// this conditions should be updated even when klusterlet is in deleting state.
if config.InstallMode == operatorapiv1.InstallModeHosted {
if helpers.IsHosted(config.InstallMode) {
if err != nil {
meta.SetStatusCondition(&klusterlet.Status.Conditions, metav1.Condition{
Type: klusterletReadyToApply, Status: metav1.ConditionFalse, Reason: "KlusterletPrepareFailed",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ func assertWorkDeployment(t *testing.T, actions []clienttesting.Action, verb, cl
"--agent-id=",
}

if mode == operatorapiv1.InstallModeHosted {
if helpers.IsHosted(mode) {
expectArgs = append(expectArgs,
"--spoke-kubeconfig=/spoke/config/kubeconfig",
"--terminate-on-files=/spoke/config/kubeconfig")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (r *managedReconcile) reconcile(ctx context.Context, klusterlet *operatorap
return klusterlet, reconcileStop, err
}

if config.InstallMode == operatorapiv1.InstallModeHosted {
if helpers.IsHosted(config.InstallMode) {
// In hosted mode, we should ensure the namespace on the managed cluster since
// some resources(eg:service account) are still deployed on managed cluster.
err := ensureNamespace(ctx, r.managedClusterClients.kubeClient, klusterlet, config.KlusterletNamespace, r.recorder)
Expand Down Expand Up @@ -134,7 +134,7 @@ func (r *managedReconcile) reconcile(ctx context.Context, klusterlet *operatorap
func (r *managedReconcile) clean(ctx context.Context, klusterlet *operatorapiv1.Klusterlet,
config klusterletConfig) (*operatorapiv1.Klusterlet, reconcileState, error) {
// nothing should be done when deploy mode is hosted and hosted finalizer is not added.
if klusterlet.Spec.DeployOption.Mode == operatorapiv1.InstallModeHosted && !hasFinalizer(klusterlet, klusterletHostedFinalizer) {
if helpers.IsHosted(klusterlet.Spec.DeployOption.Mode) && !hasFinalizer(klusterlet, klusterletHostedFinalizer) {
return klusterlet, reconcileContinue, nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (r *managementReconcile) clean(ctx context.Context, klusterlet *operatorapi
config klusterletConfig) (*operatorapiv1.Klusterlet, reconcileState, error) {
// Remove secrets
secrets := []string{config.HubKubeConfigSecret}
if config.InstallMode == operatorapiv1.InstallModeHosted {
if helpers.IsHosted(config.InstallMode) {
// In Hosted mod, also need to remove the external-managed-kubeconfig-registration and external-managed-kubeconfig-work
secrets = append(secrets, []string{config.ExternalManagedKubeConfigRegistrationSecret, config.ExternalManagedKubeConfigWorkSecret}...)
}
Expand All @@ -121,7 +121,7 @@ func (r *managementReconcile) clean(ctx context.Context, klusterlet *operatorapi
// The agent namespace on the management cluster should be removed **at the end**. Otherwise if any failure occurred,
// the managed-external-kubeconfig secret would be removed and the next reconcile will fail due to can not build the
// managed cluster clients.
if config.InstallMode == operatorapiv1.InstallModeHosted {
if helpers.IsHosted(config.InstallMode) {
// remove the agent namespace on the management cluster
err = r.kubeClient.CoreV1().Namespaces().Delete(ctx, config.AgentNamespace, metav1.DeleteOptions{})
if err != nil && !errors.IsNotFound(err) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ type runtimeReconcile struct {

func (r *runtimeReconcile) reconcile(ctx context.Context, klusterlet *operatorapiv1.Klusterlet,
config klusterletConfig) (*operatorapiv1.Klusterlet, reconcileState, error) {
if helpers.IsSingleton(config.InstallMode) {
return r.installSingletonAgent(ctx, klusterlet, config)
}

if config.InstallMode == operatorapiv1.InstallModeHosted {
if helpers.IsHosted(config.InstallMode) {
// Create managed config secret for registration and work.
if err := r.createManagedClusterKubeconfig(ctx, klusterlet, config.KlusterletNamespace, config.AgentNamespace,
config.RegistrationServiceAccount, config.ExternalManagedKubeConfigRegistrationSecret,
Expand All @@ -59,6 +55,15 @@ func (r *runtimeReconcile) reconcile(ctx context.Context, klusterlet *operatorap
runtimeConfig.Replica = 0
}

if helpers.IsSingleton(config.InstallMode) {
return r.installSingletonAgent(ctx, klusterlet, runtimeConfig)
}

return r.installAgent(ctx, klusterlet, runtimeConfig)
}

func (r *runtimeReconcile) installAgent(ctx context.Context, klusterlet *operatorapiv1.Klusterlet,
runtimeConfig klusterletConfig) (*operatorapiv1.Klusterlet, reconcileState, error) {
// Deploy registration agent
_, generationStatus, err := helpers.ApplyDeployment(
ctx,
Expand Down Expand Up @@ -88,7 +93,7 @@ func (r *runtimeReconcile) reconcile(ctx context.Context, klusterlet *operatorap
// registration-agent generated the cluster name and set it into hub config secret.
workConfig := runtimeConfig
if workConfig.ClusterName == "" {
workConfig.ClusterName, err = r.getClusterNameFromHubKubeConfigSecret(ctx, config.AgentNamespace, klusterlet)
workConfig.ClusterName, err = r.getClusterNameFromHubKubeConfigSecret(ctx, runtimeConfig.AgentNamespace, klusterlet)
if err != nil {
return klusterlet, reconcileStop, err
}
Expand Down Expand Up @@ -134,9 +139,9 @@ func (r *runtimeReconcile) reconcile(ctx context.Context, klusterlet *operatorap
}

// clean singleton agent if there is any
deployments := []string{fmt.Sprintf("%s-agent", config.KlusterletName)}
deployments := []string{fmt.Sprintf("%s-agent", runtimeConfig.KlusterletName)}
for _, deployment := range deployments {
err := r.kubeClient.AppsV1().Deployments(config.AgentNamespace).Delete(ctx, deployment, metav1.DeleteOptions{})
err := r.kubeClient.AppsV1().Deployments(runtimeConfig.AgentNamespace).Delete(ctx, deployment, metav1.DeleteOptions{})
if err != nil && !errors.IsNotFound(err) {
return klusterlet, reconcileStop, err
}
Expand All @@ -151,13 +156,6 @@ func (r *runtimeReconcile) reconcile(ctx context.Context, klusterlet *operatorap

func (r *runtimeReconcile) installSingletonAgent(ctx context.Context, klusterlet *operatorapiv1.Klusterlet,
config klusterletConfig) (*operatorapiv1.Klusterlet, reconcileState, error) {
// Check if the klusterlet is in rebootstrapping state.
// The agent is scaled to 0 if the klusterlet is in rebootstrapping state.
runtimeConfig := config
if meta.IsStatusConditionTrue(klusterlet.Status.Conditions, helpers.KlusterletRebootstrapProgressing) {
runtimeConfig.Replica = 0
}

// Deploy singleton agent
_, generationStatus, err := helpers.ApplyDeployment(
ctx,
Expand All @@ -169,7 +167,7 @@ func (r *runtimeReconcile) installSingletonAgent(ctx context.Context, klusterlet
if err != nil {
return nil, err
}
objData := assets.MustCreateAssetFromTemplate(name, template, runtimeConfig).Data
objData := assets.MustCreateAssetFromTemplate(name, template, config).Data
helpers.SetRelatedResourcesStatusesWithObj(&klusterlet.Status.RelatedResources, objData)
return objData, nil
},
Expand Down
2 changes: 1 addition & 1 deletion test/e2e-test.mk
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ bootstrap-secret-hosted:
$(KUSTOMIZE) build deploy/klusterlet/config/samples/bootstrap | $(SED_CMD) -e "s,namespace: open-cluster-management-agent,namespace: $(KLUSTERLET_NAME)," | $(KUBECTL) apply -f -

apply-spoke-cr-hosted: bootstrap-secret-hosted external-managed-secret
$(KUSTOMIZE) build deploy/klusterlet/config/samples | $(SED_CMD) -e "s,mode: Default,mode: Hosted," -e "s,quay.io/open-cluster-management/registration,$(REGISTRATION_IMAGE)," -e "s,quay.io/open-cluster-management/work,$(WORK_IMAGE)," -e "s,cluster1,$(MANAGED_CLUSTER_NAME)," -e "s,name: klusterlet,name: $(KLUSTERLET_NAME)," -r | $(KUBECTL) apply -f -
$(KUSTOMIZE) build deploy/klusterlet/config/samples | $(SED_CMD) -e "s,mode: Default,mode: SingletonHosted," -e "s,quay.io/open-cluster-management/registration,$(REGISTRATION_IMAGE)," -e "s,quay.io/open-cluster-management/work,$(WORK_IMAGE)," -e "s,quay.io/open-cluster-management/registration-operator,$(OPERATOR_IMAGE_NAME)," -e "s,cluster1,$(MANAGED_CLUSTER_NAME)," -e "s,name: klusterlet,name: $(KLUSTERLET_NAME)," -r | $(KUBECTL) apply -f -

clean-hub-cr-hosted:
$(KUBECTL) delete managedcluster --all --ignore-not-found
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ func (t *Tester) CreateKlusterlet(name, clusterName, klusterletNamespace string,
}
}

if mode == operatorapiv1.InstallModeHosted {
if helpers.IsHosted(mode) {
// create external-managed-kubeconfig, will use the same cluster to simulate the Hosted mode.
secret.Namespace = agentNamespace
secret.Name = helpers.ExternalManagedKubeConfig
Expand Down
4 changes: 3 additions & 1 deletion test/e2e/klusterlet_hosted_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"k8s.io/apimachinery/pkg/util/rand"

operatorapiv1 "open-cluster-management.io/api/operator/v1"

"open-cluster-management.io/ocm/pkg/operator/helpers"
)

var _ = Describe("Delete hosted klusterlet CR", func() {
Expand All @@ -20,7 +22,7 @@ var _ = Describe("Delete hosted klusterlet CR", func() {
var klusterletNamespace string

BeforeEach(func() {
if klusterletDeployMode != string(operatorapiv1.InstallModeHosted) {
if !helpers.IsHosted(operatorapiv1.InstallMode(klusterletDeployMode)) {
Skip(fmt.Sprintf("Klusterlet deploy is %s", klusterletDeployMode))
}
klusterletName = fmt.Sprintf("e2e-klusterlet-%s", rand.String(6))
Expand Down

0 comments on commit 4b91426

Please sign in to comment.