To access pods you have three options
- services (load balancing)
- port forwarding (through localhost for development purpose)
- ingress (network policy)
In this section we will inspect services and port forwarding.
SERVICES
To allow containers to communicate with each other and the outside world, Kubernetes allows you to expose pods as services.
Service are decoupled from deployment (they exist independently) and the only way to associate to a deployment is by using lables.
They can be used to access multiple deployment and are automatically “load balanced” by Kubernetes.
There are 3 types of services:
- ClusterIp (for internal access)
- NodePort (to allocate a specific port for external access)
- LoadBalancer (for public cloud)
- ExternalName (for DNS level redirection)
- No Selector for direct IP/Port associations (for databases and namespaces)
To expose a deployment you can use ithe imperative way:
> kubectl expose deploy flask --port 5000
A cluster IP service manifest might look like the following:
apiVersion: v1
kind: Service
metadata:
name: jupiter-crew-svc
namespace: jupiter
...
spec:
clusterIP: 10.3.245.70
ports:
- name: 8080-80
port: 8080
protocol: TCP
targetPort: 80
selector:
id: jupiter-crew
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
This would work with the following Endpoints definition:
kind: Endpoints apiVersion: v1 metadata: name: some-remote-service subsets: - addresses: - ip: 1.2.3.4 ports: - port: 1976
NODEPORT
NodePort and Load balancer are used to expose the service outside the cluster
In addition to creating the ClusterIp, this will allocate a port in the range 30000-32767 on every node of the cluster, to route to the clusterIP.
For example:
$ kubectl expose deploy flask --port 5000 --type=NodePort
The manifest looks like:
apiVersion: v1 kind: Service metadata: creationTimestamp: 2017-10-14T18:19:07Z labels: run: flask name: flask namespace: default resourceVersion: "19788" selfLink: /api/v1/namespaces/default/services/flask uid: 2afdd3aa-b10c-11e7-b586-080027768e7d spec: clusterIP: 10.0.0.39 externalTrafficPolicy: Cluster ports: - nodePort: 31501 port: 5000 protocol: TCP targetPort: 5000 selector: run: flask sessionAffinity: None type: NodePort status: loadBalancer: {}
If you don´t specify the target port, a a random port will be used.
Exposed services automatically register with the Kubernetes internal DNS, which make it easier to access them by names rather than IPs. You can get the url by using nslookup, like:
$ kubectl exec -it busybox2 --nslookup nginx
HEADLESS SERVICE
If you put in the spec “clusterIp” as “none”, you get a headless service.
It is possible to create a service grouping that does not allocate an IP address or forward traffic, if there is a reason that you want to definitively control what specific pods you connect and communicate with. This kind of service is called a headless service. You can request this setup by explicitly setting ClusterIP to None within the service definition:
For example, a headless service might be:
kind: Service apiVersion: v1 metadata: name: flask-service spec: ClusterIP: None selector: app: flask
For these kind of services, DNS entries will be created that point to the Pods backing the service, and that DNS will be automatically updated as Pods matching the selector come online (or disappear).
ENDPOINT
You can expose a remote system as a service internally by creating an endpoint for it.
For example, if you had a remote TCP service running on the internet at port 1976 at the IP address 1.2.3.4, you could define a Service and Endpoint to reference that external-to-kubernetes system:
kind: Service
apiVersion: v1
metadata:
name: some-remote-service
spec:
ports:
- protocol: TCP
port: 1976
targetPort: 1976
This would work with the following Endpoints definition:
kind: Endpoints
apiVersion: v1
metadata:
name: some-remote-service
subsets:
- addresses:
- ip: 1.2.3.4
ports:
- port: 1976
PORT FORWARDING
Now we can use that name to ask kubectl to set up a proxy that will forward all traffic from a local port we specify to a port associated with the Pod we determine.
$ kubectl port-forward flask-1599974757-b68pw 5000:5000 Forwarding from 127.0.0.1:5000 -> 5000 Forwarding from [::1]:5000 -> 5000
This is forwarding any and all traffic that gets created on your local machine at TCP port 5000 to TCP port 5000 on the Pod flask-1599974757-b68pw.