1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AWS2025年アップデート新機能】EKS Capabilitiesのハンズオンをやってみた

Last updated at Posted at 2026-01-23

はじめに

2025年に発表されたEKSの新機能「EKS Capabilities」の内容がとても興味深いものだったので実際にやってみました!
特に業務でも使用していたArgoCDがAWSマネージドな機能として利用可能となる旨の記載を見て、これは!と思いました。
というのも、業務でEKS上に自分でArgoCDをセットアップした際は、色々とエラーにあたって一苦労した思い出があり、EKS Capabilitiesによって誰でも簡単に高速にArgoCDが使えるようになるのではないかと考えたからです。
更に調べていくと、ACKという機能も業務で苦労したAWS Load Balancer Controllerの代替として使えるのではと思い、ますます実際に使ってみたくなりました。
というわけでハンズオンやっていきます。

前提

今回はCloudFormationでEKSを作成し、EKS Capabilitiesのハンズオンはマネジメントコンソール上で行うこととします。
EKSは業務でも使用していたFargateで動かします。(もし業務でCapabilitiesを入れたらという具体的なイメージをつけるためにできる限り環境は寄せたいため)

注意点

このハンズオンはコストが発生しますので、もしご自身でも実施される場合はその旨予めご了承ください。
CloudFormationスタックでEKSや必要リソースを一括作成、削除可能になっているので、1日程度でハンズオン完了してスタック削除してしまえばそこまで高コストにはならない想定です。

ArgoCDハンズオンの流れ

1. IaCテンプレートを使用して、CloudFormationスタックを作成

スタックの作成は、こちらのハンズオンの記事を参考にしてください

eks-handson.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "Simple EKS on Fargate (Hands-on) + VPC (2AZ / Public+Private / NAT) - Capabilities are set at deploy time."

Parameters:
  System:
    Description: System Name
    Type: String

  Environment:
    Description: Environment Name
    Type: String

  ClusterName:
    Type: String
    Default: "hands-on-eks-fargate"
    Description: "EKS Cluster Name"

  KubernetesVersion:
    Type: String
    Default: "1.34"
    Description: "EKS Kubernetes version (must be supported in your region/account)"

  VpcCidr:
    Type: String
    Default: "10.0.0.0/16"

  PublicSubnet1Cidr:
    Type: String
    Default: "10.0.0.0/24"
  PublicSubnet2Cidr:
    Type: String
    Default: "10.0.1.0/24"

  PrivateSubnet1Cidr:
    Type: String
    Default: "10.0.10.0/24"
  PrivateSubnet2Cidr:
    Type: String
    Default: "10.0.11.0/24"

  EndpointPublicAccess:
    Type: String
    Default: "true"
    AllowedValues: ["true", "false"]
    Description: "EKS API endpoint public access"

  EndpointPrivateAccess:
    Type: String
    Default: "true"
    AllowedValues: ["true", "false"]
    Description: "EKS API endpoint private access"

