Gọi một dịch vụ GKE nội bộ từ Cloud Function

cloudFun

Hãy xem xét một Cloud Function được tiếp xúc với Internet.
1_4B5Eg_X_nsPFqlahldq6tg.png

Khi được triển khai, có thể gọi hàm đó và logic thực hiện sẽ được thực thi. Bây giờ hãy giả sử rằng hàm muốn gọi một dịch vụ tiếp xúc REST được triển khai như một container được lưu trữ trong Kubernetes. Theo sơ đồ, cần kết thúc với:
1_mqWgG0e1TA4l2kUIORnZRg.png


Điều này cho thấy ứng dụng khách gọi Cloud Function qua Internet. Sau đó, Cloud Function gọi dịch vụ đích (MyService) được lưu trữ trong tập hợp các pod được sao chép. Các pod được thể hiện như một dịch vụ Kubernetes. Dịch vụ Kubernetes đó chỉ nổi lên bên trong mạng nội bộ GCP VPC. Rõ ràng, dịch vụ không được tiếp xúc với Internet và do đó diện tích bề mặt tấn công của dịch vụ bị giảm.

Câu chuyện này nghe có vẻ hợp lý nhưng cũng có một vài câu đố cần giải quyết. Đầu tiên là khái niệm về định nghĩa dịch vụ MyService. Khi xác định dịch vụ Kubernetes, có các lựa chọn về cách dịch vụ đó sẽ được hiển thị. Cụ thể, có thuộc tính spec.type có thể là một trong:

ClusterIP - Mặc định. Dịch vụ này được cung cấp trong mạng cluster.

NodePort - Dịch vụ có mặt trên mỗi node máy chủ cục bộ tại một cổng nhất định.

LoadBalancer - Tiếp xúc thông qua bộ cân bằng tải của nhà cung cấp đám mây.

ExternalName - Map đến một tên bên ngoài.

Trong số này, LoadBalancer dường như là sự lựa chọn rõ ràng. Tuy nhiên, nếu sử dụng nó, cài đặt mặc định là dịch vụ được hiển thị với IP Internet ổn định trông giống như sau:
1_RFq29Fh311FzIcrKCDY3qw (1).png


Mặc dù nó hoạt động theo chức năng, mọi người đã tiếp xúc MyService qua Internet và tăng diện tích bề mặt tấn công. Giải pháp là sử dụng khả năng cụ thể của GCP do GKE cung cấp, tạo ra bộ cân bằng tải chỉ tiếp xúc với mạng VPC nội bộ GCP. Điều này dẫn đến sự cân bằng tải lớp TCP / UDP bằng cách hiển thị dịch vụ với địa chỉ IP ổn định VPC. Tính năng này được bật bằng cách thêm mục nhập metadata.annotations trong mô tả dịch vụ có tên là cloud.google.com/load-balancer-type với giá trị Internal.

Một dịch vụ ví dụ có thể là:
Mã:
apiVersion: v1
kind: Service
metadata:
  name: myservice
  annotations:
    cloud.google.com/load-balancer-type: "Internal"
  labels:
    app: myservice
spec:
  type: LoadBalancer
  selector:
    app: myservice
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
Sau khi được xác định, sẽ có một bộ cân bằng tải mà khi được gọi, nó sẽ định tuyến lưu lượng đến các pod. Địa chỉ IP ổn định của bộ cân bằng tải sẽ có mặt trên mạng VPC nội bộ. Dịch vụ sẽ không tiếp xúc trên Internet.

Ở dạng sơ đồ, có:
1_Og8_G-IA-BC-M--0WTu6Hw.png


Vẫn còn một vấn đề. Cloud Function là một thành phần không có máy chủ. Khi máy khách gọi Cloud Function, Cloud Function chạy trong môi trường do Google quản lý tách biệt và khác biệt với bất kỳ tài nguyên nào khác đã xác định trong dự án GCP. Điều này bao gồm quyền truy cập vào mạng VPC. Theo mặc định, Cloud Function đơn giản là không thể truy cập mạng đó. Ngay cả khi nó cố gắng đạt được IP ổn định của dịch vụ cân bằng tải, vẫn không có đường dẫn đến nó. Rất may, có một giải pháp. Có một thành phần của mạng VPC được gọi là truy cập VPC. Thành phần này cho phép các sản phẩm GCP không có máy chủ, chẳng hạn như Cloud Function, được liên kết với mạng VPC cho phép yêu cầu truy cập vào địa chỉ IP trên mạng đó thành công.



Bây giờ có thể thực hiện cuộc gọi REST từ Cloud Function đến dịch vụ đích và nó sẽ hoạt động như mong muốn. Một điều chỉnh cuối cùng cần thực hiện là đăng ký một mục nhập DNS cho IP ổn định để có thể code yêu cầu đến một thực thể DNS có tên logic thay vì địa chỉ IP mờ. Private Zone sẽ được sử dụng trong Cloud DNS cho hiệu ứng đó. Kết quả sẽ như mong muốn và được hiển thị như trong sơ đồ ban đầu trong loạt bài này.

