mirror of
https://github.com/arangodb/kube-arangodb.git
synced 2024-12-14 11:57:37 +00:00
[Feature] [Scheduler] Shutdown Integration (#1777)
This commit is contained in:
parent
9f1bd2bc7e
commit
6f713a85e9
10 changed files with 122 additions and 18 deletions
|
@ -30,6 +30,7 @@
|
||||||
- (Improvement) Drop slash requirement from ArangoRoute
|
- (Improvement) Drop slash requirement from ArangoRoute
|
||||||
- (Feature) (Networking) Pass through Server Header
|
- (Feature) (Networking) Pass through Server Header
|
||||||
- (Feature) (Platform) Shutdown migration to CE
|
- (Feature) (Platform) Shutdown migration to CE
|
||||||
|
- (Feature) (Scheduler) Shutdown Integration
|
||||||
|
|
||||||
## [1.2.43](https://github.com/arangodb/kube-arangodb/tree/1.2.43) (2024-10-14)
|
## [1.2.43](https://github.com/arangodb/kube-arangodb/tree/1.2.43) (2024-10-14)
|
||||||
- (Feature) ArangoRoute CRD
|
- (Feature) ArangoRoute CRD
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
ARG IMAGE=ubuntu:24.04
|
ARG IMAGE=ubuntu:24.04
|
||||||
ARG ENVOY_IMAGE=envoyproxy/envoy:v1.31.0
|
ARG ENVOY_IMAGE=envoyproxy/envoy:v1.32.1
|
||||||
|
|
||||||
# Build Steps
|
# Build Steps
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,18 @@ metadata:
|
||||||
integration.profiles.arangodb.com/storage: v2
|
integration.profiles.arangodb.com/storage: v2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### [Shutdown V1](/docs/integration/shutdown.v1.md)
|
||||||
|
|
||||||
|
Shutdown Integration Sidecar
|
||||||
|
|
||||||
|
To enable:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
integration.profiles.arangodb.com/shutdown: v1
|
||||||
|
```
|
||||||
|
|
||||||
### Envs
|
### Envs
|
||||||
|
|
||||||
#### INTEGRATION_API_ADDRESS
|
#### INTEGRATION_API_ADDRESS
|
||||||
|
|
32
docs/integration/shutdown.v1.md
Normal file
32
docs/integration/shutdown.v1.md
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
layout: page
|
||||||
|
title: Authentication V1
|
||||||
|
parent: ArangoDBPlatform
|
||||||
|
---
|
||||||
|
|
||||||
|
# Shutdown V1
|
||||||
|
|
||||||
|
Definitions:
|
||||||
|
|
||||||
|
- [Service](../../integrations/shutdown/v1/definition/definition.proto)
|
||||||
|
|
||||||
|
Operator will send shutdown request once all containers marked with annotation are stopped.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
core.shutdown.arangodb.com/app: "true"
|
||||||
|
core.shutdown.arangodb.com/app2: "true"
|
||||||
|
container.shutdown.arangodb.com/app3: port1
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
- name: app2
|
||||||
|
- name: app3
|
||||||
|
ports:
|
||||||
|
name: port1
|
||||||
|
```
|
||||||
|
|
||||||
|
Pod will receive shutdown request on port `port1` if containers `app` and `app2` will be in non running state.
|
|
@ -66,7 +66,7 @@ func (d DeniedResponse) GetCheckResponse() (*pbEnvoyAuthV3.CheckResponse, error)
|
||||||
resp.Body = string(z)
|
resp.Body = string(z)
|
||||||
resp.Headers = append(resp.Headers, &corev3.HeaderValueOption{
|
resp.Headers = append(resp.Headers, &corev3.HeaderValueOption{
|
||||||
Header: &corev3.HeaderValue{
|
Header: &corev3.HeaderValue{
|
||||||
Key: "content/type",
|
Key: "content-type",
|
||||||
Value: "application/json",
|
Value: "application/json",
|
||||||
},
|
},
|
||||||
AppendAction: corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD,
|
AppendAction: corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD,
|
||||||
|
|
|
@ -153,6 +153,7 @@ func (r *Resources) EnsureArangoProfiles(ctx context.Context, cachedStatus inspe
|
||||||
Spec: spec,
|
Spec: spec,
|
||||||
DeploymentName: apiObject.GetName(),
|
DeploymentName: apiObject.GetName(),
|
||||||
})),
|
})),
|
||||||
|
gen(constants.ProfilesIntegrationShutdown, constants.ProfilesIntegrationV1, always(sidecar.IntegrationShutdownV1{})),
|
||||||
gen(constants.ProfilesIntegrationEnvoy, constants.ProfilesIntegrationV3, always(sidecar.IntegrationEnvoyV3{Spec: spec})),
|
gen(constants.ProfilesIntegrationEnvoy, constants.ProfilesIntegrationV3, always(sidecar.IntegrationEnvoyV3{Spec: spec})),
|
||||||
gen(constants.ProfilesIntegrationStorage, constants.ProfilesIntegrationV2, func() (sidecar.Integration, bool) {
|
gen(constants.ProfilesIntegrationStorage, constants.ProfilesIntegrationV2, func() (sidecar.Integration, bool) {
|
||||||
if v, err := cachedStatus.ArangoPlatformStorage().V1Alpha1(); err == nil {
|
if v, err := cachedStatus.ArangoPlatformStorage().V1Alpha1(); err == nil {
|
||||||
|
|
|
@ -29,14 +29,6 @@ const (
|
||||||
ListenPortHealthName = "health"
|
ListenPortHealthName = "health"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Integration interface {
|
|
||||||
Name() []string
|
|
||||||
Envs() ([]core.EnvVar, error)
|
|
||||||
GlobalEnvs() ([]core.EnvVar, error)
|
|
||||||
Volumes() ([]core.Volume, []core.VolumeMount, error)
|
|
||||||
Validate() error
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewShutdownAnnotations(coreContainers []string) *schedulerApi.ProfileTemplate {
|
func NewShutdownAnnotations(coreContainers []string) *schedulerApi.ProfileTemplate {
|
||||||
pt := schedulerApi.ProfileTemplate{
|
pt := schedulerApi.ProfileTemplate{
|
||||||
Pod: &schedulerPodApi.Pod{
|
Pod: &schedulerPodApi.Pod{
|
||||||
|
@ -57,6 +49,7 @@ func NewIntegrationEnablement(integrations ...Integration) (*schedulerApi.Profil
|
||||||
var envs, gEnvs []core.EnvVar
|
var envs, gEnvs []core.EnvVar
|
||||||
var volumes []core.Volume
|
var volumes []core.Volume
|
||||||
var volumeMounts []core.VolumeMount
|
var volumeMounts []core.VolumeMount
|
||||||
|
var annotations = map[string]string{}
|
||||||
|
|
||||||
for _, integration := range integrations {
|
for _, integration := range integrations {
|
||||||
name := strings.Join(integration.Name(), "/")
|
name := strings.Join(integration.Name(), "/")
|
||||||
|
@ -72,6 +65,14 @@ func NewIntegrationEnablement(integrations ...Integration) (*schedulerApi.Profil
|
||||||
volumeMounts = append(volumeMounts, lvolumeMounts...)
|
volumeMounts = append(volumeMounts, lvolumeMounts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if anns, err := getIntegrationAnnotations(integration); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "Failure in annotations %s", name)
|
||||||
|
} else {
|
||||||
|
for k, v := range anns {
|
||||||
|
annotations[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if lenvs, err := integration.Envs(); err != nil {
|
if lenvs, err := integration.Envs(); err != nil {
|
||||||
return nil, errors.Wrapf(err, "Failure in envs %s", name)
|
return nil, errors.Wrapf(err, "Failure in envs %s", name)
|
||||||
} else if len(lenvs) > 0 {
|
} else if len(lenvs) > 0 {
|
||||||
|
@ -92,6 +93,9 @@ func NewIntegrationEnablement(integrations ...Integration) (*schedulerApi.Profil
|
||||||
return &schedulerApi.ProfileTemplate{
|
return &schedulerApi.ProfileTemplate{
|
||||||
Priority: util.NewType(127),
|
Priority: util.NewType(127),
|
||||||
Pod: &schedulerPodApi.Pod{
|
Pod: &schedulerPodApi.Pod{
|
||||||
|
Metadata: &schedulerPodResourcesApi.Metadata{
|
||||||
|
Annotations: annotations,
|
||||||
|
},
|
||||||
Volumes: &schedulerPodResourcesApi.Volumes{
|
Volumes: &schedulerPodResourcesApi.Volumes{
|
||||||
Volumes: volumes,
|
Volumes: volumes,
|
||||||
},
|
},
|
||||||
|
@ -205,9 +209,6 @@ func NewIntegration(image *schedulerContainerResourcesApi.Image, integration *sc
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pt.Pod.Metadata.Annotations[fmt.Sprintf("%s/%s", constants.AnnotationShutdownContainer, ContainerName)] = ListenPortHealthName
|
|
||||||
pt.Pod.Metadata.Annotations[constants.AnnotationShutdownManagedContainer] = "true"
|
|
||||||
|
|
||||||
pt.Container.All.Environments = &schedulerContainerResourcesApi.Environments{
|
pt.Container.All.Environments = &schedulerContainerResourcesApi.Environments{
|
||||||
Env: envs,
|
Env: envs,
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,13 +21,24 @@
|
||||||
package sidecar
|
package sidecar
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
core "k8s.io/api/core/v1"
|
core "k8s.io/api/core/v1"
|
||||||
|
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/util/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IntegrationShutdownV1 struct {
|
type IntegrationShutdownV1 struct {
|
||||||
Core *Core
|
Core *Core
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i IntegrationShutdownV1) Annotations() (map[string]string, error) {
|
||||||
|
return map[string]string{
|
||||||
|
fmt.Sprintf("%s/%s", constants.AnnotationShutdownContainer, ContainerName): ListenPortHealthName,
|
||||||
|
constants.AnnotationShutdownManagedContainer: "true",
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (i IntegrationShutdownV1) Name() []string {
|
func (i IntegrationShutdownV1) Name() []string {
|
||||||
return []string{"SHUTDOWN", "V1"}
|
return []string{"SHUTDOWN", "V1"}
|
||||||
}
|
}
|
||||||
|
|
45
pkg/integrations/sidecar/integration_interface.go
Normal file
45
pkg/integrations/sidecar/integration_interface.go
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
//
|
||||||
|
// DISCLAIMER
|
||||||
|
//
|
||||||
|
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
|
//
|
||||||
|
|
||||||
|
package sidecar
|
||||||
|
|
||||||
|
import core "k8s.io/api/core/v1"
|
||||||
|
|
||||||
|
type Integration interface {
|
||||||
|
Name() []string
|
||||||
|
Envs() ([]core.EnvVar, error)
|
||||||
|
GlobalEnvs() ([]core.EnvVar, error)
|
||||||
|
Volumes() ([]core.Volume, []core.VolumeMount, error)
|
||||||
|
Validate() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type IntegrationAnnotations interface {
|
||||||
|
Integration
|
||||||
|
|
||||||
|
Annotations() (map[string]string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIntegrationAnnotations(int Integration) (map[string]string, error) {
|
||||||
|
if v, ok := int.(IntegrationAnnotations); ok {
|
||||||
|
return v.Annotations()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
|
@ -28,11 +28,12 @@ const ProfilesDeployment = ProfileGroup + "/deployment"
|
||||||
const ProfilesIntegrationPrefix = "integration." + ProfileGroup
|
const ProfilesIntegrationPrefix = "integration." + ProfileGroup
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ProfilesIntegrationAuthn = "authn"
|
ProfilesIntegrationAuthn = "authn"
|
||||||
ProfilesIntegrationAuthz = "authz"
|
ProfilesIntegrationAuthz = "authz"
|
||||||
ProfilesIntegrationSched = "sched"
|
ProfilesIntegrationSched = "sched"
|
||||||
ProfilesIntegrationEnvoy = "envoy"
|
ProfilesIntegrationEnvoy = "envoy"
|
||||||
ProfilesIntegrationStorage = "storage"
|
ProfilesIntegrationStorage = "storage"
|
||||||
|
ProfilesIntegrationShutdown = "shutdown"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
Loading…
Reference in a new issue