AWS VPC Endpoint 使用場景

POSTED BY   Chris
2022 年 3 月 14 日
AWS VPC Endpoint 使用場景

VPC Endpoint 之前總是看過觀念和文件,沒實地 hands-on 過,這次剛好有同事提到相關問題,就趁著這次好好操作一次並釐清一些概念,順手記錄下來,不免俗的,一樣會用 AWS CDK 搭配觀看 AWS Management Console 來理解

 

為何需要 AWS VPC Endpoint ?

個人認為最主要有兩個原因,一個是安全性、一個是節費,安全性的意思是如果 application 有高度安全要求,application 彼此間的所有連線,都想要走內網,不透過 Internet,那麼 AWS VPC Endpoint 是一個解決方案 (但不包含 VPC Gateway Endpoint)

另外節費的狀況是,例如 Server 的 Cloud 架構上,Best Practice 都會建議在隔離的環境下,例如 instance (不論 EC2 or ECS等) 掛在 Load Balance 之後,不綁定 public ip,也就是 input 都是經由 LB 進來,而 output 如果只有連線 AWS 服務,例如 application 只有用到 S3 服務,那麼不一定需要開 NAT Gateway,而是只要開啟 VPC Interface Endpoint,也就是打開一條通道可以連線到 S3,而且 network route 不用經由 internet,就可以節省開啟 NAT Gateway 的費用

 

VPC Endpoint 介紹

VPC Endpoint 屬於 AWS PrivateLink 的一種,AWS PrivateLink 切分兩大類,一種是本篇要介紹的 VPC Endpoint,另一種是 VPC Endpoint Service,VPC Endpoint 主要的功能是連接到 AWS Service,support service 非常多,可以參考這個連結,而 VPC Endpoint Service 最主要是針對自架的服務,一樣可以在 VPC 中打一條 private 通道到自架的服務,而本篇只會介紹 VPC Endpoint 的部分

而 VPC Endpoint 又分為 VPC Interface Endpoint 和 VPC Gateway Endpoint,VPC Interface Endpoint 支援的 AWS 服務如之前所述,非常的多,而 VPC Gateway Endpoint 就只有支援 S3 和 DynamoDB,而 VPC Gateway Endpoint 特點是完全免費,而 VPC Gateway Endpoint 連接的目標服務是 public ip,例如連線到 S3 endpoint 這個 endpoint 是 public ip

而區別 VPC Interface Endpoint 和 VPC Gateway Endpoint 的差異,以 S3 為例,要連接 S3 使用這兩種 VPC Endpoint 都可以,但還是有滿多差異的,如使用 public ip or private ip 就完全不一樣,更多差異可以參考此連結,故使用前可以先評估一下需求再做決定

 

實作

這邊以 ECS On Fargate 來說明,Fargate Service 的設定如下

  • 不 Auto Assign Public IP,ECS task 只有 attach private ip
  • subnet 上不掛 NAT Gateway,此時 subnet 是 private isolated 的類型,也就是對外連線都出不去

而實作的場景中,ECS Fargate 需要 Pull ECR image 來 deployment,故需要開 VPC Endpoint 來打通到 ECR endpoint,整個實作的參考文件是以下這篇

這邊使用 AWS CDK 來實作,程式碼如下

TypeScript
new ec2.InterfaceVpcEndpoint(this, 'VPCEndpointForECRApi', {
  vpc: this.vpc,
  service: new ec2.InterfaceVpcEndpointService('com.amazonaws.ap-northeast-1.ecr.api', 443),
  subnets: {
    subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
    availabilityZones: ['ap-northeast-1a', 'ap-northeast-1c']
  },
  privateDnsEnabled: true,
});

new ec2.InterfaceVpcEndpoint(this, 'VPCEndpointForECRDkr', {
  vpc: this.vpc,
  service: new ec2.InterfaceVpcEndpointService('com.amazonaws.ap-northeast-1.ecr.dkr', 443),
  subnets: {
    subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
    availabilityZones: ['ap-northeast-1a', 'ap-northeast-1c']
  },
  privateDnsEnabled: true,
});

