Kümeler Arası İş Yüklerini "Artırmak" İçin Istio Çoklu Küme Kullanımı

1. Hoş geldiniz

Google'ın Istio Multi Cloud Burst codelab'ine katıldığınız için teşekkür ederiz.Bu codelab için Kubernetes, Node ve Go ile ilgili başlangıç düzeyinde uygulamalı deneyim gerekir.

İhtiyacınız olanlar

  • Google Cloud Platform hesabı (mevcut bir hesabı kullanın veya ücretsiz hesap verilir)
  • Dizüstü bilgisayarınız ("kubectl", "gcloud" vb. yükleyin) veya Google Cloud Shell'i kullanabilirsiniz.

Öğrenecekleriniz

  • GKE'de Kubernetes kümesi oluşturma
  • Helm ile Kubernetes kümesine Istio'yu yükleme
  • Helm ile Istio Multicluster'ı yükleme
  • Kaynak koddan Kubernetes'e web uygulaması dağıtma
  • Istio'ya trafik yönlendirme kuralları yazma ve uygulama
  • Prometheus Metrikleri
  • Kubernetes kümesinde kapsayıcı görüntüleri oluşturma ve aktarma

2. Hazırlanma

Bu codelab'i aşağıdaki platformlardan birinde uygulayabilirsiniz:

  • Google Cloud Shell (önerilir): Tarayıcı içi kabuk, araçlar yüklü olarak gelir.
  • dizüstü bilgisayarınız (aşağıdaki talimatları uygulayın)

Google Cloud Platform'u kullanmaya başlama

  1. GCP hesabınız yoksa ücretsiz kullanıcı hesabı kartınızı eğitmeninizden alın.
  2. Google Cloud Console'a gidip "Proje seçin"i tıklayın: 5c2d9bf74c78f7e4.png
  3. Projenin "Kimlik" bilgisini bir yere not edin, ardından projeyi seçmek için tıklayın: ecc5e8e97bfa6559.png

