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

1. Hoş geldiniz

Google tarafından sunulan Istio Multi Cloud Burst codelab'e katıldığınız için teşekkürler.Bu codelab'i tamamlamak için Kubernetes, Node ve Go ile ilgili başlangıç düzeyinde uygulamalı deneyime sahip olmanız gerekir.

İhtiyacınız olanlar

  • Google Cloud Platform hesabı (mevcut hesabınızı kullanın veya ücretsiz hesap verelim)
  • 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 yükleme
  • Istio Multicluster'ı Helm ile yükleme
  • Bir web uygulamasını kaynaktan Kubernetes'e 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 yayınlama

2. Hazırlanma

Bu codelab'i şu platformlarda takip edebilirsiniz:

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

Google Cloud Platform ile Başlayın

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

Cloud Shell, tarayıcınızda ihtiyacınız olan araçların yüklü olduğu ve Google Cloud Platform hesabınızla otomatik olarak kimlik doğrulaması yapılan bir komut satırı kabuğu sağlar. (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. Yükleyin kubectx****: Buradaki bash komut dosyalarını $PATH içindeki bir konuma indirin.
  2. Yükleme helm****: Bu talimatları uygulayın.

Alternatif olarak, her ikisini de ~/.bin'e yüklemek ve $PATH değişkeninize 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ğunu yeni bir pencerede ayırın:

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 özelliği faydalı bulacaksınız.

3. Yeni sekmeler başlatın: Birden fazla terminal istemi gerekiyorsa.

4. Metni büyütme: Cloud Shell'daki varsayılan yazı tipi boyutu okunamayacak kadar küçük olabilir.

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

Kendi iş istasyonu ortamınızı Cloud Shell'den daha rahat kullanıyorsanız aşağıdaki araçları ayarlayın:

  1. gcloud:'yi yükleyin (Cloud Shell'e önceden yüklenmiştir.) gcloud'yi platformunuza yüklemek için talimatları uygulayın. Bu dosyayı, Kubernetes kümesi oluşturmak için kullanacağız.
  2. kubectl:'yi yükleyin(Cloud Shell'e ö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, varsayılan proje olarak önceden oluşturulmuş projeyi (yukarıda gösterilmiştir) seçin. (İşlem alt bölgesini yapılandırmayı atlayabilirsiniz):

gcloud init
  1. Yükleme curl: Çoğu Linux/macOS sistemine önceden yüklenmiştir. Muhtemelen zaten sahipsinizdir. Aksi takdirde, nasıl yükleyeceğinizi internette arayın.
  2. kubectx****'yi yükleyin: Buradaki bash komut dosyalarını $PATH içindeki bir konuma indirin.
  3. Yükleme helm****: Bu talimatları uygulayın.

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 şekilde çalışacağız. Hızlı referans için bir ortam değişkeni ayarlayalım.

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

Bu atölyede bazı kod ve yapılandırma dosyaları oluşturacağız. Öncelikle bir proje dizini oluşturup oraya 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 yönetilen Kubernetes kümesi oluşturabilirsiniz.

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

  • "primary" adlı,
  • us-west1-a bölgesinde,
  • Mevcut Kubernetes'in en son sürümü,
  • 4 başlangıç düğümü ile
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ümeye işaret eden kimlik bilgileriyle yapılandırır.

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

Artık kubectl'yi yeni kümenizle kullanabilirsiniz.

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

kubectl get nodes

Kullanımı kolaylaştırmak için Kubeconfig adlarını değiştirme

Bağlamlar arasında sık sık geçiş yapacağımızdan kümelerimiz için kısa bir takma ad kullanmak kullanışlıdır.

Bu komut, az önce oluşturduğunuz kubeconfig girişini primary olarak yeniden adlandırır.

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. "Burst" kümesi oluşturma

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

  • "burst" adlı bir dosya
  • us-west1-a bölgesinde,
  • Mevcut Kubernetes'in en son sürümü,
  • 1 başlangıç düğümü ile
  • 5 adede kadar düğüm için 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ümeye işaret eden kimlik bilgileriyle yapılandırır.

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

Artık kubectl'yi yeni kümenizle kullanabilirsiniz.

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

kubectl get nodes

Kullanımı kolaylaştırmak 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 birbiriyle 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

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

7. Istio'ya Giriş

Istio nedir?

