1. Chào mừng bạn
Cảm ơn bạn đã tham gia lớp học lập trình về tính năng Bùng nổ đa đám mây của Istio do Google tổ chức.Lớp học lập trình này yêu cầu bạn có kinh nghiệm thực hành ở cấp độ cơ bản với Kubernetes, Node và Go. Những gì bạn cần
|
|
Kiến thức bạn sẽ học được
- Cách tạo một cụm Kubernetes trên GKE
- Cách cài đặt Istio trên một cụm Kubernetes bằng Helm
- Cách cài đặt Istio Multicluster bằng Helm
- Triển khai một ứng dụng web từ nguồn đến Kubernetes
- Viết và áp dụng các quy tắc định tuyến lưu lượng truy cập cho Istio
- Chỉ số Prometheus
- Tạo và đẩy hình ảnh vùng chứa bên trong một cụm Kubernetes
2. Thiết lập
Bạn có thể làm theo lớp học lập trình này trên:
- Google Cloud Shell (nên dùng): shell trong trình duyệt, đi kèm với các công cụ đã cài đặt
- máy tính xách tay (làm theo hướng dẫn bên dưới)
Bắt đầu với Google Cloud Platform
- Nhận thẻ tài khoản người dùng miễn phí từ người hướng dẫn nếu bạn chưa có tài khoản GCP.
- Truy cập vào Google Cloud Console rồi nhấp vào "Chọn một dự án":

- Ghi lại "Mã nhận dạng" của dự án ở đâu đó, sau đó nhấp vào dự án để chọn:

Cách 1: Sử dụng Google Cloud Shell (nên dùng)
Cloud Shell cung cấp một trình bao dòng lệnh trong trình duyệt của bạn, với các công cụ bạn cần đã được cài đặt và tự động xác thực vào tài khoản Google Cloud Platform của bạn. (Nếu bạn không muốn chạy bài tập này trên Cloud Shell, hãy chuyển sang phần tiếp theo.)
Truy cập vào Cloud Console rồi nhấp vào "Kích hoạt Cloud Shell" trên thanh công cụ ở trên cùng bên phải:

Thêm công cụ vào Cloud Shell
- Cài đặt
kubectx****: bằng cách tải tập lệnh bash xuống từ đây vào một vị trí trong $PATH. - Cài đặt
helm****: làm theo các hướng dẫn này.
Hoặc chạy các lệnh sau để cài đặt cả hai vào ~/.bin và thêm vào $PATH:
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}
Một số mẹo nhanh có thể giúp bạn sử dụng Cloud Shell dễ dàng hơn:
1. Tách shell thành một cửa sổ mới: |
|
2. Sử dụng trình chỉnh sửa tệp: Nhấp vào biểu tượng bút chì ở trên cùng bên phải để chạy trình chỉnh sửa tệp trong trình duyệt. Bạn sẽ thấy tính năng này hữu ích vì chúng ta sẽ sao chép các đoạn mã vào tệp. |
|
3. Mở thẻ mới: Nếu bạn cần nhiều hơn một lời nhắc trên thiết bị đầu cuối. |
|
4. Tăng cỡ chữ: Cỡ chữ mặc định trên Cloud Shell có thể quá nhỏ để đọc. | Ctrl-+ trên Linux/Windows⌘-+ trên macOS. |
Cách 2: Thiết lập máy tính xách tay (không nên dùng)
Nếu bạn cảm thấy thoải mái hơn khi sử dụng môi trường máy trạm của riêng mình thay vì Cloud Shell, hãy thiết lập các công cụ sau:
- Cài đặt
gcloud:(Được cài đặt sẵn trên Cloud Shell.) Làm theo hướng dẫn để cài đặtgcloudtrên nền tảng của bạn. Chúng ta sẽ dùng thông tin này để tạo một cụm Kubernetes. - Cài đặt
kubectl:(Được cài đặt sẵn trên Cloud Shell.) Chạy lệnh sau để cài đặt:
gcloud components install kubectl
Chạy lệnh sau để xác thực gcloud. Ứng dụng sẽ yêu cầu bạn đăng nhập bằng Tài khoản Google. Sau đó, hãy chọn dự án đã tạo trước (như ở trên) làm dự án mặc định. (Bạn có thể bỏ qua bước định cấu hình vùng tính toán):
gcloud init
- Cài đặt
curl:Được cài đặt sẵn trên hầu hết các hệ thống Linux/macOS. Có lẽ bạn đã có ứng dụng này. Nếu không, hãy tìm thông tin trên Internet về cách cài đặt. - Cài đặt
kubectx****: bằng cách tải tập lệnh bash từ đây xuống một vị trí trong $PATH - Cài đặt
helm****: làm theo các hướng dẫn này.
3. Thiết lập dự án GCP
Bật API GKE (Google Kubernetes Engine), GCR (Google Container Registry) và GCB (Google Cloud Build) trên dự án của bạn:
gcloud services enable \ cloudapis.googleapis.com \ container.googleapis.com \ containerregistry.googleapis.com \ cloudbuild.googleapis.com
Thiết lập biến môi trường
Chúng ta sẽ làm việc nhiều với dự án Google Cloud trong quá trình thiết lập. Hãy đặt một biến môi trường để tham khảo nhanh
export GCLOUD_PROJECT=$(gcloud config get-value project)
Chúng ta sẽ tạo một số mã và tệp cấu hình trong hội thảo này. Vì vậy, hãy tạo một thư mục dự án và chuyển vào thư mục đó
mkdir -p src/istio-burst && \ cd src/istio-burst && \ export proj=$(pwd)
4. Tạo cụm Kubernetes "chính"
Bạn có thể dễ dàng tạo cụm Kubernetes được quản lý bằng Google Kubernetes Engine (GKE).
Lệnh sau đây sẽ tạo một cụm Kubernetes:
- có tên là "primary",
- trong vùng us-west1-a,
- Phiên bản Kubernetes mới nhất hiện có,
- với 4 nút ban đầu
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
(Quá trình này có thể mất khoảng 5 phút. Bạn có thể xem quá trình tạo cụm tại Cloud Console.)
Sau khi cụm Kubernetes được tạo, gcloud sẽ định cấu hình kubectl bằng thông tin đăng nhập trỏ đến cụm.
gcloud container clusters get-credentials $cluster --zone=$zone
Giờ đây, bạn có thể sử dụng kubectl với cụm mới.
Chạy lệnh sau để liệt kê các nút Kubernetes của cụm (các nút này phải có trạng thái "Sẵn sàng"):
kubectl get nodes
Sửa đổi tên Kubeconfig để dễ sử dụng
Chúng ta sẽ thường xuyên chuyển đổi giữa các bối cảnh, vì vậy, việc có một bí danh ngắn cho các cụm của chúng ta là rất hữu ích.
Lệnh này sẽ đổi tên mục kubeconfig mà bạn vừa tạo thành primary
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
Đặt quyền:
Để triển khai Istio, bạn phải là quản trị viên cụm. Lệnh này sẽ đặt email liên kết với tài khoản Google Cloud của bạn làm quản trị viên cụm
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
5. Tạo cụm "burst"
Lệnh sau đây sẽ tạo một cụm Kubernetes:
- có tên là "burst",
- trong vùng us-west1-a,
- Phiên bản Kubernetes mới nhất hiện có,
- Có 1 nút ban đầu
- Đã bật tính năng tự động mở rộng quy mô lên đến 5 nút
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
(Quá trình này có thể mất khoảng 5 phút. Bạn có thể xem quá trình tạo cụm tại Cloud Console.)
Sau khi cụm Kubernetes được tạo, gcloud sẽ định cấu hình kubectl bằng thông tin đăng nhập trỏ đến cụm.
gcloud container clusters get-credentials $cluster --zone=$zone
Giờ đây, bạn có thể sử dụng kubectl với cụm mới.
Chạy lệnh sau để liệt kê các nút Kubernetes của cụm (các nút này phải có trạng thái "Sẵn sàng"):
kubectl get nodes
Sửa đổi tên Kubeconfig để dễ sử dụng
Lệnh này sẽ sửa đổi mục kubeconfig mà bạn vừa tạo thành burst
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
Đặt quyền:
Để triển khai Istio Remote, bạn phải là quản trị viên cụm. Lệnh này sẽ đặt email liên kết với tài khoản Google Cloud của bạn làm quản trị viên cụm
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
6. Áp dụng quy tắc tường lửa
Để 2 cụm này giao tiếp với nhau, chúng ta cần tạo một quy tắc cho Tường lửa.
Chạy các lệnh sau để tạo một quy tắc Tường lửa trong Google Cloud Platform. Quy tắc này sẽ cho phép các cụm của chúng ta giao tiếp
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
Chúng ta đã thiết lập cả hai cụm và sẵn sàng triển khai ứng dụng cũng như Istio trên các cụm đó!
7. Giới thiệu về Istio
Istio là gì?
Istio là một lớp điều khiển lưới dịch vụ nhằm "kết nối, bảo mật, kiểm soát và giám sát các dịch vụ". Istio thực hiện việc này theo nhiều cách, nhưng chủ yếu là bằng cách thêm một vùng chứa proxy ( Envoy) vào mỗi Pod Kubernetes mà bạn đã triển khai. Vùng chứa proxy kiểm soát mọi hoạt động giao tiếp mạng giữa các vi dịch vụ cùng với một chính sách đa năng và trung tâm đo từ xa ( Mixer).