Resources:
  # -----------------------------
  # VPC
  # -----------------------------
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub "${ClusterName}-vpc"

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${ClusterName}-igw"

  VPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  # -----------------------------
  # Subnets (2AZ / Public+Private)
  # -----------------------------
  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [0, !GetAZs ""]
      CidrBlock: !Ref PublicSubnet1Cidr
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub "${ClusterName}-public-az1"
        # EKS向けタグ(LB等で利用)
        - Key: kubernetes.io/role/elb
          Value: "1"

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [1, !GetAZs ""]
      CidrBlock: !Ref PublicSubnet2Cidr
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub "${ClusterName}-public-az2"
        - Key: kubernetes.io/role/elb
          Value: "1"

  PrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [0, !GetAZs ""]
      CidrBlock: !Ref PrivateSubnet1Cidr
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub "${ClusterName}-private-az1"
        - Key: kubernetes.io/role/internal-elb
          Value: "1"

  PrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [1, !GetAZs ""]
      CidrBlock: !Ref PrivateSubnet2Cidr
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub "${ClusterName}-private-az2"
        - Key: kubernetes.io/role/internal-elb
          Value: "1"

  # -----------------------------
  # Routing (Public: IGW / Private: NAT)
  # -----------------------------
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${ClusterName}-rtb-public"

  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: VPCGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref InternetGateway

  PublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1
      RouteTableId: !Ref PublicRouteTable

  PublicSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet2
      RouteTableId: !Ref PublicRouteTable

  NatEip:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      Tags:
        - Key: Name
          Value: !Sub "${ClusterName}-nat-eip"

  NatGateway:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt NatEip.AllocationId
      SubnetId: !Ref PublicSubnet1
      Tags:
        - Key: Name
          Value: !Sub "${ClusterName}-natgw"

  PrivateRouteTable1:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${ClusterName}-rtb-private-az1"

  PrivateDefaultRoute1:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable1
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NatGateway

  PrivateSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1
      RouteTableId: !Ref PrivateRouteTable1

  PrivateRouteTable2:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${ClusterName}-rtb-private-az2"

  PrivateDefaultRoute2:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable2
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NatGateway

  PrivateSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet2
      RouteTableId: !Ref PrivateRouteTable2

  # -----------------------------
  # Security Group (Cluster)
  # -----------------------------
  EKSClusterSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "EKS Cluster Security Group (hands-on)"
      VpcId: !Ref VPC
      SecurityGroupEgress:
        - IpProtocol: "-1"
          CidrIp: "0.0.0.0/0"
      Tags:
        - Key: Name
          Value: !Sub "${ClusterName}-eks-sg"

  # -----------------------------
  # IAM Roles (EKS Cluster / Fargate Pod Execution)
  # -----------------------------
  EKSClusterRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${ClusterName}-EKSClusterRole"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: eks.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
        - arn:aws:iam::aws:policy/AmazonEKSVPCResourceController

  FargatePodExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${ClusterName}-FargatePodExecutionRole"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: eks-fargate-pods.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSFargatePodExecutionRolePolicy

  # -----------------------------
  # CloudWatch Logs (optional but handy)
  # -----------------------------
  EKSClusterLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "/aws/eks/${ClusterName}/cluster"
      RetentionInDays: 7

  # -----------------------------
  # EKS Cluster
  # -----------------------------
  EKSCluster:
    Type: AWS::EKS::Cluster
    DependsOn:
      - VPCGatewayAttachment
      - EKSClusterLogGroup
    Properties:
      Name: !Ref ClusterName
      Version: !Ref KubernetesVersion
      RoleArn: !GetAtt EKSClusterRole.Arn
      Logging:
        ClusterLogging:
          EnabledTypes:
            - Type: api
            - Type: audit
            - Type: authenticator
            - Type: controllerManager
            - Type: scheduler
      AccessConfig:
        AuthenticationMode: API_AND_CONFIG_MAP
      ResourcesVpcConfig:
        SecurityGroupIds:
          - !Ref EKSClusterSecurityGroup
        SubnetIds:
          - !Ref PrivateSubnet1
          - !Ref PrivateSubnet2
        EndpointPublicAccess: !Ref EndpointPublicAccess
        EndpointPrivateAccess: !Ref EndpointPrivateAccess

  # -----------------------------
  # Fargate Profiles
  #  - kube-system は CoreDNS などに必須
  # -----------------------------
  FargateProfileDefault:
    Type: AWS::EKS::FargateProfile
    DependsOn: EKSCluster
    Properties:
      ClusterName: !Ref ClusterName
      FargateProfileName: "fp-default"
      PodExecutionRoleArn: !GetAtt FargatePodExecutionRole.Arn
      Subnets:
        - !Ref PrivateSubnet1
        - !Ref PrivateSubnet2
      Selectors:
        - Namespace: default

  FargateProfileKubeSystem:
    Type: AWS::EKS::FargateProfile
    DependsOn: 
      - EKSCluster
      - FargateProfileDefault
    Properties:
      ClusterName: !Ref ClusterName
      FargateProfileName: "fp-kube-system"
      PodExecutionRoleArn: !GetAtt FargatePodExecutionRole.Arn
      Subnets:
        - !Ref PrivateSubnet1
        - !Ref PrivateSubnet2
      Selectors:
        - Namespace: kube-system

  FargateProfileArgoCD:
    Type: AWS::EKS::FargateProfile
    DependsOn:
      - EKSCluster
      - FargateProfileKubeSystem
    Properties:
      ClusterName: !Ref ClusterName
      FargateProfileName: "fp-argocd"
      PodExecutionRoleArn: !GetAtt FargatePodExecutionRole.Arn
      Subnets:
        - !Ref PrivateSubnet1
        - !Ref PrivateSubnet2
      Selectors:
        - Namespace: argocd

