写点什么

Docker 和 Kubernetes 应用程序打包:Metaparticle、Pulumi 与 Ballerina 比较

  • 2018-08-06
  • 本文字数:11706 字

    阅读完需:约 38 分钟

本文要点

  • 随着微服务架构的出现,软件行业正向着云原生应用程序开发和部署发展。
  • Docker 和 Kubernetes 是现代化云原生部署自动化的关键要素。
  • 目前常见的做法是借助容器创建可复制的应用程序包,但是,这涉及手工编写(和维护)YAML 部署描述文件。
  • Metaparticle、Ballerina 和 Pulumi 是三个开源项目,分别提供了自己的方法,解决 Docker 和 Kubernetes 应用程序部署中的应用打包问题。
  • 本文探讨了使用每种框架部署一个简单的“HelloWorld”应用所需要的步骤。

随着微服务架构的出现,软件行业正向着云原生应用程序开发和部署发展。双披萨团队、敏捷性、再现性、CI/CD 在当前生产力快速创新的软件行业中扮演越来越重要的角色。

Docker Kubernetes 是现代化云原生部署自动化的关键要素。常见的做法是借助容器把开发出的应用程序创建成可复制的应用程序包。Docker 使开发人员能够创建可重复的运行时环境,并在其中使用一个简单、可重复的方式定义依赖和配置应用程序。Kubernetes 是一个开源容器编排平台,使这些应用程序容器可以跨多个主机部署,并且提供了可扩展性和高可用性。这需要编写 Dockerfile 和 Kubernetes YAML 部署描述文件,这很痛苦,而且容易出错。

Metaparticle Ballerina Pulumi 是三个开源项目,分别提供了自己解决这个问题的方法。最近,我发现了三个讨论这些方法的推特。

第一个是 Andress Guisado介绍 Metaparticle 如何提供一个标准库用于创建可直接部署到 Kubernetes 的云原生应用程序。Brendan Burns 在年初的 KubeCon 大会上宣布了 Metapaticle,Andress 那时就认为这将是 2018 年的一大焦点。

在 Istio 社区聚会上接触到 Ballerina 之后,Dan Ciruli 就发推特说,Ballerina 是一门有趣的语言,因为它可以自动生成Kubernetes 和Istio YAML,作为构建过程的一部分。他进一步表示,这是一个很棒的主意,他认为其他框架也将采用这种方式。

第三个是 Ustun Ozgur 在推特上说,与繁琐的YAML 文件相比,Pulumi 把基础设施定义成代码所做的工作对于DevOps 而言就像React 针对Web 开发所做的工作。

在本文中,我将比较这三个项目如何帮助你在像 Kubernetes 这样的容器编排平台中自动化应用程序代码部署,而不必手工编写 YAML。下文将详细介绍这些方法。

Metaparticle

Metaparticle/Package 简化了构建和部署容器镜像的任务。这一个库集合使程序员可以使用他们熟悉的代码构建和部署容器。目前,它支持 Java、.NET core、Javascript(NodeJS)、Go、Python 和 Ruby 编程语言。

让我们看下如何使用 Metaparticle 把 Java 代码部署到 Kubernetes 中。

前提条件:

  1. Docker/ Kubernetes
  2. 命令行工具 mp-compiler
  3. maven 依赖 io.metaparticle:metaparticle-package

下面的代码启动一个 Kubernetes pod,其中包含一个打印“Hello World!”的 HTTP 服务: 

复制代码
package io.metaparticle.tutorial;
import io.metaparticle.annotations.Package;
import io.metaparticle.annotations.Runtime;
import static io.metaparticle.Metaparticle.Containerize;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class Main {
private static final int port = 8080;
@Runtime(ports = {port},
replicas = 4,
publicAddress = true,
executor = "metaparticle"
)
@Package(repository = "docker.io/lakwarus",
jarFile = "target/metaparticle-package-tutorial-0.1-SNAPSHOT-jar-with-dependencies.jar", publish = true)
public static void main(String[] args) {
Containerize(() -> {
try {
HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
server.createContext("/", new HttpHandler() {
@Override
public void handle(HttpExchange t) throws IOException {
String msg = "Hello World!";
t.sendResponseHeaders(200, msg.length());
OutputStream os = t.getResponseBody();
os.write(msg.getBytes());
os.close();
System.out.println("[" + t.getRequestURI() + "]");
}
});
server.start();
} catch (IOException ex) {
ex.printStackTrace();
}
});
}
}
{1}

有几点需要注意:

  • 引入 io.metaparticle.annotations.Package 和 io.metaparticle.annotations.Runtime;
  • @Package 注解描述如何打包应用程序;
  • @Runtime 注解描述应用程序的运行时配置;
  • 把 main 函数封装在 Containerize 函数中,后者会启动 Metaparticle 代码。

