Mikroservis mimarisi, uygulamaları daha küçük, bağımsız ve yönetilebilir parçalara ayırma stratejisidir. Bu mimarinin karmaşıklığını yönetmek için güçlü bir orkestrasyon aracına ihtiyaç vardır. İşte tam da burada Kubernetes devreye giriyor. Bu blog yazısında, Kubernetes’in temel objelerini, manifest dosyalarının nasıl yazılacağını ve Helm Charts ile uygulama paketlemeyi detaylıca inceleyeceğiz.
1. Kubernetes Objeleri
Kubernetes, çeşitli objeler aracılığıyla konteynerize edilmiş uygulamaları yönetir. Bu bölümde, en temel ve sık kullanılan Kubernetes objelerini inceleyeceğiz.
1.1. Pod
Pod, Kubernetes’teki en küçük ve en temel birimdir. Bir veya daha fazla container’ı gruplar ve aynı kaynakları paylaşmalarını sağlar.
Örnek bir Pod YAML manifestı:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx:latest
ports:
- containerPort: 80
```
Bu manifest:
1. `my-pod` adında bir Pod oluşturur.
2. `nginx:latest` imajını kullanan bir container içerir.
3. Container’ın 80 portunu expose eder.
1.2. Deployment
Deployment, Pod’ların istenen sayıda çalışmasını ve güncellemelerini yönetir.
Örnek bir Deployment manifestı:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-app:v1
ports:
- containerPort: 8080
```
Bu manifest:
1. `my-deployment` adında bir Deployment oluşturur.
2. 3 replika oluşturur.
3. `app: my-app` etiketine sahip Pod’ları seçer.
4. `my-app:v1` imajını kullanan container’lar oluşturur.
1.3. Service
Service, Pod’lara sabit bir IP adresi ve DNS adı sağlayarak, uygulamanın diğer bileşenler tarafından keşfedilebilmesini sağlar.
Örnek bir Service manifestı:
```yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
```
Bu manifest:
1. `my-service` adında bir Service oluşturur.
2. `app: my-app` etiketine sahip Pod’ları seçer.
3. 80 portunu 8080 portuna yönlendirir.
4. `ClusterIP` tipinde bir service oluşturur (cluster içinden erişilebilir).
1.4. Ingress
Ingress, cluster dışından HTTP ve HTTPS trafiğini yönetir ve routing kuralları tanımlar.
Örnek bir Ingress manifestı:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
```
Bu manifest:
1. `my-ingress` adında bir Ingress oluşturur.
2. `myapp.example.com` host’u için bir kural tanımlar.
3. `/api` path’ini `my-service` adlı service’e yönlendirir.
2. Kubernetes Manifest Dosyaları Yazma
Kubernetes manifest dosyaları, cluster’ınızda oluşturmak istediğiniz kaynakları tanımlayan YAML dosyalarıdır. İyi bir manifest dosyası yazmak için bazı best practice’leri takip etmelisiniz.
2.1. Manifest Dosyası Yapısı
Bir Kubernetes manifest dosyası genellikle şu bölümlerden oluşur:
1. `apiVersion`: Kullanılan Kubernetes API versiyonu
2. `kind`: Oluşturulacak kaynağın türü (örn. Pod, Deployment, Service)
3. `metadata`: İsim, namespace, etiketler gibi meta bilgiler
4. `spec`: Kaynağın özelliklerini tanımlayan bölüm
2.2. Çoklu Kaynak Tanımlama
Bir YAML dosyasında birden fazla kaynak tanımlayabilirsiniz. Kaynakları `—` ile ayırın:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
Deployment özellikleri...
---
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
Service özellikleri...
```
2.3. Ortam Değişkenleri Kullanımı
Container’lara ortam değişkenleri geçmek için `env` veya `envFrom` kullanabilirsiniz:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: my-container
image: my-app:v1
env:
- name: DATABASE_URL
value: "mysql://user:password@db-service:3306/mydb"
envFrom:
- configMapRef:
name: my-config
```
2.4. ConfigMap ve Secret Kullanımı
Konfigürasyon ve hassas bilgileri ayrı tutmak için ConfigMap ve Secret objelerini kullanın:
ConfigMap örneği:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
APP_COLOR: blue
APP_MODE: production
```
Secret örneği:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
DB_PASSWORD: base64EncodedPassword
```
Bu ConfigMap ve Secret'ları Pod'larda kullanma:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: my-container
image: my-app:v1
envFrom:
- configMapRef:
name: my-config
env:
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: my-secret
key: DB_PASSWORD
```
2.5. Resource Limits ve Requests
Container’ların kullanabileceği kaynakları sınırlamak ve garanti etmek için resource limits ve requests kullanın:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: my-container
image: my-app:v1
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
```
2.6. Health Checks
Liveness ve readiness probe’ları kullanarak uygulamanızın sağlığını kontrol edin:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: my-container
image: my-app:v1
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 3
periodSeconds: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
```
3. Helm Charts ile Uygulama Paketleme
Helm, Kubernetes uygulamalarını paketlemek, paylaşmak ve dağıtmak için kullanılan bir paket yöneticisidir. Helm Charts, uygulamanızın tüm Kubernetes kaynaklarını tek bir pakette toplamanıza olanak tanır.
3.1. Helm Chart Yapısı
Tipik bir Helm Chart yapısı şu şekildedir:
```
mychart/
Chart.yaml
values.yaml
charts/
templates/
deployment.yaml
service.yaml
ingress.yaml
charts/
README.md
```
– `Chart.yaml`: Chart’ın meta bilgilerini içerir.
– `values.yaml`: Varsayılan konfigürasyon değerlerini içerir.
– `templates/`: Kubernetes manifest şablonlarını içerir.
– `charts/`: Bağımlı chart’ları içerir (opsiyonel).
3.2. Chart.yaml Örneği
```yaml
apiVersion: v2
name: my-app
description: A Helm chart for my awesome app
version: 0.1.0
appVersion: "1.0.0"
```
3.3. values.yaml Örneği
```yaml
replicaCount: 2
image:
repository: myrepo/myapp
tag: v1.0.0
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: false
```
3.4. Template Örnekleri
deployment.yaml:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-app.fullname" . }}
spec:
replicas: {{ .Values.replicaCount }}
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: 80
protocol: TCP
```
service.yaml:
```yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include "my-app.fullname" . }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "my-app.selectorLabels" . | nindent 4 }}
```
3.5. Helm Komutları
Helm Chart oluşturma:
```
helm create my-app
```
Helm Chart'ı yükleme:
```
helm install my-release ./my-app
```
Değerleri override ederek yükleme:
```
helm install my-release ./my-app --set replicaCount=3
```
Helm Chart'ı güncelleme:
```
helm upgrade my-release ./my-app
```
Yüklü release'leri listeleme:
```
helm list
```
Bir release'i kaldırma:
```
helm uninstall my-release
```
3.6. Helm Chart Best Practices
1. **Parametreleştirme**: Mümkün olduğunca çok değeri `values.yaml` dosyasında parametreleştirin.
2. **Koşullu Kaynak Oluşturma**: Bazı kaynakları koşullu olarak oluşturmak için if-else yapılarını kullanın:
```yaml
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
...
{{- end }}
3. **Helper Fonksiyonlar**: Tekrar eden mantığı `_helpers.tpl` dosyasında tanımlayın:
```yaml
{{/* Generate basic labels */}}
{{- define "my-app.labels" -}}
app.kubernetes.io/name: {{ include "my-app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
```
4. **Bağımlılıkları Yönetme**: Bağımlı chart’ları `Chart.yaml` dosyasında belirtin:
```yaml
dependencies:
- name: mysql
version: 8.8.3
repository: https://charts.bitnami.com/bitnami
condition: mysql.enabled
```
5. **Doğrulama**: `helm lint` komutunu kullanarak chart’ınızı doğrulayın.
6. **Sürüm Kontrolü**: Chart’ınızı bir versiyon kontrol sistemi (örn. Git) ile yönetin.
4. Mikroservis Uygulaması Örneği
Şimdi, öğrendiğimiz tüm bu konseptleri bir araya getirerek basit bir e-ticaret mikroservis uygulaması için Kubernetes manifestları ve Helm Chart oluşturalım.
4.1. Uygulama Mimarisi
Uygulamamız şu mikroservislerden oluşacak:
– Product Service
– Order Service
– User Service
– API Gateway
4.2. Kubernetes Manifestları
product-deployment.yaml:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: product-service
spec:
replicas: 2
selector:
matchLabels:
app: product-service
template:
metadata:
labels:
app: product-service
spec:
containers:
- name: product-service
image: myrepo/product-service:v1
ports:
- containerPort: 8080
env:
- name: DB_HOST
value: product-db-service
```
product-service.yaml:
```yaml
apiVersion: v1
kind: Service
metadata:
name: product-service
spec:
selector:
app: product-service
ports:
- port: 80
targetPort: 8080
```
Benzer şekilde, diğer servisler için de Deployment ve Service manifestları oluşturulmalıdır.
api-gateway-ingress.yaml:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-gateway
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: myecommerce.com
http:
paths:
- path: /products
pathType: Prefix
backend:
service:
name: product-service
port:
number: 80
- path: /orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 80
- path: /users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
```
4.3. Helm Chart Oluşturma
Şimdi bu mikroservis uygulaması için bir Helm Chart oluşturalım:
```
helm create ecommerce-app
```
values.yaml:
```yaml
global:
environment: production
productService:
replicaCount: 2
image:
repository: myrepo/product-service
tag: v1
orderService:
replicaCount: 2
image:
repository: myrepo/order-service
tag: v1
userService:
replicaCount: 2
image:
repository: myrepo/user-service
tag: v1
apiGateway:
enabled: true
host: myecommerce.com
```
templates/product-deployment.yaml:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "ecommerce-app.fullname" . }}-product
spec:
replicas: {{ .Values.productService.replicaCount }}
selector:
matchLabels:
app: product-service
template:
metadata:
labels:
app: product-service
spec:
containers:
- name: product-service
image: "{{ .Values.productService.image.repository }}:{{ .Values.productService.image.tag }}"
ports:
- containerPort: 8080
env:
- name: ENVIRONMENT
value: {{ .Values.global.environment }}
```
Benzer şekilde, diğer servisler için de template'ler oluşturulmalıdır.
templates/ingress.yaml:
```yaml
{{- if .Values.apiGateway.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "ecommerce-app.fullname" . }}-gateway
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: {{ .Values.apiGateway.host }}
http:
paths:
- path: /products
pathType: Prefix
backend:
service:
name: {{ include "ecommerce-app.fullname" . }}-product
port:
number: 80
- path: /orders
pathType: Prefix
backend:
service:
name: {{ include "ecommerce-app.fullname" . }}-order
port:
number: 80
- path: /users
pathType: Prefix
backend:
service:
name: {{ include "ecommerce-app.fullname" . }}-user
port:
number: 80
{{- end }}
```
4.4. Helm Chart’ı Yükleme
Chart’ı yüklemek için:
```
helm install my-ecommerce ./ecommerce-app
```
Belirli değerleri override etmek için:
```
helm install my-ecommerce ./ecommerce-app --set productService.replicaCount=3 --set global.environment=staging
```
5. Sonuç
Bu blog yazısında, Kubernetes ile mikroservis orkestrasyonunun temellerini, Kubernetes objelerini, manifest dosyası yazma tekniklerini ve Helm Charts ile uygulama paketlemeyi detaylı bir şekilde inceledik.
Kubernetes, mikroservis mimarisinin karmaşıklığını yönetmek için güçlü araçlar sunar. Pod’lar, Deployment’lar, Service’ler ve Ingress’ler gibi temel Kubernetes objeleri, mikroservisleri ölçeklendirmek, yönetmek ve dış dünyaya açmak için gerekli yapı taşlarını oluşturur.
Manifest dosyaları, bu Kubernetes objelerini dekleratif bir şekilde tanımlamanıza olanak tanır. İyi yazılmış manifest dosyaları, uygulamanızın istenen durumunu net bir şekilde ifade eder ve Kubernetes’in bu durumu korumasını sağlar.
Helm ise, tüm bu manifest dosyalarını tek bir paket halinde yönetmenize, versiyonlamanıza ve dağıtmanıza olanak tanır. Helm Charts, mikroservis uygulamalarınızı farklı ortamlara kolayca dağıtmanızı ve yönetmenizi sağlar.