Tự động hóa Higress bằng thư viện Fabric8

Sử dụng Fabric8 Kubernetes Client để quản lý Higress thực chất là thao tác trên các Custom Resource (CRD) mà Higress cung cấp, bao gồm:

  • Domain: Cấu hình tên miền (kết nối chứng chỉ, cổng lắng nghe)
  • Route: Định nghĩa quy tắc định tuyến đường dẫn (chuyển hướng yêu cầu đến dịch vụ backend)

Bài viết cung cấp ví dụ Java đầy đủ và chạy được, bao gồm:

  1. Xây dựng lớp Java tương ứng với DomainRoute
  2. Tạo động tên miền HTTPS + định tuyến
  3. Liên kết chứng chỉ TLS
  4. Kiểm tra và dọn dẹp tài nguyên

Điều kiện tiên quyết

  1. Đã triển khai Higress trong cụm
kubectl get crd domains.networking.higress.io
kubectl get crd routes.networking.higress.io
  1. Chuẩn bị chứng chỉ TLS (tùy chọn)
kubectl create secret tls my-tls-secret \
  --cert=your-cert.pem \
  --key=your-key.pem \
  -n default
  1. Phụ thuộc Maven
<dependency>
    <groupId>io.fabric8</groupId>
    <artifactId>kubernetes-client</artifactId>
    <version>6.12.1</version>
</dependency>

Định nghĩa lớp Java cho CRD Higress

  1. Lớp Domain (tương ứng domains.networking.higress.io/v1)
// Domain.java
import io.fabric8.kubernetes.api.model.Namespaced;
import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.model.annotation.Group;
import io.fabric8.kubernetes.model.annotation.Version;

@Group("networking.higress.io")
@Version("v1")
public class Domain extends CustomResource<DomainSpec, Void> implements Namespaced {
}
// DomainSpec.java
import java.util.List;

public class DomainSpec {
    private String domainName; // Tên miền, ví dụ: api.example.com
    private List<String> certificateSecrets; // Danh sách tên Secret chứa chứng chỉ
    private Integer httpPort;  // Cổng HTTP (mặc định 80)
    private Integer httpsPort; // Cổng HTTPS (mặc định 443)

    // Getter và Setter
    public String getDomainName() { return domainName; }
    public void setDomainName(String domainName) { this.domainName = domainName; }

    public List<String> getCertificateSecrets() { return certificateSecrets; }
    public void setCertificateSecrets(List<String> certificateSecrets) { this.certificateSecrets = certificateSecrets; }

    public Integer getHttpPort() { return httpPort; }
    public void setHttpPort(Integer httpPort) { this.httpPort = httpPort; }

    public Integer getHttpsPort() { return httpsPort; }
    public void setHttpsPort(Integer httpsPort) { this.httpsPort = httpsPort; }
}
  1. Lớp Route (tương ứng routes.networking.higress.io/v1)
// Route.java
import io.fabric8.kubernetes.api.model.Namespaced;
import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.model.annotation.Group;
import io.fabric8.kubernetes.model.annotation.Version;

@Group("networking.higress.io")
@Version("v1")
public class Route extends CustomResource<RouteSpec, Void> implements Namespaced {
}
// RouteSpec.java
import java.util.List;

public class RouteSpec {
    private String targetDomain; // Tên miền mục tiêu (phải khớp với Domain.domainName)
    private List<String> routePaths; // Danh sách đường dẫn, ví dụ: ["/api/user/", "/user/"]
    private Backend targetService; // Dịch vụ backend

    public String getTargetDomain() { return targetDomain; }
    public void setTargetDomain(String targetDomain) { this.targetDomain = targetDomain; }

    public List<String> getRoutePaths() { return routePaths; }
    public void setRoutePaths(List<String> routePaths) { this.routePaths = routePaths; }

    public Backend getTargetService() { return targetService; }
    public void setTargetService(Backend targetService) { this.targetService = targetService; }
}
// Backend.java
public class Backend {
    private String serviceName; // Tên Service Kubernetes
    private int servicePort;    // Cổng dịch vụ

    public String getServiceName() { return serviceName; }
    public void setServiceName(String serviceName) { this.serviceName = serviceName; }

    public int getServicePort() { return servicePort; }
    public void setServicePort(int servicePort) { this.servicePort = servicePort; }
}

Ví dụ Java hoàn chỉnh: Tạo tên miền HTTPS + định tuyến

import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;

import java.util.Arrays;

public class HigressManager {

    private static final String NAMESPACE = "default";
    private static final String DOMAIN_NAME = "api.example.com";
    private static final String TLS_SECRET_NAME = "my-tls-secret"; // Phải tồn tại trước
    private static final String BACKEND_SERVICE = "user-service";
    private static final int BACKEND_PORT = 8080;

