title | type |
---|---|
Runtime operations |
Details |
Kyma Environment Broker allows you to configure operations that you can run on a Runtime. Each operation consists of several steps and each step is represented by a separate file. As every step can be re-launched multiple times, for each step, you should determine a behavior in case of a processing failure. It can either:
- Return an error, which interrupts the entire process, or
- Repeat the entire operation after the specified period.
NOTE: It's important to set lower timeouts for the Kyma installation in the Runtime Provisioner.
Each provisioning step is responsible for a separate part of preparing Runtime parameters. For example, in a step you can provide tokens, credentials, or URLs to integrate Kyma Runtime with external systems. All data collected in provisioning steps are used in the step called create_runtime
which transforms the data into a request input. The request is sent to the Runtime Provisioner component which provisions a Runtime.
The provisioning process contains the following steps:
Stage | Name | Domain | Description | Owner |
---|---|---|---|---|
create_runtime | Initialization | Provisioning | Starts the provisioning process. | @jasiu001 (Team Gopher) |
create_runtime | Resolve_Target_Secret | Hyperscaler Account Pool | Provides the name of a Gardener Secret that contains Hypescaler account credentials used during cluster provisioning. | @koala7659 (Team Framefrog) |
create_runtime | AVS_Create_Internal_Eval_Step | AvS | Sets up internal monitoring of Kyma Runtime. | @jasiu001 (Team Gopher) |
create_runtime | IAS_Registration | Identity Authentication Service | Registers a new ServiceProvider on IAS, generates client ID and Secret, and inserts them to Grafana overrides. This step is not required and can be disabled. | @jasiu001 (Team Gopher) |
create_runtime | EDP_Registration | Event Data Platform | Registers an SKR on Event Data Platform with the necessary parameters. This step is not required and can be disabled. | @jasiu001 (Team Gopher) |
create_runtime | Provision Azure Event Hubs | Event Hub | Creates the Azure Event Hub Namespace which is a managed Kafka cluster for a Kyma Runtime. | @k15r (Team SkyDivingTunas) |
create_runtime | Provision EMS | EMS | Provisions and binds an Enterprise Messaging instance for a Kyma Runtime using the Service Manager. | @k15r (Team SkyDivingTunas) |
create_runtime | Overrides_From_Secrets_And_Config_Step | Kyma overrides | Configures default overrides for Kyma. | @jasiu001 (Team Gopher) |
create_runtime | ServiceManagerOverrides | Service Manager | Configures overrides with Service Manager credentials. | Team Gopher |
create_runtime | Create_Runtime | Provisioning | Triggers provisioning of a Runtime in the Runtime Provisioner. | @jasiu001 (Team Gopher) |
check_runtime | Check_Runtime | Provisioning | Checks the status of the Provisioner process and asks the Director for the Dashboard URL if the provisioning in Gardener is finished. | @piotrmiskiewicz (Team Gopher) |
create_kyma | Get_Kubeconfig | Provisioning | Gets the kubeconfig (executed only for Kyma 2.0). | @piotrmiskiewicz (Team Gopher) |
create_kyma | Create_Cluster_Configuration | Reconciler | Applies the cluster configuration (executed only for Kyma 2.0). | @piotrmiskiewicz (Team Gopher) |
create_kyma | Check_Cluster_Configuration | Reconciler | Checks if the cluster configuration is applied (executed only for Kyma 2.0). | @piotrmiskiewicz (Team Gopher) |
post_actions | AVS_Create_External_Eval_Step | AvS | Sets up external monitoring of Kyma Runtime. | @piotrmiskiewicz (Team Gopher) |
post_actions | AVS_Tags | AvS | Sets up proper tags in the internal monitoring system. | @piotrmiskiewicz (Team Gopher) |
post_actions | IAS_Type | Identity Authentication Service | Configures OpenID Connect (OIDC) authentication. | @piotrmiskiewicz (Team Gopher) |
NOTE: The timeout for processing this operation is set to
24h
.
Each deprovisioning step is responsible for a separate part of cleaning Runtime dependencies. To properly deprovision all Runtime dependencies, you need the data used during the Runtime provisioning. You can fetch this data from the ProvisioningOperation struct in the initialization step.
Any deprovisioning step shouldn't block the entire deprovisioning operation. Use the RetryOperationWithoutFail
function from the DeprovisionOperationManager
struct to skip your step in case of retry timeout. Set at most 5min timeout for retries in your step.
The deprovisioning process contains the following steps:
Name | Domain | Status | Description | Owner |
---|---|---|---|---|
Deprovision_Initialization | Deprovisioning | Done | Initializes the DeprovisioningOperation instance with data fetched from the ProvisioningOperation . |
@polskikiel (Team Gopher) |
Deprovision Azure Event Hubs | Event Hub | Done | Deletes the Azure Event Hub Namespace. | @k15r (Team SkyDivingTunas) |
Deprovision EMS | EMS | Done | Unbinds and deprovisions the Enterprise Messaging instance using the Service Manager. | @k15r (Team SkyDivingTunas) |
De-provision_AVS_Evaluations | AvS | Done | Removes external and internal monitoring of Kyma Runtime. | @jasiu001 (Team Gopher) |
IAS_Deregistration | Identity Authentication Service | Done | Removes the ServiceProvider from IAS. | @jasiu001 (Team Gopher) |
EDP_Deregistration | Event Data Platform | Done | Removes all entries about SKR from Event Data Platform. | @jasiu001 (Team Gopher) |
Deregister_Cluster | Reconciler | Done | Removes the cluster from the Reconciler. | @piotrmiskiewicz (Team Gopher) |
Remove_Runtime | Deprovisioning | Done | Triggers deprovisioning of a Runtime in the Runtime Provisioner. | @polskikiel (Team Gopher) |
NOTE: The timeout for processing this operation is set to
24h
.
Each upgrade step is responsible for a separate part of upgrading Runtime dependencies. To properly upgrade the Runtime, you need the data used during the Runtime provisioning. You can fetch this data from the ProvisioningOperation struct in the initialization step.
The upgrade process contains the following steps:
Name | Domain | Status | Description | Owner |
---|---|---|---|---|
Provision EMS | EMS | Done | Provisions and binds an Enterprise Messaging instance for a Kyma Runtime using the Service Manager. | @k15r (Team SkyDivingTunas) |
Deprovision Azure Event Hubs | Event Hub | Done | Deletes the Azure Event Hub Namespace. | @k15r (Team SkyDivingTunas) |
Upgrade_Kyma_Initialisation | Upgrade | Done | Initializes the UpgradeOperation instance with data fetched from the ProvisioningOperation . |
@ksputo (Team Gopher) |
Overrides_From_Secrets_And_Config_Step | Upgrade | Done | Builds an input configuration that is passed as overrides to Runtime Provisioner. | @ksputo (Team Gopher) |
Upgrade_Runtime | Upgrade | Done | Triggers the upgrade of a Runtime in Runtime Provisioner. | @ksputo (Team Gopher) |
Get_Kubeconfig | Upgrade | Done | Gets the kubeconfig file (executed only for Kyma 2.0). | @piotrmiskiewicz (Team Gopher) |
Apply_Cluster_Configuration | Upgrade | Done | Applies a cluster configuration to the Reconciler (executed only for Kyma 2.0). | @piotrmiskiewicz (Team Gopher) |
NOTE: The timeout for processing this operation is set to
3h
.
You can configure Runtime operations by providing additional steps. To add a new step, follow these tutorials:
Provisioning
-
Create a new file in this directory.
-
Implement this interface in your provisioning step:
type Step interface { Name() string Run(operation internal.ProvisioningOperation, logger logrus.FieldLogger) (internal.ProvisioningOperation, time.Duration, error) }
Name()
method returns the name of the step that is used in logs.Run()
method implements the functionality of the step. The method receives operations as an argument to which it can add appropriate overrides or save other used variables.
operation.InputCreator.SetOverrides(COMPONENT_NAME, []*gqlschema.ConfigEntryInput{ { Key: "path.to.key", Value: SOME_VALUE, }, { Key: "path.to.secret", Value: SOME_VALUE, Secret: ptr.Bool(true), }, })
If your functionality contains long-term processes, you can store data in the storage. To do this, add this field to the provisioning operation in which you want to save data:
type ProvisioningOperation struct { Operation `json:"-"` // These fields are serialized to JSON and stored in the storage ProvisioningParameters string `json:"provisioning_parameters"` NewFieldFromCustomStep string `json:"new_field_from_custom_step"` // These fields are not stored in the storage InputCreator ProvisionerInputCreator `json:"-"` }
By saving data in the storage, you can check if you already have the necessary data and avoid time-consuming processes. You should always return the modified operation from the method.
See the example of the step implementation:
package provisioning import ( "encoding/json" "net/http" "time" "github.com/kyma-incubator/compass/components/provisioner/pkg/gqlschema" "github.com/kyma-incubator/compass/components/kyma-environment-broker/internal" "github.com/kyma-incubator/compass/components/kyma-environment-broker/internal/storage" "github.com/sirupsen/logrus" ) type HelloWorldStep struct { operationStorage storage.Operations client *http.Client } type ExternalBodyResponse struct { data string token string } func NewHelloWorldStep(operationStorage storage.Operations, client *http.Client) *HelloWorldStep { return &HelloWorldStep{ operationStorage: operationStorage, client: client, } } func (s *HelloWorldStep) Name() string { return "Hello_World" } // Your step can be repeated in case any other step fails, even if your step has already done its job func (s *HelloWorldStep) Run(operation internal.ProvisioningOperation, log *logrus.Entry) (internal.ProvisioningOperation, time.Duration, error) { log.Info("Start step") // Check whether your step should be run or if its job has been done in the previous iteration // All non-save operation data are empty (e.g. InputCreator overrides) // Add your logic here // Add a call to an external service (optional) response, err := s.client.Get("http://example.com") if err != nil { // Error during a call to an external service may be temporary so you should return time.Duration // All steps will be repeated in X seconds/minutes return operation, 1 * time.Second, nil } defer response.Body.Close() body := ExternalBodyResponse{} err = json.NewDecoder(response.Body).Decode(&body) if err != nil { log.Errorf("error: %s", err) // Handle a process failure by returning an error or time.Duration } // If a call or any other action is time-consuming, you can save the result in the operation // If you need an extra field in the ProvisioningOperation structure, add it first // in the step below; beforehand, you can check if a given value already exists in the operation operation.HelloWorlds = body.data updatedOperation, err := s.operationStorage.UpdateProvisioningOperation(operation) if err != nil { log.Errorf("error: %s", err) // Handle a process failure by returning an error or time.Duration } // If your step finishes with data which should be added to override used during the Runtime provisioning, // add an extra value to operation.InputCreator, then return the updated version of the Application updatedOperation.InputCreator.SetOverrides("component-name", []*gqlschema.ConfigEntryInput{ { Key: "some.key", Value: body.token, }, }) // Return the updated version of the Application return *updatedOperation, 0, nil }
-
Add the step to the
/cmd/broker/main.go
file:provisioningSteps := []struct { stage string step provisioning.Step }{ { stage: "create_runtime", step: provisioning.NewHelloWorldStep(db.Operations(), &http.Client{}), }, }
Once all steps in the stage have finished succeeded, the stage won't be retried even if the application is restarted.
Deprovisioning
-
Create a new file in this directory.
-
Implement this interface in your deprovisioning step:
type Step interface { Name() string Run(operation internal.DeprovisioningOperation, logger logrus.FieldLogger) (internal.DeprovisioningOperation, time.Duration, error) }
Name()
method returns the name of the step that is used in logs.Run()
method implements the functionality of the step. The method receives operations as an argument to which it can add appropriate overrides or save other used variables.
If your functionality contains long-term processes, you can store data in the storage. To do this, add this field to the deprovisioning operation in which you want to save data:
type DeprovisioningOperation struct { Operation `json:"-"` // add additional data here }
By saving data in the storage, you can check if you already have the necessary data and avoid time-consuming processes. You should always return the modified operation from the method.
See the example of the step implementation:
package deprovisioning import ( "encoding/json" "net/http" "time" "github.com/kyma-incubator/compass/components/provisioner/pkg/gqlschema" "github.com/kyma-incubator/compass/components/kyma-environment-broker/internal" "github.com/kyma-incubator/compass/components/kyma-environment-broker/internal/storage" "github.com/sirupsen/logrus" ) type HelloWorldStep struct { operationStorage storage.Operations client *http.Client } type ExternalBodyResponse struct { data string token string } func NewHelloWorldStep(operationStorage storage.Operations, client *http.Client) *HelloWorldStep { return &HelloWorldStep{ operationStorage: operationStorage, client: client, } } func (s *HelloWorldStep) Name() string { return "Hello_World" } // Your step can be repeated in case any other step fails, even if your step has already done its job func (s *HelloWorldStep) Run(operation internal.DeprovisioningOperation, log *logrus.Entry) (internal.DeprovisioningOperation, time.Duration, error) { log.Info("Start step") // Check whether your step should be run or if its job has been done in the previous iteration // All non-save operation data are empty (e.g. InputCreator overrides) // Add your logic here // Add a call to an external service (optional) response, err := s.client.Get("http://example.com") if err != nil { // Error during a call to an external service may be temporary so you should return time.Duration // All steps will be repeated in X seconds/minutes return operation, 1 * time.Second, nil } defer response.Body.Close() body := ExternalBodyResponse{} err = json.NewDecoder(response.Body).Decode(&body) if err != nil { log.Errorf("error: %s", err) // Handle a process failure by returning an error or time.Duration } // If a call or any other action is time-consuming, you can save the result in the operation // If you need an extra field in the DeprovisioningOperation structure, add it first // in the step below; beforehand, you can check if a given value already exists in the operation operation.HelloWorlds = body.data updatedOperation, err := s.operationStorage.UpdateDeprovisioningOperation(operation) if err != nil { log.Errorf("error: %s", err) // Handle a process failure by returning an error or time.Duration } // If your step finishes with data which should be added to override used during the Runtime deprovisioning, // add an extra value to operation.InputCreator, then return the updated version of the Application updatedOperation.InputCreator.SetOverrides("component-name", []*gqlschema.ConfigEntryInput{ { Key: "some.key", Value: body.token, }, }) // Return the updated version of the Application return *updatedOperation, 0, nil }
-
Add the step to the
/cmd/broker/main.go
file:deprovisioningSteps := []struct { weight int step deprovisioning.Step }{ { weight: 1, step: deprovisioning.NewHelloWorldStep(db.Operations(), &http.Client{}), }, }
The weight of the step should be greater than or equal to 1. If you want the step to be performed before a call to the Runtime Provisioner, its weight must be lower than the weight of the
remove_runtime
step.
Upgrade
-
Create a new file in this directory.
-
Implement this interface in your upgrade step:
type Step interface { Name() string Run(operation internal.UpgradeOperation, logger logrus.FieldLogger) (internal.UpgradeOperation, time.Duration, error) }
Name()
method returns the name of the step that is used in logs.Run()
method implements the functionality of the step. The method receives operations as an argument to which it can add appropriate overrides or save other used variables.
If your functionality contains long-term processes, you can store data in the storage. To do this, add this field to the upgrade operation in which you want to save data:
type UpgradeOperation struct { Operation `json:"-"` // add additional data here }
By saving data in the storage, you can check if you already have the necessary data and avoid time-consuming processes. You should always return the modified operation from the method.
See the example of the step implementation:
package upgrade import ( "encoding/json" "net/http" "time" "github.com/kyma-incubator/compass/components/provisioner/pkg/gqlschema" "github.com/kyma-incubator/compass/components/kyma-environment-broker/internal" "github.com/kyma-incubator/compass/components/kyma-environment-broker/internal/storage" "github.com/sirupsen/logrus" ) type HelloWorldStep struct { operationStorage storage.Operations client *http.Client } type ExternalBodyResponse struct { data string token string } func NewHelloWorldStep(operationStorage storage.Operations, client *http.Client) *HelloWorldStep { return &HelloWorldStep{ operationStorage: operationStorage, client: client, } } func (s *HelloWorldStep) Name() string { return "Hello_World" } // Your step can be repeated in case any other step fails, even if your step has already done its job func (s *HelloWorldStep) Run(operation internal.UpgradeOperation, log *logrus.Entry) (internal.UpgradeOperation, time.Duration, error) { log.Info("Start step") // Check whether your step should be run or if its job has been done in the previous iteration // All non-save operation data are empty (e.g. InputCreator overrides) // Add your logic here // Add a call to an external service (optional) response, err := s.client.Get("http://example.com") if err != nil { // Error during a call to an external service may be temporary so you should return time.Duration // All steps will be repeated in X seconds/minutes return operation, 1 * time.Second, nil } defer response.Body.Close() body := ExternalBodyResponse{} err = json.NewDecoder(response.Body).Decode(&body) if err != nil { log.Errorf("error: %s", err) // Handle a process failure by returning an error or time.Duration } // If a call or any other action is time-consuming, you can save the result in the operation // If you need an extra field in the UpgradeOperation structure, add it first // in the step below; beforehand, you can check if a given value already exists in the operation operation.HelloWorlds = body.data updatedOperation, err := s.operationStorage.UpdateUpgradeOperation(operation) if err != nil { log.Errorf("error: %s", err) // Handle a process failure by returning an error or time.Duration } // If your step finishes with data which should be added to override used during the Runtime upgrade, // add an extra value to operation.InputCreator, then return the updated version of the Application updatedOperation.InputCreator.SetOverrides("component-name", []*gqlschema.ConfigEntryInput{ { Key: "some.key", Value: body.token, }, }) // Return the updated version of the Application return *updatedOperation, 0, nil }
-
Add the step to the
/cmd/broker/main.go
file:upgradeSteps := []struct { weight int step upgrade_kyma.Step }{ { weight: 1, step: upgrade_kyma.NewHelloWorldStep(db.Operations(), &http.Client{}), }, }