- Published on
如何将 docker 单节点部署应用改成集群部署?
- Authors

- 作者
- 狂奔滴小马
目录
- Docker Compose 配置
- Kubernetes 集群化部署概述
- Step 1: 将 PostgreSQL 部署为 StatefulSet
- PostgreSQL Secret
- PostgreSQL StatefulSet
- PostgreSQL Service
- Step 2: Node 应用程序的 Deployment 和 Secret
- 应用程序的 Secret
- 应用程序 Deployment
- 应用程序 Service
- Step 3: Adminer Deployment 和 Service
- Adminer Deployment
- Adminer Service
- Step 4: 部署步骤
- Step 5: 验证和监控
- Kubernetes 部署的优势
- 总结
在项目开发中,Docker Compose 是一种常见的工具,能够帮助开发者在本地轻松启动多容器应用。然而,当应用扩展到生产环境,单节点的 Docker Compose 可能无法满足高可用性、容错和扩展需求。这时候,我们可以考虑将 Docker Compose 部署迁移到 Kubernetes 这样的集群环境中,实现应用的集群化管理。
本文将以我之前开发的一个 Node.js 应用(一个在线流程图系统)为例,使用 PostgreSQL、Adminer 管理数据库,介绍如何将单节点的 Docker Compose 部署转化为 Kubernetes 集群部署。
Docker Compose 配置
这是一个典型的 docker-compose.yml 文件,它定义了一个使用 PostgreSQL 作为数据库,Adminer 作为数据库管理界面,Node.js 应用作为服务的环境。
version: "3.8"services: db: image: postgres volumes: - pg_data:/var/lib/postgresql/data restart: always ports: - 5432:5432 environment: POSTGRES_DB: pro POSTGRES_USER: admin POSTGRES_PASSWORD: example adminer: image: adminer restart: always ports: - 8080:8080 app: image: maqi1520/cloneprocesson ports: - "3000:3000" environment: DATABASE_URL: "postgresql://admin:example@db:5432/pro?schema=public" JWT_SECRET: "xxxx" GITHUB_CLIENT_ID: "xxxx" GITHUB_CLIENT_SECRET: "xxxx" DOMAIN: "http://localhost:3000" EMAIL_USER: "[email protected]" EMAIL_USER_NAME: "xxxxx" EMAIL_HOST: "smtp.163.com" EMAIL_PASS: "xxxx" depends_on: - dbvolumes: pg_data:
此配置可以在本地使用 docker-compose up -d 命令启动,但如果要将其部署在生产环境中并确保高可用性,则需要迁移到 Kubernetes。接下来,我们将介绍如何完成这一转化。
Kubernetes 集群化部署概述
在 Kubernetes 中,使用多个资源来管理应用的不同组件。与 Docker Compose 的单一文件不同,Kubernetes 使用 Deployment、StatefulSet、Service、ConfigMap、Secret 等多个配置文件来描述和管理容器化应用。
为了将上述 Docker Compose 配置转移到 Kubernetes,我们需要以下几种关键组件:
- PostgreSQL StatefulSet:用于管理数据库容器,保证数据持久性。
- Deployment:用于部署 Node.js 应用和 Adminer,确保应用的可扩展性。
- Service:为应用提供集群内外的访问接口。
- Secret:用于存储敏感信息(如数据库凭证、API 密钥等)。
Step 1: 将 PostgreSQL 部署为 StatefulSet
在 Kubernetes 中,StatefulSet 用于管理有状态应用(例如数据库),它确保数据库实例的持久性和稳定性。我们首先需要创建一个用于存储数据库凭证的 Secret,然后再创建 StatefulSet。
PostgreSQL Secret
apiVersion: v1kind: Secretmetadata: name: postgres-secrettype: Opaquedata: DATABASE_URL: cG9zdGdyZXNxbDovL2FkbWluOmV4YW1wbGVAcG9zdGdyZXM6NTQzMi9wcm8/c2NoZW1hPXB1YmxpYw== # base64编码的 "postgresql://admin:example@postgres:5432/pro?schema=public" POSTGRES_DB: "cHJv" # "pro" encoded in base64 POSTGRES_USER: "YWRtaW4=" # "admin" encoded in base64 POSTGRES_PASSWORD: "ZXhhbXBsZQ==" # "example" encoded in base64
在 Kubernetes 中,Secret 中的数据可以使用 base64 编码是一种常见的做法,但不是必须的。
在 Linux 和 macOS 系统中,可以使用 base64 命令。例如,要对字符串 “postgresql://admin:example@postgres:5432/pro?schema=public” 进行编码,可以在终端中执行以下命令:
echo -n "postgresql://admin:example@postgres:5432/pro?schema=public" | base64
在 Windows 系统中,可以使用 PowerShell 中的[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("postgresql://admin:example@postgres:5432/pro?schema=public"))命令。
Kubernetes 的 Secret 对象可以存储任意数据,但为了确保数据的安全性和可读性,通常会进行某种形式的编码或加密。
PostgreSQL StatefulSet
apiVersion: apps/v1kind: StatefulSetmetadata: name: postgresspec: serviceName: "postgres" replicas: 1 selector: matchLabels: app: postgres template: metadata: labels: app: postgres spec: containers: - name: postgres image: postgres:latest ports: - containerPort: 5432 env: - name: POSTGRES_DB valueFrom: secretKeyRef: name: postgres-secret key: POSTGRES_DB - name: POSTGRES_USER valueFrom: secretKeyRef: name: postgres-secret key: POSTGRES_USER - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: postgres-secret key: POSTGRES_PASSWORD volumeMounts: - name: pg-data mountPath: /var/lib/postgresql/data volumeClaimTemplates: - metadata: name: pg-data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 1Gi
通过 StatefulSet,我们确保了数据库数据的持久化存储和稳定的网络标识。每个副本都可以访问持久存储卷。
PostgreSQL Service
apiVersion: v1kind: Servicemetadata: name: postgresspec: ports: - port: 5432 selector: app: postgres
Service 用于暴露 PostgreSQL 服务,使得应用可以通过集群内部的 DNS 名称 postgres 访问数据库。
Step 2: Node 应用程序的 Deployment 和 Secret
接下来,我们为 Node.js 应用创建一个 Deployment,并通过 Secret 管理敏感数据,例如数据库 URL、JWT 密钥和 GitHub API 凭证。
应用程序的 Secret
apiVersion: v1kind: Secretmetadata: name: app-secrettype: Opaquedata: jwt-secret: "YOUR_ENCODED_JWT_SECRET" github-client-id: "YOUR_ENCODED_GITHUB_CLIENT_ID" github-client-secret: "YOUR_ENCODED_GITHUB_CLIENT_SECRET"
应用程序 Deployment
apiVersion: apps/v1kind: Deploymentmetadata: name: appspec: replicas: 1 selector: matchLabels: app: app template: metadata: labels: app: app spec: containers: - name: app image: maqi1520/cloneprocesson:latest ports: - containerPort: 3000 env: - name: DATABASE_URL valueFrom: secretKeyRef: name: app-secret key: DATABASE_URL - name: JWT_SECRET valueFrom: secretKeyRef: name: app-secret key: jwt-secret - name: GITHUB_CLIENT_ID valueFrom: secretKeyRef: name: app-secret key: github-client-id - name: GITHUB_CLIENT_SECRET valueFrom: secretKeyRef: name: app-secret key: github-client-secret
应用程序 Service
apiVersion: v1kind: Servicemetadata: name: appspec: type: LoadBalancer ports: - port: 3000 selector: app: app
Step 3: Adminer Deployment 和 Service
最后,Adminer 作为数据库管理界面,也需要用 Deployment 和 Service 部署。
Adminer Deployment
apiVersion: apps/v1kind: Deploymentmetadata: name: adminerspec: replicas: 1 selector: matchLabels: app: adminer template: metadata: labels: app: adminer spec: containers: - name: adminer image: adminer:latest ports: - containerPort: 8080
Adminer Service
apiVersion: v1kind: Servicemetadata: name: adminerspec: type: LoadBalancer ports: - port: 8080 selector: app: adminer
Step 4: 部署步骤
将
Secret和Deployment等资源应用到 Kubernetes 集群:kubectl apply -f postgres-secret.ymlkubectl apply -f postgres-statefulset.ymlkubectl apply -f postgres-service.ymlkubectl apply -f app-secret.ymlkubectl apply -f app-deployment.ymlkubectl apply -f app-service.ymlkubectl apply -f adminer-deployment.ymlkubectl apply -f adminer-service.yml
这将会启动 PostgreSQL 数据库实例,并为数据库提供持久存储,应用程序将通过
Secret获取敏感信息,并连接到 PostgreSQL 数据库。Service将会为外部客户端提供访问 Node.js 应用的入口。Adminer 将作为数据库管理界面通过集群的LoadBalancer公开出来,允许你直接管理 PostgreSQL 数据。
Step 5: 验证和监控
完成部署后,你可以通过以下方式验证集群的运行情况:
查看所有资源是否成功创建:
kubectl get podskubectl get serviceskubectl get statefulsets
验证 PostgreSQL 连接:
可以通过访问 Adminer 服务,验证 PostgreSQL 数据库是否正常工作。你可以使用浏览器访问
http://<LoadBalancer_IP>:8080,然后使用 Secret 中的数据库凭证登录。验证应用程序连接:
访问 Node.js 应用的
Service地址,查看应用是否能正常连接 PostgreSQL 数据库,并成功启动。
如果使用本地部署可以使用minikube service app看到应用地址,他会自动打开部署 url 端口。
Kubernetes 部署的优势
相比于 Docker Compose 单节点部署,Kubernetes 的集群化部署具备以下几个显著优势:
- 高可用性和容错:Kubernetes 提供了原生的自动重启、容器健康检查、横向扩展等机制,使得应用能够在出现问题时自动恢复。
- 自动扩展:你可以根据负载的变化,通过 Kubernetes 自动或手动扩展应用的副本数,保证应用能够处理更多请求。
- 滚动更新:通过 Kubernetes,你可以实现应用的滚动更新,逐步替换旧版本的容器,而不会导致服务中断。
- 资源分配和优化:Kubernetes 允许更精细地控制资源的使用,如 CPU 和内存,确保集群资源的合理利用。
- Secret 和 ConfigMap:通过 Secret 和 ConfigMap,Kubernetes 提供了更安全和动态的方式来管理应用的配置和敏感信息,避免将敏感数据硬编码在镜像或代码中。
总结
将 Docker Compose 的单节点部署迁移到 Kubernetes,不仅能够使应用从本地开发阶段顺利过渡到生产环境,还可以通过 Kubernetes 提供的集群管理能力来提高系统的高可用性、弹性扩展和安全性。
在本文中,我们通过将 Docker Compose 配置中的 PostgreSQL、Adminer 和自定义 Node.js 应用迁移到 Kubernetes,学习了如何利用 StatefulSet、Deployment、Secret 和 Service 等 Kubernetes 资源来管理和部署复杂的集群化应用。这种方式可以帮助你在生产环境中实现更加灵活、安全和可扩展的容器管理。
