Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Spinnaker + AWS Terraform
#####################################
# Namespace: Spinnaker
#####################################
resource "kubernetes_namespace" "spinnaker" {
metadata {
name = "spinnaker"
}
}
#####################################
# S3: Spinnaker
#####################################
resource "aws_s3_bucket" "spinnaker" {
bucket = "${local.resource_prefix}-spinnaker-storage"
acl = "private"
tags = "${merge(local.resource_default_tags, map("Name", "${local.resource_prefix}-spinnaker-storage"))}"
}
#####################################
# Redis: Spinnaker
#####################################
resource "aws_elasticache_subnet_group" "spinnaker_cache" {
name = "spinnaker-cache-subnet-group"
subnet_ids = "${local.management_subnets}"
}
resource "aws_elasticache_parameter_group" "spinnaker_cache" {
name = "spinnaker-cache-parameter-group"
family = "redis5.0"
# https://www.spinnaker.io/setup/productionize/caching/externalize-redis/#using-a-hosted-redis
parameter {
name = "notify-keyspace-events"
value = "gxE"
}
}
resource "aws_elasticache_cluster" "spinnaker_cache" {
cluster_id = "spinnaker-cache"
engine = "redis"
node_type = "cache.t2.small"
num_cache_nodes = 1
parameter_group_name = "${aws_elasticache_parameter_group.spinnaker_cache.name}"
engine_version = "5.0.3"
port = 6379
subnet_group_name = "${aws_elasticache_subnet_group.spinnaker_cache.id}"
security_group_ids = ["${aws_security_group.spinnaker_cache_redis.id}"]
tags = "${merge(local.resource_default_tags, map("Name", "spinnaker-cache"))}"
}
resource "aws_security_group" "spinnaker_cache_redis" {
name = "${local.resource_prefix}_spinnaker-cache-redis"
description = "${local.resource_prefix}_spinnaker-cache-redis"
vpc_id = "${local.management_vpc_id}"
ingress {
from_port = 6379
to_port = 6379
protocol = "tcp"
security_groups = [
"${module.cluster.worker_security_group_id}",
]
}
tags = "${merge(local.resource_default_tags, map("Name", "${local.resource_prefix}_spinnaker-redis"))}"
}
####################################
# Helm: Spinnaker
####################################
resource "helm_release" "spinnaker" {
name = "spinnaker
repository = "stable"
chart = "spinnaker"
namespace = "${kubernetes_namespace.spinnaker.metadata.0.name}"
values = [
<<EOF
halyard:
image:
tag: 1.18.0
annotations:
iam.amazonaws.com/role: "${aws_iam_role.spinnaker_halyard.arn}"
additionalScripts:
create: true
data:
base_url_edit.sh: |-
echo "Setting Base URL"
$HAL_COMMAND config security ui edit --override-base-url https://${aws_acm_certificate.spinnaker.domain_name}
$HAL_COMMAND config security api edit --override-base-url https://${aws_acm_certificate.spinnaker_gate.domain_name}
enable_ecr.sh: |-
echo "Setting Amazon ECR"
$HAL_COMMAND config provider docker-registry enable
if $HAL_COMMAND config provider docker-registry account get aws-ecr; then
PROVIDER_COMMAND='edit'
else
PROVIDER_COMMAND='add'
fi
$HAL_COMMAND config provider docker-registry account $PROVIDER_COMMAND aws-ecr \
--address 123456.dkr.ecr.${local.aws_region}.amazonaws.com \
--username AWS \
--password-command "aws --region ${local.aws_region} ecr get-authorization-token --output text --query 'authorizationData[].authorizationToken' | base64 -d | sed 's/^AWS://'"
additionalProfileConfigMaps:
create: true
data:
gate-local.yml: |-
server:
tomcat:
protocolHeader: X-Forwarded-Proto
remoteIpHeader: X-Forwarded-For
internalProxies: .*
httpsServerPort: X-Forwarded-Port
redis:
configuration:
secure: true
kubeConfig:
enabled: true
secretName: kubeconfig-for-spinnaker
secretKey: kubeconfig-for-spinnaker
contexts: # your-cluster-names
- eks-management-cluster
- eks-staging-cluster
- eks-production-cluster
deploymentContext: eks-management-cluster
clouddriver:
podAnnotations:
iam.amazonaws.com/role: "${aws_iam_role.spinnaker_halyard.arn}"
redis:
enabled: false
external:
host: ${aws_elasticache_cluster.spinnaker_cache.cache_nodes.0.address}
minio:
enabled: false
s3:
enabled: true
bucket: ${aws_s3_bucket.spinnaker.id}
rootFolder: "cache"
region: "${local.aws_region}"
accessKey: "${aws_iam_access_key.spinnaker_s3.id}"
secretKey: "${aws_iam_access_key.spinnaker_s3.secret}"
ingress:
enabled: true
host: ${aws_acm_certificate.spinnaker.domain_name}
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/certificate-arn: ${aws_acm_certificate.spinnaker.arn}
alb.ingress.kubernetes.io/subnets: ${join(",", local.management_subnets)}
alb.ingress.kubernetes.io/security-groups: ${data.terraform_remote_state.management_vpc.sg_internal_system_id}
ingressGate:
enabled: true
host: ${aws_acm_certificate.spinnaker_gate.domain_name}
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/certificate-arn: ${aws_acm_certificate.spinnaker_gate.arn}
alb.ingress.kubernetes.io/subnets: ${join(",", local.management_subnets)}
alb.ingress.kubernetes.io/security-groups: ${data.terraform_remote_state.management_vpc.sg_internal_system_id}
EOF
,
]
}
#####################################
# IAM User: Spinnaker S3
#####################################
resource "aws_iam_access_key" "spinnaker_s3" {
user = "${aws_iam_user.spinnaker_s3.name}"
}
resource "aws_iam_user" "spinnaker_s3" {
name = "${local.resource_prefix}_spinnaker-s3"
}
resource "aws_iam_user_policy" "spinnaker_s3" {
name = "${local.resource_prefix}_spinnaker-s3"
user = "${aws_iam_user.spinnaker_s3.name}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"${aws_s3_bucket.spinnaker.arn}",
"${aws_s3_bucket.spinnaker.arn}/*"
]
}
]
}
EOF
}
#####################################
# IAM Role: Spinnaker CloudDriver
#####################################
resource "aws_iam_role" "spinnaker_clouddriver" {
name = "${local.resource_prefix}_spinnaker-clouddriver"
assume_role_policy = "${data.aws_iam_policy_document.kube2iam_assume_role_policy_for_pods.json}"
}
resource "aws_iam_role_policy_attachment" "spinnaker_clouddriver_ecr_readonly" {
role = "${aws_iam_role.spinnaker_clouddriver.name}"
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
}
#####################################
# IAM Role: Spinnaker Cluster Auth
#####################################
resource "aws_iam_role" "spinnaker_halyard" {
name = "${local.resource_prefix}_spinnaker-halyard"
assume_role_policy = "${data.aws_iam_policy_document.kube2iam_assume_role_policy_for_pods.json}"
}
resource "aws_iam_role_policy_attachment" "spinnaker_halyard_ecr_readonly" {
role = "${aws_iam_role.spinnaker_halyard.name}"
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
}
#####################################
# ACM & Route53: Spinnaker
#####################################
resource "aws_acm_certificate" "spinnaker" {
domain_name = "${local.spinnaker_domain}"
validation_method = "DNS"
}
resource "aws_route53_record" "spinnaker" {
count = "${length(aws_acm_certificate.spinnaker.domain_validation_options)}"
zone_id = "${local.system_apex_domain_public_hosted_zone_id}"
name = "${lookup(aws_acm_certificate.spinnaker.domain_validation_options[count.index],"resource_record_name")}"
type = "${lookup(aws_acm_certificate.spinnaker.domain_validation_options[count.index],"resource_record_type")}"
ttl = "300"
records = ["${lookup(aws_acm_certificate.spinnaker.domain_validation_options[count.index],"resource_record_value")}"]
}
resource "aws_acm_certificate" "spinnaker_gate" {
domain_name = "${local.spinnaker_gate_domain}"
validation_method = "DNS"
}
resource "aws_route53_record" "spinnaker_gate" {
count = "${length(aws_acm_certificate.spinnaker_gate.domain_validation_options)}"
zone_id = "${local.system_apex_domain_public_hosted_zone_id}"
name = "${lookup(aws_acm_certificate.spinnaker_gate.domain_validation_options[count.index],"resource_record_name")}"
type = "${lookup(aws_acm_certificate.spinnaker_gate.domain_validation_options[count.index],"resource_record_type")}"
ttl = "300"
records = ["${lookup(aws_acm_certificate.spinnaker_gate.domain_validation_options[count.index],"resource_record_value")}"]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.