> For the complete documentation index, see [llms.txt](https://notebook.iuriioapps.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://notebook.iuriioapps.com/containers-and-microservices/kubernetes/exposing-containers.md).

# 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
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
