メインコンテンツまでスキップ

kroによるリソースの作成

kroをインストールしたので、WebApplication ResourceGraphDefinitionsを使用してCartsコンポーネントをデプロイします。まず、再利用可能なWebApplication APIを定義するResourceGraphDefinitionテンプレートを確認しましょう:

RGDマニフェストの全容を表示
~/environment/eks-workshop/modules/automation/controlplanes/kro/rgds/webapp-rgd.yaml
apiVersion: kro.run/v1alpha1
kind: ResourceGraphDefinition
metadata:
name: web-application
spec:
schema:
apiVersion: v1alpha1
kind: WebApplication
spec:
appName: string | required=true description="Web Application Name"
replicas: integer | default=1 minimum=1 maximum=100
image: string | default=nginx
port: integer | default=8080
healthcheck:
readinessPath: string | default="/actuator/health/readiness"
readinessPort: integer | default=8080
livenessPath: string | default="/actuator/health/liveness"
livenessPort: integer | default=8080

service:
enabled: boolean | default=true
iamRole: string | default=""

env: map[string]string | default={}

ingress:
enabled: boolean | default=false
path: string | default="/"
healthcheckPath: string | default="/health"
groupname: string | default="eks-workshop"

resources:
- id: serviceAccount
template:
apiVersion: v1
kind: ServiceAccount
metadata:
name: ${schema.spec.appName}
namespace: ${schema.spec.appName}

- id: configMap
template:
apiVersion: v1
kind: ConfigMap
metadata:
name: ${schema.spec.appName}
namespace: ${schema.spec.appName}
data: ${schema.spec.env}

- id: deployment
template:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${schema.spec.appName}
namespace: ${schema.spec.appName}
labels:
app.kubernetes.io/created-by: "eks-workshop"
app.kubernetes.io/type: app
spec:
replicas: ${schema.spec.replicas}
revisionHistoryLimit: 3
selector:
matchLabels:
app.kubernetes.io/name: ${schema.spec.appName}
app.kubernetes.io/instance: ${schema.spec.appName}
app.kubernetes.io/component: service
template:
metadata:
annotations:
prometheus.io/path: /actuator/prometheus
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
labels:
app.kubernetes.io/name: ${schema.spec.appName}
app.kubernetes.io/instance: ${schema.spec.appName}
app.kubernetes.io/component: service
app.kubernetes.io/created-by: eks-workshop
spec:
serviceAccountName: ${schema.spec.appName}
securityContext:
fsGroup: 1000
containers:
- name: ${schema.spec.appName}
env:
- name: JAVA_OPTS
value: -XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/urandom
envFrom:
- configMapRef:
name: ${schema.spec.appName}
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
image: ${schema.spec.image}
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: ${schema.spec.port}
protocol: TCP
readinessProbe:
httpGet:
path: ${schema.spec.healthcheck.readinessPath}
port: ${schema.spec.healthcheck.readinessPort}
initialDelaySeconds: 15
periodSeconds: 3
livenessProbe:
httpGet:
path: ${schema.spec.healthcheck.livenessPath}
port: ${schema.spec.healthcheck.livenessPort}
initialDelaySeconds: 45
periodSeconds: 3
resources:
limits:
memory: 1Gi
requests:
cpu: 250m
memory: 1Gi
volumeMounts:
- mountPath: /tmp
name: tmp-volume
volumes:
- name: tmp-volume
emptyDir:
medium: Memory

- id: service
template:
apiVersion: v1
kind: Service
metadata:
name: ${schema.spec.appName}
namespace: ${schema.spec.appName}
labels:
app.kubernetes.io/created-by: eks-workshop
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: ${schema.spec.appName}
app.kubernetes.io/instance: ${schema.spec.appName}
app.kubernetes.io/component: service
includeWhen:
- ${schema.spec.service.enabled}

- id: ingress
template:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ${schema.spec.appName}
namespace: ${schema.spec.appName}
labels:
app.kubernetes.io/created-by: eks-workshop
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/healthcheck-path: ${schema.spec.ingress.healthcheckPath}
alb.ingress.kubernetes.io/group.name: ${schema.spec.ingress.groupname}
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: ${schema.spec.ingress.path}
pathType: Prefix
backend:
service:
name: ${schema.spec.appName}
port:
number: 80
includeWhen:
- ${schema.spec.ingress.enabled}

このResourceGraphDefinitionは、以下のデプロイの複雑さを抽象化するカスタムWebApplication APIを作成します:

  • ServiceAccount
  • ConfigMap
  • Deployment
  • Service
  • Ingress(オプション)

スキーマは以下に示すように、アプリケーションイメージ、レプリカ数、環境変数、ヘルスチェック設定などの主要パラメータをカスタマイズできるようにしながら、適切なデフォルト値を提供します:

    spec:
