Google Cloud Anthos Series: Anthos Multi-cloud & Hybrid story

Google Cloud Anthos Series (Deploy Anthos on AWS) : Part 9

Anchit Nishant
Google Cloud - Community
10 min readApr 4, 2022

--

Welcome to Part-9 of the ‘Google Cloud Anthos series’. You can find the complete series Here.

With Anthos clusters, you can deploy workloads to multiple clouds with a unified management, signaling, and configuration control plane.

In this example we will deploy a Kubernetes cluster on AWS through Anthos.

Install and configure the below components as a prerequisite:

AWS cli
GCloud cli
jq
Kubectl

The AWS region we will use here is us-west-2
The GCP region we will use here is us-west1

Set up some environment variables

PROJECT_ID="<your-gcp-project-id>"AWS_REGION="us-west-2"GCP_REGION="us-west1"gcloud components update

Enable the below APIs

gcloud services enable gkemulticloud.googleapis.com
gcloud services enable gkeconnect.googleapis.com
gcloud services enable connectgateway.googleapis.com
gcloud services enable cloudresourcemanager.googleapis.com
gcloud services enable anthos.googleapis.com
gcloud services enable logging.googleapis.com
gcloud services enable monitoring.googleapis.com

Let us create a VPC in AWS with Public and Private Subnets in different AZs.

aws --region $AWS_REGION ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc, Tags=[{Key=Name,Value=anthosAWSVPC}]'
VPC_ID=$(aws ec2 describe-vpcs \
--filters 'Name=tag:Name,Values=anthosAWSVPC' \
--query "Vpcs[].VpcId" --output text)
aws ec2 modify-vpc-attribute --enable-dns-hostnames --vpc-id $VPC_ID
aws ec2 modify-vpc-attribute --enable-dns-support --vpc-id $VPC_ID

Create Private and Public Subnets

aws ec2 create-subnet \
--availability-zone us-west-2a \
--vpc-id $VPC_ID \
--cidr-block 10.0.1.0/24 \
--tag-specifications 'ResourceType=subnet, Tags=[{Key=Name,Value=anthosAWSPrivateSubnet1}]'
aws ec2 create-subnet \
--availability-zone us-west-2b \
--vpc-id $VPC_ID \
--cidr-block 10.0.2.0/24 \
--tag-specifications 'ResourceType=subnet, Tags=[{Key=Name,Value=anthosAWSPrivateSubnet2}]'
aws ec2 create-subnet \
--availability-zone us-west-2c \
--vpc-id $VPC_ID \
--cidr-block 10.0.3.0/24 \
--tag-specifications 'ResourceType=subnet, Tags=[{Key=Name,Value=anthosAWSPrivateSubnet3}]'
aws ec2 create-subnet \
--availability-zone us-west-2a \
--vpc-id $VPC_ID \
--cidr-block 10.0.101.0/24 \
--tag-specifications 'ResourceType=subnet, Tags=[{Key=Name,Value=anthosAWSPublicSubnet1}]'
aws ec2 create-subnet \
--availability-zone us-west-2b \
--vpc-id $VPC_ID \
--cidr-block 10.0.102.0/24 \
--tag-specifications 'ResourceType=subnet, Tags=[{Key=Name,Value=anthosAWSPublicSubnet2}]'
aws ec2 create-subnet \
--availability-zone us-west-2c \
--vpc-id $VPC_ID \
--cidr-block 10.0.103.0/24 \
--tag-specifications 'ResourceType=subnet, Tags=[{Key=Name,Value=anthosAWSPublicSubnet3}]'

Mark Subnets as public

PUBLIC_SUBNET_ID_1=$(aws ec2 describe-subnets \
--filters 'Name=tag:Name,Values=anthosAWSPublicSubnet1' \
--query "Subnets[].SubnetId" --output text)
PUBLIC_SUBNET_ID_2=$(aws ec2 describe-subnets \
--filters 'Name=tag:Name,Values=anthosAWSPublicSubnet2' \
--query "Subnets[].SubnetId" --output text)
PUBLIC_SUBNET_ID_3=$(aws ec2 describe-subnets \
--filters 'Name=tag:Name,Values=anthosAWSPublicSubnet3' \
--query "Subnets[].SubnetId" --output text)
aws ec2 modify-subnet-attribute \
--map-public-ip-on-launch \
--subnet-id $PUBLIC_SUBNET_ID_1
aws ec2 modify-subnet-attribute \
--map-public-ip-on-launch \
--subnet-id $PUBLIC_SUBNET_ID_2
aws ec2 modify-subnet-attribute \
--map-public-ip-on-launch \
--subnet-id $PUBLIC_SUBNET_ID_3

