Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Create Environment] Adding ec module #1742

Merged
merged 25 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4c75f1f
add ec module
gurevichdmitry Dec 26, 2023
26e34e0
Merge branch 'main' into dg-upgrade-ec-dep
gurevichdmitry Dec 26, 2023
c541fae
update terraform format
gurevichdmitry Dec 26, 2023
771638a
Merge branch 'dg-upgrade-ec-dep' of github.com:elastic/cloudbeat into…
gurevichdmitry Dec 26, 2023
f54a9c2
update ec module format
gurevichdmitry Dec 26, 2023
eb9cdd5
update workflow
gurevichdmitry Dec 26, 2023
f444990
updat tf fmt
gurevichdmitry Dec 26, 2023
0e71397
update workflow and tf
gurevichdmitry Dec 26, 2023
056d798
add tags
gurevichdmitry Dec 27, 2023
558e2c3
add ec api key input support
gurevichdmitry Dec 27, 2023
62a121e
remove duplicate key
gurevichdmitry Dec 27, 2023
0eea065
update tf and workflow
gurevichdmitry Dec 27, 2023
738d28d
update workflow and docs
gurevichdmitry Dec 27, 2023
7df2760
Merge branch 'main' into dg-upgrade-ec-dep
gurevichdmitry Dec 28, 2023
cb66ca9
Merge branch 'main' into dg-upgrade-ec-dep
gurevichdmitry Jan 3, 2024
a0b08c5
Merge branch 'main' into dg-upgrade-ec-dep
gurevichdmitry Jan 3, 2024
1a1e991
update workflows
gurevichdmitry Jan 4, 2024
c19101b
Merge branch 'main' into dg-upgrade-ec-dep
gurevichdmitry Jan 4, 2024
91ed41f
Merge branch 'main' into dg-upgrade-ec-dep
gurevichdmitry Jan 4, 2024
d4f0b38
Merge branch 'main' into dg-upgrade-ec-dep
gurevichdmitry Jan 7, 2024
63bdac7
updated documentation
gurevichdmitry Jan 8, 2024
b8556f4
Merge branch 'main' into dg-upgrade-ec-dep
gurevichdmitry Jan 8, 2024
a71888e
fix review comments
gurevichdmitry Jan 9, 2024
7de6cb4
Merge branch 'main' into dg-upgrade-ec-dep
gurevichdmitry Jan 9, 2024
09f08a0
update format
gurevichdmitry Jan 9, 2024
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
15 changes: 14 additions & 1 deletion .github/workflows/test-environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ jobs:
echo "::add-mask::$ec_api_key"
echo "TF_VAR_ec_api_key=$ec_api_key" >> $GITHUB_ENV

- name: Process BC version
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider getting the hash on a different optional parameter, PIN_VERSION for example.
This way we will avoid the cleaning code implemented both in bash and terraform, and the flow of using the pinned version will be more straight forward PIN_VERSION != "".

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@amirbenun I have refactored the code to support a separate pin_version Terraform variable. This eliminates the need for cleanup version in Terraform code. I've updated the step action responsible for initializing and updating TF_vars and provided comments for clarity. Additionally, I have improved the documentation to make it more clear.

id: remove-commit-hash
run: |
# Extract the stack version
stack_version="${{ inputs.elk-stack-version }}"

# Check if the version contains a commit hash, remove it
if [[ $stack_version =~ -[a-f0-9]+ ]]; then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that we also clean that on the terraform? Where do we use the full version?

Copy link
Collaborator Author

@gurevichdmitry gurevichdmitry Jan 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Terraform, we are utilizing the TF_VAR_stack_version: ${{ inputs.elk-stack-version }} environment variable, which is passed as is. Full version is used to deploy pinned BC version.

cleaned_version=$(echo $stack_version | awk -F"-" '{print $1}')
echo "STACK_VERSION=$cleaned_version" >> $GITHUB_ENV
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove it's declaration on line 115

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updates the declaration to support the working of the entire flow retroactively. The version with the hash is only required for Terraform to pin the version of the stack to be deployed.

fi

- name: Init Enrollment Token
run: |
enrollment_token="init"
Expand Down Expand Up @@ -198,7 +210,8 @@ jobs:
terraform apply --auto-approve \
-var="deployment_name=${{ env.DEPLOYMENT_NAME }}" \
-var="region=${{ env.AWS_REGION }}" \
-var="project=${{ github.actor }}"
-var="project=${{ github.actor }}" \
-var="owner=${{ github.actor }}"
Comment on lines +232 to +233
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯


