Triển khai tài nguyên trên Azure với Bicep

Có rất nhiều các công cụ có sẵn hiện này cho phép bạn tự động hoá triển khai tài nguyên lên trên Azure sử dụng nguyên lý Infrastructure as Code (IaC), lấy ví dụ như Azure Resource Manager (ARM) template, một công cụ “chính chủ” từ Microsoft cho phép bạn định nghĩa việc triển khai tài nguyên lên trên Azure dưới dạng các JavaScript Object Notation (JSON) object; hay Terraform, một công cụ mã nguồn mở cho phép bạn khai báo các tài nguyên cần triển khai lên trên Azure sử dụng HCL (HashiCorp Configuration Language), một DSL (Domain Specific Language) phát triển bởi HashiCorp.

Azure Resource Manager (ARM) template là công cụ được mình sử dụng chủ yếu trong các dự án cần tự động hoá triển khai tài nguyên lên Azure. Có hai điểm mạnh dễ nhìn thấy mà ARM template mang lại:

  • Là công cụ “chính chủ” nên luôn luôn nhận được các bản cập nhật mới một cách nhanh nhất khi có thay đổi ở ARM.
  • Sử dụng JSON, một kiểu dữ liệu mở vô cùng phổ biến với hầu hết mọi lập trình viên bất kể ngôn ngữ lập trình nào mà họ sử dụng. JSON được hỗ trợ trong hầu hết các trình IDE hay code editor phổ biến nên lập trình viên gần như không bị ràng buộc vào công cụ phát triển để có thể viết được ARM template.

Tuy nhiên, mặc dù là “chính chủ” nhưng ARM template vẫn bộc lộ nhiều điểm yếu khi áp dụng vào trong các dự án có hạ tầng cần triển khai lên trên Azure phức tạp.

  • Sử dụng JSON dẫn tới việc khai báo trở nên dài dòng và có thể gây khó khăn cho thành viên mới khi tiếp cận. Trong một vài dự án gần đây của mình, việc viết ARM template với hàng nghìn dòng code chỉ để định nghĩa triển khai từ 3 đến 5 tài nguyên lên trên Azure là chuyện không khó để bắt gặp, và hãy thử tưởng tượng bạn là một người mới được giao duy trì phát triển những ARM template này.
  • Tách mô-đun để tái sử dụng phức tạp. Trong hệ thống lớn, việc tạo ra các mô-đun và tái sử dụng chúng là việc mà cá nhân mình luôn đặt lên hàng đầu. Lợi ích của việc làm này vô cùng lớn, nó không những giúp mình tiếp kiệm nhân lực, thời gian mà còn đảm bảo tài nguyên được triển khai lên trên Azure tuân thủ các cấu hình chuẩn được định nghĩa sẵn trong các mô-đun. Việc tách mô-đun sử dụng ARM template không quá khó nhưng đòi hòi phải tách các mô-đun dùng chung dưới dạng các ARM template riêng biệt sau đó đẩy chúng lên trên một hạ tầng lưu trữ (chẳng hạn như Azure Storage Account) mà ARM có thể tiếp cận được khi thực hiện triển khai. Tiếp sau đó, nhúng các mô-đun dùng chung này vào ARM template chính dưới dạng linked template.
  • Được thiết kế chuyên biệt cho triển khai ở mức tài nguyên Azure. Thiếu các chức năng hỗ trợ cấu hình sâu vào bên trong tài nguyên được triển khai đặc biệt là các dịch vụ tích hợp từ bên thứ ba như tạo bảng trong database, cấu hình ứng dụng kubernetes, …

Azure Bicep ra đời

Azure Bicep là một dự án mới của Microsoft với mục tiêu nhằm mang lại trải nghiệm dễ dàng hơn cho lập trình viên khi triển khai tài nguyên lên trên Azure.

Cách mà Bicep tiếp cận theo quan điểm cá nhân mình là có nhiều điểm tương đồng với Terraform, và có thể coi là “đối thủ” trực tiếp của công cụ này. Bicep cung cấp một DSL mới đi kèm là các công cụ phát triển dành cho ngôn ngữ mới này bao gồm Bicep CLI, Bicep VS Code extension, …

