# Exposing Services in Kubernetes

{{#include ../../banners/hacktricks-training.md}}

Daar is **verskillende maniere om dienste** in Kubernetes bloot te stel sodat beide **interne** eindpunte en **eksterne** eindpunte toegang kan hê. Hierdie Kubernetes-konfigurasie is redelik krities aangesien die administrateur toegang kan gee aan **aanvallers tot dienste waartoe hulle nie toegang behoort te hê nie**.

### Automatic Enumeration

Voordat jy begin om die maniere te lys wat K8s bied om dienste aan die publiek bloot te stel, weet dat as jy namespaces, dienste en ingresses kan lys, jy alles wat aan die publiek blootgestel is, kan vind met:
```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

'n **ClusterIP** diens is die **verstek** Kubernetes **diens**. Dit bied 'n **diens binne** jou kluster wat ander toepassings binne jou kluster kan toegang. Daar is **geen eksterne toegang** nie.

Dit kan egter toeganklik gemaak word met die Kubernetes Proxy:
```bash
kubectl proxy --port=8080
```
Nou kan jy deur die Kubernetes API navigeer om dienste te bekom met hierdie skema:

`http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/`

Byvoorbeeld, jy kan die volgende URL gebruik:

`http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/`

om toegang tot hierdie diens te verkry:
```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
```
_ Hierdie metode vereis dat jy `kubectl` as 'n **geverifieerde gebruiker** uitvoer._

Lys alle ClusterIPs:
```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

Wanneer **NodePort** gebruik word, word 'n aangewese poort beskikbaar gemaak op alle Nodes (wat die Virtuele Masjiene verteenwoordig). **Verkeer** wat na hierdie spesifieke poort gerig is, word dan sistematies **na die diens gelei**. Gewoonlik word hierdie metode nie aanbeveel nie weens sy nadele.

Lys alle NodePorts:
```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
```
'n Voorbeeld van NodePort-spesifikasie:
```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
```
As jy nie die **nodePort** in die yaml spesifiseer nie (dit is die poort wat geopen sal word), sal 'n poort in die **reeks 30000–32767 gebruik word**.

### LoadBalancer <a href="#id-0d96" id="id-0d96"></a>

Stel die Diens ekstern bloot **met 'n wolkverskaffer se laaibalans**. Op GKE sal dit 'n [Netwerk Laaibalans](https://cloud.google.com/compute/docs/load-balancing/network/) opstel wat vir jou 'n enkele IP-adres sal gee wat al die verkeer na jou diens sal deurstuur. In AWS sal dit 'n Laaibalans begin.

Jy moet betaal vir 'n LoadBalancer per blootgestelde diens, wat duur kan wees.

Lys alle LoadBalancers:
```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's <a href="#external-ips" id="external-ips"></a>

> [!TIP]
> Eksterne IP's word blootgestel deur dienste van tipe Load Balancers en hulle word oor die algemeen gebruik wanneer 'n eksterne Cloud Provider Load Balancer gebruik word.
>
> Om hulle te vind, kyk vir load balancers met waardes in die `EXTERNAL-IP` veld.

Verkeer wat in die kluster ingaan met die **eksterne IP** (as **bestemmings IP**), op die Service poort, sal **na een van die Service eindpunte gelei word**. `externalIPs` word nie deur Kubernetes bestuur nie en is die verantwoordelikheid van die kluster administrateur.

In die Service spesifikasie kan `externalIPs` gespesifiseer word saam met enige van die `ServiceTypes`. In die voorbeeld hieronder kan "`my-service`" deur kliënte op "`80.11.12.10:80`" (`externalIP:port`) toeganklik gemaak word.
```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

[**Uit die dokumentasie:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Dienste van tipe ExternalName **koppel 'n Dienst aan 'n DNS naam**, nie aan 'n tipiese selektor soos `my-service` of `cassandra` nie. Jy spesifiseer hierdie Dienste met die `spec.externalName` parameter.

Hierdie Dienstdefinisie, byvoorbeeld, koppel die `my-service` Dienst in die `prod` naamruimte aan `my.database.example.com`:
```yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
```
Wanneer jy die gasheer `my-service.prod.svc.cluster.local` opsoek, keer die kluster DNS-diens terug na 'n `CNAME` rekord met die waarde `my.database.example.com`. Toegang tot `my-service` werk op dieselfde manier as ander dienste, maar met die belangrike verskil dat **herleiding op die DNS-vlak plaasvind** eerder as deur middel van proxy of forwarding.

Lys alle ExternalNames:
```bash
kubectl get services --all-namespaces | grep ExternalName
```
### Ingress

Verskil van al die bogenoemde voorbeelde, **Ingress is NIE 'n tipe diens nie**. In plaas daarvan, sit dit **voor verskeie dienste en funksioneer as 'n “slimme router”** of toegangspunt tot jou kluster.

Jy kan baie verskillende dinge met 'n Ingress doen, en daar is **baie tipes Ingress kontrollers wat verskillende vermoëns het**.

Die standaard GKE ingress kontroller sal 'n [HTTP(S) Laai Balansier](https://cloud.google.com/compute/docs/load-balancing/http/) vir jou opstel. Dit sal jou toelaat om beide padgebaseerde en subdomein-gebaseerde routing na agterdienste te doen. Byvoorbeeld, jy kan alles op foo.yourdomain.com na die foo diens stuur, en alles onder die yourdomain.com/bar/ pad na die bar diens.

Die YAML vir 'n Ingress objek op GKE met 'n [L7 HTTP Laai Balansier](https://cloud.google.com/compute/docs/load-balancing/http/) mag soos volg lyk:
```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
```
Lys al die ingresses:
```bash
kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status'
```
Alhoewel dit in hierdie geval beter is om die inligting van elkeen een vir een te kry om dit beter te lees:
```bash
kubectl get ingresses --all-namespaces -o=yaml
```
### Verwysings

- [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}}
