/terraform-aws-serverless-jenkins

Scalable and reliable serverless Jenkins on AWS Fargate.

Primary LanguageHCLMIT LicenseMIT

Archived

This module is not being maintained anymore, feel free to fork it if you see fit.

Serverless Jenkins Terraform Module for AWS

Terraform module to deploy a Serverless Jenkins service on AWS, providing high availability and scalability.

This module aims to abstract the complexity of designing a reliable serverless Jenkins service, providing a easy and fast setup capable of serving multiple teams.

The base of this custom module is the fantastic work of AWS architects. For their original solution, take a look at the AWS blog post about Jenkins on Fargate.

Architecture

Architecture

Prerequisites

The following are required to deploy this Terraform module

  1. Linux OS
  2. Terraform 0.14+
  3. Docker 19+
  4. Password for Jenkins must be stored in SSM Parameter store. This parameter must be of type SecureString and have the name jenkins-admin. Username is admin.

Features

  • Full configured Jenkins Controller on AWS Fargate with template for builds on Fargate Jenkins Agents.
  • Pre-configured Jenkins Agents that can be provisioned with FARGATE or FARGATE_SPOT for cheaper pricing.
  • Builds ECR Private Registry for builded Jenkins images.
  • EFS as persistent layer for Jenkins Controller data with KMS encryption;
  • Best practices on SG configuration for internal communication and temporary assumed roles with AWS STS.
  • Builds a application load balancer with HTTP or HTTPS if provided with Route53 and AWS Certificate.
  • Single private subnet setup with configured NAT Gateway.

Usage

Complete setup for production environments

module "jenkins" {
  source = "Renatochaz/serverless-jenkins/aws"

  vpc_id                = "vpc-8282hd8sj2"
  public_subnets        = ["subnet-02396b30d428fe690", "subnet-07a209485112c354f"]
  private_subnets       = ["subnet-83hdsjs9jhe2", "subnet-dsh87273h287d82"]
  assign_public_ip      = false
  create_private_subnet = false

  alb_protocol        = "HTTPS"
  alb_policy_ssl      = "ELBSecurityPolicy-FS-1-2-Res-2019-08"
  alb_certificate_arn = var.certificate_arn

  route53_create_alias = true
  route53_zone_id      = "Z2ES7B9AZ6SHAE"
  route53_alias_name   = "jenkins"
  tags = {
    Module = "Serverless_Jenkins"
  }
}

Auto generated private subnet

If you want the private subnet and connectivity setup by the module, set the create_private_subnet to true, and use one of the public_subnets ID's for the natg_public_subnet which will route the private subnet traffic through the NAT Gateway.

module "jenkins" {
  source = "Renatochaz/serverless-jenkins/aws"

  vpc_id         = "vpc-8282hd8sj2"
  public_subnets = ["subnet-02396b30d428fe690", "subnet-07a209485112c354f"]

  assign_public_ip      = false
  create_private_subnet = true
  private_subnets       = []
  private_subnet_cidr   = "172.31.112.0/24"
  natg_public_subnet    = "subnet-02396b30d428fe690"

}

Basic deploy in public subnets only

If you want a fast and cheap environment, probably for MOC/POC's or even for studying and exploring Jenkins, use only public subnets ID's to the private_subnets input and set the jenkins_agents_provider to FARGATE_SPOT to ensure the minimal pricing for this module.

Please note that this means the environment is very vulnerable to attacks, and should not be used on production.

module "jenkins" {
  source = "Renatochaz/serverless-jenkins/aws"

  vpc_id                = "vpc-8282hd8sj2"
  public_subnets        = ["subnet-02396b30d428fe690", "subnet-07a209485112c354f"]
  private_subnets       = ["subnet-02396b30d428fe690"]
  create_private_subnet = false
  assign_public_ip      = true
  jenkins_agents_provider = "FARGATE_SPOT"

}

Requirements

Name Version
terraform >= 0.13
aws >= 4.40

Providers

Name Version
aws >= 4.40
null n/a
template n/a

Modules

Name Source Version
ecr terraform-aws-modules/ecr/aws 1.5.1
private_subnet ./modules/private_subnet n/a

Resources

