본문으로 건너뛰기

클라우드 리소스 프로비저닝

이 섹션에서는 carts에서 사용 중인 인메모리 데이터베이스를 DynamoDB로 교체하겠습니다. 기본 WebApplication 템플릿을 기반으로 구축하는 WebApplicationDynamoDB ResourceGraphDefinition을 구성하여 이를 수행하겠습니다.

먼저 이전 섹션에서 생성한 kro 인스턴스를 삭제하겠습니다:

~$kubectl delete webapplication.kro.run/carts -n carts
webapplication.kro.run "carts" deleted

이렇게 하면 관련된 모든 리소스가 정리됩니다:

~$kubectl get all -n carts
No resources found in carts namespace.

이제 재사용 가능한 WebApplicationDynamoDB API를 정의하는 ResourceGraphDefinition 템플릿을 살펴보겠습니다:

전체 RGD 매니페스트 확장
~/environment/eks-workshop/modules/automation/controlplanes/kro/rgds/webapp-dynamodb-rgd.yaml
apiVersion: kro.run/v1alpha1
kind: ResourceGraphDefinition
metadata:
name: web-application-ddb
spec:
schema:
apiVersion: v1alpha1
kind: WebApplicationDynamoDB
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

dynamodb:
tableName: string | required=true description="DynamoDB Table Name"

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

aws:
accountID: integer | required=true
region: string | default="us-west-2"

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

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

resources:
- id: podIdentityAssociation
template:
apiVersion: eks.services.k8s.aws/v1alpha1
kind: PodIdentityAssociation
metadata:
name: ${schema.spec.appName}
namespace: ${schema.spec.appName}
spec:
clusterName: "eks-workshop"
namespace: ${schema.spec.appName}
serviceAccount: ${schema.spec.appName}
roleARN: ${itemsTableIAMRole.status.ackResourceMetadata.arn}

- id: webApplication
template:
apiVersion: kro.run/v1alpha1
kind: WebApplication
metadata:
name: ${schema.spec.appName}
namespace: ${schema.spec.appName}
spec:
appName: ${schema.spec.appName}
replicas: 1
image: ${schema.spec.image}
port: 8080
healthcheck:
readinessPath: ${schema.spec.healthcheck.readinessPath}
readinessPort: ${schema.spec.healthcheck.readinessPort}
livenessPath: ${schema.spec.healthcheck.livenessPath}
livenessPort: ${schema.spec.healthcheck.livenessPort}

service:
enabled: ${schema.spec.service.enabled}
iamRole: ${podIdentityAssociation.status.ackResourceMetadata.arn}

env: ${schema.spec.env}

ingress:
enabled: ${schema.spec.ingress.enabled}
path: ${schema.spec.ingress.path}
healthcheckPath: ${schema.spec.ingress.healthcheckPath}
groupname: ${schema.spec.ingress.groupname}

- id: serviceDDB
template:
apiVersion: v1
kind: Service
metadata:
name: carts-dynamodb
labels:
app.kubernetes.io/created-by: eks-workshop
spec:
type: ClusterIP
ports:
- port: 8000
targetPort: dynamodb
protocol: TCP
name: dynamodb
selector:
app.kubernetes.io/name: ${schema.spec.appName}
app.kubernetes.io/instance: ${schema.spec.appName}
app.kubernetes.io/component: dynamodb

- id: itemsTable
template:
apiVersion: dynamodb.services.k8s.aws/v1alpha1
kind: Table
metadata:
name: items
namespace: ${schema.spec.appName}
spec:
keySchema:
- attributeName: id
keyType: HASH
attributeDefinitions:
- attributeName: id
attributeType: "S"
- attributeName: customerId
attributeType: "S"
billingMode: PAY_PER_REQUEST
tableName: ${schema.spec.dynamodb.tableName}
globalSecondaryIndexes:
- indexName: idx_global_customerId
keySchema:
- attributeName: customerId
keyType: HASH
- attributeName: id
keyType: RANGE
projection:
projectionType: "ALL"
- id: itemsTableIamPolicy
template:
apiVersion: iam.services.k8s.aws/v1alpha1
kind: Policy
metadata:
name: ${itemsTable.spec.tableName}-iam-policy
spec:
name: ${itemsTable.spec.tableName}-iam-policy
description: "EKS Workshop Carts DynamoDB Policy"
policyDocument: >
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllAPIActionsOnCart",
"Effect": "Allow",
"Action": "dynamodb:*",
"Resource": [
"arn:aws:dynamodb:${schema.spec.aws.region}:${schema.spec.aws.accountID}:table/${itemsTable.spec.tableName}",
"arn:aws:dynamodb:${schema.spec.aws.region}:${schema.spec.aws.accountID}:table/${itemsTable.spec.tableName}/index/*"
]
}
]
}
- id: itemsTableIAMRole
template:
apiVersion: iam.services.k8s.aws/v1alpha1
kind: Role
metadata:
name: ${itemsTable.spec.tableName}-iam-role
namespace: ${schema.spec.appName}
spec:
name: ${itemsTable.spec.tableName}-iam-role
description: "EKS Workshop Carts DynamoDB Role"
maxSessionDuration: 3600
policies:
- ${itemsTableIamPolicy.status.ackResourceMetadata.arn}
assumeRolePolicyDocument: >
{
"Version":"2012-10-17",
"Statement": [{
"Effect":"Allow",
"Principal": {"Service": "pods.eks.amazonaws.com"},
"Action": [
"sts:TagSession",
"sts:AssumeRole"
]
}]
}

