---
title: "Exposing StatefulSets in Kubernetes"
source: "https://wordpress-1075849-4005834.cloudwaysapps.com/blog/exposing-statefulsets-in-kubernetes/"
description: "Learn about Kubernetes StatefulSets and How you can properly expose a StatefulSet externally."
---

[Technical Blog](https://wordpress-1075849-4005834.cloudwaysapps.com/category/technical-blog/)

# Exposing StatefulSets in Kubernetes

By [Bob Killen](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/author/bob-killen/) on Jan 04, 2019 • 4 min read

By far one of the most common questions we receive in the monthly Kubernetes Office Hours is: *“How do you properly expose a StatefulSet externally?”*Usually this question is asked in the form of: *“How do I allow connections to a particular instance of Mongo or Postgres from outside the cluster?”*

Fear not! This isn’t as challenging as it seems. If you’d like the [TL;DR answer](http://medium.com/p/698730fb92a1#6fc0), just skip down to the bottom of this post. If you’d like a little bit more of an explanation, continue reading.

Following the *normal* practice of having a single Service point to all instances of your application doesn’t work when you want to query a specific instance directly. This is already handled internally with the[Headless Service](http://kubernetes.io/docs/concepts/services-networking/service/#headless-services) you create alongside the StatefulSet. The created ervice will **not**be given a `clusterIP`, but will instead simply include a list of `Endpoints`. These `Endpoints` are then used to generate instance-specific DNS records in the form of: `<StatefulSet>-<Ordinal>.<Service>.<Namespace>.svc.cluster.local`e.g., `app-0.myapp.default.svc.cluster.local`.

Now, how do you replicate that when you want to expose it externally as a `LoadBalancer` Service? The Kubernetes developers have thought of this already. 😉 Each Pod in the StatefulSet has it’s own label that includes its [generated Pod identity](http://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-identity): `statefulset.kubernetes.io/pod-name`. You know what that means? It means we can use it in a Service Selector!

```
`apiVersion: v1 kind: Service metadata: name: app-0 spec: type: LoadBalancer selector: statefulset.kubernetes.io/pod-name: app-0 ports: - protocol: TCP port: 80 targetPort: 80`
```

While the headless service might not take care of all our needs, we can create additional Services that point to the individual Pods of the StatefulSet. Generally speaking, StatefulSets aren’t being scaled up or down without some careful planning, so it’s worth the small amount of extra effort to create some additional Services.

With that, we will be able to expose our instances individually, but we can actually improve on this a bit.

When an external Kubernetes Service (`NodePort` and `LoadBalancer`) is created, it will open a port on **all**nodes in the cluster that can be used for reaching our exposed Service. This is great in a general sense, when you spread traffic across many instances of the same Pod, but not so much when you want to direct traffic to a singular one. It’d be better if we could direct traffic directly to the node running the specific instance of our StatefulSet. Thankfully, the devs thought of this scenario too!

You can route traffic directly to the node by setting the Service attribute [externalTrafficPolicy](http://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-type-loadbalancer)[to](http://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-type-loadbalancer)[Local](http://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-type-loadbalancer). This forces the Service to only proxy traffic for local endpoints. Meaning, any node in the cluster that is **not** running the specific instance of the Pod will **not** proxy traffic, and will therefore fail any external healthcheck.

```
`apiVersion: v1 kind: Service metadata: name: app-0 spec: type: LoadBalancer externalTrafficPolicy: Local selector: statefulset.kubernetes.io/pod-name: app-0 ports: - protocol: TCP port: 80 targetPort: 80`
```

This may seem a little odd, but it’s a very useful and generic method that can play nice with the various cloud providers and their load balancers. By not proxying the traffic, the nodes will automatically be removed from the load balancer pool for that external Service forcing traffic to only go to the node running that specific instance.

With that, you should be able to expose StatefulSets externally and remove the unnecessary extra hop when routing traffic to a single instance.

## Bonus:

If you don’t want to have to manage creating an additional Service per Pod for your StatefulSet, it can be automated using a powerful cluster automation tool called [metacontroller](http://metacontroller.app/). It allows you to create your own simple controllers where you can trigger additional scripts or actions. One of their examples automates the Service creation for StatefulSet instances using their[DecoratorController](http://github.com/GoogleCloudPlatform/metacontroller/tree/master/examples/service-per-pod).

## TL;DR:

- StatefulSet Pods have the label: `statefulset.kubernetes.io/pod-name`which contains their generated name (`<StatefulSet Name>-<Ordinal>`). You can create individual Services for each instance that use that label as their selector to expose the individual instances of the StatefulSet.

- To remove a potential extra hop, create the Services with the attribute `externalTrafficPolicy` and set it to `Local`.

- You can automate this process with a nifty cluster automation tool [metacontroller](http://metacontroller.app/).

This article originated from [http://itnext.io/exposing-statefulsets-in-kubernetes-698730fb92a1](http://itnext.io/exposing-statefulsets-in-kubernetes-698730fb92a1)

Bob Killen is a Tigera guest blogger. He is Research Cloud Administrator at University of Michigan, CNCF Ambassador and Kubernetes & OSS Advocate.

————————————————-

[**Free Online Training**](https://wordpress-1075849-4005834.cloudwaysapps.com/events/)

Access Live and On-Demand Kubernetes Tutorials

[**Calico Enterprise – Free Trial**](https://www.calicocloud.io/home)

Solve Common Kubernetes Roadblocks and Advance Your Enterprise Adoption

[How-To](https://wordpress-1075849-4005834.cloudwaysapps.com/tags/how-to/)[Open Source](https://wordpress-1075849-4005834.cloudwaysapps.com/tags/open-source/)

Add Tigera as a preferred source on Google to see more of our content in your search results.

[![Add as a preferred source on Google](https://wordpress-1075849-4005834.cloudwaysapps.com/app/themes/tigera2021/dist/img/google-preferred-source-light.png)](https://www.google.com/preferences/source?q=tigera.io)

## Related posts

[![AI Assistant for Calico: Troubleshooting at the Speed of Thought](https://wordpress-1075849-4005834.cloudwaysapps.com/app/uploads/2026/03/Blog-Mar-20-AI-Assistant-for-Calico.png)](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/ai-assistant-for-calico-troubleshooting-at-the-speed-of-thought/)

#### [AI Assistant for Calico: Troubleshooting at the Speed of Thought](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/ai-assistant-for-calico-troubleshooting-at-the-speed-of-thought/)

By [Veronika Smolik](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/author/veronika-smolik/)
on Mar 19, 2026

Despite the wealth of data available, distilling a coherent narrative from a Kubernetes cluster remains a challenge for modern infrastructure teams. Even with powerful visualization tools like the Policy Board, Service Graph, and specialized dashboards,...

[Read more](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/ai-assistant-for-calico-troubleshooting-at-the-speed-of-thought/)

[![What Your EKS Flow Logs Aren’t Telling You](https://wordpress-1075849-4005834.cloudwaysapps.com/app/uploads/2026/03/Blog-Mar-18-What-Your-EKS-Flow-Logs-Arent-Telling-You.png)](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/what-your-eks-flow-logs-arent-telling-you/)

#### [What Your EKS Flow Logs Aren’t Telling You](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/what-your-eks-flow-logs-arent-telling-you/)

By [Phil DiCorpo](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/author/phil-dicorpo/)
on Mar 18, 2026

If you’re running workloads on Amazon EKS, there’s a good chance you already have some form of network observability in place. VPC Flow Logs have been a staple of AWS networking for years, and AWS...

[Read more](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/what-your-eks-flow-logs-arent-telling-you/)

[![Join Calico at KubeCon Europe 2026: AI Agents, Silent Discos, and Dutch Delights!](https://wordpress-1075849-4005834.cloudwaysapps.com/app/uploads/2026/02/Blog-Kubecon-Euro-2026-.png)](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/calico-at-kubecon-cloudnativecon-europe2026/)

[Company Blog](https://wordpress-1075849-4005834.cloudwaysapps.com/category/company-blog/)

#### [Join Calico at KubeCon Europe 2026: AI Agents, Silent Discos, and Dutch Delights!](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/calico-at-kubecon-cloudnativecon-europe2026/)

By [Tigera Team](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/author/marketingtigera-io/)
on Feb 25, 2026

The cloud-native community is heading to the historic canals and vibrant tech scene of Amsterdam for KubeCon + CloudNativeCon Europe 2026! From March 23–26, Amsterdam will be buzzing with the latest in Kubernetes, platform engineering,...

[Read more](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/calico-at-kubecon-cloudnativecon-europe2026/)

<!-- plugin=object-cache-pro client=phpredis metric#hits=6142 metric#misses=17 metric#hit-ratio=99.7 metric#bytes=2196544 metric#prefetches=0 metric#store-reads=417 metric#store-writes=9 metric#store-hits=430 metric#store-misses=6 metric#sql-queries=26 metric#ms-total=924.21 metric#ms-cache=45.06 metric#ms-cache-avg=0.1060 metric#ms-cache-ratio=4.9 -->