Istio, "hizmetleri bağlamayı, güvenli hale getirmeyi, kontrol etmeyi ve gözlemlemeyi" amaçlayan bir hizmet ağı kontrol düzlemidir. Bunu çeşitli yöntemlerle yapar ancak temel olarak dağıtılan Kubernetes kapsayıcılarınızın her birine bir proxy kapsayıcısı ( Envoy) ekleyerek yapar. Proxy kapsayıcısı, 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ü, ilişkili uygulamaları yeniden dağıtmadan ağ etkinliğini gözlemleyebilir, ağ politikalarını kısıtlayabilir, yönlendirebilir veya yeniden yazabilir.

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

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

Bu atölye çalışmasında, yüzdeye dayalı trafik bölme işlemine odaklanacağız.

Çalışacağımız Istio Şartları

VirtualService

VirtualService, bir ana makine adreslendiğinde uygulanacak bir dizi trafik yönlendirme kuralı tanımlar.

Ağ geçidi

Geçiş noktası, 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ı, SNI yapılandırmaları vb. belirtebilir.

DestinationRule

DestinationRule, yönlendirme yapıldıktan sonra bir hizmete yönelik trafik için geçerli olan politikaları tanımlar. Bunlar; yük dengeleme yapılandırması, yardımcı araçtaki bağlantı havuzu boyutu ve aykırı değer algılama ayarlarını belirtir.

Istio Çoklu Küme

İ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ırma için iki neden vardır.

Öncelikle, "yerinde"den Cloud'a geçiş senaryosunu simüle etmek istiyoruz. Yerleşik bir ortamda, sabit altyapınız olduğu için otomatik ölçeklendirme kümelerine erişiminiz yoktur.

İkinci olarak, Istio'yu çalıştırmak için minimum gereksinim 4 düğümlü bir kurulumdur (yukarıda belirtildiği gibi). Bu da şu soruyu akla getiriyor: Istio en az 4 düğüm gerektiriyorsa burst kümemiz Istio'yu 1 düğümle nasıl çalıştırabilir? Bunun nedeni, Istio Çoklu Küme'nin çok daha küçük bir Istio hizmeti grubunu kurmasıdır. Ayrıca, politika kurallarını almak ve telemetri bilgilerini yayınlamak için birincil kümedeki Istio kurulumuyla iletişim kurar.

8. Uygulama mimarisine genel bakış

Bileşenlere Genel Bakış

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

İşçi

İşleyici uygulaması NodeJS'de yazılmıştır ve gelen POST HTTP isteklerini dinler, bunlar üzerinde karma oluşturma işlemi gerçekleştirir ve PREFIX adlı bir ortam değişkeni tanımlanmışsa karma oluşturma işleminin başına bu değeri ekler. Karma oluşturma işlemi tamamlandıktan sonra uygulama, sonucu belirtilen Redis sunucusunda "calculation" kanalına gönderir.

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

Referans olması amacıyla: 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

Kullanıcı arayüzü

Ön uçumuz da express kullanarak bir web sayfası barındıran bir NodeJS uygulamasıdır. Kullanıcı tarafından girilen bir sıklığı alır ve worker uygulamamıza bu hızda 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 isteği göndermeye izin verir
  • socket.io: Web sayfasından sunucuya iki yönlü iletişime olanak tanır

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

e5e3b9cbede4cac4.png

Mimari Diyagramı

7ae4bc22a58f80a6.png

Dağıtım Diyagramı

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

Aşağıda, iki kümeyi açıklayan bir şema verilmiştir. Kırmızıyla belirtilen kutular Kubernetes Hizmetleri, mavi olanlar ise Kubernetes Dağıtımları'dır. Sarı kutular, Istio'yu yüklediğimizi gösterir.

561db37c510944bd.png

burst grubunda Redis dağıtımı olmamasına rağmen Redis hizmetinin dağıtıldığına dikkat edin. Kubernetes DNS'nin isteği çözebilmesi için bu hizmetin kümede bulunması gerekir. Ancak istek gerçekten yapıldığında Istio Proxy, isteği primary kümesindeki Redis dağıtımına yeniden yönlendirir.

Nihai uygulamada, primary kümesinde istiowatcher. adlı ek bir dağıtım bulunur. Bu dağıtım, trafiğimiz belirli bir eşiği aştığında trafiği burst'ye otomatik olarak dinamik olarak yeniden yönlendirmemize olanak tanır.

8f6183bdfc3f813c.png

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

