Kubernetes API Server Nedir? Nasıl Haberleşilir?

Kubernetes API Server, Kubernetes cluster'ındaki tüm etkileşimlerin yönetildiği ve kontrol edildiği merkezi bir bileşendir. Kubernetes API Server, Kubernetes cluster'ına istemciler tarafından yapılan istekleri alır, işler ve yanıtlar.

Bir önceki yazımızda container'lar içinden, o container'ların içinde çalıştığı Pod metadata verilerine nasıl erişebileceğini görmüştük. Bu yazımızda ise, tüm cluster içindeki herhangi bir Kubernetes nesnesinin bilgilerine nasıl erişebileceğimizi göreceğiz.

Kubernetes Downward API ve Metadata
Kubernetes Downward API, bir Pod’un metadata bilgilerini container içine inject eden mekanizmadır.

API Server, Kubernetes cluster için bir dışa açık API server görevi görür. Bu API üzerinden Kubernetes kaynaklarına (Pod'lar, Deployment'lar, Service'ler, ConfigMap'ler vb.) erişilebilir, oluşturulabilir, güncellenebilir ve silinebilir. Ayrıca, eventler, loglar ve diğer önemli bilgiler gibi bilgilere de API Server üzerinden erişilebilir.

Kubernetes Server API ile iletişime geçebilmek için iki yöntemimiz bulunuyor;

  1. kubectl proxy komutu ile local makine üzerindeki bir proxy server üzerinden
  2. kubernetes service adresi ile herhangi bir container içerisinden

Bu yöntemlerin her birine detaylıca bakalım.

1. Kubectl Proxy İle Proxy Server Üzerinden Server API Erişimi

kubectl aracının yüklü olduğu local makineniz üzerinden Server API ile iletişime geçmek oldukça kolaydır. Bunun için ilk olarak Server API'ın nerede olduğunu öğrenmemiz gerekir.

Server API'ın nerede olduğunu öğrenmek için kubectl cluster-info komutunu kullanabiliriz.

$ kubectl cluster-info
Kubernetes master is running at https://192.168.99.100:8443

Kubernetes Server API'ın nerede olduğunu öğrendikten sonra herhangi bir authentication işlemi gerekmeden iletişime geçebilmek için proxy server kullanmalıyız. Aksi halde API server'a attığınız işlemler Unauthorized hatası verecektir.

$ curl https://192.168.99.100:8443 -k
Unauthorized

kubectl proxy komutu, local makinenizde HTTP bağlantılarını kabul eden ve authentication işlemini kendi halleden bir proxy sunucusu çalıştırır. Böylece her istekte authentication token iletmeniz gerekmez. Ayrıca, man-in-the-middle ataklarını engellemek için her istekte sunucunun sertifikasını doğrular.

Proxy server'ı aktif etmek için kubectl proxy komutu çalıştırmak yeterlidir. Bu komut, API server ile konuşabilmeniz için 8001 portunda bir proxy server çalıştırır.

$ kubectl proxy
Starting to serve on 127.0.0.1:8001

Artık attığınız tüm API istekleri çok basit ve zahmetsiz bir şekilde size yanıt dönecektir.

