Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

素人が勉強しながら作るawsでのvpn環境⑤

Last updated at Posted at 2024-12-08

目次

1ネットワーク設計
2.EC2構築と各種インストール
3.ドメイン周り設定
4.セキュリティ設定
5.コスト低減
6.参考文献

AWSは従量課金製で、作った時点から課金が開始され、放置しておくと多額の請求が来るようになります。
スクリーンショット 2024-06-16 18.58.21.png

ここではVPNエンドポイント、EC2、RDSについて、料金体系とコスト低減について考えていきます。

5-1-1. VPNエンドポイントについて

スクリーンショット 2024-06-16 19.04.10.png

AWS公式

AWS公式では、VPNクライアント接続構成における課金対象は、以下2つとされています。

  • AWS Client VPN 接続 
    -USD 0.05/時間
  • AWS Client VPN エンドポイントアソシエーション
    -USD 0.15/時間

 「AWS Client VPN 接続」 は、VPCとクライアントPCとの接続時に、
 接続期間中に時間単位でかかる料金のことです。

 「AWS Client VPN エンドポイントアソシエーション」 は、
 VPNエンドポイント設置時、サブネットとの関連付けのタイミングから
 時間単位で発生する料金のことです。

上記Qiitaの記事によれば、24時間×30日接続し続けた場合、発生する課金額は
関連付けられた1サブネットごとに108USドル、日本円にして(=2024/6/17現在の為替レートを1ドル150円として)16200円になります。

例えば、使用するアプリケーションが業務アプリだった場合、夜間帯は全く使用しないケースも考えられます。
終業時にVPNエンドポイントを削除し、翌日の始業時に再度構築すれば、その一両日にかかる費用は、1日の勤務時間を8時間とした場合、1/3程度に抑えることができます。

検索したところ、記事がありました。

前者はsubprocessというモジュールでOSコマンドとしてaws-cliを叩いているようです。
後者2記事はboto3というpythonからawsリソースを操作するモジュールを使って実施しているようです。

ちょっと検索するだけで3記事も出てきたので、実装方法の説明は私なんかよりよほど頭のいいそれらの記事に任せるとして、「クライアントVPNエンドポイントのID」の記述部分のみベタ書きしなくて済むよう、前述のKMSに登録して値を引っ張ってこれるようなコードを記述します。

、、、記述しようと思いましたが、これも既に誰か頭のいい方が記事を作成していました。

 パラメータストアから値を取得する方法と上記記事の記載内容を、自分なりにまとめてみます。

1.パラメータストアに、対象のVPNエンドポイント、そこに関連づけるサブネットのIDをそれぞれ登録します。
2.Lambda関数の作成
2-①:作成するLambda関数に付与するIAMRoleを作成します。
2-②:上記1.パラメータストアに登録したIDを呼び出して、
   任意の時間に接続する関数、切り離す関数をそれぞれ作成します。
2-③:CloudWatch Event をトリガーに設定して、
   任意の時間に2-②で作成した関数を交互に繰り返し、
   接続時間の短縮を実施して、コストの低減をはかります。

1.パラメータストア登録

 対象のVPNエンドポイントIDを"ClientVPNEndpointID"として、
 関連づけるサブネットのIDを"TargetAssociateSubnetID"として
 登録します。

 ①"ClientVPNEndpointID" 登録
  VPNの詳細画面からIDをコピーします。

スクリーンショット 2024-11-27 23.20.23.png

パラメータストアの作成画面に移動して登録します。

スクリーンショット 2024-11-27 23.34.53.png

スクリーンショット 2024-11-30 214036.png

 ②"TargetAssociateSubnetID" 登録
  上記クライアントVPNエンドポイントと関連付けるサブネットの
  サブネットIDをパラメータ名"TargetAssociateSubnetID"として
  パラメータストアに登録します。

  サブネットの詳細画面からサブネットIDをコピーします。

スクリーンショット 2024-11-30 215314.png

パラメータストアの作成画面に移動して登録します。

スクリーンショット 2024-11-30 220650.png

2.Lambda関数作成

 ①作成するLambda関数に付与するロールを作成します。
  図は"RoleForLambda"というロール名で、以下記事に記載のある
  JSONベースのポリシーとSSMに対するフルアクセス権限を
  アタッチしています。

スクリーンショット 2024-11-30 224919.png

スクリーンショット 2024-11-30 224950.png

 ②上記VPNエンドポイントがサブネットと接続する関数、
  接続を切り離す関数をそれぞれ作成します。

 ②-1-1 接続する方の関数を作成します。

