TheKoguryo's 기술 블로그

 Version 2024-11-29

ARM 기반 서버 성능 비교: OCI vs. AWS

OCI Ampere Altra A1

오라클은 2021년 5월부터 Arm 기반의 Ampere A1 Compute Shape을 가상 머신에서 사용할 수 있습니다.

OCI Ampere A1 성능 측정 참고 문서

최근 API Gateway인 Apache APISIX 블로그에서 클라우드 ARM 기반 서버들의 성능을 비교하였습니다. 해당 내용을 기반으로 OCI에서도 최대한 유사한 환경을 구성하여 성능 측정을 한번 해보겠습니다.

Step#1. ARM Ubuntu VM 생성

참고 문서에서 테스트한 환경

  • AWS Graviton3: ARM 아키텍처 기반
  • AWS EC2 c7g.large(2vCPU, 4GiB Memory)
  • Ubuntu 20.04
  1. OCI에서는 다음 환경을 구성합니다.

    • OCI Ampere A1: ARM 아키텍처 기반
    • VM.Standard.A1.Flex: 자유 구성이나, 동일하게 2OCPU, 4GB 메모리 선택
    • Ubuntu 22.04 Minimal aarch64: 벤치마크 테스트 모듈 설치 오류 최소화를 위해 22.04 선택
  2. Compute 인스턴스 생성 화면에서 Shape 유형을 Ampere로 선택합니다.

  3. OS를 이미지를 Ubuntu로 변경하고, 기본 22.04 Minimal aarch64로 변경합니다.

  4. 하나 있는 VM.Standard.A1.Flex Shape을 선택합니다. A1이 Arm기반 Ampere A1을 뜻하며, Flex는 CPU, Memory 선택이 자유로운 것을 뜻합니다. 2 OCPU, 4GB 메모리를 선택합니다.

  5. OS Image와 Arm 서버 Shape이 선택되었습니다.

  6. 이름, VCN, SSH Key 등 나머지는 원하는 값으로 지정하여 인스턴스를 생성합니다.

  7. 만든 인스턴스에 SSH로 접속합니다.

    ssh ubuntu@<PUBLIC-IP-OF-COMPUTE-INSTANCE>
    
Step#2. ARM Ubuntu VM에 APISIX 설치

참고 문서: How to build APISIX in ARM Ubuntu

요구사항 설치

  1. 소스 코드 복제

    sudo apt-get update
    sudo apt-get install git
    
    git clone https://github.com/apache/apisix.git
    cd apisix
    git checkout release/2.15
    
  2. OpenResty를 설치합니다. Ubuntu 22.04, ARM에 맞게 설치합니다.

    sudo apt-get -y install --no-install-recommends wget gnupg ca-certificates
    
    • Step 2: import our GPG key:
    # For ubuntu 22
    wget -O - https://openresty.org/package/pubkey.gpg | sudo gpg --dearmor -o /usr/share/keyrings/openresty.gpg
    
    • Step 3: then add the our official APT repository.
    # for arm64 or aarch64 system
    # For ubuntu 22 or above
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/openresty.gpg] http://openresty.org/package/arm64/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/openresty.list > /dev/null
    
    • Step 4: update the APT index & install openresty
    sudo apt-get update
    sudo apt-get -y install openresty
    
  3. Dependencies 설치

    bash utils/install-dependencies.sh
    sudo apt install wget sudo unzip
    sudo apt-get install make gcc
    curl https://raw.githubusercontent.com/apache/apisix/master/utils/linux-install-luarocks.sh -sL | bash -
    LUAROCKS_SERVER=https://luarocks.cn make deps
    
  4. APISIX 설치

    sudo make install
    

ETCD 설치

  1. Docker 설치

    sudo apt-get install docker.io
    
  2. etcd 시작

    sudo docker run -d --name etcd -p 2379:2379 -e ETCD_UNSUPPORTED_ARCH=arm64 -e ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 -e ETCD_ADVERTISE_CLIENT_URLS=http://0.0.0.0:2379 gcr.io/etcd-development/etcd:v3.5.1-arm64
    
  3. 확인 STATUS가 Up인지 확인합니다.

    sudo docker ps -a
    

