How to Create Services in Kubernetes¶
This guide explains how to create and manage Services in Kubernetes. A Service is an abstraction that defines a logical set of Pods and a policy by which to access them.
Prerequisites¶
- Running Kubernetes cluster
- kubectl installed and configured
- Basic understanding of Pods and Deployments
What is a Service?¶
A Service in Kubernetes is an abstraction which defines a logical set of Pods and a policy by which to access them. Services enable loose coupling between dependent Pods and can provide load balancing and service discovery.
Key features: - Service discovery - Load balancing - Stable network endpoint - Automatic updates when Pods change
Service Types¶
1. ClusterIP (Default)¶
- Exposes the Service on a cluster-internal IP
- Only reachable from within the cluster
2. NodePort¶
- Exposes the Service on each Node's IP at a static port
- Accessible from outside the cluster
3. LoadBalancer¶
- Exposes the Service externally using a cloud provider's load balancer
- Automatically creates NodePort and ClusterIP Services
4. ExternalName¶
- Maps the Service to a DNS name
- No proxying, just DNS CNAME record
Creating Services¶
1. ClusterIP Service¶
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
Create and verify the service:
# Create Service
kubectl apply -f my-app-service.yaml
service/my-app-service created
# View service details
kubectl get service my-app-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-app-service ClusterIP 10.96.123.45 <none> 80/TCP 30s
# Test service from within cluster
kubectl run test-pod --image=busybox -it --rm -- wget -O- http://my-app-service.default.svc.cluster.local
Connecting to my-app-service.default.svc.cluster.local (10.96.123.45:80)
<!DOCTYPE html>
<html>...</html>
2. NodePort Service¶
apiVersion: v1
kind: Service
metadata:
name: my-app-nodeport
spec:
type: NodePort
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
nodePort: 30080
Deploy and verify:
# Create NodePort service
kubectl apply -f my-app-nodeport.yaml
service/my-app-nodeport created
# Get service details
kubectl get service my-app-nodeport
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-app-nodeport NodePort 10.96.234.56 <none> 80:30080/TCP 45s
# Get node's external IP
kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION EXTERNAL-IP
worker-node1 Ready <none> 7d v1.24.0 192.168.1.101
worker-node2 Ready <none> 7d v1.24.0 192.168.1.102
3. LoadBalancer Service¶
apiVersion: v1
kind: Service
metadata:
name: my-app-lb
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
Create and monitor:
# Create LoadBalancer service
kubectl apply -f my-app-lb.yaml
service/my-app-lb created
# Watch service status
kubectl get service my-app-lb -w
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-app-lb LoadBalancer 10.96.345.67 <pending> 80:31080/TCP 10s
my-app-lb LoadBalancer 10.96.345.67 203.0.113.100 80:31080/TCP 45s
4. ExternalName Service¶
apiVersion: v1
kind: Service
metadata:
name: my-external-service
spec:
type: ExternalName
externalName: api.example.com
Create and verify:
# Create ExternalName service
kubectl apply -f external-service.yaml
service/my-external-service created
# Verify DNS resolution
kubectl run test-dns --image=busybox -it --rm -- nslookup my-external-service.default.svc.cluster.local
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: my-external-service.default.svc.cluster.local
Address 1: api.example.com
Advanced Configurations¶
1. Multi-Port Service¶
apiVersion: v1
kind: Service
metadata:
name: my-multiport-service
spec:
selector:
app: my-app
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
- name: https
protocol: TCP
port: 443
targetPort: 8443
Deploy and verify:
# Create multi-port service
kubectl apply -f multiport-service.yaml
service/my-multiport-service created
# Check port configuration
kubectl describe service my-multiport-service
Name: my-multiport-service
Namespace: default
Labels: <none>
Selector: app=my-app
Type: ClusterIP
IP: 10.96.456.78
Port: http 80/TCP
TargetPort: 8080/TCP
Endpoints: 10.244.1.2:8080,10.244.2.3:8080
Port: https 443/TCP
TargetPort: 8443/TCP
Endpoints: 10.244.1.2:8443,10.244.2.3:8443
2. Service with Session Affinity¶
apiVersion: v1
kind: Service
metadata:
name: sticky-service
spec:
selector:
app: my-app
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 1800
ports:
- protocol: TCP
port: 80
targetPort: 8080
Troubleshooting¶
Common Issues and Solutions¶
- Service Not Accessible
Output:
# Check service endpoints kubectl get endpoints my-app-service
NAME ENDPOINTS AGE my-app-service 10.244.1.2:8080,10.244.2.3:8080 5m
# Verify pod labels match service selector
kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
my-app-pod-1 1/1 Running 0 10m app=my-app
my-app-pod-2 1/1 Running 0 10m app=my-app
-
LoadBalancer Pending
Output:# Check service events kubectl describe service my-app-lb
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal EnsuringLoadBalancer 1m service-controller Ensuring load balancer Warning SyncLoadBalancerFailed 1m service-controller Error syncing load balancer: failed to ensure load balancer: no cloud provider configured
-
DNS Resolution Issues
Output:# Check kube-dns/CoreDNS kubectl get pods -n kube-system | grep dns
NAME READY STATUS RESTARTS AGE coredns-558bd4d5db-4d8qw 1/1 Running 0 7d coredns-558bd4d5db-dkr9w 1/1 Running 0 7d
Best Practices¶
-
Always use selectors
spec: selector: app: my-app tier: frontend
-
Name ports for clarity
spec: ports: - name: http port: 80 - name: https port: 443
-
Use appropriate service type
- ClusterIP for internal communication
- NodePort for development/testing
-
LoadBalancer for production external access
-
Add meaningful labels
metadata: labels: app: my-app tier: frontend environment: production
Monitoring Services¶
Commands for Service Monitoring¶
# Get service status
kubectl get services --all-namespaces
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d
default my-app-service ClusterIP 10.96.123.45 <none> 80/TCP 1h
default my-app-nodeport NodePort 10.96.234.56 <none> 80:30080/TCP 45m
default my-app-lb LoadBalancer 10.96.345.67 203.0.113.100 80:31080/TCP 30m
# Monitor endpoints
kubectl get endpoints -w
NAME ENDPOINTS AGE
kubernetes 192.168.1.101:6443 7d
my-app-service 10.244.1.2:8080,10.244.2.3:8080 1h
my-app-nodeport 10.244.1.2:8080,10.244.2.3:8080 45m
my-app-lb 10.244.1.2:8080,10.244.2.3:8080 30m
Next Steps¶
- Learn about Ingress controllers
- Implement service mesh
- Configure external DNS
- Set up SSL/TLS termination
- Implement service monitoring and logging