Các chính sách này có thể được áp dụng độc lập với các Dịch vụ và Hoạt động triển khai Kubernetes của bạn, tức là Network Operator có thể quan sát hoạt động mạng, hạn chế, chuyển hướng hoặc viết lại các chính sách mạng mà không cần triển khai lại các ứng dụng được liên kết.
Một số tính năng Quản lý lưu lượng truy cập mà Istio hỗ trợ là:
- Cầu dao
- Phân tách lưu lượng truy cập dựa trên tỷ lệ phần trăm
- Viết lại URL
- Chấm dứt TLS
- Kiểm tra tình trạng
- Cân bằng tải
Trong hội thảo này, chúng ta sẽ tập trung vào việc phân tách lưu lượng truy cập dựa trên tỷ lệ phần trăm.
Các điều khoản về Istio mà chúng ta sẽ sử dụng
VirtualService
VirtualService xác định một bộ quy tắc định tuyến lưu lượng truy cập để áp dụng khi một máy chủ được định địa chỉ.
Cổng
Cổng là một trình cân bằng tải hoạt động ở rìa của lưới, nhận các kết nối HTTP/TCP đến hoặc đi. Cổng có thể chỉ định Cổng, cấu hình SNI, v.v.
DestinationRule
DestinationRule xác định các chính sách áp dụng cho lưu lượng truy cập dành cho một dịch vụ sau khi quá trình định tuyến diễn ra. Chúng chỉ định cấu hình để cân bằng tải, kích thước nhóm kết nối từ sidecar và chế độ cài đặt phát hiện giá trị ngoại lệ.
Istio Multicluster
Có thể bạn đã nhận thấy khi chúng ta tạo hai cụm, cụm primary của chúng ta có 4 nút mà không có tính năng tự động mở rộng quy mô và cụm burst có 1 nút với tính năng tự động mở rộng quy mô lên đến 5 nút.
Có 2 lý do cho cấu hình này.
Trước tiên, chúng ta muốn mô phỏng một kịch bản "tại chỗ" lên đám mây. Trong môi trường tại chỗ, bạn không có quyền truy cập vào các cụm tự động mở rộng quy mô vì bạn có cơ sở hạ tầng cố định.
Thứ hai, chế độ thiết lập 4 nút (như được xác định ở trên) là yêu cầu tối thiểu để chạy Istio. Điều này đặt ra câu hỏi: nếu Istio yêu cầu tối thiểu 4 nút, thì làm cách nào để cụm burst của chúng ta chạy Istio với 1 nút? Câu trả lời là Istio Multicluster cài đặt một nhóm nhỏ hơn nhiều các dịch vụ Istio và giao tiếp với bản cài đặt Istio trong cụm chính để truy xuất các quy tắc chính sách và xuất bản thông tin đo từ xa.
8. Tổng quan về cấu trúc ứng dụng
Tổng quan về các thành phần
Chúng ta sẽ triển khai một ứng dụng gồm 3 cấp bằng cách sử dụng NodeJS và Redis.
Worker
Ứng dụng worker được viết bằng NodeJS và sẽ lắng nghe các yêu cầu POST HTTP đến, thực hiện một thao tác băm trên các yêu cầu đó và nếu một biến môi trường có tên là PREFIX được xác định, thì ứng dụng sẽ thêm giá trị đó vào trước hàm băm. Sau khi tính toán xong, ứng dụng sẽ gửi kết quả trên kênh "calculation" trên máy chủ Redis đã chỉ định.
Sau này, chúng ta sẽ sử dụng biến môi trường PREFIX để minh hoạ chức năng nhiều cụm.
Để tham khảo: đây là các gói mà ứng dụng sử dụng.
body-parser:Cho phép chúng ta phân tích cú pháp các yêu cầu httpcors:Cho phép sử dụng tính năng Chia sẻ tài nguyên trên nhiều nguồn gốcdotenv:Dễ dàng phân tích cú pháp các biến môi trườngexpress:Dễ dàng lưu trữ trang webioredis:Thư viện ứng dụng để giao tiếp với cơ sở dữ liệu Redismorgan:Cung cấp nhật ký có cấu trúc rõ ràng
Giao diện người dùng
Giao diện người dùng của chúng tôi cũng là một ứng dụng NodeJS lưu trữ một trang web bằng express. Nó lấy tần suất do người dùng nhập và gửi yêu cầu đến ứng dụng worker của chúng tôi theo tốc độ đó. Ứng dụng này cũng đăng ký nhận thông báo trên một kênh Redis có tên "calculation" và hiển thị kết quả trên một trang web.
Ứng dụng này sử dụng các phần phụ thuộc sau.
body-parser:Cho phép chúng ta phân tích cú pháp các yêu cầu httpdotenv:Dễ dàng phân tích cú pháp các biến môi trườngexpress:Dễ dàng lưu trữ trang webioredis:Thư viện ứng dụng để giao tiếp với cơ sở dữ liệu Redismorgan:Cung cấp nhật ký có cấu trúc rõ ràngrequest:Cho phép đưa ra yêu cầu HTTPsocket.io:Cho phép giao tiếp hai chiều từ Trang web đến máy chủ
Trang web này sử dụng Bootstrap để tạo kiểu và khi chạy, trang web này sẽ có dạng như sau

