Education*
Devops
Architecture
F/B End
B.Chain
Basic
Others
CLOSE
Search For:
Search
BY TAGS
linux
HTTP
golang
flutter
java
fintech
개발환경
kubernetes
network
Docker
devops
database
tutorial
cli
분산시스템
www
블록체인
AWS
system admin
bigdata
보안
금융
msa
mysql
redis
Linux command
dns
javascript
CICD
VPC
FILESYSTEM
S3
NGINX
TCP/IP
ZOOKEEPER
NOSQL
IAC
CLOUD
TERRAFORM
logging
IT용어
Kafka
docker-compose
Dart
pulumi로 S3 정적 웹사이트 구성하기
Recommanded
Free
YOUTUBE Lecture:
<% selectedImage[1] %>
yundream
2023-10-13
2023-10-13
932
## 소개 이 문서는 IaC 툴인 Pulumi에 대한 입문서다. Go, Python, Javascript 등의 익숙한 언어로 IaC를 해보고 싶은 DevOps 엔지니어에게 도움이 될 것이다. 여기에서 다룰 내용은 아래와 같다. 1. Pulumi 개발환경 및 AWS Account 환경 설정 2. Pulumi 프로젝트 생성 3. AWS S3 bucket 생성 4. S3 정적 웹 사이트를 위해서 index.html 페이지를 저장 5. 정적 웹 사이트 테스트 및 전개한 자원의 정리 준비해야 될 내용은 아래와 같다. 1. 우분투 리눅스 20.04 이상 2. GoLang 3. AWS Account ## What is pulumi * Infrastructure-as-code SDK: VPC, EC2, Container, Serverless를 생성하고 전개할 수 있다. * Python, Javascript, Go, .NET등 익숙한 프로그래밍 언어를 이용해서 인프라를 정의 할 수 있다. * 선언적 접근 방식과 명령적 접근 방식을 모두 사용 할 수 있다. * 인프라의 형재 상태를 투적하는 상태파일을 유지 관리 한다. * AWS, Azure, Google Cloud, Kubernetes 등의 다양한 클라우드 환경을 지원한다. ## Pulumi Install ```shell curl -fsSL https://get.pulumi.com | sh ``` 설치 디렉토리 $HOME/.pulumi/bin. 버전 확인 ```shell $ pulumi version v3.86.0 ``` ### IAM Key Create Pulumi 프로그램은 AWS 자원을 컨트롤 하기 때문에 그에 맞는 권한을 가지고 있어야 한다. AWS Web Console의 IAM에서 Access Key를 만들자. ![](https://docs.google.com/drawings/d/e/2PACX-1vQbojlaRs1hSELe7ooTIcTKw7ZbqZCMrmCOR2QKVsyGdGintRbrpA6JcAcPLtcbSsCmS_3wCJZ7V4xK/pub?w=1125&h=295) **Create access key**를 클릭하면 아래와 같이 AccessKey 타입을 설정하는 화면으로 이동한다. Command Line Interface(CLI)를 선택하자. ![](https://docs.google.com/drawings/d/e/2PACX-1vSMoNqRlRcbBY4pUu5MwFymRvkUBcqnUjnSSaDpBlW0t-B1ELj5HRvaWKLVJ2_4CnomKX3pF4G1wxqY/pub?w=863&h=454) Create를 하고 나면, AccessKey는 CSV 형태로 다운로드 받을 수 있다. ```text Access key ID,Secret access key AK0000000000000000000,zxdie1234xxxxxxxxxxxxxxxxxx ``` 이 값들을 이용해서 로컬 PC에 Key를 설정해야 한다. Access key의 자세한 설정은 [AWS CLI 설정](https://www.joinc.co.kr/w/man/12/aws/cli) 문서를 참고하자. ### Pulumi 새 프로젝트 만들기 **new** 명령을 이용해서 "템플릿으로 부터" 새로운 프로젝트를 만들 수 있다. 작업용 디렉토리를 만들고 aws-go 템플릿을 이용해서 새로운 프로젝트를 만들어보자. ```shell $ pulumi new aws-go Manage your Pulumi stacks by logging in. Run `pulumi --help` for alternative login options. Enter your access token from https://app.pulumi.com/account/tokens or hit <ENTER> to log in using your browser : ``` 아직 pulumi 서비스에 가입을 하지 않았다면, 가입을 위한 메시지가 출력된다. 지금 가입하자. 가입을 하면 사용자의 프로젝트와 인프라 변경내용을 웹에서 확인 할 수 있으며, 다른 동료 개발자와 함께 인프라 정보를 공유 할 수도 있다. 터미널에서 프로젝트 이름 등 필요한 정보를 설정하면 된다. ```shell project name (my-template-project): s3-static-website project description (A minimal AWS Go Pulumi program): A minimal s3 static website Created project 's3-static-website' Please enter your desired stack name. To create a stack in an organization, use the format <org-name>/<stack-name> (e.g. `acmecorp/dev`). stack name (dev): dev Created stack 'dev' aws:region: The AWS region to deploy into (us-east-1): ap-northeast-2 Saved config Installing dependencies... Finished installing dependencies Your new project is ready to go! To perform an initial deployment, run `pulumi up` ``` * project name: s3-static-website * aws region: 테스트에 사용할 서울 리전(ap-northeast-2)를 입력했다. 프로젝트를 만들면 템플릿으로 부터 프로젝트 파일들이 만들어진다. ``` $ ls Pulumi.dev.yaml Pulumi.yaml go.mod go.sum main.go ``` ## Code 분석 ```go package main import ( "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/s3" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) func main() { pulumi.Run(func(ctx *pulumi.Context) error { // Create an AWS resource (S3 Bucket) bucket, err := s3.NewBucket(ctx, "my-bucket", nil) if err != nil { return err } // Export the name of the bucket ctx.Export("bucketName", bucket.ID()) return nil }) } ``` 이 코드는 "my-bucket"이라는 새로운 버킷을 만든다. ## Stack 배포 **up** 명령으로 배포 할 수 있다. ```shell ``` 실행을 **previewing update**에서 코드 실행으로 변경되는 내용을 확인 할 수 있다. "my-bucket" S3 버킷이 새로 생성되는 것을 확인 할 수 있다. 이 변경사항을 적용할지("Do you wnat to perform this update")를 묻는데 "yes"를 선택하면 업데이트 사항이 적용된다. yes를 선택하자. ```text $ pulumi up 130 ↵ Previewing update (dev) View in Browser (Ctrl+O): https://app.pulumi.com/yundream/s3-static-website/dev/previews/4f5b0a6c-1f94-4bd7-b4f6-e22a37e892a1 Downloading plugin: 170.74 MiB / 170.74 MiB [======================] 100.00% 16s [resource plugin aws-6.2.1] installing Type Name Plan + pulumi:pulumi:Stack s3-static-website-dev create + └─ aws:s3:Bucket my-bucket create Outputs: bucketName: output<string> Resources: + 2 to create Do you want to perform this update? [Use arrows to move, type to filter] > yes no details ``` 코드가 실행되면 2개의 새로운 리소스가 만들어지는 것을 확인할 수 있다. "yes"를 선택하면 실제 리소스가 만들어진다. ``` Updating (dev) View in Browser (Ctrl+O): https://app.pulumi.com/yundream/s3-static-website/dev/updates/1 Type Name Status + pulumi:pulumi:Stack s3-static-website-dev created (3s) + └─ aws:s3:Bucket my-bucket created (1s) Outputs: bucketName: "my-bucket-938d8a1" Resources: + 2 created Duration: 5s ``` 새로운 버킷이 만들어졌다. "View in Brower"의 링크를 방문하면, 작업내용을 웹브라우저를 통해서 확인할 수 있다. ![[pulumi_s3_static_website_01.png]] stack output 명령으로 s3 버킷 이름을 확인 할 수 있다. ```shell $ pulumi stack output bucketName my-bucket-938d8a1 ``` aws cli 명령으로 확인해 보자. ```shell $ aws s3 ls 2023-10-08 22:27:23 my-bucket-938d8a1 ``` ## Static website 배포 이제 pulumi를 이용해서 **S3 static website**를 개발해 보자. IaC는 코드로 인프라를 개발하는게 아니고 인프라를 코드로 구축하는 것이다. 즉, 구축하려고 하는 인프라에 대한 지식이 필요하다. S3 static website에 대한 정보는 [S3를 이용해서 정적 웹 사이트 서비스하기](https://www.joinc.co.kr/w/s3_static_website_exam) 포스트를 참고하자. 요약하자면 S3 static website를 만들려면 아래의 요소들이 필요하다. 1. S3 Bucket 생성 2. S3 Bucket 를 public access 가능하도록 설정. 3. s3:GetObject를 허용하는 **Bucket policy** 설정 이미 S3 bucket은 만들어봤으니, 2번과 3번만 추가 설정해주면 된다. #### 예제 Code clone 테스트를 위한 예제 Code를 clone 하자. ``` $ git clone https://github.com/yundream/pulumi-s3-website-exam.git ``` 디렉토리 구조는 아래와 같다. ``` . ├── Pulumi.yaml ├── go.mod ├── go.sum ├── main.go ├── s3-static-website.go └── www ├── assets │ ├── bootstrap.bundle.min.js │ ├── bootstrap.min.css │ └── color-modes.js ├── blog.css ├── blog.rtl.css └── index.html ``` 먼저 **stack init** 명령으로 pulumi stack을 만들자. ```shell $ pulumi stack init website-testing Created stack 'website-testing' ``` Pulumi 프로그램의 기본 배포 단위는 "stack"으로 독립적으로 구성 가능한 인스턴스라고 보면된다. stack을 이용해서 devlopment, staging, production 과 같이 개발 환경별로 배포하거나 feature-x-dev와 같이 기능 단위로 분기 할 수 있다. **config set** 명령으로 프로그램을 실행 할 region을 설정하자. ```shell $ pulumi config set aws:region ap-northeast-2 ``` 실행을 하고 나면 Pulumi.website-testing.yaml 파일을 확인할 수 있을 것이다. ```yaml config: aws:region: ap-northeast-2 ``` ## 코드 분석 프로그램을 실행하기 전에, 코드 내용을 살펴보자. 아래는 main.go 이다. ```go package main import ( "fmt" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) func main() { pulumi.Run(func(ctx *pulumi.Context) error { // Create a bucket and expose a website index document f, err := NewS3Folder(ctx, "s3-website-bucket", "www", &FolderArgs{}) if err != nil { fmt.Println(">> ", err.Error()) return err } ctx.Export("bucketName", f.bucketName) ctx.Export("websiteUrl", f.websiteUrl) return nil }) } ``` main.go는 NewS3Folder 함수를 호출한다. Bucket 생성, bucket policy 주입, Object upload 등의 모든 작업은 NewS3Folder에서 실행한다. s3-static-website.go 를 분석해보자. 설명은 주석으로 대신한다. ```go func NewS3Folder(ctx *pulumi.Context, bucketName string, siteDir string, args *FolderArgs, opts ...pulumi.ResourceOption) (*Folder, error) { var resource Folder // Stack exports err := ctx.RegisterComponentResource("pulumi:example:S3Folder", bucketName, &resource, opts...) if err != nil { return nil, err } // 1. bucketName으로 새로운 bucket를 만든다. // Static website를 활성화하고, index.html을 index 문서(IndexDocument)로 설정한다. siteBucket, err := s3.NewBucket(ctx, bucketName, &s3.BucketArgs{ Website: s3.BucketWebsiteArgs{ IndexDocument: pulumi.String("index.html"), }, }, pulumi.Parent(&resource)) if err != nil { return nil, err } // 2. Bucket을 Public Access 가능하도록 설정한다. // Properties의 기본 값들은 false 이라서 굳이 이 함수를 호출할 필요는 없지만 // 명확히 하는게 좋을 것이다. _, err = s3.NewBucketPublicAccessBlock(ctx, "bucketPublicAccessBlock", &s3.BucketPublicAccessBlockArgs{ Bucket: siteBucket.ID(), BlockPublicAcls: pulumi.Bool(false), BlockPublicPolicy: pulumi.Bool(false), IgnorePublicAcls: pulumi.Bool(false), RestrictPublicBuckets: pulumi.Bool(false), }) if err != nil { return nil, err } // 3. "www" 디렉토리에 있는 파일들을 s3 bucket에 upload 한다. err = filepath.Walk(siteDir, func(name string, info fs.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { rel, err := filepath.Rel(siteDir, name) if err != nil { return err } if _, err := s3.NewBucketObject(ctx, rel, &s3.BucketObjectArgs{ Bucket: siteBucket.ID(), // reference to the s3.Bucket object Source: pulumi.NewFileAsset(name), // use FileAsset to point to a file ContentType: pulumi.String(mime.TypeByExtension(path.Ext(name))), // set the MIME type of the file }, pulumi.Parent(&resource)); err != nil { return err } } return nil }) if err != nil { return nil, err } // 4. 인터넷 사용자가 object(html, css 파일들)를 읽을 수 있도록 Bucket Policy를 설정한다. // Bucket이 새로 만들어질 경우 Bucket Policy를 설정하기 까지 1초 정도의 시간이 걸린다. // 그전에 s3.NewBucketPolicy를 호출하면 403 에러가 발생한다. // 그래서 5초를 기다렸다. time.Sleep(5 * time.Second) if _, err := s3.NewBucketPolicy(ctx, "bucketPolicy", &s3.BucketPolicyArgs{ Bucket: siteBucket.ID(), // refer to the bucket created earlier Policy: pulumi.Any(map[string]interface{}{ "Version": "2012-10-17", "Statement": []map[string]interface{}{ { "Effect": "Allow", "Principal": "*", "Action": []interface{}{ "s3:GetObject", }, "Resource": []interface{}{ pulumi.Sprintf("arn:aws:s3:::%s/*", siteBucket.ID()), // policy refers to bucket name explicitly }, }, }, }), }, pulumi.Parent(&resource)); err != nil { return nil, err } resource.bucketName = siteBucket.ID() resource.websiteUrl = siteBucket.WebsiteEndpoint ctx.RegisterResourceOutputs(&resource, pulumi.Map{ "bucketName": siteBucket.ID(), "websiteUrl": siteBucket.WebsiteEndpoint, }) return &resource, nil } ``` 1. S3 bucket을 만들고 2. S3 bucket을 static website 설정하고 3. Object를 upload 하고 4. Bucket Policy를 조정 하는 과정들이 코드로 표현된 것을 확인 할 수 있다. ## Pulumi 프로그램 실행 및 테스트 이제 프로그램을 실행해보자. ``` $ pulumi up Updating (website-testing) View in Browser (Ctrl+O): https://app.pulumi.com/yundream/aws-go-s3-folder-component/website-testing/updates/1 Type Name Status + pulumi:pulumi:Stack aws-go-s3-folder-component-website-testing created (5s) + ├─ pulumi:example:S3Folder s3-website-bucket created (7s) + │ ├─ aws:s3:Bucket s3-website-bucket created (1s) + │ ├─ aws:s3:BucketObject assets/color-modes.js created (0.35s) + │ ├─ aws:s3:BucketObject blog.rtl.css created (0.63s) + │ ├─ aws:s3:BucketObject blog.css created (1s) + │ ├─ aws:s3:BucketObject index.html created (1s) + │ ├─ aws:s3:BucketObject assets/bootstrap.min.css created (2s) + │ ├─ aws:s3:BucketObject assets/bootstrap.bundle.min.js created (2s) + │ └─ aws:s3:BucketPolicy bucketPolicy created (0.59s) + └─ aws:s3:BucketPublicAccessBlock bucketPublicAccessBlock created (1s) Outputs: bucketName: "s3-website-bucket-f8666f1" websiteUrl: "s3-website-bucket-f8666f1.s3-website.ap-northeast-2.amazonaws.com" Resources: + 11 created Duration: 12s ``` 웹 브라우저로 "websiteUrl" 에 접근해보자. ![s3 static website 테스트](https://docs.google.com/drawings/d/e/2PACX-1vT5T5TqouKlRSpPAtY1V_Mcbs6GbrCf9mAVVQwxNsfhwPQKUuu3ObgW70n33a6IqeFplbiumuV8JjTj/pub?w=1280&h=936) ## 자원 정리 테스트가 끝났다면, "destroy" 명령으로 자원을 정리하자. ``` $ pulumi destroy Do you want to perform this destroy? yes Destroying (website-testing) View in Browser (Ctrl+O): https://app.pulumi.com/yundream/aws-go-s3-folder-component/website-testing/updates/2 Type Name Status - pulumi:pulumi:Stack aws-go-s3-folder-component-website-testing deleted (0.52s) - ├─ aws:s3:BucketPublicAccessBlock bucketPublicAccessBlock deleted (2s) - └─ pulumi:example:S3Folder s3-website-bucket deleted (0.30s) - ├─ aws:s3:BucketPolicy bucketPolicy deleted (2s) - ├─ aws:s3:BucketObject blog.rtl.css deleted (2s) - ├─ aws:s3:BucketObject index.html deleted (2s) - ├─ aws:s3:BucketObject assets/bootstrap.bundle.min.js deleted (2s) - ├─ aws:s3:BucketObject assets/color-modes.js deleted (2s) - ├─ aws:s3:BucketObject assets/bootstrap.min.css deleted (2s) - ├─ aws:s3:BucketObject blog.css deleted (2s) - └─ aws:s3:Bucket s3-website-bucket deleted (1s) Outputs: - bucketName: "s3-website-bucket-f8666f1" - websiteUrl: "s3-website-bucket-f8666f1.s3-website.ap-northeast-2.amazonaws.com" Resources: - 11 deleted Duration: 9s The resources in the stack have been deleted, but the history and configuration associated with the stack are still maintained. If you want to remove the stack completely, run `pulumi stack rm website-testing`. ``` 사용하지 않는 stack을 삭제하고, 잘 삭제됐는지 확인해보자. ``` $ pulumi stack rm website-testing $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT URL joinc-vpc 56 minutes ago 0 https://app.pulumi.com/yundream/joinc-infra/joinc-vpc ```
Recent Posts
GPT를 이용한 Reranker 테스트
5분만에 만들어보는 Streamlit 챗봇
Let's encrypt로 SSL 인증서 관리하기
Upscayl을 이용한 이미지 업스케일링
스테이블 디퓨전 설치 및 사용해보기
Elasticsearch 설치
AI / LLM에 대한 친절한 소개
SLA 다운타임 계산기
Docker로 GitLab 설치하기
Ubuntu Linux에 NVIDIA 드라이버 설치
Archive Posts
Tags
aws
cloud
iac
s3
Copyrights © -
Joinc
, All Rights Reserved.
Inherited From -
Yundream
Rebranded By -
Joonphil
Recent Posts
Archive Posts
Tags