18 Mart 2022 Cuma

Kubernetes kind: Service İle NodePort Service - Servise Cluster Dışından Erişebilir

Giriş
Diğer Servisler arasındaki fark şöyle. Yani NodePort ve LoadBalancer servisi cluster dışına açar, ancak ClusterIP açmaz. 

Burada unutulmaması gereken şey "kubectl get svc" ile NodePort servisine ait bir IP adresi görsek bile bu IP adresi çalışmaz. Herhangi bir worker node'un IP adresini kullanarak NodePort'a erişilebilir. Sebebi ise NodePort ile External IP yazılmaz, çünkü her VM için VM_IP:Port numarası şeklindedir.
ClusterIP: Exposes the service on a cluster-internal IP. Choosing this value makes the service only reachable from within the cluster. This is the default ServiceType

NodePort: Exposes the service on each Node’s IP at a static port (the NodePort). A ClusterIP service, to which the NodePort service will route, is automatically created. You’ll be able to contact the NodePort service, from outside the cluster, by requesting <NodeIP>:<NodePort>.

LoadBalancer: Exposes the service externally using a cloud provider’s load balancer. NodePort and ClusterIP services, to which the external load balancer will route, are automatically created
NodePort Service için "type: NodePort" alanı belirtilmek zorundadır. Açıklaması şöyle
Kubernetes ServiceTypes allow you to specify what kind of Service you want. The default is ClusterIP.
Açıklaması şöyle. Yani NodePort yaratınca otomatik olarak ClusterIP de yaratılıyor
A ClusterIP Service, to which the NodePort Service routes, is automatically created. You'll be able to contact the NodePort Service, from outside the cluster, by requesting <NodeIP>:<NodePort>.
Örnek
NodePort ile External IP yazılmaz, çünkü her VM_IP:Port numarası şeklindedir. Şöyle yaparız
kubectl get services
NAME               TYPE         CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes        ClusterIP   10.96.0.1              <none>              443/TCP           26m
sample-service  ClusterIP   10.110.120.3        <none>              80/TCP             75s
sample-service  NodePort   10.110.126.166   <none>              80:31920/TCP   39s
Açıklaması şöyle
NodePort, as the name implies, opens a specific port on all the Nodes (the VMs), and any traffic that is sent to this port is forwarded to the service. 
...
nodePort is unique, so 2 different services cannot have the same nodePort assigned. 
Şeklen şöyle

Komut Satırı
NodePort yaratmak için 2 seçenek var.
1. kubectl komutu
2. Yaml dosyası
Örnek
Şöyle yaparız. Burada hello-quarkus isimli deployment nesnesine ait 8080 portuna NodePort yaratılıyor
kubectl expose deployment hello-quarkus --type=NodePort --port=8080
Yaml Dosyası
nodePort Alanı
Dış dünyaya açılan port numarasıdır. Açıklaması şöyle
NodePort exposes a service externally to the cluster by means of the target nodes IP address and the NodePort. NodePort is the default setting if the port field is not specified.
Açıklaması şöyle
If you don't specify an explicit nodePort: number then Kubernetes will pick something non-conflicting for you
port Alanı
Cluster içinde servis tarafından kullanılacak numaradır. Açıklaması şöyle
Port exposes the Kubernetes service on the specified port within the cluster. Other pods within the cluster can communicate with this server on the specified port.
TargetPort  Alanı
Pod'un gerçekten dinlediği numaradır. Cluster içinden gelen istekler yani port alanı ile belirtilen yere gelen istekler, targetPort alanına yönlendirilir. Açıklaması şöyle
TargetPort is the port on which the service will send requests to, that your pod will be listening on. Your application in the container will need to be listening on this port also.
Bu alan belirtilmek zorunda değil. Belirtilmezse port alanı ile aynı değerdedir. Açıklaması şöyle
A Service can map any incoming port to a targetPort. By default and for convenience, the targetPort is set to the same value as the port field.

spec/selector Alanı
Pod'un medata alanında belirttiği bir alanın değerine göre seçme yapar.
Örnek
Şöyle yaparız
kind: Service
apiVersion: v1
metadata:
  name: service-test
spec:
  type: NodePort
  selector:
    app: service_test_pod
  ports:
  - port: 80 # cluster içindeki port
    targetPort: http # pod'un dinlediği port