编译代码:

复制代码
mvn compile

这会创建一个包含所有依赖的 jar 文件。

运行代码:

复制代码
mvn exec:java -Dexec.mainClass=io.metaparticle.tutorial.Main

这会生成 Dockerfile 和 Docker 镜像,并把它推送到特定的注册中心。然后,它会在配置好的 Kubernetes 集群中使用 4 个 pod 启动一个 Kubernetes 部署。

访问服务:

你需要创建一个代理来访问服务。

复制代码
$ kubectl port-forward deployment/io-metaparticle-tutorial-main 8080:8080
$ curl http://localhost:8080/
Hello World!

要点:

  • 不会创建 YAML/JSON;
  • 完全自动部署;
  • 支持多种语言;
  • 支持有限的 Kubernetes 服务和部署功能,仅支持 clusterIP 服务;
  • 需要把用户代码封装在 Containerize() 块中,然后,你的代码不能以独立模式运行。

Ballerina

Ballerina 是一门新开源的云原生编程语言,设计用来把代码优先的敏捷性引入应对跨端点集成的挑战中。Ballerina 为 API、分布事务、断路器、流处理、数据访问、JSON、XML、gRPC 及许多其他集成挑战提供了一流的支持。

Ballerina 可以推断周围的架构;编译器可以感知环境,自动生成 Docker 镜像和 YAML,把微服务直接部署到像 Docker 和 Kubernetes 这样的基础设施中。

让我们看下如何使用 Ballerina Kubernetes 注解把代码部署到 Kubernetes。

前提条件:

  1. Ballerina
  2. Docker/Kubernetes

下面的代码启动一个打印“Hello World!”的 HTTP 服务:

复制代码
import ballerina/http;
import ballerinax/kubernetes;
@kubernetes:Service {
serviceType: "NodePort",
name: "hello-world"
}
endpoint http:Listener listener {
port: 9090
};
@kubernetes:Deployment {
image: "lakwarus/helloworld",
name: "hello-world"
}
@http:ServiceConfig {
basePath:"/"
}
service<http:Service> helloWorld bind listener {
@http:ResourceConfig {
path: "/"
}
sayHello(endpoint outboundEP, http:Request request) {
http:Response response = new;
response.setTextPayload("Hello World! \n");
_ = outboundEP->respond(response);
}
}

有几点需要注意:

  • 引入 ballerinax/kubernetes 包
  • @kubernetes:以 Ballerina 服务为基础的服务

编译代码:

编译hello_world_k8s.bal文件。编译成功后会打印运行 Kubernetes 工件的命令:

复制代码
$> ballerina build hello_world_k8s.bal
@kubernetes:Docker          - complete 3/3
@kubernetes:Deployment      - complete 1/1
@kubernetes:Service         - complete 1/1
运行下面的命令部署 Kubernetes 工件: 
kubectl apply -f ./kubernetes/

Ballerina 编译器将生成 hello_containers_k8s.balx、Dockerfile、Docker 镜像和 Kubernetes 工件,结构如下:

复制代码
$> tree
.
├── hello_world_k8s.bal
├── hello_world_k8s.balx
└── kubernetes
    ├── docker
    │   └── Dockerfile
    ├── hello_world_k8s_svc.yaml
    └── hello_world_k8s_deployment.yaml

运行代码kubectl apply -f ./kubernetes/把应用部署到 Kubernetes,并可以通过 Kubernetes NodePort 访问。

访问服务:

复制代码
$> kubectl get svc
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-world           NodePort    10.96.118.214    <none>        9090:32045/TCP   1m
$> curl http://localhost:<32045>/
Hello, World!

要点:

  • Ballerina 提供 Kubernetes 原生支持;
  • 应该使用 Ballerina 编写代码;
  • 基于代码中定义的注解生成部署工件;
  • 部署不是完全自动的,需要运行 kubectl 命令;
  • 支持许多 Kubernetes 功能,如所有类型的 Kubernetes 服务、部署、Ingress、Secret、持久卷、ConfigMap、活性探针和横向 pod 自动扩展;
  • 不需要修改或封装用户代码;Ballerina 代码使用注解修饰对象;Ballerina 编译器把注解解析成可读可处理的 AST。

Pulumi

Pulumi 是一个云开发平台,使创建云程序变得简单高效。你可以使用自己最喜欢的语言编写云程序,Pulumi 将自动保持基础设施最新:“跳过 YAML,只要编写代码”。Pulumi 支持多语言、多云,其引擎和包生态都可以扩展。

目前,它支持 JavaScript、TypeScript、Python 和 Go 编程语言。支持的云平台包括 Amazon Web Services、 Microsoft Azure、谷歌云平台和 Kubernetes。

