Skip to main content

HELM, Package Management va GitOps

Mundarija

  1. Package Management Asoslari
  2. Helm
  3. Kustomize
  4. GitOps
  5. ArgoCD
  6. Flux
  7. Best Practices

Package Management Asoslari

Muammo

Kubernetes application deploy qilish murakkab:

Oddiy Application:

  • Deployment
  • Service
  • ConfigMap
  • Secret
  • Ingress
  • PersistentVolumeClaim
  • ServiceAccount
  • RBAC rules
  • ...

Muammolar:

  1. Ko'p YAML file'lar
  2. Har bir environment uchun alohida file'lar
  3. Versioning qiyin
  4. Dependency management yo'q
  5. Rollback murakkab

Yechim: Package Managers

Ikkita asosiy yondashuv:

  1. Templating: Helm
  2. 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 install
  • post-install: After install
  • pre-delete: Before delete
  • post-delete: After delete
  • pre-upgrade: Before upgrade
  • post-upgrade: After upgrade
  • pre-rollback: Before rollback
  • post-rollback: After rollback
  • test: 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:

HelmKustomize
TemplatingOverlays
values.yamlpatches
ComplexSimple
Package managerConfiguration 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:

  1. Declarative: Desired state Git'da
  2. Versioned: Git history
  3. Immutable: Git commits
  4. 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 clusterOperator pulls from Git
kubectl applyAutomated sync
ManualDeclarative
Access to cluster neededGit access only

GitOps Tools

  1. ArgoCD (CNCF)
  2. Flux (CNCF)
  3. Jenkins X
  4. 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: Production
  • staging: Staging
  • dev: 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:

  1. Kirish va Asoslar
  2. Workload Resources
  3. Networking, Service, Ingress
  4. Storage va Volumes
  5. ConfigMap, Secret
  6. RBAC, Security
  7. Monitoring, Logging
  8. Auto-scaling, Resource Management
  9. Helm, GitOps

Keyingi Qadamlar:

  • Hands-on practice
  • Real projects
  • CKA/CKAD certification
  • Production experience