Sơ đồ kiến trúc

Sơ đồ triển khai
Chúng ta sẽ triển khai ứng dụng cuối cùng trên hai cụm mà chúng ta đã tạo. Cụm primary sẽ có tất cả các thành phần (frontend, worker và Redis) được triển khai, nhưng cụm burst sẽ chỉ có ứng dụng worker được triển khai.
Dưới đây là biểu đồ mô tả 2 cụm này. Các hộp được viền màu đỏ là Dịch vụ Kubernetes, còn các hộp màu xanh dương là Triển khai Kubernetes. Các hộp màu vàng biểu thị quá trình cài đặt Istio.
Lưu ý cách cụm burst vẫn có một dịch vụ cho Redis được triển khai cho cụm này, mặc dù không có Deployment nào cho Redis trong cụm. Chúng ta cần có dịch vụ này trong cụm để Kubernetes DNS có thể phân giải yêu cầu, nhưng khi yêu cầu thực sự được thực hiện, Istio Proxy sẽ định tuyến lại yêu cầu đến việc triển khai Redis trong cụm primary.
Ứng dụng cuối cùng sẽ có một Deployment bổ sung đang chạy trong cụm primary có tên là istiowatcher.. Đây là những gì sẽ cho phép chúng ta tự động định tuyến lại lưu lượng truy cập đến burst một cách linh hoạt khi lưu lượng truy cập vượt quá một ngưỡng nhất định.