Cloud Shell, tarayıcınızda komut satırı kabuğu sağlar. Bu kabukta, ihtiyacınız olan araçlar yüklü ve Google Cloud Platform hesabınızda otomatik olarak kimliği doğrulanmış şekilde bulunur. (Bu alıştırmayı Cloud Shell'de çalıştırmak istemiyorsanız bir sonraki bölüme geçin.)

Cloud Console'a gidin ve sağ üstteki araç çubuğunda "Cloud Shell'i Etkinleştir"i tıklayın:

68a17b036ce24ccb.png

Cloud Shell'e araç ekleme

  1. Install kubectx****: Bash komut dosyalarını buradan indirip $PATH'teki bir konuma yükleyin.
  2. helm****: Bu talimatları uygulayarak yükleyin.

Alternatif olarak, her ikisini de ~/.bin konumuna yüklemek ve $PATH'inize eklemek için şu komutları çalıştırın:

mkdir -p ~/.bin && \
cd ~/.bin && \
curl -LO https://raw.githubusercontent.com/ahmetb/kubectx/master/kubectx && \
chmod +x kubectx && \
curl -LO https://raw.githubusercontent.com/ahmetb/kubectx/master/kubens && \
chmod +x kubens && \
curl -LO  https://storage.googleapis.com/kubernetes-helm/helm-v2.12.0-linux-amd64.tar.gz && \
tar xzf helm-v2.12.0-linux-amd64.tar.gz && \
rm helm-v2.12.0-linux-amd64.tar.gz && \
mv linux-amd64/helm ./helm && \
rm -r linux-amd64 && \
export PATH=${HOME}/.bin:${PATH}

Cloud Shell'i kullanmayı kolaylaştırabilecek bazı hızlı ipuçları:

1. Kabuğu yeni bir pencereye ayırma:

2. Dosya düzenleyiciyi kullanma: Tarayıcı içi dosya düzenleyiciyi başlatmak için sağ üstteki kalem simgesini tıklayın. Kod snippet'lerini dosyalara kopyalayacağımız için bu özellikten yararlanabilirsiniz.

3. Yeni sekmeler başlatma: Birden fazla terminal istemine ihtiyacınız varsa.

4. Metni büyütme: Cloud Shell'deki varsayılan yazı tipi boyutu okumak için çok küçük olabilir.

Linux/Windows'da Ctrl-+, macOS'te ⌘-+.

Cloud Shell yerine kendi iş istasyonu ortamınızı kullanmayı tercih ediyorsanız aşağıdaki araçları kurun:

  1. gcloud:yükleyin (Cloud Shell'de önceden yüklenmiştir.) Platformunuza gcloud yüklemek için talimatları uygulayın. Bu bilgiyi Kubernetes kümesi oluşturmak için kullanacağız.
  2. Yükleyin kubectl:(Cloud Shell'de önceden yüklenmiştir.) Yüklemek için aşağıdaki komutu çalıştırın:
gcloud components install kubectl

gcloud'un kimliğini doğrulamak için aşağıdaki komutu çalıştırın. Google Hesabınızla giriş yapmanız istenir. Ardından, önceden oluşturulmuş projeyi (yukarıda gösterilmiştir) varsayılan proje olarak seçin. (İşlem alt bölgesi yapılandırmayı atlayabilirsiniz):

gcloud init
  1. Yükleme curl: Çoğu Linux/macOS sisteminde önceden yüklenmiştir. Büyük olasılıkla bu özelliği zaten kullanıyorsunuzdur. Aksi takdirde, internette nasıl yükleneceğini arayın.
  2. Yükleme kubectx****: Bash komut dosyalarını buradan $PATH'deki bir konuma indirerek yükleyin.
  3. helm****: Bu talimatları uygulayarak yükleyin.

3. GCP projesi oluşturma

Projenizde GKE (Google Kubernetes Engine), GCR (Google Container Registry) ve GCB (Google Cloud Build) API'lerini etkinleştirin:

gcloud services enable \
  cloudapis.googleapis.com \
  container.googleapis.com \
  containerregistry.googleapis.com \
  cloudbuild.googleapis.com

Ortam değişkenlerini ayarlama

Kurulum sırasında Google Cloud projemizle yoğun bir şekilde çalışacağız. Bu nedenle, hızlıca başvurmak için bir ortam değişkeni ayarlayalım.

export GCLOUD_PROJECT=$(gcloud config get-value project)

Bu atölye çalışması sırasında bazı kod ve yapılandırma dosyaları oluşturacağız. Bu nedenle, bir proje dizini oluşturalım ve bu dizine geçelim.

mkdir -p src/istio-burst && \
cd src/istio-burst && \
export proj=$(pwd)

4. "Birincil" Kubernetes kümesi oluşturma

Google Kubernetes Engine (GKE) ile kolayca yönetilen Kubernetes kümesi oluşturabilirsiniz.

Aşağıdaki komut bir Kubernetes kümesi oluşturur:

  • "primary" adlı,
  • us-west1-a bölgesinde,
  • Kullanılabilir en yeni Kubernetes sürümü,
  • 4 başlangıç düğümüyle
export cluster=primary
export zone=us-west1-a
gcloud container clusters create $cluster --zone $zone --username "admin" \
--cluster-version latest --machine-type "n1-standard-2" \
--image-type "COS" --disk-size "100" \
--scopes "https://www.googleapis.com/auth/compute",\
"https://www.googleapis.com/auth/devstorage.read_only",\
"https://www.googleapis.com/auth/logging.write",\
"https://www.googleapis.com/auth/monitoring",\
"https://www.googleapis.com/auth/servicecontrol",\
"https://www.googleapis.com/auth/service.management.readonly",\
"https://www.googleapis.com/auth/trace.append" \
--num-nodes "4" --network "default" \
--enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias

(Bu işlem yaklaşık 5 dakika sürebilir. Kümenin oluşturulmasını Cloud Console'da izleyebilirsiniz.

Kubernetes kümesi oluşturulduktan sonra gcloud, kubectl'yi kümeyi işaret eden kimlik bilgileriyle yapılandırır.

gcloud container clusters get-credentials $cluster --zone=$zone

Artık yeni kümenizle kubectl kullanabilirsiniz.

Kümenizin Kubernetes düğümlerini listelemek için aşağıdaki komutu çalıştırın (durum "Hazır" olarak gösterilmelidir):

kubectl get nodes

Kullanım kolaylığı için Kubeconfig adlarını değiştirme

Bağlamlar arasında sık sık geçiş yapacağımız için kümelerimiz için kısa bir takma ad kullanmak işimize yarayacak.

Bu komut, yeni oluşturduğunuz kubeconfig girişinin adını primary olarak değiştirir.

kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}

İzinleri ayarlama:

Istio'yu dağıtmak için küme yöneticisi olmanız gerekir. Bu komut, Google Cloud hesabınızla ilişkili e-postayı küme yöneticisi olarak ayarlar.

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole=cluster-admin \
    --user=$(gcloud config get-value core/account)

5. "Patlama" kümesi oluşturma

Aşağıdaki komut bir Kubernetes kümesi oluşturur:

  • "burst" adlı,
  • us-west1-a bölgesinde,
  • Kullanılabilir en yeni Kubernetes sürümü,
  • 1 başlangıç düğümüyle
  • 5 düğüme kadar otomatik ölçeklendirme etkinleştirildi
export cluster=burst
export zone=us-west1-a
gcloud container clusters create $cluster --zone $zone --username "admin" \
--cluster-version latest --machine-type "n1-standard-2" \
--image-type "COS" --disk-size "100" \
--scopes "https://www.googleapis.com/auth/compute",\
"https://www.googleapis.com/auth/devstorage.read_only",\
"https://www.googleapis.com/auth/logging.write",\
"https://www.googleapis.com/auth/monitoring",\
"https://www.googleapis.com/auth/servicecontrol",\
"https://www.googleapis.com/auth/service.management.readonly",\
"https://www.googleapis.com/auth/trace.append" \
--num-nodes "1" --enable-autoscaling --min-nodes=1 --max-nodes=5 \
--network "default" \
--enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias

(Bu işlem yaklaşık 5 dakika sürebilir. Kümenin oluşturulmasını Cloud Console'da izleyebilirsiniz.

Kubernetes kümesi oluşturulduktan sonra gcloud, kubectl'yi kümeyi işaret eden kimlik bilgileriyle yapılandırır.

gcloud container clusters get-credentials $cluster --zone=$zone

Artık yeni kümenizle kubectl kullanabilirsiniz.

Kümenizin Kubernetes düğümlerini listelemek için aşağıdaki komutu çalıştırın (durum "Hazır" olarak gösterilmelidir):

kubectl get nodes

Kullanım kolaylığı için Kubeconfig adlarını değiştirme

Bu komut, az önce oluşturduğunuz kubeconfig girişini burst olarak değiştirir.

kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}

İzinleri ayarlama:

Istio Remote'u dağıtmak için küme yöneticisi olmanız gerekir. Bu komut, Google Cloud hesabınızla ilişkili e-postayı küme yöneticisi olarak ayarlar.

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole=cluster-admin \
    --user=$(gcloud config get-value core/account)

6. Güvenlik Duvarı Kurallarını Uygulama

İki kümemizin birbirleriyle iletişim kurabilmesi için bir güvenlik duvarı kuralı oluşturmamız gerekir.

Google Cloud Platform'da kümelerimizin iletişim kurmasına izin verecek bir güvenlik duvarı kuralı oluşturmak için aşağıdaki komutları çalıştırın.

function join_by { local IFS="$1"; shift; echo "$*"; }
ALL_CLUSTER_CIDRS=$(gcloud container clusters list \
--filter="(name=burst OR name=primary) AND zone=$zone" \
--format='value(clusterIpv4Cidr)' | sort | uniq)
ALL_CLUSTER_CIDRS=$(join_by , $(echo "${ALL_CLUSTER_CIDRS}"))
ALL_CLUSTER_NETTAGS=$(gcloud compute instances list \
--filter="(metadata.cluster-name=burst OR metadata.cluster-name=primary) AND metadata.cluster-location=us-west1-a" \
--format='value(tags.items.[0])' | sort | uniq)
ALL_CLUSTER_NETTAGS=$(join_by , $(echo "${ALL_CLUSTER_NETTAGS}"))
gcloud compute firewall-rules create istio-multicluster-test-pods \
  --allow=tcp,udp,icmp,esp,ah,sctp \
  --direction=INGRESS \
  --priority=900 \
  --source-ranges="${ALL_CLUSTER_CIDRS}" \
  --target-tags="${ALL_CLUSTER_NETTAGS}" --quiet

İki kümemiz de kuruldu ve uygulamamızı ve Istio'yu dağıtmaya hazır.

7. Istio'ya giriş

Istio nedir?

Istio, "hizmetleri bağlamak, güvenli hale getirmek, kontrol etmek ve gözlemlemek" amacıyla kullanılan bir hizmet ağı kontrol düzlemidir. Bunu çeşitli şekillerde yapar ancak öncelikle, dağıtılan Kubernetes Pod'larınızın her birine bir proxy container ( Envoy) ekleyerek yapar. Proxy kapsayıcı, genel amaçlı bir politika ve telemetri merkezi ( Mixer) ile birlikte mikro hizmetler arasındaki tüm ağ iletişimini kontrol eder.

a25613cd581825da.png

Bu politikalar, Kubernetes dağıtımlarınızdan ve hizmetlerinizden bağımsız olarak uygulanabilir. Bu sayede, Ağ Operatörü ağ etkinliğini gözlemleyebilir, ağ politikalarını kısıtlayabilir, yönlendirebilir veya yeniden yazabilir. Bunun için ilişkili uygulamaların yeniden dağıtılması gerekmez.

Istio'nun desteklediği trafik yönetimi özelliklerinden bazıları şunlardır:

  • Devre kesiciler
  • Yüzdeye dayalı trafik bölme
  • URL yeniden yazma
  • TLS sonlandırma
  • Durum denetimleri
  • Yük dengeleme

Bu atölye çalışmasının amaçları doğrultusunda, yüzdeye dayalı trafik bölme yöntemine odaklanacağız.

Çalışacağımız Istio Terimleri

VirtualService

VirtualService, bir ana makineye erişildiğinde uygulanacak bir dizi trafik yönlendirme kuralını tanımlar.

Ağ geçidi

Ağ Geçidi, gelen veya giden HTTP/TCP bağlantılarını alan, ağın kenarında çalışan bir yük dengeleyicidir. Ağ geçitleri bağlantı noktalarını, SNI yapılandırmalarını vb. belirtebilir.

DestinationRule

DestinationRule, yönlendirme gerçekleştikten sonra bir hizmete yönelik trafik için geçerli olan politikaları tanımlar. Yük dengeleme, sidecar'dan bağlantı havuzu boyutu ve aykırı değer algılama ayarları için yapılandırmayı belirtirler.

Istio Multicluster

İki kümemizi oluştururken primary kümemizin otomatik ölçeklendirme olmadan 4 düğüm, burst kümemizin ise 5 düğüme kadar otomatik ölçeklendirme ile 1 düğüm olduğunu fark etmiş olabilirsiniz.

Bu yapılandırmanın iki nedeni vardır.

İlk olarak, "şirket içi" ortamdan buluta geçiş senaryosunu simüle etmek istiyoruz. Şirket içi bir ortamda, sabit bir altyapınız olduğundan otomatik ölçeklendirme kümelerine erişemezsiniz.

İkincisi, Istio'yu çalıştırmak için minimum gereksinimler 4 düğümlü bir kurulumdur (yukarıda tanımlandığı gibi). Bu durum şu soruyu akla getiriyor: Istio için en az 4 düğüm gerekiyorsa burst kümemiz Istio'yu 1 düğümle nasıl çalıştırabilir? Istio Multicluster, çok daha küçük bir Istio hizmetleri grubu yükler ve politika kurallarını almak ve telemetri bilgilerini yayınlamak için birincil kümedeki Istio yüklemesiyle iletişim kurar.

8. Uygulama Mimarisine Genel Bakış

Bileşenlere Genel Bakış

NodeJS ve Redis kullanarak üç katmanlı bir uygulama dağıtacağız.

Worker

Worker uygulaması NodeJS'de yazılmıştır ve gelen POST HTTP isteklerini dinler, bu isteklerde karma oluşturma işlemi gerçekleştirir ve PREFIX adlı bir ortam değişkeni tanımlanmışsa karma değerinin önüne bu değeri ekler. Karma hesaplandıktan sonra uygulama, sonucu belirtilen Redis sunucusundaki "calculation" kanalında gönderir.

Çok kümeli işlevselliği göstermek için daha sonra PREFIX ortam değişkenini kullanacağız.

Referans için: Bunlar, uygulamanın kullandığı paketlerdir.

  • body-parser: HTTP isteklerimizi ayrıştırmamıza olanak tanır.
  • cors: Merkezler arası kaynak paylaşımının kullanılmasına izin verir.
  • dotenv: Ortam değişkenlerinin kolayca ayrıştırılması
  • express: Kolay web sitesi barındırma
  • ioredis: Redis veritabanlarıyla iletişim kurmak için istemci kitaplığı
  • morgan: Güzel bir yapılandırılmış günlük sağlar

Frontend

Ön ucumuz da express kullanarak bir web sayfası barındıran bir NodeJS uygulamasıdır. Kullanıcı tarafından girilen sıklığı alır ve bu sıklıkta worker uygulamamıza istek gönderir. Bu uygulama, "calculation" adlı bir Redis kanalındaki mesajlara da abone olur ve sonuçları bir web sayfasında gösterir.

Uygulama aşağıdaki bağımlılıkları kullanır.

  • body-parser: HTTP isteklerimizi ayrıştırmamıza olanak tanır.
  • dotenv: Ortam değişkenlerinin kolayca ayrıştırılması
  • express: Kolay web sitesi barındırma
  • ioredis: Redis veritabanlarıyla iletişim kurmak için istemci kitaplığı
  • morgan: Güzel yapılandırılmış günlükler sağlar
  • request: HTTP isteklerinin gönderilmesine izin verir.
  • socket.io: Web sayfasından sunucuya çift yönlü iletişime izin verir.

Bu web sayfası, stil oluşturmak için Bootstrap'i kullanır ve çalıştırıldığında aşağıdaki gibi görünür.

e5e3b9cbede4cac4.png

Mimari Diyagramı

7ae4bc22a58f80a6.png

Dağıtım Şeması

Son uygulamamızı, oluşturduğumuz iki kümede dağıtacağız. primary kümesinde tüm bileşenler (frontend, worker ve Redis) dağıtılırken burst kümesinde yalnızca worker uygulaması dağıtılır.

İki kümeyi açıklayan bir diyagram aşağıda verilmiştir. Kırmızıyla belirtilen kutular Kubernetes Hizmetleri, maviyle belirtilenler ise Kubernetes Dağıtımlarıdır. Sarı kutular, Istio'nun yüklenmesini gösterir.

561db37c510944bd.png

burst kümesinde Redis için dağıtım olmamasına rağmen kümede Redis için bir hizmet dağıtıldığını fark edin. Kubernetes DNS'nin isteği çözümleyebilmesi için bu hizmetin kümede olması gerekir. Ancak istek gerçekten yapıldığında Istio Proxy, isteği primary kümesindeki Redis dağıtımına yeniden yönlendirir.

Son uygulamada, primary kümesinde çalışan ek bir Dağıtım olacak ve bu Dağıtım istiowatcher. olarak adlandırılacak. Bu Dağıtım, trafiğimiz belirli bir eşiği aştığında trafiği otomatik olarak burst'ye dinamik olarak yönlendirmemize olanak tanıyacak.

8f6183bdfc3f813c.png

9. Uygulama dağıtım dosyaları oluşturma

Uygulamamızı dağıtmak için bir dizi Kubernetes manifesti oluşturmamız gerekiyor.

Projenin kök dizinine geçin ve kubernetes adlı yeni bir klasör oluşturun.

mkdir ${proj}/kubernetes && cd ${proj}/kubernetes

frontend.yaml dosyasını yazın

Bu işlem, ön uç görüntümüze erişmek için hem Kubernetes dağıtımı hem de hizmeti oluşturur.

Aşağıdakileri frontend.yaml içine ekleyin.

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: frontend-deployment
  labels:
    app: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: frontend
        image: gcr.io/istio-burst-workshop/frontend
        ports:
        - containerPort: 8080
        readinessProbe:
            initialDelaySeconds: 10
            httpGet:
              path: "/_healthz"
              port: 8080
              httpHeaders:
              - name: "Cookie"
                value: "istio_session-id=x-readiness-probe"
        livenessProbe:
          initialDelaySeconds: 10
          httpGet:
            path: "/"
            port: 8080
            httpHeaders:
            - name: "Cookie"
              value: "istio_session-id=x-liveness-probe"
        env:
        - name: PORT
          value: "8080"
        - name: PROCESSOR_URL
          value: "http://worker-service"
        - name: REDIS_URL
          value: "redis-cache-service:6379"
---
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  type: ClusterIP
  selector:
    app: frontend
  ports:
  - name: http
    port: 80
    targetPort: 8080

Deployment içinde dikkat edilmesi gereken önemli noktalar

  • Uygulamanın çalışacağı bağlantı noktası 8080 olarak belirtildi.
  • Çalışanın adresini "http://worker-service" olarak ayarladık ve ortaya çıkan hizmeti çözümlemek için Kubernetes'in yerleşik DNS özelliğini kullanacağız.
  • REDIS_URL adresini "redis-cache-service:6379" olarak ayarladık ve ortaya çıkan IP adreslerini çözümlemek için Kubernetes'in yerleşik DNS özelliğini kullanacağız.
  • Ayrıca, Kubernetes'i container'ın ne zaman çalışır durumda olduğu konusunda bilgilendirmek için container'a liveness ve readiness probları ayarladık.

worker-service.yaml dosyasını yazma

Bu hizmeti birden fazla kümede yeniden kullanacağımız için Kubernetes hizmet tanımını dağıtım tanımından ayrı bir dosyada yazıyoruz ancak her küme için farklı bir dağıtım yazacağız.

worker-service.yaml içine aşağıdakileri ekleyin.

apiVersion: v1
kind: Service
metadata:
 name: worker-service
spec:
 type: ClusterIP
 selector:
   app: worker
 ports:
 - name: http
   port: 80
   targetPort: 8081

Write worker-primary.yaml

Bu, birincil kümeye göndereceğimiz worker dağıtımı olacak.

Aşağıdakileri worker-primary.yaml içine ekleyin.

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: worker-deployment
 labels:
   app: worker
spec:
 replicas: 1
 selector:
   matchLabels:
     app: worker
 template:
   metadata:
     labels:
       app: worker
       cluster-type: primary-cluster
   spec:
     containers:
     - name: worker
       image: gcr.io/istio-burst-workshop/worker
       imagePullPolicy: Always
       ports:
       - containerPort: 8081
       readinessProbe:
           initialDelaySeconds: 10
           httpGet:
             path: "/_healthz"
             port: 8081
             httpHeaders:
             - name: "Cookie"
               value: "istio_session-id=x-readiness-probe"
       livenessProbe:
         initialDelaySeconds: 10
         httpGet:
           path: "/"
           port: 8081
           httpHeaders:
           - name: "Cookie"
             value: "istio_session-id=x-liveness-probe"
       env:
       - name: PORT
         value: "8081"
       - name: REDIS_URL
         value: "redis-cache-service:6379"

Burada, uygulamamızın kullanması için liveness ve readiness yoklamaları sağlamanın yanı sıra PORT ve REDIS_URL ortam değişkenlerini belirtme konusunda aynı kalıbı izlediğimizi görüyoruz.

Bu dağıtımda dikkat edilmesi gereken bir diğer nokta ise PREFIX ortam değişkeninin olmamasıdır. Bu nedenle, hesaplama sonuçlarımız ham karma değerler (ön ek içermeyen) olacaktır.

Bu dağıtımın son önemli noktası cluster-type: primary-cluster etiketidir. Bunu daha sonra Istio çok kümeli ortamında trafik yönlendirme yaparken kullanacağız.

redis.yaml dosyasını yazın

Çalışanımızdan ön uca iletişim bir Redis kanalı üzerinden gerçekleşir. Bu nedenle, kümemize bir Redis uygulaması dağıtmamız gerekir.

redis.yaml içine aşağıdakileri ekleyin.

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: redis-cache
spec:
 template:
   metadata:
     labels:
       app: redis-cache
   spec:
     containers:
     - name: redis
       image: redis:alpine
       ports:
       - containerPort: 6379
       readinessProbe:
         periodSeconds: 5
         tcpSocket:
           port: 6379
       livenessProbe:
         periodSeconds: 5
         tcpSocket:
           port: 6379
       volumeMounts:
       - mountPath: /data
         name: redis-data
       resources:
         limits:
           memory: 256Mi
           cpu: 125m
         requests:
           cpu: 70m
           memory: 200Mi
     volumes:
     - name: redis-data
       emptyDir: {}

Bu, bir Redis uygulamasının yarı standart dağıtımıdır. redis:alpine görüntüsüne dayalı bir kapsayıcı oluşturur, uygun bağlantı noktalarını kullanıma sunar ve makul kaynak sınırları belirler.

redis-service.yaml dosyasını yazın

Redis uygulamamızla iletişim kurmak için bir Kubernetes hizmetine ihtiyacımız var.

redis-service.yaml içine aşağıdakileri ekleyin.

apiVersion: v1
kind: Service
metadata:
 name: redis-cache-service
spec:
 type: ClusterIP
 selector:
   app: redis-cache
 ports:
 - port: 6379
   targetPort: 6379

Bu, Redis dağıtımımıza erişmek için redis-cache-service adlı bir hizmet sağlar.

10. Uygulamayı dağıtma

Görüntülerimiz GCR'ye gönderildi ve Kubernetes manifestlerimiz yazıldı. Bu aşamada uygulamamızı dağıtıp nasıl çalıştığını görmemiz iyi olacaktır.

Uygulamayı dağıtmak için aşağıdaki komutları çalıştırın

  1. Doğru kümede olduğumuzdan emin olun.
kubectx primary
  1. Redis önbelleğini dağıtma
kubectl apply -f redis.yaml
  1. Redis hizmetini dağıtma
kubectl apply -f redis-service.yaml
  1. Ön ucu dağıtma
kubectl apply -f frontend.yaml
  1. Çalışanı Dağıt
kubectl apply -f worker-primary.yaml
  1. Worker Service'i dağıtma
kubectl apply -f worker-service.yaml

Uygulamamızı GKE'ye dağıttık. Tebrikler!

Test etme

Kapsüllerin internete bağlanmasını bekleyin.

kubectl get pods -w

Tüm pod'lar "Running" (Çalışıyor) durumuna geldiğinde Ctrl + C tuşlarına basın.

NAME                                   READY     STATUS    RESTARTS   AGE
frontend-deployment-695d95fbf7-76sd8   1/1       Running   0          2m
redis-cache-7475999bf5-nxj8x           1/1       Running   0          2m
worker-deployment-5b9cf9956d-g975p     1/1       Running   0          2m

Ön uç uygulamamızı LoadBalancer aracılığıyla kullanıma sunmadığımızı fark edeceksiniz. Bunun nedeni, daha sonra uygulamaya Istio üzerinden erişeceğiz. Her şeyin çalışır durumda olduğunu test etmek için kubectl port-forward. dağıtımının çalıştığı bağlantı noktası 8080'e yerel (veya Cloud Shell) makinenizdeki bağlantı noktası 8080'i yönlendirmek üzere aşağıdaki komutu çalıştıracağız.frontend

kubectl port-forward \
$(kubectl get pods -l app=frontend -o jsonpath='{.items[0].metadata.name}') \
8080:8080

Yerel olarak çalıştırıyorsanız: Bir web tarayıcısı açın ve http://localhost:8080 adresine gidin.

Cloud Shell'de çalışıyorsanız: "Web Önizlemesi" düğmesini tıklayın ve "8080 numaralı bağlantı noktasında önizle"yi seçin.

bdb5dc75f415be11.png

Ön ucu görmeniz gerekir. "Sıklık" kutusuna bir sayı girerseniz karma işaretlerinin görünmeye başladığını görürsünüz.

1caafaffab26897a.png

Tebrikler, her şey hazır!

Bağlantı noktasının yönlendirilmesini durdurmak için Ctrl+C tuşuna basın.

11. Dağıtılan Uygulamayı Temizleme

Kümemize Istio'yu uygulayacak ve ardından uygulamamızı yeniden dağıtacağız. Bu nedenle, önce mevcut uygulamamızı temizleyelim.

Oluşturduğunuz tüm dağıtımları ve hizmetleri silmek için aşağıdaki komutları çalıştırın.

  1. redis-cache-service öğesini sil
kubectl delete -f redis-service.yaml
  1. redis öğesini sil
kubectl delete -f redis.yaml
  1. frontend öğesini sil
kubectl delete -f frontend.yaml
  1. worker öğesini sil
kubectl delete -f worker-primary.yaml
  1. worker-service öğesini sil
kubectl delete -f worker-service.yaml

12. Birincil kümeye Istio'yu yükleme

Istio'yu edinme

Istio'nun sürümleri GitHub'da barındırılır. Aşağıdaki komutlar, istio'nun 1.0.0 sürümünü indirip paketi açar.

  1. Projenizin kökünü değiştirme
cd ${proj}
  1. Arşivi indirme
curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
  1. Arşivi çıkarma ve kaldırma
tar xzf istio-1.0.0-linux.tar.gz && rm istio-1.0.0-linux.tar.gz

Istio şablonu oluşturma

Aşağıdaki Helm komutunu çalıştırdığınızda, Istio'yu kümenize yüklemek için şablon oluşturulur.

helm template istio-1.0.0/install/kubernetes/helm/istio \
--name istio --namespace istio-system \
--set prometheus.enabled=true \
--set servicegraph.enabled=true  > istio-primary.yaml

Bu işlem, geçerli dizininizde Istio'yu dağıtmak ve çalıştırmak için gereken tüm tanımları ve özellikleri içeren istio-primary.yaml adlı bir dosya oluşturur.

İki --set parametresine dikkat edin. Bu hizmetler, Istio sistemine Prometheus ve ServiceGraph desteği ekler. Prometheus hizmetini laboratuvarın ilerleyen bölümlerinde kullanacağız.

Istio'yu dağıtma

Istio'yu dağıtmak için öncelikle Istio dağıtımlarının ve hizmetlerinin çalışabileceği istio-system adlı bir ad alanı oluşturmamız gerekir.

kubectl create namespace istio-system

Son olarak, Helm ile oluşturduğumuz istio-primary.yaml dosyasını uygulayın.

kubectl apply -f istio-primary.yaml

Varsayılan etiket ad alanı

Istio, dağıtımlarınızın her birine yardımcı proxy hizmeti yerleştirerek çalışır. Bu işlem, katılım esasına göre yapılır. Bu nedenle, Istio'nun yardımcı dosyayı otomatik olarak yerleştirebilmesi için default ad alanımızı istio-injection=enabled ile etiketlememiz gerekir.

kubectl label namespace default istio-injection=enabled

Tebrikler! Uygulamamızı dağıtmaya hazır, Istio'nun etkin olduğu bir kümemiz var.

13. Uygulamamızı Istio Trafik Yönetimi ile Dağıtma

Istio Trafik Yönetimi Yapılandırma Dosyaları Oluşturma

Istio, yapılandırma için YAML dosyalarını kullandığından Kubernetes'e benzer şekilde çalışır. Bu bağlamda, trafiğimizi nasıl kullanıma sunacağımızı ve yönlendireceğimizi Istio'ya bildiren bir dizi dosya oluşturmamız gerekir.

istio-manifests adlı bir dizin oluşturun ve bu dizine geçin.

mkdir ${proj}/istio-manifests && cd ${proj}/istio-manifests

frontend-gateway.yaml dosyasını yazın

Bu dosya, Kubernetes kümemizi GKE LoadBalancer'a benzer şekilde kullanıma sunar ve tüm gelen trafiği ön uç hizmetimize yönlendirir.

frontend-gateway.yaml adlı bir dosya oluşturun ve aşağıdakileri ekleyin.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
 name: frontend-gateway
spec:
 selector:
   istio: ingressgateway # use Istio default gateway implementation
 servers:
 - port:
     number: 80
     name: http
     protocol: HTTP
   hosts:
   - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: frontend-ingress-virtual-service
spec:
 hosts:
 - "*"
 gateways:
 - frontend-gateway
 http:
 - route:
   - destination:
       host: frontend-service
       port:
         number: 80

redis-virtualservice.yaml dosyasını yazın

redis-virtualservice.yaml adlı bir dosya oluşturun ve aşağıdakileri ekleyin.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: redis-virtual-service
spec:
 hosts:
 - redis-cache-service
 gateways:
 - mesh
 tcp:
 - route:
   - destination:
       host: redis-cache-service.default.svc.cluster.local

worker-virtualservice.yaml dosyasını yazın

worker-virtualservice.yaml adlı bir dosya oluşturun ve aşağıdakileri ekleyin.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: worker-virtual-service
spec:
 hosts:
 - worker-service
 gateways:
 - mesh
 http:
 - route:
   - destination:
       host: worker-service.default.svc.cluster.local   
       port:
         number: 80

Istio trafik yönetimi politikalarını dağıtma

Istio politikalarının dağıtımı, diğer Kubernetes kaynaklarıyla aynı şekilde yapılır. kubectl apply

  1. Ağ geçidimizi uygulama
kubectl apply -f frontend-gateway.yaml
  1. Redis VirtualService'imizi uygulama
kubectl apply -f redis-virtualservice.yaml
  1. Worker VirtualService'imizi uygulama
kubectl apply -f worker-virtualservice.yaml

Uygulamayı Dağıt

  1. kubernetes dizinimize geri dönme
cd ${proj}/kubernetes
  1. Redis önbelleğini dağıtma
kubectl apply -f redis.yaml
  1. Redis hizmetini dağıtma
kubectl apply -f redis-service.yaml
  1. Ön ucu dağıtma
kubectl apply -f frontend.yaml
  1. Çalışanı Dağıt
kubectl apply -f worker-primary.yaml
  1. Worker Service'i dağıtma
kubectl apply -f worker-service.yaml

Doğrula

Bu noktada uygulamamızı Istio ve trafik yönetimi politikaları içeren bir kümeye yeniden dağıttık.

Tüm iş yüklerimizin çevrimiçi olmasını bekleyelim

Tümü internete bağlandıktan sonra frontend-ingressgateway.yaml içinde yapılandırdığımız IngressGateway'i alın.

$ kubectl -n istio-system get svc istio-ingressgateway
NAME                   TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                                                                                                     AGE
istio-ingressgateway   LoadBalancer   10.36.3.112   35.199.158.10   80:31380/TCP,

<EXTERNAL-IP> adresine göz atın veya curl komutunu çalıştırın. Ardından ön ucu görmeniz gerekir.

$ curl 35.199.158.10
<!doctype html>
<html>

<head>
    <title>String Hashr</title>
    <!-- Bootstrap -->
...

14. "Burst" kümesine Istio'yu yükleme

primary kümemizde kurulum ve dağıtım yapmak için çok zaman harcadık ancak dağıtım yapacağımız başka bir kümemiz daha var.

Bu bölümde, her iki kümemizdeki yapılandırma değişkenlerini almamız gerekecek. Bu nedenle, her komut için hangi kümeye yönlendirildiğimize dikkat edin.

Istio Remote Manifest'i oluşturma

Istio'yu primary kümesine dağıtırken yaptığımız gibi, istio remote'u burst kümesine dağıtmak için Helm'i kullanacağız. Ancak bunu yapabilmemiz için primary kümemiz hakkında bazı bilgiler almamız gerekiyor.

Birincil küme bilgilerini toplama

primary kümesine geçiş

kubectx primary

Aşağıdaki komutlar, birincil kümedeki çeşitli pod'lerin IP adreslerini alır. Bunlar, Istio Remote tarafından birincil kümeyle iletişim kurmak için kullanılır.

export PILOT_POD_IP=$(kubectl -n istio-system get pod -l istio=pilot -o jsonpath='{.items[0].status.podIP}')
export POLICY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=policy -o jsonpath='{.items[0].status.podIP}')
export STATSD_POD_IP=$(kubectl -n istio-system get pod -l istio=statsd-prom-bridge -o jsonpath='{.items[0].status.podIP}')
export TELEMETRY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=telemetry -o jsonpath='{.items[0].status.podIP}')
export ZIPKIN_POD_IP=$(kubectl -n istio-system get pod -l app=jaeger -o jsonpath='{range .items[*]}{.status.podIP}{end}')

Uzak Şablon Oluşturma

Şimdi helm komutunu kullanarak istio-remote-burst.yaml adlı bir dosya oluşturacağız. Bu dosyayı daha sonra burst kümesine dağıtabiliriz.

Proje köküne geçme

cd $proj
helm template istio-1.0.0/install/kubernetes/helm/istio-remote --namespace istio-system \
--name istio-remote \
--set global.remotePilotAddress=${PILOT_POD_IP} \
--set global.remotePolicyAddress=${POLICY_POD_IP} \
--set global.remoteTelemetryAddress=${TELEMETRY_POD_IP} \
--set global.proxy.envoyStatsd.enabled=true \
--set global.proxy.envoyStatsd.host=${STATSD_POD_IP} \
--set global.remoteZipkinAddress=${ZIPKIN_POD_IP} > istio-remote-burst.yaml

Istio Remote'u genişleme kümesine yükleme

Istio'yu burst kümemize yüklemek için primary kümesine yüklerken uyguladığımız adımları izlememiz gerekir ancak bunun yerine istio-remote-burst.yaml dosyasını kullanmamız gerekir.

kubecontext'i burst olarak değiştirme

kubectx burst

istio-system ad alanını oluşturun

kubectl create ns istio-system

Apply istio-burst.yaml (istio-burst.yaml dosyasını uygula)

kubectl apply -f istio-remote-burst.yaml

Etiket varsayılan ad alanı

Bir kez daha, proxy'nin otomatik olarak yerleştirilebilmesi için default ad alanını etiketlememiz gerekiyor.

kubectl label namespace default istio-injection=enabled

Tebrikler! Bu noktada burst kümesinde Istio Remote'u kurmuş oluyoruz. Ancak bu noktada kümeler hâlâ iletişim kuramaz. İkisi arasında bağlantı oluşturmak için burst kümesi için bir kubeconfig dosyası oluşturmamız ve bu dosyayı primary kümesine dağıtmamız gerekir.

"Burst" kümesi için kubeconfig oluşturma

Patlama kümesine geçiş

kubectx burst

Ortamı ayarlama

Küme için kubeconfig dosyası oluşturmak üzere küme hakkında bazı bilgiler toplamamız gerekiyor.

  1. Kümenin adını alma
CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}")
  1. Küme sunucusunun adını alma
SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
  1. istio-multi hizmet hesabı sertifika yetkilisi için gizli dizinin adını alma
SECRET_NAME=$(kubectl get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
  1. Önceki gizli dizide depolanan sertifika yetkilisi verilerini alma
CA_DATA=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['ca\.crt']}")
  1. Önceki gizli dizide depolanan jetonu alma
TOKEN=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['token']}" | base64 --decode)

Kubeconfig dosyası oluşturma

Tüm bu ortam değişkenleri ayarlandıktan sonra kubeconfig dosyamızı oluşturmamız gerekir.

cat <<EOF > burst-kubeconfig
apiVersion: v1
clusters:
   - cluster:
       certificate-authority-data: ${CA_DATA}
       server: ${SERVER}
     name: ${CLUSTER_NAME}
contexts:
   - context:
       cluster: ${CLUSTER_NAME}
       user: ${CLUSTER_NAME}
     name: ${CLUSTER_NAME}
current-context: ${CLUSTER_NAME}
kind: Config
preferences: {}
users:
   - name: ${CLUSTER_NAME}
     user:
       token: ${TOKEN}
EOF

Bu işlem, geçerli dizininizde burst-kubeconfig adlı yeni bir dosya oluşturur. Bu dosya, primary kümesi tarafından burst kümesinin kimliğini doğrulamak ve kümeyi yönetmek için kullanılabilir.

