Use terraform or ACK apigatewayv2 EKS operator to set up apigateway in AWS

The daigram

1
2mock-restapi.example.dev(route53) -----> apigateway -----> vpclink -------> private aws nlb (eks ingress) ---> app servcie

Use Terraform to create apigateway restapi resource

to apply the resources and mapping the apigateway domain name to route53 to access the eks services

  • create the route53 and domain name and vpc link to access eks services
 1resource "aws_api_gateway_vpc_link" "to-private-nlb" {
 2  name        = "to-private-nlb"
 3  description = "rest api to private nlb"
 4  target_arns = ["arn:aws:elasticloadbalancing:xxxxx:xxxxx:loadbalancer/net/xxxxxx/xxxxxx"]
 5}
 6
 7data "aws_route53_zone" "example_dev" {
 8  name         = "example.dev."
 9  private_zone = false
10}
11
12resource "aws_api_gateway_domain_name" "mock_restapi_example_dev" {
13  domain_name              = "mock-restapi.example.dev"
14  regional_certificate_arn = "arn:aws:acm:xxxxxx:xxxxxxx:certificate/xxxxxx-xxxxxx-xxx-xxxxx"
15
16  endpoint_configuration {
17    types = ["REGIONAL"]
18  }
19}
20
21resource "aws_route53_record" "mock_restapi_example_dev" {
22  name    = aws_api_gateway_domain_name.mock_restapi_example_dev.domain_name
23  type    = "A"
24  zone_id = data.aws_route53_zone.example_dev.id
25
26  alias {
27    evaluate_target_health = true
28    name                   = aws_api_gateway_domain_name.mock_restapi_example_dev.regional_domain_name
29    zone_id                = aws_api_gateway_domain_name.mock_restapi_example_dev.regional_zone_id
30  }
31}
  • create the rest api resource and method and integration
 1resource "aws_api_gateway_rest_api" "mock_rest_api" {
 2  name        = "mock-rest-api"
 3  description = "Testing for integration the private NLB"
 4
 5  endpoint_configuration {
 6    types = ["REGIONAL"]
 7  }
 8}
 9
10resource "aws_api_gateway_resource" "root" {
11  rest_api_id = aws_api_gateway_rest_api.mock_rest_api.id
12  parent_id   = aws_api_gateway_rest_api.mock_rest_api.root_resource_id
13  path_part   = "{proxy+}"
14}
15
16
17resource "aws_api_gateway_method" "all" {
18  rest_api_id   = aws_api_gateway_rest_api.mock_rest_api.id
19  resource_id   = aws_api_gateway_resource.root.id
20  http_method   = "ANY"
21  authorization = "NONE"
22
23  request_parameters = {
24    "method.request.path.proxy" = true
25  }
26}
27
28resource "aws_api_gateway_integration" "vpclink_integration" {
29  rest_api_id = aws_api_gateway_rest_api.mock_rest_api.id
30  resource_id = aws_api_gateway_resource.root.id
31  http_method = aws_api_gateway_method.all.http_method
32  #   request_templates = {
33  #     "application/json" = ""
34  #     "application/xml"  = "#set($inputRoot = $input.path('$'))\n{ }"
35  #   }
36
37  request_parameters = {
38    "integration.request.path.proxy" = "method.request.path.proxy"
39    # "integration.request.header.X-hpa"           = "method.request.header.path"
40  }
41
42  type                    = "HTTP"
43  uri                     = "https://private-nlb.example.dev/{proxy}"
44  integration_http_method = "ANY"
45  passthrough_behavior    = "WHEN_NO_MATCH"
46  content_handling        = "CONVERT_TO_TEXT"
47
48  connection_type = "VPC_LINK"
49  connection_id   = aws_api_gateway_vpc_link.to-private-nlb.id
50}
  • Create request and response integration and domain base path mapping to route53 record
 1resource "aws_api_gateway_method_response" "all" {
 2  rest_api_id = aws_api_gateway_rest_api.mock_rest_api.id
 3  resource_id = aws_api_gateway_resource.root.id
 4  http_method = aws_api_gateway_method.all.http_method
 5  status_code = "200"
 6}
 7
 8resource "aws_api_gateway_integration_response" "all" {
 9  rest_api_id = aws_api_gateway_rest_api.mock_rest_api.id
10  resource_id = aws_api_gateway_resource.root.id
11  http_method = aws_api_gateway_method.all.http_method
12  status_code = aws_api_gateway_method_response.all.status_code
13
14  depends_on = [
15    aws_api_gateway_method.all,
16    aws_api_gateway_integration.vpclink_integration
17  ]
18}
19
20resource "aws_api_gateway_base_path_mapping" "mock_rest_api" {
21  api_id      = aws_api_gateway_rest_api.mock_rest_api.id
22  domain_name = aws_api_gateway_domain_name.mock_restapi_example_dev.id
23  stage_name  = aws_api_gateway_stage.main.stage_name
24
25
26  depends_on = [
27    aws_api_gateway_deployment.mock_rest_api,
28    aws_api_gateway_stage.main
29  ]
30}
  • create the deployment and stage and method setting to enable logs and metrics
 1resource "aws_api_gateway_deployment" "mock_rest_api" {
 2  rest_api_id = aws_api_gateway_rest_api.mock_rest_api.id
 3
 4  triggers = {
 5    redeployment = sha1(jsonencode(aws_api_gateway_rest_api.mock_rest_api.body))
 6  }
 7
 8  lifecycle {
 9    create_before_destroy = true
10  }
11
12  depends_on = [
13    aws_api_gateway_domain_name.mock_restapi_example_dev,
14    aws_api_gateway_method.all,
15    aws_api_gateway_integration.vpclink_integration
16  ]
17}
18
19resource "aws_api_gateway_stage" "main" {
20  deployment_id = aws_api_gateway_deployment.mock_rest_api.id
21  rest_api_id   = aws_api_gateway_rest_api.mock_rest_api.id
22  stage_name    = "main"
23
24
25  depends_on = [
26    aws_api_gateway_method.all,
27    aws_api_gateway_integration.vpclink_integration
28  ]
29}
30
31resource "aws_api_gateway_method_settings" "mock_rest_api" {
32  rest_api_id = aws_api_gateway_rest_api.mock_rest_api.id
33  stage_name  = aws_api_gateway_stage.main.stage_name
34  method_path = "*/*"
35
36  settings {
37    metrics_enabled = true
38    logging_level   = "INFO"
39  }
40}

