# 云原生编程语言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/)!
![云原生编程语言Pulumi](https://ws1.sinaimg.cn/large/00704eQkgy1fsm4v0a6qwj30xc0m8t9d.jpg)
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快速入门指南
- 边缘计算
- 人工智能