AWS Lambda에서의 .NET 워크로드

모듈 6

모듈 6: 실습: Lambda 함수 생성 및 배포

 실습

실습 목표

이 실습에서는 이 과정에서 배운 내용을 연습합니다

다양한 .NET 6/7 Lambda 함수를 생성하여 배포하고 호출하게 됩니다.

이 모듈은 3개의 실습으로 구성됩니다.

실습 1: Arm64에서 실행되는 .NET 6 웹 앱
실습 2: 컴퓨터의 C# 프로그램에서 Lambda 함수 호출
실습 3: Lambda 함수에서 다른 Lambda 함수 호출

사전 요구 사항

AWS 계정이 있어야 합니다.

AdministratorAccess 정책이 연결된 AWS 사용자가 있어야 합니다. 자세한 내용은 모듈 3의 권한 관련 참고 사항 섹션을 참조하세요.</p>

.NET 6 SDK가 설치되어 있어야 합니다.

AWS Extensions for .NET CLI(dotnet lamda...)가 설치되어 있어야 합니다.

AWS Lambda for .NET Core Templates가 설치되어 있어야 합니다.

PowerShell이 설치되어 있어야 합니다. Window/Mac/Linux에 설치해야 하는 경우 https://github.com/PowerShell/PowerShell을 참조하세요.

모듈 2에서 위 도구에 대한 자세한 정보를 확인할 수 있습니다.

CloudFormation 스택용 S3 버킷이 있어야 합니다. 그렇지 않은 경우 아래 지침을 따르세요.

 소요 시간

45분

실습 1: Arm64에서 실행되는 .NET 6 웹 앱

1단계: 프로젝트 생성

여기서는.NET 서버리스 프로젝트를 만들 것입니다.

1. 서버리스 .NET 프로젝트 생성

dotnet new serverless.AspNetCoreWebApp -n AspNetCoreWebApp
그러면 AspNetCoreWebApp\src\AspNetCoreWebApp 디렉터리 내에 프로젝트가 생성됩니다.
2. 프로젝트 열기
자주 사용하는 IDE에서 이 프로젝트를 엽니다.

2단계: 코드 일부 변경

이 단계에서는 생성된 프로젝트 코드를 수정합니다.
1. Index.cshtml.cs 업데이트
IDE에서 프로젝트를 연 다음, 코드 편집기에서 Pages/index.cshtml.cs를 엽니다.

using 문과 네임스페이스는 그대로 두고 IndexModel 클래스를 다음과 같이 바꿀 수 있습니다.
public class IndexModel : PageModel
{
    public string? Architecture { get; set; }
    public string? DotnetVersion { get; set; }
    
    public void OnGet()
    {
        Architecture = System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString();
        DotnetVersion = Environment.Version.ToString();
    }
}

2. Index.cshtml 업데이트

Pages/Index.cshtml 파일을 엽니다.

</h2>까지의 파일 내용을 다음으로 바꿉니다.
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
  <h1 class="display-4">Welcome to .NET Lambda functions on AWS!</h1>
  <h2>Your application is using .NET <code>@Model.DotnetVersion</code>, <code>@Model.Architecture</code>.</h2>
</div>
<svg>요소는 그대로 둡니다.

이러한 변경을 통해 실행 중인.NET 버전과 사용 중인 프로세서 유형을 확인할 수 있습니다.

3단계: 프로세서 아키텍처 구성

이 단계에서는 프로세서 아키텍처를 Arm64로 설정합니다.
1. 프로세서 아키텍처를 Arm64로 변경
한 가지를 더 변경해야 합니다.

serverless.template 파일을 엽니다.

