Menggunakan Multicluster Istio untuk "Meningkatkan" Beban Kerja Antar-Cluster

1. Selamat Datang

Terima kasih telah bergabung dengan kami di codelab Istio Multi Cloud Burst dari Google.Codelab ini memerlukan pengalaman langsung tingkat pemula dengan Kubernetes, Node, dan Go.

Yang Anda butuhkan

  • Akun Google Cloud Platform (gunakan akun yang ada, atau kami akan memberikan akun gratis)
  • Laptop Anda (instal "kubectl", "gcloud", dll.) atau Anda dapat menggunakan Google Cloud Shell.

Yang akan Anda pelajari

  • Cara membuat cluster Kubernetes di GKE
  • Cara menginstal Istio di cluster Kubernetes dengan Helm
  • Cara menginstal Istio Multicluster dengan Helm
  • Men-deploy aplikasi web dari sumber ke Kubernetes
  • Menulis dan Menerapkan aturan Perutean Traffic ke Istio
  • Metrik Prometheus
  • Membangun dan mengirim image container di dalam cluster Kubernetes

2. Mempersiapkan

Anda dapat mengikuti codelab ini di:

  • Google Cloud Shell (direkomendasikan): shell dalam browser, dilengkapi dengan alat yang sudah diinstal
  • laptop Anda (ikuti petunjuk di bawah)

Mulai dengan Google Cloud Platform

  1. Ambil kartu akun pengguna gratis Anda dari instruktur jika Anda tidak memiliki akun GCP.
  2. Buka Google Cloud Console, lalu klik "Select a project": 5c2d9bf74c78f7e4.png
  3. Catat "ID" project di suatu tempat, lalu klik project untuk memilihnya: ecc5e8e97bfa6559.png

Cloud Shell menyediakan shell command line di dalam browser Anda dengan alat yang Anda perlukan sudah diinstal dan otomatis diautentikasi ke akun Google Cloud Platform Anda. (Jika Anda tidak ingin menjalankan latihan ini di Cloud Shell, lanjutkan ke bagian berikutnya.)

Buka Cloud Console, lalu klik "Activate Cloud Shell" di toolbar kanan atas:

68a17b036ce24ccb.png

Menambahkan alat ke Cloud Shell

  1. Instal kubectx****: dengan mendownload skrip bash dari sini ke lokasi di $PATH.
  2. Instal helm****: dengan mengikuti petunjuk ini.

Atau, jalankan perintah berikut untuk menginstal keduanya ke ~/.bin dan menambahkannya ke $PATH Anda:

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}

Beberapa tips cepat yang dapat mempermudah penggunaan Cloud Shell:

1. Lepaskan shell ke jendela baru:

2. Menggunakan editor file: Klik ikon pensil di kanan atas untuk meluncurkan editor file dalam browser. Anda akan merasa ini berguna karena kita akan menyalin cuplikan kode ke dalam file.

3. Mulai tab baru: Jika Anda memerlukan lebih dari satu perintah terminal.

4. Memperbesar teks: Ukuran font default di Cloud Shell mungkin terlalu kecil untuk dibaca.

Ctrl-+ di Linux/Windows⌘-+ di macOS.

Jika Anda merasa lebih nyaman menggunakan lingkungan workstation Anda sendiri daripada Cloud Shell, siapkan alat berikut:

  1. Instal gcloud: (Sudah diinstal di Cloud Shell.) Ikuti petunjuk untuk menginstal gcloud di platform Anda. Kita akan menggunakannya untuk membuat cluster Kubernetes.
  2. Instal kubectl:(Sudah diinstal sebelumnya di Cloud Shell.) Jalankan perintah berikut untuk menginstal:
gcloud components install kubectl

Jalankan perintah berikut untuk mengautentikasi gcloud. Anda akan diminta untuk login dengan Akun Google Anda. Kemudian, pilih project yang telah dibuat sebelumnya (seperti yang terlihat di atas) sebagai project default. (Anda dapat melewati konfigurasi zona komputasi):

gcloud init
  1. Instal curl: Sudah diinstal di sebagian besar sistem Linux/macOS. Anda mungkin sudah memilikinya. Jika tidak, telusuri internet untuk mengetahui cara menginstalnya.
  2. Instal kubectx****: dengan mendownload skrip bash dari sini ke lokasi di $PATH
  3. Instal helm****: dengan mengikuti petunjuk ini.

3. Menyiapkan Project GCP

Aktifkan API GKE (Google Kubernetes Engine), GCR (Google Container Registry), dan GCB (Google Cloud Build) di project Anda:

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

Menyiapkan Variabel Lingkungan

Kita akan sering menggunakan project Google Cloud selama penyiapan. Mari kita tetapkan variabel lingkungan untuk referensi cepat

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

Kita akan membuat beberapa file kode dan konfigurasi selama workshop ini, jadi mari kita buat direktori project dan beralih ke direktori tersebut

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

4. Buat cluster Kubernetes "utama"

