# Service Discovery and DNS #2

#### Demo Senaryosu: Kubernetes'te Service Discovery ve DNS

Bu demoda, Kubernetes ortamında uygulamaların birbirini nasıl bulduğunu (Service Discovery) adım adım test edeceğiz. Öncelikle testlerimizi yapabilmek için arkada çalışan bir Nginx uygulaması ve ona ait bir Service oluşturacağız. Ardından yeni oluşturacağımız geçici bir test *Pod*'unun, bu Nginx servisini iki farklı yöntemle (Environment Variables ve DNS) nasıl keşfettiğini inceleyeceğiz.

**1. Ön Hazırlık: Uygulamanın ve Servisin Oluşturulması (YAML)**

Öncelikle Nginx *Pod*'umuzu ve ona erişmemizi sağlayacak `nginx-service` isimli *Service* kaynağımızı yaratıyoruz. Aşağıdaki konfigürasyonu `nginx-app.yaml` adıyla kaydedip çalıştıracağız.

```yaml
# 1. Nginx uygulamasını çalıştıracak Pod
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
    - name: nginx
      image: nginx:latest
      ports:
        - containerPort: 80

---
# 2. Pod'a sabit bir IP ve isim sağlayacak Service
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: ClusterIP      # Varsayılan tip, sadece cluster içinden erişim
  selector:
    app: nginx         # Hangi Pod'lara trafik gideceğini belirler
  ports:
    - protocol: TCP
      port: 80         # Servisin dinlediği port
      targetPort: 80   # Pod'un içindeki uygulamanın portu
```

Bu dosyayı sisteme uygulayıp (apply) servisimizin durumunu kontrol edelim:

```bash
# YAML dosyasını cluster'a uyguluyoruz
kubectl apply -f nginx-app.yaml

# Servisin oluştuğunu ve IP aldığını doğruluyoruz
kubectl get svc nginx-service
```

Beklenen Çıktı:

```bash
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
nginx-service   ClusterIP   10.103.206.194   <none>        80/TCP    1m
```

Çıktıdan anlıyoruz ki; Nginx servisimiz `10.103.206.194` IP adresiyle başarılı bir şekilde ayakta. Artık keşif (discovery) testlerimize başlayabiliriz.

***

**Yöntem 1: Environment Variables İle Keşif**

Kubernetes'in temel mekanizmalarından biri olarak *kubelet*, yeni bir *Pod* başlatıldığında, o *Pod* ile aynı namespace içindeki tüm aktif servislerin IP ve Port bilgilerini *Pod*'un içine çevre değişkeni olarak otomatik yazar.

Adım 1: Test Pod'unu Başlatma

İçine girip komut çalıştırabileceğimiz, işi bitince kendini otomatik silen (`--rm`) bir test *Pod*'u (CentOS) ayağa kaldırıyoruz:

```bash
kubectl run -i --tty --rm test-conn --image=centos -- bash
```

Adım 2: Değişkenleri Kontrol Etme

*Pod*'un içine girdikten sonra (shell ekranında), `nginx` kelimesi geçen çevre değişkenlerini listeliyoruz:

```bash
env | grep -i nginx
```

Beklenen Çıktı:

```bash
NGINX_SERVICE_PORT=tcp://10.103.206.194:80
NGINX_SERVICE_SERVICE_HOST=10.103.206.194
NGINX_SERVICE_SERVICE_PORT=80
```

*(Gördüğün gibi Kubernetes, servisin IP adresini ve portunu bizim için otomatik olarak Pod'un içine tanımlamış.)*

Adım 3: İstek Atma

Artık kodumuz, hedef IP adresini (10.103.206.194) ezberlemek veya *hardcode* etmek zorunda kalmadan, doğrudan bu değişkenleri kullanarak Nginx'e erişebilir:

```bash
curl http://$NGINX_SERVICE_SERVICE_HOST:$NGINX_SERVICE_SERVICE_PORT
```

* Önemli Kısıtlama: Eğer bu test *Pod*'unu farklı bir *namespace*'te ayağa kaldırsaydık, bu değişkenler oluşmayacaktı. Ayrıca *Service*'in, *Pod*'dan daha önce oluşturulmuş olması zorunludur.

***

**Yöntem 2: Cluster DNS İle Keşif (Modern ve Standart Yöntem)**

Kubernetes içinde çalışan DNS sunucusu (CoreDNS), tüm *Cluster* genelinde *Service* isimlerini IP adreslerine çevirir. Bu yöntem çok daha esnektir ve sıralama veya *namespace* kısıtlamalarına takılmaz.

Adım 1: DNS Ayarlarını İnceleme (`resolv.conf`)

Test *Pod*'unun içindeyken, Kubernetes'in DNS ayarlarını *Pod*'a nasıl işlediğine bakalım:

```bash
cat /etc/resolv.conf
```

Beklenen Çıktı:

```bash
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5
```

Buradaki `nameserver` DNS sunucusunun adresidir. `search` satırı ise biz sadece "nginx-service" yazdığımızda sistemin DNS'e sorarken sonuna otomatik olarak ekleyeceği domain uzantılarını gösterir.

Adım 2: DNS İle İstek Atma (Farklı Namespace Simülasyonu)

Eğer Nginx servisimiz farklı bir *namespace*'te olsaydı, ona tam DNS adıyla (FQDN) şu şekilde ulaşabilirdik:

```bash
curl http://nginx-service.default.svc.cluster.local
```

Adım 3: DNS İle İstek Atma (Aynı Namespace)

Bizim senaryomuzda hem Nginx servisimiz hem de test *Pod*'umuz aynı *namespace* (`default`) içinde. `resolv.conf` dosyasındaki `search` parametresi sayesinde uzun uzadıya domain yazmamıza gerek kalmaz. Sadece *Service* adını yazmamız yeterlidir:

```bash
curl http://nginx-service
```

DNS sunucusu arka planda bu ismi saniyesinde `10.103.206.194` adresine çevirir ve trafiği doğru yere yönlendirir.