Use ACK operator and apigatewayv2 to create

  • to install the ACK operator apigatewayv2 controller
1# login to aws ecr public registry
2aws ecr-public get-login-password --region us-east-1 | helm registry login --username AWS --password-stdin public.ecr.aws
3# pull the apigatewayv2 controller helm chart
4helm pull oci://public.ecr.aws/aws-controllers-k8s/apigatewayv2-chart
5# install the helm chart to eks cluster
6helm install --create-namespace -n ack-system ack-apigatewayv2-controller ./apigatewayv2 --set=aws.region=us-east-1
  • and create eks crd resources
 1apiVersion: apigatewayv2.services.k8s.aws/v1alpha1
 2kind: VPCLink
 3metadata:
 4  name: "mock-httpapi-to--private-nlb"
 5  namespace: "default"
 6spec:
 7  name: "mock-httpapi-to-istio-private-nlb"
 8  # securityGroupIDs:
 9  # - ""
10  subnetIDs:
11  - "subnet-xxxxxxx"
12  - "subnet-xxxxxxx"
13  - "subnet-xxxxxxx"
14  tags: { "Team": "xxxxxx", "Environment": "Dev"}
15
16---
17apiVersion: apigatewayv2.services.k8s.aws/v1alpha1
18kind: API
19metadata:
20  name: "mock-httpapi-testing"
21  namespace: "default"
22spec:
23  name: "mock-httpapi-testing"
24  protocolType: HTTP
25
26---
27apiVersion: apigatewayv2.services.k8s.aws/v1alpha1
28kind: Integration
29metadata:
30  name: "mock-httpapi-testing"
31  namespace: "default"
32spec:
33  apiRef:
34    from:
35      name: "mock-httpapi-testing"
36  integrationType: HTTP_PROXY
37  integrationURI: "arn:aws:elasticloadbalancing:us-east-1:xxxxxxxx:listener/net/istio-private-ingress-gateway/xxxxx/xxxxxx"
38  connectionType: "VPC_LINK"
39  connectionRef:
40    from:
41      name: "mock-httpapi-to-istio-private-nlb"
42  integrationMethod: ANY
43  payloadFormatVersion: "1.0"
44---
45apiVersion: apigatewayv2.services.k8s.aws/v1alpha1
46kind: Authorizer
47metadata:
48  name: "mock-httpapi-testing"
49  namespace: "default"
50spec:
51  name: "mock-httpapi-testing"
52  apiRef:
53    from:
54      name: "mock-httpapi-testing"
55  authorizerType: "JWT"
56  identitySource:
57  - "$request.header.Authorization"
58  jwtConfiguration:
59    audience:
60      - "openid"
61    issuer: "https://service.xxxxxxx.dev/sso"
62---
63apiVersion: apigatewayv2.services.k8s.aws/v1alpha1
64kind: Route
65metadata:
66  name: "mock-httpapi-testing"
67  namespace: "default"
68spec:
69  apiRef:
70    from:
71      name: "mock-httpapi-testing"
72  routeKey: "ANY /{proxy+}"
73  targetRef:
74    from:
75      name: "mock-httpapi-testing"
76  authorizationType: "JWT"
77  authorizerRef:
78    from:
79      name: "mock-httpapi-testing"    
80---
81apiVersion: apigatewayv2.services.k8s.aws/v1alpha1
82kind: Stage
83metadata:
84  name: "mock-httpapi-testing"
85  namespace: "default"
86spec:
87  apiRef:
88    from:
89      name: "mock-httpapi-testing"
90  stageName: "main"
91  autoDeploy: true
92  description: "auto deployed stage for mock-httpapi-testing"

Caution the apigateway has restricts

  • The ACK support HTTP APIS and WebSocket API current only ACK service
  • integration the apigatewayv2 with EKS
  • apigatewayv2 support (http api, websocket api), apigateway support(Rest api)
  • While HTTP APIs are designed with minimal features so that they can be offered at a lower price. Choose REST APIs if you need features such as API keys, per-client throttling, request validation, AWS WAF integration, or private API endpoints. Choose HTTP APIs if you don’t need the features included with REST APIs. REST API vs HTTP API
  • Maximum integration timeout: 30s (No Increased)
  • Payload size(10MB) (No Increased)
  • Timeout for Lambda authorizer response(10s No increased)

References