Running microservices in Amazon EKS with AWS App Mesh and Kong

Enter AWS App Mesh and Kong for Kubernetes Ingress Controller

Kong for Kubernetes Aarchitecture

Prerequisites

Solution deployment

Step 1: Deploy your DJ service mesh application

$ kubectl get virtualservices -n prod
NAME ARN AGE
jazz arn:aws:appmesh:us-west-2:<AWS_ACCOUNT>:mesh/dj-app/virtualService/jazz.prod.svc.cluster.local 2m39s
metal arn:aws:appmesh:us-west-2:<AWS_ACCOUNT>:mesh/dj-app/virtualService/metal.prod.svc.cluster.local 2m38s
$ kubectl get virtualrouters -n prod
NAME ARN AGE
jazz-router arn:aws:appmesh:us-west-2:<AWS_ACCOUNT>:mesh/dj-app/virtualRouter/jazz-router_prod 2m54s
metal-router arn:aws:appmesh:us-west-2:<AWS_ACCOUNT>:mesh/dj-app/virtualRouter/metal-router_prod 2m53s
$ kubectl get virtualnodes -n prod
NAME ARN AGE
dj arn:aws:appmesh:us-west-2:<AWS_ACCOUNT>:mesh/dj-app/virtualNode/dj_prod 3m8s
jazz-v1 arn:aws:appmesh:us-west-2:<AWS_ACCOUNT>:mesh/dj-app/virtualNode/jazz-v1_prod 3m4s
jazz-v2 arn:aws:appmesh:us-west-2:<AWS_ACCOUNT>:mesh/dj-app/virtualNode/jazz-v2_prod 2m41s
metal-v1 arn:aws:appmesh:us-west-2:<AWS_ACCOUNT>:mesh/dj-app/virtualNode/metal-v1_prod 3m4s
metal-v2 arn:aws:appmesh:us-west-2:<AWS_ACCOUNT>:mesh/dj-app/virtualNode/metal-v2_prod 2m40s
$ kubectl describe virtualrouter jazz-router -n prod 
...
Routes:
Http Route:
Action:
Weighted Targets:
Virtual Node Ref:
Name: jazz-v1
Weight: 95
Virtual Node Ref:
Name: jazz-v2
Weight: 5
...

Step 2: Deploy Kong for Kubernetes Ingress Controller

kubectl create namespace kong
kubectl label namespace kong mesh=dj-app appmesh.k8s.aws/sidecarInjectorWebhook=enabled
apiVersion: appmesh.k8s.aws/v1beta2
kind: VirtualNode
metadata:
name: kong
namespace: kong
spec:
podSelector:
matchLabels:
app.kubernetes.io/instance: kong
listeners:
- portMapping:
port: 80
protocol: http
backends:
- virtualService:
virtualServiceRef:
name: jazz
namespace: prod
- virtualService:
virtualServiceRef:
name: metal
namespace: prod
serviceDiscovery:
dns:
hostname: kong-kong-proxy.kong.svc.cluster.local
kubectl apply -f https://raw.githubusercontent.com/Kong/aws-blogposts/master/K4K8S+AWSAppMesh/kongvirtualnode.yml
$ kubectl get virtualnodes --all-namespaces
NAMESPACE NAME ARN AGE
kong kong arn:aws:appmesh:us-west-2::mesh/dj-app/virtualNode/kong_kong 62s
prod dj arn:aws:appmesh:us-west-2::mesh/dj-app/virtualNode/dj_prod 22m
prod jazz-v1 arn:aws:appmesh:us-west-2::mesh/dj-app/virtualNode/jazz-v1_prod 22m
prod jazz-v2 arn:aws:appmesh:us-west-2::mesh/dj-app/virtualNode/jazz-v2_prod 21m
prod metal-v1 arn:aws:appmesh:us-west-2::mesh/dj-app/virtualNode/metal-v1_prod 22m
prod metal-v2 arn:aws:appmesh:us-west-2::mesh/dj-app/virtualNode/metal-v2_prod 21m
helm repo add kong https://charts.konghq.com 
helm repo update
helm install -n kong kong kong/kong --version "1.11.0" --set ingressController.installCRDs=false
kubectl patch deploy -n kong kong-kong -p '{"spec":{"template":{"spec":{"containers":[{"name":"ingress-controller","securityContext":{"runAsUser": 1337}}]}}}}'
$ kubectl get pods -n kong
NAME READY STATUS RESTARTS AGE
kong-kong-5b4499bc4-rgxnd 3/3 Running 0 13m
$ kubectl get service -n kong
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kong-kong-proxy LoadBalancer 10.100.18.222 adf320d20effa44d4b49ca2cf279e0b8-240857585.{region}.elb.amazonaws.com 80:32445/TCP,443:32024/TCP 5d19h
$ kubectl get po -n kong -o jsonpath='{range .items[*]}{"pod: "}{.metadata.name}{"\n"}{range .spec.containers[*]}{"\tname: "}{.name}{"\n\timage: "}{.image}{"\n"}{end}'
pod: kong-kong-6f784b6686-qlrvp
name: ingress-controller
image: kong-docker-kubernetes-ingress-controller.bintray.io/kong-ingress-controller:1.0
name: proxy
image: kong:2.1
name: envoy
image: 840364872350.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy:v1.15.1.0-prod