appName: string | required=true description="Web Application Name"
replicas: integer | default=1 minimum=1 maximum=100
image: string | default=nginx
port: integer | default=8080
healthcheck:
readinessPath: string | default="/actuator/health/readiness"
readinessPort: integer | default=8080
livenessPath: string | default="/actuator/health/liveness"
livenessPort: integer | default=8080

service:
enabled: boolean | default=true
iamRole: string | default=""

env: map[string]string | default={}

ingress:
enabled: boolean | default=false
path: string | default="/"
healthcheckPath: string | default="/health"
groupname: string | default="eks-workshop"
備考

スキーマがどのようにデフォルト値と型定義を使用して、Kubernetesの複雑さを隠し、開発者に優しいAPIを作成しているかに注目してください。

このWebApplication ResourceGraphDefinitionを使用して、インメモリデータベースを使用するCartsコンポーネントのインスタンスを作成します。まず、既存のcartsデプロイメントをクリーンアップしましょう:

~$kubectl delete all --all -n carts
pod "carts-68d496fff8-9lcpc" deleted
pod "carts-dynamodb-995f7768c-wtsbr" deleted
service "carts" deleted
service "carts-dynamodb" deleted
deployment.apps "carts" deleted
deployment.apps "carts-dynamodb" deleted

次に、WebApplication APIを登録するためにResourceGraphDefinitionを適用します:

~$kubectl apply -f ~/environment/eks-workshop/modules/automation/controlplanes/kro/rgds/webapp-rgd.yaml
resourcegraphdefinition.kro.run/web-application created

これによりWebApplication APIが登録されます。kroは自動的にRGDスキーマに基づいてカスタムリソース定義(CRD)を作成します。CRDを確認しましょう:

~$kubectl get crd webapplications.kro.run
NAME                       CREATED AT
webapplications.kro.run    2024-01-15T10:30:00Z

次に、WebApplication APIを使用してCartsコンポーネントのインスタンスを作成するcarts.yamlファイルを確認しましょう:

~/environment/eks-workshop/modules/automation/controlplanes/kro/app/carts.yaml
apiVersion: kro.run/v1alpha1
kind: WebApplication
metadata:
name: carts
namespace: carts
spec:
# Basic types
appName: carts
replicas: 1
image: "public.ecr.aws/aws-containers/retail-store-sample-cart:1.2.1"
port: 8080
env:
RETAIL_CART_PERSISTENCE_PROVIDER: "in-memory"
RETAIL_CART_PERSISTENCE_DYNAMODB_TABLE_NAME: "Items"
RETAIL_CART_PERSISTENCE_DYNAMODB_CREATE_TABLE: "false"

service:
enabled: true
A

RGDによって作成されたカスタムWebApplication APIを使用します

B

carts名前空間にcartsという名前のリソースを作成します

C

リソースの命名のためにアプリケーション名を指定します

D

単一レプリカを設定します

E

小売店のカートサービスコンテナイメージを使用します

F

ポート8080でアプリケーションを公開します

G

インメモリ永続化モードのための環境変数を構成します

H

Kubernetes Serviceリソースを有効にします

アプリケーションをデプロイしましょう:

~$kubectl apply -f ~/environment/eks-workshop/modules/automation/controlplanes/kro/app/carts.yaml
webapplication.kro.run/carts created

kroはこのカスタムリソースを処理し、すべての基礎となるKubernetesリソースを作成します。カスタムリソースが作成されたことを確認しましょう:

~$kubectl get webapplication -n carts
NAME    STATE         SYNCED   AGE
carts   IN_PROGRESS   False    16s

インスタンスが「同期済み」状態に達するまで待ちましょう:

~$kubectl wait -o yaml webapplication/carts -n carts \
--for=condition=InstanceSynced=True --timeout=120s

次に、RGDのコンポーネントが実行中であることを確認します:

~$kubectl get all -n carts
NAME                         READY   STATUS    RESTARTS   AGE
pod/carts-7d58cfb7c9-xyz12   1/1     Running   0          30s
 
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/carts   ClusterIP   172.20.123.45   <none>        80/TCP    30s
 
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/carts   1/1     1            1           30s
 
NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/carts-7d58cfb7c9   1         1         1       30s

kroはCartsコンポーネントに必要なすべてのKubernetesリソースのデプロイを単一のユニットとして正常にオーケストレーションしました。kroを使用することで、通常は複数のYAMLファイルの適用が必要となるものを、単一の宣言的なAPI呼び出しに変換しました。これは複雑なリソースオーケストレーションを簡素化するkroの力を示しています。

次のセクションでは、現在cartsが使用しているインメモリデータベースをAmazon DynamoDBテーブルに置き換えます。