Anda dapat dengan mudah membuat cluster Kubernetes terkelola dengan Google Kubernetes Engine (GKE).

Perintah berikut akan membuat cluster Kubernetes:

  • bernama "primary",
  • di zona us-west1-a,
  • Versi Kubernetes terbaru yang tersedia,
  • dengan 4 node awal
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

(Proses ini mungkin memerlukan waktu sekitar 5 menit. Anda dapat melihat pembuatan cluster di Cloud Console.)

Setelah cluster Kubernetes dibuat, gcloud mengonfigurasi kubectl dengan kredensial yang mengarah ke cluster.

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

Anda sekarang dapat menggunakan kubectl dengan cluster baru Anda.

Jalankan perintah berikut untuk mencantumkan node Kubernetes cluster Anda (statusnya harus "Ready"):

kubectl get nodes

Mengubah nama Kubeconfig agar mudah digunakan

Kita akan sering beralih antar-konteks, jadi memiliki alias singkat untuk cluster kita akan sangat berguna.

Perintah ini akan mengganti nama entri kubeconfig yang baru saja Anda buat menjadi primary

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

Menetapkan izin:

Untuk men-deploy Istio, Anda harus menjadi admin cluster. Perintah ini akan menetapkan email yang terkait dengan akun Google Cloud Anda sebagai admin cluster

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

5. Buat cluster "burst"

Perintah berikut akan membuat cluster Kubernetes:

  • bernama "burst",
  • di zona us-west1-a,
  • Versi Kubernetes terbaru yang tersedia,
  • Dengan 1 node awal
  • Penskalaan otomatis diaktifkan hingga 5 node
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

(Proses ini mungkin memerlukan waktu sekitar 5 menit. Anda dapat melihat pembuatan cluster di Cloud Console.)

Setelah cluster Kubernetes dibuat, gcloud mengonfigurasi kubectl dengan kredensial yang mengarah ke cluster.

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

Anda sekarang dapat menggunakan kubectl dengan cluster baru Anda.

Jalankan perintah berikut untuk mencantumkan node Kubernetes cluster Anda (statusnya harus "Ready"):

kubectl get nodes

Mengubah nama Kubeconfig agar mudah digunakan

Perintah ini akan mengubah entri kubeconfig yang baru saja Anda buat menjadi burst

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

Menetapkan izin:

Untuk men-deploy Istio Remote, Anda harus menjadi admin cluster. Perintah ini akan menetapkan email yang terkait dengan akun Google Cloud Anda sebagai admin cluster

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

6. Menerapkan Aturan Firewall

Agar kedua cluster kita dapat berkomunikasi satu sama lain, kita perlu membuat aturan Firewall.

Jalankan perintah berikut untuk membuat aturan Firewall di Google Cloud Platform yang akan mengizinkan cluster kita berkomunikasi

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

Kita telah menyiapkan kedua cluster dan siap untuk men-deploy aplikasi dan Istio di dalamnya.

7. Pengantar Istio

Apa Itu Istio?

Istio adalah bidang kontrol mesh layanan yang bertujuan untuk "menghubungkan, mengamankan, mengontrol, dan mengamati layanan". Hal ini dilakukan dengan berbagai cara, tetapi terutama dengan menyertakan container proxy ( Envoy) ke setiap Pod Kubernetes yang di-deploy. Kontainer proxy mengontrol semua komunikasi jaringan antara microservice bersama dengan kebijakan dan hub telemetri serbaguna ( Mixer).

a25613cd581825da.png

Kebijakan ini dapat diterapkan secara terpisah dari Deployment dan Layanan Kubernetes Anda, yang berarti Operator Jaringan dapat mengamati aktivitas jaringan, membatasi, mengalihkan, atau menulis ulang kebijakan jaringan tanpa men-deploy ulang aplikasi terkait.

Beberapa fitur Pengelolaan Traffic yang Didukung Istio adalah:

  • Pemutus rangkaian
  • Pemisahan traffic berbasis persentase
  • Penulisan ulang URL
  • TLS termination
  • Health check
  • Load balancing

Untuk tujuan workshop ini, kita akan berfokus pada pembagian traffic berbasis persentase.

Istilah Istio yang Akan Kita Gunakan

Layanan Virtual

VirtualService menentukan serangkaian aturan perutean traffic yang akan diterapkan saat host ditangani.

Gateway

Gateway adalah load balancer yang beroperasi di tepi mesh yang menerima koneksi HTTP/TCP masuk atau keluar. Gateway dapat menentukan Port, konfigurasi SNI, dll.

Aturan Tujuan

DestinationRule menentukan kebijakan yang berlaku untuk traffic yang ditujukan ke layanan setelah perutean terjadi. Mereka menentukan konfigurasi untuk load balancing, ukuran kumpulan koneksi dari sidecar, dan setelan deteksi pencilan.

Istio Multicluster

Anda mungkin telah memperhatikan saat kami membuat dua cluster, bahwa cluster primary kami memiliki 4 node tanpa penskalaan otomatis, dan cluster burst kami memiliki 1 node dengan penskalaan otomatis hingga 5 node.