Create Internet Gateway

aws --region $AWS_REGION  ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway, Tags=[{Key=Name,Value=anthosAWSInternetGateway}]'
INTERNET_GW_ID=$(aws ec2 describe-internet-gateways \
--filters 'Name=tag:Name,Values=anthosAWSInternetGateway' \
--query "InternetGateways[].InternetGatewayId" --output text)
aws ec2 attach-internet-gateway \
--internet-gateway-id $INTERNET_GW_ID \
--vpc-id $VPC_ID

Configure Route Tables for Public Subnets

aws ec2 create-route-table --vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table, Tags=[{Key=Name,Value=anthosAWSPublicRouteTbl1}]'
aws ec2 create-route-table --vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table, Tags=[{Key=Name,Value=anthosAWSPublicRouteTbl2}]'
aws ec2 create-route-table --vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table, Tags=[{Key=Name,Value=anthosAWSPublicRouteTbl3}]'
PUBLIC_ROUTE_TABLE_ID_1=$(aws ec2 describe-route-tables \
--filters 'Name=tag:Name,Values=anthosAWSPublicRouteTbl1' \
--query "RouteTables[].RouteTableId" --output text)
PUBLIC_ROUTE_TABLE_ID_2=$(aws ec2 describe-route-tables \
--filters 'Name=tag:Name,Values=anthosAWSPublicRouteTbl2' \
--query "RouteTables[].RouteTableId" --output text)
PUBLIC_ROUTE_TABLE_ID_3=$(aws ec2 describe-route-tables \
--filters 'Name=tag:Name,Values=anthosAWSPublicRouteTbl3' \
--query "RouteTables[].RouteTableId" --output text)
aws ec2 associate-route-table \
--route-table-id $PUBLIC_ROUTE_TABLE_ID_1 \
--subnet-id $PUBLIC_SUBNET_ID_1
aws ec2 associate-route-table \
--route-table-id $PUBLIC_ROUTE_TABLE_ID_2 \
--subnet-id $PUBLIC_SUBNET_ID_2
aws ec2 associate-route-table \
--route-table-id $PUBLIC_ROUTE_TABLE_ID_3 \
--subnet-id $PUBLIC_SUBNET_ID_3
aws ec2 create-route --route-table-id $PUBLIC_ROUTE_TABLE_ID_1 \
--destination-cidr-block 0.0.0.0/0 --gateway-id $INTERNET_GW_ID
aws ec2 create-route --route-table-id $PUBLIC_ROUTE_TABLE_ID_2 \
--destination-cidr-block 0.0.0.0/0 --gateway-id $INTERNET_GW_ID
aws ec2 create-route --route-table-id $PUBLIC_ROUTE_TABLE_ID_3 \
--destination-cidr-block 0.0.0.0/0 --gateway-id $INTERNET_GW_ID
aws ec2 allocate-address \
--tag-specifications 'ResourceType=elastic-ip, Tags=[{Key=Name,Value=anthosAWSNatEip1}]'
aws ec2 allocate-address \
--tag-specifications 'ResourceType=elastic-ip, Tags=[{Key=Name,Value=anthosAWSNatEip2}]'
aws ec2 allocate-address \
--tag-specifications 'ResourceType=elastic-ip, Tags=[{Key=Name,Value=anthosAWSNatEip3}]'

Create NAT gateway

