Files
2nd/10_Wiki/Topics/Coding/DevOps_Crossplane_Tekton.md
T
2026-05-09 21:08:02 +09:00

8.6 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
devops-crossplane-tekton Crossplane / Tekton — K8s 안 Cloud / CI Coding draft B conceptual 2026-05-09 2026-05-09
devops
crossplane
tekton
vibe-coding
language applicable_to
YAML / K8s
DevOps
Crossplane
Tekton
Composition
K8s native CI
infrastructure as data

Crossplane / Tekton

Kubernetes-native infra. Crossplane = K8s 가 cloud 자원 관리 (Terraform 의 K8s alternative). Tekton = K8s native CI. Argo Workflows / GitOps 전체 통합.

📖 핵심 개념

  • Crossplane: cloud 자원 = K8s resource.
  • Tekton: pipeline as Custom Resource.
  • Composition: 자체 high-level resource.
  • Provider: AWS / GCP / Azure 등.

💻 코드 패턴

Crossplane 설치

helm install crossplane crossplane-stable/crossplane -n crossplane-system --create-namespace

# AWS provider
kubectl apply -f - <<EOF
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata: { name: provider-aws }
spec:
  package: xpkg.upbound.io/upbound/provider-aws-rds:v1.0
EOF

S3 bucket 만들기 (Crossplane)

apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata: { name: my-bucket }
spec:
  forProvider:
    region: us-east-1
  providerConfigRef:
    name: aws-default
kubectl apply -f bucket.yaml
# → AWS 에 S3 bucket 생성 + status reflect

RDS instance

apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
metadata: { name: my-db }
spec:
  forProvider:
    region: us-east-1
    instanceClass: db.t3.micro
    allocatedStorage: 20
    engine: postgres
    engineVersion: "16"
    masterUsername: app
    autoGeneratePassword: true
    masterPasswordSecretRef:
      name: my-db-creds
      namespace: default
      key: password
    skipFinalSnapshot: true
  writeConnectionSecretToRef:
    name: my-db-conn
    namespace: default

Composition (high-level abstraction)

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xappdatabases.acme.io
spec:
  group: acme.io
  names: { kind: XAppDatabase, plural: xappdatabases }
  claimNames: { kind: AppDatabase, plural: appdatabases }
  versions:
    - name: v1
      served: true
      referenceable: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                size: { type: string, enum: [small, medium, large] }
                region: { type: string }
# Composition
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata: { name: app-database-aws }
spec:
  compositeTypeRef:
    apiVersion: acme.io/v1
    kind: XAppDatabase
  
  resources:
    - name: rds
      base:
        apiVersion: rds.aws.upbound.io/v1beta1
        kind: Instance
        spec:
          forProvider:
            engine: postgres
            allocatedStorage: 20
      patches:
        - fromFieldPath: spec.region
          toFieldPath: spec.forProvider.region
        - fromFieldPath: spec.size
          toFieldPath: spec.forProvider.instanceClass
          transforms:
            - type: map
              map:
                small: db.t3.micro
                medium: db.t3.medium
                large: db.r6g.xlarge

Use (developer 친화)

# Developer 만 작성 — 단순
apiVersion: acme.io/v1
kind: AppDatabase
metadata: { name: orders-db }
spec:
  size: medium
  region: us-east-1

→ Crossplane 가 RDS instance + secret 자동 생성.

Tekton Pipeline

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata: { name: build-and-deploy }
spec:
  params:
    - name: repo-url
      type: string
    - name: image-name
      type: string
  
  workspaces:
    - name: shared
  
  tasks:
    - name: clone
      taskRef: { name: git-clone }
      params:
        - name: url
          value: $(params.repo-url)
      workspaces:
        - { name: output, workspace: shared }
    
    - name: test
      runAfter: [clone]
      taskSpec:
        steps:
          - name: test
            image: node:20
            workingDir: $(workspaces.source.path)
            script: yarn install && yarn test
      workspaces:
        - { name: source, workspace: shared }
    
    - name: build
      runAfter: [test]
      taskRef: { name: kaniko }
      params:
        - { name: IMAGE, value: $(params.image-name) }
      workspaces:
        - { name: source, workspace: shared }
    
    - name: deploy
      runAfter: [build]
      taskRef: { name: kubectl-deploy }
      params:
        - { name: image, value: $(params.image-name) }

