Skip to content
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
39 changes: 39 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: BuildContainerImage

on:
push:
branches:
- 'master'
tags:
- 'v*'

jobs:
build:
name: Build
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v1
with:
platforms: all

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build and push docker images
if: github.event_name == 'push'
run: |
REPO=kubesphere TAG="${GITHUB_REF#refs/*/}" make docker-build-multiarch
89 changes: 0 additions & 89 deletions .github/workflows/go.yml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
bin/

vendor/
.vscode/
183 changes: 86 additions & 97 deletions cmd/proxy/app/proxy.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
package app

import (
"context"
"flag"
"os"
"strings"
"time"

"github.com/spf13/cobra"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/uuid"
kubeinformer "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/leaderelection"
"k8s.io/client-go/tools/leaderelection/resourcelock"
"k8s.io/client-go/tools/record"
"k8s.io/klog/v2"
clientset "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"sigs.k8s.io/controller-runtime/pkg/manager/signals"

"kubesphere.io/tower/pkg/proxy"

"kubesphere.io/tower/pkg/scheme"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
)

func NewProxyCommand() *cobra.Command {
Expand All @@ -37,94 +33,7 @@ func NewProxyCommand() *cobra.Command {
return err
}

ctx := signals.SetupSignalHandler()

config, err := clientcmd.BuildConfigFromFlags("", options.ProxyOptions.KubeConfigPath)
if err != nil {
klog.Errorf("Failed to create config from kubeconfig file, %v", err)
return err
}
config.QPS = 50
config.Burst = 100

kubernetesClient, err := kubernetes.NewForConfig(config)
if err != nil {
klog.Errorf("Failed to create kubernetes clientSets, %v", err)
return err
}

clusterClient, err := clientset.NewForConfig(config)
if err != nil {
klog.Errorf("Failed to create cluster clientSets, %v", err)
return err
}

run := func(ctx context.Context) {
agentsInformerFactory := informers.NewSharedInformerFactory(clusterClient, 10*time.Minute)
serviceInformerFactory := kubeinformer.NewSharedInformerFactory(kubernetesClient, 10*time.Minute)

p, err := proxy.NewServer(options.ProxyOptions, agentsInformerFactory.Cluster().V1alpha1().Clusters(), serviceInformerFactory.Core().V1().Services(), clusterClient, kubernetesClient)
if err != nil {
klog.Fatalf("Failed to create proxy server, %v", err)
}

agentsInformerFactory.Start(ctx.Done())
serviceInformerFactory.Start(ctx.Done())
if err = p.Run(ctx.Done()); err != nil {
klog.Fatalf("Failed to start proxy server, %v", err)
}

if err = p.Wait(); err != nil {
klog.Fatalf("Failed to wait, %v", err)
}

select {}
}

if !options.LeaderElect {
run(ctx)
return nil
}

id, err := os.Hostname()
if err != nil {
return err
}

// add a uniquifier so that two processes on the same host don't accidentally both become active
id = id + "_" + string(uuid.NewUUID())

lock, err := resourcelock.New(resourcelock.LeasesResourceLock,
"kubesphere-system",
"tower",
kubernetesClient.CoreV1(),
kubernetesClient.CoordinationV1(),
resourcelock.ResourceLockConfig{
Identity: id,
EventRecorder: record.NewBroadcaster().NewRecorder(scheme.Scheme, v1.EventSource{
Component: "tower",
}),
},
)
if err != nil {
klog.Fatalf("error creating lock: %v", err)
}

leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{
Lock: lock,
LeaseDuration: options.LeaderElection.LeaseDuration,
RenewDeadline: options.LeaderElection.RenewDeadline,
RetryPeriod: options.LeaderElection.RetryPeriod,
Callbacks: leaderelection.LeaderCallbacks{
OnStartedLeading: run,
OnStoppedLeading: func() {
klog.Errorf("leadership lost")
os.Exit(0)
},
},
})

return nil
return Run(options)
},
}

Expand All @@ -139,3 +48,83 @@ func NewProxyCommand() *cobra.Command {

return cmd
}

func Run(options *ProxyRunOptions) error {
ctx := signals.SetupSignalHandler()

config, err := clientcmd.BuildConfigFromFlags("", options.ProxyOptions.KubeConfigPath)
if err != nil {
klog.Errorf("Failed to create config from kubeconfig file, %v", err)
return err
}
config.QPS = 50
config.Burst = 100

kubernetesClient, err := kubernetes.NewForConfig(config)
if err != nil {
klog.Errorf("Failed to create kubernetes clientSets, %v", err)
return err
}

client, err := runtimeclient.New(config, runtimeclient.Options{Scheme: scheme.Scheme})
if err != nil {
klog.Errorf("Failed to create runtime client, %v", err)
return err
}

cmOptions := manager.Options{
Scheme: scheme.Scheme,
MetricsBindAddress: "0",
}
if options.LeaderElect {
id, err := os.Hostname()
if err != nil {
return err
}

// add a uniquifier so that two processes on the same host don't accidentally both become active
id = id + "_" + string(uuid.NewUUID())

lock, err := resourcelock.New(resourcelock.LeasesResourceLock,
"kubesphere-system",
"tower",
kubernetesClient.CoreV1(),
kubernetesClient.CoordinationV1(),
resourcelock.ResourceLockConfig{
Identity: id,
EventRecorder: record.NewBroadcaster().NewRecorder(scheme.Scheme, v1.EventSource{
Component: "tower",
}),
},
)
if err != nil {
klog.Fatalf("error creating lock: %v", err)
}
cmOptions = manager.Options{
Scheme: scheme.Scheme,
MetricsBindAddress: "0",
LeaderElection: options.LeaderElect,
LeaseDuration: &options.LeaderElection.LeaseDuration,
RenewDeadline: &options.LeaderElection.RenewDeadline,
RetryPeriod: &options.LeaderElection.RetryPeriod,
LeaderElectionResourceLockInterface: lock,
}
}

mgr, err := manager.New(config, cmOptions)
if err != nil {
klog.Fatalf("Failed to create controller manager, %v", err)
}

p, err := proxy.NewServer(options.ProxyOptions, client, kubernetesClient)
if err != nil {
klog.Fatalf("Failed to create proxy server, %v", err)
}

err = p.SetupWithManager(mgr)
if err != nil {
klog.Fatalf("Failed to setup proxy server with manager, %v", err)
}

return mgr.Start(ctx)
}
12 changes: 12 additions & 0 deletions pkg/api/cluster/v1alpha1/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright 2024 the KubeSphere Authors.
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/

// Package v1alpha1 contains API Schema definitions for the tower v1alpha1 API group
// +k8s:openapi-gen=true
// +kubebuilder:object:generate=true
// +groupName=cluster.kubesphere.io

package v1alpha1
Loading