Install
$ agentstack add skill-flyteorg-flyte-agent-plugins-flyte-deploy-aws ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Deploying Flyte v2 on AWS (EKS + RDS + S3 + ALB)
Flyte v2 ships as a single unified binary (flyte-binary-v2) plus a separate console image. One HTTP ingress serves the console (/v2), the flyteidl2.* Connect API, and auth-discovery — there is no separate gRPC port. You scale it vertically.
The chart does NOT provision infrastructure. Stand up four things first: EKS cluster, S3 bucket, PostgreSQL (RDS), and (for external access) an ingress controller. This skill does all four with eksctl + aws + helm, then installs the flyte-binary chart (the v2 chart; defaults to flyte-binary-v2 + flyteconsole-v2).
Get the chart first. Install from the published Helm repo — this is what the official docs do, and the released chart pins the Flyte image tag to the chart version (see Image selection in Step 5). Also helm pull --untar a local copy so the TaskAction CRD file is on disk for the Step 5 idempotency check:
helm repo add flyteorg https://flyteorg.github.io/flyte && helm repo update
helm pull flyteorg/flyte-binary --untar # ./flyte-binary/templates/crds/flyte.org_taskactions.yaml now resolves
(Alternatively clone the repo — git clone https://github.com/flyteorg/flyte — and install from the local ./charts/flyte-binary path for the bleeding-edge chart; its default image tag is a floating :latest, so pair it with pullPolicy: Always — see Image selection.) Official docs: https://www.union.ai/docs/v2/flyte/oss-deployment/aws-deployment/. Validated end-to-end on EKS.
> Replace every placeholder in angle brackets and the example hostnames/IDs with your own.
Prerequisites & decisions
- CLIs:
awsv2,eksctl≥ 0.227 (older caps out at k8s 1.29 — see gotcha),kubectl,helm,jq. - Admin (or EKS+RDS+IAM+S3+EC2) creds. STS/SSO works — export the 3 env vars + region.
- eksctl writes the kubeconfig context (e.g.
@flyte-v2..eksctl.io). Pass
kubectl --context (and helm --kube-context ) per command rather than kubectl config use-context — that way you don't mutate the operator's current context.
- Decide: region, name prefix, and exposure: ALB+TLS needs a Route53 zone + ACM cert;
ALB HTTP-only needs neither (reached at the auto *.elb.amazonaws.com name) — the simplest default when you own no domain. (This skill provisions RDS PostgreSQL for the DB; an in-cluster Postgres is out of scope here — RDS is assumed by Steps 3–5.)
Persist your variables. This deploy spans many commands and derives values you can't recover later — most critically the random DBPW (Step 3), plus ACCT, BUCKET, RDS_HOST, IRSA_ARN, etc. If your shell state resets between steps (or your AWS session token expires and you re-auth in a fresh shell), these are gone. Keep them in a file you re-source at the start of every step, and append each derived value as you compute it:
export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... AWS_SESSION_TOKEN=...
export AWS_DEFAULT_REGION=us-west-2
ENVF=~/flyte-deploy.env # source this at every step
{ echo "export PREFIX=flyte-v2 REGION=us-west-2 CLUSTER=flyte-v2"
echo "export ACCT=$(aws sts get-caller-identity --query Account --output text)" # confirm the RIGHT account
} >> $ENVF && source $ENVF
# As you create infra, append its outputs, e.g.: echo "export DBPW='$DBPW' RDS_HOST=$RDS_HOST" >> $ENVF
# Check for an existing domain/cert (empty => go ALB HTTP-only):
aws route53 list-hosted-zones --query 'HostedZones[].Name' --output text
aws acm list-certificates --region $REGION --query 'CertificateSummaryList[].DomainName' --output text
Step 0 — Reuse an existing cluster?
Before creating anything, list the EKS clusters already in the account/region and ask the user whether to deploy onto one of them or stand up a fresh cluster. Reusing skips Step 1 (~15-20 min + the EKS control-plane + node cost).
aws eks list-clusters --region $REGION --query 'clusters' --output text
Present the list and let the user pick one (or choose "create new"). If they reuse one:
CLUSTER=
aws eks update-kubeconfig --region $REGION --name $CLUSTER --alias $CLUSTER # writes + selects context
kubectl --context $CLUSTER get nodes # confirm reachable + Ready
# Confirm IRSA is possible (the chart needs an OIDC provider on the cluster):
aws eks describe-cluster --region $REGION --name $CLUSTER \
--query 'cluster.identity.oidc.issuer' --output text # empty => run: eksctl utils associate-iam-oidc-provider --cluster $CLUSTER --approve
Then skip Step 1 and continue from Step 2. S3 (Step 2), RDS (Step 3), and the ALB controller (Step 4) may already exist on a reused cluster — check before recreating (aws s3 ls, aws rds describe-db-instances, kubectl --context $CLUSTER -n kube-system get deploy aws-load-balancer-controller) and reuse what's there. Otherwise proceed normally. Pass --context $CLUSTER / --kube-context $CLUSTER on the later kubectl/helm commands.
Step 0.5 — Confirm deployment parameters (ASK up front, never assume)
Before provisioning or installing anything, gather the deploy parameters by ASKING the user — do NOT silently reuse values you happen to find. A previous deploy leaves identifiers lying around (an old values-eks.yaml with HOST=/certificate-arn/password, a live flyte*-console-oidc k8s Secret, authMetadata.flyteClient.clientId, a memory of the last run). These are suggestions to confirm, not defaults. Silently reusing the prior hostname, OIDC client ID/secret, or cert is the #1 way this skill does the wrong thing.
For each parameter below, discover any prior value, then present it as a choice — e.g. "reuse previous (test.uniondemo.run, loaded from the old values file / the in-cluster Secret), enter a new one, or pick a different existing one" — and let the user decide. Restate the final set back to them before helm install.
| Parameter | Where a prior value hides | Notes | |---|---|---| | Region / name prefix / cluster | Step 0, current kube-context | | | Exposure (HTTP-only / TLS / TLS+SSO) | — | drives which params below apply | | Hostname | HOST= in old values-eks.yaml; existing Route53 record | drives cert, OIDC redirect URI, DNS | | ACM cert ARN | old values certificate-arn; aws acm list-certificates | must match the chosen hostname | | OIDC issuer / client ID / client secret | authMetadata in old values; flyte*-console-oidc Secret; the IdP app | never echo/ask for the secret in chat — have the user create the Secret themselves (see ALB edge SSO) | | OIDC CLI/PKCE client ID | authMetadata.flyteClient.clientId | | | S3 bucket / RDS host+password | Step 2/3 outputs; old values | reuse the live infra's real values |
Only after the user confirms each value do you write values-eks.yaml (Step 5). If reusing a secret/credential, confirm the user still wants that IdP app — switching IdP is just a new Secret + issuer refs (no ALB/DNS churn).
Step 1 — EKS cluster (eksctl)
cluster.yaml — iam.withOIDC: true is what makes IRSA possible:
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata: { name: flyte-v2, region: us-west-2, version: "1.33" }
iam: { withOIDC: true }
managedNodeGroups:
- name: ng-default
instanceType: m5.large
desiredCapacity: 2
minSize: 2
maxSize: 3
volumeSize: 50
iam: { withAddonPolicies: { ebs: true } }
addons: [{name: vpc-cni},{name: coredns},{name: kube-proxy},{name: aws-ebs-csi-driver}]
eksctl create cluster -f cluster.yaml # ~15-20 min; writes kubeconfig + sets context
kubectl get nodes # expect Ready
The VPC + private subnets exist within ~2 min (before the control plane finishes), so you can start RDS (step 3) in parallel.
Step 2 — S3 bucket + IRSA role
BUCKET=$PREFIX-data-$ACCT # account-id suffix => globally unique
aws s3api create-bucket --bucket $BUCKET --region $REGION \
--create-bucket-configuration LocationConstraint=$REGION
aws s3api put-public-access-block --bucket $BUCKET --public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
aws s3api put-bucket-encryption --bucket $BUCKET --server-side-encryption-configuration \
'{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'
# Scoped S3 policy: ListBucket on the bucket, Get/Put/Delete on its objects.
cat > s3-policy.json > $ENVF # persist (DBPW is unrecoverable)
aws rds create-db-instance --region $REGION --db-instance-identifier $PREFIX-db \
--engine postgres --db-instance-class db.t3.micro --allocated-storage 20 --storage-type gp3 \
--master-username flyte --master-user-password "$DBPW" --db-name flyte \
--vpc-security-group-ids $RDSSG --db-subnet-group-name $PREFIX-db-subnets \
--no-publicly-accessible --backup-retention-period 1
# Endpoint (when status=available):
RDS_HOST=$(aws rds describe-db-instances --region $REGION --db-instance-identifier $PREFIX-db \
--query 'DBInstances[0].Endpoint.Address' --output text)
echo "export RDS_HOST=$RDS_HOST" >> $ENVF
Open 5432 from the nodes — do this once the nodegroup is up (kubectl get nodes Ready), not before: pod egress uses the EKS-managed cluster SG on the nodes (eks-cluster-sg-*), NOT ClusterSharedNodeSecurityGroup (gotcha 2). If you started RDS in parallel with Step 1, the nodes may not exist yet — that's why this is its own step. The DB just needs this one rule:
NODESG=$(aws ec2 describe-instances --region $REGION \
--filters "Name=tag:eks:cluster-name,Values=$CLUSTER" "Name=instance-state-name,Values=running" \
--query 'Reservations[0].Instances[0].SecurityGroups[?contains(GroupName,`eks-cluster-sg`)].GroupId' --output text)
[ -n "$NODESG" ] || { echo "no running nodes yet — wait for the nodegroup, then re-run"; }
aws ec2 authorize-security-group-ingress --region $REGION --group-id $RDSSG \
--protocol tcp --port 5432 --source-group $NODESG # init container retries until this lands
Step 4 — AWS Load Balancer Controller (for ALB ingress)
# Use the policy matching the controller version the chart installs — currently v3.x.
curl -sL https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v3.4.0/docs/install/iam_policy.json -o alb-iam-policy.json
ALB_POLICY_ARN=$(aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy \
--policy-document file://alb-iam-policy.json --query Policy.Arn --output text)
eksctl create iamserviceaccount --cluster $CLUSTER --region $REGION \
--namespace kube-system --name aws-load-balancer-controller \
--role-name $PREFIX-alb-controller --attach-policy-arn "$ALB_POLICY_ARN" --approve
helm repo add eks https://aws.github.io/eks-charts && helm repo update eks
helm upgrade --install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system \
--set clusterName=$CLUSTER --set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller --set region=$REGION --set vpcId=$VPC
kubectl -n kube-system rollout status deploy/aws-load-balancer-controller
If the controller image is newer than the policy you fetched, you'll see AccessDenied on actions like elasticloadbalancing:DescribeListenerAttributes. Fix WITHOUT reinstalling:
curl -sL .../aws-load-balancer-controller/v/docs/install/iam_policy.json -o p.json
aws iam create-policy-version --policy-arn $ALB_POLICY_ARN --policy-document file://p.json --set-as-default
(Check version: kubectl -n kube-system get deploy aws-load-balancer-controller -o jsonpath='{..image}'.)
Step 5 — helm install flyte-binary
values-eks.yaml (ALB HTTP-only variant). The UPPERCASE tokens (BUCKET, RDS_HOST, DBPW, IRSA_ARN) and region: are placeholders — substitute your real values before installing, e.g. sed -i "s/BUCKET/$BUCKET/g; s/RDS_HOST/$RDS_HOST/; s/DBPW/$DBPW/; s#IRSA_ARN#$IRSA_ARN#; s/us-west-2/$REGION/g" values-eks.yaml (or hand-edit). Note this chart uses metadataContainer (no userDataContainer) and its run output prefix defaults to a nonexistent s3://flyte-data — override storagePrefix to your bucket:
fullnameOverride: flyte
flyte-core-components:
runs: { storagePrefix: "s3://BUCKET" } # under `runs`, NOT `runs.server` (else ignored)
# no image override needed: the repo chart pins its image tag to the chart version
# (only the git-main chart floats `:latest` — see Image selection below)
configuration:
database:
postgres:
host: RDS_HOST
port: 5432
dbname: flyte
username: flyte
password: "DBPW"
options: "sslmode=require"
storage:
metadataContainer: BUCKET
provider: s3
providerConfig: { s3: { region: us-west-2, authType: iam } } # set to your $REGION
inline: { executor: { defaultK8sServiceAccount: flyte } } # task pods inherit S3 via IRSA
serviceAccount:
create: true
name: flyte
annotations: { eks.amazonaws.com/role-arn: IRSA_ARN }
ingress:
create: true
host: "" # empty => rule matches any host => reach by ALB DNS name
ingressClassName: alb
httpAnnotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}]'
alb.ingress.kubernetes.io/healthcheck-path: /healthz # binary serves /healthz on :8090
alb.ingress.kubernetes.io/healthcheck-port: "8090"
For TLS: add certificate-arn, listen-ports: '[{"HTTP":80},{"HTTPS":443}]', ssl-redirect: "443", and set ingress.host to the cert hostname + a Route53 record. See the TLS section below — works even when DNS lives in a different AWS account.
helm install flyte flyteorg/flyte-binary -n flyte --create-namespace -f values-eks.yaml --dry-run # check
helm install flyte flyteorg/flyte-binary -n flyte --create-namespace -f values-eks.yaml
kubectl -n flyte get pods # flyte stuck Init:0/1 => wait-for-db can't reach RDS (see gotchas)
ALWAYS confirm the TaskAction CRD is present after install — the chart ships it as a plain template, so in a shared cluster it's easily deleted out-of-band, and the binary then loops Failed to watch ... taskactions.flyte.org and every run sticks at "queued" (gotcha 8). Make it idempotent at the end of every deploy:
kubectl --context get crd taskactions.flyte.org >/dev/null 2>&1 \
|| kubectl --context apply -f ./flyte-binary/templates/crds/flyte.org_taskactions.yaml # from `helm pull --untar`
kubectl --context get crd taskactions.flyte.org -o jsonpath='{.status.conditions[?(@.type=="Established")].status}' # => True
# Pre-existing CRD blocks helm adopt? patch ownership, then (re)install:
# kubectl annotate crd taskactions.flyte.org meta.helm.sh/release-name=flyte meta.helm.sh/release-namespace=flyte --overwrite
# kubectl label crd taskactions.flyte.org app.kubernetes.io/managed-by=Helm --overwrite
Only rollout restart if you applied the CRD onto an already-running binary that was missing it (the watch won't retry a resource that 404'd at boot). On a normal install the chart creates the CRD before the pod is Ready, so the watch establishes on first boot — don't restart reflexively, it's a wasted second rollout (+ image re-pull on a floating tag).
Image selection. The published repo chart (what the official docs install) pins the Flyte image tag to the chart version — e.g. chart v2.0.27 runs cr.flyte.org/flyteorg/flyte-binary-v2:v2.0.27 — plus console ghcr.io/unionai-oss/flyteconsole-v2:latest, all with the default pullPolicy: IfNotPresent. No image override is needed: the binary and the DB migrations it runs ship as a matched pair, and upgrading is helm repo update && helm upgrade (a new chart brings its new pinned image). Only
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: flyteorg
- Source: flyteorg/flyte-agent-plugins
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.