new ec2.InterfaceVpcEndpoint(this, 'VPCEndpointForCW', {
  vpc: this.vpc,
  service: new ec2.InterfaceVpcEndpointService('com.amazonaws.ap-northeast-1.logs', 443),
  subnets: {
    subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
    availabilityZones: ['ap-northeast-1a', 'ap-northeast-1c']
  },
  privateDnsEnabled: true,  
});

new ec2.InterfaceVpcEndpoint(this, 'VPCEndpointForSecretManager', {
  vpc: this.vpc,
  service: new ec2.InterfaceVpcEndpointService('com.amazonaws.ap-northeast-1.secretsmanager', 443),
  subnets: {
    subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
    availabilityZones: ['ap-northeast-1a', 'ap-northeast-1c']
  },
  privateDnsEnabled: true,
});

new ec2.InterfaceVpcEndpoint(this, 'VPCEndpointForSSM', {
  vpc: this.vpc,
  service: new ec2.InterfaceVpcEndpointService('com.amazonaws.ap-northeast-1.ssm', 443),
  subnets: {
    subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
    availabilityZones: ['ap-northeast-1a', 'ap-northeast-1c']
  },
  privateDnsEnabled: true, 
});

new ec2.InterfaceVpcEndpoint(this, 'VPCEndpointForSSMMessage', {
  vpc: this.vpc,
  service: new ec2.InterfaceVpcEndpointService('com.amazonaws.ap-northeast-1.ssmmessages', 443),
  subnets: {
    subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
    availabilityZones: ['ap-northeast-1a', 'ap-northeast-1c']
  },
  privateDnsEnabled: true, 
});

const s3GatewayEndpoint = this.vpc.addGatewayEndpoint('VpcS3GatewayEndpoint', {
  service: ec2.GatewayVpcEndpointAwsService.S3,
  subnets: [
    {
      subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
      availabilityZones: ['ap-northeast-1a', 'ap-northeast-1c']
    }
  ],
});

完整的程式碼在這裡

這邊依照文件的說明,因為是使用 Fargate version 1.4.0,故需要開 ecs.dkrecs.api 兩個 VPC Interface Endpoint,而其餘像 logs、S3 VPC Gateway Endpoint、secret management、ssm 等 VPC Interface Endpoint 也是文件中有提到的,就一起開啟了

待 deploy 完畢後,就可以看 AWS Management Console 中看一下,如下截圖

點擊圖片可放大

這邊可以看到在 Endpoint Type 有一個是 Gateway,其餘都是 interface,S3 VPC Gateway Endpoint 是照 AWS 文件上建議的來開啟,如果想用 S3 Interface Endpoint 也是沒問題的,Deploy 後就實際來測看看,把 ECS Service 的 desired count 改為大於 0 的數字,讓 task 實際 pull ECR image 來試試

而如果在還沒開 VPC Endpoint 前,會得到以下錯誤訊息

ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve ecr registry auth: service call has been retried 3 time(s): RequestError: send request failed caused by: Post https://api.ecr....

而開啟 VPC Endpoint 後,一切就打通沒問題了

 

補充

VPC Gateway Endpoint 的概念是生效在 Route Table 上,所以在 ECS Service 的 subnet 上可以看到如下 Route Table

點擊圖片可放大

Destination 選擇 S3 (可以在 EC2 的 Managed prefix lists 看到),而 Target 當然就是選擇建立出來的 VPC Endpoint

而 VPC Interface Endpoint 是直接選定 subnet,新建後就直接在 subnet 中生效,在 Route Table 上是看不到的,所以跟 VPC Gateway Endpoint 的方式略有不同

 

結論

VPC Endpoint 除了安全性以外,個人覺得最大的好處是節費,但缺點就是根據 Application 使用到的 AWS Service 有幾種就需要開幾個 VPC Endpoint,也挺累人的,相較於 NAT Gateway 來說比較麻煩一些,但如果 Application 需要連線非 AWS 服務的時候,這時候 NAT Gateway 就省不掉了,所以還是需要先了解需求,再決定要開哪種服務

歡迎留言
0

您可能也想看

Workaround for AWS Grafana alerting
2023 年 8 月 3 日
AWS, DevOps
CDK 指定 Physical names 運作方式
2021 年 12 月 4 日
AWS, CDK, Cloudformation
CDK Pipelines – 專為 CDK 打造的 CI/CD 利器
2021 年 11 月 7 日
AWS, CDK, DevOps, CI/CD