0%

Oracle Cloud 인스턴스 자동 생성 매크로 만들기

서론

오라클 클라우드는 타 클라우드에 비해 free tier가 매우 훌륭합니다. Arm 기반으로 생성을 하면 최대 24GB의 메모리를 제공받을 수 있습니다.

하지만 가입부터 인스턴스를 생성하는 과정이 매우 매우 힘듭니다. arm 인스턴스를 생성하다 보면 매우 높은 확률로 다음과 같은 에러를 만나게 됩니다.

1
Out of capacity for shape VM.Standard.A1.Flex in availability domain AD-1. Create the instance in a different availability domain or try again later. If you specified a fault domain, try creating the instance without specifying a fault domain. If that doesn’t work, please try again later. Learn more about host capacity.

그래서 이번에는 오라클 클라우드 인스턴스를 자동으로 생성하는 매크로를 만들어보겠습니다.

준비물

  • 오라클 클라우드 계정
  • 24시간 이상 사용 가능한 컴퓨터
  • docker

key 파일 준비

먼저 저희는 oci-cli를 사용 할 것입니다. 이를 사용하기 위해서는 key 파일이 필요합니다.

오라클 클라우드에 접속하여 로그인을 합니다.

우측 상단에 있는 프로필을 클릭해서 본인의 계정으로 이동합니다.
11

API 키를 클릭합니다. 그리고 Add API key를 클릭합니다.
12

private key와 public key를 다운로드 받습니다. (보관에 주의하세요)
13

그러고 나면 다음과 같은 화면이 나옵니다. 나중에 쓰일 것이니 Copy를 눌러 복사해둡니다.
14


서버 준비

24시간 돌아가는 서버에 script를 올려서 주기적으로 요청을 보낼거기 때문에 도커가 깔린 서버를 준비합니다. Free-tier에서 제공하는 VM.Standard.E2.1.Micro를 사용하셔도 무방합니다.

도커를 실행하기 전에 인증을 위한 파일을 설정해야 합니다.

1
mkdir ~/.oci

그리고 ~/.ociconfig 파일을 만들어줍니다. config 파일은 위에서 copy한 내용을 붙여넣어줍니다.

주의할 점은 key_file에는 위에서 다운 받은 private key 파일의 이름을 넣어주어야 합니다.

1
2
3
4
5
6
7
8
cat <<EOF > ~/.oci/config
[DEFAULT]
user=[copy한 내용]
fingerprint=[copy한 내용]
tenancy=[copy한 내용]
region=[copy한 내용]
key_file=~/.oci/[private key 이름].pem
EOF

이번에는 private key 파일을 ~/.oci에 옮겨줍니다. private key 파일을 열어서 내용을 복사한 뒤 다음과 같이 입력합니다.

아마 형식은 아래와 같을 것입니다.

1
2
3
4
5
6
cat <<EOF > ~/.oci/[private key 이름].pem
-----BEGIN PRIVATE KEY-----
[키내용]
-----END PRIVATE KEY-----
OCI_API_KEY
EOF

여기까지 오셨다면 거의 다 왔습니다.


도커 실행하기

1
docker run -d --name oci --entrypoint /bin/bash -v "$HOME/.oci:/oracle/.oci" ghcr.io/oracle/oci-cli:latest -c "sleep infinity"

잘 실행되었는지 확인하기 위해 다음 명령어를 실행합니다.

1
2
docker exec -it oci bash
oci iam compartment list -c [tenancy 값] --all

경고는 무시하시고 아래와 같이 나온다면 성공입니다.
15


쉘 스크립트 작성

깃 허브 기반으로 수정된 버전 입니다.

먼저 인스턴스를 인스턴스 생성을 시도해야 합니다. 아래 메뉴에서 Instances를 클릭 후 인스턴스를 생성 합니다.
1

인스턴스를 생성하기 전에 크롬 개발자 도구를 열고 Network 탭을 클릭합니다. 그 후 Create 버튼을 누르면 instances/라는 이름의 요청이 보일 것입니다. 그 요청을 우클릭 한 뒤 Copy as cURL을 클릭합니다.
16

아래와 같은 명령어가 나올 것입니다. --data-raw에 있는 내용 중 imageId, subnetId, availabilityDomain을 복사해둡니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
curl 'https://iaas.ap-osaka-1.oraclecloud.com/20160918/instances/' \
-H 'Accept: */*' \
-H 'Connection: keep-alive' \
-H 'Content-Type: application/json' \
-H 'Origin: https://cloud.oracle.com' \
-H 'Referer: https://cloud.oracle.com/' \
-H 'Sec-Fetch-Dest: empty' \
-H 'Sec-Fetch-Mode: cors' \
-H 'Sec-Fetch-Site: cross-site' \
-H 'User-Agent: ' \
-H 'accept-language: en' \
-H 'authorization: Signature keyId=""' \
-H 'opc-request-id: ' \
-H 'sec-ch-ua: "' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "macOS"' \
-H 'x-content-sha256: ' \
-H 'x-date: ' \
--data-raw '{"metadata":{"ssh_authorized_keys":"key"},"shape":"VM.Standard.A1.Flex","compartmentId":"ocid1...","displayName":"osaka-arm","availabilityDomain":"EizN:AP-OSAKA-1-AD-1","sourceDetails":{"sourceType":"image","imageId":"ocid1.image.oc1.ap-osaka-1.aaaaaaaaedxxunrduv6yjtflc4vcg5liqqbgjcymg2dmc6uagadqie4tra2a","bootVolumeSizeInGBs":150,"bootVolumeVpusPerGB":10},"isPvEncryptionInTransitEnabled":true,"createVnicDetails":{"assignPublicIp":true,"subnetId":"ocid1.subnet...","assignPrivateDnsRecord":true,"assignIpv6Ip":false},
...}'