Birincil kümeye geri dönme

kubectx primary

Bir gizli anahtar oluşturup etiketleyerek "burst" için kubeconfig'i uygulama

kubectl create secret generic burst-kubeconfig --from-file burst-kubeconfig -n istio-system

Istio'nun çok kümeli kimlik doğrulama için kullanacağını bilmesi için gizli anahtarı etiketleyin.

kubectl label secret burst-kubeconfig istio/multiCluster=true -n istio-system

Tebrikler! Her iki kümenin de kimliği doğrulanmış ve Istio Multicluster aracılığıyla birbirleriyle iletişim kuruyor olması gerekir. Uygulamamızı kümeler arası dağıtalım

15. Kümeler Arası Uygulama Dağıtma

Dağıtımlar Oluşturma

kubernetes dizinine geçin.

cd ${proj}/kubernetes

"Burst" kümesi için çalışan dağıtımı oluşturma: worker-burst.yaml

worker-burst.yaml adlı bir dosya oluşturun ve içine aşağıdakileri ekleyin:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: worker-deployment
  labels:
    app: worker
spec:
  replicas: 1
  selector:
    matchLabels:
      app: worker
  template:
    metadata:
      labels:
        app: worker
        cluster-type: burst-cluster
    spec:
      containers:
      - name: worker
        image: gcr.io/istio-burst-workshop/worker
        imagePullPolicy: Always
        ports:
        - containerPort: 8081
        readinessProbe:
            initialDelaySeconds: 10
            httpGet:
              path: "/_healthz"
              port: 8081
              httpHeaders:
              - name: "Cookie"
                value: "istio_session-id=x-readiness-probe"
        livenessProbe:
          initialDelaySeconds: 10
          httpGet:
            path: "/"
            port: 8081
            httpHeaders:
            - name: "Cookie"
              value: "istio_session-id=x-liveness-probe"
        env:
        - name: PORT
          value: "8081"
        - name: REDIS_URL
          value: "redis-cache-service:6379"
        - name: PREFIX
          value: "bursty-"