$ curl localhost:8001
{
 "paths": [
 "/api",
 "/api/v1",
 ...
$ curl http://localhost:8001/apis/batch/v1/namespaces/default/jobs/my-job
{
 "kind": "Job",
 "apiVersion": "batch/v1",
 "metadata": {
 "name": "my-job",
 "namespace": "default",
 ...
💡
API server response'larından dönen veri, kubectl get ...... -o json komutu ile aldığınız sonucun aynısıdır.

2. Kubernetes Service Adresi ile Herhangi Bir Container İçerisinden Server API Erişimi

Proxy server sayesinde Server API ile nasıl konuşabileceğimizi önceki başlıkta gördük. Fakat kubectl aracı, özel bir gayret göstermediyseniz neredeyse hiçbir container içinde yer almaz. Bu durumda proxy açamayacağımız için API server ile konuşabilmek için şu üç şeye ihtiyacımız olacak;

  1. API server adresini bulmak
  2. API server'ın sertifikasını doğrulamak
  3. Authentication işlemi

Bu üç aşamayı sırasıyla halledelim.

2.1. API Server Adresini Bulmak

İlk ihtiyaç duyduğumuz şey, konuşacağımız API Server'ın IP adres ve port bilgisini elde etmektir. Bunun için kullanabileceğimiz ilk yöntem kubectl services komutunu çalıştırmaktır.

$ kubectl get svc
NAME        CLUSTER-IP  EXTERNAL-IP  PORT(S)  AGE
kubernetes  10.0.0.1    <none>       443/TCP  46d

kubernetes isimli service, Kubernetes tarafından default namespace altında otomatik olarak expose edilir ve API server'a bağlanır.

API server'ı bulmanın diğer bir yolu ise container içinden environment variable'lar içinde yer alan KUBERNETES_SERVICE_HOST ve KUBERNETES_SERVICE_PORT değerlerini kontrol etmektir.

$ env | grep KUBERNETES_SERVICE
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_HOST=10.0.0.1
KUBERNETES_SERVICE_PORT_HTTPS=443

Kubernetes cluster içinde yer alan tüm container'lara, Service adres ve port bilgilerinin env olarak eklendiğini Service yazımızda belirtmiştik.

Kubernetes Service Nedir?
Kubernetes Service, bir Pod grubuna sabit bir adresten erişmek için kullanılan bir Kubernetes nesnesidir.

Son olarak ise her Service'in bir DNS girdisi olduğu için direkt service ismiyle containerlar içinden erişebilirsiniz. Örneğin burada https://kubernetes adresi, Server API adresidir.

2.2. API Server'ın Sertifikasını Doğrulamak

Şimdi yukarıdaki üç yöntemden herhangi birisini kullanarak Server API adresini elde edip container içinden istek attığınızda CA SSL doğrulama hatası aldığınızı göreceksiniz.

$ curl https://kubernetes
curl: (60) SSL certificate problem: unable to get local issuer certificate
...
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

Bu sorunu çözmenin en basit yolu --insecure veya -k parametresi ile bu sertifika doğrulama aşamasını disable etmenizdir. Fakat bunu önermiyoruz.

Bir önceki Secret yazımızda, Secret'ları listelediğinizde default-token-xyz ismiyle otomatik oluşturulan bir Secret kaydı görmüştünüz.

Kubernetes ConfigMap ve Secret Nedir?
Kubernetes ConfigMap ve Secret, uygulama yapılandırma bilgileri ve hassas verilerin güvenli bir şekilde saklanmasını sağlayan kaynak türleridir.

default-token-xyz isimli secret, her container'ın /var/run/secrets/kubernetes.io/serviceaccount/ dizinine otomatik olarak mount edilir ve içinde ca.crt isimli Certificate Authority (CA)'nın sertifikasını barındırır.

$ ls /var/run/secrets/kubernetes.io/serviceaccount/
ca.crt  namespace  token

Bu sertifikayı --cacert parametresi ile belirterek sertifika doğrulama aşamsını kolaylıkla geçebilirsiniz.

curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://kubernetes

Her isteğe bu parametreyi eklemek yerine CURL_CA_BUNDLE isimli environment variable ekleyerek bu parametreyi tüm isteklere otomatik ekletebilirsiniz.

export CURL_CA_BUNDLE=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
curl https://kubernetes

2.3. Authentication İşlemi

Sertifika doğrulamasını da yaptıktan sonra attığımız isteklerin Unauthorized döndüğünü görüyorsunuz.

$ curl https://kubernetes
Unauthorized

Server API ile authentication işlemini gerçekleştirebilmek için, yine default secret olan default-token-xyz ile birlikte /var/run/secrets/kubernetes.io/serviceaccount/ dizininde gelen token isimli dosyayı kullanacağız.

Baerar token değerini içeren bu dosyanın içeriğini ilk olarak TOKEN isimli environment variable'a atıyoruz.

TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)

Ardından bu baerar token'ı isteğimizin header'ına koyarak istek attığımızda Server API'ın başarılı sonuç döndüğünü görebilirsiniz.

$ curl -H "Authorization: Bearer $TOKEN" https://kubernetes
{
 "paths": [
 "/api",
 "/api/v1",
 "/apis",
 "/apis/apps",
 "/apis/apps/v1beta1",
 "/apis/authorization.k8s.io",
 ...
 "/ui/",
 "/version"
 ]
}

2.4. Namespace'ın Otomatik Tanımlanması

Bu aşama opsiyoneldir ve Pod'un içinde çalıştığı namespace'i otomatik tanımlayarak Server API'ya gönderdiği isteklerin kolaylaştırılmasını sağlar.

Default secret olan default-token-xyz ile birlikte /var/run/secrets/kubernetes.io/serviceaccount/ dizininde gelen namespace isimli dosya, pod'un hangi cluster altında çalıştığı bilgisini tutar.

Bu namespace dosya içerisindeki namespace bilgisini environment variable olarak ayarlayarak isteklerimizde kullanabiliriz.

NS=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
curl -H "Authorization: Bearer $TOKEN" https://kubernetes/api/v1/namespaces/$NS/pods

2.5. Özet

Tüm adımları sıralar ve akışı görselleştirirsek aşağıdaki şemayı elde ederiz.

  • Uygulama, API server sertifikasının, ca.crt dosyasında bulunan CA tarafından imzalanıp imzalanmadığını doğrular.
  • Uygulama, token dosyasından baerar token ile Authorization başlığını göndererek kendi kimliğini doğrular.
  • Pod'un kendi namespace'i içindeki API nesneleri üzerinde CRUD işlemleri gerçekleştirirken namespace bilgisini API sunucusuna iletmek için namespace dosyasını kullanır.

Sıradaki yazı ile eğitim serisine devam edebilirsiniz.

Kubernetes Rolling Update ve Blue-Green Deployment Nedir?
Kubernetes Rolling Update ve Blue-Green Deployment, uygulamaların güncellenmesi ve dağıtımı için kullanılan stratejilerdir.