This section continues from the previous section - make sure you do the tutorial in sequence.
There are primarily 2 ways to expose a Kubernetes Service on the public internet:
Type
Protocol
Locality
When to use?
TCP/UDP
Regional
Non-HTTP requests, or no need for a global load balancer. Connection to the Load Balancer is routed by public Internet to region of the load balancer.
HTTP(s)
Global
HTTP requests. GCP's L7 Load Balancer is a global load balancer - a single IP address can automatically route traffic to the nearest region within the GCP network.
External Network Load Balancer
Service YAML
To create an external network load balancer, simply change Kubernetes Service's type from clusterip to loadbalancer. Modify the k8s/service.yaml:
k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
annotations:
cloud.google.com/neg: '{"exposed_ports": {"8080":{}}}'
spec:
ports:
- name: 8080-8080
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: helloworld
# Use LoadBalancer type instead of ClusterIP
type: LoadBalancer
Deploy
Use kubectl command line to deploy the YAML file:
kubectl apply -f k8s/service.yaml
To verify the application is deployed, run :
kubectl get svc helloworld
You should see that the Service has a Cluster IP address, but also the External IP address with the initial value of <pending>. This is because, behind the scenes, Kubernetes Engine is provisioning a Google Cloud Network Load Balancer.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloworld ClusterIP ... <pending> 8080/TCP 7s
Connect
Continuously check the External IP address, until an IP address is assigned. Once the IP Address is assigned, you can connect to the External IP address, and it'll be load balanced to the helloworld service backend pods.
EXTERNAL_IP=$(kubectl get svc helloworld -ojsonpath="{.status.loadBalancer.ingress[0].ip}")
curl $EXTERNAL_IP:8080
Static IP Address
You can assign a static IP address to the Network Load Balancer.
Update the k8s/service.yaml to pin the Load Balancer IP address:
k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
spec:
ports:
- name: 8080-8080
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: helloworld
type: LoadBalancer
# Replace the value with the IP address you reserved
loadBalancerIP: RESERVED_IP_ADDRESS
External HTTP Load Balancer
You can configure an external HTTP load balancer using Kubernetes Ingress. In order for the HTTP Load Balancer to find the backends, it's recommended to use container-native load balancing on Google Cloud.
Service YAML
In the k8s/service.yaml, use the cloud.google.com/neg annotation to enable Network Endpoint Group (NEG) in order to use container-native load balancing:
k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
# Add the NEG annotation to enable Network Endpoint Group
# in order to use container-native load balancing
annotations:
cloud.google.com/neg: '{"ingress": true}'
spec:
ports:
- name: 8080-8080
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: helloworld
type: ClusterIP
Ingress YAML
Create a Kubernetes Ingress configuration that will create the HTTP Load Balancer. Create a k8s/ingress.yaml:
Use kubectl command line to deploy the YAML files:
# Delete the existing service because it may contain a node port:
kubectl delete -f k8s/service.yaml
# Redeploy the service
kubectl apply -f k8s/service.yaml
# Deploy the ingress
kubectl apply -f k8s/ingress.yaml
To verify the Ingress is deployed:
kubectl get ingress helloworld
You should see that the Ingress has an IP address provisioned:
NAME HOSTS ADDRESS PORTS AGE
helloworld * ... 80 81s
Many Google Cloud components are being configured behind the scenes to enable global load balancing. It'll take a few minutes before the address is accessible. Use kubectl describe to see the current status:
EXTERNAL_IP=$(kubectl get ingress helloworld -ojsonpath="{.status.loadBalancer.ingress[0].ip}")
curl $EXTERNAL_IP
Static IP Address
By default, the Ingress IP address is ephemeral - it'll change if you ever delete and recreate the Ingress. You can associate the Ingress with a static IP address instead.
Continuously check the IP address to be updated. It'll take several minutes for the IP address to update:
kubectl get ingress helloworld
SSL Certificate
In order to use a SSL certificate to serve HTTPs traffic, you must use a real fully qualified domain name and configure it to point to the IP address. If you don't have a real domain, then you can use xip.io.
EXTERNAL_IP=$(kubectl get ingress helloworld -ojsonpath="{.status.loadBalancer.ingress[0].ip}")
DOMAIN="${EXTERNAL_IP}.xip.io"
curl $DOMAIN
echo $DOMAIN
You can provision the External HTTP(s) Load Balancer using Ingress with a Managed Certificate, or you can provide your own Self-Managed Certificate.
Managed Certificate
Google Cloud can automatically provision a certificate for your domain name when using the External HTTP(s) Load Balancer.
Create a new k8s/certificate.yaml:
EXTERNAL_IP=$(kubectl get ingress helloworld -ojsonpath="{.status.loadBalancer.ingress[0].ip}")
DOMAIN="${EXTERNAL_IP}.xip.io"
cat << EOF > k8s/certificate.yaml
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: helloworld-certificate
spec:
domains:
# Replace the value with your domain name
- ${DOMAIN}
EOF
k8s/certificate.yaml
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: helloworld-certificate
spec:
domains:
# Replace the value with your domain name
- YOUR_DOMAIN_NAME
In k8s/ingress.yaml, use the networking.gke.io/managed-certificates annotation to associate the certificate:
k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: helloworld
annotations:
kubernetes.io/ingress.global-static-ip-name: "helloworld-ingress-ip"
# Associate the ingress with the certificate name
networking.gke.io/managed-certificates: "helloworld-certificate"
spec:
rules:
- http:
paths:
- path: /*
backend:
service:
name: helloworld
post:
number: 8080