Pulumi 主要是针对基础设施代码自动化,而不是应用程序代码自动化。你可以使用你喜欢的编程语言,自动化基础设施部署。

Pulumi 对公共无服务器提供商如 AWS Lambda 的 FaaS 部署提供开箱即用的支持,但是在本文中,我将重点介绍在 Docker 和 Kubernetes 上的自动化部署。

前提条件:

  1. Docker/Kubernetes
  2. 安装 Pulumi(curl -fsSL https://get.pulumi.com/ | sh)
  3. 配置Pulumi 和Kubernetes 集群

让我们看下如何使用 TypeScript 和 Pulumi 部署一个“helloworld”示例应用程序。

我已经创建了一个“helloworld”示例应用程序(对 HTTP 请求打印“Hello World”)以及相应的 Docker 镜像(lakwarus/helloworld:latest)。现在,我将使用 TypeScript 以及 Pulumi 库编写简单的代码,把我的应用部署到 Kubernetes,而不必手工编写 YAML 工件。

创建 Pulumi 项目:

复制代码
$> pulumi new
Please choose a template: typescript
This command will walk you through creating a new Pulumi project.
Enter a value or leave blank to accept the default, and press <ENTER>.
Press ^C at any time to quit.
project name: (hello)
project description: hello world
Created project 'hello'.
stack name: (hello-dev)
Created stack 'hello-dev'.
Installing dependencies...
added 113 packages in 12.549s
Finished installing dependencies.
New project is configured and ready to deploy with 'pulumi update'.

使用下面的依赖项更新 package.json:

复制代码
{
"name": "hello",
"main": "bin/index.js",
"typings": "bin/index.d.ts",
"scripts": {
"build": "tsc"
},
"devDependencies": {
"typescript": "^2.7.2",
"@types/node": "latest"
},
"dependencies": {
"@pulumi/kubernetes": "^0.14.0",
"@pulumi/pulumi": "^0.14.0",
"npm": "^6.1.0"
}
}

在 index.ts 文件中编辑应用程序和部署信息。这里,我只添加 pod 配置,不过,你可以把它扩展到其他 Kubernetes 功能。

复制代码
import * as pulumi from "@pulumi/pulumi";
import * as k8s from "@pulumi/kubernetes";
let helloPod = new k8s.core.v1.Pod("hello", {
metadata: {
name: "hello",
},
spec: {
containers: [{
name: "hello",
image: "lakwarus/helloworld",
ports: [{
containerPort: 9090,
}],
}],
},
});

编译并运行代码:

复制代码
$> npm update
$> npm run build
$> pulumi update
Previewing update of stack 'hello-dev'
Previewing changes:
Type Name Plan Info
+ pulumi:pulumi:Stack hello-hello-dev create
+ └─ kubernetes:core:Pod hello create
info: 2 changes previewed:
+ 2 resources to create
Do you want to perform this update? yes
Updating stack 'hello-dev'
Performing changes:
Type Name Status Info
+ pulumi:pulumi:Stack hello-hello-dev created
+ └─ kubernetes:core:Pod hello created
info: 2 changes performed:
+ 2 resources created
Update duration: 10.132746709s

访问服务:

复制代码
$ kubectl port-forward pod/hello 9090:9090
$ curl http://localhost:9090/
Hello World!

要点:

  • 主要是针对基础设施代码自动化;
  • 可以使用喜欢的编程语言控制你的基础设施;
  • 应用程序代码应该在函数(如 AWS Lambda)中,或者需要在可以用于自动化部署的 Docker 镜像中;
  • 支持几乎所有的公有云提供商和 Kubernetes;
  • 仅用几行代码就可以创建复杂的部署,而不必手工编写 YAML;
  • 完全自动;
  • 潜在的供应商锁定,因为你需要有一个 http://pulumi.io 账户。

小结

随着微服务架构的出现,软件行业正向着云原生应用程序开发和部署发展。Docker 和 Kubernetes 是现代化云原生部署自动化的关键要素。不过,目前需要人工创建 YAML 部署描述文件,这个过程很繁琐,而且容易出错。

在 Kubernetes 部署应用程序的其中一种流行方式是采用不同的工具和框架。 Draft Gitkube Helm Ksonnet Skaffold 都是在这方面处于领先地位的流行工具,有一篇非常有趣的文章“ Draft、Gitkube、Helm、Ksonnet、Metaparticle 和 Skaffold 对比”,比较了这些帮助开发人员在 Kubernetes 上构建和部署应用的工具。虽然所有这些工具的工作流程都不一样,但它们解决的是同一个问题,即提高在 Kubernetes 上部署应用程序的敏捷性和效率。

Metaparticle、Ballerina 和 Pulumi 提供了不同的方法,供开发人员借助编程语言本身处理部署自动化,而不必手写 YAML。这正在成为一种趋势,将改变软件行业中的 DevOps 实践。

关于作者

Lakmal Warusawithana 是世界最大开源集成供应商 WSO2 的高级主管兼架构师。Lakmal 长期从事与开源、云、DevOps 技术相关的工作,是 Apache Stratos PaaS 项目的副总裁。2015 年,Lakmal 与人合伙创建了 thinkCube,成为开发更适合电信运营商的下一代协作式云计算产品的先驱。他负责整体的工程流程,特别关注 thinkCube 解决方案的扩展性和服务交付。在与人联合创建 thinkCube 之前,Lakmal 在 ITABS 工作了四年,该公司致力于基于 Linux 的服务器部署,提供了一个简单易用的自定义服务管理接口。Lakmal 还在各种会议上发表演讲,包括 ApacheCon、 CloudOpen、QCon、JaxLondon、Cloud Expo、Cloudstack 协作大会、WSO2Con 及许多技术聚会。Lakmal 拥有斯里兰卡科伦坡大学计算机科学理学士(荣誉)学位。

查看英文原文: Packaging Applications for Docker and Kubernetes: Metaparticle vs Pulumi vs Ballerina

2018-08-06 18:032367
用户头像

发布了 1008 篇内容, 共 419.7 次阅读, 收获喜欢 346 次。

关注

评论 1 条评论

发布
暂无评论
发现更多内容

react源码分析:组件的创建和更新

flyzz177

React

react源码中的fiber架构

flyzz177

React

数据驱动型企业如何借助「新一代智能协作」提升研发效能?

LigaAI

人工智能 数据驱动 亚马逊云科技 企业号十月PK榜

实现etcd服务注册与发现

六月的

Docker-compose go-zero

React组件之间的通信方式总结(上)

beifeng1996

React

Linux下RTC驱动开发(硬件采用DS1302)

DS小龙哥

10月月更

掌握这个方法,让工作经验配得上工作时间!

博文视点Broadview

你知道Redis为什么要设计成单线程吗

芥末拌个饭吧

后端 redis 底层原理 10月月更

react源码中的协调与调度

flyzz177

React

【LeetCode】水果成篮Java题解

Albert

算法 LeetCode 10月月更

HashMap源码分析(一)

知识浅谈

hashmap 10月月更

部署 SAP UI5 应用到 SAP BTP 时遇到的 error retrieving MTA 错误消息

汪子熙

云原生 Cloud 云平台 SAP 10月月更

谈谈spark性能调优的方法

芥末拌个饭吧

spark 后端 10月月更

Redis是如何保证数据一致性的

芥末拌个饭吧

后端 redis 底层原理 10月月更

go-zero docker-compose 搭建课件服务(七):prometheus+grafana服务监控

六月的

Docker-compose go-zero

go-zero docker-compose 搭建课件服务(三):编写courseware api服务

六月的

Docker-compose go-zero

go-zero docker-compose 搭建课件服务(五):完善user服务

六月的

Docker-compose go-zero

CEF | CEF浏览器客户端功能扩展:实现下载列表功能

YOLO.

qt 10月月更 C++

Linux下驱动开发_块设备驱动开发(内存模拟存储)

DS小龙哥

10月月更

Java中的接口详解

共饮一杯无

Java 接口 10月月更

go-zero docker-compose 搭建课件服务(一):编写服务api和proto

六月的

Docker-compose go-zero

go-zero docker-compose搭建课件服务(四):生成Dockerfile

六月的

Docker-compose go-zero

CEF | CEF浏览器客户端功能扩展:实现前进、后退、刷新、调用控制台、设置cookie、网页自适应窗体大小

YOLO.

qt 10月月更 C++

Linux下驱动开发_块设备驱动开发(硬件上采用SD卡+SPI协议)

DS小龙哥

10月月更

Lerna最佳实践(内含大量代码)

鲸品堂

代码 lerna

OKR之剑·理念篇03:OKR理念认同

vivo互联网技术

团队管理 OKR 目标管理

go-zero docker-compose 搭建课件服务(二):编写courseware rpc服务

六月的

Docker-compose go-zero

react源码分析:babel如何解析jsx

flyzz177

React

无法吃午餐的学生数量

掘金安东尼

算法 10月月更

Linux下IIC驱动编写,介绍IIC子系统框架的使用

DS小龙哥

10月月更

一种基于柔性事务的分布式事务解决方案设计探究

京东科技开发者

分布式事务 事务 分布式架构 事务回滚 分布式处理

Docker和Kubernetes应用程序打包:Metaparticle、Pulumi与Ballerina比较_DevOps & 平台工程_Lakmal Warusawithana_InfoQ精选文章