APISIX 시작

  1. 소스 코드 위치로 이동

    cd ~/apisix
    
  2. Dependencies 설치

    make deps
    sudo make install
    
  3. 설정 추가

    echo "ulimit -n 4096" >> ~/.bashrc
    source ~/.bashrc
    
  4. APISIX 시작

    apisix init
    
    # start APISIX
    apisix start
    
  5. 테스트 Route 등록

    curl "http://127.0.0.1:9080/apisix/admin/routes/1" \
    -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PUT -d '
    {
      "uri": "/anything/*",
      "upstream": {
        "type": "roundrobin",
        "nodes": {
          "httpbin.org:80": 1
        }
      }
    }'
    
  6. 테스트

    curl -i http://127.0.0.1:9080/anything/das
    

    테스트 결과

    HTTP/1.1 200 OK
    .....
    
Step#3. 성능 측정

성능 테스트는 참고 문서 #1에서 언급하고 있는 Apache APISIX 공식 벤치마크 스크립트을 사용하였습니다.

성능 측정 준비

  1. 생성한 ubuntu VM에 HTTP 벤치마크 툴인 wrk를 설치합니다.

    sudo apt-get install wrk
    

측정 시나리오

아래 2가지 시나리오를 사용하였으며, 사용할 벤치마크 테스트 스크립트 안에 해당 내용이 들어 있습니다. 각 시나리오는 APISIX가 라우팅할 127.0.0.1:1980에서 서비스되는 Nginx 노드가 필요합니다. 테스트 스크립트 안에 그 부분도 포함되어 있습니다.

  1. Scenario 1: Single upstream​

    • 참고 문서 #1의 첫번째 시나리오로 플러그인 없이, single upstream을 사용합니다. 순 proxy back-to-origin 모드에서 APISIX 성능 테스트 용도라고 합니다.
    # apisix: 1 worker + 1 upstream + no plugin
    
    # register route
    curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
    {
        "uri": "/hello",
        "plugins": {
        },
        "upstream": {
            "type": "roundrobin",
            "nodes": {
                "127.0.0.1:1980":1
            }
        }
    }'
    
  2. Scenario 2: Single upstream + Two plugins​

    • 참고 문서 #1의 두번째 시나리오로 플러그인 2개, single upstream을 사용합니다. 2 코어 성능-소비 플러그인으로 limit-countprometheus을 사용하여 APISIX 성능 테스트 용도라고 합니다.
    # apisix: 1 worker + 1 upstream + 2 plugins (limit-count + prometheus)
    
    # register route
    curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
    {
        "uri": "/hello",
        "plugins": {
            "limit-count": {
                "count": 2000000000000,
                "time_window": 60,
                "rejected_code": 503,
                "key": "remote_addr"
            },
            "prometheus": {}
        },
        "upstream": {
            "type": "roundrobin",
            "nodes": {
                "127.0.0.1:1980":1
            }
        }
    }'
    

