《NestJS智能体开发》(二):云原生架构

310 阅读18分钟

什么是云原生架构?

云原生(Cloud Native)架构是一种专为云环境设计的架构模式,旨在充分利用云计算的弹性、可扩展性和灵活性。它以容器化、微服务、不可变基础设施和声明式API为核心技术。通过云原生架构,开发者可以快速构建、部署和管理应用,实现资源的高效利用和业务的快速迭代。

image.png

为什么要使用云原生架构?

云原生架构是当今数字化时代极具前瞻性和实用性的技术架构,其优势主要体现在以下几个方面:

1. 多语言支持

支持多种编程语言,开发者可以根据项目需求和技术栈灵活选择语言,提高开发效率。

2. 统一网关鉴权

通过集中式网关进行身份验证和权限管理,简化开发流程,增强安全性。

3. 微服务架构

将应用拆分为独立的微服务,提高可扩展性、灵活性和容错性,便于独立开发和维护。

4. 容器化技术

将应用及其依赖打包为容器,确保一致性和可移植性,同时实现轻量级部署和快速启动。

5. 弹性伸缩

根据负载自动调整资源,确保应用在不同流量下都能高效运行,避免资源浪费。

6. 高可用性与容错性

通过分布式部署和自动化故障转移,确保应用的高可用性和自愈能力。

7. 持续集成与持续部署(CI/CD)

支持自动化构建、测试和部署流程,加快软件交付速度,提高开发效率。

8. 降低成本

按需付费的模式和高效的运维管理,降低IT资源和人力成本。

9. 多云与混合云支持

支持多种云环境和混合云架构,提供更高的灵活性和资源优化能力。

10. 快速迭代与交付

微服务化和容器化支持并行开发和快速部署,加速产品迭代和市场响应速度。

image.png

什么是Kubernetes?

k8s(Kubernetes)是云原生架构的核心组件。它就像一个“指挥官”,负责管理应用程序的容器。在云原生架构下,应用程序被封装在容器中,而 k8s 能够帮助这些容器在云环境中更好地协作、运行和扩展。

image.png

K8s的核心概念

  1. Pod

    • Pod是k8s中最小的部署单元。可以把它想象成一个“小盒子”,一个Pod里面可以包含一个或多个容器。这些容器在同一个Pod里共享网络和存储资源。例如,一个Pod可能包含一个Web服务器容器和一个日志收集容器,它们紧密配合工作。
  2. Service

    • Service是用来定义Pod的访问方式的。它就像一个“门牌号”,让其他服务或客户端能够找到并连接到Pod。例如,你有一个运行在多个Pod中的应用程序,Service可以为这些Pod提供一个统一的访问入口,即使Pod的数量和位置发生变化,通过Service,外部请求仍然可以正确地到达应用程序。
  3. Deployment

    • Deployment是用于管理Pod的副本数量和更新策略的。它确保Pod按照你设定的数量运行,并且在更新应用程序时,能够按照一定的顺序和策略进行更新。比如,你希望应用程序始终有3个副本在运行,Deployment就会负责监控和保证这个数量。如果某个Pod出现故障,它会自动启动一个新的Pod来替换。

有关k8s的更多概念和使用请参阅Kubernetes官方文档

使用Orbstack搭建本地k8s集群

Orbstack是一个轻量级的本地开发环境工具,支持在Mac上快速搭建Kubernetes集群。以下是使用Orbstack开启本地k8s集群的步骤:

  1. 安装Orbstack:访问Orbstack官网,下载并安装适合Mac的版本。
  2. 创建集群:通过Orbstack的图形界面或命令行工具创建一个新的Kubernetes集群。可以指定集群的名称、资源限制等参数。
  3. 配置kubectl:Orbstack会自动配置kubectl的上下文,使其指向新创建的集群。通过kubectl cluster-info命令验证集群是否正常运行。
$ kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:26443
CoreDNS is running at https://127.0.0.1:26443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

Kubernetes部署Nest.js服务

1. 创建 Nest.js 服务

1.1 安装 Nest.js CLI

确保你已经安装了 Nest.js CLI,如果没有安装,可以通过以下命令安装:

pnpm add -g @nestjs/cli

1.2 创建 Nest.js 项目

创建一个新的 Nest.js 项目:

nest new my-nest-app
cd my-nest-app

1.3 创建一个简单的控制器

src/app.controller.ts 文件中,定义一个简单的控制器:

