はじめに
こんにちは。Oisixエンジニアリング部SREセクションの高木です。
OisixのECサイトは、2000年の創業から25年間でオイシックス・ラ・大地の成長を牽引してきました。
一方で、成長とともにシステム構造が複雑になっていき、アプリケーションを柔軟かつスピーディーにリリースしづらくなってきました。
このような状態が継続すると、事業成長の阻害要因になってしまいます。
ソフトウェアによる事業の加速と運用の効率化を目指して、「Oisix REBORN」と銘打ったプロジェクトが進行中です。
本記事では、Oisix REBORNプロジェクトにおけるAmazon Elastic Kubernetes Service (EKS) の利用事例をご紹介します。
Oisix REBORNプロジェクトの概要
Oisix REBORNプロジェクトは複数のフェーズに分けてシステムを改修する計画になっています。
各フェーズで計画している取り組み内容についてはバックエンドセクションの栗崎の記事をご覧ください。
本記事の執筆時点ではフェーズ0(最初のフェーズ)の最終盤から次のフェーズに移行していく段階です。
現在のシステム構成
現在のシステム構成は下図のとおりです。1
いくつかポイントを絞ってご説明します。
BFF/BackendAPI群のManifest
BFF/BackendAPI群のManifestをHelm Chartで管理しています。
当初は社内で運用実績があるKustomizeで管理していました。
Kustomizeで課題となっていた次の点の解決を目的として、Helmへ乗り換えることにしました。
- 開発するAPIの数が増えるにつれて、比例して管理対象のManifestファイル数が膨大になること
APIのManifestのテンプレートとなるHelm Chartを記述しておけば、各APIで values.yaml
を定義するだけで済みます。
Kustomizeの場合のディレクトリ構成は次のようになります。
. ├── apiA │ ├── base │ │ ├── deployment.yaml │ │ ├── hpa.yaml │ │ ├── kustomization.yaml │ │ ├── pdb.yaml │ │ ├── service.yaml │ │ ├── …… │ ├── dev │ │ ├── dapr-configuration.yaml │ │ ├── dapr-resiliency.yaml │ │ ├── deployment-patch.yaml │ │ ├── hpa-patch.yaml │ │ ├── kustomization.yaml │ │ ├── …… │ └── prod │ ├── dapr-configuration.yaml │ ├── dapr-resiliency.yaml │ ├── deployment-patch.yaml │ ├── hpa-patch.yaml │ ├── kustomization.yaml │ ├── …… └── apiB ├── base │ ├── deployment.yaml │ ├── hpa.yaml │ ├── kustomization.yaml │ ├── pdb.yaml │ ├── service.yaml ├── dev │ ├── dapr-configuration.yaml │ ├── dapr-resiliency.yaml │ ├── deployment-patch.yaml │ ├── hpa-patch.yaml │ ├── kustomization.yaml │ ├── …… └── prod ├── kustomization.yaml ├── ……
Helmの場合のディレクトリ構成は次のようになります。
. ├── charts │ └── app-chart │ ├── .helmignore │ ├── Chart.yaml │ ├── templates │ │ ├── _helpers.tpl │ │ ├── dapr-configuration.yaml │ │ ├── dapr-resiliency.yaml │ │ ├── deployment.yaml │ │ ├── hpa.yaml │ │ ├── pdb.yaml │ │ └── service.yaml │ └── values.yaml ├── apiA │ ├── dev │ │ ├── Chart.yaml │ │ └── values.yaml │ └── prod │ ├── Chart.yaml │ └── values.yaml └── apiB ├── dev │ ├── Chart.yaml │ └── values.yaml └── prod ├── Chart.yaml └── values.yaml
Kubernetesアドオン
次のKubernetesアドオンを採用しています。
- Dapr
- Argo CD
- Karpenter
- Nginx Ingress Controller
- AWS Load Balancer Controller
- Secrets Store CSI Driver
- Metrics Server
- EFS CSI Driver
- EBS CSI Driver
- External DNS
- Descheduler
Dapr
DaprはCloud Native Computing Foundation(CNCF)のオープンソースプロジェクトの1つで、マイクロサービス開発を容易にする機能を備えたランタイムです。
Daprを選定した時点ではCNCFの成熟度が「Incubating」で、2024年11月に「Graduated」になりました。
Daprの概要は公式ドキュメントの図が分かりやすいため、引用します。
画像引用元: https://docs.dapr.io/concepts/overview/
Daprを採用した決め手は、アプリケーションが依存するデータストアやメッセージングサービス、キャッシュなどをDaprのコンポーネントとして抽象化できる点です。
これにより、特定のサービスやソフトウェアに依存せず、変更に強いアーキテクチャを実現できます。
たとえば、依存先のサービスを変更する場合でも、Daprのコンポーネント定義を書き換えるだけで済み、アプリケーションコードの修正を最小限に抑えられます。
Oisix REBORNプロジェクトは数年におよぶ計画であり、不確実性が少なくありません。
当初に構想していたアーキテクチャから変更する場合でも、少ない負担で対応できる点がプロジェクトに適していました。
本記事の執筆時点では一部機能2をトライ&エラーを繰り返しながら利用しています。
まだまだ日本語の情報が少ないですが、2025/2/19に発売された書籍『Kubernetesで実践するPlatform Engineering』でDaprが紹介されています。
これから徐々に日本語の情報が増えてくると考えられ、使いこなせれば多くの利点を享受できると期待しています。
Argo CD
Argo CDはKubernetesのデプロイを効率化する非常に便利なOSSで、開発者とSREの双方にメリットがあります。
開発者にとってはリッチなGUIでSYNCを押すだけでデプロイが可能です。
SREにとってはRBACやSSO機能での権限制御が容易です。
なお、ボタンを押さずに自動デプロイする設定も可能です。
本記事の執筆時点では社内のリリースフローや運用に習熟しきっていないことを理由に、本番環境に手動でデプロイしています。
Argo CDはBFF/BackendAPI群がデプロイされているEKSクラスタとは別なEKSクラスタにインストールしています。
将来的にEKSが増えた時に、Argo CDがデプロイされているEKSクラスタから全てのEKSクラスタを中央集権的に管理できる状態を狙っています。
逆に、EKSクラスタが増えなかった場合はBFF/BackendAPI群がデプロイされているEKSクラスタ内にArgo CDを持っていく可能性もあります。
この辺りはArgo CDのバージョンアップ作業などの運用に習熟してきたら改めて判断しようと考えています。
SSO対応
Argo CDをAWS Iam Identity Center(旧称:AWS SSO)と連携させ、AWS access portalからGUIでログインできるようにしています。
設定は公式ドキュメントのIdentity Center (AWS SSO)に従って行います。
App Of Apps Pattern
App Of Apps Patternを採用し、Argo CDのApplication/ApplicationSet自体もArgo CDで管理しています。
Argo CDのApplication/ApplicationSetは次のようなディレクトリ構造で管理しています。
argocd/applications
ディレクトリ内の各yamlファイルでApplication/ApplicationSetを定義しています。
argocd ├── README.md ├── app-of-apps.yaml └── applications ├── aws-load-balancer-controller │ ├── README.md │ └── load-balancer-controller.yaml ├── csi-secrets-store │ ├── README.md │ ├── csi-secrets-store.yml │ └── secrets-provicer-aws.yml ├── dapr │ ├── README.md │ └── dapr.yaml ……
app-of-apps.yamlの内容は次のとおりです。
argocd/applications
ディレクトリ内にあるApplication/ApplicationSetを管理対象にしています。
これにより、手動でkubectl apply
を実行しなければならないManifestがapp-of-apps.yaml
1つだけになります。
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: app-of-apps namespace: argocd spec: project: default source: repoURL: '<GitHub repository URL>' path: argocd/applications targetRevision: main directory: recurse: true destination: name: in-cluster syncPolicy: automated: prune: true selfHeal: true
Karpenter
クラスターオートスケーリングにKarpenterを利用しています。
KarpenterをEKSのマネージドノードグループと併用して次のように使い分けています。
マネージドノードグループ: KarpenterのPodと、API群のHorizontal Pod Autoscaler(HPA)のminReplicasの起動に使用。
Karpenter: HPAでスケールアウトするPodを起動するために使用。
Karpenterのベストプラクティスに沿って、Karpenter管理対象のノードとKarpenter自体が起動するノードを分ける形です。
NodePool
Karpenterではkind: NodePool
のManifestを定義することで、起動するインスタンスのインスタンスタイプやスポット/オンデマンドなどの設定を柔軟に行えます。
以下はKarpenterのバージョン1.0.5
時点のkind: NodePool
のManifestの例です。
apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: default spec: template: spec: nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass name: default requirements: - key: "node.kubernetes.io/instance-type" operator: In values: ["m7g.xlarge", "m7gd.xlarge", "m7g.2xlarge", "m7gd.2xlarge"] - key: "topology.kubernetes.io/zone" operator: In values: ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"] - key: "kubernetes.io/arch" operator: In values: ["arm64"] - key: "karpenter.sh/capacity-type" operator: In values: ["spot", "on-demand"] disruption: consolidateAfter: 3m
これからのシステム構成
AWSの機能アップデートや社内の知見の増加に伴い、システム構成を継続的に更新していきます。
今後の取り組みとして考えていることの一例をご紹介します。
- Amazon API GatewayからKongへの変更
- Amazon API Gatewayでは満たせない要件があることやコスト効率を背景に、Kongへの移行を検討中
- その際、API Gateway+VPC linkのために用意したNLBが不要になるため、Nginx Ingress ControllerのNLBからALBへの変更も併せて検討
- Argo Rolloutsによるカナリアリリースの実行
- EKS Auto Modeの有効化
- KarpenterとAWS Load Balancer Controller、EBS CSI DriverなどのアドオンがAWS側の管理になり、アドオンアップデートの運用負荷が軽減される
- 一方で追加の料金が発生するため、運用コストと比較したうえでの判断が必要
おわりに
Oisix REBORNプロジェクトにおけるEKSの利用についてポイントを絞ってご紹介しました。
OisixのECサイトではOisix REBORNプロジェクト開始以前からEKSを利用していましたが、限定的な利用にとどまっていました。
これほどの規模でKubernetesのエコシステムを利用するのは前例のない試みです。
今はまだ洗練された運用ができているとは言い難いですが、小さく始めてナレッジを貯めていき、より良い状態にするべく前向きに取り組みたいと考えています。
幸運にも最近EKS経験のある優秀なメンバーが入社したこともあり、これからさらにEKSの利用が洗練されていくことが期待できます。
「もう少し詳しく聞いてみたい」という方がいらっしゃいましたら、是非ご連絡ください。カジュアルに話すだけでも大丈夫です。
- 簡略化のため、図に記述されていないリソースもあります。例えば、External DNSなどのアドオンで利用するServiceAccountやIAM Roleを省略しています。↩
- Service invocationとConfigurationを利用しています↩