'Handler'키를 찾고 그다음 줄에 다음을 추가합니다.
"Architectures": ["arm64"],
이제 코드 블록이 다음과 같이 보일 것입니다.
"AspNetCoreFunction": {
  "Type": "AWS::Serverless::Function",
  "Properties": {
    "Handler": "AspNetCoreWebApp::AspNetCoreWebApp.LambdaEntryPoint::FunctionHandlerAsync",
    "Architectures": ["arm64"],
2. 저장 및 빌드
모든 변경 사항을 저장하고 애플리케이션을 빌드하여 컴파일 오류가 발생하지 않도록 합니다.

4단계: 함수 배포

이 단계에서는 Lambda 함수를 배포하고 테스트해 보겠습니다.
1. AWS에 함수 배포
명령줄에서 다음을 실행합니다.
dotnet lambda deploy-serverless --stack-name AspNetCoreWebApp --s3-bucket your-unique-bucket-name1234
AWS가 Lambda 함수를 배포하기를 기다립니다.

작업이 진행되는 동안 완료된 각 배포 단계에 대한 출력이 표시됩니다.
8/9/2022 1:45 PM     AspNetCoreFunctionProxyResourcePermissionProd CREATE_COMPLETE
8/9/2022 1:45 PM     AspNetCoreWebApp                         CREATE_COMPLETE
Stack finished updating with status: CREATE_COMPLETE

Output Name                    Value
------------------------------ --------------------------------------------------
ApiURL                         https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/
2. .NET WebAPI 프로젝트 생성
출력 끝에 ApiURL이 표시됩니다. 이를 브라우저에서 엽니다.

5단계: 정리

이 단계에서는 AWS에서 서버리스 프로젝트를 삭제합니다.
1. 서버리스 프로젝트 삭제
실행 중에 생성된 모든 리소스를 제거하는 방법은 다음과 같습니다.
dotnet lambda delete-serverless --stack-name AspNetCoreWebApp

실습 2: 컴퓨터의 C# 프로그램에서 Lambda 함수 호출

1단계: Lambda 함수 생성

이 단계에서는 빈 Lambda 프로젝트를 생성합니다.

1. 프로젝트 생성

이전 실습을 위해 만든 디렉터리에 들어가 있는 경우, 해당 디렉터리에서 나가서 깨끗한 디렉터리로 이동합니다. 명령줄에서 새 Lambda 함수를 생성합니다.

dotnet new lambda.EmptyFunction -n GetS3Buckets
그러면 AspNetCoreWebApp\src\AspNetCoreWebApp 디렉터리 내에 프로젝트가 생성됩니다.

2단계: 코드 변경

이 단계에서는 생성된 프로젝트 코드를 수정합니다.

1. 패키지 추가

GetS3Buckets\src\ GetS3Buckets 폴더로 변경하고 AWS SDK S3 패키지를 프로젝트에 추가합니다.

cd GetS3Buckets\src\ GetS3Buckets
dotnet add package AWSSDK.S3

2. Function.cs 업데이트

IDE에서 Function.cs를 열고 코드를 다음과 같이 바꿉니다.

using Amazon.Lambda.Core;
using Amazon.S3;
using Amazon.S3.Model;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace GetS3Buckets;

public class Function
{
   public async Task<IEnumerable<string>> FunctionHandler(ILambdaContext context)
    {
        var s3Client = new AmazonS3Client();

        ListBucketsRequest listBucketsRequest = new ListBucketsRequest();
        ListBucketsResponse listBucketsResponse = await s3Client.ListBucketsAsync(listBucketsRequest);

        var bucketNames = listBucketsResponse.Buckets.Select(b => b.BucketName);

        return bucketNames;
    }
}

3단계: 함수 배포

이 단계에서는 Lambda 함수를 배포하고 테스트해 보겠습니다.

1. AWS에 함수 배포

다음을 사용하여 함수를 AWS에 배포합니다.

dotnet lambda deploy-function GetS3Buckets

역할을 선택하라는 메시지가 표시되면 새 역할을 만드는 옵션을 선택합니다. 역할 이름은 GetS3BucketsRole로 지정합니다.

정책을 연결하라는 메시지가 표시되면 AWSLambdaBasicExecutionRole 옵션을 선택합니다. 이 옵션은 목록에서 6번입니다.

4단계: ListAllMyBuckets에 권한 추가

이 단계에서는 S3 버킷을 나열할 권한을 추가해 보겠습니다.

1. IAM 정책 생성

역할에 연결한 정책에는 S3 버킷을 나열하는 데 필요한 권한이 없습니다.

S3ListAllMyBucketsPolicy.json이라는 새 파일을 생성합니다.

다음을 복사하여 파일에 붙여 넣습니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListAllMyBuckets",
            "Resource": "*"
        }
    ]
}

2. 역할에 정책 추가

정책을 GetS3BucketsRole:에 추가합니다.

aws iam put-role-policy --role-name GetS3BucketsRole --policy-name ListAllMyBuckets --policy-document file://S3ListAllMyBucketsPolicy.json

권한이 적용될 때까지 잠시 기다려 주세요.

5단계: 명령줄에서 Lambda 함수 호출

이 단계에서는 Lambda 함수를 배포하고 테스트해 보겠습니다.

1. 명령줄에서 함수 호출

함수를 호출하는 C# 프로그램을 만들기 전에 명령줄에서 호출해 보세요.

dotnet lambda invoke-function --function-name GetS3Buckets

모든 버킷이 나열된 출력이 표시되는지 확인하세요.