使用するパラメータ:
ClusterName: "eks-handson" ※任意の値
KubernetesVersion: "1.34" ※2026年1月時点の最新Ver
VpcCidr: "10.0.0.0/16"
PublicSubnet1Cidr: "10.0.0.0/24"
PublicSubnet2Cidr: "10.0.1.0/24"
PrivateSubnet1Cidr: "10.0.10.0/24"
PrivateSubnet2Cidr: "10.0.11.0/24"
EndpointPublicAccess: "true"
EndpointPrivateAccess: "true"

2. ArgoCD機能の作成

作成されたEKSクラスターの機能タブを開き、「機能を作成」を押下
image.png

ArgoCDを選択し、「次へ」を押下
image.png

「ArgoCDロールを作成」を押下し、ArgoCD用のIAMロールを作成
image.png

「確認」を押下
image.png

自動でEKS Capabilitiesが選択されているので、「次へ」を押下
image.png

許可を追加する画面は特に何も変えずに、次へを押下
image.png

必要なポリシーは自動でアタッチされている
ロール名や説明を変更可能
問題なければ、「ロールを作成」を押下
image.png

更新すると、先ほど作成したロールが選択可能
image.png

IAMアイデンティティセンターが必須ですが、私の環境では作成したことがなかったので、
「IAMアイデンティティセンターへ移動」を押下
image.png

以下の公式ドキュメントを参考に、有効化

「IAM Identity Center のアカウントインスタンスを有効に」を押下
※ベストプラクティスはAWS Organizationsで有効化のため注意、今回はPoCのためアカウントインスタンスを有効にする
image.png

「有効にする」を押下
image.png

アカウントインスタンス作成完了画面
image.png

ArgoCD用のグループを作成する
「グループ」を押下
image.png

「グループを作成」を押下
image.png

グループ名、説明を入力して「グループを作成」を押下
image.png

作成されたグループを開き、「ユーザーをグループに追加」を押下
image.png

「ユーザーを追加」を押下
image.png

自身のメールアドレス等入力して、ユーザを作成
image.png

作成したグループを選択し、「次へ」を押下
image.png

「ユーザーを追加」を押下
image.png

入力したメールに招待メールが来るので、「Accept invitation」を押下
PWを設定する
image.png

メール内にAWS access portal URLがあるので、押下しサインインしておく(この後ArgoCD GUIに入る際に必要なため)※ユーザー名/PW入力、MFAの登録が必要、手順は割愛
image.png

サインイン完了画面
image.png

EKSの画面に戻る(ページ自体を更新しないと、作成したグループが表示されなかったため、F5で更新してください)

先ほど作成したグループを選択し、今回は管理者ロールを割り当て
(ほかにもエディタ、ビューワーロールあり)
名前空間(namespaces)はデフォルトのargocdのままで良い
「次へ」を押下
image.png

確認画面で、相違ないことを確認したら「作成」を押下
image.png

作成完了画面
image.png

「Argo CD」を押下
image.png

「Argo UIに移動」を押下
image.png

「LOG IN VIA SSO」を押下
image.png

ログイン完了画面
image.png

※もしうまくいかない場合は、IAMアイデンティティセンターで作成したユーザーでAWS access portalにサインしているかを確認してください

3. ArgoCDにEKSクラスターを登録

