How to expose Kubernetes services to the public using DNS Load Balancing
Kubernetes Services in CloudFleet Kubernetes Engine (CFKE) are exposed via a DNS load balancing mechanism. All services get a unique DNS name in the format:
<service_name>.<cluster_id>.cfke.cloudfleet.dev
This DNS name resolves to the external IP of the Ingress controller, which acts as a load balancer to distribute incoming traffic to the appropriate service endpoints.
Note: Cloudfleet relies on nodes having an external IP set. If an external IP is not set, for example, in certain private networking configurations or self-managed on-premises Kubernetes nodes, Cloudfleet will default to using the private IP. This ensures that your service is accessible whether from within the cluster or from outside, provided that appropriate networking rules are in place. See Exposing applications to the Internet for more information.
Expose a web server using Kubernetes
Here’s a simple example of how to expose a web server using Kubernetes:
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld
labels:
app: helloworld
spec:
replicas: 1
selector:
matchLabels:
app: helloworld
template:
metadata:
labels:
app: helloworld
spec:
containers:
- name: webserver
image: paulbouwer/hello-kubernetes:1.10
ports:
- containerPort: 8080
env:
- name: MESSAGE
value: "Hello, I'm running on Cloudfleet!"
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: KUBERNETES_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBERNETES_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
resources:
limits:
cpu: 50m
memory: 100Mi
requests:
cpu: 10m
memory: 15Mi
---
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
spec:
type: NodePort
selector:
app: helloworld
ports:
- name: http
port: 8080
targetPort: 8080
protocol: TCP
nodePort: 30080
In this example:
- The Nginx web server is deployed using a
Deployment
. - A
Service
of typeNodePort
exposes it externally, and will be accessible viahttp://helloworld.<cluster_id>.cfke.cloudfleet.dev:30080
.
Serving Traffic with TLS
To ensure secure communication, CloudFleet uses TLS certificates issued by Let’s Encrypt. The certificate is for the DNS name in the form:
<service_name>.<cluster_id>.cfke.cloudfleet.dev
The TLS certificate is valid for 90 days and is automatically renewed by cert-manager, simplifying certificate management. The Ingress controller handles HTTPS termination, ensuring all traffic to your services is securely encrypted.
The certificate is stored in Kubernetes as a TLS secret named ingress
in the default
namespace, and it is automatically applied by the Ingress controller. Here’s an example configuration for HTTPS in the Ingress resource:
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld
labels:
app: helloworld
spec:
replicas: 1
selector:
matchLabels:
app: helloworld
template:
metadata:
labels:
app: helloworld
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- amd64
containers:
- name: nginx-tls-terminator
image: eknert/nginx-tls-terminator:1.0.1
ports:
- containerPort: 8443
volumeMounts:
- mountPath: /etc/nginx/ssl
name: tls-terminator-cert
readOnly: true
- mountPath: /tmp
name: tmp
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 2000
runAsGroup: 2000
readOnlyRootFilesystem: true
capabilities:
drop:
- all
resources:
limits:
cpu: 50m
memory: 100Mi
requests:
cpu: 10m
memory: 15Mi
- name: webserver
image: paulbouwer/hello-kubernetes:1.10
ports:
- containerPort: 8080
env:
- name: MESSAGE
value: "Hello, I'm running on Cloudfleet!"
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: KUBERNETES_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBERNETES_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
resources:
limits:
cpu: 50m
memory: 100Mi
requests:
cpu: 10m
memory: 15Mi
volumes:
- name: tls-terminator-cert
secret:
secretName: ingress
- name: tmp
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
spec:
type: NodePort
selector:
app: helloworld
ports:
- name: http
port: 8080
targetPort: 8080
protocol: TCP
nodePort: 30080
- name: https
port: 8443
targetPort: 8443
protocol: TCP
nodePort: 30433
This example illustrates:
- The use of a
tls
block to configure HTTPS for the service. - The use of Let’s Encrypt for certificate management.
- The use of a custom Nginx image to terminate TLS and forward traffic to the web server.
By using this setup, you can ensure that your public services are accessible securely over HTTPS.