Kontrol etmek için şöyle yaparız
$ kubectl get svc service-test
NAME           CLUSTER-IP     EXTERNAL-IP   PORT(S)           AGE
service-test   10.3.241.152   <none>        80:32213/TCP      1m
Örnek
Şöyle yaparız. Burada mysql dış dünyaya 30036 olarak açılıyor
apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    name: mysql
spec:
  type: NodePort
  ports:
    - port: 3306 # cluster içindeki port
      nodePort: 30036 # Dış dünyaya açılan port
      name: http
  selector:
    name: mysql # Hangi pod seçilecek
Örnek
Şöyle yaparız. Dış dünyadan 30036 portuna gelen istekler  Pod'un dinlediği 80'e gönderilir. Cluster içinden 80'e gelen istekler Pod'un dinlediği 80'e gönderilir.
apiVersion: v1
kind: Service
metadata:  
  name: my-nodeport-service
spec:
  selector:    
    app: my-app
  type: NodePort
  ports:  
  - name: http
    port: 80 # servisin kullandığı cluster içindeki port
    targetPort: 80 # pod'un dinlediği port
    nodePort: 30036 # dış dünyaya açılan port
    protocol: TCP
Örnek
Şöyle yaparız. Dış dünyadan 30036 portuna gelen istekler  Pod'un dinlediği 80'e gönderilir. Cluster içinden 8080'e gelen istekler Pod'un dinlediği 80'e gönderilir.
apiVersion: v1
kind: Service
metadata:
name: hello-world
spec:
  type: NodePort
  selector:
    app: hello-world
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80
      nodePort: 30036

---
apiVersion: v1
kind: Pod
metadata:
  name: nginx
labels:
  app: hello-world
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
      - containerPort: 80
Örnek
Port numarası yerine string kullanılabilir. Şöyle yaparız. Burada sayı yerine "banaport" string'i kullanılıyor.
kind: Pod
apiVersion: v1
metadata:
  name: banana-app
  labels:
    app: banana
spec:
  containers:
    - name: banana-app
      image: hashicorp/http-echo
      args:
        - "-text=banana"
      ports:
      - containerPort: 5678
        name: bananaport
  terminationGracePeriodSeconds: 0
---
kind: Service
apiVersion: v1
metadata:
  name: banana-service
spec:
  selector:
    app: banana
  ports:
  - port: 8080
    targetPort: bananaport

Örnek
WSL2 ve minikube ile şöyle yaparız. Burada WSL2 minikube tüm podları docker içinde çalıştırdığı için, en baştan minikube start --ports=127.0.0.1:30080:30080 ile docker portlarını açmak gerekiyor. Daha sonra minikube VM IP adresi olan 127.0.0.1 kullanılıyor
# https://stackoverflow.com/questions/71384252/cannot-access-deployed-services-when-minikube-cluster-is-installed-in-wsl2
$ minikube start --ports=127.0.0.1:30080:30080

$  kubectl create deployment hello --image=k8s.gcr.io/echoserver:1.4
deployment.apps/hello created

$ kubectl get deployments -o wide
NAME    READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                      SELECTOR
hello   1/1     1            1           81s   echoserver   k8s.gcr.io/echoserver:1.4   app=hello

# https://stackoverflow.com/questions/52522570/how-to-expose-a-kubernetes-service-on-a-specific-nodeport
$ kubectl expose deployment hello --port=8080 --type=NodePort --overrides '{ "apiVersion": "v1","spec":{"ports": [{"port":8080,"protocol":"TCP","targetPort":8080,"nodePort":30080}]}}'
service/hello exposed

$ kubectl get service hello
NAME    TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
hello   NodePort   10.100.164.132   <none>        8080:30080/TCP   22s

$ curl 127.0.0.1:30080
CLIENT VALUES:
client_address=172.17.0.1
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://127.0.0.1:8080/

SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001

HEADERS RECEIVED:
accept=*/*
host=127.0.0.1:30080
user-agent=curl/7.68.0
BODY:
-no body in request-




Hiç yorum yok:

Yorum Gönder

Cluster Propotional Autoscaler - ReplicaSet Ekler/Siler

Giriş Açıklaması şöyle CPA aims to horizontally scale the number of Pod replicas based on the cluster’s scale. A common example is DNS ser...