9. Tạo tệp triển khai ứng dụng
Chúng ta cần tạo một bộ tệp kê khai Kubernetes để triển khai ứng dụng
Thay đổi thành thư mục gốc của dự án và tạo một thư mục mới có tên là kubernetes
mkdir ${proj}/kubernetes && cd ${proj}/kubernetes
Viết frontend.yaml
Thao tác này sẽ tạo cả Kubernetes Deployment và Service để truy cập vào hình ảnh giao diện người dùng của chúng ta.
Chèn nội dung sau vào 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
Những điều quan trọng cần lưu ý trong Deployment
- Chúng tôi đã chỉ định cổng mà ứng dụng sẽ chạy là
8080 - Chúng ta đã đặt địa chỉ cho worker là "
http://worker-service" và sẽ sử dụng tính năng DNS tích hợp của Kubernetes để phân giải dịch vụ kết quả - Chúng tôi đã đặt địa chỉ cho
REDIS_URLlà "redis-cache-service:6379" và sẽ sử dụng tính năng DNS tích hợp của Kubernetes để phân giải các địa chỉ IP kết quả. - Chúng tôi cũng đã thiết lập các lệnh
livenessvàreadinessđể thăm dò vùng chứa nhằm giúp Kubernetes biết khi nào vùng chứa đang hoạt động.
Viết worker-service.yaml
Chúng ta sẽ viết định nghĩa dịch vụ Kubernetes trong một tệp riêng biệt so với định nghĩa Triển khai vì chúng ta sẽ sử dụng lại dịch vụ này trên nhiều cụm, nhưng sẽ viết một định nghĩa Triển khai khác cho mỗi cụm.
Chèn nội dung sau vào worker-service.yaml
apiVersion: v1
kind: Service
metadata:
name: worker-service
spec:
type: ClusterIP
selector:
app: worker
ports:
- name: http
port: 80
targetPort: 8081
Viết worker-primary.yaml
Đây sẽ là quá trình triển khai worker mà chúng ta sẽ chuyển sang cụm chính.
Chèn nội dung sau vào 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"
Lưu ý rằng trong ví dụ này, chúng ta đang tuân theo cùng một mẫu cung cấp các lệnh dò tìm liveness và readiness, cũng như chỉ định các biến môi trường PORT và REDIS_URL để ứng dụng của chúng ta sử dụng.
Một điều khác cần lưu ý trong quá trình triển khai này là việc thiếu biến môi trường PREFIX. Điều này có nghĩa là kết quả tính toán của chúng tôi sẽ là các hàm băm thô (không có tiền tố).
Điểm mấu chốt cuối cùng của việc triển khai này là nhãn cluster-type: primary-cluster. Chúng ta sẽ sử dụng tính năng đó sau này khi thực hiện Định tuyến lưu lượng truy cập trên Istio Multicluster
Viết redis.yaml
Thông tin liên lạc từ worker trở lại giao diện người dùng thông qua một kênh Redis. Do đó, chúng ta cần triển khai một ứng dụng Redis vào cụm.
Chèn nội dung sau vào 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: {}
Đây là một chế độ triển khai bán chuẩn của ứng dụng Redis. Thao tác này sẽ thiết lập một vùng chứa dựa trên hình ảnh redis:alpine, hiển thị các cổng thích hợp và đặt giới hạn tài nguyên hợp lý.
Viết redis-service.yaml
Chúng ta cần một Dịch vụ Kubernetes để giao tiếp với ứng dụng Redis
Chèn nội dung sau vào redis-service.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-cache-service
spec:
type: ClusterIP
selector:
app: redis-cache
ports:
- port: 6379
targetPort: 6379
Thao tác này cung cấp dịch vụ có tên redis-cache-service để truy cập vào Redis Deployment của chúng tôi.
10. Triển khai ứng dụng
Sau khi đẩy các hình ảnh của chúng ta lên GCR và viết các tệp kê khai Kubernetes, đây là thời điểm thích hợp để triển khai ứng dụng và xem cách ứng dụng hoạt động!
Chạy các lệnh sau để triển khai ứng dụng
- Đảm bảo chúng tôi đang ở đúng cụm
kubectx primary
- Triển khai bộ nhớ đệm Redis
kubectl apply -f redis.yaml
- Triển khai dịch vụ Redis
kubectl apply -f redis-service.yaml
- Triển khai giao diện người dùng
kubectl apply -f frontend.yaml
- Triển khai Worker
kubectl apply -f worker-primary.yaml
- Triển khai Dịch vụ Worker
kubectl apply -f worker-service.yaml
Chúng ta đã triển khai ứng dụng của mình lên GKE. Xin chúc mừng!
Kiểm thử
Chờ các pod chuyển sang trạng thái trực tuyến
kubectl get pods -w
Sau khi tất cả các pod đều ở trạng thái "Running" (Đang chạy), hãy nhấn tổ hợp phím 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
Bạn sẽ nhận thấy rằng chúng tôi không hiển thị giao diện người dùng thông qua LoadBalancer. Đó là vì sau này chúng ta sẽ truy cập vào ứng dụng thông qua Istio. Để kiểm thử xem mọi thứ có đang hoạt động hay không, chúng ta sẽ sử dụng kubectl port-forward. Chạy lệnh sau để chuyển tiếp cổng 8080 trên máy cục bộ (hoặc Cloud Shell) sang cổng 8080 đang chạy quá trình triển khai frontend.
kubectl port-forward \
$(kubectl get pods -l app=frontend -o jsonpath='{.items[0].metadata.name}') \
8080:8080
Nếu bạn đang chạy cục bộ: mở một trình duyệt web rồi chuyển đến http://localhost:8080
Nếu bạn đang chạy trong Cloud Shell: hãy nhấp vào nút "Xem trước trên web" rồi chọn "Xem trước trên cổng 8080"

Bạn sẽ thấy giao diện người dùng! Và nếu nhập một số vào hộp "tần suất", bạn sẽ thấy các hàm băm bắt đầu xuất hiện

