Základy síťování v kubernetesII - LB,Ingress,DNS [WOTW-5]
workshop
LoadBalancer a jak je to udělané
Implementace servisu typu LoadBalancer se může dost lišit mezi jednotlivými CLOUD providery a samozřejmě na onprem může být úplně jiná, třeba manuální.
Podstatné je že servisa typu LoadBalancer umožňuje vytvořit externí přístup k jinak interní servise, většinou tak že vytvoří pro kubernetes cluster externí objekt typu LoadBalancer (může být samozřejmě baremetal) a z něj směřuje data na backend.
K3D (K3S) používá Service LoadBalancer klipper
How the Service LB Works K3s creates a controller that creates a Pod for the service load balancer, which is a Kubernetes object of kind Service. For each service load balancer, a DaemonSet is created. The DaemonSet creates a pod with the svc prefix on each node. The Service LB controller listens for other Kubernetes Services. After it finds a Service, it creates a proxy Pod for the service using a DaemonSet on all of the nodes. This Pod becomes a proxy to the other Service, so that for example, requests coming to port 8000 on a node could be routed to your workload on port 8888. If the Service LB runs on a node that has an external IP, it uses the external IP. If multiple Services are created, a separate DaemonSet is created for each Service. It is possible to run multiple Services on the same node, as long as they use different ports. If you try to create a Service LB that listens on port 80, the Service LB will try to find a free host in the cluster for port 80. If no host with that port is available, the LB will stay in Pending.
#service typu LB ktera smeruje traffic to aplikace traefik
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/instance: traefik
app.kubernetes.io/name: traefik
name: aabb
namespace: kube-system
spec:
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: web
nodePort: 32444
port: 800
targetPort: web
- name: websecure
nodePort: 30747
port: 900
targetPort: websecure
selector:
app.kubernetes.io/instance: traefik
app.kubernetes.io/name: traefik
type: LoadBalancer
➤ oc get svc -n kube-system aabb
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
aabb LoadBalancer 10.43.134.203 172.21.0.2,172.21.0.3,172.21.0.4 800:32444/TCP,900:30747/TCP 12m
➤ kb get endpoints aabb -n kube-system
NAME ENDPOINTS AGE
aabb 10.42.2.3:8000,10.42.2.3:8443 15m
Kubeproxy nám na nodech vytvořila nová pravidla tak se na ně trochu podíváme.
➤ /usr/bin/docker ps
➤ /usr/bin/docker exec -it 37aa041af08d sh
/ # iptables-save >ss
teď trochu prozkoumáme IPTABLES
https://www.sudlice.org/openshift/linux/iptables/
# vznikla pravidlo pro cluster servis ty teď nejsou důležité
-A KUBE-SERVICES ! -s 10.42.0.0/16 -d 10.43.134.203/32 -p tcp -m comment --comment "kube-system/aabb:web cluster IP" -m tcp --dport 800 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.43.134.203/32 -p tcp -m comment --comment "kube-system/aabb:web cluster IP" -m tcp --dport 800 -j KUBE-SVC-RVAFSEPDPUT7VZG7
#pokud přijde trafic na vnější adresu nodu
-A KUBE-SERVICES -d 172.21.0.2/32 -p tcp -m comment --comment "kube-system/aabb:web loadbalancer IP" -m tcp --dport 800 -j KUBE-FW-RVAFSEPDPUT7VZG7
-A KUBE-SERVICES -d 172.21.0.3/32 -p tcp -m comment --comment "kube-system/aabb:web loadbalancer IP" -m tcp --dport 800 -j KUBE-FW-RVAFSEPDPUT7VZG7
-A KUBE-SERVICES -d 172.21.0.4/32 -p tcp -m comment --comment "kube-system/aabb:web loadbalancer IP" -m tcp --dport 800 -j KUBE-FW-RVAFSEPDPUT7VZG7
# první pravidla označí packet pro pro pozdější MASQUARADING tedy SNAT (aplikace v podu tak neuvidí naší reálnou IP adresu)
# druhé pošle na pravidlo pro SVC
# třetí dropne všechno co nematchujeme
-A KUBE-FW-RVAFSEPDPUT7VZG7 -m comment --comment "kube-system/aabb:web loadbalancer IP" -j KUBE-MARK-MASQ
-A KUBE-FW-RVAFSEPDPUT7VZG7 -m comment --comment "kube-system/aabb:web loadbalancer IP" -j KUBE-SVC-RVAFSEPDPUT7VZG7
-A KUBE-FW-RVAFSEPDPUT7VZG7 -m comment --comment "kube-system/aabb:web loadbalancer IP" -j KUBE-MARK-DROP
# jump na service endpoint
-A KUBE-SVC-RVAFSEPDPUT7VZG7 -m comment --comment "kube-system/aabb:web" -j KUBE-SEP-HJ3ILSU6YG25RESJ
# SNAT traffic který se vrací
-A KUBE-SEP-HJ3ILSU6YG25RESJ -s 10.42.2.3/32 -m comment --comment "kube-system/aabb:web" -j KUBE-MARK-MASQ
# DNAT na pod konrétní pod který je schován v endpointu (kb get endpoints)
-A KUBE-SEP-HJ3ILSU6YG25RESJ -p tcp -m comment --comment "kube-system/aabb:web" -m tcp -j DNAT --to-destination 10.42.2.3:8000
# podobné pravidlo je vytvořeno pro NODEPORT
-A KUBE-NODEPORTS -p tcp -m comment --comment "kube-system/aabb:web" -m tcp --dport 32444 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "kube-system/aabb:web" -m tcp --dport 32444 -j KUBE-SVC-RVAFSEPDPUT7VZG7
Ingress controller
https://kubernetes.io/docs/concepts/services-networking/ingress/
https://traefik.io/blog/kubernetes-ingress-service-api-demystified/
K3D používá jako ingress controller traefik a vlastně ingres kontroler není nic jiného než kontroler který sedí v kubernetes a pokud uděláte objekt typu ingress tak on ho promítne do svojí konfigurace.
V předchozí části jsme si ukázali LB a představte si traffic flow jako LB na jehož konci je traefik a ten dál pokračuje v cestě na základě svojí definice.
Takže
➤ oc get pods -n kube-system traefik-97b44b794-s9n8n -o yaml|neat|vim -
➤ kb create namespace ing
➤ kb create deployment nginx --image=nginx -n ing
➤ kb create service clusterip nginx --tcp=80:80 -n ing
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
annotations:
ingress.kubernetes.io/ssl-redirect: "false"
# traefik.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: ingress
http:
paths:
- path: /absent
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
➤ curl http://ingress/absent/
https://doc.traefik.io/traefik/v2.4/configuration/backends/kubernetes/
DNS
možná jsme to měli vzít dřív ale nějak sem nevěděl kam to zařadit
https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
DOMÁCÍ PRÁCE
Na Traefiku v k3d nefunguje z nejakeho duvodu rewrite-target annotace.
Vytořte tedy libovolnou aplikaci (klidně statickou html stránku) a skuste k ní nakonfigurovat přístup přez Ingress.
Skuste přijít na to proč anotace nefunguje (já to nevím), případně nainstalujte jiný ingress kontroler než traefik (třeba NGINX) a testněte zda rewrite-target funguje zde.