まずCloud ShellからEKSを操作できるようにするために、自身のIAMユーザーをEKSのアクセスエントリに追加し権限を付与する必要がある

CloudShellで以下のコマンドを実行

aws eks create-access-entry \
  --cluster-name eks-handson \
  --principal-arn arn:aws:iam::<AWSアカウントID>:user/<IAMユーザー名> \
  --region <リージョン> || true

aws eks associate-access-policy \
  --cluster-name eks-handson \
  --principal-arn arn:aws:iam::<AWSアカウントID>:user/<IAMユーザー名> \
  --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy \
  --access-scope type=cluster \
  --region <リージョン>

アクセスエントリに自身のIAMが追加されていることを確認
(今回はPoCのためIAMユーザーを登録しましたが、IAMロールを登録することも可能)
image.png

CloudShellを開き、以下のコマンドを実行(kubeconfig設定)

aws eks update-kubeconfig --name <EKSクラスター名> --region <リージョン名>

試しに以下のようにkubectlコマンドを実行して正常応答あれば成功
image.png

CloudShell上で、以下のコマンドを実行し、クラスターをArgoCDに登録するためのSecret作成YAMLを作成

vi argocd-secret.yaml
argocd-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: eks-handson
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: cluster
stringData:
  name: eks-handson
  server: arn:aws:eks:<リージョン名>:<AWSアカウントID>:cluster/<EKSクラスター名>
  project: default

※serverにはAPIエンドポイントURLではなく、EKSクラスターのARNを指定する旨公式ドキュメントで注釈があったため注意

以下コマンドでSecretを作成

kubectl apply -f argocd-secret.yaml

image.png

作成されていることを確認
image.png

ステータスがSuccessfulになることを確認(何かApplicationを作成した後に確認する)
image.png

4. ArgoCDアクセスエントリRBAC設定

ArgoCDの機能を作成すると自動でアクセスエントリが作成されるが、デフォルトではKubernetes RBAC権限は付与されない。(最小権限の原則に従う)
クラスター全体の読み取りアクセス、書き込みアクセスの権限付与が必要

CloudShellで以下のコマンドを実行

aws eks associate-access-policy \
  --region <リージョン名> \
  --cluster-name <EKSクラスター名> \
  --principal-arn <ArgoCD Capabilities用に作成したIAMロールのARN> \
  --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy \
  --access-scope type=cluster

アクセスエントリに権限が追加されていることを確認
image.png

※ただし公式ドキュメントにあるように本番環境ではより権限を絞る必要あり、今回付与したのはあくまで検証や開発用の権限

5. GitHubリポジトリ連携

今回はCodeConnectionsを使用して、GitHubと連携し、GitOps化する
他にもGitHubのデプロイキーを使ってGitHubをArgoCDに登録するなど様々な連携方法あり

前提として、今回は既にCodeConnectionsでGitHubとAWSが連携されていることとする
設定方法は以下の記事が分かりやすいので参照

ArgoCD Capabilities用のIAMロールに以下のポリシーをアタッチ

{
  "Version": "2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "codeconnections:UseConnection",
        "codeconnections:GetConnection"
      ],
      "Resource": "arn:aws:codeconnections:region:account-id:connection/connection-id"
    }
  ]
}

image.png

以下のコマンドを実行し、GitHub登録用のApplicationマニフェストを作成

github-connection.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: github-connection
  namespace: argocd
spec:
  source:
    repoURL: https://codeconnections.<リージョン名>.amazonaws.com/git-http/<AWSアカウントID>/<リージョン名>/<CodeConnectionsのID>/<GitHubのOwner>/<GitHubのリポジトリ名>.git
    targetRevision: main
    path: kubernetes/manifests

※RepoURLのサンプル
https://codeconnections.ap-northeast-1.amazonaws.com/git-http/111122223333/ap-northeast-1/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/github-owner/github-repos.git
(CodeConnectionsのIDはARNの末尾の数字の羅列、GitHub Owner/リポジトリは)
GitHub上でリポジトリを開いているときの「XXX/YYY」のXXXがOwner、YYYがリポジトリ名に該当)

