#kubeweek #4

Using a Service to Expose App When a worker node dies, the Pods running on the Node are also lost. A ReplicaSet might then dynamically drive the cluster back to the desired state via the creation of new Pods to keep your application running. A Service in Kubernetes is an abstraction which defines a logical set of Pods and a policy by which to access them. Services enable a loose coupling between dependent Pods. A Service is defined using YAML or JSON, like all Kubernetes object manifests. The set of Pods targeted by a Service is usually determined by a label selector.
Create a new Service
kubectl get pods
List the current Services from our cluster:
kubectl get services
To create a new service and expose it to external traffic we'll use the expose command with NodePort as parameter.
kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
kubectl get services
To find out what port was opened externally:
kubectl describe services/kubernetes-bootcamp' export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')" echo "NODE_PORT=$NODE_PORT"
we can test that the app is exposed outside of the cluster using curl
curl http://"$(minikube ip):$NODE_PORT"
Using labels
The Deployment created automatically a label for our Pod. With the describe deployment subcommand we can see the name (the key) of that label: kubectl describe deployment
Let’s use this label to query our list of Pods. kubectl get pods -l app=kubernetes-bootcamp
kubectl get services -l app=kubernetes-bootcamp
Get the name of the Pod and store it in the POD_NAME environment variable:
export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')" echo "Name of the Pod: $POD_NAME"
To apply a new label we use the label subcommand followed by the object type, object name and the new label:
kubectl label pods "$POD_NAME" version=v1
we can check it with the describe pod command:
kubectl describe pods "$POD_NAME"
List of pods using the new label:
kubectl get pods -l version=v1
Deleting a service
To delete Services :
kubectl delete service -l app=kubernetes-bootcamp
Confirm that the Service is gone:
kubectl get services
To confirm that route is not exposed anymore you can curl the previously exposed IP and port:
curl http://"$(minikube ip):$NODE_PORT"
This proves that the application is not reachable anymore from outside of the cluster. We can confirm that the app is still running with a curl from inside the pod:
kubectl exec -ti $POD_NAME -- curl http://localhost:8080
Service Discovery
In modern cloud-native infrastructure such as Kubernetes, applications are designed using microservices. The different components need to communicate within a microservices architecture for applications to function, but individual IP addresses and endpoints change dynamically.
![]()
Types of service discovery
There are multiple different types of service discovery. Let’s take a look at some of the most popular approaches.
Server-side service discovery
Server-side service discovery involves putting a load balancer (LB) in front of the service and letting the load balancer connect to service instances. This process eliminates client-side complexity. The client simply points to the IP or DNS name of the load balance.
![]()
Service registry
Another approach to service discovery is to remove the LB component and implement service discovery on the client-side using a centralized service registry.
![]()
To get started, create a test namespace for this demo:
$ kubectl create ns demo
namespace/demo created
Next, create an nginx app deployment:
$ kubectl -n demo apply -f
https://k8s.io/examples/application/deployment-update.yaml
deployment.apps/nginx-deployment created
pods are up and running and confirm if the endpoints are available.
$ kubectl -n demo get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-559d658b74-k79zt 1/1 Running 0 45s
nginx-deployment-559d658b74-xjpvb 1/1 Running 0 45s
## check if the pods endpoints are available in Kubernetes ( not yet )
$ kubectl -n demo get ep
No resources found in demo namespace.
Create a service object for the deployment using the kubectl expose command.
$ kubectl -n demo expose deployment/nginx-deployment
service/nginx-deployment exposed
$ kubectl -n demo get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-deployment ClusterIP 10.245.202.247 ‹none› 80/TCP 13s
$ kubectl -n demo get endpoints
NAME ENDPOINTS AGE
nginx-deployment 10.244.2.152:80,10.244.2.203:80 24s
$ kubectl -n demo get svc nginx-deployment -o yaml
- apiVersion: v1
kind: Service
metadata:
name: nginx-deployment
namespace: demo
resourceVersion: "31628410"
uid: 45a58559-d9e3-43a6-bfbc-e3ab6bb4aff0
spec:
clusterIP: 10.245.202.247
clusterIPs:
- 10.245.202.247
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
$ kubectl -n demo get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-deployment ClusterIP 10.245.202.247 ‹none› 80/TCP 82s
$ kubectl -n demo run tmp-shell --rm -i --tty --image nicolaka/netshoot --
/bin/bash
bash-5.1# nslookup nginx-deployment
Server:10.245.0.10
Address:10.245.0.10#53
Name:nginx-deployment.demo.svc.cluster.local ( auto mapped to FQDN )
Address: 10.245.202.247 ( IP of the service )
Access the app/service by Service name:
bash-5.1# curl nginx-deployment
‹!DOCTYPE html›
‹html›
‹head›
‹title›Welcome to nginx!‹/title›
‹style›
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
‹/style›
‹/head›
‹body›
‹h1›Welcome to nginx!‹/h1›
‹p›If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.‹/p›
‹p›For online documentation and support please refer to
‹a href="http://nginx.org/"›nginx.org‹/a›.‹br/›
Commercial support is available at
‹a href="http://nginx.com/"›nginx.com‹/a›.‹/p›
‹p›‹em›Thank you for using nginx.‹/em›‹/p›
‹/body›
‹/html›
bash-5.1#
Check the pod environment variables related to service discovery
bash-5.1# env
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_PORT=443
NGINX_DEPLOYMENT_PORT_80_TCP_PROTO=tcp
HOSTNAME=netshoot
NGINX_DEPLOYMENT_PORT_80_TCP=tcp://10.245.202.247:80
PWD=/root
HOME=/root
KUBERNETES_PORT_443_TCP=tcp://10.245.0.1:443
NGINX_DEPLOYMENT_PORT_80_TCP_ADDR=10.245.202.247
NGINX_DEPLOYMENT_SERVICE_PORT=80
NGINX_DEPLOYMENT_PORT_80_TCP_PORT=80
NGINX_DEPLOYMENT_SERVICE_HOST=10.245.202.247
TERM=xterm
SHLVL=1
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.245.0.1
NGINX_DEPLOYMENT_PORT=tcp://10.245.202.247:80
KUBERNETES_SERVICE_HOST=10.245.0.1
KUBERNETES_PORT=tcp://10.245.0.1:443
KUBERNETES_PORT_443_TCP_PORT=443
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
_=/usr/bin/env