Skip to content

Commit

Permalink
Add support for ElasticSearch/OpenSearch as a storage (#30)
Browse files Browse the repository at this point in the history
- Refactor database variables to support multiple storages more easily.
  • Loading branch information
kezhenxu94 committed Sep 2, 2023
1 parent e43e63e commit d643900
Show file tree
Hide file tree
Showing 14 changed files with 272 additions and 79 deletions.
5 changes: 4 additions & 1 deletion ansible/roles/skywalking/templates/skywalking-oap.env.j2
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@
{% set storage = database['type'] %}

{% if storage and (storage | length) %}
SW_STORAGE={{ storage | regex_replace('^rds-', '')}}
SW_STORAGE={{ storage | regex_replace('^rds_', '')}}
{% endif %}

{% if "postgresql" in storage %}
SW_JDBC_URL=jdbc:postgresql://{{ database["host"] }}:{{ database["port"] }}/{{ database["name"] }}
SW_DATA_SOURCE_USER={{ database['user'] }}
SW_DATA_SOURCE_PASSWORD={{ database['password'] }}
{% elif "elasticsearch" in storage %}
SW_STORAGE_ES_CLUSTER_NODES={{ database["host"] }}
SW_STORAGE_ES_HTTP_PROTOCOL=https
{% endif %}

{% for key, value in skywalking_oap_environment.items() %}
Expand Down
25 changes: 25 additions & 0 deletions ansible/template/group_vars/skywalking_oap.yaml.tftpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.

database:
type: ${database_type}
host: ${database_host}
port: ${database_port}
name: ${database_name}
user: ${database_user}
password: ${database_password}

8 changes: 0 additions & 8 deletions ansible/template/inventory.yaml.tftpl
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,6 @@ skywalking_oap:
%{ for oap in oap_instances ~}
${oap.private_ip}:
%{ endfor ~}
vars:
database:
type: ${database_type}
host: ${database_host}
port: ${database_port}
name: ${database_name}
user: ${database_user}
password: ${database_password}

skywalking_ui:
hosts:
Expand Down
11 changes: 11 additions & 0 deletions aws/alb-main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ module "alb" {
port = 8080
}
]
health_check = {
enabled = true
interval = 30
path = "/internal/l7check"
port = "traffic-port"
healthy_threshold = 3
unhealthy_threshold = 3
timeout = 6
protocol = "HTTP"
matcher = "200"
}
}
]

Expand Down
15 changes: 8 additions & 7 deletions aws/configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,18 @@ No requirements.