CloudShellで以下のコマンド実行し、GitHub連携用のApplicationを作成

kubectl apply -f github-connection.yaml

Applicationが作成されていることを確認
image.png

5. GitHubにマニフェストを置いて、ArgoCDによって自動デプロイ

先ほどのApplicationを見るとエラーが発生している
内容としては、指定したパスにマニフェストが存在しない旨のエラー
そこで指定したパス配下にApplication用のマニフェストを配置し、動作を確認する

連携したGitHubに以下フォルダを作成
kubernetes/manifests
ブランチはmainを使用
※もしmainブランチ以外を使用したい場合は、先ほど手動でapplyしたマニフェストのtargetRevisionに使用したいブランチを指定して、再作成

kubernetes/manifests配下に以下マニフェストを作成
今回はtest-appというApplicationを作成し、簡単なServiceとDeploymentを自動デプロイする

kubernetes/manifests/test-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: test-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://codeconnections.<リージョン名>.amazonaws.com/git-http/<AWSアカウントID>/<リージョン名>/<CodeConnectionsのID>/<GitHubのOwner>/<GitHubのリポジトリ名>.git
    targetRevision: main
    path: kubernetes/manifests/test-app
  destination:
    server: <EKSクラスターのARN>
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

kubernetes/manifests配下にtest-appフォルダを作成し、その配下に以下のマニフェストを作成

簡単なnginx PodをデプロイするDeployment

kubernetes/manifests/test-app/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: default
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.25
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "250m"
              memory: "256Mi"

上記Deploymentに紐づくService

kubernetes/manifests/test-app/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  selector:
    app: nginx
  ports:
    - name: http
      port: 80
      targetPort: 80
  type: ClusterIP

簡単に仕組みを説明すると、Applicationによって、DeploymentとServiceが作成されるように、ソースとなるGitHubの情報、参照するブランチ、パス、デプロイ先のEKSの情報をtest-application.yamlで定義している
今回はシンプルな構成にしたが、指定したパス(今回ならkubernetes/manifests/test-app/)配下にマニフェストを配置すれば、hpaやsecret等も作成可能、またkustomizeを使用して、環境ごとにoverlaysでパッチを当てたり、パス配下のどのマニフェストを対象とするかも制御可能)

上記の内容をmainブランチにpushする(PR→マージ等は各自のルールに合わせて実施してください)

数分待つと自動でデプロイされるので、ArgoCDのGUI上で確認
(mainブランチに変更があったことをArgoCDが検知して、環境に自動デプロイする)
ServiceとDeploymentが作成され、nginxのPodが1つ起動している!
image.png

ACKハンズオンの流れ

ArgoCDのハンズオンは一旦完了です
この後はACKを作成し、ArgoCDで自動デプロイしたKubernetsリソースによってAWSリソースが自動プロビジョニングされるかを試してみます

EKSクラスターの機能タブを開き、「機能を作成」を押下
image.png

ACKを選択し、「次へ」を押下
image.png

ACK用のロールを作成するため、「管理者ロールを作成」を押下
※今回はPoCのため管理者権限で作成するが、マネコンの注記にもあるように実際の業務では最小権限に設計する
image.png

「確認」を押下
image.png

自動選択されるので何も変更せず、「次へ」を押下
image.png

自動選択されるので何も変更せず、「次へ」を押下
image.png

ロール名等を任意の命名に変更可能
内容確認し、「ロールを作成」を押下
image.png

更新して、作成したロールを選択し、「次へ」を押下
image.png

「作成」を押下
image.png

作成完了画面
image.png

EKSクラスターのリソースタブより、拡張機能>CustomResourceDefinitions(CRD)を開き、CRDが追加されていることを確認
image.png

Podを外部に公開するためのALBをACKで作成してみる

まずはALB用のSGを作成
※ALBと同じテンプレート内で作成しようとしたが、ALBに紐づけるSGはIDの形で渡す必要あり、分割して作成

sg.yaml
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: SecurityGroup
metadata:
  name: alb-sg
  namespace: default
