Exposing containers

Exposing containers

  • kubectl expose creates a service for existing pods

  • A service is a stable address for pod(s)

  • If we want to connect to pod(s) we need a service

  • CoreDNS (part of control plane) allows us to resolve services by name

  • There are different types of services

    • ClusterIP (default)

      • Single, internal virtual IP allocated

      • Only reachable from within cluster (nodes and pods)

      • Pods can reach service on apps port number

      • Always available in Kubernetes

    • NodePort

      • High port allocated on each node

      • Port is open on every node's IP

      • Anyone can connect (if they can reach node)

      • Other pods need to be updated to this port

      • Always available in Kubernetes

    • LoadBalancer

      • Controls LB endpoint external to the cluster

      • Only available when infrastructure provider gives you a load balancer (AWS ELB, etc)

      • Creates NodePort + ClusterIP services, tells external load balancer to send traffic to NodePort

    • ExternalName

      • Adds CNAME DNS records to CoreDNS only

      • Not used for pods, but for giving pods a DNS name to use for something outside Kubernetes

Creating a ClusterIP service

  • kubectl get pods -w

  • kubectl create deployment httpenv --image=bretfisher/httpenv

  • kubectl scale deployment/httpenv --replicas=5

  • kubectl expose deployment/httpenv --port 8888

  • kubectl get service

  • kubectl run --generator run-pod/v1 tmp-shell --rm -it --image=bretfisher/netshoot -- bash

  • curl httpenv:8888

{
  "HOME": "/root",
  "HOSTNAME": "httpenv-7cc9888d59-s9sj6",
  "KUBERNETES_PORT": "tcp://10.96.0.1:443",
  "KUBERNETES_PORT_443_TCP": "tcp://10.96.0.1:443",
  "KUBERNETES_PORT_443_TCP_ADDR": "10.96.0.1",
  "KUBERNETES_PORT_443_TCP_PORT": "443",
  "KUBERNETES_PORT_443_TCP_PROTO": "tcp",
  "KUBERNETES_SERVICE_HOST": "10.96.0.1",
  "KUBERNETES_SERVICE_PORT": "443",
  "KUBERNETES_SERVICE_PORT_HTTPS": "443",
  "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
}

Creating a NodePort service

  • kubectl expose deployment/httpenv --port 8888 --name httpenv-np --type NodePort

  • kubectl get services

NAME

TYPE

CLUSTER-IP

EXTERNAL-IP

PORT(S)

AGE

httpenv

ClusterIP

10.107.92.157

none

8888/TCP

24h

httpenv-np

NodePort

10.109.25.172

none

8888:31642/TCP

8s

kubernetes

ClusterIP

10.96.0.1

none

443/TCP

2d13h

  • 8888:31642/TCP - from port 8888 inside the cluster to port 31642 externally accessible

  • Default port ranges in the cluster 30000-32767

  • These 3 service types are additive, each one creates one above it:

    • ClusterIP

    • NodePort

    • LoadBalancer

  • curl localhost:31642 (on Linux - goes directly to NodePort, on Mac/Windows goes through Docker VPNKit)

Creating a LoadBalancer service

  • Docker Desktop provides a built-in LoadBalancer that publishes the port on localhost

  • kubectl expose deployment/httpenv --port 8888 --name httpenv-lb --type LoadBalancer

  • curl localhost:8888

NAME

TYPE

CLUSTER-IP

EXTERNAL-IP

PORT(S)

AGE

httpenv

ClusterIP

10.107.92.157

none

8888/TCP

24h

httpenv-np

NodePort

10.109.25.172

none

8888:31642/TCP

8s

httpenv-lb

LoadBalancer

10.98.39.13

localhost

8888:30695/TCP

19s

kubernetes

ClusterIP

10.96.0.1

none

443/TCP

2d13h

Cleanup

  • kubectl delete service/httpenv service/httpenv-np service/httpenv-lb deployment/httpenv

Kubernetes Service DNS

  • Starting with 1.11, internal DNS is provided by CoreDNS

  • Like Swarm, this is DNS-based service discovery

  • Accessing services by hostname works only if they're in the same namespace

  • kubectl get namespaces

  • Services also have a FQDN

    curl <hostname>.<namespace>.svc.cluster.local

Last updated