-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit de760f7
Showing
3 changed files
with
494 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# Sentieon - Terraform | ||
Terraform configuration files for the Sentieon software | ||
|
||
## Introduction | ||
|
||
[Terraform](https://www.terraform.io/) is an open-source infrastructure as code (IaC) tool for the provisioning and management of cloud infrastructure. This repository contains example terraform configuration files that can be used to quickly deploy the Sentieon software to your cloud infrastructure. | ||
|
||
## Quick Start - Sentieon License server deployment to AWS | ||
|
||
### Requirements | ||
|
||
* The [Terraform CLI](https://developer.hashicorp.com/terraform/downloads) | ||
* The [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) | ||
* An AWS account and credentials with permission to provision resources inside the account | ||
* A Sentieon license file for your FQDN, bound to port 8990 and placed in your s3 bucket | ||
|
||
### Provision the license server | ||
|
||
Use the terraform configuration files to provision the following infrastructure: | ||
* Security groups for the Sentieon license server and any compute nodes | ||
* A CloudWatch log group for the license server logs | ||
* An IAM role and instance profile for the license server | ||
* Granting read access to the Sentieon software package and license file in AWS s3 | ||
* Granting write access to the CloudWatch log group | ||
* Starts a t3.nano ec2 instance to host the license server, using the IAM profile and security group | ||
* Using the latest Amazon Linux 2023 AMI for the region | ||
* Uses an encrypted root EBS disk with either an AWS-managed or (optionally) a customer-managed key | ||
* Has a user data script to do the following at startup, without direct user intervention: | ||
* Install, configure, and start the cloudwatch universal agent to push the license server logs to CloudWatch | ||
* Download the customer's license file from s3 | ||
* Download and install the Sentieon software. Start the license server using the license file | ||
* Create a private hosted zone with AWS Route 53 | ||
* Create a Route53 record associating the FQDN with the private IP of the license server instance | ||
|
||
|
||
```bash | ||
git clone https://github.com/sentieon/terraform | ||
cd terraform/aws_license-server | ||
|
||
# Configure your AWS credentials | ||
export AWS_ACCESS_KEY_ID=<AWS_ACCESS_KEY_ID> | ||
export AWS_SECRET_ACCESS_KEY=<AWS_SECRET_ACCESS_KEY> | ||
|
||
# Initialize the directory with Terraform | ||
terraform init | ||
|
||
# Provision the license server infrastructure | ||
terraform apply \ | ||
-var 'aws_region=<AWS_REGION>' \ | ||
-var 'licsrvr_fqdn=<FQDN>' \ | ||
-var 'license_s3_uri=s3://<S3_URI>' | ||
``` | ||
|
||
The infrastructure should startup within a few minutes. | ||
|
||
AWS will charge your account for deployed infrastructure including the ec2 instance, EBS disk, Route53 hosted zone. The deployment will also generate charges for DNS queries resolved by Route53. | ||
|
||
### Cleanup | ||
|
||
The provisioned infrastructure can be destroyed with the `terraform apply -destroy` command: | ||
```bash | ||
terraform apply -destroy \ | ||
-var 'aws_region=<AWS_REGION>' \ | ||
-var 'licsrvr_fqdn=<FQDN>' \ | ||
-var 'license_s3_uri=s3://<S3_URI>' | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
variable "aws_region" {} | ||
variable "licsrvr_fqdn" {} | ||
variable "license_s3_uri" {} | ||
variable "kms_key" { | ||
type = string | ||
default = null | ||
} | ||
variable "sentieon_version" { | ||
type = string | ||
default = "202112.07" | ||
} | ||
|
||
locals { | ||
license_bucket_arn = format("arn:aws:s3:::%s", split("/", var.license_s3_uri)[2]) | ||
license_obj_arn = format("arn:aws:s3:::%s", join("/", slice(split("/", var.license_s3_uri), 2, 5))) | ||
} | ||
|
||
terraform { | ||
required_providers { | ||
aws = { | ||
source = "hashicorp/aws" | ||
version = "~> 4.16" | ||
} | ||
dns = { | ||
source = "hashicorp/dns" | ||
} | ||
} | ||
|
||
required_version = ">= 1.2.0" | ||
} | ||
|
||
provider "aws" { | ||
region = var.aws_region | ||
} | ||
|
||
# Find the IP of the master server | ||
data "dns_a_record_set" "master" { | ||
host = "master.sentieon.com" | ||
} | ||
|
||
# Find the default VPC | ||
data "aws_vpc" "default" { | ||
default = true | ||
} | ||
|
||
# Find the AWS account ID | ||
data "aws_caller_identity" "current" {} | ||
|
||
## Configure the security group for the license server | ||
# Create a security group | ||
resource "aws_security_group" "sentieon_license_server" { | ||
name = "sentieon_license_server" | ||
description = "Security groups for the Sentieon license server" | ||
vpc_id = data.aws_vpc.default.id | ||
} | ||
|
||
# Create a security group for the compute nodes | ||
resource "aws_security_group" "sentieon_compute_nodes" { | ||
name = "sentieon_compute" | ||
description = "Security groups for Sentieon compute nodes" | ||
vpc_id = data.aws_vpc.default.id | ||
} | ||
|
||
# Security group rules are definied in a separate file | ||
|
||
# Cloudwatch log group for logs | ||
resource "aws_cloudwatch_log_group" "licsrvr" { | ||
name = "/sentieon/licsrvr/LicsrvrLog" | ||
} | ||
|
||
# IAM role for the license server | ||
resource "aws_iam_role" "licsrvr" { | ||
name = "sentieon_licsrvr_role" | ||
|
||
# Allow policy to be assumed by ec2 instances | ||
assume_role_policy = jsonencode({ | ||
Version = "2012-10-17" | ||
Statement = [ | ||
{ | ||
Action = "sts:AssumeRole" | ||
Effect = "Allow" | ||
Sid = "" | ||
Principal = { | ||
Service = "ec2.amazonaws.com" | ||
} | ||
}, | ||
] | ||
}) | ||
|
||
# s3 access to the license file in s3 and Sentieon software | ||
inline_policy { | ||
name = "s3_inline_policy" | ||
|
||
policy = jsonencode({ | ||
Version = "2012-10-17" | ||
Statement = [ | ||
{ | ||
Action = ["s3:Get*", "s3:List*", "s3-object-lambda:Get*", "s3-object-lambda:List*"] | ||
Effect = "Allow" | ||
Resource = [ | ||
local.license_bucket_arn, | ||
local.license_obj_arn, | ||
"arn:aws:s3:::sentieon-release", | ||
format("arn:aws:s3:::sentieon-release/software/sentieon-genomics-%s.tar.gz", var.sentieon_version) | ||
] | ||
}, | ||
] | ||
}) | ||
} | ||
|
||
# access to write license server logs to cloudwatch | ||
inline_policy { | ||
name = "cloudwatch_inline_policy" | ||
|
||
policy = jsonencode({ | ||
Version = "2012-10-17" | ||
Statement = [ | ||
{ | ||
Action = ["logs:PutRetentionPolicy", "logs:CreateLogGroup", "logs:PutLogEvents", "logs:CreateLogStream"] | ||
Effect = "Allow" | ||
Resource = [ | ||
format("arn:aws:logs:*:%v:log-group:%v", data.aws_caller_identity.current.account_id, aws_cloudwatch_log_group.licsrvr.name), | ||
format("arn:aws:logs:*:%v:log-group:%v:log-stream:*", data.aws_caller_identity.current.account_id, aws_cloudwatch_log_group.licsrvr.name) | ||
] | ||
}, | ||
] | ||
}) | ||
} | ||
} | ||
|
||
resource "aws_iam_instance_profile" "licsrvr" { | ||
name = "sentieon_licsrvr_profile" | ||
role = aws_iam_role.licsrvr.name | ||
} | ||
|
||
## Start the License server | ||
# Find the latest Amazon Linux AMI | ||
data "aws_ami" "al2023" { | ||
most_recent = true | ||
|
||
filter { | ||
name = "name" | ||
values = ["al2023-ami-2023.*-x86_64"] | ||
} | ||
|
||
filter { | ||
name = "virtualization-type" | ||
values = ["hvm"] | ||
} | ||
|
||
filter { | ||
name = "architecture" | ||
values = ["x86_64"] | ||
} | ||
|
||
owners = ["amazon"] | ||
} | ||
|
||
# Create the license server instance | ||
resource "aws_instance" "sentieon_licsrvr" { | ||
ami = data.aws_ami.al2023.id | ||
instance_type = "t3.nano" | ||
vpc_security_group_ids = [aws_security_group.sentieon_license_server.id] | ||
iam_instance_profile = aws_iam_instance_profile.licsrvr.id | ||
user_data_replace_on_change = true | ||
|
||
root_block_device { | ||
encrypted = true | ||
kms_key_id = var.kms_key | ||
} | ||
|
||
user_data = <<EOF | ||
#!/usr/bin/bash -xv | ||
yum update -y | ||
yum install amazon-cloudwatch-agent -y | ||
mkdir -p /opt/aws/amazon-cloudwatch-agent/bin | ||
echo '{ "agent": { "run_as_user": "root" }, "logs": { "logs_collected": { "files": { "collect_list": [ { "file_path": "/opt/sentieon/licsrvr.log", "log_group_name": "${aws_cloudwatch_log_group.licsrvr.name}", "log_stream_name": "{instance_id}", "retention_in_days": 120 } ] } } } }' > /opt/aws/amazon-cloudwatch-agent/bin/config.json | ||
amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json | ||
mkdir -p /opt/sentieon | ||
cd /opt/sentieon | ||
aws s3 cp 's3://sentieon-release/software/sentieon-genomics-${var.sentieon_version}.tar.gz' - | tar -zxf - | ||
ln -s 'sentieon-genomics-${var.sentieon_version}' 'sentieon-genomics' | ||
aws s3 cp "${var.license_s3_uri}" "./sentieon.lic" | ||
i=0 | ||
while true; do | ||
if getent ahosts "${var.licsrvr_fqdn}"; then | ||
break | ||
fi | ||
i=$((i + 1)) | ||
if [[ i -gt 300 ]]; then | ||
exit 1 | ||
fi | ||
sleep 1 | ||
done | ||
sentieon-genomics/bin/sentieon licsrvr --start --log licsrvr.log ./sentieon.lic | ||
EOF | ||
} | ||
|
||
## Create a private hosted zone | ||
# Create a hosted zone | ||
resource "aws_route53_zone" "primary" { | ||
name = var.licsrvr_fqdn | ||
|
||
vpc { | ||
vpc_id = data.aws_vpc.default.id | ||
vpc_region = var.aws_region | ||
} | ||
} | ||
|
||
resource "aws_route53_record" "licsrvr_fqdn" { | ||
zone_id = aws_route53_zone.primary.zone_id | ||
name = var.licsrvr_fqdn | ||
type = "A" | ||
ttl = "300" | ||
records = [aws_instance.sentieon_licsrvr.private_ip] | ||
} |
Oops, something went wrong.