서론 오라클 클라우드는 타 클라우드에 비해 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 파일이 필요합니다.
오라클 클라우드 에 접속하여 로그인을 합니다.
우측 상단에 있는 프로필을 클릭해서 본인의 계정으로 이동합니다.
API 키
를 클릭합니다. 그리고 Add API key
를 클릭합니다.
private key와 public key를 다운로드 받습니다. (보관에 주의하세요)
그러고 나면 다음과 같은 화면이 나옵니다. 나중에 쓰일 것이니 Copy를 눌러 복사해둡니다.
서버 준비 24시간 돌아가는 서버에 script를 올려서 주기적으로 요청을 보낼거기 때문에 도커가 깔린 서버를 준비합니다. Free-tier에서 제공하는 VM.Standard.E2.1.Micro
를 사용하셔도 무방합니다.
도커를 실행하기 전에 인증을 위한 파일을 설정해야 합니다.
그리고 ~/.oci
에 config
파일을 만들어줍니다. 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
경고는 무시하시고 아래와 같이 나온다면 성공입니다.
쉘 스크립트 작성 깃 허브 기반으로 수정된 버전 입니다.
먼저 인스턴스를 인스턴스 생성을 시도해야 합니다. 아래 메뉴에서 Instances
를 클릭 후 인스턴스를 생성 합니다.
인스턴스를 생성하기 전에 크롬 개발자 도구를 열고 Network
탭을 클릭합니다. 그 후 Create
버튼을 누르면 instances/
라는 이름의 요청이 보일 것입니다. 그 요청을 우클릭 한 뒤 Copy as cURL
을 클릭합니다.
아래와 같은 명령어가 나올 것입니다. --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
를 실행하면 인스턴스 자동 생성 매크로가 동작합니다.
참고로 저는 discord로 알림을 받기 때문에 WEBHOOK_URL
과 DISCORD_USER_ID
를 설정해주었습니다. 원하지 않으면 해당 부분을 삭제하거나 그냥 두셔도 무방합니다.
discord로 알림 받기(옵션) 본인이 채널 설정이 가능한 discord 서버에 접속합니다.
아래 사진을 보고 알림 설정
을 @mention
으로 설정해줍니다. 그 후 채널 편집에 들어갑니다.
채널 편집에 연동
에 들어간 후 웹후크URL 복사
를 클릭합니다. 그 후 위에 작성한 스크립트에 WEBHOOK_URL
에 붙여넣어주시면 됩니다.
본인 DISCORD_USER_ID
를 알아내는 방법은 우측에 맴버 목록에서 본인을 우클릭 한 뒤 사용자ID 복사하기
를 클릭하시면 됩니다. 이것도 역시 스크립트에 붙여넣어주시면 됩니다.
결과 실행을 하면 설정한 시간마다 인스턴스가 생성 요청이 날라가고 결과를 discord로 받을 수 있습니다. 만일 discord 멘션이 온다면 다른 문제가 생겼거나 인스턴스 생성에 성공한 것이니 확인해보시기 바랍니다.
아래처럼 주기적으로 결과를 discord로 받을 수 있습니다.
마무리 이로서 오라클 클라우드 인스턴스 자동 생성 매크로를 만들어보았습니다. 오라클 가입보다 어렵다는 arm인스턴스 생성에 도움이 되었으면 좋겠습니다.