NAT_EIP_ALLOCATION_ID_1=$(aws ec2 describe-addresses \
--filters 'Name=tag:Name,Values=anthosAWSNatEip1' \
--query "Addresses[].AllocationId" --output text)
NAT_EIP_ALLOCATION_ID_2=$(aws ec2 describe-addresses \
--filters 'Name=tag:Name,Values=anthosAWSNatEip2' \
--query "Addresses[].AllocationId" --output text)
NAT_EIP_ALLOCATION_ID_3=$(aws ec2 describe-addresses \
--filters 'Name=tag:Name,Values=anthosAWSNatEip3' \
--query "Addresses[].AllocationId" --output text)
aws ec2 create-nat-gateway \
--allocation-id $NAT_EIP_ALLOCATION_ID_1 \
--subnet-id $PUBLIC_SUBNET_ID_1 \
--tag-specifications 'ResourceType=natgateway, Tags=[{Key=Name,Value=anthosAWSNatGateway1}]'
aws ec2 create-nat-gateway \
--allocation-id $NAT_EIP_ALLOCATION_ID_2 \
--subnet-id $PUBLIC_SUBNET_ID_2 \
--tag-specifications 'ResourceType=natgateway, Tags=[{Key=Name,Value=anthosAWSNatGateway2}]'
aws ec2 create-nat-gateway \
--allocation-id $NAT_EIP_ALLOCATION_ID_3 \
--subnet-id $PUBLIC_SUBNET_ID_3 \
--tag-specifications 'ResourceType=natgateway, Tags=[{Key=Name,Value=anthosAWSNatGateway3}]'

Configure route table for Private Subnets

aws ec2 create-route-table --vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table, Tags=[{Key=Name,Value=anthosAWSPrivateRouteTbl1}]'
aws ec2 create-route-table --vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table, Tags=[{Key=Name,Value=anthosAWSPrivateRouteTbl2}]'
aws ec2 create-route-table --vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table, Tags=[{Key=Name,Value=anthosAWSPrivateRouteTbl3}]'
PRIVATE_SUBNET_ID_1=$(aws ec2 describe-subnets \
--filters 'Name=tag:Name,Values=anthosAWSPrivateSubnet1' \
--query "Subnets[].SubnetId" --output text)
PRIVATE_SUBNET_ID_2=$(aws ec2 describe-subnets \
--filters 'Name=tag:Name,Values=anthosAWSPrivateSubnet2' \
--query "Subnets[].SubnetId" --output text)
PRIVATE_SUBNET_ID_3=$(aws ec2 describe-subnets \
--filters 'Name=tag:Name,Values=anthosAWSPrivateSubnet3' \
--query "Subnets[].SubnetId" --output text)
PRIVATE_ROUTE_TABLE_ID_1=$(aws ec2 describe-route-tables \
--filters 'Name=tag:Name,Values=anthosAWSPrivateRouteTbl1' \
--query "RouteTables[].RouteTableId" --output text)
PRIVATE_ROUTE_TABLE_ID_2=$(aws ec2 describe-route-tables \
--filters 'Name=tag:Name,Values=anthosAWSPrivateRouteTbl2' \
--query "RouteTables[].RouteTableId" --output text)
PRIVATE_ROUTE_TABLE_ID_3=$(aws ec2 describe-route-tables \
--filters 'Name=tag:Name,Values=anthosAWSPrivateRouteTbl3' \
--query "RouteTables[].RouteTableId" --output text)
aws ec2 associate-route-table --route-table-id $PRIVATE_ROUTE_TABLE_ID_1 \
--subnet-id $PRIVATE_SUBNET_ID_1
aws ec2 associate-route-table --route-table-id $PRIVATE_ROUTE_TABLE_ID_2 \
--subnet-id $PRIVATE_SUBNET_ID_2
aws ec2 associate-route-table --route-table-id $PRIVATE_ROUTE_TABLE_ID_3 \
--subnet-id $PRIVATE_SUBNET_ID_3
NAT_GW_ID_1=$(aws ec2 describe-nat-gateways \
--filter 'Name=tag:Name,Values=anthosAWSNatGateway1' \
--query "NatGateways[].NatGatewayId" --output text)
NAT_GW_ID_2=$(aws ec2 describe-nat-gateways \
--filter 'Name=tag:Name,Values=anthosAWSNatGateway2' \
--query "NatGateways[].NatGatewayId" --output text)
NAT_GW_ID_3=$(aws ec2 describe-nat-gateways \
--filter 'Name=tag:Name,Values=anthosAWSNatGateway3' \
--query "NatGateways[].NatGatewayId" --output text)
aws ec2 create-route --route-table-id $PRIVATE_ROUTE_TABLE_ID_1 \
--destination-cidr-block 0.0.0.0/0 --gateway-id $NAT_GW_ID_1
aws ec2 create-route --route-table-id $PRIVATE_ROUTE_TABLE_ID_2 \
--destination-cidr-block 0.0.0.0/0 --gateway-id $NAT_GW_ID_2
aws ec2 create-route --route-table-id $PRIVATE_ROUTE_TABLE_ID_3 \
--destination-cidr-block 0.0.0.0/0 --gateway-id $NAT_GW_ID_3

