- Đăng vào
Cài đặt Metallb và Ingress Nginx trên Bare metal Kubernetes cluster
Giới thiệu
Trong các bài viết trước, mình đã giới thiệu về cách xây dựng một HomeLab để học về Kuberentes. Các bước cài đặt cơ bản đã xong, bước tiếp theo sẽ triển khai các ứng dụng trên Cluster đó. Nếu chưa xem các bài viết trước, bạn có thể xem lại để dễ theo dõi
- Cài đặt Kubernetes cluster trên Ubuntu server 22.04
- K8s cluster trên Ubuntu: Cài đặt Kubernetes dashboard
Trong bài viết này, mình sẽ hướng dẫn cài đặt Metallb và Ingress Nginx trên Kubernetes cluster On-premises
Metallb
MetalLB là một phần mềm cân bằng tải mạng cho các cụm Kubernetes không chạy trên cloud (bare metal Kubernetes clusters), sử dụng các giao thức định tuyến tiêu chuẩn.
Thông thường, khi cài đặt Kubernetes trên thiết bị của bạn (latop, bare metal server,…) thì chúng ta thường sử dụng NodePort service để truy cập vào app được deploy trên K8s. Nếu muốn sử dụng Serivice LoadBalancer thì chúng ta cần sử dụng các dich vụ cloud như Google Cloud, Azure, AWS,…
Metallb ra đời cung cấp giải pháp cho chúng ta có thể sử dụng LoadBalancer trên Bare metal K8s cluster. Hiện tại project mới ở giai đoạn beta nên chủ yếu chúng ta sử dụng ở môi trường dev/staging.
Ingress Nginx
Ingress Nginx là một Ingress controller cho Kubernetes sử dụng NGINX như một reverse proxy và load balancer. Ingress là một tài nguyên trong Kubernetes cho phép quản lý các kết nối đến các dịch vụ trong Kubernetes cluster. Ingress Nginx hỗ trợ khả năng căn bằng tải, SSL, URI rewrite và nhiều tính năng khác.
Thường thì Ingress Nginx mình sử dụng để cho phép bên ngoài truy cập vào ứng dụng thông qua tên miền ví dụ như: app1.example.com, app2.example.com.
NodePort
Trên bare metal K8s thì Ingress được deploy ở chế đó NodePort (Xem thêm tại đây), khi chúng ta kiểm tra thì sẽ thấy dạng như sau:
kubectl get services -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.108.142.179 <none> 80:30882/TCP,443:32446/TCP 2d7h
ingress-nginx-controller-admission ClusterIP 10.96.102.236 <none> 443/TCP 2d7h
Chúng ta có thể thấy 2 port 80/443 trên Nginx được map tương ứng sang port 30882/32446, như vậy nếu muốn access vào App1 trên K8s thông qua Ingress Nginx thì cần truy cập như sau:
Như vậy khá là bất tiện, chúng ta có thể:
- Dùng chức năng port-forward trên router để mapping tiếp port 80->30882 và 443->32446. Về cơ bản đường đi của nó như sau: Internet (80/http) –>router (port-forward) –> Kuberentes IP (30882/http) –> Nginx (80/http)
- Dùng 1 Proxy như Haproxy hoặc Nginx đứng trước K8s cluster để điều phối. Chi tiết mình sẽ không trình bày
Để tránh những phức tạp khi triển khai Ingress Nginx trên Bare metal K8s cluster, dưới đây mình sẽ giới thiệu cách triển khai Metallb và Ingress Nginx (Load Balancer)
Metallb + Ingress Nginx
Dưới đây là sơ đồ hệ thống sẽ triển khai
Đầu tiên chúng ta deploy Metallb:
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.9/config/manifests/metallb-native.yaml
Tiếp theo, chúng ta cần config dải IP sẽ cấp phát cho Metallb, tạo file config.yaml
với nội dung dưới đây:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.50/32
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
spec:
ipAddressPools:
- default-pool
Trong trường hợp của mình, do chỉ để học tập, nghiên cứu nên mình chỉ set IP Pool có duy nhất 1 IP, Sau đó chúng ta apply thiết lập này cho Metallb
kubectl apply -f config.yaml
Kiểm tra xem resouce đã được deploy thành công chưa:
kubectl get all -n metallb-system
NAME READY STATUS RESTARTS AGE
pod/controller-68bf958bf9-d7zrx 1/1 Running 2 (3d10h ago) 3d23h
pod/speaker-mhz86 1/1 Running 2 (3d10h ago) 3d23h
pod/speaker-np7bv 1/1 Running 2 (3d10h ago) 3d23h
pod/speaker-q7bcx 1/1 Running 1 (3d10h ago) 3d23h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/webhook-service ClusterIP 10.106.251.1 <none> 443/TCP 3d23h
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/speaker 3 3 3 3 3 kubernetes.io/os=linux 3d23h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/controller 1/1 1 1 3d23h
NAME DESIRED CURRENT READY AGE
replicaset.apps/controller-68bf958bf9 1 1 1 3d23h
Như vậy chúng ta đã có 1 LoadBalancer service cho Kubernetes cluster của mình, bước tiếp theo là deploy Nginx
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.7.0/deploy/static/provider/cloud/deploy.yaml
Kiểm tra xem các resouce của ingress nginx đã được triển khai chưa
kubectl get all -n ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/ingress-nginx-admission-create-lsb4v 0/1 Completed 0 3d23h
pod/ingress-nginx-admission-patch-fjz79 0/1 Completed 0 3d23h
pod/ingress-nginx-controller-6bdb654777-p7dvf 1/1 Running 1 (3d10h ago) 3d23h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
AGE
service/ingress-nginx-controller LoadBalancer 10.108.142.179 192.168.1.50 80:30882/TCP,443:32446/TCP 3d23h
service/ingress-nginx-controller-admission ClusterIP 10.96.102.236 <none> 443/TCP
3d23h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-nginx-controller 1/1 1 1 3d23h
NAME DESIRED CURRENT READY AGE
replicaset.apps/ingress-nginx-controller-6bdb654777 1 1 1 3d23h
NAME COMPLETIONS DURATION AGE
job.batch/ingress-nginx-admission-create 1/1 29s 3d23h
job.batch/ingress-nginx-admission-patch 1/1 29s 3d23h
Như vậy chúng ta có thể thấy service/ingress-nginx-controller loại LoadBalancer đã được deploy thành công và External IP là 192.168.1.50
Bước tiếp theo chúng chúng ta phải cho phép bên ngoài truy cập vào địa chỉ IP 192.168.1.50
- Nếu gói Internet của bạn có static IP (a.b.c.d)
- Vào router cấu hình mở port 80/443 và forward traffic đến IP 192.168.1.50 hoặc có thể thêm IP 192.168.1.50 vào DMZ zone.
- Bạn cần có tên miền mà trỏ đến IP a.b.c.d
- Nếu gói Internet của bạn không có static IP
- Vào router cấu hình mở port 80/443 và forward traffic đến IP 192.168.1.50 hoặc có thể thêm IP 192.168.1.50 vào DMZ zone.
- Đăng ký DDNS (Dynamic Domain Name System) để có được 1 domain trỏ đến local IP của bạn. VD: k8slab.ddns.net
Triển khai 1 ứng dụng đơn giản với thông tin trong
banana.yaml
kind: Pod
apiVersion: v1
metadata:
name: banana-app
namespace: fruit
labels:
app: banana
spec:
containers:
- name: banana-app
image: hashicorp/http-echo
args:
- '-text=banana'
---
kind: Service
apiVersion: v1
metadata:
name: banana-service
namespace: fruit
spec:
selector:
app: banana
ports:
- port: 5678 # Default port for image
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: fruits
namespace: fruit
spec:
ingressClassName: nginx
rules:
- host: banana.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: banana-service
port:
number: 5678
apple.yaml
kind: Pod
apiVersion: v1
metadata:
name: apple-app
namespace: fruit
labels:
app: apple
spec:
containers:
- name: apple-app
image: hashicorp/http-echo
args:
- "-text=apple"
---
kind: Service
apiVersion: v1
metadata:
name: apple-service
namespace: fruit
spec:
selector:
app: apple
ports:
- port: 5678 # Default port for image
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: fruits
namespace: fruit
spec:
ingressClassName: nginx
rules:
- host: apple.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: apple-service
port:
number: 5678
Deploy app:
kubectl create namespace fruits
kubectl apply -f apple.yaml
kubectl apply -f banana.yaml