chore(mimir): run on aws ecs fargate

This commit is contained in:
Michele Cereda
2025-04-25 18:17:23 +02:00
parent 5d4b5c8993
commit 4f39a1dac0
3 changed files with 643 additions and 12 deletions

View File

@@ -702,7 +702,7 @@ One must delete namespaces in AWS Cloud Map themselves.
</details> </details>
<details> <details style="padding-bottom: 1rem">
<summary>Requirements</summary> <summary>Requirements</summary>
- Tasks running in Fargate **must** use the Fargate Linux platform version 1.4.0 or higher. - Tasks running in Fargate **must** use the Fargate Linux platform version 1.4.0 or higher.
@@ -730,11 +730,75 @@ One must delete namespaces in AWS Cloud Map themselves.
</details> </details>
Procedure:
1. Configure the ECS cluster to use the desired AWS Cloud Map namespace.
<details style="padding: 0 0 1rem 1rem">
<summary>Simplified process</summary>
Create the cluster with the desired name for the AWS Cloud Map namespace, and specify that name for the namespace
when asked.<br/>
ECS will create a new HTTP namespace with the necessary configuration.<br/>
As reminder, Service Connect doesn't use or create DNS hosted zones in Amazon Route 53. FIXME: check this
</details>
1. Configure port names in the server services' task definitions for all the port mappings that the services will expose
in Service Connect.
<details style="padding: 0 0 1rem 1rem">
```json
containerDefinitions: [
{
"name": "postgres",
"protocol": "tcp",
"containerPort": 5432,
},
]
```
</details>
1. Configure the server services to create Service Connect endpoints within the namespace.
<details style="padding: 0 0 1rem 1rem">
```json
"serviceConnectConfiguration": {
"enabled": true,
"namespace": "ecs-dev-cluster",
"services": [
{
"portName": "postgres",
"discoveryName": "postgres",
"clientAliases": [{
"port": 5432,
"dnsName": "pgsql"
}]
}
]
},
```
</details>
1. Deploy the services.<br/>
This will create the endpoints AWS Cloud Map namespace used by the cluster.<br/>
ECS also injects the Service Connect proxy container in each task.
1. Deploy the client applications as ECS services.<br/>
ECS connects them to the Service Connect endpoints through the Service Connect proxy in each task.
1. Applications only use the proxy to connect to Service Connect endpoints.<br/>
No additional configuration is required to use the proxy.
1. \[optionally] Monitor traffic through the Service Connect proxy in Amazon CloudWatch.
### ECS service discovery ### ECS service discovery
Service discovery helps manage HTTP and DNS namespaces for ECS services. Service discovery helps manage HTTP and DNS namespaces for ECS services.
ECS syncs the list of launched tasks to AWS Cloud Map.<br/> ECS automatically registers and de-registers the list of launched tasks to AWS Cloud Map.<br/>
Cloud Map maintains DNS records that resolve to the internal IP addresses of one or more tasks from registered Cloud Map maintains DNS records that resolve to the internal IP addresses of one or more tasks from registered
services.<br/> services.<br/>
Other services in the **same** VPC can use such DNS records to send traffic directly to containers using their internal Other services in the **same** VPC can use such DNS records to send traffic directly to containers using their internal
@@ -756,12 +820,31 @@ configured.
Service discovery supports only the `A` and `SRV` DNS record types.<br/> Service discovery supports only the `A` and `SRV` DNS record types.<br/>
DNS records are automatically added or removed as tasks start or stop for ECS services. DNS records are automatically added or removed as tasks start or stop for ECS services.
Until ECS registers the tasks, Containers in them might complain about being unable to resolve the services they are
using.
DNS records have a TTL and it might happen that tasks died before this ended.<br/> DNS records have a TTL and it might happen that tasks died before this ended.<br/>
One **must** implement extra logic in one's applications, so that they can handle retries and deal with connection One **must** implement extra logic in one's applications, so that they can handle retries and deal with connection
failures when the records are not yet updated. failures when the records are not yet updated.
See also [Use service discovery to connect Amazon ECS services with DNS names]. See also [Use service discovery to connect Amazon ECS services with DNS names].
Procedure:
1. Create the desired AWS Cloud Map namespace.
1. Create the desired Cloud Map service in the namespace.
1. Configure ECS services to use the Cloud Map service.
<details style="padding: 0 0 1rem 1rem">
```json
"serviceRegistries": [{
"registryArn": "arn:aws:servicediscovery:eu-west-1:012345678901:service/srv-uuf33b226vw93biy"
}],
```
</details>
### VPC Lattice ### VPC Lattice
Managed application networking service that customers can use to observe, secure, and monitor applications built across Managed application networking service that customers can use to observe, secure, and monitor applications built across
@@ -799,7 +882,7 @@ Solutions:
This **will** cost money. This **will** cost money.
- Target a lambda that returns a [308 Permanent Redirect] code with the current IP addresses of the requested tasks. - Target a lambda that returns a [308 Permanent Redirect] code with the current IP addresses of the requested tasks.
- Use dynamic service discovery mechanisms like AWS Cloud Map.<br/> - Use dynamic service discovery mechanisms like [AWS Cloud Map][What Is AWS Cloud Map?].<br/>
Refer [Metrics collection from Amazon ECS using Amazon Managed Service for Prometheus] and Refer [Metrics collection from Amazon ECS using Amazon Managed Service for Prometheus] and
[aws-cloudmap-prometheus-sd]. [aws-cloudmap-prometheus-sd].
@@ -838,6 +921,7 @@ Specify a supported value for the task CPU and memory in your task definition.
- [EFS] - [EFS]
- [Amazon ECS Exec Checker] - [Amazon ECS Exec Checker]
- [ECS Execute-Command proposal] - [ECS Execute-Command proposal]
- [What Is AWS Cloud Map?]
### Sources ### Sources
@@ -864,6 +948,7 @@ Specify a supported value for the task CPU and memory in your task definition.
- [Scraping Prometheus metrics from applications running in AWS ECS] - [Scraping Prometheus metrics from applications running in AWS ECS]
- [How can I allow the tasks in my Amazon ECS services to communicate with each other?] - [How can I allow the tasks in my Amazon ECS services to communicate with each other?]
- [Interconnect Amazon ECS services] - [Interconnect Amazon ECS services]
- [Amazon ECS Service Discovery]
<!-- <!--
Reference Reference
@@ -887,6 +972,7 @@ Specify a supported value for the task CPU and memory in your task definition.
<!-- Upstream --> <!-- Upstream -->
[amazon ecs exec checker]: https://github.com/aws-containers/amazon-ecs-exec-checker [amazon ecs exec checker]: https://github.com/aws-containers/amazon-ecs-exec-checker
[Amazon ECS Service Discovery]: https://aws.amazon.com/blogs/aws/amazon-ecs-service-discovery/
[amazon ecs services]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html [amazon ecs services]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html
[amazon ecs standalone tasks]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/standalone-tasks.html [amazon ecs standalone tasks]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/standalone-tasks.html
[amazon ecs task definition differences for the fargate launch type]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-tasks-services.html [amazon ecs task definition differences for the fargate launch type]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-tasks-services.html
@@ -914,6 +1000,7 @@ Specify a supported value for the task CPU and memory in your task definition.
[Use service discovery to connect Amazon ECS services with DNS names]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-discovery.html [Use service discovery to connect Amazon ECS services with DNS names]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-discovery.html
[using amazon ecs exec to access your containers on aws fargate and amazon ec2]: https://aws.amazon.com/blogs/containers/new-using-amazon-ecs-exec-access-your-containers-fargate-ec2/ [using amazon ecs exec to access your containers on aws fargate and amazon ec2]: https://aws.amazon.com/blogs/containers/new-using-amazon-ecs-exec-access-your-containers-fargate-ec2/
[What is Amazon VPC Lattice?]: https://docs.aws.amazon.com/vpc-lattice/latest/ug/what-is-vpc-lattice.html [What is Amazon VPC Lattice?]: https://docs.aws.amazon.com/vpc-lattice/latest/ug/what-is-vpc-lattice.html
[What Is AWS Cloud Map?]: https://docs.aws.amazon.com/cloud-map/latest/dg/what-is-cloud-map.html
<!-- Others --> <!-- Others -->
[`aws ecs execute-command` results in `TargetNotConnectedException` `The execute command failed due to an internal error`]: https://stackoverflow.com/questions/69261159/aws-ecs-execute-command-results-in-targetnotconnectedexception-the-execute [`aws ecs execute-command` results in `TargetNotConnectedException` `The execute command failed due to an internal error`]: https://stackoverflow.com/questions/69261159/aws-ecs-execute-command-results-in-targetnotconnectedexception-the-execute