Chúc mừng bạn, mọi thứ đã hoạt động!
Nhấn vào Ctrl+C để dừng chuyển tiếp cổng.
11. Dọn dẹp ứng dụng đã triển khai
Chúng ta sẽ áp dụng Istio cho cụm rồi triển khai lại ứng dụng. Vì vậy, trước tiên, hãy dọn dẹp ứng dụng hiện tại.
Chạy các lệnh sau để xoá tất cả các Deployment và dịch vụ mà bạn vừa tạo
- Xoá
redis-cache-service
kubectl delete -f redis-service.yaml
- Xoá
redis
kubectl delete -f redis.yaml
- Xoá
frontend
kubectl delete -f frontend.yaml
- Xoá
worker
kubectl delete -f worker-primary.yaml
- Xoá
worker-service
kubectl delete -f worker-service.yaml
12. Cài đặt Istio trên Cụm chính
Tải Istio
Các bản phát hành của Istio được lưu trữ trên GitHub. Các lệnh sau sẽ tải phiên bản 1.0.0 của istio xuống và giải nén phiên bản đó.
- Thay đổi thành thư mục gốc của dự án
cd ${proj}
- Tải bản lưu trữ xuống
curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
- Giải nén và xoá tệp lưu trữ
tar xzf istio-1.0.0-linux.tar.gz && rm istio-1.0.0-linux.tar.gz
Tạo mẫu Istio
Việc chạy lệnh Helm sau đây sẽ tạo mẫu để cài đặt Istio vào cụm của bạn.
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
Thao tác này sẽ tạo một tệp có tên là istio-primary.yaml trong thư mục hiện tại của bạn, chứa tất cả các định nghĩa và quy cách cần thiết để triển khai và chạy Istio.
Hãy chú ý đến 2 tham số --set. Các tiện ích này bổ sung khả năng hỗ trợ Prometheus và ServiceGraph cho hệ thống Istio. Chúng ta sẽ sử dụng dịch vụ Prometheus sau trong phòng thí nghiệm.
Triển khai Istio
Để triển khai istio, trước tiên, chúng ta cần tạo một không gian tên có tên là istio-system mà các Dịch vụ và Hoạt động triển khai Istio có thể chạy trong đó.
kubectl create namespace istio-system
Cuối cùng, hãy áp dụng tệp istio-primary.yaml mà chúng ta đã tạo bằng Helm
kubectl apply -f istio-primary.yaml
Không gian tên mặc định của nhãn
Istio hoạt động bằng cách chèn một dịch vụ proxy phụ vào từng Deployment của bạn. Việc này được thực hiện dựa trên cơ chế chọn tham gia, vì vậy, chúng ta cần gắn nhãn không gian tên default bằng istio-injection=enabled để Istio có thể tự động chèn vùng chứa phụ cho chúng ta.
kubectl label namespace default istio-injection=enabled
Xin chúc mừng! Chúng ta đã có một cụm đang hoạt động với Istio, sẵn sàng để chúng ta triển khai ứng dụng!
13. Triển khai ứng dụng bằng tính năng quản lý lưu lượng truy cập của Istio
Tạo tệp cấu hình quản lý lưu lượng truy cập Istio
Istio hoạt động tương tự như Kubernetes vì sử dụng các tệp yaml để định cấu hình. Theo đó, chúng ta cần tạo một bộ tệp để cho Istio biết cách hiển thị và định tuyến lưu lượng truy cập.
Tạo một thư mục có tên là istio-manifests rồi chuyển vào thư mục đó
mkdir ${proj}/istio-manifests && cd ${proj}/istio-manifests
Viết frontend-gateway.yaml
Tệp này sẽ hiển thị cụm Kubernetes của chúng ta theo cách tương tự như GKE LoadBalancer và sẽ định tuyến tất cả lưu lượng truy cập đến dịch vụ giao diện người dùng của chúng ta.
Tạo một tệp có tên là frontend-gateway.yaml rồi chèn nội dung sau.
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
Viết redis-virtualservice.yaml
Tạo một tệp có tên là redis-virtualservice.yaml rồi chèn nội dung sau
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
Viết worker-virtualservice.yaml
Tạo một tệp có tên là worker-virtualservice.yaml rồi chèn nội dung sau
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
Triển khai các chính sách quản lý lưu lượng truy cập của Istio
Việc triển khai các chính sách của Istio được thực hiện theo cách tương tự như các tài nguyên khác của Kubernetes, bằng kubectl apply
- Áp dụng Cổng
kubectl apply -f frontend-gateway.yaml
- Áp dụng Redis VirtualService
kubectl apply -f redis-virtualservice.yaml
- Áp dụng Worker VirtualService
kubectl apply -f worker-virtualservice.yaml
Triển khai ứng dụng
- Chuyển về thư mục
kubernetescủa chúng tôi
cd ${proj}/kubernetes
- Triển khai bộ nhớ đệm Redis
kubectl apply -f redis.yaml
- Triển khai dịch vụ Redis
kubectl apply -f redis-service.yaml
- Triển khai giao diện người dùng
kubectl apply -f frontend.yaml
- Triển khai Worker
kubectl apply -f worker-primary.yaml
- Triển khai Dịch vụ Worker
kubectl apply -f worker-service.yaml
Xác minh
Tại thời điểm này, chúng tôi đã triển khai lại ứng dụng của mình trên một cụm có Istio và các chính sách quản lý lưu lượng truy cập.
Hãy đợi tất cả các khối lượng công việc của chúng ta chuyển sang trạng thái trực tuyến
Sau khi tất cả các thành phần này hoạt động, hãy lấy IngressGateway mà chúng ta đã định cấu hình trong 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,
Bạn có thể duyệt đến địa chỉ <EXTERNAL-IP> hoặc dùng lệnh curl để xem giao diện người dùng!
$ curl 35.199.158.10
<!doctype html>
<html>
<head>
<title>String Hashr</title>
<!-- Bootstrap -->
...
14. Cài đặt Istio trên Cụm "burst"
Chúng tôi đã dành rất nhiều thời gian để thiết lập và triển khai trên cụm primary, nhưng chúng tôi còn một cụm khác để triển khai!
Trong phần này, chúng ta sẽ cần lấy các biến cấu hình trên cả hai cụm. Vì vậy, hãy chú ý đến cụm mà chúng ta đang trỏ đến cho từng lệnh.
Tạo tệp kê khai từ xa Istio
Tương tự như khi triển khai Istio cho cụm primary, chúng ta sẽ sử dụng Helm để tạo mẫu cho việc triển khai Istio từ xa cho cụm burst. Tuy nhiên, trước khi có thể làm như vậy, chúng ta cần lấy một số thông tin về cụm primary của mình
Thu thập thông tin về cụm chính
Thay đổi thành cụm primary
kubectx primary
Các lệnh sau đây truy xuất địa chỉ IP của nhiều nhóm trong cụm chính. Istio Remote dùng các cổng này để giao tiếp lại với cụm chính.
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}')
Tạo mẫu từ xa
Giờ đây, chúng ta sẽ dùng helm để tạo một tệp có tên là istio-remote-burst.yaml. Sau đó, chúng ta có thể triển khai tệp này vào cụm burst.
Thay đổi thành thư mục gốc của dự án
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
Cài đặt Istio Remote trên Cụm tăng tốc
Để cài đặt Istio trên cụm burst, chúng ta cần làm theo các bước tương tự như khi cài đặt trên cụm primary, nhưng chúng ta cần sử dụng tệp istio-remote-burst.yaml.
Thay đổi kubecontext thành burst
kubectx burst
Tạo vùng chứa tên istio-system
kubectl create ns istio-system
Áp dụng istio-burst.yaml
kubectl apply -f istio-remote-burst.yaml
Không gian tên mặc định của nhãn
Một lần nữa, chúng ta cần gắn nhãn không gian tên default để có thể tự động chèn proxy.
kubectl label namespace default istio-injection=enabled
Xin chúc mừng! Đến đây, chúng ta đã thiết lập Istio Remote trên cụm burst. Tuy nhiên, tại thời điểm này, các cụm vẫn không thể giao tiếp. Chúng ta cần tạo một tệp kubeconfig cho cụm burst mà chúng ta có thể triển khai đến cụm primary để liên kết chúng với nhau.
Tạo kubeconfig cho cụm "burst"
Thay đổi thành cụm chụp liên tục
kubectx burst
Thiết lập môi trường
Chúng tôi cần thu thập một số thông tin về cụm để tạo tệp kubeconfig cho cụm đó.
- Lấy tên của cụm
CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}")
- Lấy tên máy chủ của cụm
SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
- Lấy tên của khoá bí mật cho Tổ chức phát hành chứng chỉ tài khoản dịch vụ
istio-multi
SECRET_NAME=$(kubectl get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
- Lấy dữ liệu Cơ quan cấp chứng chỉ được lưu trữ trong khoá bí mật trước đó
CA_DATA=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['ca\.crt']}")
- Lấy mã thông báo được lưu trữ trong khoá bí mật trước đó
TOKEN=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['token']}" | base64 --decode)
Tạo tệp kubeconfig
Sau khi thiết lập tất cả các biến môi trường đó, chúng ta cần tạo tệp 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
Thao tác này sẽ tạo một tệp mới có tên là burst-kubeconfig trong thư mục hiện tại. Tệp này có thể được cụm primary dùng để xác thực và quản lý cụm burst.
Chuyển về cụm chính
kubectx primary
Áp dụng kubeconfig cho "burst" bằng cách tạo một bí mật và gắn nhãn cho bí mật đó
kubectl create secret generic burst-kubeconfig --from-file burst-kubeconfig -n istio-system
Gắn nhãn cho khoá bí mật để Istio biết cách sử dụng khoá này cho quy trình xác thực nhiều cụm
kubectl label secret burst-kubeconfig istio/multiCluster=true -n istio-system
Xin chúc mừng! Chúng tôi đã xác thực cả hai cụm và giao tiếp với nhau thông qua Istio Multicluster. Hãy triển khai ứng dụng Cross-Cluster
15. Triển khai ứng dụng trên nhiều cụm
Tạo các phiên bản triển khai
Thay đổi thành thư mục kubernetes
cd ${proj}/kubernetes
Tạo việc triển khai worker cho cụm "burst": worker-burst.yaml
Tạo một tệp có tên là worker-burst.yaml rồi chèn nội dung sau vào tệp đó:
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-"
Lưu ý rằng tệp này gần giống với worker-primary.yaml mà chúng ta đã tạo trước đó. Có 2 điểm khác biệt chính.
Điểm khác biệt chính đầu tiên là chúng tôi đã thêm biến môi trường PREFIX có giá trị "bursty-"
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
- name: PREFIX
value: "bursty-"
Điều này có nghĩa là worker của chúng ta trong cụm burst sẽ thêm tiền tố "bursty-" vào tất cả các hàm băm mà worker gửi. Chúng ta có thể dùng tiền tố này để biết rằng ứng dụng của chúng ta thực sự là ứng dụng đa cụm.
Điểm khác biệt chính thứ hai là chúng tôi đã thay đổi nhãn cluster-type trên bản triển khai này từ primary-cluster thành burst-cluster
labels:
app: worker
cluster-type: burst-cluster
Chúng ta sẽ sử dụng nhãn này sau khi cập nhật VirtualService.
Sửa đổi các dịch vụ Istio
Hiện tại, các dịch vụ Istio của chúng tôi không tận dụng được cả hai quy trình triển khai. 100% lưu lượng truy cập của chúng tôi đang được chuyển đến cụm "chính". Hãy thay đổi điều đó.
Chuyển sang thư mục istio-manifests của chúng tôi
cd ${proj}/istio-manifests
Chỉnh sửa worker-virtualservice.yaml để thêm 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
Bạn có thể thấy chúng tôi đã thêm một đích đến thứ hai vào VirtualService của mình. Nó vẫn tham chiếu đến cùng một máy chủ lưu trữ (worker-service.default.svc.cluster.local)), nhưng 50% lưu lượng truy cập đang được chuyển đến tập hợp con primary và 50% còn lại được chuyển đến tập hợp con burst.
Chúng ta đã xác định tập hợp con primary là những triển khai có nhãn cluster-type: primary-cluster và tập hợp con burst là những triển khai có nhãn cluster-type: burst-cluster.
Điều này giúp phân tách lưu lượng truy cập của chúng tôi thành 50/50 giữa hai cụm.
Triển khai cho Cụm
Triển khai redis-service.yaml vào cụm tăng tốc
Thay đổi thành burst kubeconfig
kubectx burst
Thay đổi thành thư mục gốc của dự án
cd ${proj}
Sau đó, triển khai
Triển khai redis-service.yaml vào cụm burst
kubectl apply -f kubernetes/redis-service.yaml
Triển khai worker-burst.yaml vào cụm tăng tốc
kubectl apply -f kubernetes/worker-burst.yaml
Triển khai worker-service.yaml vào cụm tăng tốc
kubectl apply -f kubernetes/worker-service.yaml
Áp dụng VirtualService của Istio
Thay đổi thành primary kubeconfig
kubectx primary
Sau đó, hãy triển khai
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Xác minh xem có hiệu quả không
Để xác minh rằng tính năng này hoạt động, hãy duyệt đến điểm truy cập Istio và lưu ý rằng khoảng 50% hàm băm có tiền tố "burst-".