Ada dua alasan untuk konfigurasi ini.

Pertama, kita ingin menyimulasikan skenario "on-premise" ke Cloud. Di lingkungan lokal, Anda tidak memiliki akses ke cluster penskalaan otomatis karena Anda memiliki infrastruktur tetap.

Kedua, penyiapan 4 node (seperti yang ditentukan di atas) adalah persyaratan minimum untuk menjalankan Istio. Hal ini menimbulkan pertanyaan: jika Istio memerlukan minimal 4 node, bagaimana cluster burst kita dapat menjalankan Istio dengan 1 node? Jawabannya adalah Istio Multicluster menginstal serangkaian layanan Istio yang jauh lebih kecil, dan berkomunikasi dengan penginstalan Istio di cluster utama untuk mengambil aturan kebijakan dan memublikasikan informasi telemetri.

8. Ringkasan Arsitektur Aplikasi

Ringkasan Komponen

Kita akan men-deploy aplikasi tiga tingkat menggunakan NodeJS dan Redis.

Pekerja

Aplikasi pekerja ditulis dalam NodeJS dan akan memproses permintaan HTTP POST yang masuk, melakukan operasi hashing pada permintaan tersebut, dan jika variabel lingkungan bernama PREFIX ditentukan, aplikasi akan menambahkan nilai tersebut ke hash. Setelah hash dihitung, aplikasi akan mengirimkan hasilnya di channel "calculation" di server Redis yang ditentukan.

Kita akan menggunakan variabel lingkungan PREFIX nanti untuk mendemonstrasikan fungsi multicluster.

Sebagai referensi: berikut adalah paket yang digunakan aplikasi.

  • body-parser: Memungkinkan kita mengurai permintaan http
  • cors: Memungkinkan penggunaan Cross-Origin Resource Sharing
  • dotenv: Penguraian variabel lingkungan yang mudah
  • express: Hosting situs web yang mudah
  • ioredis: Library klien untuk berkomunikasi dengan database Redis
  • morgan: Menyediakan log terstruktur yang bagus

Frontend

Frontend kami juga merupakan aplikasi NodeJS yang menghosting halaman web menggunakan express. Aplikasi ini menggunakan frekuensi yang dimasukkan pengguna dan mengirim permintaan ke aplikasi worker kami pada kecepatan tersebut. Aplikasi ini juga berlangganan pesan di saluran Redis bernama "calculation" dan menampilkan hasilnya di halaman web.

Aplikasi ini menggunakan dependensi berikut.

  • body-parser: Memungkinkan kita mengurai permintaan http
  • dotenv: Penguraian variabel lingkungan yang mudah
  • express: Hosting situs web yang mudah
  • ioredis: Library klien untuk berkomunikasi dengan database Redis
  • morgan: Menyediakan log terstruktur yang bagus
  • request: Memungkinkan pembuatan permintaan HTTP
  • socket.io: Memungkinkan komunikasi dua arah dari Halaman Web ke server

Halaman web ini menggunakan Bootstrap untuk gaya visual dan, saat dijalankan, akan terlihat seperti berikut

e5e3b9cbede4cac4.png

Diagram Arsitektur

7ae4bc22a58f80a6.png

Diagram Deployment

Kita akan men-deploy aplikasi akhir di dua cluster yang kita buat. Cluster primary akan memiliki semua komponen (frontend, worker, dan Redis) yang di-deploy ke dalamnya, tetapi cluster burst hanya akan memiliki aplikasi worker yang di-deploy.

Berikut adalah diagram yang menjelaskan kedua cluster. Kotak yang diberi garis merah adalah Layanan Kubernetes, sedangkan yang berwarna biru adalah Deployment Kubernetes. Kotak kuning menandakan penginstalan Istio.

561db37c510944bd.png

Perhatikan bagaimana cluster burst masih memiliki layanan untuk Redis yang di-deploy ke cluster tersebut meskipun tidak ada Deployment untuk Redis di cluster. Kita memerlukan layanan ini di cluster agar DNS Kubernetes dapat menyelesaikan permintaan, tetapi saat permintaan benar-benar dibuat, Istio Proxy akan mengalihkan permintaan ke deployment Redis di cluster primary.

Aplikasi akhir akan memiliki Deployment tambahan yang berjalan di cluster primary bernama istiowatcher.. Deployment ini akan memungkinkan kita merutekan ulang traffic secara dinamis ke burst secara otomatis saat traffic kita melebihi batas tertentu.

8f6183bdfc3f813c.png

9. Membuat File Deployment Aplikasi

Kita perlu membuat serangkaian manifes Kubernetes untuk men-deploy aplikasi

Beralih ke direktori root project dan buat folder baru bernama kubernetes

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

Tulis frontend.yaml

Tindakan ini akan membuat Deployment dan Layanan Kubernetes untuk mengakses image frontend kita.