import { Controller, Get } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  getHello(): string {
    return 'Hello from Nest.js!';
  }
}

1.4 构建项目

运行以下命令构建项目:

pnpm run build

2. 创建 Dockerfile

在项目根目录下创建一个 Dockerfile,内容如下:

# 使用 Node.js 22 Alpine 镜像作为构建阶段的基础镜像
FROM node:22-alpine AS builder
# 全局安装 pnpm 作为包管理器
RUN npm install -g pnpm
# 设置工作目录为 /app
WORKDIR /app
# 将 package.json 和 pnpm-lock.yaml 复制到工作目录
COPY package.json pnpm-lock.yaml ./
# 安装项目依赖,确保依赖版本固定 
RUN pnpm install --frozen-lockfile
# 将项目的所有文件复制到工作目录
COPY . .
# 运行构建命令
RUN pnpm build

# 使用 Node.js 22 Alpine 镜像作为运行阶段的基础镜像
FROM node:22-alpine
# 全局安装 pnpm
RUN npm install -g pnpm
# 设置工作目录为 /app
WORKDIR /app
# 从构建阶段复制构建输出
COPY --from=builder /app/dist ./dist
# 复制 package.json 和 pnpm-lock.yaml
COPY --from=builder /app/package.json /app/pnpm-lock.yaml ./
# 安装生产环境依赖,确保只安装生产环境所需的包
RUN pnpm install --frozen-lockfile --prod
# 设置环境变量 NODE_ENV 为 production
ENV NODE_ENV=production
# 暴露容器的 3000 端口
EXPOSE 3000
# 启动应用的命令
CMD ["pnpm", "start:prod"]

3. 构建 Docker 镜像

在项目根目录下运行以下命令构建 Docker 镜像:

docker build -t my-nest-app .

4. Kubernetes 部署

创建一个名为 k8s/deployment.yaml 的文件,内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nest-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-nest-app
  template:
    metadata:
      labels:
        app: my-nest-app
    spec:
      containers:
      - name: my-nest-app
        image: my-nest-app:latest
        ports:
        - containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
  name: my-nest-app-service
spec:
  selector:
    app: my-nest-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: LoadBalancer

4.4 应用 Kubernetes 部署文件

运行以下命令将部署文件应用到 Kubernetes 集群中:

kubectl apply -f k8s/deployment.yaml

4.5 访问服务

运行以下命令获取服务的外部 IP:

kubectl get svc

找到 my-nest-app-serviceEXTERNAL-IP,然后在浏览器中访问 http://<EXTERNAL-IP>,你应该能看到返回的 "Hello from Nest.js!"

5. 清理资源

部署完成后,如果你需要清理资源,可以运行以下命令:

kubectl delete -f k8s/deployment.yaml

Helm:Kubernetes 的”瑞士军刀”

随着 Kubernetes 集群的规模和复杂性不断增加,管理应用的部署和运维变得愈发具有挑战性。Helm 的出现,就像为 Kubernetes 的使用者配备了一把功能强大的“瑞士军刀”,极大地简化了应用的部署和管理流程。

image.png

Helm 使用一种称为 Helm Charts 的模板格式来描述 Kubernetes 资源。这些 Charts 是一种预配置的 Kubernetes 应用模板,包含了运行一个应用所需的所有 Kubernetes 资源定义,例如 Deployment、Service、ConfigMap 等。Charts 可以被轻松地打包、分发和安装,就像我们使用软件包管理工具(如 apt、yum)来安装系统软件一样。

Helm 简单使用示例

  1. 安装 Helm

    • 在本地机器上安装 Helm。可以从 Helm 官网获取安装指南。

    • 安装完成后,运行以下命令初始化 Helm:

      helm init
      
  2. 安装一个 Helm Chart

    • Helm 提供了一个官方的 Chart 仓库,其中包含了各种常见的应用 Chart。例如,安装一个 MySQL 数据库:

      helm repo add bitnami https://charts.bitnami.com/bitnami
      helm install my-mysql bitnami/mysql
      
    • 这里,my-mysql 是你给这个 MySQL 实例定义的名称,bitnami/mysql 是 Chart 的路径。

  3. 查看部署状态

    • 查看部署的 MySQL 状态:

      helm list
      
    • 查看 MySQL 的详细信息:

      helm status my-mysql
      
  4. 删除部署

    • 如果不再需要 MySQL,可以运行以下命令删除:

      helm delete my-mysql
      