다시 서버로 와서 도커 내부에 인스턴스를 생성할 때 사용한 public key를 복사해줍니다.

1
2
3
4
5
6
7
8
mkdir ~/.ssh

cat <<EOF > ~/.ssh/[public key 이름].pub
-----BEGIN PRIVATE KEY-----
[키내용]
-----END PRIVATE KEY-----
OCI_API_KEY
EOF

그 후 .env 파일을 만들어줍니다. 아래에서 IMAGE_ID, SUBNET_ID, AVAILABILITY_DOMAIN은 cURL로 복사한 내용을 넣어주시면 됩니다. TENANCY_ID는 아까 프로필 설정에서 복사한 것을 넣어주시면 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
cat <<EOF > .env
# Go to Profile -> Tenancy (Tenancy information OCID) and copy it here
TENANCY_ID="ocid1.tenancy.oc1..***"
# Check README.md step 7
IMAGE_ID="ocid1.image.oc1.***.***"
# Check README.md step 8
SUBNET_ID="ocid1.subnet.oc1.***.***"
# Check README.md step 9
AVAILABILITY_DOMAIN="JtDP:***"
# Check README.md step 10
PATH_TO_PUBLIC_SSH_KEY="$HOME/.ssh/[public key 이름].pub"
EOF

이제 마지막으로 스크립트를 작성해줍니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
cat <<EOF > create_instance.sh
#!/bin/bash

source /oracle/.env

if [[ -z "${TENANCY_ID}" ]]; then
echo "TENANCY_ID is unset or empty. Please change in .env file"
exit 1
fi

# ----------------------CUSTOMIZE---------------------------------------------------------------------------------------

# Discord webhook URL
WEBHOOK_URL="https://discord.com/api/webhooks/****"
DISCORD_USER_ID="12341234123"
# Don't go too low or you run into 429 TooManyRequests
requestInterval=1800 # seconds
# VM params
cpus=4 # max 4 cores
ram=24 # max 24gb memory
bootVolume=150 # disk size in gb
# 인스턴스 이름 변수 설정
name="big-arm" # 원하는 인스턴스 이름으로 변경 가능
profile="DEFAULT"

# ----------------------ENDLESS LOOP TO REQUEST AN ARM INSTANCE---------------------------------------------------------

while true; do
OUTPUT=$(oci compute instance launch --no-retry \
--auth api_key \
--profile "$profile" \
--display-name "$name" \
--compartment-id "$TENANCY_ID" \
--image-id "$IMAGE_ID" \
--subnet-id "$SUBNET_ID" \
--availability-domain "$AVAILABILITY_DOMAIN" \
--shape 'VM.Standard.A1.Flex' \
--shape-config "{'ocpus':$cpus,'memoryInGBs':$ram}" \
--boot-volume-size-in-gbs "$bootVolume" \
--ssh-authorized-keys-file "$PATH_TO_PUBLIC_SSH_KEY" 2>&1)

EXIT_CODE=$?


# ========================================
# discord
# ========================================

if echo "$OUTPUT" | grep -q "Out of host capacity."; then
MESSAGE="**Error:** Out of host capacity when launching instance *osaka-arm*."
curl -H "Content-Type: application/json" \
-X POST \
-d "{\"content\": \"$MESSAGE\"}" \
"$WEBHOOK_URL"
elif [ $EXIT_CODE -ne 0 ]; then
MESSAGE="<@$DISCORD_USER_ID>**Error:** Failed to launch instance *osaka-arm*."
curl -H "Content-Type: application/json" \
-X POST \
-d "{\"content\": \"$MESSAGE\"}" \
"$WEBHOOK_URL"
echo "$OUTPUT" >> "/oracle/output.log"
else
MESSAGE="<@$DISCORD_USER_ID>**Success:** Instance *osaka-arm* launched successfully."
curl -H "Content-Type: application/json" \
-X POST \
-d "{\"content\": \"$MESSAGE\"}" \
"$WEBHOOK_URL"
break
fi
sleep $requestInterval
done
EOF

이로서 모든 준비가 끝났습니다. 이제 create_instance.sh를 실행하면 인스턴스 자동 생성 매크로가 동작합니다.

1
./create_instance.sh

참고로 저는 discord로 알림을 받기 때문에 WEBHOOK_URLDISCORD_USER_ID를 설정해주었습니다.
원하지 않으면 해당 부분을 삭제하거나 그냥 두셔도 무방합니다.


discord로 알림 받기(옵션)

본인이 채널 설정이 가능한 discord 서버에 접속합니다.

아래 사진을 보고 알림 설정@mention으로 설정해줍니다. 그 후 채널 편집에 들어갑니다.
17

채널 편집에 연동에 들어간 후 웹후크URL 복사를 클릭합니다. 그 후 위에 작성한 스크립트에 WEBHOOK_URL에 붙여넣어주시면 됩니다.

18

본인 DISCORD_USER_ID를 알아내는 방법은 우측에 맴버 목록에서 본인을 우클릭 한 뒤 사용자ID 복사하기를 클릭하시면 됩니다. 이것도 역시 스크립트에 붙여넣어주시면 됩니다.

19

결과

실행을 하면 설정한 시간마다 인스턴스가 생성 요청이 날라가고 결과를 discord로 받을 수 있습니다. 만일 discord 멘션이 온다면 다른 문제가 생겼거나 인스턴스 생성에 성공한 것이니 확인해보시기 바랍니다.

아래처럼 주기적으로 결과를 discord로 받을 수 있습니다.
20

마무리

이로서 오라클 클라우드 인스턴스 자동 생성 매크로를 만들어보았습니다. 오라클 가입보다 어렵다는 arm인스턴스 생성에 도움이 되었으면 좋겠습니다.