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 thekube-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.