Step 3: Define Ingress to expose and protect the service mesh

kubectl apply -f https://raw.githubusercontent.com/Kong/aws-blogposts/master/K4K8S%2BAWSAppMesh/fqdn-service-routing.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: djingress
namespace: prod
annotations:
konghq.com/strip-path: "true"
kubernetes.io/ingress.class: kong
konghq.com/override: do-not-preserve-host
spec:
rules:
- http:
paths:
- path: /dj/jazz
backend:
serviceName: jazz
servicePort: 9080
- path: /dj/metal
backend:
serviceName: metal
servicePort: 9080
kubectl create -f https://raw.githubusercontent.com/Kong/aws-blogposts/master/K4K8S+AWSAppMesh/dj_ingress.yml
apiVersion: configuration.konghq.com/v1
kind: KongIngress
metadata:
name: do-not-preserve-host
namespace: prod
route:
preserve_host: false
kubectl create -f https://raw.githubusercontent.com/Kong/aws-blogposts/master/K4K8S+AWSAppMesh/kongingress-dontpreservehost.yml
$ kubectl get ingress -n prod
NAME HOSTS ADDRESS PORTS AGE
djingress * {name.region}.elb.amazonaws.com
curl {your ingress address}/dj/jazz
["Astrud Gilberto","Miles Davis"]
while [ 1 ];
do curl http://{your ingress address}/dj/jazz/
echo
done
["Astrud Gilberto","Miles Davis"]
["Astrud Gilberto","Miles Davis"]
["Astrud Gilberto","Miles Davis"]
["Astrud Gilberto","Miles Davis"]
["Astrud Gilberto (Bahia, Brazil)","Miles Davis (Alton, Illinois)"]
["Astrud Gilberto","Miles Davis"]
["Astrud Gilberto","Miles Davis"]

Step 4: Apply rate-limiting policy

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: rl-by-minute
namespace: prod
config:
minute: 3
policy: local
plugin: rate-limiting
kubectl create -f https://raw.githubusercontent.com/Kong/aws-blogposts/master/K4K8S+AWSAppMesh/ratelimiting.yml
kubectl patch ingress djingress -n prod -p '{"metadata":{"annotations":{"konghq.com/plugins":"rl-by-minute"}}}'
while [ 1 ] 
do curl {your ingress address}/dj/jazz/
echo
done
["Astrud Gilberto","Miles Davis"]
["Astrud Gilberto","Miles Davis"]
["Astrud Gilberto","Miles Davis"]
{
"message":"API rate limit exceeded"
}

Step 5: Define the API key security policy

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: apikey
namespace: prod
plugin: key-auth
kubectl create -f https://raw.githubusercontent.com/Kong/aws-blogposts/master/K4K8S+AWSAppMesh/apikey.yml
kubectl patch ingress djingress -n prod -p '{"metadata":{"annotations":{"konghq.com/plugins":"apikey, rl-by-minute"}}}'
curl {your ingress address}/dj/jazz
{
"message":"No API key found in request"
}
kubectl create secret generic consumerapikey -n prod --from-literal=kongCredType=key-auth --from-literal=key=kong-secret
apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
name: consumer1
namespace: prod
annotations:
kubernetes.io/ingress.class: kong
username: consumer1
credentials:
- consumerapikey
kubectl apply -f https://raw.githubusercontent.com/Kong/aws-blogposts/master/K4K8S+AWSAppMesh/consumer.yml
curl {your ingress address}/dj/jazz -H 'apikey:kong-secret'
["Astrud Gilberto","Miles Davis"]

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store