diff --git a/.gitignore b/.gitignore index 03bdc3f..c029965 100644 --- a/.gitignore +++ b/.gitignore @@ -84,3 +84,9 @@ bin/ ### Mac OS ### .DS_Store + +# IP address restrictions (contains real IPs) +**/ingress-cidrs.yaml + +# kro instance with real IPs +**/webapp-instance.yaml diff --git a/environments/sample/main.tf b/environments/sample/main.tf index 3ec6dd3..8c5baa1 100644 --- a/environments/sample/main.tf +++ b/environments/sample/main.tf @@ -21,6 +21,7 @@ module "cluster_development" { argo_cd_idc_region = var.argo_cd_idc_region argo_cd_idc_groups = var.argo_cd_idc_groups network_flow_monitor_scope_arn = var.network_flow_monitor_scope_arn + public_access_cidrs = var.public_access_cidrs } module "platform_cluster_bootstrap" { diff --git a/environments/sample/terraform.tfvars.example b/environments/sample/terraform.tfvars.example new file mode 100644 index 0000000..d54af84 --- /dev/null +++ b/environments/sample/terraform.tfvars.example @@ -0,0 +1,15 @@ +aws_profile = "default" +aws_region = "us-east-1" +resource_prefix = "ex-idp" +argo_cd_idc_region = "us-east-1" +argo_cd_idc_instance_arn = "arn:aws:sso:::instance/ssoins-XXXXXXXXXXXXXXXX" + +argo_cd_idc_groups = { + "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" = "ADMIN" +} + +# Restrict EKS API and ALB access to your IP ranges +public_access_cidrs = [ + "x.x.x.x/32", # Your office IP + "y.y.y.y/32", # Your home IP +] diff --git a/environments/sample/variables.tf b/environments/sample/variables.tf index 01fff71..53234a5 100644 --- a/environments/sample/variables.tf +++ b/environments/sample/variables.tf @@ -37,3 +37,8 @@ variable "network_flow_monitor_scope_arn" { default = null type = string } + +variable "public_access_cidrs" { + description = "List of CIDR blocks allowed to access the EKS API server endpoint" + type = list(string) +} diff --git a/modules/platform_cluster/eks.tf b/modules/platform_cluster/eks.tf index d75d2ef..62cd48a 100644 --- a/modules/platform_cluster/eks.tf +++ b/modules/platform_cluster/eks.tf @@ -12,6 +12,7 @@ module "eks" { name = "${local.env_prefix}-cluster" kubernetes_version = var.kubernetes_version endpoint_public_access = true + endpoint_public_access_cidrs = var.public_access_cidrs create_kms_key = false encryption_config = null authentication_mode = "API" @@ -31,7 +32,7 @@ module "eks" { # EKS Addons addons = merge( - var.network_flow_monitor_scope_arn != "" ? { + var.network_flow_monitor_scope_arn != null ? { aws-network-flow-monitoring-agent = { pod_identity_association = [ { diff --git a/modules/platform_cluster/eks_capabilities_kro.tf b/modules/platform_cluster/eks_capabilities_kro.tf new file mode 100644 index 0000000..799e89f --- /dev/null +++ b/modules/platform_cluster/eks_capabilities_kro.tf @@ -0,0 +1,48 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: MIT-0 + +data "aws_iam_policy_document" "capabilities_kro_assume_role_policy" { + statement { + effect = "Allow" + actions = [ + "sts:AssumeRole", + "sts:TagSession" + ] + + principals { + type = "Service" + identifiers = ["capabilities.eks.amazonaws.com"] + } + } +} + +resource "aws_iam_role" "capabilities_kro_role" { + name = "${local.env_prefix}-capabilities-kro" + assume_role_policy = data.aws_iam_policy_document.capabilities_kro_assume_role_policy.json + + tags = local.tags +} + +resource "aws_eks_capability" "eks_capabilities_kro" { + cluster_name = module.eks.cluster_name + capability_name = "kro" + type = "KRO" + role_arn = aws_iam_role.capabilities_kro_role.arn + delete_propagation_policy = "RETAIN" + + depends_on = [ + aws_iam_role.capabilities_kro_role, + time_sleep.wait_for_iam_role_propagation + ] +} + +# Grant kro cluster admin permissions to manage K8s resources defined in RGDs +resource "aws_eks_access_policy_association" "kro_access_entry" { + cluster_name = module.eks.cluster_name + policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy" + principal_arn = aws_iam_role.capabilities_kro_role.arn + + access_scope { + type = "cluster" + } +} diff --git a/modules/platform_cluster/variables.tf b/modules/platform_cluster/variables.tf index 07e2943..3a88e93 100644 --- a/modules/platform_cluster/variables.tf +++ b/modules/platform_cluster/variables.tf @@ -50,3 +50,9 @@ variable "network_flow_monitor_scope_arn" { type = string default = null } + +variable "public_access_cidrs" { + description = "List of CIDR blocks allowed to access the EKS API server endpoint" + type = list(string) + default = ["0.0.0.0/0"] +} diff --git a/repositories/platform/bootstrap/config-kro-definitions.yaml b/repositories/platform/bootstrap/config-kro-definitions.yaml new file mode 100644 index 0000000..5b6118f --- /dev/null +++ b/repositories/platform/bootstrap/config-kro-definitions.yaml @@ -0,0 +1,34 @@ +apiVersion: argoproj.io/v1alpha1 +kind: ApplicationSet +metadata: + name: config-kro-definitions + namespace: argocd +spec: + goTemplate: true + syncPolicy: + preserveResourcesOnDeletion: true + generators: + - clusters: + selector: + matchExpressions: + - key: platform_cluster + operator: Exists + template: + metadata: + name: config-kro-definitions + spec: + project: default + source: + repoURL: '{{ .metadata.annotations.platform_repo_url }}' + targetRevision: '{{ .metadata.annotations.platform_repo_revision }}' + path: 'config/kro-definitions' + destination: + namespace: argocd + server: '{{ .server }}' + syncPolicy: + automated: + selfHeal: true + allowEmpty: true + prune: true + retry: + limit: 100 diff --git a/repositories/platform/config/kro-definitions/webapp-rgd.yaml b/repositories/platform/config/kro-definitions/webapp-rgd.yaml new file mode 100644 index 0000000..6fe30fa --- /dev/null +++ b/repositories/platform/config/kro-definitions/webapp-rgd.yaml @@ -0,0 +1,124 @@ +apiVersion: kro.run/v1alpha1 +kind: ResourceGraphDefinition +metadata: + name: webapp +spec: + schema: + apiVersion: v1alpha1 + kind: WebApp + group: kro.run + spec: + name: string | required=true + image: string | required=true + replicas: integer | default=2 + port: integer | default=8080 + ingressPath: string | default="/*" + ingressCidrs: string | default="" + resources: + - id: rollout + template: + apiVersion: argoproj.io/v1alpha1 + kind: Rollout + metadata: + name: ${schema.spec.name} + spec: + replicas: ${schema.spec.replicas} + revisionHistoryLimit: 2 + selector: + matchLabels: + app.kubernetes.io/name: ${schema.spec.name} + template: + metadata: + labels: + app.kubernetes.io/name: ${schema.spec.name} + spec: + containers: + - name: ${schema.spec.name} + image: ${schema.spec.image} + imagePullPolicy: Always + ports: + - name: http + containerPort: ${schema.spec.port} + protocol: TCP + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "256Mi" + cpu: "500m" + strategy: + blueGreen: + activeService: ${schema.spec.name}-active + previewService: ${schema.spec.name}-preview + autoPromotionEnabled: false + - id: serviceActive + template: + apiVersion: v1 + kind: Service + metadata: + name: ${schema.spec.name}-active + labels: + app.kubernetes.io/name: ${schema.spec.name} + spec: + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: ${schema.spec.name} + - id: servicePreview + template: + apiVersion: v1 + kind: Service + metadata: + name: ${schema.spec.name}-preview + labels: + app.kubernetes.io/name: ${schema.spec.name} + spec: + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: ${schema.spec.name} + - id: ingressActive + template: + apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + name: ${schema.spec.name}-active + annotations: + alb.ingress.kubernetes.io/inbound-cidrs: ${schema.spec.ingressCidrs} + spec: + rules: + - http: + paths: + - path: ${schema.spec.ingressPath} + pathType: ImplementationSpecific + backend: + service: + name: ${schema.spec.name}-active + port: + name: http + - id: ingressPreview + template: + apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + name: ${schema.spec.name}-preview + annotations: + alb.ingress.kubernetes.io/inbound-cidrs: ${schema.spec.ingressCidrs} + spec: + rules: + - http: + paths: + - path: ${schema.spec.ingressPath} + pathType: ImplementationSpecific + backend: + service: + name: ${schema.spec.name}-preview + port: + name: http diff --git a/repositories/workloads/README.md b/repositories/workloads/README.md new file mode 100644 index 0000000..4b7ae8f --- /dev/null +++ b/repositories/workloads/README.md @@ -0,0 +1,105 @@ +# Workload デプロイ方式の使い分け + +このリポジトリでは、同じアプリ(bg-demo)を **kro 版** と **従来版** の2つの方式でデプロイできます。 + +## 構成 + +``` +repositories/workloads/ex-app/ +├── bg-demo-kro/ ← kro 版 +│ └── dev/ +│ ├── kustomization.yaml +│ └── webapp-instance.yaml(.example) +│ +└── bg-demo-traditional/ ← 従来版(Kustomize + 生マニフェスト) + ├── base/ + │ ├── rollouts.yaml + │ ├── service.yaml + │ ├── ingress.yaml + │ └── kustomization.yaml + └── dev/ + ├── kustomization.yaml + └── ingress-cidrs.yaml(.example) +``` + +## 使い分け方 + +### kro 版でデプロイする場合 + +```bash +./scripts/push-workload.sh kro +``` + +Developer は `webapp-instance.yaml` の1ファイルだけ書けばよい: + +```yaml +apiVersion: kro.run/v1alpha1 +kind: WebApp +metadata: + name: bg-demo +spec: + name: bg-demo + image: argoproj/rollouts-demo:blue + replicas: 2 + port: 8080 + ingressCidrs: "x.x.x.x/32,y.y.y.y/32" +``` + +kro が Rollout / Service×2 / Ingress×2 を自動生成します。 + +### 従来版でデプロイする場合 + +```bash +./scripts/push-workload.sh traditional +``` + +Kustomize で base マニフェスト + dev overlay(IP制限パッチ)を適用します。 +Developer は Rollout / Service / Ingress の各マニフェストを個別に管理します。 + +## 前提条件 + +- `terraform apply` 済み(EKS + ArgoCD + ACK + kro Capability) +- platform リポジトリが CodeCommit に push 済み(`./scripts/push-platform.sh`) +- kro 版を使う場合: platform リポジトリに RGD が含まれていること + +## セットアップ手順 + +```bash +# 1. terraform.tfvars を作成(terraform.tfvars.example を参考) +cp environments/sample/terraform.tfvars.example environments/sample/terraform.tfvars +# → 実際の値を記入 + +# 2. Terraform apply +cd environments/sample +terraform init +terraform apply + +# 3. platform リポジトリを push +./scripts/push-platform.sh + +# 4. workload の実ファイルを作成(.example を参考) +# kro 版: +cp repositories/workloads/ex-app/bg-demo-kro/dev/webapp-instance.yaml.example \ + repositories/workloads/ex-app/bg-demo-kro/dev/webapp-instance.yaml +# → 実際のIPアドレスを記入 + +# 従来版: +cp repositories/workloads/ex-app/bg-demo-traditional/dev/ingress-cidrs.yaml.example \ + repositories/workloads/ex-app/bg-demo-traditional/dev/ingress-cidrs.yaml +# → 実際のIPアドレスを記入 + +# 5. workload を push(kro 版 or 従来版を選択) +./scripts/push-workload.sh kro +# or +./scripts/push-workload.sh traditional +``` + +## 比較 + +| 観点 | kro 版 | 従来版 | +|------|--------|--------| +| Developer が書くファイル数 | 1 | 5+ | +| 必要な K8s 知識 | WebApp spec のみ | Rollout, Service, Ingress, Kustomize | +| 構成変更の全体反映 | RGD 更新で自動反映 | 各チームが個別に修正 | +| 前提 | kro Capability + RGD が必要 | Argo Rollouts のみ | +| 成熟度 | alpha(EKS Capability) | 安定 | diff --git a/repositories/workloads/ex-app/bg-demo/dev/kustomization.yaml b/repositories/workloads/ex-app/bg-demo-kro/dev/kustomization.yaml similarity index 57% rename from repositories/workloads/ex-app/bg-demo/dev/kustomization.yaml rename to repositories/workloads/ex-app/bg-demo-kro/dev/kustomization.yaml index 869103b..4d47ba9 100644 --- a/repositories/workloads/ex-app/bg-demo/dev/kustomization.yaml +++ b/repositories/workloads/ex-app/bg-demo-kro/dev/kustomization.yaml @@ -1,3 +1,3 @@ kind: Kustomization resources: -- ../base \ No newline at end of file +- webapp-instance.yaml diff --git a/repositories/workloads/ex-app/bg-demo-kro/dev/webapp-instance.yaml.example b/repositories/workloads/ex-app/bg-demo-kro/dev/webapp-instance.yaml.example new file mode 100644 index 0000000..0027d41 --- /dev/null +++ b/repositories/workloads/ex-app/bg-demo-kro/dev/webapp-instance.yaml.example @@ -0,0 +1,10 @@ +apiVersion: kro.run/v1alpha1 +kind: WebApp +metadata: + name: bg-demo +spec: + name: bg-demo + image: argoproj/rollouts-demo:blue + replicas: 2 + port: 8080 + ingressCidrs: "x.x.x.x/32,y.y.y.y/32" diff --git a/repositories/workloads/ex-app/bg-demo/base/ingress.yaml b/repositories/workloads/ex-app/bg-demo-traditional/base/ingress.yaml similarity index 100% rename from repositories/workloads/ex-app/bg-demo/base/ingress.yaml rename to repositories/workloads/ex-app/bg-demo-traditional/base/ingress.yaml diff --git a/repositories/workloads/ex-app/bg-demo/base/kustomization.yaml b/repositories/workloads/ex-app/bg-demo-traditional/base/kustomization.yaml similarity index 100% rename from repositories/workloads/ex-app/bg-demo/base/kustomization.yaml rename to repositories/workloads/ex-app/bg-demo-traditional/base/kustomization.yaml diff --git a/repositories/workloads/ex-app/bg-demo/base/rollouts.yaml b/repositories/workloads/ex-app/bg-demo-traditional/base/rollouts.yaml similarity index 100% rename from repositories/workloads/ex-app/bg-demo/base/rollouts.yaml rename to repositories/workloads/ex-app/bg-demo-traditional/base/rollouts.yaml diff --git a/repositories/workloads/ex-app/bg-demo/base/service.yaml b/repositories/workloads/ex-app/bg-demo-traditional/base/service.yaml similarity index 100% rename from repositories/workloads/ex-app/bg-demo/base/service.yaml rename to repositories/workloads/ex-app/bg-demo-traditional/base/service.yaml diff --git a/repositories/workloads/ex-app/bg-demo-traditional/dev/ingress-cidrs.yaml.example b/repositories/workloads/ex-app/bg-demo-traditional/dev/ingress-cidrs.yaml.example new file mode 100644 index 0000000..69c6457 --- /dev/null +++ b/repositories/workloads/ex-app/bg-demo-traditional/dev/ingress-cidrs.yaml.example @@ -0,0 +1,13 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bg-demo-active + annotations: + alb.ingress.kubernetes.io/inbound-cidrs: "x.x.x.x/32,y.y.y.y/32" +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bg-demo-preview + annotations: + alb.ingress.kubernetes.io/inbound-cidrs: "x.x.x.x/32,y.y.y.y/32" diff --git a/repositories/workloads/ex-app/bg-demo-traditional/dev/kustomization.yaml b/repositories/workloads/ex-app/bg-demo-traditional/dev/kustomization.yaml new file mode 100644 index 0000000..127fadf --- /dev/null +++ b/repositories/workloads/ex-app/bg-demo-traditional/dev/kustomization.yaml @@ -0,0 +1,5 @@ +kind: Kustomization +resources: +- ../base +patches: +- path: ingress-cidrs.yaml diff --git a/scripts/push-platform.sh b/scripts/push-platform.sh new file mode 100755 index 0000000..7327c26 --- /dev/null +++ b/scripts/push-platform.sh @@ -0,0 +1,34 @@ +#!/bin/bash +set -e + +# Usage: ./push-platform.sh +# Pushes the platform repository to CodeCommit + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$SCRIPT_DIR/.." +PLATFORM_DIR="$REPO_ROOT/repositories/platform" + +TMPDIR=$(mktemp -d) +trap "rm -rf $TMPDIR" EXIT + +cd "$TMPDIR" +git init +git remote add origin https://git-codecommit.us-east-1.amazonaws.com/v1/repos/ex-idp-dev-platform +git config credential.helper '!aws --profile default codecommit credential-helper $@' +git config credential.UseHttpPath true + +cp -r "$PLATFORM_DIR"/* . + +echo "=== Files to push ===" +find . -type f -not -path './.git/*' + +git add -A +git commit -m "update: platform configuration" +git branch -M main + +echo "" +echo "Pushing to CodeCommit..." +GIT_CONFIG_GLOBAL=/dev/null git push --force origin main + +echo "" +echo "Done! ArgoCD will sync the platform configuration." diff --git a/scripts/push-workload.sh b/scripts/push-workload.sh new file mode 100755 index 0000000..03bc67f --- /dev/null +++ b/scripts/push-workload.sh @@ -0,0 +1,59 @@ +#!/bin/bash +set -e + +# Usage: ./push-workload.sh [kro|traditional] +# Pushes the selected workload variant to CodeCommit as ex-app/bg-demo/ + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$SCRIPT_DIR/.." +WORKLOAD_DIR="$REPO_ROOT/repositories/workloads" +VARIANT="${1:-kro}" + +if [[ "$VARIANT" != "kro" && "$VARIANT" != "traditional" ]]; then + echo "Usage: $0 [kro|traditional]" + echo " kro - Deploy using kro WebApp Instance (default)" + echo " traditional - Deploy using Kustomize with raw manifests" + exit 1 +fi + +SOURCE_DIR="$WORKLOAD_DIR/ex-app/bg-demo-${VARIANT}" + +# Validate source exists +if [[ ! -d "$SOURCE_DIR" ]]; then + echo "Error: $SOURCE_DIR does not exist" + exit 1 +fi + +# Create temp repo and push +TMPDIR=$(mktemp -d) +trap "rm -rf $TMPDIR" EXIT + +cd "$TMPDIR" +git init +git remote add origin https://git-codecommit.us-east-1.amazonaws.com/v1/repos/ex-idp-dev-workload +git config credential.helper '!aws --profile default codecommit credential-helper $@' +git config credential.UseHttpPath true + +# Copy files maintaining the expected directory structure +mkdir -p ex-app/bg-demo +cp -r "$SOURCE_DIR"/* ex-app/bg-demo/ + +# For traditional variant, also copy base +if [[ "$VARIANT" == "traditional" ]]; then + # base is already inside bg-demo-traditional + : +fi + +echo "=== Files to push (variant: $VARIANT) ===" +find ex-app -type f + +git add -A +git commit -m "deploy: bg-demo ($VARIANT variant)" +git branch -M main + +echo "" +echo "Pushing to CodeCommit..." +GIT_CONFIG_GLOBAL=/dev/null git push --force origin main + +echo "" +echo "Done! ArgoCD will sync the $VARIANT variant."