Mastering Kubernetes Services and Ingress: From NodePort to LoadBalancer and TLS
This guide walks through Kubernetes Service concepts, creation methods via kubectl expose and YAML, service inspection, endpoint management, and three ways to expose services externally—NodePort, LoadBalancer, and Ingress—plus detailed deployment options, TLS configuration, and practical command‑line examples.
1. Service Overview
In Kubernetes, a Service provides load balancing and automatic service discovery. It is implemented by the kube‑proxy component together with iptables.
1.1 What is a Service
A Service abstracts a set of Pods and exposes them via a stable IP and port.
1.2 Creating a Service
There are two ways to create a Service:
Using
kubectl expose:
<code>#kubectl expose deployment nginx --port=88 --type=NodePort --target-port=80 --name=nginx-service</code> --port: port exposed to the outside
--type=NodePort: access the service via node IP + port
--target-port: container port
--name: name of the Service
Using a YAML manifest:
<code>apiVersion: v1
kind: Service
metadata:
name: nginx-service
labels:
app: nginx
spec:
type: NodePort
ports:
- port: 88 # service port
targetPort: 80
selector:
app: nginx # Pods with label app=nginx belong to this Service</code>1.3 Checking a Service
Run the following command to list Services:
<code># kubectl get svc</code>2. Connecting to Services Outside the Cluster
2.1 Service Endpoints
Endpoints are the IP addresses and ports of the Pods backing a Service. You can view them with:
<code># kubectl -n kube-system get svc kube-dns
# kubectl -n kube-system describe svc kube-dns</code>Or directly list endpoint objects:
<code># kubectl -n kube-system get endpoints kube-dns
# kubectl -n kube-system describe endpoints kube-dns</code>2.2 Manually Configuring Endpoints
If a Pod does not have a selector, Kubernetes will not create an Endpoint automatically, so you must create one manually to let the Service know which Pods to route to.
3. Exposing Services to External Clients
Kubernetes offers three ways to expose a Service externally:
Set the Service type to
NodePort.
Set the Service type to
LoadBalancer.
Create an
Ingressresource.
3.1 Using a NodePort Service
A NodePort opens a static port on every node and forwards traffic to the Service. Example YAML:
<code>apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
ports:
- port: 88
targetPort: 80
nodePort: 30123 # access via nodeIP:30123
selector:
app: nginx</code>Drawbacks:
Only one Service per port.
Port range limited to 30000‑32767.
Changing node IP requires updates.
NodePort is suitable for demos or low‑cost temporary services.
3.2 Using a LoadBalancer Service
LoadBalancer creates a cloud provider load balancer with a dedicated external IP. Example YAML:
<code>apiVersion: v1
kind: Service
metadata:
name: loadBalancer-nginx
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: nginx</code>Each LoadBalancer Service incurs a separate public IP and cost.
3.3 Exposing Services via Ingress
Ingress provides intelligent routing and can expose many HTTP services behind a single public IP.
4.1 Creating an Ingress Resource
An Ingress is not a Service type; it sits in front of multiple Services and performs routing.
<code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-tomcat
namespace: ingress-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: tomcat.ingress.com
http:
paths:
- backend:
serviceName: tomcat
servicePort: 8080</code>4.2 Ingress Components
Ingress controller – converts Ingress objects into Nginx configuration.
Ingress service – abstracts the controller as a Kubernetes object.
Nginx – performs load balancing to the backend Pods.
Ingress – creates virtual hosts in Nginx.
4.3 How Ingress Works
The controller watches the Kubernetes API for Ingress changes.
It generates Nginx config based on host and path rules.
The config is written to
/etc/nginx/nginx.confinside the controller pod.
Nginx is reloaded to apply the new configuration.
4.4 Deploying Ingress Controllers
Two common deployment patterns:
Deployment + LoadBalancer Service : Deploy the controller as a Deployment and expose it with a Service of type
LoadBalancer. Cloud providers automatically allocate a public IP.
Deployment + NodePort Service : Use a NodePort Service; external traffic reaches the controller via
nodeIP:nodePort. Often combined with an external load balancer.
DaemonSet + HostNetwork + nodeSelector : Run one controller pod per node using the host network (ports 80/443 directly on the node). This eliminates NAT overhead and is suitable for high‑traffic production clusters. Example DaemonSet snippet:
<code>apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
spec:
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
spec:
hostNetwork: true
nodeSelector:
isIngress: "true"
containers:
- name: nginx-ingress-controller
image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.26.1
ports:
- containerPort: 80
- containerPort: 443</code>Label a node and deploy the DaemonSet:
<code># kubectl label node 192.168.2.220 isIngress=true
# kubectl apply -f mandatory.yaml</code>Verify the controller pod runs on the labeled node and listens on ports 80, 443, and the default backend port 8181.
4.5 Deploying an Application and Exposing It via Ingress
Example Tomcat Service and Deployment:
<code>apiVersion: v1
kind: Service
metadata:
name: tomcat
namespace: ingress-nginx
spec:
selector:
app: tomcat
ports:
- name: http
port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat-deploy
namespace: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app: tomcat
template:
metadata:
labels:
app: tomcat
spec:
containers:
- name: tomcat
image: tomcat
ports:
- containerPort: 8080</code>Apply the manifests and the Ingress rule shown earlier. After DNS resolution (e.g., add
tomcat.ingress.comto
/etc/hostspointing to the node’s external IP), accessing
http://tomcat.ingress.comdisplays the Tomcat welcome page.
4.6 Configuring HTTPS for Ingress
Generate a TLS secret (self‑signed or from a CA):
<code># openssl genrsa -out tls.key 2048
# openssl req -new -x509 -key tls.key -out tls.crt -subj "/C=CN/ST=HangZhou/L=ZheJiang/O=devops/CN=tomcat.ingress.com"
# kubectl create secret tls tomcat-ingress-https --cert=tls.crt --key=tls.key -n ingress-nginx</code>Update the Ingress to reference the secret:
<code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-tomcat
namespace: ingress-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- hosts:
- tomcat.ingress.com
secretName: tomcat-ingress-https
rules:
- host: tomcat.ingress.com
http:
paths:
- backend:
serviceName: tomcat
servicePort: 8080</code>Apply the updated Ingress and access the service via
https://tomcat.ingress.com. Because the certificate is self‑signed, browsers will show a security warning unless the certificate is trusted.
Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.