spec:
  name: alb-sg
  description: "ALB Security Group created by ACK"
  vpcID: <VPC ID>
  ingressRules:
    - ipProtocol: tcp
      fromPort: 80
      toPort: 80
      ipRanges:
        - cidrIP: <自端末のグローバルIPアドレス※確認くん等で確認する>
  egressRules:
    - ipProtocol: "-1"
      ipRanges:
        - cidrIP: 0.0.0.0/0

SG作成完了
image.png

AWS側にもSGが作成されていることを確認
image.png

EKSのSGのインバウンドルールに作成されたALBからの通信を許可
ポート: 80
ソース: ALBのSG ID
image.png

ALB作成前、何もリソースがないことを確認
image.png

GitHubリポジトリのkubernetes/manifests/test-app/配下に以下のマニフェストを作成

kubernetes/manifests/test-app/alb.yaml
apiVersion: elbv2.services.k8s.aws/v1alpha1
kind: LoadBalancer
metadata:
  name: test-alb
  namespace: default
spec:
  name: test-alb
  type: application
  scheme: internet-facing
  ipAddressType: ipv4
  # PublicサブネットのIDを指定
  subnets:
    - <Subnet1a ID>
    - <Subnet1c ID>
  securityGroups:
    - <先ほど作成したALB用のSG ID>
---
apiVersion: elbv2.services.k8s.aws/v1alpha1
kind: TargetGroup
metadata:
  name: test-tg
  namespace: default
spec:
  name: test-tg
  targetType: ip
  protocol: HTTP
  port: 80
  vpcID: <VPC ID>
  healthCheckProtocol: HTTP
  healthCheckPath: /
  healthCheckPort: traffic-port
  targets:
    - id: <nginx PodのIPアドレス※確認方法は後述>
      port: 80
---
apiVersion: elbv2.services.k8s.aws/v1alpha1
kind: Listener
metadata:
  name: test-listener-80
  namespace: default
spec:
  loadBalancerRef:
    from:
      name: test-alb
  port: 80
  protocol: HTTP
  defaultActions:
    - type: fixed-response
      fixedResponseConfig:
        statusCode: "404"
        contentType: text/plain
        messageBody: "no rule matched"
---
apiVersion: elbv2.services.k8s.aws/v1alpha1
kind: Rule
metadata:
  name: test-rule-echo
  namespace: default
spec:
  listenerRef:
    from:
      name: test-listener-80
  priority: 10
  conditions:
    - field: path-pattern
      pathPatternConfig:
        values:
          - "/*"
  actions:
    - type: forward
      forwardConfig:
        targetGroups:
          - targetGroupRef:
              from:
                name: test-tg
            weight: 1

※PodのIP確認方法
kubectl get pod -o wide

ArgoCDの自動デプロイ完了後、ALBおよび関連リソースが作成されていることを確認
※ruleのみout of syncステータス、差分としてはTargetGroupRefでTG名を指定しているが、実際のマニフェストにはTGのARNが指定されているという点、原因については要調査、一旦このハンズオンの中では問題ないため静観とした
image.png

AWS側でも作成されていることを確認
image.png

ターゲットグループのヘルスチェックも問題ないことを確認
image.png

ALBのDNSをコピー
image.png

ブラウザでコピーしたURLを開き、nginxのサンプルページが表示されることを確認
image.png

こちらでArgoCDおよびACKをEKS Capabilitiesで作成し、Kubernetes APIでKubernetesとAWSリソースどちらも作成、管理し、自端末からインターネット経由でPodへ接続するハンズオンができました!

ACKの挙動を確認する為に、削除もやってみます

先ほど配置したalb.yamlをGitHub上から削除し、ArgoCDの同期を待つと、、、

Kubernetesからはまず削除されていることを確認
image.png

AWS側も削除されていることを確認
image.png

当然先ほどのURLはアクセスできないことを確認
image.png

同様にSGも削除可能ですが、EKSのSGの許可ルールを削除してから実施して下さい
image.png

スタック削除前に、追加したCapabilitiesを削除
image.png