Bu dosyanın, daha önce oluşturduğumuz worker-primary.yaml dosyasıyla neredeyse aynı olduğuna dikkat edin. İki temel fark vardır.

İlk önemli fark, "bursty-" değerine sahip PREFIX ortam değişkenini eklemiş olmamızdır.

env:
- name: PORT
  value: "8081"
- name: REDIS_URL
  value: "redis-cache-service:6379"
- name: PREFIX
  value: "bursty-"

Bu, burst kümesindeki çalışanımızın gönderdiği tüm karma değerlerin başına "bursty-" ön ekini ekleyeceği anlamına gelir. Bu ön eki, uygulamamızın gerçekten kümeler arası olduğunu anlamak için kullanabiliriz.

İkinci önemli fark ise bu dağıtımdaki cluster-type etiketini primary-cluster yerine burst-cluster olarak değiştirmiş olmamızdır.

labels:
  app: worker
  cluster-type: burst-cluster

Bu etiketi daha sonra VirtualService'imizi güncellerken kullanacağız.

Istio Hizmetlerini Değiştirme

Şu anda Istio hizmetlerimiz dağıtımlarımızın ikisinden de yararlanmıyor. Trafiğimizin% 100'ü "birincil" kümeye yönlendiriliyor. Bu durumu değiştirelim.

