Thế nào là Ingress?
Ingress là resource Kubernetes cho phép định tuyến cấu hình Loadbalancer HTTP cho các ứng dụng chạy trên Kubernetes, được đại diện bởi một hoặc nhiều Dịch vụ. Một bộ loadbalancer như vậy là cần thiết để cung cấp các ứng dụng đó cho các máy khách như browser trình duyệt chúng ta truy cập bên ngoài cụm Kubernetes.
Thế nào là Ingress Controller?
Ingress Controller là một ứng dụng chạy trong một cluster và sử dụng cấu hình LoadBalancer HTTP theo tài nguyên Ingress. Loadbalancer này có thể là chạy bằng phần mềm trong cluster, Loadbalancer phần cứng hoặc là Loadbalancer dịch vụ cloud bên ngoài. Với mỗi LoadBalancer khác nhau đòi hỏi phải thực hiện Ingress Controller khác nhau.
Sơ đồ triển khai như sau:
Trong trường hợp này, Ingress Controller được triển khai theo dạng phần mềm.
Bạn hãy xem lại bài “Cách triển khai…” trước khi xem tiếp bài này nhé.
Hãy vào/etc/haproxy/haproxy.cfg và thêm 2 khối như sau
Khối đầu tiên có nội dung như dưới, khối này sẽ chuyển các traffic chạy port 30100 ở trong service của NGINX Ingress. Port 30100 sẽ được Forwarding ra ngoài từ port 80 bằng Service Type là NodePort
frontend http_frontend
bind *:80
mode tcp
option tcplog
default_backend http_backend
backend http_backend
mode tcp
balance roundrobin
server k8s-worker1 192.168.13.214:30100 check
server k8s-worker2 192.168.13.215:30100 check
server k8s-worker3 192.168.13.216:30100 check
Khối thứ 2 có nội dung như dưới, khối này sẽ chuyển các traffic chạy port 30101 ở trong service của NGINX Ingress. Port 30101 sẽ được Forwarding ra ngoài từ port 443 bằng Service Type là NodePort
frontend https_frontend
bind *:443
mode tcp
option tcplog
default_backend https_backend
backend https_backend
mode tcp
balance roundrobin
server k8s-worker1 192.168.13.214:30101 check
server k8s-worker2 192.168.13.215:30101 check
server k8s-worker3 192.168.13.216:30101 check
Như vậy file /etc/haproxy/haproxy.cfg sẽ có nội dung như dưới
frontend stats
bind *:8080
mode http
stats enable
stats uri /stats
stats refresh 10s
stats admin if LOCALHOST
frontend fe-apiserver
bind 0.0.0.0:6443
mode tcp
option tcplog
default_backend be-apiserver
backend be-apiserver
mode tcp
option tcplog
option tcp-check
balance roundrobin
default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
server k8s-master1 192.168.13.211:6443 check
server k8s-master2 192.168.13.212:6443 check
server k8s-master3 192.168.13.213:6443 check
frontend http_frontend
bind *:80
mode tcp
option tcplog
default_backend http_backend
backend http_backend
mode tcp
balance roundrobin
server k8s-worker1 192.168.13.214:30100 check
server k8s-worker2 192.168.13.215:30100 check
server k8s-worker3 192.168.13.216:30100 check
frontend https_frontend
bind *:443
mode tcp
option tcplog
default_backend https_backend
backend https_backend
mode tcp
balance roundrobin
server k8s-worker1 192.168.13.214:30101 check
server k8s-worker2 192.168.13.215:30101 check
server k8s-worker3 192.168.13.216:30101 check
Sau khi config xong bạn hãy khởi động lại dịch vụ Haproxy
$ sudo systemctl restart haproxy
Sau khi khởi động xong Haproxy, hãy vào url http://<vip_ipaddr_loadbalancer>:8080/stats. Ta sẽ thấy xuất hiện 2 khối mới là http_backend, https_backend nhưng chúng đang trạng thái down vì lý do NGINX Ingress chưa được triển khai nên các worker node chưa listen port 30100 và 30101.
Nếu cụm Kubernetes của bạn chưa có helm thì hãy cài nó vào bằng lệnh dưới
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
$ chmod 700 get_helm.sh && ./get_helm.sh
Để chắc chắn helm đã được cài, bạn hãy verify lại
$ helm version
version.BuildInfo{Version:"v3.10.1", GitCommit:"9f88ccb6aee40b9a0535fcc7efea6055e1ef72c9", GitTreeState:"clean", GoVersion:"go1.18.7"}
Sau khi cài xong helm chúng ta hãy tạo 1 namespace mới có tên nginx-ingress để tạo không gian riêng cho NGINX Ingress
$ kubectl create namespace nginx-ingress
namespace/nginx-ingress created
Thêm repo của NGINX Ingress vào helm
$ helm repo add nginx-stable https://helm.nginx.com/stable
"nginx-stable" has been added to your repositories
Sau khi thêm repo NGINX Ingress vào helm xong, bạn hãy triển khai NGINX Ingress bằng lệnh dưới
$ helm install ingress nginx-stable/nginx-ingress --namespace nginx-ingress
NAME: ingress
LAST DEPLOYED: Thu Oct 27 04:06:45 2022
NAMESPACE: nginx-ingress
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The NGINX Ingress Controller has been installed.
Clone source code của NGINX Ingress về trên Github
$ git clone https://github.com/nginxinc/kubernetes-ingress.git
Cloning into 'kubernetes-ingress'...
remote: Enumerating objects: 45985, done.
remote: Counting objects: 100% (121/121), done.
remote: Compressing objects: 100% (86/86), done.
remote: Total 45985 (delta 73), reused 70 (delta 35), pack-reused 45864
Receiving objects: 100% (45985/45985), 60.77 MiB | 2.38 MiB/s, done.
Resolving deltas: 100% (27378/27378), done.
Verify lại kết quả sau của việc clone ta sẽ có 12 file yaml như dưới
$ tree ./kubernetes-ingress/deployments/helm-chart/crds/
./kubernetes-ingress/deployments/helm-chart/crds/
├── appprotect.f5.com_aplogconfs.yaml
├── appprotect.f5.com_appolicies.yaml
├── appprotect.f5.com_apusersigs.yaml
├── appprotectdos.f5.com_apdoslogconfs.yaml
├── appprotectdos.f5.com_apdospolicy.yaml
├── appprotectdos.f5.com_dosprotectedresources.yaml
├── externaldns.nginx.org_dnsendpoints.yaml
├── k8s.nginx.org_globalconfigurations.yaml
├── k8s.nginx.org_policies.yaml
├── k8s.nginx.org_transportservers.yaml
├── k8s.nginx.org_virtualserverroutes.yaml
└── k8s.nginx.org_virtualservers.yaml
0 directories, 12 files
Hãy chỉnh sửa file values.yaml đổi cách triển khai từ deployment sang daemonset
$ sed -i 's|kind: deployment|kind: daemonset|g' ./kubernetes-ingress/deployments/helm-chart/values.yaml
Verify lại file values.yaml
$ cat ./kubernetes-ingress/deployments/helm-chart/values.yaml | grep kind:
kind: daemonset
Tiến hành update lại NGINX Ingress sau khi đã thay đổi giá trị trong file values.yaml
$ helm upgrade ingress nginx-stable/nginx-ingress -f ./kubernetes-ingress/deployments/helm-chart/values.yaml -n nginx-ingress
coalesce.go:220: warning: cannot overwrite table with non table for nginx-ingress.controller.serviceMonitor.endpoints (map[])
Release "ingress" has been upgraded. Happy Helming!
NAME: ingress
LAST DEPLOYED: Thu Oct 27 04:09:28 2022
NAMESPACE: nginx-ingress
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
The NGINX Ingress Controller has been installed.
Sau khi update xong bạn đã có 3 pod chạy trên 3 worker node, lý do là chúng ta đã đổi cách triển khai pod từ deployment sang daemonset
$ kubectl get po -n nginx-ingress
NAME READY STATUS RESTARTS AGE
ingress-nginx-ingress-76j7l 1/1 Running 0 30m
ingress-nginx-ingress-s6hsh 1/1 Running 0 30m
ingress-nginx-ingress-x4g52 1/1 Running 0 30m
Verify lại daemonset NGINX Ingress
$ kubectl get ds -n nginx-ingress
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
ingress-nginx-ingress 3 3 3 3 3 <none> 29m
Verify lại service chúng ta thấy service của NGINX Ingress đang có 2 port chính là 80 và 443
$ kubectl get svc -n nginx-ingress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-ingress LoadBalancer 10.109.246.83 <pending> 80:30701/TCP,443:32153/TCP 3m35s
Tạo file ConfigMap với nội dung như dưới, với:
use-proxy-protocol: đổi từ false thành true
external-status-address: là VIP Address Loadbalancer Node
$ echo """kind: ConfigMap
apiVersion: v1
metadata:
name: ingress-nginx-ingress
namespace: nginx-ingress
data:
use-proxy-protocol: "true"
proxy-connect-timeout: "10s"
proxy-read-timeout: "10s"
client-max-body-size: "2m"
external-status-address: "192.168.13.238"
""" > ./patch-configmap.yaml
Tiến hành patch configmap
$ kubectl -n nginx-ingress patch configmap ingress-nginx-ingress --patch-file ./patch-configmap.yaml
configmap/ingress-nginx-ingress patched
Show configmap chúng ta thấy namespace nginx-ingress có 3 configmap
$ kubectl -n nginx-ingress get cm
NAME DATA AGE
ingress-nginx-ingress 5 28m
ingress-nginx-ingress-leader-election 0 28m
kube-root-ca.crt 1 29m
Bạn hãy vào configmap ingress-nginx-ingress và verify lại kết quả patch đã chắc chắn chính xác
$ kubectl -n nginx-ingress edit cm/ingress-nginx-ingress
Tiếp theo chúng ta hãy đổi type service từ LoadBalancer sang NodePort để Forwarding 2 port 80 và 443 ra ngoài nhé.
Chạy lệnh dưới để tiến hành patch service ingress-nginx-ingress
$ kubectl -n nginx-ingress patch svc ingress-nginx-ingress --patch '{"spec": { "type": "NodePort", "ports": [ { "port": 80, "nodePort": 30100 }, { "port": 443, "nodePort": 30101 } ] } }'
service/ingress-nginx-ingress patched
Bây giờ service của ingress-nginx-ingress đã đổi sang type là NodePort và port 80 được forwarding ra ngoài bằng port 30100 và port 443 được forwarding ra ngoài bằng port 30101
$ kubectl get svc -n nginx-ingress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-ingress NodePort 10.109.246.83 <none> 80:30100/TCP,443:30101/TCP 31m
Lúc này khi vào lại http://<vip_ipaddr_loadbalancer>:8080/stats chúng ta thấy 2 khối mới là http_backend, https_backend đã UP màu xanh
Để kiểm tra tính chịu lỗi của cụm, mình sẽ triển khai Prometheus để test. Tạo 1 namespace cho Prometheus
$ kubectl create ns prometheus-monitor
namespace/prometheus-monitor created
Tạo file ./prometheus-Deployment.yaml với nội dung dưới
$ cat > ./prometheus-Deployment.yaml << OEF
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: prometheus-monitor
spec:
selector:
matchLabels:
run: prometheus
replicas: 5
template:
metadata:
labels:
run: prometheus
spec:
containers:
- name: prometheus
image: prom/prometheus
ports:
- containerPort: 9090
OEF
Triển khai prometheus-Deployment.yaml
$ kubectl apply -f ./prometheus-Deployment.yaml
deployment.apps/prometheus created
Verify lại kết quả triển khai prometheus-Deployment.yaml chúng ta đã có 5 pods đúng như đã khai báo ở replicas trong deployment
$ kubectl get po -n prometheus-monitor -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
prometheus-578745d58b-59xnq 1/1 Running 0 77s 10.244.194.67 k8s-worker1 <none> <none>
prometheus-578745d58b-7p69n 1/1 Running 0 77s 10.244.126.3 k8s-worker2 <none> <none>
prometheus-578745d58b-lf8w6 1/1 Running 0 77s 10.244.126.4 k8s-worker2 <none> <none>
prometheus-578745d58b-llh27 1/1 Running 0 77s 10.244.100.197 k8s-worker3 <none> <none>
prometheus-578745d58b-tw4jg 1/1 Running 0 77s 10.244.194.66 k8s-worker1 <none> <none>
Tạo file prometheus-Service.yaml với nội dung dưới
$ cat > ./prometheus-Service.yaml << OEF
apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: prometheus-monitor
labels:
run: prometheus
spec:
ports:
- name: prometheus
port: 80
targetPort: 9090
selector:
run: prometheus
OEF
Triển khai prometheus-Service.yaml
$ kubectl apply -f ./prometheus-Service.yaml
service/prometheus created
Chúng ta đã có 1 service mới của prometheus
$ kubectl get svc -n prometheus-monitor -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
prometheus ClusterIP 10.103.255.158 <none> 80/TCP 68s run=prometheus
Hãy tạo file prometheus-Ingress.yaml với nội dung dưới với prometheus.hoanghd.com chính là domain của prometheus
$ cat > ./prometheus-Ingress.yaml << OEF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: prometheus
namespace: prometheus-monitor
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: prometheus.hoanghd.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: prometheus
port:
number: 80
OEF
Triển khai prometheus-Ingress.yaml
$ kubectl apply -f ./prometheus-Ingress.yaml
ingress.networking.k8s.io/prometheus created
Kiểm tra lại quá trình triển khai nginx-ingress chúng ta thấy domain prometheus-Ingress.yaml đã được trỏ về VIP Address của Loadbalancer node
$ kubectl get ing -n prometheus-monitor -o wide
NAME CLASS HOSTS ADDRESS PORTS AGE
prometheus nginx prometheus.hoanghd.com 192.168.13.238 80 3s
Trỏ tên miền cho prometheus.hoanghd.com về VIP Address của Loadbalancer node và kiểm tra kết nối
$ ping prometheus.hoanghd.com
PING prometheus.hoanghd.com (192.168.13.238): 56 data bytes
64 bytes from 192.168.13.238: icmp_seq=0 ttl=64 time=1.526 ms
64 bytes from 192.168.13.238: icmp_seq=1 ttl=64 time=0.468 ms
64 bytes from 192.168.13.238: icmp_seq=2 ttl=64 time=0.563 ms
64 bytes from 192.168.13.238: icmp_seq=3 ttl=64 time=0.500 ms
64 bytes from 192.168.13.238: icmp_seq=4 ttl=64 time=0.452 ms
--- prometheus.hoanghd.com ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.452/0.702/1.526/0.414 ms
Hãy sử dụng trình duyệt web để kiểm tra kết quả, chúng ta đã truy cập được dịch vụ
Kết quả telnet port 80 vào domain prometheus.hoanghd.com
$ telnet prometheus.hoanghd.com 80
Trying 192.168.13.238...
Connected to prometheus.hoanghd.com.
Escape character is '^]'.
Hiện tại ip 192.168.13.238 của VIP Address của Loadbalancer node đang được gắn cho Loadbalancer2 vì Loadbalancer2 đang nắm priority keepalive lớn hơn.
Bây giờ mình sẽ tắt Loadbalancer2 có ip là 192.168.13.218
$ ip addr show ens192
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:ad:78:a2 brd ff:ff:ff:ff:ff:ff
inet 192.168.13.218/23 brd 192.168.13.255 scope global ens192
valid_lft forever preferred_lft forever
inet 192.168.13.238/32 scope global ens192
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:fead:78a2/64 scope link
valid_lft forever preferred_lft forever
Kết quả 192.168.13.218 đã mất kết nối, bây giờ chúng ta chỉ còn 1 Loadbalancer còn sống đó là Loadbalancer1 (Loadbalancer2 đã bị mình tắt)
$ ping 192.168.13.218
PING 192.168.13.218 (192.168.13.218): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2
Request timeout for icmp_seq 3
ping: sendto: No route to host
Request timeout for icmp_seq 4
--- 192.168.13.218 ping statistics ---
6 packets transmitted, 0 packets received, 100.0% packet loss
Vậy bây giờ nếu mình ssh vào 192.168.13.238 thì 192.168.13.238 sẽ kết nối vào ip 192.168.13.217 của Loadbalancer1 như ở dưới
$ ssh root@192.168.13.238
Welcome to Ubuntu 18.04.6 LTS (GNU/Linux 4.15.0-194-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Thu Oct 27 06:17:21 UTC 2022
System load: 0.0 Processes: 105
Usage of /: 3.8% of 48.27GB Users logged in: 1
Memory usage: 7% IP address for ens192: 192.168.13.217
Swap usage: 0%
* Super-optimized for small spaces - read how we shrank the memory
footprint of MicroK8s to make it the smallest full K8s around.
https://ubuntu.com/blog/microk8s-memory-optimisation
6 updates can be applied immediately.
5 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable
New release '20.04.5 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Last login: Thu Oct 27 06:15:42 2022 from 192.168.12.63
Hãy show ip của 192.168.13.238 chúng ta thấy ip 192.168.13.238 của VIP Address của Loadbalancer node đã được gắn cho 192.168.13.217 của Loadbalancer1
$ ip addr show ens192
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:ad:f9:96 brd ff:ff:ff:ff:ff:ff
inet 192.168.13.217/23 brd 192.168.13.255 scope global ens192
valid_lft forever preferred_lft forever
inet 192.168.13.238/32 scope global ens192
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:fead:f996/64 scope link
valid_lft forever preferred_lft forever
Mình tiếp tục tắt các node k8s-master2, k8s-worker2, k8s-worker3 chúng ta có thể thấy các node đã bị tắt chuyển sang trạng thái NotReady đông thời các pod của prometheus trên các node bị chết đdãđược khởi tạo lại (trạng thái ContainerCreating), các pod của prometheus trên các node bị chết sẽ bị xoá đi (trạng thái Terminating)
$ kubectl get no,po,svc,ing -n prometheus-monitor
NAME STATUS ROLES AGE VERSION
node/k8s-master1 Ready control-plane,master 14h v1.23.8
node/k8s-master2 NotReady control-plane,master 14h v1.23.8
node/k8s-master3 Ready control-plane,master 14h v1.23.8
node/k8s-worker1 Ready <none> 14h v1.23.8
node/k8s-worker2 NotReady <none> 14h v1.23.8
node/k8s-worker3 NotReady <none> 14h v1.23.8
NAME READY STATUS RESTARTS AGE
pod/prometheus-578745d58b-59xnq 1/1 Running 0 90m
pod/prometheus-578745d58b-6mgwg 0/1 ContainerCreating 0 3s
pod/prometheus-578745d58b-7p69n 1/1 Terminating 0 90m
pod/prometheus-578745d58b-lf8w6 1/1 Terminating 0 90m
pod/prometheus-578745d58b-llh27 1/1 Running 0 90m
pod/prometheus-578745d58b-smbcl 0/1 ContainerCreating 0 3s
pod/prometheus-578745d58b-tw4jg 1/1 Running 0 90m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/prometheus ClusterIP 10.103.255.158 <none> 80/TCP 89m
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/prometheus nginx prometheus.hoanghd.com 192.168.13.238 80 86m
Khi vào http://<vip_ipaddr_loadbalancer>:8080/stats để check lại thì các node k8s-master2, k8s-worker2, k8s-worker3 đã bị down chuyển sang màu đỏ
Kết quả telnet cho ta thấy mặc dù chúng ta đã bị chết 1 Loadbalancer, 1 master, 2 worker nhưng dịch vụ của chúng ta vẫn còn chạy được
$ telnet prometheus.hoanghd.com 80
Trying 192.168.13.238...
Connected to prometheus.hoanghd.com.
Escape character is '^]'.
Chúc các bạn thành công.