Masukkan kode berikut ke frontend.yaml.

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

Hal penting yang perlu diperhatikan dalam Deployment

  • Kita telah menentukan port tempat aplikasi akan berjalan menjadi 8080
  • Kita telah menetapkan alamat untuk pekerja menjadi "http://worker-service" dan akan menggunakan fitur DNS bawaan Kubernetes untuk me-resolve layanan yang dihasilkan
  • Kita telah menetapkan alamat untuk REDIS_URL menjadi "redis-cache-service:6379" dan akan menggunakan fitur DNS bawaan Kubernetes untuk menyelesaikan alamat IP yang dihasilkan.
  • Kita juga telah menyetel pemeriksaan liveness dan readiness ke container untuk membantu memberi tahu Kubernetes saat container aktif dan berjalan.

Tulis worker-service.yaml

Kita menulis definisi layanan Kubernetes dalam file terpisah dari definisi Deployment karena kita akan menggunakan kembali layanan ini di beberapa cluster, tetapi akan menulis Deployment yang berbeda untuk setiap cluster.

Masukkan kode berikut di worker-service.yaml

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

Menulis worker-primary.yaml

Ini akan menjadi deployment worker yang akan kita kirim ke cluster utama.

Masukkan kode berikut ke worker-primary.yaml.

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"

Perhatikan bahwa di sini, kita mengikuti pola yang sama dalam menyediakan probe liveness dan readiness serta menentukan variabel lingkungan PORT dan REDIS_URL yang akan digunakan aplikasi kita.

Hal lain yang perlu diperhatikan dalam deployment ini adalah tidak adanya variabel lingkungan PREFIX. Artinya, hasil penghitungan kita akan berupa hash mentah (tanpa awalan).

Titik utama akhir dari deployment ini adalah label cluster-type: primary-cluster. Kita akan menggunakannya nanti saat melakukan Perutean Traffic di Istio Multicluster

Tulis redis.yaml

Komunikasi dari pekerja kembali ke frontend dilakukan melalui saluran Redis, dan oleh karena itu, kita perlu men-deploy aplikasi Redis ke dalam cluster.

Masukkan kode berikut ke redis.yaml

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: {}

Ini adalah deployment semi-standar aplikasi Redis. Layanan ini akan membuat container berdasarkan image redis:alpine, mengekspos port yang sesuai, dan menetapkan batas resource yang wajar.

Tulis redis-service.yaml

Kita memerlukan Layanan Kubernetes untuk berkomunikasi dengan aplikasi Redis

Masukkan kode berikut ke redis-service.yaml

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

Hal ini memberikan akses layanan bernama redis-cache-service ke Deployment Redis kami.

10. Men-deploy Aplikasi

Setelah image kita di-push ke GCR dan manifes Kubernetes kita ditulis, inilah saat yang tepat untuk men-deploy aplikasi kita dan melihat cara kerjanya.

Jalankan perintah berikut untuk men-deploy aplikasi

  1. Pastikan kita berada di cluster yang tepat
kubectx primary
  1. Men-deploy Cache Redis
kubectl apply -f redis.yaml
  1. Men-deploy Layanan Redis
kubectl apply -f redis-service.yaml
  1. Men-deploy frontend
kubectl apply -f frontend.yaml
  1. Men-deploy Pekerja
kubectl apply -f worker-primary.yaml
  1. Men-deploy Layanan Pekerja
kubectl apply -f worker-service.yaml

Kita telah men-deploy aplikasi ke GKE. Selamat!

Uji

Tunggu hingga pod online

kubectl get pods -w

Setelah semua pod "Berjalan", tekan Ctrl + C

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

Anda akan melihat bahwa kita tidak mengekspos frontend melalui LoadBalancer. Hal ini karena nanti kita akan mengakses aplikasi melalui Istio. Untuk menguji apakah semuanya sudah berjalan, kita akan menggunakan kubectl port-forward. Jalankan perintah berikut untuk meneruskan port 8080 di komputer lokal (atau Cloud Shell) ke port 8080 yang menjalankan deployment frontend.

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

Jika Anda menjalankan secara lokal: buka browser web dan buka http://localhost:8080

Jika Anda menjalankan di Cloud Shell: klik tombol "Web Preview" dan pilih "Preview on port 8080"

bdb5dc75f415be11.png

Anda akan melihat frontend. Jika Anda memasukkan angka di kotak "frekuensi", Anda akan melihat tanda pagar mulai muncul

1caafaffab26897a.png

Selamat, semuanya sudah siap dan berjalan!

Tekan Ctrl+C untuk berhenti meneruskan port.

11. Membersihkan Aplikasi yang Di-deploy

Kita akan menerapkan Istio ke cluster, lalu men-deploy ulang aplikasi. Jadi, mari kita bersihkan aplikasi saat ini terlebih dahulu.

Jalankan perintah berikut untuk menghapus semua Deployment dan layanan yang baru saja Anda buat

  1. Hapus redis-cache-service
kubectl delete -f redis-service.yaml
  1. Hapus redis
