diff --git a/modules/unreal/unreal-cloud-ddc-infra/README.md b/modules/unreal/unreal-cloud-ddc-infra/README.md new file mode 100644 index 00000000..b7fdba61 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-infra/README.md @@ -0,0 +1,211 @@ +<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK --> +## Requirements + +| Name | Version | +|------|---------| +| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5 | +| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.38 | +| <a name="requirement_tls"></a> [tls](#requirement\_tls) | >= 4.0.5 | + +## Providers + +| Name | Version | +|------|---------| +| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.38 | +| <a name="provider_tls"></a> [tls](#provider\_tls) | >= 4.0.5 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_cloudwatch_log_group.unreal_cluster_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_eks_cluster.unreal_cloud_ddc_eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster) | resource | +| [aws_eks_identity_provider_config.eks_cluster_oidc_association](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_identity_provider_config) | resource | +| [aws_eks_node_group.nvme_node_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | +| [aws_eks_node_group.system_node_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | +| [aws_eks_node_group.worker_node_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | +| [aws_iam_instance_profile.scylla_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | +| [aws_iam_openid_connect_provider.unreal_cloud_ddc_oidc_provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_openid_connect_provider) | resource | +| [aws_iam_role.eks_cluster_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.monitoring_node_group_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.nvme_node_group_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.scylla_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.worker_node_group_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_instance.scylla_ec2_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | +| [aws_launch_template.nvme_launch_template](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | +| [aws_launch_template.system_launch_template](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | +| [aws_launch_template.worker_launch_template](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | +| [aws_route53_record.scylla_records](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | +| [aws_route53_zone.scylla_zone](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone) | resource | +| [aws_s3_bucket.unreal_ddc_logging_s3_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket.unreal_ddc_s3_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_logging.unreal-log-s3-log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | +| [aws_s3_bucket_logging.unreal-s3-log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | +| [aws_s3_bucket_public_access_block.unreal_ddc_log_s3_acls](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_s3_bucket_public_access_block.unreal_ddc_s3_acls](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_s3_bucket_server_side_encryption_configuration.unreal-s3-bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [aws_s3_bucket_server_side_encryption_configuration.unreal-s3-logging-bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [aws_security_group.nvme_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group.scylla_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group.system_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group.worker_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group_rule.peer_cidr_blocks_ingress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.peer_cidr_blocks_scylla_egress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.scylla_to_nvme_group_egress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.scylla_to_nvme_group_ingress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.scylla_to_worker_group_egress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.scylla_to_worker_group_ingress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.self_ingress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.self_scylla_egress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.ssm_egress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_ssm_association.scylla_config_association](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_association) | resource | +| [aws_ssm_document.config_scylla](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_document) | resource | +| [aws_ami.scylla_ami](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | +| [aws_ssm_parameter.eks_ami_latest_release](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | +| [tls_certificate.eks_tls_certificate](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/data-sources/certificate) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| <a name="input_eks_cluster_access_cidr"></a> [eks\_cluster\_access\_cidr](#input\_eks\_cluster\_access\_cidr) | List of the CIDR Ranges you want to grant public access to the EKS Cluster. | `list(string)` | n/a | yes | +| <a name="input_name"></a> [name](#input\_name) | Unreal Cloud DDC Workload Name | `string` | `"unreal-cloud-ddc"` | no | +| <a name="input_nvme_managed_node_desired_size"></a> [nvme\_managed\_node\_desired\_size](#input\_nvme\_managed\_node\_desired\_size) | Desired number of nvme managed node group instances | `number` | `2` | no | +| <a name="input_nvme_managed_node_instance_type"></a> [nvme\_managed\_node\_instance\_type](#input\_nvme\_managed\_node\_instance\_type) | Nvme managed node group instance type | `string` | `"i3en.xlarge"` | no | +| <a name="input_nvme_managed_node_max_size"></a> [nvme\_managed\_node\_max\_size](#input\_nvme\_managed\_node\_max\_size) | Max number of nvme managed node group instances | `number` | `2` | no | +| <a name="input_peer_cidr_blocks"></a> [peer\_cidr\_blocks](#input\_peer\_cidr\_blocks) | The peered cidr blocks you want your vpc to communicate with if you have a multi region ddc. | `list(string)` | `[]` | no | +| <a name="input_private_subnets"></a> [private\_subnets](#input\_private\_subnets) | Private subnets you want scylla and the worker nodes to be installed into. | `list(string)` | `[]` | no | +| <a name="input_scylla_ami_name"></a> [scylla\_ami\_name](#input\_scylla\_ami\_name) | Name of the Scylla AMI to be used to get the AMI ID | `string` | `"ScyllaDB 6.0.1"` | no | +| <a name="input_scylla_architecture"></a> [scylla\_architecture](#input\_scylla\_architecture) | The chip architecture to use when finding the scylla image. Valid | `string` | `"x86_64"` | no | +| <a name="input_scylla_db_storage"></a> [scylla\_db\_storage](#input\_scylla\_db\_storage) | Size of gp3 ebs volumes attached to Scylla DBs | `number` | `100` | no | +| <a name="input_scylla_db_throughput"></a> [scylla\_db\_throughput](#input\_scylla\_db\_throughput) | Throughput of gp3 ebs volumes attached to Scylla DBs | `number` | `200` | no | +| <a name="input_scylla_dns"></a> [scylla\_dns](#input\_scylla\_dns) | The local private dns name that you want Scylla to be queryable on. | `string` | `null` | no | +| <a name="input_scylla_instance_type"></a> [scylla\_instance\_type](#input\_scylla\_instance\_type) | The type and size of the Scylla instance. | `string` | `"i4i.2xlarge"` | no | +| <a name="input_scylla_private_subnets"></a> [scylla\_private\_subnets](#input\_scylla\_private\_subnets) | The subnets you want Scylla to be installed into. Can repeat subnet ids to install into the same subnet/az. This will also determine how many Scylla instances are deployed. | `list(string)` | `[]` | no | +| <a name="input_system_managed_node_desired_size"></a> [system\_managed\_node\_desired\_size](#input\_system\_managed\_node\_desired\_size) | Desired number of monitoring managed node group instances. | `number` | `1` | no | +| <a name="input_system_managed_node_instance_type"></a> [system\_managed\_node\_instance\_type](#input\_system\_managed\_node\_instance\_type) | Monitoring managed node group instance type. | `string` | `"m5.large"` | no | +| <a name="input_system_managed_node_max_size"></a> [system\_managed\_node\_max\_size](#input\_system\_managed\_node\_max\_size) | Max number of monitoring managed node group instances. | `number` | `2` | no | +| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | String for VPC ID | `string` | n/a | yes | +| <a name="input_worker_managed_node_desired_size"></a> [worker\_managed\_node\_desired\_size](#input\_worker\_managed\_node\_desired\_size) | Desired number of worker managed node group instances. | `number` | `1` | no | +| <a name="input_worker_managed_node_instance_type"></a> [worker\_managed\_node\_instance\_type](#input\_worker\_managed\_node\_instance\_type) | Worker managed node group instance type. | `string` | `"c5.xlarge"` | no | +| <a name="input_worker_managed_node_max_size"></a> [worker\_managed\_node\_max\_size](#input\_worker\_managed\_node\_max\_size) | Max number of worker managed node group instances. | `number` | `1` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| <a name="output_cluster_arn"></a> [cluster\_arn](#output\_cluster\_arn) | n/a | +| <a name="output_cluster_certificate_authority_data"></a> [cluster\_certificate\_authority\_data](#output\_cluster\_certificate\_authority\_data) | n/a | +| <a name="output_cluster_endpoint"></a> [cluster\_endpoint](#output\_cluster\_endpoint) | n/a | +| <a name="output_cluster_name"></a> [cluster\_name](#output\_cluster\_name) | n/a | +| <a name="output_oidc_provider_arn"></a> [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | n/a | +| <a name="output_oidc_provider_identity"></a> [oidc\_provider\_identity](#output\_oidc\_provider\_identity) | n/a | +| <a name="output_s3_bucket_id"></a> [s3\_bucket\_id](#output\_s3\_bucket\_id) | n/a | +<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK --> +<!-- BEGIN_TF_DOCS --> +## Requirements + +| Name | Version | +|------|---------| +| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5 | +| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >=5.73.0 | +| <a name="requirement_tls"></a> [tls](#requirement\_tls) | >= 4.0.6 | + +## Providers + +| Name | Version | +|------|---------| +| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.77.0 | +| <a name="provider_tls"></a> [tls](#provider\_tls) | 4.0.6 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_cloudwatch_log_group.unreal_cluster_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_eks_cluster.unreal_cloud_ddc_eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster) | resource | +| [aws_eks_node_group.nvme_node_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | +| [aws_eks_node_group.system_node_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | +| [aws_eks_node_group.worker_node_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | +| [aws_iam_instance_profile.scylla_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | +| [aws_iam_openid_connect_provider.unreal_cloud_ddc_oidc_provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_openid_connect_provider) | resource | +| [aws_iam_role.eks_cluster_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.nvme_node_group_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.scylla_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.system_node_group_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.worker_node_group_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachments_exclusive.eks_cluster_policy_attachement](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachments_exclusive) | resource | +| [aws_iam_role_policy_attachments_exclusive.nvme_policy_attachement](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachments_exclusive) | resource | +| [aws_iam_role_policy_attachments_exclusive.scylla_policy_attachement](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachments_exclusive) | resource | +| [aws_iam_role_policy_attachments_exclusive.system_policy_attachement](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachments_exclusive) | resource | +| [aws_iam_role_policy_attachments_exclusive.worker_policy_attachement](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachments_exclusive) | resource | +| [aws_instance.scylla_ec2_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | +| [aws_launch_template.nvme_launch_template](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | +| [aws_launch_template.system_launch_template](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | +| [aws_launch_template.worker_launch_template](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | +| [aws_s3_bucket.unreal_ddc_s3_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_public_access_block.unreal_ddc_s3_acls](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_s3_bucket_server_side_encryption_configuration.unreal-s3-bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [aws_security_group.nvme_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group.scylla_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group.system_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group.worker_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_ssm_association.scylla_config_association](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_association) | resource | +| [aws_ssm_document.config_scylla](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_document) | resource | +| [aws_vpc_security_group_egress_rule.nvme_egress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_egress_rule.self_scylla_egress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_egress_rule.ssm_egress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_egress_rule.system_egress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_egress_rule.worker_egress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.self_ingress_sg_rules](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource | +| [aws_ami.scylla_ami](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | +| [aws_ssm_parameter.eks_ami_latest_release](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | +| [tls_certificate.eks_tls_certificate](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/data-sources/certificate) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| <a name="input_eks_cluster_access_cidr"></a> [eks\_cluster\_access\_cidr](#input\_eks\_cluster\_access\_cidr) | List of the CIDR Ranges you want to grant public access to the EKS Cluster. | `list(string)` | `[]` | no | +| <a name="input_eks_cluster_cloudwatch_log_group_prefix"></a> [eks\_cluster\_cloudwatch\_log\_group\_prefix](#input\_eks\_cluster\_cloudwatch\_log\_group\_prefix) | Prefix to be used for the EKS cluster CloudWatch log group. | `string` | `"/aws/eks/unreal-cloud-ddc/cluster"` | no | +| <a name="input_kubernetes_version"></a> [kubernetes\_version](#input\_kubernetes\_version) | Kubernetes version to be used by the EKS cluster. | `string` | `"1.30"` | no | +| <a name="input_name"></a> [name](#input\_name) | Unreal Cloud DDC Workload Name | `string` | `"unreal-cloud-ddc"` | no | +| <a name="input_nvme_managed_node_desired_size"></a> [nvme\_managed\_node\_desired\_size](#input\_nvme\_managed\_node\_desired\_size) | Desired number of nvme managed node group instances | `number` | `2` | no | +| <a name="input_nvme_managed_node_instance_type"></a> [nvme\_managed\_node\_instance\_type](#input\_nvme\_managed\_node\_instance\_type) | Nvme managed node group instance type | `string` | `"i3en.xlarge"` | no | +| <a name="input_nvme_managed_node_max_size"></a> [nvme\_managed\_node\_max\_size](#input\_nvme\_managed\_node\_max\_size) | Max number of nvme managed node group instances | `number` | `2` | no | +| <a name="input_private_subnets"></a> [private\_subnets](#input\_private\_subnets) | Private subnets you want scylla and the worker nodes to be installed into. | `list(string)` | `[]` | no | +| <a name="input_scylla_ami_name"></a> [scylla\_ami\_name](#input\_scylla\_ami\_name) | Name of the Scylla AMI to be used to get the AMI ID | `string` | `"ScyllaDB 6.0.1"` | no | +| <a name="input_scylla_architecture"></a> [scylla\_architecture](#input\_scylla\_architecture) | The chip architecture to use when finding the scylla image. Valid | `string` | `"x86_64"` | no | +| <a name="input_scylla_db_storage"></a> [scylla\_db\_storage](#input\_scylla\_db\_storage) | Size of gp3 ebs volumes attached to Scylla DBs | `number` | `100` | no | +| <a name="input_scylla_db_throughput"></a> [scylla\_db\_throughput](#input\_scylla\_db\_throughput) | Throughput of gp3 ebs volumes attached to Scylla DBs | `number` | `200` | no | +| <a name="input_scylla_instance_type"></a> [scylla\_instance\_type](#input\_scylla\_instance\_type) | The type and size of the Scylla instance. | `string` | `"i4i.2xlarge"` | no | +| <a name="input_scylla_private_subnets"></a> [scylla\_private\_subnets](#input\_scylla\_private\_subnets) | The subnets you want Scylla to be installed into. Can repeat subnet ids to install into the same subnet/az. This will also determine how many Scylla instances are deployed. | `list(string)` | `[]` | no | +| <a name="input_system_managed_node_desired_size"></a> [system\_managed\_node\_desired\_size](#input\_system\_managed\_node\_desired\_size) | Desired number of monitoring managed node group instances. | `number` | `1` | no | +| <a name="input_system_managed_node_instance_type"></a> [system\_managed\_node\_instance\_type](#input\_system\_managed\_node\_instance\_type) | Monitoring managed node group instance type. | `string` | `"m5.large"` | no | +| <a name="input_system_managed_node_max_size"></a> [system\_managed\_node\_max\_size](#input\_system\_managed\_node\_max\_size) | Max number of monitoring managed node group instances. | `number` | `2` | no | +| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | String for VPC ID | `string` | n/a | yes | +| <a name="input_worker_managed_node_desired_size"></a> [worker\_managed\_node\_desired\_size](#input\_worker\_managed\_node\_desired\_size) | Desired number of worker managed node group instances. | `number` | `1` | no | +| <a name="input_worker_managed_node_instance_type"></a> [worker\_managed\_node\_instance\_type](#input\_worker\_managed\_node\_instance\_type) | Worker managed node group instance type. | `string` | `"c5.xlarge"` | no | +| <a name="input_worker_managed_node_max_size"></a> [worker\_managed\_node\_max\_size](#input\_worker\_managed\_node\_max\_size) | Max number of worker managed node group instances. | `number` | `1` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| <a name="output_cluster_arn"></a> [cluster\_arn](#output\_cluster\_arn) | n/a | +| <a name="output_cluster_certificate_authority_data"></a> [cluster\_certificate\_authority\_data](#output\_cluster\_certificate\_authority\_data) | n/a | +| <a name="output_cluster_endpoint"></a> [cluster\_endpoint](#output\_cluster\_endpoint) | n/a | +| <a name="output_cluster_name"></a> [cluster\_name](#output\_cluster\_name) | n/a | +| <a name="output_oidc_provider_arn"></a> [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | n/a | +| <a name="output_peer_security_group"></a> [peer\_security\_group](#output\_peer\_security\_group) | n/a | +| <a name="output_s3_bucket_id"></a> [s3\_bucket\_id](#output\_s3\_bucket\_id) | n/a | +| <a name="output_scylla_ips"></a> [scylla\_ips](#output\_scylla\_ips) | n/a | +<!-- END_TF_DOCS --> diff --git a/modules/unreal/unreal-cloud-ddc-infra/data.tf b/modules/unreal/unreal-cloud-ddc-infra/data.tf new file mode 100644 index 00000000..7571c479 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-infra/data.tf @@ -0,0 +1,12 @@ +data "aws_ami" "scylla_ami" { + most_recent = true + owners = ["797456418907", "158855661827"] + filter { + name = "name" + values = [var.scylla_ami_name] + } + filter { + name = "architecture" + values = [var.scylla_architecture] + } +} diff --git a/modules/unreal/unreal-cloud-ddc-infra/eks.tf b/modules/unreal/unreal-cloud-ddc-infra/eks.tf new file mode 100644 index 00000000..b876a233 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-infra/eks.tf @@ -0,0 +1,238 @@ +################################################################################ +# EKS Cluster +################################################################################ + +resource "aws_eks_cluster" "unreal_cloud_ddc_eks_cluster" { + #checkov:skip=CKV_AWS_39:This needs to be open to configure the eks cluster. + #checkov:skip=CKV_AWS_58:Secrets encryptiom will be enabled in a future update + #checkov:skip=CKV_AWS_38:IP restriction set in module variables + name = var.name + role_arn = aws_iam_role.eks_cluster_role.arn + version = var.kubernetes_version + enabled_cluster_log_types = ["api", "audit", "authenticator", "controllerManager", "scheduler"] + + + + access_config { + authentication_mode = "API_AND_CONFIG_MAP" + bootstrap_cluster_creator_admin_permissions = true + } + + vpc_config { + subnet_ids = var.private_subnets + endpoint_private_access = true + endpoint_public_access = true + public_access_cidrs = var.eks_cluster_access_cidr + security_group_ids = [ + aws_security_group.system_security_group.id, + aws_security_group.worker_security_group.id, + aws_security_group.nvme_security_group.id + ] + } +} + +resource "aws_cloudwatch_log_group" "unreal_cluster_cloudwatch" { + #checkov:skip=CKV_AWS_158:Ensure that CloudWatch Log Group is encrypted by KMS + name_prefix = var.eks_cluster_cloudwatch_log_group_prefix + retention_in_days = 365 +} + +data "aws_ssm_parameter" "eks_ami_latest_release" { + name = "/aws/service/eks/optimized-ami/${aws_eks_cluster.unreal_cloud_ddc_eks_cluster.version}/amazon-linux-2/recommended/release_version" +} + +################################################################################ +# Worker Node Group +################################################################################ +resource "aws_eks_node_group" "worker_node_group" { + cluster_name = aws_eks_cluster.unreal_cloud_ddc_eks_cluster.name + node_group_name = "unreal-cloud-ddc-worker-ng" + version = aws_eks_cluster.unreal_cloud_ddc_eks_cluster.version + release_version = nonsensitive(data.aws_ssm_parameter.eks_ami_latest_release.value) + node_role_arn = aws_iam_role.worker_node_group_role.arn + subnet_ids = var.private_subnets + + labels = { + "unreal-cloud-ddc/node-type" = "worker" + } + + taint { + key = "role" + value = "unreal-cloud-ddc" + effect = "NO_SCHEDULE" + } + + scaling_config { + desired_size = var.worker_managed_node_desired_size + max_size = var.worker_managed_node_max_size + min_size = 0 + } + launch_template { + id = aws_launch_template.worker_launch_template.id + version = aws_launch_template.worker_launch_template.latest_version + } + tags = { + Name = "unreal-cloud-ddc-worker-instance" + } +} + +resource "aws_launch_template" "worker_launch_template" { + name_prefix = "unreal-ddc-worker-launch-template" + instance_type = var.worker_managed_node_instance_type + vpc_security_group_ids = [ + aws_security_group.worker_security_group.id, + aws_eks_cluster.unreal_cloud_ddc_eks_cluster.vpc_config[0].cluster_security_group_id, + aws_security_group.scylla_security_group.id + ] + + metadata_options { + http_endpoint = "enabled" + http_tokens = "required" + http_put_response_hop_limit = 1 + instance_metadata_tags = "enabled" + } + + monitoring { + enabled = true + } + + tag_specifications { + resource_type = "instance" + tags = { + Name = "unreal-ddc-worker-instance" + } + } +} + +################################################################################ +# NVME Node Group +################################################################################ +resource "aws_eks_node_group" "nvme_node_group" { + cluster_name = aws_eks_cluster.unreal_cloud_ddc_eks_cluster.name + node_group_name = "unreal-cloud-ddc-nvme-ng" + version = aws_eks_cluster.unreal_cloud_ddc_eks_cluster.version + release_version = nonsensitive(data.aws_ssm_parameter.eks_ami_latest_release.value) + node_role_arn = aws_iam_role.nvme_node_group_role.arn + subnet_ids = var.private_subnets + + labels = { + "unreal-cloud-ddc/node-type" = "nvme" + } + + taint { + key = "role" + value = "unreal-cloud-ddc" + effect = "NO_SCHEDULE" + } + + scaling_config { + desired_size = var.nvme_managed_node_desired_size + max_size = var.nvme_managed_node_max_size + min_size = 1 + } + + launch_template { + id = aws_launch_template.nvme_launch_template.id + version = aws_launch_template.nvme_launch_template.latest_version + } + +} + +resource "aws_launch_template" "nvme_launch_template" { + name_prefix = "unreal-ddc-nvme-launch-template" + instance_type = var.nvme_managed_node_instance_type + user_data = base64encode(local.nvme-pre-bootstrap-userdata) + vpc_security_group_ids = [ + aws_security_group.nvme_security_group.id, + aws_eks_cluster.unreal_cloud_ddc_eks_cluster.vpc_config[0].cluster_security_group_id, + aws_security_group.scylla_security_group.id + ] + + metadata_options { + http_endpoint = "enabled" + http_tokens = "required" + http_put_response_hop_limit = 1 + instance_metadata_tags = "enabled" + } + + monitoring { + enabled = true + } + + tag_specifications { + resource_type = "instance" + tags = { + Name = "unreal-ddc-nvme-instance" + } + } +} + +################################################################################ +# System Node Group +################################################################################ +resource "aws_eks_node_group" "system_node_group" { + cluster_name = aws_eks_cluster.unreal_cloud_ddc_eks_cluster.name + node_group_name = "unreal-cloud-ddc-monitoring-ng" + version = aws_eks_cluster.unreal_cloud_ddc_eks_cluster.version + release_version = nonsensitive(data.aws_ssm_parameter.eks_ami_latest_release.value) + node_role_arn = aws_iam_role.system_node_group_role.arn + subnet_ids = var.private_subnets + labels = { + "pool" = "system-pool" + } + + launch_template { + id = aws_launch_template.system_launch_template.id + version = aws_launch_template.system_launch_template.latest_version + } + + scaling_config { + desired_size = var.system_managed_node_desired_size + max_size = var.system_managed_node_max_size + min_size = 1 + } + tags = { + Name = "unreal-cloud-ddc-system-instance" + } +} + +resource "aws_launch_template" "system_launch_template" { + #checkov:skip=CKV_AWS_341:Required for the load balancer controller + name_prefix = "unreal-ddc-system-launch-template" + instance_type = var.system_managed_node_instance_type + + metadata_options { + http_endpoint = "enabled" + http_tokens = "required" + http_put_response_hop_limit = 2 + instance_metadata_tags = "enabled" + } + + vpc_security_group_ids = [ + aws_security_group.system_security_group.id, + aws_eks_cluster.unreal_cloud_ddc_eks_cluster.vpc_config[0].cluster_security_group_id + ] + + monitoring { + enabled = true + } + + tag_specifications { + resource_type = "instance" + tags = { + Name = "unreal-ddc-system-instance" + } + } +} +################################################################################ +# EKS Cluster Open ID Connect Provider +################################################################################ +data "tls_certificate" "eks_tls_certificate" { + url = aws_eks_cluster.unreal_cloud_ddc_eks_cluster.identity[0].oidc[0].issuer +} + +resource "aws_iam_openid_connect_provider" "unreal_cloud_ddc_oidc_provider" { + client_id_list = ["sts.amazonaws.com"] + thumbprint_list = [data.tls_certificate.eks_tls_certificate.certificates[0].sha1_fingerprint] + url = data.tls_certificate.eks_tls_certificate.url +} diff --git a/modules/unreal/unreal-cloud-ddc-infra/iam.tf b/modules/unreal/unreal-cloud-ddc-infra/iam.tf new file mode 100644 index 00000000..ad088ac4 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-infra/iam.tf @@ -0,0 +1,138 @@ +################################################################################ +# EKS Node IAM Roles +################################################################################ + +################################################################################ +# System Role +################################################################################ +resource "aws_iam_role" "system_node_group_role" { + name_prefix = "system-node-group-role-" + + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "ec2.amazonaws.com" + } + }] + Version = "2012-10-17" + }) +} + +resource "aws_iam_role_policy_attachments_exclusive" "system_policy_attachement" { + role_name = aws_iam_role.system_node_group_role.name + policy_arns = [ + "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy", + "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy", + "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", + "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" + ] +} + +################################################################################ +# NVME Role +################################################################################ +resource "aws_iam_role" "nvme_node_group_role" { + name_prefix = "nvme-node-group-role-" + + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "ec2.amazonaws.com" + } + }] + Version = "2012-10-17" + }) +} + +resource "aws_iam_role_policy_attachments_exclusive" "nvme_policy_attachement" { + role_name = aws_iam_role.nvme_node_group_role.name + policy_arns = [ + "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy", + "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy", + "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", + "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" + ] +} + +################################################################################ +# Worker Node Role +################################################################################ +resource "aws_iam_role" "worker_node_group_role" { + name_prefix = "unreal-cloud-ddc-eks-node-group-role-" + + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "ec2.amazonaws.com" + } + }] + Version = "2012-10-17" + }) +} + +resource "aws_iam_role_policy_attachments_exclusive" "worker_policy_attachement" { + role_name = aws_iam_role.worker_node_group_role.name + policy_arns = [ + "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy", + "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy", + "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", + "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" + ] +} +################################################################################ +# EKS Role +################################################################################ +resource "aws_iam_role" "eks_cluster_role" { + name_prefix = "unreal-cloud-ddc-eks-cluster-role-" + + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "eks.amazonaws.com" + } + }] + Version = "2012-10-17" + }) +} + +resource "aws_iam_role_policy_attachments_exclusive" "eks_cluster_policy_attachement" { + role_name = aws_iam_role.eks_cluster_role.name + policy_arns = [ + "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy" + ] +} + +################################################################################ +# Scylla Role +################################################################################ +resource "aws_iam_role" "scylla_role" { + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Sid = "ScyllaDbRole" + Principal = { + Service = "ec2.amazonaws.com" + } + }, + ] + }) + name_prefix = "scylla-db-" +} + +resource "aws_iam_role_policy_attachments_exclusive" "scylla_policy_attachement" { + role_name = aws_iam_role.scylla_role.name + policy_arns = [ + "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" + ] +} diff --git a/modules/unreal/unreal-cloud-ddc-infra/locals.tf b/modules/unreal/unreal-cloud-ddc-infra/locals.tf new file mode 100644 index 00000000..8c6f4574 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-infra/locals.tf @@ -0,0 +1,40 @@ + +locals { + sg_rules_all = [ + { port : 7000, description : "ScyllaDB Inter-node communication (RPC)", protocol : "tcp" }, + { port : 7001, description : "ScyllaDB SSL inter-node communication (RPC)", protocol : "tcp" }, + { port : 7199, description : "ScyllaDB JMX management", protocol : "tcp" }, + { port : 9042, description : "ScyllaDB CQL (native_transport_port)", protocol : "tcp" }, + { port : 9100, description : "ScyllaDB node_exporter (Optionally)", protocol : "tcp" }, + { port : 9142, description : "ScyllaDB SSL CQL (secure client to node)", protocol : "tcp" }, + { port : 9160, description : "Scylla client port (Thrift)", protocol : "tcp" }, + { port : 9180, description : "ScyllaDB Prometheus API", protocol : "tcp" }, + { port : 10000, description : "ScyllaDB REST API", protocol : "tcp" }, + { port : 19042, description : "Native shard-aware transport port", protocol : "tcp" }, + { port : 19142, description : "Native shard-aware transport port (ssl)", protocol : "tcp" } + ] + scylla_variables = { + scylla-cluster-name = var.name + } + scylla_user_data = jsonencode( + { + "scylla_yaml" : { + "cluster_name" : local.scylla_variables.scylla-cluster-name + } + "start_scylla_on_first_boot" : false + } + ) + nvme-pre-bootstrap-userdata = <<EOF +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="//" + +--// +Content-Type: text/x-shellscript; charset="us-ascii" + +#!/bin/bash +sudo mkfs.ext4 -E nodiscard /dev/nvme1n1 +sudo mkdir /data +sudo mount /dev/nvme1n1 /data +--//--\ +EOF +} diff --git a/modules/unreal/unreal-cloud-ddc-infra/outputs.tf b/modules/unreal/unreal-cloud-ddc-infra/outputs.tf new file mode 100644 index 00000000..976d7e20 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-infra/outputs.tf @@ -0,0 +1,31 @@ +output "cluster_name" { + value = aws_eks_cluster.unreal_cloud_ddc_eks_cluster.name +} + +output "cluster_endpoint" { + value = aws_eks_cluster.unreal_cloud_ddc_eks_cluster.endpoint +} + +output "cluster_arn" { + value = aws_eks_cluster.unreal_cloud_ddc_eks_cluster.arn +} + +output "s3_bucket_id" { + value = aws_s3_bucket.unreal_ddc_s3_bucket.id +} + +output "oidc_provider_arn" { + value = aws_iam_openid_connect_provider.unreal_cloud_ddc_oidc_provider.arn +} + +output "cluster_certificate_authority_data" { + value = aws_eks_cluster.unreal_cloud_ddc_eks_cluster.certificate_authority[0].data +} + +output "peer_security_group" { + value = aws_security_group.scylla_security_group +} + +output "scylla_ips" { + value = tolist(aws_instance.scylla_ec2_instance[*].private_ip) +} diff --git a/modules/unreal/unreal-cloud-ddc-infra/s3.tf b/modules/unreal/unreal-cloud-ddc-infra/s3.tf new file mode 100644 index 00000000..53f78ac4 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-infra/s3.tf @@ -0,0 +1,33 @@ +################################################################################ +# S3 +################################################################################ +resource "aws_s3_bucket" "unreal_ddc_s3_bucket" { + #checkov:skip=CKV_AWS_21:Ensure all data stored in the S3 bucket have versioning enabled + #checkov:skip=CKV2_AWS_61:Ensure that an S3 bucket has a lifecycle configuration + #checkov:skip=CKV2_AWS_62:This bucket doesnt have any triggers needed as its only an object store + #checkov:skip=CKV_AWS_144:This bucket hosts ephemeral recreatable assets + #checkov:skip=CKV_AWS_18:Logging bucket cna be configured by customer + bucket_prefix = "${var.name}-s3-bucket" + force_destroy = true +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "unreal-s3-bucket" { + #checkov:skip=CKV2_AWS_67:SSE encryption with default kms key is enabled + bucket = aws_s3_bucket.unreal_ddc_s3_bucket.id + + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = "aws/s3" + sse_algorithm = "aws:kms" + } + } +} + +resource "aws_s3_bucket_public_access_block" "unreal_ddc_s3_acls" { + bucket = aws_s3_bucket.unreal_ddc_s3_bucket.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} diff --git a/modules/unreal/unreal-cloud-ddc-infra/scylla.tf b/modules/unreal/unreal-cloud-ddc-infra/scylla.tf new file mode 100644 index 00000000..d0d3a186 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-infra/scylla.tf @@ -0,0 +1,44 @@ +################################################################################ +# Scylla Instance Profile +################################################################################ + +resource "aws_iam_instance_profile" "scylla_instance_profile" { + name = "scylladb_instance_profile" + role = aws_iam_role.scylla_role.name +} +################################################################################ +# Scylla Instances +################################################################################ +resource "aws_instance" "scylla_ec2_instance" { + count = length(var.scylla_private_subnets) + + ami = data.aws_ami.scylla_ami.id + instance_type = var.scylla_instance_type + vpc_security_group_ids = [aws_security_group.scylla_security_group.id] + monitoring = true + + subnet_id = element(var.private_subnets, count.index) + + user_data = local.scylla_user_data + user_data_replace_on_change = true + ebs_optimized = true + + iam_instance_profile = aws_iam_instance_profile.scylla_instance_profile.name + + root_block_device { + encrypted = true + volume_type = "gp3" + throughput = var.scylla_db_throughput + volume_size = var.scylla_db_storage + } + + metadata_options { + http_endpoint = "enabled" + http_put_response_hop_limit = 1 + http_tokens = "required" + } + + tags = { + Name = "${var.name}-scylla-db" + } +} diff --git a/modules/unreal/unreal-cloud-ddc-infra/sg.tf b/modules/unreal/unreal-cloud-ddc-infra/sg.tf new file mode 100644 index 00000000..e9e376c7 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-infra/sg.tf @@ -0,0 +1,105 @@ +################################################################################ +# Scylla SG +################################################################################ +resource "aws_security_group" "scylla_security_group" { + name = "${var.name}-scylla-sg" + description = "Security group for ScyllaDB" + vpc_id = var.vpc_id + + tags = { + Name = "unreal-cloud-ddc-scylla-sg" + } +} +################################################################################ +# NVME Security Group +################################################################################ +resource "aws_security_group" "nvme_security_group" { + name = "${var.name}-nvme-sg" + description = "Security group for nvme node group" + vpc_id = var.vpc_id + + tags = { + Name = "unreal-cloud-ddc-nvme-sg" + } +} + +resource "aws_vpc_security_group_egress_rule" "nvme_egress_sg_rules" { + security_group_id = aws_security_group.nvme_security_group.id + description = "Egress All" + ip_protocol = "-1" + cidr_ipv4 = "0.0.0.0/0" +} +################################################################################ +# Worker Security Group +################################################################################ +resource "aws_security_group" "worker_security_group" { + name = "${var.name}-worker-sg" + description = "Security group for nvme node group" + vpc_id = var.vpc_id + + tags = { + Name = "unreal-cloud-ddc-worker-sg" + } +} + +resource "aws_vpc_security_group_egress_rule" "worker_egress_sg_rules" { + security_group_id = aws_security_group.worker_security_group.id + description = "Egress All" + ip_protocol = "-1" + cidr_ipv4 = "0.0.0.0/0" +} + + +################################################################################ +# SSM Egress Rules for Scylla SG +################################################################################ +resource "aws_vpc_security_group_egress_rule" "ssm_egress_sg_rules" { + security_group_id = aws_security_group.scylla_security_group.id + description = "Egress All" + ip_protocol = "-1" + cidr_ipv4 = "0.0.0.0/0" +} + + + +################################################################################ +# Scylla Security Group to Self Rules +################################################################################ +resource "aws_vpc_security_group_ingress_rule" "self_ingress_sg_rules" { + for_each = { for sg_rule in local.sg_rules_all : sg_rule.port => sg_rule } + security_group_id = aws_security_group.scylla_security_group.id + from_port = each.value.port + description = each.value.description + ip_protocol = each.value.protocol + referenced_security_group_id = aws_security_group.scylla_security_group.id + to_port = each.value.port +} + +resource "aws_vpc_security_group_egress_rule" "self_scylla_egress_sg_rules" { + security_group_id = aws_security_group.scylla_security_group.id + from_port = 0 + ip_protocol = "tcp" + referenced_security_group_id = aws_security_group.scylla_security_group.id + to_port = 0 + description = "Self SG Egress" +} + +################################################################################ +# System Security Group +################################################################################ +resource "aws_security_group" "system_security_group" { + name = "${var.name}-system-sg" + description = "Security group for system node group" + vpc_id = var.vpc_id + + tags = { + Name = "unreal-cloud-ddc-system-sg" + } +} + +resource "aws_vpc_security_group_egress_rule" "system_egress_sg_rules" { + security_group_id = aws_security_group.system_security_group.id + description = "Egress All" + ip_protocol = "-1" + cidr_ipv4 = "0.0.0.0/0" +} diff --git a/modules/unreal/unreal-cloud-ddc-infra/ssm.tf b/modules/unreal/unreal-cloud-ddc-infra/ssm.tf new file mode 100644 index 00000000..09d52fa5 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-infra/ssm.tf @@ -0,0 +1,38 @@ +################################################################################ +# SSM +################################################################################ + +resource "aws_ssm_document" "config_scylla" { + name = "${var.name}-scylla-run-command" + document_type = "Command" + document_format = "YAML" + + content = yamlencode({ + "schemaVersion" : "2.2", + "description" : "Config Scylla", + "mainSteps" : [ + { + "action" : "aws:runShellScript", + "name" : "ConfigScylla", + "inputs" : { + "runCommand" : [ + "sudo apt-get update && sudo apt-get -y upgrade", + "sudo sed -i -r 's/- seeds: ([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})/- seeds: ${aws_instance.scylla_ec2_instance[0].private_ip}/g' /etc/scylla/scylla.yaml", + "echo \"Config of /etc/scylla/scylla.yaml Done\"", + "sudo systemctl start scylla-server" + ] + } + } + ] + } + ) +} + +resource "aws_ssm_association" "scylla_config_association" { + name = aws_ssm_document.config_scylla.name + + targets { + key = "tag:Name" + values = ["${var.name}-scylla-db"] + } +} diff --git a/modules/unreal/unreal-cloud-ddc-infra/variables.tf b/modules/unreal/unreal-cloud-ddc-infra/variables.tf new file mode 100644 index 00000000..f385cecc --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-infra/variables.tf @@ -0,0 +1,138 @@ +variable "name" { + description = "Unreal Cloud DDC Workload Name" + type = string + default = "unreal-cloud-ddc" +} + +variable "vpc_id" { + description = "String for VPC ID" + type = string +} + +variable "private_subnets" { + type = list(string) + default = [] + description = "Private subnets you want scylla and the worker nodes to be installed into." +} + +variable "scylla_ami_name" { + type = string + default = "ScyllaDB 6.0.1" + description = "Name of the Scylla AMI to be used to get the AMI ID" + nullable = false +} + +variable "scylla_instance_type" { + type = string + default = "i4i.2xlarge" + description = "The type and size of the Scylla instance." + nullable = false +} + +variable "scylla_architecture" { + type = string + default = "x86_64" + description = "The chip architecture to use when finding the scylla image. Valid" + nullable = false +} + +variable "scylla_private_subnets" { + type = list(string) + default = [] + description = "The subnets you want Scylla to be installed into. Can repeat subnet ids to install into the same subnet/az. This will also determine how many Scylla instances are deployed." + nullable = false +} + +variable "scylla_db_storage" { + type = number + default = 100 + description = "Size of gp3 ebs volumes attached to Scylla DBs" + nullable = false +} + +variable "scylla_db_throughput" { + type = number + default = 200 + description = "Throughput of gp3 ebs volumes attached to Scylla DBs" + nullable = false +} + +variable "nvme_managed_node_instance_type" { + type = string + default = "i3en.xlarge" + description = "Nvme managed node group instance type" + nullable = false +} +variable "nvme_managed_node_desired_size" { + type = number + default = 2 + description = "Desired number of nvme managed node group instances" + nullable = false +} + +variable "nvme_managed_node_max_size" { + type = number + default = 2 + description = "Max number of nvme managed node group instances" + nullable = false +} + +variable "worker_managed_node_instance_type" { + type = string + default = "c5.xlarge" + description = "Worker managed node group instance type." + nullable = false +} + +variable "worker_managed_node_desired_size" { + type = number + default = 1 + description = "Desired number of worker managed node group instances." + nullable = false +} +variable "worker_managed_node_max_size" { + type = number + default = 1 + description = "Max number of worker managed node group instances." + nullable = false +} + +variable "system_managed_node_instance_type" { + type = string + default = "m5.large" + description = "Monitoring managed node group instance type." + nullable = false +} + +variable "system_managed_node_desired_size" { + type = number + default = 1 + description = "Desired number of monitoring managed node group instances." + nullable = false +} + +variable "system_managed_node_max_size" { + type = number + default = 2 + description = "Max number of monitoring managed node group instances." + nullable = false +} + +variable "eks_cluster_access_cidr" { + type = list(string) + description = "List of the CIDR Ranges you want to grant public access to the EKS Cluster." + default = [] +} + +variable "kubernetes_version" { + type = string + default = "1.30" + description = "Kubernetes version to be used by the EKS cluster." + nullable = false +} + +variable "eks_cluster_cloudwatch_log_group_prefix" { + type = string + default = "/aws/eks/unreal-cloud-ddc/cluster" + description = "Prefix to be used for the EKS cluster CloudWatch log group." +} diff --git a/modules/unreal/unreal-cloud-ddc-infra/versions.tf b/modules/unreal/unreal-cloud-ddc-infra/versions.tf new file mode 100644 index 00000000..27716b16 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-infra/versions.tf @@ -0,0 +1,13 @@ +terraform { + required_version = ">= 1.5" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">=5.73.0" + } + tls = { + source = "hashicorp/tls" + version = ">= 4.0.6" + } + } +} diff --git a/modules/unreal/unreal-cloud-ddc-intra-cluster/README.md b/modules/unreal/unreal-cloud-ddc-intra-cluster/README.md new file mode 100644 index 00000000..ec483f40 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-intra-cluster/README.md @@ -0,0 +1,117 @@ +<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK --> +## Requirements + +| Name | Version | +|------|---------| +| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5 | +| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.38 | +| <a name="requirement_helm"></a> [helm](#requirement\_helm) | >=2.9.0 | +| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >=2.24.0 | + +## Providers + +| Name | Version | +|------|---------| +| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.38 | +| <a name="provider_helm"></a> [helm](#provider\_helm) | >=2.9.0 | +| <a name="provider_kubernetes"></a> [kubernetes](#provider\_kubernetes) | >=2.24.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| <a name="module_aws_load_balancer_controller"></a> [aws\_load\_balancer\_controller](#module\_aws\_load\_balancer\_controller) | git::https://github.com/aws-ia/terraform-aws-eks-blueprints-addon.git | 327207ad17f3069fdd0a76c14d3e07936eff4582 | +| <a name="module_cert_manager"></a> [cert\_manager](#module\_cert\_manager) | git::https://github.com/aws-ia/terraform-aws-eks-blueprints-addon.git | 327207ad17f3069fdd0a76c14d3e07936eff4582 | +| <a name="module_ebs_csi_irsa_role"></a> [ebs\_csi\_irsa\_role](#module\_ebs\_csi\_irsa\_role) | git::https://github.com/terraform-aws-modules/terraform-aws-iam.git//modules/iam-role-for-service-accounts-eks | ccb4f252cc340d85fd70a8a1fb1cae496a698c1f | +| <a name="module_eks_blueprints_all_other_addons"></a> [eks\_blueprints\_all\_other\_addons](#module\_eks\_blueprints\_all\_other\_addons) | git::https://github.com/aws-ia/terraform-aws-eks-blueprints-addons.git | a9963f4a0e168f73adb033be594ac35868696a91 | +| <a name="module_eks_service_account_iam_role"></a> [eks\_service\_account\_iam\_role](#module\_eks\_service\_account\_iam\_role) | git::https://github.com/terraform-aws-modules/terraform-aws-iam.git//modules/iam-assumable-role-with-oidc | ccb4f252cc340d85fd70a8a1fb1cae496a698c1f | +| <a name="module_s3_iam_policy"></a> [s3\_iam\_policy](#module\_s3\_iam\_policy) | git::https://github.com/terraform-aws-modules/terraform-aws-iam.git//modules/iam-policy | ccb4f252cc340d85fd70a8a1fb1cae496a698c1f | + +## Resources + +| Name | Type | +|------|------| +| [helm_release.unreal_cloud_ddc](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | +| [kubernetes_namespace.unreal_cloud_ddc](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource | +| [kubernetes_service_account.unreal_cloud_ddc_service_account](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service_account) | resource | +| [aws_eks_cluster.unreal_cloud_ddc_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/eks_cluster) | data source | +| [aws_iam_policy_document.aws_load_balancer_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.cert_manager](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | +| [aws_s3_bucket.unreal_cloud_ddc_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/s3_bucket) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| <a name="input_cert_manager_hosted_zone_arns"></a> [cert\_manager\_hosted\_zone\_arns](#input\_cert\_manager\_hosted\_zone\_arns) | List of ARNs to be passed to Certificate Manager Addon | `list(string)` | n/a | yes | +| <a name="input_cluster_name"></a> [cluster\_name](#input\_cluster\_name) | Name of the EKS Cluster | `string` | n/a | yes | +| <a name="input_external_secrets_secret_manager_arn_list"></a> [external\_secrets\_secret\_manager\_arn\_list](#input\_external\_secrets\_secret\_manager\_arn\_list) | List of ARNS for Secret Manager Secrets to use in Unreal Cloud DDC | `list(string)` | `[]` | no | +| <a name="input_oidc_provider_arn"></a> [oidc\_provider\_arn](#input\_oidc\_provider\_arn) | ARN of the OIDC Provider from EKS Cluster | `string` | n/a | yes | +| <a name="input_s3_bucket_id"></a> [s3\_bucket\_id](#input\_s3\_bucket\_id) | ID of the S3 Bucket for Unreal Cloud DDC to use | `string` | n/a | yes | +| <a name="input_unreal_cloud_ddc_helm_values"></a> [unreal\_cloud\_ddc\_helm\_values](#input\_unreal\_cloud\_ddc\_helm\_values) | List of YAML files for Unreal Cloud DDC | `list(string)` | `[]` | no | +| <a name="input_unreal_cloud_ddc_namespace"></a> [unreal\_cloud\_ddc\_namespace](#input\_unreal\_cloud\_ddc\_namespace) | Namespace for Unreal Cloud DDC | `string` | `"unreal-cloud-ddc"` | no | + +## Outputs + +No outputs. +<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK --> +<!-- BEGIN_TF_DOCS --> +## Requirements + +| Name | Version | +|------|---------| +| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5 | +| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >=5.73.0 | +| <a name="requirement_helm"></a> [helm](#requirement\_helm) | >=2.16.0 | +| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >=2.33.0 | + +## Providers + +| Name | Version | +|------|---------| +| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.77.0 | +| <a name="provider_helm"></a> [helm](#provider\_helm) | 2.16.1 | +| <a name="provider_kubernetes"></a> [kubernetes](#provider\_kubernetes) | 2.34.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| <a name="module_ebs_csi_irsa_role"></a> [ebs\_csi\_irsa\_role](#module\_ebs\_csi\_irsa\_role) | git::https://github.com/terraform-aws-modules/terraform-aws-iam.git//modules/iam-role-for-service-accounts-eks | ccb4f252cc340d85fd70a8a1fb1cae496a698c1f | +| <a name="module_eks_blueprints_all_other_addons"></a> [eks\_blueprints\_all\_other\_addons](#module\_eks\_blueprints\_all\_other\_addons) | git::https://github.com/aws-ia/terraform-aws-eks-blueprints-addons.git | a9963f4a0e168f73adb033be594ac35868696a91 | +| <a name="module_eks_service_account_iam_role"></a> [eks\_service\_account\_iam\_role](#module\_eks\_service\_account\_iam\_role) | git::https://github.com/terraform-aws-modules/terraform-aws-iam.git//modules/iam-role-for-service-accounts-eks | ccb4f252cc340d85fd70a8a1fb1cae496a698c1f | + +## Resources + +| Name | Type | +|------|------| +| [aws_ecr_pull_through_cache_rule.unreal_cloud_ddc_ecr_pull_through_cache_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_pull_through_cache_rule) | resource | +| [aws_iam_policy.s3_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.secrets_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [helm_release.unreal_cloud_ddc](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | +| [kubernetes_namespace.unreal_cloud_ddc](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource | +| [kubernetes_service_account.unreal_cloud_ddc_service_account](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service_account) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_eks_cluster.unreal_cloud_ddc_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/eks_cluster) | data source | +| [aws_iam_openid_connect_provider.oidc_provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_openid_connect_provider) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | +| [aws_s3_bucket.unreal_cloud_ddc_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/s3_bucket) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| <a name="input_cluster_name"></a> [cluster\_name](#input\_cluster\_name) | Name of the EKS Cluster | `string` | n/a | yes | +| <a name="input_cluster_oidc_provider_arn"></a> [cluster\_oidc\_provider\_arn](#input\_cluster\_oidc\_provider\_arn) | ARN of the OIDC Provider from EKS Cluster | `string` | n/a | yes | +| <a name="input_gchr_credentials_secret_manager_arn"></a> [gchr\_credentials\_secret\_manager\_arn](#input\_gchr\_credentials\_secret\_manager\_arn) | Arn for credentials stored in secret manager. Needs to be prefixed with 'ecr-pullthroughcache/' to be compatible with ECR pull through cache. | `string` | n/a | yes | +| <a name="input_oidc_credentials_secret_manager_arn"></a> [oidc\_credentials\_secret\_manager\_arn](#input\_oidc\_credentials\_secret\_manager\_arn) | Arn for oidc credentials stored in secret manager. | `string` | n/a | yes | +| <a name="input_s3_bucket_id"></a> [s3\_bucket\_id](#input\_s3\_bucket\_id) | ID of the S3 Bucket for Unreal Cloud DDC to use | `string` | n/a | yes | +| <a name="input_unreal_cloud_ddc_helm_values"></a> [unreal\_cloud\_ddc\_helm\_values](#input\_unreal\_cloud\_ddc\_helm\_values) | List of YAML files for Unreal Cloud DDC | `list(string)` | `[]` | no | +| <a name="input_unreal_cloud_ddc_namespace"></a> [unreal\_cloud\_ddc\_namespace](#input\_unreal\_cloud\_ddc\_namespace) | Namespace for Unreal Cloud DDC | `string` | `"unreal-cloud-ddc"` | no | +| <a name="input_unreal_cloud_ddc_version"></a> [unreal\_cloud\_ddc\_version](#input\_unreal\_cloud\_ddc\_version) | Version of the Unreal Cloud DDC Helm chart | `string` | `"1.2.0"` | no | + +## Outputs + +No outputs. +<!-- END_TF_DOCS --> diff --git a/modules/unreal/unreal-cloud-ddc-intra-cluster/data.tf b/modules/unreal/unreal-cloud-ddc-intra-cluster/data.tf new file mode 100644 index 00000000..9fa4c16f --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-intra-cluster/data.tf @@ -0,0 +1,14 @@ +data "aws_region" "current" {} +data "aws_caller_identity" "current" {} + +data "aws_eks_cluster" "unreal_cloud_ddc_cluster" { + name = var.cluster_name +} + +data "aws_s3_bucket" "unreal_cloud_ddc_bucket" { + bucket = var.s3_bucket_id +} + +data "aws_iam_openid_connect_provider" "oidc_provider" { + arn = var.cluster_oidc_provider_arn +} diff --git a/modules/unreal/unreal-cloud-ddc-intra-cluster/helm.tf b/modules/unreal/unreal-cloud-ddc-intra-cluster/helm.tf new file mode 100644 index 00000000..21ec048a --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-intra-cluster/helm.tf @@ -0,0 +1,80 @@ +module "eks_blueprints_all_other_addons" { + #checkov:skip=CKV_TF_1:Ensure Terraform module sources use a commit hash + #checkov:skip=CKV_AWS_109:Ensure IAM policies does not allow permissions management / resource exposure without constraints + #checkov:skip=CKV_AWS_111:Ensure IAM policies does not allow write access without constraints + #checkov:skip=CKV_AWS_356:Ensure no IAM policies documents allow "*" as a statement's resource for restrictable actions + source = "git::https://github.com/aws-ia/terraform-aws-eks-blueprints-addons.git?ref=a9963f4a0e168f73adb033be594ac35868696a91" + + eks_addons = { + coredns = { + most_recent = true + } + kube-proxy = { + most_recent = true + } + vpc-cni = { + most_recent = true + } + aws-ebs-csi-driver = { + most_recent = true + service_account_role_arn = module.ebs_csi_irsa_role.iam_role_arn + } + } + + + cluster_name = data.aws_eks_cluster.unreal_cloud_ddc_cluster.name + cluster_endpoint = data.aws_eks_cluster.unreal_cloud_ddc_cluster.endpoint + cluster_version = data.aws_eks_cluster.unreal_cloud_ddc_cluster.version + oidc_provider_arn = data.aws_iam_openid_connect_provider.oidc_provider.arn + + enable_aws_load_balancer_controller = true + enable_aws_cloudwatch_metrics = true + + tags = { + Environment = var.cluster_name + } +} + +resource "kubernetes_namespace" "unreal_cloud_ddc" { + depends_on = [module.eks_blueprints_all_other_addons] + metadata { + name = var.unreal_cloud_ddc_namespace + } +} + +resource "kubernetes_service_account" "unreal_cloud_ddc_service_account" { + depends_on = [kubernetes_namespace.unreal_cloud_ddc] + metadata { + name = "${var.unreal_cloud_ddc_namespace}-sa" + namespace = var.unreal_cloud_ddc_namespace + labels = { aws-usage : "application" } + annotations = { "eks.amazonaws.com/role-arn" : module.eks_service_account_iam_role.iam_role_arn } + } + automount_service_account_token = true +} + + + +################################################################################ +# Helm +################################################################################ +resource "aws_ecr_pull_through_cache_rule" "unreal_cloud_ddc_ecr_pull_through_cache_rule" { + ecr_repository_prefix = "github" + upstream_registry_url = "ghcr.io" + credential_arn = var.gchr_credentials_secret_manager_arn +} + +resource "helm_release" "unreal_cloud_ddc" { + name = "unreal-cloud-ddc" + chart = "unreal-cloud-ddc" + repository = "oci://${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/github/epicgames" + namespace = var.unreal_cloud_ddc_namespace + version = "${var.unreal_cloud_ddc_version}+helm" + depends_on = [ + kubernetes_service_account.unreal_cloud_ddc_service_account, + kubernetes_namespace.unreal_cloud_ddc, + aws_ecr_pull_through_cache_rule.unreal_cloud_ddc_ecr_pull_through_cache_rule + ] + + values = var.unreal_cloud_ddc_helm_values +} diff --git a/modules/unreal/unreal-cloud-ddc-intra-cluster/iam.tf b/modules/unreal/unreal-cloud-ddc-intra-cluster/iam.tf new file mode 100644 index 00000000..f4c3e915 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-intra-cluster/iam.tf @@ -0,0 +1,95 @@ +################################################################################ +# IAM Roles & Policies +################################################################################ + +module "eks_service_account_iam_role" { + #checkov:skip=CKV_AWS_111:Ensure IAM policies does not allow write access without constraints + #checkov:skip=CKV_AWS_356:Ensure no IAM policies documents allow "*" as a statement's resource for restrictable actions + source = "git::https://github.com/terraform-aws-modules/terraform-aws-iam.git//modules/iam-role-for-service-accounts-eks?ref=ccb4f252cc340d85fd70a8a1fb1cae496a698c1f" + depends_on = [data.aws_eks_cluster.unreal_cloud_ddc_cluster] + + create_role = true + role_name_prefix = "unreal-ddc-sa-role-" + + + tags = { + Role = "eks-unreal-cloud-ddc-role" + } + + role_policy_arns = { + policy_1 = aws_iam_policy.s3_iam_policy.arn, + policy_2 = aws_iam_policy.secrets_iam_policy.arn + } + + oidc_providers = { + ex = { + provider_arn = data.aws_iam_openid_connect_provider.oidc_provider.arn + namespace_service_accounts = ["${var.unreal_cloud_ddc_namespace}:${var.unreal_cloud_ddc_namespace}-sa"] + } + } +} + +module "ebs_csi_irsa_role" { + #checkov:skip=CKV_AWS_109:Ensure IAM policies does not allow permissions management / resource exposure without constraints + #checkov:skip=CKV_AWS_111:Ensure IAM policies does not allow write access without constraints + #checkov:skip=CKV_AWS_356:Ensure no IAM policies documents allow "*" as a statement's resource for restrictable actions + source = "git::https://github.com/terraform-aws-modules/terraform-aws-iam.git//modules/iam-role-for-service-accounts-eks?ref=ccb4f252cc340d85fd70a8a1fb1cae496a698c1f" + + role_name_prefix = "ebs-csi-role-" + attach_ebs_csi_policy = true + + oidc_providers = { + ex = { + provider_arn = data.aws_iam_openid_connect_provider.oidc_provider.arn + namespace_service_accounts = ["kube-system:ebs-csi-controller-sa"] + } + } +} + +resource "aws_iam_policy" "secrets_iam_policy" { + name_prefix = "unreal-ddc-secrets-policy-" + path = "/" + description = "Policy to grant access to oidc provider secrets" + + policy = jsonencode({ + "Version" : "2012-10-17", + "Statement" : [ + { + "Action" : [ + "secretsmanager:GetSecretValue", + ], + "Effect" : "Allow", + "Resource" : [ + var.oidc_credentials_secret_manager_arn + ] + } + ] + }) +} + +resource "aws_iam_policy" "s3_iam_policy" { + depends_on = [data.aws_s3_bucket.unreal_cloud_ddc_bucket] + + name_prefix = "unreal-ddc-s3-policy-" + path = "/" + description = "Policy to grant access to unreal cloud ddc bucket" + + policy = jsonencode({ + "Version" : "2012-10-17", + "Statement" : [ + { + "Action" : [ + "s3:PutObject", + "s3:GetObject", + "s3:DeleteObject", + "s3:List*", + ], + "Effect" : "Allow", + "Resource" : [ + data.aws_s3_bucket.unreal_cloud_ddc_bucket.arn, + "${data.aws_s3_bucket.unreal_cloud_ddc_bucket.arn}/*" + ] + } + ] + }) +} diff --git a/modules/unreal/unreal-cloud-ddc-intra-cluster/outputs.tf b/modules/unreal/unreal-cloud-ddc-intra-cluster/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/modules/unreal/unreal-cloud-ddc-intra-cluster/variables.tf b/modules/unreal/unreal-cloud-ddc-intra-cluster/variables.tf new file mode 100644 index 00000000..d2488089 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-intra-cluster/variables.tf @@ -0,0 +1,41 @@ +variable "cluster_name" { + type = string + description = "Name of the EKS Cluster" +} +variable "cluster_oidc_provider_arn" { + type = string + description = "ARN of the OIDC Provider from EKS Cluster" +} + +variable "s3_bucket_id" { + type = string + description = "ID of the S3 Bucket for Unreal Cloud DDC to use" +} + +variable "unreal_cloud_ddc_namespace" { + type = string + description = "Namespace for Unreal Cloud DDC" + default = "unreal-cloud-ddc" +} + +variable "unreal_cloud_ddc_helm_values" { + type = list(string) + description = "List of YAML files for Unreal Cloud DDC" + default = [] +} + +variable "gchr_credentials_secret_manager_arn" { + type = string + description = "Arn for credentials stored in secret manager. Needs to be prefixed with 'ecr-pullthroughcache/' to be compatible with ECR pull through cache." +} + +variable "oidc_credentials_secret_manager_arn" { + type = string + description = "Arn for oidc credentials stored in secret manager." +} + +variable "unreal_cloud_ddc_version" { + type = string + description = "Version of the Unreal Cloud DDC Helm chart" + default = "1.2.0" +} diff --git a/modules/unreal/unreal-cloud-ddc-intra-cluster/versions.tf b/modules/unreal/unreal-cloud-ddc-intra-cluster/versions.tf new file mode 100644 index 00000000..fd37f266 --- /dev/null +++ b/modules/unreal/unreal-cloud-ddc-intra-cluster/versions.tf @@ -0,0 +1,17 @@ +terraform { + required_version = ">= 1.5" + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = ">=2.33.0" + } + helm = { + source = "hashicorp/helm" + version = ">=2.16.0" + } + aws = { + source = "hashicorp/aws" + version = ">=5.73.0" + } + } +} diff --git a/samples/unreal-cloud-ddc-single-region/README.md b/samples/unreal-cloud-ddc-single-region/README.md new file mode 100644 index 00000000..10623d52 --- /dev/null +++ b/samples/unreal-cloud-ddc-single-region/README.md @@ -0,0 +1,102 @@ +To use this example you will need to deploy each module individually. +``` +terraform apply --target module.unreal_cloud_ddc_vpc +terraform apply --target module.unreal_cloud_ddc_infra +terraform apply --target module.unreal_cloud_ddc_intra_cluster +``` + +<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK --> +## Requirements + +| Name | Version | +|------|---------| +| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 | +| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.38 | +| <a name="requirement_helm"></a> [helm](#requirement\_helm) | >= 2.9.0 | +| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >= 2.24.0 | + +## Providers + +| Name | Version | +|------|---------| +| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.38 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| <a name="module_unreal_cloud_ddc_infra"></a> [unreal\_cloud\_ddc\_infra](#module\_unreal\_cloud\_ddc\_infra) | ../../modules/unreal/unreal-cloud-ddc-infra | n/a | +| <a name="module_unreal_cloud_ddc_intra_cluster"></a> [unreal\_cloud\_ddc\_intra\_cluster](#module\_unreal\_cloud\_ddc\_intra\_cluster) | ../../modules/unreal/unreal-cloud-ddc-intra-cluster | n/a | +| <a name="module_unreal_cloud_ddc_vpc"></a> [unreal\_cloud\_ddc\_vpc](#module\_unreal\_cloud\_ddc\_vpc) | git::https://github.com/terraform-aws-modules/terraform-aws-vpc.git | 25322b6b6be69db6cca7f167d7b0e5327156a595 | + +## Resources + +| Name | Type | +|------|------| +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| <a name="input_caller_ip"></a> [caller\_ip](#input\_caller\_ip) | IPs that will be allow listed to access cluster over internet | `list(string)` | `[]` | no | +| <a name="input_ghcr_password"></a> [ghcr\_password](#input\_ghcr\_password) | GHCR password | `string` | n/a | yes | +| <a name="input_ghcr_username"></a> [ghcr\_username](#input\_ghcr\_username) | GHCR username | `string` | n/a | yes | +| <a name="input_jwt_audience"></a> [jwt\_audience](#input\_jwt\_audience) | JWT Audience | `string` | n/a | yes | +| <a name="input_jwt_authority"></a> [jwt\_authority](#input\_jwt\_authority) | JWT Authority | `string` | n/a | yes | +| <a name="input_okta_auth_server_id"></a> [okta\_auth\_server\_id](#input\_okta\_auth\_server\_id) | Okta Auth Server ID | `string` | n/a | yes | +| <a name="input_okta_domain"></a> [okta\_domain](#input\_okta\_domain) | Okta Domain | `string` | n/a | yes | +| <a name="input_profile"></a> [profile](#input\_profile) | AWS Profile name | `string` | `"default"` | no | +| <a name="input_region"></a> [region](#input\_region) | AWS Region | `string` | `"us-west-2"` | no | + +## Outputs + +No outputs. +<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK --> +<!-- BEGIN_TF_DOCS --> +## Requirements + +| Name | Version | +|------|---------| +| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 | +| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.73.0 | +| <a name="requirement_helm"></a> [helm](#requirement\_helm) | >= 2.9.0 | +| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >= 2.24.0 | + +## Providers + +| Name | Version | +|------|---------| +| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.77.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| <a name="module_unreal_cloud_ddc_infra"></a> [unreal\_cloud\_ddc\_infra](#module\_unreal\_cloud\_ddc\_infra) | ../../modules/unreal/unreal-cloud-ddc-infra | n/a | +| <a name="module_unreal_cloud_ddc_intra_cluster"></a> [unreal\_cloud\_ddc\_intra\_cluster](#module\_unreal\_cloud\_ddc\_intra\_cluster) | ../../modules/unreal/unreal-cloud-ddc-intra-cluster | n/a | +| <a name="module_unreal_cloud_ddc_vpc"></a> [unreal\_cloud\_ddc\_vpc](#module\_unreal\_cloud\_ddc\_vpc) | ./vpc | n/a | + +## Resources + +| Name | Type | +|------|------| +| [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 | +| [aws_ecr_authorization_token.token](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecr_authorization_token) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | +| [aws_secretsmanager_secret.oidc_secrets](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/secretsmanager_secret) | data source | +| [aws_secretsmanager_secret_version.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/secretsmanager_secret_version) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| <a name="input_eks_cluster_ip_allow_list"></a> [eks\_cluster\_ip\_allow\_list](#input\_eks\_cluster\_ip\_allow\_list) | IPs that will be allow listed to access cluster over internet | `list(string)` | `[]` | no | +| <a name="input_github_credential_arn"></a> [github\_credential\_arn](#input\_github\_credential\_arn) | Github Credential ARN | `string` | n/a | yes | +| <a name="input_oidc_credential_arn"></a> [oidc\_credential\_arn](#input\_oidc\_credential\_arn) | OIDC Secrets Credential ARN | `string` | n/a | yes | + +## Outputs + +No outputs. +<!-- END_TF_DOCS --> diff --git a/samples/unreal-cloud-ddc-single-region/assets/unreal_cloud_ddc_base.yaml b/samples/unreal-cloud-ddc-single-region/assets/unreal_cloud_ddc_base.yaml new file mode 100644 index 00000000..8c6e8ee5 --- /dev/null +++ b/samples/unreal-cloud-ddc-single-region/assets/unreal_cloud_ddc_base.yaml @@ -0,0 +1,58 @@ +# This is the base settings of your deployment, most things should go into here except for anything that is unique to a single region +config: + Scylla: &scylla-connection-info + ConnectionString: Contact Points=${scylla_ips};Default Keyspace=jupiter; + # if you have a locally attached filesystem for caching (we recommend you do) then this configures it + #Filesystem: + # MaxSizeBytes: 800000000000 # 800 Gb - the amount of storage we can use on the storage + +# This enables a worker deployment for your scheduled tasks - we recommend running with this to keep the api more responsive +worker: + enabled: false + + # Any configuration specified in the api deployment that also applies to workers needs to be duplicated that is not part of the global scope + config: + Scylla: *scylla-connection-info + GC: + CleanOldRefRecords: false # this should be enabled in one region - it will delete old ref records no longer in use across the entire system. + CleanOldBlobs: true # this will delete old blobs that are no longer referenced by any ref - this runs in each region to cleanup that regions blob stores + +global: + #AWS specific configuration + cloudProvider: "AWS" + awsRegion: ${region} + awsRole: AssumeRoleWebIdentity # service accounts are IAM mapped + + auth: + enabled: true + defaultScheme: Bearer # this should match the name under schemes + schemes: + Bearer: + implementation: "Okta" + oktaDomain: ${okta_domain} # this will be given to you by your okta admin + oktaAuthorizationServerId: ${okta_auth_server_id} # this will be given to you by your okta admin + jwtAudience: ${jwt_audience} # the audience defined for the authorization server + jwtAuthority: ${jwt_authority} # the full path to your authorization server - is usually <domain>/oauth2/<auth-server> + + acls: + # This is an example of how to setup a claim to grant special privileges + # In this case we expect a group called app-ddc-storage-admin to indicate admins which are granted full access to everything + - claims: + - groups=app-ddc-storage-admin + actions: + - ReadObject + - WriteObject + - DeleteObject + - DeleteBucket + - DeleteNamespace + - AdminAction + + namespaces: + Policies: + unreal-cloud-ddc: + acls: + - actions: + - ReadObject + - WriteObject + claims: + - "*" diff --git a/samples/unreal-cloud-ddc-single-region/assets/unreal_cloud_ddc_region_values.yaml b/samples/unreal-cloud-ddc-single-region/assets/unreal_cloud_ddc_region_values.yaml new file mode 100644 index 00000000..ac552ded --- /dev/null +++ b/samples/unreal-cloud-ddc-single-region/assets/unreal_cloud_ddc_region_values.yaml @@ -0,0 +1,22 @@ +config: + Scylla: &scylla-connection-info + LocalKeyspaceReplicationStrategy: + class : "NetworkTopologyStrategy" + us-west-2 : 2 + LocalDatacenterName: ${region} + LocalKeyspaceSuffix: "ddc" + S3: &s3-connection-info + BucketName: ${bucket_name} + + +worker: + config: + GC: + CleanOldRefRecords: true + + Scylla: *scylla-connection-info + S3: *s3-connection-info + +global: + awsRegion: ${region} + siteName: ${region} diff --git a/samples/unreal-cloud-ddc-single-region/assets/unreal_cloud_ddc_values.yaml b/samples/unreal-cloud-ddc-single-region/assets/unreal_cloud_ddc_values.yaml new file mode 100644 index 00000000..504822e0 --- /dev/null +++ b/samples/unreal-cloud-ddc-single-region/assets/unreal_cloud_ddc_values.yaml @@ -0,0 +1,280 @@ +config: + HostSwaggerDocumentation: false + +replicaCount: 2 + +## Docker image configuration +image: + repository: "ghcr.io/epicgames/unreal-cloud-ddc" + pullPolicy: IfNotPresent + +tolerations: + - key: role + operator: Equal + value: unreal-cloud-ddc + effect: NoSchedule + +nodeSelector: + unreal-cloud-ddc/node-type: nvme + +serviceAccount: + create: false + name: unreal-cloud-ddc-sa + +persistence: + enabled: false +# volume: +# hostPath: +# path: /data +# type: Directory + + ## Persistent Volume Storage Class + ## If defined, storageClassName: <storageClass> + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + #storageClass: "gp2" + + + ## Persistent Volume Claim annotations + ## + annotations: {} + +## Service properties +## +service: + ## Service type + ## + type: LoadBalancer + portName: http + port: 80 + targetPort: nginx-http + extraPort: + - name: http2 + port: 8080 + targetPort: nginx-h2 + + + ## Specify the nodePort value for the LoadBalancer and NodePort service types. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + # nodePort: + + ## Provide any additional annotations which may be required. This can be used to + ## set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + annotations: + service.beta.kubernetes.io/aws-load-balancer-name: "unreal-cloud-ddc" + service.beta.kubernetes.io/aws-load-balancer-type: "external" + service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip" + service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing" + service.beta.kubernetes.io/aws-load-balancer-healthcheck-protocol: "HTTP" + service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "80" + service.beta.kubernetes.io/aws-load-balancer-healthcheck-path: "/health/live" + service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold: "2" + service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold: "2" + service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags: "application=unreal-cloud-ddc" + + ## loadBalancerIP for the PrestaShop Service (optional, cloud specific) + ## ref: http://kubernetes.io/docs/user-guide/services/#type-loadbalancer + ## + # loadBalancerIP: + +## Configure the ingress resource that allows you to access the pod +## +ingress: + ## Set to true to enable ingress record generation + ## + enabled: false + + ## Ingress Path type + ## + pathType: ImplementationSpecific + + ## Override API Version (automatically detected if not set) + ## + apiVersion: + + ## When the ingress is enabled, a host pointing to this will be created + ## + # hostname: hostname.example + + ## The Path to host the ingress under. You may need to set this to '/*' in order to use this + ## with ALB ingress controllers. + ## + path: /api + + ## Ingress annotations done as key:value pairs + ## + annotations: {} + + ## The list of additional hostnames to be covered with this ingress record. + ## Most likely the hostname above will be enough, but in the event more hosts are needed, this is an array + ## extraHosts: + ## - name: hostname.example + ## path: / + ## + + ## Any additional arbitrary paths that may need to be added to the ingress under the main host. + ## For example: The ALB ingress controller requires a special rule for handling SSL redirection. + ## extraPaths: + ## - path: /* + ## backend: + ## name: ssl-redirect + ## port: + ## name: use-annotation + ## + +## A secondary ingress, identical to the first ingress +## +ingressExtra: + ## Set to true to enable ingress record generation + ## + enabled: false + + ## Ingress Path type + ## + pathType: ImplementationSpecific + + ## Override API Version (automatically detected if not set) + ## + apiVersion: + + ## When the ingress is enabled, a host pointing to this will be created + ## + # hostname: hostname.example + + ## The Path to host the ingress under. You may need to set this to '/*' in order to use this + ## with ALB ingress controllers. + ## + path: /api + + ## Ingress annotations done as key:value pairs + ## + annotations: {} + + ## The list of additional hostnames to be covered with this ingress record. + ## Most likely the hostname above will be enough, but in the event more hosts are needed, this is an array + ## extraHosts: + ## - name: hostname.example + ## path: / + ## + + ## Any additional arbitrary paths that may need to be added to the ingress under the main host. + ## For example: The ALB ingress controller requires a special rule for handling SSL redirection. + ## extraPaths: + ## - path: /* + ## backend: + ## name: ssl-redirect + ## port: + ## name: use-annotation + ## + + +## Role Based Access +## Ref: https://kubernetes.io/docs/admin/authorization/rbac/ +## +rbac: + ## Specifies whether RBAC rules should be created + ## + create: true + + +## Dotnet debugging +## Enable to install a sidecar container which allows you to remoteley run dotnet monitoring tools +## see https://devblogs.microsoft.com/dotnet/introducing-dotnet-monitor/ +useDotnetMonitorSidecar : false + +## Peer pod blobs +## Attempt to fetch blobs from other pods in the same deployment before hitting blob store +## this is typically faster then falling back to global blob store +fetchBlobsFromPeerPods: false + +## Nginx configuration +nginx: + + ## Enable this option to run a nginx proxy in the all pods that is able to serve content directly from the filesystem + enabled: true + + ## Set this to add a header whenever X-Accel is used from nginx to send blobs + addXAccelDebugHeader: false + + ## Set this to use Unix domain sockets rather then ports for inter process communication + useDomainSockets: true + + ## Set to enable access log output, can be useful for debugging but will generate a lot of logs in prod + accessLogging: false + + ## Control the number of worker connections used for nginx + workerConnections: 1024 + + ## Number of connections to keep alive between nginx and Jupiter + keepAliveConnections: 2048 + + ## The length of the nginx backlog, bump this if you increase `net.core.somaxconn` beyond 4096 + backlog: 4096 + + ## Liveness and readiness probes, defaults to corresponding endpoints + ## + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + +worker: + enabled: false + + replicaCount: 1 + + image: + repository: "ghcr.io/epicgames/unreal-cloud-ddc" + pullPolicy: IfNotPresent + + tolerations: + - key: role + operator: Equal + value: unreal-cloud-ddc + effect: NoSchedule + + nodeSelector: + unreal-cloud-ddc/node-type: worker + + persistence: + enabled: false + + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + + podAffinityPreset: "" + + podAntiAffinityPreset: soft + + nodeAffinityPreset: + type: "" + key: "" + values: [] diff --git a/samples/unreal-cloud-ddc-single-region/local.tf b/samples/unreal-cloud-ddc-single-region/local.tf new file mode 100644 index 00000000..fdbef60f --- /dev/null +++ b/samples/unreal-cloud-ddc-single-region/local.tf @@ -0,0 +1,18 @@ +data "aws_availability_zones" "available" { + exclude_zone_ids = ["usw2-lax1-az1", "usw2-lax1-az2", "usw2-hnl1-az1", "usw2-las1-az1", "usw2-den1-az1"] +} + +data "aws_region" "current" {} + +data "aws_ecr_authorization_token" "token" {} + +data "aws_caller_identity" "current" {} + +locals { + azs = slice(data.aws_availability_zones.available.names, 0, 2) + + tags = { + Environment = "cgd" + Application = "unreal-cloud-ddc" + } +} diff --git a/samples/unreal-cloud-ddc-single-region/main.tf b/samples/unreal-cloud-ddc-single-region/main.tf new file mode 100644 index 00000000..733507e0 --- /dev/null +++ b/samples/unreal-cloud-ddc-single-region/main.tf @@ -0,0 +1,78 @@ +data "aws_secretsmanager_secret" "oidc_secrets" { + arn = var.oidc_credential_arn +} + +data "aws_secretsmanager_secret_version" "current" { + secret_id = data.aws_secretsmanager_secret.oidc_secrets.id +} + + +module "unreal_cloud_ddc_vpc" { + source = "./vpc" + vpc_cidr = "192.168.0.0/23" + private_subnets_cidrs = ["192.168.0.0/25", "192.168.0.128/25"] + public_subnets_cidrs = ["192.168.1.0/25", "192.168.1.128/25"] + availability_zones = local.azs + additional_tags = local.tags +} + +################################################################################ +# Single Region +################################################################################ + +module "unreal_cloud_ddc_infra" { + depends_on = [module.unreal_cloud_ddc_vpc] + source = "../../modules/unreal/unreal-cloud-ddc-infra" + name = "unreal-cloud-ddc" + vpc_id = module.unreal_cloud_ddc_vpc.vpc_id + private_subnets = module.unreal_cloud_ddc_vpc.private_subnet_ids + eks_cluster_access_cidr = var.eks_cluster_ip_allow_list + + scylla_private_subnets = module.unreal_cloud_ddc_vpc.private_subnet_ids + scylla_ami_name = "ScyllaDB 6.2.1" + scylla_architecture = "x86_64" + scylla_instance_type = "i4i.xlarge" + + scylla_db_throughput = 200 + scylla_db_storage = 100 + + nvme_managed_node_instance_type = "i3en.xlarge" + nvme_managed_node_desired_size = 2 + + worker_managed_node_instance_type = "c5.xlarge" + worker_managed_node_desired_size = 0 + + system_managed_node_instance_type = "m5.large" + system_managed_node_desired_size = 1 +} + +module "unreal_cloud_ddc_intra_cluster" { + depends_on = [ + module.unreal_cloud_ddc_infra, + module.unreal_cloud_ddc_infra.oidc_provider_arn + ] + + source = "../../modules/unreal/unreal-cloud-ddc-intra-cluster" + cluster_name = module.unreal_cloud_ddc_infra.cluster_name + cluster_oidc_provider_arn = module.unreal_cloud_ddc_infra.oidc_provider_arn + gchr_credentials_secret_manager_arn = var.github_credential_arn + oidc_credentials_secret_manager_arn = var.oidc_credential_arn + + s3_bucket_id = module.unreal_cloud_ddc_infra.s3_bucket_id + + unreal_cloud_ddc_helm_values = [ + templatefile("./assets/unreal_cloud_ddc_region_values.yaml", { + region = data.aws_region.current.name + bucket_name = module.unreal_cloud_ddc_infra.s3_bucket_id + }), + templatefile("./assets/unreal_cloud_ddc_base.yaml", { + scylla_ips = "${module.unreal_cloud_ddc_infra.scylla_ips[0]},${module.unreal_cloud_ddc_infra.scylla_ips[1]}" + region = data.aws_region.current.name + okta_domain = jsondecode(data.aws_secretsmanager_secret_version.current.secret_string)["okta_domain"] + okta_auth_server_id = jsondecode(data.aws_secretsmanager_secret_version.current.secret_string)["okta_auth_server_id"] + jwt_audience = jsondecode(data.aws_secretsmanager_secret_version.current.secret_string)["jwt_audience"] + jwt_authority = jsondecode(data.aws_secretsmanager_secret_version.current.secret_string)["jwt_authority"] + }), + file("./assets/unreal_cloud_ddc_values.yaml") + ] +} diff --git a/samples/unreal-cloud-ddc-single-region/providers.tf b/samples/unreal-cloud-ddc-single-region/providers.tf new file mode 100644 index 00000000..ca67a44d --- /dev/null +++ b/samples/unreal-cloud-ddc-single-region/providers.tf @@ -0,0 +1,44 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.73.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.24.0" + } + helm = { + source = "hashicorp/helm" + version = ">= 2.9.0" + } + } + required_version = ">= 1.0" +} + +provider "kubernetes" { + host = module.unreal_cloud_ddc_infra.cluster_endpoint + cluster_ca_certificate = base64decode(module.unreal_cloud_ddc_infra.cluster_certificate_authority_data) + exec { + api_version = "client.authentication.k8s.io/v1beta1" + command = "aws" + args = ["eks", "get-token", "--cluster-name", module.unreal_cloud_ddc_infra.cluster_name, "--output", "json"] + } +} + +provider "helm" { + kubernetes { + host = module.unreal_cloud_ddc_infra.cluster_endpoint + cluster_ca_certificate = base64decode(module.unreal_cloud_ddc_infra.cluster_certificate_authority_data) + exec { + api_version = "client.authentication.k8s.io/v1beta1" + command = "aws" + args = ["eks", "get-token", "--cluster-name", module.unreal_cloud_ddc_infra.cluster_name, "--output", "json"] + } + } + registry { + url = "oci://${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com" + username = data.aws_ecr_authorization_token.token.user_name + password = data.aws_ecr_authorization_token.token.password + } +} diff --git a/samples/unreal-cloud-ddc-single-region/variables.tf b/samples/unreal-cloud-ddc-single-region/variables.tf new file mode 100644 index 00000000..f1b850f4 --- /dev/null +++ b/samples/unreal-cloud-ddc-single-region/variables.tf @@ -0,0 +1,17 @@ +variable "oidc_credential_arn" { + type = string + sensitive = true + description = "OIDC Secrets Credential ARN" +} + +variable "github_credential_arn" { + type = string + sensitive = true + description = "Github Credential ARN" +} + +variable "eks_cluster_ip_allow_list" { + type = list(string) + default = [] + description = "IPs that will be allow listed to access cluster over internet" +} diff --git a/samples/unreal-cloud-ddc-single-region/vpc/main.tf b/samples/unreal-cloud-ddc-single-region/vpc/main.tf new file mode 100644 index 00000000..a1fb0411 --- /dev/null +++ b/samples/unreal-cloud-ddc-single-region/vpc/main.tf @@ -0,0 +1,135 @@ +########################################## +# VPC +########################################## + +resource "aws_vpc" "unreal_cloud_ddc_vpc" { + #checkov:skip=CKV2_AWS_11:flow logs are out of scope for sample architecture. + cidr_block = var.vpc_cidr + enable_dns_hostnames = true + + tags = merge(var.additional_tags, + { + Name = "unreal-cloud-ddc-vpc" + } + ) +} + +resource "aws_default_security_group" "default" { + vpc_id = aws_vpc.unreal_cloud_ddc_vpc.id +} + +########################################## +# Subnets +########################################## + +resource "aws_subnet" "public_subnets" { + count = length(var.public_subnets_cidrs) + vpc_id = aws_vpc.unreal_cloud_ddc_vpc.id + cidr_block = element(var.public_subnets_cidrs, count.index) + availability_zone = element(var.availability_zones, count.index) + + tags = merge(var.additional_tags, + { + "kubernetes.io/role/elb" = 1 + Name = "unreal-cloud-ddc-public-subnet-${count.index + 1}" + } + ) + +} + +resource "aws_subnet" "private_subnets" { + count = length(var.private_subnets_cidrs) + vpc_id = aws_vpc.unreal_cloud_ddc_vpc.id + cidr_block = element(var.private_subnets_cidrs, count.index) + availability_zone = element(var.availability_zones, count.index) + + tags = merge(var.additional_tags, + { + "kubernetes.io/role/internal-elb" = 1 + Name = "unreal-cloud-ddc-private-subnet-${count.index + 1}" + } + ) + +} + +########################################## +# Internet Gateway +########################################## + +resource "aws_internet_gateway" "igw" { + vpc_id = aws_vpc.unreal_cloud_ddc_vpc.id + tags = merge(var.additional_tags, + { + Name = "unreal-cloud-ddc-igw" + } + ) +} + +########################################## +# Route Tables & NAT Gateway +########################################## + + +resource "aws_route_table" "public_rt" { + vpc_id = aws_vpc.unreal_cloud_ddc_vpc.id + + # public route to the internet + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.igw.id + } + + tags = merge(var.additional_tags, + { + Name = "unreal-cloud-ddc-public-rt" + } + ) +} + +resource "aws_route_table_association" "public_rt_asso" { + count = length(aws_subnet.public_subnets) + route_table_id = aws_route_table.public_rt.id + subnet_id = aws_subnet.public_subnets[count.index].id +} + +resource "aws_eip" "nat_gateway_eip" { + depends_on = [aws_internet_gateway.igw] + #checkov:skip=CKV2_AWS_19:EIP associated with NAT Gateway through association ID + tags = merge(var.additional_tags, + { + Name = "unreal-cloud-ddc-nat-eip" + } + ) +} + +resource "aws_route_table" "private_rt" { + vpc_id = aws_vpc.unreal_cloud_ddc_vpc.id + + # private route to the internet through NAT gateway + route { + cidr_block = "0.0.0.0/0" + nat_gateway_id = aws_nat_gateway.nat_gateway.id + } + + tags = merge(var.additional_tags, + { + Name = "unreal-cloud-ddc-private-rt" + } + ) +} + +resource "aws_route_table_association" "private_rt_asso" { + count = length(aws_subnet.private_subnets) + route_table_id = aws_route_table.private_rt.id + subnet_id = aws_subnet.private_subnets[count.index].id +} + +resource "aws_nat_gateway" "nat_gateway" { + allocation_id = aws_eip.nat_gateway_eip.id + subnet_id = aws_subnet.public_subnets[0].id + tags = merge(var.additional_tags, + { + Name = "unreal-cloud-ddc-nat" + } + ) +} diff --git a/samples/unreal-cloud-ddc-single-region/vpc/outputs.tf b/samples/unreal-cloud-ddc-single-region/vpc/outputs.tf new file mode 100644 index 00000000..88abfee1 --- /dev/null +++ b/samples/unreal-cloud-ddc-single-region/vpc/outputs.tf @@ -0,0 +1,7 @@ +output "private_subnet_ids" { + value = aws_subnet.private_subnets[*].id +} + +output "vpc_id" { + value = aws_vpc.unreal_cloud_ddc_vpc.id +} diff --git a/samples/unreal-cloud-ddc-single-region/vpc/variables.tf b/samples/unreal-cloud-ddc-single-region/vpc/variables.tf new file mode 100644 index 00000000..0633ba83 --- /dev/null +++ b/samples/unreal-cloud-ddc-single-region/vpc/variables.tf @@ -0,0 +1,25 @@ +variable "vpc_cidr" { + type = string + description = "VPC CIDR Block" +} + +variable "additional_tags" { + default = {} + description = "Additional resource tags" + type = map(string) +} + +variable "private_subnets_cidrs" { + type = list(string) + description = "Private Subnet CIDR Range" +} + +variable "public_subnets_cidrs" { + type = list(string) + description = "Public Subnet CIDR Range" +} + +variable "availability_zones" { + type = list(string) + description = "Availability Zones" +} diff --git a/samples/unreal-cloud-ddc-single-region/vpc/versions.tf b/samples/unreal-cloud-ddc-single-region/vpc/versions.tf new file mode 100644 index 00000000..d6f41307 --- /dev/null +++ b/samples/unreal-cloud-ddc-single-region/vpc/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.5" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">=5.69.0" + } + } +}