Khởi tạo và cấu hình Kubernetes Cluster với K3s
Cài đặt K3s trên máy chủ Linux
Chúng ta sẽ sử dụng K3s, một phân phối Kubernetes nhẹ, để làm nền tảng cho các phần sau. Điều này giúp giảm tải tài nguyên so với Kubernetes tiêu chuẩn mà vẫn giữ đầy đủ tính năng cần thiết cho Serverless.
Thực thi lệnh cài đặt K3s với chế độ single-node (server) để khởi tạo master và worker trên cùng một máy. Lệnh này sẽ tự động tải và cài đặt các thành phần cần thiết.
curl -sfL https://get.k3s.io | sh -
Kết quả mong đợi: Lệnh chạy xong không báo lỗi, và bạn thấy thông báo "k3s is installed and ready". Dịch vụ k3s sẽ tự động chạy và khởi động.
Cấu hình quyền truy cập (kubectl)
Sau khi cài đặt, bạn cần cấu hình client kubectl để giao tiếp với API server của cluster. K3s lưu cấu hình này trong thư mục của root.
mkdir -p $HOME/.kube
sudo cp /etc/rancher/k3s/k3s.yaml $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Kết quả mong đợi: Bạn có thể chạy lệnh kubectl get nodes mà không cần sudo, và thấy trạng thái của node là Ready.
Verify Cluster
Để đảm bảo cluster hoạt động ổn định trước khi triển khai các thành phần khác, hãy kiểm tra trạng thái của các node và các namespace mặc định.
kubectl get nodes
kubectl get pods -n kube-system
Kết quả mong đợi: Node duy nhất hiển thị trạng thái Ready. Các pod trong namespace kube-system đều ở trạng thái Running hoặc Completed.
Cài đặt và cấu hình Ingress Controller (Traefik)
Triển khai Traefik qua Helm
Chúng ta sẽ sử dụng Traefik làm Ingress Controller vì nó hỗ trợ tốt cho các tính năng động của Serverless và Edge như routing dựa trên header, gRPC, và WebSocket. Cài đặt qua Helm đảm bảo tính nhất quán và dễ nâng cấp.
Thêm repository Helm của Traefik và cài đặt chart với namespace riêng biệt để cô lập.
kubectl create namespace traefik
helm repo add traefik https://traefik.github.io/charts
helm repo update
helm install traefik traefik/traefik --namespace traefik --set providers.kubernetes.ingressClass=traefik --set providers.kubernetes.allowExternalNameServices=true
Kết quả mong đợi: Helm báo thành công (STATUS: deployed). Các pod của Traefik trong namespace traefik sẽ chuyển sang trạng thái Running.
Cấu hình Service để mở cổng
Để expose dịch vụ ra ngoài, chúng ta cần đảm bảo Service của Traefik đang lắng nghe trên cổng 80 (HTTP) và 443 (HTTPS). Mặc định Helm đã làm điều này, nhưng hãy xác nhận lại.
kubectl get svc -n traefik
Kết quả mong đợi: Có service traefik hoặc traefik-public với kiểu LoadBalancer hoặc NodePort, và các cổng 80, 443 đã được mở.
Verify Ingress Controller
Tạo một ingress đơn giản để test việc routing có hoạt động hay không. Đây là bước kiểm chứng cơ bản trước khi cấu hình SSL.
cat
Kết quả mong đợi: Ingress được tạo thành công. Khi truy cập http:///dashboard/ (hoặc cấu hình DNS test.local), bạn sẽ thấy giao diện quản lý của Traefik.
Tích hợp Cert-Manager để tự động cấp phát SSL
Cài đặt Cert-Manager
Cert-Manager sẽ tự động quản lý việc cấp phát và làm mới chứng chỉ SSL từ Let's Encrypt. Đây là yêu cầu bắt buộc cho bất kỳ API Serverless nào muốn chạy trên HTTPS.
kubectl create namespace cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml
Kết quả mong đợi: Các CRD của Cert-Manager được tạo, và các pod cert-manager trong namespace tương ứng chuyển sang trạng thái Running.
Cấu hình ClusterIssuer cho Let's Encrypt
Chúng ta cần định nghĩa một nguồn phát hành chứng chỉ (Issuer) sử dụng Let's Encrypt với chế độ Staging để tránh bị chặn (rate limit) trong quá trình test. Sau khi ổn định, bạn sẽ đổi sang Production.
Tạo file cấu hình /tmp/cluster-issuer.yaml với nội dung sau:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
email: admin@example.com
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-staging-key
solvers:
- http01:
ingress:
class: traefik
Áp dụng cấu hình:
kubectl apply -f /tmp/cluster-issuer.yaml
Kết quả mong đợi: Resource ClusterIssuer được tạo thành công. Cert-Manager đã sẵn sàng để cấp phát chứng chỉ cho các Ingress có annotation phù hợp.
Verify Cert-Manager
Chạy lệnh kiểm tra để đảm bảo Cert-Manager đã đăng ký đúng các CRD và có thể giao tiếp với API server.
kubectl get clusterissuer
Kết quả mong đợi: Bạn thấy letsencrypt-staging với trạng thái Ready hoặc Active.
Cấu hình Persistent Volumes cho lưu trữ tạm thời
Thiết lập StorageClass sử dụng hostPath
Trong môi trường phát triển hoặc single-node (như K3s), chúng ta có thể sử dụng hostPath để tạo Persistent Volume (PV) nhanh chóng mà không cần hệ thống lưu trữ phức tạp như NFS hay Ceph. Điều này phục vụ cho việc lưu cache của OpenFaaS hoặc logs tạm thời.
Tạo file /tmp/storage-class.yaml:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Retain
Áp dụng cấu hình:
kubectl apply -f /tmp/storage-class.yaml
Kết quả mong đợi: StorageClass local-storage được tạo và được đánh dấu là mặc định (default).
Tạo PersistentVolumeClaim mẫu
Để test tính năng, hãy tạo một PersistentVolumeClaim (PVC) yêu cầu 1Gi dung lượng. Kubernetes sẽ tự động bind PVC này vào một PV mới được tạo trên disk của host.
cat
Kết quả mong đợi: PVC faas-cache-pvc được tạo với trạng thái Bound. Bạn có thể kiểm tra bằng lệnh kubectl get pvc -n openfaas.
Verify Storage
Kiểm tra xem PV đã được tạo tự động hay chưa và dung lượng có khớp với yêu cầu.
kubectl get pvc -n openfaas
kubectl get pv
Kết quả mong đợi: PVC hiển thị Bound và PV tương ứng hiển thị Bound với capacity 1Gi.
Thiết lập Network Policies cơ bản để cô lập namespaces
Kích hoạt Network Policy Controller
Trên K3s, tính năng Network Policy thường được bật mặc định nếu bạn không dùng CNI bên thứ 3. Tuy nhiên, để đảm bảo an toàn, chúng ta cần cài đặt một CNI hỗ trợ Network Policy như Calico hoặc Cilium. Ở đây chúng ta dùng Calico cho sự đơn giản và tương thích.
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/calico.yaml
Kết quả mong đợi: Các pod của Calico (calico-node, calico-kube-controllers) trong namespace kube-system chuyển sang Running.
Áp dụng chính sách cô lập namespace
Chúng ta sẽ tạo một Network Policy để ngăn chặn mọi traffic vào namespace openfaas từ bên ngoài, trừ traffic từ namespace traefik (Ingress Controller). Điều này đảm bảo chỉ có Gateway mới gọi được các function.
Tạo file /tmp/network-policy.yaml:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-traffic
namespace: openfaas
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Áp dụng chính sách mặc định (deny all):
kubectl apply -f /tmp/network-policy.yaml
Cho phép traffic từ Traefik
Bây giờ, tạo một policy cụ thể cho phép Ingress Controller (ở namespace traefik) gọi vào các pod của OpenFaaS.
cat
Kết quả mong đợi: NetworkPolicy được tạo thành công. Traffic từ bên ngoài (ngoài Traefik) sẽ bị drop khi cố gắng gọi trực tiếp vào pod OpenFaaS.
Verify Network Policy
Kiểm tra danh sách các Network Policy đã áp dụng trong namespace openfaas.
kubectl get networkpolicy -n openfaas
Kết quả mong đợi: Bạn thấy 2 policies: deny-all-traffic và allow-ingress-traffic. Khi test gọi API trực tiếp vào pod IP sẽ bị timeout, nhưng gọi qua Ingress sẽ thành công.
Điều hướng series:
Mục lục: Series: Series: Xây dựng nền tảng Serverless và Edge Computing an toàn với OpenFaaS, Cloudflare Workers và Wasm trên hạ tầng Kubernetes
« Phần 1: Chuẩn bị môi trường phát triển và yêu cầu hệ thống
Phần 3: Đưa OpenFaaS vào Kubernetes và cấu hình Gateway »