この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
前回のブログ では プロキシサーバー シングル構成の検証環境を構築しました。
今回は 高可用性(HA)を目的としたプロキシサーバー冗長化 を検証してみます。 想定する本番環境は下記の通り。
※ そもそもプロキシサーバーを使用している理由
などは前回のブログを参照ください
目次
環境構築
検証環境は以下のとおりです。
- 2つの Availability Zone(AZ) にそれぞれサブネットを作成
- プロキシサーバーを 2サブネットに配置する Auto Scaling Group を作成
- Network Load Balancer (NLB) を使って ターゲットを分散
APPサーバーから NLB → Proxyサーバー経由で Serviceを利用できるか確かめてみます。 構築は勉強も兼ねて CloudFormation(CFn)で行います。
github に今回作成した CFnテンプレートを上げています。
- 00-network.yaml: ネットワークリソース作成用
- 01-sg.yaml: セキュリティグループ作成用
- 02-nlb.yaml: NLB 作成用
- 03-as.yaml: Auto Scaling Group 作成用
- 04-ec2-service.yaml: サービスサーバー (Linux) 作成用
- 05-ec2-app.yaml: アプリサーバー (Windows) 作成用
以降、Proxy-VPC内の システム周りを中心に説明します。
NLB
下記 3リソースを作成します。
- LoadBalancer (AWS CloudFormation ドキュメント)
- TargetGroup (AWS CloudFormation ドキュメント)
- Listener (AWS CloudFormation ドキュメント)
▼— LoadBalancer ---
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub ${Prefix}-nlb
Type: network
Scheme: internal
IpAddressType: ipv4
Subnets:
- Fn::ImportValue: !Sub ${Prefix}-subnet2-a
- Fn::ImportValue: !Sub ${Prefix}-subnet2-c
- NLBを作成するので
Type: network
とします - 内部向けを想定しているので
Scheme: internal
とします - NLBを 2サブネットに設置するための設定を
Subnets:
に記載します
▼— TargetGroup ---
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub ${Prefix}-nlb-tg
TargetType: instance
Protocol: TCP
Port: 3128 # squid
VpcId:
Fn::ImportValue: !Sub ${Prefix}-vpc2
後ほどこのターゲットグループが Auto Scaling Group と関連付けられます。
NLBは ターゲットグループに対して Protocol: TCP
、 Port: 3128
(squidで使うポート番号) のリクエストを送信します。
TargetType:
は instance
もしくは ip
が選択できます。今回は instance
を選択しますが、
留意点は TargetType:
によって NLBから送られる パケットの送信元IPアドレス が変わる ことです。
インスタンス ID を使用してターゲットを指定すると、 クライアントの送信元 IP アドレス が保持 され、アプリケーションに提供されます。
ターゲットを IP アドレスで指定する場合、送信元 IP アドレスは ロードーバランサノードのプライベート IP アドレス となります。
▼— Listener ---
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
Port: 3128
Protocol: TCP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref NLBTargetGroup
LoadBalancerArn: !Ref NLB
- クライアントからのリクエストを
Port: 3128
、Protocol: TCP
で受け付けます DefaultActions:
でアクションを設定します。 リクエストを指定したTargetGroup
へルーティング (forward
) します。
セキュリティグループ
NLB構成としたことでプロキシサーバーに設定するセキュリティグループの設定内容が少々変わってきます。
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: SG for Proxy Server
GroupName: !Sub ${Prefix}-proxy-sg
VpcId:
Fn::ImportValue: !Sub ${Prefix}-vpc2
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3128
ToPort: 3128
CidrIp: 10.0.0.0/24 # from Proxy-VPC (for healthcheck)
- IpProtocol: tcp
FromPort: 3128
ToPort: 3128
CidrIp: 192.168.0.0/24 # from APP-VPC
# - IpProtocol: tcp
# FromPort: 3128
# ToPort: 3128
# SourceSecurityGroupId: !Ref AppSG
コメントアウトしている部分が前回の シングル構成時のルール です (クライアントSGからの ポート3128を許可)。
今回は NLB経由の接続ですが、 NLBは セキュリティグループを持ちません 。
また、 TargetType: instance
としているため、 NLBで送信元IPをクライアントのIPに置き換えています 。
そのため、 CIDR形式で 以下の通信を許可する必要があります。
- NLBを配置しているネットワークCIDR からの通信 (ヘルスチェックのため)
- クライアントを配置しているネットワークCIDR からの通信 (メインの通信のため)
プロキシサーバーのAMI
Auto Scaling で使用する AMIを事前に作成します。
Amazon Linux2 EC2インスタンスを起動して squid のインストール・自動起動の設定をします。
設定ファイル /etc/squid/squid.conf
の修正内容としては大きく 2つ。
acl localnet src 192.168.0.0/24 # VPC Network (Application side)
acl localnet src 10.0.0.0/24 # VPC Network (Proxy side: for NLB health check)
...
# disable cache
acl NOCACHE src all
cache deny NOCACHE
前 2行で アクセス制御の設定、後ろ2行でキャッシュの無効化を行っています ( 参考: Qiita: Squidのキャッシュ機能を無効化する )。
設定後、AMIを作成します。
Auto Scaling Group
下記 2リソースを作成します。
- Launch Configuration (AWS CloudFormation ドキュメント)
- Auto Scaling Group (AWS CloudFormation ドキュメント)
▼— Launch Configuration ---
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
LaunchConfigurationName: !Sub ${Prefix}-launch-configuration
ImageId: !Ref ProxyServerImageId
InstanceType: t3.micro
SecurityGroups:
- Fn::ImportValue: !Sub ${Prefix}-proxy-sg
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
DeleteOnTermination: True
VolumeType: gp2
VolumeSize: 8
KeyName: !Ref Ec2KeyName
# ... 略
ImageId:
に事前に作成したAMIの IDを入れます。
他は EC2インスタンスを作成するときと同じように設定していきます。
▼— Auto Scaling Group ---
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AutoScalingGroupName: !Sub ${Prefix}-as-group
LaunchConfigurationName: !Ref LaunchConfiguration
DesiredCapacity: 2
MaxSize: 2
MinSize: 2
VPCZoneIdentifier:
- Fn::ImportValue: !Sub ${Prefix}-subnet2-a
- Fn::ImportValue: !Sub ${Prefix}-subnet2-c
TargetGroupARNs:
- Fn::ImportValue: !Sub ${Prefix}-nlb-tg
HealthCheckType: ELB
# ... 略
LaunchConfigurationName:
に前述の LaunchConfigurationを指定します。- 常に 2台を維持する設定とするため、
DesiredCapacity:
、MaxSize:
、MinSize:
を2
とします。 TargetGroupARNs:
に NLBの TargetGroup を指定します
検証
接続・ステータス確認
APPサーバーにログインして、Service-VPCにある サービスを利用できるか検証します。 (Serviceの EC2インスタンスには httpd を入れておきます)
※APPサーバーのプロキシ設定は以下の通り。
APPサーバーにログインして、ServiceのローカルIPにアクセスしてみます。
Serviceの httpd ログを見てみます。APPサーバーを 2台立てて交互にアクセスしてみました。 2台のプロキシサーバーからアクセスされていることが確認できます。
ターゲットグループを見てみます。 2台ともヘルスチェックに合格しています。
Auto Scaling Group のステータスは以下の通り。
インスタンスを止めてみる
1つの プロキシサーバーを止めてみます。
止めたインスタンスが Unhealthy
となりました。
ライフサイクルが 終了中
に変わります。
新しい命が作られそうです。
無事に入れ替わりました。
Service のログにも新しくできたプロキシサーバーからのアクセスが確認できます。
(参考) 一連のアクティビティ履歴は以下の通り。
おわりに
HA構成プロキシ環境を NLBを使って構築してみました。 NLB, Auto Scaling 周りの 動作は勉強はしていたものの実際に見てはいなかったので、 確認できてよかったです。 CFnテンプレートを書く筋肉も付いてきた気がします。
今後は下記 2点あたりを考えて、まとめていけたらなと思っています。
- NLB, Auto Scaling のパラメータチューニング (今回はほとんどデフォルト)
- 運用・ログ監視周り
(追記) 通信要件によっては、そもそも ALB(IPターゲット) をリバースプロキシとして使えば実装できるみたいです。そちらの検証を今後行ってみます。