# 云原生編程語言Pulumi
2018年6月18日 Joe Duffy在[他的博客](http://joeduffyblog.com/2018/06/18/hello-pulumi/)中宣布開源了云原生編程語言[Pulumi](https://pulumi.io)。這是繼[Ballerina](https://ballerina.io)之后我看到的另一款云原生編程語言,他們之間有一些共同的特點,例如都是為了支持多種云環境,基于不可變基礎設施和基礎設施即代碼的理念構建,使云原生應用的集成更加方便,但也有一些不同,Ballerina是直接創建了一個基于JVM的語言,而Pulumi是為不同編程語言構建了SDK。
下文部分來自Joe Duffy的博客[Hello, Pulumi](http://joeduffyblog.com/2018/06/18/hello-pulumi/)!

TL;DR 有了Pulumi,38頁的手動操作說明將變成了38行代碼。25000行YAML配置變成了使用真實編程語言的500行語句。
Pulumi的整個運行時、CLI、支持的庫都可以在GitHub上免費下載。我們的團隊正急切的等待您的反饋。與此同時,我需要告訴您一些關于Pulumi的事情,為什么我們會創造它。
## Pulumi是什么?
Pulumi是一個支持多語言和混合云開發平臺。它可以讓您使用真實語言和真實代碼創建云計算的各個方面,從基礎設施到應用程序本身。只需編寫程序并運行它們,Pulumi就能幫你完成出其余部分。
Pulumi的中心是一個云對象模型,與運行時相結合以了解如何以任何語言編寫程序,理解執行它們所需的云資源,然后以強大的方式規劃和管理您的云資源。這種云運行時和對象模型本質上是與語言、云中立的,這就是為什么我們能夠支持如此多的語言和云平臺。更多支持正在路上。
Pulumi采用了基礎設施即代碼以及不可變基礎設施的概念,并可讓您從您最喜歡的語言(而不是YAML或DSL)中獲得自動化和可重復性優勢。在部署它們之前,您可以對變更進行區分,并且我們會對誰更改了什么以及何時更改進行完善的審計追蹤。核心模型因此是陳述性的。
使用真正的語言可以帶來巨大的好處:
- **熟悉**:不需要學習新的定制DSL或基于YAML的模板語言
- **抽象**:正如我們喜愛的編程語言那樣,我們可以用更小的東西來構建更大的東西
- **共享和重用**:利用現有的語言包管理器共享和重用這些抽象,無論是與社區、團隊內部共享
- **表現力**:充分利用您的編程語言,包括異步、循環和條件
- **工具**:通過使用真正的語言,我們可以即時訪問IDE、重構、測試、靜態分析和編排等等
- **生產力**:將以上所有好處加在一起,一起將變得更快,我們也會變得更快樂
當提供原始云資源時,這些好處當然最重要,但是我們在團隊中發現,您只能使用抽象。這包括在函數中包裝事物以消除樣板并創建引入更高級別概念的自定義類,通常將它們打包并重復使用。
例如,此代碼在AWS中創建一個DynamoDB數據庫:
```python
import * as aws from "@pulumi/aws";
let music = new aws.dynamodb.Table("music", {
attributes: [
{ name: "Album", type: "S" },
{ name: "Artist", type: "S" },
],
hashKey: "Album",
rangeKey: "Artist",
});
```
此代碼創建一個基于容器的任務和無服務器功能,由一個存儲桶觸發:
```python
import * as cloud from "@pulumi/cloud";
let bucket = new cloud.Bucket("bucket");
let task = new cloud.Task("ffmpegThumbTask", {
build: "./path_to_dockerfile/",
});
bucket.onPut("onNewVideo", bucketArgs => {
let file = bucketArgs.key;
return task.run({
environment: {
"S3_BUCKET": bucket.id.get(),
"INPUT_VIDEO": file,
"TIME_OFFSET": file.substring(file.indexOf('_')+1, file.indexOf('.')).replace('-',':'),
"OUTPUT_FILE": file.substring(0, file.indexOf('_')) + '.jpg',
},
});
});
```
更好的是,這些代碼可以根據您的需求部署到任何公共或私有云中。
最后,這個例子創建了一個Redis緩存。我們怎么知道?我們不需要。緩存組件是一個抽象,它封裝了我們可以安全忽略的不重要的細節:
```python
import {Cache} from "./cache";
let cache = new Cache("url-cache");
```
在使用Pulumi之后,你不會再以同樣的方式考慮基礎設施。你的大腦將不再是一個獨立于應用程序的獨特“事物”,而是開始將分布式云系統看作是你的程序架構的核心部分,而不是事后的想法。
由于抽象,我們已經能夠提供一些強大的庫。該庫是提煉和執行最佳實踐的絕佳方式。當然,對于我們自己的庫來說沒有什么特別的,因為它們只是功能、類和代碼,我們期待著看到你為自己、你的團隊或者社區建立的那些庫。
我們最復雜的庫——Pulumi云框架——提供了一些令人興奮的正在進行的工作的早期預覽,展示如何創建跨越云提供商自己對諸如容器、無服務器功能和存儲桶等核心概念的抽象。以同樣的方式,您可以用Node.js、Python、Java、.NET等語言編寫功能強大的應用程序,利用進程、線程和文件系統,無論是在macOS、Linux還是Windows上,這種方法都可以讓您創建針對任何云提供商的現代混合云應用程序。像Kubernetes和其他CNCF產品組合這樣的技術正在幫助推動這一不可避免的結果,因為它們在整個云基板上實現了對基本計算抽象的民主化和共識。
Pulumi不是PaaS,盡管它提供類似PaaS的生產力;您的程序總是直接針對您選擇的云運行,并且始終可以訪問該基礎云的全部功能。即使您選擇使用更高級別的組件,它也會向下兼容,并且您可以隨時直接使用原始資源。它就像任何復雜的現代軟件:有時,整個事情必須用C++編寫,以便訪問底層平臺的全部功能,但對于大多數常見情況,70%到100%可以是平臺獨立代碼,而只有不到30%的專業化才能真正需要直接與操作系統交互。
接下來我還將發布十幾篇博客文章來介紹Pulumi所有方面的更多細節。然而,為了保持這篇文章盡量簡短,我將首先介紹下Pulumi的一些我最喜歡的方面。
## 我最喜歡的東西
這很難選擇,但這里有一些關于Pulumi我最喜歡的東西:
**開源**。我堅信所有開發人員工具都應該是開源的。當然,Pulumi也是一家公司,但是有充足的機會通過增加便利性以建立商業模式。(可以認為是??Git與GitHub的關系)我們從以前的工作中受益匪淺,其中包括Docker、Terraform、Kubernetes、TypeScript以及其他許多明確提及的工作。我們期待成為生態系統的一部分。因為我們在開放源代碼方面下了很大功夫,所以我很高興看到社區給我們帶來什么,特別是在更高級別的軟件包領域。
**多語言**。就像使用Java和.NET一樣,Pulumi運行時的架構可以支持多種語言,并以目標語言的所有方面(風格、語法、軟件包等)的慣用方式來實現。因為我們是開源的,任何人都可以貢獻自己的力量。
**混合云**。我們的云對象模型是一個強大的基礎,可以支持任何云提供商。這提供了一個統一的編程模型,工具和控制平面,用于在任何地方管理云軟件。如果僅僅是為了讓一個簡單的基于容器的應用程序在生產中運行起來,沒有必要學習三種不同的YAML方言和五種不同的CLI。
**云對象模型**。這個底層云對象模型為您的云計算構建方式提供了豐富的視圖。所得到的對象使用程序中的依賴關系組成一個DAG,系統可以分析和理解這些依賴關系以提供洞察力,這是我們打算隨著時間的推移解鎖復雜的靜態分析和可視化的功能。
**可重復使用的組件**。由于擁有真正的語言,我們可以構建更高層次的抽象。我最喜歡的例子之一是幫助我們的客戶定期從部署中排除1000行YAML,這是我們的AWS基礎架構軟件包。它采用AWS最佳實踐來設置虛擬私有云,并提供專用子網和多可用區域支持,并將其轉變為幾行代碼以配置整個網絡:
```python
import * as awsinfra from "@pulumi/aws-infra";
let network = new awsinfra.Network(`${prefix}-net`, {
numberOfAvailabilityZones: 3, // Create subnets in many AZs
usePrivateSubnets: true, // Run inside private per-AZ subnets
});
```
迄今為止,我最喜歡的成功案例是將客戶的25,000行AWS CloudFormation YAML文件(其中使用無服務器、容器、基礎設施和三個自定義部署管道)使用500行TypeScript和一個Pulumi的持續部署架構來替換。這不僅僅使得公司所有工程師都可以理解的代碼變得少得多,這樣他們可以將過去需要花費數周時間才能完成的事情現在用一個下午就可以搞定,而且現在可以在任何云或原生的Kubernetes上運行,而不僅是在AWS。管理團隊的CloudFormation堆棧,而不是一個工作量過飽和的工程師,整個團隊可以更加高效。
**統一的容器構建/發布管道**。嘗試將容器投入生產時有個問題讓我早就感到很沮喪,就是同步我的應用程序、容器和基礎架構管理,因為每個容器都傾向于使用不同的工具。我們的云框架演示了一個集成的工作流程,在這個工作流程中,只需簡單地運行Pulumi構建、diff、推送和拉取新的容器鏡像,所有這些都經過精心安排,以消除停機時間。
**Lambda無服務器功能 **。 AWS的取了個好名字:Lambda。在Pulumi中,我現在可以用我最喜歡的語言使用lambda表達式來編寫我的無服務器函數,而不需要一行YAML:
```python
import * as aws from "@pulumi/aws";
import * as serverless from "@pulumi/aws-serverless";
let topic = new aws.sns.Topic("topic");
serverless.cloudwatch.onEvent("hourly", "rate(60 minutes)", event => {
const sns = new (await import "aws-sdk").SNS();
return sns.publish({
Message: JSON.stringify({ event: event }),
TopicArn: topic.id.get(),
}).promise();
});
```
此功能允許您捕獲對變量的引用:常量、配置設置或加密,甚至可以引用其他資源,以便與它們進行通信。當你第一次這樣做的時候,我保證你會有一個“哇塞”的時刻,將無服務器連接到你寫過的每一個事件驅動的代碼片段。
**使用API的資源**。因為我可以捕獲對其他云資源的引用,所以我可以在其上創建API以使它們更易于在我的運行時代碼中使用。這使得“演員般的”編程模型無需處理配置和服務發現。
**堆棧**。 Pulumi的核心是“堆棧”的概念。堆棧是您的云計算的獨立實例,其資源和配置與所有其他堆棧不同。您可能有一堆用于生產、暫存和測試的堆棧,或者可能是每個單一租戶的環境。Pulumi的CLI使得啟動和卸載大量堆棧變得輕而易舉。這會打開以前可能沒有嘗試過的工作流,例如每個開發人員都擁有自己的堆棧,將新堆疊起來(并拆除)以測試每個Pull請求,甚至將服務的層拆分成多個鏈接在一起的堆棧。
我將在未來的博客文章介紹如何做。現在Pulumi已經公開,期望在接下來的幾天和幾周內聽到更多的消息。我希望這能讓您更好地了解整體平臺,其方法和獨特優勢。
## 下一步是什么?
我們希望通過Pulumi,開發人員和DevOps團隊都將體驗到云的復興。構建強大的云軟件將更加愉快、更高效、更具協作性。現代云計算軟件將從代碼孤島轉變為等量的配置膠水,成為優雅的分布式系統。
這是一個難題。我絕不會說我們已經解決了它。我確實相信Pulumi是我親身見過并希望最接近我心目中的云開發平臺。在這個激動人心的時刻,投注于語言將使我們所有人“站在巨人的肩膀上”,這讓我感到樂觀;語言總是一個安全的賭注。
今天很可能是我職業生涯中最激動人心的一天。我想感謝我們的團隊和所有幫助過我們的人,放縱我們的瘋狂想法并相信我們。
現在訪問[https://pulumi.io](https://pulumi.io/),或者直接運行:
```bash
$ curl -fsSL https://get.pulumi.com | sh
```
我迫不及待想看看你將使用Pulumi構建的所有令人難以置信的東西。
## 參考
- [Pulumi](https://pulumi.io)
- [Hello, Pulumi!](http://joeduffyblog.com/2018/06/18/hello-pulumi/)
- 序言
- 云原生
- 云原生(Cloud Native)的定義
- CNCF - 云原生計算基金會簡介
- CNCF章程
- 云原生的設計哲學
- Play with Kubernetes
- 快速部署一個云原生本地實驗環境
- Kubernetes與云原生應用概覽
- 云原生應用之路——從Kubernetes到Cloud Native
- 云原生編程語言
- 云原生編程語言Ballerina
- 云原生編程語言Pulumi
- 云原生的未來
- Kubernetes架構
- 設計理念
- Etcd解析
- 開放接口
- CRI - Container Runtime Interface(容器運行時接口)
- CNI - Container Network Interface(容器網絡接口)
- CSI - Container Storage Interface(容器存儲接口)
- Kubernetes中的網絡
- Kubernetes中的網絡解析——以flannel為例
- Kubernetes中的網絡解析——以calico為例
- 具備API感知的網絡和安全性管理開源軟件Cilium
- Cilium架構設計與概念解析
- 資源對象與基本概念解析
- Pod狀態與生命周期管理
- Pod概覽
- Pod解析
- Init容器
- Pause容器
- Pod安全策略
- Pod的生命周期
- Pod Hook
- Pod Preset
- Pod中斷與PDB(Pod中斷預算)
- 集群資源管理
- Node
- Namespace
- Label
- Annotation
- Taint和Toleration(污點和容忍)
- 垃圾收集
- 控制器
- Deployment
- StatefulSet
- DaemonSet
- ReplicationController和ReplicaSet
- Job
- CronJob
- Horizontal Pod Autoscaling
- 自定義指標HPA
- 準入控制器(Admission Controller)
- 服務發現
- Service
- Ingress
- Traefik Ingress Controller
- 身份與權限控制
- ServiceAccount
- RBAC——基于角色的訪問控制
- NetworkPolicy
- 存儲
- Secret
- ConfigMap
- ConfigMap的熱更新
- Volume
- Persistent Volume(持久化卷)
- Storage Class
- 本地持久化存儲
- 集群擴展
- 使用自定義資源擴展API
- 使用CRD擴展Kubernetes API
- Aggregated API Server
- APIService
- Service Catalog
- 資源調度
- QoS(服務質量等級)
- 用戶指南
- 資源對象配置
- 配置Pod的liveness和readiness探針
- 配置Pod的Service Account
- Secret配置
- 管理namespace中的資源配額
- 命令使用
- Docker用戶過度到kubectl命令行指南
- kubectl命令概覽
- kubectl命令技巧大全
- 使用etcdctl訪問kubernetes數據
- 集群安全性管理
- 管理集群中的TLS
- kubelet的認證授權
- TLS bootstrap
- 創建用戶認證授權的kubeconfig文件
- IP偽裝代理
- 使用kubeconfig或token進行用戶身份認證
- Kubernetes中的用戶與身份認證授權
- Kubernetes集群安全性配置最佳實踐
- 訪問Kubernetes集群
- 訪問集群
- 使用kubeconfig文件配置跨集群認證
- 通過端口轉發訪問集群中的應用程序
- 使用service訪問群集中的應用程序
- 從外部訪問Kubernetes中的Pod
- Cabin - Kubernetes手機客戶端
- Kubernetic - Kubernetes桌面客戶端
- Kubernator - 更底層的Kubernetes UI
- 在Kubernetes中開發部署應用
- 適用于kubernetes的應用開發部署流程
- 遷移傳統應用到Kubernetes中——以Hadoop YARN為例
- 最佳實踐概覽
- 在CentOS上部署Kubernetes集群
- 創建TLS證書和秘鑰
- 創建kubeconfig文件
- 創建高可用etcd集群
- 安裝kubectl命令行工具
- 部署master節點
- 安裝flannel網絡插件
- 部署node節點
- 安裝kubedns插件
- 安裝dashboard插件
- 安裝heapster插件
- 安裝EFK插件
- 生產級的Kubernetes簡化管理工具kubeadm
- 使用kubeadm在Ubuntu Server 16.04上快速構建測試集群
- 服務發現與負載均衡
- 安裝Traefik ingress
- 分布式負載測試
- 網絡和集群性能測試
- 邊緣節點配置
- 安裝Nginx ingress
- 安裝配置DNS
- 安裝配置Kube-dns
- 安裝配置CoreDNS
- 運維管理
- Master節點高可用
- 服務滾動升級
- 應用日志收集
- 配置最佳實踐
- 集群及應用監控
- 數據持久化問題
- 管理容器的計算資源
- 集群聯邦
- 存儲管理
- GlusterFS
- 使用GlusterFS做持久化存儲
- 使用Heketi作為Kubernetes的持久存儲GlusterFS的external provisioner
- 在OpenShift中使用GlusterFS做持久化存儲
- GlusterD-2.0
- Ceph
- 用Helm托管安裝Ceph集群并提供后端存儲
- 使用Ceph做持久化存儲
- 使用rbd-provisioner提供rbd持久化存儲
- OpenEBS
- 使用OpenEBS做持久化存儲
- Rook
- NFS
- 利用NFS動態提供Kubernetes后端存儲卷
- 集群與應用監控
- Heapster
- 使用Heapster獲取集群和對象的metric數據
- Prometheus
- 使用Prometheus監控kubernetes集群
- Prometheus查詢語言PromQL使用說明
- 使用Vistio監控Istio服務網格中的流量
- 分布式跟蹤
- OpenTracing
- 服務編排管理
- 使用Helm管理Kubernetes應用
- 構建私有Chart倉庫
- 持續集成與發布
- 使用Jenkins進行持續集成與發布
- 使用Drone進行持續集成與發布
- 更新與升級
- 手動升級Kubernetes集群
- 升級dashboard
- 領域應用概覽
- 微服務架構
- 微服務中的服務發現
- 使用Java構建微服務并發布到Kubernetes平臺
- Spring Boot快速開始指南
- Service Mesh 服務網格
- 企業級服務網格架構
- Service Mesh基礎
- Service Mesh技術對比
- 采納和演進
- 定制和集成
- 總結
- Istio
- 安裝并試用Istio service mesh
- 配置請求的路由規則
- 安裝和拓展Istio service mesh
- 集成虛擬機
- Istio中sidecar的注入規范及示例
- 如何參與Istio社區及注意事項
- Istio教程
- Istio免費學習資源匯總
- 深入理解Istio Service Mesh中的Envoy Sidecar注入與流量劫持
- 深入理解Istio Service Mesh中的Envoy Sidecar代理的路由轉發
- Linkerd
- Linkerd 使用指南
- Conduit
- Condiut概覽
- 安裝Conduit
- Envoy
- Envoy的架構與基本術語
- Envoy作為前端代理
- Envoy mesh教程
- SOFAMesh
- SOFAMesh中的Dubbo on x-protocol
- SOFAMosn
- 使用 SOFAMosn 構建 SOFAMesh
- 大數據
- Spark standalone on Kubernetes
- 運行支持Kubernetes原生調度的Spark程序
- Serverless架構
- 理解Serverless
- FaaS-函數即服務
- OpenFaaS快速入門指南
- 邊緣計算
- 人工智能