# 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&#x20;
* Accessing services by hostname works only if they're in the same namespace
* `kubectl get namespaces`
* Services also have a FQDN

  &#x20; `curl <hostname>.<namespace>.svc.cluster.local`


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://notebook.iuriioapps.com/containers-and-microservices/kubernetes/exposing-containers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
