mirror of
https://gitea.com/mcereda/oam.git
synced 2026-02-09 05:44:23 +00:00
chore(mimir): run on aws ecs fargate
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
);
|
||||||
Reference in New Issue
Block a user