istio-manifests dizinimize geçin.

cd ${proj}/istio-manifests

worker-virtualservice.yaml dosyasını DestinationRules'u içerecek şekilde düzenleyin

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: worker-virtual-service
spec:
  hosts:
  - worker-service
  gateways:
  - mesh
  http:
  - route:
    - destination:
        host: worker-service.default.svc.cluster.local    
        subset: primary
        port:
          number: 80        
      weight: 50
    - destination:
        host: worker-service.default.svc.cluster.local     
        subset: burst  
        port:
          number: 80        
      weight: 50
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: worker-destination-rule
spec:
  host: worker-service
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: primary
    labels:
      cluster-type: primary-cluster
  - name: burst
    labels:
     cluster-type: burst-cluster

VirtualService'imize ikinci bir hedef eklediğimizi görebilirsiniz. Aynı ana makineye (worker-service.default.svc.cluster.local)) referans vermeye devam ediyor ancak trafiğin% 50'si primary alt kümesine, diğer% 50'si ise burst alt kümesine yönlendiriliyor.

primary alt kümesini, cluster-type: primary-cluster etiketine sahip dağıtımlar, burst alt kümesini ise cluster-type: burst-cluster etiketine sahip dağıtımlar olarak tanımladık.

Bu sayede trafiğimiz iki küme arasında 50/50 oranında etkili bir şekilde bölünür.

Kümeye Dağıt

redis-service.yaml dosyasını patlama kümesine dağıtın.

burst kubeconfig olarak değiştirme

kubectx burst

Projemizin kök dizinine geçin.

cd ${proj}

Ardından dağıtın.

redis-service.yaml dosyasını burst kümesine dağıtın

kubectl apply -f kubernetes/redis-service.yaml

worker-burst.yaml dosyasını seri işlem kümesine dağıtın

kubectl apply -f kubernetes/worker-burst.yaml

worker-service.yaml dosyasını burst kümesine dağıtın

kubectl apply -f kubernetes/worker-service.yaml

Istio VirtualService'leri uygulama

primary kubeconfig olarak değiştirme

kubectx primary

Ardından Dağıt'ı tıklayın.

kubectl apply -f istio-manifests/worker-virtualservice.yaml

Çalıştığını Doğrulama

