$ vi hello-nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: hello-nginx
spec:
type: ClusterIP # this's default if the field type is skipped
ports:
- port: 80
targetPort: 80 # this defaults to the Port's value if the field targetPort is skipped
protocol: TCP # this's the default if the field protocol is skipped
selector: # the Service's selector verifies Pods that define all its labels
app: hello-nginx
The Service defines a Selector (spec.selector): "app=hello-nginx"$ kubectl apply -f hello-nginx-service.yaml
service/hello-nginx createdCheck the Service:
$ kubectl get service hello-nginx -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR hello-nginx ClusterIP 10.109.87.124 <none> 80/TCP 11m app=hello-nginxIn the bellow Deployment example, the Pods will be selected because they define (spec.template.metadata.labels) the label "app=hello-nginx". The other labels of the Pods ("product=mtitek", "stage=dev") are not considered.
$ vi hello-nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-nginx
spec:
replicas: 2
selector:
matchLabels:
app: hello-nginx
template:
metadata:
labels: # a subset of the Pod's labels must match the Service's selector
app: hello-nginx
product: mtitek
stage: dev
spec:
containers:
- name: hello-nginx
image: nginx:latest
ports:
- containerPort: 80
Let's apply the Deployment:$ kubectl apply -f hello-nginx-deployment.yaml
deployment.apps/hello-nginx createdVerify that Pods are running and ready (note the IP addresses of each Pod):
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES hello-nginx-5d77cc88f4-gj6k2 1/1 Running 0 13m 10.1.0.157 docker-desktop <none> <none> hello-nginx-5d77cc88f4-pz9dj 1/1 Running 0 13m 10.1.0.156 docker-desktop <none> <none>Let's validate the Service (note that the Endpoints field contains the Pods' IP addresses):
$ kubectl describe service hello-nginx
Name: hello-nginx Namespace: default Labels: <none> Annotations: <none> Selector: app=hello-nginx # list of labels that Pods must define so they can bed added to the Service's Endpoints Type: ClusterIP IP: 10.109.87.124 # clusterIP address (internal) of the Service Port: <unset> 80/TCP # the port that the Service listens on inside the cluster TargetPort: 80/TCP # the port that the Pods are listening on Endpoints: 10.1.0.156:80,10.1.0.157:80 # list of Pods (IP addresses) that are healthy and their labels match the service's label selector Session Affinity: None Events: <none>Check the Endpoints object of the Service (note the ENDPOINTS column):
$ kubectl get endpoints hello-nginx
NAME ENDPOINTS AGE hello-nginx 10.1.0.156:80,10.1.0.157:80 23mDescribe the Endpoints object of the Service (note the Addresses field):
$ kubectl describe endpoints hello-nginx
Name: hello-nginx
Namespace: default
Labels: <none>
Annotations: endpoints.kubernetes.io/last-change-trigger-time: 2021-06-06T10:31:11Z
Subsets:
Addresses: 10.1.0.156,10.1.0.157
NotReadyAddresses: <none>
Ports:
Name Port Protocol
---- ---- --------
<unset> 80 TCP
Events: <none>
To access the service from inside the cluster:$ kubectl exec -ti hello-nginx-5d77cc88f4-gj6k2 -- bash
root@hello-nginx-5d77cc88f4-gj6k2:/# curl -I -X GET 10.109.87.124:80 HTTP/1.1 200 OK Server: nginx/1.21.0 Date: Wed, 06 Jun 2021 02:52:40 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 25 May 2021 12:28:56 GMT Connection: keep-alive ETag: "60aced88-264" Accept-Ranges: bytes root@hello-nginx-5d77cc88f4-gj6k2:/#
$ vi hello-nginx-service-node-port.yaml
apiVersion: v1
kind: Service
metadata:
name: hello-nginx-node-port
spec:
type: NodePort
ports:
- port: 80
targetPort: 80 # this defaults to the Port's value if the field targetPort is skipped
protocol: TCP # this's the default if the field protocol is skipped
nodePort: 30080 # if not defined, Kubernetes will assign a port from a range (default: 30000-32767)
selector: # the Service's selector verifies Pods that define all its labels
app: hello-nginx
Let's apply the Service:$ kubectl apply -f hello-nginx-service-node-port.yaml
service/hello-nginx-node-port createdCheck the Service:
$ kubectl get service hello-nginx-node-port -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR hello-nginx-node-port NodePort 10.106.138.253 <none> 80:30080/TCP 24s app=hello-nginxLet's validate that Service (note that the Endpoints field contains the Pods' IP addresses):
$ kubectl describe service hello-nginx-node-port
Name: hello-nginx-node-port Namespace: default Labels: <none> Annotations: <none> Selector: app=hello-nginx Type: NodePort IP: 10.106.138.253 LoadBalancer Ingress: localhost Port: <unset> 80/TCP TargetPort: 80/TCP NodePort: <unset> 30080/TCP # the port to access the Service from outside the cluster Endpoints: 10.1.0.156:80,10.1.0.157:80 Session Affinity: None External Traffic Policy: Cluster Events: <none>Check the Endpoints object of the Service (note the ENDPOINTS column):
$ kubectl get endpoints hello-nginx-node-port
NAME ENDPOINTS AGE hello-nginx-node-port 10.1.0.156:80,10.1.0.157:80 83sDescribe the Endpoints object of the Service (note the Addresses field):
$ kubectl describe endpoints hello-nginx-node-port
Name: hello-nginx-node-port
Namespace: default
Labels: <none>
Annotations: endpoints.kubernetes.io/last-change-trigger-time: 2021-06-09T02:36:41Z
Subsets:
Addresses: 10.1.0.156,10.1.0.157
NotReadyAddresses: <none>
Ports:
Name Port Protocol
---- ---- --------
<unset> 80 TCP
Events: <none>
To access the service from inside the cluster, execute the same command we did above for the ClusterIP service (on port 80).$ curl -I -X GET 192.168.2.10:30080
HTTP/1.1 200 OK Server: nginx/1.21.0 Date: Wed, 06 Jun 2021 02:58:03 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 25 May 2021 12:28:56 GMT Connection: keep-alive ETag: "60aced88-264" Accept-Ranges: bytes
$ kubectl expose deployment hello-nginx \ --name=hello-nginx \ --port=80 \ --target-port=80 \ --type=ClusterIP
service/hello-nginx exposed
$ kubectl get services hello-nginx -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR hello-nginx ClusterIP 10.97.96.83 <none> 80/TCP 76s app=hello-nginx
$ kubectl delete -f hello-nginx-service.yaml
service "hello-nginx" deletedTo delete a Service using its name:
$ kubectl delete services hello-nginx
service "hello-nginx" deleted
$ kubectl exec -i -t dnsutils -- nslookup hello-nginx
Server: 10.96.0.10 <- The IP address of the Kubernetes DNS (kube-dns Service ClusterIP) Address: 10.96.0.10#53 Name: hello-nginx.default.svc.cluster.local <- The FQDN of the hello-nginx Service Address: 10.109.87.124 <- The clusterIP of the hello-nginx ServiceWhen Pods are created, they are configured to know about the Kubernetes DNS (ClusterIP, search domains). This will allow Pods to query the Kubernetes DNS to resolve a service's name to its IP address.
$ kubectl exec hello-nginx-5d77cc88f4-gj6k2 -- cat /etc/resolv.conf
nameserver 10.96.0.10 <- Kubernetes DNS IP address (kube-dns Service ClusterIP) to which request will be senn search default.svc.cluster.local svc.cluster.local cluster.local #<- search domains to be appended to unqualified names options ndots:5