    public static void main(String[] args) {
        try (KubernetesClient client = new DefaultKubernetesClient()) {

            // === 1. Tạo Domain (kích hoạt HTTPS)===
            Domain domain = new Domain();
            domain.getMetadata().setName("example-domain");
            domain.getMetadata().setNamespace(NAMESPACE);

            DomainSpec domainSpec = new DomainSpec();
            domainSpec.setDomainName(DOMAIN_NAME);
            domainSpec.setCertificateSecrets(Arrays.asList(TLS_SECRET_NAME)); // Liên kết chứng chỉ
            domainSpec.setHttpsPort(443);
            domain.setSpec(domainSpec);

            client.resources(Domain.class)
                  .inNamespace(NAMESPACE)
                  .createOrReplace(domain);

            System.out.println("✅ Domain đã được tạo: " + DOMAIN_NAME);

            // === 2. Tạo Route ===
            Route route = new Route();
            route.getMetadata().setName("user-api-route");
            route.getMetadata().setNamespace(NAMESPACE);

            RouteSpec routeSpec = new RouteSpec();
            routeSpec.setTargetDomain(DOMAIN_NAME); // Phải khớp với Domain.domainName
            routeSpec.setRoutePaths(Arrays.asList("/api/user/", "/user/"));
            
            Backend backend = new Backend();
            backend.setServiceName(BACKEND_SERVICE);
            backend.setServicePort(BACKEND_PORT);
            routeSpec.setTargetService(backend);
            
            route.setSpec(routeSpec);

            client.resources(Route.class)
                  .inNamespace(NAMESPACE)
                  .createOrReplace(route);

            System.out.println("✅ Route đã được tạo cho tên miền: " + DOMAIN_NAME);

            // === 3. Kiểm tra ===
            Domain fetchedDomain = client.resources(Domain.class)
                                           .inNamespace(NAMESPACE)
                                           .withName("example-domain")
                                           .get();
            System.out.println("Tên miền truy xuất: " + fetchedDomain.getSpec().getDomainName());

        } catch (Exception e) {
            System.err.println("❌ Lỗi: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Lưu ý quan trọng

  1. Mối quan hệ giữa Domain và Route
  • Route.spec.targetDomain phải bằng Domain.spec.domainName
  • Nếu không tạo Domain, Higress sẽ dùng lắng nghe chung (không hỗ trợ HTTPS)
  1. Hỗ trợ HTTPS
  • Chỉ kích hoạt HTTPS khi DomaincertificateSecrets
  • Secret phải là kiểu kubernetes.io/tls và nằm trong cùng namespace
  1. Quy tắc định tuyến
  • Đường dẫn phải kết thúc bằng / (ví dụ: /api/user/)
  • Hỗ trợ nhiều đường dẫn: một Route có thể định tuyến nhiều đường dẫn về cùng backend
  1. Quyền RBAC Đảm bảo ServiceAccount của ứng dụng Java có quyền thao tác CRD Higress:
# rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: higress-manager
rules:
- apiGroups: ["networking.higress.io"]
  resources: ["domains", "routes"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: java-app-higress
  namespace: default
subjects:
- kind: ServiceAccount
  name: default  # Hoặc SA tùy chỉnh
  namespace: default
roleRef:
  kind: Role
  name: higress-manager
  apiGroup: rbac.authorization.k8s.io

Kiểm tra hiệu quả

  1. Xem tài nguyên
kubectl get domains -n default
kubectl get routes -n default
  1. Thử nghiệm truy cập
# HTTP
curl -H "Host: api.example.com" http://<higress-gateway-ip>/api/user/

# HTTPS (cần tin cậy chứng chỉ)
curl -k -H "Host: api.example.com" https://<higress-gateway-ip>/api/user/

Địa chỉ IP gateway Higress lấy từ kubectl get svc -n higress-system higress-gateway

Dọn dẹp tài nguyên

// Xóa Route
client.resources(Route.class)
      .inNamespace(NAMESPACE)
      .withName("user-api-route")
      .delete();

// Xóa Domain
client.resources(Domain.class)
      .inNamespace(NAMESPACE)
      .withName("example-domain")
      .delete();

Mở rộng cho các tình huống phức tạp

Yêu cầu Cách thực hiện
**Chuyển hướng HTTP → HTTPS** Thiết lập redirectEnabled: true trong DomainSpec (yêu cầu Higress v1.3+)
**Cấu hình plugin (JWT)** Thêm trường plugins trong RouteSpec (cần định nghĩa lớp Plugin)
**Phát hành từng phần** Tạo nhiều Route, sử dụng trọng số hoặc header để phân luồng

Thẻ: Fabric8 Kubernetes Higress CRD Java

Đăng vào ngày 26 tháng 5 lúc 11:15