Uygulamamızı dağıtmak için bir dizi Kubernetes manifest'i 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ı yazma

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'te dikkat edilmesi gereken önemli noktalar

  • Uygulamanın çalışacağı bağlantı noktasını 8080 olarak belirttik
  • İşleyicinin adresini "http://worker-service" olarak ayarladık ve ortaya çıkan hizmeti çözmek için Kubernetes'in yerleşik DNS özelliğini kullanacağız.
  • REDIS_URL adresimizi "redis-cache-service:6379" olarak ayarladık ve elde edilen IP adreslerini çözümlemek için Kubernetes'in yerleşik DNS özelliğini kullanacağız.
  • Ayrıca, Kubernetes'in kapsayıcı çalışır durumda olduğunda bilgilendirilmesine yardımcı olmak için kapsayıcıya liveness ve readiness probları da ayarladık.

worker-service.yaml dosyasını yazma

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

Aşağıdakileri worker-service.yaml alanına ekleyin

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

worker-primary.yaml dosyasını yazma

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

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, liveness ve readiness probları sağlamanın yanı sıra uygulamamızın kullanacağı PORT ve REDIS_URL ortam değişkenlerini belirtme konusunda aynı kalıbı izlediğimizi görebilirsiniz.

Bu dağıtımda dikkat edilmesi gereken bir diğer nokta da PREFIX ortam değişkeninin olmamasıdır. Bu, hesaplama sonuçlarımızın ham karma oluşturma işlemleri olacağı anlamına gelir (önlerine hiçbir şey eklenmez).

Bu dağıtımın son önemli noktası cluster-type: primary-cluster etiketidir. Bunu daha sonra Istio Çoklu Küme'de Trafik Yönlendirme yaparken kullanacağız.

redis.yaml dosyasını yazma

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

Aşağıdakileri redis.yaml alanına 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, Redis uygulamasının yarı standart bir dağıtımıdır. redis:alpine görüntüsüne dayalı bir kapsayıcı oluşturur, uygun bağlantı noktalarını gösterir ve makul kaynak sınırlamaları belirler.

redis-service.yaml dosyasını yazma

Redis uygulamamızla iletişim kurmak için bir Kubernetes Hizmeti'ne ihtiyacımız var

Aşağıdakileri redis-service.yaml alanına 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ı hizmeti sağlar.

10. Uygulamayı dağıtma

Görüntülerimiz GCR'ye gönderilmiş ve Kubernetes manifest'lerimiz yazılmış durumda. Bu noktada uygulamamızı dağıtıp nasıl çalıştığını görebiliriz.

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

  1. Doğru kümede olduğumuzdan emin olma
kubectx primary
  1. Redis önbelleğini dağıtma
kubectl apply -f redis.yaml
  1. Redis Hizmeti'ni dağıtma
kubectl apply -f redis-service.yaml
  1. Ön ucu dağıtma
kubectl apply -f frontend.yaml
  1. Çalışanı dağıtma
kubectl apply -f worker-primary.yaml
  1. Çalışan Hizmeti'ni dağıtma
kubectl apply -f worker-service.yaml

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

Test

Kapsüllerin internete bağlanmasını bekleyin

kubectl get pods -w

Tüm kapsüller "Ç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ç hizmetimizi bir LoadBalancer üzerinden göstermediğimizi fark edeceksiniz. Bunun nedeni, daha sonra uygulamaya Istio üzerinden erişeceğimizdir. Her şeyin çalışır durumda olduğunu test etmek için kubectl port-forward. kullanacağız. Yerel (veya Cloud Shell) makinenizdeki 8080 numaralı bağlantı noktasını, frontend dağıtımını çalıştıran 8080 numaralı bağlantı noktasına yönlendirmek için aşağıdaki komutu çalıştırın.

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ıştırıyorsanız: "Web Önizlemesi" düğmesini tıklayın ve "8080 bağlantı noktasında önizle"yi seçin.

bdb5dc75f415be11.png

Ön uçu göreceksiniz. "Sıklık" kutusuna bir sayı girerseniz karma oluşturma işlemlerinin görünmeye başladığını görürsünüz.

1caafaffab26897a.png

Tebrikler, tüm işlemler tamamlandı.

Bağlantı noktasını yönlendirmeyi durdurmak için Ctrl+C simgesine basın.

11. Dağıtılmış Uygulamayı Temizleme

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

Az önce 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. Istio'yu birincil kümeye 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 paketini açar.

  1. Projenizin köküne geçme
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 ayıklama 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ırarak Istio'yu kümenize yüklemek için şablonu oluşturun.

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 spesifikasyonları içeren istio-primary.yaml adlı bir dosya oluşturur.