- name: Set Environment Output
id: env-output
Expand Down
33 changes: 26 additions & 7 deletions .github/workflows/upgrade-environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ jobs:
init:
runs-on: ubuntu-20.04
outputs:
stack-version: ${{ steps.set-previous-version.outputs.PREVIOUS_VERSION }}
base-stack-version: ${{ steps.set-previous-version.outputs.PREVIOUS_VERSION }}
ess-region: ${{ env.TF_VAR_ess_region }}
target-agent-version: ${{ steps.clean-version.outputs.AGENT_VERSION }}
steps:
- name: Check out the repo
uses: actions/checkout@v4
Expand All @@ -52,7 +53,20 @@ jobs:
PREVIOUS_VERSION=$(./.ci/scripts/get-previous-version.sh "$VERSION")
echo "PREVIOUS_VERSION=$PREVIOUS_VERSION" >> $GITHUB_OUTPUT
else
echo "PREVIOUS_VERSION=${{ inputs.base-elk-stack-version }}" >> $GITHUB_ENV
echo "PREVIOUS_VERSION=${{ inputs.base-elk-stack-version }}" >> $GITHUB_OUTPUT
fi
- name: Process BC version
id: clean-version
run: |
# Extract the stack version
stack_version="${{ inputs.target-elk-stack-version }}"

# Check if the version contains a commit hash, remove it
if [[ $stack_version =~ -[a-f0-9]+ ]]; then
cleaned_version=$(echo $stack_version | awk -F"-" '{print $1}')
echo "AGENT_VERSION=$cleaned_version" >> $GITHUB_OUTPUT
else
echo "AGENT_VERSION=$stack_version" >> $GITHUB_OUTPUT
Comment on lines +58 to +69
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we reuse this part maybe we can export it to a script or to an action

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The common part is just to retrieve cleaned_version. Afterwards, the handling is different. In this action, we are adding AGENT_VERSION to GITHUB_OUTPUT (different jobs), and in the test-environments step, we are updating env vars of the same job.

fi
deploy:
uses: ./.github/workflows/test-environment.yml
Expand All @@ -63,7 +77,7 @@ jobs:
id-token: 'write'
with:
deployment_name: ${{ inputs.deployment_name }}
elk-stack-version: ${{ needs.init.outputs.stack-version }}
elk-stack-version: ${{ needs.init.outputs.base-stack-version }}
ess-region: ${{ needs.init.outputs.ess-region }}
run-sanity-tests: false # Set to true once the issue at https://github.com/elastic/kibana/pull/171200 is resolved.
serverless_mode: false
Expand Down Expand Up @@ -125,7 +139,11 @@ jobs:
id: apply
if: success()
run: |
terraform apply --auto-approve -var="deployment_name=${{ inputs.deployment_name }}" -var="region=${{ env.AWS_REGION }}"
terraform apply --auto-approve \
-var="deployment_name=${{ inputs.deployment_name }}" \
-var="region=${{ env.AWS_REGION }}" \
-var="project=${{ github.actor }}" \
-var="owner=${{ github.actor }}"

- name: Set Environment Output
id: env-output
Expand Down Expand Up @@ -167,7 +185,7 @@ jobs:
working-directory: ./tests
env:
USE_K8S: false
AGENT_VERSION: ${{ needs.init.outputs.stack-version }}
AGENT_VERSION: ${{ needs.init.outputs.base-stack-version }}
run: |
poetry install
poetry run pytest -m "sanity" --alluredir=./allure/results/ --clean-alluredir --maxfail=4
Expand Down Expand Up @@ -198,20 +216,21 @@ jobs:
--name $(terraform output -raw deployment_name) --alias eks-config
kubectl config use-context eks-config
kubectl set image daemonset elastic-agent -n kube-system elastic-agent=${{ env.DOCKER_IMAGE }}
kubectl rollout restart daemonset/elastic-agent -n kube-system

