Введение: Почему C# и Kubernetes — это мощная связка
Современная разработка всё чаще требует не просто написать код, но и правильно его упаковать и запустить в облачной среде. Kubernetes (или K8s) стал стандартом де-факто для оркестрации контейнеров, а C# (.NET) — одним из самых популярных языков для создания высоконагруженных веб-приложений и микросервисов.
В этом руководстве мы пройдём путь от готового приложения на C# до его полноценного деплоя в кластер Kubernetes. Вы узнаете, как создать Docker-образ, написать манифесты для развертывания и сервиса, а затем запустить всё с помощью kubectl. Никакой магии — только практика.
Шаг 1: Подготовка .NET приложения и контейнеризация
1.1 Создание простого веб-API на C#
Для демонстрации мы создадим минимальный ASP.NET Core Web API. Откройте терминал и выполните:
dotnet new webapi -n MyK8sApp
cd MyK8sApp
По умолчанию проект уже содержит контроллер WeatherForecastController. Убедимся, что приложение запускается локально:
dotnet run
Перейдите по адресу http://localhost:5000/weatherforecast — вы должны увидеть JSON-ответ. Теперь наше приложение готово к упаковке.
1.2 Создание Dockerfile
Деплой в Kubernetes невозможен без контейнеризации. Создадим файл Dockerfile в корне проекта:
# Используем официальный образ для сборки
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app
# Копируем файлы проекта и восстанавливаем зависимости
COPY *.csproj .
RUN dotnet restore
# Копируем остальные файлы и собираем приложение
COPY . .
RUN dotnet publish -c Release -o out
# Финальный образ — только runtime
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /app/out .
ENTRYPOINT ["dotnet", "MyK8sApp.dll"]
Обратите внимание: мы используем многоступенчатую сборку (multi-stage build) — это уменьшает итоговый размер образа и повышает безопасность.
1.3 Сборка и проверка Docker-образа
Соберите образ и запустите его локально:
docker build -t myk8sapp:latest .
docker run -d -p 8080:80 --name myapp myk8sapp:latest
Проверьте работу: http://localhost:8080/weatherforecast. Если всё работает — отлично. Остановите контейнер:
docker stop myapp && docker rm myapp
Шаг 2: Основы Kubernetes — что нужно знать для деплоя
Прежде чем писать манифесты, разберёмся с ключевыми понятиями Kubernetes:
- Pod — минимальная единица развертывания. Содержит один или несколько контейнеров.
- Deployment — управляет состоянием Pod'ов: масштабирование, обновления, восстановление после сбоев.
- Service — абстракция, которая обеспечивает сетевой доступ к Pod'ам. Обычно используется типа
ClusterIP(внутренний) илиLoadBalancer(внешний). - ConfigMap / Secret — для хранения конфигурации и чувствительных данных.
Мы будем использовать minikube для локального тестирования. Установите его по официальной инструкции.
Запустите кластер:
minikube start
Шаг 3: Создание манифестов Kubernetes для C# приложения
3.1 Манифест Deployment
Создайте файл deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myk8sapp-deployment
spec:
replicas: 3
selector:
matchLabels:
app: myk8sapp
template:
metadata:
labels:
app: myk8sapp
spec:
containers:
- name: myk8sapp
image: myk8sapp:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
Здесь мы указываем:
replicas: 3— запустим 3 копии приложения для отказоустойчивости.image: myk8sapp:latest— наш образ. Важно: для minikube образ должен быть доступен локально (см. ниже).containerPort: 80— приложение слушает порт 80 (как в Dockerfile).
Важно! Чтобы minikube использовал локальный образ, выполните:
minikube image load myk8sapp:latest
Либо укажите imagePullPolicy: Never.
3.2 Манифест Service
Создайте файл service.yaml:
apiVersion: v1
kind: Service
metadata:
name: myk8sapp-service
spec:
type: NodePort
selector:
app: myk8sapp
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
Тип NodePort позволяет обратиться к приложению через IP узла кластера и порт 30080. Для продакшена обычно используют LoadBalancer или Ingress.
Шаг 4: Развертывание и тестирование
4.1 Применение манифестов
Убедитесь, что вы находитесь в папке с deployment.yaml и service.yaml. Выполните команды:
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
Проверьте статус подов: