Sim*_*leJ 3 amazon-web-services amazon-cloudfront docker aws-fargate aws-cdk
我正在尝试使用 AWS-CDK 将相当基本的 Nodejs CRUD API 部署到 AWS。该服务在 Docker 容器中运行,我将其部署到 ALB 后面的 ECS Fargate 集群。我在 Route53 中也有一个我正在尝试使用的域。
我遇到的问题是我似乎无法通过域访问 ALB。我可以通过 HTTP 使用其默认 AWS DNS (XXXXX.us-west-2.elb.amazonaws.com/) 直接访问 ALB,但当我尝试通过域访问它时,出现 504 超时。
我对 AWS 和 CDK 还很陌生,所以我确信我在这里遗漏了一些明显的东西。任何建议或推荐的资源/示例将不胜感激。这是我的 CDK 代码:
import { Stack, StackProps } from "aws-cdk-lib";
import { Construct } from "constructs";
import * as Cloudfront from "aws-cdk-lib/aws-cloudfront";
import * as CloudfrontOrigins from "aws-cdk-lib/aws-cloudfront-origins";
import * as Route53 from "aws-cdk-lib/aws-route53";
import * as Route53Targets from "aws-cdk-lib/aws-route53-targets";
import * as ACM from "aws-cdk-lib/aws-certificatemanager";
import * as EC2 from "aws-cdk-lib/aws-ec2";
import * as ECS from "aws-cdk-lib/aws-ecs";
import * as EcsPatterns from "aws-cdk-lib/aws-ecs-patterns";
interface Props extends StackProps {
domainName: string;
dockerDir: string;
}
export class AppStack extends Stack {
constructor(scope: Construct, id: string, { domainName, dockerDir, ...rest }: Props) {
super(scope, id, rest);
const hostedZone = Route53.HostedZone.fromLookup(this, `${id}_Zone`, {
domainName,
});
const vpc = new EC2.Vpc(this, `${id}_Vpc`, { maxAzs: 2 });
const cluster = new ECS.Cluster(this, `${id}_Ec2Cluster`, { vpc });
cluster.addCapacity(`${id}_DefaultAutoScalingGroup`, {
instanceType: EC2.InstanceType.of(
EC2.InstanceClass.T3,
EC2.InstanceSize.MICRO
),
minCapacity: 1,
maxCapacity: 3,
});
const certificate = new ACM.DnsValidatedCertificate(
this,
`${id}_SiteCertificate`,
{
domainName,
hostedZone,
region: "us-east-1",
}
);
const fargateService = new EcsPatterns.ApplicationLoadBalancedFargateService(
this,
`${id}_FargateLoadBalancedService`,
{
cluster,
desiredCount: 1,
publicLoadBalancer: true,
taskImageOptions: {
image: ECS.ContainerImage.fromAsset(dockerDir),
containerPort: 8000,
environment: {
PORT: '8000',
},
},
}
);
const distribution = new Cloudfront.Distribution(
this,
`${id}_SiteDistribution`,
{
certificate,
domainNames: [domainName],
minimumProtocolVersion: Cloudfront.SecurityPolicyProtocol.TLS_V1_2_2021,
defaultBehavior: {
origin: new CloudfrontOrigins.HttpOrigin(
fargateService.loadBalancer.loadBalancerDnsName
),
compress: false,
cachePolicy: Cloudfront.CachePolicy.CACHING_DISABLED,
allowedMethods: Cloudfront.AllowedMethods.ALLOW_ALL,
},
}
);
new Route53.ARecord(this, `${id}_SiteAliasRecord`, {
recordName: domainName,
target: Route53.RecordTarget.fromAlias(
new Route53Targets.CloudFrontTarget(distribution)
),
zone: hostedZone,
});
}
}
Run Code Online (Sandbox Code Playgroud)
这个类是在我的 bin/infra.ts 文件中创建的:
#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "aws-cdk-lib";
import * as path from "path";
import { AppStack } from "../lib/AppStack";
const appId = `MyApp`;
const app = new cdk.App();
new AppStack(app, `${appId}Stack`, {
dockerDir: path.resolve(__dirname, "..", "api"), // contains the Dockerfile
domainName: 'mydomain.com',
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
},
});
Run Code Online (Sandbox Code Playgroud)
这是 Dockerfile,以防万一它有用。
FROM node:16-alpine as builder
ENV NODE_ENV build
USER node
WORKDIR /home/node
COPY package*.json ./
RUN npm i
COPY --chown=node:node . .
RUN npm run build \
&& npm prune --production
# ---
FROM node:16-alpine
ENV PORT 8000
ENV NODE_ENV production
# Add curl for healthcheck
RUN apk --no-cache add curl
USER node
WORKDIR /home/node
COPY --from=builder --chown=node:node /home/node/package*.json ./
COPY --from=builder --chown=node:node /home/node/node_modules/ ./node_modules/
COPY --from=builder --chown=node:node /home/node/dist/ ./dist/
EXPOSE 8000
CMD ["node", "dist/main.js"]
HEALTHCHECK CMD curl -f http://localhost:8000/api/healthcheck || exit 1
Run Code Online (Sandbox Code Playgroud)
当我通过我的域访问我的服务时,为什么会收到 504 错误?或者我可以在哪里寻找以更好地了解我所缺少的内容?
默认情况下,CloudFront 通过 HTTPS(端口 443)与其源进行对话。ALB(无论是由构造显式创建还是隐式创建ApplicationLoadBalancedFargateService)默认侦听 HTTP(端口 80),除非显式设置为 HTTPS。由于您的 ALB 未配置为侦听 HTTPS,CloudFront 会尝试与仅侦听 HTTP 的 ALB 进行 HTTPS 通信。
要解决此问题,请设置origin.protocolPolicy为OriginProtocolPolicy.HTTP_ONLY,这会指示 CloudFront 与您的 ALB 进行 HTTP 通信。请注意,下面的代码使用 CDK v2,而且我也使用了LoadBalancerV2Originover HttpOrigin,尽管两者的工作原理应该相同。
const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', {
vpc,
internetFacing: true,
});
new cloudfront.Distribution(this, 'myDist', {
defaultBehavior: {
new origins.LoadBalancerV2Origin(loadBalancer, {
protocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY,
})
},
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1499 次 |
| 最近记录: |