- name: Upgrade Linux agents
working-directory: ${{ env.WORKING_DIR }}/${{ env.FLEET_API_DIR }}
env:
CNVM_STACK_NAME: ${{ needs.deploy.outputs.cnvm-stack-name }}
STACK_VERSION: ${{ inputs.target-elk-stack-version }}
STACK_VERSION: ${{ needs.init.outputs.target-agent-version }}
run: |
poetry run python upgrade_agents.py

- name: Run Upgrade Sanity checks
if: success()
working-directory: ./tests
env:
AGENT_VERSION: ${{ inputs.target-elk-stack-version }}
AGENT_VERSION: ${{ needs.init.outputs.target-agent-version }}
USE_K8S: false
run: |
poetry install
Expand Down
67 changes: 67 additions & 0 deletions deploy/cloud/modules/ec/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
locals {
version = var.stack_version
region = var.region
name_prefix = var.deployment_name_prefix
deployment_template = var.deployment_template
es_docker_image = lookup(var.docker_image, "elasticsearch", "")
es_docker_image_tag_override = lookup(var.docker_image_tag_override, "elasticsearch", "")
kibana_docker_image = lookup(var.docker_image, "kibana", "")
kibana_docker_image_tag_override = lookup(var.docker_image_tag_override, "kibana", "")
apm_docker_image = lookup(var.docker_image, "apm", "")
apm_docker_image_tag_override = lookup(var.docker_image_tag_override, "apm", "")
Comment on lines +6 to +11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really have a usecase of overriding these?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main use case is to support pinned BC versions. As described in this task, if we provide just the version (e.g., 8.12.0) and a new BC candidate is released, the stack will be updated with the newest version underneath. To prevent that, we should provide the exact version to be deployed. Unfortunately, the ec provider does not support the direct deployment of versions with a hash. To work around this, we need to override the docker_image for all stack components (ElasticSearch, Kibana, and Integrations Server). In the test environments' main.tf, we provide docker_image_tag_override, which is then passed to the ec module and used to deploy the custom image.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we even need the apm component?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default manual deployment on the cloud includes the Integrations server component.
We are installing the Integrations server component, which was introduced in version 8.x and consists of APM and Fleet Server. Fleet is necessary to centrally manage all agents, integrations, and APM is part of Integrations server component.

}

data "ec_stack" "deployment_version" {
version_regex = local.version
region = local.region
}

resource "ec_deployment" "deployment" {
name = "${local.name_prefix}-${data.ec_stack.deployment_version.version}"
version = data.ec_stack.deployment_version.version
region = local.region
deployment_template_id = local.deployment_template
tags = var.tags

elasticsearch = {
autoscale = var.elasticsearch_autoscale
strategy = "rolling_all"
config = {
docker_image = local.es_docker_image_tag_override != "" ? "${local.es_docker_image}:${local.es_docker_image_tag_override}" : null
}

cold = {
autoscaling = {}
}

frozen = {
autoscaling = {}
}

hot = {
autoscaling = {
max_size = "128g"
max_size_resource = "memory"
}
size = var.elasticsearch_size
zone_count = var.elasticsearch_zone_count
}

warm = {
autoscaling = {}
}
}

kibana = {
config = {
docker_image = local.kibana_docker_image_tag_override != "" ? "${local.kibana_docker_image}:${local.kibana_docker_image_tag_override}" : null
}
}

integrations_server = {
config = {
docker_image = local.apm_docker_image_tag_override != "" ? "${local.apm_docker_image}:${local.apm_docker_image_tag_override}" : null
}
}

}
26 changes: 26 additions & 0 deletions deploy/cloud/modules/ec/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
output "kibana_url" {
value = ec_deployment.deployment.kibana.https_endpoint
description = "The secure Kibana URL"
}

output "elasticsearch_url" {
value = ec_deployment.deployment.elasticsearch.https_endpoint
description = "The secure Elasticsearch URL"
}

output "elasticsearch_username" {
value = ec_deployment.deployment.elasticsearch_username
sensitive = true
description = "The Elasticsearch username"
}

output "elasticsearch_password" {
value = ec_deployment.deployment.elasticsearch_password
sensitive = true
description = "The Elasticsearch password"
}

output "stack_version" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, we should start using it instead of the "requested" version.

value = data.ec_stack.deployment_version.version
description = "The matching stack pack version from the provided stack_version"
}
10 changes: 10 additions & 0 deletions deploy/cloud/modules/ec/terraform.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.3, <2.0.0"

