k8s beginner 06 - services
service
Services enables communication with outside to make pods accessible for users or other applications.
service
usecase:
- external communication
To ping from server to pod we need something between outside and pod. This is where a service
came to play. It is an object like a replicaset
or a pod
. One usecase is to listen on a port from a node to a port on a running pod. This service is known as a NodePort
service because the service listen on port from a node to a port.
service exports a pod.
service types:
NodePort
- which is the service aboveClusterIP
- creates a virtual ip inside the clusetr to enable communication as example front- and backend communication inside a nodeLoadBalancer
- provisioning a load balancer
NodePort
Mapping a port on the node to a port on a pod
3 ports are envolved
pod
port -targetPort
service
port -port
- a virtual server in a node - has its own ip address
node
port -nodePort
- can only exported in the default valid range which is 30000 to 327670
create service-definition.yml
---
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: NodePort
ports:
- targetPort: 3000
port: 3000
nodePort: 30030
selector:
app: grafana
type: front-end
dont forget to define containerPort
in deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-grafana
labels:
app: grafana
spec:
selector:
matchLabels:
app: grafana
replicas: 3
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana
image: grafana/grafana
ports:
- containerPort: 3000 # defines port
spec: is most important part
-
spec:
- type: NodePort # can be ClusterIP or also LoadBalacer
-
ports:
targetPort
: 3000- port from
pod
- port from
port
: 3000- port from
service
- port from
nodePort
: 30030- port from
node
- port from
If you dont provide a targetPort
- service
it will use a port from the default valid port range. We have to declare on which pod the service should run.
In this case we defined to use label and selector for this
# aplly service yaml
> kubectl apply -f service-definition.yml
# show services
> kubectl get services
---
myapp-service NodePort 10.109.132.205 <none> 80:30008/TCP 28s
# get node ip
> minikube service list
# check connection
> nc -zv 192.168.49.2 30030
Connection to 192.168.49.2 30030 port [tcp/*] succeeded!
> curl http://192.168.49.2:30030
<a href="/login">Found</a>.
> kubectl describe svc myapp-service-grafana
---
Name: myapp-service-grafana
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=grafana
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.99.172.11
IPs: 10.99.172.11
Port: <unset> 8080/TCP
TargetPort: 3000/TCP
NodePort: <unset> 30030/TCP
Endpoints: 172.17.0.2:3000,172.17.0.5:3000,172.17.0.3000
Events: <none>
Session Affinity: None
External Traffic Policy: Cluster
---
# exec printenv
> kubectl exec myapp-deployment-grafana-7d9d9-hjkh -- printenv | grep SERVICE
---
KUBERNETES_SERVICE_HOST=10.96.0.1
MYAPP_SERVICE_GRAFANA_SERVICE_PORT=3000
MYAPP_SERVICE_GRAFANA_PORT_3000_TCP=tcp://10.99.172.11:3000
MYAPP_SERVICE_GRAFANA_PORT_3000_TCP_PROTO=tcp
MYAPP_SERVICE_GRAFANA_SERVICE_HOST=10.99.172.11
MYAPP_SERVICE_GRAFANA_PORT=tcp://10.99.172.11:3000
KUBERNETES_SERVICE_PORT_HTTPS=443
MYAPP_SERVICE_GRAFANA_PORT_3000_TCP_PORT=3000
MYAPP_SERVICE_GRAFANA_PORT_3000_TCP_ADDR=10.99.172.11
KUBERNETES_SERVICE_PORT=443
---
> kubectl get node -o wide
---
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
minikube Ready control-plane,master 5h34m v1.22.1 192.168.49.2 <none> Ubuntu 20.04.2 LTS 4.18.0-305.12.1.el8_4.x86_64 docker://20.10.8
sometimes minikube needs to be restarted for working correctly - keep an eye on the
selector
, multi label entrys means that multi labels must also match…
MultiNode NodePort
In multi node pod setup we will using labels instead of ports within selector. k8s automaticly creates a network for using in our service. Only ports are used - no addresses
- algorythm: Random
- SessionAffinity: Yes
ClusterIP
The case can be:
- front-end
pod
- back-end
pod
- database
pod
Communication over ip is not really possible cause pod ip’s will change from time to time. We can create a service using a single interface for an application to access the database or back-end connection.
edit clusterip.yml
---
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
type: ClusterIP
ports:
- targetPort: 3000
port: 3000
selector:
app: grafana
type: front-end
# apply service
> kubectl apply -f clusterip.yml
ClusterIP
is the default type
LoadBalancer
Could use a combination of address
and port
- it will be accessible for all nodes in a cluster.
One way to make an app accessible from a domain is to create a new vm (node) and install a LoadBalancer
service like haproxy
or nginx
on it. Then configure the LB to route traffic to the different nodes which can be a tbs task. We can use also cloud provider integrated services. k8s can handle almost all of this.
edit clusterip.yml
---
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
type: LoadBalancer
ports:
- targetPort: 3000
port: 3000
nodePort: 30030
selector:
app: grafana
type: front-end