ACK - AWS Controller for Kubernetes

使用ACK(AWS Controller for Kubernetes)可以直接在k8s内部配置API Gateway和DynamoDB等AWS资源,不需要再从外部创建。

我们将使用ACK创建以下架构,使用internal ALB暴露应用,这个应用使用DynamoDB作为存储(由ACK DynamoDB controller创建),使用API Gateway提供对外访问(由ACK API Gateway controller创建):

img

除了API Gateway和DynamoDB外,当然还有其他 ACK controllers。

cd terraform-aws-eks-ack-addons/examples/complete
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws
terraform init
terraform plan
terraform apply -auto-approve -var aws_region=<aws_region> #defaults to us-west-2

Once done, you’ll get the outputs similar to the following diagram. You need to modify your deployment yaml files with those output values in the following steps.

img

Configure kubeconfig

Use the configure_kubectl output from the Terraform output to configure your kubectl access from your workstation.

region=<your region> # set region variable for following commands
aws eks --region $region update-kubeconfig --name ack-eks-complete

Verify cluster access

Ensure kubectl access is configured correctly.

kubectl get nodes

Deploy the sample application

The sample application is a simple NodeJS API application that has two API methods. The post /rows/add method takes input payload and saves it to DynamoDB. The get /rows/all method fetches all the data from the DynamoDB table and returns to frontend. The sample application relies on the IAM role created by Amazon EKS Blueprints above to access DynamoDB.

Modify app.yaml before deployment:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-api-dynamodb
  namespace: ack-demo
....

    env:
    - name: aws_region
        value: "<same region as your eks cluster>" # replace with your region 
kubectl apply -f sample-app/app.yaml

Verify the deployment is successful:

kubectl get pods -n ack-demo

img

The deployment script exposes the API application through an internal ALB. Use the script below to get the ALB listener arn:

aws elbv2 describe-listeners \
  --region $region \
  --load-balancer-arn $(aws elbv2 describe-load-balancers \
  --region $region \
  --query “LoadBalancers[?contains(DNSName, ‘$(kubectl get ingress ingress-api-dynamodb -n ack-demo -o=jsonpath=”{.status.loadBalancer.ingress[].hostname}”)’)].LoadBalancerArn” \
  --output text) \
  --query “Listeners[0].ListenerArn” \
  --output text

img

Deploy API gateway resources

The ACK controller for API Gateway and the VPClink, which is required for connecting API Gateway with internal ALB, have been created by the Amazon EKS Blueprints.

Update <em>apigwv2-httpapi.yaml</em> before deploy:

apiVersion: apigatewayv2.services.k8s.aws/v1alpha1
kind: Integration
metadata:
  name: "vpc-integration"
spec:
  apiRef:
    from:
      name: "ack-api"
  integrationType: HTTP_PROXY
  integrationURI: "<your ALB listener arn>" # replace
  integrationMethod: ANY
  payloadFormatVersion: "1.0"
  connectionID: "<your vpclink id>" # api_gatewayv2_vpc_link_id in terraform output
  connectionType: "VPC_LINK"
  
kubectl apply -f sample-app/apigwv2-httpapi.yaml

Verify API Gateway is deployed via the AWS CLI:

aws apigatewayv2 get-apis --region $region

img

Next, let’s verify the integration with ALB was created successfully:

aws apigatewayv2 get-integrations --api-id <insert-api-id> --region $region

img

Deploy DynamoDB table

apiVersion: dynamodb.services.k8s.aws/v1alpha1
kind: Table
metadata:
  name: ack-demo
  namespace: ack-demo
spec:
  keySchema:
    - attributeName: Id
      keyType: HASH
  attributeDefinitions:
    - attributeName: Id
      attributeType: 'S'
  provisionedThroughput:
    readCapacityUnits: 1
    writeCapacityUnits: 1
  tableName: "ack-demo-table"

Deploy the DynamoDB table and verify it was created successfully:

kubectl apply -f sample-app/dynamodb-table.yaml
aws dynamodb list-tables --region $region

img

Test API methods

Now, you have deployed all the components for your API methods. Let’s use the following script to get the API gateway endpoint and test:

URL=$(kubectl get -n ack-demo api ack-api -o jsonpath="{.status.apiEndpoint}") 

We first test the post method with curl:

curl -X POST $URL/rows/add -H 'Content-Type: application/json' -d '{"name": "external"}'

Response: 
{"success":true} 

Then test get method <your api gateway endpoint>/rows/all. Since we only posted one record, you only see one record returned for now.

curl $URL/rows/all

Response:
["external"]

Cleaning up

kubectl delete -f sample-app/.

### Please wait a couple of minutes for ACK deleting resources before running code below
terraform destroy -target="module.eks_ack_addons" -target="module.eks_blueprints_kubernetes_addons" -auto-approve -var aws_region=$region
terraform destroy -target="module.eks_blueprints" -auto-approve -var aws_region=$region
terraform destroy -auto-approve -var aws_region=$region

Conclusion

In this post, we showed how to deploy microservices API application to your Amazon EKS cluster only using Kubernetes API and commands. The AWS Controller for Kubernetes allows you to manage Amazon API Gateway and DynamoDB in the same way you manage Kubernetes resources (e.g., pods, deployments, services, ingresses, and so on). Amazon EKS Blueprints automates the Amazon EKS cluster provision and ACK controller installation.

With ACK, you can create and manage more AWS services like Amazon RDS, Amazon S3, AWS Lambda, and others from your Amazon EKS cluster. Please refer to this link for the supported service list. Amazon EKS Blueprints for Terraform can be used to provision many other Kubernetes add-ons. Please refer to this link for the add-ons list.