Развёртывание в K8s через Helm, kubectl, GitOps-подходы.
Kubernetes — стандарт де-факто для оркестрации контейнеров. Изучите деплой через kubectl, Helm, GitOps-подходы и лучшие практики для production.
| Способ | Сложность | Гибкость | Использование |
|---|---|---|---|
| kubectl apply | Низкая | Средняя | Быстрый деплой, development |
| kubectl set image | Низкая | Низкая | Обновление образа |
| Helm | Средняя | Высокая | Production, версионирование |
| Kustomize | Средняя | Высокая | Environment-specific configs |
| GitOps (ArgoCD) | Высокая | Очень высокая | Production, audit trail |
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: myregistry/my-app:v1.0.0
ports:
- containerPort: 8080
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 20# Применить конфигурацию
kubectl apply -f deployment.yaml
# Проверить статус
kubectl get deployments
kubectl get pods
kubectl describe deployment my-app# Обновить image
kubectl set image deployment/my-app app=myregistry/my-app:v2.0.0
# С записью причины в историю
kubectl set image deployment/my-app app=myregistry/my-app:v2.0.0 --record
# Проверить статус rollout
kubectl rollout status deployment/my-app
# Просмотреть историю ревизий
kubectl rollout history deployment/my-app
# Откатиться к предыдущей версии
kubectl rollout undo deployment/my-app
# Откатиться к конкретной ревизии
kubectl rollout undo deployment/my-app --to-revision=2# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-app-config
data:
LOG_LEVEL: "info"
API_TIMEOUT: "30s"
DATABASE_HOST: "db.example.com"
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: my-app-secret
type: Opaque
stringData:
DATABASE_PASSWORD: "super-secret-password"
API_KEY: "api-key-value"# deployment.yaml с ConfigMap и Secret
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: app
image: myregistry/my-app:v1.0.0
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: my-app-config
key: LOG_LEVEL
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: my-app-secret
key: DATABASE_PASSWORD
envFrom:
- configMapRef:
name: my-app-config
- secretRef:
name: my-app-secret# Создать ConfigMap и Secret
kubectl apply -f configmap.yaml
kubectl apply -f secret.yaml
# Или создать через CLI
kubectl create configmap my-app-config \
--from-literal=LOG_LEVEL=info \
--from-literal=API_TIMEOUT=30s
kubectl create secret generic my-app-secret \
--from-literal=DATABASE_PASSWORD=super-secret \
--from-literal=API_KEY=api-keyHelm — пакетный менеджер для Kubernetes.
my-app/
├── Chart.yaml # Метаданные chart
├── values.yaml # Значения по умолчанию
├── values-staging.yaml # Переопределения для staging
├── values-prod.yaml # Переопределения для production
└── templates/
├── deployment.yaml
├── service.yaml
├── configmap.yaml
├── secret.yaml
├── ingress.yaml
└── _helpers.tpl
apiVersion: v2
name: my-app
description: My Application Helm Chart
type: application
version: 1.0.0
appVersion: "2.0.0"
keywords:
- web
- api
maintainers:
- name: DevOps Team
email: devops@example.comreplicaCount: 3
image:
repository: myregistry/my-app
tag: "2.0.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 8080
ingress:
enabled: true
className: nginx
hosts:
- host: app.example.com
paths:
- path: /
pathType: Prefix
resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 80
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 15
periodSeconds: 20apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-app.fullname" . }}
labels:
{{- include "my-app.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "my-app.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "my-app.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.targetPort }}
protocol: TCP
readinessProbe:
{{- toYaml .Values.readinessProbe | nindent 12 }}
livenessProbe:
{{- toYaml .Values.livenessProbe | nindent 12 }}
resources:
{{- toYaml .Values.resources | nindent 12 }}apiVersion: v1
kind: Service
metadata:
name: {{ include "my-app.fullname" . }}
labels:
{{- include "my-app.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
protocol: TCP
name: http
selector:
{{- include "my-app.selectorLabels" . | nindent 4 }}{{/*
Expand the name of the chart.
*/}}
{{- define "my-app.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "my-app.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "my-app.labels" -}}
helm.sh/chart: {{ include "my-app.chart" . }}
{{ include "my-app.selectorLabels" . }}
app.kubernetes.io/version: {{ .Values.image.tag | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "my-app.selectorLabels" -}}
app.kubernetes.io/name: {{ include "my-app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create chart name and version
*/}}
{{- define "my-app.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
# Установить chart
helm install my-app ./my-app -n production
# Установить с переопределением значений
helm install my-app ./my-app \
-n production \
--set image.tag=v2.0.0 \
--set replicaCount=5
# Установить с values файлом
helm install my-app ./my-app \
-n production \
-f values-prod.yaml
# Обновить релиз
helm upgrade my-app ./my-app \
-n production \
-f values-prod.yaml \
--atomic \
--timeout 5m
# Откатиться к предыдущей версии
helm rollback my-app -n production
# Просмотреть историю
helm history my-app -n production
# Удалить релиз
helm uninstall my-app -n production
# Проверить chart без установки
helm lint ./my-app
helm template my-app ./my-app -f values-prod.yaml# values-staging.yaml
replicaCount: 2
image:
tag: "latest"
resources:
limits:
cpu: 250m
memory: 128Mi
ingress:
hosts:
- host: staging.app.example.com
paths:
- path: /
pathType: Prefix
autoscaling:
enabled: false# values-prod.yaml
replicaCount: 5
image:
tag: "2.0.0"
resources:
limits:
cpu: 1000m
memory: 512Mi
ingress:
hosts:
- host: app.example.com
paths:
- path: /
pathType: Prefix
autoscaling:
enabled: true
minReplicas: 5
maxReplicas: 20Kustomize позволяет кастомизировать manifests без шаблонов.
my-app/
├── base/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
├── overlays/
│ ├── staging/
│ │ ├── patch.yaml
│ │ └── kustomization.yaml
│ └── production/
│ ├── patch.yaml
│ └── kustomization.yaml
└── kustomization.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: myregistry/my-app:v1.0.0
ports:
- containerPort: 8080apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
commonLabels:
app.kubernetes.io/name: my-app
app.kubernetes.io/managed-by: kustomizeapiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
namePrefix: staging-
commonLabels:
environment: staging
patches:
- path: patch.yaml
configMapGenerator:
- name: my-app-config
literals:
- LOG_LEVEL=debug
- ENV=stagingapiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 2
template:
spec:
containers:
- name: app
image: myregistry/my-app:latest
resources:
limits:
cpu: 250m
memory: 128Mi# Preview для staging
kubectl apply -k overlays/staging/ --dry-run=client
# Применить staging
kubectl apply -k overlays/staging/ -n staging
# Применить production
kubectl apply -k overlays/production/ -n productionArgoCD автоматически синхронизирует состояние кластера с Git репозиторием.
k8s-gitops/
├── apps/
│ └── my-app/
│ ├── Chart.yaml
│ └── values.yaml
├── environments/
│ ├── staging/
│ │ └── my-app-values.yaml
│ └── production/
│ └── my-app-values.yaml
└── argo/
└── applications/
└── my-app-staging.yaml
# argo/applications/my-app-staging.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app-staging
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/org/k8s-gitops.git
targetRevision: HEAD
path: apps/my-app
helm:
valueFiles:
- ../../environments/staging/my-app-values.yaml
destination:
server: https://kubernetes.default.svc
namespace: staging
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
- PruneLast=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3mname: GitOps Deploy
on:
push:
branches: [main]
jobs:
update-gitops:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build and push image
run: |
docker build -t myregistry/my-app:${{ github.sha }} .
docker push myregistry/my-app:${{ github.sha }}
- name: Update Helm values
run: |
sed -i "s/tag:.*/tag: \"${{ github.sha }}\"/" \
environments/production/my-app-values.yaml
- name: Commit and push
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git add environments/production/my-app-values.yaml
git commit -m "Update my-app to ${{ github.sha }}"
git pushname: Kubernetes Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Set up kubectl
uses: azure/setup-kubectl@v3
with:
version: 'v1.29.0'
- name: Configure kubectl
run: |
echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > kubeconfig
export KUBECONFIG=kubeconfig
- name: Deploy application
run: |
kubectl apply -f k8s/deployment.yaml
kubectl set image deployment/my-app \
app=myregistry/my-app:${{ github.sha }}
kubectl rollout status deployment/my-app --timeout=300s
env:
KUBECONFIG: kubeconfig
- name: Verify deployment
run: |
kubectl get pods -l app=my-app
kubectl get svc my-app
env:
KUBECONFIG: kubeconfigname: Helm Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Set up Helm
uses: azure/setup-helm@v3
with:
version: 'v3.14.0'
- name: Set up kubectl
uses: azure/setup-kubectl@v3
- name: Configure kubectl
run: |
echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > kubeconfig
export KUBECONFIG=kubeconfig
- name: Helm upgrade
run: |
helm upgrade my-app ./helm/my-app \
--install \
--namespace production \
--set image.tag=${{ github.sha }} \
--set image.repository=myregistry/my-app \
-f helm/values-prod.yaml \
--atomic \
--timeout 10m \
--wait \
--wait-for-jobs
env:
KUBECONFIG: kubeconfigВопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.