kubectl delete -f redis.yaml
  1. Hapus frontend
kubectl delete -f frontend.yaml
  1. Hapus worker
kubectl delete -f worker-primary.yaml
  1. Hapus worker-service
kubectl delete -f worker-service.yaml

12. Instal Istio di Cluster utama

Mendapatkan Istio

Rilis Istio dihosting di GitHub. Perintah berikut akan mendownload versi 1.0.0 istio dan mengekstraknya.

  1. Beralih ke root project Anda
cd ${proj}
  1. Download arsip
curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
  1. Mengekstrak dan menghapus arsip
tar xzf istio-1.0.0-linux.tar.gz && rm istio-1.0.0-linux.tar.gz

Buat Template Istio

Menjalankan perintah Helm berikut akan membuat template untuk menginstal Istio ke cluster Anda.

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

Tindakan ini akan membuat file bernama istio-primary.yaml di direktori saat ini yang berisi semua definisi dan spesifikasi yang diperlukan untuk men-deploy dan menjalankan Istio.

Perhatikan dua parameter --set. Add-on ini menambahkan dukungan Prometheus dan ServiceGraph ke sistem Istio. Kita akan menggunakan layanan Prometheus nanti di lab ini.

Deploy Istio

Untuk men-deploy Istio, pertama-tama kita perlu membuat namespace yang disebut istio-system agar Deployment dan Layanan Istio dapat berjalan di dalamnya.

kubectl create namespace istio-system

Terakhir, terapkan file istio-primary.yaml yang kita buat dengan Helm

kubectl apply -f istio-primary.yaml

Namespace default label

Istio berfungsi dengan menyuntikkan layanan proxy file bantuan ke setiap Deployment Anda. Hal ini dilakukan berdasarkan keikutsertaan, jadi kita perlu memberi label pada namespace default dengan istio-injection=enabled agar Istio dapat otomatis memasukkan sidecar untuk kita.

kubectl label namespace default istio-injection=enabled

Selamat! Kita memiliki cluster yang sudah aktif dan berjalan dengan Istio yang siap untuk men-deploy aplikasi kita.

13. Men-deploy Aplikasi Kita dengan Pengelolaan Traffic Istio

Membuat File Konfigurasi Pengelolaan Traffic Istio

Istio berfungsi mirip dengan Kubernetes karena menggunakan file yaml untuk konfigurasi. Oleh karena itu, kita perlu membuat serangkaian file yang memberi tahu Istio cara mengekspos dan merutekan traffic kita.

Buat direktori bernama istio-manifests dan pindah ke direktori tersebut

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

Tulis frontend-gateway.yaml

File ini akan mengekspos cluster Kubernetes kita dengan cara yang mirip dengan LoadBalancer GKE dan akan merutekan semua traffic masuk ke layanan frontend kita.

Buat file bernama frontend-gateway.yaml dan masukkan kode berikut.

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

Tulis redis-virtualservice.yaml

Buat file bernama redis-virtualservice.yaml dan masukkan kode berikut

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

Tulis worker-virtualservice.yaml

Buat file bernama worker-virtualservice.yaml dan masukkan kode berikut

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

Men-deploy Kebijakan Pengelolaan Traffic Istio

Deployment kebijakan Istio dilakukan dengan cara yang sama seperti resource Kubernetes lainnya, dengan kubectl apply

  1. Menerapkan Gateway kami
kubectl apply -f frontend-gateway.yaml
  1. Terapkan VirtualService Redis kami
kubectl apply -f redis-virtualservice.yaml
  1. Terapkan Worker VirtualService kami
kubectl apply -f worker-virtualservice.yaml

Men-deploy Aplikasi

  1. Kembali ke direktori kubernetes
cd ${proj}/kubernetes
  1. Men-deploy Cache Redis
kubectl apply -f redis.yaml
  1. Men-deploy Layanan Redis
kubectl apply -f redis-service.yaml
  1. Men-deploy frontend
kubectl apply -f frontend.yaml
  1. Men-deploy Pekerja
kubectl apply -f worker-primary.yaml
  1. Men-deploy Layanan Pekerja
kubectl apply -f worker-service.yaml

Verifikasi

Pada tahap ini, kita telah men-deploy ulang aplikasi di cluster dengan kebijakan pengelolaan traffic dan Istio.

Mari kita tunggu hingga semua workload kita aktif

Setelah semuanya online, dapatkan IngressGateway yang kita konfigurasi di 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,

Buka alamat <EXTERNAL-IP>, atau gunakan curl dan Anda akan melihat frontend.

$ curl 35.199.158.10
<!doctype html>
<html>

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

14. Menginstal Istio di Cluster "burst"

Kita telah menghabiskan banyak waktu untuk menyiapkan dan men-deploy di cluster primary, tetapi kita memiliki cluster lain untuk di-deploy.

Di bagian ini, kita perlu mengambil variabel konfigurasi di kedua cluster, jadi perhatikan baik-baik cluster yang dituju untuk setiap perintah.

