Skip to content

Commit

Permalink
Allow rate limit changes for inCluster mode (#606)
Browse files Browse the repository at this point in the history
* Allow rate limit changes for inCluster mode

---------

Co-authored-by: João Bologna <joao.bologna@wildlifestudios.com>
  • Loading branch information
joaobologna and João Bologna authored Mar 1, 2024
1 parent 78254ce commit 6b6a0b7
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 3 deletions.
4 changes: 4 additions & 0 deletions docs/reference/Kubernetes.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ Maestro provides two ways for configuring kubernetes cluster access.
Set `adapters.runtime.kubernetes.inCluster` config value to true or use its env var equivalent, the kubernetes client will be configured
automatically using the same _service account_ of the maestro component running pod.

The kubernetes client has a default rate limiter which implements a token bucket approach.
The inCluster mode allows rate limit changes via `adapters.runtime.kubernetes.qps`
and `adapters.runtime.kubernetes.burst` configs.

This mode is recommended to be used when running maestro components in the same cluster
in which the schedulers and rooms will be managed.

Expand Down
21 changes: 18 additions & 3 deletions internal/service/adapters.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import (
"github.com/topfreegames/maestro/internal/core/services/schedulers"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)

Expand All @@ -67,6 +68,8 @@ const (
runtimeKubernetesMasterURLPath = "adapters.runtime.kubernetes.masterUrl"
runtimeKubernetesKubeconfigPath = "adapters.runtime.kubernetes.kubeconfig"
runtimeKubernetesInClusterPath = "adapters.runtime.kubernetes.inCluster"
runtimeKubernetesQPS = "adapters.runtime.kubernetes.qps"
runtimeKubernetesBurst = "adapters.runtime.kubernetes.burst"
// Redis operation storage
operationStorageRedisURLPath = "adapters.operationStorage.redis.url"
operationLeaseStorageRedisURLPath = "adapters.operationLeaseStorage.redis.url"
Expand Down Expand Up @@ -115,14 +118,22 @@ func NewEventsForwarder(c config.Config) (ports.EventsForwarder, error) {
func NewRuntimeKubernetes(c config.Config) (ports.Runtime, error) {
var masterURL string
var kubeConfigPath string
var qps int
var burst int

inCluster := c.GetBool(runtimeKubernetesInClusterPath)
if !inCluster {
if inCluster {
qps = c.GetInt(runtimeKubernetesQPS)
burst = c.GetInt(runtimeKubernetesBurst)
} else {
masterURL = c.GetString(runtimeKubernetesMasterURLPath)
kubeConfigPath = c.GetString(runtimeKubernetesKubeconfigPath)
}

clientSet, err := createKubernetesClient(masterURL, kubeConfigPath)
clientSet, err := createKubernetesClient(masterURL, kubeConfigPath, func(conf *rest.Config) {
conf.QPS = float32(qps)
conf.Burst = burst
})
if err != nil {
return nil, fmt.Errorf("failed to initialize Kubernetes runtime: %w", err)
}
Expand Down Expand Up @@ -275,14 +286,18 @@ func connectToPostgres(url string) (*pg.Options, error) {
return opts, nil
}

func createKubernetesClient(masterURL, kubeconfigPath string) (kubernetes.Interface, error) {
func createKubernetesClient(masterURL, kubeconfigPath string, opts ...func(*rest.Config)) (kubernetes.Interface, error) {
// NOTE: if neither masterURL or kubeconfigPath are not passed, this will
// fallback to in cluster config.
kubeconfig, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfigPath)
if err != nil {
return nil, fmt.Errorf("failed to construct kubernetes config: %w", err)
}

for _, opt := range opts {
opt(kubeconfig)
}

client, err := kubernetes.NewForConfig(kubeconfig)
if err != nil {
return nil, fmt.Errorf("failed to create kubernetes client: %w", err)
Expand Down

0 comments on commit 6b6a0b7

Please sign in to comment.