Services

Services

  • Pods are very dynamic, they come and go on Kubernetes cluster
    • When using a Replication Controller, pods are terminated  and created during scaling operations
    • When using Deployments, when updating the image version, pods are terminated and new pods take the place of older pods
  • That's why Pods should never be accessed directly, but always through a Service
  • A service is the logical bridge between the "mortal" pods and other services or end-users
  • When using the kubectl expose command earlier, you created a new Service for your pod, so it could be accessed externally
  • Create a service will create an endpoint for your pods(s):
    • a ClusterIP: a virtual IP address only reachable from within the cluster (this is the default)
    • a NodePort: a port that is the same on each node that is also reachable externally
    • a LoadBalancer: a LoadBalancer created by the cloud provider that will route external traffic to every node on the NodePort (e.g. ELB on AWS)
  • The options just shown only allow you to create virtual IPs or ports
  • There is also a possibility to use DNS names
    • ExternalName can provide a DNS name for the service
    • e.g. for service discovery using DNS
    • This only works when the DNS add-on is enabled

Example Service

apiVersion: v1
kind: Service
metadata:
  name: helloworld-service
spec:
  ports:
  - port: 31001
    nodePort: 31001
    targetPort: nodejs-port
    protocol: TCP
  selector:
    app: helloworld
  type: NodePort
  • Note: By default, service can only run between port 30000-32767. But you could change this behavior by adding --service-node-port-range= argument to the kube-apiserver (in the init scripts)

Demo

Create Pod

$ kubectl create -f pod-helloworld.yml
pod "nodehelloworld.example.com" created

$ kubectl get pod
NAME                         READY     STATUS    RESTARTS   AGE
nodehelloworld.example.com   1/1       Running   0          9s

$ kubectl describe pod nodehelloworld.example.com
Name:		nodehelloworld.example.com
Namespace:	default
Node:		k8s-agent-7d111633-0/10.240.0.4
Start Time:	Mon, 07 May 2018 13:55:55 +0000
Labels:		app=helloworld
Annotations:	<none>
Status:		Running
IP:		10.244.1.10
Containers:
  k8s-demo:
    Container ID:	docker://88b44009636f515c1af43c940fa7b351ba7e772af7d8fe71e572a8cdba0d6505
    Image:		wardviaene/k8s-demo
    Image ID:		docker-pullable://wardviaene/k8s-demo@sha256:2c050f462f5d0b3a6430e7869bcdfe6ac48a447a89da79a56d0ef61460c7ab9e
    Port:		3000/TCP
    State:		Running
      Started:		Mon, 07 May 2018 13:55:59 +0000
    Ready:		True
    Restart Count:	0
    Environment:	<none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-lr576 (ro)
Conditions:
  Type		Status
  Initialized 	True
  Ready 	True
  PodScheduled 	True
Volumes:
  default-token-lr576:
    Type:	Secret (a volume populated by a Secret)
    SecretName:	default-token-lr576
    Optional:	false
QoS Class:	BestEffort
Node-Selectors:	<none>
Tolerations:	<none>
Events:
  FirstSeen	LastSeen	Count	From				SubObjectPath			Type		Reason			Message
  ---------	--------	-----	----				-------------			--------	------			-------
  37s		37s		1	default-scheduler						Normal		Scheduled		Successfully assigned nodehelloworld.example.com to k8s-agent-7d111633-0
  37s		37s		1	kubelet, k8s-agent-7d111633-0					Normal		SuccessfulMountVolume	MountVolume.SetUp succeeded for volume "default-token-lr576"
  36s		36s		1	kubelet, k8s-agent-7d111633-0	spec.containers{k8s-demo}	Normal		Pulling			pulling image "wardviaene/k8s-demo"
  33s		33s		1	kubelet, k8s-agent-7d111633-0	spec.containers{k8s-demo}	Normal		Pulled			Successfully pulled image "wardviaene/k8s-demo"
  33s		33s		1	kubelet, k8s-agent-7d111633-0	spec.containers{k8s-demo}	Normal		Created			Created container
  32s		32s		1	kubelet, k8s-agent-7d111633-0	spec.containers{k8s-demo}	Normal		Started			Started container

Create Service

$ cat helloworld-service.yml
apiVersion: v1
kind: Service
metadata:
  name: helloworld-service
spec:
  ports:
  - port: 31001
    nodePort: 31001
    targetPort: nodejs-port
    protocol: TCP
  selector:
    app: helloworld
  type: NodePort

$ kubectl create -f helloworld-service.yml
service "helloworld-service" created

$ kubectl get svc
NAME                 CLUSTER-IP     EXTERNAL-IP   PORT(S)           AGE
helloworld-service   10.0.240.190   <nodes>       31001:31001/TCP   12s
kubernetes           10.0.0.1       <none>        443/TCP           15d

$ kubectl describe svc helloworld-service
Name:			helloworld-service
Namespace:		default
Labels:			<none>
Annotations:		<none>
Selector:		app=helloworld
Type:			NodePort
IP:			10.0.240.190
Port:			<unset>	31001/TCP
NodePort:		<unset>	31001/TCP
Endpoints:		<none>
Session Affinity:	None

Re-create Service

$ kubectl delete svc helloworld-service
service "helloworld-service" deleted

$ kubectl create -f helloworld-service.yml
service "helloworld-service" created

$ kubectl describe svc helloworld-service
Name:			helloworld-service
Namespace:		default
Labels:			<none>
Annotations:		<none>
Selector:		app=helloworld
Type:			NodePort
IP:			10.0.166.250
Port:			<unset>	31001/TCP
NodePort:		<unset>	31001/TCP
Endpoints:		<none>
Session Affinity:	None

Please note that the virtual IP address is changed.

No Comments

Back to top