Skip to content

Helm 차트 구성

SMCTF의 백엔드 및 Container Provisioner, Ingress와 SA/RBAC 리소스 등을 배포하기 위해 Kubernetes 내 모든 리소스는 Helm 차트를 통해 배포됩니다. 로깅/모니터링(FluentBit + ServiceMonitor)은 별도의 kubernetes-observability Helm 차트에서 관리합니다.

아래의 명령어로 Helm 차트를 배포할 수 있습니다.

Terminal window
helm upgrade --install smctf ./kubernetes -f kubernetes/values.yaml

기본적으로 필요한 네임스페이스 등이 포함되어 있으며, values.yaml은 배포 전에 적절하게 수정하여 사용해야 합니다.

SMCTF Helm 차트 설치 후 AWS LB Controller를 설치하세요. (IRSA 및 VPC ID를 필요로 하기 때문에 반드시 SMCTF Helm 차트 설치 후에 설치해야 합니다.)

Terminal window
helm repo add eks https://aws.github.io/eks-charts
helm repo update eks
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=smctf \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller \
--set nodeSelector.role=backend \
--set vpcId="<VPC_ID>" \
--set region=ap-northeast-2

Prometheus 스택 설치 후 observability 차트를 설치합니다. (ServiceMonitor CRD 포함)

Terminal window
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm upgrade --install kube-prometheus-stack prometheus-community/kube-prometheus-stack \
-n monitoring --create-namespace \
--set grafana.enabled=false \
--set alertmanager.enabled=false \
--set prometheus.prometheusSpec.nodeSelector.role=backend \
--set prometheusOperator.nodeSelector.role=backend \
--set kubeStateMetrics.nodeSelector.role=backend \
--set nodeExporter.nodeSelector.role=backend
helm upgrade --install smctf-observability ./kubernetes-observability -f kubernetes-observability/values.yaml

values.yaml을 구성하기 위해 Terraform을 통해 프로비저닝된 리소스들의 출력 결과를 확인해야 합니다. 이는 terraform output 명령어를 통해 확인할 수 있으며, 이를 기반으로 Helm 차트의 values.yaml을 적절하게 수정하여 배포해야 합니다.

Terraform 출력에 맞게 수정해야하는 필드는 아래와 같습니다.

# - elbController.serviceAccount.annotations.eks.amazonaws.com/role-arn (AWS Account ID/IRSA Role ARN)
# - backend.serviceAccount.annotations.eks.amazonaws.com/role-arn (AWS Account ID/IRSA Role ARN)
# - provisioner.serviceAccount.annotations.eks.amazonaws.com/role-arn (AWS Account ID/IRSA Role ARN)
# - backend.config.DB_HOST (PostgreSQL RDS Endpoint)
# - backend.config.REDIS_ADDR (ElastiCache Redis Endpoint, usually in the format "<cache-cluster-name>.xxxxxx.0001.use1.cache.amazonaws.com:6379")
# - backend.ingress.securityGroupId (ALB Security Group ID)
# - backend.ingress.https.certificateArn (ALB Certificate ARN, if HTTPS is enabled)
# - provisioner.config.DDB_STACK_TABLE (DynamoDB Configuration)
  • backend.ingress.securityGroupId는 설정하지 않고 주석처리 할 수 있습니다. 이 경우 자동으로 HTTP 80 포트 또는 HTTPS 443 포트가 열리도록 ALB 보안 그룹이 구성됩니다.
  • HTTPS Ingress를 위한 ACM은 따로 발급받은 인증서 ARN이 필요합니다. 이는 Terraform에서 ACM 인증서를 생성하지 않습니다.
  • CloudWatch Logs Group Name은 /aws/eks/<project>-<env>/logs 형식으로 설정되어야 하며, IRSA 설정으로 인해 고정된 형식이여야 합니다. (observability 차트의 values.yaml에서 설정)

values.yaml 업데이트 또는 특정 필드를 업데이트하려면 아래와 같은 Helm 명령어를 사용할 수 있습니다.