Membuat Manifes Jarak Jauh Istio

Sama seperti saat men-deploy Istio ke cluster primary, kita akan menggunakan Helm untuk membuat template deployment istio remote ke cluster burst. Namun, sebelum dapat melakukannya, kita perlu mendapatkan beberapa informasi tentang cluster primary

Mengumpulkan informasi cluster utama

Beralih ke cluster primary

kubectx primary

Perintah berikut mengambil alamat IP berbagai pod di cluster utama. Ini digunakan oleh Istio Remote untuk berkomunikasi kembali dengan cluster utama.

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}')

Membuat Template Jarak Jauh

Sekarang kita akan menggunakan helm untuk membuat file bernama istio-remote-burst.yaml yang kemudian dapat kita deploy ke cluster burst.

Berubah ke root project

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

Menginstal Istio Remote di Cluster lonjakan

Untuk menginstal Istio di cluster burst, kita harus mengikuti langkah-langkah yang sama seperti saat menginstal di cluster primary, tetapi kita harus menggunakan file istio-remote-burst.yaml.

Mengubah kubecontext ke burst

kubectx burst

Buat namespace istio-system

kubectl create ns istio-system

Terapkan istio-burst.yaml

kubectl apply -f istio-remote-burst.yaml

Namespace default label

Sekali lagi, kita perlu memberi label pada namespace default agar proxy dapat dimasukkan secara otomatis.

kubectl label namespace default istio-injection=enabled

Selamat! Pada tahap ini, kita telah menyiapkan Istio Remote di cluster burst. Namun, pada titik ini, cluster masih tidak dapat berkomunikasi. Kita perlu membuat file kubeconfig untuk cluster burst yang dapat kita deploy ke cluster primary untuk menautkannya.

Buat kubeconfig untuk cluster "burst"

Perubahan pada cluster burst

kubectx burst

Menyiapkan lingkungan

Kita perlu mengumpulkan beberapa informasi tentang cluster untuk membuat file kubeconfig untuk cluster tersebut.

  1. Mendapatkan nama cluster
CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}")
  1. Mendapatkan nama server cluster
SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
  1. Dapatkan nama secret untuk Otoritas Sertifikat akun layanan istio-multi
SECRET_NAME=$(kubectl get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
  1. Mendapatkan data Otoritas Sertifikat yang disimpan dalam secret sebelumnya
CA_DATA=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['ca\.crt']}")
  1. Dapatkan token yang disimpan di secret sebelumnya
TOKEN=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['token']}" | base64 --decode)

Buat file kubeconfig

Setelah semua variabel lingkungan tersebut ditetapkan, kita perlu membuat file kubeconfig

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

Perintah ini akan membuat file baru bernama burst-kubeconfig di direktori saat ini yang dapat digunakan oleh cluster primary untuk mengautentikasi dan mengelola cluster burst.

Beralih kembali ke cluster utama

kubectx primary

Terapkan kubeconfig untuk "burst", dengan membuat secret dan melabelinya

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

Beri label pada secret agar Istio tahu cara menggunakannya untuk autentikasi multicluster

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

Selamat! Kita telah mengautentikasi kedua cluster dan membuatnya berkomunikasi satu sama lain melalui Istio Multicluster. Mari kita deploy aplikasi Cross-Cluster

15. Men-deploy Aplikasi Lintas Cluster

Membuat Deployment

Ubah ke direktori kubernetes

cd ${proj}/kubernetes

Buat deployment worker untuk cluster "burst": worker-burst.yaml

Buat file bernama worker-burst.yaml dan masukkan kode berikut ke dalamnya:

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

Perhatikan bahwa file ini hampir identik dengan worker-primary.yaml yang kita buat sebelumnya. Ada dua perbedaan utama.

Perbedaan utama pertama adalah kita telah menambahkan variabel lingkungan PREFIX dengan nilai "bursty-"

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

Artinya, pekerja di cluster burst akan menambahkan awalan "bursty-" ke semua hash yang dikirimkannya. Kita dapat menggunakan awalan ini untuk mengetahui bahwa aplikasi kita benar-benar lintas cluster.

Perbedaan utama kedua adalah kami telah mengubah label cluster-type pada deployment ini dari primary-cluster menjadi burst-cluster

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

Kita akan menggunakan label ini nanti saat memperbarui VirtualService.

Mengubah Layanan Istio

Saat ini, layanan Istio kita tidak memanfaatkan kedua deployment kita. 100% traffic kami dirutekan ke cluster "utama". Mari kita ubah.

Beralih ke direktori istio-manifests

cd ${proj}/istio-manifests

Edit worker-virtualservice.yaml untuk menyertakan DestinationRules

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

Anda dapat melihat bahwa kita telah menambahkan tujuan kedua ke VirtualService. Traffic masih merujuk ke host yang sama (worker-service.default.svc.cluster.local), tetapi 50% traffic dirutekan ke subkumpulan primary dan 50% lainnya dirutekan ke subkumpulan burst.