Điều này có nghĩa là chúng ta đang giao tiếp thành công trên nhiều cụm! Hãy thử thay đổi trọng số trên các dịch vụ khác nhau và áp dụng tệp worker-virtualservice.yaml. Đây là một cách hay để cân bằng lưu lượng truy cập giữa các cụm, nhưng nếu chúng ta có thể thực hiện việc này một cách tự động thì sao?
16. Khai thác các chỉ số Prometheus
Giới thiệu về Prometheus
Prometheus là một bộ công cụ nguồn mở để giám sát và cảnh báo hệ thống, ban đầu được xây dựng tại SoundCloud. Nền tảng này duy trì một mô hình dữ liệu đa chiều với dữ liệu chuỗi thời gian được xác định bằng tên chỉ số và các cặp khoá/giá trị.
Để tham khảo, đây là sơ đồ Kiến trúc Prometheus:

Khi được triển khai cùng với Prometheus, Istio sẽ tự động báo cáo nhiều chỉ số cho máy chủ Prometheus. Chúng ta có thể sử dụng các chỉ số này để quản lý các cụm của mình ngay lập tức.
Khám phá các chỉ số Prometheus của chúng tôi
Để bắt đầu, chúng ta cần hiển thị Prometheus Deployment.
Chuyển đến thẻ Workloads (Khối lượng công việc) trong GKE, truy sâu vào khối lượng công việc "prometheus".