image.png
 ・関数名-仮に"VPNConnectSubnet"とします。
 ・ランタイム-上記記事に紹介されていた通りPython3.8とします。
 ・実行ロール-上記①で作成したロールを指定します。

image.png
 ・コードソース-上図①のエリアに以下コードをコピペし
  Ctrl/Control、S キーで保存し、Deployボタンを押下します。

VPNConnectSubnet
import boto3
client = boto3.client('ec2')

## SSM region
REGION = 'ap-northeast-1'

## parameter name
param_key1 = "ClientVPNEndpointID"
param_key2 = "TargetAssociateSubnetID"

def lambda_handler(event,context):

    ## Function for get_parameters
    def get_parameters(param_key):
        ssm = boto3.client('ssm', region_name=REGION)
        response = ssm.get_parameters(
            Names=[
                 param_key
            ],
            WithDecryption=True
        )
        return response['Parameters'][0]['Value']

    def main():

        ## get parameter value
        param_value1 = get_parameters(param_key1)
        print(param_value1)
        param_value2 = get_parameters(param_key2)
        print(param_value2)

        client.associate_client_vpn_target_network(
        ClientVpnEndpointId = param_value1,
        SubnetId = param_value2
        )
        
    main() 

 ②-1-2 接続する方の関数について、トリガーを設定します。

スクリーンショット 2024-12-07 225143.png

「+ トリガーを追加」をクリックするとトリガーの設定画面に遷移します。

image.png

 ・トリガーの設定
  -"EventBridge"を選択します。
 ・ルール
  -"新規ルールを作成"を選択
  -任意のルール名を指定します。ここではTrigger_VPNConnectSubnetとします。
 ・ルールタイプ
  -スケジュール式を選択します。
 ・スケジュール式
  -cron式で入力します。
   AWSの仕様でUTC+0:00に読み替えて入力する必要があります。
   日本時間は UTC+9:00なので、
   UTC+9:00 = 接続を開始したい時刻、
   朝9時に接続するとして、
   UTC+9:00 = 9:00、 UTC = 0:00 としました。
   また、接続するのは平日のみとしています。

cron(0 0 ? * MON-FRI *) //(00分 0時※日本時間で朝9時 指定なし 毎月 月~金曜日 毎年)

詳しいcron式の記載方法は、以下サイトに詳細が記されています。

 ②-2-1 接続を切り離す関数を作成します。要領は上記②-1と同様です。

image.png
・関数名-任意の関数名を入力します。
 ここでは"VPNDisconnectSubnet"とします。

・ランタイム-python3.8
・実行ロール
 -「既存のロールを使用する」
  ※上記①で作成したロールを選択します。

image.png

 ・コードソース-上図①のエリアに以下コードをコピペし
  Ctrl/Control、S キーで保存し、Deployボタンを押下します。

VPNDisconnectSubnet
import boto3
client = boto3.client('ec2')

## SSM region
REGION = 'ap-northeast-1'

## parameter name
param_key1 = "ClientVPNEndpointID"
param_key2 = "TargetAssociateSubnetID"

def lambda_handler(event,context):

    ## Function for get_parameters
    def get_parameters(param_key):
        ssm = boto3.client('ssm', region_name=REGION)
        response = ssm.get_parameters(
            Names=[
                 param_key
            ],
            WithDecryption=True
        )
        return response['Parameters'][0]['Value']

    def main():

        ## get parameter value
        param_value1 = get_parameters(param_key1)
        print(param_value1)
        param_value2 = get_parameters(param_key2)
        print(param_value2)

        ClientVpnData = client.describe_client_vpn_target_networks(
        ClientVpnEndpointId = param_value1
        )
        AssociationId = ClientVpnData['ClientVpnTargetNetworks'][0]['AssociationId']

        client.disassociate_client_vpn_target_network(
        ClientVpnEndpointId = param_value1,
        AssociationId = AssociationId
        )
        
    main()

 ②-2-2 接続を切り離す関数について、トリガーを作成します。

image.png

・トリガーの設定-"EventBridge"を選択
・ルール
 -新規ルールを作成
  ルール名「VPNDisconnectSubnet」
・ルールタイプ
 -"スケジュール式"を選択します。
・スケジュール式
 -日本時間で21時に接続を切るように設定します。

cron(0 12 ? * MON-FRI *) //(00分 12時※日本時間で夜21時 指定なし 毎月 月~金曜日 毎年)
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?