rewrite-target
ŘEŠENÍ
#nainstaluju cisty cluster
k3d cluster create deadless -a 2
kb create namespace app
kb config set-context --current --namespace app
kb create deployment nginxapp --image=nginx
kb create service clusterip nginxapp --tcp=80:80
# /usr/share/nginx/html/index.html na nginx containeru upravim
kb exec nginxapp-74c8bd997c-4brpg -- bash -c "echo Hello NgINXapp > /usr/share/nginx/html/index.html"
#create ingress resource
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginxapp
annotations:
ingress.kubernetes.io/ssl-redirect: "false"
traefik.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: nginxapp.k3d.local
http:
paths:
- path: /absent
pathType: Prefix
backend:
service:
name: nginxapp
port:
number: 80
# tato definice nam rika, pokud prijde nekdo na host http://nginxapp.k3d.local/absent nasmeruj ho na servisu nginxapp a vsechno co je za
# / smaz (rewrite-target)
# jenze to nefunguje
curl http://nginxapp.k3d.local/absent
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.21.1</center>
</body>
</html>
#koukneme na logy
kb logs nginxapp-74c8bd997c-4brpg
2021/08/03 14:04:00 [error] 33#33: *1 open() "/usr/share/nginx/html/absent" failed (2: No such file or directory), client: 10.42.1.2, server: localhost, request: "GET /absent HTTP/1.1", host: "nginxapp.k3d.local"
# ok porad to smeruje na /absent
Nechtelo se mi uplne patrat kde je problem v traeffiku ktery by jako ingress controller mel tenhle problem resit a misto toho pouzijeme jako controller NGINX
# install nginx controleru
kubectl create namespace ingress-external
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install nginx-ingress-external ingress-nginx/ingress-nginx -n ingress-external --set controller.ingressClass=nginx-external --set --enable-ssl-passthrough=true
kb get pods -n ingress-external
kb describe pod -n ingress-external svclb-nginx-ingress-external-ingress-nginx-controller-4pqlq
#neni mozne mit soubeh dvou podu na stejnem portu (80,443) - klipper
#ok smazeme traefik lb service
kb delete svc -n kube-system traefik
# a vytvorime novy ingress controller s pouzitou ingress class
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginxapp
annotations:
ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: "nginx-external"
spec:
rules:
- host: nginxapp.k3d.local
http:
paths:
- path: /absent
pathType: Prefix
backend:
service:
name: nginxapp
port:
number: 80
#test
curl http://nginxapp.k3d.local/absent
Hello NgINXapp
Na Nginx ingress controleru je taky krasne videt injektnuti CR Ing do konfigurace
kb exec -n ingress-external nginx-ingress-external-ingress-nginx-controller-5976cfbfff4shrl -- bash -c "cat /etc/nginx/nginx.conf"