{"id":36712690,"url":"https://github.com/hops-ops/aws-auto-eks-cluster","last_synced_at":"2026-04-02T11:52:50.410Z","repository":{"id":331711740,"uuid":"1129328562","full_name":"hops-ops/aws-auto-eks-cluster","owner":"hops-ops","description":"EKS configured with Auto Mode, with default nodeclass and nodepool to run on autoscaling spot pool","archived":false,"fork":false,"pushed_at":"2026-03-24T05:28:51.000Z","size":124,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-25T06:22:53.823Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go Template","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hops-ops.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-06T23:58:58.000Z","updated_at":"2026-03-24T05:03:58.000Z","dependencies_parsed_at":"2026-01-31T00:04:59.923Z","dependency_job_id":null,"html_url":"https://github.com/hops-ops/aws-auto-eks-cluster","commit_stats":null,"previous_names":["hops-ops/aws-auto-eks-cluster"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/hops-ops/aws-auto-eks-cluster","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hops-ops%2Faws-auto-eks-cluster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hops-ops%2Faws-auto-eks-cluster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hops-ops%2Faws-auto-eks-cluster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hops-ops%2Faws-auto-eks-cluster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hops-ops","download_url":"https://codeload.github.com/hops-ops/aws-auto-eks-cluster/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hops-ops%2Faws-auto-eks-cluster/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31305867,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T09:48:21.550Z","status":"ssl_error","status_checked_at":"2026-04-02T09:48:19.196Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-12T11:50:25.603Z","updated_at":"2026-04-02T11:52:50.403Z","avatar_url":"https://github.com/hops-ops.png","language":"Go Template","funding_links":[],"categories":[],"sub_categories":[],"readme":"# configuration-aws-auto-eks-cluster\n\nProduction-ready EKS clusters with Auto Mode enabled, removing the operational overhead of node management while maintaining full control over workload scheduling.\n\n## Why EKS Auto Mode?\n\n**Without EKS Auto Mode:**\n- Manual node group management with constant right-sizing decisions\n- Complex Karpenter configuration and ongoing maintenance\n- Separate control plane and data plane infrastructure concerns\n- Multiple IAM roles and policies to manage across components\n- Operational burden of scaling, patching, and upgrading nodes\n\n**With EKS Auto Mode:**\n- AWS manages compute, networking, storage, and load balancing automatically\n- No node group configuration required - AWS handles provisioning\n- Built-in Karpenter for intelligent workload scheduling\n- Simplified IAM with only two roles (control plane + nodes)\n- Focus on workloads instead of infrastructure\n\n## The Journey\n\n### Stage 1: Getting Started (Individual/Small Team)\n\nMinimal configuration for getting a production-ready cluster quickly. Perfect for startups, individual projects, or proof-of-concepts that need a solid foundation.\n\n**Why start here?**\n- Get a production-ready cluster in minutes, not days\n- KMS encryption enabled by default for secrets at rest\n- Private API endpoint with no public exposure\n- Sensible defaults for node sizing and scaling\n\n```yaml\napiVersion: aws.hops.ops.com.ai/v1alpha1\nkind: AutoEKSCluster\nmetadata:\n  name: my-cluster\n  namespace: default\nspec:\n  clusterName: my-cluster\n  region: us-east-1\n  accountId: \"123456789012\"\n  version: \"1.31\"\n  subnetIds:\n    - subnet-aaaaaaaa\n    - subnet-bbbbbbbb\n    - subnet-cccccccc\n```\n\nThis creates:\n- EKS cluster with Auto Mode enabled\n- IAM roles for control plane and nodes\n- KMS key for secrets encryption\n- Default NodeClass and NodePool for spot instances\n\n### Stage 2: Growing (Small Org)\n\nAdd features as your team grows - custom access entries, tags, and node configuration.\n\n**Why expand?**\n- Multiple team members need cluster access\n- Cost allocation requires proper tagging\n- Workloads need custom node requirements (instance types, architectures)\n\n```yaml\napiVersion: aws.hops.ops.com.ai/v1alpha1\nkind: AutoEKSCluster\nmetadata:\n  name: staging\n  namespace: platform\nspec:\n  clusterName: staging\n  region: us-west-2\n  accountId: \"123456789012\"\n  version: \"1.31\"\n  subnetIds:\n    - subnet-private-a\n    - subnet-private-b\n    - subnet-private-c\n\n  tags:\n    environment: staging\n    team: platform\n    cost-center: engineering\n\n  accessEntries:\n    - principalArn: arn:aws:iam::123456789012:role/PlatformAdmins\n      accessPolicies:\n        - policyArn: arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy\n          accessScope:\n            type: cluster\n\n  nodeConfig:\n    nodeClass:\n      ephemeralStorage:\n        size: \"100Gi\"\n    nodePool:\n      # Custom requirements for Graviton support\n      requirements:\n      - key: karpenter.sh/capacity-type\n        operator: In\n        values: [\"spot\"]\n      - key: eks.amazonaws.com/instance-category\n        operator: In\n        values: [\"c\", \"m\", \"r\"]\n      - key: eks.amazonaws.com/instance-generation\n        operator: Gt\n        values: [\"6\"]\n      - key: kubernetes.io/arch\n        operator: In\n        values: [\"amd64\", \"arm64\"]\n      - key: kubernetes.io/os\n        operator: In\n        values: [\"linux\"]\n```\n\n### Stage 3: Enterprise Scale\n\nFull-featured configuration for large organizations with multiple clusters, strict security requirements, and IRSA needs.\n\n**Why this matters at scale?**\n- Permissions boundaries for compliance\n- OIDC provider for IRSA (IAM Roles for Service Accounts)\n- Custom security group rules for network policies\n- Multi-architecture support for cost optimization\n\n```yaml\napiVersion: aws.hops.ops.com.ai/v1alpha1\nkind: AutoEKSCluster\nmetadata:\n  name: production\n  namespace: production\nspec:\n  clusterName: production\n  region: us-east-1\n  accountId: \"123456789012\"\n  version: \"1.31\"\n  subnetIds:\n    - subnet-prod-a\n    - subnet-prod-b\n    - subnet-prod-c\n\n  providerConfigRef:\n    name: production-aws\n    kind: ProviderConfig\n\n  tags:\n    environment: production\n    compliance: sox\n    data-classification: confidential\n\n  permissionsBoundary: arn:aws:iam::123456789012:policy/EKSPermissionsBoundary\n\n  # Enable OIDC for IRSA\n  oidc:\n    enabled: true\n\n  # Custom security group rules for VPN access\n  securityGroupRules:\n    enabled: true\n    ingress:\n      - description: \"Allow kubectl from VPN\"\n        cidrIpv4: \"10.100.0.0/16\"\n        fromPort: 443\n        toPort: 443\n        ipProtocol: tcp\n\n  accessEntries:\n    - principalArn: arn:aws:iam::123456789012:role/ProductionAdmins\n      accessPolicies:\n        - policyArn: arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy\n          accessScope:\n            type: cluster\n    - principalArn: arn:aws:iam::123456789012:role/DeveloperRole\n      kubernetesGroups: [\"developers\"]\n      accessPolicies:\n        - policyArn: arn:aws:eks::aws:cluster-access-policy/AmazonEKSViewPolicy\n          accessScope:\n            type: namespace\n            namespaces: [\"app-team\"]\n\n  nodeConfig:\n    nodeClass:\n      ephemeralStorage:\n        size: \"200Gi\"\n        iops: 6000\n        throughput: 250\n    nodePool:\n      # Production: on-demand, larger instances, conservative disruption\n      requirements:\n      - key: karpenter.sh/capacity-type\n        operator: In\n        values: [\"on-demand\"]\n      - key: eks.amazonaws.com/instance-category\n        operator: In\n        values: [\"c\", \"m\", \"r\"]\n      - key: eks.amazonaws.com/instance-generation\n        operator: Gt\n        values: [\"6\"]\n      - key: kubernetes.io/arch\n        operator: In\n        values: [\"amd64\", \"arm64\"]\n      - key: kubernetes.io/os\n        operator: In\n        values: [\"linux\"]\n      disruption:\n        consolidationPolicy: WhenEmpty  # Conservative for production\n        consolidateAfter: \"1h\"\n        budgets:\n          - nodes: \"5%\"\n```\n\n### Stage 4: Import Existing (Optional)\n\nBring existing EKS cluster resources under management without recreating them.\n\n**Why import?**\n- Preserve existing cluster and workloads\n- Gradual adoption of infrastructure as code\n- No disruption to running applications\n\n```yaml\napiVersion: aws.hops.ops.com.ai/v1alpha1\nkind: AutoEKSCluster\nmetadata:\n  name: imported-cluster\n  namespace: default\nspec:\n  clusterName: my-existing-cluster\n  region: us-east-1\n  accountId: \"123456789012\"\n  version: \"1.31\"\n  subnetIds:\n    - subnet-existing-a\n    - subnet-existing-b\n\n  # Exclude Delete to safely import without risk of accidental deletion\n  managementPolicies:\n    - Create\n    - Observe\n    - Update\n    - LateInitialize\n\n  # External names of existing AWS resources to import\n  externalName: my-existing-cluster\n  iam:\n    controlPlaneRole:\n      externalName: my-existing-cluster-controlplane\n    nodeRole:\n      externalName: my-existing-cluster-node\n  kms:\n    externalName: 12345678-1234-1234-1234-123456789012\n  # oidc:\n  #   enabled: true\n  #   externalName: arn:aws:iam::123456789012:oidc-provider/...\n\n  # Disable node config initially during import\n  nodeConfig:\n    enabled: false\n```\n\n**Import workflow:**\n1. Get the external names of your existing resources (cluster name, role names, KMS key ID)\n2. Apply the manifest - Crossplane will adopt the resources\n3. Once stable, optionally add \"Delete\" to managementPolicies for full management\n\n## Using AutoEKSCluster\n\nReference the cluster's status fields in downstream resources:\n\n```yaml\n# Reference the cluster in a Helm Release\napiVersion: helm.crossplane.io/v1beta1\nkind: Release\nmetadata:\n  name: my-app\nspec:\n  providerConfigRef:\n    name: production  # Matches the cluster name\n  forProvider:\n    chart:\n      name: my-app\n      repository: https://charts.example.com\n    namespace: app\n```\n\n## Status\n\n| Field | Description |\n|-------|-------------|\n| `clusterEndpoint` | API server endpoint URL |\n| `clusterSecurityGroupId` | Cluster security group ID |\n| `oidc` | OIDC provider URL (without https://) |\n| `controlPlaneStatus` | Control plane status (e.g., \"Available\") |\n| `encryptionKeyArn` | ARN of the KMS encryption key |\n| `nodeRoleArn` | ARN of the node IAM role |\n| `controlPlaneRoleArn` | ARN of the control plane IAM role |\n\n## Composed Resources\n\n| Resource | Purpose | Condition |\n|----------|---------|-----------|\n| `iam.Role` (controlplane) | EKS control plane permissions | Always |\n| `iam.Role` (node) | Node instance permissions | Always |\n| `iam.Policy` (resource-tagging) | Auto Mode resource tagging | Always |\n| `iam.RolePolicyAttachment` (6x) | AWS managed policy attachments | When roles ready |\n| `kms.Key` + `kms.Alias` | Secrets encryption | When encryption enabled |\n| `eks.Cluster` | EKS cluster with Auto Mode | When IAM/KMS ready |\n| `eks.ClusterAuth` | Kubeconfig generation | When cluster ready |\n| `eks.AccessEntry` + `AccessPolicyAssociation` | Cluster access | When cluster ready |\n| `iam.OpenIDConnectProvider` | IRSA support | When OIDC enabled |\n| `ec2.SecurityGroupIngressRule` | Custom ingress rules | When SG rules enabled |\n| `kubernetes.Object` (NodeClass) | Karpenter node configuration | When cluster auth ready |\n| `kubernetes.Object` (NodePool) | Karpenter workload scheduling | When node config enabled |\n| `kubernetes.ProviderConfig` | K8s provider for in-cluster (uses namespace from claim) | When cluster auth ready |\n| `helm.ProviderConfig` | Helm provider for in-cluster (uses namespace from claim) | When cluster auth ready |\n\n## Configuration Reference\n\n**Namespace behavior:** The `metadata.namespace` of the claim is automatically used for the kubeconfig secret location. The generated Kubernetes and Helm ProviderConfigs reference this namespace to find the cluster credentials.\n\n| Field | Required | Default | Description |\n|-------|----------|---------|-------------|\n| `clusterName` | Yes | - | Name of the EKS cluster |\n| `region` | Yes | - | AWS region |\n| `accountId` | Yes | - | AWS account ID |\n| `version` | Yes | - | Kubernetes version (e.g., \"1.31\") |\n| `subnetIds` | Cond. | - | Subnet IDs for cluster. Use this OR `subnetSelector`. |\n| `subnetSelector.matchLabels` | Cond. | - | Label selector to find subnets dynamically |\n| `subnetSelector.matchControllerRef` | No | `false` | Match subnets with same controller reference |\n| `providerConfigRef.name` | No | `default` | AWS ProviderConfig name |\n| `providerConfigRef.kind` | No | `ProviderConfig` | Provider config kind |\n| `kubernetesProviderConfigRef.name` | No | `default` | Kubernetes ProviderConfig for cluster-specific configs |\n| `kubernetesProviderConfigRef.kind` | No | `ProviderConfig` | Kind of the Kubernetes provider config |\n| `managementPolicies` | No | `[\"*\"]` | Crossplane management policies |\n| `adminRoleArn` | No | - | IAM role ARN to grant cluster-admin access |\n| `externalName` | No | - | Existing EKS cluster name to import |\n| `iam.controlPlaneRole.externalName` | No | - | Existing control plane IAM role name to import |\n| `iam.nodeRole.externalName` | No | - | Existing node IAM role name to import |\n| `kms.externalName` | No | - | Existing KMS key ID to import (not ARN) |\n| `oidc.externalName` | No | - | Existing OIDC provider ARN to import |\n| `tags` | No | `{hops.ops.com.ai/managed: \"true\"}` | Additional AWS tags merged with defaults |\n| `labels` | No | `{hops.ops.com.ai/managed: \"true\"}` | Additional Kubernetes labels merged with defaults |\n| `permissionsBoundary` | No | - | IAM permissions boundary ARN |\n| `privateAccess` | No | `true` | Enable private API endpoint |\n| `publicAccess` | No | `false` | Enable public API endpoint |\n| `encryptionEnabled` | No | `true` | Enable KMS secrets encryption |\n| `accessEntries` | No | `[]` | Custom cluster access entries |\n| `securityGroupRules.enabled` | No | `false` | Enable custom SG rules |\n| `oidc.enabled` | No | `false` | Create OIDC provider for IRSA |\n| `nodeConfig.enabled` | No | `true` | Create NodeClass/NodePool |\n| `nodeConfig.nodeClass.name` | No | `hops-default` | NodeClass name |\n| `nodeConfig.nodeClass.ephemeralStorage.size` | No | `80Gi` | Ephemeral storage size |\n| `nodeConfig.nodeClass.ephemeralStorage.iops` | No | `3000` | Ephemeral storage IOPS |\n| `nodeConfig.nodeClass.ephemeralStorage.throughput` | No | `125` | Ephemeral storage throughput (MiB/s) |\n| `nodeConfig.nodePool.enabled` | No | `true` | Create the NodePool |\n| `nodeConfig.nodePool.name` | No | `hops-spot` | NodePool name |\n| `nodeConfig.nodePool.requirements` | No | spot, c/m/r, gen4+, amd64 | Karpenter node requirements |\n| `nodeConfig.nodePool.expireAfter` | No | `336h` | Duration after which nodes expire |\n| `nodeConfig.nodePool.disruption.consolidationPolicy` | No | `WhenEmptyOrUnderutilized` | Consolidation policy |\n| `nodeConfig.nodePool.disruption.consolidateAfter` | No | `30s` | Time before consolidating |\n| `nodeConfig.nodePool.disruption.budgets` | No | `[{nodes: \"10%\"}]` | Disruption budgets |\n\n## Development\n\n```bash\n# Render examples\nmake render:all\n\n# Validate examples\nmake validate:all\n\n# Run unit tests\nmake test\n\n# Run E2E tests\nmake e2e\n```\n\n## License\n\nApache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhops-ops%2Faws-auto-eks-cluster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhops-ops%2Faws-auto-eks-cluster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhops-ops%2Faws-auto-eks-cluster/lists"}