HELM, Package Management va GitOps
Mundarija
Package Management Asoslari
Muammo
Kubernetes application deploy qilish murakkab:
Oddiy Application:
- Deployment
- Service
- ConfigMap
- Secret
- Ingress
- PersistentVolumeClaim
- ServiceAccount
- RBAC rules
- ...
Muammolar:
- Ko'p YAML file'lar
- Har bir environment uchun alohida file'lar
- Versioning qiyin
- Dependency management yo'q
- Rollback murakkab
Yechim: Package Managers
Ikkita asosiy yondashuv:
- Templating: Helm
- Overlays: Kustomize
Helm
Ta'rif
Helm - bu Kubernetes uchun package manager (apt, yum, brew kabi).
Asosiy Kontseptsiyalar:
- Chart: Kubernetes resource'larini o'z ichiga olgan package
- Release: Chart'ning cluster'da deploy qilingan instance
- Repository: Chart'lar saqlanadigan joy
Helm Architecture
Helm 3 Architecture:
helm CLI → Kubernetes API Server → Kubernetes Cluster
Helm 2 (deprecated):
helm CLI → Tiller (server) → Kubernetes API Server
Helm 3'da Tiller o'chirildi (security reasons).
Helm Installation
Script:
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
Package Manager:
# macOS
brew install helm
# Ubuntu/Debian
sudo snap install helm --classic
# Windows (Chocolatey)
choco install kubernetes-helm
Verify:
helm version
Helm Repositories
Add repo:
# Bitnami
helm repo add bitnami https://charts.bitnami.com/bitnami
# Stable (archived)
helm repo add stable https://charts.helm.sh/stable
# Prometheus
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
Update:
helm repo update
Search:
# Search in repos
helm search repo nginx
# Search Artifact Hub
helm search hub wordpress
Installing Charts
Basic Install:
helm install my-release bitnami/nginx
Custom Values:
helm install my-release bitnami/nginx \
--set replicaCount=3 \
--set service.type=LoadBalancer
Values File:
# values.yaml
replicaCount: 3
service:
type: LoadBalancer
port: 80
ingress:
enabled: true
hostname: myapp.example.com
helm install my-release bitnami/nginx -f values.yaml
Namespace:
helm install my-release bitnami/nginx \
--namespace production \
--create-namespace
Helm Commands
List Releases
# All releases
helm list
# All namespaces
helm list --all-namespaces
# Specific namespace
helm list -n production
Upgrade
# Upgrade
helm upgrade my-release bitnami/nginx -f values.yaml
# Install or upgrade
helm upgrade --install my-release bitnami/nginx
Rollback
# Rollback to previous
helm rollback my-release
# Rollback to specific revision
helm rollback my-release 3
History
helm history my-release
Output:
REVISION UPDATED STATUS CHART DESCRIPTION
1 Mon Jan 1 10:00:00 2024 superseded nginx-1.0.0 Install complete
2 Mon Jan 1 11:00:00 2024 superseded nginx-1.1.0 Upgrade complete
3 Mon Jan 1 12:00:00 2024 deployed nginx-1.2.0 Upgrade complete
Uninstall
helm uninstall my-release
# Keep history
helm uninstall my-release --keep-history
Get Values
# Default values
helm show values bitnami/nginx
# Current values
helm get values my-release
# All values (including defaults)
helm get values my-release --all
Creating Charts
Chart Structure:
mychart/
├── Chart.yaml # Chart metadata
├── values.yaml # Default values
├── charts/ # Dependencies
├── templates/ # Kubernetes manifests (templates)
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── _helpers.tpl # Template helpers
│ └── NOTES.txt # Post-install notes
└── .helmignore # Files to ignore
Create Chart:
helm create mychart
Chart.yaml
apiVersion: v2
name: mychart
description: A Helm chart for my application
type: application
version: 1.0.0 # Chart version
appVersion: "1.0" # Application version
maintainers:
- name: John Doe
email: john@example.com
dependencies:
- name: postgresql
version: "12.x.x"
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled
values.yaml
replicaCount: 2
image:
repository: myapp
tag: "1.0.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: false
className: nginx
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
autoscaling:
enabled: false
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "mychart.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "mychart.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 80
protocol: TCP
resources:
{{- toYaml .Values.resources | nindent 10 }}
templates/_helpers.tpl
{{/*
Expand the name of the chart.
*/}}
{{- define "mychart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "mychart.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 "mychart.labels" -}}
helm.sh/chart: {{ include "mychart.chart" . }}
{{ include "mychart.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "mychart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "mychart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
Template Functions
Built-in Objects:
.Values: values.yaml.Chart: Chart.yaml.Release: Release info.Files: Chart file'lar.Capabilities: Cluster capabilities
Functions:
String:
# Upper/Lower
{{ .Values.name | upper }}
{{ .Values.name | lower }}
# Quote
{{ .Values.name | quote }}
# Default
{{ .Values.name | default "myapp" }}
# Trim
{{ .Values.name | trim }}
Logic:
# If/Else
{{- if .Values.ingress.enabled }}
# Ingress config
{{- else }}
# No ingress
{{- end }}
# Ternary
{{ .Values.service.type | default (ternary "ClusterIP" "LoadBalancer" .Values.production) }}
List:
# Range
{{- range .Values.hosts }}
- {{ . }}
{{- end }}
Yaml:
# toYaml
resources:
{{- toYaml .Values.resources | nindent 2 }}
# nindent: newline + indent
Helm Testing
Test File: templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "mychart.fullname" . }}-test-connection"
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "mychart.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never
Run Test:
helm test my-release
Helm Hooks
Hook Annotations:
pre-install: Before installpost-install: After installpre-delete: Before deletepost-delete: After deletepre-upgrade: Before upgradepost-upgrade: After upgradepre-rollback: Before rollbackpost-rollback: After rollbacktest: Test hooks
Example:
apiVersion: batch/v1
kind: Job
metadata:
name: "{{ .Release.Name }}-db-migrate"
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-weight": "1"
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
containers:
- name: migrate
image: myapp:{{ .Values.image.tag }}
command: ["/bin/sh", "-c", "rake db:migrate"]
restartPolicy: Never
Helm Dependencies
Chart.yaml:
dependencies:
- name: postgresql
version: "12.x.x"
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled
- name: redis
version: "17.x.x"
repository: https://charts.bitnami.com/bitnami
condition: redis.enabled
Update Dependencies:
helm dependency update mychart
values.yaml:
postgresql:
enabled: true
auth:
username: myapp
password: secret
database: myapp_db
redis:
enabled: true
auth:
password: secret
Kustomize
Ta'rif
Kustomize - bu template-free Kubernetes configuration management tool.
Helm vs Kustomize:
| Helm | Kustomize |
|---|---|
| Templating | Overlays |
| values.yaml | patches |
| Complex | Simple |
| Package manager | Configuration manager |
Kustomize Asoslari
Base + Overlays:
kustomize/
├── base/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
├── overlays/
│ ├── development/
│ │ ├── kustomization.yaml
│ │ └── replica-patch.yaml
│ └── production/
│ ├── kustomization.yaml
│ ├── replica-patch.yaml
│ └── resource-patch.yaml
Base Configuration
base/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0.0
ports:
- containerPort: 8080
base/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
base/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
commonLabels:
app: myapp
managed-by: kustomize
Overlays
overlays/development/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
namePrefix: dev-
commonLabels:
environment: development
patches:
- path: replica-patch.yaml
overlays/development/replica-patch.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 2
overlays/production/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
namePrefix: prod-
commonLabels:
environment: production
patches:
- path: replica-patch.yaml
- path: resource-patch.yaml
images:
- name: myapp
newTag: 2.0.0
Kustomize Commands
Build:
# Development
kubectl kustomize overlays/development
# Production
kubectl kustomize overlays/production
Apply:
# Development
kubectl apply -k overlays/development
# Production
kubectl apply -k overlays/production
Kustomize Features
1. ConfigMap/Secret Generator
configMapGenerator:
- name: app-config
literals:
- APP_ENV=production
- LOG_LEVEL=info
files:
- config.properties
secretGenerator:
- name: app-secret
literals:
- DB_PASSWORD=secret123
type: Opaque
2. Images
images:
- name: myapp
newName: myregistry.com/myapp
newTag: v2.0.0
3. Replicas
replicas:
- name: myapp
count: 5
4. Namespace
namespace: production
5. Name Prefix/Suffix
namePrefix: prod-
nameSuffix: -v1
GitOps
Ta'rif
GitOps - bu Git'ni single source of truth sifatida ishlatib, infrastructure va application'larni declarative boshqarish.
Principles:
- Declarative: Desired state Git'da
- Versioned: Git history
- Immutable: Git commits
- Pulled Automatically: Agent cluster'da o'zgarishlarni pull qiladi
GitOps Workflow
Developer → Git Push → Git Repository
↓
GitOps Operator
↓
Kubernetes Cluster
Traditional vs GitOps:
| Traditional (Push) | GitOps (Pull) |
|---|---|
| CI/CD pushes to cluster | Operator pulls from Git |
| kubectl apply | Automated sync |
| Manual | Declarative |
| Access to cluster needed | Git access only |
GitOps Tools
- ArgoCD (CNCF)
- Flux (CNCF)
- Jenkins X
- Tekton
ArgoCD
Ta'rif
ArgoCD - bu Kubernetes uchun declarative GitOps continuous delivery tool.
Installation
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Access UI:
# Port forward
kubectl port-forward svc/argocd-server -n argocd 8080:443
# Get admin password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
# Login: admin / <password>
Application
application.yaml:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/myapp-config
targetRevision: main
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Apply:
kubectl apply -f application.yaml
Sync Strategies
1. Manual Sync
syncPolicy: {}
UI yoki CLI orqali qo'lda sync.
2. Automated Sync
syncPolicy:
automated:
prune: true # Remove resources not in Git
selfHeal: true # Revert manual changes
ArgoCD CLI
Install:
# macOS
brew install argocd
# Linux
curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
chmod +x /usr/local/bin/argocd
Login:
argocd login localhost:8080
Create App:
argocd app create myapp \
--repo https://github.com/myorg/myapp-config \
--path k8s \
--dest-server https://kubernetes.default.svc \
--dest-namespace production
Sync:
argocd app sync myapp
Status:
argocd app get myapp
Multi-Cluster
# Add cluster
argocd cluster add <context-name>
# List clusters
argocd cluster list
Application:
destination:
server: https://my-other-cluster.example.com
namespace: production
App of Apps Pattern
Root Application:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/gitops
path: apps
destination:
server: https://kubernetes.default.svc
namespace: argocd
apps/ directory:
apps/
├── app1.yaml
├── app2.yaml
└── app3.yaml
Flux
Ta'rif
Flux - bu Kubernetes uchun GitOps toolkit.
Installation
# Install Flux CLI
curl -s https://fluxcd.io/install.sh | sudo bash
# Bootstrap
flux bootstrap github \
--owner=myorg \
--repository=fleet-infra \
--branch=main \
--path=clusters/my-cluster \
--personal
GitRepository
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: myapp
namespace: flux-system
spec:
interval: 1m
url: https://github.com/myorg/myapp-config
ref:
branch: main
Kustomization
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: myapp
namespace: flux-system
spec:
interval: 10m
sourceRef:
kind: GitRepository
name: myapp
path: ./k8s
prune: true
wait: true
timeout: 5m
HelmRelease
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: myapp
namespace: production
spec:
interval: 10m
chart:
spec:
chart: myapp
version: '1.x.x'
sourceRef:
kind: HelmRepository
name: myrepo
values:
replicaCount: 3
image:
tag: v2.0.0
Image Automation
ImageRepository:
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
name: myapp
namespace: flux-system
spec:
image: myregistry.com/myapp
interval: 1m
ImagePolicy:
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
name: myapp
namespace: flux-system
spec:
imageRepositoryRef:
name: myapp
policy:
semver:
range: 1.0.x
ImageUpdateAutomation:
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageUpdateAutomation
metadata:
name: myapp
namespace: flux-system
spec:
sourceRef:
kind: GitRepository
name: myapp
interval: 1m
git:
commit:
author:
name: fluxbot
email: flux@example.com
update:
strategy: Setters
path: ./k8s
Best Practices
1. Helm Best Practices
Chart Structure:
- Clear naming conventions
- Comprehensive values.yaml
- Good documentation (README.md)
- Meaningful default values
Versioning:
- Semantic versioning (semver)
- Chart version ≠ App version
- Changelog
Security:
- Don't commit secrets
- Use external secret management
- RBAC for chart install
Testing:
- Helm test
- Helm lint
- Chart unit tests (helm-unittest)
2. GitOps Best Practices
Repository Structure:
gitops-repo/
├── apps/
│ ├── app1/
│ ├── app2/
│ └── app3/
├── infrastructure/
│ ├── monitoring/
│ ├── ingress/
│ └── storage/
└── clusters/
├── development/
├── staging/
└── production/
Branch Strategy:
main: Productionstaging: Stagingdev: Development
Pull Requests:
- Code review
- Automated tests
- Preview environments
Secrets:
- Never commit plain secrets
- Use Sealed Secrets or External Secrets
3. Multi-Environment
Helm:
mychart/
├── values.yaml # Default
├── values-dev.yaml
├── values-staging.yaml
└── values-prod.yaml
helm install myapp mychart -f values-prod.yaml
Kustomize:
kustomize/
├── base/
└── overlays/
├── dev/
├── staging/
└── prod/
4. CI/CD Integration
Pipeline:
1. Code Push → Git
2. Build → Docker Image
3. Tag Image → Registry
4. Update Git Manifests → GitOps Repo
5. ArgoCD/Flux Syncs → Cluster
Xulosa
Kubernetes Package Management va GitOps:
✅ Helm: Template-based package manager ✅ Kustomize: Overlay-based configuration ✅ GitOps: Git as single source of truth ✅ ArgoCD: Declarative continuous delivery ✅ Flux: GitOps toolkit
GitOps Afzalliklari:
- Version control
- Audit trail
- Disaster recovery
- Declarative
- Automated
Bu bilan Kubernetes to'liq nazariy kurs yakunlandi!
Barcha Mavzular:
- Kirish va Asoslar
- Workload Resources
- Networking, Service, Ingress
- Storage va Volumes
- ConfigMap, Secret
- RBAC, Security
- Monitoring, Logging
- Auto-scaling, Resource Management
- Helm, GitOps
Keyingi Qadamlar:
- Hands-on practice
- Real projects
- CKA/CKAD certification
- Production experience