İki --set parametresine dikkat edin. Bu sürümler, 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

Etiketin varsayılan ad alanı

Istio, dağıtımlarınızın her birine yardımcı dosya proxy hizmeti ekleyerek çalışır. Bu işlem etkinleştirme esasına göre yapılır. Bu nedenle, Istio'nun bizim için otomatik olarak yan aracı ekleyebilmesi 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 ile çalışan 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ı kullandığından Kubernetes'e benzer şekilde çalışır. Bu bağlamda, Istio'ya trafiğimizi nasıl göstereceğini ve yönlendireceğini söyleyen 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ı yazma

Bu dosya, Kubernetes kümemizi GKE LoadBalancer'a benzer bir şekilde kullanıma sunar ve gelen tüm 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ı yazma

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ı yazma

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 uygulayın
kubectl apply -f worker-virtualservice.yaml

Uygulamayı dağıtma

  1. kubernetes dizine geri dönme
cd ${proj}/kubernetes
  1. Redis önbelleğini dağıtma
kubectl apply -f redis.yaml
  1. Redis Hizmeti'ni dağıtma
kubectl apply -f redis-service.yaml
  1. Ön ucu dağıtma
kubectl apply -f frontend.yaml
  1. Çalışanı dağıtma
kubectl apply -f worker-primary.yaml
  1. Çalışan Hizmeti'ni 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 online olmasını bekleyelim

Tüm düğümler çevrimiçi olduktan sonra frontend-ingressgateway.yaml

$ 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 gidin veya bu adresi curl ile işleyin. Ön ucu göreceksiniz.

$ curl 35.199.158.10
<!doctype html>
<html>

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

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

primary kümemizi ayarlamak ve dağıtmak için çok zaman harcadık ancak dağıtacağı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 gerekir. Bu nedenle, her komut için hangi kümeye yönlendirildiğimize dikkat edin.

Istio uzak manifestini oluşturma

Istio'yu primary kümesine dağıttığımızda olduğu gibi, Istio uzaktan dağıtımını burst kümesine şablonlamak için Helm'i kullanacağız. Ancak bunu yapabilmemiz için primary kümemiz hakkında bazı bilgiler edinmemiz gerekiyor.

Birincil küme bilgilerini toplama

primary kümesine geçme

kubectx primary

Aşağıdaki komutlar, birincil kümedeki çeşitli kapsüllerin IP adreslerini alır. Bunlar, Istio Remote tarafından birincil kümeyle geri 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 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

Burst kümesine Istio Remote'ı yükleme

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

kubecontext değerini burst olarak değiştirme

kubectx burst

istio-system ad alanını oluşturma

kubectl create ns istio-system

istio-burst.yaml dosyasını uygulama

kubectl apply -f istio-remote-burst.yaml

Etiketin varsayılan ad alanı

Proxy'nin otomatik olarak eklenebilmesi için default ad alanını tekrar etiketlememiz gerekir.

kubectl label namespace default istio-injection=enabled

Tebrikler! Bu noktada burst kümesinde Istio Remote'u kurduk. Ancak bu noktada kümeler hâlâ iletişim kuramıyor. burst kümesi için, bunları birbirine bağlamak üzere primary kümesine dağıtabileceğimiz bir kubeconfig dosyası oluşturmamız gerekir.

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

Burst kümesine geçme

kubectx burst

Ortam oluşturma

Küme için bir 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 sunucusu adını alma
SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
  1. istio-multi hizmet hesabı sertifika yetkilisinin gizlisinin adını alın
SECRET_NAME=$(kubectl get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
  1. Önceki gizlilikte depolanan sertifika yetkilisi verilerini alma
CA_DATA=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['ca\.crt']}")
  1. Önceki gizli anahtarda 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, mevcut dizininizde burst-kubeconfig adlı yeni bir dosya oluşturur. Bu dosya, primary kümesi tarafından burst kümesinin kimliğini doğrulamak ve yönetmek için kullanılabilir.

Birincil kümeye geri dönme

kubectx primary

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ğrulaması için kullanacağını bilmesi amacıyla gizliyi etiketleyin

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

Tebrikler! Her iki kümenin de kimliği doğrulandı ve Istio Multicluster üzerinden birbirleriyle iletişim kuruyor. Uygulamamızı kümeler arası dağıtalım

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

Dağıtım oluşturma

kubernetes dizinine geçin

cd ${proj}/kubernetes

"burst" kümesi için çalışan dağıtımı oluşturun: 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-"