| Name | Type |
|------|------|
| [aws_elasticsearch_domain.elasticsearch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticsearch_domain) | resource |
| [aws_security_group.alb-skywalking-ui](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_security_group.allow_apps](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_security_group.elasticsearch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_security_group.public-egress-access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [local_file.elasticsearch_vars](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
| [local_file.h2_vars](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
| [local_file.inventories](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
| [local_file.rds_postgresql_vars](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
| [random_password.rds_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |

## Inputs

Expand All @@ -43,12 +49,6 @@ No requirements.
| <a name="input_cluster_name"></a> [cluster\_name](#input\_cluster\_name) | Name of the cluster | `string` | `"skywalking-cluster"` | no |
| <a name="input_create_lb"></a> [create\_lb](#input\_create\_lb) | Create load balancer for SkyWalking UI | `bool` | `true` | no |
| <a name="input_database_subnets"></a> [database\_subnets](#input\_database\_subnets) | CIDR used for database subnets | `set(string)` | <pre>[<br> "11.0.104.0/24",<br> "11.0.105.0/24",<br> "11.0.106.0/24"<br>]</pre> | no |
| <a name="input_db_instance_class"></a> [db\_instance\_class](#input\_db\_instance\_class) | Instance class for the database | `string` | `"db.t3.medium"` | no |
| <a name="input_db_max_storage_size"></a> [db\_max\_storage\_size](#input\_db\_max\_storage\_size) | Maximum storage size for the database, in GB | `number` | `100` | no |
| <a name="input_db_name"></a> [db\_name](#input\_db\_name) | Name of the database | `string` | `"skywalking"` | no |
| <a name="input_db_password"></a> [db\_password](#input\_db\_password) | Password for the database, if not set, a random password will be generated. | `string` | `null` | no |
| <a name="input_db_storage_size"></a> [db\_storage\_size](#input\_db\_storage\_size) | Storage size for the database, in GB | `number` | `5` | no |
| <a name="input_db_username"></a> [db\_username](#input\_db\_username) | Username for the database | `string` | `"skywalking"` | no |
| <a name="input_extra_tags"></a> [extra\_tags](#input\_extra\_tags) | Additional tags to be added to all resources | `map(string)` | `{}` | no |
| <a name="input_oap_instance_count"></a> [oap\_instance\_count](#input\_oap\_instance\_count) | Number of OAP instances, if you want to use H2 storage, you must set it to 1. | `number` | `1` | no |
| <a name="input_oap_instance_type"></a> [oap\_instance\_type](#input\_oap\_instance\_type) | CPU, memory, storage and networking capacity for OAP instances | `string` | `"c5.xlarge"` | no |
Expand All @@ -57,7 +57,7 @@ No requirements.
| <a name="input_public_subnets"></a> [public\_subnets](#input\_public\_subnets) | CIDR used for public subnets | `set(string)` | <pre>[<br> "11.0.101.0/24",<br> "11.0.102.0/24",<br> "11.0.103.0/24"<br>]</pre> | no |
| <a name="input_region"></a> [region](#input\_region) | Physical location for clustered data centers. | `string` | `"us-east-1"` | no |
| <a name="input_secret_key"></a> [secret\_key](#input\_secret\_key) | Secret key of the AWS account, if you have configured AWS CLI, you can leave it empty. | `string` | `""` | no |
| <a name="input_storage"></a> [storage](#input\_storage) | Storage type for SkyWalking OAP, can be 'h2', or 'rds-postgresql' | `string` | `"rds-postgresql"` | no |
| <a name="input_storage"></a> [storage](#input\_storage) | Storage configuration for SkyWalking OAP | <pre>object({<br> h2 = optional(object({}))<br> rds_postgresql = optional(object({<br> db_storage_size_gb = optional(number)<br> db_max_storage_size_gb = optional(number)<br> db_instance_class = optional(string)<br> db_name = optional(string)<br> db_username = optional(string)<br> db_password = optional(string)<br> }))<br> elasticsearch = optional(object({<br> domain_name = optional(string)<br> version = optional(string)<br> instance_type = optional(string)<br> instance_count = optional(number)<br> additional_security_groups = optional(list(string))<br> zone_awareness_enabled = optional(bool)<br> availability_zone_count = optional(number)<br> ebs_enabled = optional(bool)<br> }))<br> })</pre> | <pre>{<br> "h2": {}<br>}</pre> | no |
| <a name="input_ui_instance_count"></a> [ui\_instance\_count](#input\_ui\_instance\_count) | Number of UI instances | `number` | `1` | no |
| <a name="input_ui_instance_type"></a> [ui\_instance\_type](#input\_ui\_instance\_type) | CPU, memory, storage and networking capacity for UI instances | `string` | `"t2.medium"` | no |

Expand All @@ -72,6 +72,7 @@ No requirements.
| <a name="output_database_password"></a> [database\_password](#output\_database\_password) | The database password |
| <a name="output_database_port"></a> [database\_port](#output\_database\_port) | The database port |
| <a name="output_database_username"></a> [database\_username](#output\_database\_username) | The database username |
| <a name="output_elasticsearch_endpoint"></a> [elasticsearch\_endpoint](#output\_elasticsearch\_endpoint) | The elasticsearch endpoint |
| <a name="output_oap_ips"></a> [oap\_ips](#output\_oap\_ips) | The private IPs of the OAP instances |
| <a name="output_ssh_user_key_file"></a> [ssh\_user\_key\_file](#output\_ssh\_user\_key\_file) | The SSH private key file to use to connect to the bastion host |
| <a name="output_ui_ips"></a> [ui\_ips](#output\_ui\_ips) | The IPs of the SkyWalking UI instances |
Expand Down
14 changes: 4 additions & 10 deletions aws/ec2-main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,9 @@ resource "local_file" "inventories" {
filename = "${path.module}/../ansible/inventory/skywalking.yaml"
file_permission = "0600"
content = templatefile("${path.module}/../ansible/template/inventory.yaml.tftpl", {
bastion = module.skywalking.bastion_instances[0]
oap_instances = module.skywalking.oap_instances
ui_instances = module.skywalking.ui_instances
private_key_file = module.skywalking.ssh_user_key_file
database_type = var.storage
database_host = var.storage == "rds-postgresql" ? module.rds[0].db_instance_address : ""
database_port = var.storage == "rds-postgresql" ? module.rds[0].db_instance_port : ""
database_user = var.storage == "rds-postgresql" ? module.rds[0].db_instance_username : ""
database_name = var.storage == "rds-postgresql" ? module.rds[0].db_instance_name : ""
database_password = var.storage == "rds-postgresql" ? local.database_password : ""
bastion = module.skywalking.bastion_instances[0]
oap_instances = module.skywalking.oap_instances
ui_instances = module.skywalking.ui_instances
private_key_file = module.skywalking.ssh_user_key_file
})
}
99 changes: 99 additions & 0 deletions aws/elasticsearch-main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.

locals {
elasticsearch_domain_name = coalesce(lookup(local.storage_config, "domain_name"), var.cluster_name)
elasticsearch_version = coalesce(lookup(local.storage_config, "version"), "7.10")
elasticsearch_instance_type = coalesce(lookup(local.storage_config, "instance_type"), "m3.medium.elasticsearch")
elasticsearch_instance_count = coalesce(lookup(local.storage_config, "instance_count"), 2)
elasticsearch_additional_security_groups = coalesce(lookup(local.storage_config, "additional_security_groups"), [])
elasticsearch_zone_awareness_enabled = coalesce(lookup(local.storage_config, "zone_awareness_enabled"), false)
elasticsearch_availability_zone_count = coalesce(lookup(local.storage_config, "availability_zone_count"), 2)
elasticsearch_ebs_enabled = coalesce(lookup(local.storage_config, "ebs_enabled"), false)
}

data "aws_caller_identity" "current" {}

resource "aws_elasticsearch_domain" "elasticsearch" {
count = local.storage_name == "elasticsearch" ? 1 : 0

domain_name = local.elasticsearch_domain_name
elasticsearch_version = local.elasticsearch_version

cluster_config {
instance_type = local.elasticsearch_instance_type
instance_count = local.elasticsearch_instance_count
zone_awareness_enabled = local.elasticsearch_zone_awareness_enabled
zone_awareness_config {
availability_zone_count = local.elasticsearch_availability_zone_count
}
}

vpc_options {
subnet_ids = slice(module.vpc.private_subnets, 0, local.elasticsearch_zone_awareness_enabled ? 2 : 1)

security_group_ids = [aws_security_group.elasticsearch.id]
}

ebs_options {
ebs_enabled = local.elasticsearch_ebs_enabled
}

access_policies = <<CONFIG
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "es:*",
"Principal": "*",
"Effect": "Allow",
"Resource": "arn:aws:es:${var.region}:${data.aws_caller_identity.current.account_id}:domain/${local.elasticsearch_domain_name}/*"
}
]
}
CONFIG

tags = var.extra_tags
}

resource "aws_security_group" "elasticsearch" {
name = "${module.vpc.vpc_id}-elasticsearch-${local.elasticsearch_domain_name}"
description = "Security group to allow requests to ElasticSearch"
vpc_id = module.vpc.vpc_id

ingress {
from_port = 443
to_port = 443
protocol = "tcp"
security_groups = module.skywalking.oap_security_groups
}
}

resource "local_file" "elasticsearch_vars" {
count = local.storage_name == "elasticsearch" ? 1 : 0

filename = "${path.module}/../ansible/inventory/group_vars/skywalking_oap.yaml"
file_permission = "0600"
content = templatefile("${path.module}/../ansible/template/group_vars/skywalking_oap.yaml.tftpl", {
database_type = local.storage_name
database_host = local.storage_name == "elasticsearch" ? aws_elasticsearch_domain.elasticsearch[0].endpoint : ""
database_port = ""
database_user = ""
database_name = ""
database_password = ""
})
}
21 changes: 21 additions & 0 deletions aws/elasticsearch-output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.

output "elasticsearch_endpoint" {
value = local.storage_name == "elasticsearch" ? aws_elasticsearch_domain.elasticsearch[0].endpoint : ""
description = "The elasticsearch endpoint"
}
31 changes: 31 additions & 0 deletions aws/h2-main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.

resource "local_file" "h2_vars" {
count = local.storage_name == "h2" ? 1 : 0

filename = "${path.module}/../ansible/inventory/group_vars/skywalking_oap.yaml"
file_permission = "0600"
content = templatefile("${path.module}/../ansible/template/group_vars/skywalking_oap.yaml.tftpl", {
database_type = local.storage_name
database_host = ""
database_port = ""
database_user = ""
database_name = ""
database_password = ""
})
}
2 changes: 1 addition & 1 deletion aws/modules/skywalking/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ No modules.
| <a name="input_oap_instance_subnet_id"></a> [oap\_instance\_subnet\_id](#input\_oap\_instance\_subnet\_id) | Subnet ID for OAP instances | `string` | n/a | yes |
| <a name="input_oap_instance_type"></a> [oap\_instance\_type](#input\_oap\_instance\_type) | CPU, memory, storage and networking capacity for OAP instances | `string` | `"c5.xlarge"` | no |
| <a name="input_public_key_path"></a> [public\_key\_path](#input\_public\_key\_path) | Path to store the key file for SSH access to the instances. | `string` | `"~/.ssh"` | no |
| <a name="input_storage"></a> [storage](#input\_storage) | Storage type for SkyWalking OAP, can be `h2`, or `rds-postgresql` | `string` | `"rds-postgresql"` | no |
| <a name="input_storage"></a> [storage](#input\_storage) | Storage type for SkyWalking OAP, can be `h2`, `elasticsearch` or `rds-postgresql` | `string` | `"rds-postgresql"` | no |
| <a name="input_ui_instance_ami_id"></a> [ui\_instance\_ami\_id](#input\_ui\_instance\_ami\_id) | AMI ID for UI instances, if not set, a suitable AMI ID will be selected automatically. | `string` | `""` | no |
| <a name="input_ui_instance_count"></a> [ui\_instance\_count](#input\_ui\_instance\_count) | Number of UI instances | `number` | `1` | no |
| <a name="input_ui_instance_security_group_ids"></a> [ui\_instance\_security\_group\_ids](#input\_ui\_instance\_security\_group\_ids) | Additional security groups for UI instances | `list(string)` | `[]` | no |
Expand Down
6 changes: 3 additions & 3 deletions aws/modules/skywalking/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,12 @@ variable "extra_tags" {
## Storage
variable "storage" {
type = string
description = "Storage type for SkyWalking OAP, can be `h2`, or `rds-postgresql`"
description = "Storage type for SkyWalking OAP, can be `h2`, `elasticsearch` or `rds-postgresql`"
default = "rds-postgresql"

validation {
condition = contains(["h2", "rds-postgresql"], var.storage)
error_message = "Allowed values for storage are \"h2\", \"rds-postgresql\"."
condition = contains(["h2", "elasticsearch", "rds_postgresql"], var.storage)
error_message = "Allowed values for storage are \"h2\", \"rds_postgresql\"."
}
}

Expand Down

0 comments on commit d643900

Please sign in to comment.