벤치마크 테스트 스크립트 수행

  1. 소스 코드 위치로 이동

    cd ~/apisix
    
  2. 편집 툴 설치

    sudo apt-get install vim
    
  3. 백엔드 Nginx 기동을 확인하기 위해 ./benchmark/run.sh 스크립트의 103줄에 curl 명령을 추가합니다.

    curl -i http://127.0.0.1:9080/hello
    wrk -d 5 -c 16 http://127.0.0.1:9080/hello
    
  4. ./benchmark/run.sh 스크립트에서 테스트를 위해 부하 시간을 기본 5초에서 60초로 늘립니다. -d 5-d 60으로 변경합니다.

    wrk -d 60 -c 16 http://127.0.0.1:9080/hello
    
  5. 벤치마크 스크립트를 수행합니다.

    ./benchmark/run.sh
    
  6. 실행 결과

    ubuntu@oci-arm-ubuntu-c2m4:~/apisix$ ./benchmark/run.sh
    + '[' -n '' ']'
    + worker_cnt=1
    + '[' -n '' ']'
    + upstream_cnt=1
    + mkdir -p benchmark/server/logs
    + mkdir -p benchmark/fake-apisix/logs
    + make init
    [ info ] init -> [ Start ]
    ...
    apisix: 1 worker + 1 upstream + no plugin
    + curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
    {
        "uri": "/hello",
        "plugins": {
        },
        "upstream": {
            "type": "roundrobin",
            "nodes": {
                "127.0.0.1:1980":1
            }
        }
    }'
    {"node":{"key":"\/apisix\/routes\/1","value":{"uri":"\/hello","update_time":1664362611,"plugins":{},"status":1,"create_time":1664361560,"priority":0,"upstream":{"scheme":"http","pass_host":"pass","nodes":{"127.0.0.1:1980":1},"hash_on":"vars","type":"roundrobin"},"id":"1"}},"action":"set"}
    + sleep 1
    + curl -i http://127.0.0.1:9080/hello
    HTTP/1.1 200 OK
    Content-Type: text/plain; charset=utf-8
    Transfer-Encoding: chunked
    Connection: keep-alive
    Date: Wed, 28 Sep 2022 10:56:52 GMT
    Server: APISIX/2.15.0
    
    1234567890+ wrk -d 60 -c 16 http://127.0.0.1:9080/hello
    Running 1m test @ http://127.0.0.1:9080/hello
      2 threads and 16 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     1.02ms  188.43us  13.83ms   97.08%
        Req/Sec     7.86k   505.69     8.73k    89.58%
      938523 requests in 1.00m, 171.84MB read
    Requests/sec:  15640.38
    Transfer/sec:      2.86MB
    + sleep 1
    + wrk -d 60 -c 16 http://127.0.0.1:9080/hello
    Running 1m test @ http://127.0.0.1:9080/hello
      2 threads and 16 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     1.03ms  112.62us  10.02ms   93.94%
        Req/Sec     7.82k   314.04    15.89k    88.01%
      934559 requests in 1.00m, 171.12MB read
    Requests/sec:  15550.03
    Transfer/sec:      2.85MB
    
    ...
    
    apisix: 1 worker + 1 upstream + 2 plugins (limit-count + prometheus)
    + curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
    {
        "uri": "/hello",
        "plugins": {
            "limit-count": {
                "count": 2000000000000,
                "time_window": 60,
                "rejected_code": 503,
                "key": "remote_addr"
            },
            "prometheus": {}
        },
        "upstream": {
            "type": "roundrobin",
            "nodes": {
                "127.0.0.1:1980":1
            }
        }
    }'
    {"node":{"key":"\/apisix\/routes\/1","value":{"uri":"\/hello","update_time":1664362734,"plugins":{"limit-count":{"time_window":60,"key":"remote_addr","rejected_code":503,"count":2000000000000,"key_type":"var","policy":"local","allow_degradation":false,"show_limit_quota_header":true},"prometheus":{"prefer_name":false}},"status":1,"create_time":1664361560,"priority":0,"upstream":{"scheme":"http","pass_host":"pass","nodes":{"127.0.0.1:1980":1},"hash_on":"vars","type":"roundrobin"},"id":"1"}},"action":"set"}
    + sleep 3
    + wrk -d 60 -c 16 http://127.0.0.1:9080/hello
    Running 1m test @ http://127.0.0.1:9080/hello
      2 threads and 16 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     1.31ms  192.72us  17.15ms   95.50%
        Req/Sec     6.15k   294.98     6.71k    71.83%
      734891 requests in 1.00m, 185.02MB read
    Requests/sec:  12248.00
    Transfer/sec:      3.08MB
    + sleep 1
    + wrk -d 60 -c 16 http://127.0.0.1:9080/hello
    Running 1m test @ http://127.0.0.1:9080/hello
      2 threads and 16 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     1.30ms  141.40us  12.13ms   93.56%
        Req/Sec     6.17k   254.42     6.87k    64.83%
      736422 requests in 1.00m, 185.41MB read
    Requests/sec:  12271.99
    Transfer/sec:      3.09MB
    ...
    

성능 측정 결과

  • Scenario 1: Single upstream​

    • apisix: 1 worker + 1 upstream + no plugin 부분
    항목 1차 2차 평균
    Requests/sec (초당 요청건) 15640.38 15550.03 15595.205
    Avg Latency (평균 응답지연) 1.02ms 1.03ms 1.025ms
  • Scenario 2: Single upstream + Two plugins​

    • apisix: 1 worker + 1 upstream + 2 plugins (limit-count + prometheus)
    항목 1차 2차 평균
    Requests/sec (초당 요청건) 12248.00 12271.99 12259.995
    Avg Latency (평균 응답지연) 1.31ms 1.30ms 1.305ms
  • 테스트시 CPU, Memory 상태

    • CPU: 부하로 인해 백엔드 Nginx Worker 프로세스가 CPU를 많이 사용하고 있음
    • Memory: Nginx 단순 웹페이지라 메모리는 크게 사용하지 않음
