网站首页 > 精选教程 正文
使用 Go 定义您的 Kubernetes 应用程序
基础设施即代码 (IaC) 是一种成熟的范例,是指以与应用程序代码相同的方式处理基础设施(网络、磁盘、存储、数据库、消息队列等)并应用包括源代码在内的一般软件工程实践的标准实践 控制版本控制、测试等。 例如,Terraform 和 AWS CloudFormation 是广泛采用的技术,它们使用配置文件/模板来表示基础设施组件。
Infrastructure-IS-Code - 一种不同的思考方式
想象一下,您有一个应用程序,该应用程序包含一个以 API 网关为前端的无服务器功能以及作为后端的 NoSQL 数据库。 与其以静态方式(使用 JSON、YAML 等)定义它,不如使用标准编程语言结构(如类、方法等)来表示这些组件。这是一个伪代码示例:
DBTable table = new DBTable("demo-table");
table.addPrimaryKey("email", Type.String);Function function = new Function("demo-func");
function.addEnvVars("TABLE_NAME", table.Name());APIGateway apigw = new APIGateway();
apigw.addFunctionIntegration(function);
注意(假设的)类 DBTable、Function 和 APIGateway 以及它们的使用方式。例如一个函数可以引用表对象并获得它的名称——所有这些都在程序运行时出现,并由底层框架/平台的实现细节处理。
但是您不必为生产基础设施编写伪代码!
…感谢现有的解决方案,例如 cdk8s、AWS CDK、Pulumi、CDK for Terraform (cdktf) 等。几乎所有这些解决方案都遵循类似的方法 - 编写代码来定义基础设施,然后将其转换为配置,例如Kubernetes 清单 (YAML)、AWS CloudFormation 模板、HCL 配置等,然后可以使用标准工具进行应用。
当我们谈到这个话题时,很难不提到 Go 编程语言及其在云服务和基础设施领域无处不在的存在。它结合了编译语言的安全性和解释语言(如 Python)的速度,拥有强大的标准库并编译为单个二进制文件。这些以及更多的品质导致了许多用 Go 编写的云原生软件(IaC、监控、可观察性等),例如 Prometheus、Terraform、Grafana、Jaeger 等。
“事实上,云原生计算基金会中超过 75% 的项目都是用 Go 编写的。”
将“Infra-Is-Code”口号应用于 Kubernetes
在多篇博文中,我将介绍 Go 开发人员如何使用 cdk8s(Kubernetes 的云开发工具包)项目来定义 Kubernetes 资源。它是一个开源框架(也是 CNCF 的一部分),提供高级抽象,可以组合成更大的 Kubernetes 应用程序。 cdk8s 没有采用 YAML 或其他配置/模板驱动的方法,而是支持多种编程语言,这意味着您可以使用熟悉的概念(例如类、方法等)来使用 Kubernetes 资源。最终,cdk8s 会生成您可以使用 kubectl 应用的 Kubernetes 清单- 照常营业!
在撰写本文时,cdk8s 支持 Go、Typescript、Python 和 Java
这篇博文将开始并提供对 cdk8s 的温和而实用的介绍。到最后,您将熟悉关键概念并了解如何使用 cdk8s Go API 定义 Kubernetes 应用程序、部署(使用 kubectl)和测试它。
在你开始之前…
确保您已安装 Go(v1.16 或更高版本)和 cdk8s CLI。此外,您需要有权访问 Kubernetes 集群。对于学习和实验,我建议使用本地运行的单节点集群——例如 minikube、kind 等。
我一般用minikube,所以搭建集群就像minikube start一样简单
安装 cdk8s CLI。
您可以从以下选项中进行选择:
#homebrew
brew install cdk8s#npm
npm install -g cdk8s-cli#yarn
yarn global add cdk8s-cli
好吧,让我们开始吧!
cdk8s 让您可以非常轻松地开始和引导您的应用程序。 您无需猜测和弄清楚如何构建项目、设置依赖项等,因为 cdk8s init 命令会为您完成!
cdk8s init go-app#output
.... Your cdk8s Go project is ready! cat help Prints this message
cdk8s synth Synthesize k8s manifests to dist/
cdk8s import Imports k8s API objects to "imports/k8s" Deploy:
kubectl apply -f dist/
完成后,您将获得如下目录结构:
.
├── cdk8s.yaml
├── dist
│ └── test.k8s.yaml
├── go.mod
├── go.sum
├── help
├── imports
│ └── k8s
│ ├── internal
│ │ └── types.go
│ ├── jsii
│ │ ├── jsii.go
│ │ └── k8s-0.0.0.tgz
│ ├── k8s.go
│ ├── k8s.init.go
│ └── version
└── main.go
更新生成 go.mod 文件,并将其替换为以下内容 - 这是为了让您更简单。
如果需要,请随意使用最新版本的模块。
module getting-started-with-cdk8s-gogo 1.16require (
github.com/aws/constructs-go/constructs/v10 v10.1.42
github.com/aws/jsii-runtime-go v1.60.1
github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.3.29
)
你们都准备好写一些 Go 代码了!
规范的 Kubernetes “hello world”是让 nginx 服务器启动并运行。 最简单的选择是简单地使用 kubectl run 例如 kubectl 运行 nginx --image=nginx。 但是,由于这是必须的,我们切换到声明式方式,在其中定义我们想要的状态(在 yaml 文件中)并要求 Kubernetes 解决问题。
例如 我们可以编写一个部署清单并使用 kubectl apply -f <name of the yaml file> 将其提交给 Kubernetes。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: hello-nginx
template:
metadata:
labels:
app: hello-nginx
spec:
containers:
- image: nginx
name: nginx-container
ports:
- containerPort: 8080
但我们在这里是为了尽量减少 yaml……
因此,打开 main.go 文件并复制以下 Go 代码。 别着急,小编带你一探究竟!
package mainimport (
"getting-started-with-cdk8s-go/imports/k8s"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
"github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2"
)type NginxChartProps struct {
cdk8s.ChartProps
}func NewNginxChart(scope constructs.Construct, id string, props *NginxChartProps) cdk8s.Chart {
var cprops cdk8s.ChartProps
if props != nil {
cprops = props.ChartProps
}
chart := cdk8s.NewChart(scope, jsii.String(id), &cprops) selector := &k8s.LabelSelector{MatchLabels: &map[string]*string{"app": jsii.String("hello-nginx")}} labels := &k8s.ObjectMeta{Labels: &map[string]*string{"app": jsii.String("hello-nginx")}} nginxContainer := &k8s.Container{Name: jsii.String("nginx-container"), Image: jsii.String("nginx"), Ports: &[]*k8s.ContainerPort{{ContainerPort: jsii.Number(80)}}} k8s.NewKubeDeployment(chart, jsii.String("deployment"),
&k8s.KubeDeploymentProps{
Spec: &k8s.DeploymentSpec{
Replicas: jsii.Number(1),
Selector: selector,
Template: &k8s.PodTemplateSpec{
Metadata: labels,
Spec: &k8s.PodSpec{
Containers: &[]*k8s.Container{nginxContainer}}}}}) return chart
}func main() {
app := cdk8s.NewApp(nil)
NewNginxChart(app, "nginx", nil)
app.Synth()
}
在用任何语言编写基于 cdk8s 的代码时,您都会遇到一组常见的概念/术语——包括 Construct、App 和 Chart。我将在我们浏览代码时解释这些。
稍微绕道(代码演练和概念)
首先从main函数开始——我们使用cdk8s.NewApp来创建一个App。
那么,App 中到底有什么?它是一个构造,您可以将构造视为表示状态的更高级别的构建块。需要注意的关键是这些构造是可组合的。这意味着您可以定义这些构造的级别(每个级别提供/公开不同的抽象层)并将它们组合起来以创建您想要的最终状态——在这种情况下,它恰好是一个带有诸如 Deployment 之类的对象的 Kubernetes 清单,但是它可能是别的东西。
例如一个 AWS CloudFormation 模板(如果您要使用 AWS CDK,请不要与 cdk8s 混淆)
回到 App - 所以,App 也是一个构造。实际上,您可以将其视为构造树(层次结构)中的根。那么,那棵树上还有什么?查看主函数中的第二行 - NewNginxChart(app, "getting-started", nil) - 这会调用一个函数 NewNginxChart,该函数返回一个 cdk8s.Chart,它是层次结构中的下一个组件。 AA cdk8s 应用程序可以包含多个图表,并且每个图表都可以转换(或用精确的 cdk8s 术语 - 合成)为单独的 Kubernetes 清单文件(您很快就会看到此操作)。
最后,请注意 NewNginxChart 函数。它有很多东西,但请注意对 k8s.NewKubeDeployment 函数的调用。这是我们在代码中实际定义 Kubernetes 部署的地方(在下一节中,我们还将向图表添加一个服务。)
您可以在一个图表中定义多个 Kubernetes 组件,例如 Pod、Service、Ingress、Job 等——您的应用程序在 Kubernetes 上运行所需的一切。
总而言之,这是我刚才解释的直观表示——记住一切都是构造(应用程序、图表等)
等等,Kubernetes API 依赖项呢?
如果您花时间以编程方式访问 Kubernetes,那么这是一个显而易见(而且很棒!)的问题。如果您要使用 go 处理 k8s 对象,那么您至少需要 Kubernetes client-go、API 机器等。猜猜看,cdk8s 也可以满足您的需求!
您实际上不需要引入这些依赖项,因为 cdk8s 允许您将这些 Kubernetes API 对象视为构造 - 请记住,一切都是构造!当您运行 cdk8s init 命令时,它们会自动导入到您的项目中,但您也可以使用 cdk8s import 显式执行此操作。生成的 API 可作为导入文件夹的一部分使用(是的,继续检查一遍!)。在 main.go 顶部,检查导入的包 - 它只是指导入文件夹。
不过,cdk8s 导入还有更多内容。但是您必须等待其他博客文章才能看到这一点 - 我们才刚刚开始!
好吧,让我们回到正轨……
..并继续实际操作。是时候生成一些 yaml 了——你无法消除它,但至少你不必手动编写它!为此,只需运行:
cdk8s synth
一旦完成(应该很快!),检查 dist 目录以检查 cdk8s 生成了什么。
为了更容易理解,这里有一个图表,它在 cdk8s 代码对象/属性与它们在 yaml 中的对应对象之间具有一对一映射(注意标签 1、2、3 等?),例如spec.replicas、spec.selector、template.spec 等。
您现在可以使用旧的 kubectl 将其部署到 Kubernetes,因为 cdk8s 不会为您这样做,至少现在还不会;)
kubectl apply -f dist/
kubectl get pods -w
一旦 Deployment 准备就绪,Pod 应该处于 Running 状态。 只需使用 port-forward 在本地访问 nginx 容器端口:
kubectl port-forward <enter nginx pod name> 8080:80
要访问 nginx 主页,请使用浏览器导航到 http://localhost:8080
您还可以使用 CLI 工具,例如 卷曲本地主机:8080。
那不是全部!
代替端口转发,让我们通过定义一个 Service 资源来使用标准 Kubernetes 访问应用程序的方式,该资源通常定义如下:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
ports:
- port: 9090
targetPort: 8080
selector:
app: hello-nginx
type: LoadBalancer
但你知道规则 - 不要手动编写 yaml! 因此,在 main.go 文件的 NewNginxChart 函数中,在定义 Deployment 的部分之后添加这段代码:
k8s.NewKubeService(chart, jsii.String("service"), &k8s.KubeServiceProps{
Spec: &k8s.ServiceSpec{
Type: jsii.String("LoadBalancer"),
Ports: &[]*k8s.ServicePort{{Port: jsii.Number(9090), TargetPort: k8s.IntOrString_FromNumber(jsii.Number(80))}},
Selector: &map[string]*string{"app": jsii.String("hello-nginx")}}})
首先,删除现有的 Deployment - kubectl delete -f dist/。 然后,再次运行 cdk8s synth 以在 dist 文件夹中创建新的清单。
服务和部署都在同一个文件中 - 这是因为它们是同一个图表的一部分。
您如何访问该服务将取决于 Kubernetes 集群。 如果您使用的是云提供商,它可能会提供该云原生的负载均衡器服务,例如 AWS 中的应用程序负载均衡器。 请根据您的设置进行调整。
在终端中,运行以下命令(它作为单独的进程运行):
minikube tunnel
在另一个终端中,删除现有的 Deployment,然后应用新的清单:
kubectl apply -f dist/
kubectl get pods -w
检查服务:
kubectl get svc
要访问 nginx 服务器,请导航到外部 IP(根据服务)。 对于 minikube,您可以简单地使用 localhost:9090 或 127.0.0.0:9090
请记住使用端口 9090,因为这是我们在代码的服务配置中指定的外部端口
在结束之前…
.. 我想强调 cdk8s 中的其他一些有用的东西。
引用和重用现有清单和 Helm 图表
假设您已经在 service.yaml 文件中定义了一个服务。 您可以将它作为您可能拥有的更大应用程序/图表的一部分包含在您的 cdk8s 中。 这是一个例子:
cdk8s.NewInclude(chart, jsii.String("existing service"), &cdk8s.IncludeProps{Url: jsii.String("service.yaml")})
同样,您也可以包含 Helm 图表。 假设你想添加 bitnami/nginx:
cdk8s.NewHelm(chart, jsii.String("bitnami nginx helm chart"), &cdk8s.HelmProps{
Chart: jsii.String("bitnami/nginx"),
Values: &map[string]interface{}{"service.type": "ClusterIP"}})
另一个方便的功能是……
... 声明任何两个 cdk8s 结构之间的依赖关系的能力。 例如,在前面的示例中,我们有一个部署和一个服务。 您可以这样创建依赖项:
deployment := k8s.NewKubeDeployment(...)
service := k8s.NewKubeService(...)deployment.AddDependency(service)
多亏了 AddDependency,生成的清单将使得 Service 被放置在 Deployment 对象之前。
依赖性不限于图表中的单个构造。 如果您有多个图表作为 cdk8s 应用程序的一部分,您也可以建立跨图表的依赖关系。
结论
惊人的。 因此,您可以通过“编码”解决问题并忽略 YAML。 希望你喜欢它! 为简单起见,我演示了一个部署和服务,但您可以从其他 Kubernetes 组件中进行选择,例如 Ingress、Job 等。它们都使用类似的模式(例如 NewKube)公开。 NewKubeJob、NewKubeIngress 等。
但是在定义 Kubernetes 组件时仍然涉及到很多样板代码。 编写 Go 代码听起来比 YAML 工程好得多(至少对我而言),似乎我们正在将现有的 YAML 转换为 Go 结构(和字段)。 在随后的博客文章中,我们将探讨如何进一步改进这一点。
快乐编码!
关注七爪网,获取更多APP/小程序/网站源码资源!
猜你喜欢
- 2024-10-19 GO 编程:5个开源项目 Codis,Etcd,Kubernetes,Caddy,Go-MySQL
- 2024-10-19 把SpringBoot搬到K8s,居然翻船?体验到了Go在云原生的两个优势
- 2024-10-19 在kubernetes上部署Go Micro代码(一)
- 2024-10-19 这个开源项目为编写各种Docker-Compose提供了样本
- 2024-10-19 goaccess实现可视化监控access.log日志
- 2024-10-19 Nginx Ingress 高并发实践 nginx 高并发原理
- 2024-10-19 Go 比 PHP 强吗? golang和php哪个厉害
- 2024-10-19 nginx 部署 go 搭建的后端 nginx如何部署
- 2024-10-19 go-websocket 分布式IM websocket分get和post请求吗
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)