Sau khi bạn xem thông tin chi tiết về việc triển khai, hãy chuyển đến phần Actions (Hành động) -> Expose (Hiển thị).

Chọn chuyển tiếp đến cổng 9090 rồi nhập "Bộ cân bằng tải"

Sau đó, chọn "Phơi sáng"
Thao tác này sẽ tạo một Dịch vụ trên địa chỉ IP có thể truy cập công khai mà chúng ta có thể dùng để khám phá các Chỉ số Prometheus
Đợi cho đến khi điểm cuối hoạt động, sau đó nhấp vào địa chỉ IP bên cạnh "Điểm cuối bên ngoài" 
Lúc này, bạn sẽ thấy giao diện người dùng Prometheus.

Prometheus cung cấp đủ chỉ số để trở thành một hội thảo riêng. Tuy nhiên, trước mắt, chúng ta sẽ bắt đầu bằng cách khám phá chỉ số istio_requests_total.
Việc thực thi truy vấn đó sẽ trả về một loạt dữ liệu. Đây là các chỉ số về tất cả các yêu cầu đang được xử lý thông qua lưới dịch vụ Istio. Chúng ta sẽ thay đổi biểu thức để lọc ra những gì chúng ta thực sự quan tâm:
Các yêu cầu mà dịch vụ đích là worker-service.default.svc.cluster.local và nguồn là frontend-deployment chỉ giới hạn trong 15 giây gần nhất
Truy vấn đó có dạng như sau:
istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s]
Và cung cấp cho chúng tôi một tập dữ liệu dễ quản lý hơn nhiều để làm việc

Nhưng vẫn còn hơi dày. Chúng tôi muốn biết số yêu cầu mỗi giây, chứ không phải tất cả các yêu cầu.
Để lấy được giá trị đó, chúng ta có thể sử dụng hàm rate tích hợp sẵn
rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])

Điều này giúp chúng ta tiến gần hơn, nhưng chúng ta cần giảm thêm một chút các chỉ số đó thành một nhóm logic.
Để làm việc này, chúng ta có thể dùng các từ khoá sum và by để nhóm và tính tổng kết quả
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)

Tuyệt lắm! Chúng ta có thể lấy chính xác các chỉ số cần thiết từ Prometheus.
Câu truy vấn Prometheus cuối cùng
Với tất cả những gì chúng ta đã học, truy vấn cuối cùng mà chúng ta cần hỏi Prometheus là
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)
Giờ đây, chúng ta có thể sử dụng HTTP API của họ để lấy chỉ số này.
Chúng ta có thể truy vấn API của chúng bằng truy vấn của mình bằng cách đưa ra yêu cầu GET http như sau. Thay thế <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\)
Sau đây là một ví dụ về phản hồi:
{
"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"
]
}
]
}
}
Giờ đây, chúng ta có thể trích xuất giá trị chỉ số từ JSON
Dọn dẹp
Chúng ta cần xoá Dịch vụ mà chúng ta vừa dùng để hiển thị Prometheus. Trong Google Cloud Console, hãy chuyển đến đầu dịch vụ mà chúng ta vừa tạo rồi nhấp vào "Xoá"