Bunun daha önce oluşturduğumuz worker-primary.yaml ile neredeyse aynı olduğunu fark edin. İki temel fark vardır.

İlk önemli fark, PREFIX ortam değişkenini "bursty-" değeriyle eklememizdir.

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

Bu, burst kümesindeki işleyicimizin gönderdiği tüm karma oluşturma işlemlerinin başına "bursty-" ön ekini ekleyeceği anlamına gelir. Bu, uygulamamızın gerçekten kümeler arası olduğunu öğrenmek için kullanabileceğimiz bir özelliktir.

İkinci önemli fark, 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 her iki dağıtımdan da yararlanmıyor. Trafiğimizin% 100'ü "birincil" kümeye yönlendiriliyor. Bunu değiştirelim.

istio-manifests dizinimize geçin

cd ${proj}/istio-manifests

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

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 eder ancak trafiğin% 50'si primary alt kümesine, diğer% 50'si ise burst alt kümesine yönlendirilir.

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 eşit olarak bölünür.

Kümeye dağıtma

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

burst kubeconfig olarak değiştirin

kubectx burst

Proje kökümüzü değiştirme

cd ${proj}

Ardından dağıtın

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

kubectl apply -f kubernetes/redis-service.yaml

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

kubectl apply -f kubernetes/worker-burst.yaml

worker-service.yaml dosyasını ani artış kümesine dağıtma

kubectl apply -f kubernetes/worker-service.yaml

Istio VirtualServices'i uygulama

primary kubeconfig olarak değiştirin

kubectx primary

Ardından dağıtın

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

İşleyip İşlemediğini Doğrulama

Bu işlemin çalıştığını doğrulamak için Istio giriş noktanıza göz atın ve karmaların yaklaşık% 50'sinin önüne "burst-" eklendiğini fark edin.

78fb6e235e9f4a07.png

Bu, kümeler arası başarıyla konuştuğumuz anlamına geliyor. Farklı hizmetlerdeki ağırlıkları değiştirmeyi ve worker-virtualservice.yaml dosyasını uygulamayı deneyin. Bu, kümeler arasındaki trafiği dengelemek için mükemmel bir yöntemdir. Peki bunu otomatik olarak yapabilseydik ne olurdu?

16. Prometheus metriklerinden yararlanma

Prometheus'a Giriş

Prometheus, başlangıçta SoundCloud'da geliştirilmiş açık kaynak bir sistem izleme ve uyarı aracıdır. Metrik adı ve anahtar/değer çiftleriyle tanımlanan zaman serisi verilerini içeren çok boyutlu bir veri modeli kullanır.

Referans olarak kullanabileceğiniz Prometheus mimari şeması aşağıda verilmiştir:

601e1155a825e0c2.png

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

Prometheus metriklerimizi keşfetme

Başlamak için Prometheus dağıtımını göstermemiz gerekir.

GKE'deki İş Yükleri sekmesine gidin, "prometheus" iş yüküne gidin.

b4a7a3cd67db05b3.png

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

c04a482e55bdfd41.png

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

d5af3ba22a7a6ebb.png

Ardından "Expose"i (Belirleme) seçin.

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

Uç noktasının çalışmaya başlamasını bekleyin ve çalışmaya başladıktan sonra "Harici uç noktalar"ın yanındaki IP adresini tıklayın b1e40ad90851da29.png

Şimdi Prometheus kullanıcı arayüzüne bakıyor olmalısınız.

ed273552270337ec.png

Prometheus, kendi atölyesi olacak kadar yeterli metrik sağlar. Şimdilik istio_requests_total metriğini keşfetmeye başlayacağız.

Bu sorgunun yürütülmesi bir dizi veri döndürür. Istio hizmet ağı üzerinden geçen tüm isteklerle ilgili metriklerdir ve bu çok fazladır. Gerçekten ilgilendiğimiz verilere ulaşabilmek için ifademizi değiştireceğiz:

Hedef hizmeti worker-service.default.svc.cluster.local olan ve kaynağı son 15 saniyeyle sınırlı olan frontend-deployment istekleri

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]

Bu sayede, daha kolay yönetilebilir bir veri kümesiyle çalışabiliriz.

19d551fd5eac3785.png

Ancak yine de biraz yoğun. Tüm isteklerin değil, saniye başına 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 biraz daha yaklaştırıyor ancak bu metrikleri mantıklı bir grupta biraz daha azaltmamız gerekiyor.

