Spring project 생성

* 환경: jdk-21, Gradle, vscode 활용

 

vscode에서 ctrl + shift + p (Show all commands) 단축키를 누르고 spring Initializr 를 검색합니다.

원하는 대로 선택 후 프로젝트 생성하면 됩니다.

 

CICD-Test/src/main/java/com/example/cicdtest/resoures 아래 static 폴더 생성 후 index.html 추가

테스트 용도의 간단한 페이지를 하나 생성합니다. (! + enter 치면 기본 html 틀 코드 생성됨)

cd <project-folder>

./gradlew
./gradlew build
./gradlew bootRun

vscode의 bash terminal 위에서 해당 명령어들을 입력해 확인합니다. (http://localhost:8080)

 

해당 프로젝트를 github에 올립니다.

cd <project-folder>

git config --global user.email "~~~"
git init

git add .
git status
git commit -m "~~~"

git remote add origin <github-주소>
git push origin master

 

배포할 EC2 인스턴스 생성

원하는 인스턴스 유형과 키페어, 네트워크 설정(퍼블릭) 후 인스턴스를 생성합니다.

(보안그룹의 경우 ssh(내 IP), 8080(0.0.0.0/0) ,http(0.0.0.0/0) 열어주기)

 

 

수동 배포

아래 명령어들을 EC2 인스턴스 ssh 접속 후 차례로 입력합니다.

sudo yum install git

sudo yum install java-21-amazon-corretto
java -version

sudo timedatectl set-timezone Asia/Seoul

mkdir app
cd ~/app
git clone https://github.com/realyun99/cicd-test.git
cd cicd-test

# gradle clean build
sudo chmod +x gradlew
sudo ./gradlew build

cd build/libs/
java -jar cicd-test-0.0.1-SNAPSHOT.jar

nohup java -jar cicd-test-0.0.1-SNAPSHOT.jar 1>log.out 2>err.out &
tail -f log.out
tail -f err.out

 

잘 설정되었는지 http://<ec2-public-ip>:8080 으로 확인합니다.

 

현재 수동 배포의 명령어들을 스크립트로 짜보려고 합니다.

 

배포 스크립트 생성

위에서 git clone을 받았던 /app/git 폴더로 들어가 deploy.sh 파일을 생성한 후 아래의 스크립트를 넣어줍니다.

#!/bin/bash

REPOSITORY=/home/ec2-user/app
cd $REPOSITORY/cicd-test/

echo "> Git Pull"
git pull

echo "> 프로젝트 Build 시작"
./gradlew build

echo "> Build 파일 복사"
cp ./build/libs/*.jar $REPOSITORY/

echo "> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -f cicd-test)

echo "$CURRENT_PID"

if [ -z $CURRENT_PID ]; then
    echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다."
else
    echo "> kill -2 $CURRENT_PID"
    kill -9 $CURRENT_PID
    sleep 5
fi

echo "> 새 어플리케이션 배포"
JAR_NAME=$(ls $REPOSITORY/ |grep 'cicd-test' | tail -n 1)

echo "> JAR Name: $JAR_NAME"
nohup java -jar $REPOSITORY/$JAR_NAME &

 

아래의 명령어를 통해 스크립트를 실행합니다.

cd /app/git/cicd-test
sudo chmod +x gradlew

cd /app/git
sudo chmod 755 ./deploy.sh
./deploy.sh

여기까지 다 적용했다면 현재까지 구현된 기능은 아래와 같습니다.

1) 코드 수정 후 git push

2) ec2 접속 후 deploy.sh 실행 → 코드 배포

'Toy Project' 카테고리의 다른 글

[CI/CD] EC2 CodePipeline Test -3  (0) 2024.03.25
[CI/CD] EC2 CodePipeline Test -2  (1) 2024.03.19

* 기본적인 세팅은 되어 있는 상태 입니다. (VPC, Nat GW, ALB, EC2(private subnet) 구성)

* private ec2: etech-private-ec2(10.0.11.130)


3. OpenVPN을 통한 접속

OpenVPN은 가상 사설 네트워크(VPN)를 구축하여 외부에서 안전하게 인프라에 접속할 수 있도록 합니다.

사용자는 OpenVPN 클라이언트를 사용하여 VPN에 연결한 후 private 리소스에 접속할 수 있습니다.

 

1) OpenVPN 서버를 생성합니다.

 

원하는 이름 설정

더 많은 AMI 찾아보기를 클릭합니다.

 

openvpn을 검색하고 Marketplace AMI 중 제일 위에 있는 이미지를 선택합니다.

 

인스턴스 유형은 small 이상으로 잡아주시면 됩니다.

 

vpc는 private-ec2가 올라가있는 public subnet을 선택하고 인바운드 보안 그룹 규칙은 디폴트로 설정 합니다.

(TCP/22 (SSH), TCP/943, TCP/443(웹 인터페이스에 대한 HTTPS 액세스) 및 UDP/1194)

 

나머지 설정은 디폴트로 두고 인스턴스 시작을 클릭합니다.

 

* EIP를 할당해 openvpn server의 ip가 고정이 될 수 있게 설정을 하는 것을 추천드립니다.

 

 

2) OpenVPN 서버에 접속해 설정 및 사용자를 생성 합니다.

ssh 접속

host에 OpenVPN 서버의 public ip를, username에 openvpnas, 서버의 key pair까지 넣고 ssh 접속을 합니다.

 

yes 입력 후 enter

쭉 디폴트로 enter를 치면 끝에 이미지와 같이 접속 정보를 얻을 수 있습니다.

 

Admin UI 주소로 접속

해당 서버에서 자체 발행 한 인증서를 통해 SSL 접속을 제공하기 때문에 브라우저에서 접속이 안전하지 않을 수도 있음을 경고하는 것으로 고급을 클릭한 뒤 안전하지 않음으로 이동해주세요.

 

해당 Admin UI 주소로 접속한 뒤 user / password를 입력합니다.

agree 클릭

 

 

왼쪽 내비게이션 바 CONFIGURATION > VPN Settings로 들어가 사진에 표시되어 있는 부분을 Yes로 바꿔줍니다.

 

스크롤을 쭉 내려서 Save Settings 버튼 클릭 해줍니다.

 

저는 user1으로 생성을 하였고 More Settings을 클릭하여 Password를 입력해주고 스크롤을 내려 Save Settings 버튼을 클릭 합니다.

 

그리고 꼭 Update Running server를 클릭해 줘야 설정값들이 업데이트됩니다.

 

 

3) 위에서 생성한 사용자로 로그인 합니다.

admin을 제외한 주소인 Client UI로 접속해 생성했던 사용자(user1)로 로그인 합니다.

 

접속할 사용자 OS에 맞는 클라이언트를 다운로드 한 뒤 설치 합니다.

 

OpenVPN server IP를 넣어주고 NEXT 버튼 클릭 후 Accept 버튼을 클릭합니다.

 

사용자(user1)을 넣어주고 VPN을 켜줍니다.

 

private ec2 ssh 접속

private ec2 접속이 잘 되는 것을 확인할 수 있습니다.

 

 

4. EIC endpoint를 통한 접속

EC2 인스턴스에 연결하기 위한 엔드포인트로 EC2 웹 콘솔이나 AWS CLI를 통해서 Endpoint에 접근해 인스턴스로 접속할 수 있습니다.

(SSM과의 차이점은 NAT Gateway가 없어도 EIC endpoint를 통해 접속이 가능합니다.)

 

1) VPC endpoint를 생성합니다.

EC2 > 보안그룹 > 보안 그룹 생성

엔드포인트 생성 전에 보안그룹을 먼저 생성합니다. VPC는 private ec2가 있는 vpc를 선택합니다.

(인바운드 규칙은 신경쓰지 않으셔도 좋습니다.)

 

VPC > 엔드포인트 > 엔드포인트 생성

EIC 엔드포인트를 생성합니다. VPC는 private ec2가 있는 vpc를 선택합니다.

 

위에서 생성했던 보안그룹을 선택하고 서브넷은 원하는 곳으로 선택합니다. (private, public 둘 다 가능합니다.)

엔드포인트 생성 버튼을 클릭합니다.

 

엔드포인트가 사용 가능 상태가 된다면, private ec2 접속 가능합니다.

 

 

2) private ec2에 접속합니다.

 

인스턴스 연결을 클릭합니다.

 

EC2 EIC 엔드포인트를 사용하여 연결을 클릭한 뒤 연결 버튼을 클릭합니다.

 

위 이미지와 같은 화면이 확인되면 성공적으로 접속되었음을 알 수 있습니다.

 

 

+) AWS CLI를 활용한 ssh로 접속합니다.

* aws cli 설치 되어있음

 

EIC 터널링 전용 IAM 사용자를 생성하기 위해 정책을 먼저 생성 합니다.

IAM > 정책 > 정책 생성

더보기
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "EC2InstanceConnect",
	    "Effect": "Allow",
	    "Action": "ec2-instance-connect:*",
	    "Resource": "*"
        },
        {
            "Sid": "Describe",
            "Action": [
            "ec2:DescribeInstances",
            "ec2:DescribeInstanceConnectEndpoints"
            ],
        "Effect": "Allow",
        "Resource": "*"
        }
    ]
}

원하는 이름 설정 후 정책 생성

 

EIC 터널링 전용 IAM 사용자를 생성 합니다.

IAM > 사용자 > 사용자 생성

위에서 생성했던 정책을 연결해 사용자를 생성합니다.

 

IAM > 사용자 > 생성한 사용자 > 액세스 키 생성

해당 사용자 인증을 위한 액세스 키를 발급 받습니다.

 

터미널 위에서 ssh 접속을 시도 합니다.

 

생성했던 액세스 키로 aws configure 명령어를 통해 저장 합니다.

 

aws ec2-instance-connect ssh --instance-id <private-ec2-id> --connection-type eice

위의 명령어를 입력합니다.

 

위와 같이 접속한 화면을 확인 할 수 있습니다.

 

* 기본적인 세팅은 되어 있는 상태 입니다. (VPC, Nat GW, ALB, EC2(private subnet) 구성)

* private ec2: etech-private-ec2(10.0.11.130)


1. bastion server를 통한 접속

사용자가 Bastion Server를 통해 private ec2에 ssh 프로토콜을 사용해 접속합니다.

 

1) bastion server를 생성합니다.

 

원하는 이름 설정
원하는 OS 이미지 선택
인스턴스 유형 선택

(t3.nano의 작은 유형으로도 bastion server에는 충분합니다.)

 

키페어 선택
private ec2의 vpc를 선택

vpc의 public subnet을 선택해주시고, public ip 활성화를 선택해줍니다.

보안 그룹은 원하는 이름을 넣어주시고 소스 유형을 "내 IP"로 선택해 관리자만 접속할 수 있게 설정해줍니다.

 

나머지 설정은 디폴트로 두고 인스턴스 시작을 클릭해 생성합니다.

 

 

2) 관리자가 사용하기 편한 ssh 접속 툴을 활용해 bastion server를 통해 private ec2에 접속합니다.

* MobaXterm을 활용했습니다.

 

새로운 session 추가

Remote host는 private ec2의 ip를 넣고 Specify username에는 OS에 맞는 username을 넣어줍니다.

private key는 인스턴스 생성 시 선택했던 key pair를 넣어 주시면 됩니다.

 

Bastion Host 작업을 위해 클릭
bastion server 설정

위에서 생성했던 bastion server의 public ip와 username, port와 ssh key pair를 넣고 세션을 연결합니다.

 

성공적으로 접속하면 아래와 같은 화면을 보실 수 있습니다.

 

2) SSM(System Manager)를 통한 접속

IAM 역할에 SSM 권한을 부여합니다. 그런 다음 해당 IAM 역할을 EC2에 연결하여, private 네트워크에서도 안전하게 접속할 수 있습니다.

 

1) AmazonSSMManagedInstanceCore 역할을 생성합니다.

 

AmazonSSMManagedInstanceCore가 잘 들어갔는지 확인

ssm 연결을 위해 ec2에 필요한 역할을 생성해줍니다.

 

원하는 이름 설정

위 설정이 끝나면 역할 생성을 클릭합니다.

 

 

2) private ec2에 위에서 생성한 역할을 연결해줍니다.

IAM 역할 수정 버튼 클릭

 

위에서 생성한 역할을 선택한 뒤 IAM 역할 업데이트를 클릭합니다.

( 해당 역할을 적용하는 데 시간이 상당히 소요될 수 있습니다. 빠르게 적용시키기 위해 인스턴스를 재부팅하여 시간을 단축시킬 수 있습니다.)

 

3) private ec2 에 접속합니다.

 

연결 버튼 클릭
session manager 연결 클릭

 

위와 같은 화면을 보면 private ec2에 접속 성공한 것을 알 수 있습니다.

Bulk registration 란?

IoT Core 서비스에 사물 등록을 대량으로 할 수 있게 도와주는 기능 입니다.

https://docs.aws.amazon.com/ko_kr/iot/latest/developerguide/bulk-provisioning.html

 

이번 게시물에서는 IoT Device Management의 기능 중 하나인 Bulk registration을 활용해 IoT Core 서비스에 많은 수의 디바이스를 한번에 등록하는 과정을 보여드리겠습니다.

* 실습 참고: https://catalog.us-east-1.prod.workshops.aws/workshops/753d4f22-945d-486d-8f65-8e655441c571/ko-KR/3/1


AWS Cloud9 instance를 IoT device로 활용

Cloud9의 환경 생성 화면으로 이동합니다.

(버지니아 북부(us-east-1) 리전을 기준으로 진행됩니다.)

 

1) 이름을 지정합니다.

2) 나머지 설정값은 모두 default 값을 그대로 사용합니다. 아래로 스크롤하여 생성을 클릭합니다.

 

3) Cloud9 환경이 생성 중인 대시보드를 확인할 수 있습니다. 열림 버튼을 클릭 합니다.

4) 잠시 후 Cloud9 IDE가 생성 완료되고, 아래 이미지와 같은 화면을 볼 수 있습니다.

설정 버튼을 클릭해 Show Home in Favorites를 체크합니다.

여기까지 진행했을 때 실습에 사용할 IoT device가 준비되었습니다.

 

CloudFormation template으로 resource 생성

링크를 클릭해 이번 실습에서 사용할 IAM Role resource를 생성합니다.

 

1) '스택 생성' 화면에서 다음을 클릭합니다.

2) '스택 세부 정보 지정' 화면에서 다음을 클릭합니다.

3) '스택 옵션 구성' 화면에서 다음을 클릭합니다.

4) '검토' 화면에서 문구가 있는 체크박스에 체크하고 전송을 클릭합니다.

 

리소스의 생성이 완료되는 데까지 시간이 걸립니다.

 

Bulk registration

1) 고유한 이름의 S3 버킷을 command를 활용해 생성합니다.

(여기서부터 사용되는 command들은 cloud9 terminal에 입력합니다.)

AWS account의 number를 변수로 입력받아 버킷 이름의 일부로 사용합니다.

MY_AWS_ACCOUNT_NUMBER=`aws sts get-caller-identity --query Account --output text`
aws s3 mb s3://mybucket-$MY_AWS_ACCOUNT_NUMBER

2) 새로운 사물 그룹과 타입을 생성합니다. 

aws iot create-thing-group --thing-group-name bulk-group
aws iot create-thing-type --thing-type-name bulk-type

3) mk-bulk.sh 파일을 다운로드 합니다. 이후 해당 스크립트에 실행 권한을 부여 합니다.

bulk registration을 위한 registration template을 생성하기 위한 스크립트 파일 입니다.

wget "https://ke-eu-central-1.s3.eu-central-1.amazonaws.com/devicemanagement/mk-bulk.sh"
chmod +x mk-bulk.sh

4) 아래 command를 활용해 스크립트를 실행합니다.

뒤에 파라미터로 전달되는 bulk-thing는 대량으로 등록되는 사물의 base name이고 100은 100개의 사물에 대한 정보를 registration template에 생성하겠다는 것을 의미합니다.

openssl rand -out /home/ubuntu/.rnd -hex 256
./mk-bulk.sh bulk-thing 100

위 스크립트의 결과물로 bulk-[사물이름]-[datetime] 형식의 디렉토리에 100개의 사물에 대한 key와 CSR(Certificate Signing)가 생성된 것을 확인할 수 있습니다.

bulk registration을 위한 registration template로써 bulk.json 파일이 생성된 것을 확인할 수 있습니다.

5) 생성된 디렉토리로 이동한 뒤 위에서 생성했던 S3 bucket에 registration template 파일을 업로드 합니다.

cd  bulk-thing-2023-10-18_05-00-27/
aws s3 cp bulk.json s3://mybucket-$MY_AWS_ACCOUNT_NUMBER

6) bulk registration에 사용할 template body를 아래와 같은 명령으로 다운로드 받습니다.

template body에는 bulk registration에 사용되는 파라미터와 리소스에 대한 정의가 되어 있습니다.

sudo wget "https://ke-eu-central-1.s3.eu-central-1.amazonaws.com/devicemanagement/templateBody.json"

7) 아래의 형식의 command를 활용하여, bulk registration task를 진행합니다.

[bulk registration을 수행하기 위한 IAM Role의 ARN]은 앞서 생성하신 CloudFormation의 output 탭에서 확인할 수 있습니다.

aws iot start-thing-registration-task \
  --template-body file://templateBody.json \
  --input-file-bucket mybucket-$MY_AWS_ACCOUNT_NUMBER \
  --input-file-key bulk.json --role-arn [bulk registration을 수행하기 위한 IAM Role의 ARN]

8) "taskId"를 이용해 아래 명령어로 bulk registration 수행 중 발생된 에러 및 결과를 확인합니다.

aws iot list-thing-registration-task-reports \
  --report-type ERRORS --task-id [YOUR_TASK_ID]

aws iot list-thing-registration-task-reports \
  --report-type RESULTS --task-id [YOUR_TASK_ID]

명령의 결과로써 resourceLinks가 리턴됩니다. 이는 뒤에 이어지는 절차를 위해 사용됩니다.

 

9) resoureLinks로 부터 결과를 저장합니다.

sudo wget -O results.json [resourceLinks]

결과는 results.json이라는 이름의 파일로 저장됩니다.

10) 마지막으로 bulk registration을 통하여 등록된 100개의 사물에 대한 인증서를 results.json 파일에서 추출하여 저장하기 위해 python script를 다운로드 받고 실행합니다.

wget "https://ke-eu-central-1.s3.eu-central-1.amazonaws.com/devicemanagement/bulk-result.py"
python bulk-result.py results.json

 

아래의 명령으로 bulk registration을 통해 등록된 사물의 목록을 확인합니다.

aws iot list-things

IoT Core 콘솔 화면에서도 확인할 수 있습니다.


간단하게 위 실습에서 사용했던 스크립트들의 내용을 확인하고자 합니다.

 

bulk registration을 사용하기 위해서는 아래 이미지와 같은 형식의 JSON 파일이 필요합니다.

이와 같은 파일을 얻기 위해 사용했던 스크립트가 mk-bulk.sh 이며, 결과물은 bulk.json 입니다.

 

  • mk-bulk.sh
#!/bin/bash

# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# A copy of the License is located at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# or in the "license" file accompanying this file. This file is distributed
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied. See the License for the specific language governing
# permissions and limitations under the License.

set -e

if [ -z $1 ] || [ -z $2 ]; then
    echo "usage: $0 <base_thingname> <num_things>"
    exit 1
fi

thing_name=$1
num_things=$2

date_time=$(date "+%Y-%m-%d_%H-%M-%S")

out_dir=$thing_name-$date_time
mkdir $out_dir || exit 1


for i in $(seq 1 $num_things) ; do
  openssl req -new -newkey rsa:2048 -nodes -keyout $out_dir/$thing_name$i.key -out $out_dir/$thing_name$i.csr -subj "/C=DE/ST=Berlin/L=Berlin/O=AWS/CN=Big Orchestra"

  one_line_csr=$(awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' $out_dir/$thing_name$i.csr)

  echo "{\"ThingName\": \"$thing_name$i\", \"SerialNumber\": \"$i\", \"CSR\": \"$one_line_csr\"}" >> $out_dir/bulk.json
done

echo "output written to $out_dir/bulk.json"
  • bulk.json
{"ThingName": "bulk-thing1", "SerialNumber": "1", "CSR": "-----BEGIN CERTIFICATE REQUEST-----\nMIICmjCCAYICAQAwVTELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0G\nA1UEBwwGQmVybGluMQwwCgYDVQQKDANBV1MxFjAUBgNVBAMMDUJpZyBPcmNoZXN0\ncmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrJZg2YorjtNRTTpkn\nJqaEHZDwvjixOObRNJQTKDVfpEhN5SUpxSqFZW+1aCNtH4w3Wj50lGTYomPB0BjA\n1hUlUiSqYWKgzQdXbc3EvmML/vZ2O8ky1qbTv0PiV7VyBvwPbhpTf8F+zqNwJ5WQ\nZdxkLTqNqe2b1W8EppN98mDmbKN6cN0olRTVGhbwMggHmaViVKQRgO5Mv7AcZzxX\n0MlANi52SPiP+gzx1fPj7R3SGTse2E9/eaIQfzUYWZ5woiF+L2pfvHfwAWOdRWX7\nrqiWGZmw87fq7CKox92Gid16hWuz9cifVHnpCMCQnK3j3n7eaaSYZYoFHWyHi4Kx\nnvmPAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAe/O21OLOFbzk0MiLLaIiW9EV\nR67WSaaaTSU+aurp4dQOUE7yY3u7VvdTYl4kmwSnFUipkv9KnR0WtdUvzOakXJNj\nOLlDUSFIxWWI2ovPM50kqH8u9b3f1B9XuvzU9OxBoAsTyOMPLK3SnZ5Mb1MV2wir\nUg9NqAnRAJxmOg7Zvlf4YVOw+fXvULIcbbWDEVYewu7Rxrk+uYmGOQPnDtmKi1NV\nj/Dr43YKoeweO1o86dxWkbu7ybEVCEYvX7b7n3gnAso9ppDFS0ObiveB4Jv6SIr3\nKBwDq19ojtO3f72/zqBLN5fAksWzMDlZ+pSa4cpUqqaASuOxZywS4AOGTlZk/w==\n-----END CERTIFICATE REQUEST-----\n"}
{"ThingName": "bulk-thing2", "SerialNumber": "2", "CSR": "-----BEGIN CERTIFICATE REQUEST-----\nMIICmjCCAYICAQAwVTELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0G\nA1UEBwwGQmVybGluMQwwCgYDVQQKDANBV1MxFjAUBgNVBAMMDUJpZyBPcmNoZXN0\ncmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgbZ69aKZTREVx8ieG\nptNZsWF8sm2YB46EehpVjtFY+ITNv6Ubo22K52DanoMlFqlCWRcCPWM0wmY1q3ui\ndcx1yD/bDSXP88UR/KMbe7UhPyz6zJTynFIzSmxgtlr1G5W3XBVhSKOsOlc161JA\nouVxwQyFknkIIBxTAcloRCG4/BiFTj0Sq/W9qUSBudsoOG1WCTyGYYxkuXa7OYX6\ncCNK4BFOXsptvUXJOEV3fhQLqb++Ubngrofe1tSoSjU2xOylRwkz18sqA6R0+Wie\n7AGTiCSQJK+PJmyxct7ieqzzcEocMFt75zl3vNI1xQJ3hJCXJ+tbB6LtSlW247S2\nErDtAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAdmEQEX4efWKC0WV9jAEOgBO9\nMikEnJvFdjK38K0gfK3RYarsJKlWqnUmL6tL+jCpHfqygMuxdvKwk4ewvAYI1RQA\ntMaF87DeF19vf6pVqyBIAI1+Njniio2v8BKPWNTfgbRZXwGgru2JJL4hsIkxcvnK\nGSRSNuRKstZ9oNbRizXYKSgq1BTzt9+ufXqYYPd50ReU5AZ5o9DTeUOkJI92UihN\nIH/abMGZJ0t23mGRRMHriWWRozaonp+kxnpI6VLdZamgDVk1WVRB24K7S6pYnUgw\n0MfVXkNFeUB+xgQshPi+GaLoEDT6flPqKNiorml3aoaVQ6BtcWuJm4icDHKZ3g==\n-----END CERTIFICATE REQUEST-----\n"}
{"ThingName": "bulk-thing3", "SerialNumber": "3", "CSR": "-----BEGIN CERTIFICATE REQUEST-----\nMIICmjCCAYICAQAwVTELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0G\nA1UEBwwGQmVybGluMQwwCgYDVQQKDANBV1MxFjAUBgNVBAMMDUJpZyBPcmNoZXN0\ncmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEVVg+gbu7hA2g+cUu\nlSnR7QkGUe3Z7ZKz/zEfN24yfY4xjJDdmcSyGYGfCUlmByfL5p80kuqv4GBvhVPK\nU9Re8xFU3CfMCjW1HEDWFbPo97SUrHWVk2glPsz9TJUi8+GcB6X6Zq5NTzkCYtcv\nF0eX+E7YeQBrSu8JqzrfCXlvNvNGS4m25Iug1i64Z+OD85opfxZogVc69Ans/PvN\nPvZH26gEtimab2Bvz74D/tMZ3GmU4Ox3lZfUU26XLgHRFEltP0leuBZJ5CTYqBHK\nhAVXExtITFdpR1jrCGWkXrR4cFibrjAxjGeCNVdnaKJvwlqyLDewEhYI5+FfCBy+\nKItbAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAls4+bShW0Oo5h7iAX6YABswk\nHVn12D3t0ab5gh1+cad15MdvlwMd4nXXxTp1eKiWoRCxERnBcfz49axkmCtO46/S\nG33A2Zf6pLmDUHToZymPwrthogKN7FadqLK9cS0OUNylCVB9pZiyhTcqEIe4uPtw\nwESKkEiKzYdtKq5904flBi/VEv01xXrh+FrnBsxprCwJ+bqFpZPpRPISPr74JX2M\nK+zqCdTZGT4J5I2yLm4jyTRiG9jyEaMt46aZnVnc0I3A0PBuKa7a9yhIph8s/6t8\nuixtflUid0kUrAodW4mHlVFiaDXNf89HvFTz27Cven7GHcJ8DZNIcwIg18Kh6A==\n-----END CERTIFICATE REQUEST-----\n"}
{"ThingName": "bulk-thing4", "SerialNumber": "4", "CSR": "-----BEGIN CERTIFICATE REQUEST-----\nMIICmjCCAYICAQAwVTELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0G\nA1UEBwwGQmVybGluMQwwCgYDVQQKDANBV1MxFjAUBgNVBAMMDUJpZyBPcmNoZXN0\ncmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDExTtxTw21CqyV4szp\neC1T8ilN1lxn4VUrna1HtrLkj2PRcjzggz4/s5EG4pntHgM5cbdknhUZ11eQHrLk\naB/YVm/lsAo4LlzCsFnzSDQlLBUuWNggzdkJDjrvhG9ZUYt75XD9gOfD2diLFCij\nLdF4BkaPLlO/4K+M90zrW5H6P6laflUQQ2r3jVH57YfhDeEBdpd21ykF/mBq1zgp\nyNzrdeamzizrTDu9vrfvlRKrPMQqiiuH0JLaSDX26zLjp6H2LoF7d3e5LiTyWosu\nV0VCq74JktWT9T9V7FMxeHnNfvlKa8o0DPjBDc6myshReMuH9ncEmgdITi9OWcvc\nnG0fAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAXo8KdoTFwtgkwSJM+4YdYeE9\n24vbVJZiwkXcVwm20wgYgrRFDwLAADfaWylo9gWXMjM8gZh5/DH77ixkhJw833F5\nhxRRG+oFGrUZMFutUSg0jO2HoFEh7bIpzNy3CVzpO8LXPZ1rzTvBR9ZLYutdTE03\noRHwvV4XL5DLoRHoU9+KhcF0B5+hmRI9fAavJLieOw3lezfjwEaERhrB5CwGv4mS\nkQeR03sBKuI2AyKDClH0AHHDjaQgOG2kQ/uVIMJ+XzrMRtG2k5J6MqkZlTpAvh1G\n7nfc6jRKetK9pZzyqHqnaFUgal9flMfoHgmJeGdpN7HXwOKI3ioCcv9NPyidMw==\n-----END CERTIFICATE REQUEST-----\n"}
{"ThingName": "bulk-thing5", "SerialNumber": "5", "CSR": "-----BEGIN CERTIFICATE REQUEST-----\nMIICmjCCAYICAQAwVTELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0G\nA1UEBwwGQmVybGluMQwwCgYDVQQKDANBV1MxFjAUBgNVBAMMDUJpZyBPcmNoZXN0\ncmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsGjxWIhhjVMa7YuPx\nuSHfJQmkoZuInblb4MzsYRTiRuopbqq9PKEX3ChNstRuByp/XzebxRbbfvH58kDu\n+npB8W0gb+HRHnheLfp3uDTHvo6USq5oMSpVlz5ASpdoouP1cpTkUhwK7FGdv9xi\nBQ9RDDyJSIfYcCLC+qe+ldFeoehchWFlpPhz0nU1zBDhcvekTarBl77a+5cEPu2K\nvmPGoFf8TsXqG5zBe6CSXyTa+7MUeEYBndLugcGCHTCZbmUIV4Qjm73QeRteC7q+\nwsgRgRpeDtdMVtYL0y4k0AJ15TJeBGDJtu62YH6rdNGfxecjaZ7U9smsQNGWt2WQ\nnGbtAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAah1FTcn1B2KxlPuxAKxLS6Py\nIJljoAKAXsZM0VSk7N0vfuurSepkd2XHTxFaj6gobxPpmT2Mu5zbnILpL8kC5sGX\nx+hEF1OXomkIsfw4WXMF0yKqMBrQdMTqTa+TlqG5te+TA2JfgZjp7Kot6iLdLC8H\nZuvBg4PUKtIlk2o6S0V/fORg70ZhHKb3G9qCJbotsg6zcChKTWzfSF1IgZzhe79V\nB4ZgECv60c8XpzpxYLGvcKc6CX/Yl9NppmrteXGJvTAhdzMaJUagWM58Oh3XJsQh\nUX726VmnZM78PmY46KcZt3O5z3IEv0EbmytAFoZS+leLqT7b1cDf2mAQRU7Uhg==\n-----END CERTIFICATE REQUEST-----\n"}
...

 

bulk registration은 start-thing-registration-task 명령을 사용해 진행합니다.

inputFileBucketS3 bucket, inputFileKeybulk.json, roleArn은 위에서 cloudformation으로 생성했던 role이며

templatebody는 아래의 스크립트 입니다. 

templatebody는 bulk registration에 사용되는 파라미터와 리소스에 대한 정의가 되어 있어야 합니다.

  • templateBody.json
{
  "Parameters" : {
     "ThingName" : {
       "Type" : "String"
     },
     "SerialNumber" : {
       "Type" : "String"
     },
     "Location" : {
        "Type" : "String",
        "Default" : "WA"
     },
     "CSR" : {
       "Type" : "String"
     }
  },
  "Resources" : {
    "thing" : {
      "Type" : "AWS::IoT::Thing",
      "Properties" : {
        "ThingName" : {"Ref" : "ThingName"},
        "AttributePayload" : { "version" : "v1", "serialNumber" :  {"Ref" : "SerialNumber"}},
        "ThingTypeName" :  "bulk-type",
        "ThingGroups" : ["bulk-group"]
      }
    },
    "certificate" : {
      "Type" : "AWS::IoT::Certificate",
      "Properties" : {
        "CertificateSigningRequest": {"Ref" : "CSR"},
        "Status" : "ACTIVE"
      }
    },
    "policy" : {
      "Type" : "AWS::IoT::Policy",
      "Properties" : {
        "PolicyDocument": "{\"Version\": \"2012-10-17\",\"Statement\": [{\"Effect\": \"Allow\",\"Action\": [\"iot:*\"],\"Resource\": [\"*\"]}]}"
      }
    }
  }
}

 

결과로 Task ID를 확인할 수 있으며 resourceLinks 리턴 값을 확인하기 위해 필요합니다.

얻은 resourceLinks로 부터 실행 결과를 저장합니다. 저장한 파일이 results.json 파일 입니다.

  • results.json
{"lineNumber":1,"offset":1057,"response":{"CertificatePem":"-----BEGIN CERTIFICATE-----\nMIIDkDCCAnigAwIBAgIUWS2Okfw8JY6kC/+jEJfv8vvwyPEwDQYJKoZIhvcNAQEL\nBQAwTTFLMEkGA1UECwxCQW1hem9uIFdlYiBTZXJ2aWNlcyBPPUFtYXpvbi5jb20g\nSW5jLiBMPVNlYXR0bGUgU1Q9V2FzaGluZ3RvbiBDPVVTMB4XDTIzMTAxODA1MTEz\nMloXDTQ5MTIzMTIzNTk1OVowVTELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxp\nbjEPMA0GA1UEBwwGQmVybGluMQwwCgYDVQQKDANBV1MxFjAUBgNVBAMMDUJpZyBP\ncmNoZXN0cmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrJZg2Yorj\ntNRTTpknJqaEHZDwvjixOObRNJQTKDVfpEhN5SUpxSqFZW+1aCNtH4w3Wj50lGTY\nomPB0BjA1hUlUiSqYWKgzQdXbc3EvmML/vZ2O8ky1qbTv0PiV7VyBvwPbhpTf8F+\nzqNwJ5WQZdxkLTqNqe2b1W8EppN98mDmbKN6cN0olRTVGhbwMggHmaViVKQRgO5M\nv7AcZzxX0MlANi52SPiP+gzx1fPj7R3SGTse2E9/eaIQfzUYWZ5woiF+L2pfvHfw\nAWOdRWX7rqiWGZmw87fq7CKox92Gid16hWuz9cifVHnpCMCQnK3j3n7eaaSYZYoF\nHWyHi4KxnvmPAgMBAAGjYDBeMB8GA1UdIwQYMBaAFDLldBsUWUJZzfI2E7nzlgYh\nSyocMB0GA1UdDgQWBBSoES/LeLU38FdLKaCbwqDZeXYEszAMBgNVHRMBAf8EAjAA\nMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAQEAj+SDRZTvuqib7bTH\nz5YRxuCTNlFFV/n0VgI6NY2J/taZTscYQowanA6dQoKK3Run00qsW/MjbBpVQGrb\nC67SabsZNIjkGmCHpiW1VwlMYwapMAbZJNzRVi9amO0EEJYS+Gdy1wlT/qwE2YRD\n2hOtTwG/L9E+Oy9xTVMzRDDU4snuVQfYuHH3HL/KxEEg9MZbM8VMYI+VQmiKHZe8\nYQXYR37t9Hxq7bfyQvpfSIsKsZ283aYxY3dmHB+xrFQ2tjS8dfuXpEzrgjdYwddm\nmR6SEf7kwsPgTPDJM/U5FciNcuXmnrVki4wuGIqeI3Iwt9qHpWcnuixqmb7rHf7c\nM7mCDQ==\n-----END CERTIFICATE-----\n","ResourceArns":{"certificate":"arn:aws:iot:us-east-1:986611521344:cert/df6c6420c47571595daba7446b203a2ffdabafc68e2e7a94972e9e77a696cb38","policy":"arn:aws:iot:us-east-1:986611521344:policy/EA1A0CDFCEDEAEE65D65B7AB012F0D7D89208F1EDA825C85F28063F9DC4005BC","thing":"arn:aws:iot:us-east-1:986611521344:thing/bulk-thing1"}}}
{"lineNumber":2,"offset":2114,"response":{"CertificatePem":"-----BEGIN CERTIFICATE-----\nMIIDkDCCAnigAwIBAgIUS/f0saWs0Lc5U/Hy407Gj8wN3A4wDQYJKoZIhvcNAQEL\nBQAwTTFLMEkGA1UECwxCQW1hem9uIFdlYiBTZXJ2aWNlcyBPPUFtYXpvbi5jb20g\nSW5jLiBMPVNlYXR0bGUgU1Q9V2FzaGluZ3RvbiBDPVVTMB4XDTIzMTAxODA1MTEz\nMloXDTQ5MTIzMTIzNTk1OVowVTELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxp\nbjEPMA0GA1UEBwwGQmVybGluMQwwCgYDVQQKDANBV1MxFjAUBgNVBAMMDUJpZyBP\ncmNoZXN0cmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgbZ69aKZT\nREVx8ieGptNZsWF8sm2YB46EehpVjtFY+ITNv6Ubo22K52DanoMlFqlCWRcCPWM0\nwmY1q3uidcx1yD/bDSXP88UR/KMbe7UhPyz6zJTynFIzSmxgtlr1G5W3XBVhSKOs\nOlc161JAouVxwQyFknkIIBxTAcloRCG4/BiFTj0Sq/W9qUSBudsoOG1WCTyGYYxk\nuXa7OYX6cCNK4BFOXsptvUXJOEV3fhQLqb++Ubngrofe1tSoSjU2xOylRwkz18sq\nA6R0+Wie7AGTiCSQJK+PJmyxct7ieqzzcEocMFt75zl3vNI1xQJ3hJCXJ+tbB6Lt\nSlW247S2ErDtAgMBAAGjYDBeMB8GA1UdIwQYMBaAFCehQabmnQRs29ETKNaNKTJo\nFGySMB0GA1UdDgQWBBQgQze4qB6CJG06d8Xjbh7WqsQzJTAMBgNVHRMBAf8EAjAA\nMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAQEAi2JZadms+v2srXlJ\nDgcg4gvVWXoPaQk0ujnaHqE4545urRn70vy8JMpB1IeBsbPxLFML2C/gCARdcXE2\nOEhcIw1Y3XKDxYTxSbUU6U7XilXpPNItJf4AnS2e37y9ufHHTDq7dMuNV91SyCNn\nnlscbdbatjkLDojeu3/Wv5WIiKHf8WGHN1Hrso+uZeDJxYrtkgTD9G/ypkdzCPw6\nuSCpN4j0J6Qg8pvR/TaL7lisXoRqFna9BTm9B1FIrheZlDCcvi6XtbaPoDAkuqeQ\nIuKeV9N5DR9k1fuuu7RENftkVfOiIJnS76FI7N9cuU9KL/LB2yYDh/Z0bEPz2kd5\nwO6RaA==\n-----END CERTIFICATE-----\n","ResourceArns":{"certificate":"arn:aws:iot:us-east-1:986611521344:cert/c305346f959b269a9e434397ffd6b3c8dbe7ed12539440483fd4bbf5f55bef14","policy":"arn:aws:iot:us-east-1:986611521344:policy/EA1A0CDFCEDEAEE65D65B7AB012F0D7D89208F1EDA825C85F28063F9DC4005BC","thing":"arn:aws:iot:us-east-1:986611521344:thing/bulk-thing2"}}}
{"lineNumber":3,"offset":3171,"response":{"CertificatePem":"-----BEGIN CERTIFICATE-----\nMIIDkDCCAnigAwIBAgIUBeVIR2wCJdZMO2XFaxph/dSWBJgwDQYJKoZIhvcNAQEL\nBQAwTTFLMEkGA1UECwxCQW1hem9uIFdlYiBTZXJ2aWNlcyBPPUFtYXpvbi5jb20g\nSW5jLiBMPVNlYXR0bGUgU1Q9V2FzaGluZ3RvbiBDPVVTMB4XDTIzMTAxODA1MTEz\nMloXDTQ5MTIzMTIzNTk1OVowVTELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxp\nbjEPMA0GA1UEBwwGQmVybGluMQwwCgYDVQQKDANBV1MxFjAUBgNVBAMMDUJpZyBP\ncmNoZXN0cmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEVVg+gbu7\nhA2g+cUulSnR7QkGUe3Z7ZKz/zEfN24yfY4xjJDdmcSyGYGfCUlmByfL5p80kuqv\n4GBvhVPKU9Re8xFU3CfMCjW1HEDWFbPo97SUrHWVk2glPsz9TJUi8+GcB6X6Zq5N\nTzkCYtcvF0eX+E7YeQBrSu8JqzrfCXlvNvNGS4m25Iug1i64Z+OD85opfxZogVc6\n9Ans/PvNPvZH26gEtimab2Bvz74D/tMZ3GmU4Ox3lZfUU26XLgHRFEltP0leuBZJ\n5CTYqBHKhAVXExtITFdpR1jrCGWkXrR4cFibrjAxjGeCNVdnaKJvwlqyLDewEhYI\n5+FfCBy+KItbAgMBAAGjYDBeMB8GA1UdIwQYMBaAFF2PWXbNwWujfogNBhqjK4/6\nNPg/MB0GA1UdDgQWBBSB+SGoDg4XKzQWd3NFY8Qg8VOVrjAMBgNVHRMBAf8EAjAA\nMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAQEAllSQWPysC1p3IkyX\nJ4Pzvl2chkRCBFR9/tob90SOXJSJ3WYN/5Bbgl/WURppj9VJXCxawj3AxqBxBMfx\n66a0uL1dxEgYYOJf79ODxupipUFxIg1yTfQSKpIoL9UDZ+84y9h4wMpzIHyIXxMP\nntKuOIivw2qizIEuSyqvIc2nZ2W9gMxxVVvN2KhfBkJ9QBDdM4Q2TJ8gSKoSDt8r\noP5b4oeVVPYKuP+QYlth2MsJJEr0Zwzlq6jZe8tLofbqkl+Vk+nAVj8DyoPqANi4\n17zbWYb37zMfrx21Y5NEZY25JxgkU5lnONzbpoTIZpJCM/0D7hvhgPWdXidCDzW1\nn/eObQ==\n-----END CERTIFICATE-----\n","ResourceArns":{"certificate":"arn:aws:iot:us-east-1:986611521344:cert/4d3db30b101486d79bdba67acdd044e006b03be805662e2fcdf54c98b83425e0","policy":"arn:aws:iot:us-east-1:986611521344:policy/EA1A0CDFCEDEAEE65D65B7AB012F0D7D89208F1EDA825C85F28063F9DC4005BC","thing":"arn:aws:iot:us-east-1:986611521344:thing/bulk-thing3"}}}
{"lineNumber":4,"offset":4228,"response":{"CertificatePem":"-----BEGIN CERTIFICATE-----\nMIIDkTCCAnmgAwIBAgIVAIWvypjuGj6W2AIslOrGetxD0ZFrMA0GCSqGSIb3DQEB\nCwUAME0xSzBJBgNVBAsMQkFtYXpvbiBXZWIgU2VydmljZXMgTz1BbWF6b24uY29t\nIEluYy4gTD1TZWF0dGxlIFNUPVdhc2hpbmd0b24gQz1VUzAeFw0yMzEwMTgwNTEx\nMzJaFw00OTEyMzEyMzU5NTlaMFUxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIDAZCZXJs\naW4xDzANBgNVBAcMBkJlcmxpbjEMMAoGA1UECgwDQVdTMRYwFAYDVQQDDA1CaWcg\nT3JjaGVzdHJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxMU7cU8N\ntQqsleLM6XgtU/IpTdZcZ+FVK52tR7ay5I9j0XI84IM+P7ORBuKZ7R4DOXG3ZJ4V\nGddXkB6y5Ggf2FZv5bAKOC5cwrBZ80g0JSwVLljYIM3ZCQ4674RvWVGLe+Vw/YDn\nw9nYixQooy3ReAZGjy5Tv+CvjPdM61uR+j+pWn5VEENq941R+e2H4Q3hAXaXdtcp\nBf5gatc4Kcjc63Xmps4s60w7vb6375USqzzEKoorh9CS2kg19usy46eh9i6Be3d3\nuS4k8lqLLldFQqu+CZLVk/U/VexTMXh5zX75SmvKNAz4wQ3OpsrIUXjLh/Z3BJoH\nSE4vTlnL3JxtHwIDAQABo2AwXjAfBgNVHSMEGDAWgBQy5XQbFFlCWc3yNhO585YG\nIUsqHDAdBgNVHQ4EFgQUhYszV4B85CElJU6VACJzmZDWEhgwDAYDVR0TAQH/BAIw\nADAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBALQjwi6ksFANrA6t\nVm0OAKC6yRYD3yNr7BubqnIWlhyNhzYCvUbC/tmOh2lCA/20Cnrkf4BLofYVb227\nt1jsE65zVgPtAt5dAiG0DrJqdSKtieftkGsZ0iSKsKtFUc3s5HxGuwsn/eJn+GTG\nOBWlK9J1PeQJf07iHWimWzZCaPJwK9aT+m8s7vfgmOJ01dtyOW2yrrxYiCEQAyA6\nYLL2/uA8X/WqJVsqPaVku0t0LEKmg6Ir6MkPi3auLDEUKkuKljsQ3CuD4eqON19T\nJzNHFlsiYOhtDn+G0KYiqMmt495hsegvIbdiPyseYeU/DcNLocp8fEeiNS2WSWnA\n4fE3ges=\n-----END CERTIFICATE-----\n","ResourceArns":{"certificate":"arn:aws:iot:us-east-1:986611521344:cert/0f084113392b5c78e57dfc1e00040617eb1e5d71c17215d3963b7ca40fb3cf74","policy":"arn:aws:iot:us-east-1:986611521344:policy/EA1A0CDFCEDEAEE65D65B7AB012F0D7D89208F1EDA825C85F28063F9DC4005BC","thing":"arn:aws:iot:us-east-1:986611521344:thing/bulk-thing4"}}}
{"lineNumber":5,"offset":5285,"response":{"CertificatePem":"-----BEGIN CERTIFICATE-----\nMIIDkDCCAnigAwIBAgIUFcHa6lHkMdUDK7SSUkMWxe4tbZkwDQYJKoZIhvcNAQEL\nBQAwTTFLMEkGA1UECwxCQW1hem9uIFdlYiBTZXJ2aWNlcyBPPUFtYXpvbi5jb20g\nSW5jLiBMPVNlYXR0bGUgU1Q9V2FzaGluZ3RvbiBDPVVTMB4XDTIzMTAxODA1MTEz\nMloXDTQ5MTIzMTIzNTk1OVowVTELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxp\nbjEPMA0GA1UEBwwGQmVybGluMQwwCgYDVQQKDANBV1MxFjAUBgNVBAMMDUJpZyBP\ncmNoZXN0cmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsGjxWIhhj\nVMa7YuPxuSHfJQmkoZuInblb4MzsYRTiRuopbqq9PKEX3ChNstRuByp/XzebxRbb\nfvH58kDu+npB8W0gb+HRHnheLfp3uDTHvo6USq5oMSpVlz5ASpdoouP1cpTkUhwK\n7FGdv9xiBQ9RDDyJSIfYcCLC+qe+ldFeoehchWFlpPhz0nU1zBDhcvekTarBl77a\n+5cEPu2KvmPGoFf8TsXqG5zBe6CSXyTa+7MUeEYBndLugcGCHTCZbmUIV4Qjm73Q\neRteC7q+wsgRgRpeDtdMVtYL0y4k0AJ15TJeBGDJtu62YH6rdNGfxecjaZ7U9sms\nQNGWt2WQnGbtAgMBAAGjYDBeMB8GA1UdIwQYMBaAFOopp+NqKhItJByY4EHCINF9\nPRqTMB0GA1UdDgQWBBQdKrfT2/+w3Or5AF6icH14JjXJjjAMBgNVHRMBAf8EAjAA\nMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAQEAUUvQ8JaYwaUW99Ma\nE+Yk5GdqSzkR4hqlKzdt/GOWw+KP3dVa8fUlSmWwQd3B7IgbBegwFLbSykjPWfru\n+rpYvzkV9PQjV1PRDPbtEf4CUEj2skOMWj/bz0nOpi38cbNcCZTNDQ61Oq+h0Qt9\nLYmyl+Dg4gwlzmyfMArlmUqQVT3+9mbo4DLkX2DcMiElYkF9soJ8RlKImLf266UR\nNLV4NCafl70h/3fAnDSI4/ch+Jhcs+h2yEPMk5RksFGhvSf8cPqiZ00ndCE++yAG\nMpfhYyNVL1NsixL4wBlgylwS2zlD5OvSQatXp5VzoqGQKjexgr/5cBxS8Juzw28n\nHN7X3A==\n-----END CERTIFICATE-----\n","ResourceArns":{"certificate":"arn:aws:iot:us-east-1:986611521344:cert/125249f7baa1510da78a560e83de53fb4c59730837d7a91e2ede0a93c1cc333e","policy":"arn:aws:iot:us-east-1:986611521344:policy/EA1A0CDFCEDEAEE65D65B7AB012F0D7D89208F1EDA825C85F28063F9DC4005BC","thing":"arn:aws:iot:us-east-1:986611521344:thing/bulk-thing5"}}}
...

 

인증서(pem 파일)를 results.json 파일에서 추출하여 파일로 저장하기 위해 아래의 python 스크립트를 실행합니다.

(해당 응답을 잃어버리면 인증서를 얻을 방법이 없기 때문에 파일로 추출해 저장하는 것이 좋습니다.)

  • bulk-result.py
#!/usr/bin/python

# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# A copy of the License is located at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# or in the "license" file accompanying this file. This file is distributed
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied. See the License for the specific language governing
# permissions and limitations under the License.

import json
import os
import sys


def process_line(line):
    d = json.loads(line)
    crt = d["response"]["CertificatePem"]
    thing = d["response"]["ResourceArns"]["thing"].split('/')[1]
    print("creating file {}.cert.pem for thing {}".format(thing, thing))
    file = open(thing + ".cert.pem", "w")
    file.write(crt)
    file.close()

def process_results(file):
    try:
        with open(file) as f:
            for line in f:
                process_line(line)
        f.close()
    except Exception as e:
        print("error opening file {}: {}".format(file,e))
        return None

def main(argv):
    if len(argv) == 0:
        print("usage: {} <result_filename>".format(os.path.basename(__file__)))
        sys.exit(1)

    process_results(argv[0])

if __name__ == "__main__":
    main(sys.argv[1:])

 

감사합니다.

참고: https://catalog.us-east-1.prod.workshops.aws/workshops/de4e38cb-a0d9-4ffe-a777-bf00d498fa49/ko-KR

고객사에서 OpenSearch 서비스를 활용 중이라 무슨 서비스인지 알고 싶어서 무작정 따라해봤다..!


Amazon OpenSearch 클러스터 생성

  • create domain

테스트니까 네트워크는 퍼블릭으로, 나머지 설정들은 디폴트로 놔두면 된다..

(뭐시기 에러뜨면.. 고급 클러스터 설정 쪽 최대 절 수 그냥 1024로 설정..)

생성 완료까지 시간이 좀 걸린다.

 

AWS Blog 문서를 Amazon OpenSearch로 검색하기

  • cloud9 인스턴스 생성
  • OpenSearch - 인덱스 생성

OpenSearch 대시보드에 들어간다.

로그인의 경우 아까 클러스터 생성할 때 사용했던 ID/Password를 사용하면 된다.

해당 버튼을 클릭하고 접속한다.

private &rarr; confirm

메뉴의 Dev Tools 를 클릭한다.

(검색을 위한 index 생성하고 mapping 설정)

아래 코드 붙여넣고 화살표 클릭해서 실행

PUT /aws-blog
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "author": {
        "type": "keyword"
      },
      "body": {
        "type": "text"
      },
      "category": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "date": {
        "type": "date",
        "format": "dd MMM yyyy HH:mm:ss z"
      },
      "url": {
        "type": "keyword"
      }
    }
  }
}

여기까지의 단계가 AWS blog 문서들을 색인할 index를 생성한 것!

 

  • Blog 문서를 index에 저장하기

cloud9에 접속 후 아래 명령어를 입력한다.

git clone https://github.com/jinuland/aws-blog-crawler.git

해당 파일을 클릭하고 host, id, password를 입력한다. host는 OpenSearch의 도메인 엔드포인트이다.

cd aws-blog-crawler
./ingest_ko.sh

위 명령어 처럼 프로그램을 실행시킨다. (AWS Blog 글들이 OpenSearch 도메인으로 색인된다.)

 

  • OpenSearch 대시보드에서 문서 검색해보기

OpenSearch의 DevTools로 돌아가 아래처럼 입력한다.

GET /aws-blog/_search
{
  "query": {
    "match_all": {
    }
  }
}

 

Full Text 검색

  • Dev Tools에서 API 호출

(workshop 기준으론 Dev Tools로  API를 호출하지만, Application에서 검색 서비스 제공을 하고 싶으면 

API Gateway + Lambda + OpenSearch로 구현할 수 있다.)

즉, Dev Tools에서 아래처럼 쿼리를 날리면 원하는 결과를 얻을 수 있다.

# 자연어 검색
GET /aws-blog/_search
{
  "query": {
    "multi_match": {
      "query": "aws 리전 및 인프라",
      "fields": ["title","body"]
    }
  }
}

# Author 별 Aggregation
GET /aws-blog/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "title": "데이터"
          }
        }
      ]
    }
  },
  "aggs": {
    "category": {
      "terms": {
        "field": "author"
      }
    }
  }
}

위와 같이 OpenSearch를 활용한다... 

시각화를 구현하진 않았지만.. 시각화까지 가능함!

 

[OpenSearch 기능]

https://aws.amazon.com/ko/opensearch-service/features/

미리 AWS 환경은 세팅해둔 상태! (external alb - web(ec2) - was(ec2))

직접 apache와 tomcat을 올려보기 위한 작업을 할 것이다...

 

왜 web - was 분리 구성을 하는가?

https://hwanchang.tistory.com/5


WEB 서버 구성(Apache)

  • Apache 설치 및 시작
yum install -y httpd
systemctl start httpd
  • alb 의 target group 상태검사 경로 변경 

  • index.html 생성
cd /var/www/html
vi index.html

# index.html
<html>
<body>WEB-A 서버입니다.</body>
</html>
  • health check: alb dns 주소를 통해 확인

  • health check: curl 명령어 활용

 

WAS 서버 구성(Tomcat)

  • java 다운로드 & tomcat 다운로드

https://www.oracle.com/java/technologies/downloads/

https://tomcat.apache.org/에서 다운로드

tar xvzf <파일명>
cp -R <디렉토리명> /usr/local/src
  • tomcat, jdk 경로 설정
vi /etc/profile

# 경로 확인
source /etc/profile
echo $JAVA_HOME
echo $CATALINA_HOME

  • tomcat 서비스 등록
cd /etc/init.d
vi tomcat

# tomcat file
#!/bin/bash
# Startup script for the Tomcat Server
# chkconfig : 345 50 50
# description: Tomcat is a Web application server.
# processname : java
# directory :
CATALINA_HOME=/usr/local/src/apache-tomcat-10.1.11
export JAVA_HOME=/usr/local/src/jdk-17.0.8
export CATALINA_HOME=/usr/local/src/apache-tomcat-10.1.11
case "$1" in
start)
echo "Starting tomcat: "
$CATALINA_HOME/bin/startup.sh
;;
stop)
echo "Shutting down tomcat: "
$CATALINA_HOME/bin/shutdown.sh
;;
restart)
echo "Restarting tomcat: "
$CATALINA_HOME/bin/shutdown.sh
$CATALINA_HOME/bin/startup.sh
;;
*)
echo "Usage: service tomcat"
start|stop|restart
exit 1
esac
exit 0

chmod 755 tomcat
service tomcat start

  • EC2 SG에 8080 포트 오픈
  • WAS 서버 index.html 생성
cd /usr/local/src/apache-tomcat-10.1.11/webapps/ROOT
vi index.html

# index.html
<html>
<body>WAS-A 서버입니다.</body>
</html>

 

WEB 서버 - WAS 서버 연동

  • WEB 서버 내부에 httpd.conf 파일 수정
vi /etc/httpd/conf/httpd.conf

###New Configuration
<VirtualHost *:80>
    ServerName <alb-dns주소>

    ProxyPass / http://<was-ip>:8080/
    ProxyPassReverse / http://<was-ip>:8080/
</VirtualHost>

systemctl restart httpd.service
  • WAS 서버
cd /usr/local/src/tomcat/bin
./shutdown.sh
./startup.sh
  • alb dns 접속 시 WAS 화면이 뜨면 성공 

 

 

참고: https://sweetysnail1011.tistory.com/57

 

❗java 다운받을 때 프로세서 확인 꼭 하기 uname -i 명령어 활용❗

'Computer Science > DevOps' 카테고리의 다른 글

[Monitoring] Monitoring vs Observability  (0) 2025.01.13
[Jenkins] 다양한 플러그인 활용  (0) 2023.07.24
[Jenkins] Jenkins Pipeline 구축  (0) 2023.07.03
[Jenkins] Jenkins 다뤄보기  (0) 2023.06.27
[OS] OS 모음집  (0) 2021.08.12

+ Recent posts