# Izlaganje usluga u Kubernetesu {{#include ../../banners/hacktricks-training.md}} Postoje **različiti načini za izlaganje usluga** u Kubernetesu tako da i **interni** i **eksterni** krajnji tačke mogu da im pristupe. Ova Kubernetes konfiguracija je prilično kritična jer administrator može dati pristup **napadačima uslugama kojima ne bi trebali imati pristup**. ### Automatska enumeracija Pre nego što počnete da enumerišete načine na koje K8s nudi izlaganje usluga javnosti, znajte da ako možete da listate namespace-ove, usluge i ingrese, možete pronaći sve što je izloženo javnosti sa: ```bash kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do echo "Namespace: $ns" kubectl get service -n "$ns" kubectl get ingress -n "$ns" echo "==============================================" echo "" echo "" done | grep -v "ClusterIP" # Remove the last '| grep -v "ClusterIP"' to see also type ClusterIP ``` ### ClusterIP **ClusterIP** servis je **podrazumevani** Kubernetes **servis**. Omogućava vam **servis unutar** vašeg klastera kojem mogu pristupiti druge aplikacije unutar vašeg klastera. **Nema spoljnog pristupa**. Međutim, ovo se može pristupiti koristeći Kubernetes Proxy: ```bash kubectl proxy --port=8080 ``` Sada možete navigirati kroz Kubernetes API da biste pristupili uslugama koristeći ovu shemu: `http://localhost:8080/api/v1/proxy/namespaces//services/:/` Na primer, možete koristiti sledeći URL: `http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/` da biste pristupili ovoj usluzi: ```yaml apiVersion: v1 kind: Service metadata: name: my-internal-service spec: selector: app: my-app type: ClusterIP ports: - name: http port: 80 targetPort: 80 protocol: TCP ``` _Ova metoda zahteva da pokrenete `kubectl` kao **autentifikovani korisnik**._ Nabrojte sve ClusterIP-ove: ```bash kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep ClusterIP ``` ### NodePort Kada se koristi **NodePort**, određeni port je dostupan na svim čvorovima (koji predstavljaju virtuelne mašine). **Saobraćaj** usmeren na ovaj specifičan port se sistematski **usmerava ka servisu**. Obično, ova metoda se ne preporučuje zbog svojih nedostataka. Lista svih NodePort-ova: ```bash kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep NodePort ``` Primer specifikacije NodePort: ```yaml apiVersion: v1 kind: Service metadata: name: my-nodeport-service spec: selector: app: my-app type: NodePort ports: - name: http port: 80 targetPort: 80 nodePort: 30036 protocol: TCP ``` Ako **ne navedete** **nodePort** u yaml-u (to je port koji će biti otvoren), koristiće se port u **opsegu 30000–32767**. ### LoadBalancer Izlaže Servis spolja **koristeći load balancer provajdera u oblaku**. Na GKE, ovo će pokrenuti [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) koji će vam dati jedinstvenu IP adresu koja će preusmeriti sav saobraćaj na vaš servis. U AWS-u će pokrenuti Load Balancer. Morate plaćati za LoadBalancer po izloženom servisu, što može biti skupo. Lista svih LoadBalancera: ```bash kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,EXTERNAL-IP:.status.loadBalancer.ingress[*],PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep LoadBalancer ``` ### Eksterne IP adrese > [!TIP] > Eksterne IP adrese su izložene od strane usluga tipa Load Balancers i obično se koriste kada se koristi eksterna Cloud Provider Load Balancer. > > Da biste ih pronašli, proverite load balancere sa vrednostima u polju `EXTERNAL-IP`. Saobraćaj koji ulazi u klaster sa **eksternom IP adresom** (kao **odredišna IP adresa**), na portu usluge, biće **usmeren na jedan od krajnjih tačaka usluge**. `externalIPs` nisu upravljane od strane Kubernetesa i odgovornost su administratora klastera. U specifikaciji usluge, `externalIPs` mogu biti navedene zajedno sa bilo kojim od `ServiceTypes`. U sledećem primeru, "`my-service`" može biti pristupljeno od strane klijenata na "`80.11.12.10:80`" (`externalIP:port`) ```yaml apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: MyApp ports: - name: http protocol: TCP port: 80 targetPort: 9376 externalIPs: - 80.11.12.10 ``` ### ExternalName [**Iz dokumenata:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Servisi tipa ExternalName **mapiraju servis na DNS ime**, a ne na tipičan selektor kao što je `my-service` ili `cassandra`. Ove servise definišete pomoću parametra `spec.externalName`. Ova definicija servisa, na primer, mapira `my-service` servis u `prod` imenskom prostoru na `my.database.example.com`: ```yaml apiVersion: v1 kind: Service metadata: name: my-service namespace: prod spec: type: ExternalName externalName: my.database.example.com ``` Kada se traži host `my-service.prod.svc.cluster.local`, klasterska DNS usluga vraća `CNAME` zapis sa vrednošću `my.database.example.com`. Pristup `my-service` funkcioniše na isti način kao i druge usluge, ali sa ključnom razlikom da **preusmeravanje se dešava na DNS nivou** umesto putem proksiranja ili prosleđivanja. Nabrojte sve ExternalNames: ```bash kubectl get services --all-namespaces | grep ExternalName ``` ### Ingress Za razliku od svih gore navedenih primera, **Ingress NIJE tip usluge**. Umesto toga, on se nalazi **ispred više usluga i deluje kao “pametan ruter”** ili ulazna tačka u vaš klaster. Možete raditi mnogo različitih stvari sa Ingress-om, i postoje **različite vrste Ingress kontrolera koji imaju različite mogućnosti**. Podrazumevani GKE ingress kontroler će pokrenuti [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) za vas. Ovo će vam omogućiti da radite i rutiranje zasnovano na putanji i rutiranje zasnovano na poddomenama ka pozadinskim uslugama. Na primer, možete poslati sve na foo.yourdomain.com ka foo usluzi, i sve ispod putanje yourdomain.com/bar/ ka bar usluzi. YAML za Ingress objekat na GKE sa [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) može izgledati ovako: ```yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: my-ingress spec: backend: serviceName: other servicePort: 8080 rules: - host: foo.mydomain.com http: paths: - backend: serviceName: foo servicePort: 8080 - host: mydomain.com http: paths: - path: /bar/* backend: serviceName: bar servicePort: 8080 ``` Nabrojite sve ulaze: ```bash kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status' ``` Iako je u ovom slučaju bolje dobiti informacije o svakom pojedinačno kako bi se lakše pročitali: ```bash kubectl get ingresses --all-namespaces -o=yaml ``` ### Reference - [https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0](https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0) - [https://kubernetes.io/docs/concepts/services-networking/service/](https://kubernetes.io/docs/concepts/services-networking/service/) {{#include ../../banners/hacktricks-training.md}}