이를 통해 Lambda 함수가 예상대로 작동하는지 확인할 수 있습니다.

6단계: 명령줄에서 Lambda 함수 호출

이 단계에서는 Lambda 함수를 호출하는 C# 프로그램을 생성해 보겠습니다.

1. 콘솔 애플리케이션 생성

다음을 사용하여 .NET 콘솔 애플리케이션을 생성합니다.

dotnet new console -n GetS3BucketsCallFromLocal

2. AWSSDK.Lambda 패키지 추가

GetS3BucketsCallFromLocal 폴더로 변경합니다.

cd GetS3BucketsCallFromLocal

AWS SDK Lambda 패키지를 추가하면 Lambda 함수를 호출할 수 있습니다.

dotnet add package AWSSDK.Lambda

3. Program.cs 업데이트

Program.cs 파일을 열고 다음과 같이 바꿉니다.

using System.Text.Json;
using Amazon.Lambda;
using Amazon.Lambda.Model;

AmazonLambdaClient client = new AmazonLambdaClient();

var request = new InvokeRequest
{
    FunctionName = "GetS3Buckets"
};

var result = await client.InvokeAsync(request);

var buckets = JsonSerializer.Deserialize<IEnumerable<string>>(result.Payload);

foreach (var bucket in buckets)
{
    Console.WriteLine(bucket);
}

7단계: 사용해 보기

이 단계에서는 콘솔 프로그램을 테스트하고 Lambda 함수를 호출합니다.

1. 콘솔 애플리케이션 실행

GetS3BucketsCallFromLocal 디렉터리의 명령줄에서 다음을 실행합니다.

dotnet run 

버킷 이름 목록이 나와야 합니다.

8단계: 정리

이 함수는 다음 실습에서 사용할 것이므로 지금은 정리할 필요가 없습니다.

실습 3: Lambda 함수에서 다른 Lambda 함수 호출

1단계: GetS3Buckets 함수 생성

이전 실습을 완료하세요.

2단계: Lambda 함수 생성

이 단계에서는 GetS3Buckets 함수를 호출하는 Lambda 함수를 생성해 보겠습니다.

1. 빈 Lambda 프로젝트 생성

명령줄에서 다음을 실행합니다.

dotnet new lambda.EmptyFunction -n GetS3BucketsCallFromLambdaFunction

2. 폴더 변경

GetS3BucketsCallFromLambdaFunction\src\GetS3BucketsCallFromLambdaFunction 디렉터리로 변경합니다.

3단계: 코드 업데이트

이 단계에서는 프로젝트 코드를 업데이트합니다.

1. AWSSDK.Lambda 패키지 추가

프로젝트에 AWS SDK Lambda 패키지를 추가합니다.

dotnet add package AWSSDK.Lambda

2. Function.cs 업데이트

Function.cs 파일을 열고 코드를 다음과 같이 바꿉니다.

using Amazon.Lambda;
using Amazon.Lambda.Core;
using Amazon.Lambda.Model;
using System.Text.Json;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace GetS3BucketsCallFromLambdaFunction;

public class Function
{
    
    public async Task<IEnumerable<string>> FunctionHandler(ILambdaContext context)
    {
        AmazonLambdaClient client = new AmazonLambdaClient();

        var request = new InvokeRequest
        {
            FunctionName = "GetS3Buckets",
        };

        var result = await client.InvokeAsync(request);

        var bucketNames = JsonSerializer.Deserialize<IEnumerable<string>>(result.Payload);

        return bucketNames;
    }
}

이 예시에서 Lambda 함수 GetS3BucketsCallFromLambdaFunction은 GetS3Buckets 함수를 호출하여 응답을 반하는데, 응답은 변경되지 않습니다.

4단계: GetS3BucketsCallFromLambdaFunction 배포

이 단계에서는 Lambda 함수 GetS3BucketsCallFromLambdaFunction을 AWS에 배포할 것입니다.

1. 함수 배포

명령줄에서 다음을 실행합니다.

dotnet lambda deploy-function GetS3BucketsCallFromLambdaFunction

2. 역할 생성

다음과 같은 이름의 새 함수 역할을 생성합니다. 

GetS3BucketsCallFromLambdaFunctionRole.

3. 역할에 정책 연결

AWSLambdaBasicExecutionRole 정책을 역할에 연결합니다.

5단계: GetS3BucketsCallFromLambdaFunction 호출

이 단계에서는 함수를 호출해 봅니다.

1. 함수 배포

GetS3BucketsCallFromLambdaFunctionRole을 호출해 봅니다.

