可以 ChatGPT 简化 Azure DevOps 工程师的生活吗?
大家好,
我已经与Azure Cloud紧密合作相当长时间了。尽管有与GCP和AWS的经验,我发现微软的产品最为熟悉。也许是因为我偶尔可以休息一下控制台和PowerShell脚本 :)
上周,我花时间组织我们的IaC项目。我计划进行一次重要的清理和重构,意味着需要破坏和修复许多东西。然而,我始终在想这应该由一个LLM代理来完成,而不是一个人。
我以前用过各种不同的模型进行剧本写作,现在看来是时候测试一下这个聊天与 Bicep 有多好了。
对于这项任务,我要求它写一个简单的结构,包括一个静态网站、一个API以及两个分别与不同数据库交互的服务。
我的提示是:
免责声明:此提示是即兴写的,没有经过认真分析。
You are an Azure DevOps Engineer. Your main task is to write configurations for Azure Cloud infrastructure. You always verify the answer before providing it. Your strong suit is Bicep.
Please write me a Bicep configuration for:
Two container applications:
cap-lsl-usermngmnt-westuk-001'
cap-lsl-alerting-westuk-001
Two databases:
sqldb-lsl-usermngmnt-westuk-001 - Azure SQL
sqldb-lsl-alerting-westuk-001 - MongoDB on CosmosDB server
One App Service:
app-lsl-apigateway-westuk-001
One Static Web App that uses the App Service as its API:
swa-lsl-board-westeu-001
Configure all components that can be deployed as a container to use a single Container Registry with temporary URL, login, and password.
我故意跳过了创建容器环境、SQL Server 和具有 MongoDB 的 Azure CosmosDB 等事项。我很好奇看看这个模型能否独立管理得如何。
让我们拆分一下:
参数:
param containerRegistryUsername string = 'myUsername'
param containerRegistryPassword string = 'myPassword'
很高兴看到参数被从主要指令中分离出来。但是这是聊天已经处理得很好一段时间了。
接下来,聊天创建了一个资源组。我并没有提出,但这是一个好主意。
// resource group
resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: 'myResourceGroup'
location: 'westeurope'
}
聊天完全忘记创建容器环境和所有相关服务,直接转向应用程序服务。
服务大致上是正确创建的。请注意,聊天并没有在最低功能的服务设置上节衣缩食,而是选择了更强大的设置。
resource userMngmntContainerApp 'Microsoft.ContainerInstance/containerGroups@2021-03-01' = {
name: 'cap-lsl-usermngmnt-westuk-001'
location: 'westeurope'
properties: {
containers: [
{
name: 'usermngmnt'
properties: {
image: '${containerRegistry.properties.loginServer}/usermngmnt:latest'
resources: {
requests: {
cpu: 1
memoryInGb: 1.5
}
}
}
}
]
osType: 'Linux'
}
resource alertingContainerApp 'Microsoft.ContainerInstance/containerGroups@2021-03-01' = {
name: 'cap-lsl-alerting-westuk-001'
location: 'westeurope'
properties: {
containers: [
{
name: 'alerting'
properties: {
image: '${containerRegistry.properties.loginServer}/alerting:latest'
resources: {
requests: {
cpu: 1
memoryInGb: 1.5
}
}
}
}
]
osType: 'Linux'
}
}
我想指出的是,这种内存和CPU的组合是不可能的,所以我们绝对会在这里遇到错误。
我更详细地描述我的服务,就像这样:
// Product level of infrustructure
param location string
param vNetExternalId string // this is not the best way to work with existing resources, I recomment to get it by name in each bicep module.
param sNetName string
param caeName string
resource cae 'Microsoft.App/managedEnvironments@2023-08-01-preview' = {
name: caeName
location: location
properties: {
vnetConfiguration: {
internal: true
infrastructureSubnetId: '${vNetExternalId}/subnets/${sNetName}'
platformReservedCidr:
platformReservedDnsIP:
}
zoneRedundant: false
}
}
// Applications level of infrustructure
var cap_lslalerting_name = 'cap-lslalerting-${shortEnvironment}-westuk-001'
resource cap_lslalerting 'Microsoft.App/containerapps@2023-05-02-preview' = if (alertingCA) { // I use conditions for deploying services as a feature
name: cap_alerting_name
kind: 'containerapps'
location: location
tags: {
'global-environment': envTag
}
properties: {
environmentId: cae.id // this is the Container Environment
managedEnvironmentId: cae.id // this is the Container Environment
configuration: {
secrets: alertingConfig
registries: [
{
server: '${containerRegistry.properties.loginServer}'
username: 'login'
passwordSecretRef: 'reg-pswd-xxxxx-xxxx'
}
]
activeRevisionsMode: 'Single'
ingress: {
targetPort: 80
external: true
transport: 'auto'
allowInsecure: true
clientCertificateMode: 'ignore'
stickySessions: {
affinity: 'none'
}
}
}
template: {
containers: [
{
name: cap_lslpalerting_name
image: '${containerRegistry.properties.loginServer}/alerting:latest'
command: []
resources: {
cpu: '0.25'
memory: '.5Gi'
}
env: [...]
}
]
scale: {
minReplicas: 0
maxReplicas: 10
rules: [
{
name: 'http-scaler'
http: {
metadata: { concurrentRequests: '10' }
}
}
]
}
}
}
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${uaiId}': {}
'${uaiHubId}': {}
}
}
dependsOn: [
caeExternal
]
}
不幸的是,聊天没有处理数据库,并且只包括数据库本身,而不是它们的服务器。这很奇怪,因为在其他情况下,它试图创建容器注册表和服务计划都一并处理。
resource sqlDatabase 'Microsoft.Sql/servers@2021-02-01-preview' = {
name: 'sqldb-lsl-usermngmnt-westuk-001'
location: rg.location
properties: {
administratorLogin: 'sqladmin'
administratorLoginPassword: 'sqlpassword!'
}
resources: [
{
name: 'usermngmntdb'
type: 'databases'
properties: {
collation: 'SQL_Latin1_General_CP1_CI_AS'
maxSizeBytes: 2147483648
sku: {
name: 'Basic'
}
}
}
]
}
resource cosmosDB 'Microsoft.DocumentDB/databaseAccounts@2021-04-15' = {
name: 'sqldb-lsl-alerting-westuk-001'
location: rg.location
properties: {
consistencyPolicy: {
defaultConsistencyLevel: 'Session'
}
locations: [
{
locationName: rg.location
failoverPriority: 0
}
]
databaseAccountOfferType: 'Standard'
}
}
常常聊天也会使用错误的命名空间。
总结:
1. 如果您是初学者,使用聊天功能来写基础架构绝对是值得的。
2. 聊天可以帮助你捕捉你错过的东西,但也可能通过添加不必要的项目来误导你。
3. 不要指望一个完美的结果,但是你总是可以把它作为一个起点。如果像我一样,你绘制的组件图可以很容易地用XML或者其他结构化的语言描述,那么将聊天集成到你的工作流程中绝对是值得的。
4. 不要害怕尝试。您可能最终会开发出一个完整的代理程序,可以从存储库中获取源代码,修改Bicep文件,在Azure Cloud上运行它们,修复错误,然后再次检查所有内容。
祝你好运!
附言。
ChatGPT-4o中的二头肌
// Parameters
param containerRegistryUsername string = 'myUsername'
param containerRegistryPassword string = 'myPassword'
// resource group
resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: 'myResourceGroup'
location: 'westeurope'
}
// Container registry
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2021-06-01-preview' = {
name: 'myContainerRegistry'
location: rg.location
sku: {
name: 'Basic'
}
adminUserEnabled: true
}
// Container Apps
resource userMngmntContainerApp 'Microsoft.ContainerInstance/containerGroups@2021-03-01' = {
name: 'cap-lsl-usermngmnt-westuk-001'
location: 'westeurope'
properties: {
containers: [
{
name: 'usermngmnt'
properties: {
image: '${containerRegistry.properties.loginServer}/usermngmnt:latest'
resources: {
requests: {
cpu: 1
memoryInGb: 1.5
}
}
}
}
]
osType: 'Linux'
}
}
resource alertingContainerApp 'Microsoft.ContainerInstance/containerGroups@2021-03-01' = {
name: 'cap-lsl-alerting-westuk-001'
location: 'westeurope'
properties: {
containers: [
{
name: 'alerting'
properties: {
image: '${containerRegistry.properties.loginServer}/alerting:latest'
resources: {
requests: {
cpu: 1
memoryInGb: 1.5
}
}
}
}
]
osType: 'Linux'
}
}
// Databases
resource sqlDatabase 'Microsoft.Sql/servers@2021-02-01-preview' = {
name: 'sqldb-lsl-usermngmnt-westuk-001'
location: rg.location
properties: {
administratorLogin: 'sqladmin'
administratorLoginPassword: 'sqlpassword!'
}
resources: [
{
name: 'usermngmntdb'
type: 'databases'
properties: {
collation: 'SQL_Latin1_General_CP1_CI_AS'
maxSizeBytes: 2147483648
sku: {
name: 'Basic'
}
}
}
]
}
resource cosmosDB 'Microsoft.DocumentDB/databaseAccounts@2021-04-15' = {
name: 'sqldb-lsl-alerting-westuk-001'
location: rg.location
properties: {
consistencyPolicy: {
defaultConsistencyLevel: 'Session'
}
locations: [
{
locationName: rg.location
failoverPriority: 0
}
]
databaseAccountOfferType: 'Standard'
}
}
// App Service
resource appServicePlan 'Microsoft.Web/serverfarms@2021-02-01' = {
name: 'appServicePlan'
location: rg.location
sku: {
name: 'B1'
tier: 'Basic'
}
}
resource appService 'Microsoft.Web/sites@2021-02-01' = {
name: 'app-lsl-apigateway-westuk-001'
location: rg.location
properties: {
serverFarmId: appServicePlan.id
}
}
// Static Web App
resource staticWebApp 'Microsoft.Web/staticSites@2021-02-01' = {
name: 'swa-lsl-board-westeu-001'
location: 'westeurope'
properties: {
sku: {
name: 'Free'
tier: 'Free'
}
repositoryToken: '<github-token>'
buildProperties: {
apiLocation: 'api'
appLocation: 'app'
outputLocation: 'build'
}
}
}