Tag Subnets for Load balancers

aws ec2 create-tags \
--resources $PUBLIC_SUBNET_ID_1 \
--tags Key=kubernetes.io/role/elb,Value=1
aws ec2 create-tags \
--resources $PUBLIC_SUBNET_ID_2 \
--tags Key=kubernetes.io/role/elb,Value=1
aws ec2 create-tags \
--resources $PUBLIC_SUBNET_ID_3 \
--tags Key=kubernetes.io/role/elb,Value=1
aws ec2 create-tags \
--resources $PRIVATE_SUBNET_ID_1 \
--tags Key=kubernetes.io/role/internal-elb,Value=1
aws ec2 create-tags \
--resources $PRIVATE_SUBNET_ID_2 \
--tags Key=kubernetes.io/role/internal-elb,Value=1
aws ec2 create-tags \
--resources $PRIVATE_SUBNET_ID_3 \
--tags Key=kubernetes.io/role/internal-elb,Value=1

Create KMS Key in AWS

AWS_KMS_DATA=$(aws --region $AWS_REGION kms create-key \
--description "kms_key")
AWS_KMS_ARN=$(echo $AWS_KMS_DATA | jq .KeyMetadata.Arn -r)

Create IAM policies and roles

PROJECT_ID="$(gcloud config get-value project)"PROJECT_NUMBER=$(gcloud projects describe "$PROJECT_ID" \
--format "value(projectNumber)")

