将 Swift 部署到 Kubernetes:从本地构建到生产集群
\nSwift 不仅仅是 iOS 和 macOS 的语言。借助 Vapor 和 Kitura 等框架,Swift 越来越多地被用于编写服务器端应用程序。但是如何将这些应用程序交付给用户呢?答案是 Kubernetes。在本指南中,我们将介绍如何将 Swift 应用程序打包到 Docker 中,配置 CI/CD,并将其部署到 K8s 集群中。您将了解在 Linux 下构建 Swift 时有哪些注意事项,如何优化镜像,以及如何为 Kubernetes 编写正确的清单。
\n\n1. 准备用于容器化的 Swift 应用程序
\n开发者首先会遇到的问题是 Swift 在 Linux 上的运行。如果您在 macOS 上编写代码,则需要为 Linux(amd64/arm64)交叉编译应用程序。我们来看一个基于 Vapor 4 的示例。
\n创建一个简单的 HTTP 应用程序:
\n// Sources/App/routes.swift\nimport Vapor\n\nfunc routes(_ app: Application) throws {\n app.get { req async in\n "Hello from Swift on Kubernetes!"\n }\n app.get("health") { req async in\n "OK"\n }\n}\n\n为了在 Linux 下构建,我们使用官方的 Swift 镜像。创建一个包含两阶段构建的 Dockerfile:
# 第一阶段:构建\nFROM swift:5.9-focal as builder\nWORKDIR /app\nCOPY Package.swift Package.resolved ./\nRUN swift package resolve\nCOPY . .\nRUN swift build -c release --static-swift-stdlib\n\n# 第二阶段:最小化镜像\nFROM ubuntu:22.04\nRUN apt-get update && apt-get install -y ca-certificates libsqlite3-0 && rm -rf /var/lib/apt/lists/*\nWORKDIR /app\nCOPY --from=builder /app/.build/release/Run .\nEXPOSE 8080\nCMD ["./Run"]\n\n关键点是 --static-swift-stdlib 标志。它启用了 Swift 标准库的静态链接,从而减小了镜像大小并简化了部署。没有它,镜像大小可能会超过 1 GB。
2. 构建镜像并上传到仓库
\n构建镜像并推送到 Docker Hub(或任何其他仓库):
\n# 构建\ndocker build -t myrepo/swift-k8s-demo:1.0.0 .\n\n# 本地测试\ndocker run -p 8080:8080 myrepo/swift-k8s-demo:1.0.0\ncurl http://localhost:8080\n# 响应:Hello from Swift on Kubernetes!\n\n# 推送到仓库\ndocker push myrepo/swift-k8s-demo:1.0.0\n\n大小优化:基于 ubuntu:22.04 的镜像大小约为 150 MB。如果使用 alpine,可以减小到 50 MB,但需要解决 glibc 问题(Swift 需要它)。建议使用官方的 Ubuntu 或 Debian 镜像。
3. 用于 Swift 应用程序的 Kubernetes 清单
\n现在将我们的应用程序部署到集群中。创建 Deployment 和 Service。
\ndeployment.yaml:
\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: swift-app\n labels:\n app: swift-app\nspec:\n replicas: 3\n selector:\n matchLabels:\n app: swift-app\n template:\n metadata:\n labels:\n app: swift-app\n spec:\n containers:\n - name: swift-app\n image: myrepo/swift-k8s-demo:1.0.0\n ports:\n - containerPort: 8080\n livenessProbe:\n httpGet:\n path: /health\n port: 8080\n initialDelaySeconds: 5\n periodSeconds: 10\n readinessProbe:\n httpGet:\n path: /health\n port: 8080\n initialDelaySeconds: 3\n periodSeconds: 5\n resources:\n requests:\n memory: "64Mi"\n cpu: "100m"\n limits:\n memory: "128Mi"\n cpu: "250m"\n\nservice.yaml:
\napiVersion: v1\nkind: Service\nmetadata:\n name: swift-app-service\nspec:\n selector:\n app: swift-app\n ports:\n - protocol: TCP\n port: 80\n targetPort: 8080\n type: ClusterIP\n\n请注意 probes(探针)。