Çalıştığını doğrulamak için Istio Ingress noktanıza göz atın ve karma değerlerin yaklaşık% 50'sinin "burst-" ile başladığını fark edin.

78fb6e235e9f4a07.png

Bu, kümeler arası iletişimin başarıyla sağlandığı anlamına gelir. Farklı hizmetlerdeki ağırlıkları değiştirmeyi ve worker-virtualservice.yaml dosyasını uygulamayı deneyin. Bu, kümeler arasındaki trafiği dengelemenin harika bir yoludur ancak bunu otomatik olarak yapabilirsek ne olur?

16. Prometheus metriklerinden yararlanma

Prometheus'a Giriş

Prometheus, başlangıçta SoundCloud'da oluşturulan açık kaynaklı bir sistem izleme ve uyarı araç setidir. Metrik adı ve anahtar/değer çiftleriyle tanımlanan zaman serisi verileri içeren çok boyutlu bir veri modeli kullanır.

Referans olarak Prometheus mimari şemasını aşağıda bulabilirsiniz:

601e1155a825e0c2.png

Prometheus ile dağıtılan Istio, çeşitli metrikleri Prometheus sunucusuna otomatik olarak bildirir. Bu metrikleri kullanarak kümelerimizi anında yönetebiliriz.

Prometheus metriklerimizi keşfetme

Başlamak için Prometheus dağıtımını kullanıma sunmamız gerekir.

GKE'de İş Yükleri sekmesine gidin ve "prometheus" iş yüküne ayrıntılı olarak bakın.

b4a7a3cd67db05b3.png

Dağıtımın ayrıntılarını görüntülerken İşlemler -> Göster'e gidin.

c04a482e55bdfd41.png

9090 bağlantı noktasına yönlendirmeyi seçin ve "Yük dengeleyici" yazın.

d5af3ba22a7a6ebb.png

"Expose"u (Göster) seçin.

Bu işlem, Prometheus metriklerimizi keşfetmek için kullanabileceğimiz, herkese açık bir IP adresinde bir hizmet oluşturur.

Uç noktanın çalışır duruma gelmesini bekleyin ve çalışır duruma geldiğinde "Harici uç noktalar"ın yanındaki IP adresini tıklayın. b1e40ad90851da29.png

Artık Prometheus kullanıcı arayüzünü görüyor olmalısınız.

ed273552270337ec.png

Prometheus, kendi atölyesi olacak kadar çok metrik sağlar. Şimdilik istio_requests_total metriğini inceleyerek başlayacağız.

Bu sorguyu yürütmek bir dizi veri döndürür. Bu metrikler, Istio hizmet ağından geçen tüm isteklerle ilgilidir ve bu isteklerin sayısı çok fazladır. İlgilendiğimiz öğeleri filtrelemek için ifademizi şu şekilde değiştiririz:

Hedef hizmetin worker-service.default.svc.cluster.local, kaynağın ise frontend-deployment olduğu istekler son 15 saniyeyle sınırlıdır.

Bu sorgu şu şekilde görünür:

istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s]

Ayrıca, üzerinde çalışabileceğimiz çok daha yönetilebilir bir veri kümesi sunar.

19d551fd5eac3785.png

Ancak yine de biraz yoğun. Tüm istekleri değil, saniye başına düşen istek sayısını öğrenmek istiyoruz.

Bunu elde etmek için yerleşik rate işlevini kullanabiliriz.

rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])

dbb9dc063a18da9b.png

Bu, bizi hedefe yaklaştırıyor ancak bu metrikleri biraz daha azaltarak mantıksal bir grupta toplamamız gerekiyor.

Bunu yapmak için sonuçlarımızı gruplandırmak ve toplamak üzere sum ve by anahtar kelimelerini kullanabiliriz.

sum(rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])) by (source_workload,
source_app, destination_service)

898519966930ec56.png

Mükemmel! Prometheus'tan tam olarak ihtiyacımız olan metrikleri alabiliriz.

Son Prometheus sorgumuz

Öğrendiklerimiz ışığında Prometheus'a sormamız gereken son sorgu şudur:

sum(rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])) by (source_workload,
source_app, destination_service)

Artık metriği almak için HTTP API'lerini kullanabiliriz.

Aşağıdaki gibi bir HTTP GET isteği göndererek sorgumuzu kullanarak API'lerini sorgulayabiliriz. <prometheus-ip-here> yerine kendi IP'nizi girin.

curl http://<prometheus-ip-here>/api/v1/query?query=sum\(rate\(istio_requests_total%7Breporter%3D%22destination%22%2C%0Adestination_service%3D%22worker-service.default.svc.cluster.local%22%2C%0Asource_workload%3D%22frontend-deployment%22%7D%5B15s%5D\)\)%20by%20\(source_workload%2C%0Asource_app%2C%20destination_service\)

Örnek yanıt:

{
    "status": "success",
    "data": {
        "resultType": "vector",
        "result": [
            {
                "metric": {
                    "destination_service": "worker-service.default.svc.cluster.local",
                    "source_app": "frontend",
                    "source_workload": "frontend-deployment"
                },
                "value": [
                    1544404907.503,
                    "18.892886390062788"
                ]
            }
        ]
    }
}

Şimdi metrik değerimizi JSON'dan çıkarabiliriz.

Temizleme

Prometheus'u kullanıma sunmak için kullandığımız hizmeti silmemiz gerekiyor. Google Cloud Console'da, yeni oluşturduğumuz hizmetin en üstüne gidin ve "Sil"i tıklayın.

d58cb51b4c922751.png

Sonraki Adımlar:

Trafiğin küme içinde nasıl ve hangi hızda hareket ettiğini keşfetmenin bir yolunu bulduktan sonraki adımımız, periyodik olarak Prometheus'u sorgulayan küçük bir ikili program yazmaktır. worker için saniye başına istek sayısı belirli bir eşiğin üzerine çıkarsa tüm trafiği burst kümesine göndermek için çalışan sanal hizmetimizde farklı hedef ağırlıkları uygularız. Saniyedeki istek sayısı daha düşük bir eşiğin altına düştüğünde tüm trafiği primary'ya geri gönderin.

17. Küme Arası Patlama Oluşturma

Ayarlar

Çalışan hizmeti için tüm trafiği birincil kümeye ayarlama

worker-service için hedeflenen ve primary kümesine yönlendirilen tüm trafiği uygulamamızın "varsayılan" durumu olarak kabul edeceğiz.

$proj/istio-manifests/worker-virtualservice.yaml öğesini aşağıdaki gibi görünecek şekilde düzenleyin.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: worker-virtual-service
spec:
  hosts:
  - worker-service
  gateways:
  - mesh
  http:
  - route:
    - destination:
        host: worker-service.default.svc.cluster.local    
        subset: primary
        port:
          number: 80        
      weight: 100
    - destination:
        host: worker-service.default.svc.cluster.local     
        subset: burst  
        port:
          number: 80        
      weight: 0
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: worker-destination-rule
spec:
  host: worker-service
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: primary
    labels:
      cluster-type: primary-cluster
  - name: burst
    labels:
     cluster-type: burst-cluster

primary kümesine bağlı olduğunuzdan emin olun.

kubectx primary

istio-manifests/worker-virtualservice.yaml dosyasını uygulayın

kubectl apply -f istio-manifests/worker-virtualservice.yaml

