iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 15
1
DevOps

用 CDK 定義 AWS 架構系列 第 15

Day 15 - 使用 CDK 控制 Elastic Load Balancing - Network Load Balancer

在負載平衡中 AWS 提供了我們三種負載平衡 Application Load Balancer(ALB)、Network Load Balancer(NLB) 與 Classic Load Balancer,而 Classic Load Balancer 屬於上一代的負載平衡所以並不會提到它

https://ithelp.ithome.com.tw/upload/images/20201001/20117701qD5IUlduzr.jpg

而 Network Load Balancer 與 Application Load Balancer 最大的不同點在於 Network Load Balancer 為第四層(Transport Layer) 服務而 Application Load Balancer 處於 第七層(Application Layer) 服務,如果以我們目前介紹的用法來出其實沒有太大的差別,因為我們都是把它當 HTTP 的負載平衡器來使用,不過還是先體驗一下吧!

建立 Load Balancing

建立 Network Load Balancer(NLB)

竟然說到 NLB 當然是先建立它拉!

const lb = new elbv2.NetworkLoadBalancer(this, "LB", {
  vpc,
  internetFacing: true,
});
new cdk.CfnOutput(this, "NetworkLoadBalancerDNS", {
  value: lb.loadBalancerDnsName,
});

新增 Listener

建立一個 port 80 的 Listener

const listener = lb.addListener("Listener", {
  port: 80,
});

新增 Target 到 Listener

這邊分為兩個建立方法,大家可以評估自己的需求來選用想要用的方法

使用 Instance type 方法建立

Target 設定為 Instance 與 IP 最大的不同在於 Security Group 的設定

使用 Instance Type 可以想像所有的流量會從 ALB 外面直接流進機器,而 NLB 不像是 ALB 一樣擁有 Security Group 因此無法使用 Security Group 對接的方法來保護機器,所以說對應到機器 Security Group 的 Port 需要全開,不然會沒有辦法通

listener.addTargets("Targets", {
  port: httpPort,
  targets: [
    new targets.InstanceTarget(ec2Instance),
  ],
});

使用 IP type 方法建立

Target 設定為 IP Type 的好處在於所有的流量會經由內網丟進去,所以在機器 Security Group 的地方就可以選用 VPC CIDR 的方法指定,以安全性來說可以阻止使用者使用機器的 Public IP 連線或許有的人比較喜歡此方法。
有人可能會詢問那這樣內部的機器是不是就沒有辦法知道 client 的 IP 呢?如果要支援大家可以開啟 proxy protocol version 2 的支援就可以了,不過此 Protocol 需要軟體支援大家需要特別注意!

listener.addTargets("Targets", {
  port: httpPort,
  targets: [
    new targets.IpTarget(ec2Instance.instancePrivateIp),
  ],
});

詳細的 Security 規則大家可以參考 AWS 文件

整理整個服務的 Code

只要使用以上兩個步驟就可以把整個 Network Load Balancer 完成,感覺是不是很快呢 XD
因為這邊的步驟怕大家搞混,所以我們把 Instance type 建立方法與 IP type 建立方法獨立成兩種方法讓大家比較好理解

使用 Instance type 方法建立

const vpc = new ec2.Vpc(this, "VPC", {
  maxAzs: 3,
  natGateways: 0,
});

const mySecurityGroup = new ec2.SecurityGroup(this, "SecurityGroup", {
  vpc,
  allowAllOutbound: true,
});
mySecurityGroup.addIngressRule(
  ec2.Peer.anyIpv4(),
  ec2.Port.tcp(22),
  "allow public ssh access"
);

mySecurityGroup.addIngressRule(
  ec2.Peer.anyIpv4(),
  ec2.Port.tcp(80),
  "allow public http access"
);

const asset = new assets.Asset(this, "Asset", {
  path: path.join(__dirname, "../", "ec2-config", "configure.sh"),
});

const ec2Instance = new ec2.Instance(this, "Instance", {
  vpc,
  instanceType: ec2.InstanceType.of(
    ec2.InstanceClass.T3,
    ec2.InstanceSize.NANO
  ),
  machineImage: ec2.MachineImage.latestAmazonLinux({
    generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
  }),
  securityGroup: mySecurityGroup,
  vpcSubnets: {
    subnetType: ec2.SubnetType.PUBLIC,
  },
  keyName: "KeyPair",
});
new cdk.CfnOutput(this, "EC2PublicDns", {
  value: ec2Instance.instancePublicDnsName,
});
new cdk.CfnOutput(this, "EC2PublicIp", {
  value: ec2Instance.instancePublicIp,
});

const localPath = ec2Instance.userData.addS3DownloadCommand({
  bucket: asset.bucket,
  bucketKey: asset.s3ObjectKey,
});
ec2Instance.userData.addExecuteFileCommand({
  filePath: localPath,
  arguments: "--verbose -y",
});
asset.grantRead(ec2Instance.role);

const httpPort = 80;
const lb = new elbv2.NetworkLoadBalancer(this, "LB", {
  vpc,
  internetFacing: true,
});
new cdk.CfnOutput(this, "NetworkLoadBalancerDNS", {
  value: lb.loadBalancerDnsName,
});