Các bước tiếp theo:
Sau khi tìm ra cách khám phá lưu lượng truy cập đang di chuyển qua cụm và tốc độ di chuyển, bước tiếp theo của chúng tôi là viết một tệp nhị phân nhỏ định kỳ truy vấn prometheus và nếu số yêu cầu mỗi giây đến worker vượt quá một ngưỡng nhất định, hãy áp dụng các trọng số đích đến khác nhau cho dịch vụ ảo của worker để gửi tất cả lưu lượng truy cập đến cụm burst. Khi số yêu cầu mỗi giây giảm xuống dưới một ngưỡng thấp hơn, hãy gửi tất cả lưu lượng truy cập trở lại primary.
17. Tạo một Cụm tăng tốc chéo
Thiết lập
Đặt tất cả lưu lượng truy cập cho dịch vụ worker vào cụm chính
Chúng tôi sẽ coi tất cả lưu lượng truy cập đến worker-service được định tuyến đến cụm primary là trạng thái "mặc định" của ứng dụng
Chỉnh sửa $proj/istio-manifests/worker-virtualservice.yaml để có dạng như sau
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
Đảm bảo bạn đã kết nối với cụm primary
kubectx primary
Áp dụng istio-manifests/worker-virtualservice.yaml
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Viết trình nền istiowatcher
Chúng ta sẽ sử dụng Go để viết dịch vụ này vì tốc độ và tính di động của nó. Quy trình tổng thể của ứng dụng sẽ là khởi động và mỗi giây, truy vấn prometheus,
Tạo một thư mục mới trong src có tên là istiowatcher
mkdir -p ${proj}/src/istiowatcher && cd ${proj}/src/istiowatcher
Chúng ta sẽ gọi istioctl từ bên trong vùng chứa để thao tác với bảng điều khiển Istio từ bên trong cụm.
Viết istiowatcher.go
Tạo một tệp có tên istiowatcher.go trong thư mục đó rồi chèn nội dung sau vào tệp
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)
}
}
Viết tệp Docker
Tạo một tệp mới có tên Dockerfile và chèn nội dung sau vào tệp đó.
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 nhiều giai đoạn này tải xuống và trích xuất bản phát hành 1.0.0 của Istio ở giai đoạn đầu tiên. Giai đoạn thứ hai sao chép mọi thứ từ thư mục của chúng ta vào hình ảnh, sau đó sao chép istioctl từ giai đoạn xây dựng sang /usr/local/bin (để ứng dụng của chúng ta có thể gọi), lấy các phần phụ thuộc, biên dịch mã và đặt CMD thành "istiowatcher"
Viết burst.yaml
Đây là tệp istiowatcher sẽ áp dụng khi số yêu cầu/giây đến worker từ frontend vượt quá 15.
Tạo một tệp mới có tên burst.yaml và chèn nội dung sau vào tệp đó.
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
Viết natural.yaml
Chúng tôi sẽ coi đây là trạng thái "tự nhiên" mà chúng tôi quay lại khi số yêu cầu/giây từ frontend đến worker giảm xuống dưới 10. Ở trạng thái này, 100% lưu lượng truy cập đang được định tuyến đến cụm primary.
Tạo một tệp mới có tên natural.yaml rồi chèn nội dung sau vào tệp đó
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
Tạo và đẩy istiowatcher
Chạy lệnh sau để gửi thư mục hiện tại đến Google Cloud Build (GCB). Thư mục này sẽ tạo và gắn thẻ hình ảnh trong GCR.
gcloud builds submit -t gcr.io/${GCLOUD_PROJECT}/istiowatcher
Triển khai istiowatcher
Chuyển sang thư mục kubernetes của chúng tôi
cd ${proj}/kubernetes/
Viết tệp triển khai: istiowatcher.yaml
Tạo một tệp có tên là istiowatcher.yaml và chèn nội dung sau (Thay thế <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
Triển khai
Đảm bảo chúng tôi đang chạy trong cụm chính
kubectx primary
Triển khai istiowatcher.yaml trong không gian tên istio-system
kubectl apply -n istio-system -f istiowatcher.yaml
Điều quan trọng cần lưu ý là các chỉ thị serviceAccountName và automountServiceAccountToken trong yaml. Thao tác này cung cấp cho chúng ta thông tin đăng nhập cần thiết để chạy istioctl trong cụm.
Chúng ta cũng cần triển khai việc này trong không gian tên istio-system để đảm bảo có thông tin đăng nhập cho istio-pilot-service-account. (không tồn tại trong không gian tên default).
Xem lưu lượng truy cập tự động chuyển đổi!
Giờ là khoảnh khắc kỳ diệu! Hãy chuyển đến giao diện người dùng và tăng số yêu cầu/giây lên 20
Bạn sẽ thấy quá trình này mất vài giây, nhưng chúng ta sẽ tăng tốc độ và tất cả các hàm băm đều có tiền tố "bursty-"!
Nguyên nhân là do chúng tôi đang lấy mẫu prometheus trong phạm vi 15s, điều này khiến thời gian phản hồi của chúng tôi bị trễ một chút. Nếu muốn có một dải băng hẹp hơn nhiều, chúng ta có thể thay đổi truy vấn thành prometheus thành 5s.
18. Tiếp theo là gì?
Dọn dẹp
Bạn không cần dọn dẹp nếu đang sử dụng tài khoản tạm thời được cung cấp cho hội thảo này.
Bạn có thể xoá các cụm Kubernetes, quy tắc tường lửa và hình ảnh trong 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
Tiến về phía trước
- Tham dự một số buổi trò chuyện về Istio!
- Nhận chứng chỉ: Xây dựng ứng dụng tiếp theo bằng Kubernetes + Istio
- Bài phát biểu quan trọng: Kubernetes, Istio, Knative: Nền tảng đám mây mở mới – Aparna Sinha, Giám đốc sản phẩm nhóm phụ trách Kubernetes, Google
- Hướng dẫn: Sử dụng Istio – Lee Calcote và Girish Ranganathan, SolarWinds
- Istio – The Packet's-Eye View – Matt Turner, Tetrate
- Istio có phải là Tường lửa thế hệ tiếp theo tiên tiến nhất từng được tạo ra không? – John Morello, Twistlock
- Đọc tài liệu về Istio
- Tham gia Các nhóm làm việc của Istio
- Theo dõi @IstioMesh trên Twitter