Write istiowatcher daemon (İstiowatcher daemon'ı yaz)

Bu hizmeti yazarken hız ve taşınabilirlik özellikleri nedeniyle Go programlama dilini kullanacağız. Uygulamanın genel akışı, başlatma ve her saniyede Prometheus'a sorgu gönderme şeklinde olacaktır.

src içinde istiowatcher adlı yeni bir dizin oluşturun.

mkdir -p ${proj}/src/istiowatcher && cd ${proj}/src/istiowatcher

Küme içinden Istio kontrol düzlemini değiştirmek için istioctl numaralı telefonu container'ımızdan arayacağız.

istiowatcher.go yazın

Bu dizinde istiowatcher.go adlı bir dosya oluşturun ve aşağıdaki kodu bu dosyaya ekleyin.

package main

import (
        "github.com/tidwall/gjson"
        "io/ioutil"
        "log"
        "net/http"
        "os/exec"
        "time"
)

func main() {
        //These are in requests per second
        var targetLow float64 = 10
        var targetHigh float64 = 15
        // This is for the ticker in milliseconds
        ticker := time.NewTicker(1000 * time.Millisecond)

        isBurst := false

        // Our prometheus query
        reqQuery := `/api/v1/query?query=sum(rate(istio_requests_total{reporter="destination",destination_service="worker-service.default.svc.cluster.local",source_workload="frontend-deployment"}[15s]))by(source_workload,source_app,destination_service)`

        for t := range ticker.C {
                log.Printf("Checking Prometheus at %v", t)

                // Check prometheus
                // Note that b/c we are querying over the past 5 minutes, we are getting a very SLOW ramp of our reqs/second
                // If we wanted this to be a little "snappier" we can scale it down to say 30s
                resp, err := http.Get("http://prometheus.istio-system.svc.cluster.local:9090" + reqQuery)
                if err != nil {
                        log.Printf("Error: %v", err)
                        continue
                }
                defer resp.Body.Close()
                body, _ := ioutil.ReadAll(resp.Body)

                val := gjson.Get(string(body), "data.result.0.value.1")
                log.Printf("Value: %v", val)

                currentReqPerSecond := val.Float()
                log.Printf("Reqs per second %f", currentReqPerSecond)

                if currentReqPerSecond > targetHigh && !isBurst {
                        applyIstio("burst.yaml")
                        log.Println("Entering burst mode")
                        isBurst = true
                } else if currentReqPerSecond < targetLow && isBurst {
                        applyIstio("natural.yaml")
                        log.Println("Returning to natural state.")
                        isBurst = false
                }
        }
}

func applyIstio(filename string) {
        cmd := exec.Command("istioctl", "replace", "-f", filename)
        if err := cmd.Run(); err != nil {
                log.Printf("Error hit applying istio manifests: %v", err)
        }
}

Dockerfile yazma

Dockerfile adlı yeni bir dosya oluşturun ve içine aşağıdakileri ekleyin.

FROM golang:1.11.2-stretch as base

FROM base as builder

WORKDIR /workdir
RUN curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
RUN tar xzf istio-1.0.0-linux.tar.gz
RUN cp istio-1.0.0/bin/istioctl ./istioctl

FROM base 

WORKDIR /go/src/istiowatcher
COPY . .
COPY --from=builder /workdir/istioctl /usr/local/bin/istioctl

RUN go get -d -v ./...
RUN go install -v ./...

CMD ["istiowatcher"]

Bu çok kademeli Dockerfile, ilk aşamada Istio'nun 1.0.0 sürümünü indirip ayıklar. İkinci aşamada, dizinimizdeki her şey görüntüye kopyalanır, ardından derleme aşamasındaki istioctl, /usr/local/bin'ye kopyalanır (böylece uygulamamız tarafından çağrılabilir), bağımlılıklar alınır, kod derlenir ve CMD, "istiowatcher" olarak ayarlanır.

burst.yaml dosyasını yazın

Bu, frontend tarafından worker adresine gönderilen saniyedeki istek sayısı 15'i aştığında istiowatcher dosyasının uygulanacağı anlamına gelir.

burst.yaml adlı yeni bir dosya oluşturun ve içine aşağıdakileri ekleyin.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: worker-virtual-service
spec:
 hosts:
 - worker-service
 gateways:
 - mesh
 http:
 - route:
   - destination:
       host: worker-service.default.svc.cluster.local   
       subset: primary
       port:
         number: 80       
     weight: 0
   - destination:
       host: worker-service.default.svc.cluster.local    
       subset: burst 
       port:
         number: 80       
     weight:  100

natural.yaml dosyasını yazın

Bu durumu, frontend ile worker arasındaki saniyedeki istek sayısı 10'un altına düştüğünde döndüğümüz "doğal" durum olarak kabul ederiz. Bu durumda trafiğin% 100'ü primary kümesine yönlendirilir.

natural.yaml adlı yeni bir dosya oluşturun ve içine aşağıdakileri ekleyin

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: worker-virtual-service
spec:
 hosts:
 - worker-service
 gateways:
 - mesh
 http:
 - route:
   - destination:
       host: worker-service.default.svc.cluster.local   
       subset: primary
       port:
         number: 80       
     weight: 100
   - destination:
       host: worker-service.default.svc.cluster.local    
       subset: burst 
       port:
         number: 80       
     weight: 0

Build and Push istiowatcher

Mevcut dizini Google Cloud Build'e (GCB) göndermek için aşağıdaki komutu çalıştırın. GCB, görüntüyü GCR'de oluşturup etiketler.

gcloud builds submit -t gcr.io/${GCLOUD_PROJECT}/istiowatcher

istiowatcher'ı dağıtma

kubernetes dizinimize geçin.

cd ${proj}/kubernetes/

Dağıtım dosyası yazma: istiowatcher.yaml

istiowatcher.yaml adlı bir dosya oluşturun ve aşağıdaki kodu ekleyin (<your-project-id> yerine proje kimliğinizi girin).

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: istiowatcher-deployment
  labels:
    app: istiowatcher
spec:
  replicas: 1
  selector:
    matchLabels:
      app: istiowatcher
  template:
    metadata:
      labels:
        app: istiowatcher
    spec:
      serviceAccountName: istio-pilot-service-account
      automountServiceAccountToken: true
      containers:
      - name: istiowatcher
        image: gcr.io/<your-project-id>/istiowatcher
        imagePullPolicy: Always

Dağıt

Birincil kümede çalıştığımızdan emin olun

kubectx primary

istiowatcher.yaml öğesini istio-system ad alanında dağıtın

kubectl apply -n istio-system -f istiowatcher.yaml

Yaml dosyasındaki serviceAccountName ve automountServiceAccountToken yönergelerinin önemli olduğunu unutmayın. Bu, küme içinden istioctl çalıştırmak için gereken kimlik bilgilerini bize verir.

Ayrıca, istio-pilot-service-account için kimlik bilgilerine sahip olduğumuzdan emin olmak amacıyla bunu istio-system ad alanında dağıtmamız gerekiyor. (default ad alanında mevcut değil).

Trafiğin otomatik olarak değişmesini izleyin.

Şimdi büyülü anı yaşayalım. Ön uca gidip saniyedeki istek sayısını 20'ye çıkaralım.

Bu işlemin birkaç saniye sürdüğünü ancak tüm karma işlemlerimizin "bursty-" ön ekiyle başladığını fark edebilirsiniz.

Bunun nedeni, 15s aralığında Prometheus örneklemesi yapmamızdır. Bu durum, yanıt süremizin biraz gecikmesine neden olur. Çok daha dar bir bant istiyorsak sorgumuzu prometheus olarak değiştirebiliriz. 5s.

18. Sırada ne var?

Temizleme

Bu atölye çalışması için sağlanan geçici bir hesap kullanıyorsanız temizlik yapmanız gerekmez.

Kubernetes kümelerinizi, güvenlik duvarı kuralını ve GCR'deki görüntüleri silebilirsiniz.

gcloud container clusters delete primary --zone=us-west1-a
gcloud container clusters delete burst --zone=us-west1-a
gcloud compute firewall-rules delete istio-multicluster-test-pods 
gcloud container images delete gcr.io/$GCLOUD_PROJECT/istiowatcher

Geleceğe Yönelik