Name Type
aws_cloudwatch_log_group.jenkins_controller_log_group resource
aws_ecs_cluster.jenkins_agents resource
aws_ecs_cluster.jenkins_controller resource
aws_ecs_cluster_capacity_providers.jenkins_agents_provider resource
aws_ecs_cluster_capacity_providers.jenkins_controller_provider resource
aws_ecs_service.jenkins_controller resource
aws_ecs_task_definition.jenkins_controller resource
aws_efs_access_point.this resource
aws_efs_file_system.this resource
aws_efs_file_system_policy.this resource
aws_efs_mount_target.this resource
aws_iam_policy.ecs_execution_policy resource
aws_iam_policy.jenkins_controller_task_policy resource
aws_iam_role.ecs_execution_role resource
aws_iam_role.jenkins_controller_task_role resource
aws_iam_role_policy_attachment.ecs_execution resource
aws_iam_role_policy_attachment.jenkins_controller_task resource
aws_kms_key.cloudwatch resource
aws_lb.this resource
aws_lb_listener.alb resource
aws_lb_target_group.this resource
aws_security_group.alb_security_group resource
aws_security_group.efs_security_group resource
aws_security_group.jenkins_controller_security_group resource
aws_service_discovery_private_dns_namespace.controller resource
aws_service_discovery_service.controller resource
null_resource.build_docker_image resource
null_resource.push_docker_image resource
null_resource.render_template resource
aws_caller_identity.current data source
aws_ecr_authorization_token.token data source
aws_iam_policy_document.cloudwatch data source
aws_iam_policy_document.ecs_assume_policy data source
aws_iam_policy_document.ecs_execution_policy data source
aws_iam_policy_document.efs_resource_policy data source
aws_iam_policy_document.jenkins_controller_task_policy data source
aws_region.current data source
aws_vpc.target_vpc data source
template_file.jenkins_configuration_def data source

Inputs

Name Description Type Default Required
alb_certificate_arn ARN of the SSL certificate. string null no
alb_ingress_allow_cidrs A list of cidrs to allow inbound into Jenkins. Default to all. list(string)
[
"0.0.0.0/0"
]
no
alb_policy_ssl SSL policy name. Required if alb_protocol is HTTPS or TLS string null no
alb_protocol Protocol to use for the ALB. string "HTTP" no
assign_public_ip Should public ip be assigned to Jenkins Controller and Agents. Use only if you need to deploy ECS on public subnets, instead of Private subnets with Nat Gateway. bool false no
create_private_subnet Creates a private subnet with a NAT Gateway setup for ECS communication. bool true no
efs_access_point_gid The gid number to associate with the EFS access point. number 1000 no
efs_access_point_uid The uid number to associate with the EFS access point. number 1000 no
efs_enable_encryption Enable EFS encryption. bool true no
efs_ia_lifecycle_policy EFS ia lifecycle policy. string "AFTER_7_DAYS" no
efs_kms_key_arn KMS Key arn for the EFS. string null no
efs_performance_mode EFS performance mode. string "generalPurpose" no
efs_provisioned_throughput_in_mibps EFS total provisioned throughput in mibs. number null no
efs_throughput_mode EFS throughput mode. string "bursting" no
jenkins_agents_cpu Jenkins agents CPU. number 512 no
jenkins_agents_memory_limit Hard limit on memory for jenkins agents. If 0, no memory limit is applied. number 0 no
jenkins_agents_provider FARGATE or FARGATE_SPOT string "FARGATE" no
jenkins_controller_cpu Jenkins controller CPU. number 2048 no
jenkins_controller_memory Jenkins controller memory. number 4096 no
jenkins_controller_port Jenkins controller port number. number 8080 no
jenkins_controller_task_log_retention_days Days to retain logs of Jenkins controller. number 7 no
jenkins_ecr_repository_name Name for the Jenkins controller ECR repository. string "jenkins-controller" no
jenkins_jnlp_port Jenkins jnlp port number. number 50000 no
name_prefix Prefix to be used on general resources. string "jenkins" no
natg_public_subnet ID of a public subnet to route the NAT Gateway if create_private_subnets is True. string "" no
private_subnet_cidr CIDR block for the private subnet that will be setup if create_private_subnets is True. string "" no
private_subnets A list of (preferable) different availability zone private subnets. Use empty value if create_private_subnet is True. list(string) n/a yes
public_subnets A list of (preferable) different availability zone public subnets. list(string) n/a yes
tags A map of tags to add to all resources. map(string) {} no
vpc_id ID of the VPC where the Jenkins will be deployed. string n/a yes
route53_alias_name Route53 alias name. string "jenkins" no
route53_create_alias should create alias from Route53 DNS. string false no
route53_zone_id Route53 zone ID. string null no

Outputs

Name Description
ecr_repository_arn ECR Repository ARN
efs_access_point_id EFS Access Point ID
efs_file_system_dns_name EFS file system DNS name
efs_file_system_id EFS file system ID
jenkins_alb_arn Jenkins Controller Load Balancer ARN
jenkins_alb_dns Jenkins Controller Load Balancer DNS name
repository_registry_id Registry ID where the ECR repository was created
repository_url ECR Repository URL