Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example for ingress gateway using App Mesh in k8s #299

Merged
merged 7 commits into from
Jun 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion walkthroughs/howto-k8s-grpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ You can use v1beta2 example manifest with [aws-app-mesh-controller-for-k8s](http
## Setup

```
1. Clone this repository and navigate to the walkthrough/howto-k8s-http2 folder, all commands will be ran from this location
1. Clone this repository and navigate to the walkthrough/howto-k8s-grpc folder, all commands will be ran from this location
1. **Your** account id:

export AWS_ACCOUNT_ID=<your_account_id>
Expand Down
2 changes: 1 addition & 1 deletion walkthroughs/howto-k8s-http-headers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ You can use v1beta2 example manifest with [aws-app-mesh-controller-for-k8s](http
```
## Setup

1. Clone this repository and navigate to the walkthrough/howto-k8s-cloudmap folder, all commands will be ran from this location
1. Clone this repository and navigate to the walkthrough/howto-k8s-http-headers folder, all commands will be ran from this location
2. **Your** account id:

export AWS_ACCOUNT_ID=<your_account_id>
Expand Down
1 change: 1 addition & 0 deletions walkthroughs/howto-k8s-ingress-gateway/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_output
118 changes: 118 additions & 0 deletions walkthroughs/howto-k8s-ingress-gateway/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Configuring Ingress Gateway

In this walkthrough, we'll configure an Ingress Gateway in our existing example color app but with a VirtualGateway resource instead of VirtualNode for ingress traffic.

A virtual gateway allows resources outside your mesh to communicate to resources that are inside your mesh. The virtual gateway represents an Envoy proxy running in an Amazon ECS, in a Kubernetes service, or on an Amazon EC2 instance. Unlike a virtual node, which represents a proxy running with an application, a virtual gateway represents the proxy deployed by itself.

## Prerequisites
This feature is currently only available in App Mesh preview and will work with App Mesh manager [here](https://github.com/aws/eks-charts/tree/master/stable/appmesh-manager)
fawadkhaliq marked this conversation as resolved.
Show resolved Hide resolved

This example requires [aws-app-mesh-controller-for-k8s](https://github.com/aws/aws-app-mesh-controller-for-k8s) version [>=v1.0.0](https://github.com/aws/aws-app-mesh-controller-for-k8s/blob/master/CHANGELOG.md). Run the following to check the version of controller you are running.
```
$ kubectl get deployment -n appmesh-system appmesh-manager -o json | jq -r ".spec.template.spec.containers[].image" | cut -f2 -d ':'|tail -n1
```

## Setup

1. Clone this repository and navigate to the walkthrough/howto-k8s-ingress-gateway folder, all commands will be ran from this location
2. **Your** account id:

export AWS_ACCOUNT_ID=<your_account_id>

3. **Region** e.g. us-west-2

export AWS_DEFAULT_REGION=us-west-2

4. **ENVOY_IMAGE** environment variable is set to App Mesh Envoy, see https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html

export ENVOY_IMAGE=...

5. Deploy
```.
./deploy.sh
```

## Use Ingress gateway

There are two GatewayRoutes setup in this example: 1) `gateway-route-headers` 2) `gateway-route-paths`.
`gateway-route-headers` will route traffic to VirtualService `color-headers` and `gateway-route-paths` will route traffic to VirtualService `color-paths`

VirtualService `color-headers` uses a VirtualRouter to match HTTP headers to choose the backend VirtualNode. VirtualService `color-paths` uses HTTP path prefixes to choose backend VirtualNode

Let's look at the VirtualGateway deployed:

```
kubectl get virtualgateway -n howto-k8s-ingress-gateway
NAME ARN AGE
ingress-gw arn:aws:appmesh-preview:us-west-2:112233333455:mesh/howto-k8s-ingress-gateway/virtualGateway/ingress-gw_howto-k8s-ingress-gateway 113s
```
fawadkhaliq marked this conversation as resolved.
Show resolved Hide resolved

The entry point for traffic will be an Envoy linked to the VirtualGateway `ingress-gw`:

```
kubectl get pod -n howto-k8s-ingress-gateway
NAME READY STATUS RESTARTS AGE
blue-574fc6f766-jtc76 2/2 Running 0 13s
green-5fdb4488cb-mtrsl 2/2 Running 0 13s
ingress-gw-c9c9b895-rqv9r 1/1 Running 0 13s
red-54b44b859b-jqmxx 2/2 Running 0 13s
white-85685c459b-rgj4f 2/2 Running 0 13s
yellow-67b88f8cf4-mtnhq 2/2 Running 0 13s
```

`ingress-gw-c9c9b895-rqv9r` is pointing to VirtualGateway and is accessible via LoadBalancer type k8s Service:

```
kubectl get svc -n howto-k8s-ingress-gateway
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
color-blue ClusterIP 10.100.10.91 <none> 8080/TCP 3m21s
color-green ClusterIP 10.100.81.185 <none> 8080/TCP 3m22s
color-headers ClusterIP 10.100.90.162 <none> 8080/TCP 3m21s
color-paths ClusterIP 10.100.49.62 <none> 8080/TCP 3m21s
color-red ClusterIP 10.100.247.202 <none> 8080/TCP 3m21s
color-white ClusterIP 10.100.5.232 <none> 8080/TCP 3m21s
color-yellow ClusterIP 10.100.151.20 <none> 8080/TCP 3m21s
ingress-gw LoadBalancer 10.100.177.113 a0b14c18c13114255ab46432fcb9e1f8-135255798.us-west-2.elb.amazonaws.com 80:30151/TCP 3m21s
```

Let's verify connectivity into the Mesh:

```
GW_ENDPOINT=$(kubectl get svc ingress-gw -n howto-k8s-ingress-gateway --output jsonpath='{.status.loadBalancer.ingress[0].hostname}')
```

Connect to VirtualNode red via VirtualService color-paths
```
curl ${GW_ENDPOINT}/paths/red ; echo;
red
```

Connect to VirtualNode blue via VirtualService color-paths
```
curl ${GW_ENDPOINT}/paths/blue ; echo;
blue
```

Connect to VirtualNode yellow via VirtualService color-paths
```
curl ${GW_ENDPOINT}/paths/yellow ; echo;
yellow
```

Connect to VirtualNode blue via VirtualService color-headers
```
curl -H "color_header: blue" ${GW_ENDPOINT}/headers ; echo;
blue
```

Connect to VirtualNode red via VirtualService color-headers
```
curl -H "color_header: red" ${GW_ENDPOINT}/headers ; echo;
red
```

## Cleanup

```
kubectl delete -f _output/manifest.yaml
```
6 changes: 6 additions & 0 deletions walkthroughs/howto-k8s-ingress-gateway/colorapp/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM python:3

COPY serve.py ./
RUN chmod +x ./serve.py

CMD ["python", "-u", "./serve.py"]
29 changes: 29 additions & 0 deletions walkthroughs/howto-k8s-ingress-gateway/colorapp/serve.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env python3

try:
import os
from http.server import BaseHTTPRequestHandler, HTTPServer
except Exception as e:
print(f'[ERROR] {e}')

COLOR = os.environ.get('COLOR', 'no color!')
print(f'COLOR is {COLOR}')

PORT = int(os.environ.get('PORT', '8080'))
print(f'PORT is {PORT}')

class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/ping':
self.send_response(200)
self.end_headers()
return

self.send_response(200)
self.end_headers()
self.wfile.write(bytes(COLOR, 'utf8'))

print('starting server...')
httpd = HTTPServer(('', PORT), Handler)
print('running server...')
httpd.serve_forever()
116 changes: 116 additions & 0 deletions walkthroughs/howto-k8s-ingress-gateway/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/bin/bash

set -eo pipefail

if [ -z $AWS_ACCOUNT_ID ]; then
echo "AWS_ACCOUNT_ID environment variable is not set."
exit 1
fi

if [ -z $AWS_DEFAULT_REGION ]; then
echo "AWS_DEFAULT_REGION environment variable is not set."
exit 1
fi

if [ -z $ENVOY_IMAGE ]; then
echo "ENVOY_IMAGE environment variable is not set to App Mesh Envoy, see https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html"
exit 1
fi

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
PROJECT_NAME="howto-k8s-ingress-gateway"
APP_NAMESPACE=${PROJECT_NAME}
MESH_NAME=${PROJECT_NAME}
APPMESH_PREVIEW="enabled"

ECR_IMAGE_PREFIX="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${PROJECT_NAME}"
COLOR_APP_IMAGE="${ECR_IMAGE_PREFIX}/colorapp"
MANIFEST_VERSION="${1:-v1beta2}"
AWS_CLI_VERSION=$(aws --version 2>&1 | cut -d/ -f2 | cut -d. -f1)

error() {
echo $1
exit 1
}

check_k8s_virtualgateway() {
#check CRD
crd=$(kubectl get crd virtualgateways.appmesh.k8s.aws -o json )
if [ -z "$crd" ]; then
error "$PROJECT_NAME requires virtualgateways.appmesh.k8s.aws CRD to support Ingress gateway. See https://github.com/aws/aws-app-mesh-controller-for-k8s/blob/master/CHANGELOG.md"
else
echo "CRD check passed!"
fi
}

check_k8s_gatewayroutes() {
#check CRD
crd=$(kubectl get crd gatewayroutes.appmesh.k8s.aws -o json )
if [ -z "$crd" ]; then
error "$PROJECT_NAME requires gatewayroutes.appmesh.k8s.aws CRD to support Ingress gateway. See https://github.com/aws/aws-app-mesh-controller-for-k8s/blob/master/CHANGELOG.md"
else
echo "CRD check passed!"
fi
}

check_appmesh_k8s() {
#check aws-app-mesh-controller version
if [ "$MANIFEST_VERSION" = "v1beta2" ]; then
currentver=$(kubectl get deployment -n appmesh-system appmesh-manager -o json | jq -r ".spec.template.spec.containers[].image" | cut -f2 -d ':'|tail -n1)
requiredver="v1.0.0"
check_k8s_virtualgateway
check_k8s_gatewayroutes
else
error "$PROJECT_NAME unexpected manifest version input: $MANIFEST_VERSION. Should be v1beta2 or v1beta1 based on the AppMesh controller version. See https://github.com/aws/aws-app-mesh-controller-for-k8s/blob/master/CHANGELOG.md"
fi

if [ "$(printf '%s\n' "$requiredver" "$currentver" | sort -V | head -n1)" = "$requiredver" ]; then
echo "aws-app-mesh-controller check passed! $currentver >= $requiredver"
else
error "$PROJECT_NAME requires aws-app-mesh-controller version >=$requiredver but found $currentver. See https://github.com/aws/aws-app-mesh-controller-for-k8s/blob/master/CHANGELOG.md"
fi
}

ecr_login() {
if [ $AWS_CLI_VERSION -eq 1 ]; then
$(aws ecr get-login --no-include-email)
elif [ $AWS_CLI_VERSION -eq 2 ]; then
aws ecr get-login-password | docker login --username AWS --password-stdin ${ECR_URL}
else
echo "Invalid AWS CLI version"
exit 1
fi
}

deploy_images() {
for app in colorapp; do
aws ecr describe-repositories --repository-name $PROJECT_NAME/$app >/dev/null 2>&1 || aws ecr create-repository --repository-name $PROJECT_NAME/$app
docker build -t ${ECR_IMAGE_PREFIX}/${app} ${DIR}/${app}
ecr_login
docker push ${ECR_IMAGE_PREFIX}/${app}
done
}

deploy_app() {
EXAMPLES_OUT_DIR="${DIR}/_output/"
mkdir -p ${EXAMPLES_OUT_DIR}
eval "cat <<EOF
$(<${DIR}/${MANIFEST_VERSION}/manifest.yaml.template)
EOF
" >${EXAMPLES_OUT_DIR}/manifest.yaml

kubectl apply -f ${EXAMPLES_OUT_DIR}/manifest.yaml
}

main() {
check_appmesh_k8s

if [ -z $SKIP_IMAGES ]; then
echo "deploy images..."
deploy_images
fi

deploy_app
}

main
Loading