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

alb

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.