Bunu yapmak için sum ve by anahtar kelimelerini kullanarak sonuçlarımızı gruplandırıp toplayabiliriz.

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 ihtiyaç duyduğumuz metrikleri alabiliriz.

Son Prometheus Sorgumuz

Tüm öğrendiklerimizle birlikte, 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 API'lerini sorgumuzla sorgulayabiliriz. <prometheus-ip-here> yerine

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"
                ]
            }
        ]
    }
}

Artık metrik değerimizi JSON'dan ayıklayabiliriz.

Temizleme

Prometheus'u göstermek için kullandığımız hizmeti silmemiz gerekiyor. Google Cloud Console'da, yeni oluşturduğumuz hizmetin üst kısmına gidin ve "Sil"i tıklayın.

d58cb51b4c922751.png

Sonraki Adımlar:

Trafiğin kümede nasıl ve hangi hızda hareket ettiğini keşfetmenin bir yolunu bulduktan sonra, bir sonraki adımımız prometheus'i düzenli olarak sorgulayan küçük bir ikili dosya yazmak ve worker'e saniye başına gelen istek sayısı belirli bir eşiğin üzerine çıkarsa tüm trafiği burst kümesine göndermek için çalışan sanal hizmetimize farklı hedef ağırlıkları uygulamaktır. Saniye başına istek sayısı daha düşük bir eşiğin altına düştüğünde tüm trafiği primary adresine geri gönderin.

17. Kümeler Arası Patlama Oluşturma

Ayarlar

İşçi hizmetinin tüm trafiğini birincil kümeye ayarlama

worker-service adresine giden ve primary kümesine yönlendirilen tüm trafiği, uygulamamızın "varsayılan" durumu olarak kabul ederiz.

$proj/istio-manifests/worker-virtualservice.yaml öğesini aşağıdaki gibi 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

istiowatcher daemon'ı yazma

Bu hizmeti yazmak için hız ve taşınabilirlik avantajlarından yararlanmak üzere Go'yu kullanacağız. Uygulamanın genel akışı, başlatıldıktan sonra her saniye prometheus'i sorgulamak olacaktır.

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

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

Istio kontrol düzleminde küme içinden değişiklik yapmak için kapsayıcımızdan istioctl'i çağıracağız.

istiowatcher.go dosyasını yazma

Söz konusu dizinde istiowatcher.go adlı bir dosya oluşturun ve içine aşağıdakileri 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 aşağıdakileri bu dosyaya 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 aşamalı Dockerfile, ilk aşamada Istio'nun 1.0.0 sürümünü indirip açar. İkinci aşamada, dizinimizdeki her şey görüntüye kopyalanır, ardından istioctl derleme aşamasından /usr/local/bin'a 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ı yazma

Bu, frontend'den worker'a saniye başına gelen istek sayısı 15'i aştığında istiowatcher'nin uygulanacağı dosyadır.

burst.yaml adlı yeni bir dosya oluşturun ve aşağıdakileri bu dosyaya 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ı yazma

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

natural.yaml adlı yeni bir dosya oluşturun ve aşağıdakileri bu dosyaya 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

istiowatcher'ı derleme ve yayınlama

Mevcut dizini Google Cloud Build'e (GCB) göndermek için aşağıdaki komutu çalıştırın. Bu komut, 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ğıdakileri ekleyin (<proje-kimliğiniz> yerine kendi 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ım

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

kubectx primary

istiowatcher.yamlistio-system ad alanında dağıtma

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

yaml dosyasında serviceAccountName ve automountServiceAccountToken yönergelerinin yer aldığını unutmayın. Bu sayede, istioctl'ü küme içinde çalıştırmak için gereken kimlik bilgilerini elde ederiz.

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 gerekir. (default ad alanında mevcut değildir).

Trafiği otomatik olarak geçişini izleyin.

Şimdi büyülü anı yaşamaya hazır olun. Ön uçumuza gidip saniye başına istek sayısını 20'ye çıkaralım.

Bu işlemin birkaç saniye sürdüğünü fark edeceksiniz. Ancak hızlanır ve tüm karma oluşturma işlemlerinin önüne "bursty-" ön eki eklenir.

Bunun nedeni, prometheus'i 15s aralığında örneklememizdir. Bu da yanıt süremizin biraz gecikmesine neden olur. Daha dar bir bant aralığı isterseniz sorgumuzu prometheus olarak değiştirerek 5s.

18. Sırada ne var?

Temizleme

Bu atölye için sağlanan geçici bir hesap kullanıyorsanız temizleme 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

Sonraki adımlar