Skip to content

Use Amazon Bedrock AgentCore capabilities from your existing EKS agents in a no-egress VPC (IRSA + PrivateLink)

8 minute read
Content level: Advanced
0

Privately reach Amazon Bedrock AgentCore (Runtime and Memory) from a self-hosted EKS agent authenticated with IRSA/SigV4, inside a no-egress VPC. Covers the AWS STS interface endpoint and regional STS configuration, the AgentCore data-plane and control-plane interface VPC endpoints, endpoint policies, and the IAM trust policy.

Overview

Regulated environments often run Amazon EKS in a fully private VPC: no internet gateway, no NAT gateway, egress only through AWS PrivateLink interface endpoints.

Scope: this guide covers a custom agent running on your own EKS pods (self-hosted, authenticated with IRSA / SigV4) that consumes Amazon Bedrock AgentCore capabilities — Runtime and Memory — over PrivateLink. It is not about the managed AgentCore Runtime hosting model.

Out of scope (separate paths): OAuth / Bearer-Token inbound auth (this guide assumes SigV4 via IRSA), AgentCore Gateway (a follow-up article will cover Gateway inbound access and target egress), the Browser Tool (needs internet/NAT for public web browsing — incompatible with a strict no-egress design), and AgentCore Evaluations/Optimizations and Policy. Those are configured the same PrivateLink way but are not covered here.

AgentCore is composable. Its primitives are independently consumable — you can use Memory without Runtime, or Built-in Tools on their own. The practical consequence: the endpoints you create are a function of which capabilities you consume, not of AgentCore as a product. Create only the endpoints for the capabilities your agent uses (Step 3).

Your agent code and framework stay where they are; AgentCore becomes a set of privately-reachable APIs it calls. Two things must be reachable privately, or the agent fails at startup (typically a hang, or AccessDenied/403 on its first AWS call):

  1. AWS STS — IRSA exchanges a Kubernetes token for AWS credentials via sts:AssumeRoleWithWebIdentity.
  2. Bedrock AgentCore — the agent's calls to the AgentCore data plane (and, for in-cluster management operations, the control plane).

Architecture

Private VPC (no IGW / no NAT)
  Pod (agent on EKS), ServiceAccount --IRSA-->  Interface endpoints (443):
    AssumeRoleWithWebIdentity  ------------------>  com.amazonaws.<region>.sts (regional)
    AgentCore data-plane calls ------------------>  com.amazonaws.<region>.bedrock-agentcore
    AgentCore mgmt (optional)  ------------------>  com.amazonaws.<region>.bedrock-agentcore-control
    image pull / logging       ------------------>  ecr.api, ecr.dkr, logs (interface) + s3 (gateway)
  Private DNS enabled on every interface endpoint; SGs allow 443 from node/pod ENIs.

Prerequisites

  • A private EKS cluster with no internet egress.
  • IRSA configured: cluster IAM OIDC provider created; an IAM role whose trust policy allows the pod's service account.
  • Permissions to create VPC endpoints and edit security groups.

Step 1 — Create the AWS STS interface endpoint (most commonly overlooked)

IRSA calls sts:AssumeRoleWithWebIdentity. With no egress and no STS endpoint, that call has no route and the pod never receives credentials.

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-0123456789abcdef0 \
  --vpc-endpoint-type Interface \
  --service-name com.amazonaws.<region>.sts \
  --subnet-ids subnet-aaaa subnet-bbbb \
  --security-group-ids sg-endpoints \
  --private-dns-enabled

Step 2 — Make the agent use the regional STS endpoint

An STS interface endpoint only serves the regional endpoint (sts.<region>.amazonaws.com). Requests to the global endpoint sts.amazonaws.com do not traverse your VPC interface endpoint. (Note: in Regions enabled by default, AWS now serves global-endpoint requests from the same Region — but that is service-side routing to a public endpoint, not a private path through your VPC endpoint. A private path still requires the regional endpoint.)

Most current AWS SDKs default AWS_STS_REGIONAL_ENDPOINTS / sts_regional_endpoints to regional, but the default has per-SDK exceptions — older majors (AWS CLI v1, SDK for Go 1.x, Java 1.x, JavaScript 2.x) default to legacy (global). Set it explicitly to be certain:

env:
  - name: AWS_REGION
    value: "<region>"
  - name: AWS_STS_REGIONAL_ENDPOINTS
    value: "regional"

(See "AWS STS Regional endpoints" in the AWS SDKs and Tools Reference for the per-SDK defaults.)

Step 3 — Create the AgentCore interface endpoints you need (by capability)

AgentCore APIs span two planes. Create only the endpoints for the capabilities your agent actually uses:

What the agent doesPlane / endpointExample operations
Use a capability at runtime (incl. Memory read/write)Data plane — com.amazonaws.<region>.bedrock-agentcoreInvokeAgentRuntime, CreateEvent, RetrieveMemoryRecords, ListEvents
Provision or manage AgentCore resourcesControl plane — com.amazonaws.<region>.bedrock-agentcore-controlMemory management (create/update/delete the Memory resource), Runtime management

On the control plane's scope: the AgentCore PrivateLink page's service-name mapping describes the control plane as "Runtime and Memory management," but its own PrivateLink support matrix lists all primitives as control-plane-supported. Treat the control-plane endpoint as covering management of any AgentCore resource you provision from inside the VPC — e.g. in-cluster CI/CD that creates a Memory resource needs this endpoint.