비용대비 성능 비교

OCI Arm 기반 Shape

OCI Arm 기반 가상 머신 비용

  • OCI Ampere A1 Compute
    • https://www.oracle.com/cloud/compute/arm/
    • Arm CPU 아키텍처(Ampere)에서는 1 OCPU = 1 vCPU 입니다.
    • Cloud Account내 Ampere A1 shape의 매달 전체 사용량 중에 첫 3,000 OCPU-시간과 첫 18,000 GB-시간 까지는 무료입니다.
    • Flex Shape으로 OCPU와 Memory를 조정할 수 있어, 각각 단위 비용이 있습니다.
    • OCI는 모든 리전이 가격이 동일합니다.
    Compute - Virtual Machine Instances Comparison Price ( /vCPU)* Unit Price Unit
    Compute – Ampere A1 – OCPU $0.01 $0.01 시간당 OCPU
    Compute – Ampere A1 – Memory - $0.0015 시간당 기가바이트
벤치마크 테스트 관련 비용 비교

비교 조건

  • ARM 서버 기준입니다.
  • AWS: C7g (US East Ohio) 기준 시간당 비용입니다.
  • OCI: VM.Standard.A1.Flex 기준 시간당 비용입니다.
    • OCI는 모든 리전이 가격이 동일합니다.
    • 비교를 위해 AWS C7g와 같은 크기의 CPU, Memory로 비교한 가격입니다.
    • VM.Standard.A1.Flex 가격은 CPU 가격과 Memory 가격의 합입니다.

시간당 비용

VM series / vCPU(Memory) 1 (2G) 2 (4G) 4 (8G) 8 (16G) 16 (32G) 32 (64G) 64 (128G)
AWS C7g $0.0361 $0.0723 $0.1445 $0.289 $0.5781 $1.1562 $1.7342
OCI Ampere A1 $0.013 $0.026 $0.052 $0.104 $0.208 $0.416 $0.832

연간 비용: 테스트 시나리오 1 기준

  • QPS (queries per second): 초당 요청 처리 건수
  • AWS c7g.large의 QPS는 참조 문서 #1, #2 결과 기준
  • 참조 문서 #1, #2를 참고하여 최대한 동일한 구성으로 테스트하였으나, 참조 문서의 최종 부하 요청, 그 당시 자원 사용량을 알 수 없으므로, 아래 성능 및 비용 대비 성능은 절대적인 것이 아닌 참고용입니다.
  • OCI Flex Shape은 구성이 자유로우므로 OCPU는 2개 그대로하고 사용량이 적은 Memory를 2GB로 구성하는 것도 가능합니다.
시간당 비용 일년(24*365) 총 시간 Annual Cost QPS Cost Performance(QPS/cost)
AWS c7g.large $0.0723 8760 시간 $633.3 23000 36.3
OCI VM.Standard.A1.Flex 2 OCPU, 4 GB Memory $0.026 8760 시간 $227.8 15595.205 68.5
OCI VM.Standard.A1.Flex 2 OCPU, 2 GB Memory $0.023 8760 시간 $201.5 15595.205 77.4

테넌트내 테스트 환경만 사용한다는 가정하에 무료 제공량 제외시

  • Cloud Account내 Ampere A1 shape의 매달 전체 사용량 중에 첫 3,000 OCPU-시간과 첫 18,000 GB-시간 까지는 무료입니다.
  • 한달 최대 사용 시간: 24시간 * 31일 = 744시간
한달 최대 사용량 무료 제외후 한달 사용량 일년 사용량 Unit Price Annual Cost
OCI VM.Standard.A1.Flex 2 OCPU 1,488 OCPU-시간 0 OCPU-시간 0 $0.01 $0
OCI VM.Standard.A1.Flex 4 GB Memory 2,976 GB-시간 0 GB-시간 0 $0.0015 $0


이 글은 개인으로서, 개인의 시간을 할애하여 작성된 글입니다. 글의 내용에 오류가 있을 수 있으며, 글 속의 의견은 개인적인 의견입니다.