Đa số các nhà cung cấp dịch vụ Cloud đều phát hành thêm các API giúp thu thập thông tin định giá, ví dụ như về chi phí sử dụng máy ảo (virtual machine) hoặc lưu trữ trên Cloud. Bài viết này sẽ đi sâu vào API Resource RateCard của Azure và API Cloud Billing Catalog của Nền tảng Cloud Google (GCP).
Azure’s Resource RateCard API
API Resource RateCard được Azure phát triển như một phần trong số các API Lập hóa đơn (Billing API) của hãng. Trong bản hướng dẫn của API này, Azure đã giải thích rất kỹ càng về các vùng và giá trị trong yêu cầu và phản hồi. Tuy nhiên, hãng lại không nhắc nhiều tới các setup ban đầu trước khi bắt đầu sử dụng được API này, mà thay vào đó chỉ yêu cần người dùng sở hữu một bearer token OAuth lấy từ Azure Active Directory. Đây cũng chính là lý do tại sao ta có thể cần tới vài tiếng đồng hồ để tạo được cài đặt phù hợp.
Hẳn là chẳng ai muốn phí thời gian cho bước “của nợ” này, và vì vậy, bài viết này đã ra đời với từng bước cụ thể, giúp bạn biết được cách sử dụng API Resource RateCard để lấy các thông tin ước tính định giá cho những dịch vụ của Azure.
Trước hết, ta sẽ bắt đầu thực hiện các bước để truy cập được API RateCard này, giả sử rằng ta đang dùng một tài khoản Azure mới.
Cài đặt ban đầu
Bước 1: Cài đặt Azure CLI
Trước hết, hãy làm theo các chỉ dẫn trong link này để cài đặt Azure CLI. Ta cũng có thể sử dụng cổng Azure để thay thế, nhưng cá nhân tôi thích sử dụng CLI hơn. Sau đó, ta sẽ cần lấy được chứng nhận admin:
$ az login
Bước 2: Đăng ký nhà cung cấp tài nguyên
Từ bản hướng dẫn có thể thấy rằng, API RateCard có nhà cung cấp tài nguyên là “Microsoft.Commerce” (Chi tiết tại: Các nhà cung cấp và kiểu tài nguyên Azure)
Ta sẽ thực hiện đăng ký “Microsoft.Commerce” thông qua lệnh sau:
$ az provider register --namespace Microsoft.Commerce
Lưu ý: Một số bài viết sẽ yêu cầu bạn phải đăng ký một số nhà cung cấp khác như: Microsoft.Compute, Microsoft.Resources, Microsoft.ContainerService… Song tôi khẳng định rằng ta chỉ cần đăng ký cho “Microsoft.Commerce”.
Bước 3: Tạo định nghĩa vai trò tùy chỉnh
Trong bước này, ta sẽ tạo một vai trò với các quyền cần thiết. (Chi tiết có thể xem tại vai trò tùy chỉnh trên Azure).
Tạo một tệp JSON có chứa định nghĩa vai trò, đặt tên tệp này là ratecard-role.json (Nhớ thay thế {SUBSCRIPTION_ID} bằng ID tài khoản của bạn):
ratecard-role.json
{
"Name": "MyRateCardAPIRole",
"IsCustom": true,
"Description": "Role for RateCardAPI",
"Actions": [
"Microsoft.Commerce/RateCard/read"
],
"AssignableScopes": [
"/subscriptions/{SUBSCRIPTION_ID}"
]
}
Sau đó hãy đăng ký định nghĩa vai trò sau:
$ az role definition create --verbose --role-definition @ratecard-role.json
{
"assignableScopes": [
"/subscriptions/{SUBSCRIPTION_ID}"
],
"description": "Role for RateCardAPI",
"id": "/subscriptions/{SUBSCRIPTION_ID}/providers/Microsoft.Authorization/roleDefinitions/{ID}",
"name": "{ID}",
"permissions": [
{
"actions": [
"Microsoft.Commerce/RateCard/read"
],
"dataActions": [],
"notActions": [],
"notDataActions": []
}
],
"roleName": "MyRateCardAPIRole",
"roleType": "CustomRole",
"type": "Microsoft.Authorization/roleDefinitions"
}
Lưu ý: Giống như ở bước 2, một số bài viết sẽ yêu cầu vai trò tùy chỉnh phải có nhiều loại quyền. Cũng như ở trên, tôi khẳng định rằng chúng ta chỉ cần tới quyền “Microsoft.Commerce/RateCard/read”, ta không muốn cấp quá nhiều quyền khi không cần thiết.
Bước 4: Đăng ký ứng dụng
Tiếp theo, chúng ta đăng ký một ứng dụng và liên hệ nó với vai trò vừa được tạo ở bước 3:
$ az ad sp create-for-rbac --name "MyRateCardAPIApp" --role "MyRateCardAPIRole" --sdk-auth true > my_credentials.jsons
Đổi "MyRateCardAPIApp" một URL hợp lệ có dạng "http://MyRateCardAPIApp", cũng là định dạng được quy định cho các tên dịch vụ chính.
Tạo phân bổ vai trò dưới dạng "/subscriptions/{SUBSCRIPTION_ID}"
Thử lại việc tạo phân bổ vai trò : 1/36
Các chứng nhận sẽ được lưa trong tệp my_credentials.json, và sẽ được sử dụng như sau:
my_credentails.json
{
"clientId": "{CLIENT_ID}",
"clientSecret": "{CLIENT_SECRET}",
"subscriptionId": "{SUBSCRIPTION_ID}",
"tenantId": "{TENANT_ID}",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"
Gọi API
Để thực hiện gọi API tới API RateCard, ta sẽ thực hiện các bước được trình bày trong sơ đồ dưới đây:
Bước 1: Lấy access token (token truy cập) từ Azure Active Directory (Bước 1 & 2 trong sơ đồ)
Azure không cung cấp SDK cho API RateCard, vì vậy ta sẽ cần sử dụng một khách hàng REST để thực hiện gọi API. Dưới đây là một minh họa đơn giản sử dụng cURL.
Theo sơ đồ bên trên, ta sẽ trước hết cần thực hiện một cuộc gọi client_credential tới Azure Active Directory để lấy access token.
$ curl https://login.microsoftonline.com/{TENANT_ID}/oauth2/token \
-F grant_type=client_credentials \
-F resource=https://management.core.windows.net/ \
-F client_id={CLIENT_ID} \
-F client_secret={CLIENT_SECRET}
{
"token_type": "Bearer",
"expires_in": "3600",
"ext_expires_in": "3600",
"expires_on": "1576495607",
"not_before": "1576491707",
"resource": "https://management.core.windows.net/",
"access_token": "{ACCESS_TOKEN}"
}
Ta có thể lấy {TENANT_ID}, {CLIENT_ID}, {CLIENT_SECRET” từ tệp my_credentials.json đã được tổng hợp ở phần trước.
Bước 2: Gọi API RateCard (Bước 3 & 4 trong sơ đồ)
Ở bước trước, ta đã thu được access token. Bây giờ ta sẽ sử dụng access token này để gọi API RateCard:
$ curl -L \ "https://management.azure.com/subscriptions/YOUR_SUBSCRIPTION_ID/providers/Microsoft.Commerce/RateCard?api-version=2016-08-31-preview&%24filter=OfferDurableId+eq+'MS-AZR-0003P'+and+Currency+eq+'USD'+and+Locale+eq+'en-US'+and+RegionInfo+eq+'US'" \
-H 'Authorization: Bearer {ACCESS_TOKEN}' > output.json
Hãy lưu ý rằng trong lệnh phía trên, giá trị của OfferDurableId được định là “MS-AZR-0003P”, mà đây lại là Offer ID – một hình thức trả phí Azure theo nhu cầu sử dụng (Để lấy Offer ID tương ứng với gói Azure bạn đang sử dụng, hãy truy cập Chi tiết gói dịch vụ Microsoft Azure). Gói Doanh nghiệp (Enterprise) hiện không hỗ trợ API RateCard, và hướng dẫn trên cũng chỉ ra rằng, tài khoản thuộc gói này không có Offer ID.
Cuộc gọi có thể tốn tới vài giây để hoàn thành, do phản hồi lên tới khoảng 16MB. Tuy rằng API đã tồn tại được nhiều năm, tới nay ta vẫn chỉ tìm kiếm được một số thông tin cần thiết trong tệp lớn này. Hy vọng rằng trong tương lai sẽ xuất hiện một cơ chế tương tự như API Price List của AWS. Quay lại với cuộc gọi, kết quả sẽ được hiển thị trong tệp output.json:
output.json
{
"OfferTerms": [],
"Meters": [
{
"EffectiveDate": "2020-05-01T00:00:00Z",
"IncludedQuantity": 0.0,
"MeterCategory": "Virtual Machines",
"MeterId": "cd2d7ca5-2d4c-5f93-94d0-8cee0662c71c",
"MeterName": "E20 v4",
"MeterRates": {
"0": 1.52
},
"MeterRegion": "AP Southeast",
"MeterStatus": "Active",
"MeterSubCategory": "Ev4 Series",
"MeterTags": [],
"Unit": "1 Hour",
}
.
.
.
.
.
]
}
Có thể thấy rằng, kết quả chứa rất nhiều loại Meter, mà mỗi Meter lại là một đối tượng trong JSON. Điều này có nghĩa là, Azure đã tổng hợp cho chúng ta một đối tượng JSON khổng lồ nặng tới 16MB. Do vậy, ta sẽ phải thực hiện lọc đối tượng này để tìm thấy các nhóm giá hoặc tài nguyên cụ thể mà ta đang cần. Dưới đây là một số gợi ý về các loại Meter hữu ích cho việc lọc:
MeterRegion (Meter khu vực): Khu vực có hỗ trợ dịch vụ Azure.
MeterCategory (Meter phân loại): Phân loại của meter (“Máy ảo” (Virtual Machine), “Mạng ảo” (Virtual Network)…)
MeterSubCategory (Meter phân loại phụ): Phân loại phụ của Meter (“Series Ev4” (Ev4 Series), “Địa chỉ IP” (IP Addresses)…)
MeterName (Meter tên): Tên của Meter bên trong một phân loại meter cho trước.
Ngoài ra, “MeterId” (yếu tố định danh riêng của tài nguyên) sẽ dẫn chúng ta tới đích xác sản phẩm mà ta cần. Bạn có thể chọn bất cứ Meter nào, miễn là chúng thỏa mãn các nhu cầu của bạn.
Cuối cùng, hãy xem xét kết quả. Ví dụ một đối tượng Meter như sau:
{
"EffectiveDate": "2020-03-01T00:00:00Z",
"IncludedQuantity": 0.0,
"MeterCategory": "Storage",
"MeterId": "fae5184f-e8d4-4864-ad02-5853d49b3403",
"MeterName": "Hot LRS Data Stored",
"MeterRates": {
"0": 0.021,
"51200.0000000000": 0.02,
"512000.0000000000": 0.0191
},
"MeterRegion": "US North Central",
"MeterStatus": "Active",
"MeterSubCategory": "General Block Blob v2 Hierarchical Namespace",
"MeterTags": [],
"Unit": "1 GB/Month"
},
Quan sát các mục Meter Rates (Tỷ số Meter) và Unit (Đơn vị), ta sẽ có được giá ước tính của General Block Blob v2 Hierarchical Namespace trong khu vực US North Central (Trung tâm Bắc Mỹ) như sau:
51200Gb đầu: 0,021USD/tháng
52100 – 512000Gb: 0,02USD/tháng
> 512000Gb: 0,0191USD/tháng
API Cloud Billing Catalog của GCP
API Cloud Billing Catalog là một phần Dịch vụ Cloud Billing của GCP. Bảng hướng dẫn của GPC về API này rõ ràng hơn rất nhiều và cũng đơn giản hơn, trong đó chỉ ra 3 cách gọi API:
Qua SDK
Qua RESTAPI
Qua RPC API
Tương tự như đa số các nhà phát triển, ta sẽ đi thẳng vào phương pháp sử dụng SDK. Hướng dẫn về RESTAPI đã rất rõ ràng, còn nếu bạn muốn dùng RPC, thì bài viết sau về cách sử dụng API RPC của GCP sẽ rất hữu ích cho bạn.
Bước 1: Xác thực
Trước hết, ta cần xác thực yêu cầu để có thể sử dụng các API của GCP. (Chi tiết được nêu trong: Tổng quan Xác thực Google Cloud). Trong phần này, ta sẽ sử dụng API key để xác thực.
Ta có thể tạo một tài khoản dịch vụ trên trang Google Cloud Console > Chứng nhận (Credentials):
Bước 2: Lấy danh sách các dịch vụ
Trong bước này, ta sẽ lấy một danh sách các dịch vụ công của GCP (Compute Engine, Cloud Storage…) với {API_KEY} là API key mà ta tổng hợp được trong bước phía trước:
package main
import (
"context"
"encoding/json"
"fmt"
"google.golang.org/api/cloudbilling/v1"
"google.golang.org/api/option"
)
func main() {
ctx := context.Background()
cloudbillingService, err := cloudbilling.NewService(ctx, option.WithAPIKey("{API_KEY}"))
if err != nil {
panic(err)
}
rsp, err := cloudbillingService.Services.List().PageToken("").Do()
if err != nil {
panic(err)
}
rs, _ := json.Marshal(rsp)
fmt.Println(string(rs))
}
Ở đây ta sẽ thu được kết quả sau:
{
"services": [
{
"name": "services/6F81-5844-456A",
"serviceId": "6F81-5844-456A",
"displayName": "Compute Engine",
"businessEntityName": "businessEntities/GCP"
},
.
.
.
],
"nextPageToken": ""
}
Trong đó:
name: tên tài nguyên cho dịch vụ.
serviceId: yếu tố định danh dịch vụ.
displayName: tên hiển thị của dịch vụ mà con người có thể đọc được.
Ta sẽ cần sử dụng name cho bước tiếp theo.
Hãy lưu ý rằng mỗi cuộc gọi chỉ trả một số dịch vụ. Ta sẽ cần đi qua nextPageToken để đến code, rồi thực hiện gọi liên tục cho tới khi nextPageToken trống để lấy được danh sách dịch vụ đầy đủ.
Bước 3: Lấy danh sách SKU
Bây giờ ta sẽ cần thấy được giá ước tính cho dịch vụ của GCP, với {API_KEY} ở bước 1 và {SERVICE_NAME} - name trong bước 2:
package main
import (
"context"
"encoding/json"
"fmt"
"google.golang.org/api/cloudbilling/v1"
"google.golang.org/api/option"
)
func main() {
ctx := context.Background()
cloudbillingService, err := cloudbilling.NewService(ctx, option.WithAPIKey("{API_KEY}"))
if err != nil {
panic(err)
}
rsp, err := cloudbillingService.Services.Skus.List("{SERVICE_NAME}").Do()
if err != nil {
panic(err)
}
rs, _ := json.Marshal(rsp)
fmt.Println(string(rs))
}
Thay thế {SERVICE_NAME} với name trong bước 2. Ví dụ: thay {SERVICE_NAME} thành “services/6F81-5844-456A”, tức tên của dịch vụ Compute Engine, và ta sẽ có kết quả sau:
{
"skus": [
{
"name": "services/6F81-5844-456A/skus/B698-B91F-65F3",
"skuId": "B698-B91F-65F3",
"description": "Preemptible Compute optimized Ram running in Frankfurt",
"category": {
"serviceDisplayName": "Compute Engine",
"resourceFamily": "Compute",
"resourceGroup": "RAM",
"usageType": "Preemptible"
},
"serviceRegions": [
"europe-west3"
],
"pricingInfo": [
{
"summary": "",
"pricingExpression": {
"usageUnit": "GiBy.h",
"usageUnitDescription": "gibibyte hour",
"baseUnit": "By.s",
"baseUnitDescription": "byte second",
"baseUnitConversionFactor": 3865470566400,
"displayQuantity": 1,
"tieredRates": [
{
"startUsageAmount": 0,
"unitPrice": {
"currencyCode": "USD",
"units": "0",
"nanos": 1347000
}
}
]
},
"currencyConversionRate": 1,
"effectiveTime": "2020-08-18T22:12:14.341Z"
}
],
"serviceProviderName": "Google",
"geoTaxonomy": {
"type": "REGIONAL",
"regions": [
"europe-west3"
]
}
},
.
.
.
],
"nextPageToken": ""
}
Cũng tương tự như API RateCard, kết quả sẽ chứa nhiều dạng skus (thay cho các dạng Meter), với mỗi sku là một đối tượng JSON. Tiếp tục gọi liên tục cho tới khi nextPageToken trở lên trống để lấy được danh sách đầy đủ (tương tự như trong bước 2).
GCP đã phân nhóm các skus theo service, tức phản hồi đã nhỏ hơn rất nhiều, song ta vẫn cần thực hiện bước lọc. Dưới đây là một số loại sku sẽ hữu ích cho việc lọc này:
serviceRegions: khu vực có hỗ trợ SKU.
description: mô tả về SKU mà con người có thể đọc được.
resourceGroup: một nhóm các phân loại có liên quan tới SKU ("RAM, "GPU", "InterregionEgress",…)
Cũng giống như “MeterID”, “skuId” (yếu tố định danh SKU) sẽ dẫn ta tới đích xác sản phẩm đang cần.
Cuối cùng, hãy xem xét kết quả. Ví dụ một đối tượng SKU như sau:
{
"name": "services/6F81-5844-456A/skus/B62C-9514-EC43",
"skuId": "B62C-9514-EC43",
"description": "Network Inter Region Egress from Americas to Sao Paulo",
"category": {
"serviceDisplayName": "Compute Engine",
"resourceFamily": "Network",
"resourceGroup": "InterregionEgress",
"usageType": "OnDemand"
},
"serviceRegions": [
"us-central1",
"us-east1",
"us-west1"
],
"pricingInfo": [
{
"summary": "",
"pricingExpression": {
"usageUnit": "GiBy",
"usageUnitDescription": "gibibyte",
"baseUnit": "By",
"baseUnitDescription": "byte",
"baseUnitConversionFactor": 1073741824,
"displayQuantity": 1,
"tieredRates": [
{
"startUsageAmount": 0,
"unitPrice": {
"currencyCode": "USD",
"units": "0",
"nanos": 0
}
},
{
"startUsageAmount": 1,
"unitPrice": {
"currencyCode": "USD",
"units": "0",
"nanos": 80000000
}
}
]
},
"aggregationInfo": {
"aggregationLevel": "ACCOUNT",
"aggregationInterval": "MONTHLY",
"aggregationCount": 1
},
"currencyConversionRate": 1,
"effectiveTime": "2020-08-18T22:12:14.341Z"
}
],
"serviceProviderName": "Google"
}
Quan sát các miền usageUnit, units, nanos và aggregationInterval ta sẽ thấy giá ước tính của Network Inter Region Egress from Americas to Sao Paulo (Mạng xuyên khu vực từ Mỹ tới Sao Paulo) như sau:
1GB đầu: 0USD/tháng
>1Gb: 80000000/10^9 = 0,08USD/tháng
Kết luận
Cả API RateCard và API Cloud Billing Catalog đều trả kết quả là một đối tượng JSON khổng lồ cần được xử lý thêm. Bài viết cũng đã gợi ý một số vùng trong đối tượng JSON hữu ích cho quá trình lọc. Qua bài viết, hi vọng bạn có thể sử dụng API RateCard và API Cloud Billing Catalog dễ dàng hơn, giúp tiết kiệm nhiều thời gian hơn khi khám phá các API này. Cảm ơn bạn đã dành thời gian theo dõi bài viết!
Liên hệ với chúng tôi để biết thêm thông tin chi tiết về dịch vụ của FPT CloudFanpage: https://www.facebook.com/fptsmartcloud/Email:
[email protected]: 1900 638 399