Creating AWS Elasticache Instances manually using kubectl (experimental)
This topic describes how to use Services Toolkit to allow Tanzu Application Platform workloads to consume AWS Elasticache for Redis. This particular topic makes use of AWS Controller for Kubernetes (ACK) to manage AWS Elasticache resources.
Following this guide, you will be creating all the resources in the service-instances
namespace. It's important to make sure it exists before reading on.
Create a cache subnet group¶
The Elasticache instances must be created in a Cache Subnet Group, that can be created in a number of ways, here you will leverage ACK to create it.
First of all, you have to get the IDs of the subnets you want to build the Cache Subnet Group for.
Example
You could have a list of all the subnets in a given VPC and then choose amongst them.
VPC_NAME="my-vpc-name"
VPC_ID=$(aws ec2 describe-vpcs --filter "Name=tag:Name,Values=${VPC_NAME}" --query "Vpcs[0].VpcId" --output text)
SUBNET_IDS=$(aws ec2 describe-subnets --filters "Name=vpc-id,Values=${VPC_ID}" --query "Subnets[].SubnetId")
This is just an example. Make sure you do choose your subnets carefully.
When you have a list of subnetIDs stored in the SUBNET_IDS
shell variable, you can create your CacheSubnetGroup
. Create the following ytt
template
cache-subnet-group.ytt.yaml | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 |
|
Now you can use ytt
to add the proper values and pipe it to kubectl apply
CACHE_SUBNET_GROUP_NAME="ack-elasticache"
ytt \
-v cacheSubnetGroupName="${CACHE_SUBNET_GROUP_NAME}" \
-v subnetIDs="${SUBNET_IDS}" \
-f cache-subnet-group.ytt.yaml \
| kubectl apply -f -
Create the users to log into Elasticache¶
You need at least one usergroup with at least one member user to associate to the Elasticache instance. Every group must have one user with name default
and up to 100 total users (more on Elasticache quotas).
However, there can be only one user with id default
per Elasticache instance, which is automatically made available by AWS, but there can be more users with name default
and different id. This is useful to know in order to create proper default users for each group.
For the sake of this example, you will create just one user group and a default user in it with all the permissions. In order to generate a random password, you will make use of Secretgen Controller, which is provided out of the box by TAP, thus if you went through the prerequisites it should have already been installed.
The following snippet declares the default user along with its auto-generated password and the usergroup:
elasticache-user.yaml | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Store it into the elasticache-user.yaml
file and apply it:
kubectl apply -f elasticache-user.yaml
Create the ReplicationGroup¶
Before going ahead and create the ReplicationGroup
resource, which maps to the actual instance that can be consumed, you need to create a proper security group for filtering the incoming and outgoing traffic.
Assuming that you want to be able to connect to Elasticache from the EKS instance created previously, you can use the EKS security group as source for the new security group which will actually filter the Elasticache traffic.
# AWS region you're operating in
export AWS_REGION="eu-west-1"
# EKS cluster name
CLUSTER_NAME="my-eks-cluster"
EKS_SECURITY_GROUP_ID=$(aws eks describe-cluster --name ${CLUSTER_NAME} --query 'cluster.resourcesVpcConfig.clusterSecurityGroupId' --output text)
# VPC_ID has been defined above in "Create a cache subnet group"
ELASTICACHE_SECURITY_GROUP_ID=$(aws ec2 create-security-group --group-name "Elasticache" --description "Elasticache security group" --vpc-id ${VPC_ID} --output text --query GroupId)
REDIS_PORT=6379
aws ec2 authorize-security-group-ingress --group-id ${ELASTICACHE_SECURITY_GROUP_ID} --source-group ${EKS_SECURITY_GROUP_ID} --protocol tcp --port ${REDIS_PORT}
Now you can define the ReplicationGroup
using the following ytt
template
replication-group.ytt.yaml | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
and apply it
ytt \
-v cacheSubnetGroupName="${CACHE_SUBNET_GROUP_NAME}" \
-v securityGroupID="${ELASTICACHE_SECURITY_GROUP_ID}" \
-f replication-group.ytt.yaml \
| kubectl apply -f -
It will take 5 to 10 minutes to create. You can wait for the resource to be ready running the command
kubectl -n service-instances wait --for=condition=ACK.ResourceSynced=True replicationgroups.elasticache.services.k8s.aws ack-elasticache
or you can take a closer look at the new resource
kubectl -n service-instances get replicationgroups.elasticache.services.k8s.aws ack-elasticache -o yaml
particularly at the status
field, which eventually will display something like
status:
...
conditions:
- status: "True"
type: ACK.ResourceSynced
...
status: available
The status object also contains the details of the provisioned AWS resource, along with the nodegroups and their endpoints.
Create a Binding Specification Compatible Secret¶
As mentioned in Creating service instances that are compatible with Tanzu Application Platform, in order for Tanzu Application Platform workloads to be able to claim and bind to services such as AWS Elasticache, a resource compatible with Service Binding Specification must exist in the cluster. This can take the form of either a ProvisionedService
, as defined by the specification, or a Kubernetes Secret
with some known keys, also as defined in the specification.
In this guide, you create a Kubernetes secret in the necessary format using the secretgen-controller tooling. You do so by using the SecretTemplate
API to extract values from the ACK resources and populate a new spec-compatible secret with the values.
Create a ServiceAccount for Secret Templating¶
As part of using the SecretTemplate
API, a Kubernetes ServiceAccount
must be provided. The ServiceAccount
is used for reading the ReplicationGroup
resource and the Secret
created from the Password
resource above.
Create the following Kubernetes resources on your EKS cluster:
rbac.yaml | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
|
kubectl apply -f rbac.yaml
Create a SecretTemplate¶
In combination with the ServiceAccount
just created, a SecretTemplate
can be used to declaratively create a secret that is compatible with the service binding specification. For more information on this API see the Secret Template Documentation.
Create the following Kubernetes resource on your EKS cluster:
secrettemplate.yaml | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
kubectl apply -f secrettemplate.yaml
Verify the Service Instance¶
Wait until the ReplicationGroup
instance is ready as described before.
Next, ensure a bindable Secret
was produced by the SecretTemplate
. To do so, run:
kubectl -n service-instances wait --for=condition=ReconcileSucceeded=True secrettemplates.secretgen.carvel.dev ack-elasticache-default-creds-bindable
kubectl -n service-instances get secret ack-elasticache-default-creds-bindable