Terminal window
helm upgrade --install smctf ./kubernetes \
--set backend.deployment.image.tag=v1.2.0 \
--set backend.deployment.replicas=3
helm upgrade --install smctf ./kubernetes -f new-values.yaml

아래부터 values.yaml의 주요 구성 요소에 대한 설명과 예시 설정을 제공합니다. 필요에 따라 적절히 수정해야하며, 여기에 애플리케이션의 환경 변수가 모두 포함됩니다. 외부에 노출되지 않도록 절대적으로 주의하세요.

namespaces:
create: true
backend: backend
stacks: stacks

logging, monitoring 네임스페이스는 observability 차트에서 생성됩니다.

elbController:
enabled: true
serviceAccount:
name: aws-load-balancer-controller
namespace: kube-system
labels:
app.kubernetes.io/name: aws-load-balancer-controller
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/smctf-dev-irsa-alb
stacksQuota:
enabled: true
name: stacks-resource-quota
namespace: stacks
hard:
requests.cpu: '6'
requests.memory: '6Gi'
limits.cpu: '6'
limits.memory: '6Gi'
stacksLimitRange:
enabled: true
name: stacks-limit-range
namespace: stacks
containerDefaults:
max:
cpu: '500m'
memory: '512Mi'
default:
cpu: '500m'
memory: '512Mi'
defaultRequest:
cpu: '500m'
memory: '512Mi'
stacksDenyNetworkPolicy:
enabled: true
namePrefix: deny-from-stacks
denyFromNamespace: stacks
namespaces:
- monitoring
- backend
backend:
enabled: true
serviceAccount:
name: smctf-backend
namespace: backend
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/smctf-dev-irsa-backend
configName: smctf-backend-config
secretName: smctf-backend-secret
config:
APP_ENV: 'production'
HTTP_ADDR: ':8080'
SHUTDOWN_TIMEOUT: '10s'
AUTO_MIGRATE: 'true'
BCRYPT_COST: '12'
DB_HOST: 'smctf-dev-postgres.cp4cewyumxw7.ap-northeast-2.rds.amazonaws.com'
DB_PORT: '5432'
DB_USER: 'app_user'
DB_NAME: 'app_db'
DB_SSLMODE: 'require'
DB_MAX_OPEN_CONNS: '25'
DB_MAX_IDLE_CONNS: '10'
DB_CONN_MAX_LIFETIME: '30m'
REDIS_ADDR: 'smctf-dev-redis.q2pzrs.ng.0001.apn2.cache.amazonaws.com:6379'
REDIS_DB: '0'
REDIS_POOL_SIZE: '20'
JWT_ISSUER: 'smctf'
JWT_ACCESS_TTL: '24h'
JWT_REFRESH_TTL: '168h'
SUBMIT_WINDOW: '1m'
SUBMIT_MAX: '10'
TIMELINE_CACHE_TTL: '60s'
LEADERBOARD_CACHE_TTL: '60s'
APP_CONFIG_CACHE_TTL: '2m'
CORS_ALLOWED_ORIGINS: 'http://localhost:3000,http://localhost:5173,https://smctf.example.com,https://ctf.swua.kr'
STACKS_ENABLED: 'true'
STACKS_MAX_PER_USER: '3'
STACKS_PROVISIONER_BASE_URL: 'http://container-provisioner.backend.svc.cluster.local:8081'
STACKS_PROVISIONER_TIMEOUT: '5s'
STACKS_CREATE_WINDOW: '1m'
STACKS_CREATE_MAX: '1'
LOG_DIR: 'logs'
LOG_FILE_PREFIX: 'app'
LOG_MAX_BODY_BYTES: '1048576'
S3_ENABLED: 'true'
S3_REGION: 'ap-northeast-2'
S3_BUCKET: 'smctf-challenges-bucket'
# S3_ENDPOINT: ""
S3_FORCE_PATH_STYLE: 'false'
S3_PRESIGN_TTL: '15m'
BOOTSTRAP_ADMIN_TEAM: 'true'
BOOTSTRAP_ADMIN_USER: 'true'
BOOTSTRAP_ADMIN_USERNAME: 'admin'
secret:
DB_PASSWORD: 'app_password'
REDIS_PASSWORD: ''
JWT_SECRET: 'change-me-strong'
FLAG_HMAC_SECRET: 'change-me-too-strong'
STACKS_PROVISIONER_API_KEY: 'secret-strong'
# S3_ACCESS_KEY_ID: ""
# S3_SECRET_ACCESS_KEY: ""
BOOTSTRAP_ADMIN_USERNAME: 'admin'
BOOTSTRAP_ADMIN_EMAIL: 'admin@smctf.com'
BOOTSTRAP_ADMIN_PASSWORD: 'admin123!'
deployment:
name: smctf-backend
replicas: 2
containerName: smctf-backend-app
image:
repository: <AWS_ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com/backend
tag: latest
pullPolicy: IfNotPresent
port: 8080
nodeSelector:
role: backend
automountServiceAccountToken: true
service:
name: smctf-backend
type: NodePort
port: 80
targetPort: 8080
nodePort: 30080
ingress:
enabled: true
className: alb
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: instance
alb.ingress.kubernetes.io/backend-protocol: HTTP
alb.ingress.kubernetes.io/healthcheck-path: /healthz
# securityGroupId: sg-0316b2f31ab20189d
host: ''
path: /
pathType: Prefix
http:
enabled: false
listenPorts: '[{"HTTP":80}]'
https:
enabled: true
listenPorts: '[{"HTTP":80},{"HTTPS":443}]'
certificateArn: arn:aws:acm:ap-northeast-2:<AWS_ACCOUNT_ID>:certificate/3cc6e4d6-c43f-411a-9b5a-3c07105fb2c6
sslRedirect: true
provisioner:
enabled: true
serviceAccount:
name: container-provisioner
namespace: backend
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/smctf-dev-irsa-container-provisioner
configName: container-provisioner-config
secretName: container-provisioner-secret
rbac:
clusterRoleName: container-provisioner-role
clusterRoleBindingName: container-provisioner-binding
config:
APP_ENV: 'local'
HTTP_ADDR: ':8081'
SHUTDOWN_TIMEOUT: '10s'
API_KEY_ENABLED: 'true'
LOG_DIR: 'logs'
LOG_FILE_PREFIX: 'app'
LOG_MAX_BODY_BYTES: '1048576'
STACK_NAMESPACE: 'stacks'
STACK_TTL: '2h'
STACK_SCHEDULER_INTERVAL: '10s'
STACK_NODEPORT_MIN: '31001'
STACK_NODEPORT_MAX: '32767'
STACK_PORT_LOCK_TTL: '30s'
STACK_NODE_ROLE: 'stack'
STACK_REQUIRE_INGRESS_NETWORK_POLICY: 'true'
DDB_USE_MOCK: 'false'
DDB_STACK_TABLE: 'smctf-container-provisioner-stacks'
DDB_CONSISTENT_READ: 'true'
AWS_REGION: 'ap-northeast-2'
# AWS_ENDPOINT: ""
K8S_USE_MOCK: 'false'
# K8S_KUBECONFIG: ""
# K8S_CONTEXT: ""
K8S_CLIENT_QPS: '20'
K8S_CLIENT_BURST: '40'
STACK_SCHEDULING_TIMEOUT: '20s'
secret:
API_KEY: 'secret-strong'
LOG_DISCORD_WEBHOOK_URL: ''
LOG_SLACK_WEBHOOK_URL: ''

Container Provisioner Deployment 및 Service 구성

Section titled “Container Provisioner Deployment 및 Service 구성”
deployment:
name: container-provisioner
replicas: 2
containerName: container-provisioner-app
image:
repository: <AWS_ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com/container-provisioner
tag: latest
pullPolicy: IfNotPresent
port: 8081
nodeSelector:
role: backend
automountServiceAccountToken: true
service:
name: container-provisioner
type: ClusterIP
port: 8081
targetPort: 8081

로깅(FluentBit)과 모니터링(ServiceMonitor)은 kubernetes-observability/values.yaml에서 관리합니다. 자세한 구성은 Observability 문서에서 확인하세요.