自定义 Nest.js Helm Charts

1. 创建 Helm Chart 结构

运行以下命令创建一个新的 Helm Chart:

helm create my-nestjs-app

这会生成一个名为 my-nestjs-app 的目录,其结构如下:

my-nestjs-app/
├── Chart.yaml
├── values.yaml
├── .helmignore
├── templates/
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── ingress.yaml
│   ├── service.yaml
│   └── hpa.yaml
└── charts/

2. 修改 Chart.yaml

编辑 Chart.yaml 文件,定义你的 Chart 信息:

apiVersion: v2
name: my-nestjs-app
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: "1.0"

3. 配置 values.yaml

编辑 values.yaml 文件,定义默认的配置值:

replicaCount: 1

image:
  repository: my-nestjs-app
  pullPolicy: IfNotPresent
  tag: latest

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  annotations: {}
  hosts:
    - host: my-nestjs-app.local
      paths:
        - path: /
          pathType: Prefix

resources: {}

4. 修改模板文件

根据你的需求修改 templates 目录下的模板文件。例如,修改 deployment.yaml 文件,使其适合 Nest.js 应用:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Values.name }}
  template:
    metadata:
      labels:
        app: {{ .Values.name }}
    spec:
      containers:
      - name: {{ .Values.name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        ports:
        - containerPort: {{ .Values.service.port }}
        resources:
          {{- toYaml .Values.resources | nindent 12 }}

5. 打包和部署

  1. 打包 Helm Chart:

    helm package my-nestjs-app
    
  2. 安装 Helm Chart:

    helm install my-nestjs my-nestjs-app-0.1.0.tgz
    
  3. 查看部署状态:

    helm list
    

使用 Tilt 简化和共享开发工作流

Tilt 是什么?

Tilt 是一个开源的开发工具,用于简化 Kubernetes 应用的开发和部署流程。它可以帮助开发者快速启动和管理 Kubernetes 应用,同时提供实时更新和调试功能。Tilt 通过自动构建和部署代码更改,使开发过程更加高效。

image.png

为什么要用 Tilt?

  1. 简化开发流程:Tilt 提供了一种更简单的方式来管理 Kubernetes 应用的开发过程。它自动处理代码的构建和部署,减少了手动操作的复杂性。
  2. 实时更新:Tilt 支持实时更新功能,当代码发生变化时,它会自动重新构建和部署应用,无需手动干预。这大大提高了开发效率,尤其是在开发阶段需要频繁更新代码时。
  3. 集成多种工具:Tilt 可以与多种开发工具和框架集成,如 Docker、Kubernetes、Helm 等。这种集成能力使得 Tilt 能够适应不同的开发环境和需求。
  4. 可视化和调试:Tilt 提供了直观的可视化界面,帮助开发者更好地理解应用的部署状态。此外,它还支持调试功能,方便开发者快速定位和解决问题。
  5. 团队协作:Tilt 支持团队协作,允许多个开发者同时在一个项目上工作。它通过共享配置和状态,确保团队成员之间的开发环境一致,减少因环境差异导致的问题。

Tilt 简单使用

在项目根目录下创建一个 Tiltfile,用于定义 Tilt 的配置:

# 定义 Kubernetes 部署
k8s_yaml('k8s/deployment.yaml')

# 定义 Docker 镜像构建
docker_build('my-nestjs-app', '.')

# 定义 Kubernetes 部署
k8s_resource('my-nestjs-app', port_forward=8080)

在项目根目录下运行以下命令启动 Tilt:

tilt up

Traefik: 云原生网关

什么是 Traefik?

Traefik 是一个现代的开源反向代理和负载均衡器,专为微服务架构和容器化应用设计。它支持多种后端(如 Docker、Kubernetes、Consul、Etcd 等),并提供了简便的配置方式和丰富的功能。

image.png

Traefik 的核心特性如下:

  1. 自动发现服务:Traefik 能够自动检测并配置后端服务,无需手动配置每个服务。它通过与容器编排平台(如 Kubernetes、Docker Swarm 等)集成,实时发现新服务并自动更新路由。
  2. 动态配置:支持动态更新配置,减少了重启服务的需求。当服务发生变化(如容器的启动或停止)时,Traefik 会即时调整路由配置。
  3. 中间件支持:可以轻松添加认证、速率限制、重定向等功能。
  4. 集成 Let’s Encrypt:自动管理 SSL/TLS 证书,提供 HTTPS 支持。
  5. 强大的监控和日志功能:支持 Prometheus、Grafana 等监控工具,并提供丰富的日志信息。
  6. 支持多种协议:不仅支持传统的 HTTP/HTTPS 协议,还支持 WebSocket、TCP、UDP 等协议。

为什么使用 Traefik?

  1. 简化配置:Traefik 的配置通常更为简洁,支持使用 YAML 文件或 Kubernetes 注释来定义路由规则,易于理解和维护。
  2. 适合云原生和微服务架构:Traefik 特别适合需要高度动态调整的场景,尤其是在微服务架构和容器化环境中。
  3. 自动化和动态更新:Traefik 能够自动根据服务健康状况进行动态路由,避免了不必要的负载压力。
  4. 强大的安全功能:通过中间件功能提供了强大的安全控制能力,如访问控制、IP 限制和基于 JWT 的身份验证。
  5. 易于集成:与多种容器编排平台和云服务提供商无缝集成,能够快速适应不同的开发和部署环境。

使用 Tilt 管理开发环境

使用 Tilt 部署一个基于 HelmKubernetes 的应用,包括 TraefikNATS 的 Helm Charts,以及一个自定义的 Nest.js 应用。

# -*- mode: Python -*-
load('ext://namespace', 'namespace_create')
load('ext://helm_resource', 'helm_resource', 'helm_repo')
  • 加载 Tilt 的扩展模块,namespacehelm_resource

    • namespace_create:用于创建 Kubernetes 命名空间。
    • helm_resourcehelm_repo:用于管理 Helm 仓库和 Helm Charts 的部署。
env = os.getenv('ENV', 'dev')
print("ENV:{}".format(env))
  • 从环境变量中获取 ENV 的值,如果没有设置,则默认为 dev。这个变量用于区分不同的环境(如开发、测试、生产等)。
namespace = "app-{}".format(env)
namespace_create(namespace)
  • 根据环境变量 env 创建一个命名空间,格式为 app-<env>。例如,如果 envdev,则创建的命名空间为 app-dev
helm_repo("traefik-repo", "https://traefik.github.io/charts")
helm_resource(
  'traefik',
  'traefik-repo/traefik',
  resource_deps=['traefik-repo'],
  namespace=namespace,
  flags=[
    "--version", "28.0.0",
    "--set", "dashboard.enabled=true"
  ]
)
  • 添加 Traefik 的 Helm 仓库,并部署 Traefik Helm Chart。

    • helm_repo:添加 Traefik 的 Helm 仓库。

    • helm_resource:部署 Traefik Helm Chart。

      • resource_deps:指定依赖的 Helm 仓库。
      • namespace:指定部署到的命名空间。
      • flags:设置 Helm 部署的参数,例如指定版本号 28.0.0 和启用 Traefik 的 Dashboard。
helm_repo("nats-repo", "https://nats-io.github.io/k8s/helm/charts")
helm_resource(
  'nats',
  'nats-repo/nats',
  resource_deps=['nats-repo'],
  namespace=namespace,
  flags=[
    "--set", "jetstream.enabled=true"
  ]
)
  • 添加 NATS 的 Helm 仓库,并部署 NATS Helm Chart。

    • helm_repo:添加 NATS 的 Helm 仓库。

    • helm_resource:部署 NATS Helm Chart。

      • resource_deps:指定依赖的 Helm 仓库。
      • namespace:指定部署到的命名空间。
      • flags:设置 Helm 部署的参数,例如启用 JetStream 功能。
image_name = "nest-api-{}".format(env)
docker_build(image_name, '.')
  • 构建一个 Docker 镜像,镜像名称为 nest-api-<env>,使用当前目录下的 Dockerfile 构建。
helm_chart_path = './infrastructure/helm'
yaml = helm(
  helm_chart_path,
  name=image_name,
  namespace=namespace,
  values=['./infrastructure/helm/values.yaml', './infrastructure/helm/values-{}.yaml'.format(env)],
)
  • 部署自定义的 Helm Chart。

    • helm_chart_path:指定 Helm Chart 的路径。
    • name:指定 Helm Chart 的名称。
    • namespace:指定部署到的命名空间。
    • values:指定 Helm Chart 的配置文件,支持多个文件,例如默认的 values.yaml 和环境特定的 values-<env>.yaml
k8s_yaml(yaml)
k8s_yaml('./infrastructure/k8s/{}/jwt-auth.yaml'.format(env))
k8s_yaml('./infrastructure/k8s/{}/dashboard.yaml'.format(env))
k8s_yaml('./infrastructure/k8s/{}/nest-config.yaml'.format(env))
k8s_yaml('./infrastructure/k8s/{}/nest-route.yaml'.format(env))
  • 将生成的 Helm Chart 的 YAML 文件以及一些额外的 Kubernetes 配置文件(如 JWT 认证、Traefik Dashboard、Nest.js 路由)应用到 Kubernetes 集群中。

    • k8s_yaml:将指定的 YAML 文件应用到 Kubernetes 集群。

jwt-auth.yaml

*.k8s.orb.local 是 OrbStack 提供的一个泛域名(wildcard domain),用于简化本地 Kubernetes 环境中服务的访问

apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: jwt-auth
  namespace: app-dev
spec:
  forwardAuth:
    address: http://api.k8s.orb.local/auth
    forwardBody: true
    authResponseHeaders:
      - X-Auth-User

1. apiVersion

apiVersion: traefik.io/v1alpha1
  • apiVersion 指定了 Traefik 的 API 版本。traefik.io/v1alpha1 是 Traefik 2.x 中用于定义中间件的 API 版本。

2. kind

kind: Middleware
  • kind 指定了资源的类型。在这里,资源类型是 Middleware,这是 Traefik 的一个自定义资源定义(CRD),用于定义中间件。

3. metadata

metadata:
  name: jwt-auth
  namespace: app-dev
  • metadata 包含资源的元数据。

    • name:中间件的名称,这里是 jwt-auth
    • namespace:中间件所在的 Kubernetes 命名空间,这里是 app-dev

4. spec

spec:
  forwardAuth:
    address: http://api.k8s.orb.local/auth
    forwardBody: true
    authResponseHeaders:
      - X-Auth-User
  • spec 包含中间件的具体配置。
4.1 forwardAuth
  • forwardAuth 是一个中间件类型,用于将请求转发到一个外部认证服务进行认证。
4.1.1 address
address: http://api.k8s.orb.local/auth
  • address 指定了外部认证服务的地址。在这里,认证服务的地址是 http://api.k8s.orb.local/auth
4.1.2 forwardBody
forwardBody: true
  • forwardBody 指定了是否将请求体转发到认证服务。在这里,设置为 true,表示请求体也会被转发。
4.1.3 authResponseHeaders
authResponseHeaders:
  - X-Auth-User
  • authResponseHeaders 指定了认证服务返回的响应头中哪些头会被传递回客户端。在这里,指定传递 X-Auth-User 头。

通过这个中间件,Traefik 可以将请求转发到指定的认证服务进行认证,并根据认证结果处理请求。

nest-route.yaml

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: nest-route
  namespace: app-dev
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`api.k8s.orb.local`) && PathPrefix(`/`) && !PathPrefix(`/auth`)
      kind: Rule
      middlewares:
        - name: jwt-auth
      services:
        - name: nest-api
          port: 3000
    - match: Host(`api.k8s.orb.local`) && PathPrefix(`/auth`)
      kind: Rule
      services:
        - name: nest-api
          port: 3000

1. apiVersion

apiVersion: traefik.io/v1alpha1
  • apiVersion 指定了 Traefik 的 API 版本。traefik.io/v1alpha1 是 Traefik 2.x 中用于定义 IngressRoute 的 API 版本。

2. kind

kind: IngressRoute
  • kind 指定了资源的类型。在这里,资源类型是 IngressRoute,这是 Traefik 的一个自定义资源定义(CRD),用于定义路由规则。

3. metadata

metadata:
  name: nest-route
  namespace: app-dev
  • metadata 包含资源的元数据。

    • name:资源的名称,这里是 nest-route
    • namespace:资源所在的 Kubernetes 命名空间,这里是 app-dev

4. spec

spec:
  entryPoints:
    - web
  routes:
    - match: Host(`api.k8s.orb.local`) && PathPrefix(`/`) && !PathPrefix(`/auth`)
      kind: Rule
      middlewares:
        - name: jwt-auth
      services:
        - name: nest-api
          port: 3000
    - match: Host(`api.k8s.orb.local`) && PathPrefix(`/auth`)
      kind: Rule
      services:
        - name: nest-api
          port: 3000
  • spec 包含资源的具体配置。
4.1 entryPoints
entryPoints:
  - web
  • entryPoints 指定了 Traefik 的入口点。在这里,使用了 web 入口点,这通常是 Traefik 配置中定义的 HTTP 入口点。
4.2 routes
routes:
  - match: Host(`api.k8s.orb.local`) && PathPrefix(`/`) && !PathPrefix(`/auth`)
    kind: Rule
    middlewares:
      - name: jwt-auth
    services:
      - name: nest-api
        port: 3000
  - match: Host(`api.k8s.orb.local`) && PathPrefix(`/auth`)
    kind: Rule
    services:
      - name: nest-api
        port: 3000
  • routes 是一个数组,定义了多个路由规则。
4.2.1 第一个路由规则
- match: Host(`api.k8s.orb.local`) && PathPrefix(`/`) && !PathPrefix(`/auth`)
  kind: Rule
  middlewares:
    - name: jwt-auth
  services:
    - name: nest-api
      port: 3000
  • match:定义了匹配条件。

    • Host(api.k8s.orb.local):匹配请求的主机名为 api.k8s.orb.local
    • PathPrefix(/):匹配请求路径以 / 开头。
    • !PathPrefix(/auth):排除请求路径以 /auth 开头的情况。
  • kind:定义了规则的类型,这里是 Rule

  • middlewares:定义了中间件。

    • name: jwt-auth:应用名为 jwt-auth 的中间件。这个中间件可能用于 JWT 认证。
  • services:定义了后端服务。

    • name: nest-api:后端服务的名称为 nest-api
    • port: 3000:后端服务的端口为 3000
4.2.2 第二个路由规则
- match: Host(`api.k8s.orb.local`) && PathPrefix(`/auth`)
  kind: Rule
  services:
    - name: nest-api
      port: 3000
  • match:定义了匹配条件。

    • Host(api.k8s.orb.local):匹配请求的主机名为 api.k8s.orb.local
    • PathPrefix(/auth):匹配请求路径以 /auth 开头。
  • kind:定义了规则的类型,这里是 Rule

  • services:定义了后端服务。

    • name: nest-api:后端服务的名称为 nest-api
    • port: 3000:后端服务的端口为 3000

通过这种方式,Traefik 可以根据请求的路径和主机名,将流量路由到不同的后端服务,并在需要时应用中间件。

完整的 Tilefile 如下:

# -*- mode: Python -*-
load('ext://namespace', 'namespace_create')
load('ext://helm_resource', 'helm_resource', 'helm_repo')

env = os.getenv('ENV', 'dev')
print("ENV:{}".format(env))

namespace = "app-{}".format(env)
namespace_create(namespace)

helm_repo("traefik-repo", "https://traefik.github.io/charts")
helm_resource(
  'traefik',
  'traefik-repo/traefik',
  resource_deps=['traefik-repo'],
  namespace=namespace,
  flags=[
    "--version", "28.0.0",
    "--set", "dashboard.enabled=true"
  ]
)

helm_repo("nats-repo", "https://nats-io.github.io/k8s/helm/charts/")
helm_resource(
  'nats',
  'nats-repo/nats',
  resource_deps=['nats-repo'],
  namespace=namespace,
  flags=[
    "--set", "jetstream.enabled=true"
  ]
)

image_name = "nest-api-{}".format(env)
docker_build(image_name, '.')

helm_chart_path = './infrastructure/helm'
yaml = helm(
  helm_chart_path,
  name=image_name,
  namespace=namespace,
  values=['./infrastructure/helm/values.yaml', './infrastructure/helm/values-{}.yaml'.format(env)],
)

k8s_yaml(yaml)
k8s_yaml('./infrastructure/k8s/{}/jwt-auth.yaml'.format(env))
k8s_yaml('./infrastructure/k8s/{}/dashboard.yaml'.format(env))
k8s_yaml('./infrastructure/k8s/{}/nest-config.yaml'.format(env))
k8s_yaml('./infrastructure/k8s/{}/nest-route.yaml'.format(env))

执行 tilt up 并访问 http://localhost:10350 可以查看服务编排情况

image.png

总结

本文详细介绍了云原生架构的概念、优势,以及如何使用 Kubernetes、Helm、Tilt 等工具搭建和管理云原生应用,包括通过 OrbStack 搭建本地 Kubernetes 集群,部署 Nest.js 服务,以及使用 Traefik 作为云原生网关。