이 ResourceGraphDefinition은:

  1. WebApplication RGD를 구성하는 사용자 정의 WebApplicationDynamoDB API를 생성합니다
  2. ACK를 사용하여 DynamoDB 테이블을 프로비저닝합니다
  3. DynamoDB 액세스를 위한 IAM 역할 및 정책을 생성합니다
  4. 애플리케이션 Pod에서 안전한 액세스를 위해 EKS Pod Identity를 구성합니다

EKS Pod Identity에 대해 자세히 알아보려면 공식 문서를 참조하세요.

정보

이 RGD가 리소스 섹션에 WebApplication RGD를 포함하고 있는 것을 주목하세요. webApplication을 참조함으로써 이 템플릿은 기본 WebApplication RGD에 정의된 모든 Kubernetes 리소스를 재사용하면서 DynamoDB, IAM 및 Pod Identity 리소스를 추가합니다.

ResourceGraphDefinition을 적용하여 WebApplicationDynamoDB API를 등록하겠습니다:

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

이렇게 하면 WebApplicationDynamoDB API가 등록됩니다. Custom Resource Definition (CRD)을 확인하세요:

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

이제 WebApplicationDynamoDB API를 사용하여 Carts 컴포넌트의 인스턴스를 생성할 carts-ddb.yaml 파일을 살펴보겠습니다:

~/environment/eks-workshop/modules/automation/controlplanes/kro/app/carts-ddb.yaml
apiVersion: kro.run/v1alpha1
kind: WebApplicationDynamoDB
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

dynamodb:
tableName: "eks-workshop-carts-kro"

env:
RETAIL_CART_PERSISTENCE_PROVIDER: "dynamodb"
RETAIL_CART_PERSISTENCE_DYNAMODB_TABLE_NAME: "eks-workshop-carts-kro"

aws:
accountID: ${AWS_ACCOUNT_ID}
region: ${AWS_REGION}
A

RGD에서 생성한 사용자 정의 WebApplicationDynamoDB API를 사용합니다

B

carts 네임스페이스에 carts라는 이름의 리소스를 생성합니다

C

리소스 이름 지정을 위한 애플리케이션 이름을 지정합니다

D

단일 레플리카를 설정합니다

E

소매점 장바구니 서비스 컨테이너 이미지를 사용합니다

F

포트 8080에 애플리케이션을 노출합니다

G

DynamoDB 테이블 이름을 지정합니다

H

DynamoDB 지속성 모드를 활성화하기 위한 환경 변수를 설정합니다

I

IAM 및 Pod Identity 구성을 위한 AWS 계정 ID와 리전을 제공합니다

다음으로 carts-ddb.yaml 파일을 활용하여 업데이트된 컴포넌트를 배포하겠습니다:

~$kubectl kustomize ~/environment/eks-workshop/modules/automation/controlplanes/kro/app \
| envsubst | kubectl apply -f-
webapplicationdynamodb.kro.run/carts created

kro는 이 사용자 정의 리소스를 처리하고 DynamoDB 테이블을 포함한 모든 기본 리소스를 생성합니다. 사용자 정의 리소스가 생성되었는지 확인하겠습니다:

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

이제 인스턴스가 "synced" 상태에 도달할 때까지 기다릴 수 있습니다:

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

DynamoDB 테이블이 생성되었는지 확인하기 위해 생성된 ACK 리소스를 확인할 수 있습니다:

~$kubectl wait table.dynamodb.services.k8s.aws items -n carts --for=condition=ACK.ResourceSynced --timeout=15m
table.dynamodb.services.k8s.aws/items condition met
~$kubectl get table.dynamodb.services.k8s.aws items -n carts -ojson | yq '.status."tableStatus"'
ACTIVE

AWS CLI를 사용하여 테이블이 생성되었는지 확인하겠습니다:

~$aws dynamodb list-tables
 
{
    "TableNames": [
        "eks-workshop-carts-kro"
    ]
}

kro의 구성 가능한 접근 방식을 사용하여 DynamoDB 테이블과 컴포넌트가 성공적으로 생성되었습니다.

컴포넌트가 새 DynamoDB 테이블과 함께 작동하는지 확인하기 위해 브라우저를 통해 상호 작용할 수 있습니다. 테스트를 위해 샘플 애플리케이션을 노출하는 NLB가 생성되었습니다:

~$ADDRESS=$(kubectl get ingress -n ui ui -o jsonpath="{.status.loadBalancer.ingress[*].hostname}")
~$echo "http://${ADDRESS}"
http://k8s-ui-ui-a9797f0f61.elb.us-west-2.amazonaws.com
정보

새로운 Network Load Balancer 엔드포인트가 프로비저닝되므로 이 명령을 실행할 때 실제 엔드포인트는 다를 것입니다.

로드 밸런서 프로비저닝이 완료되었는지 확인하려면 다음 명령을 실행할 수 있습니다:

로드 밸런서가 프로비저닝되면 웹 브라우저에 URL을 붙여넣어 액세스할 수 있습니다. 웹 스토어의 UI가 표시되며 사용자로서 사이트를 탐색할 수 있습니다.

http://k8s-ui-ui-a9797f0f61.elb.us-west-2.amazonaws.com/

Carts 모듈이 방금 프로비저닝한 DynamoDB 테이블을 실제로 사용하고 있는지 확인하려면 장바구니에 몇 가지 항목을 추가해 보세요.

이러한 항목이 DynamoDB 테이블에도 있는지 확인하려면 다음을 실행하세요:

~$aws dynamodb scan --table-name "${EKS_CLUSTER_NAME}-carts-kro"

축하합니다! 기본 WebApplication 템플릿을 기반으로 구축하여 DynamoDB 스토리지를 추가함으로써 kro의 구성 가능성을 성공적으로 시연했습니다.