
文章目录
-
-
- [**一、 环境与项目准备**](#一、 环境与项目准备)
-
- [**1.1 前提条件**](#1.1 前提条件)
- [**1.2 项目结构**](#1.2 项目结构)
- [**1.3 应用配置**](#1.3 应用配置)
- [**二、 容器化 .NET Core 应用**](#二、 容器化 .NET Core 应用)
- [**三、 部署 Kubernetes 资源**](#三、 部署 Kubernetes 资源)
-
- [**3.1 部署 MySQL**](#3.1 部署 MySQL)
- [**3.2 部署 Redis**](#3.2 部署 Redis)
- [**3.3 部署 .NET Core WebAPI**](#3.3 部署 .NET Core WebAPI)
- [**3.4 部署 Nginx Ingress**](#3.4 部署 Nginx Ingress)
- [**四、 验证与测试**](#四、 验证与测试)
- [**五、 核心配置与连接总结**](#五、 核心配置与连接总结)
- **后续建议**
-

这里整理了一份将 .NET Core WebAPI 项目(包含 MySQL、Redis、Nginx)部署到 Kubernetes 的全流程指南。教程的核心步骤已在下图中展示,可以通过它快速了解部署流程与各组件间的联系。
开始 准备项目
与 Docker 镜像 配置 Kubernetes 资源 部署核心依赖服务 部署 MySQL 部署 Redis 部署 .NET Core WebAPI 部署 Nginx Ingress 验证与测试 检查 Pod 状态 测试 API 连通性 通过域名访问 部署完成
一、 环境与项目准备
1.1 前提条件
在开始之前,请确保你已准备好以下环境:
- Kubernetes 集群:可以是一个本地集群(如 Minikube、Kind、Docker Desktop 内置 K8s),或云服务商提供的集群(如 AKS、EKS、GKE)。
- kubectl:已安装并配置好,可以管理你的集群。
- .NET SDK:本地开发环境需安装相应版本的 .NET SDK(如 .NET 6/7/8)。
- Docker:用于构建应用程序的容器镜像。
1.2 项目结构
假设你的 .NET Core WebAPI 项目结构如下:
k8s-dotnet-demo/
├── src/
│ └── MyWebApi/ # .NET Core WebAPI 项目目录
│ ├── Controllers/
│ ├── Program.cs
│ ├── appsettings.json
│ ├── MyWebApi.csproj
│ └── Dockerfile # 项目Dockerfile
└── k8s-manifests/ # 所有K8s YAML配置文件
├── 01-mysql.yaml
├── 02-redis.yaml
├── 03-webapi.yaml
└── 04-ingress.yaml
1.3 应用配置
确保你的 appsettings.json 或通过环境变量的配置支持从外部读取数据库和缓存连接字符串。这是云原生应用配置的关键。
json
{
"ConnectionStrings": {
// 注意:这里的 Server 和 Port 使用的是K8s中Service的名称和端口
"MySqlConnection": "Server=mysql-service;Port=3306;Database=mydb;User=root;Password=${MYSQL_ROOT_PASSWORD};",
"RedisConnection": "${REDIS_CONNECTION_STRING}" // 例如: redis://redis-service:6379
}
}
重要 :连接字符串中的服务器地址(如
mysql-service,redis-service)是后续在 Kubernetes 中创建的 Service 名称。Kubernetes 内置的 DNS 服务会自动将其解析为对应 Pod 的 Cluster IP。
二、 容器化 .NET Core 应用
为你的 WebAPI 项目创建 Dockerfile,推荐使用多阶段构建以减小最终镜像体积。
dockerfile
# 构建阶段
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["src/MyWebApi/MyWebApi.csproj", "."]
RUN dotnet restore "MyWebApi.csproj"
COPY src/MyWebApi/ .
RUN dotnet publish "MyWebApi.csproj" -c Release -o /app/publish
# 运行时阶段
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /app/publish .
# 暴露应用端口(通常为80或5000)
EXPOSE 80
ENTRYPOINT ["dotnet", "MyWebApi.dll"]
构建并推送镜像到你的镜像仓库(如 Docker Hub、阿里云容器镜像服务等):
bash
docker build -t yourusername/mywebapi:1.0.0 ./src/MyWebApi
docker push yourusername/mywebapi:1.0.0
三、 部署 Kubernetes 资源
3.1 部署 MySQL
创建 k8s-manifests/01-mysql.yaml。使用 PersistentVolumeClaim (PVC) 来持久化存储数据库数据,防止 Pod 重启后数据丢失。
yaml
# 持久化存储声明
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
# 配置信息 (ConfigMap)
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
data:
database: "mydb"
# 敏感信息 (Secret),务必在生产环境中使用!
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
type: Opaque
stringData:
root-password: "YourStrongPassword123!"
# 部署 (Deployment)
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-deployment
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: root-password
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: mysql-config
key: database
ports:
- containerPort: 3306
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql-storage
volumes:
- name: mysql-storage
persistentVolumeClaim:
claimName: mysql-pvc
# 服务 (Service) - 在集群内部暴露MySQL
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
# ClusterIP类型,只在集群内部可访问
type: ClusterIP
应用配置:kubectl apply -f k8s-manifests/01-mysql.yaml
3.2 部署 Redis
创建 k8s-manifests/02-redis.yaml。Redis 通常也建议进行数据持久化。
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-deployment
spec:
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
command: ["redis-server"]
args: ["--appendonly", "yes"] # 启用AOF持久化
ports:
- containerPort: 6379
volumeMounts:
- name: redis-data
mountPath: /data
volumes:
- name: redis-data
emptyDir: {} # 简单示例,生产环境建议使用PVC
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
type: ClusterIP
应用配置:kubectl apply -f k8s-manifests/02-redis.yaml
3.3 部署 .NET Core WebAPI
创建 k8s-manifests/03-webapi.yaml。这是最核心的部分,需要配置环境变量、健康检查探针和资源限制。
yaml
# 将数据库连接密码等敏感信息存入Secret
apiVersion: v1
kind: Secret
metadata:
name: webapi-secret
type: Opaque
stringData:
mysql-password: "YourStrongPassword123!"
redis-connection: "redis://redis-service:6379"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapi-deployment
spec:
replicas: 2 # 运行两个副本以实现基本的高可用
selector:
matchLabels:
app: webapi
template:
metadata:
labels:
app: webapi
spec:
containers:
- name: webapi
image: yourusername/mywebapi:1.0.0 # 替换为你的实际镜像
ports:
- containerPort: 80
env:
# 从Secret和硬编码(仅为示例,生产环境应全放Secret)注入连接字符串
- name: ConnectionStrings__MySqlConnection
value: "Server=mysql-service;Port=3306;Database=mydb;User=root;Password=$(MYSQL_ROOT_PASSWORD);"
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: webapi-secret
key: mysql-password
- name: ConnectionStrings__RedisConnection
valueFrom:
secretKeyRef:
name: webapi-secret
key: redis-connection
# 健康检查是关键配置,让K8s能管理应用的生命周期
livenessProbe:
httpGet:
path: /healthz # 你的应用需要实现健康检查端点
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
---
# 内部服务,用于Ingress或服务间通信
apiVersion: v1
kind: Service
metadata:
name: webapi-service
spec:
selector:
app: webapi
ports:
- port: 80
targetPort: 80
type: ClusterIP
应用配置:kubectl apply -f k8s-manifests/03-webapi.yaml
3.4 部署 Nginx Ingress
首先,确保你的 Kubernetes 集群已经安装了 Ingress-NGINX 控制器 。安装方法因集群而异。
创建 k8s-manifests/04-ingress.yaml,定义外部访问规则。
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: webapi-ingress
annotations:
# 使用nginx-ingress的注解实现HTTP到HTTPS的重定向
nginx.ingress.kubernetes.io/ssl-redirect: "false" # 假设暂未配置TLS
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
spec:
ingressClassName: nginx
rules:
- host: api.yourdomain.com # 将此处替换为你的域名或Minikube IP
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapi-service
port:
number: 80
应用配置:kubectl apply -f k8s-manifests/04-ingress.yaml
四、 验证与测试
-
检查所有资源状态:
bashkubectl get pods,svc,ingress,pvc等待所有 Pod 的状态变为
Running。 -
查看应用日志,排查启动问题:
bashkubectl logs -l app=webapi --tail=50 -
测试内部连接:
bash# 进入WebAPI的Pod执行命令 kubectl exec -it <webapi-pod-name> -- curl -v http://localhost/healthz # 测试从WebAPI Pod能否连接MySQL和Redis kubectl exec -it <webapi-pod-name> -- bash # 在Pod内执行 apt-get update && apt-get install -y mysql-client redis-tools mysql -h mysql-service -uroot -p$MYSQL_ROOT_PASSWORD redis-cli -h redis-service ping -
外部访问测试:
- Minikube :
minikube service webapi-service --url(如果使用Service类型为NodePort,此教程为ClusterIP,由Ingress暴露)。 - 通过Ingress : 获取Ingress的外部IP (
kubectl get ingress),然后使用curl -H "Host: api.yourdomain.com" http://<INGRESS_IP>或配置本地hosts文件后访问。
- Minikube :
五、 核心配置与连接总结
为了方便你理解,以下是两个关键的连接与检查配置表:
服务连接配置摘要
| 组件 | 在 K8s 中的 Service 名称 | 端口 | 在 .NET Core 连接字符串中的地址示例 |
|---|---|---|---|
| MySQL | mysql-service |
3306 | Server=mysql-service;Port=3306;... |
| Redis | redis-service |
6379 | redis-service:6379 |
| WebAPI | webapi-service |
80 | 内部服务,供 Ingress 或其他服务调用 |
.NET Core 健康检查端点配置(示例)
在 Program.cs 中添加健康检查,这是配置 K8s 探针 (livenessProbe, readinessProbe) 的基础。
csharp
var builder = WebApplication.CreateBuilder(args);
// 添加健康检查服务
builder.Services.AddHealthChecks();
// 可以添加针对MySQL、Redis的特定健康检查,例如:
// builder.Services.AddHealthChecks().AddMySql(...).AddRedis(...);
var app = builder.Build();
// 映射健康检查端点
app.MapHealthChecks("/healthz"); // 用于存活探针
app.MapHealthChecks("/ready"); // 用于就绪探针
后续建议
- 生产环境安全:务必使用更安全的方式管理密码(如 HashiCorp Vault 或云厂商的密钥管理服务),并考虑为 MySQL 和 Redis 配置密码认证。
- 配置管理 :将更多配置(如数据库名、超时时间)移入
ConfigMap。 - 网络策略 :定义
NetworkPolicy来限制 Pod 之间的网络流量,实现最小权限访问。 - 使用 Helm :当应用复杂时,使用 Helm Chart 来打包和管理所有这些 YAML 文件,实现参数化部署。
