Thông tin về lớp học lập trình này
1. Chào mừng
Cảm ơn bạn đã tham gia lớp học lập trình Istio Multi Cloud Burst của Google.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 độ mới bắt đầu 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 cụm Kubernetes trên GKE
- Cách cài đặt Istio trên cụm Kubernetes bằng Helm
- Cách cài đặt Istio Multicluster bằng Helm
- Triển khai ứng dụng web từ nguồn đến Kubernetes
- Viết và áp dụng 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 vào cụm Kubernetes
2. Thiết lập
Bạn có thể tham gia 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í của bạn 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ã" của dự án ở đâu đó, sau đó nhấp vào dự án để chọn dự án đó:
Cách 1: Sử dụng Google Cloud Shell (nên dùng)
Cloud Shell cung cấp một màn hình dòng lệnh bên trong trình duyệt của bạn, trong đó có các công cụ bạn cần cài đặt và tự động xác thực với 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 (Bảng điều khiển trên đám mây) 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 hướng dẫn này.
Ngoài ra, hãy 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 vỏ vào 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 khi chúng ta sao chép các đoạn mã vào tệp. | |
3. Bắt đầu thẻ mới: Nếu bạn cần nhiều lời nhắc dòng lệnh. | |
4. Phóng to văn bản: 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 so với Cloud Shell, hãy thiết lập các công cụ sau:
- Cài đặt
gcloud:
(Đã cài đặt sẵn trên Cloud Shell.) Làm theo hướng dẫn để cài đặtgcloud
trên nền tảng của bạn. Chúng ta sẽ sử dụng thông tin này để tạo một cụm Kubernetes. - Cài đặt
kubectl:
(Đã 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. Bạn sẽ được yêu cầu đăng nhập bằng Tài khoản Google của mình. Sau đó, chọn dự án tạo sẵn (xem ở trên) làm dự án mặc định. (Bạn có thể bỏ qua bước định cấu hình vùng điện 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ó thể bạn đã có ứng dụng này. Nếu không, hãy tìm kiếm trên Internet về cách cài đặt trình bổ trợ đó. - 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 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 sang 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à "chính",
- 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 cụm đang được tạo trong Cloud Console.)
Sau khi tạo cụm Kubernetes, gcloud
sẽ định cấu hình kubectl
bằng thông tin xác thực 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 sẽ hiển thị 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 ngữ cảnh, vì vậy, việc có một bí danh ngắn cho các cụm của chúng ta sẽ rất hữu ích.
Lệnh này sẽ đổi tên mục kubeconfig 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 "bùng nổ"
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 cụm đang được tạo trong Cloud Console.)
Sau khi tạo cụm Kubernetes, gcloud
sẽ định cấu hình kubectl
bằng thông tin xác thực 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 sẽ hiển thị 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 nhập 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
Để hai cụm của chúng ta giao tiếp với nhau, chúng ta cần tạo một quy tắc Tường lửa.
Chạy các lệnh sau để tạo quy tắc Tường lửa trong Google Cloud Platform, 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 xong 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 vùng điều khiển lưới dịch vụ nhằm "kết nối, bảo mật, kiểm soát và quan sát các dịch vụ". Công cụ này thực hiện việc này theo nhiều cách, nhưng chủ yếu là bằng cách gắn một vùng chứa proxy ( Envoy) vào mỗi Pod Kubernetes đã triển khai. Vùng chứa proxy kiểm soát tất cả hoạt động giao tiếp mạng giữa các dịch vụ vi mô cùng với chính sách đa năng và trung tâm đo từ xa ( Mixer).
Bạn có thể áp dụng các chính sách này độc lập với các Dịch vụ và Bản triển khai Kubernetes. Điều này có nghĩa là Nhà điều hành mạng có thể quan sát hoạt động mạng, hạn chế, chuyển hướng hoặc viết lại chính sách mạng mà không cần triển khai lại các ứng dụng liên quan.
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 chia lưu lượng truy cập dựa trên tỷ lệ phần trăm
- Viết lại URL
- Kết thúc TLS
- Kiểm tra tình trạng
- Cân bằng tải
Trong phạm vi hội thảo này, chúng ta sẽ tập trung vào việc phân chia lưu lượng truy cập dựa trên tỷ lệ phần trăm.
Các thuật ngữ 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ủ lưu trữ được định địa chỉ.
Cổng
Cổng là một trình cân bằng tải hoạt động ở cạnh của mạng lưới nhận 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. Các tệp này chỉ định cấu hình cho việc cân bằng tải, kích thước nhóm kết nối từ xe bên và chế độ cài đặt phát hiện giá trị ngoại lai.
Istio Multicluster
Bạn có thể nhận thấy khi chúng ta tạo hai cụm, cụm primary
có 4 nút không tự động mở rộng quy mô và cụm burst
có 1 nút với khả năng tự động mở rộng quy mô lên đến 5 nút.
Có hai lý do cho cấu hình này.
Trước tiên, chúng ta muốn mô phỏng một tình huống "tại chỗ" sang đám mây. Trong môi trường cục bộ, bạn không có quyền truy cập vào các cụm tự động điều chỉnh quy mô vì bạn có cơ sở hạ tầng cố định.
Thứ hai, việc thiết lập 4 nút (như đã 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, 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 dịch vụ Istio nhỏ hơn nhiều và giao tiếp với quá trình cài đặt Istio trong cụm chính để truy xuất các quy tắc chính sách và phát hành thông tin đo từ xa.
8. Tổng quan về cấu trúc ứng dụng
Tổng quan về thành phần
Chúng ta sẽ triển khai một ứng dụng ba 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ẽ theo dõi các yêu cầu HTTP POST đến, thực hiện 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 PREFIX
được xác định, thì ứng dụng này sẽ thêm giá trị đó vào đầu hàm băm. Sau khi tính toán hàm băm, ứng dụng sẽ gửi kết quả trên kênh "calculation
" trên máy chủ Redis đã chỉ định.
Chúng ta sẽ sử dụng biến môi trường PREFIX
sau để 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ịch vụ lưu trữ trang web dễ dàngioredis:
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 đẹp
Giao diện người dùng
Giao diện người dùng của chúng ta cũng là một ứng dụng NodeJS lưu trữ một trang web bằng express. Ứng dụng này 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
theo tốc độ đó. Ứng dụng này cũng đăng ký nhận thông báo trên kênh Redis có tên "calculation
" và hiển thị kết quả trong một trang web.
Ứng dụng 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ịch vụ lưu trữ trang web dễ dàngioredis:
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 đẹprequest:
Cho phép tạo 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 sẽ có dạng như sau
Sơ đồ cấu trúc
Biểu đồ triển khai
Chúng ta sẽ triển khai ứng dụng hoàn thiện trên hai cụm đã tạo. Cụm primary
sẽ có tất cả các thành phần (frontend
, worker
và Redis) được triển khai cho cụm này, nhưng cụm burst
sẽ chỉ có ứng dụng worker
được triển khai.
Dưới đây là sơ đồ mô tả hai cụm. Các hộp được viền màu đỏ là Dịch vụ Kubernetes, các hộp màu xanh dương là Các bản triển khai Kubernetes. Các hộp màu vàng cho biết chúng ta đã cài đặt Istio.
Hãy lưu ý cách cụm burst
vẫn có một dịch vụ cho Redis được triển khai cho cụm đó mặc dù không có quá trình Triển khai cho Redis trong cụm. Chúng ta cần có dịch vụ này trong cụm để DNS Kubernetes 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, Proxy Istio sẽ định tuyến lại yêu cầu đến lượt triển khai Redis trong cụm primary
.
Ứng dụng cuối cùng sẽ có một quá trình Triển khai bổ sung chạy trong cụm primary
có tên là istiowatcher.
. Đây là điều 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 động 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 tập hợp tệp kê khai Kubernetes để triển khai ứng dụng
Chuyển sang 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ả Dịch vụ và quá trình Triển khai Kubernetes để truy cập vào hình ảnh giao diện người dùng.
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 chính cần lưu ý trong Deployment
- Chúng ta đã 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 sẵn của Kubernetes để phân giải dịch vụ thu được - Chúng ta đã đặt địa chỉ cho
REDIS_URL
là "redis-cache-service:6379
" và sẽ sử dụng tính năng DNS tích hợp sẵn của Kubernetes để phân giải các địa chỉ IP thu được. - Chúng tôi cũng đã đặt các đầu dò
liveness
vàreadiness
vào vùng chứa để giúp thông báo cho Kubernetes khi 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 với định nghĩa về quá trình 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 quá trình Triển khai khác nhau 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ẽ đẩy vào 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 ý trong phần này, chúng ta đang tuân theo cùng một mẫu cung cấp đầu dò 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à 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 ta sẽ là các hàm băm thô (không có tiền tố nào).
Điểm chính cuối cùng của quá trình triển khai này là nhãn cluster-type: primary-cluster
. Chúng ta sẽ sử dụng thông tin đó sau khi định tuyến lưu lượng truy cập trên nhiều cụm Istio
Viết redis.yaml
Quá trình giao tiếp từ worker trở lại giao diện người dùng là 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 của mình.
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à cách triển khai bán chuẩn của một ứng dụng Redis. Thư viện này 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 các 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 Mô hình triển khai Redis của chúng tôi.
10. Triển khai ứng dụng
Khi hình ảnh được đẩy vào GCR và tệp kê khai Kubernetes được viết, đây là thời điểm thích hợp để triển khai ứng dụng và xem cách hoạt động của ứng dụng!
Chạy các lệnh sau để triển khai ứng dụng
- Đảm bảo chúng ta đ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 nhóm này xuất hiện trên mạng
kubectl get pods -w
Khi tất cả các pod đều "Đ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ứ đã hoạt động hay chưa, 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ộ: hãy mở 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
Xin chúc mừng! Mọi thứ đã sẵn sàng hoạt động!
Nhấn 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 của mình 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 lượt triển khai 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 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à thông số kỹ thuật cần thiết để triển khai và chạy Istio.
Hãy lưu ý hai tham số --set
. Các tính năng này sẽ thêm tính năng hỗ trợ Prometheus và ServiceGraph vào hệ thống Istio. Chúng ta sẽ sử dụng dịch vụ Prometheus sau trong lớp học lập trình.
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
Vùng chứa tên mặc định của nhãn
Istio hoạt động bằng cách chèn dịch vụ proxy sidecar vào từng lượt Triển khai. Việc này được thực hiện trên cơ sở 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 sidecar 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 chạy với Istio để sẵn sàng 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 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. Do đó, chúng ta cần tạo một tập hợp 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 istio-manifests
rồi chuyển sang 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ư LoadBalancer GKE 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
và 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
và 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 Chính sách quản lý lưu lượng truy cập Istio
Việc triển khai các chính sách Istio được thực hiện theo cách tương tự như các tài nguyên Kubernetes khác, với kubectl apply
- Áp dụng Cổng của chúng tôi
kubectl apply -f frontend-gateway.yaml
- Áp dụng VirtualService Redis
kubectl apply -f redis-virtualservice.yaml
- Áp dụng VirtualService của Worker
kubectl apply -f worker-virtualservice.yaml
Triển khai ứng dụng
- Thay đổi trở lại thư mục
kubernetes
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 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 chờ tất cả khối lượng công việc của chúng ta được đưa lên mạng
Sau khi tất cả các máy chủ đều có kết nối mạ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,
Hãy duyệt đến địa chỉ <EXTERNAL-IP> hoặc curl địa chỉ đó và bạn sẽ thấy 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 "bùng nổ"
Chúng ta đã dành nhiều thời gian để thiết lập và triển khai trên cụm primary
, nhưng chúng ta còn có một cụm khác để triển khai!
Trong phần này, chúng ta 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 được trỏ đến cho mỗi 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 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 có một số thông tin về cụm primary
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 truy xuất địa chỉ IP của nhiều vùng chứa trong cụm chính. Các thông tin này được Istio Remote sử dụng để 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
Bây giờ, chúng ta sẽ 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 cho 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 burst
Để 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 không gian tên istio-system
kubectl create ns istio-system
Áp dụng istio-burst.yaml
kubectl apply -f istio-remote-burst.yaml
Vùng chứa tên mặc định của nhãn
Xin nhắc lại, chúng ta cần gắn nhãn cho 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! Tại thời điểm 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 cho cụm primary
để liên kết các cụm này với nhau.
Tạo kubeconfig cho cụm "bùng nổ"
Thay đổi thành cụm bắn phá
kubectx burst
Thiết lập môi trường
Chúng ta 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ụ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ỉ của 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 đặt 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 của bạn. Cụm primary
có thể sử dụng tệp này để xác thực và quản lý cụm burst
.
Thay đổi trở lại cụm chính
kubectx primary
Áp dụng kubeconfig cho "burst" (luồng dữ liệu) bằng cách tạo một khoá bí mật và gắn nhãn cho khoá đó
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 sử dụng khoá đó cho việc 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 và giao tiếp với nhau qua Istio Multicluster. Hãy triển khai ứng dụng của chúng ta trên nhiều cụm
15. Triển khai ứng dụng trên nhiều cụm
Tạo bản triển khai
Thay đổi thành thư mục kubernetes
cd ${proj}/kubernetes
Tạo bản triển khai worker cho cụm "bùng nổ": 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-"
Hãy 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ó hai điểm khác biệt chính.
Điểm khác biệt chính đầu tiên là chúng ta đã 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 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ể sử dụng thông tin này để biết rằng ứng dụng của mình thực sự chạy trên nhiều 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 lầ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 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 lần triển khai. 100% lưu lượng truy cập của chúng tôi đang được định tuyến đến cụm "chính". Hãy thay đổi điều đó.
Thay đổi thành thư mục istio-manifests
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 ta đã thêm một đích đến thứ hai vào VirtualService. Tệp này 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 định tuyến đến tập hợp con primary
và 50% còn lại được định tuyến đến tập hợp con burst
.
Chúng tôi đã xác định tập hợp con primary
là các bản triển khai có nhãn cluster-type: primary-cluster
và tập hợp con burst
là các bản triển khai có nhãn cluster-type: burst-cluster
.
Điều này giúp phân chia lưu lượng truy cập một cách hiệu quả theo tỷ lệ 50/50 giữa hai cụm.
Triển khai cho cụm
Triển khai redis-service.yaml cho cụm burst
Thay đổi thành kubeconfig burst
kubectx burst
Thay đổi thành thư mục gốc của dự án
cd ${proj}
Sau đó, hãy triển khai
Triển khai redis-service.yaml cho cụm burst
kubectl apply -f kubernetes/redis-service.yaml
Triển khai worker-burst.yaml cho cụm burst
kubectl apply -f kubernetes/worker-burst.yaml
Triển khai worker-service.yaml cho cụm burst
kubectl apply -f kubernetes/worker-service.yaml
Áp dụng VirtualServices của Istio
Thay đổi thành kubeconfig primary
kubectx primary
Sau đó, hãy triển khai
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Xác minh rằng mã hoạt động
Để xác minh 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ố là "burst-".
Điều này có nghĩa là chúng ta đang trò chuyện thành công giữa các 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 tuyệt vời để 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ể tự động thực hiện việc này thì sao?
16. Tận dụng các chỉ số Prometheus
Giới thiệu về Prometheus
Prometheus là một bộ công cụ cảnh báo và giám sát hệ thống nguồn mở, ban đầu được xây dựng tại SoundCloud. Lớp này duy trì mô hình dữ liệu nhiều chiều với dữ liệu chuỗi thời gian được xác định theo tên chỉ số và cặp khoá/giá trị.
Để tham khảo, sau đây là sơ đồ Cấu trúc Prometheus:
Khi được triển khai 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 một cách linh hoạt.
Khám phá các chỉ số Prometheus
Để bắt đầu, chúng ta cần hiển thị hoạt động Triển khai Prometheus.
Chuyển đến thẻ Workloads (Khối lượng công việc) trong GKE, sau đó chuyển đến khối lượng công việc "prometheus".
Khi bạn đang xem thông tin chi tiết về quá trình triển khai, hãy chuyển đến Hành động -> Hiển thị.
Chọn chuyển tiếp đến cổng 9090
rồi nhập "Trình cân bằng tải"
Rồi chọn "Hiển thị"
Thao tác này sẽ tạo một Dịch vụ trên một địa chỉ IP có thể truy cập công khai mà chúng ta có thể sử dụng để khám phá các Chỉ số Prometheus
Chờ đ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"
Bây giờ, 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, hiện tại, 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 đi qua mạng lưới dịch vụ Istio và có rất nhiều chỉ số! 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
bị giới hạn ở 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 ta một tập dữ liệu dễ quản lý hơn nhiều
Nhưng vẫn hơi dày. Chúng ta muốn biết số yêu cầu mỗi giây, chứ không phải tất cả yêu cầu.
Để làm được điều đó, 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])
Chúng ta đã gần đến đích, nhưng cần phải giảm bớt các chỉ số đó thành một nhóm hợp lý.
Để làm việc này, chúng ta có thể sử dụng từ khoá sum
và by
để nhóm và tổng hợp 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 các chỉ số chính xác mà chúng ta cần từ Prometheus.
Truy vấn Prometheus cuối cùng của chúng ta
Với tất cả những gì chúng ta đã tìm hiểu, truy vấn cuối cùng mà chúng ta cần gửi đến 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)
Bây giờ, chúng ta có thể sử dụng API HTTP của họ để lấy chỉ số này.
Chúng ta có thể truy vấn API của họ bằng truy vấn của mình bằng cách tạo một 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\)
Dưới đây là 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"
]
}
]
}
}
Bây giờ, 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á cách lưu lượng truy cập di chuyển qua cụm và tốc độ, bước tiếp theo của chúng ta là viết một tệp nhị phân nhỏ truy vấn định kỳ 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 khác nhau trên 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 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 luồng dữ liệu nhiều cụm
Thiết lập
Đặt tất cả lưu lượng truy cập cho worker-service thành cụm chính
Chúng ta 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
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à khả năng di chuyển của ngôn ngữ này. 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 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 vùng điều khiển Istio từ bên trong cụm.
Viết istiowatcher.go
Tạo một tệp trong thư mục đó có tên là istiowatcher.go
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)
}
}
Ghi Dockerfile
Tạo một tệp mới có tên Dockerfile
rồi 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"]
Tệp Dockerfile nhiều giai đoạn này sẽ 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 bản 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 mà 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
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: 0
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 100
Viết natural.yaml
Chúng ta sẽ coi đây là trạng thái "tự nhiên" mà chúng ta 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). Công 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
Thay đổi thành thư mục kubernetes
cd ${proj}/kubernetes/
Ghi tệp triển khai: istiowatcher.yaml
Tạo một tệp có tên istiowatcher.yaml rồi 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 ta đ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 lệnh serviceAccountName
và automountServiceAccountToken
trong yaml. Thao tác này cung cấp cho chúng ta thông tin xác thực cần thiết để chạy istioctl
từ trong cụm.
Chúng ta cũng cần triển khai thông tin này trong không gian tên istio-system
để đảm bảo chúng ta có thông tin xác thực 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!
Bây giờ là khoảnh khắc kỳ diệu! Hãy chuyển sang giao diện người dùng và tăng số yêu cầu/giây lên 20
Lưu ý rằng quá trình này sẽ mất vài giây, nhưng chúng ta sẽ tăng tốc và tất cả hàm băm của chúng ta đều có tiền tố "bursty-"!
Điều này là do chúng ta đang lấy mẫu prometheus trên phạm vi 15s
, khiến thời gian phản hồi bị trễ một chút. Nếu muốn có một dải tần số chặt chẽ hơn, chúng ta có thể thay đổi truy vấn của mình 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ụ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 nói 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 chính: Kubernetes, Istio, Knative: Nền tảng đám mây mở mới – Aparna Sinha, Nhà quản lý sản phẩm nhóm Kubernetes, Google
- Hướng dẫn: Sử dụng Istio – Lee Calcote và Girish Ranganathan, SolarWinds
- Istio – Chế độ xem từ góc độ gói – Matt Turner, Tetrate
- Istio có phải là tường lửa thế hệ mới nhất từng được tạo không? – John Morello, Twistlock
- Đọc tài liệu về Istio
- Tham gia Nhóm làm việc về Istio
- Theo dõi @IstioMesh trên Twitter