Nguyên lý hoạt động của Bicep

Cách Bicep hoạt động về cơ bản khá dễ hiểu, bạn tạo ra một file với đuôi .bicep sau đó định nghĩa các tài nguyên cần triển khai trong file này sử dụng Bicep syntax. Sau khi định nghĩa xong, bạn sử dụng Bicep CLI để dịch (compile) file .bicep đó sang ARM template và sử dụng các công cụ có sẵn để triển khai ARM template này lên Azure như Azure CLI, Azure PowerShell. Với Bicep, ARM template được coi là ngôn ngữ trung gian (Intermediate Language (IL)).

Bicep Syntax

Hãy cùng nhìn vào một ví dụ của một file .bicep sau:

param location string = ‘westus’
param name string = ‘lionsta’
var storageKind = ‘Storage’
resource sta ‘Microsoft.Storage/storageAccounts@2019-06-01’ = {
name: name
location: location
kind: storageKind
sku: {
name: ‘Standard_LRS’
}
}
output storageResourceId string = sta.id

Với ví dụ trên, hãy cùng so sánh syntax giữa Bicep và Terraform cũng như Bicep và ARM template.

Terraform vs Bicep

Nếu bạn sử dụng Terraform thì có thể dễ dàng nhận thấy sự tương đồng giữa hai DSL này. Dưới đây là bảng so sánh nhanh syntax giữa Bicep và Terraform:

Bicep Terraform
Variable
var storageKind = ‘Storage’
locals {
storageKind = “Storage”
}
Terraform sử dụng từ khóa locals để định nghĩa các biến số trong khi Bicep sử dụng từ khóa var. Theo mình thấy cách mà Bicep đặt tên từ khóa cũng như cách khai báo biến số của ngôn ngữ này nhìn dễ hiểu, gọn và sạch hơn so với Terraform.
Parameter
param location string = ‘westus’
variable “location” {
type = string
default = “westus”
}
Terraform sử dụng từ khóa variable để định nghĩa các tham số trong khi Bicep sử dụng từ khóa param. Việc định nghĩa tham số trong Terraform có một chút cồng kềnh hơn so với Bicep khi syntax khai báo tham số của Terraform khá giống với khai báo một JSON object.
Output
output storageResourceId string = sta.id
output “storageResourceId” {
value = data.sta.id
}
Cả hai DSL đều sử dụng từ khóa output để định nghĩa giá trị trả về. Cách định nghĩa giá trị trả về trong Bicep ở cái nhìn đầu tiên trong gọn hơn so với Terraform.
Resource
resource sta ‘Microsoft.Storage/storageAccounts@2019-06-01’ = {
name: name
location: location
kind: storageKind
sku: {
name: ‘Standard_LRS’
}
}
resource “azurerm_storage_account” “sta” {
name = var.name
location = var.location
account_tier = “Standard”
account_replication_type = “GRS”
account_kind = local.storageKind
}
Cả hai DSL đều sử dụng từ khóa resource để định nghĩa các tài nguyên cần triển khai. Khác với Terraform khi mà các resource của DSL này được HashiCorp xây dựng với các tùy biến của riêng họ về schema thuộc tính (property) của resource, Bicep sử dụng schema giống với những gì mà ARM API yêu cầu (bao gồm tên, cấu trúc, kiểu dữ liệu của thuộc tính) điều này giúp làm tăng tính nhất quán cũng như dễ tham chiếu giữa Bicep và ARM API trong quá trình phát triển. Hay nói một cách khác lập trình viên đã quen thuộc với việc sử dụng ARM API sẽ gần như không cần phải học lại schema thuộc tính tài nguyên khi sử dụng Bicep.

Bicep vs ARM template