PipelineRun

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata: { generateName: build-and-deploy- }
spec:
  pipelineRef: { name: build-and-deploy }
  params:
    - { name: repo-url, value: https://github.com/myorg/app }
    - { name: image-name, value: ghcr.io/myorg/app:v1 }
  workspaces:
    - name: shared
      volumeClaimTemplate:
        spec:
          accessModes: [ReadWriteOnce]
          resources: { requests: { storage: 5Gi } }

Trigger (webhook)

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata: { name: github-listener }
spec:
  triggers:
    - name: github-push
      interceptors:
        - ref: { name: github }
          params:
            - name: secretRef
              value:
                secretName: github-secret
                secretKey: token
            - name: eventTypes
              value: [push]
      bindings:
        - ref: github-push-binding
      template:
        ref: build-and-deploy-template

→ GitHub push → Pipeline 자동 trigger.

Tekton Task (재사용 step)

apiVersion: tekton.dev/v1beta1
kind: Task
metadata: { name: kaniko }
spec:
  params:
    - name: IMAGE
      type: string
  workspaces:
    - name: source
  steps:
    - name: build
      image: gcr.io/kaniko-project/executor:latest
      args:
        - --dockerfile=$(workspaces.source.path)/Dockerfile
        - --context=$(workspaces.source.path)
        - --destination=$(params.IMAGE)

Tekton Hub (catalog)

# 공유 task 사용
tkn hub install task git-clone
tkn hub install task kaniko
tkn hub install task npm

Tekton vs GitHub Actions / GitLab CI

Tekton:
+ K8s native (자원 효율)
+ Reusable (Task / Pipeline)
+ Cloud-agnostic
- 학습 곡선
- UI 약함

GitHub Actions:
+ 가장 인기
+ Marketplace 커
+ UI / 통합 강

→ K8s 사용 + on-prem CI = Tekton. 일반 = GHA.

Argo Workflows (alternative)

Tekton 와 비슷 — K8s native workflow.
ML pipeline 친화 (Argo MLOps).

Crossplane vs Terraform

Terraform:
+ 인기, 큰 ecosystem
+ 어떤 시스템 — K8s 외 OK
+ Plan 명확

Crossplane:
+ K8s native (declarative + reconcile loop)
+ GitOps 친화 (ArgoCD 가 manage)
+ Composition 으로 자체 abstraction
- K8s required
- 옛 자원 일부 X

→ K8s 중심 = Crossplane. 일반 = Terraform.

Backstage + Crossplane + Tekton

1. Dev 가 Backstage scaffolder 클릭 ("New service")
2. Tekton 가 GitHub repo 생성 + CI setup
3. Crossplane 가 RDS / S3 자동 생성
4. ArgoCD 가 cluster 에 deploy
5. Backstage 에 자동 등록

→ Self-service developer experience.

KubeVela (alternative)

Crossplane 비슷 — open application model (OAM).
Less popular but cleaner abstraction.

Operator pattern (Crossplane 의 underpinning)

Custom Resource + Controller = Operator.
- CR 가 desired state.
- Controller 가 reconcile (current = desired).
// Controller pseudocode
for {
  desired = readCR()
  current = readCloud()
  if desired != current {
    apply(desired)
  }
  sleep(30s)
}

→ Crossplane 가 cloud 의 controller.

🤔 의사결정 기준

작업 추천
K8s 친화 IaC Crossplane
일반 IaC Terraform
K8s native CI Tekton
일반 CI GitHub Actions
ML pipeline Argo Workflows
개발자 portal Backstage
Self-service Backstage + Crossplane + Tekton

안티패턴

  • Crossplane + 큰 cloud account 첫 시도: 학습 비용. 작은 부분 부터.
  • Tekton 가 GHA 대체 (작은 팀): overkill.
  • Composition 무 versioning: breaking 시 모든 instance 영향.
  • Provider config 매 namespace: 한 곳.
  • Terraform + Crossplane 같은 자원 동시: drift / 충돌.
  • Tekton step 큰 image: 매 step pull 시간.

🤖 LLM 활용 힌트

  • K8s + GitOps = Crossplane + ArgoCD.
  • Self-service portal = Backstage.
  • Tekton 가 K8s native CI but GHA 가 일반.
  • Composition 가 high-level abstraction.

🔗 관련 문서