Điều tiếp theo là từng bước thực hiện để tạo một dịch vụ Kubernetes mẫu và gọi nó từ Cloud Function như được mô tả trước đây.

1. Tạo một cluster

Sử dụng Cloud Console để tạo một cluster được gọi là my-cluster.
1_cXJ-vfnX94RGS1XwyqcCKw.png

Cuối cùng bấm create. Nó sẽ mất một vài phút để tạo ra cluster .

2. Tạo một ứng dụng

Cần một ứng dụng đơn giản để chạy trong nhóm pod.
Mã:
const http = require('http');
const os = require('os');
const handler = function(request, response) {
    response.writeHead(200);
    response.end("You've hit " + os.hostname() + "\n");
};
var www = http.createServer(handler);
www.listen(8080);
Dưới đây là nội dung tương ứng của Dockerfile được sử dụng để xây dựng docker image:
Mã:
FROM node:7
ADD app.js /app.js
ENTRYPOINT ["node", "app.js"]
3. Tạo một docker image và đưa nó vào sổ đăng ký (registry)
Mã:
gcloud container clusters get-credentials my-cluster --zone us-central1-a
docker build -t gcr.io/[PROJECT]/my-image
docker push gcr.io/[PROJECT]/my-image
4. Tạo một Kubernetes ReplicaSet
Tạo một tệp có tên là replica-set.yaml với nội dung sau
Mã:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: my-replica-set
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: gcr.io/[PROJECT]/my-image
Áp dụng cho cluster Kubernetes:
Mã:
kubectl apply -f replica-set.yaml
Trong Console, hãy truy cập Kubernetes Engine -> Workloads và chờ trạng thái của workload my-replica-set chuyển thành OK.
1_mbTwYECfs4zQs6GPRyrGEw.png


Tại thời điểm này, các pod đang chạy.

5. Tạo một dịch vụ
Tạo một dịch vụ với loại LoadBalancer đang sử dụng bộ cân bằng tải TCP/ UDP nội bộ. Tạo một tệp có tên là service.yaml có chứa:
Mã:
apiVersion: v1
kind: Service
metadata:
  name: my-service
  annotations:
    cloud.google.com/load-balancer-type: "Internal"
  labels:
    app: my-service
spec:
  type: LoadBalancer
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
Áp dụng cho cluster Kubernetes:
Mã:
kubectl apply -f service.yaml
Trong Console, hãy truy cập Kubernetes Engine -> Services & Ingress. Đợi dịch vụ my-service đạt trạng thái OK .

1_IkbQ6eRyi4lLN4AuCEUb2g.png

Hãy lưu ý địa chỉ IP. Đây là IP trên mạng VPC nơi có thể kết nối đến Cân bằng tải.

6. Tạo một mục DNS
Trong Console, truy cập Network services -> Cloud DNS. Nhấp vào Create zone.
1_uHcNOqX-Y7m-v7XBZNTpYg.png

Đặt loại Zone là Private.
1_GGwsOzYvY5puG_5swY1z6A.png



Nhấp vào Add record set.
1_t-TeMtLkFs8ATYCT54xMzA.png

Tại thời điểm này, sẽ map từ myservice.mycompany.internal đến LoadBalancer.

7. Xác định truy cập VPC không có máy chủ.
Truy cập VPC network -> Serverless VPC access. Nhấp vào CREATE CONNECTOR.
1_A_5pBRJrhlryzXl8ZDZHKA.png


8. Tạo Cloud Function sẽ gọi dịch vụ REST.
Đây là mã JavaScript sẽ được thực thi khi thực hiện cuộc gọi đến Cloud Function. Trọng tâm của minh họa là yêu cầu REST gọi dịch vụ Kubernetes:
Mã:
exports.helloWorld = (req, res) => {
  const request = require('request');
  request('http://myservice.mycompany.internal',
   (err, resS, body) => {
    let message = "Hello from Cloud Function: " + body;
    res.status(200).send(message);
  });
};
package.json nên chứa:
Mã:
{
  "name": "sample-http",
  "version": "0.0.1",
  "dependencies": {
    "request": "latest"
  }
}
Trong định nghĩa Function, trong các tùy chọn nâng cao trong Networking, hãy tham khảo trình kết nối VPC:

1_WK02SXWeRPNW8vkf-Tvn4w.png


9. Kiểm tra chức năng
Bây giờ có thể gọi Cloud Function và thấy rằng dịch vụ lưu trữ Kubernetes nội bộ đang được gọi.

Nguồn: https://medium.com/
 
Top