自动化yaml文件_从YAML到TypeScript:开发人员对云自动化的看法
自動化yaml文件
The rise of managed cloud services, cloud-native, and serverless applications brings both new possibilities and challenges. More and more practices from software development processes like version control, code review, continuous integration, and automated testing are applied to cloud infrastructure automation.
受管云服務,云原生和無服務器應用程序的興起帶來了新的可能性和挑戰。 來自軟件開發過程的越來越多的實踐(例如版本控制,代碼審查,持續集成和自動化測試)被應用到云基礎架構自動化中。
Most existing tools suggest defining infrastructure in text-based markup formats, YAML being the favorite. In this article, I’m making a case for using real programming languages like TypeScript instead. Such a change makes even more software development practices applicable to the infrastructure realm.
大多數現有工具建議以基于文本的標記格式定義基礎結構,YAML是最受歡迎的工具。 在本文中,我將提出使用諸如TypeScript之類的真實編程語言的理由。 這樣的改變使得更多的軟件開發實踐適用于基礎架構領域。
樣品申請 (Sample Application)
It’s easier to make a case given a specific example. For this article, we’ll build a URL Shortener application, a basic clone of tinyurl.com or bit.ly. There is an administrative page where we can define short aliases for long URLs:
在給出具體示例的情況下進行案例比較容易。 對于本文,我們將構建一個URL Shortener應用程序,它是tinyurl.com或bit.ly的基本克隆。 在一個管理頁面中,我們可以為長URL定義短別名:
Now, whenever a visitor goes to the base URL of the application + an existing alias, they get redirected to the full URL.
現在,只要訪問者轉到應用程序的基本URL +現有別名,他們就會被重定向到完整URL。
This app is simple to describe but involves enough moving parts to be representative of some real-world issues. As a bonus, there are many existing implementations on the web to compare with.
該應用程序易于描述,但涉及足夠多的運動部件,可以代表一些實際問題。 值得一提的是,網絡上有許多現有的實現方式可以與之進行比較。
無服務器URL縮短器 (Serverless URL Shortener)
I’m a big proponent of serverless architecture: the style of cloud applications being a combination of serverless functions and managed cloud services. They are fast to develop, effortless to run, and cost pennies unless the application gets lots of users. However, even serverless applications have to deal with infrastructure, like databases, queues, and other sources of events and destinations of data.
我大力支持無服務器架構:云應用程序的風格是無服務器功能和托管云服務的結合。 除非應用程序吸引大量用戶,否則它們開發速度快,運行省力且花費不菲。 但是,即使是無服務器的應用程序也必須處理基礎結構,例如數據庫,隊列以及其他事件源和數據目標。
My examples are going to use Amazon’s AWS, but this could be Microsoft Azure or Google Cloud Platform too.
我的示例將使用亞馬遜的AWS,但這也可能是Microsoft Azure或Google Cloud Platform。
So, the gist is to store URLs with short names as key-value pairs in Amazon DynamoDB and use AWS Lambdas to run the application code. Here is the initial sketch:
因此,要點是將帶有短名稱的URL作為鍵值對存儲在Amazon DynamoDB中,并使用AWS Lambdas運行應用程序代碼。 這是初始草圖:
The Lambda at the top receives an event when somebody decides to add a new URL. It extracts the name and the URL from the request and saves them as an item in the DynamoDB table.
當有人決定添加新的URL時,頂部的Lambda會收到一個事件。 它從請求中提取名稱和URL,并將它們另存為DynamoDB表中的一項。
The Lambda at the bottom is called whenever a user navigates to a short URL. The code reads the full URL based on the requested path and returns a 301 response with the corresponding location.
每當用戶導航到短URL時,都會調用底部的Lambda。 該代碼根據請求的路徑讀取完整的URL,并返回帶有相應位置的301響應。
Here is the implementation of the Open URL Lambda in JavaScript:
這是JavaScript中Open URL Lambda的實現:
const aws = require('aws-sdk'); const table = new aws.DynamoDB.DocumentClient(); exports.handler = async (event) => { const name = event.path.substring(1); const params = { TableName: "urls", Key: { "name": name } }; const value = await table.get(params).promise(); const url = value && value.Item && value.Item.url; return url ? { statusCode: 301, body: "", headers: { "Location": url } } : { statusCode: 404, body: name + " not found" }; };That’s 11 lines of code. I’ll skip the implementation of Add URL function because it's very similar. Considering a third function to list the existing URLs for UI, we might end up with 30-40 lines of JavaScript in total.
那是11行代碼。 因為它非常相似,所以我將跳過“ Add URL功能的實現。 考慮到列出UI的現有URL的第三個功能,我們最終可能總共需要30-40行JavaScript。
So, how do we deploy the application?
那么,我們如何部署應用程序?
Well, before we do that, we should realize that the above picture was an over-simplification:
好吧,在我們這樣做之前,我們應該意識到上面的圖片過于簡單了:
- AWS Lambda can’t handle HTTP requests directly, so we need to add AWS API Gateway in front of it. AWS Lambda無法直接處理HTTP請求,因此我們需要在其前面添加AWS API Gateway。
- We also need to serve some static files for the UI, which we’ll put into AWS S3 and proxy it with the same API Gateway. 我們還需要為UI提供一些靜態文件,這些文件將放入AWS S3中并使用相同的API網關進行代理。
Here is the updated diagram:
這是更新的圖:
This is a viable design, but the details are even more complicated:
這是一個可行的設計,但細節更加復雜:
- API Gateway is a complex beast which needs Stages, Deployments, and REST Endpoints to be appropriately configured. API網關是一個復雜的野獸,需要適當配置階段,部署和REST端點。
- Permissions and Policies need to be defined so that API Gateway could call Lambda and Lambda could access DynamoDB. 需要定義權限和策略,以便API網關可以調用Lambda,而Lambda可以訪問DynamoDB。
- Static Files should go to S3 Bucket Objects. 靜態文件應轉到S3存儲桶對象。
So, the actual setup involves a couple of dozen objects to be configured in AWS:
因此,實際設置涉及在AWS中配置的數十個對象:
How do we approach this task?
我們如何完成這項任務?
提供基礎架構的選項 (Options to Provision the Infrastructure)
There are many options to provision a cloud application, and each one has its trade-offs. Let’s quickly go through the list of possibilities to understand the landscape.
部署云應用程序有很多選擇,每個選擇都有其取舍。 讓我們快速瀏覽一下各種可能性以了解景觀。
AWS Web控制臺 (AWS Web Console)
AWS, like any other cloud, has a web user interface to configure its resources:
與其他任何云一樣,AWS具有一個Web用戶界面來配置其資源:
That’s a decent place to start — good for experimenting, figuring out the available options, following the tutorials, i.e., for exploration.
這是一個不錯的起點–適用于進行實驗,根據教程(例如進行探索)找出可用選項。
However, it doesn’t suit particularly well for long-lived ever-changing applications developed in teams. A manually clicked deployment is pretty hard to reproduce in the exact manner, which becomes a maintainability issue pretty fast.
但是,它不適用于團隊中長期存在且不斷變化的應用程序。 手動單擊的部署很難以精確的方式進行復制,這很快成為可維護性問題。
AWS命令行界面 (AWS Command Line Interface)
The AWS Command Line Interface (CLI) is a unified tool to manage all AWS services from a command prompt. You write the calls like this:
AWS Command Line Interface (CLI)是一個統一的工具,可從命令提示符管理所有AWS服務。 您可以這樣編寫呼叫:
aws apigateway create-rest-api --name 'My First API' --description 'This is my first API' aws apigateway create-stage --rest-api-id 1234123412 --stage-name 'dev' --description 'Development stage' --deployment-id a1b2c3The initial experience might not be as smooth as clicking buttons in the browser, but the huge benefit is that you can reuse commands that you once wrote. You can build scripts by combining many commands into cohesive scenarios. So, your colleague can benefit from the same script that you created. You can provision multiple environments by parameterizing the scripts.
最初的體驗可能不如單擊瀏覽器中的按鈕那么順暢,但是巨大的好處是您可以重用曾經編寫的命令。 您可以通過將許多命令組合到有凝聚力的方案中來構建腳本。 因此,您的同事可以從您創建的相同腳本中受益。 您可以通過參數化腳本來設置多個環境。
Frankly speaking, I’ve never done that for several reasons:
坦白地說,出于以下幾個原因,我從未這樣做過:
- CLI scripts feel too imperative to me. I have to describe “how” to do things, not “what” I want to get in the end. CLI腳本對我來說太重要了。 我必須描述“如何”做事情,而不是最后要表達的“什么”。
- There seems to be no good story for updating existing resources. Do I write small delta scripts for each change? Do I have to keep them forever and run the full suite every time I need a new environment? 更新現有資源似乎沒有好故事。 是否為每次更改編寫小的增量腳本? 我是否需要永久保留它們并在每次需要新環境時都運行完整套件?
- If a failure occurs mid-way through the script, I need to manually repair everything to a consistent state. This gets messy real quick, and I have no desire to exercise this process, especially in production. 如果腳本中途發生故障,我需要手動將所有內容修復到一致狀態。 這很快就會變得凌亂,我不希望執行此過程,尤其是在生產中。
To overcome such limitations, the notion of the Desired State Configuration (DSC) was invented. Under this paradigm, we describe the desired layout of the infrastructure, and then the tooling takes care of either provisioning it from scratch or applying the required changes to an existing environment.
為了克服這些限制,發明了期望狀態配置 (DSC)的概念。 在此范例下,我們描述了所需的基礎結構布局,然后該工具負責從頭開始進行配置或將所需的更改應用于現有環境。
Which tool provides DSC model for AWS? There are legions.
哪個工具為AWS提供DSC模型? 有軍團。
AWS CloudFormation (AWS CloudFormation)
AWS CloudFormation is the first-party tool for Desired State Configuration management from Amazon. CloudFormation templates use YAML to describe all the infrastructure resources of AWS.
AWS CloudFormation是Amazon進行所需狀態配置管理的第一方工具。 CloudFormation模板使用YAML來描述AWS的所有基礎架構資源。
Here is a snippet from a private URL shortener example kindly provided on the AWS blog:
以下是AWS博客上提供的私有URL縮短程序示例的摘錄:
Resources:S3BucketForURLs:Type: "AWS::S3::Bucket"DeletionPolicy: DeleteProperties:BucketName: !If ["CreateNewBucket", !Ref "AWS::NoValue", !Ref S3BucketName ]WebsiteConfiguration:IndexDocument: "index.html"LifecycleConfiguration:Rules:-Id: DisposeShortUrlsExpirationInDays: !Ref URLExpirationPrefix: "u"Status: EnabledThis is just a very short fragment: the complete example consists of 317 lines of YAML. That’s an order of magnitude more than the actual JavaScript code that we have in the application!
這只是一個很短的片段:完整的示例包含317行YAML。 這比我們在應用程序中擁有的實際JavaScript代碼高出一個數量級!
CloudFormation is a powerful tool, but it demands quite some learning to be done to master it. Moreover, it’s specific to AWS: you won’t be able to transfer the skill to other cloud providers.
CloudFormation是一個功能強大的工具,但要掌握它需要大量的學習。 而且,它特定于AWS:您將無法將該技能轉讓給其他云提供商。
Wouldn’t it be great if there was a universal DSC format? Meet Terraform.
如果有通用的DSC格式不是很好嗎? 認識Terraform。
地貌 (Terraform)
HashiCorp Terraform is an open source tool to define infrastructure in declarative configuration files. It has a pluggable architecture, so the tool supports all major clouds and even hybrid scenarios.
HashiCorp Terraform是一個開放源代碼工具,用于在聲明性配置文件中定義基礎結構。 它具有可插拔架構,因此該工具支持所有主要云甚至混合方案。
The custom text-based Terraform .tf format is used to define the configurations. The templating language is quite powerful, and once you learn it, you can use it for different cloud providers.
基于文本的自定義Terraform .tf格式用于定義配置。 模板語言功能強大,一旦學習,便可以將其用于其他云提供商。
Here is a snippet from AWS Lambda Short URL Generator example:
這是AWS Lambda短URL生成器示例的片段:
resource "aws_api_gateway_rest_api" "short_urls_api_gateway" {name = "Short URLs API"description = "API for managing short URLs." } resource "aws_api_gateway_usage_plan" "short_urls_api_usage_plan" {name = "Short URLs admin API key usage plan"description = "Usage plan for the admin API key for Short URLS."api_stages {api_id = "${aws_api_rest_api.short_urls_gateway.id}"stage = "${aws_api_deployment.short_url_deployment.stage_name}"} }This time, the complete example is around 450 lines of textual templates. Are there ways to reduce the size of the infrastructure definition?
這次,完整的示例是大約450行文本模板。 有沒有辦法減小基礎架構定義的大小?
Yes, by raising the level of abstraction. It’s possible with Terraform’s modules, or by using other, more specialized tools.
是的,通過提高抽象水平。 使用Terraform的模塊,或使用其他更專業的工具,這是可能的。
無服務器框架和SAM (Serverless Framework and SAM)
The Serverless Framework is an infrastructure management tool focused on serverless applications. It works across cloud providers (AWS support is the strongest though) and only exposes features related to building applications with cloud functions.
無服務器框架是針對無服務器應用程序的基礎結構管理工具。 它可跨云提供商使用(盡管AWS支持最強),并且僅公開與使用云功能構建應用程序有關的功能。
The benefit is that it’s much more concise. Once again, the tool is using YAML to define the templates, here is the snippet from Serverless URL Shortener example:
好處是它更加簡潔。 該工具再次使用YAML定義模板,這是Serverless URL Shortener示例的摘錄:
functions:store:handler: api/store.handleevents:- http:path: /method: postcors: trueThe domain-specific language yields a shorter definition: this example has 45 lines of YAML + 123 lines of JavaScript functions.
特定領域的語言產生了一個較短的定義:此示例包含45行的YAML + 123行JavaScript函數。
However, the conciseness has a flip side: as soon as you veer outside of the fairly “thin” golden path — the cloud functions and an incomplete list of event sources — you have to fall back to more generic tools like CloudFormation. As soon as your landscape includes lower-level infrastructure work or some container-based components, you’re stuck using multiple config languages and tools again.
但是,簡潔有一個缺點:一旦您走出了相當“細”的黃金路徑(云功能和事件源列表不完整)之外,您就不得不依靠CloudFormation等更通用的工具。 一旦您的環境包括較低級別的基礎結構工作或某些基于容器的組件,您將再次陷入使用多種配置語言和工具的困境。
Amazon’s AWS Serverless Application Model (SAM) looks very similar to the Serverless Framework but is tailored to be AWS-specific.
亞馬遜的AWS無服務器應用程序模型 (SAM)看起來與無服務器框架非常相似,但專門針對AWS而量身定制。
Is that the end game? I don’t think so.
那是最后的比賽嗎? 我不這么認為。
基礎架構定義工具的所需屬性 (Desired Properties of Infrastructure Definition Tool)
So what have we learned while going through the existing landscape? The perfect infrastructure tools should:
那么,在瀏覽現有環境時我們學到了什么? 完善的基礎架構工具應:
Provide reproducible results of deployments
提供可重復的部署結果
Be scriptable, i.e., require no human intervention after the definition is complete
可編寫腳本 ,即在定義完成后無需人工干預
Define the desired state rather than exact steps to achieve it
定義所需的狀態,而不是實現它的確切步驟
Support multiple cloud providers and hybrid scenarios
支持多個云提供商和混合方案
Be universal in the sense of using the same tool to define any type of resource
在使用相同工具定義任何類型的資源的意義上具有通用性
Be succinct and concise to stay readable and manageable
簡潔 明了,以保持可讀性和可管理性
- ?U???s???e??? ???Y???A???M???L???-???b???a???s???e???d??? ???f???o???r???m???a???t??? ?U???s???e??????Y???A???M???L???-???b???a???s???e???d??????f???o???r???m???a???t???
Nah, I crossed out the last item. YAML seems to be the most popular language among this class of tools (and I haven’t even touched Kubernetes yet!), but I’m not convinced it works well for me. YAML has many flaws, and I just don’t want to use it.
不,我刪除了最后一個項目。 在這類工具中,YAML似乎是最受歡迎的語言(而且我還沒有接觸過Kubernetes!),但我不認為它對我來說效果很好。 YAML有很多缺陷,我只是不想使用它 。
Have you noticed that I haven’t mentioned Infrastructure as code a single time yet? Well, here we go (from Wikipedia):
您是否注意到我還沒有一次提到基礎架構作為代碼 ? 好吧,我們開始(來自Wikipedia ):
Infrastructure as code (IaC) is the process of managing and provisioning computer data centers through machine-readable definition files, rather than physical hardware configuration or interactive configuration tools.
基礎架構即代碼(IaC)是通過機器可讀的定義文件而不是物理硬件配置或交互式配置工具來管理和配置計算機數據中心的過程。
Shouldn’t it be called “Infrastructure as definition files”, or “Infrastructure as YAML”?
不應將其稱為“基礎結構定義文件”或“基礎結構YAML”嗎?
As a software developer, what I really want is “Infrastructure as actual code, you know, the program thing”. I want to use the same language that I already know. I want to stay in the same editor. I want to get IntelliSense auto-completion when I type. I want to see the compilation errors when what I typed is not syntactically correct. I want to reuse the developer skills that I already have. I want to come up with abstractions to generalize my code and create reusable components. I want to leverage the open-source community who would create much better components than I ever could. I want to combine the code and infrastructure in one code project.
作為軟件開發人員,我真正想要的是“將基礎結構作為實際的程序代碼”。 我想使用我已經知道的相同語言 。 我想留在同一個編輯器中。 我想在鍵入時獲得IntelliSense 自動完成功能 。 當我鍵入的內容在語法上不正確時,我想查看編譯錯誤 。 我想重用已經擁有的開發人員技能 。 我想提出抽象來概括我的代碼并創建可重用的組件 。 我想利用開源社區 , 該社區將創建比以往任何時候都更好的組件。 我想將代碼和基礎結構合并到一個代碼項目中。
If you are with me on that, keep reading. You get all of that with Pulumi.
如果您和我在一起,請繼續閱讀。 您可以通過Pulumi獲得所有這些。
普魯米 (Pulumi)
Pulumi is a tool to build cloud-based software using real programming languages. They support all major cloud providers, plus Kubernetes.
Pulumi是使用真正的編程語言構建基于云的軟件的工具。 他們支持所有主要的云提供商以及Kubernetes。
Pulumi programming model supports Go and Python too, but I’m going to use TypeScript for the rest of the article.
Pulumi編程模型也支持Go和Python,但在本文的其余部分中,我將使用TypeScript。
While prototyping a URL shortener, I explain the fundamental way of working and illustrate the benefits and some trade-offs. If you want to follow along, install Pulumi.
在為URL縮短器制作原型時,我解釋了基本的工作方式,并說明了其好處和一些折衷。 如果要繼續, 請安裝Pulumi 。
Pulumi如何運作 (How Pulumi Works)
Let’s start defining our URL shortener application in TypeScript. I installed @pulumi/pulumi and @pulumi/aws NPM modules so that I can start the program. The first resource to create is a DynamoDB table:
讓我們開始在TypeScript中定義我們的URL縮短程序。 我安裝了@pulumi/pulumi和@pulumi/aws NPM模塊,以便可以啟動該程序。 創建的第一個資源是DynamoDB表:
import * as aws from "@pulumi/aws";// A DynamoDB table with a single primary key let counterTable = new aws.dynamodb.Table("urls", {name: "urls",attributes: [{ name: "name", type: "S" },],hashKey: "name",readCapacity: 1,writeCapacity: 1 });I use pulumi CLI to run this program to provision the actual resource in AWS:
我使用pulumi CLI運行該程序來配置AWS中的實際資源:
> pulumi up Previewing update (urlshortener): Type Name Plan + pulumi:pulumi:Stack urlshortener create + aws:dynamodb:Table urls create Resources: + 2 to create Do you want to perform this update? yes Updating (urlshortener): Type Name Status + pulumi:pulumi:Stack urlshortener created + aws:dynamodb:Table urls created Resources: + 2 createdThe CLI first shows the preview of the changes to be made, and when I confirm, it creates the resource. It also creates a stack — a container for all the resources of the application.
CLI首先顯示要進行的更改的預覽,當我確認時,它將創建資源。 它還創建了一個堆棧 -應用程序所有資源的容器。
This code might look like an imperative command to create a DynamoDB table, but it actually isn’t. If I go ahead and change readCapacity to 2 and then re-run pulumi up, it produces a different outcome:
這段代碼看起來像是創建DynamoDB表的命令命令,但實際上并非如此。 如果我繼續將readCapacity更改為2 ,然后重新運行pulumi up ,它將產生不同的結果:
> pulumi up Previewing update (urlshortener):Type Name Planpulumi:pulumi:Stack urlshortener ~ aws:dynamodb:Table urls update [diff: ~readCapacity] Resources: ~ 1 to update 1 unchangedIt detects the exact change that I made and suggests an update. The following picture illustrates how Pulumi works:
它檢測到我所做的確切更改并建議進行更新。 下圖說明了Pulumi的工作方式:
index.ts in the red square is my program. Pulumi's language host understands TypeScript and translates the code to commands to the internal engine. As a result, the engine builds a tree of resources-to-be-provisioned, the desired state of the infrastructure.
index.ts中的index.ts是我的程序。 Pulumi的語言宿主理解TypeScript并將代碼轉換為命令到內部引擎。 結果,引擎構建了待配置資源的樹,即基礎結構的期望狀態。
The end state of the last deployment is persisted in the storage (can be in pulumi.com backend or a file on disk). The engine then compares the current state of the system with the desired state of the program and calculates the delta in terms of create-update-delete commands to the cloud provider.
上次部署的結束狀態保留在存儲中(可以位于pulumi.com后端或磁盤上的文件中)。 然后,引擎將系統的當前狀態與程序的期望狀態進行比較,并根據向云提供商提供的create-update-delete命令來計算增量。
類型幫助 (Help Of Types)
Now I can proceed to the code that defines a Lambda function:
現在,我可以繼續定義Lambda函數的代碼:
// Create a Role giving our Lambda access. let policy: aws.iam.PolicyDocument = { /* Redacted for brevity */ }; let role = new aws.iam.Role("lambda-role", {assumeRolePolicy: JSON.stringify(policy), }); let fullAccess = new aws.iam.RolePolicyAttachment("lambda-access", {role: role,policyArn: aws.iam.AWSLambdaFullAccess, });// Create a Lambda function, using code from the `./app` folder. let lambda = new aws.lambda.Function("lambda-get", {runtime: aws.lambda.NodeJS8d10Runtime,code: new pulumi.asset.AssetArchive({".": new pulumi.asset.FileArchive("./app"),}),timeout: 300,handler: "read.handler",role: role.arn,environment: { variables: {"COUNTER_TABLE": counterTable.name}}, }, { dependsOn: [fullAccess] });You can see that the complexity kicked in and the code size is growing. However, now I start to gain real benefits from using a typed programming language:
您會看到復雜性增加了,代碼大小也在增加。 但是,現在我開始從使用類型化的編程語言中獲得真正的好處:
- I’m using objects in the definitions of other object’s parameters. If I misspell their name, I don’t get a runtime failure but an immediate error message from the editor. 我在其他對象的參數定義中使用對象。 如果我拼錯了他們的名字,我不會遇到運行時失敗,而是會收到來自編輯器的立即錯誤消息。
- If I don’t know which options I need to provide, I can go to the type definition and look it up (or use IntelliSense). 如果我不知道需要提供哪些選項,則可以轉到類型定義并進行查找(或使用IntelliSense)。
- If I forget to specify a mandatory option, I get a clear error. 如果忘記指定強制性選項,則會收到明確的錯誤消息。
- If the type of the input parameter doesn’t match the type of the object I’m passing, I get an error again. 如果輸入參數的類型與我傳遞的對象的類型不匹配,則會再次出現錯誤。
I can use language features like JSON.stringify right inside my program. In fact, I can reference and use any NPM module.
我可以在程序內部使用JSON.stringify類的語言功能。 實際上,我可以引用和使用任何NPM模塊。
You can see the code for API Gateway here. It looks too verbose, doesn’t it? Moreover, I’m only half-way through with only one Lambda function defined.
您可以在此處查看API Gateway的代碼。 它看起來太冗長了,不是嗎? 而且,我只定義了一個Lambda函數而已完成一半。
可重復使用的組件 (Reusable Components)
We can do better than that. Here is the improved definition of the same Lambda function:
我們可以做得更好。 這是相同Lambda函數的改進定義:
import { Lambda } from "./lambda";const func = new Lambda("lambda-get", {path: "./app",file: "read",environment: { "COUNTER_TABLE": counterTable.name}, });Now, isn’t that beautiful? Only the essential options remained, while all the machinery is gone. Well, it’s not completely gone, it’s been hidden behind an abstraction.
現在,那不漂亮嗎? 只剩下基本的選擇,而所有的機器都消失了。 嗯,它還沒有完全消失,它已經被隱藏在一個抽象背后。
I defined a custom component called Lambda:
我定義了一個名為Lambda的自定義組件 :
export interface LambdaOptions {readonly path: string;readonly file: string;readonly environment?: pulumi.Input<{[key: string]: pulumi.Input<string>;}>; }export class Lambda extends pulumi.ComponentResource {public readonly lambda: aws.lambda.Function;constructor(name: string,options: LambdaOptions,opts?: pulumi.ResourceOptions) {super("my:Lambda", name, opts);const role = //... Role as defined in the last snippetconst fullAccess = //... RolePolicyAttachment as defined in the last snippetthis.lambda = new aws.lambda.Function(`${name}-func`, {runtime: aws.lambda.NodeJS8d10Runtime,code: new pulumi.asset.AssetArchive({".": new pulumi.asset.FileArchive(options.path),}),timeout: 300,handler: `${options.file}.handler`,role: role.arn,environment: {variables: options.environment}}, { dependsOn: [fullAccess], parent: this });} }The interface LambdaOptions defines options that are important for my abstraction. The class Lambda derives from pulumi.ComponentResource and creates all the child resources in its constructor.
接口LambdaOptions定義了對我的抽象很重要的選項。 Lambda類從pulumi.ComponentResource派生,并在其構造函數中創建所有子資源。
A nice effect is that one can see the structure in pulumi preview:
一個不錯的效果是,可以在pulumi預覽中看到結構:
> pulumi up Previewing update (urlshortener):Type Name Plan + pulumi:pulumi:Stack urlshortener create + my:Lambda lambda-get create + aws:iam:Role lambda-get-role create + aws:iam:RolePolicyAttachment lambda-get-access create + aws:lambda:Function lambda-get-func create + aws:dynamodb:Table urls createThe Endpoint component simplifies the definition of API Gateway (see the source):
Endpoint組件簡化了API網關的定義(請參閱參考資料 ):
const api = new Endpoint("urlapi", {path: "/{proxy+}",lambda: func.lambda });The component hides the complexity from the clients — if the abstraction was selected correctly, that is. The component class can be reused in multiple places, in several projects, across teams, etc.
該組件向客戶端隱藏了復雜性-也就是說,如果正確選擇了抽象。 組件類可以在多個地方,多個項目中,跨團隊等中重用。
標準組件庫 (Standard Component Library)
In fact, the Pulumi team came up with lots of high-level components that build abstractions on top of raw resources. The components from the @pulumi/cloud-aws package are particularly useful for serverless applications.
實際上,Pulumi團隊提出了許多高級組件,它們在原始資源的基礎上構建了抽象。 @pulumi/cloud-aws軟件包中的組件對于無服務器應用程序特別有用。
Here is the full URL shortener application with DynamoDB table, Lambdas, API Gateway, and S3-based static files:
這是帶有DynamoDB表,Lambdas,API Gateway和基于S3的靜態文件的完整URL縮短器應用程序:
import * as aws from "@pulumi/cloud-aws";// Create a table `urls`, with `name` as primary key. let urlTable = new aws.Table("urls", "name");// Create a web server. let endpoint = new aws.API("urlshortener");// Serve all files in the www directory to the root. endpoint.static("/", "www");// GET /url/{name} redirects to the target URL based on a short-name. endpoint.get("/url/{name}", async (req, res) => {let name = req.params["name"];let value = await urlTable.get({name});let url = value && value.url;// If we found an entry, 301 redirect to it; else, 404.if (url) {res.setHeader("Location", url);res.status(301);res.end("");}else {res.status(404);res.end("");} });// POST /url registers a new URL with a given short-name. endpoint.post("/url", async (req, res) => {let url = req.query["url"];let name = req.query["name"];await urlTable.insert({ name, url });res.json({ shortenedURLName: name }); });export let endpointUrl = endpoint.publish().url;The coolest thing here is that the actual implementation code of AWS Lambdas is intertwined with the definition of resources. The code looks very similar to an Express application. AWS Lambdas are defined as TypeScript lambdas. All strongly typed and compile-time checked.
這里最酷的是,AWS Lambdas的實際實現代碼與資源的定義 交織在一起 。 該代碼看起來與Express應用程序非常相似。 AWS Lambda被定義為TypeScript lambda。 所有強類型和編譯時檢查。
It’s worth noting that at the moment such high-level components only exist in TypeScript. One could create their custom components in Python or Go, but there is no standard library available. Pulumi folks are actively trying to figure out a way to bridge this gap.
值得注意的是,目前此類高級組件僅存在于TypeScript中。 可以使用Python或Go創建其自定義組件,但沒有標準庫可用。 普魯米(Pulumi)鄉親正在積極嘗試尋找一種彌合這種差距的方法 。
避免供應商鎖定? (Avoiding Vendor Lock-in?)
If you look closely at the previous code block, you notice that only one line is AWS-specific: the import statement. The rest is just naming.
如果仔細查看前一個代碼塊,您會發現只有一行是特定于AWS的: import語句。 其余只是命名。
We can get rid of that one too: just change the import to import * as cloud from "@pulumi/cloud"; and replace aws. with cloud. everywhere. Now, we'd have to go to the stack configuration file and specify the cloud provider there:
我們也可以擺脫這種情況:只需將導入更改為import * as cloud from "@pulumi/cloud"; 并更換aws. 與cloud. 到處。 現在,我們必須轉到堆棧配置文件并在此處指定云提供商:
config: cloud:provider: awsWhich is enough to make the application work again!
這足以使應用程序再次運行!
Vendor lock-in seems to be a big concern among many people when it comes to cloud architectures heavily relying on managed cloud services, including serverless applications. While I don’t necessarily share those concerns and am not sure if generic abstractions are the right way to go, Pulumi Cloud library can be one direction for the exploration.
當涉及嚴重依賴托管云服務(包括無服務器應用程序)的云體系結構時,供應商鎖定似乎是許多人關注的大問題。 雖然我不一定會分享這些擔憂,并且不確定通用抽象是否是正確的方法,但Pulumi Cloud庫可以是探索的一個方向。
The following picture illustrates the choice of the level of abstraction that Pulumi provides:
下圖說明了Pulumi提供的抽象級別的選擇:
Working on top of the cloud provider’s API and internal resource provider, you can choose to work with raw components with maximum flexibility, or opt-in for higher-level abstractions. Mix-and-match in the same program is possible too.
您可以選擇在云提供商的API和內部資源提供商的基礎上使用具有最大靈活性的原始組件,也可以選擇加入更高級別的抽象。 同一程序中也可以進行混搭。
基礎架構即實代碼 (Infrastructure as Real Code)
Designing applications for the modern cloud means utilizing multiple cloud services which have to be configured to play nicely together. The Infrastructure as Code approach is almost a requirement to keep the management of such applications reliable in a team setting and over the extended period.
為現代云設計應用程序意味著必須利用多個云服務,這些服務必須配置為可以很好地協同工作。 幾乎需要一種“基礎結構即代碼”方法,以在團隊環境中和較長時間內保持此類應用程序的管理可靠。
Application code and supporting infrastructure become more and more blended, so it’s natural that software developers take the responsibility to define both. The next logical step is to use the same set of languages, tooling, and practices for both software and infrastructure.
應用程序代碼和支持基礎結構變得越來越融合,因此軟件開發人員自然有責任同時定義兩者。 下一步的邏輯步驟是對軟件和基礎架構使用相同的語言,工具和實踐集。
Pulumi exposes cloud resources as APIs in several popular general-purpose programming languages. Developers can directly transfer their skills and experience to define, build, compose, and deploy modern cloud-native and serverless applications more efficiently than ever.
Pulumi以幾種流行的通用編程語言將云資源作為API公開。 開發人員可以直接轉移他們的技能和經驗,從而比以往更有效地定義,構建,組成和部署現代的云原生和無服務器應用程序。
Originally published at mikhail.io.
最初發表于mikhail.io 。
翻譯自: https://www.freecodecamp.org/news/from-yaml-to-typescript-a-developers-view-on-cloud-automation/
自動化yaml文件
總結
以上是生活随笔為你收集整理的自动化yaml文件_从YAML到TypeScript:开发人员对云自动化的看法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到困到电梯里怎么回事
- 下一篇: 做梦梦到被猫抓伤是什么意思