
文章目录
这里整理了一份将 .NET Core WebAPI 项目(包含 MySQL、Redis、Nginx)部署到 Kubernetes 的全流程指南。教程的核心步骤已在下图中展示,可以通过它快速了解部署流程与各组件间的联系。
一、 环境与项目准备
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 或通过环境变量的配置支持从外部读取数据库和缓存连接字符串。这是云原生应用配置的关键。
{
"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,推荐使用多阶段构建以减小最终镜像体积。
# 构建阶段
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、阿里云容器镜像服务等):
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 重启后数据丢失。
# 持久化存储声明
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 通常也建议进行数据持久化。
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。这是最核心的部分,需要配置环境变量、健康检查探针和资源限制。
# 将数据库连接密码等敏感信息存入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,定义外部访问规则。
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
四、 验证与测试
-
检查所有资源状态:
kubectl get pods,svc,ingress,pvc等待所有 Pod 的状态变为
Running。 -
查看应用日志,排查启动问题:
kubectl logs -l app=webapi --tail=50 -
测试内部连接:
# 进入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) 的基础。
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 文件,实现参数化部署。

8799