Về mặt cấu trúc, giống với ARM template, một file .bicep được cấu thành bởi 4 thành phần khai báo chính sau:

  • Parameter: Các tham số sẽ được khai báo giá trị ở tại thời điểm triển khai.
  • Variable: Các biến số được sử dụng trong cấu hình tài nguyên cần triển khai.
  • Resource: Các tài nguyên cần triển khai.
  • Output: Các giá trị sẽ được trả ra sau khi thực hiện triển khai.

Các thành phần trên có thể được định nghĩa với thứ tự tuỳ ý và có thể trộn xen lẫn nhau giúp cho việc tổ chức code trở nên linh hoạt hơn. Bạn không cần phải bắt buộc khai báo parameter ở một cụm rồi sau đó mới khai báo các cụm thành phần khác như trong ARM template. Cùng ví dụ ở trên, thay vì khai báo output đặt cuối cùng, mình có thể chuyển nó lên vị trí đầu tiên cũng như đẩy phần khai báo parameter xuống bên dưới resource và thậm trí có thể chia tách phần khai báo tham số location và name ở hai vi trí khác nhau:

output storageResourceId string = sta.id
param location string = ‘westus’
var storageKind = ‘Storage’
resource sta ‘Microsoft.Storage/storageAccounts@2019-06-01’ = {
name: name
location: location
kind: storageKind
sku: {
name: ‘Standard_LRS’
}
}
param name string = ‘lionsta’

Nói đến tổ chức code, một điểm khác tuy nhỏ mà mình thích ở Bicep đó là DSL này cho phép đặt comment dễ dàng và linh hoạt hơn so với ARM template. Mặc dù ARM template hỗ trợ đặt comment tuy nhiên chỉ ở mức in-line comment tức comment 1 dòng, điều này khiến cho việc đặt comment vô cùng hạn chế. Ngoài ra việc đặt comment trong JSON không được hỗ trợ phổ biến ở nhiều công cụ phát triển. Với Bicep thì ngoài khả năng đặt in-line comment, mình có thể đặt comment với nhiều dòng, giúp cho việc đặt comment trở nên linh hoạt và dễ đọc hơn rất nhiều.

Trong ARM template, Microsoft cung cấp các ARM template function được viết sẵn như resourceGroup()concat(), … để lập trình viên có thể sử dụng chúng trong quá trình khai báo tài nguyên cần triển khai. Bicep cũng cho phép bạn sử dụng các ARM template function này khi viết .bicep file.

Dưới đây là bảng so sánh nhanh syntax giữa Bicep và ARM template:

Bicep ARM Template
Variable
var storageKind = ‘Storage’
“variables”: {
“storageKind”: “Storage”
}
Không có sự khác biệt nhiều trong syntax khai báo biến số giữa Bicep và ARM template.
Parameter
param location string = ‘westus’
“parameters”: {
“location”: {
“type”: “string”,
“defaultValue”: “westus”
}
}
Cách khai báo tham số của Bicep gọn nhẹ hơn rất nhiều, bạn không cần phải có một trường riêng để khai báo kiểu dữ liệu rồi có thêm một trường khác để khai báo giá trị mặc định của tham số như trong ARM template, tất cả các định nghĩa này đều được khai báo với 1 dòng code trong Bicep.
Output
output storageResourceId string = sta.id
“outputs”: {
“storageResourceId”: {
“type”: “string”,
“value”: “[resourceId(‘Microsoft.Storage/storageAccounts’, parameters(‘name’))]”
}
}
Tương tự như parameter, cách khai báo giá trị trả về của Bicep nhìn gọn nhẹ hơn rất nhiều so với ARM template.
Resource
resource sta ‘Microsoft.Storage/storageAccounts@2019-06-01’ = {
name: name
location: location
kind: storageKind
sku: {
name: ‘Standard_LRS’
}
}
“resources”: [
{
“type”: “Microsoft.Storage/storageAccounts”,
“apiVersion”: “2019-06-01”,
“name”: “[parameters(‘name’)]”,
“location”: “[parameters(‘location’)]”,
“kind”: “[variables(‘storageKind’)]”,
“sku”: {
“name”: “Standard_LRS”
}
}
]
Về số lượng dòng code cần viết khi khai báo resource giữa Bicep và ARM template về cơ bản là không khác nhau nhiều vì sử dụng chung schema thuộc tính. Tuy nhiên có thể thấy cách tham chiếu tới parameter hay variable trong Bicep nhìn gọn hơn khi bạn không cần phải khai báo thêm từ khóa để phân biệt đâu là tham số đâu là biến số.