Kita telah menentukan subset primary sebagai deployment yang memiliki label cluster-type: primary-cluster dan subset burst sebagai deployment yang memiliki label cluster-type: burst-cluster.

Hal ini secara efektif membagi traffic kita 50/50 antara kedua cluster.

Deploy ke Cluster

Deploy redis-service.yaml ke cluster lonjakan

Ubah ke kubeconfig burst

kubectx burst

Beralih ke root project kita

cd ${proj}

Kemudian, deploy

Deploy redis-service.yaml ke cluster lonjakan

kubectl apply -f kubernetes/redis-service.yaml

Deploy worker-burst.yaml ke cluster lonjakan

kubectl apply -f kubernetes/worker-burst.yaml

Deploy worker-service.yaml ke cluster lonjakan

kubectl apply -f kubernetes/worker-service.yaml

Menerapkan VirtualService Istio

Ubah ke kubeconfig primary

kubectx primary

Kemudian Deploy

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

Verifikasi Cara Kerjanya

Untuk memverifikasi bahwa ini berfungsi, buka titik Istio Ingress Anda, dan perhatikan bahwa sekitar 50% hash diawali dengan "burst-".

78fb6e235e9f4a07.png

Artinya, kita berhasil berkomunikasi antar-cluster. Coba ubah bobot pada berbagai layanan dan terapkan file worker-virtualservice.yaml. Cara ini sangat bagus untuk menyeimbangkan traffic antar-cluster, tetapi bagaimana jika kita dapat melakukannya secara otomatis?

16. Memanfaatkan Metrik Prometheus

Pengantar Prometheus

Prometheus adalah alat open source untuk memantau dan mengirimkan pemberitahuan sistem yang awalnya dibuat di SoundCloud. Layanan ini mempertahankan model data multidimensi dengan data deret waktu yang diidentifikasi berdasarkan nama metrik dan key/value pair.

Sebagai referensi, berikut adalah diagram Arsitektur Prometheus:

601e1155a825e0c2.png

Istio, saat di-deploy dengan Prometheus, secara otomatis melaporkan berbagai metrik ke server Prometheus. Kita dapat menggunakan metrik ini untuk mengelola cluster secara langsung.

Menjelajahi Metrik Prometheus

Untuk memulai, kita perlu mengekspos Deployment Prometheus.

Buka tab Workloads di GKE, lihat detail workload "prometheus".

b4a7a3cd67db05b3.png

Setelah Anda melihat detail deployment, buka Actions -> Expose.

c04a482e55bdfd41.png

Pilih untuk meneruskan ke port 9090, lalu ketik "Load balancer"

d5af3ba22a7a6ebb.png

Lalu pilih "Expose"

Tindakan ini akan membuat Layanan di alamat IP yang dapat diakses secara publik yang dapat kita gunakan untuk menjelajahi Metrik Prometheus

Tunggu hingga endpoint beroperasi, lalu klik alamat IP di samping "Endpoint eksternal" b1e40ad90851da29.png

Sekarang Anda akan melihat UI Prometheus.

ed273552270337ec.png

Prometheus menyediakan metrik yang cukup untuk menjadi workshopnya sendiri. Namun, untuk saat ini, kita akan mulai dengan mempelajari metrik istio_requests_total.

Mengeksekusi kueri tersebut akan menampilkan banyak data. Ini adalah metrik pada semua permintaan yang melewati mesh layanan Istio, dan jumlahnya sangat banyak. Kita akan mengubah ekspresi untuk memfilter hal-hal yang benar-benar kita minati:

Permintaan dengan layanan tujuan adalah worker-service.default.svc.cluster.local, dan sumbernya adalah frontend-deployment dibatasi hingga 15 detik terakhir

Kueri tersebut akan terlihat seperti ini:

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

Dan memberi kita sekumpulan data yang jauh lebih mudah dikelola untuk dikerjakan

19d551fd5eac3785.png

Namun, masih sedikit padat. Kita ingin mengetahui permintaan per detik, bukan semua permintaan.

Untuk mendapatkannya, kita dapat menggunakan fungsi rate bawaan

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

dbb9dc063a18da9b.png

Hal ini membuat kita semakin dekat, tetapi kita perlu mengurangi metrik tersebut sedikit lebih jauh ke dalam grup logis.

Untuk melakukannya, kita dapat menggunakan kata kunci sum dan by untuk mengelompokkan dan menjumlahkan hasil

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

Sempurna! Kita bisa mendapatkan metrik persis yang kita butuhkan dari Prometheus.

Kueri Prometheus Akhir Kita

Dengan semua yang telah kita pelajari, kueri terakhir yang perlu kita ajukan ke Prometheus adalah

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)

Sekarang kita dapat menggunakan HTTP API mereka untuk mendapatkan metrik.

Kita dapat mengkueri API mereka dengan kueri kita dengan membuat permintaan GET http seperti ini. Ganti <prometheus-ip-here>

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\)