aws iam create-role --role-name ANTHOS_API_ROLE \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Federated": "accounts.google.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"accounts.google.com:sub": "service-'$PROJECT_NUMBER'@gcp-sa-gkemulticloud.iam.gserviceaccount.com"
}
}
}
]
}'
ANTHOS_API_ROLE_ARN=$(aws iam get-role --role-name "ANTHOS_API_ROLE" --query "Role.Arn" --output text)aws iam create-policy --policy-name ANTHOS_API_POLICY \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:DescribeKey",
"iam:CreateServiceLinkedRole",
"iam:PassRole",
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeListeners",
"elasticloadbalancing:DeleteTargetGroup",
"elasticloadbalancing:DeleteLoadBalancer",
"elasticloadbalancing:DeleteListener",
"elasticloadbalancing:CreateTargetGroup",
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:AddTags",
"elasticloadbalancing:ModifyTargetGroupAttributes",
"ec2:ModifyNetworkInterfaceAttribute",
"ec2:DescribeAccountAttributes",
"ec2:DescribeInternetGateways",
"ec2:RunInstances",
"ec2:RevokeSecurityGroupIngress",
"ec2:RevokeSecurityGroupEgress",
"ec2:DescribeVpcs",
"ec2:DescribeVolumes",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeLaunchTemplates",
"ec2:DescribeKeyPairs",
"ec2:DeleteVolume",
"ec2:DeleteTags",
"ec2:DeleteSecurityGroup",
"ec2:DeleteNetworkInterface",
"ec2:DeleteLaunchTemplate",
"ec2:CreateVolume",
"ec2:CreateTags",
"ec2:CreateSecurityGroup",
"ec2:CreateNetworkInterface",
"ec2:CreateLaunchTemplate",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:AuthorizeSecurityGroupEgress",
"autoscaling:UpdateAutoScalingGroup",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DeleteTags",
"autoscaling:DeleteAutoScalingGroup",
"autoscaling:CreateOrUpdateTags",
"autoscaling:CreateAutoScalingGroup"
],
"Resource": "*"
}
]
}'
ANTHOS_API_POLICY_ARN=arn:aws:iam::$(aws sts get-caller-identity | jq .Account -r):policy/ANTHOS_API_POLICYaws iam attach-role-policy \
--policy-arn $ANTHOS_API_POLICY_ARN \
--role-name ANTHOS_API_ROLE
aws iam create-role --role-name ANTHOS_CONTROL_PLANE_ROLE \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
aws iam create-policy --policy-name ANTHOS_CONTROL_PLANE_POLICY \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:Decrypt"
],
"Resource": "'"$AWS_KMS_ARN"'"
},
{
"Sid": "",
"Effect": "Allow",
"Action": [
"iam:CreateServiceLinkedRole",
"elasticloadbalancing:SetLoadBalancerPoliciesOfListener",
"elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"elasticloadbalancing:ModifyTargetGroup",
"elasticloadbalancing:ModifyLoadBalancerAttributes",
"elasticloadbalancing:ModifyListener",
"elasticloadbalancing:DetachLoadBalancerFromSubnets",
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeLoadBalancerPolicies",
"elasticloadbalancing:DescribeLoadBalancerAttributes",
"elasticloadbalancing:DescribeListeners",
"elasticloadbalancing:DeregisterTargets",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:DeleteTargetGroup",
"elasticloadbalancing:DeleteLoadBalancerListeners",
"elasticloadbalancing:DeleteLoadBalancer",
"elasticloadbalancing:DeleteListener",
"elasticloadbalancing:CreateTargetGroup",
"elasticloadbalancing:CreateLoadBalancerPolicy",
"elasticloadbalancing:CreateLoadBalancerListeners",
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:ConfigureHealthCheck",
"elasticloadbalancing:AttachLoadBalancerToSubnets",
"elasticloadbalancing:ApplySecurityGroupsToLoadBalancer",
"elasticloadbalancing:AddTags",
"ec2:RevokeSecurityGroupIngress",
"ec2:ModifyVolume",
"ec2:ModifyInstanceAttribute",
"ec2:DetachVolume",
"ec2:DescribeDhcpOptions",
"ec2:DescribeVpcs",
"ec2:DescribeVolumesModifications",
"ec2:DescribeVolumes",
"ec2:DescribeTags",
"ec2:DescribeSubnets",
"ec2:DescribeSnapshots",
"ec2:DescribeSecurityGroups",
"ec2:DescribeRouteTables",
"ec2:DescribeRegions",
"ec2:DescribeLaunchTemplateVersions",
"ec2:DescribeInstances",
"ec2:DeleteVolume",
"ec2:DeleteTags",
"ec2:DeleteSnapshot",
"ec2:DeleteSecurityGroup",
"ec2:DeleteRoute",
"ec2:CreateVolume",
"ec2:CreateTags",
"ec2:CreateSnapshot",
"ec2:CreateSecurityGroup",
"ec2:CreateRoute",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:AttachVolume",
"ec2:AttachNetworkInterface",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"autoscaling:SetDesiredCapacity",
"autoscaling:DescribeTags",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:DescribeAutoScalingGroups"
],
"Resource": "*"
}
]
}'
ANTHOS_CONTROL_PLANE_POLICY_ARN=arn:aws:iam::$(aws sts get-caller-identity | jq .Account -r):policy/ANTHOS_CONTROL_PLANE_POLICYaws iam attach-role-policy \
--policy-arn $ANTHOS_CONTROL_PLANE_POLICY_ARN \
--role-name ANTHOS_CONTROL_PLANE_ROLE
aws iam create-instance-profile \
--instance-profile-name ANTHOS_CONTROL_PLANE_PROFILE
aws iam add-role-to-instance-profile \
--instance-profile-name ANTHOS_CONTROL_PLANE_PROFILE \
--role-name ANTHOS_CONTROL_PLANE_ROLE
aws iam create-role --role-name ANTHOS_NODE_POOL_ROLE \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
aws iam create-policy \
--policy-name ANTHOS_NODE_POOL_POLICY \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:Decrypt"
],
"Resource": "'"$AWS_KMS_ARN"'"
},
{
"Sid": "",
"Effect": "Allow",
"Action": [
"autoscaling:DescribeAutoScalingGroups",
"ec2:AttachNetworkInterface",
"ec2:DescribeInstances",
"ec2:DescribeTags"
],
"Resource": "*"
}
]
}'
ANTHOS_NODE_POOL_POLICY_ARN=arn:aws:iam::$(aws sts get-caller-identity | jq .Account -r):policy/ANTHOS_NODE_POOL_POLICYaws iam attach-role-policy --role-name ANTHOS_NODE_POOL_ROLE \
--policy-arn $ANTHOS_NODE_POOL_POLICY_ARN
aws iam create-instance-profile \
--instance-profile-name ANTHOS_NODE_POOL_PROFILE
aws iam add-role-to-instance-profile \
--instance-profile-name ANTHOS_NODE_POOL_PROFILE \
--role-name ANTHOS_NODE_POOL_ROLE