Tính đến thời điểm mình viết bài viết này, Bicep chưa hỗ trợ user-defined function, một tính năng vô cùng hữu dụng cho phép lập trình viên định nghĩa các hàm dùng chung để tái sử dụng chúng trong các phần định nghĩa resourse hay variable. Không rõ Microsoft sẽ hỗ trợ tính năng này ở mức nào trong Bicep nhưng cá nhân mình rất hy vọng khả năng định nghĩa user-defined function cũng như sử dụng chúng sẽ không bị giới hạn chỉ trong cùng một file .bicep mà có thể chia sẻ và sử dụng chúng trong nhiều file .bicep khác nhau, tất nhiên không phải bằng việc copy-n-paste.

Sử dụng Bicep ra sao?

Để có thể bắt đầu sử dụng Bicep, trước tiên bạn cần phải cài đặt Bicep CLI, đây là công cụ để dịch file .bicep sang ARM template. Công cụ này hỗ trợ đa nền tảng nên đây là một điểm cộng rất lớn cho Bicep.

Lưu ý: Bicep CLI được xây dựng dựa trên .NET Core nên bạn cần phải có framework này cài đặt sẵn trong máy trước khi tiến hành cài đặt Bicep CLI.

Sau khi Bicep CLI được cài đặt thành công, về cơ bản là bạn đã có thể sẵn sàng code với Bicep rồi. Tuy nhiên nếu bạn sử dụng Visual Studio Code, bạn nên cài đặt thêm Bicep VS Code extension, đây là một phần bổ trợ rất rất hữu ích cho bạn khi code với Bicep sử dụng VS Code, nó cung cấp các tính năng như intellisense, bắt lỗi cú pháp, … giúp tăng hiệu suất code của bạn lên rất nhiều.

Bicep VS Code extension – Intellisense, syntax highlighting

Để tải cũng như chi tiết hướng dẫn cài đặt Bicep CLI và Bicep VS Code extension bạn có thể tham khảo tại đây.

Bắt đầu nhanh với Bicep

Để bắt đầu, bạn tạo một file .bicep trống sau đó sao chép nội dung của ví dụ mà mình chia sẻ ở đầu bài viết vào trong file được tạo (mình sẽ sử dụng tên file là lion.bicep để làm ví dụ cho phần hướng dẫn này). Nếu bạn sử dụng VS Code với Bicep VS Code extension được cài đặt, bạn sẽ thấy được syntax highlighting cho Bicep code mà bạn vừa sao chép như hình ở trên. Tiếp theo, bạn chạy câu lệnh sau để dịch file .bicep vừa được tạo:

bicep build lion.bicep

Sau khi dịch thành công, bạn sẽ thấy một file cùng tên nhưng với đuôi là .json được tạo trong cùng thư mục với file .bicep của bạn. Mở file .json đó lên bạn sẽ thấy được nội dung của ARM template được dịch từ file .bicep:

{
“$schema”: “https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#”,
“contentVersion”: “1.0.0.0”,
“parameters”: {
“location”: {
“type”: “string”,
“defaultValue”: “westus”
},
“name”: {
“type”: “string”,
“defaultValue”: “lionsta”
}
},
“functions”: [],
“variables”: {
“storageKind”: “Storage”
},
“resources”: [
{
“type”: “Microsoft.Storage/storageAccounts”,
“apiVersion”: “2019-06-01”,
“name”: “[parameters(‘name’)]”,
“location”: “[parameters(‘location’)]”,
“kind”: “[variables(‘storageKind’)]”,
“sku”: {
“name”: “Standard_LRS”
}
}
],
“outputs”: {
“storageResourceId”: {
“type”: “string”,
“value”: “[resourceId(‘Microsoft.Storage/storageAccounts’, parameters(‘name’))]”
}
}
}