const listener = lb.addListener("Listener", {
  port: httpPort,
});

listener.addTargets("Targets", {
  port: httpPort,
  targets: [
    new targets.InstanceTarget(ec2Instance),
  ],
});

使用 IP type 方法建立

const vpc = new ec2.Vpc(this, "VPC", {
  maxAzs: 3,
  natGateways: 0,
});

const mySecurityGroup = new ec2.SecurityGroup(this, "SecurityGroup", {
  vpc,
  allowAllOutbound: true,
});
mySecurityGroup.addIngressRule(
  ec2.Peer.anyIpv4(),
  ec2.Port.tcp(22),
  "allow public ssh access"
);

mySecurityGroup.addIngressRule(
  ec2.Peer.ipv4(vpc.vpcCidrBlock),
  ec2.Port.tcp(80),
  "allow vpc cidr http access"
);

const asset = new assets.Asset(this, "Asset", {
  path: path.join(__dirname, "../", "ec2-config", "configure.sh"),
});

const ec2Instance = new ec2.Instance(this, "Instance", {
  vpc,
  instanceType: ec2.InstanceType.of(
    ec2.InstanceClass.T3,
    ec2.InstanceSize.NANO
  ),
  machineImage: ec2.MachineImage.latestAmazonLinux({
    generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
  }),
  securityGroup: mySecurityGroup,
  vpcSubnets: {
    subnetType: ec2.SubnetType.PUBLIC,
  },
  keyName: "KeyPair",
});
new cdk.CfnOutput(this, "EC2PublicDns", {
  value: ec2Instance.instancePublicDnsName,
});
new cdk.CfnOutput(this, "EC2PublicIp", {
  value: ec2Instance.instancePublicIp,
});

const localPath = ec2Instance.userData.addS3DownloadCommand({
  bucket: asset.bucket,
  bucketKey: asset.s3ObjectKey,
});
ec2Instance.userData.addExecuteFileCommand({
  filePath: localPath,
  arguments: "--verbose -y",
});
asset.grantRead(ec2Instance.role);

const httpPort = 80;
const lb = new elbv2.NetworkLoadBalancer(this, "LB", {
  vpc,
  internetFacing: true,
});
new cdk.CfnOutput(this, "NetworkLoadBalancerDNS", {
  value: lb.loadBalancerDnsName,
});

const listener = lb.addListener("Listener", {
  port: httpPort,
});

listener.addTargets("Targets", {
  port: httpPort,
  targets: [
    new targets.IpTarget(ec2Instance.instancePrivateIp),
  ],
});

測試 NLB 網址

目前拿到的

測試 Test Page

打開它試試看
https://ithelp.ithome.com.tw/upload/images/20200929/201177010EWKEhmVm0.png

測試 phpinfo.php

http://cdkec-albae-1qhysttihzwc-231561288.us-west-2.elb.amazonaws.com/phpinfo.php

https://ithelp.ithome.com.tw/upload/images/20200929/20117701nwoy0p1IgZ.png

結論

基本上與昨天的結果會是一樣的,因為測試的範例是使用 HTTP 網頁作為範例,所以比較沒有感覺

而 Network Load Balancer 主要是用來解決需要處理第四層以上的服務所生的,想要理解更多可以查看一下 AWS Console 打開 Listeners 可以看到除了 TCP 還可以支援 TLS、UDP 或是同時處理 TCP 與 UDP 的服務
https://ithelp.ithome.com.tw/upload/images/20200929/20117701sBEAt55WxC.png

TLS 支援

以 TLS 來說我們可能有一個服務是 RTSP 而我們的程式可能因為某些原因不方便直接讓程式支援 TLS 可以又必須支援 RTSP over SSL 的時候所使用

UDP 支援

以 UDP 來說可能是 DNS 服務或是 QUIC

TCP 與 UDP

可能類似 DNS


以上為今日的 Network Load Balancer 介紹,希望有幫助到大家

想要看更多嗎?歡迎到我的部落格參觀

文章內容主要是網路或是程式開發類型的文章

本文同步刊載於 Clarence 部落格:Day 15 - 使用 CDK 控制 Elastic Load Balancing - Network Load Balancer


「AWS CDK 完全學習手冊:打造雲端基礎架構程式碼 IaC」
本書改編並延伸自第 12 屆 iT 邦幫忙鐵人賽獲得 DevOps 組冠軍的《用 CDK 定義 AWS 架構》系列文章,以簡單、好讀的行文風格詳述技術細節,並提供完整的程式碼範例與說明,一步一步帶領新手從零開始踏上 AWS CDK 技術達人之路。

有興趣的朋友歡迎至天瓏書局選購!

購書連結 https://bit.ly/2ZMAebE

https://ithelp.ithome.com.tw/upload/images/20211103/20117701W7l6fQnn2L.jpg


上一篇
Day 14 - 使用 CDK 控制 Elastic Load Balancing - Application Load Balancer
下一篇
Day 16 - 要串接 API 除了 API Gateway 你還有另外的選擇 Application Load Balancer
系列文
用 CDK 定義 AWS 架構30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言