View File

@@ -12,6 +12,7 @@ and set up alerting rules across multiple tenants to leverage tenant federation.
1. [Setup](#setup) 1. [Setup](#setup)
1. [Monolithic mode](#monolithic-mode) 1. [Monolithic mode](#monolithic-mode)
1. [Microservices mode](#microservices-mode) 1. [Microservices mode](#microservices-mode)
1. [Run on AWS ECS Fargate](#run-on-aws-ecs-fargate)
1. [Storage](#storage) 1. [Storage](#storage)
1. [Object storage](#object-storage) 1. [Object storage](#object-storage)
1. [Authentication and authorization](#authentication-and-authorization) 1. [Authentication and authorization](#authentication-and-authorization)
@@ -31,8 +32,8 @@ Scrapers (like Prometheus or Grafana's Alloy) need to send metrics data to Mimir
Mimir will **not** scrape metrics itself. Mimir will **not** scrape metrics itself.
Mimir listens by default on port `8080` for HTTP and on port `9095` for GRPC.<br/> Mimir listens by default on port `8080` for HTTP and on port `9095` for GRPC.<br/>
It also internally advertises data or actions to members in the cluster using the [gossip protocol]. This uses port It also internally advertises data or actions to members in the cluster using [hashicorp/memberlist], which implements a
`7946` by default and **must** be reachable by all members in the cluster to work. [gossip protocol]. This uses port `7946` by default, and **must** be reachable by all members in the cluster to work.
Mimir stores time series in TSDB blocks, that are uploaded to an object storage bucket.<br/> Mimir stores time series in TSDB blocks, that are uploaded to an object storage bucket.<br/>
Such blocks are the same that Prometheus and Thanos use, though each application stores blocks in different places and Such blocks are the same that Prometheus and Thanos use, though each application stores blocks in different places and
@@ -79,21 +80,28 @@ helm --namespace 'mimir-test' upgrade --install --create-namespace 'mimir' 'graf
mimir -help mimir -help
mimir -help-all mimir -help-all
# Validate configuration files # Validate configuration files.
mimir -modules -config.file 'path/to/config.yaml' mimir -modules -config.file 'path/to/config.yaml'
# See the current configuration of components # Run tests.
# Refer <https://grafana.com/docs/mimir/latest/manage/tools/mimir-continuous-test/>.
mimir -target='continuous-test' \
-tests.write-endpoint='http://localhost:8080' -tests.read-endpoint='http://localhost:8080' \
-tests.smoke-test \ # just once
-server.http-listen-port='18080' -server.grpc-listen-port='19095' # avoid colliding with the running instance
# See the current configuration of components.
GET /config GET /config
GET /runtime_config GET /runtime_config
# See changes in the runtime configuration from the default one # See changes in the runtime configuration from the default one.
GET /runtime_config?mode=diff GET /runtime_config?mode=diff
# Check the service is ready # Check the service is ready.
# A.K.A. readiness probe # A.K.A. readiness probe.
GET /ready GET /ready
# Get metrics # Get metrics.
GET /metrics GET /metrics
``` ```
@@ -305,6 +313,27 @@ Recommended using Kubernetes and the [`mimir-distributed` Helm chart][helm chart
Each component scales up independently.<br/> Each component scales up independently.<br/>
This allows for greater flexibility and more granular failure domains. This allows for greater flexibility and more granular failure domains.
### Run on AWS ECS Fargate
See also [AWS ECS] and [Mimir on AWS ECS Fargate].
Things to consider:
- Go for [ECS service discovery] instead of [ECS Service Connect].
<details style="padding: 0 0 1rem 1rem">
> This needs to be confirmed, but it is how it worked for me.
Apparently, at the time of writing, Service Connect _prefers_ answering in IPv6 for ECS-related queries.<br/>
There seems to be no way to customize this for now.
At the same time, [hashicorp/memberlist] seems to only use IPv4 unless explicitly required to listen on a IPv6
address.<br/>
Which, one would have no way to programmatically set **before** creating the resources.
</details>
## Storage ## Storage
Mimir supports the `s3`, `gcs`, `azure`, `swift`, and `filesystem` backends.<br/> Mimir supports the `s3`, `gcs`, `azure`, `swift`, and `filesystem` backends.<br/>
@@ -488,6 +517,8 @@ ingester:
- [Codebase] - [Codebase]
- [Prometheus] - [Prometheus]
- [Grafana] - [Grafana]
- [hashicorp/memberlist]
- [Gossip protocol]
- [Ceiling Function] - [Ceiling Function]
Alternatives: Alternatives:
@@ -518,6 +549,8 @@ Alternatives:
[aws ecs]: cloud%20computing/aws/ecs.md [aws ecs]: cloud%20computing/aws/ecs.md
[aws efs]: cloud%20computing/aws/efs.md [aws efs]: cloud%20computing/aws/efs.md
[cortex]: cortex.md [cortex]: cortex.md
[ecs service connect]: cloud%20computing/aws/ecs.md#ecs-service-connect
[ecs service discovery]: cloud%20computing/aws/ecs.md#ecs-service-discovery
[grafana]: grafana.md [grafana]: grafana.md
[prometheus]: prometheus/README.md [prometheus]: prometheus/README.md
[thanos]: thanos.md [thanos]: thanos.md
@@ -540,5 +573,7 @@ Alternatives:
[website]: https://grafana.com/oss/mimir/ [website]: https://grafana.com/oss/mimir/
<!-- Others --> <!-- Others -->
[Gossip protocol]: https://en.wikipedia.org/wiki/Gossip_protocol
[Ceiling Function]: https://www.geeksforgeeks.org/ceiling-function/ [Ceiling Function]: https://www.geeksforgeeks.org/ceiling-function/
[Gossip protocol]: https://en.wikipedia.org/wiki/Gossip_protocol
[hashicorp/memberlist]: https://github.com/hashicorp/memberlist
[Mimir on AWS ECS Fargate]: https://github.com/grafana/mimir/discussions/3807#discussioncomment-4602413

View File

@@ -0,0 +1,509 @@
import * as pulumi from '@pulumi/pulumi';
import * as aws from '@pulumi/aws';
const dnsZone: pulumi.Output<aws.route53.GetZoneResult> = aws.route53.getZoneOutput({ name: 'example.com.' });
const ecsCluster: pulumi.Output<aws.ecs.GetClusterResult> = aws.ecs.getClusterOutput({ clusterName: 'development' });
const ecsTaskExecutionRole: pulumi.Output<aws.iam.GetRoleResult> = aws.iam.getRoleOutput({ name: 'DefaultEcsTaskExecutionRole' });
const privateSubnets: pulumi.Output<aws.ec2.GetSubnetsResult> = aws.ec2.getSubnetsOutput({
filters: [{
name: 'tag:Name',
values: [
'private-a',
'private-b',
'private-c',
],
}],
});
const vpc: pulumi.Output<aws.ec2.GetVpcResult> = aws.ec2.getVpcOutput({ default: true });
// FIXME: check before use
const securityGroup: aws.ec2.SecurityGroup = new aws.ec2.SecurityGroup(
'mimir',
{
name: 'mimir',
description: 'Manage access to and from the Mimir ECS service',
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Networking',
Name: 'Mimir',
},
vpcId: vpc.id,
},
);
new aws.vpc.SecurityGroupIngressRule(
'mimir-internalTraffic',
{
securityGroupId: securityGroup.id,
description: 'Traffic within the Security Group',
tags: {
Name: 'Intra-SG traffic',
},
referencedSecurityGroupId: securityGroup.id,
ipProtocol: '-1',
},
{
deleteBeforeReplace: true,
parent: securityGroup,
},
);
new aws.vpc.SecurityGroupIngressRule(
'mimir-VPC:IPv4-httpServer',
{
securityGroupId: securityGroup.id,
tags: {
Name: 'VPC IPv4 to HTTP server',
},
description: 'Access the Mimir HTTP server from resources in the VPC via IPv4',
cidrIpv4: vpc.cidrBlock,
ipProtocol: 'tcp',
fromPort: 8080,
toPort: 8080,
},
{
deleteBeforeReplace: true,
parent: securityGroup,
},
);
new aws.vpc.SecurityGroupIngressRule(
'mimir-VPC:IPv6-httpServer',
{
securityGroupId: securityGroup.id,
tags: {
Name: 'VPC IPv6 to HTTP server',
},
description: 'Access the Mimir HTTP server from resources in the VPC via IPv6',
cidrIpv6: vpc.ipv6CidrBlock,
ipProtocol: 'tcp',
fromPort: 8080,
toPort: 8080,
},
{
deleteBeforeReplace: true,
parent: securityGroup,
},
);
new aws.vpc.SecurityGroupIngressRule(
'mimir-VPC:IPv4-gRPCServer',
{
securityGroupId: securityGroup.id,
tags: {
Name: 'VPC IPv4 to gRPC server',
},
description: 'Access the Mimir gRPC server from resources in the VPC via IPv4',
cidrIpv4: vpc.cidrBlock,
ipProtocol: 'tcp',
fromPort: 9095,
toPort: 9095,
},
{
deleteBeforeReplace: true,
parent: securityGroup,
},
);
new aws.vpc.SecurityGroupIngressRule(
'mimir-VPC:IPv6-gRPCServer',
{
securityGroupId: securityGroup.id,
tags: {
Name: 'CurrentEverythingVpc IPv6 to gRPC server',
},
description: 'Access the Mimir gRPC server from resources in the VPC via IPv6',
cidrIpv6: vpc.ipv6CidrBlock,
ipProtocol: 'tcp',
fromPort: 9095,
toPort: 9095,
},
{
deleteBeforeReplace: true,
parent: securityGroup,
},
);
new aws.vpc.SecurityGroupEgressRule(
'mimir-allowAllIPv4',
{
securityGroupId: securityGroup.id,
tags: {
Name: 'All IPv4',
},
description: 'Connect everywhere from Mimir on IPv4',
cidrIpv4: '0.0.0.0/0',
ipProtocol: '-1',
},
{
deleteBeforeReplace: true,
parent: securityGroup,
},
);
new aws.vpc.SecurityGroupEgressRule(
'mimir-allowAllIPv6',
{
securityGroupId: securityGroup.id,
tags: {
Name: 'All IPv6',
},
description: 'Connect everywhere from Mimir on IPv6',
cidrIpv6: '::/0',
ipProtocol: '-1',
},
{
deleteBeforeReplace: true,
parent: securityGroup,
},
);
const bucket: aws.s3.BucketV2 = new aws.s3.BucketV2(
'mimir',
{
bucket: 'mimir',
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Storage',
},
},
);
const ecsTaskRole: aws.iam.Role = new aws.iam.Role(
'mimir-ecsTask',
{
name: 'Mimir-ECSTask',
description: 'Allow Mimir ECS tasks to access the resources they need',
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Server',
},
assumeRolePolicy: JSON.stringify({
Version: '2012-10-17',
Statement: [{
Effect: 'Allow',
Principal: {
Service: 'ecs-tasks.amazonaws.com',
},
Action: 'sts:AssumeRole',
}],
}),
},
);
new aws.iam.RolePolicy(
'mimir-ecsTask-allowRoleFunctions',
{
role: ecsTaskRole,
name: 'AllowRoleFunctions',
policy: pulumi.jsonStringify({
Version: '2012-10-17',
Statement: [{
Sid: 'AllowUsingS3BucketsForData',
Effect: 'Allow',
Action: [
's3:ListBucket',
's3:PutObject',
's3:GetObject',
's3:DeleteObject',
],
Resource: [
pulumi.interpolate `${bucket.arn}`,
pulumi.interpolate `${bucket.arn}/*`,
],
}],
}),
},
);
const cloudMap_namespace = new aws.servicediscovery.PrivateDnsNamespace(
'mimir',
{
name: 'mimir.dev.ecs.local',
description: 'Mimir Development',
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Networking',
},
vpc: vpc.id,
},
);
const cloudMap_service = new aws.servicediscovery.Service(
'mimir-memberlist',
{
name: 'memberlist',
description: 'Gossip ring for ingesters in Mimir',
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Networking',
},
namespaceId: cloudMap_namespace.id,
dnsConfig: {
namespaceId: cloudMap_namespace.id,
dnsRecords: [{
type: 'A',
ttl: 10,
}],
routingPolicy: 'MULTIVALUE',
},
},
);
const logGroup: aws.cloudwatch.LogGroup = new aws.cloudwatch.LogGroup(
'mimir',
{
name: '/ecs/dev/mimir',
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Server',
},
retentionInDays: 7,
},
);
const taskDefinition: aws.ecs.TaskDefinition = new aws.ecs.TaskDefinition(
'mimir',
{
family: 'mimir',
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Server',
},
networkMode: 'awsvpc',
requiresCompatibilities: [ 'FARGATE' ],
cpu: '512', // Fargate requirement. See <https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-tasks-services.html#fargate-tasks-size>.
memory: '1024', // Fargate requirement. See <https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-tasks-services.html#fargate-tasks-size>.
executionRoleArn: ecsTaskExecutionRole.arn, // logging requirement
taskRoleArn: ecsTaskRole.arn,
containerDefinitions: pulumi.jsonStringify([
{
name: 'mimir',
image: '012345678901.dkr.ecr.eu-west-1.amazonaws.com/cache/docker-hub/grafana/mimir:2.15.2',
essential: true,
command: [
'-auth.multitenancy-enabled=false',
pulumi.interpolate `-memberlist.join=dns+${cloudMap_service.name}.${cloudMap_namespace.name}:7946`,
'-common.storage.backend=s3',
'-common.storage.s3.endpoint=s3.eu-west-1.amazonaws.com', // required
pulumi.interpolate `-common.storage.s3.bucket-name=${bucket.bucket}`,
'-alertmanager-storage.storage-prefix=alertmanager',
'-blocks-storage.storage-prefix=blocks',
'-ruler-storage.storage-prefix=ruler',
'-ingester.max-global-series-per-user=300000',
'-ingester.out-of-order-time-window=5m',
'-ingester.ring.replication-factor=1', // required when using less than 3 replicas
],
// healthCheck: {
// // FIXME: the image uses `blobs` as base, which has no binaries but `mimir`
// // FIXME: mimir -target='continuous-test' -tests.write-endpoint='http://localhost:8080' -tests.read-endpoint='http://localhost:8080' -tests.smoke-test -server.http-listen-port='18080' -server.grpc-listen-port='19095' ??
// command: [
// 'CMD-SHELL',
// 'wget -qO- localhost:8080/ready || exit 1',
// ],
// startPeriod: 60, // it takes a while
// retries: 10,
// },
portMappings: [
{
name: 'memberlist',
protocol: 'tcp',
appProtocol: 'http',
containerPort: 7946,
hostPort: 7946,
},
{
name: 'api',
protocol: 'tcp',
appProtocol: 'http',
containerPort: 8080,
hostPort: 8080,
},
{
name: 'grpc',
protocol: 'tcp',
appProtocol: 'http',
containerPort: 9095,
hostPort: 9095,
},
],
logConfiguration: {
logDriver: 'awslogs',
options: {
'awslogs-group': logGroup.name,
'awslogs-region': 'eu-west-1',
'awslogs-stream-prefix': 'ecs/dev',
},
},
// explicitly specified to avoid showing changes on every run
environment: [],
mountPoints: [],
systemControls: [],
volumesFrom: [],
},
]),
},
);
const alb_targetGroup_http = new aws.alb.TargetGroup(
'mimir-http',
{
name: 'mimir-http',
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Networking',
},
vpcId: vpc.id,
targetType: 'ip',
ipAddressType: 'ipv4',
protocol: 'HTTP',
port: 8080,
healthCheck: {
path: '/ready',
},
},
);
const alb_targetGroup_grpc = new aws.alb.TargetGroup(
'mimir-grpc',
{
name: 'mimir-grpc',
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Networking',
},
vpcId: vpc.id,
targetType: 'ip',
ipAddressType: 'ipv4',
protocol: 'HTTP', // FIXME
port: 9095,
// healthCheck: {
// // FIXME
// path: '/ready',
// },
},
);
const alb = new aws.alb.LoadBalancer(
'mimir',
{
name: 'mimir',
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Networking',
},
internal: true,
ipAddressType: 'ipv4',
subnets: privateSubnets.ids,
securityGroups: [ securityGroup.id ],
accessLogs: {
bucket: bucket.bucket,
},
},
);
new aws.route53.Record(
'mimir',
{
zoneId: dnsZone.id,
name: pulumi.interpolate `mimir.dev.${dnsZone.name}`,
type: 'A',
aliases: [{
name: alb.dnsName,
zoneId: alb.zoneId,
evaluateTargetHealth: true,
}],
},
);
new aws.alb.Listener(
'mimir-http',
{
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Networking',
},
loadBalancerArn: alb.arn,
port: 8080,
protocol: 'HTTP',
defaultActions: [{
order: 1,
targetGroupArn: alb_targetGroup_http.arn,
type: 'forward',
}],
},
);
new aws.alb.Listener(
'mimir-grpc',
{
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Networking',
},
loadBalancerArn: alb.arn,
port: 9095,
protocol: 'HTTP', // FIXME?
defaultActions: [{
order: 1,
targetGroupArn: alb_targetGroup_grpc.arn,
type: 'forward',
}],
},
);
new aws.ecs.Service(
'mimir',
{
name: 'mimir',
tags: {
Environment: 'Development',
Application: 'Mimir',
Component: 'Server',
},
cluster: ecsCluster.arn,
taskDefinition: taskDefinition.arn,
desiredCount: 1, // requires mimir to start with the '-ingester.ring.replication-factor=1' option
launchType: 'FARGATE',
networkConfiguration: {
subnets: privateSubnets.ids,
securityGroups: [ securityGroup.id ],
},
loadBalancers: [
{
containerName: 'mimir',
containerPort: 8080,
targetGroupArn: alb_targetGroup_http.arn,
},
{
containerName: 'mimir',
containerPort: 9095,
targetGroupArn: alb_targetGroup_grpc.arn,
},
],
// enableExecuteCommand: true, // FIXME: the image uses `blobs` as base, which has no binaries but `mimir`
serviceRegistries: {
registryArn: cloudMap_service.arn,
},
},
{ deleteBeforeReplace: true },
);