Với file ARM template này, bạn có thể sử dụng Azure CLI hoặc Azure PowerShell để triển khai lên trên Azure.

az deployment group create \
-n lion-bicep-deployment \
-g lion-bicep-rg \
–template-file lion.json

Tiềm năng của Bicep?

Theo Microsoft chia sẻ, mặc dù hai công cụ Bicep và Teraform có thể được coi là “đối thủ” trực tiếp của nhau, tuy nhiên Microsoft khẳng định rằng họ vẫn tiếp tục hỗ trợ Terraform ở mức tốt nhất. Sự ra đời của Bicep đứng ở phía Microsoft được coi đơn giản chỉ là mang thêm một lựa chọn cho lập trình viên khi tìm kiếm một công cụ IaC phù hợp với dự án của họ, đặc biệt với những dự án khó tính trong việc sử dụng các công cụ thuộc bên thứ ba.

Bicep phù hợp cho những ai, dự án nào?

Dựa vào những gì mà Bicep hiện có, dưới đây là những kịch bản mà theo mình Bicep có thể chiếm lợi thế:

  • Bicep có thể phù hợp với những dự án mới, khi chưa có quá nhiều ràng buộc với ARM template hay Terraform.
  • Bicep là lựa chọn phù hợp với những lập trình viên là “fan ruột” của Terraform tuy nhiên bị ràng buộc bởi những giới hạn của dự án trong việc sử dụng các công cụ thuộc bên thứ ba như Terraform.
  • Bicep là lựa chọn tốt hơn so với ARM template nếu như dự án đang tìm kiếm một giải pháp IaC “chính chủ” với syntax gọn nhẹ, dễ hiểu, dễ học.

Đối với cá nhân mình, một trong những điểm then chốt để có thể thuyết phục được mình trong việc chuyển từ sử dụng ARM template sang Bicep đó là khả năng mô-đun hóa của Bicep sẽ được hỗ trợ tới đâu? Sự linh hoạt trong cách đóng gói cũng như chia sẻ, tái sử dụng Bicep mô-đun sẽ như thế nào? Nếu khả năng mô-đun hóa của Bicep sẽ chỉ đơn thuần là giống với cách mà ARM template hiện hỗ trợ, việc dịch chuyển sang sử dụng Bicep sẽ không thật sự mang nhiều ý nghĩa với mình.

Bicep vẫn đang ở giai đoạn phát triển, còn rất nhiều tính năng hiện có trong ARM template mà Microsoft vẫn chưa hỗ trợ trong Bicep. Tiềm năng và sự hiệu quả của công cụ này ra sao vẫn còn là một giấu hỏi lớn với cá nhân mình khi trải nghiệm với công cụ này ở mức production vẫn còn là con số không. Hy vọng mình sẽ sớm có cơ hội áp dụng nó ở các dự án của mình và sẽ cập nhật với các bạn về những trải nghiệm mà mình có khi sử dụng Bicep.

Chi tiết về dự án Bicep này bạn có thể tham khảo thêm tại đây.

Theo https://blog.lionpham.com/2020/09/30/azure-bicep-iac/

Theo dõi
Thông báo của
guest
0 Góp ý
Phản hồi nội tuyến
Xem tất cả bình luận
spot_img

Có thể bạn sẽ thích

EVsideURL là gì? Cấu trúc của URL

Khi duyệt web bạn chắc hẳn bạn đã nghe nói về URL (đọc tiếng Anh nôm na...

Vulnerable JavaScript dependency là gì

Theo một nghiên cứu của Veracode – doanh nghiệp chuyên về bảo mật ứng dụng, gần như...

SMTP là gì?

SMTP là gì? SMTP là viết tắt của Simple Mail Transfer Protocol (Giao thức Truyền tải Thư tin...