Create an EC2 key pair

ssh-keygen -t rsa -m PEM -b 4096 -C "$USER" \
-f SSH_PRIVATE_KEY -N "" 1>/dev/null

aws ec2 import-key-pair --key-name ANTHOS_SSH_KEY_PAIR \
--public-key-material fileb://SSH_PRIVATE_KEY.pub

Anthos deployment

gcloud config set container_aws/location $AWS_REGION

Create a Cluster

gcloud container aws clusters create aws-cluster-0 \
--cluster-version 1.21.6-gke.1500 \
--aws-region $AWS_REGION \
--fleet-project $PROJECT_ID \
--vpc-id $VPC_ID \
--subnet-ids $PRIVATE_SUBNET_ID_1,$PRIVATE_SUBNET_ID_2,$PRIVATE_SUBNET_ID_3 \
--pod-address-cidr-blocks 172.31.0.0/20 \
--service-address-cidr-blocks 172.31.32.0/20 \
--role-arn $ANTHOS_API_ROLE_ARN \
--iam-instance-profile ANTHOS_CONTROL_PLANE_PROFILE \
--database-encryption-kms-key-arn $AWS_KMS_ARN \
--config-encryption-kms-key-arn $AWS_KMS_ARN \
--tags "google:gkemulticloud:cluster=aws-cluster-0" \
--location $GCP_REGION

Create a node pool

gcloud container aws node-pools create pool-0 \
--cluster aws-cluster-0 \
--node-version 1.21.6-gke.1500 \
--min-nodes 1 \
--max-nodes 5 \
--max-pods-per-node 110 \
--root-volume-size 50 \
--subnet-id $PRIVATE_SUBNET_ID_1 \
--iam-instance-profile ANTHOS_NODE_POOL_PROFILE \
--config-encryption-kms-key-arn $AWS_KMS_ARN \
--ssh-ec2-key-pair ANTHOS_SSH_KEY_PAIR \
--tags "google:gkemulticloud:cluster=aws-cluster-0" \
--location $GCP_REGION

Get Authentication credentials for your cluster

gcloud container aws clusters get-credentials aws-cluster-0 --location $GCP_REGION

Clone the Online Boutique repository.

git clone https://github.com/GoogleCloudPlatform/microservices-demo.git
cd microservices-demo

Deploy the Online Boutique application

kubectl apply -f ./release/kubernetes-manifests.yaml

Check your application through the AWS Load Balancer endpoint

kubectl get service frontend-external | awk '{print $4}'

Now that we have got the Anthos cluster deployed and registered, we can view it in the GCP console.

Login to the cluster

You can explore the Kubernetes engine UI and get all the information on the Cluster.

Since Anthos uses AWS EC2 for its Control plane and Nodes, you can view them in the AWS console as well.

Let us install Anthos Service mesh to get a better visibility of microservices.

curl https://storage.googleapis.com/csm-artifacts/asm/asmcli_1.12 > asmclichmod +x asmcliKUBECONFIG_LOCATION=$(echo "$HOME/.kube/config")./asmcli install \
--fleet_id $PROJECT_ID \
--kubeconfig $KUBECONFIG_LOCATION \
--platform multicloud \
--enable_all \
--ca mesh_ca
kubectl -n istio-system get pods -l app=istiod --show-labelsREV=[rev-label]
kubectl label namespace default istio.io/rev=${REV} istio-injection- --overwrite
kubectl delete pod -n default --all
kubectl get pod -n default

You can check the Anthos Service Mesh dashboard which should list all the Services.

You can use the below commands to delete the cluster to avoid unwanted billing on EC2.

gcloud container aws node-pools delete pool-0 --cluster aws-cluster-0 --location $GCP_REGIONgcloud container aws clusters delete aws-cluster-0 --location $GCP_REGION

Contributors: Pushkar Kothavade, Shijimol A K, Dhandus

--

--