I've expressed on how to use LoadBalancer type of k8s service to create NLB with AWS Load Balancer Controller in part 1, now I'm going to use Ingress to create an ALB to serve multiple services across namespaces
NLB is good to act as Layer 4 load balancer, but one drawback we could not avoid is that we have to create a NLB for each service and it's costy, if we only expose RESTFUL service, we could aggragate all the RESTFUL service into one ALB. below is an example
the deployment is the same as part 1
apiVersion: apps/v1
kind: Deployment
metadata:
name: acme-api
spec:
selector:
matchLabels:
app: acme-api
replicas: 1
template:
metadata:
labels:
app: acme-api
spec:
containers:
- name: acme-api
image: us.gcr.io/acme/acme-api:1
imagePullPolicy: Always
resources:
requests:
memory: 128Mi
readinessProbe:
exec:
command:
- /bin/bash
- -c
- ps -ef | grep server | grep -v "grep"
initialDelaySeconds: 8
timeoutSeconds: 10
livenessProbe:
exec:
command:
- /bin/bash
- -c
- ps -ef | grep server | grep -v "grep"
initialDelaySeconds: 60
timeoutSeconds: 10
ports:
- name: grpc
containerPort: 8080
volumeMounts:
- name: config-volume
mountPath: /app/.env
subPath: .env
- name: esp
image: gcr.io/endpoints-release/endpoints-runtime:1
imagePullPolicy: Always
args: [
"--http_port=9000",
"--backend=grpc://127.0.0.1:8080",
"--service={{.service_name}}",
"--version={{.service_conf}}",
"--transcoding_preserve_proto_field_names",
"--transcoding_always_print_primitive_fields",
"--service_account_key=/etc/nginx/creds/google-service-account-key-name"
]
ports:
- name: http
containerPort: 9000
volumeMounts:
- mountPath: /etc/nginx/creds
name: google-service-account-key
readOnly: true
volumes:
- name: config-volume
configMap:
name: acme-cm
- name: google-service-account-key
secret:
secretName: google-service-account-key
the service definition is different from part 1, I've changed the service type to NodePort
and remove all the annotation from service definition
apiVersion: v1
kind: Service
metadata:
name: acme-api
spec:
type: NodePort
ports:
- name: http
port: 9000
targetPort: 9000
selector:
app: acme-api
one extra step I need to do is to create the ingress part,
to aggregate different ingress into the same ALB, we need to define alb.ingress.kubernetes.io/group.name: acme
, the ingress with the same group.name will share the same ALB, we could also customize the health check path via alb.ingress.kubernetes.io/healthcheck-path
, this path must support http GET method and return 200 , so that the target could be registered in ALB
- the dev ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
# Ingress Core Settings
kubernetes.io/ingress.class: "alb"
alb.ingress.kubernetes.io/scheme: internal
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/healthcheck-path: /acme/common/echo/acme
alb.ingress.kubernetes.io/group.name: acme
name: acme-api
namespace: dev
spec:
rules:
- host: dev-acme-api.vipmind.me
http:
paths:
- backend:
service:
name: acme-api
port:
number: 9000
path: /acme/
pathType: Prefix
- the staging ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
# Ingress Core Settings
kubernetes.io/ingress.class: "alb"
alb.ingress.kubernetes.io/scheme: internal
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/healthcheck-path: /acme/common/echo/acme
alb.ingress.kubernetes.io/group.name: acme
name: acme-api
namespace: stg
spec:
rules:
- host: stg-acme-api.vipmind.me
http:
paths:
- backend:
service:
name: acme-api
port:
number: 9000
path: /acme/
pathType: Prefix
I could use 2 ingress definition to aggregate the service from both dev and stg namespace together, because ALB works on layer 7, so it could check the host name and url etc.