dotnet lambda invoke-function --function-name GetS3BucketsCallFromLambdaFunction

다음과 같은 오류가 발생합니다.

Payload:
{
  "errorType": "AmazonLambdaException",
  "errorMessage": "User: arn:aws:sts::000000000000:assumed-role/GetS3BucketsCallFromLambdaFunctionRole/GetS3BucketsCallFromLambdaFunction 
is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-east-1:000000000000:function:GetS3Buckets because no 
identity-based policy allows the lambda:InvokeFunction action",

이는 GetS3BucketsCallFromLambdaFunction에 GetS3Buckets를 호출할 권한이 필요하기 때문입니다.

다음 단계에서는 GetS3BucketsCallFromLambdaFunction에 필요한 권한을 부여하여 인라인 정책을 추가할 것입니다.

6단계: GetS3BucketsCallFromLambdaFunction에 권한을 부여하여 GetS3Buckets 호출

이 단계에서는 GetS3BucketsCallFromLambdaFunction에 GetS3Buckets를 호출하기 위한 권한을 부여합니다.

1. GetS3Buckets의 ARN 가져오기

GetS3BucketsCallFromLambdaFunction에 호출 권한을 부여하기 전에 GetS3Buckets의 Amazon 리소스 이름(ARN)을 가져와야 합니다.

이 작업을 수행하는 방법은 몇 가지가 있습니다. 먼저 AWS Console에서 시작합니다. Lambda 서비스로 이동하여 GetS3Buckets 함수를 선택합니다.

강조 표시된 두 영역 모두에서 ARN 복사를 클릭할 수 있습니다.

명령줄에서 GetS3Buckets의 ARN을 가져오려면 다음을 실행합니다.

dotnet lambda get-function-config GetS3Buckets

다음과 같은 출력이 표시됩니다.

프로젝트 홈: https://github.com/aws/aws-extensions-for-dotnet-cli,

 https://github.com/aws/aws-lambda-dotnet

Name:                         GetS3Buckets
Arn:                          arn:aws:lambda:us-east-1:000000000000:function:GetS3Buckets
Package Type:                 Zip
Runtime:                      dotnet6
Function Handler:             GetS3Buckets::GetS3Buckets.Function::FunctionHandler
Last Modified:                2022-08-10T13:58:29.211+0000
Memory Size:                  256
Ephemeral Storage Size:       512
Role:                         arn:aws:iam::000000000000:role/GetS3Buckets
Timeout:                      30
Version:                      $LATEST
State:                        Active
Last Update Status:           Successful
KMS Key ARN:                  (default) aws/lambda

유용한 정보가 많지만 필요한 정보는 표의 두 번째 줄인 Arn에 있습니다.

InvokeGetS3Buckets.json이라는 파일을 만들고 여기에 다음을 추가합니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action":[
                "lambda:InvokeFunction"
            ],
            "Resource": "arn:aws:lambda:us-east-1:000000000000:function:GetS3Buckets"
        }
    ]
}
Repl

'Resource'를 명령줄 또는 콘솔 UI에서 가져온 Lambda 함수의 ARN으로 바꿉니다.

2. 권한 업데이트

다음을 실행합니다.

aws iam put-role-policy --role-name GetS3BucketsCallFromLambdaFunctionRole
 --policy-name InvokeGetS3BucketsFunction 
 --policy-document file://InvokeGetS3Buckets.json

AWS에서 권한을 업데이트하는 데 몇 분 정도 소요될 수 있습니다.

7단계: GetS3BucketsCallFromLambdaFunction 다시 호출하기

이 단계에서는 함수를 다시 호출합니다.

1. dotnet lambda invoke-function으로 함수 호출하기

이번에는 함수를 호출할 수 있습니다.

dotnet lambda invoke-function --function-name GetS3BucketsCallFromLambdaFunction

결론

이 실습에서는 학습한 내용을 실습에 적용합니다. 처음에는 전 세계 어디서나 액세스할 수 있는 웹 애플리케이션을 만들었습니다. 그런 다음, 컴퓨터의 C# 프로그램에서 직접 호출한 Lambda 함수를 배포했습니다. 그 후 두 번째 실습을 발전시켜 다른 Lambda 함수를 배포하고 Lambda 함수에서 다른 Lambda 함수를 호출했습니다. 또한, 권한 문제가 발생하면 이를 해결했습니다.

여기에서 Lambda 함수와 함께 다른 AWS 서비스를 실험해 보고 더 복잡한 Lambda 애플리케이션을 구축해 볼 수 있습니다.

이 페이지의 내용이 도움이 되었나요?

기술 평가