Memory note: runtime memory read/write (e.g. RetrieveMemoryRecords, CreateEvent) is data plane — the data-plane endpoint already covers agents that only read/write memory. The control-plane endpoint is needed only if something inside the no-egress VPC also creates or manages the Memory resource itself (e.g. in-cluster CD).

# Data plane (Runtime invoke, Memory read/write, Identity) — required for a running agent
aws ec2 create-vpc-endpoint --vpc-id vpc-0123456789abcdef0 --vpc-endpoint-type Interface \
  --service-name com.amazonaws.<region>.bedrock-agentcore \
  --subnet-ids subnet-aaaa subnet-bbbb --security-group-ids sg-endpoints --private-dns-enabled

# Control plane — add only if you provision/manage AgentCore resources from inside the VPC
# (e.g. in-cluster CI/CD). A steady-state agent making only data-plane calls does not need it.
aws ec2 create-vpc-endpoint --vpc-id vpc-0123456789abcdef0 --vpc-endpoint-type Interface \
  --service-name com.amazonaws.<region>.bedrock-agentcore-control \
  --subnet-ids subnet-aaaa subnet-bbbb --security-group-ids sg-endpoints --private-dns-enabled

Step 4 — Add the supporting endpoints the pod lifecycle needs

These are standard private-EKS endpoints (not AgentCore-specific). See the EKS "Deploy private clusters with limited internet access" doc.

PurposeEndpointType
Pull container imagescom.amazonaws.<region>.ecr.api, com.amazonaws.<region>.ecr.dkrInterface
Image layerscom.amazonaws.<region>.s3Gateway
Loggingcom.amazonaws.<region>.logsInterface
If you provision the cluster OIDC provider privatelycom.amazonaws.<region>.oidc-eksInterface

Service names for oidc-eks (and eks-auth below) are per the EKS private-clusters doc. Verify the exact name in your Region before running create-vpc-endpoint.

Note (Pod Identity users): If your pods use EKS Pod Identity instead of IRSA, they obtain credentials from the EKS Auth API, not from sts:AssumeRoleWithWebIdentity. In a no-egress VPC you instead need com.amazonaws.<region>.eks-auth, and Steps 1–2 (STS) and the oidc-eks row do not apply. Everything else is unchanged.

Step 5 — Security groups, endpoint policies, and DNS

  • Security groups: the endpoint security group must allow inbound TCP 443 from the node/pod ENI security group (or VPC CIDR).

  • Private DNS: keep it enabled on every interface endpoint so pods keep using the standard service hostnames with no code change.

  • Endpoint policies (important for regulated environments): by default, an AgentCore interface endpoint allows full access. Attach a custom endpoint policy to restrict access (least privilege). Because this guide uses SigV4 via IRSA, you can scope the policy Principal to the specific IRSA role ARN and the exact AgentCore actions/resources your agent uses.

    If your agents use OAuth / Bearer-Token inbound auth instead, endpoint-policy behavior differs (a wildcard Principal is required) — that is a separate path, out of scope here.

Step 6 — Confirm the IAM trust policy (authorization, not network)

Private connectivity is not the authorization boundary — the role's trust policy is. The :aud value stays sts.amazonaws.com even in a regional/private setup — it is the OIDC token audience claim (a string identifier), not a network endpoint. Do not change it to a regional hostname; doing so breaks IRSA. Keep the :sub condition too — without it, any service account in the cluster could assume the role.

{
  "Effect": "Allow",
  "Principal": { "Federated": "arn:aws:iam::<account-id>:oidc-provider/oidc.eks.<region>.amazonaws.com/id/<oidc-id>" },
  "Action": "sts:AssumeRoleWithWebIdentity",
  "Condition": {
    "StringEquals": {
      "oidc.eks.<region>.amazonaws.com/id/<oidc-id>:aud": "sts.amazonaws.com",
      "oidc.eks.<region>.amazonaws.com/id/<oidc-id>:sub": "system:serviceaccount:<namespace>:<serviceaccount>"
    }
  }
}

Step 7 — Verify

# 1) DNS resolves to the endpoint's private IPs (not a public IP):
nslookup sts.<region>.amazonaws.com
nslookup bedrock-agentcore.<region>.amazonaws.com

# 2) From inside a pod using the service account, credentials resolve via IRSA:
kubectl exec -it <pod> -- aws sts get-caller-identity
#   -> returns the IRSA role's assumed-role ARN

# 3) The agent can reach AgentCore (exercise a lightweight AgentCore data-plane API from the pod).

Troubleshooting

SymptomLikely causeFix
Pod hangs / connect timeout getting credentialsNo STS interface endpoint, or client using global sts.amazonaws.comStep 1 + Step 2
AssumeRoleWithWebIdentity returns AccessDeniedTrust policy aud/sub mismatch (not a network issue)Step 6
AgentCore data-plane call (incl. Memory read/write) times out but STS worksMissing data-plane endpoint / private DNS offStep 3, Step 5
Provisioning/managing a Runtime or Memory from in-cluster CD hangsMissing control-plane endpoint bedrock-agentcore-controlStep 3
ImagePullBackOffMissing ECR/S3 endpointsStep 4
DNS returns a public IPPrivate DNS not enabled on the endpointStep 5

Cost and clean-up

Each interface endpoint incurs hourly and data-processing charges (see AWS PrivateLink pricing). Remove unused endpoints with aws ec2 delete-vpc-endpoints.

References

Contributors

Kiran Khambete (khambete) · Krish Balaraman (krbalara)