required_providers {
ec = {
source = "elastic/ec"
version = ">=0.9.0"
}
}
}
76 changes: 76 additions & 0 deletions deploy/cloud/modules/ec/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
variable "ec_api_key" {
type = string
}

variable "stack_version" {
description = "Optional version of the Elastic Cloud deployment"
type = string
default = "latest"
}

variable "region" {
description = "Optional region of the Elastic Cloud deployment"
type = string
default = "gcp-us-west2"
}

variable "deployment_template" {
description = "Optional defaults to the CPU optimized template for GCP"
type = string
default = "gcp-compute-optimized-v3"
}

variable "deployment_name_prefix" {
description = "Prefix for the Elastic Cloud deployment name"
type = string
default = "cloud-security"
}

variable "tags" {
type = map(string)
default = {
"deployment" = "cloud-security",
"environment" = "test-enviroment",
}
description = "Optional set of tags to use for all deployments"
}

variable "elasticsearch_size" {
default = "8g"
type = string
description = "Optional Elasticsearch instance size"
}

variable "elasticsearch_zone_count" {
default = 2
type = number
description = "Optional Elasticsearch zone count"
}

variable "elasticsearch_autoscale" {
default = false
type = bool
description = "Optional autoscale the Elasticsearch cluster"
}

# Docker image overrides

variable "docker_image_tag_override" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comments on why those are needed especially when deploying BC versions.

default = {
"elasticsearch" = "",
"kibana" = "",
"apm" = "",
Comment on lines +64 to +66
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need those?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, each stack component may use a different image tag

}
description = "Optional docker image tag overrides, The full map needs to be specified"
type = map(string)
}

variable "docker_image" {
default = {
"elasticsearch" = "docker.elastic.co/cloud-release/elasticsearch-cloud-ess",
"kibana" = "docker.elastic.co/cloud-release/kibana-cloud",
"apm" = "docker.elastic.co/cloud-release/elastic-agent-cloud",
}
type = map(string)
description = "Optional docker image overrides. The full map needs to be specified"
}
19 changes: 11 additions & 8 deletions deploy/test-environments/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ locals {
org = "${var.org}"
team = "${var.team}"
project = "${var.project}"
owner = "${var.owner}"
}
ec_url = "https://cloud.elastic.co"
ec_headers = {
Content-type = "application/json"
Authorization = "ApiKey ${var.ec_api_key}"
}
cleaned_version = length(regexall("(-[0-9a-z]{4})", var.stack_version)) > 0 ? split("-", var.stack_version)[0] : var.stack_version
}

# EC2 + kind deployment
Expand Down Expand Up @@ -54,25 +56,26 @@ provider "restapi" {

# Elastic Cloud (EC) deployment
module "ec_deployment" {
count = var.serverless_mode ? 0 : 1
source = "github.com/elastic/apm-server/testing/infra/terraform/modules/ec_deployment"
count = var.serverless_mode ? 0 : 1

source = "../cloud/modules/ec"
ec_api_key = var.ec_api_key
region = var.ess_region
stack_version = var.stack_version
stack_version = local.cleaned_version
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we don't even deploy the requested version? Where do we use the commit sha?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of a released or snapshot version, stack_version will not be modified and remains the same. However, in the case of a BC version, we need to remove the hash from stack_version. This is essential because the ec provider might fail with an unknown version if the hash is included. Additionally, we need to override docker_image_tag. Instead of creating complex logic to handle different scenarios, we always provide docker_image_override in all cases to ensure that our deployment deploys the pinned version.

tags = local.common_tags

deployment_template = var.deployment_template
deployment_name_prefix = "${var.deployment_name}-${random_string.suffix.result}"

integrations_server = true

elasticsearch_autoscale = true
elasticsearch_size = var.elasticsearch_size
elasticsearch_zone_count = var.elasticsearch_zone_count

docker_image = var.docker_image_override
docker_image_tag_override = {
"elasticsearch" : "",
"kibana" : "",
"apm" : ""
"elasticsearch" = "${var.stack_version}",
"kibana" = "${var.stack_version}",
"apm" = "${var.stack_version}"
}
}

Expand Down
2 changes: 1 addition & 1 deletion deploy/test-environments/terraform.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ terraform {

ec = {
source = "elastic/ec"
version = ">=0.5.0"
version = ">=0.9.0"
}

restapi = {
Expand Down
Loading