最後にハンズオンが完了したら、スタックを削除して下さい

実際に使ってみた感想

ArgoCDについて

ArgoCDについてはimageUpdaterが使えない等の制約はあるものの、業務で使用していたArgoCD(自前でEKS上にデプロイしている)と使用感は変わらずにそのまま利用することができました!
しかも何よりセットアップが簡単かつ、時間も短いです
業務のArgoCDはHelmインストール、そのためのvalues.yamlの作成や、ArgoCD GUI用のALBの作成、Route53にALBのレコードを登録、接続用のWorkspacesの払い出しetc...様々な作業工程があり、1つの環境でセットアップするのに最低でも3~4h程度かかっていました
また途中エラー等でうまくいかないこともあり、ある程度KubernetesやArgoCD周りの経験がある人が実施する必要がある点も考慮するとかなり大変です
それがEKS Capabilitiesを使用すると30分程度でArgoCDのセットアップを完了することができました!しかもさほどKubernetesやArgoCDの知識がない人でも、公式ドキュメント通りに実施していけば実施可能なくらい簡単にできるという印象です
今回は実施しませんでしたが、アカウントやリージョン等をまたいだマルチクラスター管理、リモートクラスター管理等もできそうな記述を公式ドキュメントで目にしたので色々と活用できそうという点でも今後も触っておきたいと思います!

ACKについて

これは完全に私の知識不足と事前の調査不足なのですが、AWS Load balancer Controllerを代替できるのかなと淡い期待を抱いて色々試してみたのですが、結論代替不可でした。。。
やはり従来のようにKubernetes APIでingress/serviceを作成し、AWS側にはALB/NLBをプロビジョニングして、連携する(ALBへのターゲットの自動登録等が可能)ということをやりたいときはAWS Load Balancer Controllerを使用する必要があります
ACKではALB自体の作成はできるものの、Pod(Service)を動的に紐づけて、Podが再作成されたら自動でIPをターゲットグループに登録しなおすといったことはできませんでした
そのため今回のハンズオンでは、手動でPodのIPを取得し、ALBのマニフェストに記述するというイレギュラーな構成となっています。(業務ではまずあり得ない構成なので参考にしないでください)
SGとALBを同じテンプレート内で作成、紐づけできない点も不便でした

とはいえ、Kubernetes API経由で簡単にAWSリソースが作成できる点はとても興味深かったです!
今回は実施していないですが、公式の例だとS3バケットやDynamoDB等も作成でき、その他いろいろなAWSサービスに対応していそうだなという印象を受けました
Kubernetesに完結した形で、開発者に必要なAWS/Kubernetesリソースを作成、管理、さらにそちらをArgoCDでGitOps化して自動デプロイするといった構成は、素早く開発環境を提供するときなどに役立ちそうだなーと思いました
具体的なユースケースを想像するだけでも楽しいですよね!
今回は実施していないKROも使えば、この辺りがさらに抽象化されて、簡素になるのかなと思っていますが、そちらの検証はまた追って実施します

まとめとしては、今後色々な課題の解決の1つのソリューションとして期待できそうという所感です
引き続きEKS Capabilitiesについては実際に触ってみながら、あわよくば業務で使用する機会をうかがいたいですね(より実践的なナレッジがたまったらまた発信します)
シンプルに触っていてめちゃくちゃ楽しかったです!

ここまで読んでいただきありがとうございました!

備忘録

引っかかりポイント

  • 手動ApplyしたApplication(github-connections.yaml)ではServerはEKSクラスター名を指定して問題なかったが、GitOpsで自動作成させたApplication(test-application.yaml)ではEKSクラスター名を指定するとnot foundとなった
    EKSのARNに変更すると正常に作成された
    下記公式情報によると、EKSクラスター名、ARNどちらでもよく、可読性のためにクラスター名が推奨されていた
    原因については引き続き調査する

今後のハンズオンのイメージ

  • Capabilitiesの作成自体をIaC化できないかの検証
  • KROのハンズオン
  • より実践を想定して権限を最小権限で実施

参考サイト

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?