Ambassador Edge Stack (AES) is built on Envoy Proxy. It can function as a high-performance API gateway and Ingress controller for Kubernetes clusters. AES functions as a control plane that translates Kubernetes custom resources to Envoy configurations for Envoy to handle requests. AES is integrated with rate limiting, request identification, load balancing, and observability. This topic describes how to use AES to manage Ingresses.

Deploy AES in ACK clusters

By default, AES is not deployed in clusters of Alibaba Cloud Container Service for Kubernetes (ACK). You need to manually deploy AES in ACK clusters. The following example describes how to deploy AES in an ACK clusters by using a YAML file. For more information about how to deploy AES in other ways, see AES official documentation.

Run the following commands to deploy AES in an ACK cluster:
kubectl apply -f https://www.getambassador.io/yaml/aes-crds.yaml && \
kubectl wait --for condition=established --timeout=90s crd -lproduct=aes && \
kubectl apply -f https://www.getambassador.io/yaml/aes.yaml && \
kubectl -n ambassador wait --for condition=available --timeout=90s deploy -lproduct=aes

If the following output is printed, AES is deployed:

customresourcedefinition.apiextensions.k8s.io/authservices.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/consulresolvers.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/hosts.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/kubernetesendpointresolvers.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/kubernetesserviceresolvers.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/logservices.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/mappings.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/modules.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/ratelimitservices.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/tcpmappings.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/tlscontexts.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/tracingservices.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/filterpolicies.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/filters.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/ratelimits.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/projectcontrollers.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/projects.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/projectrevisions.getambassador.io created
customresourcedefinition.apiextensions.k8s.io/authservices.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/consulresolvers.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/filterpolicies.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/filters.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/hosts.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/kubernetesendpointresolvers.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/kubernetesserviceresolvers.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/logservices.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/mappings.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/modules.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/projectcontrollers.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/projectrevisions.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/projects.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/ratelimits.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/ratelimitservices.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/tcpmappings.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/tlscontexts.getambassador.io condition met
customresourcedefinition.apiextensions.k8s.io/tracingservices.getambassador.io condition met
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
namespace/ambassador configured
serviceaccount/ambassador created
clusterrole.rbac.authorization.k8s.io/ambassador created
clusterrolebinding.rbac.authorization.k8s.io/ambassador created
clusterrole.rbac.authorization.k8s.io/ambassador-projects created
clusterrolebinding.rbac.authorization.k8s.io/ambassador-projects created
service/ambassador-redis created
deployment.apps/ambassador-redis created
ratelimitservice.getambassador.io/ambassador-edge-stack-ratelimit created
authservice.getambassador.io/ambassador-edge-stack-auth created
secret/ambassador-edge-stack created
mapping.getambassador.io/ambassador-devportal created
mapping.getambassador.io/ambassador-devportal-api created
service/ambassador created
service/ambassador-admin created
deployment.apps/ambassador created
deployment.extensions/ambassador condition met
deployment.extensions/ambassador-redis condition met

Verify that AES functions as an Ingress controller

To verify that AES functions as an Ingress controller, you need to create a Deployment.

  1. Use the following template to create a Deployment:
    cat <<-EOF | kubectl apply -f -
    apiVersion: v1
    kind: Service
      metadata:
        name: quote
    spec:
      ports:
      - name: http
        port: 80
        targetPort: 8080
      selector:
        app: quote
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: quote
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: quote
        strategy:
          type: RollingUpdate
      template:
        metadata:
          labels:
            app: quote
        spec:
          containers:
          - name: backend
            image: quay.io/datawire/quote:0.3.0
            ports:
            - name: http
              containerPort: 8080
    EOF
  2. Use the following template to create an Ingress:
    cat <<-EOF | kubectl apply -f - 
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: ambassador
      name: test-ingress
    spec:
      rules:
      - http:
          paths:
          - path: /backend/
            backend:
              serviceName: quote
              servicePort: 80
    EOF

    The following Mapping resource is equivalent to the preceding Ingress resource. For more information about how to use custom resources in AES, see AES official documentation.

    cat > quote-backend.yaml <<-EOF
    apiVersion: getambassador.io/v2
    kind: Mapping
    metadata:
        name: backend
    spec:
        prefix: /backend/
        service: quote
    EOF
  3. Run the following command to query the IP address of the target cluster:
    kubectl get -n ambassador service ambassador -o "go-template={{range .status.loadBalancer.ingress}}{{or .ip .hostname}}{{end}}"
  4. Run the following command to verify that AES functions as an Ingress controller:
    curl -k https://{{AMBASSADOR_IP}}/backend/    # Replace the value of AMBASSADOR_IP with the obtained IP address.

    If the following output is printed, this indicates that AES functions as an Ingress controller:

      {
        "server": "icky-grapefruit-xar5if66",
        "quote": "A small mercy is nothing at all?",
        "time": "2020-07-17T09:00:57.646315605Z"
      }