Berikut adalah contoh respons:

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

Sekarang, kita dapat mengekstrak nilai metrik dari JSON

Pembersihan

Kita perlu menghapus Layanan yang baru saja kita gunakan untuk mengekspos Prometheus. Di Konsol Google Cloud, buka bagian atas layanan yang baru saja kita buat, lalu klik "Hapus"

d58cb51b4c922751.png

Langkah Berikutnya:

Setelah menemukan cara untuk mengetahui bagaimana traffic bergerak melalui cluster, dan pada tingkat berapa, langkah berikutnya adalah menulis biner kecil yang secara berkala membuat kueri prometheus, dan jika permintaan per detik ke worker melebihi batas tertentu, terapkan bobot tujuan yang berbeda pada layanan virtual pekerja untuk mengirim semua traffic ke cluster burst. Setelah permintaan per detik berada di bawah nilai minimum, kirim semua traffic kembali ke primary.

17. Membuat Cross Cluster Burst

Penyiapan

Menetapkan semua traffic untuk worker-service ke cluster utama

Kami akan menganggap semua traffic yang ditujukan untuk worker-service yang dirutekan ke cluster primary sebagai status "default" aplikasi kami

Edit $proj/istio-manifests/worker-virtualservice.yaml agar terlihat seperti berikut

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

Pastikan Anda terhubung ke cluster primary

kubectx primary

Terapkan istio-manifests/worker-virtualservice.yaml

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

Menulis daemon istiowatcher

Kita akan menggunakan Go untuk menulis layanan ini karena kecepatan dan portabilitasnya. Alur keseluruhan aplikasi adalah memulai dan setiap detik, kueri prometheus,

Buat direktori baru di src bernama istiowatcher

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

Kita akan memanggil istioctl dari dalam penampung untuk memanipulasi bidang kontrol Istio dari dalam cluster.

Tulis istiowatcher.go

Buat file di direktori tersebut dengan nama istiowatcher.go dan masukkan kode berikut ke dalamnya

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)
        }
}

Menulis Dockerfile

Buat file baru bernama Dockerfile dan masukkan kode berikut ke dalamnya.

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

Dockerfile multi-tahap ini mendownload dan mengekstrak rilis 1.0.0 Istio pada tahap pertama. Tahap kedua menyalin semuanya dari direktori kita ke dalam gambar, lalu menyalin istioctl dari tahap build ke /usr/local/bin (sehingga dapat dipanggil oleh aplikasi kita), mendapatkan dependensi, mengompilasi kode, dan menetapkan CMD menjadi "istiowatcher"

Tulis burst.yaml

Ini adalah file yang akan diterapkan istiowatcher saat permintaan/detik ke worker dari frontend melebihi 15.

Buat file baru bernama burst.yaml dan masukkan kode berikut ke dalamnya.

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

Tulis natural.yaml

Kami akan menganggap ini sebagai status "alami" yang akan kami kembalikan saat permintaan/detik dari frontend ke worker turun di bawah 10. Dalam status ini, 100% traffic dialihkan ke cluster primary.

Buat file baru bernama natural.yaml dan masukkan kode berikut ke dalamnya

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

Bangun dan Kirim istiowatcher

Jalankan perintah berikut untuk mengirim direktori saat ini ke Google Cloud Build (GCB), yang akan membangun dan memberi tag pada image di GCR.

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

Deploy istiowatcher

Beralih ke direktori kubernetes

cd ${proj}/kubernetes/

Tulis file deployment: istiowatcher.yaml

Buat file bernama istiowatcher.yaml dan masukkan kode berikut (Ganti <your-project-id>).

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

Deploy

Pastikan kita berjalan di cluster utama

kubectx primary

Deploy istiowatcher.yaml di namespace istio-system

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

Yang penting untuk diperhatikan adalah direktif serviceAccountName dan automountServiceAccountToken dalam yaml. Tindakan ini akan memberi kita kredensial yang diperlukan untuk menjalankan istioctl dari dalam cluster.

Kita juga perlu men-deploy ini dalam namespace istio-system untuk memastikan kita memiliki kredensial untuk istio-pilot-service-account. (tidak ada di namespace default).

Saksikan peralihan traffic secara otomatis!

Sekarang saatnya momen ajaib! Mari kita buka frontend dan tingkatkan req/detik menjadi 20

Perhatikan bahwa proses ini memerlukan waktu beberapa detik, tetapi semua hash kita akan memiliki awalan "bursty-".

Hal ini karena kita mengambil sampel prometheus dalam rentang 15s yang membuat waktu respons kita sedikit tertinggal. Jika menginginkan rentang yang lebih sempit, kita dapat mengubah kueri menjadi prometheus untuk menjadi 5s.

18. Apa langkah selanjutnya?

Pembersihan

Anda tidak perlu membersihkan jika menggunakan akun sementara yang disediakan untuk workshop ini.

Anda dapat menghapus cluster Kubernetes, aturan firewall, dan image di GCR

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

Langkah Selanjutnya